diff --git a/newsfragments/5375.fixed.md b/newsfragments/5375.fixed.md new file mode 100644 index 00000000000..ee6b3893e76 --- /dev/null +++ b/newsfragments/5375.fixed.md @@ -0,0 +1 @@ +Fixed `PyModuleMethods::add_submodul()` to use the last segment of the submodule name as the attribute name on the parent module instead of using the full name. \ No newline at end of file diff --git a/src/types/module.rs b/src/types/module.rs index 72ba2d341d9..57e9177299c 100644 --- a/src/types/module.rs +++ b/src/types/module.rs @@ -35,7 +35,8 @@ pub struct PyModule(PyAny); pyobject_native_type_core!(PyModule, pyobject_native_static_type_object!(ffi::PyModule_Type), #checkfunction=ffi::PyModule_Check); impl PyModule { - /// Creates a new module object with the `__name__` attribute set to `name`. + /// Creates a new module object with the `__name__` attribute set to `name`. When creating + /// a submodule pass the full path as the name such as `top_level.name`. /// /// # Examples /// @@ -514,7 +515,11 @@ impl<'py> PyModuleMethods<'py> for Bound<'py, PyModule> { } fn add_submodule(&self, module: &Bound<'_, PyModule>) -> PyResult<()> { - let name = module.name()?; + let name = module + .name()? + .call_method1("rpartition", (".",))? + .get_item(2)? + .downcast_into::()?; self.add(name, module) } diff --git a/tests/test_module.rs b/tests/test_module.rs index 5e6244420e0..b310c113c76 100644 --- a/tests/test_module.rs +++ b/tests/test_module.rs @@ -285,10 +285,10 @@ fn superfunction() -> String { #[pymodule] fn supermodule(module: &Bound<'_, PyModule>) -> PyResult<()> { module.add_function(wrap_pyfunction!(superfunction, module)?)?; - let module_to_add = PyModule::new(module.py(), "submodule")?; + let module_to_add = PyModule::new(module.py(), "supermodule.submodule")?; submodule(&module_to_add)?; module.add_submodule(&module_to_add)?; - let module_to_add = PyModule::new(module.py(), "submodule_with_init_fn")?; + let module_to_add = PyModule::new(module.py(), "supermodule.submodule_with_init_fn")?; submodule_with_init_fn(&module_to_add)?; module.add_submodule(&module_to_add)?; Ok(()) @@ -316,6 +316,36 @@ fn test_module_nesting() { supermodule, "supermodule.submodule_with_init_fn.subfunction() == 'Subfunction'" ); + + // submodule dunder name and attribute name + py_assert!( + py, + supermodule, + "supermodule.submodule.__name__ == 'supermodule.submodule'" + ); + py_assert!(py, supermodule, "'submodule' in supermodule.__dict__"); + py_assert!( + py, + supermodule, + "'supermodule.submodule' not in supermodule.__dict__" + ); + + // submodule_with_init_fn dunder name and attribute name + py_assert!( + py, + supermodule, + "supermodule.submodule_with_init_fn.__name__ == 'supermodule.submodule_with_init_fn'" + ); + py_assert!( + py, + supermodule, + "'submodule_with_init_fn' in supermodule.__dict__" + ); + py_assert!( + py, + supermodule, + "'supermodule.submodule_with_init_fn' not in supermodule.__dict__" + ); }); }