ominfra 0.0.0.dev157__py3-none-any.whl → 0.0.0.dev158__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.
@@ -142,9 +142,9 @@ InjectorBindingOrBindings = ta.Union['InjectorBinding', 'InjectorBindings']
142
142
  ConfigMapping = ta.Mapping[str, ta.Any]
143
143
 
144
144
  # ../../omlish/http/handlers.py
145
- HttpHandler = ta.Callable[['HttpHandlerRequest'], 'HttpHandlerResponse']
145
+ HttpHandler = ta.Callable[['HttpHandlerRequest'], 'HttpHandlerResponse'] # ta.TypeAlias
146
146
 
147
- # ../../omlish/http/coroserver.py
147
+ # ../../omlish/http/coro/server.py
148
148
  CoroHttpServerFactory = ta.Callable[[SocketAddress], 'CoroHttpServer']
149
149
 
150
150
 
@@ -2202,6 +2202,13 @@ json_dump_compact: ta.Callable[..., bytes] = functools.partial(json.dump, **JSON
2202
2202
  json_dumps_compact: ta.Callable[..., str] = functools.partial(json.dumps, **JSON_COMPACT_KWARGS)
2203
2203
 
2204
2204
 
2205
+ ########################################
2206
+ # ../../../omlish/lite/logs.py
2207
+
2208
+
2209
+ log = logging.getLogger(__name__)
2210
+
2211
+
2205
2212
  ########################################
2206
2213
  # ../../../omlish/lite/maybes.py
2207
2214
 
@@ -2486,6 +2493,116 @@ class Func3(ta.Generic[A0, A1, A2, T]):
2486
2493
  return self.fn(a0, a1, a2)
2487
2494
 
2488
2495
 
2496
+ ########################################
2497
+ # ../../../omlish/logs/filters.py
2498
+
2499
+
2500
+ class TidLogFilter(logging.Filter):
2501
+ def filter(self, record):
2502
+ record.tid = threading.get_native_id()
2503
+ return True
2504
+
2505
+
2506
+ ########################################
2507
+ # ../../../omlish/logs/proxy.py
2508
+
2509
+
2510
+ class ProxyLogFilterer(logging.Filterer):
2511
+ def __init__(self, underlying: logging.Filterer) -> None: # noqa
2512
+ self._underlying = underlying
2513
+
2514
+ @property
2515
+ def underlying(self) -> logging.Filterer:
2516
+ return self._underlying
2517
+
2518
+ @property
2519
+ def filters(self):
2520
+ return self._underlying.filters
2521
+
2522
+ @filters.setter
2523
+ def filters(self, filters):
2524
+ self._underlying.filters = filters
2525
+
2526
+ def addFilter(self, filter): # noqa
2527
+ self._underlying.addFilter(filter)
2528
+
2529
+ def removeFilter(self, filter): # noqa
2530
+ self._underlying.removeFilter(filter)
2531
+
2532
+ def filter(self, record):
2533
+ return self._underlying.filter(record)
2534
+
2535
+
2536
+ class ProxyLogHandler(ProxyLogFilterer, logging.Handler):
2537
+ def __init__(self, underlying: logging.Handler) -> None: # noqa
2538
+ ProxyLogFilterer.__init__(self, underlying)
2539
+
2540
+ _underlying: logging.Handler
2541
+
2542
+ @property
2543
+ def underlying(self) -> logging.Handler:
2544
+ return self._underlying
2545
+
2546
+ def get_name(self):
2547
+ return self._underlying.get_name()
2548
+
2549
+ def set_name(self, name):
2550
+ self._underlying.set_name(name)
2551
+
2552
+ @property
2553
+ def name(self):
2554
+ return self._underlying.name
2555
+
2556
+ @property
2557
+ def level(self):
2558
+ return self._underlying.level
2559
+
2560
+ @level.setter
2561
+ def level(self, level):
2562
+ self._underlying.level = level
2563
+
2564
+ @property
2565
+ def formatter(self):
2566
+ return self._underlying.formatter
2567
+
2568
+ @formatter.setter
2569
+ def formatter(self, formatter):
2570
+ self._underlying.formatter = formatter
2571
+
2572
+ def createLock(self):
2573
+ self._underlying.createLock()
2574
+
2575
+ def acquire(self):
2576
+ self._underlying.acquire()
2577
+
2578
+ def release(self):
2579
+ self._underlying.release()
2580
+
2581
+ def setLevel(self, level):
2582
+ self._underlying.setLevel(level)
2583
+
2584
+ def format(self, record):
2585
+ return self._underlying.format(record)
2586
+
2587
+ def emit(self, record):
2588
+ self._underlying.emit(record)
2589
+
2590
+ def handle(self, record):
2591
+ return self._underlying.handle(record)
2592
+
2593
+ def setFormatter(self, fmt):
2594
+ self._underlying.setFormatter(fmt)
2595
+
2596
+ def flush(self):
2597
+ self._underlying.flush()
2598
+
2599
+ def close(self):
2600
+ self._underlying.close()
2601
+
2602
+ def handleError(self, record):
2603
+ self._underlying.handleError(record)
2604
+
2605
+
2489
2606
  ########################################
2490
2607
  # ../events.py
2491
2608
 
@@ -4733,367 +4850,97 @@ inj = Injection
4733
4850
 
4734
4851
 
4735
4852
  ########################################
4736
- # ../../../omlish/lite/logs.py
4853
+ # ../../../omlish/lite/marshal.py
4737
4854
  """
4738
4855
  TODO:
4739
- - translate json keys
4740
- - debug
4856
+ - pickle stdlib objs? have to pin to 3.8 pickle protocol, will be cross-version
4857
+ - namedtuple
4858
+ - literals
4859
+ - newtypes?
4741
4860
  """
4742
4861
 
4743
4862
 
4744
- log = logging.getLogger(__name__)
4745
-
4746
-
4747
4863
  ##
4748
4864
 
4749
4865
 
4750
- class TidLogFilter(logging.Filter):
4751
-
4752
- def filter(self, record):
4753
- record.tid = threading.get_native_id()
4754
- return True
4866
+ @dc.dataclass(frozen=True)
4867
+ class ObjMarshalOptions:
4868
+ raw_bytes: bool = False
4869
+ nonstrict_dataclasses: bool = False
4755
4870
 
4756
4871
 
4757
- ##
4872
+ class ObjMarshaler(abc.ABC):
4873
+ @abc.abstractmethod
4874
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
4875
+ raise NotImplementedError
4758
4876
 
4877
+ @abc.abstractmethod
4878
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
4879
+ raise NotImplementedError
4759
4880
 
4760
- class JsonLogFormatter(logging.Formatter):
4761
4881
 
4762
- KEYS: ta.Mapping[str, bool] = {
4763
- 'name': False,
4764
- 'msg': False,
4765
- 'args': False,
4766
- 'levelname': False,
4767
- 'levelno': False,
4768
- 'pathname': False,
4769
- 'filename': False,
4770
- 'module': False,
4771
- 'exc_info': True,
4772
- 'exc_text': True,
4773
- 'stack_info': True,
4774
- 'lineno': False,
4775
- 'funcName': False,
4776
- 'created': False,
4777
- 'msecs': False,
4778
- 'relativeCreated': False,
4779
- 'thread': False,
4780
- 'threadName': False,
4781
- 'processName': False,
4782
- 'process': False,
4783
- }
4882
+ class NopObjMarshaler(ObjMarshaler):
4883
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
4884
+ return o
4784
4885
 
4785
- def format(self, record: logging.LogRecord) -> str:
4786
- dct = {
4787
- k: v
4788
- for k, o in self.KEYS.items()
4789
- for v in [getattr(record, k)]
4790
- if not (o and v is None)
4791
- }
4792
- return json_dumps_compact(dct)
4886
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
4887
+ return o
4793
4888
 
4794
4889
 
4795
- ##
4890
+ @dc.dataclass()
4891
+ class ProxyObjMarshaler(ObjMarshaler):
4892
+ m: ta.Optional[ObjMarshaler] = None
4796
4893
 
4894
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
4895
+ return check.not_none(self.m).marshal(o, ctx)
4797
4896
 
4798
- STANDARD_LOG_FORMAT_PARTS = [
4799
- ('asctime', '%(asctime)-15s'),
4800
- ('process', 'pid=%(process)-6s'),
4801
- ('thread', 'tid=%(thread)x'),
4802
- ('levelname', '%(levelname)s'),
4803
- ('name', '%(name)s'),
4804
- ('separator', '::'),
4805
- ('message', '%(message)s'),
4806
- ]
4897
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
4898
+ return check.not_none(self.m).unmarshal(o, ctx)
4807
4899
 
4808
4900
 
4809
- class StandardLogFormatter(logging.Formatter):
4901
+ @dc.dataclass(frozen=True)
4902
+ class CastObjMarshaler(ObjMarshaler):
4903
+ ty: type
4810
4904
 
4811
- @staticmethod
4812
- def build_log_format(parts: ta.Iterable[ta.Tuple[str, str]]) -> str:
4813
- return ' '.join(v for k, v in parts)
4905
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
4906
+ return o
4814
4907
 
4815
- converter = datetime.datetime.fromtimestamp # type: ignore
4908
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
4909
+ return self.ty(o)
4816
4910
 
4817
- def formatTime(self, record, datefmt=None):
4818
- ct = self.converter(record.created) # type: ignore
4819
- if datefmt:
4820
- return ct.strftime(datefmt) # noqa
4821
- else:
4822
- t = ct.strftime('%Y-%m-%d %H:%M:%S')
4823
- return '%s.%03d' % (t, record.msecs) # noqa
4824
4911
 
4912
+ class DynamicObjMarshaler(ObjMarshaler):
4913
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
4914
+ return ctx.manager.marshal_obj(o, opts=ctx.options)
4825
4915
 
4826
- ##
4916
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
4917
+ return o
4827
4918
 
4828
4919
 
4829
- class ProxyLogFilterer(logging.Filterer):
4830
- def __init__(self, underlying: logging.Filterer) -> None: # noqa
4831
- self._underlying = underlying
4920
+ @dc.dataclass(frozen=True)
4921
+ class Base64ObjMarshaler(ObjMarshaler):
4922
+ ty: type
4832
4923
 
4833
- @property
4834
- def underlying(self) -> logging.Filterer:
4835
- return self._underlying
4924
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
4925
+ return base64.b64encode(o).decode('ascii')
4836
4926
 
4837
- @property
4838
- def filters(self):
4839
- return self._underlying.filters
4927
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
4928
+ return self.ty(base64.b64decode(o))
4840
4929
 
4841
- @filters.setter
4842
- def filters(self, filters):
4843
- self._underlying.filters = filters
4844
4930
 
4845
- def addFilter(self, filter): # noqa
4846
- self._underlying.addFilter(filter)
4931
+ @dc.dataclass(frozen=True)
4932
+ class BytesSwitchedObjMarshaler(ObjMarshaler):
4933
+ m: ObjMarshaler
4847
4934
 
4848
- def removeFilter(self, filter): # noqa
4849
- self._underlying.removeFilter(filter)
4935
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
4936
+ if ctx.options.raw_bytes:
4937
+ return o
4938
+ return self.m.marshal(o, ctx)
4850
4939
 
4851
- def filter(self, record):
4852
- return self._underlying.filter(record)
4853
-
4854
-
4855
- class ProxyLogHandler(ProxyLogFilterer, logging.Handler):
4856
- def __init__(self, underlying: logging.Handler) -> None: # noqa
4857
- ProxyLogFilterer.__init__(self, underlying)
4858
-
4859
- _underlying: logging.Handler
4860
-
4861
- @property
4862
- def underlying(self) -> logging.Handler:
4863
- return self._underlying
4864
-
4865
- def get_name(self):
4866
- return self._underlying.get_name()
4867
-
4868
- def set_name(self, name):
4869
- self._underlying.set_name(name)
4870
-
4871
- @property
4872
- def name(self):
4873
- return self._underlying.name
4874
-
4875
- @property
4876
- def level(self):
4877
- return self._underlying.level
4878
-
4879
- @level.setter
4880
- def level(self, level):
4881
- self._underlying.level = level
4882
-
4883
- @property
4884
- def formatter(self):
4885
- return self._underlying.formatter
4886
-
4887
- @formatter.setter
4888
- def formatter(self, formatter):
4889
- self._underlying.formatter = formatter
4890
-
4891
- def createLock(self):
4892
- self._underlying.createLock()
4893
-
4894
- def acquire(self):
4895
- self._underlying.acquire()
4896
-
4897
- def release(self):
4898
- self._underlying.release()
4899
-
4900
- def setLevel(self, level):
4901
- self._underlying.setLevel(level)
4902
-
4903
- def format(self, record):
4904
- return self._underlying.format(record)
4905
-
4906
- def emit(self, record):
4907
- self._underlying.emit(record)
4908
-
4909
- def handle(self, record):
4910
- return self._underlying.handle(record)
4911
-
4912
- def setFormatter(self, fmt):
4913
- self._underlying.setFormatter(fmt)
4914
-
4915
- def flush(self):
4916
- self._underlying.flush()
4917
-
4918
- def close(self):
4919
- self._underlying.close()
4920
-
4921
- def handleError(self, record):
4922
- self._underlying.handleError(record)
4923
-
4924
-
4925
- ##
4926
-
4927
-
4928
- class StandardLogHandler(ProxyLogHandler):
4929
- pass
4930
-
4931
-
4932
- ##
4933
-
4934
-
4935
- @contextlib.contextmanager
4936
- def _locking_logging_module_lock() -> ta.Iterator[None]:
4937
- if hasattr(logging, '_acquireLock'):
4938
- logging._acquireLock() # noqa
4939
- try:
4940
- yield
4941
- finally:
4942
- logging._releaseLock() # type: ignore # noqa
4943
-
4944
- elif hasattr(logging, '_lock'):
4945
- # https://github.com/python/cpython/commit/74723e11109a320e628898817ab449b3dad9ee96
4946
- with logging._lock: # noqa
4947
- yield
4948
-
4949
- else:
4950
- raise Exception("Can't find lock in logging module")
4951
-
4952
-
4953
- def configure_standard_logging(
4954
- level: ta.Union[int, str] = logging.INFO,
4955
- *,
4956
- json: bool = False,
4957
- target: ta.Optional[logging.Logger] = None,
4958
- force: bool = False,
4959
- handler_factory: ta.Optional[ta.Callable[[], logging.Handler]] = None,
4960
- ) -> ta.Optional[StandardLogHandler]:
4961
- with _locking_logging_module_lock():
4962
- if target is None:
4963
- target = logging.root
4964
-
4965
- #
4966
-
4967
- if not force:
4968
- if any(isinstance(h, StandardLogHandler) for h in list(target.handlers)):
4969
- return None
4970
-
4971
- #
4972
-
4973
- if handler_factory is not None:
4974
- handler = handler_factory()
4975
- else:
4976
- handler = logging.StreamHandler()
4977
-
4978
- #
4979
-
4980
- formatter: logging.Formatter
4981
- if json:
4982
- formatter = JsonLogFormatter()
4983
- else:
4984
- formatter = StandardLogFormatter(StandardLogFormatter.build_log_format(STANDARD_LOG_FORMAT_PARTS))
4985
- handler.setFormatter(formatter)
4986
-
4987
- #
4988
-
4989
- handler.addFilter(TidLogFilter())
4990
-
4991
- #
4992
-
4993
- target.addHandler(handler)
4994
-
4995
- #
4996
-
4997
- if level is not None:
4998
- target.setLevel(level)
4999
-
5000
- #
5001
-
5002
- return StandardLogHandler(handler)
5003
-
5004
-
5005
- ########################################
5006
- # ../../../omlish/lite/marshal.py
5007
- """
5008
- TODO:
5009
- - pickle stdlib objs? have to pin to 3.8 pickle protocol, will be cross-version
5010
- - namedtuple
5011
- - literals
5012
- - newtypes?
5013
- """
5014
-
5015
-
5016
- ##
5017
-
5018
-
5019
- @dc.dataclass(frozen=True)
5020
- class ObjMarshalOptions:
5021
- raw_bytes: bool = False
5022
- nonstrict_dataclasses: bool = False
5023
-
5024
-
5025
- class ObjMarshaler(abc.ABC):
5026
- @abc.abstractmethod
5027
- def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
5028
- raise NotImplementedError
5029
-
5030
- @abc.abstractmethod
5031
- def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
5032
- raise NotImplementedError
5033
-
5034
-
5035
- class NopObjMarshaler(ObjMarshaler):
5036
- def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
5037
- return o
5038
-
5039
- def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
5040
- return o
5041
-
5042
-
5043
- @dc.dataclass()
5044
- class ProxyObjMarshaler(ObjMarshaler):
5045
- m: ta.Optional[ObjMarshaler] = None
5046
-
5047
- def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
5048
- return check.not_none(self.m).marshal(o, ctx)
5049
-
5050
- def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
5051
- return check.not_none(self.m).unmarshal(o, ctx)
5052
-
5053
-
5054
- @dc.dataclass(frozen=True)
5055
- class CastObjMarshaler(ObjMarshaler):
5056
- ty: type
5057
-
5058
- def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
5059
- return o
5060
-
5061
- def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
5062
- return self.ty(o)
5063
-
5064
-
5065
- class DynamicObjMarshaler(ObjMarshaler):
5066
- def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
5067
- return ctx.manager.marshal_obj(o, opts=ctx.options)
5068
-
5069
- def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
5070
- return o
5071
-
5072
-
5073
- @dc.dataclass(frozen=True)
5074
- class Base64ObjMarshaler(ObjMarshaler):
5075
- ty: type
5076
-
5077
- def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
5078
- return base64.b64encode(o).decode('ascii')
5079
-
5080
- def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
5081
- return self.ty(base64.b64decode(o))
5082
-
5083
-
5084
- @dc.dataclass(frozen=True)
5085
- class BytesSwitchedObjMarshaler(ObjMarshaler):
5086
- m: ObjMarshaler
5087
-
5088
- def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
5089
- if ctx.options.raw_bytes:
5090
- return o
5091
- return self.m.marshal(o, ctx)
5092
-
5093
- def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
5094
- if ctx.options.raw_bytes:
5095
- return o
5096
- return self.m.unmarshal(o, ctx)
4940
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
4941
+ if ctx.options.raw_bytes:
4942
+ return o
4943
+ return self.m.unmarshal(o, ctx)
5097
4944
 
5098
4945
 
5099
4946
  @dc.dataclass(frozen=True)
@@ -5464,6 +5311,60 @@ def check_runtime_version() -> None:
5464
5311
  raise OSError(f'Requires python {REQUIRED_PYTHON_VERSION}, got {sys.version_info} from {sys.executable}') # noqa
5465
5312
 
5466
5313
 
5314
+ ########################################
5315
+ # ../../../omlish/logs/json.py
5316
+ """
5317
+ TODO:
5318
+ - translate json keys
5319
+ """
5320
+
5321
+
5322
+ class JsonLogFormatter(logging.Formatter):
5323
+ KEYS: ta.Mapping[str, bool] = {
5324
+ 'name': False,
5325
+ 'msg': False,
5326
+ 'args': False,
5327
+ 'levelname': False,
5328
+ 'levelno': False,
5329
+ 'pathname': False,
5330
+ 'filename': False,
5331
+ 'module': False,
5332
+ 'exc_info': True,
5333
+ 'exc_text': True,
5334
+ 'stack_info': True,
5335
+ 'lineno': False,
5336
+ 'funcName': False,
5337
+ 'created': False,
5338
+ 'msecs': False,
5339
+ 'relativeCreated': False,
5340
+ 'thread': False,
5341
+ 'threadName': False,
5342
+ 'processName': False,
5343
+ 'process': False,
5344
+ }
5345
+
5346
+ def __init__(
5347
+ self,
5348
+ *args: ta.Any,
5349
+ json_dumps: ta.Optional[ta.Callable[[ta.Any], str]] = None,
5350
+ **kwargs: ta.Any,
5351
+ ) -> None:
5352
+ super().__init__(*args, **kwargs)
5353
+
5354
+ if json_dumps is None:
5355
+ json_dumps = json_dumps_compact
5356
+ self._json_dumps = json_dumps
5357
+
5358
+ def format(self, record: logging.LogRecord) -> str:
5359
+ dct = {
5360
+ k: v
5361
+ for k, o in self.KEYS.items()
5362
+ for v in [getattr(record, k)]
5363
+ if not (o and v is None)
5364
+ }
5365
+ return self._json_dumps(dct)
5366
+
5367
+
5467
5368
  ########################################
5468
5369
  # ../../../omlish/os/journald.py
5469
5370
 
@@ -5852,6 +5753,126 @@ class UnsupportedMethodHttpHandlerError(Exception):
5852
5753
  pass
5853
5754
 
5854
5755
 
5756
+ ########################################
5757
+ # ../../../omlish/logs/standard.py
5758
+ """
5759
+ TODO:
5760
+ - structured
5761
+ - prefixed
5762
+ - debug
5763
+ """
5764
+
5765
+
5766
+ ##
5767
+
5768
+
5769
+ STANDARD_LOG_FORMAT_PARTS = [
5770
+ ('asctime', '%(asctime)-15s'),
5771
+ ('process', 'pid=%(process)-6s'),
5772
+ ('thread', 'tid=%(thread)x'),
5773
+ ('levelname', '%(levelname)s'),
5774
+ ('name', '%(name)s'),
5775
+ ('separator', '::'),
5776
+ ('message', '%(message)s'),
5777
+ ]
5778
+
5779
+
5780
+ class StandardLogFormatter(logging.Formatter):
5781
+ @staticmethod
5782
+ def build_log_format(parts: ta.Iterable[ta.Tuple[str, str]]) -> str:
5783
+ return ' '.join(v for k, v in parts)
5784
+
5785
+ converter = datetime.datetime.fromtimestamp # type: ignore
5786
+
5787
+ def formatTime(self, record, datefmt=None):
5788
+ ct = self.converter(record.created) # type: ignore
5789
+ if datefmt:
5790
+ return ct.strftime(datefmt) # noqa
5791
+ else:
5792
+ t = ct.strftime('%Y-%m-%d %H:%M:%S')
5793
+ return '%s.%03d' % (t, record.msecs) # noqa
5794
+
5795
+
5796
+ ##
5797
+
5798
+
5799
+ class StandardLogHandler(ProxyLogHandler):
5800
+ pass
5801
+
5802
+
5803
+ ##
5804
+
5805
+
5806
+ @contextlib.contextmanager
5807
+ def _locking_logging_module_lock() -> ta.Iterator[None]:
5808
+ if hasattr(logging, '_acquireLock'):
5809
+ logging._acquireLock() # noqa
5810
+ try:
5811
+ yield
5812
+ finally:
5813
+ logging._releaseLock() # type: ignore # noqa
5814
+
5815
+ elif hasattr(logging, '_lock'):
5816
+ # https://github.com/python/cpython/commit/74723e11109a320e628898817ab449b3dad9ee96
5817
+ with logging._lock: # noqa
5818
+ yield
5819
+
5820
+ else:
5821
+ raise Exception("Can't find lock in logging module")
5822
+
5823
+
5824
+ def configure_standard_logging(
5825
+ level: ta.Union[int, str] = logging.INFO,
5826
+ *,
5827
+ json: bool = False,
5828
+ target: ta.Optional[logging.Logger] = None,
5829
+ force: bool = False,
5830
+ handler_factory: ta.Optional[ta.Callable[[], logging.Handler]] = None,
5831
+ ) -> ta.Optional[StandardLogHandler]:
5832
+ with _locking_logging_module_lock():
5833
+ if target is None:
5834
+ target = logging.root
5835
+
5836
+ #
5837
+
5838
+ if not force:
5839
+ if any(isinstance(h, StandardLogHandler) for h in list(target.handlers)):
5840
+ return None
5841
+
5842
+ #
5843
+
5844
+ if handler_factory is not None:
5845
+ handler = handler_factory()
5846
+ else:
5847
+ handler = logging.StreamHandler()
5848
+
5849
+ #
5850
+
5851
+ formatter: logging.Formatter
5852
+ if json:
5853
+ formatter = JsonLogFormatter()
5854
+ else:
5855
+ formatter = StandardLogFormatter(StandardLogFormatter.build_log_format(STANDARD_LOG_FORMAT_PARTS))
5856
+ handler.setFormatter(formatter)
5857
+
5858
+ #
5859
+
5860
+ handler.addFilter(TidLogFilter())
5861
+
5862
+ #
5863
+
5864
+ target.addHandler(handler)
5865
+
5866
+ #
5867
+
5868
+ if level is not None:
5869
+ target.setLevel(level)
5870
+
5871
+ #
5872
+
5873
+ return StandardLogHandler(handler)
5874
+
5875
+
5855
5876
  ########################################
5856
5877
  # ../configs.py
5857
5878
 
@@ -6145,7 +6166,7 @@ def parse_logging_level(value: ta.Union[str, int]) -> int:
6145
6166
 
6146
6167
 
6147
6168
  ########################################
6148
- # ../../../omlish/http/coroserver.py
6169
+ # ../../../omlish/http/coro/server.py
6149
6170
  # PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
6150
6171
  # --------------------------------------------
6151
6172
  #
@@ -6885,7 +6906,7 @@ class ProcessGroup(
6885
6906
 
6886
6907
 
6887
6908
  ########################################
6888
- # ../../../omlish/io/fdio/corohttp.py
6909
+ # ../../../omlish/http/coro/fdio.py
6889
6910
 
6890
6911
 
6891
6912
  class CoroHttpServerConnectionFdioHandler(SocketFdioHandler):