omlish 0.0.0.dev430__py3-none-any.whl → 0.0.0.dev432__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.
omlish/__about__.py CHANGED
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev430'
2
- __revision__ = '36144d896de4a99623dc872d90d16dfe60a47934'
1
+ __version__ = '0.0.0.dev432'
2
+ __revision__ = '7ead9c62b6897ffcbdb85f12366ebaaf41f89d7a'
3
3
 
4
4
 
5
5
  #
@@ -104,7 +104,7 @@ class AsyncIoProxy:
104
104
  __proxied_cls__: ta.ClassVar[type]
105
105
 
106
106
  def __init_subclass__(cls, *, proxied_cls=None, **kwargs): # noqa
107
- super().__init_subclass__()
107
+ super().__init_subclass__(**kwargs)
108
108
 
109
109
  cls.__proxied_cls__ = check.isinstance(proxied_cls, (type, None))
110
110
 
@@ -1,11 +1,17 @@
1
- from .executors import ( # noqa
2
- ImmediateExecutor,
3
- new_executor,
4
- )
5
-
6
- from .futures import ( # noqa
7
- FutureError,
8
- FutureTimeoutError,
9
- wait_futures,
10
- wait_dependent_futures,
11
- )
1
+ from .. import lang as _lang
2
+
3
+
4
+ with _lang.auto_proxy_init(globals()):
5
+ ##
6
+
7
+ from .executors import ( # noqa
8
+ ImmediateExecutor,
9
+ new_executor,
10
+ )
11
+
12
+ from .futures import ( # noqa
13
+ FutureError,
14
+ FutureTimeoutError,
15
+ wait_futures,
16
+ wait_dependent_futures,
17
+ )
omlish/funcs/match.py CHANGED
@@ -208,7 +208,7 @@ class MatchFnClass(MatchFn[P, T]):
208
208
  return mf
209
209
 
210
210
  def __init_subclass__(cls, strict: bool = False, **kwargs: ta.Any) -> None:
211
- super().__init_subclass__()
211
+ super().__init_subclass__(**kwargs)
212
212
 
213
213
  if '_cls_match_fn' in cls.__dict__:
214
214
  raise AttributeError('_cls_match_fn')
@@ -644,9 +644,10 @@ def auto_proxy_init(
644
644
  update_exports: bool = False,
645
645
  ) -> ta.Iterator[AutoProxyInit]:
646
646
  """
647
- This is a bit extreme - use sparingly. It relies on an interpreter-global import lock, but much of the ecosystem
648
- implicitly does anyway. It further relies on temporarily patching `__builtins__.__import__`, but could be switched
649
- to use any number of other import hooks.
647
+ This is a bit extreme, but worth it. For simplicity, it currently relies on temporarily patching
648
+ `__builtins__.__import__` for the duration of its context manager, but it can be switched to use any number of other
649
+ import hooks (like `sys.meta_path`). It does not rely on any permanent modification to import machinery, only for
650
+ the duration of its capture.
650
651
  """
651
652
 
652
653
  inst = AutoProxyInit(
omlish/logs/all.py CHANGED
@@ -9,6 +9,10 @@ with _lang.auto_proxy_init(globals()):
9
9
  TidLoggingFilter,
10
10
  )
11
11
 
12
+ from .std.formatters import ( # noqa
13
+ StdLoggingFormatter,
14
+ )
15
+
12
16
  from .std.handlers import ( # noqa
13
17
  ListLoggingHandler,
14
18
  )
@@ -44,23 +48,17 @@ with _lang.auto_proxy_init(globals()):
44
48
  AsyncNopLogger,
45
49
  )
46
50
 
47
- from .callers import ( # noqa
48
- LoggingCaller,
49
- )
50
-
51
51
  from .contexts import ( # noqa
52
- LoggingExcInfoTuple,
53
- LoggingExcInfo,
54
-
55
52
  LoggingContext,
56
53
  )
57
54
 
55
+ from .formatters import ( # noqa
56
+ LoggingContextFormatter,
57
+ )
58
+
58
59
  from .infos import ( # noqa
59
- LoggingSourceFileInfo,
60
- LoggingThreadInfo,
61
- LoggingProcessInfo,
62
- LoggingMultiprocessingInfo,
63
- LoggingAsyncioTaskInfo,
60
+ LoggingContextInfo,
61
+ LoggingContextInfos,
64
62
  )
65
63
 
66
64
  from .levels import ( # noqa
omlish/logs/base.py CHANGED
@@ -166,36 +166,6 @@ class AnyLogger(Abstract, ta.Generic[T]):
166
166
 
167
167
  ##
168
168
 
169
- @classmethod
170
- def _prepare_msg_args(cls, msg: ta.Union[str, tuple, LoggingMsgFn], *args: ta.Any) -> ta.Tuple[str, tuple]:
171
- if callable(msg):
172
- if args:
173
- raise TypeError(f'Must not provide both a message function and args: {msg=} {args=}')
174
- x = msg()
175
- if isinstance(x, str):
176
- return x, ()
177
- elif isinstance(x, tuple):
178
- if x:
179
- return x[0], x[1:]
180
- else:
181
- return '', ()
182
- else:
183
- raise TypeError(x)
184
-
185
- elif isinstance(msg, tuple):
186
- if args:
187
- raise TypeError(f'Must not provide both a tuple message and args: {msg=} {args=}')
188
- if msg:
189
- return msg[0], msg[1:]
190
- else:
191
- return '', ()
192
-
193
- elif isinstance(msg, str):
194
- return msg, args
195
-
196
- else:
197
- raise TypeError(msg)
198
-
199
169
  @abc.abstractmethod
200
170
  def _log(self, ctx: CaptureLoggingContext, msg: ta.Union[str, tuple, LoggingMsgFn], *args: ta.Any, **kwargs: ta.Any) -> T: # noqa
201
171
  raise NotImplementedError
omlish/logs/contexts.py CHANGED
@@ -1,94 +1,64 @@
1
1
  # ruff: noqa: UP006 UP007 UP045 UP046
2
2
  # @omlish-lite
3
3
  import abc
4
- import sys
5
4
  import time
6
- import types
7
5
  import typing as ta
8
6
 
9
7
  from ..lite.abstract import Abstract
10
- from .callers import LoggingCaller
11
- from .infos import LoggingAsyncioTaskInfo
12
- from .infos import LoggingMultiprocessingInfo
13
- from .infos import LoggingProcessInfo
14
- from .infos import LoggingSourceFileInfo
15
- from .infos import LoggingThreadInfo
8
+ from .infos import LoggingContextInfo
9
+ from .infos import LoggingContextInfos
10
+ from .infos import LoggingExcInfoArg
11
+ from .infos import LoggingMsgFn
16
12
  from .levels import LogLevel
17
- from .levels import NamedLogLevel
18
- from .times import LoggingTimeFields
19
13
 
20
14
 
21
- LoggingExcInfoTuple = ta.Tuple[ta.Type[BaseException], BaseException, ta.Optional[types.TracebackType]] # ta.TypeAlias
22
- LoggingExcInfo = ta.Union[BaseException, LoggingExcInfoTuple] # ta.TypeAlias
23
- LoggingExcInfoArg = ta.Union[LoggingExcInfo, bool, None] # ta.TypeAlias
15
+ LoggingContextInfoT = ta.TypeVar('LoggingContextInfoT', bound=LoggingContextInfo)
24
16
 
25
17
 
26
18
  ##
27
19
 
28
20
 
29
21
  class LoggingContext(Abstract):
30
- @property
31
22
  @abc.abstractmethod
32
- def level(self) -> NamedLogLevel:
23
+ def get_info(self, ty: ta.Type[LoggingContextInfoT]) -> ta.Optional[LoggingContextInfoT]:
33
24
  raise NotImplementedError
34
25
 
35
- #
36
-
37
- @property
38
- @abc.abstractmethod
39
- def time_ns(self) -> int:
40
- raise NotImplementedError
41
-
42
- @property
43
- @abc.abstractmethod
44
- def times(self) -> LoggingTimeFields:
45
- raise NotImplementedError
46
-
47
- #
48
-
49
- @property
50
- @abc.abstractmethod
51
- def exc_info(self) -> ta.Optional[LoggingExcInfo]:
52
- raise NotImplementedError
26
+ @ta.final
27
+ def __getitem__(self, ty: ta.Type[LoggingContextInfoT]) -> ta.Optional[LoggingContextInfoT]:
28
+ return self.get_info(ty)
53
29
 
54
- @property
55
- @abc.abstractmethod
56
- def exc_info_tuple(self) -> ta.Optional[LoggingExcInfoTuple]:
57
- raise NotImplementedError
30
+ @ta.final
31
+ def must_get_info(self, ty: ta.Type[LoggingContextInfoT]) -> LoggingContextInfoT:
32
+ if (info := self.get_info(ty)) is None:
33
+ raise TypeError(f'LoggingContextInfo absent: {ty}')
34
+ return info
58
35
 
59
- #
60
36
 
61
- @abc.abstractmethod
62
- def caller(self) -> ta.Optional[LoggingCaller]:
63
- raise NotImplementedError
37
+ @ta.final
38
+ class SimpleLoggingContext(LoggingContext):
39
+ def __init__(self, *infos: LoggingContextInfo) -> None:
40
+ self._infos: ta.Dict[ta.Type[LoggingContextInfo], LoggingContextInfo] = {type(i): i for i in infos}
64
41
 
65
- @abc.abstractmethod
66
- def source_file(self) -> ta.Optional[LoggingSourceFileInfo]:
67
- raise NotImplementedError
42
+ def get_info(self, ty: ta.Type[LoggingContextInfoT]) -> ta.Optional[LoggingContextInfoT]:
43
+ return self._infos.get(ty)
68
44
 
69
- #
70
45
 
71
- @abc.abstractmethod
72
- def thread(self) -> ta.Optional[LoggingThreadInfo]:
73
- raise NotImplementedError
46
+ ##
74
47
 
75
- @abc.abstractmethod
76
- def process(self) -> ta.Optional[LoggingProcessInfo]:
77
- raise NotImplementedError
78
48
 
49
+ class CaptureLoggingContext(LoggingContext, Abstract):
79
50
  @abc.abstractmethod
80
- def multiprocessing(self) -> ta.Optional[LoggingMultiprocessingInfo]:
81
- raise NotImplementedError
51
+ def set_basic(
52
+ self,
53
+ name: str,
82
54
 
83
- @abc.abstractmethod
84
- def asyncio_task(self) -> ta.Optional[LoggingAsyncioTaskInfo]:
55
+ msg: ta.Union[str, tuple, LoggingMsgFn],
56
+ args: tuple,
57
+ ) -> 'CaptureLoggingContext':
85
58
  raise NotImplementedError
86
59
 
60
+ #
87
61
 
88
- ##
89
-
90
-
91
- class CaptureLoggingContext(LoggingContext, Abstract):
92
62
  class AlreadyCapturedError(Exception):
93
63
  pass
94
64
 
@@ -119,80 +89,50 @@ class CaptureLoggingContextImpl(CaptureLoggingContext):
119
89
 
120
90
  exc_info: LoggingExcInfoArg = False,
121
91
 
122
- caller: ta.Union[LoggingCaller, ta.Type[NOT_SET], None] = NOT_SET,
92
+ caller: ta.Union[LoggingContextInfos.Caller, ta.Type[NOT_SET], None] = NOT_SET,
123
93
  stack_offset: int = 0,
124
94
  stack_info: bool = False,
125
95
  ) -> None:
126
- self._level: NamedLogLevel = level if level.__class__ is NamedLogLevel else NamedLogLevel(level) # type: ignore[assignment] # noqa
127
-
128
- #
96
+ # TODO: Name, Msg, Extra
129
97
 
130
98
  if time_ns is None:
131
99
  time_ns = time.time_ns()
132
- self._time_ns: int = time_ns
133
-
134
- #
135
-
136
- if exc_info is True:
137
- sys_exc_info = sys.exc_info()
138
- if sys_exc_info[0] is not None:
139
- exc_info = sys_exc_info
140
- else:
141
- exc_info = None
142
- elif exc_info is False:
143
- exc_info = None
144
-
145
- if exc_info is not None:
146
- self._exc_info: ta.Optional[LoggingExcInfo] = exc_info
147
- if isinstance(exc_info, BaseException):
148
- self._exc_info_tuple: ta.Optional[LoggingExcInfoTuple] = (type(exc_info), exc_info, exc_info.__traceback__) # noqa
149
- else:
150
- self._exc_info_tuple = exc_info
151
100
 
152
- #
101
+ self._infos: ta.Dict[ta.Type[LoggingContextInfo], LoggingContextInfo] = {}
102
+ self._set_info(
103
+ LoggingContextInfos.Level.build(level),
104
+ LoggingContextInfos.Time.build(time_ns),
105
+ LoggingContextInfos.Exc.build(exc_info),
106
+ )
153
107
 
154
108
  if caller is not CaptureLoggingContextImpl.NOT_SET:
155
- self._caller = caller # type: ignore[assignment]
109
+ self._infos[LoggingContextInfos.Caller] = caller
156
110
  else:
157
111
  self._stack_offset = stack_offset
158
112
  self._stack_info = stack_info
159
113
 
160
- ##
161
-
162
- @property
163
- def level(self) -> NamedLogLevel:
164
- return self._level
165
-
166
- #
167
-
168
- @property
169
- def time_ns(self) -> int:
170
- return self._time_ns
171
-
172
- _times: LoggingTimeFields
173
-
174
- @property
175
- def times(self) -> LoggingTimeFields:
176
- try:
177
- return self._times
178
- except AttributeError:
179
- pass
180
-
181
- times = self._times = LoggingTimeFields.build(self.time_ns)
182
- return times
114
+ def _set_info(self, *infos: ta.Optional[LoggingContextInfo]) -> 'CaptureLoggingContextImpl':
115
+ for info in infos:
116
+ if info is not None:
117
+ self._infos[type(info)] = info
118
+ return self
183
119
 
184
- #
120
+ def get_info(self, ty: ta.Type[LoggingContextInfoT]) -> ta.Optional[LoggingContextInfoT]:
121
+ return self._infos.get(ty)
185
122
 
186
- _exc_info: ta.Optional[LoggingExcInfo] = None
187
- _exc_info_tuple: ta.Optional[LoggingExcInfoTuple] = None
123
+ ##
188
124
 
189
- @property
190
- def exc_info(self) -> ta.Optional[LoggingExcInfo]:
191
- return self._exc_info
125
+ def set_basic(
126
+ self,
127
+ name: str,
192
128
 
193
- @property
194
- def exc_info_tuple(self) -> ta.Optional[LoggingExcInfoTuple]:
195
- return self._exc_info_tuple
129
+ msg: ta.Union[str, tuple, LoggingMsgFn],
130
+ args: tuple,
131
+ ) -> 'CaptureLoggingContextImpl':
132
+ return self._set_info(
133
+ LoggingContextInfos.Name(name),
134
+ LoggingContextInfos.Msg.build(msg, *args),
135
+ )
196
136
 
197
137
  ##
198
138
 
@@ -206,71 +146,25 @@ class CaptureLoggingContextImpl(CaptureLoggingContext):
206
146
 
207
147
  _has_captured: bool = False
208
148
 
209
- _caller: ta.Optional[LoggingCaller]
210
- _source_file: ta.Optional[LoggingSourceFileInfo]
211
-
212
- _thread: ta.Optional[LoggingThreadInfo]
213
- _process: ta.Optional[LoggingProcessInfo]
214
- _multiprocessing: ta.Optional[LoggingMultiprocessingInfo]
215
- _asyncio_task: ta.Optional[LoggingAsyncioTaskInfo]
216
-
217
149
  def capture(self) -> None:
218
150
  if self._has_captured:
219
151
  raise CaptureLoggingContextImpl.AlreadyCapturedError
220
152
  self._has_captured = True
221
153
 
222
- if not hasattr(self, '_caller'):
223
- self._caller = LoggingCaller.find(
154
+ if LoggingContextInfos.Caller not in self._infos:
155
+ self._set_info(LoggingContextInfos.Caller.build(
224
156
  self._stack_offset + 1,
225
157
  stack_info=self._stack_info,
226
- )
227
-
228
- if (caller := self._caller) is not None:
229
- self._source_file = LoggingSourceFileInfo.build(caller.file_path)
230
- else:
231
- self._source_file = None
232
-
233
- self._thread = LoggingThreadInfo.build()
234
- self._process = LoggingProcessInfo.build()
235
- self._multiprocessing = LoggingMultiprocessingInfo.build()
236
- self._asyncio_task = LoggingAsyncioTaskInfo.build()
237
-
238
- #
239
-
240
- def caller(self) -> ta.Optional[LoggingCaller]:
241
- try:
242
- return self._caller
243
- except AttributeError:
244
- raise CaptureLoggingContext.NotCapturedError from None
245
-
246
- def source_file(self) -> ta.Optional[LoggingSourceFileInfo]:
247
- try:
248
- return self._source_file
249
- except AttributeError:
250
- raise CaptureLoggingContext.NotCapturedError from None
251
-
252
- #
253
-
254
- def thread(self) -> ta.Optional[LoggingThreadInfo]:
255
- try:
256
- return self._thread
257
- except AttributeError:
258
- raise CaptureLoggingContext.NotCapturedError from None
259
-
260
- def process(self) -> ta.Optional[LoggingProcessInfo]:
261
- try:
262
- return self._process
263
- except AttributeError:
264
- raise CaptureLoggingContext.NotCapturedError from None
265
-
266
- def multiprocessing(self) -> ta.Optional[LoggingMultiprocessingInfo]:
267
- try:
268
- return self._multiprocessing
269
- except AttributeError:
270
- raise CaptureLoggingContext.NotCapturedError from None
271
-
272
- def asyncio_task(self) -> ta.Optional[LoggingAsyncioTaskInfo]:
273
- try:
274
- return self._asyncio_task
275
- except AttributeError:
276
- raise CaptureLoggingContext.NotCapturedError from None
158
+ ))
159
+
160
+ if (caller := self[LoggingContextInfos.Caller]) is not None:
161
+ self._set_info(LoggingContextInfos.SourceFile.build(
162
+ caller.file_path,
163
+ ))
164
+
165
+ self._set_info(
166
+ LoggingContextInfos.Thread.build(),
167
+ LoggingContextInfos.Process.build(),
168
+ LoggingContextInfos.Multiprocessing.build(),
169
+ LoggingContextInfos.AsyncioTask.build(),
170
+ )
@@ -0,0 +1,13 @@
1
+ import abc
2
+
3
+ from ..lite.abstract import Abstract
4
+ from .contexts import LoggingContext
5
+
6
+
7
+ ##
8
+
9
+
10
+ class LoggingContextFormatter(Abstract):
11
+ @abc.abstractmethod
12
+ def format(self, ctx: LoggingContext) -> str:
13
+ raise NotImplementedError