omlish 0.0.0.dev398__py3-none-any.whl → 0.0.0.dev400__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 +2 -2
- omlish/bootstrap/__init__.py +2 -2
- omlish/collections/__init__.py +135 -149
- omlish/configs/formats.py +6 -2
- omlish/diag/lsof.py +4 -3
- omlish/funcs/builders.py +2 -1
- omlish/lang/__init__.py +26 -5
- omlish/lang/imports/__init__.py +0 -0
- omlish/lang/imports/conditional.py +33 -0
- omlish/lang/imports/lazy.py +66 -0
- omlish/lang/imports/proxyinit.py +445 -0
- omlish/lang/imports/resolution.py +86 -0
- omlish/lang/imports/traversal.py +104 -0
- omlish/lang/lazyglobals.py +59 -0
- omlish/lang/resources.py +1 -1
- omlish/lite/imports.py +1 -1
- omlish/lite/reprs.py +2 -1
- omlish/manifests/base.py +2 -1
- omlish/manifests/loading.py +1 -1
- omlish/marshal/__init__.py +2 -2
- omlish/os/pidfiles/pinning.py +2 -1
- omlish/secrets/all.py +2 -2
- omlish/secrets/secrets.py +1 -1
- omlish/specs/jsonrpc/__init__.py +2 -2
- omlish/specs/jsonschema/__init__.py +2 -2
- omlish/specs/openapi/__init__.py +2 -2
- omlish/sql/api/__init__.py +2 -2
- omlish/sql/queries/__init__.py +3 -9
- omlish/sql/tabledefs/__init__.py +2 -2
- omlish/typedvalues/__init__.py +2 -2
- {omlish-0.0.0.dev398.dist-info → omlish-0.0.0.dev400.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev398.dist-info → omlish-0.0.0.dev400.dist-info}/RECORD +36 -30
- omlish/lang/imports.py +0 -418
- {omlish-0.0.0.dev398.dist-info → omlish-0.0.0.dev400.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev398.dist-info → omlish-0.0.0.dev400.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev398.dist-info → omlish-0.0.0.dev400.dist-info}/licenses/LICENSE +0 -0
- {omlish-0.0.0.dev398.dist-info → omlish-0.0.0.dev400.dist-info}/top_level.txt +0 -0
omlish/lang/imports.py
DELETED
@@ -1,418 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
TODO:
|
3
|
-
- proxy_init 'as' alias support - attrs of (src, dst)
|
4
|
-
- use importlib.util.resolve_name
|
5
|
-
"""
|
6
|
-
import contextlib
|
7
|
-
import functools
|
8
|
-
import importlib.util
|
9
|
-
import sys
|
10
|
-
import types
|
11
|
-
import typing as ta
|
12
|
-
|
13
|
-
|
14
|
-
##
|
15
|
-
|
16
|
-
|
17
|
-
def can_import(name: str, package: str | None = None) -> bool:
|
18
|
-
try:
|
19
|
-
spec = importlib.util.find_spec(name, package)
|
20
|
-
except ImportError:
|
21
|
-
return False
|
22
|
-
else:
|
23
|
-
return spec is not None
|
24
|
-
|
25
|
-
|
26
|
-
##
|
27
|
-
|
28
|
-
|
29
|
-
def lazy_import(
|
30
|
-
name: str,
|
31
|
-
package: str | None = None,
|
32
|
-
*,
|
33
|
-
optional: bool = False,
|
34
|
-
cache_failure: bool = False,
|
35
|
-
) -> ta.Callable[[], ta.Any]:
|
36
|
-
result = not_set = object()
|
37
|
-
|
38
|
-
def inner():
|
39
|
-
nonlocal result
|
40
|
-
|
41
|
-
if result is not not_set:
|
42
|
-
if isinstance(result, Exception):
|
43
|
-
raise result
|
44
|
-
return result
|
45
|
-
|
46
|
-
try:
|
47
|
-
mod = importlib.import_module(name, package=package)
|
48
|
-
|
49
|
-
except Exception as e:
|
50
|
-
if optional:
|
51
|
-
if cache_failure:
|
52
|
-
result = None
|
53
|
-
return None
|
54
|
-
|
55
|
-
if cache_failure:
|
56
|
-
result = e
|
57
|
-
raise
|
58
|
-
|
59
|
-
result = mod
|
60
|
-
return mod
|
61
|
-
|
62
|
-
return inner
|
63
|
-
|
64
|
-
|
65
|
-
def proxy_import(
|
66
|
-
name: str,
|
67
|
-
package: str | None = None,
|
68
|
-
extras: ta.Iterable[str] | None = None,
|
69
|
-
) -> types.ModuleType:
|
70
|
-
if isinstance(extras, str):
|
71
|
-
raise TypeError(extras)
|
72
|
-
|
73
|
-
omod = None
|
74
|
-
|
75
|
-
def __getattr__(att): # noqa
|
76
|
-
nonlocal omod
|
77
|
-
if omod is None:
|
78
|
-
omod = importlib.import_module(name, package=package)
|
79
|
-
if extras:
|
80
|
-
for x in extras:
|
81
|
-
importlib.import_module(f'{name}.{x}', package=package)
|
82
|
-
return getattr(omod, att)
|
83
|
-
|
84
|
-
lmod = types.ModuleType(name)
|
85
|
-
lmod.__getattr__ = __getattr__ # type: ignore
|
86
|
-
return lmod
|
87
|
-
|
88
|
-
|
89
|
-
##
|
90
|
-
|
91
|
-
|
92
|
-
SPECIAL_IMPORTABLE: ta.AbstractSet[str] = frozenset([
|
93
|
-
'__init__.py',
|
94
|
-
'__main__.py',
|
95
|
-
])
|
96
|
-
|
97
|
-
|
98
|
-
def yield_importable(
|
99
|
-
package_root: str,
|
100
|
-
*,
|
101
|
-
recursive: bool = False,
|
102
|
-
filter: ta.Callable[[str], bool] | None = None, # noqa
|
103
|
-
include_special: bool = False,
|
104
|
-
) -> ta.Iterator[str]:
|
105
|
-
from importlib import resources
|
106
|
-
|
107
|
-
def rec(cur):
|
108
|
-
if cur.split('.')[-1] == '__pycache__':
|
109
|
-
return
|
110
|
-
|
111
|
-
try:
|
112
|
-
module = sys.modules[cur]
|
113
|
-
except KeyError:
|
114
|
-
try:
|
115
|
-
__import__(cur)
|
116
|
-
except ImportError:
|
117
|
-
return
|
118
|
-
module = sys.modules[cur]
|
119
|
-
|
120
|
-
# FIXME: pyox
|
121
|
-
if getattr(module, '__file__', None) is None:
|
122
|
-
return
|
123
|
-
|
124
|
-
for file in resources.files(cur).iterdir():
|
125
|
-
if file.is_file() and file.name.endswith('.py'):
|
126
|
-
if not (include_special or file.name not in SPECIAL_IMPORTABLE):
|
127
|
-
continue
|
128
|
-
|
129
|
-
name = cur + '.' + file.name[:-3]
|
130
|
-
if filter is not None and not filter(name):
|
131
|
-
continue
|
132
|
-
|
133
|
-
yield name
|
134
|
-
|
135
|
-
elif recursive and file.is_dir():
|
136
|
-
name = cur + '.' + file.name
|
137
|
-
if filter is not None and not filter(name):
|
138
|
-
continue
|
139
|
-
with contextlib.suppress(ImportError, NotImplementedError):
|
140
|
-
yield from rec(name)
|
141
|
-
|
142
|
-
yield from rec(package_root)
|
143
|
-
|
144
|
-
|
145
|
-
def yield_import_all(
|
146
|
-
package_root: str,
|
147
|
-
*,
|
148
|
-
globals: dict[str, ta.Any] | None = None, # noqa
|
149
|
-
locals: dict[str, ta.Any] | None = None, # noqa
|
150
|
-
recursive: bool = False,
|
151
|
-
filter: ta.Callable[[str], bool] | None = None, # noqa
|
152
|
-
include_special: bool = False,
|
153
|
-
) -> ta.Iterator[str]:
|
154
|
-
for import_path in yield_importable(
|
155
|
-
package_root,
|
156
|
-
recursive=recursive,
|
157
|
-
filter=filter,
|
158
|
-
include_special=include_special,
|
159
|
-
):
|
160
|
-
__import__(import_path, globals=globals, locals=locals)
|
161
|
-
yield import_path
|
162
|
-
|
163
|
-
|
164
|
-
def import_all(
|
165
|
-
package_root: str,
|
166
|
-
*,
|
167
|
-
recursive: bool = False,
|
168
|
-
filter: ta.Callable[[str], bool] | None = None, # noqa
|
169
|
-
include_special: bool = False,
|
170
|
-
) -> None:
|
171
|
-
for _ in yield_import_all(
|
172
|
-
package_root,
|
173
|
-
recursive=recursive,
|
174
|
-
filter=filter,
|
175
|
-
include_special=include_special,
|
176
|
-
):
|
177
|
-
pass
|
178
|
-
|
179
|
-
|
180
|
-
def try_import(spec: str) -> types.ModuleType | None:
|
181
|
-
s = spec.lstrip('.')
|
182
|
-
l = len(spec) - len(s)
|
183
|
-
try:
|
184
|
-
return __import__(s, globals(), level=l)
|
185
|
-
except ImportError:
|
186
|
-
return None
|
187
|
-
|
188
|
-
|
189
|
-
##
|
190
|
-
|
191
|
-
|
192
|
-
def resolve_import_name(name: str, package: str | None = None) -> str:
|
193
|
-
# FIXME: importlib.util.resolve_name
|
194
|
-
level = 0
|
195
|
-
|
196
|
-
if name.startswith('.'):
|
197
|
-
if not package:
|
198
|
-
raise TypeError("the 'package' argument is required to perform a relative import for {name!r}")
|
199
|
-
for character in name:
|
200
|
-
if character != '.':
|
201
|
-
break
|
202
|
-
level += 1
|
203
|
-
|
204
|
-
name = name[level:]
|
205
|
-
|
206
|
-
if not isinstance(name, str):
|
207
|
-
raise TypeError(f'module name must be str, not {type(name)}')
|
208
|
-
if level < 0:
|
209
|
-
raise ValueError('level must be >= 0')
|
210
|
-
if level > 0:
|
211
|
-
if not isinstance(package, str):
|
212
|
-
raise TypeError('__package__ not set to a string')
|
213
|
-
elif not package:
|
214
|
-
raise ImportError('attempted relative import with no known parent package')
|
215
|
-
if not name and level == 0:
|
216
|
-
raise ValueError('Empty module name')
|
217
|
-
|
218
|
-
if level > 0:
|
219
|
-
bits = package.rsplit('.', level - 1) # type: ignore
|
220
|
-
if len(bits) < level:
|
221
|
-
raise ImportError('attempted relative import beyond top-level package')
|
222
|
-
base = bits[0]
|
223
|
-
name = f'{base}.{name}' if name else base
|
224
|
-
|
225
|
-
return name
|
226
|
-
|
227
|
-
|
228
|
-
##
|
229
|
-
|
230
|
-
|
231
|
-
_REGISTERED_CONDITIONAL_IMPORTS: dict[str, list[str] | None] = {}
|
232
|
-
|
233
|
-
|
234
|
-
def _register_conditional_import(when: str, then: str, package: str | None = None) -> None:
|
235
|
-
wn = resolve_import_name(when, package)
|
236
|
-
tn = resolve_import_name(then, package)
|
237
|
-
if tn in sys.modules:
|
238
|
-
return
|
239
|
-
if wn in sys.modules:
|
240
|
-
__import__(tn)
|
241
|
-
else:
|
242
|
-
tns = _REGISTERED_CONDITIONAL_IMPORTS.setdefault(wn, [])
|
243
|
-
if tns is None:
|
244
|
-
raise Exception(f'Conditional import trigger already cleared: {wn=} {tn=}')
|
245
|
-
tns.append(tn)
|
246
|
-
|
247
|
-
|
248
|
-
def _trigger_conditional_imports(package: str) -> None:
|
249
|
-
tns = _REGISTERED_CONDITIONAL_IMPORTS.get(package, [])
|
250
|
-
if tns is None:
|
251
|
-
raise Exception(f'Conditional import trigger already cleared: {package=}')
|
252
|
-
_REGISTERED_CONDITIONAL_IMPORTS[package] = None
|
253
|
-
for tn in tns:
|
254
|
-
__import__(tn)
|
255
|
-
|
256
|
-
|
257
|
-
##
|
258
|
-
|
259
|
-
|
260
|
-
class LazyGlobals:
|
261
|
-
def __init__(
|
262
|
-
self,
|
263
|
-
*,
|
264
|
-
globals: ta.MutableMapping[str, ta.Any] | None = None, # noqa
|
265
|
-
update_globals: bool = False,
|
266
|
-
) -> None:
|
267
|
-
super().__init__()
|
268
|
-
|
269
|
-
self._globals = globals
|
270
|
-
self._update_globals = update_globals
|
271
|
-
|
272
|
-
self._attr_fns: dict[str, ta.Callable[[], ta.Any]] = {}
|
273
|
-
|
274
|
-
@classmethod
|
275
|
-
def install(cls, globals: ta.MutableMapping[str, ta.Any]) -> 'LazyGlobals': # noqa
|
276
|
-
try:
|
277
|
-
xga = globals['__getattr__']
|
278
|
-
except KeyError:
|
279
|
-
pass
|
280
|
-
else:
|
281
|
-
if not isinstance(xga, cls):
|
282
|
-
raise RuntimeError(f'Module already has __getattr__ hook: {xga}') # noqa
|
283
|
-
return xga
|
284
|
-
|
285
|
-
lm = cls(
|
286
|
-
globals=globals,
|
287
|
-
update_globals=True,
|
288
|
-
)
|
289
|
-
|
290
|
-
globals['__getattr__'] = lm
|
291
|
-
|
292
|
-
return lm
|
293
|
-
|
294
|
-
def set_fn(self, attr: str, fn: ta.Callable[[], ta.Any]) -> 'LazyGlobals':
|
295
|
-
self._attr_fns[attr] = fn
|
296
|
-
return self
|
297
|
-
|
298
|
-
def get(self, attr: str) -> ta.Any:
|
299
|
-
try:
|
300
|
-
fn = self._attr_fns[attr]
|
301
|
-
except KeyError:
|
302
|
-
raise AttributeError(attr) from None
|
303
|
-
|
304
|
-
val = fn()
|
305
|
-
|
306
|
-
if self._update_globals and self._globals is not None:
|
307
|
-
self._globals[attr] = val
|
308
|
-
|
309
|
-
return val
|
310
|
-
|
311
|
-
def __call__(self, attr: str) -> ta.Any:
|
312
|
-
return self.get(attr)
|
313
|
-
|
314
|
-
|
315
|
-
##
|
316
|
-
|
317
|
-
|
318
|
-
class NamePackage(ta.NamedTuple):
|
319
|
-
name: str
|
320
|
-
package: str
|
321
|
-
|
322
|
-
|
323
|
-
class _ProxyInit:
|
324
|
-
class _Import(ta.NamedTuple):
|
325
|
-
pkg: str
|
326
|
-
attr: str
|
327
|
-
|
328
|
-
def __init__(
|
329
|
-
self,
|
330
|
-
lazy_globals: LazyGlobals,
|
331
|
-
name_package: NamePackage,
|
332
|
-
) -> None:
|
333
|
-
super().__init__()
|
334
|
-
|
335
|
-
self._lazy_globals = lazy_globals
|
336
|
-
self._name_package = name_package
|
337
|
-
|
338
|
-
self._imps_by_attr: dict[str, _ProxyInit._Import] = {}
|
339
|
-
self._mods_by_pkgs: dict[str, ta.Any] = {}
|
340
|
-
|
341
|
-
@property
|
342
|
-
def name_package(self) -> NamePackage:
|
343
|
-
return self._name_package
|
344
|
-
|
345
|
-
def add(self, package: str, attrs: ta.Iterable[str | tuple[str, str]]) -> None:
|
346
|
-
if isinstance(attrs, str):
|
347
|
-
raise TypeError(attrs)
|
348
|
-
|
349
|
-
for attr in attrs:
|
350
|
-
if isinstance(attr, tuple):
|
351
|
-
imp_attr, attr = attr
|
352
|
-
else:
|
353
|
-
imp_attr = attr
|
354
|
-
|
355
|
-
self._imps_by_attr[attr] = self._Import(package, imp_attr)
|
356
|
-
|
357
|
-
self._lazy_globals.set_fn(attr, functools.partial(self.get, attr))
|
358
|
-
|
359
|
-
def get(self, attr: str) -> ta.Any:
|
360
|
-
try:
|
361
|
-
imp = self._imps_by_attr[attr]
|
362
|
-
except KeyError:
|
363
|
-
raise AttributeError(attr) # noqa
|
364
|
-
|
365
|
-
try:
|
366
|
-
mod = self._mods_by_pkgs[imp.pkg]
|
367
|
-
except KeyError:
|
368
|
-
mod = importlib.import_module(imp.pkg, package=self._name_package.package)
|
369
|
-
|
370
|
-
val = getattr(mod, imp.attr)
|
371
|
-
|
372
|
-
return val
|
373
|
-
|
374
|
-
|
375
|
-
def proxy_init(
|
376
|
-
globals: ta.MutableMapping[str, ta.Any], # noqa
|
377
|
-
package: str,
|
378
|
-
attrs: ta.Iterable[str | tuple[str, str]],
|
379
|
-
) -> None:
|
380
|
-
if isinstance(attrs, str):
|
381
|
-
raise TypeError(attrs)
|
382
|
-
|
383
|
-
init_name_package = NamePackage(
|
384
|
-
globals['__name__'],
|
385
|
-
globals['__package__'],
|
386
|
-
)
|
387
|
-
|
388
|
-
pi: _ProxyInit
|
389
|
-
try:
|
390
|
-
pi = globals['__proxy_init__']
|
391
|
-
|
392
|
-
except KeyError:
|
393
|
-
pi = _ProxyInit(
|
394
|
-
LazyGlobals.install(globals),
|
395
|
-
init_name_package,
|
396
|
-
)
|
397
|
-
globals['__proxy_init__'] = pi
|
398
|
-
|
399
|
-
else:
|
400
|
-
if pi.name_package != init_name_package:
|
401
|
-
raise Exception(f'Wrong init name: {pi.name_package=} != {init_name_package=}')
|
402
|
-
|
403
|
-
pi.add(package, attrs)
|
404
|
-
|
405
|
-
|
406
|
-
##
|
407
|
-
|
408
|
-
|
409
|
-
def get_real_module_name(globals: ta.Mapping[str, ta.Any]) -> str: # noqa
|
410
|
-
module = sys.modules[globals['__name__']]
|
411
|
-
|
412
|
-
if module.__spec__ and module.__spec__.name:
|
413
|
-
return module.__spec__.name
|
414
|
-
|
415
|
-
if module.__package__:
|
416
|
-
return module.__package__
|
417
|
-
|
418
|
-
raise RuntimeError("Can't determine real module name")
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|