Summary
source/bind/python/CEA.pyx's public-API export list (__all__, built at CEA.pyx:5091-5093) is a hand-maintained blocklist that excludes a handful of named helper-module imports from globals(), but misses two: os and importlib.resources (imported as importlib_resources). Both are real, live attributes of the public cea package after import cea.
Reproduction
- Interface: Python
- Minimal input / steps:
import cea
print(cea.os) # a live reference to the stdlib os module
print(cea.importlib_resources) # a live reference to importlib.resources
print('os' in cea.__all__, 'importlib_resources' in cea.__all__)
- Command or API call used:
import cea
Expected behavior
cea.os and cea.importlib_resources should not exist — the public cea namespace should only expose the library's actual API (classes, functions, constants), not implementation-detail imports used internally by CEA.pyx.
Actual behavior
Confirmed by running the reproduction above against the built cea-dev package:
cea.os -> <module 'os' (frozen)>
cea.importlib_resources -> <module 'importlib.resources' from '...'>
True True
Root cause: CEA.pyx:9-10 does top-level import os and import importlib.resources as importlib_resources, but the _public_exclude set at CEA.pyx:5092 that filters globals() down to __all__ only lists {"cython", "ctypes", "array", "warnings", "np", "Optional"} — os and importlib_resources were never added. cea/__init__.py:16 then does from cea.lib.libcea import *, so anything in libcea.__all__ becomes part of the public cea package.
Environment
- OS: Windows 11
- CEA version/commit: 3.3.4 /
7ec0859
- Compiler or Python version (if relevant): Python 3.x,
cea-dev conda env
Additional context
Beyond the two confirmed leaks, this exclusion mechanism is inherently fragile: it's a manually-maintained blocklist rather than an allowlist, so any future top-level import added to CEA.pyx leaks into the public API by default unless someone remembers to add it to _public_exclude. Worth considering an allowlist approach instead (e.g. explicitly listing what should be public, or filtering by checking inspect.ismodule(...) to exclude all bare module references automatically) so this class of bug can't recur.
Drafted with Claude's assistance
- Confirmed numerically: ran the reproduction above against the built
cea-dev package; both cea.os and cea.importlib_resources resolve to live module objects, and both names are present in cea.__all__/libcea.__all__.
- Checked
gh issue list on djkees/cea before filing (searched __all__, namespace) — no existing issue.
Summary
source/bind/python/CEA.pyx's public-API export list (__all__, built atCEA.pyx:5091-5093) is a hand-maintained blocklist that excludes a handful of named helper-module imports fromglobals(), but misses two:osandimportlib.resources(imported asimportlib_resources). Both are real, live attributes of the publicceapackage afterimport cea.Reproduction
import ceaExpected behavior
cea.osandcea.importlib_resourcesshould not exist — the publicceanamespace should only expose the library's actual API (classes, functions, constants), not implementation-detail imports used internally byCEA.pyx.Actual behavior
Confirmed by running the reproduction above against the built
cea-devpackage:Root cause:
CEA.pyx:9-10does top-levelimport osandimport importlib.resources as importlib_resources, but the_public_excludeset atCEA.pyx:5092that filtersglobals()down to__all__only lists{"cython", "ctypes", "array", "warnings", "np", "Optional"}—osandimportlib_resourceswere never added.cea/__init__.py:16then doesfrom cea.lib.libcea import *, so anything inlibcea.__all__becomes part of the publicceapackage.Environment
7ec0859cea-devconda envAdditional context
Beyond the two confirmed leaks, this exclusion mechanism is inherently fragile: it's a manually-maintained blocklist rather than an allowlist, so any future top-level
importadded toCEA.pyxleaks into the public API by default unless someone remembers to add it to_public_exclude. Worth considering an allowlist approach instead (e.g. explicitly listing what should be public, or filtering by checkinginspect.ismodule(...)to exclude all bare module references automatically) so this class of bug can't recur.Drafted with Claude's assistance
cea-devpackage; bothcea.osandcea.importlib_resourcesresolve to live module objects, and both names are present incea.__all__/libcea.__all__.gh issue liston djkees/cea before filing (searched__all__,namespace) — no existing issue.