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

source-academy / py-slang / 32939238869
86%

Build:
DEFAULT BRANCH: main
Ran 26 Aug 2026 06:56AM UTC
Jobs 1
Files 139
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 Aug 2026 06:41AM UTC coverage: 85.61% (+0.02%) from 85.592%
32939238869

push

github

web-flow
Stepper: a def-local reassignment shadows the whole function body (#448)

* Stepper: a def-local reassignment shadows the whole function body (#447)

Python decides a name is local to a function from every assignment in its
body, not just the ones textually before a given read. The substitution
stepper's substitute() only skipped a def's own name/parameters when
deciding whether to substitute an outer binding into its body, so an outer
z = 2 was baked into print(z) even though f() later reassigns z, making z
local throughout f and that read an UnboundLocalError in real Python.

substitute() now also skips a def whose body assigns the name anywhere
(ast.ts's new assignedNamesOf, a recursive scan reusing declaredNamesOf).
The now-unsubstituted identifier is caught at reduction time: reduceExpr's
Identifier case raises UnboundLocalError for any non-builtin bare name
instead of treating it as an inert value, and statement-level assignment
binding (isReadyValue) forces that same check before aliasing such a name
into another variable, so the error can't be silently bypassed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Stepper: fix formatting, self-name shadowing, and NameError vs UnboundLocalError

Addresses CodeRabbit review on #448:

- prettier formatting (a wrapped line in the new getSteps.test.ts describe
  block failed yarn format:ci).
- A def that reassigns its own name (def f(): print(f); f = 3) was still
  resolving the early f to the function value, since contractCall's selfName
  binding substituted unconditionally rather than checking assignedNamesOf
  like substitute()'s own FunctionDeclaration case does.
- Every unresolved non-builtin identifier was reported as UnboundLocalError,
  even a name never bound anywhere in the program (a NameError in real
  Python). substitute/markUnboundLocal (ast.ts) now tag specifically the
  occurrences left behind for local-shadowing reasons with an `unboundLocal`
  flag; reduceExpr's Identifier... (continued)

4839 of 6077 branches covered (79.63%)

Branch coverage included in aggregate %.

32 of 32 new or added lines in 2 files covered. (100.0%)

2 existing lines in 2 files now uncovered.

10825 of 12220 relevant lines covered (88.58%)

161646.44 hits per line

Coverage Regressions

Lines Coverage ∆ File
1
96.36
-0.61% src/conductor/stepper/getSteps.ts
1
94.66
-0.05% src/conductor/stepper/reduce.ts
Jobs
ID Job ID Ran Files Coverage
1 32939238869.1 26 Aug 2026 06:56AM UTC 139
85.61
GitHub Action Run
Source Files on build 32939238869
  • Tree
  • List 139
  • Changed 3
  • Source Changed 2
  • Coverage Changed 3
Coverage ∆ File Lines Relevant Covered Missed Hits/Line Branch Hits Branch Misses
  • Back to Repo
  • Github Actions Build #32939238869
  • 5d7ed7a0 on github
  • Prev Build on main (#32512435957)
  • Next Build on main (#33248548384)
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