omlish 0.0.0.dev458__py3-none-any.whl → 0.0.0.dev460__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- omlish/__about__.py +3 -3
- omlish/diag/pydevd.py +23 -1
- omlish/lang/imports/_capture.cc +5 -4
- omlish/lang/imports/capture.py +361 -170
- omlish/lang/imports/proxy.py +445 -152
- omlish/lang/lazyglobals.py +22 -9
- omlish/term/vt100/terminal.py +0 -3
- {omlish-0.0.0.dev458.dist-info → omlish-0.0.0.dev460.dist-info}/METADATA +3 -3
- {omlish-0.0.0.dev458.dist-info → omlish-0.0.0.dev460.dist-info}/RECORD +13 -13
- {omlish-0.0.0.dev458.dist-info → omlish-0.0.0.dev460.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev458.dist-info → omlish-0.0.0.dev460.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev458.dist-info → omlish-0.0.0.dev460.dist-info}/licenses/LICENSE +0 -0
- {omlish-0.0.0.dev458.dist-info → omlish-0.0.0.dev460.dist-info}/top_level.txt +0 -0
omlish/lang/imports/proxy.py
CHANGED
@@ -1,10 +1,27 @@
|
|
1
1
|
"""
|
2
2
|
TODO:
|
3
|
+
- _ProxyImports
|
3
4
|
- if already imported just return?
|
5
|
+
- no, need sub-imports..
|
6
|
+
- seal on first use? or just per module? can't seal roots and still be usable
|
7
|
+
- only if not hasattr?
|
8
|
+
- audit for deadlock risk - does importlib._bootstrap do it for us? do we need a global _ProxyImporter lock? would only
|
9
|
+
happen on reification
|
10
|
+
- ProxyImportError
|
11
|
+
|
12
|
+
See:
|
13
|
+
- https://peps.python.org/pep-0810/
|
14
|
+
- https://github.com/LazyImportsCabal/cpython/tree/lazy
|
15
|
+
- https://developers.facebook.com/blog/post/2022/06/15/python-lazy-imports-with-cinder/
|
16
|
+
- https://engineering.fb.com/2024/01/18/developer-tools/lazy-imports-cinder-machine-learning-meta/
|
17
|
+
- https://www.hudsonrivertrading.com/hrtbeat/inside-hrts-python-fork/
|
18
|
+
- https://bugreports.qt.io/browse/PYSIDE-2404
|
19
|
+
- https://scientific-python.org/specs/spec-0001/
|
20
|
+
- https://github.com/scientific-python/lazy-loader
|
4
21
|
"""
|
5
|
-
import contextlib
|
6
22
|
import functools
|
7
23
|
import importlib.util
|
24
|
+
import threading
|
8
25
|
import types
|
9
26
|
import typing as ta
|
10
27
|
|
@@ -13,138 +30,340 @@ from .capture import ImportCapture
|
|
13
30
|
from .capture import _new_import_capture_hook
|
14
31
|
|
15
32
|
|
33
|
+
_ProxyImporterModuleAttr: ta.TypeAlias = ta.Literal[
|
34
|
+
'child', # 'outranks' proxy_attr - all child attrs must be proxy_attrs but not vice versa
|
35
|
+
'proxy_attr',
|
36
|
+
'pending_child',
|
37
|
+
'pending_attr',
|
38
|
+
]
|
39
|
+
|
40
|
+
|
16
41
|
##
|
17
42
|
|
18
43
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
44
|
+
class _ProxyImporter:
|
45
|
+
def __init__(
|
46
|
+
self,
|
47
|
+
*,
|
48
|
+
owner_globals: ta.MutableMapping[str, ta.Any] | None = None,
|
49
|
+
) -> None:
|
50
|
+
super().__init__()
|
26
51
|
|
27
|
-
|
52
|
+
self._owner_globals = owner_globals
|
53
|
+
|
54
|
+
self._owner_name: str | None = owner_globals.get('__name__') if owner_globals else None
|
55
|
+
|
56
|
+
# NOTE: Import machinery may be reentrant for things like gc ops and signal handling:
|
57
|
+
# TODO: audit for reentrancy this lol
|
58
|
+
# https://github.com/python/cpython/blob/72f25a8d9a5673d39c107cf522465a566b979ed5/Lib/importlib/_bootstrap.py#L233-L237 # noqa
|
59
|
+
self._lock = threading.RLock()
|
60
|
+
|
61
|
+
self._modules_by_name: dict[str, _ProxyImporter._Module] = {}
|
62
|
+
self._modules_by_proxy_obj: dict[types.ModuleType, _ProxyImporter._Module] = {}
|
63
|
+
|
64
|
+
class _Module:
|
65
|
+
def __init__(
|
66
|
+
self,
|
67
|
+
name: str,
|
68
|
+
getattr_handler: ta.Callable[['_ProxyImporter._Module', str], ta.Any],
|
69
|
+
*,
|
70
|
+
parent: ta.Optional['_ProxyImporter._Module'] = None,
|
71
|
+
) -> None:
|
72
|
+
super().__init__()
|
73
|
+
|
74
|
+
self.name = name
|
75
|
+
self.parent = parent
|
76
|
+
|
77
|
+
self.base_name = name.rpartition('.')[2]
|
78
|
+
self.root: _ProxyImporter._Module = parent.root if parent is not None else self # noqa
|
79
|
+
|
80
|
+
self.children: dict[str, _ProxyImporter._Module] = {}
|
81
|
+
self.descendants: set[_ProxyImporter._Module] = set()
|
82
|
+
|
83
|
+
self.proxy_obj = types.ModuleType(f'<{self.__class__.__qualname__}: {name}>')
|
84
|
+
self.proxy_obj.__file__ = None
|
85
|
+
self.proxy_obj.__getattr__ = functools.partial(getattr_handler, self) # type: ignore[method-assign]
|
86
|
+
|
87
|
+
self.pending_children: set[str] = set()
|
88
|
+
self.pending_attrs: set[str] = set()
|
89
|
+
|
90
|
+
real_obj: types.ModuleType | None = None
|
91
|
+
|
92
|
+
def __repr__(self) -> str:
|
93
|
+
return f'{self.__class__.__name__}<{self.name}{"!" if self.real_obj is not None else ""}>'
|
94
|
+
|
95
|
+
def find_attr(self, attr: str) -> _ProxyImporterModuleAttr | None:
|
96
|
+
is_child = attr in self.children
|
97
|
+
is_proxy_attr = attr in self.proxy_obj.__dict__
|
98
|
+
is_pending_child = attr in self.pending_children
|
99
|
+
is_pending_attr = attr in self.pending_attrs
|
100
|
+
|
101
|
+
if is_child:
|
102
|
+
if (
|
103
|
+
not is_proxy_attr or
|
104
|
+
is_pending_child or
|
105
|
+
is_pending_attr
|
106
|
+
):
|
107
|
+
raise RuntimeError
|
108
|
+
return 'child'
|
109
|
+
|
110
|
+
elif is_proxy_attr:
|
111
|
+
if (
|
112
|
+
is_pending_child or
|
113
|
+
is_pending_attr
|
114
|
+
):
|
115
|
+
raise RuntimeError
|
116
|
+
return 'proxy_attr'
|
117
|
+
|
118
|
+
elif is_pending_child:
|
119
|
+
if (
|
120
|
+
is_child or
|
121
|
+
is_proxy_attr or
|
122
|
+
is_pending_attr
|
123
|
+
):
|
124
|
+
raise RuntimeError
|
125
|
+
return 'pending_child'
|
126
|
+
|
127
|
+
elif is_pending_attr:
|
128
|
+
if (
|
129
|
+
is_child or
|
130
|
+
is_proxy_attr or
|
131
|
+
is_pending_child
|
132
|
+
):
|
133
|
+
raise RuntimeError
|
134
|
+
return 'pending_attr'
|
28
135
|
|
29
|
-
|
30
|
-
|
31
|
-
if omod is None:
|
32
|
-
omod = importlib.import_module(spec, package=package)
|
33
|
-
if extras:
|
34
|
-
for x in extras:
|
35
|
-
importlib.import_module(f'{spec}.{x}', package=package)
|
36
|
-
return getattr(omod, att)
|
136
|
+
else:
|
137
|
+
return None
|
37
138
|
|
38
|
-
|
39
|
-
lmod.__getattr__ = __getattr__ # type: ignore[method-assign]
|
40
|
-
return lmod
|
139
|
+
#
|
41
140
|
|
141
|
+
def _get_or_make_module_locked(self, name: str) -> _Module:
|
142
|
+
try:
|
143
|
+
return self._modules_by_name[name]
|
144
|
+
except KeyError:
|
145
|
+
pass
|
42
146
|
|
43
|
-
|
147
|
+
parent: _ProxyImporter._Module | None = None
|
148
|
+
if '.' in name:
|
149
|
+
rest, _, attr = name.rpartition('.')
|
150
|
+
parent = self._get_or_make_module_locked(rest)
|
44
151
|
|
152
|
+
fa = parent.find_attr(attr)
|
153
|
+
if not (fa == 'pending_child' or fa is None):
|
154
|
+
raise RuntimeError
|
45
155
|
|
46
|
-
|
47
|
-
|
48
|
-
*,
|
49
|
-
disable: bool = False,
|
156
|
+
if (ro := parent.real_obj) is not None and attr not in ro.__dict__:
|
157
|
+
raise NotImplementedError
|
50
158
|
|
51
|
-
|
52
|
-
|
159
|
+
module = self._modules_by_name[name] = _ProxyImporter._Module(
|
160
|
+
name,
|
161
|
+
self._handle_module_getattr,
|
162
|
+
)
|
53
163
|
|
54
|
-
|
55
|
-
|
56
|
-
inst = ImportCapture(
|
57
|
-
mod_globals,
|
58
|
-
_hook=_new_import_capture_hook(
|
59
|
-
mod_globals,
|
60
|
-
stack_offset=_stack_offset + 1,
|
61
|
-
),
|
62
|
-
disable=disable,
|
63
|
-
)
|
164
|
+
self._modules_by_name[name] = module
|
165
|
+
self._modules_by_proxy_obj[module.proxy_obj] = module
|
64
166
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
):
|
71
|
-
yield inst
|
167
|
+
if parent is not None:
|
168
|
+
parent.pending_children.discard(module.base_name)
|
169
|
+
parent.children[module.base_name] = module
|
170
|
+
setattr(parent.proxy_obj, module.base_name, module.proxy_obj)
|
171
|
+
parent.root.descendants.add(module)
|
72
172
|
|
73
|
-
|
74
|
-
for pi in inst.captured.imports:
|
75
|
-
for sa, ma in pi.attrs:
|
76
|
-
mod_globals[ma] = proxy_import(pi.spec + (('.' + sa) if sa is not None else ''), pkg)
|
173
|
+
return module
|
77
174
|
|
78
|
-
|
175
|
+
def _extend_module_locked(
|
176
|
+
self,
|
177
|
+
module: _Module,
|
178
|
+
*,
|
179
|
+
children: ta.Iterable[str] | None = None,
|
180
|
+
attrs: ta.Iterable[str] | None = None,
|
181
|
+
) -> None:
|
182
|
+
for l in (children, attrs):
|
183
|
+
for n in l or ():
|
184
|
+
if n in module.proxy_obj.__dict__:
|
185
|
+
raise NotImplementedError
|
79
186
|
|
187
|
+
if (ro := module.real_obj) is not None and n in ro.__dict__:
|
188
|
+
raise NotImplementedError
|
80
189
|
|
81
|
-
|
190
|
+
for n in children or ():
|
191
|
+
fa = module.find_attr(n)
|
192
|
+
if not (fa == 'pending_child' or fa is None):
|
193
|
+
raise RuntimeError
|
82
194
|
|
195
|
+
for n in attrs or ():
|
196
|
+
fa = module.find_attr(n)
|
197
|
+
if not (fa == 'pending_attr' or fa is None):
|
198
|
+
raise RuntimeError
|
83
199
|
|
84
|
-
|
85
|
-
class NamePackage(ta.NamedTuple):
|
86
|
-
name: str
|
87
|
-
package: str
|
200
|
+
#
|
88
201
|
|
89
|
-
|
90
|
-
|
91
|
-
|
202
|
+
if children:
|
203
|
+
module.pending_children.update(n for n in children if n not in module.children)
|
204
|
+
if attrs:
|
205
|
+
module.pending_attrs.update(attrs)
|
92
206
|
|
93
|
-
def
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
207
|
+
def _retrieve_from_module_locked(self, module: _Module, attr: str) -> ta.Any:
|
208
|
+
fa = module.find_attr(attr)
|
209
|
+
|
210
|
+
if fa == 'child' or fa == 'proxy_attr':
|
211
|
+
return module.proxy_obj.__dict__[attr]
|
212
|
+
|
213
|
+
val: ta.Any
|
214
|
+
|
215
|
+
if fa == 'pending_child':
|
216
|
+
if module.name == self._owner_name:
|
217
|
+
val = importlib.import_module(f'{module.name}.{attr}')
|
218
|
+
|
219
|
+
else:
|
220
|
+
mod = __import__(
|
221
|
+
module.name,
|
222
|
+
self._owner_globals or {},
|
223
|
+
{},
|
224
|
+
[attr],
|
225
|
+
0,
|
226
|
+
)
|
227
|
+
|
228
|
+
val = getattr(mod, attr)
|
229
|
+
|
230
|
+
module.pending_children.remove(attr)
|
99
231
|
|
100
|
-
|
101
|
-
|
232
|
+
elif fa == 'pending_attr' or fa is None:
|
233
|
+
if module.name == self._owner_name:
|
234
|
+
raise NotImplementedError
|
102
235
|
|
103
|
-
|
104
|
-
|
236
|
+
if (ro := module.real_obj) is None:
|
237
|
+
ro = module.real_obj = importlib.import_module(module.name)
|
105
238
|
|
106
|
-
|
107
|
-
|
108
|
-
|
239
|
+
val = getattr(ro, attr)
|
240
|
+
|
241
|
+
if fa == 'pending_attr':
|
242
|
+
module.pending_attrs.remove(attr)
|
243
|
+
|
244
|
+
else:
|
245
|
+
raise TypeError(fa)
|
246
|
+
|
247
|
+
setattr(module.proxy_obj, attr, val)
|
248
|
+
return val
|
249
|
+
|
250
|
+
#
|
251
|
+
|
252
|
+
def _handle_module_getattr(self, module: _Module, attr: str) -> ta.Any:
|
253
|
+
with self._lock:
|
254
|
+
return self._retrieve_from_module_locked(module, attr)
|
109
255
|
|
110
256
|
def add(
|
111
257
|
self,
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
258
|
+
module: str,
|
259
|
+
*,
|
260
|
+
children: ta.Iterable[str] | None = None,
|
261
|
+
attrs: ta.Iterable[str] | None = None,
|
262
|
+
) -> types.ModuleType:
|
263
|
+
if isinstance(children, str):
|
264
|
+
raise TypeError(children)
|
265
|
+
|
266
|
+
# Leaf modules get collapsed into parents' pending_children
|
267
|
+
if not children and not attrs and '.' in module:
|
268
|
+
module, _, child = module.rpartition('.')
|
269
|
+
children = [child]
|
270
|
+
|
271
|
+
with self._lock:
|
272
|
+
m = self._get_or_make_module_locked(module)
|
273
|
+
|
274
|
+
if children or attrs:
|
275
|
+
self._extend_module_locked(
|
276
|
+
m,
|
277
|
+
children=children,
|
278
|
+
attrs=attrs,
|
279
|
+
)
|
280
|
+
|
281
|
+
return m.proxy_obj
|
282
|
+
|
283
|
+
def get_module(self, name: str) -> types.ModuleType:
|
284
|
+
try:
|
285
|
+
return self._modules_by_name[name].proxy_obj
|
286
|
+
except KeyError:
|
287
|
+
pass
|
119
288
|
|
120
|
-
|
121
|
-
|
122
|
-
self._lazy_globals.set_fn(as_attr, functools.partial(self.get, as_attr))
|
289
|
+
with self._lock:
|
290
|
+
return self._get_or_make_module_locked(name).proxy_obj
|
123
291
|
|
124
|
-
def
|
125
|
-
|
292
|
+
def lookup(self, spec: str) -> ta.Any:
|
293
|
+
if '.' not in spec:
|
294
|
+
return self._modules_by_name[spec].proxy_obj
|
126
295
|
|
127
|
-
def get(self, attr: str) -> ta.Any:
|
128
296
|
try:
|
129
|
-
|
297
|
+
module = self._modules_by_name[spec]
|
130
298
|
except KeyError:
|
131
|
-
|
299
|
+
pass
|
300
|
+
else:
|
301
|
+
return module.proxy_obj
|
132
302
|
|
133
|
-
|
303
|
+
rest, _, attr = spec.rpartition('.')
|
304
|
+
module = self._modules_by_name[rest]
|
305
|
+
return getattr(module.proxy_obj, attr)
|
134
306
|
|
135
|
-
if imp.attr is None:
|
136
|
-
val = self._import_module(imp.spec)
|
137
307
|
|
138
|
-
|
139
|
-
try:
|
140
|
-
mod = self._mods_by_spec[imp.spec]
|
141
|
-
except KeyError:
|
142
|
-
mod = self._import_module(imp.spec)
|
143
|
-
self._mods_by_spec[imp.spec] = mod
|
308
|
+
#
|
144
309
|
|
145
|
-
val = getattr(mod, imp.attr)
|
146
310
|
|
147
|
-
|
311
|
+
_MODULE_PROXY_IMPORTER_GLOBAL_NAME = '__proxy_importer__'
|
312
|
+
|
313
|
+
|
314
|
+
def _get_module_proxy_importer(mod_globals: ta.MutableMapping[str, ta.Any]) -> _ProxyImporter:
|
315
|
+
"""Assumed to only be called in a module body - no locking is done."""
|
316
|
+
|
317
|
+
pi: _ProxyImporter
|
318
|
+
try:
|
319
|
+
pi = mod_globals[_MODULE_PROXY_IMPORTER_GLOBAL_NAME]
|
320
|
+
|
321
|
+
except KeyError:
|
322
|
+
pi = _ProxyImporter(
|
323
|
+
owner_globals=mod_globals,
|
324
|
+
)
|
325
|
+
mod_globals[_MODULE_PROXY_IMPORTER_GLOBAL_NAME] = pi
|
326
|
+
|
327
|
+
else:
|
328
|
+
if pi.__class__ is not _ProxyImporter:
|
329
|
+
raise TypeError(pi)
|
330
|
+
|
331
|
+
if pi._owner_globals is not mod_globals: # noqa
|
332
|
+
raise RuntimeError
|
333
|
+
|
334
|
+
return pi
|
335
|
+
|
336
|
+
|
337
|
+
##
|
338
|
+
|
339
|
+
|
340
|
+
def proxy_import(
|
341
|
+
spec: str,
|
342
|
+
package: str | None = None,
|
343
|
+
extras: ta.Iterable[str] | None = None,
|
344
|
+
) -> types.ModuleType:
|
345
|
+
"""'Legacy' proxy import mechanism."""
|
346
|
+
|
347
|
+
if isinstance(extras, str):
|
348
|
+
raise TypeError(extras)
|
349
|
+
|
350
|
+
omod = None
|
351
|
+
|
352
|
+
def __getattr__(att): # noqa
|
353
|
+
nonlocal omod
|
354
|
+
if omod is None:
|
355
|
+
omod = importlib.import_module(spec, package=package)
|
356
|
+
if extras:
|
357
|
+
for x in extras:
|
358
|
+
importlib.import_module(f'{spec}.{x}', package=package)
|
359
|
+
return getattr(omod, att)
|
360
|
+
|
361
|
+
lmod = types.ModuleType(spec)
|
362
|
+
lmod.__getattr__ = __getattr__ # type: ignore[method-assign]
|
363
|
+
return lmod
|
364
|
+
|
365
|
+
|
366
|
+
#
|
148
367
|
|
149
368
|
|
150
369
|
def proxy_init(
|
@@ -152,6 +371,13 @@ def proxy_init(
|
|
152
371
|
spec: str,
|
153
372
|
attrs: ta.Iterable[str | tuple[str | None, str | None] | None] | None = None,
|
154
373
|
) -> None:
|
374
|
+
name = importlib.util.resolve_name(
|
375
|
+
spec,
|
376
|
+
package=init_globals['__package__'] if spec.startswith('.') else None,
|
377
|
+
)
|
378
|
+
|
379
|
+
#
|
380
|
+
|
155
381
|
if isinstance(attrs, str):
|
156
382
|
raise TypeError(attrs)
|
157
383
|
|
@@ -181,76 +407,143 @@ def proxy_init(
|
|
181
407
|
|
182
408
|
#
|
183
409
|
|
184
|
-
|
185
|
-
|
186
|
-
|
410
|
+
pi = _get_module_proxy_importer(init_globals)
|
411
|
+
lg = LazyGlobals.install(init_globals)
|
412
|
+
|
413
|
+
pi.add(
|
414
|
+
name,
|
415
|
+
children=[r for l, r in al if r is not None],
|
187
416
|
)
|
188
417
|
|
189
|
-
|
190
|
-
|
191
|
-
pi = init_globals['__proxy_init__']
|
418
|
+
for imp_attr, as_attr in al:
|
419
|
+
lg.set_fn(as_attr, functools.partial(pi.lookup, name if imp_attr is None else f'{name}.{imp_attr}'))
|
192
420
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
421
|
+
|
422
|
+
##
|
423
|
+
|
424
|
+
|
425
|
+
class _AutoProxy:
|
426
|
+
def __init__(
|
427
|
+
self,
|
428
|
+
mod_globals: ta.MutableMapping[str, ta.Any],
|
429
|
+
*,
|
430
|
+
disable: bool = False,
|
431
|
+
eager: bool = False,
|
432
|
+
|
433
|
+
unreferenced_callback: ta.Callable[[ta.Sequence[str]], None] | None = None,
|
434
|
+
raise_unreferenced: bool = False,
|
435
|
+
|
436
|
+
update_exports: bool = False,
|
437
|
+
|
438
|
+
_stack_offset: int = 0,
|
439
|
+
_capture_impl: str | None = None,
|
440
|
+
) -> None:
|
441
|
+
super().__init__()
|
442
|
+
|
443
|
+
self._mod_globals = mod_globals
|
444
|
+
|
445
|
+
self._disabled = disable
|
446
|
+
self._eager = eager
|
447
|
+
|
448
|
+
self._unreferenced_callback = unreferenced_callback
|
449
|
+
self._raise_unreferenced = raise_unreferenced
|
450
|
+
|
451
|
+
self._update_exports = update_exports
|
452
|
+
|
453
|
+
self._ic = ImportCapture(
|
454
|
+
mod_globals,
|
455
|
+
_hook=_new_import_capture_hook(
|
456
|
+
mod_globals,
|
457
|
+
stack_offset=_stack_offset + 1,
|
458
|
+
capture_impl=_capture_impl,
|
459
|
+
),
|
460
|
+
disable=disable,
|
197
461
|
)
|
198
|
-
|
462
|
+
self._icc: ta.Any = None
|
199
463
|
|
200
|
-
|
201
|
-
if
|
202
|
-
raise
|
464
|
+
def __enter__(self) -> ImportCapture:
|
465
|
+
if self._icc is not None:
|
466
|
+
raise RuntimeError
|
203
467
|
|
204
|
-
|
468
|
+
self._icc = self._ic.capture(
|
469
|
+
unreferenced_callback=self._unreferenced_callback,
|
470
|
+
raise_unreferenced=self._raise_unreferenced,
|
471
|
+
)
|
205
472
|
|
473
|
+
return self._icc.__enter__() # noqa
|
206
474
|
|
207
|
-
|
475
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
476
|
+
if self._icc is None:
|
477
|
+
raise RuntimeError
|
208
478
|
|
479
|
+
self._icc.__exit__(exc_type, exc_val, exc_tb)
|
209
480
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
),
|
229
|
-
disable=disable,
|
230
|
-
)
|
481
|
+
if not self._disabled and exc_type is None:
|
482
|
+
self._install()
|
483
|
+
|
484
|
+
# @abc.abstractmethod
|
485
|
+
def _install(self) -> None:
|
486
|
+
raise NotImplementedError
|
487
|
+
|
488
|
+
|
489
|
+
@ta.final
|
490
|
+
class _AutoProxyImport(_AutoProxy):
|
491
|
+
def _install(self) -> None:
|
492
|
+
cap = self._ic.captured
|
493
|
+
|
494
|
+
for cm in cap.modules.values():
|
495
|
+
if cm.attrs:
|
496
|
+
raise RuntimeError
|
497
|
+
|
498
|
+
pi = _get_module_proxy_importer(self._mod_globals)
|
231
499
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
raise_unreferenced=raise_unreferenced,
|
237
|
-
):
|
238
|
-
yield inst
|
239
|
-
|
240
|
-
for pi in inst.captured.imports:
|
241
|
-
proxy_init(
|
242
|
-
init_globals,
|
243
|
-
pi.spec,
|
244
|
-
pi.attrs,
|
500
|
+
for cm in cap.modules.values():
|
501
|
+
pi.add(
|
502
|
+
cm.name,
|
503
|
+
children=cm.children,
|
245
504
|
)
|
246
505
|
|
247
|
-
|
248
|
-
|
506
|
+
for ci in cap.imports.values():
|
507
|
+
pm = pi.get_module(ci.module.name)
|
508
|
+
for a in ci.as_ or ():
|
509
|
+
self._mod_globals[a] = pm
|
249
510
|
|
250
|
-
|
511
|
+
if self._eager:
|
512
|
+
for ci in cap.imports.values():
|
513
|
+
pi.lookup(ci.module.name)
|
514
|
+
|
515
|
+
if self._update_exports:
|
516
|
+
self._ic.update_exports()
|
517
|
+
|
518
|
+
|
519
|
+
@ta.final
|
520
|
+
class _AutoProxyInit(_AutoProxy):
|
521
|
+
def _install(self) -> None:
|
522
|
+
cap = self._ic.captured
|
523
|
+
|
524
|
+
pi = _get_module_proxy_importer(self._mod_globals)
|
525
|
+
lg = LazyGlobals.install(self._mod_globals)
|
526
|
+
|
527
|
+
for cm in cap.modules.values():
|
528
|
+
pi.add(
|
529
|
+
cm.name,
|
530
|
+
children=cm.children,
|
531
|
+
attrs=cm.attrs,
|
532
|
+
)
|
533
|
+
|
534
|
+
for ci in cap.imports.values():
|
535
|
+
for a in ci.as_ or ():
|
536
|
+
lg.set_fn(a, functools.partial(pi.lookup, ci.module.name))
|
537
|
+
for sa, da in ci.attrs or ():
|
538
|
+
lg.set_fn(da, functools.partial(pi.lookup, f'{ci.module.name}.{sa}'))
|
539
|
+
|
540
|
+
if self._eager:
|
541
|
+
for a in cap.attrs:
|
251
542
|
lg.get(a)
|
252
543
|
|
253
|
-
if
|
254
|
-
|
544
|
+
if self._update_exports:
|
545
|
+
self._ic.update_exports()
|
546
|
+
|
255
547
|
|
256
|
-
|
548
|
+
auto_proxy_import = _AutoProxyImport
|
549
|
+
auto_proxy_init = _AutoProxyInit
|