From 3c54dc11aeac4574564debca32c651c0b5d2d74d Mon Sep 17 00:00:00 2001 From: Josh Mitchell Date: Tue, 12 Nov 2024 17:07:44 +1100 Subject: [PATCH 1/2] Always getattr() in lazy import machinery --- openff/toolkit/__init__.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/openff/toolkit/__init__.py b/openff/toolkit/__init__.py index 5fcd9bc70..f576a4f8e 100644 --- a/openff/toolkit/__init__.py +++ b/openff/toolkit/__init__.py @@ -79,10 +79,7 @@ def __getattr__(name): obj_mod = _lazy_imports_obj.get(name) if obj_mod is not None: mod = importlib.import_module(obj_mod) - try: - return mod.__dict__[name] - except KeyError: # account for lazy loaders - return getattr(mod, name) + return getattr(mod, name) lazy_mod = _lazy_imports_mod.get(name) if lazy_mod is not None: From 0705bee31eb9a7da3bb183336f81553a0b2cdf30 Mon Sep 17 00:00:00 2001 From: Josh Mitchell Date: Tue, 12 Nov 2024 17:29:58 +1100 Subject: [PATCH 2/2] Add explanatory safety comment about getattr recursion --- openff/toolkit/__init__.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/openff/toolkit/__init__.py b/openff/toolkit/__init__.py index f576a4f8e..a5fe42fa3 100644 --- a/openff/toolkit/__init__.py +++ b/openff/toolkit/__init__.py @@ -79,6 +79,12 @@ def __getattr__(name): obj_mod = _lazy_imports_obj.get(name) if obj_mod is not None: mod = importlib.import_module(obj_mod) + # This only causes an infinite recursive loop if an object that does not + # exist is declared in `_lazy_imports_obj` to be lazy loaded from the + # current module. Since there is no reason to include either an object + # from the current module or an object that does not exist in + # `_lazy_imports_obj`, and since the function would fail in this case + # anyway, this is safe. return getattr(mod, name) lazy_mod = _lazy_imports_mod.get(name)