Closed hoedt closed 1 year ago
@hoedt Thank you very much for your comments, and sorry for missing the issue here initially.
Can I ask you to please file a single pull request per feature you want to add, then we can decide what to do. If you first want to discuss, we can start with an issue per item.
I'll give you my gut feel on each item:
__all__
and __dir__
mechanism is what we have to work with; you can of course choose not to make use of the produced __all__
, or you can modify it after the fact.import x as y
isn't currently supported, but I think that's a reasonable feature to request. I haven't checked, but there is a possibility that the stub loader already supports this.__dir__
does not list special attributes; this was by design, but if you have a good motivation for why it needs to be there (and there may well be one!), then we can add it back in.
I am pretty new to writing packages, but I was recently looking for exactly this kind of functionality. However, I noticed that this does not exactly does what I had in mind (or maybe it does not quite cover my use case).
E.g. Consider a package with multiple files (e.g.
err.py
,core.py
,bells.py
andwhistles.py
) implementing different aspects of the code. Assuming that I would like to make everything accessible, the__init__.py
file could look something like this:Now, if I wanted to load the
bells
andwhistles
modules lazily (and understood everything correctly), I could do:Technically this should give (almost) the same result as the eager version (I didn't test it), but I do see a few issues:
import ... as ...
) could be made to work here. I believe this also makes it impossible to import features from different submodules that have the same name.__all__
and__dir__
does feel quite clumsy and I would argue that a better user experience should be possible here. This might not be the biggest of issues, but as soon as you wish to have something like__version__
in your package, an override like this seems to be necessary.__all__
), since theattach
simply dumps every feature in there even if it should not be available for wildcard imports.Apart from these issues specific to lazy loading, I also noticed that lazy and eager loading are not so equivalent after all. The main differences that I noticed are:
__dir__
does not list the special dunder variables (e.g.__package__
,__name__
, ...)pkg.bells
from the example above would raise anAttributeError
in the lazy setting, but return the sub-module when imported eagerly)A possible solution
To circumvent these issues, I took the liberty to mess with the code a bit and I arrived at something that could be the beginning of a solution:
The main difference is that we use the default names from
dir()
and use an additionaldict
to allow duplicate names (and aliasing). I also made sure that all sub-modules are available through__getattr__
. This also made it possible to mergesubmodules
andsubmod_attrs
because you can always pass an empty list of attributes / functions to load only the module.Now, this could be used as follows (using the same example as above):
I hope I have been clear. Just let me know if you need more information (or counterarguments).