Skip to content

Commit 4ae6350

Browse files
committed
chore: mid work
1 parent be3b426 commit 4ae6350

5 files changed

Lines changed: 448 additions & 427 deletions

File tree

packages/@jsii/python-runtime/src/jsii/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
kernel,
1515
proxy_for,
1616
)
17+
from ._utils import _LazyImport
1718
from . import python
1819

1920

@@ -49,6 +50,7 @@
4950
__all__ = [
5051
"__version__",
5152
"__jsii_runtime_version__",
53+
"_LazyImport",
5254
"JSIIAssembly",
5355
"JSIIMeta",
5456
"JSIIAbstractClass",

packages/@jsii/python-runtime/src/jsii/_utils.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import functools
2+
import importlib
23

34
from typing import Any, MutableMapping, Type
45

@@ -24,3 +25,28 @@ def wrapped(self):
2425
return stored[0]
2526

2627
return property(wrapped)
28+
29+
30+
class _LazyImport:
31+
"""Defers ``importlib.import_module()`` until first attribute access.
32+
33+
This is used by jsii-pacmak generated code to lazily import cross-module
34+
dependencies, breaking circular import chains and reducing module load time.
35+
36+
The imported module is cached after first successful resolution. Failed
37+
imports are NOT cached, allowing retry on subsequent access.
38+
"""
39+
40+
def __init__(self, module_name: str) -> None:
41+
self._module_name = module_name
42+
self._module: Any = None
43+
44+
def __getattr__(self, name: str) -> Any:
45+
if self._module is None:
46+
self._module = importlib.import_module(self._module_name)
47+
return getattr(self._module, name)
48+
49+
def __repr__(self) -> str:
50+
if self._module is not None:
51+
return repr(self._module)
52+
return f"_LazyImport({self._module_name!r})"

packages/jsii-pacmak/lib/targets/python.ts

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2164,30 +2164,13 @@ class PythonModule implements PythonType {
21642164
}
21652165

21662166
/**
2167-
* Emit the `_LazyImport` helper class that defers `importlib.import_module()`
2168-
* until first attribute access via `__getattr__`.
2169-
*
2170-
* The class is emitted once per module that has cross-module imports. It wraps
2171-
* a module name string and caches the imported module after first access.
2172-
* Failed imports are NOT cached, allowing retry on subsequent access.
2167+
* Emit the `_LazyImport` alias that references `jsii._LazyImport` from the
2168+
* runtime package. This avoids duplicating the class definition in every
2169+
* generated module.
21732170
*/
2174-
private emitLazyImportClass(code: CodeMaker) {
2171+
private emitLazyImportAlias(code: CodeMaker) {
21752172
code.line();
2176-
code.openBlock('class _LazyImport');
2177-
// __init__
2178-
code.openBlock('def __init__(self, module_name: str) -> None');
2179-
code.line('self._module_name = module_name');
2180-
code.line('self._module: typing.Any = None');
2181-
code.closeBlock();
2182-
// __getattr__
2183-
code.openBlock('def __getattr__(self, name: str) -> typing.Any');
2184-
code.openBlock('if self._module is None');
2185-
code.line('import importlib');
2186-
code.line('self._module = importlib.import_module(self._module_name)');
2187-
code.closeBlock();
2188-
code.line('return getattr(self._module, name)');
2189-
code.closeBlock();
2190-
code.closeBlock();
2173+
code.line('_LazyImport = jsii._LazyImport');
21912174
}
21922175

21932176
/**
@@ -2258,8 +2241,8 @@ class PythonModule implements PythonType {
22582241
return;
22592242
}
22602243

2261-
// Emit _LazyImport class definition
2262-
this.emitLazyImportClass(code);
2244+
// Emit a local alias to jsii._LazyImport for use in lazy proxy assignments
2245+
this.emitLazyImportAlias(code);
22632246

22642247
// Emit TYPE_CHECKING block with original import statements for static type checkers,
22652248
// and lazy proxy assignments in the else branch for runtime.

0 commit comments

Comments
 (0)