sonolus.py 0.10.2__py3-none-any.whl → 0.10.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of sonolus.py might be problematic. Click here for more details.

sonolus/build/cli.py CHANGED
@@ -14,7 +14,7 @@ from sonolus.build.dev_server import run_server
14
14
  from sonolus.build.engine import no_gil, package_engine, validate_engine
15
15
  from sonolus.build.level import package_level_data
16
16
  from sonolus.build.project import build_project_to_collection, get_project_schema
17
- from sonolus.script.internal.context import ProjectContextState
17
+ from sonolus.script.internal.context import ProjectContextState, RuntimeChecks
18
18
  from sonolus.script.internal.error import CompilationError
19
19
  from sonolus.script.project import BuildConfig, Project
20
20
 
@@ -128,9 +128,20 @@ def get_config(args: argparse.Namespace) -> BuildConfig:
128
128
  build_watch=build_watch,
129
129
  build_preview=build_preview,
130
130
  build_tutorial=build_tutorial,
131
+ runtime_checks=get_runtime_checks(args),
131
132
  )
132
133
 
133
134
 
135
+ def get_runtime_checks(args: argparse.Namespace) -> RuntimeChecks:
136
+ if hasattr(args, "runtime_checks") and args.runtime_checks:
137
+ return {
138
+ "none": RuntimeChecks.NONE,
139
+ "terminate": RuntimeChecks.TERMINATE,
140
+ "notify": RuntimeChecks.NOTIFY_AND_TERMINATE,
141
+ }[args.runtime_checks]
142
+ return RuntimeChecks.NOTIFY_AND_TERMINATE if args.command == "dev" else RuntimeChecks.NONE
143
+
144
+
134
145
  def main():
135
146
  parser = argparse.ArgumentParser(description="Sonolus project build and development tools")
136
147
  subparsers = parser.add_subparsers(dest="command", required=True)
@@ -147,6 +158,12 @@ def main():
147
158
  "-O2", "--optimize-standard", action="store_true", help="Use standard optimization passes"
148
159
  )
149
160
 
161
+ parser.add_argument(
162
+ "--runtime-checks",
163
+ choices=["none", "terminate", "notify"],
164
+ help="Runtime error checking mode (default: none for build, notify for dev)",
165
+ )
166
+
150
167
  build_components = parser.add_argument_group("build components")
151
168
  build_components.add_argument("--play", action="store_true", help="Build play component")
152
169
  build_components.add_argument("--watch", action="store_true", help="Build watch component")
@@ -57,7 +57,8 @@ DETAILED_HELP_TEXT = [
57
57
  description=[
58
58
  (
59
59
  "Decode a debug message code to its original text with a stack trace. "
60
- "Message codes are generated by assert statements, debug.error(), and debug.notify() calls. "
60
+ "Message codes are generated by assert statements and certain debug-related functions such as "
61
+ "debug.error() and debug.notify(). "
61
62
  "The game is automatically paused when these are triggered in debug mode and the message code "
62
63
  "can be found in the debug log."
63
64
  ),
@@ -117,7 +118,7 @@ class RebuildCommand:
117
118
  print("Rebuilding...")
118
119
  try:
119
120
  start_time = perf_counter()
120
- server_state.project_state = ProjectContextState(dev=True)
121
+ server_state.project_state = ProjectContextState.from_build_config(server_state.config)
121
122
  server_state.project = project_module.project
122
123
  build_collection(
123
124
  server_state.project,
@@ -189,7 +190,13 @@ def parse_dev_command(command_line: str) -> Command | None:
189
190
  subparsers.add_parser("quit", aliases=["q"])
190
191
 
191
192
  try:
192
- args = parser.parse_args(shlex.split(command_line))
193
+ split_args = shlex.split(command_line)
194
+ except ValueError as e:
195
+ print(f"Error parsing command: {e}\n")
196
+ return None
197
+
198
+ try:
199
+ args = parser.parse_args(split_args)
193
200
  if args.cmd in {"rebuild", "r"}:
194
201
  return RebuildCommand()
195
202
  elif args.cmd in {"decode", "d"}:
@@ -226,8 +233,7 @@ def command_input_thread(command_queue: queue.Queue, prompt_event: threading.Eve
226
233
  except EOFError:
227
234
  break
228
235
  except Exception as e:
229
- print(f"Error reading command: {e}")
230
- break
236
+ print(f"Error reading command: {e}\n")
231
237
 
232
238
 
233
239
  def get_local_ips():
@@ -260,7 +266,7 @@ def run_server(
260
266
  from sonolus.build.cli import build_collection
261
267
 
262
268
  cache = CompileCache()
263
- project_state = ProjectContextState(dev=True)
269
+ project_state = ProjectContextState.from_build_config(config)
264
270
 
265
271
  start_time = perf_counter()
266
272
  build_collection(project, build_dir, config, cache=cache, project_state=project_state)
@@ -311,12 +317,12 @@ def run_server(
311
317
 
312
318
  try:
313
319
  while True:
320
+ cmd = command_queue.get()
314
321
  try:
315
- cmd = command_queue.get(timeout=0.5)
316
322
  cmd.execute(server_state)
317
- prompt_event.set()
318
- except queue.Empty:
319
- continue
323
+ except Exception:
324
+ print(f"{traceback.format_exc()}\n")
325
+ prompt_event.set()
320
326
  except KeyboardInterrupt:
321
327
  print("Exiting...")
322
328
  sys.exit(0)
sonolus/build/engine.py CHANGED
@@ -76,7 +76,7 @@ def package_engine(
76
76
 
77
77
  config = config or BuildConfig()
78
78
  if project_state is None:
79
- project_state = ProjectContextState()
79
+ project_state = ProjectContextState.from_build_config(config)
80
80
  configuration = build_engine_configuration(engine.options, engine.ui)
81
81
  if no_gil():
82
82
  # process_cpu_count is available in Python 3.13+
@@ -209,9 +209,11 @@ def package_engine(
209
209
  def validate_engine(
210
210
  engine: EngineData,
211
211
  config: BuildConfig | None = None,
212
+ project_state: ProjectContextState | None = None,
212
213
  ):
213
214
  config = config or BuildConfig()
214
- project_state = ProjectContextState()
215
+ if project_state is None:
216
+ project_state = ProjectContextState.from_build_config(config)
215
217
 
216
218
  play_mode = engine.play if config.build_play else empty_play_mode()
217
219
  watch_mode = engine.watch if config.build_watch else empty_watch_mode()
sonolus/script/array.py CHANGED
@@ -30,6 +30,8 @@ class ArrayMeta(ABCMeta):
30
30
  class Array[T, Size](GenericValue, ArrayLike[T], metaclass=ArrayMeta):
31
31
  """A fixed size array of values.
32
32
 
33
+ Supports negative indexes.
34
+
33
35
  Usage:
34
36
  ```python
35
37
  array_1 = Array(1, 2, 3)
@@ -87,6 +87,8 @@ class Pair[T, U](Record):
87
87
  class VarArray[T, Capacity](Record, ArrayLike[T]):
88
88
  """An array with a variable size and fixed maximum capacity.
89
89
 
90
+ Supports negative indexes.
91
+
90
92
  Usage:
91
93
  ```python
92
94
  VarArray[T, Capacity].new() # Create a new empty array
@@ -125,6 +127,8 @@ class VarArray[T, Capacity](Record, ArrayLike[T]):
125
127
  def __getitem__(self, item) -> T:
126
128
  """Return the element at the given index.
127
129
 
130
+ Supports negative indexes.
131
+
128
132
  The returned value continues to be part of the array.
129
133
  Future modifications to the array will affect the returned value.
130
134
 
@@ -183,7 +187,7 @@ class VarArray[T, Capacity](Record, ArrayLike[T]):
183
187
  assert self._size + len(values) <= len(self._array), "Array is full"
184
188
  i = 0
185
189
  while i < len(values):
186
- self._array.set_unchecked(self._size + i, values[i])
190
+ self._array.set_unchecked(self._size + i, values.get_unchecked(i))
187
191
  i += 1
188
192
  self._size += len(values)
189
193
 
@@ -310,6 +314,8 @@ class VarArray[T, Capacity](Record, ArrayLike[T]):
310
314
  class ArrayPointer[T](Record, ArrayLike[T]):
311
315
  """An array defined by a size and pointer to the first element.
312
316
 
317
+ Supports negative indexes.
318
+
313
319
  This is intended to be created internally and improper use may result in hard to debug issues.
314
320
 
315
321
  Usage:
sonolus/script/debug.py CHANGED
@@ -1,13 +1,13 @@
1
1
  from collections.abc import Callable, Sequence
2
2
  from contextvars import ContextVar
3
- from typing import Any, Literal, Never
3
+ from typing import Any, Literal, Never, assert_never
4
4
 
5
5
  from sonolus.backend.mode import Mode
6
6
  from sonolus.backend.ops import Op
7
7
  from sonolus.backend.optimize.flow import cfg_to_mermaid
8
8
  from sonolus.backend.optimize.passes import CompilerPass, OptimizerConfig, run_passes
9
9
  from sonolus.backend.optimize.simplify import RenumberVars
10
- from sonolus.script.internal.context import ModeContextState, ProjectContextState, ctx, set_ctx
10
+ from sonolus.script.internal.context import ModeContextState, ProjectContextState, RuntimeChecks, ctx, set_ctx
11
11
  from sonolus.script.internal.impl import meta_fn, validate_value
12
12
  from sonolus.script.internal.native import native_function
13
13
  from sonolus.script.internal.simulation_context import SimulationContext
@@ -18,12 +18,12 @@ debug_log_callback = ContextVar[Callable[[Num], None]]("debug_log_callback")
18
18
 
19
19
  @meta_fn
20
20
  def error(message: str | None = None) -> Never: # type: ignore
21
- """Raise an error, and if in a dev build, log a message and pause the game.
21
+ """Raise an error, and if runtime checks are set to notify, log a message and pause the game.
22
22
 
23
- This function is used to raise an error during runtime.
24
- When this happens, the game will pause in debug mode. The current callback will also immediately return 0.
23
+ This function is used to raise an error during runtime and terminate the current callback.
25
24
 
26
- In non-dev builds, this function will terminate the current callback silently.
25
+ If runtime checks are set to notify (default in dev), this function will log a message and pause the game
26
+ before terminating.
27
27
 
28
28
  Args:
29
29
  message: The message to log.
@@ -32,9 +32,14 @@ def error(message: str | None = None) -> Never: # type: ignore
32
32
  if not isinstance(message, str):
33
33
  raise ValueError("Expected a string")
34
34
  if ctx():
35
- if ctx().project_state.dev:
36
- debug_log(ctx().map_debug_message(message))
37
- debug_pause()
35
+ match ctx().project_state.runtime_checks:
36
+ case RuntimeChecks.NOTIFY_AND_TERMINATE:
37
+ debug_log(ctx().map_debug_message(message))
38
+ debug_pause()
39
+ case RuntimeChecks.TERMINATE | RuntimeChecks.NONE:
40
+ pass
41
+ case _ as unreachable:
42
+ assert_never(unreachable)
38
43
  terminate()
39
44
  else:
40
45
  raise RuntimeError(message)
@@ -79,9 +84,9 @@ def debug_pause():
79
84
 
80
85
  @meta_fn
81
86
  def notify(message: str):
82
- """Log a code that can be decoded by the dev server and pause the game if in debug mode and in a dev build.
87
+ """Log a code that can be decoded by the dev server and pause the game if runtime checks are set to notify.
83
88
 
84
- Does nothing if not a dev build.
89
+ If runtime checks are not set to notify, this function will do nothing.
85
90
 
86
91
  Args:
87
92
  message: The message to log.
@@ -90,7 +95,7 @@ def notify(message: str):
90
95
  if not isinstance(message, str):
91
96
  raise ValueError("Expected a string")
92
97
  if ctx():
93
- if ctx().project_state.dev:
98
+ if ctx().project_state.runtime_checks == RuntimeChecks.NOTIFY_AND_TERMINATE:
94
99
  debug_log(ctx().map_debug_message(message))
95
100
  debug_pause()
96
101
  else:
@@ -101,11 +106,10 @@ def notify(message: str):
101
106
  def require(value: int | float | bool, message: str | None = None):
102
107
  """Require a condition to be true, or raise an error.
103
108
 
104
- Similar to assert, but does not get stripped in non-dev builds.
105
-
106
- If in a dev build, this function will log a message and pause the game if the condition is false.
109
+ Similar to assert, but will terminate the current callback even if runtime checks are set to none.
107
110
 
108
- In non-dev builds, this function will terminate the current callback silently if the condition is false.
111
+ If runtime checks are set to notify (default in dev), this function will log a message and pause the game
112
+ before terminating.
109
113
 
110
114
  Args:
111
115
  value: The condition to check.
@@ -134,7 +138,7 @@ def require(value: int | float | bool, message: str | None = None):
134
138
 
135
139
  @meta_fn
136
140
  def assert_true(value: int | float | bool, message: str | None = None):
137
- if ctx() and not ctx().project_state.dev:
141
+ if ctx() and ctx().project_state.runtime_checks == RuntimeChecks.NONE:
138
142
  return
139
143
  require(value, message)
140
144
 
sonolus/script/effect.py CHANGED
@@ -98,6 +98,8 @@ class ScheduledLoopedEffectHandle(Record):
98
98
  class EffectGroup(Record, ArrayLike[Effect]):
99
99
  """A group of effect clips.
100
100
 
101
+ Does not support negative indexes.
102
+
101
103
  Usage:
102
104
  ```python
103
105
  EffectGroup(start_id: int, size: int)
@@ -4,8 +4,9 @@ from collections.abc import Iterable, Sequence
4
4
  from contextlib import contextmanager
5
5
  from contextvars import ContextVar
6
6
  from dataclasses import dataclass
7
+ from enum import Enum
7
8
  from threading import Lock
8
- from typing import Any, Literal, Self
9
+ from typing import TYPE_CHECKING, Any, Literal, Self
9
10
 
10
11
  from sonolus.backend.blocks import BlockData, PlayBlock
11
12
  from sonolus.backend.ir import IRConst, IRExpr, IRStmt
@@ -15,6 +16,9 @@ from sonolus.backend.place import Block, BlockPlace, TempBlock
15
16
  from sonolus.script.globals import _GlobalInfo, _GlobalPlaceholder
16
17
  from sonolus.script.internal.value import Value
17
18
 
19
+ if TYPE_CHECKING:
20
+ from sonolus.script.project import BuildConfig
21
+
18
22
  _compiler_internal_ = True
19
23
 
20
24
  context_var: ContextVar[Context | None] = ContextVar("context_var", default=None) # type: ignore
@@ -39,25 +43,53 @@ _disabled_debug_config = DebugConfig(
39
43
  debug_var = ContextVar("debug_var", default=_disabled_debug_config)
40
44
 
41
45
 
46
+ class RuntimeChecks(Enum):
47
+ """Runtime error checking modes."""
48
+
49
+ NONE = "none"
50
+ """No runtime checks."""
51
+
52
+ TERMINATE = "terminate"
53
+ """Terminate on errors."""
54
+
55
+ NOTIFY_AND_TERMINATE = "notify_and_terminate"
56
+ """Log, debug pause, and terminate on errors."""
57
+
58
+
42
59
  class ProjectContextState:
43
60
  rom: ReadOnlyMemory
44
61
  const_mappings: dict[Any, int]
45
62
  debug_str_mappings: dict[str, int]
46
63
  lock: Lock
47
- dev: bool
64
+ runtime_checks: RuntimeChecks
48
65
 
49
66
  def __init__(
50
67
  self,
51
68
  rom: ReadOnlyMemory | None = None,
52
69
  const_mappings: dict[Any, int] | None = None,
53
70
  debug_str_mappings: dict[str, int] | None = None,
54
- dev: bool = False,
71
+ runtime_checks: RuntimeChecks = RuntimeChecks.NONE,
55
72
  ):
56
73
  self.rom = ReadOnlyMemory() if rom is None else rom
57
74
  self.const_mappings = {} if const_mappings is None else const_mappings
58
75
  self.debug_str_mappings = {} if debug_str_mappings is None else debug_str_mappings
59
76
  self.lock = Lock()
60
- self.dev = dev
77
+ self.runtime_checks = runtime_checks
78
+
79
+ @classmethod
80
+ def from_build_config(
81
+ cls,
82
+ config: BuildConfig,
83
+ rom: ReadOnlyMemory | None = None,
84
+ const_mappings: dict[Any, int] | None = None,
85
+ debug_str_mappings: dict[str, int] | None = None,
86
+ ) -> Self:
87
+ return cls(
88
+ rom=rom,
89
+ const_mappings=const_mappings,
90
+ debug_str_mappings=debug_str_mappings,
91
+ runtime_checks=config.runtime_checks,
92
+ )
61
93
 
62
94
 
63
95
  class ModeContextState:
@@ -58,6 +58,8 @@ class ParticleHandle(Record):
58
58
  class ParticleGroup(Record, ArrayLike[Particle]):
59
59
  """A group of particle effects.
60
60
 
61
+ Does not support negative indexes.
62
+
61
63
  Usage:
62
64
  ```python
63
65
  ParticleGroup(start_id: int, size: int)
sonolus/script/project.py CHANGED
@@ -10,6 +10,7 @@ from sonolus.backend.optimize import optimize
10
10
  from sonolus.backend.optimize.passes import CompilerPass
11
11
  from sonolus.script.archetype import ArchetypeSchema
12
12
  from sonolus.script.engine import Engine
13
+ from sonolus.script.internal.context import RuntimeChecks
13
14
  from sonolus.script.level import ExternalLevelData, Level, LevelData
14
15
 
15
16
 
@@ -66,7 +67,7 @@ class Project:
66
67
  from sonolus.build.cli import run_server
67
68
 
68
69
  if config is None:
69
- config = BuildConfig()
70
+ config = BuildConfig(runtime_checks=RuntimeChecks.NOTIFY_AND_TERMINATE)
70
71
 
71
72
  run_server(
72
73
  Path(build_dir) / "site",
@@ -145,3 +146,6 @@ class BuildConfig:
145
146
 
146
147
  override_resource_level_engines: bool = True
147
148
  """Whether to override any levels included in resources to use the engine of this project."""
149
+
150
+ runtime_checks: RuntimeChecks = RuntimeChecks.NONE
151
+ """Runtime error checking mode."""
sonolus/script/sprite.py CHANGED
@@ -126,6 +126,8 @@ class Sprite(Record):
126
126
  class SpriteGroup(Record, ArrayLike[Sprite]):
127
127
  """A group of sprites.
128
128
 
129
+ Does not support negative indexes.
130
+
129
131
  Usage:
130
132
  ```python
131
133
  SpriteGroup(start_id: int, size: int)
sonolus/script/stream.py CHANGED
@@ -6,6 +6,7 @@ from typing import cast, dataclass_transform
6
6
  from sonolus.backend.ir import IRConst, IRExpr, IRInstr, IRPureInstr
7
7
  from sonolus.backend.mode import Mode
8
8
  from sonolus.backend.ops import Op
9
+ from sonolus.script.array_like import check_positive_index
9
10
  from sonolus.script.internal.context import ctx
10
11
  from sonolus.script.internal.descriptor import SonolusDescriptor
11
12
  from sonolus.script.internal.impl import meta_fn
@@ -469,6 +470,8 @@ class Stream[T](Record):
469
470
  class StreamGroup[T, Size](Record):
470
471
  """Represents a group of streams.
471
472
 
473
+ Does not support negative indexes.
474
+
472
475
  Most users should use [`@streams`][sonolus.script.stream.streams] to declare stream groups rather than using this
473
476
  class directly.
474
477
 
@@ -506,9 +509,12 @@ class StreamGroup[T, Size](Record):
506
509
  return 0 <= item < self.size()
507
510
 
508
511
  def __getitem__(self, index: int) -> Stream[T]:
509
- """Get the stream at the given index."""
512
+ """Get the stream at the given index.
513
+
514
+ Does not support negative indexes.
515
+ """
510
516
  _check_can_read_or_write_stream()
511
- assert index in self
517
+ check_positive_index(index, self.size())
512
518
  # Size 0 elements still need 1 stream to preserve the key.
513
519
  t = self.type_var_value(T)
514
520
  return Stream[t](max(1, sizeof(self.element_type())) * index + self.offset)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sonolus.py
3
- Version: 0.10.2
3
+ Version: 0.10.4
4
4
  Summary: Sonolus engine development in Python
5
5
  Project-URL: Documentation, https://sonolus.py.qwewqa.xyz/
6
6
  Project-URL: Repository, https://github.com/qwewqa/sonolus.py
@@ -26,23 +26,23 @@ sonolus/backend/optimize/passes.py,sha256=YyFKy6qCwcR_Ua2_SXpcBODfvBbm_ygVYcqloO
26
26
  sonolus/backend/optimize/simplify.py,sha256=wvhixe0SfditrGMh0nX0Wt0JR00JqAmz4BKBzMoBAVI,14701
27
27
  sonolus/backend/optimize/ssa.py,sha256=raQO0furQQRPYb8iIBKfNrJlj-_5wqtI4EWNfLZ8QFo,10834
28
28
  sonolus/build/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
- sonolus/build/cli.py,sha256=GQHzXGj55pqz84AnOKa21t74Nrbt7gUKfQe88gXIKtI,9357
29
+ sonolus/build/cli.py,sha256=t6oK0SGU6fkxXVbGu6OuRIHDKD6u4SqXAShdPtatZ-8,10060
30
30
  sonolus/build/collection.py,sha256=6hniAzriPWBKUeGDkXabNXpbdHiHnqiK9shs6U1OExM,12748
31
31
  sonolus/build/compile.py,sha256=KOmncDKmGfgzC_FWB_LTxAl0s9w4wnaDe-luACMlCVs,8397
32
- sonolus/build/dev_server.py,sha256=EOnIgAkFZAKiCwhFqDyKMLkJfYtGdjlacqYWZ2F2mAU,9891
33
- sonolus/build/engine.py,sha256=No_q4O6PRMwxEPHvSlbaBKVe5CXJswWFZdR3xgfIuI8,14672
32
+ sonolus/build/dev_server.py,sha256=HOFFlG8eWnhZnYiYUBokyDoIPXjj26zG57fm99Mm_YM,10119
33
+ sonolus/build/engine.py,sha256=jMymxbBXu-ekv71uU8TF2KbFaHs3yGjyJAztd1SoRDs,14808
34
34
  sonolus/build/level.py,sha256=KLqUAtxIuIqrzeFURJA97rdqjA5pcvYSmwNZQhElaMQ,702
35
35
  sonolus/build/node.py,sha256=gnX71RYDUOK_gYMpinQi-bLWO4csqcfiG5gFmhxzSec,1330
36
36
  sonolus/build/project.py,sha256=Uuz82QtTNFdklrVJ_i7EPp8hSjyOxLU1xAeOloa6G00,8579
37
37
  sonolus/script/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
38
  sonolus/script/archetype.py,sha256=ck_LR8z0ipVq3T9b735VwvQI2mxVUyjHylr4BFagXT8,49631
39
- sonolus/script/array.py,sha256=0ZUI0alrwKztpQOpZodZPSPafu5cGwaiffBGQbY19LQ,13316
39
+ sonolus/script/array.py,sha256=EbrNwl_WuJ0JjjkX0s_VJNXWqvYdm_ljTbyrDEMLGUY,13348
40
40
  sonolus/script/array_like.py,sha256=E6S4TW2muXgcyVkhUASQVt7JSYUkpvdJPgHz6YiSHNo,14708
41
41
  sonolus/script/bucket.py,sha256=yIod3DgX7Hv7RLe-4Cn81FcydvbkbdMt26FzpRj7oUI,7794
42
- sonolus/script/containers.py,sha256=qKIyTs5Q_UpQggR6s0AfgWQAvPv-IM2DW9s951koKSc,19303
43
- sonolus/script/debug.py,sha256=YOq06q5ahWI-uEG5naonOBWF62Qn_Af7JSV_Ra8Zr6E,7415
42
+ sonolus/script/containers.py,sha256=nPjyyLmGnTxndMipqdfJ9CxmIT09wNLRQM7efagtZHI,19417
43
+ sonolus/script/debug.py,sha256=yYg6EZt3NUOUeph1pu_5cA_2lxs8SZ91v76eOC1Sw-8,7747
44
44
  sonolus/script/easing.py,sha256=2FUJI_nfp990P_armCcRqHm2329O985glJAhSC6tnxs,11379
45
- sonolus/script/effect.py,sha256=aOxhBmX6I8vUS-bE53YFNBEN3wwdmpraqZjLeCqbgIY,7920
45
+ sonolus/script/effect.py,sha256=SfJxSNF3RlPCRXnkt62ZlWhCXw3mmmRCsoMsvTErUP0,7960
46
46
  sonolus/script/engine.py,sha256=etI9dJsQ7V9YZICVNZg54WqpLijPxG8eTPHiV-_EiG8,10687
47
47
  sonolus/script/globals.py,sha256=nlXSNS4NRXsgQU2AJImVIs752h1WqsMnShSKgU011c4,10270
48
48
  sonolus/script/instruction.py,sha256=Dd-14D5Amo8nhPBr6DNyg2lpYw_rqZkT8Kix3HkfE7k,6793
@@ -53,15 +53,15 @@ sonolus/script/maybe.py,sha256=VYvTWgEfPzoXqI3i3zXhc4dz0pWBVoHmW8FtWH0GQvM,8194
53
53
  sonolus/script/metadata.py,sha256=ttRK27eojHf3So50KQJ-8yj3udZoN1bli5iD-knaeLw,753
54
54
  sonolus/script/num.py,sha256=9pahERQcIh16ytoDjJB3u3L6fH1Xh11Y99l8SYxkjMA,15927
55
55
  sonolus/script/options.py,sha256=05y_4j2kr8fzct5FLqmSp5ZAjnq6-slmNgtsh4fVEpg,9451
56
- sonolus/script/particle.py,sha256=BuBM7fvLAj79upLf9yI4FyZhVUK7-H2dFj0D7UiYS7I,10458
56
+ sonolus/script/particle.py,sha256=3HbxehuW7Fdri3s8NenGxiwxVU7tVDH8SQ4VyCc0wMk,10498
57
57
  sonolus/script/pointer.py,sha256=FoOfyD93r0G5d_2BaKfeOT9SqkOP3hq6sqtOs_Rb0c8,1511
58
58
  sonolus/script/printing.py,sha256=mNYu9QWiacBBGZrnePZQMVwbbguoelUps9GiOK_aVRU,2096
59
- sonolus/script/project.py,sha256=4svmMWYihF7olmYSMS5uoSjlnzbd7Ip2zTRY86oL1L8,4629
59
+ sonolus/script/project.py,sha256=YouKKm6Z9PpwbO9aSA2syZqFv_j1DShVGlENUT565Js,4831
60
60
  sonolus/script/quad.py,sha256=8lZ_5-eWeqePldNGBkNZTuOgS_IRb41URgGwSW4h2T0,14445
61
61
  sonolus/script/record.py,sha256=BrQ8k-O4WX9FT_EfoRmNnKC1BZM9gWydZ4R4swh3chc,13051
62
62
  sonolus/script/runtime.py,sha256=TjxcfIIPRH6oxlEjWfLHDj1oo7fPfwTBdwETfnhN7h4,33331
63
- sonolus/script/sprite.py,sha256=d_wqUn7oMbkLZMdvnyDZVBykycTtiwegcarWXMcZMUI,18408
64
- sonolus/script/stream.py,sha256=Fu02SNjH8j1FQ9_7ncacR9uRIhoWtAZR-sTi8qBT7rA,24707
63
+ sonolus/script/sprite.py,sha256=KhQNnq0wKm1tDMQTrlZIr0mL0jPCfojTORzsCK5qO1o,18448
64
+ sonolus/script/stream.py,sha256=Yot99RLKqJN1XK3x5s_qeV-50qEtuG2U6zbEPWLyvW8,24879
65
65
  sonolus/script/text.py,sha256=wxujIgKYcCfl2AD2_Im8g3vh0lDEHYwTSRZg9wsBPEU,13402
66
66
  sonolus/script/timing.py,sha256=DklMvuxcFg3MzXsecUo6Yhdk7pScOJ7STwXvAiTvLKM,3067
67
67
  sonolus/script/transform.py,sha256=4aS7-NNzX0v9KMXZ4gIGOaU1Cd-ok7DO_OvIBca0mGU,21418
@@ -72,7 +72,7 @@ sonolus/script/internal/__init__.py,sha256=T6rzLoiOUaiSQtaHMZ88SNO-ijSjSSv33TKtU
72
72
  sonolus/script/internal/builtin_impls.py,sha256=tpNbaH6fLICd8TYj9Hf_wrPSWk3RkhmSPVN9nqOuqj4,13372
73
73
  sonolus/script/internal/callbacks.py,sha256=vWzJG8uiJoEtsNnbeZPqOHogCwoLpz2D1MnHY2wVV8s,2801
74
74
  sonolus/script/internal/constant.py,sha256=3ycbGkDJVUwcrCZ96vLjAoAARgsvaqDM8rJ_YCrLrvo,4289
75
- sonolus/script/internal/context.py,sha256=C0VMHBRppsnwPDVPc03Lpz7tO9djQMB5ELdtpFPMdsk,18779
75
+ sonolus/script/internal/context.py,sha256=56pPjiPy8ZaxY3t5iEufsOMEj6BSy31G-5SoYqS6tPo,19694
76
76
  sonolus/script/internal/descriptor.py,sha256=XRFey-EjiAm_--KsNl-8N0Mi_iyQwlPh68gDp0pKf3E,392
77
77
  sonolus/script/internal/dict_impl.py,sha256=alu_wKGSk1kZajNf64qbe7t71shEzD4N5xNIATH8Swo,1885
78
78
  sonolus/script/internal/error.py,sha256=ZNnsvQVQAnFKzcvsm6-sste2lo-tP5pPI8sD7XlAZWc,490
@@ -87,8 +87,8 @@ sonolus/script/internal/simulation_context.py,sha256=LGxLTvxbqBIhoe1R-SfwGajNIDw
87
87
  sonolus/script/internal/transient.py,sha256=y2AWABqF1aoaP6H4_2u4MMpNioC4OsZQCtPyNI0txqo,1634
88
88
  sonolus/script/internal/tuple_impl.py,sha256=DPNdmmRmupU8Ah4_XKq6-PdT336l4nt15_uCJKQGkkk,3587
89
89
  sonolus/script/internal/value.py,sha256=OngrCdmY_h6mV2Zgwqhuo4eYFad0kTk6263UAxctZcY,6963
90
- sonolus_py-0.10.2.dist-info/METADATA,sha256=07hKS146L3Ck4bScU9kbuWDHtIrExXvCIlygmvfxCbE,554
91
- sonolus_py-0.10.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
92
- sonolus_py-0.10.2.dist-info/entry_points.txt,sha256=oTYspY_b7SA8TptEMTDxh4-Aj-ZVPnYC9f1lqH6s9G4,54
93
- sonolus_py-0.10.2.dist-info/licenses/LICENSE,sha256=JEKpqVhQYfEc7zg3Mj462sKbKYmO1K7WmvX1qvg9IJk,1067
94
- sonolus_py-0.10.2.dist-info/RECORD,,
90
+ sonolus_py-0.10.4.dist-info/METADATA,sha256=466Gjf9XnGo8ax6wyh37RiRma9X0foDPqGlBUaFJv-Y,554
91
+ sonolus_py-0.10.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
92
+ sonolus_py-0.10.4.dist-info/entry_points.txt,sha256=oTYspY_b7SA8TptEMTDxh4-Aj-ZVPnYC9f1lqH6s9G4,54
93
+ sonolus_py-0.10.4.dist-info/licenses/LICENSE,sha256=JEKpqVhQYfEc7zg3Mj462sKbKYmO1K7WmvX1qvg9IJk,1067
94
+ sonolus_py-0.10.4.dist-info/RECORD,,