commit:     071b4950affe4f84d1633b66e542402fb34b7f75
Author:     Brian Harring <ferringb <AT> gmail <DOT> com>
AuthorDate: Wed Dec 17 23:02:20 2025 +0000
Commit:     Brian Harring <ferringb <AT> gmail <DOT> com>
CommitDate: Sat Jan 10 10:15:42 2026 +0000
URL:        
https://gitweb.gentoo.org/proj/pkgcore/snakeoil.git/commit/?id=071b4950

reimplement delay import via delayed.import_module

This time around we can do this via just proxying against the
shape of a module, wrapping importlib to do it.  Much, much
simpler since python caught up.

Usage of this to cycle break is a sign of "restructure yo shiat",
but it's also usable for perf reasons.  Much like why python
added lazy imports for 3.15, and this is limited to just module
imports to make that transition simpler.

Signed-off-by: Brian Harring <ferringb <AT> gmail.com>

 src/snakeoil/delayed/__init__.py |  7 +++++++
 tests/test_delayed.py            | 14 ++++++++++++++
 2 files changed, 21 insertions(+)

diff --git a/src/snakeoil/delayed/__init__.py b/src/snakeoil/delayed/__init__.py
index 3a469ca..8feb83c 100644
--- a/src/snakeoil/delayed/__init__.py
+++ b/src/snakeoil/delayed/__init__.py
@@ -1,7 +1,9 @@
 __all__ = ("regexp",)
 
 import functools
+import importlib
 import re
+import types
 
 from ..obj import DelayedInstantiation
 
@@ -10,3 +12,8 @@ from ..obj import DelayedInstantiation
 def regexp(pattern: str, flags: int = 0):
     """Lazily compile a regexp; reify it only when it's needed"""
     return DelayedInstantiation(re.Pattern, re.compile, pattern, flags)
+
+
+def import_module(target: str) -> types.ModuleType:
+    """Import a module at time of access.  This is a shim for python's lazy 
import in 3.15"""
+    return DelayedInstantiation(types.ModuleType, importlib.import_module, 
target)

diff --git a/tests/test_delayed.py b/tests/test_delayed.py
index c74f454..82e4fd7 100644
--- a/tests/test_delayed.py
+++ b/tests/test_delayed.py
@@ -1,6 +1,7 @@
 import re
 
 from snakeoil import delayed
+from snakeoil.python_namespaces import protect_imports
 
 
 def test_regexp():
@@ -13,3 +14,16 @@ def test_regexp():
 
     # assert we lie.
     assert isinstance(delayed.regexp("asdf"), re.Pattern)
+
+
+def test_import_module(tmp_path):
+    with (tmp_path / "blah.py").open("w") as f:
+        f.write("x=1")
+    with protect_imports() as (path, modules):
+        path.append(str(tmp_path))
+        f = delayed.import_module("blah")
+        assert "blah" not in modules
+        assert "blah" == f.__name__
+        assert "blah" in modules
+        assert 1 == f.x
+        assert modules["blah"] is not f

Reply via email to