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

Type hints/Mypy best practices? #28

Closed vnmabus closed 1 year ago

vnmabus commented 1 year ago

Unfortunately it seems that Mypy cannot obtain the information to type lazy imports using this module. The only way that I found to work around this is to REPEAT the imports in a if TYPE_CHECKING block, which honestly feels like a defeat. Is there any other way to "play well to Mypy" using this package?

nstarman commented 1 year ago

Following up on this comment, this package might be able to implement mypy and pyright plugins (e.g. https://mypy.readthedocs.io/en/stable/extending_mypy.html for the former). Then there would not be a need for the __init__.pyi file the SPEC suggests.

stefanv commented 1 year ago

We've now tried the __init__.pyi stub loader in a library (librosa) and it works perfectly.

@vnmabus can you give it a try? I've updated the SPEC with relevant usage information.

leroyvn commented 1 year ago

I just tried it on my project eradiate/eradiate and it work perfectly, thanks a lot!

nstarman commented 1 year ago

Followup: using numpy's mypy plugin as a reference, I specced out a quick mypy plugin (see https://github.com/nstarman/lazy_loader/tree/mypy_plugin) and unfortunately it doesn't look like there's an easy replacement to the pyi file. If this package mandated that a single import be included, then I think I know how to overload that import and add on the contents of lazy_loader.attach:

from . import ...   # THIS IS MANDATORY
import lazy_loader as _lazy_loader

..., __all__ = _lazy_loader.attach(...)

Short of that, I haven't grokked out how to inject a new import line.

stefanv commented 1 year ago

@nstarman It looks to me like this may warrant a new issue. I'm going to close this one (since it's been resolved), but feel free to open another issue for the mypy plugin discussion.