Repository navigation
Conversation
* Add recursion guard to the c-api * Do not change with_recursion as this has side effects
…thon#8953) Let quote-only fields use the existing unquoted escaping path and enable the existing CPython regression test. Tested: test_csv, CSV snippet, 240 CPython comparisons, workspace and C-API tests, Clippy, prek Assisted-by: Codex:gpt-6.1-sol
* Release replaced list item outside the lock in STORE_SUBSCR_LIST_INT Assisted-by: Claude Code:claude-opus-5-5 * Add a snippet for finalizers reading a list during a specialized store Assisted-by: Claude Code:claude-opus-5-5
…n#8960) Return the context's canonical None singleton when standard streams are disabled. Check the exact set type before accessing user-rebindable conditional-annotation tracking objects. Both fixes apply to the unchanged Python 3.14 target. Include the no-stdio embedding regression and the unchanged canonical regression from CPython's 3.14 maintenance backport c21e7c45, after the vulnerable 3.14.7 tag. Extracted from the larger 3.15 migration; no marshal or version changes. Assisted-by: Codex:model-version-unavailable
* Use populated entries for unpickler MEMOIZE indexes A sparse BINPUT followed by MEMOIZE must use the number of occupied memo entries, not the largest index plus one. Store populated entries in a map, preserve ascending memo copies, reserve fallibly, and release displaced references after memo guards end. Keep existing memo assignment/proxy behavior and add one bounded regression for sparse BINPUT, MEMOIZE identity and copy order. No protocol version, GC traversal or unrelated pickle input changes are included. Extracted from the Python 3.15 migration onto the unchanged 3.14 target. Assisted-by: Codex:model-version-unavailable * Move sparse memo regression to standard pickle snippet Use the module-level snippet name requested in review without changing the regression assertions. Assisted-by: Codex:model-version-unavailable
…on#8964) Assisted-by: Codex:gpt-6
…hon#8965) Read the stored executable address when casting a function pointer and accept function pointer types as cast destinations. The existing ownership dictionary retains the original callback through a cast roundtrip. Extracted independently on the unchanged Python 3.14 target, without typed callback argument or broader py_object transport changes. One unique callback-address/ownership regression extends the existing ctypes snippet; canonical coverage was checked for duplicates. Assisted-by: Codex:model-version-unavailable
* Implement the sentinel builtin from PEP 661 Add unique sentinel values with copy/pickle identity, caller module capture, union support, and cycle collection. Compare constructor behavior and six upstream tests with CPython v3.15.0rc2; retain the existing Python target and bundled libraries. Assisted-by: Codex:model-version-unavailable * Remove duplicate sentinel snippet tests Rely on the canonical Lib/test/test_builtin.py sentinel cases when the standard library is updated, as requested in PR RustPython#8945 review. Remove the custom snippet without changing the runtime implementation or existing standard-library tests. Assisted-by: Codex:model-version-unavailable
…hon#8946) * Add the eager-runtime importlib lazy-attribute hook Expose _imp._set_lazy_attributes(modobj, name, /), used by CPython 3.15 importlib after eager loading. Match its empty pending-lazy-module registry behavior, including name type and string-subclass hashing checks. This does not implement lazy imports or change the target version or bundled libraries. Assisted-by: Codex:model-version-unavailable * Consolidate lazy import hook tests into stdlib_imp Move the distinct direct-hook argument and hashing contracts into the existing _imp snippet and remove the separate file. Preserve every pre-existing assertion and the CPython version guard; canonical 3.15 lazy-import tests already cover feature-level registry and reification behavior. Assisted-by: Codex:model-version-unavailable
…#8967) * Match CPython's str subscript TypeError message `str.__getitem__` with a non-index key raised the shared sequence wording ("str indices must be integers or slices or classes that override __index__ operator, not 'x'") instead of CPython's str-specific "string indices must be integers, not 'x'" (bpo-44110 / gh-88276, Python 3.11). Add `SequenceIndex::try_from_borrowed_object_with_err`, which takes a caller-supplied error closure, and have the existing `try_from_borrowed_object` delegate to it with the unchanged shared message. `str._getitem` now supplies the CPython-accurate message, which flows through both `__getitem__` and the mapping subscript slot. Other sequence types keep the shared wording. Removes the expectedFailure marker on `string_tests.StringLikeTest.test_subscript`, fixing it for both test_str and test_userstring. Co-Authored-By: Claude Opus 4.8 <[email protected]> * Fold str's subscript TypeError into the shared index helper The previous commit added `SequenceIndex::try_from_borrowed_object_with_err` (a closure-taking function) so `str` could raise CPython's "string indices must be integers, not ..." message. Per review, a whole helper API plus a thin wrapper was overkill for a single caller. Instead, inline that one error case into `try_from_borrowed_object`: when `type_name` is "str", raise the str-specific message; every other type keeps the shared sequence wording. `str._getitem` goes back to the plain `match` over `SequenceIndex` with no duplicated index parsing. A bad slice key (e.g. `'a'[::'x']`) still surfaces the slice-specific error, since only the non-index/non-slice branch is customized. Co-Authored-By: Claude Opus 4.8 <[email protected]> * Truncate index TypeError type names to 200 characters Route str's non-index TypeError through a function pointer message helper. Sequence index errors use the same 200-character type-name cap. Assisted-by: Grok:4.6 * Encode sequence index TypeError names as type params `&'static str` cannot be a const generic. SequenceIndexName holds the name as an associated constant, matching ArgName. Both str and sequence errors go through one fn(&str) -> String and a cold TypeError helper. Assisted-by: Grok:4.6 --------- Co-authored-by: Jaedeok Kim <[email protected]> Co-authored-by: Claude Opus 4.8 <[email protected]>
…n#8948) * Reorder the module cache atomically during imports Add a private exact-dict move primitive and importlib dispatcher so shutdown-order updates never temporarily remove a module. Preserve current values and custom-mapping fallback behavior; validate reentrant equality probe witnesses, invalidate layout caches, and compact moved entries. Cover all four existing bootstrap reorder sites, including legacy-loader cleanup. Add deterministic trace-window, loader replacement/removal, reentrancy, cache, iterator and compaction regressions. The private native primitive uses true-move semantics; it does not promise arbitrary pop/set callback equivalence. Assisted-by: Codex:model-version-unavailable * Keep atomic import regression compatible with modern bootstrap Run legacy-loader cases when the bootstrap exposes that helper, preserving all four 3.14 paths and the two remaining 3.15 paths. Always retain modern load and exec regressions. Assisted-by: Codex:model-version-unavailable * Keep the copied bootstrap unchanged in the native relocation PR Restore the exact CPython 3.14 bootstrap and retain only the private exact-dict relocation primitive and its direct native regressions. Remove the PR-added callback integration tests while preserving native helper assertions. This prepares a primitive only; imports do not call it and the import race remains unresolved. Assisted-by: Codex:model-version-unavailable
…thon#8969) Bumps [https://github.com/rbubley/mirrors-prettier](https://github.com/rbubley/mirrors-prettier) from v3.9.8 to 3.9.9. - [Commits](rbubley/mirrors-prettier@v3.9.8...v3.9.9) --- updated-dependencies: - dependency-name: https://github.com/rbubley/mirrors-prettier dependency-version: 3.9.9 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…ustPython#8975) Bumps [github/gh-aw/actions/setup](https://github.com/github/gh-aw) from 0.89.17 to 0.89.21. - [Release notes](https://github.com/github/gh-aw/releases) - [Changelog](https://github.com/github/gh-aw/blob/main/CHANGELOG.md) - [Commits](github/gh-aw@0045747...c353937) --- updated-dependencies: - dependency-name: github/gh-aw/actions/setup dependency-version: 0.89.21 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…ython#8970) Bumps [https://github.com/astral-sh/ruff-pre-commit](https://github.com/astral-sh/ruff-pre-commit) from v0.16.8 to 0.16.9. - [Release notes](https://github.com/astral-sh/ruff-pre-commit/releases) - [Commits](astral-sh/ruff-pre-commit@v0.16.8...v0.16.9) --- updated-dependencies: - dependency-name: https://github.com/astral-sh/ruff-pre-commit dependency-version: 0.16.9 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…tPython#8968) * Order chmod's arguments the way CPython declares them posix.chmod took dir_fd between path and mode. Since RustPython#8807 renders each argument's parameter kind, that put `/` after `*`, which inspect cannot parse, and path and mode stayed positional-only, so os.chmod(path=..., mode=...) raised TypeError. A ChmodArgs struct follows CPython's order, as nt.chmod already does. path and mode are positional-or-keyword. follow_symlinks shows CPython's text through py_default, like LinkArgs. Assisted-by: Claude Code:claude-opus-5 * Reject a text signature that puts `/` after `*` or `**` The writer counts positional-only parameters up front and emits `/` when they run out, which assumes they come first in the Rust argument list. Nothing enforced that, and posix.chmod violated it. The signature is composed in a const context, so the assert fails the build and names the fix. Assisted-by: Claude Code:claude-opus-5
* Give dict a CPython-style message for unhashable keys Dict operations (subscription, membership, get/pop/setdefault, ...) now raise "cannot use 'X' as a dict key (unhashable type: 'X')", matching CPython 3.14 and mirroring the existing PySetInner wrapping. The key is only materialized on the error path, so hashable keys pay no extra cost. Enables Lib/test/test_dict.py::DictTest::test_unhashable_key. Assisted-by: Claude Opus 4.8 (Anthropic) * dict: only rewrite hashing failures, not key-comparison errors wrap_unhashable_error previously rewrote any TypeError from a dict operation as an unhashable-key error, but those operations also compare keys on a hash collision, so a TypeError from a colliding key's __eq__ was mislabeled. Disambiguate on the error path by re-hashing the key, so the successful path still hashes exactly once (keeps the do-not-rehash / atomic invariants) while comparison errors propagate unchanged. Adds a colliding-key regression test. Assisted-by: Claude Opus 4.8 (Anthropic) * dict: hash unhashable keys once up front and cover every insertion path Addresses the review feedback (thanks @luantaraschi): - The message now reaches update(), the constructor and |= as well, not just __setitem__: merge_object_with_override and merge_from_seq2 now hash the key up front and thread it into contains_known_hash/insert_known_hash. - Hash the key once instead of re-hashing on the error path. This threads the hash through the *_known_hash operations (add dict_inner get_known_hash), so a __hash__ that fails only on its first call is still reported instead of escaping unwrapped. - Use the fully-qualified type name (matching CPython's %T). - Only an exact TypeError is rewritten; a __hash__ raising a TypeError subclass now propagates unchanged. pop() and setdefault() have no *_known_hash entry point on the inner map, so they hash once up front for the message and then do their own single lookup. Assisted-by: Claude Opus 4.8 * dict: thread the known hash through setdefault and pop as well Follow-up on the review: setdefault() and pop() previously hashed the key a second time (inside the inner map) after hash_or_unhashable already hashed it, so a stateful __hash__ failing on the second call would skip the dict-specific message. Add setdefault_known_hash / pop_known_hash to the inner map and thread the precomputed hash, so every operation now hashes exactly once. Adds a regression test asserting setdefault/pop call __hash__ only once. Assisted-by: Claude Opus 4.8 * test: hash the key on a non-empty dict so CPython 3.14 exercises the pop path `{}.pop(CountingHash())` on an empty dict does not hash the key under CPython 3.14 (the lookup short-circuits), so `CountingHash.calls == 1` was 0 and the snippet failed its CPython parity run. Use a non-empty dict so the lookup must hash the key exactly once, on both CPython and RustPython. Also applied `ruff format` (two blank lines before top-level defs). Assisted-by: Claude Opus 4.8 (Anthropic) * dict: drop unused internal pop wrapper Per review, the vm-taking Dict::pop wrapper was dead code (#[allow(dead_code)], kept only for API symmetry) with no callers. Remove it and fold its doc into pop_known_hash. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> * dict: rename pop_known_hash to pop Per review, with the plain pop gone the _known_hash suffix no longer earns its keep, so drop it. Matches the remaining known-hash helpers that still pair with a base method. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> * dict: fold setdefault wrapper into setdefault, drop unused setdefault_entry Per review, apply the same pattern as pop: the dead setdefault wrapper only hashed and delegated, so remove it and rename setdefault_known_hash to setdefault (callers already thread the hash). Also drop setdefault_entry, which this PR added but nothing uses. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> * dict: use set_cause and Result from fully_qualified_name After rebasing onto main, fully_qualified_name returns PyResult and set___cause__ is a private Python setter. Assisted-by: Grok:4.6 * dict_inner: take a hash for every key operation Drop the hashing wrappers and *_known_hash aliases. Callers hash the key and pass it in. Assisted-by: Grok:4.6 * snippets: add blank line before BadEq class ruff format requires two blank lines before a top-level class. Assisted-by: Grok:4.6 --------- Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]> Co-authored-by: Jeong YunWon <[email protected]>
Bumps [siphasher](https://github.com/jedisct1/rust-siphash) from 1.0.3 to 1.0.4. - [Commits](jedisct1/rust-siphash@1.0.3...1.0.4) --- updated-dependencies: - dependency-name: siphasher dependency-version: 1.0.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [glob](https://github.com/rust-lang/glob) from 0.3.3 to 0.3.4. - [Release notes](https://github.com/rust-lang/glob/releases) - [Changelog](https://github.com/rust-lang/glob/blob/master/CHANGELOG.md) - [Commits](rust-lang/glob@v0.3.3...v0.3.4) --- updated-dependencies: - dependency-name: glob dependency-version: 0.3.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Match invalid format specifier error details Assisted-by: Codex:gpt-5.6-sol * format: convert FormatSpecError in one helper InvalidFormatSpecifier needs the spec and the object type. Drop IntoPyException so that path cannot produce a generic message. Assisted-by: Grok:4.6 --------- Co-authored-by: Jeong YunWon <[email protected]>
Bumps [bstr](https://github.com/BurntSushi/bstr) from 1.13.0 to 1.13.1. - [Commits](BurntSushi/bstr@1.13.0...1.13.1) --- updated-dependencies: - dependency-name: bstr dependency-version: 1.13.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…ustPython#8977) Bumps [reviewdog/action-actionlint](https://github.com/reviewdog/action-actionlint) from 1.76.0 to 1.77.0. - [Release notes](https://github.com/reviewdog/action-actionlint/releases) - [Commits](reviewdog/action-actionlint@320fcdd...2085657) --- updated-dependencies: - dependency-name: reviewdog/action-actionlint dependency-version: 1.77.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [thin-vec](https://github.com/mozilla/thin-vec) from 0.2.19 to 0.2.20. - [Changelog](https://github.com/mozilla/thin-vec/blob/main/RELEASES.md) - [Commits](mozilla/thin-vec@v0.2.19...v0.2.20) --- updated-dependencies: - dependency-name: thin-vec dependency-version: 0.2.20 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [which](https://github.com/harryfei/which-rs) from 8.0.5 to 8.0.6. - [Release notes](https://github.com/harryfei/which-rs/releases) - [Changelog](https://github.com/harryfei/which-rs/blob/master/CHANGELOG.md) - [Commits](harryfei/which-rs@8.0.5...8.0.6) --- updated-dependencies: - dependency-name: which dependency-version: 8.0.6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…tPython#8976) * build(deps): bump taiki-e/install-action from 2.87.17 to 2.87.21 Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.87.17 to 2.87.21. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](taiki-e/install-action@94c31af...4cef141) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-version: 2.87.21 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> * Ignore spurious warning from shellcheck We do not put the `EXTRA_TEST_ARGS` and `SKIPS` variables in quotes by design. --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: fanninpm <[email protected]>
Bumps [bitflags](https://github.com/bitflags/bitflags) from 2.13.1 to 2.13.2. - [Release notes](https://github.com/bitflags/bitflags/releases) - [Changelog](https://github.com/bitflags/bitflags/blob/main/CHANGELOG.md) - [Commits](bitflags/bitflags@2.13.1...2.13.2) --- updated-dependencies: - dependency-name: bitflags dependency-version: 2.13.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…ustPython#8984) Bumps [proxy-addr](https://github.com/jshttp/proxy-addr) from 2.0.7 to 2.0.8. - [Release notes](https://github.com/jshttp/proxy-addr/releases) - [Changelog](https://github.com/jshttp/proxy-addr/blob/master/HISTORY.md) - [Commits](jshttp/proxy-addr@v2.0.7...v2.0.8) --- updated-dependencies: - dependency-name: proxy-addr dependency-version: 2.0.8 dependency-type: indirect ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [rustls](https://github.com/rustls/rustls) from 0.23.43 to 0.23.45. - [Release notes](https://github.com/rustls/rustls/releases) - [Changelog](https://github.com/rustls/rustls/blob/main/CHANGELOG.md) - [Commits](rustls/rustls@v/0.23.43...v/0.23.45) --- updated-dependencies: - dependency-name: rustls dependency-version: 0.23.45 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…RustPython#8987) Bumps [source-map-js](https://github.com/7rulnik/source-map-js) from 1.2.1 to 1.2.2. - [Release notes](https://github.com/7rulnik/source-map-js/releases) - [Changelog](https://github.com/7rulnik/source-map-js/blob/main/CHANGELOG.md) - [Commits](7rulnik/source-map-js@v1.2.1...v1.2.2) --- updated-dependencies: - dependency-name: source-map-js dependency-version: 1.2.2 dependency-type: indirect ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…RustPython#8988) Bumps [shell-quote](https://github.com/ljharb/shell-quote) from 1.10.0 to 1.12.0. - [Changelog](https://github.com/ljharb/shell-quote/blob/main/CHANGELOG.md) - [Commits](ljharb/shell-quote@v1.10.0...v1.12.0) --- updated-dependencies: - dependency-name: shell-quote dependency-version: 1.12.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…on#8989) Bumps [postcss-selector-parser](https://github.com/postcss/postcss-selector-parser) from 7.1.5 to 7.1.6. - [Release notes](https://github.com/postcss/postcss-selector-parser/releases) - [Changelog](https://github.com/postcss/postcss-selector-parser/blob/main/CHANGELOG.md) - [Commits](postcss/postcss-selector-parser@7.1.5...7.1.6) --- updated-dependencies: - dependency-name: postcss-selector-parser dependency-version: 7.1.6 dependency-type: indirect ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [rustix](https://github.com/bytecodealliance/rustix) from 1.1.4 to 1.1.5. - [Release notes](https://github.com/bytecodealliance/rustix/releases) - [Changelog](https://github.com/bytecodealliance/rustix/blob/main/CHANGES.md) - [Commits](bytecodealliance/rustix@v1.1.4...v1.1.5) --- updated-dependencies: - dependency-name: rustix dependency-version: 1.1.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Match CPython's SyntaxError range for unparenthesized `except` types
CPython's `invalid_except_stmt` rule raises the error only once the whole
clause has matched, and reports a range that starts at the first exception
type and ends at the `:` closing the clause, so it covers the `as NAME`
part as well:
invalid_except_stmt:
| 'except' a=expression ',' expressions 'as' NAME ':' {
RAISE_SYNTAX_ERROR_STARTING_FROM(a, "multiple exception types
must be parenthesized when using 'as'") }
The parser reports the exception types alone, so look up that `:` in the
source and widen the range to match. Only `as NAME` may follow the
exception types, which is why the first `:` after them is the one closing
the clause.
try:
pass
except A, B, C as e:
pass
CPython 3.14: ('x.py', 3, 8, 'except A, B, C as e:\n', 3, 20)
before: ('x.py', 3, 8, 'except A, B, C as e:\n', 3, 15)
Fixes RustPython#8496
Co-Authored-By: Claude Opus 5 <[email protected]>
* Clarify that the `except` error range stops before the closing colon
`invalid_except_stmt_end` returns the exclusive end of the range, so the
column it yields is the one the `:` sits on even though the `:` is not part
of the range. The previous "ending at the `:`" wording read as if the colon
were included, which invites an off-by-one "fix".
Comments only; no behavior change.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
* Fix the `except ... as` error column for non-ASCII names and line joins
`invalid_except_stmt_end` recovers the end of CPython's range by scanning the
source, which has to redo by hand what CPython gets from its tokenizer:
- The column was the byte distance from the line start, but `end_offset` is a
character column. `except Ä, B as e:` reported 18 instead of 17. CPython
converts explicitly, in `_PyPegen_byte_offset_to_character_offset`.
- The colon scan already spans explicit line joins, but the `as` check ran on
the raw slice, so a `\` before `as` left the range unextended.
`except A, B \` + `as exc:` reported (3, 12) instead of (4, 7).
Add regression cases to `syntax_invalid.py` covering both, plus the whitespace,
`except*` and line-join placements that already worked. All values are verified
against CPython 3.14.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
* Update the Ruff fork to 0.16.10
Point the rustpython-ruff_* dependencies at the 0.16.10-rustpython tag
of the RustPython Ruff fork and port to its AST changes:
`ExprCompare` stores all operands in `operands`, call arguments use
`ThinVec`, dict comprehension generators and f-string elements are boxed
slices, `FStringValue` iterates `FStringPartRef`, and `TokenKind::Name`
is now `TokenKind::Identifier`.
Assisted-by: Grok:grok-4.6
Assisted-by: Claude Code:claude-opus-5-5
* Drop the source scan for the `except ... as` error range
The parser now reports the unparenthesized exception types error with a
range ending at the `:` that closes the clause, so
`invalid_except_stmt_end` and the message match that widened the range
are removed.
Assisted-by: Claude Code:claude-opus-5-5
* Take parse error messages from the parser as they are
The Ruff fork now emits the final message texts, so `vm_new.rs` no
longer rewrites parse error messages by matching their text and no
longer lowercases the first character of every message.
`analyze_compile_error` keeps only the caret narrowing for starred
expressions and the line number in the unterminated string message.
The compiler matches the new lowercase texts for indented block and
mixed bytes literal errors.
The fork is referenced by revision until it is published.
Assisted-by: Claude Code:claude-opus-5-5
* Take starred and bytes literal error ranges from the parser
The Ruff fork now reports misplaced starred expressions at the `*` and
non-ASCII bytes literal errors over the whole literal. `vm_new.rs` drops
`narrow_caret` together with `SyntaxErrorInfo`, which only carried the
message after that, and the compiler drops `bytes_literal_span`.
Assisted-by: Claude Code:claude-opus-5-5
* Take indentation error kinds and positions from the parser
The Ruff fork now reports `TabError` and `TooDeepIndentation` as their
own lexer errors and places indentation and line continuation errors
itself. `vm_new.rs` picks TabError or IndentationError from the error
kind instead of scanning the source for mixed indentation, drops the
TabError message override, and sets the end offset of tokenizer errors
to 0 or -1 by kind. The compiler drops the line-end relocation of
unindent errors and the line continuation rewrite. `_tokenize` raises
TabError and depth errors for the token they replace, also for sources
containing tabs.
Remove expectedFailure from test_tokenize.test_max_indent and four
test_tabnanny tests.
Assisted-by: Claude Code:claude-opus-5-5
* Take unterminated string messages from the parser
The Ruff fork's unterminated string errors now include the detected
line and are reported at the start of the string. `vm_new.rs` drops its
message override for `UnclosedStringError`, and the shell continues a
line on an unterminated triple-quoted string by the error's
`triple_quoted` flag instead of reading the quotes from the source.
Assisted-by: Claude Code:claude-opus-5-5
* Take bracket errors and tokenizer error priority from the parser
Bump the ruff fork, which now reports unmatched, mismatched, unclosed
and too deeply nested brackets and decides whether a tokenizer error
replaces the parser's first error.
Remove the bracket, unterminated string and nesting depth source
scanners and `pre_parse_source_error`. A tokenizer error from the
parser now wins over source scanner diagnostics found after it. An
unclosed bracket is incomplete input only when the parser reports it
as such, and other tokenizer errors end where they start.
Remove the expected failure markers from test_unicode_identifiers
test_invalid and the `import ä £` doctest in test_syntax.
Assisted-by: Claude Code:claude-opus-5-5
* Take number literal, string prefix and non-printable errors from the parser
Bump the ruff fork, which now reports malformed number literals,
incompatible string prefixes and non-printable characters itself.
Remove the number literal, string prefix and non-printable character
source scanners and the override classes that ranked them. Leading zero
and string prefix errors keep their range instead of ending where they
start.
Assisted-by: Claude Code:claude-opus-5-5
* Take the missing indented block error from the parser
Bump the ruff fork, which now reports `ExpectedIndentedBlock` with the
clause and the line of its header keyword.
Remove the message rewrite that derived the clause and line from the
source. The VM chooses IndentationError or incomplete input by the
error variant instead of its message.
Assisted-by: Claude Code:claude-opus-5-5
* Take binding target errors from the parser
Bump the ruff fork, which now names the invalid expression in
assignment, augmented assignment, delete, `for`, `with`, import,
pattern and `except` target errors.
Remove the source scanners for those targets and the message rewrites
of `InvalidAssignmentTarget` and `InvalidNamedAssignmentTarget`.
Remove the expected failure markers from test_syntax doctests that now
pass.
Assisted-by: Claude Code:claude-opus-5-5
* Take parameter, argument, star, comma and dictionary errors from the parser
Bump the ruff fork to 36919b62fa. Remove the source scanners for type
parameters, parameter lists, star annotations, call arguments, def type
parameters, parenthesized groups, missing commas and dictionary items.
Set end_offset 0 for ExpectedColonAfterDictionaryKey. Remove 14
EXPECTED_FAILURE markers in test_syntax and test_unpack_ex.
Assisted-by: Claude Code:claude-opus-5-5
* Take expression errors from the parser
Bump the ruff fork to 4f922d2124. Remove the source scanners for
comprehensions, collection and condition assignments, expressions
between strings, named expression targets, missing `in` after for-loop
variables and statements in `if` expressions. Remove the now passing
expected failure markers in test_syntax and test_named_expressions.
Assisted-by: Claude Code:claude-opus-5-5
* Take statement errors from the parser
Bump the ruff fork to c7f6594ed6. Remove the source scanners for
standalone except, `import ... from`, `**_` mapping rests, `elif` after
`else` and mixed except handlers, and the post-parse scanners for call
arguments, match targets, yield after a comma and parenthesized star
imports.
Assisted-by: Claude Code:claude-opus-5-5
* Take string and f-string errors from the parser
Bump the ruff fork to 6b46d0dfc8. Remove the source scanners for
malformed `\N` escapes, f-string and t-string replacement fields, mixed
t-string literals and `print`/`exec` statements, and the override
plumbing they used. Drop the `f'{x'; '` case from the compiler test,
whose expected message differs from CPython 3.14.
Assisted-by: Claude Code:claude-opus-5-5
* Restore the bracket depth check and fix incomplete unclosed strings
Restore `pre_parse_source_error`, which rejects bracket nesting past 200
levels before parsing. The parser reports the same error but still
builds the full tree, which overflows the native stack when dropped.
Remove the VM's unclosed string scanner, which ignored the mode and
treated `'abc` in exec mode as incomplete input. The compiler's check
now skips escaped newlines.
Assisted-by: Claude Code:claude-opus-5-5
* Report multiple statements before later errors in single mode
In single mode, when the first statement is a simple statement, report
code after its line as multiple statements before any error found
later, at the newline token or the comment before it. This replaces the
multiple statements check on the parsed body and also applies to
`ast.parse(mode='single')`.
An unclosed string that follows an earlier syntax error is no longer
incomplete input. The bracket depth error range is now empty.
Assisted-by: Claude Code:claude-opus-5-5
* Update the Ruff fork for parser speed and starred annotations
Bump the ruff fork to 8b59b85344, which skips the tokenizer error pass
when parsing finds no errors, stops allocating for every identifier's
string prefix check, and reports `def f(*args: *b = ...)` as invalid
syntax.
Remove expected failure markers from test_code_module
test_indentation_error and test_sysexcepthook_indentation_error, and
from test_dictcomps test_illegal_assignment.
Assisted-by: Claude Code:claude-opus-5-5
* Use the published Ruff fork 0.16.10 crates
Switch the rustpython-ruff_* dependencies from the git revision to the
0.16.10 crates.io release, published from the same commit (8b59b85344).
Assisted-by: Claude Code:claude-opus-5-5
---------
Co-authored-by: zzarbttoo <[email protected]>
Co-authored-by: Claude Opus 5 <[email protected]>
…stPython#8986) * fix: signal.SIGINT and signal() raise NotImplementedError on wasi - Problem: signal.SIGINT and friends don't exist on wasi, and signal.signal() is hard-stubbed to raise NotImplementedError there - Cause: wasi-libc emulates signal()/raise() in a separate opt-in library that Rust's own wasm32-wasip1 target distribution doesn't ship - Fix: vendor wasi-sdk's prebuilt libwasi-emulated-signal.a, link it for wasm32-wasip1, and wire SIGINT/SIGABRT/SIGFPE/SIGILL/SIGSEGV/SIGTERM, signal()/getsignal()/raise_signal() through it. CPython's own WASI build links the same library Assisted-by: Claude Code:claude-sonnet-5 Signed-off-by: Jiwoo Ahn <[email protected]> * Group WASI signal definitions in mod wasm Move WASI-only types, constants, FFI, and handlers into `mod wasm` and re-export them with `#[cfg(target_os = "wasi")]`. Assisted-by: Grok 4.6 --------- Signed-off-by: Jiwoo Ahn <[email protected]> Co-authored-by: Jeong YunWon <[email protected]>
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.2.66 to 1.5.1. - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](rust-lang/cc-rs@cc-v1.2.66...cc-v1.5.1) --- updated-dependencies: - dependency-name: cc dependency-version: 1.5.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
round(x, ndigits) ran ndigits through __index__ before calling __round__, so a user-defined __round__ never saw a non-integer ndigits and an __index__ object reached it already converted to int. CPython's builtin_round_impl() forwards ndigits as-is and leaves the conversion to float.__round__ and int.__round__. Forward the object, and take ndigits as ArgIndex in both slots so they apply __index__ themselves. Calling the slots directly with an __index__ object now works as in CPython instead of raising TypeError. Assisted-by: Claude Code:claude-opus-5 Assisted-by: Claude Code:claude-opus-5-5
RustPython#8828 made bin(), chr() and several other arguments that were bound as PyIntRef go through __index__, but these still downcast to int and reject an object that only defines __index__: the start and end of the str/bytes/bytearray find family, enumerate(start=), itertools.combinations/combinations_with_replacement/batched, _thread.stack_size, resource.getrlimit/setrlimit, pwd.getpwuid, grp.getgrgid, fcntl.fcntl/lockf and mmap.move/madvise. CPython converts all of them with _PyNumber_Index or _PyEval_SliceIndex. Bind them as ArgIndex, as RustPython#8828 did for the others. test_mmap.test_madvise and test_mmap_closed_by_int_scenarios now pass, so drop their expectedFailure markers. Assisted-by: Claude Code:claude-opus-5-5
Assisted-by: Claude Code:claude-opus-5-5 Assisted-by: Codex:gpt-6
…9001) Bumps [rustls-pki-types](https://github.com/rustls/pki-types) from 1.15.0 to 1.15.1. - [Release notes](https://github.com/rustls/pki-types/releases) - [Commits](rustls/pki-types@v/1.15.0...v/1.15.1) --- updated-dependencies: - dependency-name: rustls-pki-types dependency-version: 1.15.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* vm: drop trailing space from RecursionError text Format Python-limit and native-stack RecursionError messages through one helper so empty context is not a trailing space or an empty string. Assisted-by: Grok 4.6 * test: deepen nested hash snippets for release stack frames The cold RecursionError helper thins with_recursion's hot frame, so 100_000 nested hashes no longer trip the native stack guard in release. Assisted-by: Grok 4.6 * vm: let RecursionError callers own the where-clause space The helper concatenates an empty suffix or one that already starts with a space. Call sites supply that space. Assisted-by: Grok 4.6
Bumps [dns-lookup](https://github.com/keeperofdakeys/dns-lookup) from 4.0.1 to 4.0.2. - [Commits](keeperofdakeys/dns-lookup@4.0.1...4.0.2) --- updated-dependencies: - dependency-name: dns-lookup dependency-version: 4.0.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Take re pos/endpos as signed integers Negative values clamp to 0, and values beyond Py_ssize_t raise OverflowError. Assisted-by: Claude Code:claude-opus-5-5 * Port the remaining runtime fixes from RustPython#7993 - bytearray: keep the buffer exported while converting the needle of find/count/index/rfind/rindex/__contains__/split/rsplit and the hex separator, so resizing from there raises BufferError - str(): report non-str encoding/errors as "str() argument 'X' must be str, not T", and check argument counts and name/position duplicates for keyword calls - _json.scanstring: take end as a signed integer and raise ValueError when it is out of bounds - lzma: reject filter specs with keys the filter does not take - mmap: raise ValueError when growing a shared anonymous mapping on Linux/NetBSD - _sqlite3: check that the backup progress argument is callable - Remove the expectedFailure markers of the tests these fix Assisted-by: Claude Code:claude-opus-5-5 * Reject arguments given by name and position in FuncArgs::bind_for bind_for reports a keyword that fills a parameter already given by position before other binding errors, using the parameter list of the FromArgs type. getargs shares the message, str() drops its own check, and blake2b/blake2s name themselves in binding errors. Assisted-by: Claude Code:claude-opus-5-5 --------- Co-authored-by: James David Clarke <[email protected]>
Assisted-by: Claude Code:claude-opus-5-5
Split `builtin_method` out as a subclass of `builtin_function_or_method`. Ordinary descriptor bind and `__new__` wrappers allocate a CFunction; only `build_bound_method` uses the METH_METHOD payload. Keep `types.BuiltinMethodType` as an alias of `BuiltinFunctionType`. Assisted-by: Grok 4.6
…hon#9005) `PyMethodDef::new_const`, `PyMethodDef::new_raw_const` and `Context::new_method_def` add the calling convention (`NOARGS`, `O`, `FASTCALL`, or `FASTCALL | KEYWORDS`) inferred from the `FromArgs::PARAMS` of each argument, exposed as `IntoPyNativeFn::ARGS`. Flags that already contain a calling convention, such as C-API `ml_flags`, are kept. For `METHOD` and `CLASS` the first argument is the bound receiver. Raw functions get `FASTCALL | KEYWORDS`. The derive macros pass only binding flags and no longer infer call flags from Rust type names. Definitions built without the macros, such as the `__new__` wrapper and `vm.new_function`, get calling convention flags the same way. Assisted-by: Claude Code:claude-opus-5-5
Assisted-by: Codex:gpt-6-astra Assisted-by: Devin:swe-2-max Assisted-by: Claude Code:claude-opus-5-5
062a04b to
9f27f33
Compare
📦 Library DependenciesThe following Lib/ modules were modified. Here are their dependencies: [x] lib: cpython/Lib/tokenize.py dependencies:
dependent tests: (154 tests)
[ ] test: cpython/Lib/test/test_dict.py (TODO: 3) dependencies: dependent tests: (no tests depend on dict) [x] test: cpython/Lib/test/test_str.py (TODO: 4) dependencies: dependent tests: (no tests depend on str) [x] test: cpython/Lib/test/test_mmap.py (TODO: 19) dependencies: dependent tests: (2 tests)
[x] lib: cpython/Lib/lzma.py dependencies:
dependent tests: (102 tests)
[ ] lib: cpython/Lib/json dependencies:
dependent tests: (13 tests)
[x] test: cpython/Lib/test/test_format.py dependencies: dependent tests: (no tests depend on format) [x] test: cpython/Lib/test/test_unpack.py dependencies: dependent tests: (no tests depend on unpack) [ ] test: cpython/Lib/test/test_bytes.py (TODO: 15) dependencies: dependent tests: (no tests depend on bytes) [x] lib: cpython/Lib/code.py dependencies:
dependent tests: (2 tests) [x] lib: cpython/Lib/hashlib.py dependencies:
dependent tests: (146 tests)
[x] lib: cpython/Lib/tabnanny.py dependencies:
dependent tests: (1 tests)
[ ] lib: cpython/Lib/enum.py dependencies:
dependent tests: (16 tests)
[ ] lib: cpython/Lib/csv.py dependencies:
dependent tests: (4 tests)
[x] lib: cpython/Lib/sqlite3 dependencies:
dependent tests: (2 tests)
[ ] test: cpython/Lib/test/test_unicodedata.py (TODO: 24) dependencies: dependent tests: (no tests depend on unicode) [x] test: cpython/Lib/test/test_named_expressions.py dependencies: dependent tests: (no tests depend on named_expressions) [ ] lib: cpython/Lib/typing.py dependencies:
dependent tests: (19 tests)
[ ] test: cpython/Lib/test/test_syntax.py (TODO: 13) dependencies: dependent tests: (no tests depend on syntax) Legend:
|
|
Superseded by the fix-module-docstring-global branch, rebased onto current upstream main. |
Draft in the author's fork for human review of the code changes. Human code review and manual verification are pending before upstream submission.
Summary
Store the module docstring through the existing
store_namepath instead of always emittingStoreName.When a nested scope declares
global __doc__, CPython stores the module docstring in globals. RustPython currently stores it in locals when the module code is executed with separate globals and locals dictionaries. This change resolves the name normally, producingStoreGlobalfor that case.The production change replaces two lines with one call in
crates/codegen/src/compile.rs. The remaining additions are five compiler regression tests and a dedicated runtime snippet inextra_tests/snippets/compiler_module_doc_global.py. They cover the nested declaration, deeper nesting, normal module behavior, optimization levels, and class docstrings.module doc NoneNone module docValidation
The Rust implementation and compiler tests match the previously validated patch. The required commit hook only joined equivalent adjacent string literals in the Python snippet; its parsed syntax tree was confirmed unchanged. The snippet was rerun successfully on RustPython and CPython after that formatting change.
The completed validation on this Linux host included:
extra_testswith asqlite-enabled release build: 482 passed, 3 warnings.test_compile,test_global, andtest___all__modules passed. Clippy, rustfmt, Ruff, and whitespace checks passed.Review base and AI assistance
The fork's
mainhas diverged from upstream. This PR usesreview/e3-module-docstring-base, pointing to the tested upstream commitada43c4f82b9df4e260f1368038c31cd55c4a61e, so its diff contains only this change. It is a review draft inteddygood/RustPythonand has not been submitted to the upstream repository.Codex (
gpt-6-astra) assisted the earlier design and analysis. Devin (swe-2-max) implemented the fix and performed the recorded validation. Codex also prepared this draft PR. Human review and manual use have not yet been claimed or completed.