omlish 0.0.0.dev6__py3-none-any.whl → 0.0.0.dev7__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.

Files changed (106) hide show
  1. omlish/__about__.py +109 -5
  2. omlish/__init__.py +0 -8
  3. omlish/asyncs/__init__.py +0 -9
  4. omlish/asyncs/anyio.py +40 -0
  5. omlish/bootstrap.py +737 -0
  6. omlish/check.py +1 -1
  7. omlish/collections/__init__.py +4 -0
  8. omlish/collections/exceptions.py +2 -0
  9. omlish/collections/utils.py +38 -9
  10. omlish/configs/strings.py +2 -0
  11. omlish/dataclasses/__init__.py +7 -0
  12. omlish/dataclasses/impl/descriptors.py +95 -0
  13. omlish/dataclasses/impl/reflect.py +1 -1
  14. omlish/dataclasses/utils.py +23 -0
  15. omlish/{lang/datetimes.py → datetimes.py} +8 -4
  16. omlish/diag/procfs.py +1 -1
  17. omlish/diag/threads.py +131 -48
  18. omlish/docker.py +16 -1
  19. omlish/fnpairs.py +0 -4
  20. omlish/{serde → formats}/dotenv.py +3 -0
  21. omlish/{serde → formats}/yaml.py +2 -2
  22. omlish/graphs/trees.py +1 -1
  23. omlish/http/consts.py +6 -0
  24. omlish/http/sessions.py +2 -2
  25. omlish/inject/__init__.py +4 -0
  26. omlish/inject/binder.py +3 -3
  27. omlish/inject/elements.py +1 -1
  28. omlish/inject/impl/injector.py +57 -27
  29. omlish/inject/impl/origins.py +2 -0
  30. omlish/inject/origins.py +3 -0
  31. omlish/inject/utils.py +18 -0
  32. omlish/iterators.py +69 -2
  33. omlish/lang/__init__.py +16 -7
  34. omlish/lang/classes/restrict.py +10 -0
  35. omlish/lang/contextmanagers.py +1 -1
  36. omlish/lang/descriptors.py +3 -3
  37. omlish/lang/imports.py +67 -0
  38. omlish/lang/iterables.py +40 -0
  39. omlish/lang/maybes.py +3 -0
  40. omlish/lang/objects.py +38 -0
  41. omlish/lang/strings.py +25 -0
  42. omlish/lang/sys.py +9 -0
  43. omlish/lang/typing.py +37 -0
  44. omlish/lite/__init__.py +1 -0
  45. omlish/lite/cached.py +18 -0
  46. omlish/lite/check.py +29 -0
  47. omlish/lite/contextmanagers.py +18 -0
  48. omlish/lite/json.py +30 -0
  49. omlish/lite/logs.py +52 -0
  50. omlish/lite/marshal.py +316 -0
  51. omlish/lite/reflect.py +49 -0
  52. omlish/lite/runtime.py +18 -0
  53. omlish/lite/secrets.py +19 -0
  54. omlish/lite/strings.py +25 -0
  55. omlish/lite/subprocesses.py +112 -0
  56. omlish/logs/configs.py +15 -2
  57. omlish/logs/formatters.py +7 -2
  58. omlish/marshal/__init__.py +28 -0
  59. omlish/marshal/any.py +5 -5
  60. omlish/marshal/base.py +27 -11
  61. omlish/marshal/base64.py +24 -9
  62. omlish/marshal/dataclasses.py +34 -28
  63. omlish/marshal/datetimes.py +74 -18
  64. omlish/marshal/enums.py +14 -8
  65. omlish/marshal/exceptions.py +11 -1
  66. omlish/marshal/factories.py +59 -74
  67. omlish/marshal/forbidden.py +35 -0
  68. omlish/marshal/global_.py +11 -4
  69. omlish/marshal/iterables.py +21 -24
  70. omlish/marshal/mappings.py +23 -26
  71. omlish/marshal/numbers.py +51 -0
  72. omlish/marshal/optionals.py +11 -12
  73. omlish/marshal/polymorphism.py +86 -21
  74. omlish/marshal/primitives.py +4 -5
  75. omlish/marshal/standard.py +13 -8
  76. omlish/marshal/uuids.py +4 -5
  77. omlish/matchfns.py +218 -0
  78. omlish/os.py +64 -0
  79. omlish/reflect/__init__.py +39 -0
  80. omlish/reflect/isinstance.py +38 -0
  81. omlish/reflect/ops.py +84 -0
  82. omlish/reflect/subst.py +110 -0
  83. omlish/reflect/types.py +275 -0
  84. omlish/secrets/__init__.py +18 -2
  85. omlish/secrets/crypto.py +132 -0
  86. omlish/secrets/marshal.py +36 -7
  87. omlish/secrets/openssl.py +207 -0
  88. omlish/secrets/secrets.py +260 -8
  89. omlish/secrets/subprocesses.py +42 -0
  90. omlish/sql/dbs.py +6 -5
  91. omlish/sql/exprs.py +12 -0
  92. omlish/sql/secrets.py +10 -0
  93. omlish/term.py +1 -1
  94. omlish/testing/pytest/plugins/switches.py +54 -19
  95. omlish/text/glyphsplit.py +5 -0
  96. omlish-0.0.0.dev7.dist-info/METADATA +50 -0
  97. {omlish-0.0.0.dev6.dist-info → omlish-0.0.0.dev7.dist-info}/RECORD +104 -76
  98. {omlish-0.0.0.dev6.dist-info → omlish-0.0.0.dev7.dist-info}/WHEEL +1 -1
  99. omlish/reflect.py +0 -470
  100. omlish-0.0.0.dev6.dist-info/METADATA +0 -34
  101. /omlish/{asyncs/futures.py → concurrent.py} +0 -0
  102. /omlish/{serde → formats}/__init__.py +0 -0
  103. /omlish/{serde → formats}/json.py +0 -0
  104. /omlish/{serde → formats}/props.py +0 -0
  105. {omlish-0.0.0.dev6.dist-info → omlish-0.0.0.dev7.dist-info}/LICENSE +0 -0
  106. {omlish-0.0.0.dev6.dist-info → omlish-0.0.0.dev7.dist-info}/top_level.txt +0 -0
omlish/reflect.py DELETED
@@ -1,470 +0,0 @@
1
- """
2
- TODO:
3
- - visitor / transformer
4
- - uniform collection isinstance - items() for mappings, iter() for other
5
- - also check instance type in isinstance not just items lol
6
- - ta.Generic in mro causing trouble - omit? no longer 1:1
7
- - cache this shit, esp generic_mro shit
8
- - cache __hash__ in Generic/Union
9
- """
10
- import collections.abc
11
- import dataclasses as dc
12
- import types
13
- import typing as ta
14
-
15
- from . import c3
16
- from . import lang
17
-
18
-
19
- if ta.TYPE_CHECKING:
20
- from .collections import cache
21
- else:
22
- cache = lang.proxy_import('.collections.cache', __package__)
23
-
24
-
25
- _NoneType = types.NoneType # type: ignore
26
-
27
- _NONE_TYPE_FROZENSET: frozenset['Type'] = frozenset([_NoneType])
28
-
29
-
30
- _GenericAlias = ta._GenericAlias # type: ignore # noqa
31
- _CallableGenericAlias = ta._CallableGenericAlias # type: ignore # noqa
32
- _SpecialGenericAlias = ta._SpecialGenericAlias # type: ignore # noqa
33
- _UnionGenericAlias = ta._UnionGenericAlias # type: ignore # noqa
34
- _AnnotatedAlias = ta._AnnotatedAlias # type: ignore # noqa
35
-
36
-
37
- ##
38
-
39
-
40
- class _Special(ta.NamedTuple):
41
- name: str
42
- alias: _SpecialGenericAlias # type: ignore
43
- origin: type
44
- nparams: int
45
-
46
-
47
- _KNOWN_SPECIALS = [
48
- _Special(
49
- v._name, # noqa
50
- v,
51
- v.__origin__,
52
- v._nparams, # noqa
53
- )
54
- for v in ta.__dict__.values()
55
- if isinstance(v, _SpecialGenericAlias)
56
- ]
57
-
58
- _KNOWN_SPECIALS_BY_NAME = {s.name: s for s in _KNOWN_SPECIALS}
59
- _KNOWN_SPECIALS_BY_ALIAS = {s.alias: s for s in _KNOWN_SPECIALS}
60
- _KNOWN_SPECIALS_BY_ORIGIN = {s.origin: s for s in _KNOWN_SPECIALS}
61
-
62
- _MAX_KNOWN_SPECIAL_TYPE_VARS = 16
63
-
64
- _KNOWN_SPECIAL_TYPE_VARS = tuple(
65
- ta.TypeVar(f'_{i}') # noqa
66
- for i in range(_MAX_KNOWN_SPECIAL_TYPE_VARS)
67
- )
68
-
69
-
70
- ##
71
-
72
-
73
- def get_params(obj: ta.Any) -> tuple[ta.TypeVar, ...]:
74
- if isinstance(obj, type):
75
- if issubclass(obj, ta.Generic): # type: ignore
76
- return obj.__dict__.get('__parameters__', ()) # noqa
77
-
78
- if (ks := _KNOWN_SPECIALS_BY_ORIGIN.get(obj)) is not None:
79
- return _KNOWN_SPECIAL_TYPE_VARS[:ks.nparams]
80
-
81
- oty = type(obj)
82
-
83
- if (
84
- oty is _GenericAlias or
85
- oty is ta.GenericAlias # type: ignore # noqa
86
- ):
87
- return obj.__dict__.get('__parameters__', ()) # noqa
88
-
89
- if oty is _CallableGenericAlias:
90
- raise NotImplementedError('get_params not yet implemented for typing.Callable')
91
-
92
- raise TypeError(obj)
93
-
94
-
95
- def is_union_type(cls: ta.Any) -> bool:
96
- if hasattr(ta, 'UnionType'):
97
- return ta.get_origin(cls) in {ta.Union, getattr(ta, 'UnionType')}
98
-
99
- else:
100
- return ta.get_origin(cls) in {ta.Union}
101
-
102
-
103
- def get_orig_class(obj: ta.Any) -> ta.Any:
104
- return obj.__orig_class__ # noqa
105
-
106
-
107
- ##
108
-
109
-
110
- Type = ta.Union[
111
- type,
112
- ta.TypeVar,
113
- 'Union',
114
- 'Generic',
115
- 'NewType',
116
- 'Annotated',
117
- ]
118
-
119
-
120
- class Union(ta.NamedTuple):
121
- args: frozenset[Type]
122
-
123
- @property
124
- def is_optional(self) -> bool:
125
- return _NoneType in self.args
126
-
127
- def without_none(self) -> Type:
128
- if _NoneType not in self.args:
129
- return self
130
- rem = self.args - _NONE_TYPE_FROZENSET
131
- if len(rem) == 1:
132
- return next(iter(rem))
133
- return Union(rem)
134
-
135
-
136
- @dc.dataclass(frozen=True)
137
- class Generic:
138
- cls: type
139
- args: tuple[Type, ...] # map[int, V] = (int, V) | map[T, T] = (T, T)
140
-
141
- params: tuple[ta.TypeVar, ...] = dc.field(compare=False, repr=False) # map[int, V] = (_0, _1) | map[T, T] = (_0, _1) # noqa
142
- # params2: tuple[ta.TypeVar, ...] # map[int, V] = (V,) | map[T, T] = (T,)
143
-
144
- obj: ta.Any = dc.field(compare=False, repr=False)
145
-
146
- # def __post_init__(self) -> None:
147
- # if not isinstance(self.cls, type):
148
- # raise TypeError(self.cls)
149
-
150
- def full_eq(self, other: 'Generic') -> bool:
151
- return (
152
- self.cls == other.cls and
153
- self.args == other.args and
154
- self.params == other.params and
155
- self.obj == other.obj
156
- )
157
-
158
-
159
- class NewType(ta.NamedTuple):
160
- obj: ta.Any
161
-
162
-
163
- @dc.dataclass(frozen=True)
164
- class Annotated:
165
- ty: Type
166
- md: ta.Sequence[ta.Any]
167
-
168
- obj: ta.Any = dc.field(compare=False, repr=False)
169
-
170
-
171
- TYPES: tuple[type, ...] = (
172
- type,
173
- ta.TypeVar,
174
- Union,
175
- Generic,
176
- NewType,
177
- Annotated,
178
- )
179
-
180
-
181
- ##
182
-
183
-
184
- def is_type(obj: ta.Any) -> bool:
185
- if isinstance(obj, (Union, Generic, ta.TypeVar, NewType)): # noqa
186
- return True
187
-
188
- oty = type(obj)
189
-
190
- return (
191
- oty is _UnionGenericAlias or oty is types.UnionType or # noqa
192
-
193
- isinstance(obj, ta.NewType) or # noqa
194
-
195
- (
196
- oty is _GenericAlias or
197
- oty is ta.GenericAlias or # type: ignore # noqa
198
- oty is _CallableGenericAlias
199
- ) or
200
-
201
- isinstance(obj, type) or
202
-
203
- isinstance(obj, _SpecialGenericAlias)
204
- )
205
-
206
-
207
- def type_(obj: ta.Any) -> Type:
208
- if isinstance(obj, (Union, Generic, ta.TypeVar, NewType)): # noqa
209
- return obj
210
-
211
- oty = type(obj)
212
-
213
- if oty is _UnionGenericAlias or oty is types.UnionType:
214
- return Union(frozenset(type_(a) for a in ta.get_args(obj)))
215
-
216
- if isinstance(obj, ta.NewType): # noqa
217
- return NewType(obj)
218
-
219
- if (
220
- oty is _GenericAlias or
221
- oty is ta.GenericAlias or # type: ignore # noqa
222
- oty is _CallableGenericAlias
223
- ):
224
- origin = ta.get_origin(obj)
225
- args = ta.get_args(obj)
226
- if oty is _CallableGenericAlias:
227
- p, r = args
228
- if p is Ellipsis or isinstance(p, ta.ParamSpec):
229
- raise TypeError(f'Callable argument not yet supported for {obj=}')
230
- args = (*p, r)
231
- params = _KNOWN_SPECIAL_TYPE_VARS[:len(args)]
232
- elif origin is ta.Generic:
233
- params = args
234
- else:
235
- params = get_params(origin)
236
- if len(args) != len(params):
237
- raise TypeError(f'Mismatched {args=} and {params=} for {obj=}')
238
- return Generic(
239
- origin,
240
- tuple(type_(a) for a in args),
241
- params,
242
- obj,
243
- )
244
-
245
- if isinstance(obj, type):
246
- if issubclass(obj, ta.Generic): # type: ignore
247
- params = get_params(obj)
248
- return Generic(
249
- obj,
250
- params,
251
- params,
252
- obj,
253
- )
254
- return obj
255
-
256
- if isinstance(obj, _SpecialGenericAlias):
257
- if (ks := _KNOWN_SPECIALS_BY_ALIAS.get(obj)) is not None:
258
- params = _KNOWN_SPECIAL_TYPE_VARS[:ks.nparams]
259
- return Generic(
260
- ks.origin,
261
- params,
262
- params,
263
- obj,
264
- )
265
-
266
- if isinstance(obj, _AnnotatedAlias):
267
- o = ta.get_args(obj)[0]
268
- return Annotated(type_(o), md=obj.__metadata__, obj=obj)
269
-
270
- raise TypeError(obj)
271
-
272
-
273
- ##
274
-
275
-
276
- def strip_objs(ty: Type) -> Type:
277
- if isinstance(ty, (type, ta.TypeVar, NewType)):
278
- return ty
279
-
280
- if isinstance(ty, Union):
281
- return Union(frozenset(map(strip_objs, ty.args)))
282
-
283
- if isinstance(ty, Generic):
284
- return Generic(ty.cls, tuple(map(strip_objs, ty.args)), ty.params, None)
285
-
286
- if isinstance(ty, Annotated):
287
- return Annotated(strip_objs(ty.ty), ty.md, None)
288
-
289
- raise TypeError(ty)
290
-
291
-
292
- def strip_annotations(ty: Type) -> Type:
293
- if isinstance(ty, (type, ta.TypeVar, NewType)):
294
- return ty
295
-
296
- if isinstance(ty, Union):
297
- return Union(frozenset(map(strip_annotations, ty.args)))
298
-
299
- if isinstance(ty, Generic):
300
- return Generic(ty.cls, tuple(map(strip_annotations, ty.args)), ty.params, ty.obj)
301
-
302
- if isinstance(ty, Annotated):
303
- return strip_annotations(ty.ty)
304
-
305
- raise TypeError(ty)
306
-
307
-
308
- def types_equivalent(l: Type, r: Type) -> bool:
309
- if isinstance(l, Generic) and isinstance(r, Generic):
310
- return l.cls == r.cls and l.args == r.args
311
-
312
- return l == r
313
-
314
-
315
- def get_underlying(nt: NewType) -> Type:
316
- return type_(nt.obj.__supertype__) # noqa
317
-
318
-
319
- def get_concrete_type(ty: Type) -> type | None:
320
- if isinstance(ty, type):
321
- return ty
322
-
323
- if isinstance(ty, Generic):
324
- return ty.cls
325
-
326
- if isinstance(ty, NewType):
327
- return get_concrete_type(get_underlying(ty))
328
-
329
- if isinstance(ty, (Union, ta.TypeVar)):
330
- return None
331
-
332
- raise TypeError(ty)
333
-
334
-
335
- def get_type_var_replacements(ty: Type) -> ta.Mapping[ta.TypeVar, Type]:
336
- if isinstance(ty, Generic):
337
- return dict(zip(ty.params, ty.args))
338
-
339
- return {}
340
-
341
-
342
- def to_annotation(ty: Type) -> ta.Any:
343
- if isinstance(ty, Generic):
344
- return ty.obj if ty.obj is not None else ty.cls
345
-
346
- if isinstance(ty, Union):
347
- return ta.Union[*tuple(to_annotation(e) for e in ty.args)]
348
-
349
- if isinstance(ty, (type, ta.TypeVar, NewType)):
350
- return ty
351
-
352
- raise TypeError(ty)
353
-
354
-
355
- def replace_type_vars(
356
- ty: Type,
357
- rpl: ta.Mapping[ta.TypeVar, Type],
358
- *,
359
- update_aliases: bool = False,
360
- ) -> Type:
361
- def rec(cur):
362
- if isinstance(cur, type):
363
- return cur
364
-
365
- if isinstance(cur, NewType):
366
- return cur
367
-
368
- if isinstance(cur, Generic):
369
- args = tuple(rec(a) for a in cur.args)
370
- if update_aliases:
371
- obj = cur.obj
372
- if (ops := get_params(obj)):
373
- nargs = [to_annotation(rpl[p]) for p in ops]
374
- if ta.get_origin(obj) is ta.Generic:
375
- # FIXME: None? filter_typing_generic in get_generic_bases?
376
- pass
377
- else:
378
- obj = cur.obj[*nargs]
379
- else:
380
- obj = None
381
- return dc.replace(cur, args=args, obj=obj)
382
-
383
- if isinstance(cur, Union):
384
- return Union(frozenset(rec(e) for e in cur.args))
385
-
386
- if isinstance(cur, ta.TypeVar):
387
- return rpl[cur]
388
-
389
- raise TypeError(cur)
390
-
391
- return rec(ty)
392
-
393
-
394
- class GenericSubstitution:
395
- def __init__(
396
- self,
397
- *,
398
- update_aliases: bool = False,
399
- cache_size: int = 0, # FIXME: ta.Generic isn't weakrefable..
400
- ) -> None:
401
- super().__init__()
402
-
403
- self._update_aliases = update_aliases
404
-
405
- if cache_size > 0:
406
- self.get_generic_bases = cache.cache(weak_keys=True, max_size=cache_size)(self.get_generic_bases) # type: ignore # noqa
407
- self.generic_mro = cache.cache(weak_keys=True, max_size=cache_size)(self.generic_mro) # type: ignore
408
-
409
- def get_generic_bases(self, ty: Type) -> tuple[Type, ...]:
410
- if (cty := get_concrete_type(ty)) is not None:
411
- rpl = get_type_var_replacements(ty)
412
- ret: list[Type] = []
413
- for b in types.get_original_bases(cty):
414
- bty = type_(b)
415
- if isinstance(bty, Generic) and isinstance(b, type):
416
- # FIXME: throws away relative types, but can't use original vars as they're class-contextual
417
- bty = type_(b[*((ta.Any,) * len(bty.params))]) # type: ignore
418
- rty = replace_type_vars(bty, rpl, update_aliases=self._update_aliases)
419
- ret.append(rty)
420
- return tuple(ret)
421
- return ()
422
-
423
- def generic_mro(self, obj: ta.Any) -> list[Type]:
424
- mro = c3.mro(
425
- type_(obj),
426
- get_bases=lambda t: self.get_generic_bases(t),
427
- is_subclass=lambda l, r: issubclass(get_concrete_type(l), get_concrete_type(r)), # type: ignore
428
- )
429
- return [ty for ty in mro if get_concrete_type(ty) is not ta.Generic]
430
-
431
-
432
- DEFAULT_GENERIC_SUBSTITUTION = GenericSubstitution()
433
-
434
- get_generic_bases = DEFAULT_GENERIC_SUBSTITUTION.get_generic_bases
435
- generic_mro = DEFAULT_GENERIC_SUBSTITUTION.generic_mro
436
-
437
- ALIAS_UPDATING_GENERIC_SUBSTITUTION = GenericSubstitution(update_aliases=True)
438
-
439
-
440
- ##
441
-
442
-
443
- KNOWN_GENERICS: ta.AbstractSet[type] = frozenset([
444
- collections.abc.Mapping,
445
- collections.abc.Sequence,
446
- collections.abc.Set,
447
- ])
448
-
449
-
450
- def isinstance_of(rfl: Type) -> ta.Callable[[ta.Any], bool]:
451
- if isinstance(rfl, type):
452
- return lambda o: isinstance(o, rfl)
453
-
454
- if isinstance(rfl, NewType):
455
- return isinstance_of(get_underlying(rfl))
456
-
457
- if isinstance(rfl, Union):
458
- fns = [isinstance_of(a) for a in rfl.args]
459
- return lambda o: any(fn(o) for fn in fns)
460
-
461
- if isinstance(rfl, Generic):
462
- if rfl.cls in (collections.abc.Sequence, collections.abc.Set):
463
- [efn] = map(isinstance_of, rfl.args)
464
- return lambda o: isinstance(o, rfl.cls) and all(efn(e) for e in o) # type: ignore
465
-
466
- if rfl.cls == collections.abc.Mapping:
467
- kfn, vfn = map(isinstance_of, rfl.args)
468
- return lambda o: isinstance(o, rfl.cls) and all(kfn(k) and vfn(v) for k, v in o.items()) # type: ignore
469
-
470
- raise TypeError(rfl)
@@ -1,34 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: omlish
3
- Version: 0.0.0.dev6
4
- Summary: omlish
5
- Author: wrmsr
6
- License: BSD-3-Clause
7
- Project-URL: source, https://github.com/wrmsr/omlish
8
- Classifier: License :: OSI Approved :: BSD License
9
- Classifier: Development Status :: 2 - Pre-Alpha
10
- Classifier: Intended Audience :: Developers
11
- Classifier: Operating System :: OS Independent
12
- Requires-Python: >=3.12
13
- License-File: LICENSE
14
- Provides-Extra: async
15
- Requires-Dist: anyio ; extra == 'async'
16
- Provides-Extra: http
17
- Requires-Dist: httpx ; extra == 'http'
18
- Provides-Extra: server
19
- Requires-Dist: h11 ; extra == 'server'
20
- Requires-Dist: h2 ; extra == 'server'
21
- Requires-Dist: priority ; extra == 'server'
22
- Requires-Dist: wsproto ; extra == 'server'
23
- Provides-Extra: sql
24
- Requires-Dist: sqlalchemy ; extra == 'sql'
25
- Provides-Extra: test
26
- Requires-Dist: pytest ; extra == 'test'
27
- Provides-Extra: trio
28
- Requires-Dist: trio ; extra == 'trio'
29
- Requires-Dist: trio-asyncio ; extra == 'trio'
30
- Provides-Extra: wrapt
31
- Requires-Dist: wrapt ; extra == 'wrapt'
32
- Provides-Extra: yaml
33
- Requires-Dist: pyyaml ; extra == 'yaml'
34
-
File without changes
File without changes
File without changes
File without changes