omlish 0.0.0.dev141__py3-none-any.whl → 0.0.0.dev143__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
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"