From 116c0fcd10b4c01ed17c9525ae2a2f3cfc32d926 Mon Sep 17 00:00:00 2001 From: Sachaa-Thanasius Date: Fri, 20 Sep 2024 03:53:44 +0530 Subject: [PATCH] Add check for module or proxy type before doing subproxy attachment in _deferred___import__ --- pyproject.toml | 1 - src/defer_imports/__init__.py | 31 ++++++++++++++++--------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d2afcbd..a143229 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -82,7 +82,6 @@ plugins = ["covdefaults"] source = ["defer_imports", "tests"] omit = [ "src/defer_imports/_typing.py", # Has a module-level __getattr__ that isn't invoked at runtime. - "src/defer_imports/console.py", # Has a REPL that is manually tested currently. ] [tool.coverage.report] diff --git a/src/defer_imports/__init__.py b/src/defer_imports/__init__.py index 823c385..614b7bd 100644 --- a/src/defer_imports/__init__.py +++ b/src/defer_imports/__init__.py @@ -702,7 +702,7 @@ def path_hook( def path_hook_for_DeferredFileFinder(path: str) -> _tp.Self: """Path hook for DeferredFileFinder.""" - if not os.path.isdir(path): # noqa: PTH112 + if not os.path.isdir(path): # noqa: PTH112 # os is loaded on startup. msg = "only directories are supported" raise ImportError(msg, path=path) @@ -980,7 +980,7 @@ def _deferred___import__( # noqa: ANN202 fromlist = fromlist or () - package = _calc___package__(locals) + package = _calc___package__(globals) _sanity_check(name, package, level) # Resolve the names of relative imports. @@ -992,23 +992,24 @@ def _deferred___import__( # noqa: ANN202 if not fromlist and ("." in name): name_parts = name.split(".") try: - # TODO: Consider adding a condition that base_parent must be a ModuleType or a _DeferredImportProxy, to - # avoid attaching proxies to a random thing that would've normally been clobbered by the import? base_parent = parent = locals[name_parts[0]] except KeyError: pass else: - # Nest submodule proxies as needed. - for limit, attr_name in enumerate(name_parts[1:], start=2): - if attr_name not in vars(parent): - nested_proxy = _DeferredImportProxy(".".join(name_parts[:limit]), globals, locals, (), level) - nested_proxy.defer_proxy_sub = attr_name - setattr(parent, attr_name, nested_proxy) - parent = nested_proxy - else: - parent = getattr(parent, attr_name) - - return base_parent + # NOTE: We assume that if base_parent is a ModuleType or _DeferredImportProxy, then it shouldn't be getting + # clobbered. Not sure if this is right, but it feels like the safest move. + if isinstance(base_parent, (type(sys), _DeferredImportProxy)): + # Nest submodule proxies as needed. + for limit, attr_name in enumerate(name_parts[1:], start=2): + if attr_name not in vars(parent): + nested_proxy = _DeferredImportProxy(".".join(name_parts[:limit]), globals, locals, (), level) + nested_proxy.defer_proxy_sub = attr_name + setattr(parent, attr_name, nested_proxy) + parent = nested_proxy + else: + parent = getattr(parent, attr_name) + + return base_parent return _DeferredImportProxy(name, globals, locals, fromlist, level)