omlish 0.0.0.dev23__py3-none-any.whl → 0.0.0.dev25__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 +16 -4
- omlish/_manifests.json +1 -0
- omlish/bootstrap/diag.py +2 -2
- omlish/check.py +202 -24
- omlish/collections/__init__.py +2 -2
- omlish/collections/utils.py +3 -3
- omlish/concurrent/threadlets.py +5 -0
- omlish/dataclasses/__init__.py +1 -0
- omlish/dataclasses/impl/LICENSE +279 -0
- omlish/dataclasses/impl/init.py +10 -2
- omlish/dataclasses/impl/metadata.py +3 -3
- omlish/dataclasses/impl/reflect.py +1 -1
- omlish/dataclasses/utils.py +16 -3
- omlish/diag/pycharm.py +69 -10
- omlish/docker.py +16 -11
- omlish/genmachine.py +2 -1
- omlish/graphs/trees.py +1 -1
- omlish/lang/__init__.py +14 -1
- omlish/lang/cached.py +5 -2
- omlish/lang/descriptors.py +33 -16
- omlish/lang/resources.py +60 -0
- omlish/lang/typing.py +32 -0
- omlish/lite/logs.py +133 -4
- omlish/logs/__init__.py +17 -2
- omlish/logs/configs.py +13 -1
- omlish/logs/formatters.py +0 -1
- omlish/marshal/__init__.py +2 -0
- omlish/marshal/helpers.py +27 -0
- omlish/specs/jsonschema/keywords/base.py +2 -2
- omlish/specs/jsonschema/keywords/parse.py +1 -1
- omlish/specs/jsonschema/schemas/draft202012/metaschema.json +58 -0
- omlish/specs/jsonschema/schemas/draft202012/vocabularies/applicator.json +48 -0
- omlish/specs/jsonschema/schemas/draft202012/vocabularies/content.json +17 -0
- omlish/specs/jsonschema/schemas/draft202012/vocabularies/core.json +51 -0
- omlish/specs/jsonschema/schemas/draft202012/vocabularies/format-annotation.json +14 -0
- omlish/specs/jsonschema/schemas/draft202012/vocabularies/format-assertion.json +14 -0
- omlish/specs/jsonschema/schemas/draft202012/vocabularies/format.json +14 -0
- omlish/specs/jsonschema/schemas/draft202012/vocabularies/meta-data.json +37 -0
- omlish/specs/jsonschema/schemas/draft202012/vocabularies/unevaluated.json +15 -0
- omlish/specs/jsonschema/schemas/draft202012/vocabularies/validation.json +98 -0
- omlish/stats.py +1 -0
- {omlish-0.0.0.dev23.dist-info → omlish-0.0.0.dev25.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev23.dist-info → omlish-0.0.0.dev25.dist-info}/RECORD +46 -33
- {omlish-0.0.0.dev23.dist-info → omlish-0.0.0.dev25.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev23.dist-info → omlish-0.0.0.dev25.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev23.dist-info → omlish-0.0.0.dev25.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.dev25'
|
2
|
+
__revision__ = '123812c0156cbb06af42b6e2ee3b7912d5bf5fc8'
|
3
3
|
|
4
4
|
|
5
5
|
#
|
@@ -111,8 +111,6 @@ class SetuptoolsBase:
|
|
111
111
|
'global-exclude **/conftest.py',
|
112
112
|
]
|
113
113
|
|
114
|
-
include_package_data = False
|
115
|
-
|
116
114
|
find_packages = {
|
117
115
|
'exclude': [
|
118
116
|
'*.tests',
|
@@ -120,6 +118,20 @@ class SetuptoolsBase:
|
|
120
118
|
],
|
121
119
|
}
|
122
120
|
|
121
|
+
package_data = {
|
122
|
+
'*': [
|
123
|
+
'*.c',
|
124
|
+
'*.cc',
|
125
|
+
'*.h',
|
126
|
+
|
127
|
+
'*.json',
|
128
|
+
|
129
|
+
'*.sql',
|
130
|
+
|
131
|
+
'LICENSE',
|
132
|
+
],
|
133
|
+
}
|
134
|
+
|
123
135
|
|
124
136
|
class Setuptools(SetuptoolsBase):
|
125
137
|
find_packages = {
|
omlish/_manifests.json
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
[]
|
omlish/bootstrap/diag.py
CHANGED
@@ -166,12 +166,12 @@ class PycharmBootstrap(SimpleBootstrap['PycharmBootstrap.Config']):
|
|
166
166
|
class Config(Bootstrap.Config):
|
167
167
|
debug_host: ta.Optional[str] = None
|
168
168
|
debug_port: ta.Optional[int] = None
|
169
|
-
|
169
|
+
version: ta.Optional[str] = None
|
170
170
|
|
171
171
|
def run(self) -> None:
|
172
172
|
if self._config.debug_port is not None:
|
173
173
|
diagpc.pycharm_remote_debugger_attach(
|
174
174
|
self._config.debug_host,
|
175
175
|
self._config.debug_port,
|
176
|
-
version=self._config.
|
176
|
+
version=self._config.version,
|
177
177
|
)
|
omlish/check.py
CHANGED
@@ -75,6 +75,9 @@ def enable_args_rendering() -> bool:
|
|
75
75
|
return True
|
76
76
|
|
77
77
|
|
78
|
+
enable_args_rendering()
|
79
|
+
|
80
|
+
|
78
81
|
#
|
79
82
|
|
80
83
|
|
@@ -142,7 +145,14 @@ def _unpack_isinstance_spec(spec: ta.Any) -> tuple:
|
|
142
145
|
|
143
146
|
def isinstance(v: ta.Any, spec: type[T] | tuple, msg: Message = None) -> T: # noqa
|
144
147
|
if not _isinstance(v, _unpack_isinstance_spec(spec)):
|
145
|
-
_raise(
|
148
|
+
_raise(
|
149
|
+
TypeError,
|
150
|
+
'Must be instance',
|
151
|
+
msg,
|
152
|
+
_Args(v, spec),
|
153
|
+
render_fmt='not isinstance(%s, %s)',
|
154
|
+
)
|
155
|
+
|
146
156
|
return v
|
147
157
|
|
148
158
|
|
@@ -155,7 +165,13 @@ def of_isinstance(spec: type[T] | tuple, msg: Message = None) -> ta.Callable[[ta
|
|
155
165
|
|
156
166
|
def cast(v: ta.Any, cls: type[T], msg: Message = None) -> T: # noqa
|
157
167
|
if not _isinstance(v, cls):
|
158
|
-
_raise(
|
168
|
+
_raise(
|
169
|
+
TypeError,
|
170
|
+
'Must be instance',
|
171
|
+
msg,
|
172
|
+
_Args(v, cls),
|
173
|
+
)
|
174
|
+
|
159
175
|
return v
|
160
176
|
|
161
177
|
|
@@ -168,7 +184,14 @@ def of_cast(cls: type[T], msg: Message = None) -> ta.Callable[[T], T]:
|
|
168
184
|
|
169
185
|
def not_isinstance(v: T, spec: ta.Any, msg: Message = None) -> T: # noqa
|
170
186
|
if _isinstance(v, _unpack_isinstance_spec(spec)):
|
171
|
-
_raise(
|
187
|
+
_raise(
|
188
|
+
TypeError,
|
189
|
+
'Must not be instance',
|
190
|
+
msg,
|
191
|
+
_Args(v, spec),
|
192
|
+
render_fmt='isinstance(%s, %s)',
|
193
|
+
)
|
194
|
+
|
172
195
|
return v
|
173
196
|
|
174
197
|
|
@@ -184,13 +207,27 @@ def of_not_isinstance(spec: ta.Any, msg: Message = None) -> ta.Callable[[T], T]:
|
|
184
207
|
|
185
208
|
def issubclass(v: type[T], spec: ta.Any, msg: Message = None) -> type[T]: # noqa
|
186
209
|
if not _issubclass(v, spec):
|
187
|
-
_raise(
|
210
|
+
_raise(
|
211
|
+
TypeError,
|
212
|
+
'Must be subclass',
|
213
|
+
msg,
|
214
|
+
_Args(v, spec),
|
215
|
+
render_fmt='not issubclass(%s, %s)',
|
216
|
+
)
|
217
|
+
|
188
218
|
return v
|
189
219
|
|
190
220
|
|
191
221
|
def not_issubclass(v: type[T], spec: ta.Any, msg: Message = None) -> type[T]: # noqa
|
192
222
|
if _issubclass(v, spec):
|
193
|
-
_raise(
|
223
|
+
_raise(
|
224
|
+
TypeError,
|
225
|
+
'Must not be subclass',
|
226
|
+
msg,
|
227
|
+
_Args(v, spec),
|
228
|
+
render_fmt='issubclass(%s, %s)',
|
229
|
+
)
|
230
|
+
|
194
231
|
return v
|
195
232
|
|
196
233
|
|
@@ -199,19 +236,40 @@ def not_issubclass(v: type[T], spec: ta.Any, msg: Message = None) -> type[T]: #
|
|
199
236
|
|
200
237
|
def in_(v: T, c: ta.Container[T], msg: Message = None) -> T:
|
201
238
|
if v not in c:
|
202
|
-
_raise(
|
239
|
+
_raise(
|
240
|
+
ValueError,
|
241
|
+
'Must be in',
|
242
|
+
msg,
|
243
|
+
_Args(v, c),
|
244
|
+
render_fmt='%s not in %s',
|
245
|
+
)
|
246
|
+
|
203
247
|
return v
|
204
248
|
|
205
249
|
|
206
250
|
def not_in(v: T, c: ta.Container[T], msg: Message = None) -> T:
|
207
251
|
if v in c:
|
208
|
-
_raise(
|
252
|
+
_raise(
|
253
|
+
ValueError,
|
254
|
+
'Must not be in',
|
255
|
+
msg,
|
256
|
+
_Args(v, c),
|
257
|
+
render_fmt='%s in %s',
|
258
|
+
)
|
259
|
+
|
209
260
|
return v
|
210
261
|
|
211
262
|
|
212
263
|
def empty(v: SizedT, msg: Message = None) -> SizedT:
|
213
264
|
if len(v) != 0:
|
214
|
-
_raise(
|
265
|
+
_raise(
|
266
|
+
ValueError,
|
267
|
+
'Must be empty',
|
268
|
+
msg,
|
269
|
+
_Args(v),
|
270
|
+
render_fmt='%s',
|
271
|
+
)
|
272
|
+
|
215
273
|
return v
|
216
274
|
|
217
275
|
|
@@ -222,20 +280,40 @@ def iterempty(v: ta.Iterable[T], msg: Message = None) -> ta.Iterable[T]:
|
|
222
280
|
except StopIteration:
|
223
281
|
pass
|
224
282
|
else:
|
225
|
-
_raise(
|
283
|
+
_raise(
|
284
|
+
ValueError,
|
285
|
+
'Must be empty',
|
286
|
+
msg,
|
287
|
+
_Args(v),
|
288
|
+
render_fmt='%s',
|
289
|
+
)
|
290
|
+
|
226
291
|
return v
|
227
292
|
|
228
293
|
|
229
294
|
def not_empty(v: SizedT, msg: Message = None) -> SizedT:
|
230
295
|
if len(v) == 0:
|
231
|
-
_raise(
|
296
|
+
_raise(
|
297
|
+
ValueError,
|
298
|
+
'Must not be empty',
|
299
|
+
msg,
|
300
|
+
_Args(v),
|
301
|
+
render_fmt='%s',
|
302
|
+
)
|
303
|
+
|
232
304
|
return v
|
233
305
|
|
234
306
|
|
235
307
|
def unique(it: ta.Iterable[T], msg: Message = None) -> ta.Iterable[T]:
|
236
308
|
dupes = [e for e, c in collections.Counter(it).items() if c > 1]
|
237
309
|
if dupes:
|
238
|
-
_raise(
|
310
|
+
_raise(
|
311
|
+
ValueError,
|
312
|
+
'Must be unique',
|
313
|
+
msg,
|
314
|
+
_Args(it, dupes),
|
315
|
+
)
|
316
|
+
|
239
317
|
return it
|
240
318
|
|
241
319
|
|
@@ -243,9 +321,15 @@ def single(obj: ta.Iterable[T], message: Message = None) -> T:
|
|
243
321
|
try:
|
244
322
|
[value] = obj
|
245
323
|
except ValueError:
|
246
|
-
_raise(
|
247
|
-
|
248
|
-
|
324
|
+
_raise(
|
325
|
+
ValueError,
|
326
|
+
'Must be single',
|
327
|
+
message,
|
328
|
+
_Args(obj),
|
329
|
+
render_fmt='%s',
|
330
|
+
)
|
331
|
+
|
332
|
+
return value
|
249
333
|
|
250
334
|
|
251
335
|
def optional_single(obj: ta.Iterable[T], message: Message = None) -> T | None:
|
@@ -254,11 +338,19 @@ def optional_single(obj: ta.Iterable[T], message: Message = None) -> T | None:
|
|
254
338
|
value = next(it)
|
255
339
|
except StopIteration:
|
256
340
|
return None
|
341
|
+
|
257
342
|
try:
|
258
343
|
next(it)
|
259
344
|
except StopIteration:
|
260
345
|
return value # noqa
|
261
|
-
|
346
|
+
|
347
|
+
_raise(
|
348
|
+
ValueError,
|
349
|
+
'Must be empty or single',
|
350
|
+
message,
|
351
|
+
_Args(obj),
|
352
|
+
render_fmt='%s',
|
353
|
+
)
|
262
354
|
|
263
355
|
|
264
356
|
##
|
@@ -266,12 +358,25 @@ def optional_single(obj: ta.Iterable[T], message: Message = None) -> T | None:
|
|
266
358
|
|
267
359
|
def none(v: ta.Any, msg: Message = None) -> None:
|
268
360
|
if v is not None:
|
269
|
-
_raise(
|
361
|
+
_raise(
|
362
|
+
ValueError,
|
363
|
+
'Must be None',
|
364
|
+
msg,
|
365
|
+
_Args(v),
|
366
|
+
render_fmt='%s',
|
367
|
+
)
|
270
368
|
|
271
369
|
|
272
370
|
def not_none(v: T | None, msg: Message = None) -> T:
|
273
371
|
if v is None:
|
274
|
-
_raise(
|
372
|
+
_raise(
|
373
|
+
ValueError,
|
374
|
+
'Must not be None',
|
375
|
+
msg,
|
376
|
+
_Args(v),
|
377
|
+
render_fmt='%s',
|
378
|
+
)
|
379
|
+
|
275
380
|
return v
|
276
381
|
|
277
382
|
|
@@ -280,42 +385,115 @@ def not_none(v: T | None, msg: Message = None) -> T:
|
|
280
385
|
|
281
386
|
def equal(v: T, o: ta.Any, msg: Message = None) -> T:
|
282
387
|
if o != v:
|
283
|
-
_raise(
|
388
|
+
_raise(
|
389
|
+
ValueError,
|
390
|
+
'Must be equal',
|
391
|
+
msg,
|
392
|
+
_Args(v, o),
|
393
|
+
render_fmt='%s != %s',
|
394
|
+
)
|
395
|
+
|
284
396
|
return v
|
285
397
|
|
286
398
|
|
287
399
|
def is_(v: T, o: ta.Any, msg: Message = None) -> T:
|
288
400
|
if o is not v:
|
289
|
-
_raise(
|
401
|
+
_raise(
|
402
|
+
ValueError,
|
403
|
+
'Must be the same',
|
404
|
+
msg,
|
405
|
+
_Args(v, o),
|
406
|
+
render_fmt='%s is not %s',
|
407
|
+
)
|
408
|
+
|
290
409
|
return v
|
291
410
|
|
292
411
|
|
293
412
|
def is_not(v: T, o: ta.Any, msg: Message = None) -> T:
|
294
413
|
if o is v:
|
295
|
-
_raise(
|
414
|
+
_raise(
|
415
|
+
ValueError,
|
416
|
+
'Must not be the same',
|
417
|
+
msg,
|
418
|
+
_Args(v, o),
|
419
|
+
render_fmt='%s is %s',
|
420
|
+
)
|
421
|
+
|
296
422
|
return v
|
297
423
|
|
298
424
|
|
299
425
|
def callable(v: T, msg: Message = None) -> T: # noqa
|
300
426
|
if not _callable(v):
|
301
|
-
_raise(
|
427
|
+
_raise(
|
428
|
+
TypeError,
|
429
|
+
'Must be callable',
|
430
|
+
msg,
|
431
|
+
_Args(v),
|
432
|
+
render_fmt='%s',
|
433
|
+
)
|
434
|
+
|
302
435
|
return v # type: ignore
|
303
436
|
|
304
437
|
|
305
438
|
def non_empty_str(v: str | None, msg: Message = None) -> str:
|
306
439
|
if not _isinstance(v, str) or not v:
|
307
|
-
_raise(
|
440
|
+
_raise(
|
441
|
+
ValueError,
|
442
|
+
'Must be non-empty str',
|
443
|
+
msg,
|
444
|
+
_Args(v),
|
445
|
+
render_fmt='%s',
|
446
|
+
)
|
447
|
+
|
308
448
|
return v
|
309
449
|
|
310
450
|
|
451
|
+
def replacing(expected: ta.Any, old: ta.Any, new: T, msg: Message = None) -> T:
|
452
|
+
if old != expected:
|
453
|
+
_raise(
|
454
|
+
ValueError,
|
455
|
+
'Must be replacing',
|
456
|
+
msg,
|
457
|
+
_Args(expected, old, new),
|
458
|
+
render_fmt='%s -> %s -> %s',
|
459
|
+
)
|
460
|
+
|
461
|
+
return new
|
462
|
+
|
463
|
+
|
464
|
+
def replacing_none(old: ta.Any, new: T, msg: Message = None) -> T:
|
465
|
+
if old is not None:
|
466
|
+
_raise(
|
467
|
+
ValueError,
|
468
|
+
'Must be replacing None',
|
469
|
+
msg,
|
470
|
+
_Args(old, new),
|
471
|
+
render_fmt='%s -> %s',
|
472
|
+
)
|
473
|
+
|
474
|
+
return new
|
475
|
+
|
476
|
+
|
311
477
|
##
|
312
478
|
|
313
479
|
|
314
480
|
def arg(v: bool, msg: Message = None) -> None:
|
315
481
|
if not v:
|
316
|
-
_raise(
|
482
|
+
_raise(
|
483
|
+
RuntimeError,
|
484
|
+
'Argument condition not met',
|
485
|
+
msg,
|
486
|
+
_Args(v),
|
487
|
+
render_fmt='%s',
|
488
|
+
)
|
317
489
|
|
318
490
|
|
319
491
|
def state(v: bool, msg: Message = None) -> None:
|
320
492
|
if not v:
|
321
|
-
_raise(
|
493
|
+
_raise(
|
494
|
+
RuntimeError,
|
495
|
+
'State condition not met',
|
496
|
+
msg,
|
497
|
+
_Args(v),
|
498
|
+
render_fmt='%s',
|
499
|
+
)
|
omlish/collections/__init__.py
CHANGED
omlish/collections/utils.py
CHANGED
@@ -72,7 +72,7 @@ def unique(
|
|
72
72
|
return ret
|
73
73
|
|
74
74
|
|
75
|
-
def
|
75
|
+
def make_map(
|
76
76
|
kvs: ta.Iterable[tuple[K, V]],
|
77
77
|
*,
|
78
78
|
identity: bool = False,
|
@@ -88,14 +88,14 @@ def unique_map(
|
|
88
88
|
return d
|
89
89
|
|
90
90
|
|
91
|
-
def
|
91
|
+
def make_map_by(
|
92
92
|
fn: ta.Callable[[V], K],
|
93
93
|
vs: ta.Iterable[V],
|
94
94
|
*,
|
95
95
|
identity: bool = False,
|
96
96
|
strict: bool = False,
|
97
97
|
) -> ta.MutableMapping[K, V]:
|
98
|
-
return
|
98
|
+
return make_map(
|
99
99
|
((fn(v), v) for v in vs),
|
100
100
|
identity=identity,
|
101
101
|
strict=strict,
|
omlish/concurrent/threadlets.py
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
"""
|
2
|
+
An abstraction over greenlet's api. Greenlet doesn't currently support nogil but its functionality is needed for async
|
3
|
+
bridge code (both here and in sqlalchemy). This can be implemented with real threads at the expense of overhead, but
|
4
|
+
this code is only intended to be used in already fairly heavy situations (bootstrap, db calls).
|
5
|
+
"""
|
1
6
|
import abc
|
2
7
|
import dataclasses as dc
|
3
8
|
import typing as ta
|