• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

source-academy / py-slang / 30200213350
86%

Build:
DEFAULT BRANCH: main
Ran 26 Jul 2026 11:41AM UTC
Jobs 1
Files 116
Run time 1min
Badge
Embed ▾
README BADGES
x

If you need to use a raster PNG badge, change the '.svg' to '.png' in the link

Markdown

Textile

RDoc

HTML

Rst

26 Jul 2026 11:29AM UTC coverage: 86.135% (+0.01%) from 86.125%
30200213350

push

github

web-flow
py2js: closure_call_sync fast path for module closures called from Python (#353)

* py2js: give module closures crossing into Python a closure_call_sync fast path

moduleToPython's DataType.CLOSURE case (a module function imported into
Python, e.g. `from math import sqrt`) always built an asyncOnly PyFunction:
a defensive-backstop sync body that unconditionally threw, and an async
body that unconditionally paid the mandatory async-generator tax via
closure_call_unchecked - even for a closure that carries a `.sync` twin
proving it never needs a real host round-trip.

That fast path already exists and is already generic: GenericDataHandler.
closure_call_sync looks up a closure's underlying function in closureMap
and calls its `.sync` twin directly if present, regardless of whether the
closure originated from a module or from Python - it's the same mechanism
pythonToModule's `.sync` attach already uses for the opposite direction
(a Python closure crossing into a module, e.g. sound's wave sampling).
Only the moduleToPython side never attempted it.

The sync body now tries dh.closure_call_sync first (converting arguments/
result through the same restricted scalar converters, moduleToPythonSync/
pythonToModuleSync, the other direction's fast path already uses), and
falls back to the exact same "needs a frontend round-trip" error only when
no `.sync` twin is available for that specific call - a dynamic, per-call
decision now, rather than the fixed asyncOnly flag that used to reject
every sync call unconditionally regardless of what the closure was capable
of. The asyncBody fallback is unchanged.

Motivated by the modules repo's pix_n_flix migration: a redesigned pixel
API (get_pixel_value/set_pixel_value over an opaque image handle) needs to
be called from inside a student's filter up to width*height*8 times per
frame - the same shape of hot loop as sound's per-sample wave callback,
just the reverse direction across the module boundary. Depends on
source-aca... (continued)

4409 of 5511 branches covered (80.0%)

Branch coverage included in aggregate %.

15 of 17 new or added lines in 1 file covered. (88.24%)

9563 of 10710 relevant lines covered (89.29%)

178044.66 hits per line

Uncovered Changes

Lines Coverage ∆ File
2
83.23
1.48% src/engines/py2js/moduleInterop.ts
Jobs
ID Job ID Ran Files Coverage
1 30200213350.1 26 Jul 2026 11:41AM UTC 116
86.14
GitHub Action Run
Source Files on build 30200213350
  • Tree
  • List 116
  • Changed 1
  • Source Changed 1
  • Coverage Changed 1
Coverage ∆ File Lines Relevant Covered Missed Hits/Line Branch Hits Branch Misses
  • Back to Repo
  • Github Actions Build #30200213350
  • f91e4d23 on github
  • Prev Build on main (#30162144554)
  • Next Build on main (#30200231867)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc