omlish 0.0.0.dev141__py3-none-any.whl → 0.0.0.dev143__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.
Files changed (38) hide show
  1. omlish/__about__.py +4 -2
  2. omlish/check.py +2 -0
  3. omlish/collections/coerce.py +1 -0
  4. omlish/docker/__init__.py +2 -1
  5. omlish/docker/helpers.py +0 -6
  6. omlish/funcs/pairs.py +2 -2
  7. omlish/io/compress/__init__.py +9 -0
  8. omlish/io/compress/abc.py +4 -4
  9. omlish/io/compress/adapters.py +12 -11
  10. omlish/io/compress/base.py +24 -0
  11. omlish/io/compress/brotli.py +33 -0
  12. omlish/io/compress/bz2.py +26 -21
  13. omlish/io/compress/gzip.py +43 -10
  14. omlish/io/compress/lz4.py +77 -0
  15. omlish/io/compress/lzma.py +51 -16
  16. omlish/io/compress/snappy.py +20 -0
  17. omlish/io/compress/zlib.py +60 -0
  18. omlish/io/compress/zstd.py +30 -0
  19. omlish/io/generators/__init__.py +53 -0
  20. omlish/io/generators/consts.py +1 -0
  21. omlish/io/generators/direct.py +13 -0
  22. omlish/io/generators/readers.py +15 -9
  23. omlish/io/generators/stepped.py +85 -14
  24. omlish/io/pyio.py +5 -2
  25. omlish/lang/__init__.py +1 -0
  26. omlish/lang/iterables.py +20 -0
  27. omlish/lite/docker.py +3 -0
  28. omlish/lite/marshal.py +213 -141
  29. omlish/lite/pycharm.py +48 -0
  30. omlish/lite/subprocesses.py +13 -0
  31. omlish/logs/abc.py +0 -1
  32. {omlish-0.0.0.dev141.dist-info → omlish-0.0.0.dev143.dist-info}/METADATA +3 -1
  33. {omlish-0.0.0.dev141.dist-info → omlish-0.0.0.dev143.dist-info}/RECORD +37 -29
  34. omlish/io/compress/types.py +0 -29
  35. {omlish-0.0.0.dev141.dist-info → omlish-0.0.0.dev143.dist-info}/LICENSE +0 -0
  36. {omlish-0.0.0.dev141.dist-info → omlish-0.0.0.dev143.dist-info}/WHEEL +0 -0
  37. {omlish-0.0.0.dev141.dist-info → omlish-0.0.0.dev143.dist-info}/entry_points.txt +0 -0
  38. {omlish-0.0.0.dev141.dist-info → omlish-0.0.0.dev143.dist-info}/top_level.txt +0 -0
omlish/lite/marshal.py CHANGED
@@ -32,21 +32,26 @@ T = ta.TypeVar('T')
32
32
  ##
33
33
 
34
34
 
35
+ @dc.dataclass(frozen=True)
36
+ class ObjMarshalOptions:
37
+ raw_bytes: bool = False
38
+
39
+
35
40
  class ObjMarshaler(abc.ABC):
36
41
  @abc.abstractmethod
37
- def marshal(self, o: ta.Any) -> ta.Any:
42
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
38
43
  raise NotImplementedError
39
44
 
40
45
  @abc.abstractmethod
41
- def unmarshal(self, o: ta.Any) -> ta.Any:
46
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
42
47
  raise NotImplementedError
43
48
 
44
49
 
45
50
  class NopObjMarshaler(ObjMarshaler):
46
- def marshal(self, o: ta.Any) -> ta.Any:
51
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
47
52
  return o
48
53
 
49
- def unmarshal(self, o: ta.Any) -> ta.Any:
54
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
50
55
  return o
51
56
 
52
57
 
@@ -54,29 +59,29 @@ class NopObjMarshaler(ObjMarshaler):
54
59
  class ProxyObjMarshaler(ObjMarshaler):
55
60
  m: ta.Optional[ObjMarshaler] = None
56
61
 
57
- def marshal(self, o: ta.Any) -> ta.Any:
58
- return check_not_none(self.m).marshal(o)
62
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
63
+ return check_not_none(self.m).marshal(o, opts)
59
64
 
60
- def unmarshal(self, o: ta.Any) -> ta.Any:
61
- return check_not_none(self.m).unmarshal(o)
65
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
66
+ return check_not_none(self.m).unmarshal(o, opts)
62
67
 
63
68
 
64
69
  @dc.dataclass(frozen=True)
65
70
  class CastObjMarshaler(ObjMarshaler):
66
71
  ty: type
67
72
 
68
- def marshal(self, o: ta.Any) -> ta.Any:
73
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
69
74
  return o
70
75
 
71
- def unmarshal(self, o: ta.Any) -> ta.Any:
76
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
72
77
  return self.ty(o)
73
78
 
74
79
 
75
80
  class DynamicObjMarshaler(ObjMarshaler):
76
- def marshal(self, o: ta.Any) -> ta.Any:
81
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
77
82
  return marshal_obj(o)
78
83
 
79
- def unmarshal(self, o: ta.Any) -> ta.Any:
84
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
80
85
  return o
81
86
 
82
87
 
@@ -84,21 +89,36 @@ class DynamicObjMarshaler(ObjMarshaler):
84
89
  class Base64ObjMarshaler(ObjMarshaler):
85
90
  ty: type
86
91
 
87
- def marshal(self, o: ta.Any) -> ta.Any:
92
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
88
93
  return base64.b64encode(o).decode('ascii')
89
94
 
90
- def unmarshal(self, o: ta.Any) -> ta.Any:
95
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
91
96
  return self.ty(base64.b64decode(o))
92
97
 
93
98
 
99
+ @dc.dataclass(frozen=True)
100
+ class BytesSwitchedObjMarshaler(ObjMarshaler):
101
+ m: ObjMarshaler
102
+
103
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
104
+ if opts.raw_bytes:
105
+ return o
106
+ return self.m.marshal(o, opts)
107
+
108
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
109
+ if opts.raw_bytes:
110
+ return o
111
+ return self.m.unmarshal(o, opts)
112
+
113
+
94
114
  @dc.dataclass(frozen=True)
95
115
  class EnumObjMarshaler(ObjMarshaler):
96
116
  ty: type
97
117
 
98
- def marshal(self, o: ta.Any) -> ta.Any:
118
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
99
119
  return o.name
100
120
 
101
- def unmarshal(self, o: ta.Any) -> ta.Any:
121
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
102
122
  return self.ty.__members__[o] # type: ignore
103
123
 
104
124
 
@@ -106,15 +126,15 @@ class EnumObjMarshaler(ObjMarshaler):
106
126
  class OptionalObjMarshaler(ObjMarshaler):
107
127
  item: ObjMarshaler
108
128
 
109
- def marshal(self, o: ta.Any) -> ta.Any:
129
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
110
130
  if o is None:
111
131
  return None
112
- return self.item.marshal(o)
132
+ return self.item.marshal(o, opts)
113
133
 
114
- def unmarshal(self, o: ta.Any) -> ta.Any:
134
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
115
135
  if o is None:
116
136
  return None
117
- return self.item.unmarshal(o)
137
+ return self.item.unmarshal(o, opts)
118
138
 
119
139
 
120
140
  @dc.dataclass(frozen=True)
@@ -123,11 +143,11 @@ class MappingObjMarshaler(ObjMarshaler):
123
143
  km: ObjMarshaler
124
144
  vm: ObjMarshaler
125
145
 
126
- def marshal(self, o: ta.Any) -> ta.Any:
127
- return {self.km.marshal(k): self.vm.marshal(v) for k, v in o.items()}
146
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
147
+ return {self.km.marshal(k, opts): self.vm.marshal(v, opts) for k, v in o.items()}
128
148
 
129
- def unmarshal(self, o: ta.Any) -> ta.Any:
130
- return self.ty((self.km.unmarshal(k), self.vm.unmarshal(v)) for k, v in o.items())
149
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
150
+ return self.ty((self.km.unmarshal(k, opts), self.vm.unmarshal(v, opts)) for k, v in o.items())
131
151
 
132
152
 
133
153
  @dc.dataclass(frozen=True)
@@ -135,11 +155,11 @@ class IterableObjMarshaler(ObjMarshaler):
135
155
  ty: type
136
156
  item: ObjMarshaler
137
157
 
138
- def marshal(self, o: ta.Any) -> ta.Any:
139
- return [self.item.marshal(e) for e in o]
158
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
159
+ return [self.item.marshal(e, opts) for e in o]
140
160
 
141
- def unmarshal(self, o: ta.Any) -> ta.Any:
142
- return self.ty(self.item.unmarshal(e) for e in o)
161
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
162
+ return self.ty(self.item.unmarshal(e, opts) for e in o)
143
163
 
144
164
 
145
165
  @dc.dataclass(frozen=True)
@@ -148,11 +168,11 @@ class DataclassObjMarshaler(ObjMarshaler):
148
168
  fs: ta.Mapping[str, ObjMarshaler]
149
169
  nonstrict: bool = False
150
170
 
151
- def marshal(self, o: ta.Any) -> ta.Any:
152
- return {k: m.marshal(getattr(o, k)) for k, m in self.fs.items()}
171
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
172
+ return {k: m.marshal(getattr(o, k), opts) for k, m in self.fs.items()}
153
173
 
154
- def unmarshal(self, o: ta.Any) -> ta.Any:
155
- return self.ty(**{k: self.fs[k].unmarshal(v) for k, v in o.items() if not self.nonstrict or k in self.fs})
174
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
175
+ return self.ty(**{k: self.fs[k].unmarshal(v, opts) for k, v in o.items() if not self.nonstrict or k in self.fs})
156
176
 
157
177
 
158
178
  @dc.dataclass(frozen=True)
@@ -172,50 +192,50 @@ class PolymorphicObjMarshaler(ObjMarshaler):
172
192
  {i.tag: i for i in impls},
173
193
  )
174
194
 
175
- def marshal(self, o: ta.Any) -> ta.Any:
195
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
176
196
  impl = self.impls_by_ty[type(o)]
177
- return {impl.tag: impl.m.marshal(o)}
197
+ return {impl.tag: impl.m.marshal(o, opts)}
178
198
 
179
- def unmarshal(self, o: ta.Any) -> ta.Any:
199
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
180
200
  [(t, v)] = o.items()
181
201
  impl = self.impls_by_tag[t]
182
- return impl.m.unmarshal(v)
202
+ return impl.m.unmarshal(v, opts)
183
203
 
184
204
 
185
205
  @dc.dataclass(frozen=True)
186
206
  class DatetimeObjMarshaler(ObjMarshaler):
187
207
  ty: type
188
208
 
189
- def marshal(self, o: ta.Any) -> ta.Any:
209
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
190
210
  return o.isoformat()
191
211
 
192
- def unmarshal(self, o: ta.Any) -> ta.Any:
212
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
193
213
  return self.ty.fromisoformat(o) # type: ignore
194
214
 
195
215
 
196
216
  class DecimalObjMarshaler(ObjMarshaler):
197
- def marshal(self, o: ta.Any) -> ta.Any:
217
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
198
218
  return str(check_isinstance(o, decimal.Decimal))
199
219
 
200
- def unmarshal(self, v: ta.Any) -> ta.Any:
220
+ def unmarshal(self, v: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
201
221
  return decimal.Decimal(check_isinstance(v, str))
202
222
 
203
223
 
204
224
  class FractionObjMarshaler(ObjMarshaler):
205
- def marshal(self, o: ta.Any) -> ta.Any:
225
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
206
226
  fr = check_isinstance(o, fractions.Fraction)
207
227
  return [fr.numerator, fr.denominator]
208
228
 
209
- def unmarshal(self, v: ta.Any) -> ta.Any:
229
+ def unmarshal(self, v: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
210
230
  num, denom = check_isinstance(v, list)
211
231
  return fractions.Fraction(num, denom)
212
232
 
213
233
 
214
234
  class UuidObjMarshaler(ObjMarshaler):
215
- def marshal(self, o: ta.Any) -> ta.Any:
235
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
216
236
  return str(o)
217
237
 
218
- def unmarshal(self, o: ta.Any) -> ta.Any:
238
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
219
239
  return uuid.UUID(o)
220
240
 
221
241
 
@@ -225,7 +245,7 @@ class UuidObjMarshaler(ObjMarshaler):
225
245
  _DEFAULT_OBJ_MARSHALERS: ta.Dict[ta.Any, ObjMarshaler] = {
226
246
  **{t: NopObjMarshaler() for t in (type(None),)},
227
247
  **{t: CastObjMarshaler(t) for t in (int, float, str, bool)},
228
- **{t: Base64ObjMarshaler(t) for t in (bytes, bytearray)},
248
+ **{t: BytesSwitchedObjMarshaler(Base64ObjMarshaler(t)) for t in (bytes, bytearray)},
229
249
  **{t: IterableObjMarshaler(t, DynamicObjMarshaler()) for t in (list, tuple, set, frozenset)},
230
250
  **{t: MappingObjMarshaler(t, DynamicObjMarshaler(), DynamicObjMarshaler()) for t in (dict,)},
231
251
 
@@ -251,117 +271,169 @@ _OBJ_MARSHALER_GENERIC_ITERABLE_TYPES: ta.Dict[ta.Any, type] = {
251
271
  }
252
272
 
253
273
 
254
- def _make_obj_marshaler(
255
- ty: ta.Any,
256
- rec: ta.Callable[[ta.Any], ObjMarshaler],
257
- *,
258
- nonstrict_dataclasses: bool = False,
259
- ) -> ObjMarshaler:
260
- if isinstance(ty, type):
261
- if abc.ABC in ty.__bases__:
262
- return PolymorphicObjMarshaler.of([ # type: ignore
263
- PolymorphicObjMarshaler.Impl(
264
- ity,
265
- ity.__qualname__,
266
- rec(ity),
267
- )
268
- for ity in deep_subclasses(ty)
269
- if abc.ABC not in ity.__bases__
270
- ])
271
-
272
- if issubclass(ty, enum.Enum):
273
- return EnumObjMarshaler(ty)
274
-
275
- if dc.is_dataclass(ty):
276
- return DataclassObjMarshaler(
277
- ty,
278
- {f.name: rec(f.type) for f in dc.fields(ty)},
279
- nonstrict=nonstrict_dataclasses,
280
- )
281
-
282
- if is_generic_alias(ty):
283
- try:
284
- mt = _OBJ_MARSHALER_GENERIC_MAPPING_TYPES[ta.get_origin(ty)]
285
- except KeyError:
286
- pass
287
- else:
288
- k, v = ta.get_args(ty)
289
- return MappingObjMarshaler(mt, rec(k), rec(v))
290
-
291
- try:
292
- st = _OBJ_MARSHALER_GENERIC_ITERABLE_TYPES[ta.get_origin(ty)]
293
- except KeyError:
294
- pass
295
- else:
296
- [e] = ta.get_args(ty)
297
- return IterableObjMarshaler(st, rec(e))
298
-
299
- if is_union_alias(ty):
300
- return OptionalObjMarshaler(rec(get_optional_alias_arg(ty)))
301
-
302
- raise TypeError(ty)
303
-
304
-
305
274
  ##
306
275
 
307
276
 
308
- _OBJ_MARSHALERS_LOCK = threading.RLock()
309
-
310
- _OBJ_MARSHALERS: ta.Dict[ta.Any, ObjMarshaler] = dict(_DEFAULT_OBJ_MARSHALERS)
311
-
312
- _OBJ_MARSHALER_PROXIES: ta.Dict[ta.Any, ProxyObjMarshaler] = {}
313
-
314
-
315
- def register_opj_marshaler(ty: ta.Any, m: ObjMarshaler) -> None:
316
- with _OBJ_MARSHALERS_LOCK:
317
- if ty in _OBJ_MARSHALERS:
318
- raise KeyError(ty)
319
- _OBJ_MARSHALERS[ty] = m
320
-
277
+ class ObjMarshalerManager:
278
+ def __init__(
279
+ self,
280
+ *,
281
+ default_options: ObjMarshalOptions = ObjMarshalOptions(),
282
+
283
+ default_obj_marshalers: ta.Dict[ta.Any, ObjMarshaler] = _DEFAULT_OBJ_MARSHALERS, # noqa
284
+ generic_mapping_types: ta.Dict[ta.Any, type] = _OBJ_MARSHALER_GENERIC_MAPPING_TYPES, # noqa
285
+ generic_iterable_types: ta.Dict[ta.Any, type] = _OBJ_MARSHALER_GENERIC_ITERABLE_TYPES, # noqa
286
+ ) -> None:
287
+ super().__init__()
288
+
289
+ self._default_options = default_options
290
+
291
+ self._obj_marshalers = dict(default_obj_marshalers)
292
+ self._generic_mapping_types = generic_mapping_types
293
+ self._generic_iterable_types = generic_iterable_types
294
+
295
+ self._lock = threading.RLock()
296
+ self._marshalers: ta.Dict[ta.Any, ObjMarshaler] = dict(_DEFAULT_OBJ_MARSHALERS)
297
+ self._proxies: ta.Dict[ta.Any, ProxyObjMarshaler] = {}
298
+
299
+ #
300
+
301
+ def make_obj_marshaler(
302
+ self,
303
+ ty: ta.Any,
304
+ rec: ta.Callable[[ta.Any], ObjMarshaler],
305
+ *,
306
+ nonstrict_dataclasses: bool = False,
307
+ ) -> ObjMarshaler:
308
+ if isinstance(ty, type):
309
+ if abc.ABC in ty.__bases__:
310
+ return PolymorphicObjMarshaler.of([ # type: ignore
311
+ PolymorphicObjMarshaler.Impl(
312
+ ity,
313
+ ity.__qualname__,
314
+ rec(ity),
315
+ )
316
+ for ity in deep_subclasses(ty)
317
+ if abc.ABC not in ity.__bases__
318
+ ])
319
+
320
+ if issubclass(ty, enum.Enum):
321
+ return EnumObjMarshaler(ty)
322
+
323
+ if dc.is_dataclass(ty):
324
+ return DataclassObjMarshaler(
325
+ ty,
326
+ {f.name: rec(f.type) for f in dc.fields(ty)},
327
+ nonstrict=nonstrict_dataclasses,
328
+ )
321
329
 
322
- def get_obj_marshaler(
323
- ty: ta.Any,
324
- *,
325
- no_cache: bool = False,
326
- **kwargs: ta.Any,
327
- ) -> ObjMarshaler:
328
- with _OBJ_MARSHALERS_LOCK:
329
- if not no_cache:
330
+ if is_generic_alias(ty):
330
331
  try:
331
- return _OBJ_MARSHALERS[ty]
332
+ mt = self._generic_mapping_types[ta.get_origin(ty)]
332
333
  except KeyError:
333
334
  pass
335
+ else:
336
+ k, v = ta.get_args(ty)
337
+ return MappingObjMarshaler(mt, rec(k), rec(v))
334
338
 
335
- try:
336
- return _OBJ_MARSHALER_PROXIES[ty]
337
- except KeyError:
338
- pass
339
+ try:
340
+ st = self._generic_iterable_types[ta.get_origin(ty)]
341
+ except KeyError:
342
+ pass
343
+ else:
344
+ [e] = ta.get_args(ty)
345
+ return IterableObjMarshaler(st, rec(e))
346
+
347
+ if is_union_alias(ty):
348
+ return OptionalObjMarshaler(rec(get_optional_alias_arg(ty)))
349
+
350
+ raise TypeError(ty)
351
+
352
+ #
353
+
354
+ def register_opj_marshaler(self, ty: ta.Any, m: ObjMarshaler) -> None:
355
+ with self._lock:
356
+ if ty in self._obj_marshalers:
357
+ raise KeyError(ty)
358
+ self._obj_marshalers[ty] = m
359
+
360
+ def get_obj_marshaler(
361
+ self,
362
+ ty: ta.Any,
363
+ *,
364
+ no_cache: bool = False,
365
+ **kwargs: ta.Any,
366
+ ) -> ObjMarshaler:
367
+ with self._lock:
368
+ if not no_cache:
369
+ try:
370
+ return self._obj_marshalers[ty]
371
+ except KeyError:
372
+ pass
339
373
 
340
- rec = functools.partial(
341
- get_obj_marshaler,
342
- no_cache=no_cache,
343
- **kwargs,
344
- )
374
+ try:
375
+ return self._proxies[ty]
376
+ except KeyError:
377
+ pass
345
378
 
346
- p = ProxyObjMarshaler()
347
- _OBJ_MARSHALER_PROXIES[ty] = p
348
- try:
349
- m = _make_obj_marshaler(ty, rec, **kwargs)
350
- finally:
351
- del _OBJ_MARSHALER_PROXIES[ty]
352
- p.m = m
379
+ rec = functools.partial(
380
+ self.get_obj_marshaler,
381
+ no_cache=no_cache,
382
+ **kwargs,
383
+ )
353
384
 
354
- if not no_cache:
355
- _OBJ_MARSHALERS[ty] = m
356
- return m
385
+ p = ProxyObjMarshaler()
386
+ self._proxies[ty] = p
387
+ try:
388
+ m = self.make_obj_marshaler(ty, rec, **kwargs)
389
+ finally:
390
+ del self._proxies[ty]
391
+ p.m = m
392
+
393
+ if not no_cache:
394
+ self._obj_marshalers[ty] = m
395
+ return m
396
+
397
+ #
398
+
399
+ def marshal_obj(
400
+ self,
401
+ o: ta.Any,
402
+ ty: ta.Any = None,
403
+ opts: ta.Optional[ObjMarshalOptions] = None,
404
+ ) -> ta.Any:
405
+ m = self.get_obj_marshaler(ty if ty is not None else type(o))
406
+ return m.marshal(o, opts or self._default_options)
407
+
408
+ def unmarshal_obj(
409
+ self,
410
+ o: ta.Any,
411
+ ty: ta.Union[ta.Type[T], ta.Any],
412
+ opts: ta.Optional[ObjMarshalOptions] = None,
413
+ ) -> T:
414
+ m = self.get_obj_marshaler(ty)
415
+ return m.unmarshal(o, opts or self._default_options)
416
+
417
+ def roundtrip_obj(
418
+ self,
419
+ o: ta.Any,
420
+ ty: ta.Any = None,
421
+ opts: ta.Optional[ObjMarshalOptions] = None,
422
+ ) -> ta.Any:
423
+ if ty is None:
424
+ ty = type(o)
425
+ m: ta.Any = self.marshal_obj(o, ty, opts)
426
+ u: ta.Any = self.unmarshal_obj(m, ty, opts)
427
+ return u
357
428
 
358
429
 
359
430
  ##
360
431
 
361
432
 
362
- def marshal_obj(o: ta.Any, ty: ta.Any = None) -> ta.Any:
363
- return get_obj_marshaler(ty if ty is not None else type(o)).marshal(o)
433
+ OBJ_MARSHALER_MANAGER = ObjMarshalerManager()
364
434
 
435
+ register_opj_marshaler = OBJ_MARSHALER_MANAGER.register_opj_marshaler
436
+ get_obj_marshaler = OBJ_MARSHALER_MANAGER.get_obj_marshaler
365
437
 
366
- def unmarshal_obj(o: ta.Any, ty: ta.Union[ta.Type[T], ta.Any]) -> T:
367
- return get_obj_marshaler(ty).unmarshal(o)
438
+ marshal_obj = OBJ_MARSHALER_MANAGER.marshal_obj
439
+ unmarshal_obj = OBJ_MARSHALER_MANAGER.unmarshal_obj
omlish/lite/pycharm.py ADDED
@@ -0,0 +1,48 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import dataclasses as dc
3
+ import typing as ta
4
+
5
+
6
+ DEFAULT_PYCHARM_VERSION = '242.23726.102'
7
+
8
+
9
+ @dc.dataclass(frozen=True)
10
+ class PycharmRemoteDebug:
11
+ port: int
12
+ host: ta.Optional[str] = 'localhost'
13
+ install_version: ta.Optional[str] = DEFAULT_PYCHARM_VERSION
14
+
15
+
16
+ def pycharm_debug_connect(prd: PycharmRemoteDebug) -> None:
17
+ if prd.install_version is not None:
18
+ import subprocess
19
+ import sys
20
+ subprocess.check_call([
21
+ sys.executable,
22
+ '-mpip',
23
+ 'install',
24
+ f'pydevd-pycharm~={prd.install_version}',
25
+ ])
26
+
27
+ pydevd_pycharm = __import__('pydevd_pycharm') # noqa
28
+ pydevd_pycharm.settrace(
29
+ prd.host,
30
+ port=prd.port,
31
+ stdoutToServer=True,
32
+ stderrToServer=True,
33
+ )
34
+
35
+
36
+ def pycharm_debug_preamble(prd: PycharmRemoteDebug) -> str:
37
+ import inspect
38
+ import textwrap
39
+
40
+ return textwrap.dedent(f"""
41
+ {inspect.getsource(pycharm_debug_connect)}
42
+
43
+ pycharm_debug_connect(PycharmRemoteDebug(
44
+ {prd.port!r},
45
+ host={prd.host!r},
46
+ install_version={prd.install_version!r},
47
+ ))
48
+ """)
@@ -10,6 +10,19 @@ from .logs import log
10
10
  from .runtime import is_debugger_attached
11
11
 
12
12
 
13
+ SubprocessChannelOption = ta.Literal['pipe', 'stdout', 'devnull']
14
+
15
+
16
+ ##
17
+
18
+
19
+ SUBPROCESS_CHANNEL_OPTION_VALUES: ta.Mapping[SubprocessChannelOption, int] = {
20
+ 'pipe': subprocess.PIPE,
21
+ 'stdout': subprocess.STDOUT,
22
+ 'devnull': subprocess.DEVNULL,
23
+ }
24
+
25
+
13
26
  ##
14
27
 
15
28
 
omlish/logs/abc.py CHANGED
@@ -1,7 +1,6 @@
1
1
  # ruff: noqa: A002
2
2
  # ruff: noqa: N802
3
3
  # ruff: noqa: N815
4
-
5
4
  import types
6
5
  import typing as ta
7
6
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: omlish
3
- Version: 0.0.0.dev141
3
+ Version: 0.0.0.dev143
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -21,6 +21,7 @@ Requires-Dist: trio-asyncio~=0.15; extra == "all"
21
21
  Requires-Dist: lz4~=4.3; extra == "all"
22
22
  Requires-Dist: python-snappy~=0.7; extra == "all"
23
23
  Requires-Dist: zstandard~=0.23; extra == "all"
24
+ Requires-Dist: brotli~=1.1; extra == "all"
24
25
  Requires-Dist: asttokens~=3.0; extra == "all"
25
26
  Requires-Dist: executing~=2.1; extra == "all"
26
27
  Requires-Dist: psutil~=6.0; extra == "all"
@@ -60,6 +61,7 @@ Provides-Extra: compress
60
61
  Requires-Dist: lz4~=4.3; extra == "compress"
61
62
  Requires-Dist: python-snappy~=0.7; extra == "compress"
62
63
  Requires-Dist: zstandard~=0.23; extra == "compress"
64
+ Requires-Dist: brotli~=1.1; extra == "compress"
63
65
  Provides-Extra: diag
64
66
  Requires-Dist: asttokens~=3.0; extra == "diag"
65
67
  Requires-Dist: executing~=2.1; extra == "diag"