Question
How to make a lazy loader play nice with static type checking?
I've written a crude lazy importer so you can do stuff like this:
from loader import Lazy
httpx = Lazy("httpx") # The `httpx` module is not yet loaded
httpx.get("https://google.ca/") # Loads the `httpx` module and calls `.get()`
This is what it looks like:
from functools import cached_property
from importlib import import_module
from typing import Any, TYPE_CHECKING
class Lazy:
def __init__(self, name: str) -> None:
self._name = name
def __getattr__(self, item: str) -> Any:
return getattr(self._module, item)
@cached_property
def _module(self):
return import_module(self._name)
...and it works! However, static type checkers like Mypy and PyCharm treat the lazily-imported httpx
module as if it's capable of anything, so code like this:
from loader import Lazy
httpx = Lazy("httpx")
httpx.get(42)
httpx.woot
...isn't flagged for being broken. PyCharm has no way of autocompleting method names or arguments either, so while the code runs, it's much harder to develop on.
In a perfect world, the lazy loader would have a way of swapping itself out for the lazily-imported module in the eyes of the static type checker, but that'd require the static typechecker to do dynamic things, so I'm not even sure that can be done.
Is there an option available to me, or is this simply a no-no in Pythonland? Normally, I wouldn't even try to do something like this, but the codebase I'm working on is Very Big and a lazy loader could got a long way to improving start times when doing local development.