Skip to content

Update _ast_unparse and fix unparse, type_comments#6961

Merged
youknowone merged 8 commits intoRustPython:mainfrom
youknowone:unparse
Feb 3, 2026
Merged

Update _ast_unparse and fix unparse, type_comments#6961
youknowone merged 8 commits intoRustPython:mainfrom
youknowone:unparse

Conversation

@youknowone
Copy link
Member

@youknowone youknowone commented Feb 2, 2026

Summary by CodeRabbit

  • New Features

    • AST-only compilation mode support
    • t-string unparsing support
  • Bug Fixes

    • Replaced internal panics with explicit syntax errors for malformed patterns
    • Types now raise a proper "not subscriptable" TypeError when appropriate
    • Safeguard for truncated string literals to avoid crashes
  • Improvements

    • AST initialization applies sensible field defaults (including ImportFrom level)
    • AST nodes consistently emit type_comment as None
  • Serialization

    • Type-parameter default_value exposed and round-tripped
  • Documentation

    • Updated developer test command exclusions

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 2, 2026

📝 Walkthrough

Walkthrough

Convert internal panics/asserts into explicit syntax errors in codegen; guard truncated string-literal parsing; add t-string unparse support; restrict type subscripting to non-None __class_getitem__; add AST field-defaulting, default_value for type-parameter nodes, and always emit type_comment = None for certain nodes; implement PyCF_ONLY_AST short-circuit in compile().

Changes

Cohort / File(s) Summary
Codegen / Pattern validation
crates/codegen/src/compile.rs
Replace panics/asserts with explicit self.error(...) returns for forbidden-name checks, class-pattern (too many subpatterns), and MatchOr size ≤ 1; tighten error handling.
String parsing & t-string unparse
crates/codegen/src/string_parser.rs, crates/codegen/src/unparse.rs
Guard parse_string_literal against truncated sources (return raw source when too short); add unparse_tstring(&TStringValue) and route TString rendering through it using fstring-body composition + UnicodeEscape.
VM protocol / subscripting error
crates/vm/src/protocol/object.rs
Only call __class_getitem__ on types when attribute exists and is not None; otherwise raise TypeError: type '<Name>' is not subscriptable.
AST init & defaulting
crates/vm/src/stdlib/ast/python.rs, crates/vm/src/stdlib/ast/pyast.rs
Track provided fields during AST init, mark built-ins with _field_types, default missing built-in fields (lists → [], others → None), and add default_value to TypeVar/ParamSpec/TypeVarTuple field lists.
AST serialization / node emissions
crates/vm/src/stdlib/ast/expression.rs, crates/vm/src/stdlib/ast/parameter.rs, crates/vm/src/stdlib/ast/statement.rs, crates/vm/src/stdlib/ast/type_parameters.rs, crates/vm/src/stdlib/ast.rs
Emit args as empty_arguments_object for lambdas with no params; always emit type_comment = None for several nodes; add round-trip default_value handling for type-parameter nodes; add empty_arguments_object and mode_type_and_name helpers.
Compile builtin: AST-only mode
crates/vm/src/stdlib/builtins.rs, crates/vm/src/stdlib/ast.rs
Implement PyCF_ONLY_AST handling: parse flags, map mode → expected AST node class, validate mode, and short-circuit by returning AST node when it matches expected type.
Minor serialization cast change
crates/vm/src/stdlib/ast/other.rs
Serialize ConversionFlag as i8 instead of u8.
Docs / scripts
AGENTS.md, DEVELOPMENT.md
Exclude additional crate rustpython-venvlauncher from workspace cargo test invocations.

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant BuiltinsCompile as builtins::compile
    participant Parser
    participant ASTNode as ParsedAST
    Caller->>BuiltinsCompile: compile(source, filename, mode, flags)
    BuiltinsCompile->>BuiltinsCompile: extract PyCF_ONLY_AST from flags
    BuiltinsCompile->>Parser: parse(source) -> ParsedAST
    alt PyCF_ONLY_AST set
        BuiltinsCompile->>BuiltinsCompile: mode_type_and_name(mode) -> expected_type
        BuiltinsCompile->>ASTNode: inspect node type
        alt node.type == expected_type
            BuiltinsCompile-->>Caller: return AST node (short-circuit)
        else mismatch
            BuiltinsCompile-->>Caller: raise TypeError (expected vs actual)
        end
    else normal compile
        BuiltinsCompile->>BuiltinsCompile: continue compile pipeline
        BuiltinsCompile-->>Caller: return compiled result
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested labels

skip:ci

Suggested reviewers

  • ShaharNaveh

Poem

🐇 I nudged the panics into softer sighs,
I checked the quotes where tiny truncation lies,
T-strings now sparkle, defaults tucked in place,
Subscripted types now fail with kinder grace,
🥕 A hop, a nibble—code in tidy files.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.74% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title refers to AST unparsing and type comments, which are core to multiple changes across the PR, particularly in unparse.rs, statement.rs, and parameter.rs files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 2, 2026

Code has been automatically formatted

The code in this PR has been formatted using:

  • cargo fmt --all
    Please pull the latest changes before pushing again:
git pull origin unparse

@youknowone youknowone force-pushed the unparse branch 2 times, most recently from 6eea5dc to 017ae40 Compare February 2, 2026 08:12
@youknowone youknowone marked this pull request as ready for review February 2, 2026 09:24
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/vm/src/stdlib/ast/type_parameters.rs (1)

116-120: ⚠️ Potential issue | 🟡 Minor

Change default_value deserialization from required to optional for TypeVar, ParamSpec, and TypeVarTuple.

In Python 3.13+, the default_value field of TypeVar, ParamSpec, and TypeVarTuple AST nodes is optional and can be None. Currently, the code uses get_node_field() which requires the field to be present, causing errors when default_value is absent from an input AST object.

Apply the same pattern used for the bound field to all three locations:

  • Line 116-120 (TypeVar)
  • Line 163-167 (ParamSpec)
  • Line 213-217 (TypeVarTuple)

Replace get_node_field(_vm, &_object, "default_value", "TypeVar")? with:

+            default: get_node_field_opt(_vm, &_object, "default_value")?
+                .map(|obj| Node::ast_from_object(_vm, source_file, obj))
+                .transpose()?,
🤖 Fix all issues with AI agents
In `@crates/vm/src/stdlib/builtins.rs`:
- Around line 144-166: The AST-only branch currently returns early when
ast::PY_COMPILE_FLAG_AST_ONLY is set without validating the rest of the flags;
update the block around flags/args.flags and ast::PY_COMPILE_FLAG_AST_ONLY to
run the same unrecognized-flag validation used in the parser branch (i.e.,
detect and reject any unsupported flag bits and raise vm.new_value_error for
invalid flags) before checking mode_str/expected_type and returning
Ok(args.source); reference the existing symbols flags, args.flags,
ast::PY_COMPILE_FLAG_AST_ONLY, mode_str and the early return to locate and
insert this validation.
🧹 Nitpick comments (1)
crates/vm/src/protocol/object.rs (1)

710-713: Use expect() for consistency with codebase conventions.

The downcast is safe here since the outer condition at line 699 guarantees self is a type object. However, elsewhere in this file (lines 525 and 618-619), expect() with an explanatory message is used when an invariant is guaranteed by prior checks.

Suggested change
 return Err(vm.new_type_error(format!(
     "type '{}' is not subscriptable",
-    self.downcast_ref::<PyType>().unwrap().name()
+    self.downcast_ref::<PyType>().expect("self is verified to be a type").name()
 )));

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/vm/src/stdlib/ast/type_parameters.rs (1)

116-120: ⚠️ Potential issue | 🟠 Major

Use get_node_field_opt with .map().transpose() pattern for optional default_value field.

The deserialization treats default_value as required using get_node_field, but Python 3.13's AST specification defines default_value as optional (can be None for type parameters without defaults). This causes a TypeError when constructing AST nodes without explicitly providing default_value.

The pattern for optional fields is already correctly implemented for bound (lines 113-115) using get_node_field_opt. Apply the same pattern to default_value in TypeParamTypeVar (lines 116-120), TypeParamParamSpec (lines 163-167), and TypeParamTypeVarTuple (lines 213-217):

Example fix for TypeParamTypeVar
-default: Node::ast_from_object(
-    _vm,
-    source_file,
-    get_node_field(_vm, &_object, "default_value", "TypeVar")?,
-)?,
+default: get_node_field_opt(_vm, &_object, "default_value")?
+    .map(|obj| Node::ast_from_object(_vm, source_file, obj))
+    .transpose()?,
🤖 Fix all issues with AI agents
In `@crates/vm/src/stdlib/ast/python.rs`:
- Around line 99-137: The defaulting logic uses a global LIST_FIELDS to decide
list-vs-none which causes Lambda.args to be set to an empty list; change the
loop that assigns defaults (the block referencing LIST_FIELDS, fields, and
zelf.set_attr) to consult the node-specific _field_types metadata instead of the
global LIST_FIELDS: for each field in &fields, look up its declared type in
self._field_types (or equivalent per-node field-type map) and only create
vm.ctx.new_list(vec![]) when that field’s declared type is a sequence/list type;
otherwise use vm.ctx.none() so fields like Lambda.args (declared as an arguments
node) are not defaulted to an empty list. Ensure you still use
vm.ctx.intern_str(field.as_str()) and set the attribute via
zelf.set_attr(vm.ctx.intern_str(...), default, vm)?.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@crates/vm/src/stdlib/builtins.rs`:
- Around line 148-164: The code currently compares the source AST class name
string to expected_type (using cls_name != expected_type), which rejects
subclasses; change this to map mode_str to the actual AST type class object
(e.g., the Module/Expression/Interactive/FunctionType class from the VM/ctx
types) and use fast_issubclass(args.source.class(), expected_type_class) to
validate inheritance; if fast_issubclass returns false, return the same
vm.new_type_error with a message like "expected {expected_type} node, got
{cls_name}" so subclasses are accepted while still failing on unrelated types.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@crates/vm/src/stdlib/ast/python.rs`:
- Around line 90-149: The body-field list detection in
crates/vm/src/stdlib/ast/python.rs incorrectly treats IfExp.body as a list;
update the conditional that computes is_list_field (which uses class_name,
field_name, and LIST_FIELDS) so the "body" branch also excludes "IfExp" (i.e.,
ensure class_name != "Lambda" && class_name != "Expression" && class_name !=
"IfExp") before choosing the default and calling zelf.set_attr.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@crates/vm/src/stdlib/ast/python.rs`:
- Around line 129-154: The code incorrectly uses exact class name string
comparisons (class_name == "Call", "Lambda", "Expression", "IfExp") to decide
list defaults, which misclassifies subclasses; change those comparisons to
subclass checks using vm.ctx.fast_issubclass against the canonical AST base
classes so subclasses inherit the same defaults. Specifically, in the
is_list_field logic replace checks like class_name == "Call" or class_name ==
"arguments" and the matches!(...) for "Lambda"|"Expression"|"IfExp" with calls
to vm.ctx.fast_issubclass(zelf.class(), <Call_class_obj>) etc.; obtain the base
class objects once (e.g., look up the Call, Lambda, Expression, IfExp class
objects from the VM context) and use those in fast_issubclass checks, keeping
LIST_FIELDS and the rest of the default/list logic intact and falling back to
the string-based behavior only if the type lookup fails.
🧹 Nitpick comments (2)
crates/vm/src/protocol/object.rs (1)

708-715: Logic looks good; prefer expect() over unwrap() for clarity.

The change correctly handles the case where __class_getitem__ is explicitly set to None, producing a clearer error message than the previous "NoneType is not callable".

However, the unwrap() on line 714 doesn't communicate the safety invariant to readers. While it's safe here (we're inside the fast_issubclass(type_type) check, so self must be a PyType), using expect() would document this assumption and provide a better panic message if the invariant is ever violated.

📝 Suggested improvement for clarity
                 return Err(vm.new_type_error(format!(
                     "type '{}' is not subscriptable",
-                    self.downcast_ref::<PyType>().unwrap().name()
+                    self.downcast_ref::<PyType>()
+                        .expect("self is a type object (checked by fast_issubclass)")
+                        .name()
                 )));
crates/codegen/src/unparse.rs (1)

630-641: Optional: consolidate f/t-string rendering to avoid drift.

unparse_tstring mirrors unparse_fstring closely; consider extracting a small shared helper (prefix + body builder) to keep escaping behavior consistent as string kinds evolve. Also please confirm cargo fmt and cargo clippy run clean for this change.

As per coding guidelines, follow the default rustfmt code style by running cargo fmt to format Rust code; always run clippy to lint Rust code (cargo clippy) before completing tasks and fix any warnings or lints introduced by changes.

Comment on lines 129 to 154
let class_name = zelf.class().name().to_string();

for field in &fields {
if !set_fields.contains(field.as_str()) {
let field_name = field.as_str();
// Some field names have different ASDL types depending on the node.
// For example, "args" is `expr*` in Call but `arguments` in Lambda.
// "body" and "orelse" are `stmt*` in most nodes but `expr` in IfExp.
let is_list_field = if field_name == "args" {
class_name == "Call" || class_name == "arguments"
} else if field_name == "body" || field_name == "orelse" {
!matches!(
class_name.as_str(),
"Lambda" | "Expression" | "IfExp"
)
} else {
LIST_FIELDS.contains(&field_name)
};

let default: PyObjectRef = if is_list_field {
vm.ctx.new_list(vec![]).into()
} else {
vm.ctx.none()
};
zelf.set_attr(vm.ctx.intern_str(field_name), default, vm)?;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cd crates/vm && head -200 src/stdlib/ast/python.rs | tail -100

Repository: RustPython/RustPython

Length of output: 3868


🏁 Script executed:

sed -n '100,160p' crates/vm/src/stdlib/ast/python.rs

Repository: RustPython/RustPython

Length of output: 2601


🏁 Script executed:

# Search for fast_issubclass usage in the codebase to understand the pattern
rg "fast_issubclass" crates/vm/src/stdlib/ast/ -A 2 -B 2

Repository: RustPython/RustPython

Length of output: 47


🏁 Script executed:

# Look for NodeExprCall, NodeArguments, NodeExprLambda types in the codebase
rg "NodeExprCall|NodeArguments|NodeExprLambda|NodeModExpression|NodeExprIfExp" crates/vm/src/stdlib/ast/

Repository: RustPython/RustPython

Length of output: 1907


🏁 Script executed:

# Check what node types are available in the pyast module
fd "pyast" crates/vm/src/stdlib/ast/ && ls -la crates/vm/src/stdlib/ast/pyast* 2>/dev/null || find crates/vm/src/stdlib/ast -name "*pyast*" -type f

Repository: RustPython/RustPython

Length of output: 182


🏁 Script executed:

rg "fast_issubclass" crates/vm --type rust

Repository: RustPython/RustPython

Length of output: 6337


🏁 Script executed:

# Search for issubclass patterns in the codebase
rg "\.is\(.*::static_type" crates/vm/src/stdlib/ast/ -A 1 -B 1

Repository: RustPython/RustPython

Length of output: 25507


🏁 Script executed:

# Check what methods are available on PyClass for subclass checking
rg "impl.*PyClass" crates/vm/src/builtins/ -A 10 | head -50

Repository: RustPython/RustPython

Length of output: 3469


🏁 Script executed:

# Look for subclass checking methods in the PyClass implementation
fd "class.rs" crates/vm/src && head -100 "$(fd 'class.rs' crates/vm/src)"

Repository: RustPython/RustPython

Length of output: 3451


🏁 Script executed:

# Search for how .is() method is used on PyClass
rg "\.is\(" crates/vm/src/stdlib/ast/python.rs -B 2 -A 2

Repository: RustPython/RustPython

Length of output: 47


Use subclass checking instead of exact class name matching for field defaults.

When _field_types is inherited by subclasses, string comparison like class_name == "Call" misclassifies subclasses and defaults fields incorrectly. Use fast_issubclass against the base node types so subclasses follow the same defaults as their parents.

🛠️ Suggested fix
-                let class_name = zelf.class().name().to_string();
+                let class = zelf.class();
+                let class_name = class.name().to_string();
 ...
-                        let is_list_field = if field_name == "args" {
-                            class_name == "Call" || class_name == "arguments"
-                        } else if field_name == "body" || field_name == "orelse" {
-                            !matches!(
-                                class_name.as_str(),
-                                "Lambda" | "Expression" | "IfExp"
-                            )
-                        } else {
-                            LIST_FIELDS.contains(&field_name)
-                        };
+                        let is_list_field = if field_name == "args" {
+                            class.fast_issubclass(super::pyast::NodeExprCall::static_type())
+                                || class.fast_issubclass(super::pyast::NodeArguments::static_type())
+                        } else if field_name == "body" || field_name == "orelse" {
+                            !(class.fast_issubclass(super::pyast::NodeExprLambda::static_type())
+                                || class.fast_issubclass(super::pyast::NodeModExpression::static_type())
+                                || class.fast_issubclass(super::pyast::NodeExprIfExp::static_type()))
+                        } else {
+                            LIST_FIELDS.contains(&field_name)
+                        };
🤖 Prompt for AI Agents
In `@crates/vm/src/stdlib/ast/python.rs` around lines 129 - 154, The code
incorrectly uses exact class name string comparisons (class_name == "Call",
"Lambda", "Expression", "IfExp") to decide list defaults, which misclassifies
subclasses; change those comparisons to subclass checks using
vm.ctx.fast_issubclass against the canonical AST base classes so subclasses
inherit the same defaults. Specifically, in the is_list_field logic replace
checks like class_name == "Call" or class_name == "arguments" and the
matches!(...) for "Lambda"|"Expression"|"IfExp" with calls to
vm.ctx.fast_issubclass(zelf.class(), <Call_class_obj>) etc.; obtain the base
class objects once (e.g., look up the Call, Lambda, Expression, IfExp class
objects from the VM context) and use those in fast_issubclass checks, keeping
LIST_FIELDS and the rest of the default/list logic intact and falling back to
the string-based behavior only if the type lookup fails.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@DEVELOPMENT.md`:
- Around line 67-69: The fenced code block contains a shell prompt character ("$
") before the command string "cargo test --workspace --exclude rustpython_wasm
--exclude rustpython-venvlauncher" which triggers markdownlint MD014; edit the
fenced block to remove the leading "$ " so it contains just the plain command
line (i.e., "cargo test --workspace --exclude rustpython_wasm --exclude
rustpython-venvlauncher") to satisfy the lint rule.
🧹 Nitpick comments (1)
crates/vm/src/stdlib/ast/python.rs (1)

154-158: Minor: ImportFrom.level gets set twice.

When level is not provided, the loop at lines 131-152 first sets it to None, then lines 155-157 immediately overwrite it to 0. This results in two set_attr calls for the same field.

Consider handling this inside the loop to avoid the redundant attribute assignment:

♻️ Suggested consolidation
                         let default: PyObjectRef = if is_list_field {
                             vm.ctx.new_list(vec![]).into()
+                        } else if field_name == "level" && class_name == "ImportFrom" {
+                            vm.ctx.new_int(0).into()
                         } else {
                             vm.ctx.none()
                         };
                         zelf.set_attr(vm.ctx.intern_str(field_name), default, vm)?;
                     }
                 }
-
-                // Special defaults that are not None or empty list
-                if class_name == "ImportFrom" && !set_fields.contains("level") {
-                    zelf.set_attr("level", vm.ctx.new_int(0), vm)?;
-                }

Comment on lines 67 to 69
```shell
$ cargo test --workspace --exclude rustpython_wasm
$ cargo test --workspace --exclude rustpython_wasm --exclude rustpython-venvlauncher
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove the shell prompt to satisfy markdownlint MD014.

The $ prompt in a fenced block without output triggers MD014. Consider removing it.

Suggested edit
-$ cargo test --workspace --exclude rustpython_wasm --exclude rustpython-venvlauncher
+cargo test --workspace --exclude rustpython_wasm --exclude rustpython-venvlauncher
🧰 Tools
🪛 markdownlint-cli2 (0.20.0)

[warning] 68-68: Dollar signs used before commands without showing output

(MD014, commands-show-output)

🤖 Prompt for AI Agents
In `@DEVELOPMENT.md` around lines 67 - 69, The fenced code block contains a shell
prompt character ("$ ") before the command string "cargo test --workspace
--exclude rustpython_wasm --exclude rustpython-venvlauncher" which triggers
markdownlint MD014; edit the fenced block to remove the leading "$ " so it
contains just the plain command line (i.e., "cargo test --workspace --exclude
rustpython_wasm --exclude rustpython-venvlauncher") to satisfy the lint rule.

- Extract empty_arguments_object helper from expression.rs
- Fix LIST_FIELDS ambiguity: "args" and "body" have different
  ASDL types per node (e.g. Lambda.args is `arguments`, not
  `expr*`; Lambda.body is `expr`, not `stmt*`)
- Replace class name string comparison in compile() with
  fast_isinstance to accept AST subclasses
@github-actions
Copy link
Contributor

github-actions bot commented Feb 3, 2026

📦 Library Dependencies

The following Lib/ modules were modified. Here are their dependencies:

[x] lib: cpython/Lib/ast.py
[x] lib: cpython/Lib/_ast_unparse.py
[x] test: cpython/Lib/test/test_unparse.py (TODO: 6)
[x] test: cpython/Lib/test/test_type_comments.py (TODO: 15)

dependencies:

  • ast

dependent tests: (48 tests)

  • ast: test_ast test_builtin test_compile test_dis test_fstring test_future_stmt test_site test_ssl test_type_comments test_ucn test_unparse
    • annotationlib: test_functools test_inspect test_reprlib test_typing
      • inspect: test_abc test_argparse test_asyncgen test_code test_collections test_coroutines test_decimal test_enum test_generators test_grammar test_ntpath test_operator test_patma test_posixpath test_signal test_traceback test_types test_unittest test_yield_from test_zipimport
    • dbm.dumb: test_dbm_dumb
    • inspect:
      • bdb: test_bdb
      • dataclasses: test__colorize test_genericalias test_pprint test_regrtest test_zoneinfo
      • importlib.metadata: test_importlib
      • rlcompleter: test_rlcompleter
      • trace: test_trace
      • xmlrpc.server: test_docxmlrpc test_xmlrpc
    • pyclbr: test_pyclbr

[x] test: cpython/Lib/test/test_exceptions.py (TODO: 31)
[ ] test: cpython/Lib/test/test_baseexception.py
[x] test: cpython/Lib/test/test_except_star.py (TODO: 1)
[ ] test: cpython/Lib/test/test_exception_group.py (TODO: 1)
[x] test: cpython/Lib/test/test_exception_hierarchy.py (TODO: 2)
[x] test: cpython/Lib/test/test_exception_variations.py

dependencies:

dependent tests: (no tests depend on exception)

[x] lib: cpython/Lib/typing.py
[ ] test: cpython/Lib/test/test_typing.py (TODO: 21)
[ ] test: cpython/Lib/test/test_type_aliases.py
[ ] test: cpython/Lib/test/test_type_annotations.py
[ ] test: cpython/Lib/test/test_type_params.py
[ ] test: cpython/Lib/test/test_genericalias.py (TODO: 3)

dependencies:

  • typing

dependent tests: (9 tests)

  • typing: test_enum test_fractions test_functools test_genericalias test_grammar test_importlib test_isinstance test_types test_typing

[ ] test: cpython/Lib/test/test_class.py (TODO: 16)
[x] test: cpython/Lib/test/test_genericclass.py
[x] test: cpython/Lib/test/test_subclassinit.py

dependencies:

dependent tests: (no tests depend on class)

Legend:

  • [+] path exists in CPython
  • [x] up-to-date, [ ] outdated

@youknowone youknowone merged commit 1821572 into RustPython:main Feb 3, 2026
14 checks passed
@youknowone youknowone deleted the unparse branch February 3, 2026 06:41
This was referenced Feb 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant