-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
feat: add lazy_context (beware: magic) #12
Conversation
@tlambert03 Hah, fun and clever! But, indeed, the |
there is a way by patching |
mad respect for the crazy magic |
@stefanv you could achieve the same by loading an invalid package, e.g.:
|
or really use any exception of your choice to stop the process. actually thinking about this i like that form of magic 😂 for example u could make a function |
For extra confusion, you can use: with lazy_loader.lazy_imports():
...
0//4
...
from . import rank
from ._fft_based import butterworth
from ._gabor import gabor, gabor_kernel
from ._gaussian import difference_of_gaussians, gaussian 😄 Maybe more sensibly: with lazy_loader.lazy_imports() as delay_imports:
delay_imports()
from . import rank
from ._fft_based import butterworth
from ._gabor import gabor, gabor_kernel
from ._gaussian import difference_of_gaussians, gaussian |
Apparently, the assignment to a variable also counts as part of the code inside the You would want to catch in the |
I still cannot let this syntax go (it is better than stubs). from contextlib import contextmanager
def raise_exc(*args, **kwargs):
raise ImportError
@contextmanager
def remove_exceptions():
import builtins
import_fun = builtins.__import__
builtins.__import__ = raise_exc
try:
yield None
finally:
builtins.__import__ = import_fun
with remove_exceptions:
from numpy import mean This approach even allows to remove the magic, letting Python machinery give us the import names themselves!!!: import builtins
from types import SimpleNamespace
class SaveModules():
def __init__(self):
self.imports = []
def __enter__(self):
self.import_fun = builtins.__import__
builtins.__import__ = self._my_import
return None
def __exit__(self, type, value, tb):
builtins.__import__ = self.import_fun
print(self.imports)
def _my_import(self, name, globals=None, locals=None, fromlist=(), level=0):
builtins.__import__ = self.import_fun
self.imports.append({"name": name, "fromlist": fromlist, "level": level})
builtins.__import__ = self._my_import
if fromlist:
return SimpleNamespace(**{k: None for k in fromlist})
return None
with SaveModules():
from numpy import mean
import scipy
from .. import kk |
The advantage of the stubs is that you get type inference, which is more important to a lot of people than I realized. But this is certainly an improvement in syntax over |
Why shouldn't you get type inference with this approach? As far as I know Mypy will assume that the imports work as normal (I haven't tested it) and use their associated types. |
Worth a try! |
indeed. worth a try! :) |
I was intrigued by @maurosilber context manager concept from #11 ...
This PR achieves that syntax using some serious ridiculousness 😂
believe it or not, it works! and it makes IDEs happy without any pyi files. It basically parses the source code from the
with
block using the same ast parser from #10 ... and then injects the output into the module globalsThat said, I wouldn't be surprised or offended in the least if you closed this PR immediately and rushed off to take a shower 🛀 Opening this mostly as a proof of principle and record of a little magic exploration :)