Skip to content

Conversation

altendky
Copy link
Contributor

@altendky altendky commented Aug 29, 2025

with submodules, the module .__name__ is the full dotted import path (below, "this.that"). pyo3 is presently using that value for the key when adding the submodule to the parent but should instead be using just the last segment (below, "that"). there may be a more proper way to achieve this than this pr, but here's a starting point to consider at least.

below is my present workaround code. fix_import_path() is stripping out the extension module layer since we re-export from the pyo3 extension module (chia_rs.chia_rs) out through a top layer python package (chia_rs). this bit isn't exactly related, just explaining the presence of that function call here.

    let single_element_module_name = "datalayer";
    let original_path = format!("{}.{}", parent.name()?, single_element_module_name);
    let module_path = fix_import_path(&original_path);
    let module = PyModule::new(py, &module_path)?;
    parent.add_submodule(&module)?;

    // https://github.com/PyO3/pyo3/pull/5375
    // move attribute to proper name
    parent.delattr(module.name()?)?;
    parent.setattr(single_element_module_name, &module)?;
    // update __all__ as well
    let all = parent.getattr("__all__")?;
    all.call_method1("remove", (module.name()?,))?;
    all.call_method1("append", (single_element_module_name,))?;

here's a pure python example for reference on the expected forms of the values.

mkdir -p this/
touch this/__init__.py
touch this/that.py
python -c 'import this.that; print(repr(next(name for name in dir(this) if "that" in name)))'
python -c 'import this.that; print(repr(this.that.__name__))'
$ mkdir -p this/
$ touch this/__init__.py
$ touch this/that.py
$ python -c 'import this.that; print(repr(next(name for name in dir(this) if "that" in name)))'
'that'
$ python -c 'import this.that; print(repr(this.that.__name__))'
'this.that'

Warning

the output below is not from a minimal or clean project. i am in the middle of working through various aspects of this and related topics here. i'm still leaving it for reference, but don't be too attached to particular output. i think the above minimal pure python example and the tests stand by themselves.

(or at least they should stand by themselves and if they don't then i should fix that)

in a real project without this i get:

$ venv/bin/python -c 'import chia_rs; print(next(name for name in dir(chia_rs) if "datalayer" in name)); print(chia_rs.datalayer.__name__)'
chia_rs.datalayer
Traceback (most recent call last):
  File "<string>", line 1, in <module>
AttributeError: module 'chia_rs' has no attribute 'datalayer'
$ venv/bin/python -c 'from chia_rs import datalayer; print(datalayer.__name__)'
chia_rs.datalayer

and with this pr:

$ venv/bin/python -c 'import chia_rs; print(next(name for name in dir(chia_rs) if "datalayer" in name)); print(chia_rs.datalayer.__name__)'
datalayer
chia_rs.datalayer

in both cases i do have this workaround in place.

    // https://github.com/PyO3/pyo3/issues/1517#issuecomment-808664021
    // https://github.com/PyO3/pyo3/issues/759
    py.import("sys")?
        .getattr("modules")?
        .set_item("chia_rs.datalayer", datalayer)?;

draft for:

  • reviewing contributing documentation
  • add changelog entry ( 👉 towncrier... )
  • add tests
  • consider other options that do not require the submodule to repeat the name of the super module it will later be added to
  • check and possibly revise documentation for clarity around what should be passed when creating a module that will be a submodule, "that" vs. "this.that" etc

@altendky
Copy link
Contributor Author

when i run nox -s test locally it seems to be skipping everything, but without ignoring or filtering. any particular suggestions here?

partial output:

     Running tests/test_module.rs (target/debug/deps/test_module-7f86ac533fd70caf)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
full output
$ venv/bin/nox -s test
nox > Running session test
nox > cargo test --no-fail-fast --package=pyo3-build-config
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.09s
     Running unittests src/lib.rs (target/debug/deps/pyo3_build_config-adde72ad5785b19b)

running 37 tests
test errors::tests::error_report ... ok
test impl_::tests::build_flags_default ... ok
test impl_::tests::build_flags_fixup ... ok
test impl_::tests::abi3_version_cannot_be_higher_than_interpreter ... ok
test impl_::tests::build_flags_from_sysconfigdata ... ok
test impl_::tests::config_from_empty_sysconfigdata ... ok
test impl_::tests::config_from_sysconfigdata ... ok
test impl_::tests::config_from_sysconfigdata_framework ... ok
test impl_::tests::default_lib_name_windows ... ok
test impl_::tests::default_lib_name_unix ... ok
test impl_::tests::mingw_hardcoded_cross_compile ... ok
test impl_::tests::parse_cross_python_version ... ok
test impl_::tests::parse_script_output ... ok
test impl_::tests::test_build_script_outputs_abi3 ... ok
test impl_::tests::pypy_hardcoded_cross_compile ... ok
test impl_::tests::test_build_script_outputs_base ... ok
test impl_::tests::interpreter_version_reduced_to_abi3 ... ok
test impl_::tests::test_conda_env_interpreter ... ok
test impl_::tests::test_config_file_roundtrip ... ok
test impl_::tests::test_build_script_outputs_gil_disabled ... ok
test impl_::tests::test_config_file_roundtrip_with_escaping ... ok
test impl_::tests::test_config_file_unknown_keys ... ok
test impl_::tests::test_build_script_outputs_debug ... ok
test impl_::tests::test_find_sysconfigdata_in_invalid_lib_dir ... ok
test impl_::tests::test_is_cross_compiling_from_to ... ok
test impl_::tests::test_config_file_defaults ... ok
test impl_::tests::test_from_pyo3_config_file_env_rebuild ... ok
test impl_::tests::test_not_cross_compiling_from_to ... ok
test impl_::tests::test_venv_interpreter ... ok
test impl_::tests::unix_hardcoded_abi3_compile ... ok
test impl_::tests::unix_hardcoded_cross_compile ... ok
test impl_::tests::windows_hardcoded_abi3_compile ... ok
test impl_::tests::windows_hardcoded_cross_compile ... ok
test tests::extension_module_link_args ... ok
test impl_::tests::config_from_interpreter ... ok
test impl_::tests::test_run_python_script ... ok
test impl_::tests::test_run_python_script_with_envs ... ok

test result: ok. 37 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.38s

   Doc-tests pyo3_build_config

running 1 test
test pyo3-build-config/src/impl_.rs - impl_::BuildFlags (line 1159) - compile ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.03s

nox > cargo test --no-fail-fast --package=pyo3-macros-backend
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.09s
     Running unittests src/lib.rs (target/debug/deps/pyo3_macros_backend-824e93812e498f44)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

   Doc-tests pyo3_macros_backend

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

nox > cargo test --no-fail-fast --package=pyo3-macros
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.03s
     Running unittests src/lib.rs (target/debug/deps/pyo3_macros-67d2942950fa2961)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

   Doc-tests pyo3_macros

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

nox > cargo test --no-fail-fast --package=pyo3-ffi
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.06s
     Running unittests src/lib.rs (target/debug/deps/pyo3_ffi-3b2b94a4a8dab6ef)

running 13 tests
test compat::py_3_10::test_Py_NewRef_export::test_export ... ok
test compat::py_3_10::test_PyModule_AddObjectRef_export::test_export ... ok
test compat::py_3_13::test_PyDict_GetItemRef_export::test_export ... ok
test compat::py_3_13::test_PyImport_AddModuleRef_export::test_export ... ok
test compat::py_3_10::test_Py_XNewRef_export::test_export ... ok
test compat::py_3_13::test_PyList_Clear_export::test_export ... ok
test compat::py_3_13::test_PyModule_Add_export::test_export ... ok
test compat::py_3_13::test_PyList_Extend_export::test_export ... ok
test compat::py_3_13::test_PyList_GetItemRef_export::test_export ... ok
test compat::py_3_13::test_PyWeakref_GetRef_export::test_export ... ok
test compat::py_3_14::test_Py_HashBuffer_export::test_export ... ok
test compat::py_3_9::test_PyObject_CallMethodNoArgs_export::test_export ... ok
test compat::py_3_9::test_PyObject_CallNoArgs_export::test_export ... ok

test result: ok. 13 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

   Doc-tests pyo3_ffi

running 5 tests
test pyo3-ffi/src/lib.rs - (line 125) ... ignored
test pyo3-ffi/src/lib.rs - (line 58) ... ignored
test pyo3-ffi/src/lib.rs - (line 74) ... ignored
test pyo3-ffi/src/lib.rs - c_str (line 361) - compile ... ok
test pyo3-ffi/src/lib.rs - (line 132) - compile ... ok

test result: ok. 2 passed; 0 failed; 3 ignored; 0 measured; 0 filtered out; finished in 0.04s

None
nox > cargo test --no-fail-fast --no-default-features --all-targets
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.12s
     Running unittests src/lib.rs (target/debug/deps/pyo3-80d0aab3a1f0a9f8)
/home/altendky/repos/pyo3/target/debug/deps/pyo3-80d0aab3a1f0a9f8: error while loading shared libraries: libpython3.12.so.1.0: cannot open shared object file: No such file or directory
error: test failed, to rerun pass `--lib`

Caused by:
  process didn't exit successfully: `/home/altendky/repos/pyo3/target/debug/deps/pyo3-80d0aab3a1f0a9f8` (exit status: 127)
note: test exited abnormally; to see the full output pass --nocapture to the harness.
     Running tests/test_anyhow.rs (target/debug/deps/test_anyhow-9acd7614a58214fe)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_append_to_inittab.rs (target/debug/deps/test_append_to_inittab-9a1a1440c6d1b026)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_arithmetics.rs (target/debug/deps/test_arithmetics-9c5ef096d41bffce)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_buffer.rs (target/debug/deps/test_buffer-8e4e59dce804c1fa)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_buffer_protocol.rs (target/debug/deps/test_buffer_protocol-5bd8f42f07d6402c)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_bytes.rs (target/debug/deps/test_bytes-d6fbcbcc9146b539)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_class_attributes.rs (target/debug/deps/test_class_attributes-107e11663f2ca21b)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_class_basics.rs (target/debug/deps/test_class_basics-f8469ca5e9bc5bd9)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_class_comparisons.rs (target/debug/deps/test_class_comparisons-35720b4d414944cc)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_class_conversion.rs (target/debug/deps/test_class_conversion-aeee38b52f778948)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_class_formatting.rs (target/debug/deps/test_class_formatting-1e4db252196ab885)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_class_new.rs (target/debug/deps/test_class_new-8d30ec9c6fe37bc7)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_compile_error.rs (target/debug/deps/test_compile_error-d5cfbfd64366dd7a)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_coroutine.rs (target/debug/deps/test_coroutine-4b7dcc7c10777742)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_datetime.rs (target/debug/deps/test_datetime-697f2e33aec83f31)
/home/altendky/repos/pyo3/target/debug/deps/test_datetime-697f2e33aec83f31: error while loading shared libraries: libpython3.12.so.1.0: cannot open shared object file: No such file or directory
error: test failed, to rerun pass `--test test_datetime`

Caused by:
  process didn't exit successfully: `/home/altendky/repos/pyo3/target/debug/deps/test_datetime-697f2e33aec83f31` (exit status: 127)
note: test exited abnormally; to see the full output pass --nocapture to the harness.
     Running tests/test_datetime_import.rs (target/debug/deps/test_datetime_import-70517d87ebd4ebcb)
/home/altendky/repos/pyo3/target/debug/deps/test_datetime_import-70517d87ebd4ebcb: error while loading shared libraries: libpython3.12.so.1.0: cannot open shared object file: No such file or directory
error: test failed, to rerun pass `--test test_datetime_import`

Caused by:
  process didn't exit successfully: `/home/altendky/repos/pyo3/target/debug/deps/test_datetime_import-70517d87ebd4ebcb` (exit status: 127)
note: test exited abnormally; to see the full output pass --nocapture to the harness.
     Running tests/test_declarative_module.rs (target/debug/deps/test_declarative_module-d6d995c721e50dbe)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_default_impls.rs (target/debug/deps/test_default_impls-92b47ee9b4fa9431)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_enum.rs (target/debug/deps/test_enum-07e57df77aa311ee)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_exceptions.rs (target/debug/deps/test_exceptions-bad68a489336a95d)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_field_cfg.rs (target/debug/deps/test_field_cfg-7ed5de47ba747563)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_frompy_intopy_roundtrip.rs (target/debug/deps/test_frompy_intopy_roundtrip-6781c403e8e09eab)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_frompyobject.rs (target/debug/deps/test_frompyobject-bc54c9c33aea1201)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_gc.rs (target/debug/deps/test_gc-89b3eebd7cf59b02)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_getter_setter.rs (target/debug/deps/test_getter_setter-829dec3f48a5e1d1)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_inheritance.rs (target/debug/deps/test_inheritance-0bdeabf31a6a3fac)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_intopyobject.rs (target/debug/deps/test_intopyobject-0847ab30cdff63b1)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_macro_docs.rs (target/debug/deps/test_macro_docs-57b1a8ce0016164d)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_macros.rs (target/debug/deps/test_macros-4039754fa89bd447)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_mapping.rs (target/debug/deps/test_mapping-d18eab1be01a0a9f)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_methods.rs (target/debug/deps/test_methods-d0fc32e4573fb3b4)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_module.rs (target/debug/deps/test_module-7f86ac533fd70caf)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_multiple_pymethods.rs (target/debug/deps/test_multiple_pymethods-2ca89a4527fa9888)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_proto_methods.rs (target/debug/deps/test_proto_methods-1e746f60a1772d76)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_pybuffer_drop_without_interpreter.rs (target/debug/deps/test_pybuffer_drop_without_interpreter-b049dd37bd4b2a86)
/home/altendky/repos/pyo3/target/debug/deps/test_pybuffer_drop_without_interpreter-b049dd37bd4b2a86: error while loading shared libraries: libpython3.12.so.1.0: cannot open shared object file: No such file or directory
error: test failed, to rerun pass `--test test_pybuffer_drop_without_interpreter`

Caused by:
  process didn't exit successfully: `/home/altendky/repos/pyo3/target/debug/deps/test_pybuffer_drop_without_interpreter-b049dd37bd4b2a86` (exit status: 127)
note: test exited abnormally; to see the full output pass --nocapture to the harness.
     Running tests/test_pyerr_debug_unformattable.rs (target/debug/deps/test_pyerr_debug_unformattable-c37cbe57a1788a09)
/home/altendky/repos/pyo3/target/debug/deps/test_pyerr_debug_unformattable-c37cbe57a1788a09: error while loading shared libraries: libpython3.12.so.1.0: cannot open shared object file: No such file or directory
error: test failed, to rerun pass `--test test_pyerr_debug_unformattable`

Caused by:
  process didn't exit successfully: `/home/altendky/repos/pyo3/target/debug/deps/test_pyerr_debug_unformattable-c37cbe57a1788a09` (exit status: 127)
note: test exited abnormally; to see the full output pass --nocapture to the harness.
     Running tests/test_pyfunction.rs (target/debug/deps/test_pyfunction-03b647e4d1b3ce4d)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_pyself.rs (target/debug/deps/test_pyself-985b57820d60ea1d)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_sequence.rs (target/debug/deps/test_sequence-3401b5cf8b232b87)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_serde.rs (target/debug/deps/test_serde-2e33039245d6898b)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_static_slots.rs (target/debug/deps/test_static_slots-cdbbaa0615828f37)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_string.rs (target/debug/deps/test_string-14dce35373ace895)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_super.rs (target/debug/deps/test_super-ee257f7bec8a2526)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_text_signature.rs (target/debug/deps/test_text_signature-dcbe2d303786bbfe)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_variable_arguments.rs (target/debug/deps/test_variable_arguments-484d25e584866f66)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/test_various.rs (target/debug/deps/test_various-097ff2c11d5b6ab3)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

error: 5 targets failed:
    `--lib`
    `--test test_datetime`
    `--test test_datetime_import`
    `--test test_pybuffer_drop_without_interpreter`
    `--test test_pyerr_debug_unformattable`
nox > Command cargo test --no-fail-fast --no-default-features --all-targets failed with exit code 101
nox > Session test failed.

@altendky
Copy link
Contributor Author

huh, same thing in ci. maybe there's an actual problem, or maybe i just don't know how to read this.

https://github.com/PyO3/pyo3/actions/runs/17324975335/job/49186955142?pr=5375#step:18:1038

       Running tests/test_module.rs (target/debug/deps/test_module-1a3555288f167f4d)
  
  running 0 tests
  
  test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

@Icxolu
Copy link
Contributor

Icxolu commented Aug 29, 2025

Some of our tests require certain features. Quite a lot of them require macros (like test_module). This particular run is without any features enabled (cargo test --no-fail-fast --no-default-features --all-targets), so these tests are not available. So this output is normal for these runs.

@altendky
Copy link
Contributor Author

thanks for the explanation. i've gotten the tests to run locally.

@altendky altendky marked this pull request as ready for review August 29, 2025 23:07
@altendky
Copy link
Contributor Author

my reading of the coverage complaint is that (probably) the failure cases are not covered. it appears that this was the case before as well, though i have also added more ? that aren't being exercised. i'll guess that that is not a concern. maybe i'm wrong, only you know. :]

while i'm not confident that this is ready, i do think it's complete enough to hopefully express the idea and mostly that's where my concern is. anyways, i look forward to hearing some feedback about this when you have time.

cheers,
-kyle

Copy link
Member

@davidhewitt davidhewitt left a comment

Choose a reason for hiding this comment

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

Thanks very much for the PR. I think what you're proposing here broadly makes sense, and probably goes some way to answering historical pain we've had with #759

I am slightly unsure about the use of PyModule::new here as the way you've had to create submodules. We are heading in the direction of preferring declarative modules due to us being able to do tricks like optimize them better and automatically generate type hints (which is WIP).

Can you please update (or create) test cases which demonstrate this issue using the declarative structure and show that it is also resolved by this PR?

Copy link
Contributor

@Icxolu Icxolu left a comment

Choose a reason for hiding this comment

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

An alternative API could perhaps look something also like this:

fn add_submodule(&self, name: &str) -> PyResult<Bound<'py, PyModule>>

Just take the unqualified name, construct the fully qualified name internally, add it to the parent and return the (sub)module object with the correct name set,

@altendky
Copy link
Contributor Author

altendky commented Sep 1, 2025

i'll catch myself up on the declarative module approach. this is one of the aspects where i just fit in with the existing pattern in the project i was working on that uses pyo3 (kinda...).

i agree that the pattern i had of pre-creating the module then passing in to the parent is awkward compared with the .add_submodule() option as a module creator method. i wasn't sure how much interest to expect in changing api patterns. i'm happy to look at options like this.

@davidhewitt
Copy link
Member

Thanks, see also test_declarative_module.

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.

3 participants