ominfra 0.0.0.dev428__py3-none-any.whl → 0.0.0.dev430__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.
@@ -1600,8 +1600,6 @@ class AttrOps(ta.Generic[T]):
1600
1600
  self._eq = _eq
1601
1601
  return _eq
1602
1602
 
1603
- #
1604
-
1605
1603
  @property
1606
1604
  def hash_eq(self) -> ta.Tuple[
1607
1605
  ta.Callable[[T], int],
@@ -1609,6 +1607,8 @@ class AttrOps(ta.Generic[T]):
1609
1607
  ]:
1610
1608
  return (self.hash, self.eq)
1611
1609
 
1610
+ #
1611
+
1612
1612
  @property
1613
1613
  def repr_hash_eq(self) -> ta.Tuple[
1614
1614
  ta.Callable[[T], str],
@@ -1619,20 +1619,25 @@ class AttrOps(ta.Generic[T]):
1619
1619
 
1620
1620
  #
1621
1621
 
1622
+ class NOT_SET: # noqa
1623
+ def __new__(cls, *args, **kwargs): # noqa
1624
+ raise TypeError
1625
+
1622
1626
  def install(
1623
1627
  self,
1624
1628
  locals_dct: ta.MutableMapping[str, ta.Any],
1625
1629
  *,
1626
- all: bool = False, # noqa
1627
- repr: bool = False, # noqa
1628
- hash: bool = False, # noqa
1629
- eq: bool = False,
1630
+ repr: ta.Union[bool, ta.Type[NOT_SET]] = NOT_SET, # noqa
1631
+ hash: ta.Union[bool, ta.Type[NOT_SET]] = NOT_SET, # noqa
1632
+ eq: ta.Union[bool, ta.Type[NOT_SET]] = NOT_SET,
1630
1633
  ) -> 'AttrOps[T]':
1631
- if repr or all:
1634
+ if all(a is self.NOT_SET for a in (repr, hash, eq)):
1635
+ repr = hash = eq = True # noqa
1636
+ if repr:
1632
1637
  locals_dct.update(__repr__=self.repr)
1633
- if hash or all:
1638
+ if hash:
1634
1639
  locals_dct.update(__hash__=self.hash)
1635
- if eq or all:
1640
+ if eq:
1636
1641
  locals_dct.update(__eq__=self.eq)
1637
1642
  return self
1638
1643
 
@@ -2691,19 +2696,16 @@ def format_num_bytes(num_bytes: int) -> str:
2691
2696
  ##
2692
2697
 
2693
2698
 
2694
- class _LoggingContextInfo:
2695
- def __mro_entries__(self, bases):
2696
- return ()
2697
-
2698
-
2699
- LoggingContextInfo: type = ta.cast(ta.Any, _LoggingContextInfo())
2699
+ def logging_context_info(cls):
2700
+ return cls
2700
2701
 
2701
2702
 
2702
2703
  ##
2703
2704
 
2704
2705
 
2706
+ @logging_context_info
2705
2707
  @ta.final
2706
- class LoggingSourceFileInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
2708
+ class LoggingSourceFileInfo(ta.NamedTuple):
2707
2709
  file_name: str
2708
2710
  module: str
2709
2711
 
@@ -2720,16 +2722,17 @@ class LoggingSourceFileInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore[
2720
2722
  return None
2721
2723
 
2722
2724
  return cls(
2723
- file_name,
2724
- module,
2725
+ file_name=file_name,
2726
+ module=module,
2725
2727
  )
2726
2728
 
2727
2729
 
2728
2730
  ##
2729
2731
 
2730
2732
 
2733
+ @logging_context_info
2731
2734
  @ta.final
2732
- class LoggingThreadInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
2735
+ class LoggingThreadInfo(ta.NamedTuple):
2733
2736
  ident: int
2734
2737
  native_id: ta.Optional[int]
2735
2738
  name: str
@@ -2737,31 +2740,33 @@ class LoggingThreadInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc
2737
2740
  @classmethod
2738
2741
  def build(cls) -> 'LoggingThreadInfo':
2739
2742
  return cls(
2740
- threading.get_ident(),
2741
- threading.get_native_id() if hasattr(threading, 'get_native_id') else None,
2742
- threading.current_thread().name,
2743
+ ident=threading.get_ident(),
2744
+ native_id=threading.get_native_id() if hasattr(threading, 'get_native_id') else None,
2745
+ name=threading.current_thread().name,
2743
2746
  )
2744
2747
 
2745
2748
 
2746
2749
  ##
2747
2750
 
2748
2751
 
2752
+ @logging_context_info
2749
2753
  @ta.final
2750
- class LoggingProcessInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
2754
+ class LoggingProcessInfo(ta.NamedTuple):
2751
2755
  pid: int
2752
2756
 
2753
2757
  @classmethod
2754
2758
  def build(cls) -> 'LoggingProcessInfo':
2755
2759
  return cls(
2756
- os.getpid(),
2760
+ pid=os.getpid(),
2757
2761
  )
2758
2762
 
2759
2763
 
2760
2764
  ##
2761
2765
 
2762
2766
 
2767
+ @logging_context_info
2763
2768
  @ta.final
2764
- class LoggingMultiprocessingInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
2769
+ class LoggingMultiprocessingInfo(ta.NamedTuple):
2765
2770
  process_name: str
2766
2771
 
2767
2772
  @classmethod
@@ -2771,15 +2776,16 @@ class LoggingMultiprocessingInfo(LoggingContextInfo, ta.NamedTuple): # type: ig
2771
2776
  return None
2772
2777
 
2773
2778
  return cls(
2774
- mp.current_process().name,
2779
+ process_name=mp.current_process().name,
2775
2780
  )
2776
2781
 
2777
2782
 
2778
2783
  ##
2779
2784
 
2780
2785
 
2786
+ @logging_context_info
2781
2787
  @ta.final
2782
- class LoggingAsyncioTaskInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
2788
+ class LoggingAsyncioTaskInfo(ta.NamedTuple):
2783
2789
  name: str
2784
2790
 
2785
2791
  @classmethod
@@ -2797,7 +2803,7 @@ class LoggingAsyncioTaskInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore
2797
2803
  return None
2798
2804
 
2799
2805
  return cls(
2800
- task.get_name(), # Always non-None
2806
+ name=task.get_name(), # Always non-None
2801
2807
  )
2802
2808
 
2803
2809
 
@@ -2820,36 +2826,66 @@ class NamedLogLevel(int):
2820
2826
 
2821
2827
  #
2822
2828
 
2823
- @property
2824
- def exact_name(self) -> ta.Optional[str]:
2825
- return self._NAMES_BY_INT.get(self)
2829
+ _CACHE: ta.ClassVar[ta.MutableMapping[int, 'NamedLogLevel']] = {}
2830
+
2831
+ @ta.overload
2832
+ def __new__(cls, name: str, offset: int = 0, /) -> 'NamedLogLevel':
2833
+ ...
2826
2834
 
2827
- _effective_name: ta.Optional[str]
2835
+ @ta.overload
2836
+ def __new__(cls, i: int, /) -> 'NamedLogLevel':
2837
+ ...
2838
+
2839
+ def __new__(cls, x, offset=0, /):
2840
+ if isinstance(x, str):
2841
+ return cls(cls._INTS_BY_NAME[x.upper()] + offset)
2842
+ elif not offset and (c := cls._CACHE.get(x)) is not None:
2843
+ return c
2844
+ else:
2845
+ return super().__new__(cls, x + offset)
2846
+
2847
+ #
2848
+
2849
+ _name_and_offset: ta.Tuple[str, int]
2828
2850
 
2829
2851
  @property
2830
- def effective_name(self) -> ta.Optional[str]:
2852
+ def name_and_offset(self) -> ta.Tuple[str, int]:
2831
2853
  try:
2832
- return self._effective_name
2854
+ return self._name_and_offset
2833
2855
  except AttributeError:
2834
2856
  pass
2835
2857
 
2836
- if (n := self.exact_name) is None:
2858
+ if (n := self._NAMES_BY_INT.get(self)) is not None:
2859
+ t = (n, 0)
2860
+ else:
2837
2861
  for n, i in self._NAME_INT_PAIRS: # noqa
2838
2862
  if self >= i:
2863
+ t = (n, (self - i))
2839
2864
  break
2840
2865
  else:
2841
- n = None
2866
+ t = ('NOTSET', int(self))
2867
+
2868
+ self._name_and_offset = t
2869
+ return t
2842
2870
 
2843
- self._effective_name = n
2871
+ @property
2872
+ def exact_name(self) -> ta.Optional[str]:
2873
+ n, o = self.name_and_offset
2874
+ return n if not o else None
2875
+
2876
+ @property
2877
+ def effective_name(self) -> str:
2878
+ n, _ = self.name_and_offset
2844
2879
  return n
2845
2880
 
2846
2881
  #
2847
2882
 
2848
- def __repr__(self) -> str:
2849
- return f'{self.__class__.__name__}({int(self)})'
2850
-
2851
2883
  def __str__(self) -> str:
2852
- return self.exact_name or f'{self.effective_name or "INVALID"}:{int(self)}'
2884
+ return self.exact_name or f'{self.effective_name}{int(self):+}'
2885
+
2886
+ def __repr__(self) -> str:
2887
+ n, o = self.name_and_offset
2888
+ return f'{self.__class__.__name__}({n!r}{f", {int(o)}" if o else ""})'
2853
2889
 
2854
2890
  #
2855
2891
 
@@ -2869,6 +2905,9 @@ NamedLogLevel.DEBUG = NamedLogLevel(logging.DEBUG)
2869
2905
  NamedLogLevel.NOTSET = NamedLogLevel(logging.NOTSET)
2870
2906
 
2871
2907
 
2908
+ NamedLogLevel._CACHE.update({i: NamedLogLevel(i) for i in NamedLogLevel._NAMES_BY_INT}) # noqa
2909
+
2910
+
2872
2911
  ########################################
2873
2912
  # ../../../../../omlish/logs/std/filters.py
2874
2913
 
@@ -4912,7 +4951,9 @@ def check_lite_runtime_version() -> None:
4912
4951
  ##
4913
4952
 
4914
4953
 
4915
- class LoggingCaller(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
4954
+ @logging_context_info
4955
+ @ta.final
4956
+ class LoggingCaller(ta.NamedTuple):
4916
4957
  file_path: str
4917
4958
  line_no: int
4918
4959
  name: str
@@ -4965,10 +5006,10 @@ class LoggingCaller(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
4965
5006
  sinfo = sinfo[:-1]
4966
5007
 
4967
5008
  return cls(
4968
- f.f_code.co_filename,
4969
- f.f_lineno or 0,
4970
- f.f_code.co_name,
4971
- sinfo,
5009
+ file_path=f.f_code.co_filename,
5010
+ line_no=f.f_lineno or 0,
5011
+ name=f.f_code.co_name,
5012
+ stack_info=sinfo,
4972
5013
  )
4973
5014
 
4974
5015
 
@@ -5036,7 +5077,9 @@ class JsonLoggingFormatter(logging.Formatter):
5036
5077
  ##
5037
5078
 
5038
5079
 
5039
- class LoggingTimeFields(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
5080
+ @logging_context_info
5081
+ @ta.final
5082
+ class LoggingTimeFields(ta.NamedTuple):
5040
5083
  """Maps directly to stdlib `logging.LogRecord` fields, and must be kept in sync with it."""
5041
5084
 
5042
5085
  created: float
@@ -5084,9 +5127,9 @@ class LoggingTimeFields(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc
5084
5127
  relative_created = (time_ns - start_time_ns) / 1e6
5085
5128
 
5086
5129
  return cls(
5087
- created,
5088
- msecs,
5089
- relative_created,
5130
+ created=created,
5131
+ msecs=msecs,
5132
+ relative_created=relative_created,
5090
5133
  )
5091
5134
 
5092
5135
 
@@ -5730,7 +5773,7 @@ def subprocess_maybe_shell_wrap_exec(*cmd: str) -> ta.Tuple[str, ...]:
5730
5773
 
5731
5774
  class AnyLogger(Abstract, ta.Generic[T]):
5732
5775
  def is_enabled_for(self, level: LogLevel) -> bool:
5733
- return self.get_effective_level() >= level
5776
+ return level >= self.get_effective_level()
5734
5777
 
5735
5778
  @abc.abstractmethod
5736
5779
  def get_effective_level(self) -> LogLevel:
@@ -5927,7 +5970,7 @@ class AsyncLogger(AnyLogger[ta.Awaitable[None]], Abstract):
5927
5970
  class AnyNopLogger(AnyLogger[T], Abstract):
5928
5971
  @ta.final
5929
5972
  def get_effective_level(self) -> LogLevel:
5930
- return 999
5973
+ return -999
5931
5974
 
5932
5975
 
5933
5976
  @ta.final
@@ -6237,7 +6280,7 @@ class LoggingContextLogRecord(logging.LogRecord):
6237
6280
 
6238
6281
 
6239
6282
  ########################################
6240
- # ../../../../../omlish/logs/std/adapters.py
6283
+ # ../../../../../omlish/logs/std/loggers.py
6241
6284
 
6242
6285
 
6243
6286
  ##
@@ -6253,6 +6296,9 @@ class StdLogger(Logger):
6253
6296
  def std(self) -> logging.Logger:
6254
6297
  return self._std
6255
6298
 
6299
+ def is_enabled_for(self, level: LogLevel) -> bool:
6300
+ return self._std.isEnabledFor(level)
6301
+
6256
6302
  def get_effective_level(self) -> LogLevel:
6257
6303
  return self._std.getEffectiveLevel()
6258
6304
 
ominfra/scripts/manage.py CHANGED
@@ -2779,8 +2779,6 @@ class AttrOps(ta.Generic[T]):
2779
2779
  self._eq = _eq
2780
2780
  return _eq
2781
2781
 
2782
- #
2783
-
2784
2782
  @property
2785
2783
  def hash_eq(self) -> ta.Tuple[
2786
2784
  ta.Callable[[T], int],
@@ -2788,6 +2786,8 @@ class AttrOps(ta.Generic[T]):
2788
2786
  ]:
2789
2787
  return (self.hash, self.eq)
2790
2788
 
2789
+ #
2790
+
2791
2791
  @property
2792
2792
  def repr_hash_eq(self) -> ta.Tuple[
2793
2793
  ta.Callable[[T], str],
@@ -2798,20 +2798,25 @@ class AttrOps(ta.Generic[T]):
2798
2798
 
2799
2799
  #
2800
2800
 
2801
+ class NOT_SET: # noqa
2802
+ def __new__(cls, *args, **kwargs): # noqa
2803
+ raise TypeError
2804
+
2801
2805
  def install(
2802
2806
  self,
2803
2807
  locals_dct: ta.MutableMapping[str, ta.Any],
2804
2808
  *,
2805
- all: bool = False, # noqa
2806
- repr: bool = False, # noqa
2807
- hash: bool = False, # noqa
2808
- eq: bool = False,
2809
+ repr: ta.Union[bool, ta.Type[NOT_SET]] = NOT_SET, # noqa
2810
+ hash: ta.Union[bool, ta.Type[NOT_SET]] = NOT_SET, # noqa
2811
+ eq: ta.Union[bool, ta.Type[NOT_SET]] = NOT_SET,
2809
2812
  ) -> 'AttrOps[T]':
2810
- if repr or all:
2813
+ if all(a is self.NOT_SET for a in (repr, hash, eq)):
2814
+ repr = hash = eq = True # noqa
2815
+ if repr:
2811
2816
  locals_dct.update(__repr__=self.repr)
2812
- if hash or all:
2817
+ if hash:
2813
2818
  locals_dct.update(__hash__=self.hash)
2814
- if eq or all:
2819
+ if eq:
2815
2820
  locals_dct.update(__eq__=self.eq)
2816
2821
  return self
2817
2822
 
@@ -3993,19 +3998,16 @@ def typing_annotations_attr() -> str:
3993
3998
  ##
3994
3999
 
3995
4000
 
3996
- class _LoggingContextInfo:
3997
- def __mro_entries__(self, bases):
3998
- return ()
3999
-
4000
-
4001
- LoggingContextInfo: type = ta.cast(ta.Any, _LoggingContextInfo())
4001
+ def logging_context_info(cls):
4002
+ return cls
4002
4003
 
4003
4004
 
4004
4005
  ##
4005
4006
 
4006
4007
 
4008
+ @logging_context_info
4007
4009
  @ta.final
4008
- class LoggingSourceFileInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
4010
+ class LoggingSourceFileInfo(ta.NamedTuple):
4009
4011
  file_name: str
4010
4012
  module: str
4011
4013
 
@@ -4022,16 +4024,17 @@ class LoggingSourceFileInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore[
4022
4024
  return None
4023
4025
 
4024
4026
  return cls(
4025
- file_name,
4026
- module,
4027
+ file_name=file_name,
4028
+ module=module,
4027
4029
  )
4028
4030
 
4029
4031
 
4030
4032
  ##
4031
4033
 
4032
4034
 
4035
+ @logging_context_info
4033
4036
  @ta.final
4034
- class LoggingThreadInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
4037
+ class LoggingThreadInfo(ta.NamedTuple):
4035
4038
  ident: int
4036
4039
  native_id: ta.Optional[int]
4037
4040
  name: str
@@ -4039,31 +4042,33 @@ class LoggingThreadInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc
4039
4042
  @classmethod
4040
4043
  def build(cls) -> 'LoggingThreadInfo':
4041
4044
  return cls(
4042
- threading.get_ident(),
4043
- threading.get_native_id() if hasattr(threading, 'get_native_id') else None,
4044
- threading.current_thread().name,
4045
+ ident=threading.get_ident(),
4046
+ native_id=threading.get_native_id() if hasattr(threading, 'get_native_id') else None,
4047
+ name=threading.current_thread().name,
4045
4048
  )
4046
4049
 
4047
4050
 
4048
4051
  ##
4049
4052
 
4050
4053
 
4054
+ @logging_context_info
4051
4055
  @ta.final
4052
- class LoggingProcessInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
4056
+ class LoggingProcessInfo(ta.NamedTuple):
4053
4057
  pid: int
4054
4058
 
4055
4059
  @classmethod
4056
4060
  def build(cls) -> 'LoggingProcessInfo':
4057
4061
  return cls(
4058
- os.getpid(),
4062
+ pid=os.getpid(),
4059
4063
  )
4060
4064
 
4061
4065
 
4062
4066
  ##
4063
4067
 
4064
4068
 
4069
+ @logging_context_info
4065
4070
  @ta.final
4066
- class LoggingMultiprocessingInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
4071
+ class LoggingMultiprocessingInfo(ta.NamedTuple):
4067
4072
  process_name: str
4068
4073
 
4069
4074
  @classmethod
@@ -4073,15 +4078,16 @@ class LoggingMultiprocessingInfo(LoggingContextInfo, ta.NamedTuple): # type: ig
4073
4078
  return None
4074
4079
 
4075
4080
  return cls(
4076
- mp.current_process().name,
4081
+ process_name=mp.current_process().name,
4077
4082
  )
4078
4083
 
4079
4084
 
4080
4085
  ##
4081
4086
 
4082
4087
 
4088
+ @logging_context_info
4083
4089
  @ta.final
4084
- class LoggingAsyncioTaskInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
4090
+ class LoggingAsyncioTaskInfo(ta.NamedTuple):
4085
4091
  name: str
4086
4092
 
4087
4093
  @classmethod
@@ -4099,7 +4105,7 @@ class LoggingAsyncioTaskInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore
4099
4105
  return None
4100
4106
 
4101
4107
  return cls(
4102
- task.get_name(), # Always non-None
4108
+ name=task.get_name(), # Always non-None
4103
4109
  )
4104
4110
 
4105
4111
 
@@ -4122,36 +4128,66 @@ class NamedLogLevel(int):
4122
4128
 
4123
4129
  #
4124
4130
 
4125
- @property
4126
- def exact_name(self) -> ta.Optional[str]:
4127
- return self._NAMES_BY_INT.get(self)
4131
+ _CACHE: ta.ClassVar[ta.MutableMapping[int, 'NamedLogLevel']] = {}
4132
+
4133
+ @ta.overload
4134
+ def __new__(cls, name: str, offset: int = 0, /) -> 'NamedLogLevel':
4135
+ ...
4128
4136
 
4129
- _effective_name: ta.Optional[str]
4137
+ @ta.overload
4138
+ def __new__(cls, i: int, /) -> 'NamedLogLevel':
4139
+ ...
4140
+
4141
+ def __new__(cls, x, offset=0, /):
4142
+ if isinstance(x, str):
4143
+ return cls(cls._INTS_BY_NAME[x.upper()] + offset)
4144
+ elif not offset and (c := cls._CACHE.get(x)) is not None:
4145
+ return c
4146
+ else:
4147
+ return super().__new__(cls, x + offset)
4148
+
4149
+ #
4150
+
4151
+ _name_and_offset: ta.Tuple[str, int]
4130
4152
 
4131
4153
  @property
4132
- def effective_name(self) -> ta.Optional[str]:
4154
+ def name_and_offset(self) -> ta.Tuple[str, int]:
4133
4155
  try:
4134
- return self._effective_name
4156
+ return self._name_and_offset
4135
4157
  except AttributeError:
4136
4158
  pass
4137
4159
 
4138
- if (n := self.exact_name) is None:
4160
+ if (n := self._NAMES_BY_INT.get(self)) is not None:
4161
+ t = (n, 0)
4162
+ else:
4139
4163
  for n, i in self._NAME_INT_PAIRS: # noqa
4140
4164
  if self >= i:
4165
+ t = (n, (self - i))
4141
4166
  break
4142
4167
  else:
4143
- n = None
4168
+ t = ('NOTSET', int(self))
4144
4169
 
4145
- self._effective_name = n
4170
+ self._name_and_offset = t
4171
+ return t
4172
+
4173
+ @property
4174
+ def exact_name(self) -> ta.Optional[str]:
4175
+ n, o = self.name_and_offset
4176
+ return n if not o else None
4177
+
4178
+ @property
4179
+ def effective_name(self) -> str:
4180
+ n, _ = self.name_and_offset
4146
4181
  return n
4147
4182
 
4148
4183
  #
4149
4184
 
4150
- def __repr__(self) -> str:
4151
- return f'{self.__class__.__name__}({int(self)})'
4152
-
4153
4185
  def __str__(self) -> str:
4154
- return self.exact_name or f'{self.effective_name or "INVALID"}:{int(self)}'
4186
+ return self.exact_name or f'{self.effective_name}{int(self):+}'
4187
+
4188
+ def __repr__(self) -> str:
4189
+ n, o = self.name_and_offset
4190
+ return f'{self.__class__.__name__}({n!r}{f", {int(o)}" if o else ""})'
4155
4191
 
4156
4192
  #
4157
4193
 
@@ -4171,6 +4207,9 @@ NamedLogLevel.DEBUG = NamedLogLevel(logging.DEBUG)
4171
4207
  NamedLogLevel.NOTSET = NamedLogLevel(logging.NOTSET)
4172
4208
 
4173
4209
 
4210
+ NamedLogLevel._CACHE.update({i: NamedLogLevel(i) for i in NamedLogLevel._NAMES_BY_INT}) # noqa
4211
+
4212
+
4174
4213
  ########################################
4175
4214
  # ../../../omlish/logs/std/filters.py
4176
4215
 
@@ -7590,7 +7629,9 @@ class PredicateTimeout(Timeout):
7590
7629
  ##
7591
7630
 
7592
7631
 
7593
- class LoggingCaller(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
7632
+ @logging_context_info
7633
+ @ta.final
7634
+ class LoggingCaller(ta.NamedTuple):
7594
7635
  file_path: str
7595
7636
  line_no: int
7596
7637
  name: str
@@ -7643,10 +7684,10 @@ class LoggingCaller(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
7643
7684
  sinfo = sinfo[:-1]
7644
7685
 
7645
7686
  return cls(
7646
- f.f_code.co_filename,
7647
- f.f_lineno or 0,
7648
- f.f_code.co_name,
7649
- sinfo,
7687
+ file_path=f.f_code.co_filename,
7688
+ line_no=f.f_lineno or 0,
7689
+ name=f.f_code.co_name,
7690
+ stack_info=sinfo,
7650
7691
  )
7651
7692
 
7652
7693
 
@@ -7657,6 +7698,7 @@ class LoggingCaller(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
7657
7698
  ##
7658
7699
 
7659
7700
 
7701
+ @ta.runtime_checkable
7660
7702
  class LoggerLike(ta.Protocol):
7661
7703
  """Satisfied by both our Logger and stdlib logging.Logger."""
7662
7704
 
@@ -7745,7 +7787,9 @@ class JsonLoggingFormatter(logging.Formatter):
7745
7787
  ##
7746
7788
 
7747
7789
 
7748
- class LoggingTimeFields(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
7790
+ @logging_context_info
7791
+ @ta.final
7792
+ class LoggingTimeFields(ta.NamedTuple):
7749
7793
  """Maps directly to stdlib `logging.LogRecord` fields, and must be kept in sync with it."""
7750
7794
 
7751
7795
  created: float
@@ -7793,9 +7837,9 @@ class LoggingTimeFields(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc
7793
7837
  relative_created = (time_ns - start_time_ns) / 1e6
7794
7838
 
7795
7839
  return cls(
7796
- created,
7797
- msecs,
7798
- relative_created,
7840
+ created=created,
7841
+ msecs=msecs,
7842
+ relative_created=relative_created,
7799
7843
  )
7800
7844
 
7801
7845
 
@@ -10966,7 +11010,7 @@ class DeploySpec(DeploySpecKeyed[DeployKey]):
10966
11010
 
10967
11011
  class AnyLogger(Abstract, ta.Generic[T]):
10968
11012
  def is_enabled_for(self, level: LogLevel) -> bool:
10969
- return self.get_effective_level() >= level
11013
+ return level >= self.get_effective_level()
10970
11014
 
10971
11015
  @abc.abstractmethod
10972
11016
  def get_effective_level(self) -> LogLevel:
@@ -11163,7 +11207,7 @@ class AsyncLogger(AnyLogger[ta.Awaitable[None]], Abstract):
11163
11207
  class AnyNopLogger(AnyLogger[T], Abstract):
11164
11208
  @ta.final
11165
11209
  def get_effective_level(self) -> LogLevel:
11166
- return 999
11210
+ return -999
11167
11211
 
11168
11212
 
11169
11213
  @ta.final
@@ -12085,7 +12129,7 @@ class SingleDirDeployPathOwner(DeployPathOwner, Abstract):
12085
12129
 
12086
12130
 
12087
12131
  ########################################
12088
- # ../../../omlish/logs/std/adapters.py
12132
+ # ../../../omlish/logs/std/loggers.py
12089
12133
 
12090
12134
 
12091
12135
  ##
@@ -12101,6 +12145,9 @@ class StdLogger(Logger):
12101
12145
  def std(self) -> logging.Logger:
12102
12146
  return self._std
12103
12147
 
12148
+ def is_enabled_for(self, level: LogLevel) -> bool:
12149
+ return self._std.isEnabledFor(level)
12150
+
12104
12151
  def get_effective_level(self) -> LogLevel:
12105
12152
  return self._std.getEffectiveLevel()
12106
12153
 
@@ -2125,8 +2125,6 @@ class AttrOps(ta.Generic[T]):
2125
2125
  self._eq = _eq
2126
2126
  return _eq
2127
2127
 
2128
- #
2129
-
2130
2128
  @property
2131
2129
  def hash_eq(self) -> ta.Tuple[
2132
2130
  ta.Callable[[T], int],
@@ -2134,6 +2132,8 @@ class AttrOps(ta.Generic[T]):
2134
2132
  ]:
2135
2133
  return (self.hash, self.eq)
2136
2134
 
2135
+ #
2136
+
2137
2137
  @property
2138
2138
  def repr_hash_eq(self) -> ta.Tuple[
2139
2139
  ta.Callable[[T], str],
@@ -2144,20 +2144,25 @@ class AttrOps(ta.Generic[T]):
2144
2144
 
2145
2145
  #
2146
2146
 
2147
+ class NOT_SET: # noqa
2148
+ def __new__(cls, *args, **kwargs): # noqa
2149
+ raise TypeError
2150
+
2147
2151
  def install(
2148
2152
  self,
2149
2153
  locals_dct: ta.MutableMapping[str, ta.Any],
2150
2154
  *,
2151
- all: bool = False, # noqa
2152
- repr: bool = False, # noqa
2153
- hash: bool = False, # noqa
2154
- eq: bool = False,
2155
+ repr: ta.Union[bool, ta.Type[NOT_SET]] = NOT_SET, # noqa
2156
+ hash: ta.Union[bool, ta.Type[NOT_SET]] = NOT_SET, # noqa
2157
+ eq: ta.Union[bool, ta.Type[NOT_SET]] = NOT_SET,
2155
2158
  ) -> 'AttrOps[T]':
2156
- if repr or all:
2159
+ if all(a is self.NOT_SET for a in (repr, hash, eq)):
2160
+ repr = hash = eq = True # noqa
2161
+ if repr:
2157
2162
  locals_dct.update(__repr__=self.repr)
2158
- if hash or all:
2163
+ if hash:
2159
2164
  locals_dct.update(__hash__=self.hash)
2160
- if eq or all:
2165
+ if eq:
2161
2166
  locals_dct.update(__eq__=self.eq)
2162
2167
  return self
2163
2168
 
@@ -3076,19 +3081,16 @@ def typing_annotations_attr() -> str:
3076
3081
  ##
3077
3082
 
3078
3083
 
3079
- class _LoggingContextInfo:
3080
- def __mro_entries__(self, bases):
3081
- return ()
3082
-
3083
-
3084
- LoggingContextInfo: type = ta.cast(ta.Any, _LoggingContextInfo())
3084
+ def logging_context_info(cls):
3085
+ return cls
3085
3086
 
3086
3087
 
3087
3088
  ##
3088
3089
 
3089
3090
 
3091
+ @logging_context_info
3090
3092
  @ta.final
3091
- class LoggingSourceFileInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
3093
+ class LoggingSourceFileInfo(ta.NamedTuple):
3092
3094
  file_name: str
3093
3095
  module: str
3094
3096
 
@@ -3105,16 +3107,17 @@ class LoggingSourceFileInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore[
3105
3107
  return None
3106
3108
 
3107
3109
  return cls(
3108
- file_name,
3109
- module,
3110
+ file_name=file_name,
3111
+ module=module,
3110
3112
  )
3111
3113
 
3112
3114
 
3113
3115
  ##
3114
3116
 
3115
3117
 
3118
+ @logging_context_info
3116
3119
  @ta.final
3117
- class LoggingThreadInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
3120
+ class LoggingThreadInfo(ta.NamedTuple):
3118
3121
  ident: int
3119
3122
  native_id: ta.Optional[int]
3120
3123
  name: str
@@ -3122,31 +3125,33 @@ class LoggingThreadInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc
3122
3125
  @classmethod
3123
3126
  def build(cls) -> 'LoggingThreadInfo':
3124
3127
  return cls(
3125
- threading.get_ident(),
3126
- threading.get_native_id() if hasattr(threading, 'get_native_id') else None,
3127
- threading.current_thread().name,
3128
+ ident=threading.get_ident(),
3129
+ native_id=threading.get_native_id() if hasattr(threading, 'get_native_id') else None,
3130
+ name=threading.current_thread().name,
3128
3131
  )
3129
3132
 
3130
3133
 
3131
3134
  ##
3132
3135
 
3133
3136
 
3137
+ @logging_context_info
3134
3138
  @ta.final
3135
- class LoggingProcessInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
3139
+ class LoggingProcessInfo(ta.NamedTuple):
3136
3140
  pid: int
3137
3141
 
3138
3142
  @classmethod
3139
3143
  def build(cls) -> 'LoggingProcessInfo':
3140
3144
  return cls(
3141
- os.getpid(),
3145
+ pid=os.getpid(),
3142
3146
  )
3143
3147
 
3144
3148
 
3145
3149
  ##
3146
3150
 
3147
3151
 
3152
+ @logging_context_info
3148
3153
  @ta.final
3149
- class LoggingMultiprocessingInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
3154
+ class LoggingMultiprocessingInfo(ta.NamedTuple):
3150
3155
  process_name: str
3151
3156
 
3152
3157
  @classmethod
@@ -3156,15 +3161,16 @@ class LoggingMultiprocessingInfo(LoggingContextInfo, ta.NamedTuple): # type: ig
3156
3161
  return None
3157
3162
 
3158
3163
  return cls(
3159
- mp.current_process().name,
3164
+ process_name=mp.current_process().name,
3160
3165
  )
3161
3166
 
3162
3167
 
3163
3168
  ##
3164
3169
 
3165
3170
 
3171
+ @logging_context_info
3166
3172
  @ta.final
3167
- class LoggingAsyncioTaskInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
3173
+ class LoggingAsyncioTaskInfo(ta.NamedTuple):
3168
3174
  name: str
3169
3175
 
3170
3176
  @classmethod
@@ -3182,7 +3188,7 @@ class LoggingAsyncioTaskInfo(LoggingContextInfo, ta.NamedTuple): # type: ignore
3182
3188
  return None
3183
3189
 
3184
3190
  return cls(
3185
- task.get_name(), # Always non-None
3191
+ name=task.get_name(), # Always non-None
3186
3192
  )
3187
3193
 
3188
3194
 
@@ -3205,36 +3211,66 @@ class NamedLogLevel(int):
3205
3211
 
3206
3212
  #
3207
3213
 
3208
- @property
3209
- def exact_name(self) -> ta.Optional[str]:
3210
- return self._NAMES_BY_INT.get(self)
3214
+ _CACHE: ta.ClassVar[ta.MutableMapping[int, 'NamedLogLevel']] = {}
3215
+
3216
+ @ta.overload
3217
+ def __new__(cls, name: str, offset: int = 0, /) -> 'NamedLogLevel':
3218
+ ...
3211
3219
 
3212
- _effective_name: ta.Optional[str]
3220
+ @ta.overload
3221
+ def __new__(cls, i: int, /) -> 'NamedLogLevel':
3222
+ ...
3223
+
3224
+ def __new__(cls, x, offset=0, /):
3225
+ if isinstance(x, str):
3226
+ return cls(cls._INTS_BY_NAME[x.upper()] + offset)
3227
+ elif not offset and (c := cls._CACHE.get(x)) is not None:
3228
+ return c
3229
+ else:
3230
+ return super().__new__(cls, x + offset)
3231
+
3232
+ #
3233
+
3234
+ _name_and_offset: ta.Tuple[str, int]
3213
3235
 
3214
3236
  @property
3215
- def effective_name(self) -> ta.Optional[str]:
3237
+ def name_and_offset(self) -> ta.Tuple[str, int]:
3216
3238
  try:
3217
- return self._effective_name
3239
+ return self._name_and_offset
3218
3240
  except AttributeError:
3219
3241
  pass
3220
3242
 
3221
- if (n := self.exact_name) is None:
3243
+ if (n := self._NAMES_BY_INT.get(self)) is not None:
3244
+ t = (n, 0)
3245
+ else:
3222
3246
  for n, i in self._NAME_INT_PAIRS: # noqa
3223
3247
  if self >= i:
3248
+ t = (n, (self - i))
3224
3249
  break
3225
3250
  else:
3226
- n = None
3251
+ t = ('NOTSET', int(self))
3252
+
3253
+ self._name_and_offset = t
3254
+ return t
3227
3255
 
3228
- self._effective_name = n
3256
+ @property
3257
+ def exact_name(self) -> ta.Optional[str]:
3258
+ n, o = self.name_and_offset
3259
+ return n if not o else None
3260
+
3261
+ @property
3262
+ def effective_name(self) -> str:
3263
+ n, _ = self.name_and_offset
3229
3264
  return n
3230
3265
 
3231
3266
  #
3232
3267
 
3233
- def __repr__(self) -> str:
3234
- return f'{self.__class__.__name__}({int(self)})'
3235
-
3236
3268
  def __str__(self) -> str:
3237
- return self.exact_name or f'{self.effective_name or "INVALID"}:{int(self)}'
3269
+ return self.exact_name or f'{self.effective_name}{int(self):+}'
3270
+
3271
+ def __repr__(self) -> str:
3272
+ n, o = self.name_and_offset
3273
+ return f'{self.__class__.__name__}({n!r}{f", {int(o)}" if o else ""})'
3238
3274
 
3239
3275
  #
3240
3276
 
@@ -3254,6 +3290,9 @@ NamedLogLevel.DEBUG = NamedLogLevel(logging.DEBUG)
3254
3290
  NamedLogLevel.NOTSET = NamedLogLevel(logging.NOTSET)
3255
3291
 
3256
3292
 
3293
+ NamedLogLevel._CACHE.update({i: NamedLogLevel(i) for i in NamedLogLevel._NAMES_BY_INT}) # noqa
3294
+
3295
+
3257
3296
  ########################################
3258
3297
  # ../../../omlish/logs/std/filters.py
3259
3298
 
@@ -6177,7 +6216,9 @@ def check_lite_runtime_version() -> None:
6177
6216
  ##
6178
6217
 
6179
6218
 
6180
- class LoggingCaller(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
6219
+ @logging_context_info
6220
+ @ta.final
6221
+ class LoggingCaller(ta.NamedTuple):
6181
6222
  file_path: str
6182
6223
  line_no: int
6183
6224
  name: str
@@ -6230,10 +6271,10 @@ class LoggingCaller(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
6230
6271
  sinfo = sinfo[:-1]
6231
6272
 
6232
6273
  return cls(
6233
- f.f_code.co_filename,
6234
- f.f_lineno or 0,
6235
- f.f_code.co_name,
6236
- sinfo,
6274
+ file_path=f.f_code.co_filename,
6275
+ line_no=f.f_lineno or 0,
6276
+ name=f.f_code.co_name,
6277
+ stack_info=sinfo,
6237
6278
  )
6238
6279
 
6239
6280
 
@@ -6244,6 +6285,7 @@ class LoggingCaller(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
6244
6285
  ##
6245
6286
 
6246
6287
 
6288
+ @ta.runtime_checkable
6247
6289
  class LoggerLike(ta.Protocol):
6248
6290
  """Satisfied by both our Logger and stdlib logging.Logger."""
6249
6291
 
@@ -6332,7 +6374,9 @@ class JsonLoggingFormatter(logging.Formatter):
6332
6374
  ##
6333
6375
 
6334
6376
 
6335
- class LoggingTimeFields(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc]
6377
+ @logging_context_info
6378
+ @ta.final
6379
+ class LoggingTimeFields(ta.NamedTuple):
6336
6380
  """Maps directly to stdlib `logging.LogRecord` fields, and must be kept in sync with it."""
6337
6381
 
6338
6382
  created: float
@@ -6380,9 +6424,9 @@ class LoggingTimeFields(LoggingContextInfo, ta.NamedTuple): # type: ignore[misc
6380
6424
  relative_created = (time_ns - start_time_ns) / 1e6
6381
6425
 
6382
6426
  return cls(
6383
- created,
6384
- msecs,
6385
- relative_created,
6427
+ created=created,
6428
+ msecs=msecs,
6429
+ relative_created=relative_created,
6386
6430
  )
6387
6431
 
6388
6432
 
@@ -9574,7 +9618,7 @@ class CoroHttpServer:
9574
9618
 
9575
9619
  class AnyLogger(Abstract, ta.Generic[T]):
9576
9620
  def is_enabled_for(self, level: LogLevel) -> bool:
9577
- return self.get_effective_level() >= level
9621
+ return level >= self.get_effective_level()
9578
9622
 
9579
9623
  @abc.abstractmethod
9580
9624
  def get_effective_level(self) -> LogLevel:
@@ -9771,7 +9815,7 @@ class AsyncLogger(AnyLogger[ta.Awaitable[None]], Abstract):
9771
9815
  class AnyNopLogger(AnyLogger[T], Abstract):
9772
9816
  @ta.final
9773
9817
  def get_effective_level(self) -> LogLevel:
9774
- return 999
9818
+ return -999
9775
9819
 
9776
9820
 
9777
9821
  @ta.final
@@ -10354,7 +10398,7 @@ class CoroHttpServerConnectionFdioHandler(SocketFdioHandler):
10354
10398
 
10355
10399
 
10356
10400
  ########################################
10357
- # ../../../omlish/logs/std/adapters.py
10401
+ # ../../../omlish/logs/std/loggers.py
10358
10402
 
10359
10403
 
10360
10404
  ##
@@ -10370,6 +10414,9 @@ class StdLogger(Logger):
10370
10414
  def std(self) -> logging.Logger:
10371
10415
  return self._std
10372
10416
 
10417
+ def is_enabled_for(self, level: LogLevel) -> bool:
10418
+ return self._std.isEnabledFor(level)
10419
+
10373
10420
  def get_effective_level(self) -> LogLevel:
10374
10421
  return self._std.getEffectiveLevel()
10375
10422
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ominfra
3
- Version: 0.0.0.dev428
3
+ Version: 0.0.0.dev430
4
4
  Summary: ominfra
5
5
  Author: wrmsr
6
6
  License-Expression: BSD-3-Clause
@@ -14,8 +14,8 @@ Classifier: Programming Language :: Python :: 3.13
14
14
  Requires-Python: >=3.13
15
15
  Description-Content-Type: text/markdown
16
16
  License-File: LICENSE
17
- Requires-Dist: omdev==0.0.0.dev428
18
- Requires-Dist: omlish==0.0.0.dev428
17
+ Requires-Dist: omdev==0.0.0.dev430
18
+ Requires-Dist: omlish==0.0.0.dev430
19
19
  Provides-Extra: all
20
20
  Requires-Dist: paramiko~=4.0; extra == "all"
21
21
  Requires-Dist: asyncssh~=2.21; extra == "all"
@@ -112,9 +112,9 @@ ominfra/manage/targets/connection.py,sha256=mOHCsDVG-DZBhl3Mb7TTr1vhPb0gxDOOMW1x
112
112
  ominfra/manage/targets/inject.py,sha256=3M4wBkxtvymq_yhiotHlTN8iydELMjVCndyp9Bq-4eo,1572
113
113
  ominfra/manage/targets/targets.py,sha256=LjSQrDsHEjEQMDHcxtNKmLjy0YGLXJRGPFdUjazzFIM,1918
114
114
  ominfra/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
115
- ominfra/scripts/journald2aws.py,sha256=iUjxqPegHGyvIgUNWMPAeN2-P_sLfe_Nmf6naYicg7c,225783
116
- ominfra/scripts/manage.py,sha256=PopDg9ZR_2hAFOqr-HQF6Y_rasAUvPL_A8I1aXWYLZ8,449470
117
- ominfra/scripts/supervisor.py,sha256=51HD1rLxo5PhSXceIatbpVoatzs7Hf3cAJYuJ84dRFA,359209
115
+ ominfra/scripts/journald2aws.py,sha256=KQk5-KwQ3qJ55BUXW5pqErekh3DtX8f0BIxTBcMAm7Y,226969
116
+ ominfra/scripts/manage.py,sha256=3QIvVi1F1RwkYKk7ZIDsLd6VdNastEC2SUSG7kwUUHU,450678
117
+ ominfra/scripts/supervisor.py,sha256=ztxeLtlQCpmelXJYW9wotwTSc0JZBf4FauAnlu4ufV0,360417
118
118
  ominfra/supervisor/LICENSE.txt,sha256=ZrHY15PVR98y26Yg6iQfa-SXnUaYTDhrUsPVcEO5OKM,1874
119
119
  ominfra/supervisor/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
120
120
  ominfra/supervisor/__main__.py,sha256=I0yFw-C08OOiZ3BF6lF1Oiv789EQXu-_j6whDhQUTEA,66
@@ -156,9 +156,9 @@ ominfra/tailscale/api.py,sha256=XASv9C_CWI-u-yX5jVzhJrkJhlwQRkYQWQQG1uJwAd8,1375
156
156
  ominfra/tailscale/cli.py,sha256=zRV7-tKB7kBah1oTVZlol-vwx1FBlnfzYAPGkeU5jX4,3543
157
157
  ominfra/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
158
158
  ominfra/tools/listresources.py,sha256=ePmo7cUAiBZARkM_3K4GKYZXxV73An_aioS1m-AAJis,6181
159
- ominfra-0.0.0.dev428.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
160
- ominfra-0.0.0.dev428.dist-info/METADATA,sha256=DgoChKK9hL_QYLqC-3iF7P2A56nIQLlawcecm_Kd_00,2377
161
- ominfra-0.0.0.dev428.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
162
- ominfra-0.0.0.dev428.dist-info/entry_points.txt,sha256=kgecQ2MgGrM9qK744BoKS3tMesaC3yjLnl9pa5CRczg,37
163
- ominfra-0.0.0.dev428.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
164
- ominfra-0.0.0.dev428.dist-info/RECORD,,
159
+ ominfra-0.0.0.dev430.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
160
+ ominfra-0.0.0.dev430.dist-info/METADATA,sha256=B2xt-CHjl1EF8ATwYHnpAEuHRSLrtUofFVa-UWDA2KU,2377
161
+ ominfra-0.0.0.dev430.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
162
+ ominfra-0.0.0.dev430.dist-info/entry_points.txt,sha256=kgecQ2MgGrM9qK744BoKS3tMesaC3yjLnl9pa5CRczg,37
163
+ ominfra-0.0.0.dev430.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
164
+ ominfra-0.0.0.dev430.dist-info/RECORD,,