Skip to content

#[pymodule] submodule support and implicit module_name inheritance#7203

Merged
youknowone merged 2 commits intoRustPython:mainfrom
youknowone:pymodule
Feb 23, 2026
Merged

#[pymodule] submodule support and implicit module_name inheritance#7203
youknowone merged 2 commits intoRustPython:mainfrom
youknowone:pymodule

Conversation

@youknowone
Copy link
Member

@youknowone youknowone commented Feb 23, 2026

Summary by CodeRabbit

  • New Features
    • Detects nested modules and automatically initializes, registers, and binds submodules during module setup.
    • Struct-sequence items now default to the enclosing module when no module is specified, simplifying module association.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 23, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 75b0e48 and 649a2bf.

📒 Files selected for processing (1)
  • crates/derive-impl/src/pymodule.rs

📝 Walkthrough

Walkthrough

Detects nested #[pymodule] items and emits per-item submodule initialization code injected into the parent module's init flow (preserving each item's cfg attributes). Also computes has_module/module_name for StructSequenceItem, auto-filling nested module meta with the current module name when absent.

Changes

Cohort / File(s) Summary
Pymodule nested detection & struct-sequence handling
crates/derive-impl/src/pymodule.rs
Detect nested #[pymodule] items and collect submodule_inits; inject generated submodule init blocks into __init_attributes (module creation, init, exec, binding) while honoring per-item #[cfg]. Update StructSequenceItem to compute has_module/module_name from meta or default to current module.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I found a tunnel in the code so deep,
Little submodules woke from their sleep,
Init hops in, flags kept in sight,
Defaults filled softly in the night,
A rabbit cheers for nested delight 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 accurately describes the main changes: adding submodule support for #[pymodule] and implementing implicit module_name inheritance, which matches the AI-generated summary of changes.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 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.

@youknowone youknowone marked this pull request as ready for review February 23, 2026 07:13
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.

🧹 Nitpick comments (1)
crates/derive-impl/src/pymodule.rs (1)

840-841: Cache the result of meta.module()? to avoid the double call.

meta.module()? is called twice in consecutive lines — once to check is_some() and once to get the value. A single call with caching is cleaner.

♻️ Proposed refactor
-        let has_module = meta.module()?.is_some();
-        let module_name = meta.module()?.unwrap_or_else(|| args.context.name.clone());
+        let module_opt = meta.module()?;
+        let has_module = module_opt.is_some();
+        let module_name = module_opt.unwrap_or_else(|| args.context.name.clone());
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/derive-impl/src/pymodule.rs` around lines 840 - 841, Cache the result
of meta.module()? into a local variable instead of calling it twice: call
meta.module()? once (e.g., let module_opt = meta.module()?;) then set has_module
= module_opt.is_some(); and compute module_name = module_opt.unwrap_or_else(||
args.context.name.clone()); update uses of has_module and module_name
accordingly to avoid duplicate calls to meta.module()?.
ℹ️ Review info

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ccfa938 and f4e1407.

📒 Files selected for processing (1)
  • crates/derive-impl/src/pymodule.rs
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@crates/derive-impl/src/pymodule.rs`:
- Around line 840-841: Cache the result of meta.module()? into a local variable
instead of calling it twice: call meta.module()? once (e.g., let module_opt =
meta.module()?;) then set has_module = module_opt.is_some(); and compute
module_name = module_opt.unwrap_or_else(|| args.context.name.clone()); update
uses of has_module and module_name accordingly to avoid duplicate calls to
meta.module()?.

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.

🧹 Nitpick comments (1)
crates/derive-impl/src/pymodule.rs (1)

233-243: Consider using .expect() with submodule name for better panic diagnostics.

All .unwrap() calls here are consistent with the existing patterns elsewhere in this file (e.g., lines 798, 892). However, since submodule initialization adds a layer of indirection, a panic during init could be hard to diagnose. Using .expect() with the submodule name would help.

💡 Proposed improvement for diagnostics
                 submodule_inits.push(quote! {
                     #(`#cfgs`)*
                     {
                         let child_def = `#mod_ident`::module_def(ctx);
-                        let child = child_def.create_module(vm).unwrap();
-                        child.__init_methods(vm).unwrap();
-                        `#mod_ident`::module_exec(vm, &child).unwrap();
+                        let child = child_def.create_module(vm)
+                            .expect(concat!("failed to create submodule ", `#py_name`));
+                        child.__init_methods(vm)
+                            .expect(concat!("failed to init methods for submodule ", `#py_name`));
+                        `#mod_ident`::module_exec(vm, &child)
+                            .expect(concat!("failed to exec submodule ", `#py_name`));
                         let child: ::rustpython_vm::PyObjectRef = child.into();
                         vm.__module_set_attr(module, ctx.intern_str(`#py_name`), child).unwrap();
                     }
                 });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/derive-impl/src/pymodule.rs` around lines 233 - 243, Replace the four
.unwrap() calls in the submodule initialization block pushed into
submodule_inits with .expect(...) so panics include the submodule name (use the
`#py_name` variable). Specifically update the calls to
`#mod_ident`::module_def(ctx).create_module(vm).unwrap(),
child.__init_methods(vm).unwrap(), `#mod_ident`::module_exec(vm, &child).unwrap(),
and vm.__module_set_attr(...).unwrap() to use .expect() messages that reference
`#py_name` (e.g., "failed to create/init/exec/set attr for submodule {`#py_name`}")
so failures during submodule init produce clear diagnostics for the named
submodule.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@crates/derive-impl/src/pymodule.rs`:
- Around line 233-243: Replace the four .unwrap() calls in the submodule
initialization block pushed into submodule_inits with .expect(...) so panics
include the submodule name (use the `#py_name` variable). Specifically update the
calls to `#mod_ident`::module_def(ctx).create_module(vm).unwrap(),
child.__init_methods(vm).unwrap(), `#mod_ident`::module_exec(vm, &child).unwrap(),
and vm.__module_set_attr(...).unwrap() to use .expect() messages that reference
`#py_name` (e.g., "failed to create/init/exec/set attr for submodule {`#py_name`}")
so failures during submodule init produce clear diagnostics for the named
submodule.

ℹ️ Review info

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f4e1407 and 75b0e48.

📒 Files selected for processing (1)
  • crates/derive-impl/src/pymodule.rs

@youknowone youknowone merged commit 39a5d39 into RustPython:main Feb 23, 2026
1 check passed
@youknowone youknowone deleted the pymodule branch February 23, 2026 13:17
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