ominfra 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 (31) hide show
  1. ominfra/manage/__init__.py +10 -0
  2. ominfra/manage/__main__.py +4 -0
  3. ominfra/manage/bootstrap.py +11 -0
  4. ominfra/manage/bootstrap_.py +18 -0
  5. ominfra/manage/commands/base.py +133 -1
  6. ominfra/manage/commands/execution.py +23 -0
  7. ominfra/manage/commands/inject.py +122 -0
  8. ominfra/manage/commands/marshal.py +26 -0
  9. ominfra/manage/commands/subprocess.py +18 -17
  10. ominfra/manage/config.py +10 -0
  11. ominfra/manage/inject.py +55 -0
  12. ominfra/manage/main.py +54 -132
  13. ominfra/manage/marshal.py +12 -0
  14. ominfra/manage/remote/__init__.py +0 -0
  15. ominfra/manage/remote/channel.py +52 -0
  16. ominfra/manage/remote/config.py +12 -0
  17. ominfra/manage/remote/execution.py +193 -0
  18. ominfra/manage/remote/inject.py +29 -0
  19. ominfra/manage/{payload.py → remote/payload.py} +7 -1
  20. ominfra/manage/{spawning.py → remote/spawning.py} +31 -35
  21. ominfra/pyremote.py +53 -14
  22. ominfra/scripts/journald2aws.py +216 -131
  23. ominfra/scripts/manage.py +2180 -452
  24. ominfra/scripts/supervisor.py +203 -130
  25. ominfra/supervisor/inject.py +2 -1
  26. {ominfra-0.0.0.dev141.dist-info → ominfra-0.0.0.dev143.dist-info}/METADATA +3 -3
  27. {ominfra-0.0.0.dev141.dist-info → ominfra-0.0.0.dev143.dist-info}/RECORD +31 -17
  28. {ominfra-0.0.0.dev141.dist-info → ominfra-0.0.0.dev143.dist-info}/LICENSE +0 -0
  29. {ominfra-0.0.0.dev141.dist-info → ominfra-0.0.0.dev143.dist-info}/WHEEL +0 -0
  30. {ominfra-0.0.0.dev141.dist-info → ominfra-0.0.0.dev143.dist-info}/entry_points.txt +0 -0
  31. {ominfra-0.0.0.dev141.dist-info → ominfra-0.0.0.dev143.dist-info}/top_level.txt +0 -0
ominfra/pyremote.py CHANGED
@@ -2,6 +2,9 @@
2
2
  # @omlish-lite
3
3
  """
4
4
  Basically this: https://mitogen.networkgenomics.com/howitworks.html
5
+
6
+ TODO:
7
+ - log: ta.Optional[logging.Logger] = None + log.debug's
5
8
  """
6
9
  import base64
7
10
  import dataclasses as dc
@@ -23,6 +26,9 @@ import zlib
23
26
  class PyremoteBootstrapOptions:
24
27
  debug: bool = False
25
28
 
29
+ DEFAULT_MAIN_NAME_OVERRIDE: ta.ClassVar[str] = '__pyremote__'
30
+ main_name_override: ta.Optional[str] = DEFAULT_MAIN_NAME_OVERRIDE
31
+
26
32
 
27
33
  ##
28
34
 
@@ -177,12 +183,14 @@ def _pyremote_bootstrap_main(context_name: str) -> None:
177
183
  os.close(f)
178
184
 
179
185
  # Save vars
180
- os.environ[_PYREMOTE_BOOTSTRAP_CHILD_PID_VAR] = str(cp)
181
- os.environ[_PYREMOTE_BOOTSTRAP_ARGV0_VAR] = sys.executable
182
- os.environ[_PYREMOTE_BOOTSTRAP_CONTEXT_NAME_VAR] = context_name
186
+ env = os.environ
187
+ exe = sys.executable
188
+ env[_PYREMOTE_BOOTSTRAP_CHILD_PID_VAR] = str(cp)
189
+ env[_PYREMOTE_BOOTSTRAP_ARGV0_VAR] = exe
190
+ env[_PYREMOTE_BOOTSTRAP_CONTEXT_NAME_VAR] = context_name
183
191
 
184
192
  # Start repl reading stdin from r0
185
- os.execl(sys.executable, sys.executable + (_PYREMOTE_BOOTSTRAP_PROC_TITLE_FMT % (context_name,)))
193
+ os.execl(exe, exe + (_PYREMOTE_BOOTSTRAP_PROC_TITLE_FMT % (context_name,)))
186
194
 
187
195
  else:
188
196
  # Child process
@@ -246,12 +254,12 @@ def pyremote_build_bootstrap_cmd(context_name: str) -> str:
246
254
  if cl.strip()
247
255
  )
248
256
 
249
- bs_z = zlib.compress(bs_src.encode('utf-8'))
250
- bs_z64 = base64.encodebytes(bs_z).replace(b'\n', b'')
257
+ bs_z = zlib.compress(bs_src.encode('utf-8'), 9)
258
+ bs_z85 = base64.b85encode(bs_z).replace(b'\n', b'')
251
259
 
252
260
  stmts = [
253
261
  f'import {", ".join(_PYREMOTE_BOOTSTRAP_IMPORTS)}',
254
- f'exec(zlib.decompress(base64.decodebytes({bs_z64!r})))',
262
+ f'exec(zlib.decompress(base64.b85decode({bs_z85!r})))',
255
263
  f'_pyremote_bootstrap_main({context_name!r})',
256
264
  ]
257
265
 
@@ -337,6 +345,10 @@ def pyremote_bootstrap_finalize() -> PyremotePayloadRuntime:
337
345
  os.dup2(nfd := os.open('/dev/null', os.O_WRONLY), 1)
338
346
  os.close(nfd)
339
347
 
348
+ if (mn := options.main_name_override) is not None:
349
+ # Inspections like typing.get_type_hints need an entry in sys.modules.
350
+ sys.modules[mn] = sys.modules['__main__']
351
+
340
352
  # Write fourth ack
341
353
  output.write(_PYREMOTE_BOOTSTRAP_ACK3)
342
354
 
@@ -355,14 +367,41 @@ def pyremote_bootstrap_finalize() -> PyremotePayloadRuntime:
355
367
 
356
368
 
357
369
  class PyremoteBootstrapDriver:
358
- def __init__(self, main_src: str, options: PyremoteBootstrapOptions = PyremoteBootstrapOptions()) -> None:
370
+ def __init__(
371
+ self,
372
+ main_src: ta.Union[str, ta.Sequence[str]],
373
+ options: PyremoteBootstrapOptions = PyremoteBootstrapOptions(),
374
+ ) -> None:
359
375
  super().__init__()
360
376
 
361
377
  self._main_src = main_src
362
- self._main_z = zlib.compress(main_src.encode('utf-8'))
363
-
364
378
  self._options = options
379
+
380
+ self._prepared_main_src = self._prepare_main_src(main_src, options)
381
+ self._main_z = zlib.compress(self._prepared_main_src.encode('utf-8'))
382
+
365
383
  self._options_json = json.dumps(dc.asdict(options), indent=None, separators=(',', ':')).encode('utf-8') # noqa
384
+ #
385
+
386
+ @classmethod
387
+ def _prepare_main_src(
388
+ cls,
389
+ main_src: ta.Union[str, ta.Sequence[str]],
390
+ options: PyremoteBootstrapOptions,
391
+ ) -> str:
392
+ parts: ta.List[str]
393
+ if isinstance(main_src, str):
394
+ parts = [main_src]
395
+ else:
396
+ parts = list(main_src)
397
+
398
+ if (mn := options.main_name_override) is not None:
399
+ parts.insert(0, f'__name__ = {mn!r}')
400
+
401
+ if len(parts) == 1:
402
+ return parts[0]
403
+ else:
404
+ return '\n\n'.join(parts)
366
405
 
367
406
  #
368
407
 
@@ -440,7 +479,7 @@ class PyremoteBootstrapDriver:
440
479
 
441
480
  #
442
481
 
443
- def run(self, stdin: ta.IO, stdout: ta.IO) -> Result:
482
+ def run(self, input: ta.IO, output: ta.IO) -> Result: # noqa
444
483
  gen = self.gen()
445
484
 
446
485
  gi: ta.Optional[bytes] = None
@@ -454,11 +493,11 @@ class PyremoteBootstrapDriver:
454
493
  return e.value
455
494
 
456
495
  if isinstance(go, self.Read):
457
- if len(gi := stdout.read(go.sz)) != go.sz:
496
+ if len(gi := input.read(go.sz)) != go.sz:
458
497
  raise EOFError
459
498
  elif isinstance(go, self.Write):
460
499
  gi = None
461
- stdin.write(go.d)
462
- stdin.flush()
500
+ output.write(go.d)
501
+ output.flush()
463
502
  else:
464
503
  raise TypeError(go)
@@ -72,6 +72,9 @@ ConfigMapping = ta.Mapping[str, ta.Any]
72
72
  # ../../../threadworkers.py
73
73
  ThreadWorkerT = ta.TypeVar('ThreadWorkerT', bound='ThreadWorker')
74
74
 
75
+ # ../../../../omlish/lite/subprocesses.py
76
+ SubprocessChannelOption = ta.Literal['pipe', 'stdout', 'devnull']
77
+
75
78
 
76
79
  ########################################
77
80
  # ../../../../../omdev/toml/parser.py
@@ -2163,21 +2166,26 @@ TODO:
2163
2166
  ##
2164
2167
 
2165
2168
 
2169
+ @dc.dataclass(frozen=True)
2170
+ class ObjMarshalOptions:
2171
+ raw_bytes: bool = False
2172
+
2173
+
2166
2174
  class ObjMarshaler(abc.ABC):
2167
2175
  @abc.abstractmethod
2168
- def marshal(self, o: ta.Any) -> ta.Any:
2176
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2169
2177
  raise NotImplementedError
2170
2178
 
2171
2179
  @abc.abstractmethod
2172
- def unmarshal(self, o: ta.Any) -> ta.Any:
2180
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2173
2181
  raise NotImplementedError
2174
2182
 
2175
2183
 
2176
2184
  class NopObjMarshaler(ObjMarshaler):
2177
- def marshal(self, o: ta.Any) -> ta.Any:
2185
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2178
2186
  return o
2179
2187
 
2180
- def unmarshal(self, o: ta.Any) -> ta.Any:
2188
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2181
2189
  return o
2182
2190
 
2183
2191
 
@@ -2185,29 +2193,29 @@ class NopObjMarshaler(ObjMarshaler):
2185
2193
  class ProxyObjMarshaler(ObjMarshaler):
2186
2194
  m: ta.Optional[ObjMarshaler] = None
2187
2195
 
2188
- def marshal(self, o: ta.Any) -> ta.Any:
2189
- return check_not_none(self.m).marshal(o)
2196
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2197
+ return check_not_none(self.m).marshal(o, opts)
2190
2198
 
2191
- def unmarshal(self, o: ta.Any) -> ta.Any:
2192
- return check_not_none(self.m).unmarshal(o)
2199
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2200
+ return check_not_none(self.m).unmarshal(o, opts)
2193
2201
 
2194
2202
 
2195
2203
  @dc.dataclass(frozen=True)
2196
2204
  class CastObjMarshaler(ObjMarshaler):
2197
2205
  ty: type
2198
2206
 
2199
- def marshal(self, o: ta.Any) -> ta.Any:
2207
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2200
2208
  return o
2201
2209
 
2202
- def unmarshal(self, o: ta.Any) -> ta.Any:
2210
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2203
2211
  return self.ty(o)
2204
2212
 
2205
2213
 
2206
2214
  class DynamicObjMarshaler(ObjMarshaler):
2207
- def marshal(self, o: ta.Any) -> ta.Any:
2215
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2208
2216
  return marshal_obj(o)
2209
2217
 
2210
- def unmarshal(self, o: ta.Any) -> ta.Any:
2218
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2211
2219
  return o
2212
2220
 
2213
2221
 
@@ -2215,21 +2223,36 @@ class DynamicObjMarshaler(ObjMarshaler):
2215
2223
  class Base64ObjMarshaler(ObjMarshaler):
2216
2224
  ty: type
2217
2225
 
2218
- def marshal(self, o: ta.Any) -> ta.Any:
2226
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2219
2227
  return base64.b64encode(o).decode('ascii')
2220
2228
 
2221
- def unmarshal(self, o: ta.Any) -> ta.Any:
2229
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2222
2230
  return self.ty(base64.b64decode(o))
2223
2231
 
2224
2232
 
2233
+ @dc.dataclass(frozen=True)
2234
+ class BytesSwitchedObjMarshaler(ObjMarshaler):
2235
+ m: ObjMarshaler
2236
+
2237
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2238
+ if opts.raw_bytes:
2239
+ return o
2240
+ return self.m.marshal(o, opts)
2241
+
2242
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2243
+ if opts.raw_bytes:
2244
+ return o
2245
+ return self.m.unmarshal(o, opts)
2246
+
2247
+
2225
2248
  @dc.dataclass(frozen=True)
2226
2249
  class EnumObjMarshaler(ObjMarshaler):
2227
2250
  ty: type
2228
2251
 
2229
- def marshal(self, o: ta.Any) -> ta.Any:
2252
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2230
2253
  return o.name
2231
2254
 
2232
- def unmarshal(self, o: ta.Any) -> ta.Any:
2255
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2233
2256
  return self.ty.__members__[o] # type: ignore
2234
2257
 
2235
2258
 
@@ -2237,15 +2260,15 @@ class EnumObjMarshaler(ObjMarshaler):
2237
2260
  class OptionalObjMarshaler(ObjMarshaler):
2238
2261
  item: ObjMarshaler
2239
2262
 
2240
- def marshal(self, o: ta.Any) -> ta.Any:
2263
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2241
2264
  if o is None:
2242
2265
  return None
2243
- return self.item.marshal(o)
2266
+ return self.item.marshal(o, opts)
2244
2267
 
2245
- def unmarshal(self, o: ta.Any) -> ta.Any:
2268
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2246
2269
  if o is None:
2247
2270
  return None
2248
- return self.item.unmarshal(o)
2271
+ return self.item.unmarshal(o, opts)
2249
2272
 
2250
2273
 
2251
2274
  @dc.dataclass(frozen=True)
@@ -2254,11 +2277,11 @@ class MappingObjMarshaler(ObjMarshaler):
2254
2277
  km: ObjMarshaler
2255
2278
  vm: ObjMarshaler
2256
2279
 
2257
- def marshal(self, o: ta.Any) -> ta.Any:
2258
- return {self.km.marshal(k): self.vm.marshal(v) for k, v in o.items()}
2280
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2281
+ return {self.km.marshal(k, opts): self.vm.marshal(v, opts) for k, v in o.items()}
2259
2282
 
2260
- def unmarshal(self, o: ta.Any) -> ta.Any:
2261
- return self.ty((self.km.unmarshal(k), self.vm.unmarshal(v)) for k, v in o.items())
2283
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2284
+ return self.ty((self.km.unmarshal(k, opts), self.vm.unmarshal(v, opts)) for k, v in o.items())
2262
2285
 
2263
2286
 
2264
2287
  @dc.dataclass(frozen=True)
@@ -2266,11 +2289,11 @@ class IterableObjMarshaler(ObjMarshaler):
2266
2289
  ty: type
2267
2290
  item: ObjMarshaler
2268
2291
 
2269
- def marshal(self, o: ta.Any) -> ta.Any:
2270
- return [self.item.marshal(e) for e in o]
2292
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2293
+ return [self.item.marshal(e, opts) for e in o]
2271
2294
 
2272
- def unmarshal(self, o: ta.Any) -> ta.Any:
2273
- return self.ty(self.item.unmarshal(e) for e in o)
2295
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2296
+ return self.ty(self.item.unmarshal(e, opts) for e in o)
2274
2297
 
2275
2298
 
2276
2299
  @dc.dataclass(frozen=True)
@@ -2279,11 +2302,11 @@ class DataclassObjMarshaler(ObjMarshaler):
2279
2302
  fs: ta.Mapping[str, ObjMarshaler]
2280
2303
  nonstrict: bool = False
2281
2304
 
2282
- def marshal(self, o: ta.Any) -> ta.Any:
2283
- return {k: m.marshal(getattr(o, k)) for k, m in self.fs.items()}
2305
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2306
+ return {k: m.marshal(getattr(o, k), opts) for k, m in self.fs.items()}
2284
2307
 
2285
- def unmarshal(self, o: ta.Any) -> ta.Any:
2286
- return self.ty(**{k: self.fs[k].unmarshal(v) for k, v in o.items() if not self.nonstrict or k in self.fs})
2308
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2309
+ 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})
2287
2310
 
2288
2311
 
2289
2312
  @dc.dataclass(frozen=True)
@@ -2303,50 +2326,50 @@ class PolymorphicObjMarshaler(ObjMarshaler):
2303
2326
  {i.tag: i for i in impls},
2304
2327
  )
2305
2328
 
2306
- def marshal(self, o: ta.Any) -> ta.Any:
2329
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2307
2330
  impl = self.impls_by_ty[type(o)]
2308
- return {impl.tag: impl.m.marshal(o)}
2331
+ return {impl.tag: impl.m.marshal(o, opts)}
2309
2332
 
2310
- def unmarshal(self, o: ta.Any) -> ta.Any:
2333
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2311
2334
  [(t, v)] = o.items()
2312
2335
  impl = self.impls_by_tag[t]
2313
- return impl.m.unmarshal(v)
2336
+ return impl.m.unmarshal(v, opts)
2314
2337
 
2315
2338
 
2316
2339
  @dc.dataclass(frozen=True)
2317
2340
  class DatetimeObjMarshaler(ObjMarshaler):
2318
2341
  ty: type
2319
2342
 
2320
- def marshal(self, o: ta.Any) -> ta.Any:
2343
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2321
2344
  return o.isoformat()
2322
2345
 
2323
- def unmarshal(self, o: ta.Any) -> ta.Any:
2346
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2324
2347
  return self.ty.fromisoformat(o) # type: ignore
2325
2348
 
2326
2349
 
2327
2350
  class DecimalObjMarshaler(ObjMarshaler):
2328
- def marshal(self, o: ta.Any) -> ta.Any:
2351
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2329
2352
  return str(check_isinstance(o, decimal.Decimal))
2330
2353
 
2331
- def unmarshal(self, v: ta.Any) -> ta.Any:
2354
+ def unmarshal(self, v: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2332
2355
  return decimal.Decimal(check_isinstance(v, str))
2333
2356
 
2334
2357
 
2335
2358
  class FractionObjMarshaler(ObjMarshaler):
2336
- def marshal(self, o: ta.Any) -> ta.Any:
2359
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2337
2360
  fr = check_isinstance(o, fractions.Fraction)
2338
2361
  return [fr.numerator, fr.denominator]
2339
2362
 
2340
- def unmarshal(self, v: ta.Any) -> ta.Any:
2363
+ def unmarshal(self, v: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2341
2364
  num, denom = check_isinstance(v, list)
2342
2365
  return fractions.Fraction(num, denom)
2343
2366
 
2344
2367
 
2345
2368
  class UuidObjMarshaler(ObjMarshaler):
2346
- def marshal(self, o: ta.Any) -> ta.Any:
2369
+ def marshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2347
2370
  return str(o)
2348
2371
 
2349
- def unmarshal(self, o: ta.Any) -> ta.Any:
2372
+ def unmarshal(self, o: ta.Any, opts: ObjMarshalOptions) -> ta.Any:
2350
2373
  return uuid.UUID(o)
2351
2374
 
2352
2375
 
@@ -2356,7 +2379,7 @@ class UuidObjMarshaler(ObjMarshaler):
2356
2379
  _DEFAULT_OBJ_MARSHALERS: ta.Dict[ta.Any, ObjMarshaler] = {
2357
2380
  **{t: NopObjMarshaler() for t in (type(None),)},
2358
2381
  **{t: CastObjMarshaler(t) for t in (int, float, str, bool)},
2359
- **{t: Base64ObjMarshaler(t) for t in (bytes, bytearray)},
2382
+ **{t: BytesSwitchedObjMarshaler(Base64ObjMarshaler(t)) for t in (bytes, bytearray)},
2360
2383
  **{t: IterableObjMarshaler(t, DynamicObjMarshaler()) for t in (list, tuple, set, frozenset)},
2361
2384
  **{t: MappingObjMarshaler(t, DynamicObjMarshaler(), DynamicObjMarshaler()) for t in (dict,)},
2362
2385
 
@@ -2382,120 +2405,172 @@ _OBJ_MARSHALER_GENERIC_ITERABLE_TYPES: ta.Dict[ta.Any, type] = {
2382
2405
  }
2383
2406
 
2384
2407
 
2385
- def _make_obj_marshaler(
2386
- ty: ta.Any,
2387
- rec: ta.Callable[[ta.Any], ObjMarshaler],
2388
- *,
2389
- nonstrict_dataclasses: bool = False,
2390
- ) -> ObjMarshaler:
2391
- if isinstance(ty, type):
2392
- if abc.ABC in ty.__bases__:
2393
- return PolymorphicObjMarshaler.of([ # type: ignore
2394
- PolymorphicObjMarshaler.Impl(
2395
- ity,
2396
- ity.__qualname__,
2397
- rec(ity),
2398
- )
2399
- for ity in deep_subclasses(ty)
2400
- if abc.ABC not in ity.__bases__
2401
- ])
2402
-
2403
- if issubclass(ty, enum.Enum):
2404
- return EnumObjMarshaler(ty)
2405
-
2406
- if dc.is_dataclass(ty):
2407
- return DataclassObjMarshaler(
2408
- ty,
2409
- {f.name: rec(f.type) for f in dc.fields(ty)},
2410
- nonstrict=nonstrict_dataclasses,
2411
- )
2408
+ ##
2412
2409
 
2413
- if is_generic_alias(ty):
2414
- try:
2415
- mt = _OBJ_MARSHALER_GENERIC_MAPPING_TYPES[ta.get_origin(ty)]
2416
- except KeyError:
2417
- pass
2418
- else:
2419
- k, v = ta.get_args(ty)
2420
- return MappingObjMarshaler(mt, rec(k), rec(v))
2421
2410
 
2422
- try:
2423
- st = _OBJ_MARSHALER_GENERIC_ITERABLE_TYPES[ta.get_origin(ty)]
2424
- except KeyError:
2425
- pass
2426
- else:
2427
- [e] = ta.get_args(ty)
2428
- return IterableObjMarshaler(st, rec(e))
2411
+ class ObjMarshalerManager:
2412
+ def __init__(
2413
+ self,
2414
+ *,
2415
+ default_options: ObjMarshalOptions = ObjMarshalOptions(),
2429
2416
 
2430
- if is_union_alias(ty):
2431
- return OptionalObjMarshaler(rec(get_optional_alias_arg(ty)))
2417
+ default_obj_marshalers: ta.Dict[ta.Any, ObjMarshaler] = _DEFAULT_OBJ_MARSHALERS, # noqa
2418
+ generic_mapping_types: ta.Dict[ta.Any, type] = _OBJ_MARSHALER_GENERIC_MAPPING_TYPES, # noqa
2419
+ generic_iterable_types: ta.Dict[ta.Any, type] = _OBJ_MARSHALER_GENERIC_ITERABLE_TYPES, # noqa
2420
+ ) -> None:
2421
+ super().__init__()
2432
2422
 
2433
- raise TypeError(ty)
2423
+ self._default_options = default_options
2434
2424
 
2425
+ self._obj_marshalers = dict(default_obj_marshalers)
2426
+ self._generic_mapping_types = generic_mapping_types
2427
+ self._generic_iterable_types = generic_iterable_types
2435
2428
 
2436
- ##
2429
+ self._lock = threading.RLock()
2430
+ self._marshalers: ta.Dict[ta.Any, ObjMarshaler] = dict(_DEFAULT_OBJ_MARSHALERS)
2431
+ self._proxies: ta.Dict[ta.Any, ProxyObjMarshaler] = {}
2437
2432
 
2433
+ #
2438
2434
 
2439
- _OBJ_MARSHALERS_LOCK = threading.RLock()
2435
+ def make_obj_marshaler(
2436
+ self,
2437
+ ty: ta.Any,
2438
+ rec: ta.Callable[[ta.Any], ObjMarshaler],
2439
+ *,
2440
+ nonstrict_dataclasses: bool = False,
2441
+ ) -> ObjMarshaler:
2442
+ if isinstance(ty, type):
2443
+ if abc.ABC in ty.__bases__:
2444
+ return PolymorphicObjMarshaler.of([ # type: ignore
2445
+ PolymorphicObjMarshaler.Impl(
2446
+ ity,
2447
+ ity.__qualname__,
2448
+ rec(ity),
2449
+ )
2450
+ for ity in deep_subclasses(ty)
2451
+ if abc.ABC not in ity.__bases__
2452
+ ])
2453
+
2454
+ if issubclass(ty, enum.Enum):
2455
+ return EnumObjMarshaler(ty)
2456
+
2457
+ if dc.is_dataclass(ty):
2458
+ return DataclassObjMarshaler(
2459
+ ty,
2460
+ {f.name: rec(f.type) for f in dc.fields(ty)},
2461
+ nonstrict=nonstrict_dataclasses,
2462
+ )
2440
2463
 
2441
- _OBJ_MARSHALERS: ta.Dict[ta.Any, ObjMarshaler] = dict(_DEFAULT_OBJ_MARSHALERS)
2464
+ if is_generic_alias(ty):
2465
+ try:
2466
+ mt = self._generic_mapping_types[ta.get_origin(ty)]
2467
+ except KeyError:
2468
+ pass
2469
+ else:
2470
+ k, v = ta.get_args(ty)
2471
+ return MappingObjMarshaler(mt, rec(k), rec(v))
2442
2472
 
2443
- _OBJ_MARSHALER_PROXIES: ta.Dict[ta.Any, ProxyObjMarshaler] = {}
2473
+ try:
2474
+ st = self._generic_iterable_types[ta.get_origin(ty)]
2475
+ except KeyError:
2476
+ pass
2477
+ else:
2478
+ [e] = ta.get_args(ty)
2479
+ return IterableObjMarshaler(st, rec(e))
2444
2480
 
2481
+ if is_union_alias(ty):
2482
+ return OptionalObjMarshaler(rec(get_optional_alias_arg(ty)))
2445
2483
 
2446
- def register_opj_marshaler(ty: ta.Any, m: ObjMarshaler) -> None:
2447
- with _OBJ_MARSHALERS_LOCK:
2448
- if ty in _OBJ_MARSHALERS:
2449
- raise KeyError(ty)
2450
- _OBJ_MARSHALERS[ty] = m
2484
+ raise TypeError(ty)
2451
2485
 
2486
+ #
2487
+
2488
+ def register_opj_marshaler(self, ty: ta.Any, m: ObjMarshaler) -> None:
2489
+ with self._lock:
2490
+ if ty in self._obj_marshalers:
2491
+ raise KeyError(ty)
2492
+ self._obj_marshalers[ty] = m
2493
+
2494
+ def get_obj_marshaler(
2495
+ self,
2496
+ ty: ta.Any,
2497
+ *,
2498
+ no_cache: bool = False,
2499
+ **kwargs: ta.Any,
2500
+ ) -> ObjMarshaler:
2501
+ with self._lock:
2502
+ if not no_cache:
2503
+ try:
2504
+ return self._obj_marshalers[ty]
2505
+ except KeyError:
2506
+ pass
2452
2507
 
2453
- def get_obj_marshaler(
2454
- ty: ta.Any,
2455
- *,
2456
- no_cache: bool = False,
2457
- **kwargs: ta.Any,
2458
- ) -> ObjMarshaler:
2459
- with _OBJ_MARSHALERS_LOCK:
2460
- if not no_cache:
2461
2508
  try:
2462
- return _OBJ_MARSHALERS[ty]
2509
+ return self._proxies[ty]
2463
2510
  except KeyError:
2464
2511
  pass
2465
2512
 
2466
- try:
2467
- return _OBJ_MARSHALER_PROXIES[ty]
2468
- except KeyError:
2469
- pass
2513
+ rec = functools.partial(
2514
+ self.get_obj_marshaler,
2515
+ no_cache=no_cache,
2516
+ **kwargs,
2517
+ )
2470
2518
 
2471
- rec = functools.partial(
2472
- get_obj_marshaler,
2473
- no_cache=no_cache,
2474
- **kwargs,
2475
- )
2519
+ p = ProxyObjMarshaler()
2520
+ self._proxies[ty] = p
2521
+ try:
2522
+ m = self.make_obj_marshaler(ty, rec, **kwargs)
2523
+ finally:
2524
+ del self._proxies[ty]
2525
+ p.m = m
2476
2526
 
2477
- p = ProxyObjMarshaler()
2478
- _OBJ_MARSHALER_PROXIES[ty] = p
2479
- try:
2480
- m = _make_obj_marshaler(ty, rec, **kwargs)
2481
- finally:
2482
- del _OBJ_MARSHALER_PROXIES[ty]
2483
- p.m = m
2527
+ if not no_cache:
2528
+ self._obj_marshalers[ty] = m
2529
+ return m
2530
+
2531
+ #
2484
2532
 
2485
- if not no_cache:
2486
- _OBJ_MARSHALERS[ty] = m
2487
- return m
2533
+ def marshal_obj(
2534
+ self,
2535
+ o: ta.Any,
2536
+ ty: ta.Any = None,
2537
+ opts: ta.Optional[ObjMarshalOptions] = None,
2538
+ ) -> ta.Any:
2539
+ m = self.get_obj_marshaler(ty if ty is not None else type(o))
2540
+ return m.marshal(o, opts or self._default_options)
2541
+
2542
+ def unmarshal_obj(
2543
+ self,
2544
+ o: ta.Any,
2545
+ ty: ta.Union[ta.Type[T], ta.Any],
2546
+ opts: ta.Optional[ObjMarshalOptions] = None,
2547
+ ) -> T:
2548
+ m = self.get_obj_marshaler(ty)
2549
+ return m.unmarshal(o, opts or self._default_options)
2550
+
2551
+ def roundtrip_obj(
2552
+ self,
2553
+ o: ta.Any,
2554
+ ty: ta.Any = None,
2555
+ opts: ta.Optional[ObjMarshalOptions] = None,
2556
+ ) -> ta.Any:
2557
+ if ty is None:
2558
+ ty = type(o)
2559
+ m: ta.Any = self.marshal_obj(o, ty, opts)
2560
+ u: ta.Any = self.unmarshal_obj(m, ty, opts)
2561
+ return u
2488
2562
 
2489
2563
 
2490
2564
  ##
2491
2565
 
2492
2566
 
2493
- def marshal_obj(o: ta.Any, ty: ta.Any = None) -> ta.Any:
2494
- return get_obj_marshaler(ty if ty is not None else type(o)).marshal(o)
2567
+ OBJ_MARSHALER_MANAGER = ObjMarshalerManager()
2495
2568
 
2569
+ register_opj_marshaler = OBJ_MARSHALER_MANAGER.register_opj_marshaler
2570
+ get_obj_marshaler = OBJ_MARSHALER_MANAGER.get_obj_marshaler
2496
2571
 
2497
- def unmarshal_obj(o: ta.Any, ty: ta.Union[ta.Type[T], ta.Any]) -> T:
2498
- return get_obj_marshaler(ty).unmarshal(o)
2572
+ marshal_obj = OBJ_MARSHALER_MANAGER.marshal_obj
2573
+ unmarshal_obj = OBJ_MARSHALER_MANAGER.unmarshal_obj
2499
2574
 
2500
2575
 
2501
2576
  ########################################
@@ -3058,6 +3133,16 @@ class ThreadWorkerGroup:
3058
3133
  ##
3059
3134
 
3060
3135
 
3136
+ SUBPROCESS_CHANNEL_OPTION_VALUES: ta.Mapping[SubprocessChannelOption, int] = {
3137
+ 'pipe': subprocess.PIPE,
3138
+ 'stdout': subprocess.STDOUT,
3139
+ 'devnull': subprocess.DEVNULL,
3140
+ }
3141
+
3142
+
3143
+ ##
3144
+
3145
+
3061
3146
  _SUBPROCESS_SHELL_WRAP_EXECS = False
3062
3147
 
3063
3148