Skip to content

Commit

Permalink
Automatically treat nested modules as submodules
Browse files Browse the repository at this point in the history
fixes PyO3#4286
  • Loading branch information
alex committed Jul 5, 2024
1 parent 9afc38a commit 8e3c276
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 3 deletions.
1 change: 1 addition & 0 deletions newsfragments/4308.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Nested declarative `#[pymodule]` are automatically treated as submodules (no `PyInit_` entrypoint is created)
12 changes: 10 additions & 2 deletions pyo3-macros-backend/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ impl PyModuleOptions {
fn set_submodule(&mut self, submod: SubmoduleAttribute) -> Result<()> {
ensure_spanned!(
!self.is_submodule,
submod.span() => "`submodule` may only be specified once"
submod.span() => "`submodule` may only be specified once (it is implicitly always specified for nested modules)"
);

self.is_submodule = true;
Expand Down Expand Up @@ -116,7 +116,14 @@ pub fn pymodule_module_impl(
} else {
name.to_string()
};
is_submodule = is_submodule || options.is_submodule;

is_submodule = match (is_submodule, options.is_submodule) {
(true, true) => {
bail_spanned!(module.span() => "`submodule` may only be specified once (it is implicitly always specified for nested modules)")
}
(false, false) => false,
(true, false) | (false, true) => true,
};

let mut module_items = Vec::new();
let mut module_items_cfg_attrs = Vec::new();
Expand Down Expand Up @@ -273,6 +280,7 @@ pub fn pymodule_module_impl(
)? {
set_module_attribute(&mut item_mod.attrs, &full_name);
}
item_mod.attrs.push(parse_quote!(#[pyo3(submodule)]));
}
}
Item::ForeignMod(item) => {
Expand Down
1 change: 1 addition & 0 deletions tests/test_compile_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,5 @@ fn test_compile_errors() {
t.compile_fail("tests/ui/abi3_weakref.rs");
#[cfg(all(Py_LIMITED_API, not(Py_3_9)))]
t.compile_fail("tests/ui/abi3_dict.rs");
t.compile_fail("tests/ui/duplicate_pymodule_submodule.rs");
}
2 changes: 1 addition & 1 deletion tests/test_declarative_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ mod declarative_module {
}
}

#[pymodule(submodule)]
#[pymodule]
#[pyo3(module = "custom_root")]
mod inner_custom_root {
use super::*;
Expand Down
7 changes: 7 additions & 0 deletions tests/ui/duplicate_pymodule_submodule.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#[pyo3::pymodule]
mod mymodule {
#[pyo3::pymodule(submodule)]
mod submod {}
}

fn main() {}
11 changes: 11 additions & 0 deletions tests/ui/duplicate_pymodule_submodule.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error: `submodule` may only be specified once (it is implicitly always specified for nested modules)
--> tests/ui/duplicate_pymodule_submodule.rs:4:2
|
4 | mod submod {}
| ^^^

error[E0433]: failed to resolve: use of undeclared crate or module `submod`
--> tests/ui/duplicate_pymodule_submodule.rs:4:6
|
4 | mod submod {}
| ^^^^^^ use of undeclared crate or module `submod`

0 comments on commit 8e3c276

Please sign in to comment.