scientific-python / lazy-loader

Populate library namespace without incurring immediate import costs
BSD 3-Clause "New" or "Revised" License
118 stars 19 forks source link

expose submodules of attribute imports by default #49

Closed hoedt closed 1 year ago

hoedt commented 1 year ago

This addresses one of the points addressed in #32

With this change, it should also be possible to do away with the distinction between submodules and attr_to_modules, because all submodules could be specified as attr_to_modules with an empty list of attributes or a special value (e.g. None).

stefanv commented 1 year ago

Thanks, @hoedt. Can you clarify the purpose of the change, the problem it addresses, and the change in behavior relative to the existing implementation?

hoedt commented 1 year ago

@stefanv Let me try:

Purpose

Expose submodules of attribute imports by default so that

__getattr__, __dir__, __all__ = lazy.attach(__name__, None, submod_attrs={"submodule": ["attr"]})

assert "submodule" in __all__
assert "submodule" in __dir__()
submodule = __getattr__("submodule")
Problem

README claims equivalence to regular imports, but this is not true if submodules of attribute imports are not exposed. However, I do not know of any particular scenarios this "feature" is actually used.

Changes

Submodules of attribute imports are now also available through __getattr__, __dir__ and __all__. This should be (more) equivalent to regular imports than the original implementation. Also, lazy.attach(__name__, None, {"submodule": []}) is now equivalent to lazy.attach(__name__, ["submodule"], None). Before this change, the former was a no-op. This could be used to get rid of the submodules argument entirely.

stefanv commented 1 year ago

Unavailability of unimported submodules is known, and if not already done should be documented. It's a side-effect of regular importing, and probably not a desirable one, causing projects to have to delete or hide those modules, so we don't want to add that back in.