omlish 0.0.0.dev443__py3-none-any.whl → 0.0.0.dev445__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.
Potentially problematic release.
This version of omlish might be problematic. Click here for more details.
- omlish/__about__.py +5 -2
- omlish/formats/json/stream/lexing.py +47 -33
- omlish/inject/binder.py +3 -1
- omlish/inject/impl/elements.py +3 -1
- omlish/inject/impl/scopes.py +3 -1
- omlish/inject/injector.py +3 -1
- omlish/inject/inspect.py +3 -1
- omlish/inject/managed.py +5 -1
- omlish/inject/maysync.py +3 -1
- omlish/inject/scopes.py +6 -2
- omlish/inject/sync.py +3 -1
- omlish/lang/__init__.py +2 -6
- omlish/lang/imports/_capture.cc +101 -0
- omlish/lang/imports/capture.py +288 -73
- omlish/lang/imports/proxy.py +206 -12
- omlish/lite/asyncs.py +1 -1
- omlish/sync.py +27 -0
- {omlish-0.0.0.dev443.dist-info → omlish-0.0.0.dev445.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev443.dist-info → omlish-0.0.0.dev445.dist-info}/RECORD +23 -23
- omlish/lang/imports/proxyinit.py +0 -176
- {omlish-0.0.0.dev443.dist-info → omlish-0.0.0.dev445.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev443.dist-info → omlish-0.0.0.dev445.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev443.dist-info → omlish-0.0.0.dev445.dist-info}/licenses/LICENSE +0 -0
- {omlish-0.0.0.dev443.dist-info → omlish-0.0.0.dev445.dist-info}/top_level.txt +0 -0
omlish/lang/imports/capture.py
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Insufficient alt impls:
|
|
3
|
+
- `sys.meta_path`:
|
|
4
|
+
- need access to the `fromlist` and `level` arguments passed to `__import__`
|
|
5
|
+
- need to return fake modules to the import operation which are not added to `sys.modules`
|
|
6
|
+
- `sys.addaudithook`: cannot prevent import or inject result
|
|
7
|
+
- `sys.settrace` / bytecode tracing: same
|
|
8
|
+
- jit bytecode rewriting: slower than just importing everything
|
|
9
|
+
|
|
10
|
+
Possible alt impls:
|
|
11
|
+
- aot static analysis, codegen, compare, if valid skip ctxmgr body and inject proxies, otherwise warn and run
|
|
12
|
+
"""
|
|
1
13
|
import builtins
|
|
2
14
|
import contextlib
|
|
3
15
|
import functools
|
|
16
|
+
import sys
|
|
17
|
+
import threading
|
|
4
18
|
import types
|
|
5
19
|
import typing as ta
|
|
6
20
|
|
|
@@ -58,7 +72,10 @@ class ImportCaptureErrors:
|
|
|
58
72
|
pass
|
|
59
73
|
|
|
60
74
|
|
|
61
|
-
|
|
75
|
+
##
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class _ImportCaptureHook:
|
|
62
79
|
class ModuleSpec(ta.NamedTuple):
|
|
63
80
|
name: str
|
|
64
81
|
level: int
|
|
@@ -69,20 +86,26 @@ class _ImportCaptureImpl:
|
|
|
69
86
|
def __repr__(self) -> str:
|
|
70
87
|
return repr(str(self))
|
|
71
88
|
|
|
72
|
-
def __init__(
|
|
89
|
+
def __init__(
|
|
90
|
+
self,
|
|
91
|
+
*,
|
|
92
|
+
forbid_uncaptured_imports: bool = False,
|
|
93
|
+
) -> None:
|
|
73
94
|
super().__init__()
|
|
74
95
|
|
|
75
|
-
self.
|
|
76
|
-
|
|
96
|
+
self._forbid_uncaptured_imports = forbid_uncaptured_imports
|
|
97
|
+
|
|
98
|
+
self._modules_by_spec: dict[_ImportCaptureHook.ModuleSpec, _ImportCaptureHook._Module] = {}
|
|
99
|
+
self._modules_by_module_obj: dict[types.ModuleType, _ImportCaptureHook._Module] = {}
|
|
77
100
|
|
|
78
|
-
self._attrs: dict[
|
|
101
|
+
self._attrs: dict[_ImportCaptureHook._ModuleAttr, tuple[_ImportCaptureHook._Module, str]] = {}
|
|
79
102
|
|
|
80
103
|
#
|
|
81
104
|
|
|
82
105
|
class _ModuleAttr:
|
|
83
106
|
def __init__(
|
|
84
107
|
self,
|
|
85
|
-
module: '
|
|
108
|
+
module: '_ImportCaptureHook._Module',
|
|
86
109
|
name: str,
|
|
87
110
|
) -> None:
|
|
88
111
|
super().__init__()
|
|
@@ -96,9 +119,9 @@ class _ImportCaptureImpl:
|
|
|
96
119
|
class _Module:
|
|
97
120
|
def __init__(
|
|
98
121
|
self,
|
|
99
|
-
spec: '
|
|
122
|
+
spec: '_ImportCaptureHook.ModuleSpec',
|
|
100
123
|
*,
|
|
101
|
-
getattr_handler: ta.Callable[['
|
|
124
|
+
getattr_handler: ta.Callable[['_ImportCaptureHook._Module', str], ta.Any] | None = None,
|
|
102
125
|
) -> None:
|
|
103
126
|
super().__init__()
|
|
104
127
|
|
|
@@ -109,7 +132,7 @@ class _ImportCaptureImpl:
|
|
|
109
132
|
self.module_obj.__getattr__ = functools.partial(getattr_handler, self) # type: ignore[method-assign] # noqa
|
|
110
133
|
self.initial_module_dict = dict(self.module_obj.__dict__)
|
|
111
134
|
|
|
112
|
-
self.contents: dict[str,
|
|
135
|
+
self.contents: dict[str, _ImportCaptureHook._ModuleAttr | types.ModuleType] = {}
|
|
113
136
|
self.imported_whole = False
|
|
114
137
|
|
|
115
138
|
def __repr__(self) -> str:
|
|
@@ -133,17 +156,17 @@ class _ImportCaptureImpl:
|
|
|
133
156
|
if attr in module.contents:
|
|
134
157
|
raise ImportCaptureErrors.AttrError(str(module.spec), attr)
|
|
135
158
|
|
|
136
|
-
v:
|
|
159
|
+
v: _ImportCaptureHook._ModuleAttr | types.ModuleType
|
|
137
160
|
if not module.spec.name:
|
|
138
161
|
if not module.spec.level:
|
|
139
162
|
raise ImportCaptureError
|
|
140
|
-
cs =
|
|
163
|
+
cs = _ImportCaptureHook.ModuleSpec(attr, module.spec.level)
|
|
141
164
|
cm = self._get_or_make_module(cs)
|
|
142
165
|
cm.imported_whole = True
|
|
143
166
|
v = cm.module_obj
|
|
144
167
|
|
|
145
168
|
else:
|
|
146
|
-
ma =
|
|
169
|
+
ma = _ImportCaptureHook._ModuleAttr(module, attr)
|
|
147
170
|
self._attrs[ma] = (module, attr)
|
|
148
171
|
v = ma
|
|
149
172
|
|
|
@@ -173,7 +196,7 @@ class _ImportCaptureImpl:
|
|
|
173
196
|
bad = False
|
|
174
197
|
if x is not module.contents.get(attr):
|
|
175
198
|
bad = True
|
|
176
|
-
if isinstance(x,
|
|
199
|
+
if isinstance(x, _ImportCaptureHook._ModuleAttr):
|
|
177
200
|
if self._attrs[x] != (module, attr):
|
|
178
201
|
bad = True
|
|
179
202
|
elif isinstance(x, types.ModuleType):
|
|
@@ -202,7 +225,7 @@ class _ImportCaptureImpl:
|
|
|
202
225
|
):
|
|
203
226
|
return None
|
|
204
227
|
|
|
205
|
-
spec =
|
|
228
|
+
spec = _ImportCaptureHook.ModuleSpec(name, level)
|
|
206
229
|
module = self._get_or_make_module(spec)
|
|
207
230
|
|
|
208
231
|
self._handle_import(
|
|
@@ -212,64 +235,33 @@ class _ImportCaptureImpl:
|
|
|
212
235
|
|
|
213
236
|
return module.module_obj
|
|
214
237
|
|
|
238
|
+
@ta.final
|
|
215
239
|
@contextlib.contextmanager
|
|
216
240
|
def hook_context(
|
|
217
241
|
self,
|
|
218
242
|
mod_globals: ta.MutableMapping[str, ta.Any], # noqa
|
|
219
|
-
*,
|
|
220
|
-
forbid_uncaptured_imports: bool = False,
|
|
221
243
|
) -> ta.Iterator[None]:
|
|
222
244
|
if self._MOD_SELF_ATTR in mod_globals:
|
|
223
245
|
raise ImportCaptureErrors.HookError
|
|
224
246
|
|
|
225
|
-
old_import = builtins.__import__
|
|
226
|
-
|
|
227
|
-
def new_import(
|
|
228
|
-
name,
|
|
229
|
-
globals=None, # noqa
|
|
230
|
-
locals=None, # noqa
|
|
231
|
-
fromlist=None,
|
|
232
|
-
level=0,
|
|
233
|
-
):
|
|
234
|
-
if (im := self._intercept_import(
|
|
235
|
-
name,
|
|
236
|
-
globals=globals,
|
|
237
|
-
from_list=fromlist,
|
|
238
|
-
level=level,
|
|
239
|
-
)) is not None:
|
|
240
|
-
return im
|
|
241
|
-
|
|
242
|
-
if forbid_uncaptured_imports:
|
|
243
|
-
raise ImportCaptureErrors.UncapturedImportForbiddenError(
|
|
244
|
-
str(_ImportCaptureImpl.ModuleSpec(name, level)),
|
|
245
|
-
fromlist,
|
|
246
|
-
)
|
|
247
|
-
|
|
248
|
-
return old_import(
|
|
249
|
-
name,
|
|
250
|
-
globals=globals,
|
|
251
|
-
locals=locals,
|
|
252
|
-
fromlist=fromlist,
|
|
253
|
-
level=level,
|
|
254
|
-
)
|
|
255
|
-
|
|
256
|
-
#
|
|
257
|
-
|
|
258
247
|
mod_globals[self._MOD_SELF_ATTR] = self
|
|
259
|
-
builtins.__import__ = new_import
|
|
260
248
|
|
|
261
249
|
try:
|
|
262
|
-
|
|
250
|
+
with self._hook_context(mod_globals):
|
|
251
|
+
yield
|
|
263
252
|
|
|
264
253
|
finally:
|
|
265
|
-
if not
|
|
266
|
-
mod_globals[self._MOD_SELF_ATTR] is self and
|
|
267
|
-
builtins.__import__ is new_import
|
|
268
|
-
):
|
|
254
|
+
if mod_globals[self._MOD_SELF_ATTR] is not self:
|
|
269
255
|
raise ImportCaptureErrors.HookError
|
|
270
256
|
|
|
271
257
|
del mod_globals[self._MOD_SELF_ATTR]
|
|
272
|
-
|
|
258
|
+
|
|
259
|
+
# @abc.abstractmethod
|
|
260
|
+
def _hook_context(
|
|
261
|
+
self,
|
|
262
|
+
mod_globals: ta.MutableMapping[str, ta.Any], # noqa
|
|
263
|
+
) -> ta.ContextManager[None]:
|
|
264
|
+
raise NotImplementedError
|
|
273
265
|
|
|
274
266
|
#
|
|
275
267
|
|
|
@@ -298,16 +290,16 @@ class _ImportCaptureImpl:
|
|
|
298
290
|
*,
|
|
299
291
|
collect_unreferenced: bool = False,
|
|
300
292
|
) -> 'ImportCapture.Captured':
|
|
301
|
-
dct: dict[
|
|
293
|
+
dct: dict[_ImportCaptureHook._Module, list[tuple[str | None, str]]] = {}
|
|
302
294
|
|
|
303
|
-
rem_whole_mods: set[
|
|
304
|
-
rem_mod_attrs: set[
|
|
295
|
+
rem_whole_mods: set[_ImportCaptureHook._Module] = set()
|
|
296
|
+
rem_mod_attrs: set[_ImportCaptureHook._ModuleAttr] = set()
|
|
305
297
|
if collect_unreferenced:
|
|
306
298
|
rem_whole_mods.update([m for m in self._modules_by_spec.values() if m.imported_whole])
|
|
307
299
|
rem_mod_attrs.update(self._attrs)
|
|
308
300
|
|
|
309
301
|
for attr, obj in mod_globals.items():
|
|
310
|
-
if isinstance(obj,
|
|
302
|
+
if isinstance(obj, _ImportCaptureHook._ModuleAttr):
|
|
311
303
|
try:
|
|
312
304
|
m, a = self._attrs[obj]
|
|
313
305
|
except KeyError:
|
|
@@ -315,7 +307,7 @@ class _ImportCaptureImpl:
|
|
|
315
307
|
dct.setdefault(m, []).append((a, attr))
|
|
316
308
|
rem_mod_attrs.discard(obj)
|
|
317
309
|
|
|
318
|
-
elif isinstance(obj,
|
|
310
|
+
elif isinstance(obj, _ImportCaptureHook._Module):
|
|
319
311
|
raise ImportCaptureErrors.AttrError(None, attr) from None
|
|
320
312
|
|
|
321
313
|
elif isinstance(obj, types.ModuleType):
|
|
@@ -362,14 +354,236 @@ class _ImportCaptureImpl:
|
|
|
362
354
|
)
|
|
363
355
|
|
|
364
356
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
357
|
+
#
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
class _AbstractBuiltinsImportCaptureHook(_ImportCaptureHook):
|
|
361
|
+
def _new_import(
|
|
362
|
+
self,
|
|
363
|
+
old_import,
|
|
364
|
+
name,
|
|
365
|
+
globals=None, # noqa
|
|
366
|
+
locals=None, # noqa
|
|
367
|
+
fromlist=None,
|
|
368
|
+
level=0,
|
|
369
|
+
):
|
|
370
|
+
if (im := self._intercept_import(
|
|
371
|
+
name,
|
|
372
|
+
globals=globals,
|
|
373
|
+
from_list=fromlist,
|
|
374
|
+
level=level,
|
|
375
|
+
)) is not None:
|
|
376
|
+
return im
|
|
377
|
+
|
|
378
|
+
if self._forbid_uncaptured_imports:
|
|
379
|
+
raise ImportCaptureErrors.UncapturedImportForbiddenError(
|
|
380
|
+
str(_ImportCaptureHook.ModuleSpec(name, level)),
|
|
381
|
+
fromlist,
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
return old_import(
|
|
385
|
+
name,
|
|
386
|
+
globals=globals,
|
|
387
|
+
locals=locals,
|
|
388
|
+
fromlist=fromlist,
|
|
389
|
+
level=level,
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
class _UnsafeGlobalBuiltinsImportCaptureHook(_AbstractBuiltinsImportCaptureHook):
|
|
394
|
+
@contextlib.contextmanager
|
|
395
|
+
def _hook_context(
|
|
396
|
+
self,
|
|
397
|
+
mod_globals: ta.MutableMapping[str, ta.Any], # noqa
|
|
398
|
+
) -> ta.Iterator[None]:
|
|
399
|
+
old_import = builtins.__import__
|
|
400
|
+
new_import = functools.partial(self._new_import, old_import)
|
|
401
|
+
|
|
402
|
+
builtins.__import__ = new_import
|
|
403
|
+
|
|
404
|
+
try:
|
|
405
|
+
yield
|
|
406
|
+
|
|
407
|
+
finally:
|
|
408
|
+
if builtins.__import__ is not new_import:
|
|
409
|
+
raise ImportCaptureErrors.HookError
|
|
410
|
+
|
|
411
|
+
builtins.__import__ = old_import
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
class _SomewhatThreadSafeGlobalBuiltinsImportCaptureHook(_AbstractBuiltinsImportCaptureHook):
|
|
415
|
+
class _AlreadyPatchedError(Exception):
|
|
416
|
+
pass
|
|
417
|
+
|
|
418
|
+
@ta.final
|
|
419
|
+
class _Patch:
|
|
420
|
+
__lock: ta.ClassVar[threading.Lock] = threading.Lock()
|
|
421
|
+
|
|
422
|
+
def __init__(self, old_import):
|
|
423
|
+
self.__old_import = old_import
|
|
424
|
+
self.__hooks = {}
|
|
425
|
+
self.__uninstalled = False
|
|
426
|
+
|
|
427
|
+
@classmethod
|
|
428
|
+
def _add_hook(cls, mod_globals, new_import) -> '_SomewhatThreadSafeGlobalBuiltinsImportCaptureHook._Patch':
|
|
429
|
+
gi = id(mod_globals)
|
|
430
|
+
for _ in range(1_000):
|
|
431
|
+
try:
|
|
432
|
+
with cls.__lock:
|
|
433
|
+
x: ta.Any = builtins.__import__
|
|
434
|
+
p: _SomewhatThreadSafeGlobalBuiltinsImportCaptureHook._Patch
|
|
435
|
+
if x.__class__ is cls:
|
|
436
|
+
p = x
|
|
437
|
+
if p.__uninstalled: # noqa
|
|
438
|
+
raise _SomewhatThreadSafeGlobalBuiltinsImportCaptureHook._AlreadyPatchedError # noqa
|
|
439
|
+
else:
|
|
440
|
+
p = cls(x)
|
|
441
|
+
builtins.__import__ = p
|
|
442
|
+
p.__hooks[gi] = (mod_globals, new_import)
|
|
443
|
+
return p
|
|
444
|
+
except _SomewhatThreadSafeGlobalBuiltinsImportCaptureHook._AlreadyPatchedError:
|
|
445
|
+
pass
|
|
446
|
+
raise ImportCaptureErrors.HookError('Failed to install builtins hook')
|
|
447
|
+
|
|
448
|
+
def _remove_hook(self, mod_globals, *, no_raise=False):
|
|
449
|
+
gi = id(mod_globals)
|
|
450
|
+
with self.__lock:
|
|
451
|
+
tg, _ = self.__hooks[gi]
|
|
452
|
+
del self.__hooks[gi]
|
|
453
|
+
if not self.__uninstalled and not self.__hooks:
|
|
454
|
+
self.__uninstalled = True
|
|
455
|
+
if builtins.__import__ is not self:
|
|
456
|
+
if not no_raise:
|
|
457
|
+
# TODO: warn?
|
|
458
|
+
raise ImportCaptureErrors.HookError('Unexpected builtins hook')
|
|
459
|
+
else:
|
|
460
|
+
builtins.__import__ = self.__old_import
|
|
461
|
+
if tg is not mod_globals:
|
|
462
|
+
if not no_raise:
|
|
463
|
+
# TODO: warn?
|
|
464
|
+
raise ImportCaptureErrors.HookError('Mismatched globals')
|
|
465
|
+
|
|
466
|
+
def __call__(
|
|
467
|
+
self,
|
|
468
|
+
name,
|
|
469
|
+
globals=None, # noqa
|
|
470
|
+
locals=None, # noqa
|
|
471
|
+
fromlist=None,
|
|
472
|
+
level=0,
|
|
473
|
+
):
|
|
474
|
+
if globals is not None and (tup := self.__hooks.get(id(globals))) is not None:
|
|
475
|
+
tg, tf = tup
|
|
476
|
+
if tg is globals:
|
|
477
|
+
return tf(
|
|
478
|
+
self.__old_import,
|
|
479
|
+
name,
|
|
480
|
+
globals=globals,
|
|
481
|
+
locals=locals,
|
|
482
|
+
fromlist=fromlist,
|
|
483
|
+
level=level,
|
|
484
|
+
)
|
|
485
|
+
else:
|
|
486
|
+
self._remove_hook(tg, no_raise=True)
|
|
487
|
+
|
|
488
|
+
return self.__old_import(
|
|
489
|
+
name,
|
|
490
|
+
globals=globals,
|
|
491
|
+
locals=locals,
|
|
492
|
+
fromlist=fromlist,
|
|
493
|
+
level=level,
|
|
494
|
+
)
|
|
495
|
+
|
|
496
|
+
@contextlib.contextmanager
|
|
497
|
+
def _hook_context(
|
|
498
|
+
self,
|
|
499
|
+
mod_globals: ta.MutableMapping[str, ta.Any], # noqa
|
|
500
|
+
) -> ta.Iterator[None]:
|
|
501
|
+
patch = _SomewhatThreadSafeGlobalBuiltinsImportCaptureHook._Patch._add_hook(mod_globals, self._new_import) # noqa
|
|
502
|
+
|
|
503
|
+
try:
|
|
504
|
+
yield
|
|
505
|
+
|
|
506
|
+
finally:
|
|
507
|
+
patch._remove_hook(mod_globals) # noqa
|
|
372
508
|
|
|
509
|
+
|
|
510
|
+
#
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
_capture: ta.Any = None
|
|
514
|
+
try:
|
|
515
|
+
from . import _capture # type: ignore
|
|
516
|
+
except ImportError:
|
|
517
|
+
pass
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
class _FrameBuiltinsImportCaptureHook(_AbstractBuiltinsImportCaptureHook):
|
|
521
|
+
def __init__(
|
|
522
|
+
self,
|
|
523
|
+
*,
|
|
524
|
+
_frame: types.FrameType,
|
|
525
|
+
**kwargs: ta.Any,
|
|
526
|
+
) -> None:
|
|
527
|
+
super().__init__(**kwargs)
|
|
528
|
+
|
|
529
|
+
self._frame = _frame
|
|
530
|
+
|
|
531
|
+
@classmethod
|
|
532
|
+
def _set_frame_builtins(
|
|
533
|
+
cls,
|
|
534
|
+
frame: types.FrameType,
|
|
535
|
+
new_builtins: dict[str, ta.Any],
|
|
536
|
+
) -> bool:
|
|
537
|
+
return _capture._set_frame_builtins(frame, frame.f_builtins, new_builtins) # noqa
|
|
538
|
+
|
|
539
|
+
@contextlib.contextmanager
|
|
540
|
+
def _hook_context(
|
|
541
|
+
self,
|
|
542
|
+
mod_globals: ta.MutableMapping[str, ta.Any], # noqa
|
|
543
|
+
) -> ta.Iterator[None]:
|
|
544
|
+
old_builtins = self._frame.f_builtins
|
|
545
|
+
old_import = old_builtins['__import__']
|
|
546
|
+
new_import = functools.partial(self._new_import, old_import)
|
|
547
|
+
|
|
548
|
+
new_builtins = dict(old_builtins)
|
|
549
|
+
new_builtins['__import__'] = new_import
|
|
550
|
+
if not self._set_frame_builtins(self._frame, new_builtins):
|
|
551
|
+
raise ImportCaptureErrors.HookError
|
|
552
|
+
|
|
553
|
+
try:
|
|
554
|
+
yield
|
|
555
|
+
|
|
556
|
+
finally:
|
|
557
|
+
if self._frame.f_builtins is not new_builtins:
|
|
558
|
+
raise ImportCaptureErrors.HookError
|
|
559
|
+
|
|
560
|
+
if not self._set_frame_builtins(self._frame, old_builtins):
|
|
561
|
+
raise ImportCaptureErrors.HookError
|
|
562
|
+
|
|
563
|
+
|
|
564
|
+
#
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
def _new_import_capture_hook(
|
|
568
|
+
mod_globals: ta.MutableMapping[str, ta.Any], # noqa
|
|
569
|
+
*,
|
|
570
|
+
stack_offset: int = 0,
|
|
571
|
+
**kwargs: ta.Any,
|
|
572
|
+
) -> '_ImportCaptureHook':
|
|
573
|
+
frame: types.FrameType | None = sys._getframe(1 + stack_offset) # noqa
|
|
574
|
+
if frame is None or frame.f_globals is not mod_globals:
|
|
575
|
+
raise ImportCaptureError("Can't find importing frame")
|
|
576
|
+
|
|
577
|
+
if _capture is not None:
|
|
578
|
+
return _FrameBuiltinsImportCaptureHook(_frame=frame, **kwargs)
|
|
579
|
+
|
|
580
|
+
return _SomewhatThreadSafeGlobalBuiltinsImportCaptureHook(**kwargs)
|
|
581
|
+
|
|
582
|
+
|
|
583
|
+
##
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
class ImportCapture:
|
|
373
587
|
class Import(ta.NamedTuple):
|
|
374
588
|
spec: str
|
|
375
589
|
attrs: ta.Sequence[tuple[str | None, str]]
|
|
@@ -390,11 +604,14 @@ class ImportCapture:
|
|
|
390
604
|
self,
|
|
391
605
|
mod_globals: ta.MutableMapping[str, ta.Any],
|
|
392
606
|
*,
|
|
607
|
+
_hook: _ImportCaptureHook,
|
|
608
|
+
|
|
393
609
|
disable: bool = False,
|
|
394
610
|
) -> None:
|
|
395
611
|
super().__init__()
|
|
396
612
|
|
|
397
613
|
self._mod_globals = mod_globals
|
|
614
|
+
self._hook = _hook
|
|
398
615
|
|
|
399
616
|
self._disabled = disable
|
|
400
617
|
|
|
@@ -445,14 +662,12 @@ class ImportCapture:
|
|
|
445
662
|
yield self
|
|
446
663
|
return
|
|
447
664
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
with cap.hook_context(self._mod_globals):
|
|
665
|
+
with self._hook.hook_context(self._mod_globals):
|
|
451
666
|
yield self
|
|
452
667
|
|
|
453
|
-
|
|
668
|
+
self._hook.verify_state(self._mod_globals)
|
|
454
669
|
|
|
455
|
-
blt =
|
|
670
|
+
blt = self._hook.build_captured(
|
|
456
671
|
self._mod_globals,
|
|
457
672
|
collect_unreferenced=unreferenced_callback is not None or raise_unreferenced,
|
|
458
673
|
)
|