8000 Replace pkgutil.get_loader/load_module in adapter discovery with importlib by EricMG1 · Pull Request #490 · llnl/maestrowf · GitHub
[go: up one dir, main page]

Skip to content

Replace pkgutil.get_loader/load_module in adapter discovery with importlib - #490

Open
EricMG1 wants to merge 2 commits into
llnl:developfrom
EricMG1:bugfix/importlib_adapter_discovery
Open

EricMG1 wants to merge 2 commits into
llnl:developfrom
EricMG1:bugfix/importlib_adapter_discovery

Conversation

@EricMG1
@EricMG1 EricMG1 commented Nov 1, 2026
Copy link
Copy Markdown

Fixes #486, closes #489.

pkgutil.get_loader was removed in Python 3.14, and Loader.load_module() is slated for removal in 3.15.
ScriptAdapterFactory.iter_adapters and FluxFactory._iter_flux used both to discover their implementations, so on 3.14 import maestrowf.interfaces raises AttributeError: module 'pkgutil' has no attribute 'get_loader' and the maestro and conductor entry points die on startup (#486).
On 3.12 and 3.13 the same import emits six DeprecationWarnings for it, hidden in CI by -p no:warnings.

What changed

  • Discovery imports the package and each of its modules with importlib.import_module and still enumerates them with pkgutil.iter_modules, which is not deprecated. No change to which classes are found or how they are keyed.
  • A side effect goes away: the load_module() shim re-executes a module that is already in sys.modules, so every call re-ran each adapter module (and iter_adapters ran script/__init__.py twice at import). A second call therefore returned classes that were not the ones registered in the factory. import_module returns the module already imported, so discovery is idempotent now.
  • Tests (tests/interfaces/test_script_adapter.py): the built-in adapters are found under their keys, discovery returns the very classes the factories registered, and neither discovery raises a DeprecationWarning. The identity and warning tests fail against 1.2.1 on 3.12, and all of them fail there on 3.14.
  • CI: the pip matrix gains 3.14, and the "Test editable install" step now also imports maestrowf.interfaces and runs maestro --version, so that leg checks more than that the build backend succeeded.
  • Dev version ticked to 1.2.2dev1; scriv fragment added (Fixed + Maintenance).

Why the poetry matrix stays at 3.13

poetry install from the current lock cannot complete on 3.14: the locked rpds-py 0.20.0 (via jsonschema) has no 3.14 wheel, and its source build fails (PyO3 0.22 stops at 3.13). Every rpds-py release that ships 3.14 wheels requires Python >= 3.9, so with a single locked version that leg is tied to the 3.8 floor rather than to this change. #487's lock refresh is the place to pick that up.

Verification

  • pytest on Windows under Python 3.12, 3.13, 3.14 and 3.15 (pytest 8, CI=true hypothesis profile): identical results on all four, and identical to unmodified develop on 3.12 apart from the new tests passing. The pre-existing failures on this box are the path-sanitiser, status-renderer and Slurm-fixture tests, which depend on POSIX paths and a scheduler.
  • python -W 8000 default -c "import maestrowf.interfaces" on 3.12: no warnings from maestrowf (six before).
  • maestro --version starts on 3.14 and 3.15.
  • flake8 clean on the changed source files; the test file keeps its two pre-existing E275s.

One comment/note that was picked up during the review/work was that: FluxInterface_0170 and FluxInterface_0190 are abstract on develop (neither implements get_flux_urgency), so FluxFactory registers only 0.26.0 and 0.49.0.
I don't really have a good understanding of that nuance/relevancy but might be a useful note for other future developers

Developed/reviewed with AI assistance

EricMG1 and others added 2 commits November 1, 2026 16:16
…rtlib

pkgutil.get_loader was removed in Python 3.14 and Loader.load_module is
slated for removal in 3.15. ScriptAdapterFactory and FluxFactory used both
to discover their implementations, so `import maestrowf.interfaces` -- and
with it the maestro and conductor CLIs -- failed on 3.14 (llnl#486, llnl#489).

Discovery now imports the package and each of its modules with
importlib.import_module and still enumerates them with pkgutil.iter_modules,
which is not deprecated. The old load_module() shim also re-executed a
module that was already imported, so a later call could hand back classes
other than the ones registered at import; import_module returns the module
already in sys.modules, so discovery is idempotent now.

Tests cover the discovered adapters and Flux interfaces, identity with the
registered classes, and that discovery raises no DeprecationWarning. CI's
pip matrix gains 3.14 and now imports the package and runs `maestro
--version` after installing it. The poetry matrix cannot run on 3.14 until
the locked rpds-py (0.20.0, built on PyO3 0.22, which stops at 3.13) moves;
every rpds-py with 3.14 wheels needs Python >= 3.9, so that is tied to the
3.8 floor rather than to this change.

Tick the dev version to 1.2.2dev1 and add the changelog fragment.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant

0