Skip to content

Import utils relative-first to avoid cross-extension shadowing - #2

Open
marc-lehner wants to merge 1 commit into
rdkit:mainfrom
knime-community:fix/utils-import-shadowing-upstream
Open

marc-lehner wants to merge 1 commit into
rdkit:mainfrom
knime-community:fix/utils-import-shadowing-upstream

Conversation

@marc-lehner

Copy link
Copy Markdown

Problem

These nodes fail to load in a KNIME installation that also has the PM4KNIME extension:

File ".../org.rdkit.python_rdkit_nodes_0.1.0.../src/main/python/src/standardizer_parent.py", line 80
    category=utils.category,
AttributeError: module 'utils' has no attribute 'category'

KNIME adds the module directory of every registered Python port-object converter (and every PythonValueFactory module's parent directory) to the sys.path of every Python gateway — not just the one belonging to the contributing extension. PM4KNIME contributes a directory containing a top-level utils/ with no __init__.py, i.e. a namespace package named utils.

Three modules here do:

try:
    import utils
except ImportError:
    from . import utils

Normally the absolute import utils fails and the relative fallback runs. With such an extension installed the absolute import succeeds and binds the other extension's namespace package, which has no attributes at all — so utils.category raises AttributeError, and the fallback never fires because it only catches ImportError.

Any extension shipping a generically named top-level module can trigger this; PM4KNIME is just the one that surfaced it.

Fix

Swap the order: try the relative import first, keep the absolute one as the fallback for the test suite, which imports these modules without a package context. Three files — the ones activated in src/__init__.py.

Verification

  • Reproduced the exact failure in isolation (a package module plus a rogue top-level utils namespace package on sys.path): old order → AttributeError: module 'utils' has no attribute 'category'; new order → binds the extension's own utils.
  • Standalone import path (what the test suite uses) still resolves correctly: import standardizer_parent with src on sys.path binds src/utils.py, with utils.category present.
  • pytest src fails identically before and after this change — collection errors from a pre-existing ModuleNotFoundError: No module named 'SA_Score' (RDKit Contrib not on the path in that environment). Not touched here.

Notes

The other utils importers in this repo (from new_rdkit_nodes import utils in molecule_grid_image.py, standardizer_normalize.py, visualize_*.py, rgroup_highlight.py) reference a package name that no longer exists, but all of those modules are commented out in src/__init__.py, so they are dormant and left alone here.

🤖 Generated with Claude Code

KNIME puts the module directory of every registered Python port-object
converter on the sys.path of every Python gateway, not just the one
belonging to the contributing extension. Another extension (PM4KNIME)
contributes a top-level `utils` namespace package, so the bare
`import utils` here bound the wrong module and `utils.category` raised
AttributeError, breaking extension loading in any KNIME installation that
has both extensions.

Trying the relative import first binds this extension's own utils. The
absolute import stays as the fallback for the test suite, which imports
these modules without a package context.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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