Files
mrleo1nidandClaude Sonnet 5.5 ff82d882c0 feat: add ATL animation timelines and try/raise to the Ren'Py player
Python sandbox
- try/except/else/finally, raise (incl. re-raise), assert, for/while ... else
- Multi-generator and dict comprehensions
- Builtin exception hierarchy; user exceptions subclass it
- Inside try, missing keys/indexes, division by zero, attribute access on None
  and unknown names raise Python exceptions; lookups stay lenient elsewhere
- int()/float() raise ValueError on non-numeric strings

ATL
- converter/atl.py: set/move (linear, ease, easein, easeout), pause, repeat,
  parallel, choice, block, on show/hide and named transforms become a timeline
  shipped as game.json "atl"; Move() becomes a linear slide
- player/atl.ts: timeline runner wired into the renderer; `on hide` plays
  before the picture is removed
- function, time, contains, matrixcolor and expressions still block the import

Tests: exceptions/ATL fixtures and runtime tests, converter ATL tests; README
and ARCHITECTURE updated.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 12:11:07 +03:00

100 lines
1.7 KiB
Python

# Source of exceptions.ir.json. Regenerate from backend/ with:
# python -m tests.make_ir ../frontend/tests/fixtures/exceptions.py ../frontend/tests/fixtures/exceptions.ir.json
class AppError(Exception):
def __init__(self, msg, code=0):
super().__init__(msg)
self.code = code
def risky(n):
if n == 0:
raise AppError("zero", code=7)
return 10 // n
log = []
try:
risky(0)
except AppError as e:
log.append(str(e))
result_code = e.code
else:
log.append("no")
finally:
log.append("fin")
try:
d = {"a": 1}
v = d["b"]
except KeyError:
result_key = "keyerror"
try:
xs = [1]
xs[5]
except (IndexError, ValueError):
result_index = "indexerror"
try:
int("abc")
except ValueError:
result_value = "valueerror"
try:
risky(0)
except Exception:
result_generic = True
try:
result_zero = 1 / 0
except ZeroDivisionError:
result_zero = "zerodiv"
def retry():
for i in range(3):
try:
if i < 2:
raise ValueError("again")
return i
except ValueError:
continue
return -1
result_retry = retry()
found = None
for n in [1, 3, 5]:
if n % 2 == 0:
found = n
break
else:
found = "none"
result_forelse = found
k = 0
while k < 3:
k += 1
else:
k = k * 10
result_whileelse = k
try:
try:
raise RuntimeError("inner")
except RuntimeError:
raise
except RuntimeError as e3:
result_reraise = str(e3)
result_pairs = [(x, y) for x in [1, 2] for y in [3, 4]]
result_dictcomp = {a: b for a in [1, 2] for b in [a * 10] if b > 10}
try:
assert 1 == 2, "boom"
except AssertionError as e4:
result_assert = str(e4)