Skip to content

Commit a2da876

Browse files
committed
fix coverage
1 parent 387c180 commit a2da876

4 files changed

Lines changed: 496 additions & 10 deletions

File tree

pyproject.toml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,10 @@ check = [
191191
'bun run --cwd "{root}/src/js/packages/@reactpy/client" checkTypes',
192192
'bun run --cwd "{root}/src/js/packages/@reactpy/app" checkTypes',
193193
]
194-
fix = ['bun install --cwd "{root}/src/js"', 'bun run --cwd "{root}/src/js" format']
194+
fix = [
195+
'bun install --cwd "{root}/src/js"',
196+
'bun run --cwd "{root}/src/js" format',
197+
]
195198
test = ['hatch run javascript:build_event_to_object --dev', 'bun test']
196199
build = [
197200
'hatch run "{root}/src/build_scripts/clean_js_dir.py"',
@@ -206,7 +209,9 @@ build = [
206209
build_event_to_object = [
207210
'hatch run "{root}/src/build_scripts/build_js_event_to_object.py" {args}',
208211
]
209-
build_client = ['hatch run "{root}/src/build_scripts/build_js_client.py" {args}']
212+
build_client = [
213+
'hatch run "{root}/src/build_scripts/build_js_client.py" {args}',
214+
]
210215
build_app = ['hatch run "{root}/src/build_scripts/build_js_app.py" {args}']
211216
publish_event_to_object = [
212217
'hatch run javascript:build_event_to_object',

src/build_scripts/install_deps.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def install_deps():
3737
DEPENDENCIES.discard(
3838
"ruff"
3939
) # ruff only exists in dev dependencies for CI purposes.
40-
subprocess.run(["uv", "pip", "install", "-U", *DEPENDENCIES], check=False) # noqa: S607
40+
subprocess.run(["uv", "pip", "install", "-U", *DEPENDENCIES], check=False) # noqa: S607,S603
4141

4242

4343
if __name__ == "__main__":

src/reactpy/core/_event_inspect.py

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
"""
2+
In order to retain a JavaScript-like event handler API, ReactPy allows users to configure event handlers with `event.debounce = <milliseconds>`.
3+
Implementing this syntax necessitates inspecting the bytecode of event handler functions.
4+
"""
5+
16
from __future__ import annotations
27

38
import dis
@@ -76,11 +81,13 @@ def inspect_event_handler(func: Callable) -> tuple[bool, bool, int | None]:
7681
continue
7782

7883
# CPython 3.11+ may fuse ``LOAD_FAST value; LOAD_FAST target`` into
79-
# the superinstruction ``LOAD_FAST_BORROW_LOAD_FAST_BORROW`` whose
80-
# argval is ``(value_name, target_name)``. Treat it like a normal
81-
# event load when the target matches.
84+
# a superinstruction whose argval is ``(value_name, target_name)``.
85+
# Two variants may appear depending on the interpreter:
86+
# * ``LOAD_FAST_LOAD_FAST`` (CPython 3.13+)
87+
# * ``LOAD_FAST_BORROW_LOAD_FAST_BORROW`` (CPython 3.14+)
88+
# Treat either as a normal event load when the target matches.
8289
if (
83-
instr.opname == "LOAD_FAST_BORROW_LOAD_FAST_BORROW"
90+
instr.opname in ("LOAD_FAST_LOAD_FAST", "LOAD_FAST_BORROW_LOAD_FAST_BORROW")
8491
and isinstance(instr.argval, (list, tuple))
8592
and len(instr.argval) == _LOAD_FAST_BORROW_PAIR_SIZE
8693
and instr.argval[1] == event_arg_name
@@ -209,8 +216,11 @@ def _resolve_debounce_value(
209216
prev = instructions[store_index - 1]
210217

211218
# CPython 3.11+ superinstruction: argval is ``(value_name, target_name)``.
212-
# The value comes from a function argument default.
213-
if prev.opname == "LOAD_FAST_BORROW_LOAD_FAST_BORROW":
219+
# The value comes from a function argument default. Two superinstructions
220+
# may appear here depending on the interpreter version:
221+
# * ``LOAD_FAST_LOAD_FAST`` (CPython 3.13+)
222+
# * ``LOAD_FAST_BORROW_LOAD_FAST_BORROW`` (CPython 3.14+)
223+
if prev.opname in ("LOAD_FAST_LOAD_FAST", "LOAD_FAST_BORROW_LOAD_FAST_BORROW"):
214224
names = prev.argval
215225
if isinstance(names, Iterable) and not isinstance(names, str):
216226
names = list(names)
@@ -226,7 +236,16 @@ def _resolve_debounce_value(
226236
val_instr = instructions[store_index - 2]
227237
target_instr = prev
228238

229-
if target_instr.opname not in ("LOAD_FAST", "LOAD_FAST_BORROW"):
239+
if target_instr.opname not in (
240+
"LOAD_FAST",
241+
"LOAD_FAST_BORROW",
242+
# CPython 3.13+ may fuse two ``LOAD_FAST`` instructions into
243+
# ``LOAD_FAST_LOAD_FAST`` whose argval is ``(value_name, target_name)``.
244+
# The detector above already covers this case for debounce values,
245+
# but the standalone form can also appear if the value isn't a
246+
# default and the event is loaded separately.
247+
"LOAD_FAST_LOAD_FAST",
248+
):
230249
return None
231250
if target_instr.argval != event_arg_name:
232251
return None

0 commit comments

Comments
 (0)