feat: add lazy_context (beware: magic)#12
feat: add lazy_context (beware: magic)#12tlambert03 wants to merge 1 commit intoscientific-python:mainfrom
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 meanThis 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
withblock 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 :)