ominfra 0.0.0.dev7__py3-none-any.whl → 0.0.0.dev8__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.
ominfra/__about__.py CHANGED
@@ -22,6 +22,6 @@ class Project(ProjectBase):
22
22
 
23
23
  class Setuptools(SetuptoolsBase):
24
24
  find_packages = {
25
- 'include': ['ominfra', 'ominfra.*'],
25
+ 'include': [Project.name, f'{Project.name}.*'],
26
26
  'exclude': [*SetuptoolsBase.find_packages['exclude']],
27
27
  }
@@ -62,6 +62,7 @@ import shlex
62
62
  import subprocess
63
63
  import sys
64
64
  import textwrap
65
+ import threading
65
66
  import typing as ta
66
67
  import uuid
67
68
  import weakref # noqa
@@ -225,14 +226,28 @@ def deep_subclasses(cls: ta.Type[T]) -> ta.Iterator[ta.Type[T]]:
225
226
  # ../../../../omlish/lite/logs.py
226
227
  """
227
228
  TODO:
229
+ - translate json keys
228
230
  - debug
229
231
  """
230
- # ruff: noqa: UP007
232
+ # ruff: noqa: UP006 UP007 N802
231
233
 
232
234
 
233
235
  log = logging.getLogger(__name__)
234
236
 
235
237
 
238
+ ##
239
+
240
+
241
+ class TidLogFilter(logging.Filter):
242
+
243
+ def filter(self, record):
244
+ record.tid = threading.get_native_id()
245
+ return True
246
+
247
+
248
+ ##
249
+
250
+
236
251
  class JsonLogFormatter(logging.Formatter):
237
252
 
238
253
  KEYS: ta.Mapping[str, bool] = {
@@ -268,9 +283,62 @@ class JsonLogFormatter(logging.Formatter):
268
283
  return json_dumps_compact(dct)
269
284
 
270
285
 
271
- def configure_standard_logging(level: ta.Union[int, str] = logging.INFO) -> None:
272
- logging.root.addHandler(logging.StreamHandler())
273
- logging.root.setLevel(level)
286
+ ##
287
+
288
+
289
+ STANDARD_LOG_FORMAT_PARTS = [
290
+ ('asctime', '%(asctime)-15s'),
291
+ ('process', 'pid=%(process)-6s'),
292
+ ('thread', 'tid=%(thread)-16s'),
293
+ ('levelname', '%(levelname)-8s'),
294
+ ('name', '%(name)s'),
295
+ ('separator', '::'),
296
+ ('message', '%(message)s'),
297
+ ]
298
+
299
+
300
+ class StandardLogFormatter(logging.Formatter):
301
+
302
+ @staticmethod
303
+ def build_log_format(parts: ta.Iterable[ta.Tuple[str, str]]) -> str:
304
+ return ' '.join(v for k, v in parts)
305
+
306
+ converter = datetime.datetime.fromtimestamp # type: ignore
307
+
308
+ def formatTime(self, record, datefmt=None):
309
+ ct = self.converter(record.created) # type: ignore
310
+ if datefmt:
311
+ return ct.strftime(datefmt) # noqa
312
+ else:
313
+ t = ct.strftime("%Y-%m-%d %H:%M:%S") # noqa
314
+ return '%s.%03d' % (t, record.msecs)
315
+
316
+
317
+ ##
318
+
319
+
320
+ def configure_standard_logging(
321
+ level: ta.Union[int, str] = logging.INFO,
322
+ *,
323
+ json: bool = False,
324
+ ) -> logging.Handler:
325
+ handler = logging.StreamHandler()
326
+
327
+ formatter: logging.Formatter
328
+ if json:
329
+ formatter = JsonLogFormatter()
330
+ else:
331
+ formatter = StandardLogFormatter(StandardLogFormatter.build_log_format(STANDARD_LOG_FORMAT_PARTS))
332
+ handler.setFormatter(formatter)
333
+
334
+ handler.addFilter(TidLogFilter())
335
+
336
+ logging.root.addHandler(handler)
337
+
338
+ if level is not None:
339
+ logging.root.setLevel(level)
340
+
341
+ return handler
274
342
 
275
343
 
276
344
  ########################################
@@ -278,6 +346,7 @@ def configure_standard_logging(level: ta.Union[int, str] = logging.INFO) -> None
278
346
  """
279
347
  TODO:
280
348
  - pickle stdlib objs? have to pin to 3.8 pickle protocol, will be cross-version
349
+ - nonstrict toggle
281
350
  """
282
351
  # ruff: noqa: UP006 UP007
283
352
 
@@ -399,12 +468,13 @@ class IterableObjMarshaler(ObjMarshaler):
399
468
  class DataclassObjMarshaler(ObjMarshaler):
400
469
  ty: type
401
470
  fs: ta.Mapping[str, ObjMarshaler]
471
+ nonstrict: bool = False
402
472
 
403
473
  def marshal(self, o: ta.Any) -> ta.Any:
404
474
  return {k: m.marshal(getattr(o, k)) for k, m in self.fs.items()}
405
475
 
406
476
  def unmarshal(self, o: ta.Any) -> ta.Any:
407
- return self.ty(**{k: self.fs[k].unmarshal(v) for k, v in o.items()})
477
+ return self.ty(**{k: self.fs[k].unmarshal(v) for k, v in o.items() if self.nonstrict or k in self.fs})
408
478
 
409
479
 
410
480
  @dc.dataclass(frozen=True)
@@ -3,6 +3,7 @@
3
3
  # @omdev-amalg-output main.py
4
4
  import abc
5
5
  import dataclasses as dc
6
+ import datetime
6
7
  import functools
7
8
  import inspect
8
9
  import json
@@ -14,6 +15,7 @@ import stat
14
15
  import subprocess
15
16
  import sys
16
17
  import textwrap
18
+ import threading
17
19
  import typing as ta
18
20
 
19
21
 
@@ -287,14 +289,28 @@ class Deploy(ConcernsContainer[DeployConcern, DeployConfig]):
287
289
  # ../../../../omlish/lite/logs.py
288
290
  """
289
291
  TODO:
292
+ - translate json keys
290
293
  - debug
291
294
  """
292
- # ruff: noqa: UP007
295
+ # ruff: noqa: UP006 UP007 N802
293
296
 
294
297
 
295
298
  log = logging.getLogger(__name__)
296
299
 
297
300
 
301
+ ##
302
+
303
+
304
+ class TidLogFilter(logging.Filter):
305
+
306
+ def filter(self, record):
307
+ record.tid = threading.get_native_id()
308
+ return True
309
+
310
+
311
+ ##
312
+
313
+
298
314
  class JsonLogFormatter(logging.Formatter):
299
315
 
300
316
  KEYS: ta.Mapping[str, bool] = {
@@ -330,9 +346,62 @@ class JsonLogFormatter(logging.Formatter):
330
346
  return json_dumps_compact(dct)
331
347
 
332
348
 
333
- def configure_standard_logging(level: ta.Union[int, str] = logging.INFO) -> None:
334
- logging.root.addHandler(logging.StreamHandler())
335
- logging.root.setLevel(level)
349
+ ##
350
+
351
+
352
+ STANDARD_LOG_FORMAT_PARTS = [
353
+ ('asctime', '%(asctime)-15s'),
354
+ ('process', 'pid=%(process)-6s'),
355
+ ('thread', 'tid=%(thread)-16s'),
356
+ ('levelname', '%(levelname)-8s'),
357
+ ('name', '%(name)s'),
358
+ ('separator', '::'),
359
+ ('message', '%(message)s'),
360
+ ]
361
+
362
+
363
+ class StandardLogFormatter(logging.Formatter):
364
+
365
+ @staticmethod
366
+ def build_log_format(parts: ta.Iterable[ta.Tuple[str, str]]) -> str:
367
+ return ' '.join(v for k, v in parts)
368
+
369
+ converter = datetime.datetime.fromtimestamp # type: ignore
370
+
371
+ def formatTime(self, record, datefmt=None):
372
+ ct = self.converter(record.created) # type: ignore
373
+ if datefmt:
374
+ return ct.strftime(datefmt) # noqa
375
+ else:
376
+ t = ct.strftime("%Y-%m-%d %H:%M:%S") # noqa
377
+ return '%s.%03d' % (t, record.msecs)
378
+
379
+
380
+ ##
381
+
382
+
383
+ def configure_standard_logging(
384
+ level: ta.Union[int, str] = logging.INFO,
385
+ *,
386
+ json: bool = False,
387
+ ) -> logging.Handler:
388
+ handler = logging.StreamHandler()
389
+
390
+ formatter: logging.Formatter
391
+ if json:
392
+ formatter = JsonLogFormatter()
393
+ else:
394
+ formatter = StandardLogFormatter(StandardLogFormatter.build_log_format(STANDARD_LOG_FORMAT_PARTS))
395
+ handler.setFormatter(formatter)
396
+
397
+ handler.addFilter(TidLogFilter())
398
+
399
+ logging.root.addHandler(handler)
400
+
401
+ if level is not None:
402
+ logging.root.setLevel(level)
403
+
404
+ return handler
336
405
 
337
406
 
338
407
  ########################################
@@ -20,6 +20,7 @@ import shlex
20
20
  import subprocess
21
21
  import sys
22
22
  import textwrap
23
+ import threading
23
24
  import typing as ta
24
25
  import uuid
25
26
  import weakref # noqa
@@ -308,14 +309,28 @@ def deep_subclasses(cls: ta.Type[T]) -> ta.Iterator[ta.Type[T]]:
308
309
  # ../../../omlish/lite/logs.py
309
310
  """
310
311
  TODO:
312
+ - translate json keys
311
313
  - debug
312
314
  """
313
- # ruff: noqa: UP007
315
+ # ruff: noqa: UP006 UP007 N802
314
316
 
315
317
 
316
318
  log = logging.getLogger(__name__)
317
319
 
318
320
 
321
+ ##
322
+
323
+
324
+ class TidLogFilter(logging.Filter):
325
+
326
+ def filter(self, record):
327
+ record.tid = threading.get_native_id()
328
+ return True
329
+
330
+
331
+ ##
332
+
333
+
319
334
  class JsonLogFormatter(logging.Formatter):
320
335
 
321
336
  KEYS: ta.Mapping[str, bool] = {
@@ -351,9 +366,62 @@ class JsonLogFormatter(logging.Formatter):
351
366
  return json_dumps_compact(dct)
352
367
 
353
368
 
354
- def configure_standard_logging(level: ta.Union[int, str] = logging.INFO) -> None:
355
- logging.root.addHandler(logging.StreamHandler())
356
- logging.root.setLevel(level)
369
+ ##
370
+
371
+
372
+ STANDARD_LOG_FORMAT_PARTS = [
373
+ ('asctime', '%(asctime)-15s'),
374
+ ('process', 'pid=%(process)-6s'),
375
+ ('thread', 'tid=%(thread)-16s'),
376
+ ('levelname', '%(levelname)-8s'),
377
+ ('name', '%(name)s'),
378
+ ('separator', '::'),
379
+ ('message', '%(message)s'),
380
+ ]
381
+
382
+
383
+ class StandardLogFormatter(logging.Formatter):
384
+
385
+ @staticmethod
386
+ def build_log_format(parts: ta.Iterable[ta.Tuple[str, str]]) -> str:
387
+ return ' '.join(v for k, v in parts)
388
+
389
+ converter = datetime.datetime.fromtimestamp # type: ignore
390
+
391
+ def formatTime(self, record, datefmt=None):
392
+ ct = self.converter(record.created) # type: ignore
393
+ if datefmt:
394
+ return ct.strftime(datefmt) # noqa
395
+ else:
396
+ t = ct.strftime("%Y-%m-%d %H:%M:%S") # noqa
397
+ return '%s.%03d' % (t, record.msecs)
398
+
399
+
400
+ ##
401
+
402
+
403
+ def configure_standard_logging(
404
+ level: ta.Union[int, str] = logging.INFO,
405
+ *,
406
+ json: bool = False,
407
+ ) -> logging.Handler:
408
+ handler = logging.StreamHandler()
409
+
410
+ formatter: logging.Formatter
411
+ if json:
412
+ formatter = JsonLogFormatter()
413
+ else:
414
+ formatter = StandardLogFormatter(StandardLogFormatter.build_log_format(STANDARD_LOG_FORMAT_PARTS))
415
+ handler.setFormatter(formatter)
416
+
417
+ handler.addFilter(TidLogFilter())
418
+
419
+ logging.root.addHandler(handler)
420
+
421
+ if level is not None:
422
+ logging.root.setLevel(level)
423
+
424
+ return handler
357
425
 
358
426
 
359
427
  ########################################
@@ -361,6 +429,7 @@ def configure_standard_logging(level: ta.Union[int, str] = logging.INFO) -> None
361
429
  """
362
430
  TODO:
363
431
  - pickle stdlib objs? have to pin to 3.8 pickle protocol, will be cross-version
432
+ - nonstrict toggle
364
433
  """
365
434
  # ruff: noqa: UP006 UP007
366
435
 
@@ -482,12 +551,13 @@ class IterableObjMarshaler(ObjMarshaler):
482
551
  class DataclassObjMarshaler(ObjMarshaler):
483
552
  ty: type
484
553
  fs: ta.Mapping[str, ObjMarshaler]
554
+ nonstrict: bool = False
485
555
 
486
556
  def marshal(self, o: ta.Any) -> ta.Any:
487
557
  return {k: m.marshal(getattr(o, k)) for k, m in self.fs.items()}
488
558
 
489
559
  def unmarshal(self, o: ta.Any) -> ta.Any:
490
- return self.ty(**{k: self.fs[k].unmarshal(v) for k, v in o.items()})
560
+ return self.ty(**{k: self.fs[k].unmarshal(v) for k, v in o.items() if self.nonstrict or k in self.fs})
491
561
 
492
562
 
493
563
  @dc.dataclass(frozen=True)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ominfra
3
- Version: 0.0.0.dev7
3
+ Version: 0.0.0.dev8
4
4
  Summary: ominfra
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -12,7 +12,7 @@ Classifier: Operating System :: OS Independent
12
12
  Classifier: Operating System :: POSIX
13
13
  Requires-Python: >=3.12
14
14
  License-File: LICENSE
15
- Requires-Dist: omlish ==0.0.0.dev7
15
+ Requires-Dist: omlish ==0.0.0.dev8
16
16
  Provides-Extra: ssh
17
17
  Requires-Dist: paramiko >=3.4 ; extra == 'ssh'
18
18
  Requires-Dist: asyncssh >=2.16 ; (python_version < "3.13") and extra == 'ssh'
@@ -1,11 +1,11 @@
1
- ominfra/__about__.py,sha256=r96OJZKL0ZT-kzNGOrHTi8aHgSojbop-FegP8FDR07s,614
1
+ ominfra/__about__.py,sha256=UHZXku_vuVCWVTvIoELaTCPcNv5JXT2DdJqZ2GpzYD4,625
2
2
  ominfra/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  ominfra/cmds.py,sha256=E0AfnvEmnKntXWvmLW5L05_NeDpBET1VBXn7vV6EwBQ,2083
4
4
  ominfra/ssh.py,sha256=U-JCvx41KI0B0riHy7cpFCKCx_LAHeSn-Irz5aAao2w,5393
5
5
  ominfra/bootstrap/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  ominfra/bootstrap/bootstrap.py,sha256=gS2FvvdZTmNqD2dEXWTCFgCXNCepFSHVojBZ5WG6mqk,65
7
7
  ominfra/deploy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- ominfra/deploy/_executor.py,sha256=Q6ClLm3yKmkjxOF76ONaASQ3gQ9yxHBUgCgBqVjPZGU,27268
8
+ ominfra/deploy/_executor.py,sha256=n4GH3Wyrr3of4lF8G4Nc95Mhs_hM5xGF5BusfD3Kiv8,28783
9
9
  ominfra/deploy/configs.py,sha256=qi0kwT7G2NH7dXLOQic-u6R3yeadup_QtvrjwWIggbM,435
10
10
  ominfra/deploy/remote.py,sha256=LJSe3AJlpvNgb_5QtUiK2JIkKC2OgMvjSD1701_y2uI,2147
11
11
  ominfra/deploy/executor/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
@@ -20,7 +20,7 @@ ominfra/deploy/executor/concerns/systemd.py,sha256=MtsSEToEa1HNouern_JukcYTnypw_
20
20
  ominfra/deploy/executor/concerns/user.py,sha256=j5LDfQXquIp-eEM7t6aShsrYoQrM_ILXZycTmTcRVxA,686
21
21
  ominfra/deploy/executor/concerns/venv.py,sha256=jbRriqJHO4r9Zyo5Hfl_qVmcU6Qm6UgrouBroKcPn2g,775
22
22
  ominfra/deploy/poly/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
23
- ominfra/deploy/poly/_main.py,sha256=L1WlgPeSmGRsqkUSQkpLfK73-xYNEIis-Y9AdQ59dTM,18573
23
+ ominfra/deploy/poly/_main.py,sha256=7mbPWYWuUIlHOMw8he5YmJB7RbnoJZNBU3p43GCDtvI,20022
24
24
  ominfra/deploy/poly/base.py,sha256=Bd-CzUTaDvTRbdXKiTxMxs77WCEXItwNoBYCRnTk1u4,4167
25
25
  ominfra/deploy/poly/configs.py,sha256=9bzWdbxhOk_Q4KokDjmRz254KHnUU71Vl1frLlhQyU4,584
26
26
  ominfra/deploy/poly/deploy.py,sha256=tMYKslXLjstcv86siRt5j37USsS0Wd6lsfeGRE26zio,544
@@ -32,13 +32,13 @@ ominfra/deploy/poly/site.py,sha256=QJwDDJoVm2-kxi4bxIrp-mn4y2qDLuW3CAUax3W8gv8,2
32
32
  ominfra/deploy/poly/supervisor.py,sha256=zkl6VQBcAZaMAhyR9DbbbqULcgFCDZoe9S_vP-mMFQ8,2289
33
33
  ominfra/deploy/poly/venv.py,sha256=BoipDEa4NTeodjf3L57KJfq9eGKLagFNKwD8pS4yrzA,1552
34
34
  ominfra/pyremote/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
- ominfra/pyremote/_runcommands.py,sha256=hsfd6f63Xxn5DUd4OJWvjlgLURAaWUI9Qh3tAJOQeUw,21091
35
+ ominfra/pyremote/_runcommands.py,sha256=KnOjlIhnHLABVuK7eWN8llr04Ywfg-lX9WIYfOWvFJA,22606
36
36
  ominfra/pyremote/bootstrap.py,sha256=ybXxNitrNKuPAIl0SrU55Ktn-4R-bDveAm_ZURrmfF0,3368
37
37
  ominfra/pyremote/runcommands.py,sha256=hXXP41rvgL46Oe_HOcLSp2Y84ZMQfEZqqV_jNd1x7Ak,1570
38
38
  ominfra/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
39
  ominfra/tools/listresources.py,sha256=vgLgohPwRog8e5pEljI2hOGg-Li5fcwjj-nXj2j8IQo,5918
40
- ominfra-0.0.0.dev7.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
41
- ominfra-0.0.0.dev7.dist-info/METADATA,sha256=G6jrSu4MhhjISrJ0cUPlMcazUJzZOCwUiEYGgBcZcgQ,617
42
- ominfra-0.0.0.dev7.dist-info/WHEEL,sha256=Mdi9PDNwEZptOjTlUcAth7XJDFtKrHYaQMPulZeBCiQ,91
43
- ominfra-0.0.0.dev7.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
44
- ominfra-0.0.0.dev7.dist-info/RECORD,,
40
+ ominfra-0.0.0.dev8.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
41
+ ominfra-0.0.0.dev8.dist-info/METADATA,sha256=XtYPpSbemhJSFWqUR0g-iDy5d84OnWEKGHuh7Fqt324,617
42
+ ominfra-0.0.0.dev8.dist-info/WHEEL,sha256=Mdi9PDNwEZptOjTlUcAth7XJDFtKrHYaQMPulZeBCiQ,91
43
+ ominfra-0.0.0.dev8.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
44
+ ominfra-0.0.0.dev8.dist-info/RECORD,,