omlish 0.0.0.dev458__py3-none-any.whl → 0.0.0.dev459__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 +310 -163
- omlish/lang/imports/proxy.py +72 -28
- {omlish-0.0.0.dev458.dist-info → omlish-0.0.0.dev459.dist-info}/METADATA +3 -3
- {omlish-0.0.0.dev458.dist-info → omlish-0.0.0.dev459.dist-info}/RECORD +11 -11
- {omlish-0.0.0.dev458.dist-info → omlish-0.0.0.dev459.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev458.dist-info → omlish-0.0.0.dev459.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev458.dist-info → omlish-0.0.0.dev459.dist-info}/licenses/LICENSE +0 -0
- {omlish-0.0.0.dev458.dist-info → omlish-0.0.0.dev459.dist-info}/top_level.txt +0 -0
omlish/__about__.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
__version__ = '0.0.0.
|
2
|
-
__revision__ = '
|
1
|
+
__version__ = '0.0.0.dev459'
|
2
|
+
__revision__ = 'a12178d42c88b1d69bca74aaf2cd0f1fd8106a47'
|
3
3
|
|
4
4
|
|
5
5
|
#
|
@@ -83,7 +83,7 @@ class Project(ProjectBase):
|
|
83
83
|
],
|
84
84
|
|
85
85
|
'secrets': [
|
86
|
-
'cryptography ~=
|
86
|
+
'cryptography ~= 46.0',
|
87
87
|
],
|
88
88
|
|
89
89
|
'sqlalchemy': [
|
omlish/diag/pydevd.py
CHANGED
@@ -6,7 +6,7 @@ an already-debugging PyCharm instance to debug PySpark jobs.
|
|
6
6
|
TODO:
|
7
7
|
- https://www.jetbrains.com/help/pycharm/remote-debugging-with-product.html#
|
8
8
|
|
9
|
-
|
9
|
+
====
|
10
10
|
|
11
11
|
https://www.jetbrains.com/help/pycharm/remote-debugging-with-product.html#remote-debug-config ->
|
12
12
|
|
@@ -25,6 +25,28 @@ buf = textwrap.dedent(f'''
|
|
25
25
|
stderrToServer=True,
|
26
26
|
)
|
27
27
|
''') + '\n' * 2 + buf
|
28
|
+
|
29
|
+
====
|
30
|
+
|
31
|
+
TODO: monkeypatch:
|
32
|
+
|
33
|
+
/Applications/PyCharm.app/Contents/plugins/python-ce/helpers/pydev/_pydev_bundle/pydev_monkey.py ::
|
34
|
+
|
35
|
+
def starts_with_python_shebang(path):
|
36
|
+
try:
|
37
|
+
with open(path) as f:
|
38
|
+
for line in f:
|
39
|
+
line = line.strip()
|
40
|
+
if line:
|
41
|
+
for name in PYTHON_NAMES:
|
42
|
+
if line.startswith('#!/usr/bin/env %s' % name):
|
43
|
+
return True
|
44
|
+
return False
|
45
|
+
except (UnicodeDecodeError, IsADirectoryError): # <-- Add catch for `IsADirectoryError`
|
46
|
+
return False
|
47
|
+
except:
|
48
|
+
traceback.print_exc()
|
49
|
+
return False
|
28
50
|
"""
|
29
51
|
import json
|
30
52
|
import os
|
omlish/lang/imports/_capture.cc
CHANGED
@@ -5,6 +5,9 @@
|
|
5
5
|
#define Py_BUILD_CORE 1
|
6
6
|
#include "Python.h"
|
7
7
|
#include "internal/pycore_frame.h"
|
8
|
+
#if PY_VERSION_HEX >= 0x030E0000
|
9
|
+
#include "internal/pycore_interpframe.h"
|
10
|
+
#endif
|
8
11
|
#undef Py_BUILD_CORE
|
9
12
|
|
10
13
|
#if PY_VERSION_HEX < 0x030D0000
|
@@ -50,14 +53,12 @@ _set_frame_builtins(PyObject *self, PyObject *args)
|
|
50
53
|
|
51
54
|
std::atomic_ref<PyObject*> builtins_ref(iframe->f_builtins);
|
52
55
|
PyObject* expected = old_builtins;
|
53
|
-
|
56
|
+
if (builtins_ref.compare_exchange_strong(
|
54
57
|
expected,
|
55
58
|
new_builtins,
|
56
59
|
std::memory_order_acq_rel,
|
57
60
|
std::memory_order_acquire
|
58
|
-
)
|
59
|
-
|
60
|
-
if (success) {
|
61
|
+
)) {
|
61
62
|
Py_RETURN_TRUE;
|
62
63
|
} else {
|
63
64
|
Py_RETURN_FALSE;
|
omlish/lang/imports/capture.py
CHANGED
@@ -15,6 +15,7 @@ Possible alt impls:
|
|
15
15
|
import builtins
|
16
16
|
import contextlib
|
17
17
|
import functools
|
18
|
+
import importlib.util
|
18
19
|
import sys
|
19
20
|
import threading
|
20
21
|
import types
|
@@ -46,14 +47,27 @@ class ImportCaptureErrors:
|
|
46
47
|
return f'{self.__class__.__qualname__}(module={self.module!r}, name={self.name!r})'
|
47
48
|
|
48
49
|
class ImportError(ImportCaptureError): # noqa
|
49
|
-
def __init__(
|
50
|
+
def __init__(
|
51
|
+
self,
|
52
|
+
name: str,
|
53
|
+
*,
|
54
|
+
level: int | None = None,
|
55
|
+
from_list: ta.Sequence[str] | None,
|
56
|
+
) -> None:
|
50
57
|
super().__init__()
|
51
58
|
|
52
|
-
self.
|
59
|
+
self.name = name
|
60
|
+
self.level = level
|
53
61
|
self.from_list = from_list
|
54
62
|
|
55
63
|
def __repr__(self) -> str:
|
56
|
-
return
|
64
|
+
return ''.join([
|
65
|
+
f'{self.__class__.__qualname__}(',
|
66
|
+
f'name={self.name!r}',
|
67
|
+
*([f', level={self.level!r}'] if self.level is not None else []),
|
68
|
+
*([f', from_list={self.from_list!r}'] if self.from_list is not None else []),
|
69
|
+
')',
|
70
|
+
])
|
57
71
|
|
58
72
|
class ImportStarForbiddenError(ImportError):
|
59
73
|
pass
|
@@ -62,7 +76,7 @@ class ImportCaptureErrors:
|
|
62
76
|
pass
|
63
77
|
|
64
78
|
class UnreferencedImportsError(ImportCaptureError):
|
65
|
-
def __init__(self, unreferenced: ta.
|
79
|
+
def __init__(self, unreferenced: ta.Sequence[str]) -> None:
|
66
80
|
super().__init__()
|
67
81
|
|
68
82
|
self.unreferenced = unreferenced
|
@@ -78,136 +92,144 @@ class ImportCaptureErrors:
|
|
78
92
|
|
79
93
|
|
80
94
|
class _ImportCaptureHook:
|
81
|
-
class ModuleSpec(ta.NamedTuple):
|
82
|
-
name: str
|
83
|
-
level: int
|
84
|
-
|
85
|
-
def __str__(self) -> str:
|
86
|
-
return f'{"." * self.level}{self.name}'
|
87
|
-
|
88
|
-
def __repr__(self) -> str:
|
89
|
-
return repr(str(self))
|
90
|
-
|
91
95
|
def __init__(
|
92
96
|
self,
|
93
97
|
*,
|
98
|
+
package: str | None = None,
|
94
99
|
forbid_uncaptured_imports: bool = False,
|
95
100
|
) -> None:
|
96
101
|
super().__init__()
|
97
102
|
|
103
|
+
self._package = package
|
98
104
|
self._forbid_uncaptured_imports = forbid_uncaptured_imports
|
99
105
|
|
100
|
-
self.
|
106
|
+
self._modules_by_name: dict[str, _ImportCaptureHook._Module] = {}
|
101
107
|
self._modules_by_module_obj: dict[types.ModuleType, _ImportCaptureHook._Module] = {}
|
102
108
|
|
103
|
-
self._attrs: dict[_ImportCaptureHook._ModuleAttr, tuple[_ImportCaptureHook._Module, str]] = {}
|
104
|
-
|
105
109
|
#
|
106
110
|
|
107
|
-
class
|
111
|
+
class _Module:
|
108
112
|
def __init__(
|
109
113
|
self,
|
110
|
-
module: '_ImportCaptureHook._Module',
|
111
114
|
name: str,
|
115
|
+
getattr_handler: ta.Callable[['_ImportCaptureHook._Module', str], ta.Any],
|
116
|
+
*,
|
117
|
+
parent: ta.Optional['_ImportCaptureHook._Module'] = None,
|
112
118
|
) -> None:
|
113
119
|
super().__init__()
|
114
120
|
|
115
|
-
|
116
|
-
|
121
|
+
if name.startswith('.'):
|
122
|
+
raise ImportCaptureError
|
123
|
+
self.name = name
|
124
|
+
self.base_name = name.rpartition('.')[2]
|
125
|
+
self.parent = parent
|
126
|
+
|
127
|
+
self.module_obj = types.ModuleType(f'<{self.__class__.__qualname__}: {name}>')
|
128
|
+
self.module_obj.__file__ = None
|
129
|
+
self.module_obj.__getattr__ = functools.partial(getattr_handler, self) # type: ignore[method-assign] # noqa
|
130
|
+
self.initial_module_dict = dict(self.module_obj.__dict__)
|
131
|
+
|
132
|
+
self.children: dict[str, _ImportCaptureHook._Module] = {}
|
133
|
+
self.descendants: set[_ImportCaptureHook._Module] = set()
|
134
|
+
self.explicit = False
|
135
|
+
self.immediate = False
|
117
136
|
|
118
137
|
def __repr__(self) -> str:
|
119
|
-
return f'
|
138
|
+
return f'{self.__class__.__name__}<{self.name}{"!" if self.immediate else "+" if self.explicit else ""}>'
|
120
139
|
|
121
|
-
|
122
|
-
def
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
140
|
+
@property
|
141
|
+
def root(self) -> '_ImportCaptureHook._Module':
|
142
|
+
out = self
|
143
|
+
while out.parent is not None:
|
144
|
+
out = out.parent
|
145
|
+
return out
|
146
|
+
|
147
|
+
def set_explicit(self) -> None:
|
148
|
+
cur: _ImportCaptureHook._Module | None = self
|
149
|
+
while cur is not None and not cur.explicit:
|
150
|
+
cur.explicit = True
|
151
|
+
cur = cur.parent
|
129
152
|
|
130
|
-
|
153
|
+
#
|
131
154
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
155
|
+
@property
|
156
|
+
def _modules(self) -> ta.Sequence[_Module]:
|
157
|
+
return sorted(self._modules_by_name.values(), key=lambda m: m.name)
|
158
|
+
|
159
|
+
def _get_or_make_module(self, name: str) -> _Module:
|
160
|
+
def rec(name: str) -> _ImportCaptureHook._Module: # noqa
|
161
|
+
try:
|
162
|
+
return self._modules_by_name[name]
|
163
|
+
except KeyError:
|
164
|
+
pass
|
165
|
+
|
166
|
+
parent: _ImportCaptureHook._Module | None = None
|
167
|
+
if '.' in name:
|
168
|
+
rest, _, attr = name.rpartition('.')
|
169
|
+
parent = rec(rest)
|
170
|
+
if attr in parent.children:
|
171
|
+
raise ImportCaptureErrors.AttrError(rest, attr)
|
172
|
+
|
173
|
+
module = self._Module(
|
174
|
+
name,
|
175
|
+
self._handle_module_getattr,
|
176
|
+
parent=parent,
|
177
|
+
)
|
178
|
+
self._modules_by_name[name] = module
|
179
|
+
self._modules_by_module_obj[module.module_obj] = module
|
136
180
|
|
137
|
-
|
138
|
-
|
181
|
+
if parent is not None:
|
182
|
+
parent.children[attr] = module # noqa
|
183
|
+
setattr(parent.module_obj, attr, module.module_obj)
|
184
|
+
parent.root.descendants.add(module)
|
139
185
|
|
140
|
-
|
141
|
-
return f'{self.__class__.__name__}({self.spec!r})'
|
186
|
+
return module
|
142
187
|
|
143
|
-
|
144
|
-
try:
|
145
|
-
return self._modules_by_spec[spec]
|
146
|
-
except KeyError:
|
147
|
-
pass
|
188
|
+
return rec(name)
|
148
189
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
)
|
153
|
-
self._modules_by_spec[spec] = module
|
154
|
-
self._modules_by_module_obj[module.module_obj] = module
|
155
|
-
return module
|
190
|
+
def _make_child_module(self, module: _Module, attr: str) -> _Module:
|
191
|
+
if attr in module.children:
|
192
|
+
raise ImportCaptureErrors.AttrError(module.name, attr)
|
156
193
|
|
157
|
-
|
158
|
-
if attr in module.contents:
|
159
|
-
raise ImportCaptureErrors.AttrError(str(module.spec), attr)
|
194
|
+
return self._get_or_make_module(f'{module.name}.{attr}')
|
160
195
|
|
161
|
-
|
162
|
-
if not module.spec.name:
|
163
|
-
if not module.spec.level:
|
164
|
-
raise ImportCaptureError
|
165
|
-
cs = _ImportCaptureHook.ModuleSpec(attr, module.spec.level)
|
166
|
-
cm = self._get_or_make_module(cs)
|
167
|
-
cm.imported_whole = True
|
168
|
-
v = cm.module_obj
|
196
|
+
#
|
169
197
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
v = ma
|
198
|
+
def _handle_module_getattr(self, module: _Module, attr: str) -> ta.Any:
|
199
|
+
if not module.explicit:
|
200
|
+
raise ImportCaptureErrors.AttrError(module.name, attr)
|
174
201
|
|
175
|
-
module.
|
176
|
-
setattr(module.module_obj, attr, v)
|
177
|
-
return v
|
202
|
+
return self._make_child_module(module, attr).module_obj
|
178
203
|
|
179
204
|
def _handle_import(
|
180
205
|
self,
|
181
|
-
|
206
|
+
name: str,
|
182
207
|
*,
|
183
208
|
from_list: ta.Sequence[str] | None,
|
184
|
-
) ->
|
185
|
-
|
186
|
-
if module.spec.level or not module.spec.name:
|
187
|
-
raise ImportCaptureError
|
209
|
+
) -> types.ModuleType:
|
210
|
+
module = self._get_or_make_module(name)
|
188
211
|
|
189
|
-
|
212
|
+
if from_list is None:
|
213
|
+
module.set_explicit()
|
214
|
+
module.root.immediate = True
|
215
|
+
return module.root.module_obj
|
190
216
|
|
191
217
|
else:
|
192
218
|
for attr in from_list:
|
193
219
|
if attr == '*':
|
194
|
-
raise ImportCaptureErrors.ImportStarForbiddenError(
|
220
|
+
raise ImportCaptureErrors.ImportStarForbiddenError(module.name, from_list=from_list)
|
221
|
+
|
222
|
+
if (cm := module.children.get(attr)) is None:
|
223
|
+
cm = self._make_child_module(module, attr)
|
224
|
+
cm.set_explicit()
|
225
|
+
cm.immediate = True
|
226
|
+
continue
|
195
227
|
|
196
228
|
x = getattr(module.module_obj, attr)
|
229
|
+
if x is not cm.module_obj or x not in self._modules_by_module_obj:
|
230
|
+
raise ImportCaptureErrors.AttrError(module.name, attr)
|
197
231
|
|
198
|
-
|
199
|
-
if x is not module.contents.get(attr):
|
200
|
-
bad = True
|
201
|
-
if isinstance(x, _ImportCaptureHook._ModuleAttr):
|
202
|
-
if self._attrs[x] != (module, attr):
|
203
|
-
bad = True
|
204
|
-
elif isinstance(x, types.ModuleType):
|
205
|
-
if x not in self._modules_by_module_obj:
|
206
|
-
bad = True
|
207
|
-
else:
|
208
|
-
bad = True
|
209
|
-
if bad:
|
210
|
-
raise ImportCaptureErrors.AttrError(str(module.spec), attr)
|
232
|
+
return module.module_obj
|
211
233
|
|
212
234
|
#
|
213
235
|
|
@@ -227,16 +249,16 @@ class _ImportCaptureHook:
|
|
227
249
|
):
|
228
250
|
return None
|
229
251
|
|
230
|
-
|
231
|
-
|
252
|
+
if level:
|
253
|
+
if not self._package:
|
254
|
+
raise ImportCaptureError
|
255
|
+
name = importlib.util.resolve_name(('.' * level) + name, self._package)
|
232
256
|
|
233
|
-
self._handle_import(
|
234
|
-
|
257
|
+
return self._handle_import(
|
258
|
+
name,
|
235
259
|
from_list=from_list,
|
236
260
|
)
|
237
261
|
|
238
|
-
return module.module_obj
|
239
|
-
|
240
262
|
@ta.final
|
241
263
|
@contextlib.contextmanager
|
242
264
|
def hook_context(
|
@@ -271,18 +293,24 @@ class _ImportCaptureHook:
|
|
271
293
|
self,
|
272
294
|
mod_globals: ta.MutableMapping[str, ta.Any], # noqa
|
273
295
|
) -> None:
|
274
|
-
for m in self.
|
296
|
+
for m in self._modules_by_name.values():
|
297
|
+
if m.immediate and not m.explicit:
|
298
|
+
raise ImportCaptureError
|
299
|
+
|
300
|
+
if not m.explicit and m.children:
|
301
|
+
raise ImportCaptureError
|
302
|
+
|
275
303
|
for a, o in m.module_obj.__dict__.items():
|
276
304
|
try:
|
277
305
|
i = m.initial_module_dict[a]
|
278
306
|
|
279
307
|
except KeyError:
|
280
|
-
if o is not m.
|
281
|
-
raise ImportCaptureErrors.AttrError(
|
308
|
+
if o is not m.children[a].module_obj:
|
309
|
+
raise ImportCaptureErrors.AttrError(m.name, a) from None
|
282
310
|
|
283
311
|
else:
|
284
312
|
if o != i:
|
285
|
-
raise ImportCaptureErrors.AttrError(
|
313
|
+
raise ImportCaptureErrors.AttrError(m.name, a)
|
286
314
|
|
287
315
|
#
|
288
316
|
|
@@ -292,24 +320,16 @@ class _ImportCaptureHook:
|
|
292
320
|
*,
|
293
321
|
collect_unreferenced: bool = False,
|
294
322
|
) -> 'ImportCapture.Captured':
|
295
|
-
|
296
|
-
|
297
|
-
rem_whole_mods: set[_ImportCaptureHook._Module] = set()
|
298
|
-
rem_mod_attrs: set[_ImportCaptureHook._ModuleAttr] = set()
|
323
|
+
rem_explicit_mods: set[_ImportCaptureHook._Module] = set()
|
299
324
|
if collect_unreferenced:
|
300
|
-
|
301
|
-
rem_mod_attrs.update(self._attrs)
|
325
|
+
rem_explicit_mods.update([m for m in self._modules_by_name.values() if m.immediate])
|
302
326
|
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
m, a = self._attrs[obj]
|
307
|
-
except KeyError:
|
308
|
-
raise ImportCaptureErrors.AttrError(None, attr) from None
|
309
|
-
dct.setdefault(m, []).append((a, attr))
|
310
|
-
rem_mod_attrs.discard(obj)
|
327
|
+
#
|
328
|
+
|
329
|
+
dct: dict[_ImportCaptureHook._Module, list[tuple[str | None, str]]] = {}
|
311
330
|
|
312
|
-
|
331
|
+
for attr, obj in mod_globals.items():
|
332
|
+
if isinstance(obj, _ImportCaptureHook._Module):
|
313
333
|
raise ImportCaptureErrors.AttrError(None, attr) from None
|
314
334
|
|
315
335
|
elif isinstance(obj, types.ModuleType):
|
@@ -317,41 +337,80 @@ class _ImportCaptureHook:
|
|
317
337
|
m = self._modules_by_module_obj[obj]
|
318
338
|
except KeyError:
|
319
339
|
continue
|
320
|
-
if not m.imported_whole:
|
321
|
-
raise RuntimeError(f'ImportCapture module {m.spec!r} not imported_whole')
|
322
|
-
dct.setdefault(m, []).append((None, attr))
|
323
|
-
rem_whole_mods.discard(m)
|
324
|
-
|
325
|
-
lst: list[ImportCapture.Import] = []
|
326
|
-
for m, ts in dct.items():
|
327
|
-
if not m.spec.name:
|
328
|
-
if not m.spec.level:
|
329
|
-
raise ImportCaptureError
|
330
|
-
for imp_attr, as_attr in ts:
|
331
|
-
if not imp_attr:
|
332
|
-
raise RuntimeError
|
333
|
-
lst.append(ImportCapture.Import(
|
334
|
-
'.' * m.spec.level + imp_attr,
|
335
|
-
[(None, as_attr)],
|
336
|
-
))
|
337
340
|
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
341
|
+
if m.explicit:
|
342
|
+
dct.setdefault(m, []).append((None, attr))
|
343
|
+
if m in rem_explicit_mods:
|
344
|
+
# Remove everything reachable from this root *except* items imported immediately, such as
|
345
|
+
# `from x import y` - those still need to be immediately reachable.
|
346
|
+
rem_explicit_mods -= {dm for dm in m.descendants if not dm.immediate}
|
347
|
+
rem_explicit_mods.remove(m)
|
348
|
+
|
349
|
+
else:
|
350
|
+
p = m.parent
|
351
|
+
if p is None or not p.explicit:
|
352
|
+
raise ImportCaptureError
|
353
|
+
dct.setdefault(p, []).append((m.base_name, attr))
|
354
|
+
|
355
|
+
#
|
356
|
+
|
357
|
+
mods: dict[str, ImportCapture.Module] = {}
|
358
|
+
|
359
|
+
def build_import_module(m: _ImportCaptureHook._Module) -> ImportCapture.Module:
|
360
|
+
children: dict[str, ImportCapture.Module] = {}
|
361
|
+
attrs: list[str] = []
|
362
|
+
for cm in sorted(m.children.values(), key=lambda cm: cm.name):
|
363
|
+
if not cm.explicit:
|
364
|
+
attrs.append(cm.base_name)
|
365
|
+
else:
|
366
|
+
children[cm.base_name] = build_import_module(cm)
|
367
|
+
|
368
|
+
mod = ImportCapture.Module(
|
369
|
+
m.name,
|
370
|
+
children or None,
|
371
|
+
attrs or None,
|
372
|
+
)
|
373
|
+
|
374
|
+
if m.parent is None:
|
375
|
+
mod.parent = None
|
376
|
+
for c in children.values():
|
377
|
+
c.parent = mod
|
378
|
+
|
379
|
+
mods[mod.name] = mod
|
380
|
+
return mod
|
381
|
+
|
382
|
+
root_mods: dict[str, ImportCapture.Module] = {
|
383
|
+
m.base_name: build_import_module(m)
|
384
|
+
for m in self._modules_by_name.values()
|
385
|
+
if m.parent is None
|
386
|
+
}
|
387
|
+
|
388
|
+
mods = dict(sorted(mods.items(), key=lambda t: t[0]))
|
389
|
+
root_mods = dict(sorted(root_mods.items(), key=lambda t: t[0]))
|
390
|
+
|
391
|
+
#
|
392
|
+
|
393
|
+
imps: list[ImportCapture.Import] = []
|
394
|
+
|
395
|
+
for m, ts in sorted(dct.items(), key=lambda t: t[0].name):
|
396
|
+
imps.append(ImportCapture.Import(
|
397
|
+
mods[m.name],
|
398
|
+
[r for l, r in ts if l is None],
|
399
|
+
[(l, r) for l, r in ts if l is not None],
|
400
|
+
))
|
401
|
+
|
402
|
+
#
|
403
|
+
|
404
|
+
unreferenced: list[str] | None = None
|
405
|
+
if collect_unreferenced and rem_explicit_mods:
|
406
|
+
unreferenced = sorted(m.name for m in rem_explicit_mods)
|
352
407
|
|
353
408
|
return ImportCapture.Captured(
|
354
|
-
|
409
|
+
{i.module.name: i for i in imps},
|
410
|
+
|
411
|
+
mods,
|
412
|
+
root_mods,
|
413
|
+
|
355
414
|
unreferenced,
|
356
415
|
)
|
357
416
|
|
@@ -379,8 +438,9 @@ class _AbstractBuiltinsImportCaptureHook(_ImportCaptureHook):
|
|
379
438
|
|
380
439
|
if self._forbid_uncaptured_imports:
|
381
440
|
raise ImportCaptureErrors.UncapturedImportForbiddenError(
|
382
|
-
|
383
|
-
|
441
|
+
name,
|
442
|
+
level=level,
|
443
|
+
from_list=fromlist,
|
384
444
|
)
|
385
445
|
|
386
446
|
return old_import(
|
@@ -579,6 +639,8 @@ def _new_import_capture_hook(
|
|
579
639
|
if frame is None or frame.f_globals is not mod_globals:
|
580
640
|
raise ImportCaptureError("Can't find importing frame")
|
581
641
|
|
642
|
+
kwargs.setdefault('package', mod_globals.get('__package__'))
|
643
|
+
|
582
644
|
if _capture is not None:
|
583
645
|
return _FrameBuiltinsImportCaptureHook(_frame=frame, **kwargs)
|
584
646
|
|
@@ -588,21 +650,110 @@ def _new_import_capture_hook(
|
|
588
650
|
##
|
589
651
|
|
590
652
|
|
653
|
+
ImportCaptureModuleKind: ta.TypeAlias = ta.Literal[
|
654
|
+
'parent',
|
655
|
+
'terminal',
|
656
|
+
'leaf',
|
657
|
+
]
|
658
|
+
|
659
|
+
|
591
660
|
class ImportCapture:
|
592
|
-
|
593
|
-
|
594
|
-
|
661
|
+
@ta.final
|
662
|
+
class Module:
|
663
|
+
def __init__(
|
664
|
+
self,
|
665
|
+
name: str,
|
666
|
+
children: ta.Mapping[str, 'ImportCapture.Module'] | None = None,
|
667
|
+
attrs: ta.Sequence[str] | None = None,
|
668
|
+
) -> None:
|
669
|
+
self.name = name
|
670
|
+
self.children = children
|
671
|
+
self.attrs = attrs
|
672
|
+
|
673
|
+
self.base_name = name.rpartition('.')[2]
|
674
|
+
|
675
|
+
if not self.children and not self.attrs:
|
676
|
+
self.kind = 'leaf'
|
677
|
+
elif not self.children or all(c.kind == 'leaf' for c in self.children.values()):
|
678
|
+
self.kind = 'terminal'
|
679
|
+
else:
|
680
|
+
self.kind = 'parent'
|
681
|
+
|
682
|
+
parent: ta.Optional['ImportCapture.Module']
|
683
|
+
|
684
|
+
kind: ImportCaptureModuleKind
|
685
|
+
|
686
|
+
def __repr__(self) -> str:
|
687
|
+
return ''.join([
|
688
|
+
f'{self.__class__.__name__}(',
|
689
|
+
f'{self.name!r}',
|
690
|
+
f', :{self.kind}',
|
691
|
+
*([f', children=[{", ".join(map(repr, self.children))}]'] if self.children else []),
|
692
|
+
*([f', attrs={self.attrs!r}'] if self.attrs else []),
|
693
|
+
')',
|
694
|
+
])
|
695
|
+
|
696
|
+
@property
|
697
|
+
def root(self) -> 'ImportCapture.Module':
|
698
|
+
out = self
|
699
|
+
while out.parent is not None:
|
700
|
+
out = out.parent
|
701
|
+
return out
|
702
|
+
|
703
|
+
@ta.final
|
704
|
+
class Import:
|
705
|
+
def __init__(
|
706
|
+
self,
|
707
|
+
module: 'ImportCapture.Module',
|
708
|
+
as_: ta.Sequence[str],
|
709
|
+
attrs: ta.Sequence[tuple[str, str]], # ('foo', 'bar') -> `import foo as bar` - explicitly not a dict
|
710
|
+
) -> None:
|
711
|
+
self.module = module
|
712
|
+
self.as_ = as_
|
713
|
+
self.attrs = attrs
|
714
|
+
|
715
|
+
def __repr__(self) -> str:
|
716
|
+
return ''.join([
|
717
|
+
f'{self.__class__.__name__}(',
|
718
|
+
f'{self.module.name!r}',
|
719
|
+
*([f', as_={self.as_!r}'] if self.as_ else []),
|
720
|
+
*([f', attrs={self.attrs!r}'] if self.attrs else []),
|
721
|
+
')',
|
722
|
+
])
|
723
|
+
|
724
|
+
@ta.final
|
725
|
+
class Captured:
|
726
|
+
def __init__(
|
727
|
+
self,
|
595
728
|
|
596
|
-
|
597
|
-
|
598
|
-
|
729
|
+
imports: ta.Mapping[str, 'ImportCapture.Import'],
|
730
|
+
|
731
|
+
modules: ta.Mapping[str, 'ImportCapture.Module'],
|
732
|
+
root_modules: ta.Mapping[str, 'ImportCapture.Module'],
|
733
|
+
|
734
|
+
unreferenced: ta.Sequence[str] | None,
|
735
|
+
) -> None:
|
736
|
+
self.imports = imports
|
737
|
+
|
738
|
+
self.modules = modules
|
739
|
+
self.root_modules = root_modules
|
740
|
+
|
741
|
+
self.unreferenced = unreferenced
|
599
742
|
|
600
743
|
@property
|
601
744
|
def attrs(self) -> ta.Iterator[str]:
|
602
|
-
for pi in self.imports:
|
745
|
+
for pi in self.imports.values():
|
746
|
+
yield from pi.as_
|
603
747
|
for _, a in pi.attrs:
|
604
748
|
yield a
|
605
749
|
|
750
|
+
EMPTY_CAPTURED: ta.ClassVar[Captured] = Captured(
|
751
|
+
{},
|
752
|
+
{},
|
753
|
+
{},
|
754
|
+
None,
|
755
|
+
)
|
756
|
+
|
606
757
|
#
|
607
758
|
|
608
759
|
def __init__(
|
@@ -651,7 +802,7 @@ class ImportCapture:
|
|
651
802
|
def capture(
|
652
803
|
self,
|
653
804
|
*,
|
654
|
-
unreferenced_callback: ta.Callable[[ta.
|
805
|
+
unreferenced_callback: ta.Callable[[ta.Sequence[str]], None] | None = None,
|
655
806
|
raise_unreferenced: bool = False,
|
656
807
|
) -> ta.Iterator[ta.Self]:
|
657
808
|
if self._result_ is not None:
|
@@ -659,10 +810,7 @@ class ImportCapture:
|
|
659
810
|
|
660
811
|
if self._disabled:
|
661
812
|
self._result_ = ImportCapture._Result(
|
662
|
-
ImportCapture.
|
663
|
-
[],
|
664
|
-
None,
|
665
|
-
),
|
813
|
+
ImportCapture.EMPTY_CAPTURED,
|
666
814
|
)
|
667
815
|
yield self
|
668
816
|
return
|
@@ -683,9 +831,8 @@ class ImportCapture:
|
|
683
831
|
if raise_unreferenced:
|
684
832
|
raise ImportCaptureErrors.UnreferencedImportsError(blt.unreferenced)
|
685
833
|
|
686
|
-
for
|
687
|
-
|
688
|
-
del self._mod_globals[a]
|
834
|
+
for a in blt.attrs:
|
835
|
+
del self._mod_globals[a]
|
689
836
|
|
690
837
|
self._result_ = ImportCapture._Result(
|
691
838
|
blt,
|
omlish/lang/imports/proxy.py
CHANGED
@@ -1,7 +1,3 @@
|
|
1
|
-
"""
|
2
|
-
TODO:
|
3
|
-
- if already imported just return?
|
4
|
-
"""
|
5
1
|
import contextlib
|
6
2
|
import functools
|
7
3
|
import importlib.util
|
@@ -16,6 +12,47 @@ from .capture import _new_import_capture_hook
|
|
16
12
|
##
|
17
13
|
|
18
14
|
|
15
|
+
def _translate_old_style_import_capture(
|
16
|
+
cap: ImportCapture.Captured,
|
17
|
+
) -> ta.Mapping[str, ta.Sequence[tuple[str | None, str]]]:
|
18
|
+
dct: dict[str, list[tuple[str | None, str]]] = {}
|
19
|
+
|
20
|
+
for ci in cap.imports.values():
|
21
|
+
if ci.module.kind == 'leaf':
|
22
|
+
if (p := ci.module.parent) is None:
|
23
|
+
raise NotImplementedError
|
24
|
+
|
25
|
+
if ci.attrs:
|
26
|
+
raise NotImplementedError
|
27
|
+
|
28
|
+
for a in ci.as_:
|
29
|
+
dct.setdefault(p.name, []).append(
|
30
|
+
(ci.module.base_name, a),
|
31
|
+
)
|
32
|
+
|
33
|
+
elif ci.module.kind == 'terminal':
|
34
|
+
if ci.module.children:
|
35
|
+
raise NotImplementedError
|
36
|
+
|
37
|
+
for a in ci.as_:
|
38
|
+
dct.setdefault(ci.module.name, []).append(
|
39
|
+
(None, a),
|
40
|
+
)
|
41
|
+
|
42
|
+
for sa, da in ci.attrs:
|
43
|
+
dct.setdefault(ci.module.name, []).append(
|
44
|
+
(sa, da),
|
45
|
+
)
|
46
|
+
|
47
|
+
else:
|
48
|
+
raise NotImplementedError
|
49
|
+
|
50
|
+
return dct
|
51
|
+
|
52
|
+
|
53
|
+
##
|
54
|
+
|
55
|
+
|
19
56
|
def proxy_import(
|
20
57
|
spec: str,
|
21
58
|
package: str | None = None,
|
@@ -48,7 +85,7 @@ def auto_proxy_import(
|
|
48
85
|
*,
|
49
86
|
disable: bool = False,
|
50
87
|
|
51
|
-
unreferenced_callback: ta.Callable[[ta.
|
88
|
+
unreferenced_callback: ta.Callable[[ta.Sequence[str]], None] | None = None,
|
52
89
|
raise_unreferenced: bool = False,
|
53
90
|
|
54
91
|
_stack_offset: int = 0,
|
@@ -70,10 +107,9 @@ def auto_proxy_import(
|
|
70
107
|
):
|
71
108
|
yield inst
|
72
109
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
mod_globals[ma] = proxy_import(pi.spec + (('.' + sa) if sa is not None else ''), pkg)
|
110
|
+
for spec, attrs in _translate_old_style_import_capture(inst.captured).items():
|
111
|
+
for sa, ma in attrs:
|
112
|
+
mod_globals[ma] = proxy_import(spec + (('.' + sa) if sa is not None else ''))
|
77
113
|
|
78
114
|
return inner()
|
79
115
|
|
@@ -87,7 +123,7 @@ class _ProxyInit:
|
|
87
123
|
package: str
|
88
124
|
|
89
125
|
class _Import(ta.NamedTuple):
|
90
|
-
|
126
|
+
name: str
|
91
127
|
attr: str | None
|
92
128
|
|
93
129
|
def __init__(
|
@@ -101,7 +137,6 @@ class _ProxyInit:
|
|
101
137
|
self._name_package = name_package
|
102
138
|
|
103
139
|
self._imps_by_attr: dict[str, _ProxyInit._Import] = {}
|
104
|
-
self._mods_by_spec: dict[str, ta.Any] = {}
|
105
140
|
|
106
141
|
@property
|
107
142
|
def name_package(self) -> NamePackage:
|
@@ -109,21 +144,18 @@ class _ProxyInit:
|
|
109
144
|
|
110
145
|
def add(
|
111
146
|
self,
|
112
|
-
|
147
|
+
name: str,
|
113
148
|
attrs: ta.Iterable[tuple[str | None, str]],
|
114
149
|
) -> None:
|
115
150
|
for imp_attr, as_attr in attrs:
|
116
151
|
if imp_attr is None:
|
117
|
-
self._imps_by_attr[as_attr] = self._Import(
|
152
|
+
self._imps_by_attr[as_attr] = self._Import(name, None)
|
118
153
|
self._lazy_globals.set_fn(as_attr, functools.partial(self.get, as_attr))
|
119
154
|
|
120
155
|
else:
|
121
|
-
self._imps_by_attr[as_attr] = self._Import(
|
156
|
+
self._imps_by_attr[as_attr] = self._Import(name, imp_attr)
|
122
157
|
self._lazy_globals.set_fn(as_attr, functools.partial(self.get, as_attr))
|
123
158
|
|
124
|
-
def _import_module(self, name: str) -> ta.Any:
|
125
|
-
return importlib.import_module(name, package=self._name_package.package)
|
126
|
-
|
127
159
|
def get(self, attr: str) -> ta.Any:
|
128
160
|
try:
|
129
161
|
imp = self._imps_by_attr[attr]
|
@@ -133,14 +165,19 @@ class _ProxyInit:
|
|
133
165
|
val: ta.Any
|
134
166
|
|
135
167
|
if imp.attr is None:
|
136
|
-
val =
|
168
|
+
val = importlib.import_module(imp.name)
|
169
|
+
|
170
|
+
elif imp.name == self._name_package.name:
|
171
|
+
val = importlib.import_module(f'{imp.name}.{imp.attr}')
|
137
172
|
|
138
173
|
else:
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
174
|
+
mod = __import__(
|
175
|
+
imp.name,
|
176
|
+
self._lazy_globals._globals, # noqa
|
177
|
+
{},
|
178
|
+
[imp.attr],
|
179
|
+
0,
|
180
|
+
)
|
144
181
|
|
145
182
|
val = getattr(mod, imp.attr)
|
146
183
|
|
@@ -152,6 +189,13 @@ def proxy_init(
|
|
152
189
|
spec: str,
|
153
190
|
attrs: ta.Iterable[str | tuple[str | None, str | None] | None] | None = None,
|
154
191
|
) -> None:
|
192
|
+
name = importlib.util.resolve_name(
|
193
|
+
spec,
|
194
|
+
package=init_globals['__package__'] if spec.startswith('.') else None,
|
195
|
+
)
|
196
|
+
|
197
|
+
#
|
198
|
+
|
155
199
|
if isinstance(attrs, str):
|
156
200
|
raise TypeError(attrs)
|
157
201
|
|
@@ -201,7 +245,7 @@ def proxy_init(
|
|
201
245
|
if pi.name_package != init_name_package:
|
202
246
|
raise Exception(f'Wrong init name: {pi.name_package=} != {init_name_package=}')
|
203
247
|
|
204
|
-
pi.add(
|
248
|
+
pi.add(name, al)
|
205
249
|
|
206
250
|
|
207
251
|
#
|
@@ -213,7 +257,7 @@ def auto_proxy_init(
|
|
213
257
|
disable: bool = False,
|
214
258
|
eager: bool = False,
|
215
259
|
|
216
|
-
unreferenced_callback: ta.Callable[[ta.
|
260
|
+
unreferenced_callback: ta.Callable[[ta.Sequence[str]], None] | None = None,
|
217
261
|
raise_unreferenced: bool = False,
|
218
262
|
|
219
263
|
update_exports: bool = False,
|
@@ -237,11 +281,11 @@ def auto_proxy_init(
|
|
237
281
|
):
|
238
282
|
yield inst
|
239
283
|
|
240
|
-
for
|
284
|
+
for spec, attrs in _translate_old_style_import_capture(inst.captured).items():
|
241
285
|
proxy_init(
|
242
286
|
init_globals,
|
243
|
-
|
244
|
-
|
287
|
+
spec,
|
288
|
+
attrs,
|
245
289
|
)
|
246
290
|
|
247
291
|
if eager:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: omlish
|
3
|
-
Version: 0.0.0.
|
3
|
+
Version: 0.0.0.dev459
|
4
4
|
Summary: omlish
|
5
5
|
Author: wrmsr
|
6
6
|
License-Expression: BSD-3-Clause
|
@@ -34,7 +34,7 @@ Requires-Dist: cbor2~=5.7; extra == "all"
|
|
34
34
|
Requires-Dist: cloudpickle~=3.1; extra == "all"
|
35
35
|
Requires-Dist: httpx[http2]~=0.28; extra == "all"
|
36
36
|
Requires-Dist: wrapt~=1.17; extra == "all"
|
37
|
-
Requires-Dist: cryptography~=
|
37
|
+
Requires-Dist: cryptography~=46.0; extra == "all"
|
38
38
|
Requires-Dist: sqlalchemy[asyncio]~=2.0; extra == "all"
|
39
39
|
Requires-Dist: pg8000~=1.31; extra == "all"
|
40
40
|
Requires-Dist: pymysql~=1.1; extra == "all"
|
@@ -80,7 +80,7 @@ Requires-Dist: httpx[http2]~=0.28; extra == "http"
|
|
80
80
|
Provides-Extra: misc
|
81
81
|
Requires-Dist: wrapt~=1.17; extra == "misc"
|
82
82
|
Provides-Extra: secrets
|
83
|
-
Requires-Dist: cryptography~=
|
83
|
+
Requires-Dist: cryptography~=46.0; extra == "secrets"
|
84
84
|
Provides-Extra: sqlalchemy
|
85
85
|
Requires-Dist: sqlalchemy[asyncio]~=2.0; extra == "sqlalchemy"
|
86
86
|
Provides-Extra: sqldrivers
|
@@ -1,5 +1,5 @@
|
|
1
1
|
omlish/.omlish-manifests.json,sha256=FLw7xkPiSXuImZgqSP8BwrEib2R1doSzUPLUkc-QUIA,8410
|
2
|
-
omlish/__about__.py,sha256=
|
2
|
+
omlish/__about__.py,sha256=xtL6Mzn2wu2_IspeSZ_MxiJmXyGvptjs7xRjcNyq79E,3613
|
3
3
|
omlish/__init__.py,sha256=SsyiITTuK0v74XpKV8dqNaCmjOlan1JZKrHQv5rWKPA,253
|
4
4
|
omlish/c3.py,sha256=ZNIMl1kwg3qdei4DiUrJPQe5M81S1e76N-GuNSwLBAE,8683
|
5
5
|
omlish/cached.py,sha256=MLap_p0rdGoDIMVhXVHm1tsbcWobJF0OanoodV03Ju8,542
|
@@ -205,7 +205,7 @@ omlish/diag/procfs.py,sha256=eeB3L9UpNBpAfsax3U6OczayYboPlFzOGplqlQ4gBNY,9700
|
|
205
205
|
omlish/diag/procstats.py,sha256=EJEe2Zc58ykBoTfqMXro7H52aQa_pd6uC2hsIPFceso,825
|
206
206
|
omlish/diag/ps.py,sha256=MEpMU6fbkh0bSWrOHh_okOa0JDTUSUQUVSYBdh1TGvE,1672
|
207
207
|
omlish/diag/pycharm.py,sha256=_WVmPm1E66cBtR4ukgUAaApe_3rX9Cv3sQRP5PL37P8,5013
|
208
|
-
omlish/diag/pydevd.py,sha256=
|
208
|
+
omlish/diag/pydevd.py,sha256=JEHC0hiSJxL-vVtuxKUi1BNkgUKnRC1N4alDg6JP5WQ,8363
|
209
209
|
omlish/diag/threads.py,sha256=sjtlTl41wxssoVCDkBB6xeLF-9kJEK3eA6hmSFWJSQA,3643
|
210
210
|
omlish/diag/timers.py,sha256=cxX3GgjTIjBx9DI4pzCCO5Hfqb1TM3uo22yim7kjfRU,3831
|
211
211
|
omlish/diag/_pycharm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -451,11 +451,11 @@ omlish/lang/classes/restrict.py,sha256=xHLIK20MQ_jJPQ7JVzMNhyN4Xc4eLBgrcxqDnTbeK
|
|
451
451
|
omlish/lang/classes/simple.py,sha256=3AJSs-plVg2flq4SC6I39LxP0nBaB241puv3D5YCP5I,2973
|
452
452
|
omlish/lang/classes/virtual.py,sha256=J4y-uiv1RaP2rfFeptXqQ1a4MRek0TMlAFFraO_lzhs,3397
|
453
453
|
omlish/lang/imports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
454
|
-
omlish/lang/imports/_capture.cc,sha256=
|
455
|
-
omlish/lang/imports/capture.py,sha256=
|
454
|
+
omlish/lang/imports/_capture.cc,sha256=cp-L5yFGjftfBa12sKNz0Q5Yhh54a88DH7VEN1oa5hU,2313
|
455
|
+
omlish/lang/imports/capture.py,sha256=z91F2CVcBDX4trhd2oRB5YL_d_Nu9KBTjzhy98N9YDQ,26170
|
456
456
|
omlish/lang/imports/conditional.py,sha256=R-E47QD95mMonPImWlrde3rnJrFKCCkYz71c94W05sc,1006
|
457
457
|
omlish/lang/imports/lazy.py,sha256=Eefs9hkj5surMdwgxX_Q3BOqPcox10v0sKT5rKIQknc,808
|
458
|
-
omlish/lang/imports/proxy.py,sha256=
|
458
|
+
omlish/lang/imports/proxy.py,sha256=tIIChKvl5TCZp_vg6D7WR7NxnN0J-L-bqjp0DYvgUuA,7562
|
459
459
|
omlish/lang/imports/resolving.py,sha256=DeRarn35Fryg5JhVhy8wbiC9lvr58AnllI9B_reswUE,2085
|
460
460
|
omlish/lang/imports/traversal.py,sha256=pbFQIa880NGjSfcLsno2vE_G41_CLwDHb-7gWg2J3BI,2855
|
461
461
|
omlish/lifecycles/__init__.py,sha256=zOuvV4pErPwxcKUSgshmME2Duw9GrjwckpNmW3FPKng,810
|
@@ -826,9 +826,9 @@ omlish/typedvalues/marshal.py,sha256=2xqX6JllhtGpmeYkU7C-qzgU__0x-vd6CzYbAsocQlc
|
|
826
826
|
omlish/typedvalues/of_.py,sha256=UXkxSj504WI2UrFlqdZJbu2hyDwBhL7XVrc2qdR02GQ,1309
|
827
827
|
omlish/typedvalues/reflect.py,sha256=PAvKW6T4cW7u--iX80w3HWwZUS3SmIZ2_lQjT65uAyk,1026
|
828
828
|
omlish/typedvalues/values.py,sha256=ym46I-q2QJ_6l4UlERqv3yj87R-kp8nCKMRph0xQ3UA,1307
|
829
|
-
omlish-0.0.0.
|
830
|
-
omlish-0.0.0.
|
831
|
-
omlish-0.0.0.
|
832
|
-
omlish-0.0.0.
|
833
|
-
omlish-0.0.0.
|
834
|
-
omlish-0.0.0.
|
829
|
+
omlish-0.0.0.dev459.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
830
|
+
omlish-0.0.0.dev459.dist-info/METADATA,sha256=vA7Ker_93at2wRMI8zaoBhaoAnE8BmZqvBEDDGy9gEg,19003
|
831
|
+
omlish-0.0.0.dev459.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
832
|
+
omlish-0.0.0.dev459.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
|
833
|
+
omlish-0.0.0.dev459.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
|
834
|
+
omlish-0.0.0.dev459.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|