omlish 0.0.0.dev420__py3-none-any.whl → 0.0.0.dev422__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 +2 -2
- omlish/asyncs/bluelet/core.py +2 -2
- omlish/asyncs/bluelet/events.py +4 -3
- omlish/asyncs/bluelet/files.py +2 -2
- omlish/asyncs/bluelet/sockets.py +2 -2
- omlish/collections/frozen.py +1 -1
- omlish/collections/kv/base.py +1 -1
- omlish/collections/multimaps.py +1 -1
- omlish/collections/persistent/treapmap.py +2 -1
- omlish/concurrent/threadlets.py +2 -2
- omlish/configs/formats.py +5 -4
- omlish/configs/processing/flattening.py +2 -1
- omlish/configs/processing/rewriting.py +2 -2
- omlish/configs/shadow.py +3 -2
- omlish/daemons/spawning.py +2 -2
- omlish/daemons/targets.py +1 -1
- omlish/daemons/waiting.py +2 -1
- omlish/dataclasses/impl/generation/base.py +3 -2
- omlish/dataclasses/impl/generation/compilation.py +2 -1
- omlish/dataclasses/impl/generation/ops.py +2 -2
- omlish/dataclasses/impl/generation/processor.py +1 -1
- omlish/dataclasses/metaclass/meta.py +1 -0
- omlish/dataclasses/tools/static.py +5 -1
- omlish/formats/dotenv.py +3 -1
- omlish/formats/logfmt.py +111 -0
- omlish/formats/yaml.py +1 -1
- omlish/funcs/builders.py +2 -1
- omlish/funcs/match.py +1 -1
- omlish/funcs/pairs.py +41 -23
- omlish/funcs/pipes.py +3 -1
- omlish/http/asgi.py +2 -1
- omlish/http/coro/client/io.py +3 -2
- omlish/http/coro/server/server.py +2 -2
- omlish/http/handlers.py +2 -1
- omlish/http/jwt.py +1 -1
- omlish/http/parsing.py +2 -2
- omlish/io/compress/base.py +3 -2
- omlish/io/coro/readers.py +4 -3
- omlish/io/fdio/handlers.py +3 -2
- omlish/io/fdio/pollers.py +3 -1
- omlish/lang/__init__.py +20 -8
- omlish/lang/attrs.py +3 -1
- omlish/lang/casing.py +3 -1
- omlish/lang/classes/abstract.py +35 -96
- omlish/lang/classes/virtual.py +2 -2
- omlish/lang/contextmanagers.py +6 -4
- omlish/lang/generators.py +2 -2
- omlish/lang/iterables.py +6 -6
- omlish/lang/objects.py +0 -58
- omlish/lang/outcomes.py +3 -1
- omlish/lang/typing.py +5 -24
- omlish/lite/abstract.py +119 -0
- omlish/lite/contextmanagers.py +4 -1
- omlish/lite/inject.py +9 -9
- omlish/lite/marshal.py +230 -114
- omlish/lite/maybes.py +3 -1
- omlish/lite/maysync.py +4 -2
- omlish/lite/objects.py +81 -0
- omlish/lite/reflect.py +0 -15
- omlish/lite/timeouts.py +3 -1
- omlish/lite/wrappers.py +23 -0
- omlish/logs/abc.py +21 -5
- omlish/logs/all.py +14 -3
- omlish/logs/callers.py +23 -4
- omlish/logs/configs.py +13 -10
- omlish/logs/levels.py +7 -0
- omlish/logs/protocol.py +84 -42
- omlish/logs/typed/__init__.py +0 -0
- omlish/logs/typed/bindings.py +537 -0
- omlish/logs/typed/contexts.py +138 -0
- omlish/logs/typed/types.py +484 -0
- omlish/logs/typed/values.py +114 -0
- omlish/marshal/__init__.py +1 -0
- omlish/os/atomics.py +3 -2
- omlish/os/deathpacts/base.py +4 -2
- omlish/os/forkhooks.py +2 -2
- omlish/os/pidfiles/pinning.py +2 -1
- omlish/reflect/types.py +4 -3
- omlish/secrets/crypto.py +1 -1
- omlish/sockets/bind.py +2 -1
- omlish/sockets/handlers.py +3 -2
- omlish/sockets/server/handlers.py +2 -1
- omlish/sockets/server/server.py +4 -3
- omlish/sql/api/base.py +2 -2
- omlish/subprocesses/asyncs.py +2 -1
- omlish/subprocesses/base.py +2 -2
- omlish/subprocesses/maysync.py +1 -2
- omlish/subprocesses/run.py +2 -1
- omlish/subprocesses/sync.py +2 -1
- omlish/term/coloring.py +3 -1
- omlish/testing/pytest/plugins/asyncs/backends/base.py +3 -1
- omlish/testing/unittest/loading.py +2 -2
- omlish/text/asdl.py +4 -3
- {omlish-0.0.0.dev420.dist-info → omlish-0.0.0.dev422.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev420.dist-info → omlish-0.0.0.dev422.dist-info}/RECORD +99 -89
- {omlish-0.0.0.dev420.dist-info → omlish-0.0.0.dev422.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev420.dist-info → omlish-0.0.0.dev422.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev420.dist-info → omlish-0.0.0.dev422.dist-info}/licenses/LICENSE +0 -0
- {omlish-0.0.0.dev420.dist-info → omlish-0.0.0.dev422.dist-info}/top_level.txt +0 -0
omlish/lite/reflect.py
CHANGED
@@ -91,18 +91,3 @@ def is_literal_type(spec: ta.Any) -> bool:
|
|
91
91
|
|
92
92
|
def get_literal_type_args(spec: ta.Any) -> ta.Iterable[ta.Any]:
|
93
93
|
return spec.__args__
|
94
|
-
|
95
|
-
|
96
|
-
##
|
97
|
-
|
98
|
-
|
99
|
-
def deep_subclasses(cls: ta.Type[T]) -> ta.Iterator[ta.Type[T]]:
|
100
|
-
seen = set()
|
101
|
-
todo = list(reversed(cls.__subclasses__()))
|
102
|
-
while todo:
|
103
|
-
cur = todo.pop()
|
104
|
-
if cur in seen:
|
105
|
-
continue
|
106
|
-
seen.add(cur)
|
107
|
-
yield cur
|
108
|
-
todo.extend(reversed(cur.__subclasses__()))
|
omlish/lite/timeouts.py
CHANGED
@@ -7,6 +7,8 @@ import abc
|
|
7
7
|
import time
|
8
8
|
import typing as ta
|
9
9
|
|
10
|
+
from .abstract import Abstract
|
11
|
+
|
10
12
|
|
11
13
|
TimeoutLike = ta.Union['Timeout', ta.Type['Timeout.DEFAULT'], ta.Iterable['TimeoutLike'], float, None] # ta.TypeAlias
|
12
14
|
|
@@ -14,7 +16,7 @@ TimeoutLike = ta.Union['Timeout', ta.Type['Timeout.DEFAULT'], ta.Iterable['Timeo
|
|
14
16
|
##
|
15
17
|
|
16
18
|
|
17
|
-
class Timeout(
|
19
|
+
class Timeout(Abstract):
|
18
20
|
@property
|
19
21
|
@abc.abstractmethod
|
20
22
|
def can_expire(self) -> bool:
|
omlish/lite/wrappers.py
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# ruff: noqa: UP006
|
2
|
+
import functools
|
3
|
+
import typing as ta
|
4
|
+
|
5
|
+
|
6
|
+
##
|
7
|
+
|
8
|
+
|
9
|
+
_ANNOTATION_ATTRS: ta.FrozenSet[str] = frozenset([
|
10
|
+
'__annotations__',
|
11
|
+
|
12
|
+
'__annotate__',
|
13
|
+
'__annotate_func__',
|
14
|
+
|
15
|
+
'__annotations_cache__',
|
16
|
+
])
|
17
|
+
|
18
|
+
_UPDATE_WRAPPER_ASSIGNMENTS_NO_ANNOTATIONS: ta.Sequence[str] = list(frozenset(functools.WRAPPER_ASSIGNMENTS) - _ANNOTATION_ATTRS) # noqa
|
19
|
+
|
20
|
+
|
21
|
+
def update_wrapper_no_annotations(wrapper, wrapped):
|
22
|
+
functools.update_wrapper(wrapper, wrapped, assigned=_UPDATE_WRAPPER_ASSIGNMENTS_NO_ANNOTATIONS)
|
23
|
+
return wrapper
|
omlish/logs/abc.py
CHANGED
@@ -1,6 +1,4 @@
|
|
1
|
-
# ruff: noqa: A002
|
2
|
-
# ruff: noqa: N802
|
3
|
-
# ruff: noqa: N815
|
1
|
+
# ruff: noqa: A002 N802 N815
|
4
2
|
import types
|
5
3
|
import typing as ta
|
6
4
|
|
@@ -94,6 +92,8 @@ class LogRecord:
|
|
94
92
|
|
95
93
|
|
96
94
|
class Formatter(ta.Protocol):
|
95
|
+
"""https://docs.python.org/3/library/logging.html#formatter-objects"""
|
96
|
+
|
97
97
|
default_time_format: ta.ClassVar[str]
|
98
98
|
default_msec_format: ta.ClassVar[str]
|
99
99
|
|
@@ -111,6 +111,8 @@ class Formatter(ta.Protocol):
|
|
111
111
|
|
112
112
|
|
113
113
|
class BufferingFormatter(ta.Protocol):
|
114
|
+
"""https://docs.python.org/3/library/logging.html#logging.BufferingFormatter"""
|
115
|
+
|
114
116
|
def formatHeader(self, records: ta.Sequence[LogRecord]) -> str: ...
|
115
117
|
|
116
118
|
def formatFooter(self, records: ta.Sequence[LogRecord]) -> str: ...
|
@@ -122,10 +124,14 @@ class BufferingFormatter(ta.Protocol):
|
|
122
124
|
|
123
125
|
|
124
126
|
class Filter(ta.Protocol):
|
127
|
+
"""https://docs.python.org/3/library/logging.html#filter-objects"""
|
128
|
+
|
125
129
|
def filter(self, record: LogRecord) -> bool: ...
|
126
130
|
|
127
131
|
|
128
132
|
class Filterer(ta.Protocol):
|
133
|
+
"""A base class for loggers and handlers which allows them to share common code."""
|
134
|
+
|
129
135
|
def addFilter(self, filter: Filter) -> None: ...
|
130
136
|
|
131
137
|
def removeFilter(self, filter: Filter) -> None: ...
|
@@ -136,7 +142,9 @@ class Filterer(ta.Protocol):
|
|
136
142
|
##
|
137
143
|
|
138
144
|
|
139
|
-
class Handler(ta.Protocol):
|
145
|
+
class Handler(Filterer, ta.Protocol):
|
146
|
+
"""https://docs.python.org/3/library/logging.html#handler-objects"""
|
147
|
+
|
140
148
|
level: Level
|
141
149
|
|
142
150
|
def get_name(self) -> str: ...
|
@@ -176,7 +184,9 @@ class Stream(ta.Protocol):
|
|
176
184
|
def close(self) -> None: ... # OPTIONAL METHOD
|
177
185
|
|
178
186
|
|
179
|
-
class StreamHandler(Handler):
|
187
|
+
class StreamHandler(Handler, ta.Protocol):
|
188
|
+
"""https://docs.python.org/3/library/logging.handlers.html#logging.StreamHandler"""
|
189
|
+
|
180
190
|
terminator: ta.ClassVar[str]
|
181
191
|
|
182
192
|
stream: Stream
|
@@ -192,6 +202,8 @@ class StreamHandler(Handler):
|
|
192
202
|
|
193
203
|
|
194
204
|
class Manager(ta.Protocol):
|
205
|
+
"""There is [under normal circumstances] just one Manager instance, which holds the hierarchy of loggers."""
|
206
|
+
|
195
207
|
root: 'Logger'
|
196
208
|
|
197
209
|
disable: Level
|
@@ -215,6 +227,8 @@ Caller: ta.TypeAlias = tuple[
|
|
215
227
|
|
216
228
|
|
217
229
|
class Logger(Filterer, ta.Protocol):
|
230
|
+
"""https://docs.python.org/3/library/logging.html#logger-objects"""
|
231
|
+
|
218
232
|
name: str
|
219
233
|
level: Level
|
220
234
|
parent: ta.Optional['Logger']
|
@@ -274,6 +288,8 @@ class Logger(Filterer, ta.Protocol):
|
|
274
288
|
|
275
289
|
|
276
290
|
class LoggerAdapter(ta.Protocol):
|
291
|
+
"""https://docs.python.org/3/library/logging.html#loggeradapter-objects"""
|
292
|
+
|
277
293
|
logger: Logger
|
278
294
|
extra: ta.Mapping[str, ta.Any]
|
279
295
|
|
omlish/logs/all.py
CHANGED
@@ -25,16 +25,27 @@ with _lang.auto_proxy_init(globals()):
|
|
25
25
|
JsonLogFormatter,
|
26
26
|
)
|
27
27
|
|
28
|
+
from .levels import ( # noqa
|
29
|
+
LogLevel,
|
30
|
+
)
|
31
|
+
|
28
32
|
from .noisy import ( # noqa
|
29
33
|
silence_noisy_loggers,
|
30
34
|
)
|
31
35
|
|
32
36
|
from .protocol import ( # noqa
|
33
|
-
|
34
|
-
|
37
|
+
AnyLogging,
|
35
38
|
Logging,
|
36
|
-
|
39
|
+
AsyncLogging,
|
40
|
+
|
41
|
+
AnyAbstractLogging,
|
37
42
|
AbstractLogging,
|
43
|
+
AbstractAsyncLogging,
|
44
|
+
|
45
|
+
AnyNopLogging,
|
46
|
+
NopLogging,
|
47
|
+
NopAsyncLogging,
|
48
|
+
|
38
49
|
StdlibLogging,
|
39
50
|
)
|
40
51
|
|
omlish/logs/callers.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# ruff: noqa: UP006 UP007 UP045
|
2
2
|
# @omlish-lite
|
3
3
|
import io
|
4
|
+
import os.path
|
4
5
|
import sys
|
5
6
|
import traceback
|
6
7
|
import types
|
@@ -16,18 +17,36 @@ class LoggingCaller(ta.NamedTuple):
|
|
16
17
|
func: str
|
17
18
|
sinfo: ta.Optional[str]
|
18
19
|
|
20
|
+
@classmethod
|
21
|
+
def is_internal_frame(cls, frame: types.FrameType) -> bool:
|
22
|
+
filename = os.path.normcase(frame.f_code.co_filename)
|
23
|
+
|
24
|
+
# https://github.com/python/cpython/commit/5ca6d7469be53960843df39bb900e9c3359f127f
|
25
|
+
if 'importlib' in filename and '_bootstrap' in filename:
|
26
|
+
return True
|
27
|
+
|
28
|
+
return False
|
29
|
+
|
19
30
|
@classmethod
|
20
31
|
def find_frame(cls, ofs: int = 0) -> types.FrameType:
|
21
|
-
f: ta.
|
22
|
-
|
32
|
+
f: ta.Optional[types.FrameType] = sys._getframe(2 + ofs) # noqa
|
33
|
+
|
34
|
+
while f is not None and hasattr(f, 'f_code'):
|
23
35
|
if f.f_code.co_filename != __file__:
|
24
36
|
return f
|
37
|
+
|
25
38
|
f = f.f_back
|
39
|
+
|
26
40
|
raise RuntimeError
|
27
41
|
|
28
42
|
@classmethod
|
29
|
-
def find(
|
30
|
-
|
43
|
+
def find(
|
44
|
+
cls,
|
45
|
+
ofs: int = 0,
|
46
|
+
*,
|
47
|
+
stack_info: bool = False,
|
48
|
+
) -> 'LoggingCaller':
|
49
|
+
f = cls.find_frame(ofs + 1)
|
31
50
|
# TODO: ('(unknown file)', 0, '(unknown function)', None) ?
|
32
51
|
|
33
52
|
sinfo = None
|
omlish/logs/configs.py
CHANGED
@@ -1,17 +1,20 @@
|
|
1
|
+
# ruff: noqa: UP006 UP045
|
2
|
+
# @omlish-lite
|
1
3
|
"""
|
2
4
|
https://docs.python.org/3/howto/logging.html#configuring-logging
|
5
|
+
https://docs.python.org/3/library/logging.config.html#logging-config-dictschema
|
3
6
|
"""
|
4
7
|
import dataclasses as dc
|
5
8
|
import typing as ta
|
6
9
|
|
7
10
|
|
8
|
-
|
11
|
+
FilterConfig = ta.Dict[str, ta.Any] # ta.TypeAlias
|
12
|
+
FormatterConfig = ta.Dict[str, ta.Any] # ta.TypeAlias
|
13
|
+
HandlerConfig = ta.Dict[str, ta.Any] # ta.TypeAlias
|
14
|
+
LoggerConfig = ta.Dict[str, ta.Any] # ta.TypeAlias
|
9
15
|
|
10
16
|
|
11
|
-
|
12
|
-
FormatterConfig: ta.TypeAlias = dict[str, ta.Any]
|
13
|
-
HandlerConfig: ta.TypeAlias = dict[str, ta.Any]
|
14
|
-
LoggerConfig: ta.TypeAlias = dict[str, ta.Any]
|
17
|
+
##
|
15
18
|
|
16
19
|
|
17
20
|
@dc.dataclass()
|
@@ -19,8 +22,8 @@ class DictConfig:
|
|
19
22
|
version: int = 1
|
20
23
|
incremental: bool = False
|
21
24
|
disable_existing_loggers: bool = False
|
22
|
-
filters:
|
23
|
-
formatters:
|
24
|
-
handlers:
|
25
|
-
loggers:
|
26
|
-
root: LoggerConfig
|
25
|
+
filters: ta.Dict[str, FilterConfig] = dc.field(default_factory=dict)
|
26
|
+
formatters: ta.Dict[str, FormatterConfig] = dc.field(default_factory=dict)
|
27
|
+
handlers: ta.Dict[str, HandlerConfig] = dc.field(default_factory=dict)
|
28
|
+
loggers: ta.Dict[str, LoggerConfig] = dc.field(default_factory=dict)
|
29
|
+
root: ta.Optional[LoggerConfig] = None
|
omlish/logs/levels.py
ADDED
omlish/logs/protocol.py
CHANGED
@@ -6,49 +6,50 @@ import sys
|
|
6
6
|
import typing as ta
|
7
7
|
|
8
8
|
from .callers import LoggingCaller
|
9
|
+
from .levels import LogLevel
|
9
10
|
|
10
11
|
|
11
|
-
|
12
|
+
T = ta.TypeVar('T')
|
13
|
+
T_co = ta.TypeVar('T_co', covariant=True)
|
12
14
|
|
13
15
|
|
14
16
|
##
|
15
17
|
|
16
18
|
|
17
|
-
class
|
18
|
-
def isEnabledFor(self, level: LogLevel) -> bool: # noqa
|
19
|
-
...
|
19
|
+
class AnyLogging(ta.Protocol[T_co]):
|
20
|
+
def isEnabledFor(self, level: LogLevel) -> bool: ... # noqa
|
20
21
|
|
21
|
-
def getEffectiveLevel(self) -> LogLevel: # noqa
|
22
|
-
...
|
22
|
+
def getEffectiveLevel(self) -> LogLevel: ... # noqa
|
23
23
|
|
24
24
|
#
|
25
25
|
|
26
|
-
def debug(self, msg: str, *args: ta.Any, **kwargs: ta.Any) ->
|
27
|
-
|
26
|
+
def debug(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> T_co: ...
|
27
|
+
|
28
|
+
def info(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> T_co: ...
|
29
|
+
|
30
|
+
def warning(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> T_co: ...
|
31
|
+
|
32
|
+
def error(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> T_co: ...
|
28
33
|
|
29
|
-
def
|
30
|
-
...
|
34
|
+
def exception(self, msg: str, *args: ta.Any, exc_info: bool = True, **kwargs: ta.Any) -> T_co: ...
|
31
35
|
|
32
|
-
def
|
33
|
-
...
|
36
|
+
def critical(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> T_co: ...
|
34
37
|
|
35
|
-
def
|
36
|
-
...
|
38
|
+
def log(self, level: LogLevel, msg: str, *args: ta.Any, **kwargs: ta.Any) -> T_co: ...
|
37
39
|
|
38
|
-
def exception(self, msg: str, *args: ta.Any, exc_info: bool = True, **kwargs) -> None:
|
39
|
-
...
|
40
40
|
|
41
|
-
|
42
|
-
|
41
|
+
class Logging(AnyLogging[None], ta.Protocol):
|
42
|
+
pass
|
43
43
|
|
44
|
-
|
45
|
-
|
44
|
+
|
45
|
+
class AsyncLogging(AnyLogging[ta.Awaitable[None]], ta.Protocol):
|
46
|
+
pass
|
46
47
|
|
47
48
|
|
48
49
|
##
|
49
50
|
|
50
51
|
|
51
|
-
class
|
52
|
+
class AnyAbstractLogging(abc.ABC, ta.Generic[T]):
|
52
53
|
@ta.final
|
53
54
|
def isEnabledFor(self, level: LogLevel) -> bool: # noqa
|
54
55
|
return self.is_enabled_for(level)
|
@@ -66,34 +67,44 @@ class AbstractLogging(abc.ABC):
|
|
66
67
|
|
67
68
|
#
|
68
69
|
|
69
|
-
def debug(self, msg: str, *args: ta.Any, **kwargs: ta.Any) ->
|
70
|
-
|
71
|
-
self.log(logging.DEBUG, msg, args, **kwargs)
|
70
|
+
def debug(self, msg: str, *args: ta.Any, _logging_stack_offset: int = 0, **kwargs: ta.Any) -> T:
|
71
|
+
return self.log(logging.DEBUG, msg, *args, _logging_stack_offset=_logging_stack_offset + 1, **kwargs)
|
72
72
|
|
73
|
-
def info(self, msg: str, *args: ta.Any, **kwargs: ta.Any) ->
|
74
|
-
|
75
|
-
self.log(logging.INFO, msg, args, **kwargs)
|
73
|
+
def info(self, msg: str, *args: ta.Any, _logging_stack_offset: int = 0, **kwargs: ta.Any) -> T:
|
74
|
+
return self.log(logging.INFO, msg, *args, _logging_stack_offset=_logging_stack_offset + 1, **kwargs)
|
76
75
|
|
77
|
-
def warning(self, msg: str, *args: ta.Any, **kwargs: ta.Any) ->
|
78
|
-
|
79
|
-
self.log(logging.WARNING, msg, args, **kwargs)
|
76
|
+
def warning(self, msg: str, *args: ta.Any, _logging_stack_offset: int = 0, **kwargs: ta.Any) -> T:
|
77
|
+
return self.log(logging.WARNING, msg, *args, _logging_stack_offset=_logging_stack_offset + 1, **kwargs)
|
80
78
|
|
81
|
-
def error(self, msg: str, *args: ta.Any, **kwargs: ta.Any) ->
|
82
|
-
|
83
|
-
self.log(logging.ERROR, msg, args, **kwargs)
|
79
|
+
def error(self, msg: str, *args: ta.Any, _logging_stack_offset: int = 0, **kwargs: ta.Any) -> T:
|
80
|
+
return self.log(logging.ERROR, msg, *args, _logging_stack_offset=_logging_stack_offset + 1, **kwargs)
|
84
81
|
|
85
|
-
def exception(self, msg: str, *args: ta.Any, exc_info: bool = True, **kwargs: ta.Any) ->
|
86
|
-
self.error(msg, *args, exc_info=exc_info, **kwargs)
|
82
|
+
def exception(self, msg: str, *args: ta.Any, exc_info: bool = True, _logging_stack_offset: int = 0, **kwargs: ta.Any) -> T: # noqa
|
83
|
+
return self.error(msg, *args, exc_info=exc_info, _logging_stack_offset=_logging_stack_offset + 1, **kwargs) # noqa
|
87
84
|
|
88
|
-
def critical(self, msg: str, *args: ta.Any, **kwargs: ta.Any) ->
|
89
|
-
|
90
|
-
self.log(logging.CRITICAL, msg, args, **kwargs)
|
85
|
+
def critical(self, msg: str, *args: ta.Any, _logging_stack_offset: int = 0, **kwargs: ta.Any) -> T:
|
86
|
+
return self.log(logging.CRITICAL, msg, *args, _logging_stack_offset=_logging_stack_offset + 1, **kwargs)
|
91
87
|
|
92
|
-
|
88
|
+
@abc.abstractmethod
|
89
|
+
def log(
|
90
|
+
self,
|
91
|
+
level: int,
|
92
|
+
msg: str,
|
93
|
+
*args: ta.Any,
|
94
|
+
exc_info: ta.Any = None,
|
95
|
+
extra: ta.Any = None,
|
96
|
+
stack_info: bool = False,
|
97
|
+
_logging_stack_offset: int = 0,
|
98
|
+
) -> T:
|
99
|
+
raise NotImplementedError
|
100
|
+
|
101
|
+
|
102
|
+
class AbstractLogging(AnyAbstractLogging[None], abc.ABC):
|
103
|
+
def log(self, level: LogLevel, msg: str, *args: ta.Any, _logging_stack_offset: int = 0, **kwargs: ta.Any) -> None:
|
93
104
|
if not isinstance(level, int):
|
94
105
|
raise TypeError('Level must be an integer.')
|
95
106
|
if self.is_enabled_for(level):
|
96
|
-
self._log(level, msg, args, **kwargs)
|
107
|
+
self._log(level, msg, args, _logging_stack_offset=_logging_stack_offset + 1, **kwargs)
|
97
108
|
|
98
109
|
@abc.abstractmethod
|
99
110
|
def _log(
|
@@ -105,21 +116,51 @@ class AbstractLogging(abc.ABC):
|
|
105
116
|
exc_info: ta.Any = None,
|
106
117
|
extra: ta.Any = None,
|
107
118
|
stack_info: bool = False,
|
119
|
+
_logging_stack_offset: int = 0,
|
108
120
|
) -> None:
|
109
121
|
raise NotImplementedError
|
110
122
|
|
111
123
|
|
124
|
+
class AbstractAsyncLogging(AnyAbstractLogging[ta.Awaitable[None]], abc.ABC):
|
125
|
+
async def log(self, level: LogLevel, msg: str, *args: ta.Any, _logging_stack_offset: int = 0, **kwargs: ta.Any) -> None: # noqa
|
126
|
+
if not isinstance(level, int):
|
127
|
+
raise TypeError('Level must be an integer.')
|
128
|
+
if self.is_enabled_for(level):
|
129
|
+
await self._log(level, msg, args, _logging_stack_offset=_logging_stack_offset + 1, **kwargs)
|
130
|
+
|
131
|
+
@abc.abstractmethod
|
132
|
+
def _log(
|
133
|
+
self,
|
134
|
+
level: int,
|
135
|
+
msg: str,
|
136
|
+
args: ta.Any,
|
137
|
+
*,
|
138
|
+
exc_info: ta.Any = None,
|
139
|
+
extra: ta.Any = None,
|
140
|
+
stack_info: bool = False,
|
141
|
+
_logging_stack_offset: int = 0,
|
142
|
+
) -> ta.Awaitable[None]:
|
143
|
+
raise NotImplementedError
|
144
|
+
|
145
|
+
|
112
146
|
##
|
113
147
|
|
114
148
|
|
115
|
-
class
|
149
|
+
class AnyNopLogging(AnyAbstractLogging[T], abc.ABC):
|
116
150
|
def get_effective_level(self) -> LogLevel:
|
117
151
|
return logging.CRITICAL + 1
|
118
152
|
|
153
|
+
|
154
|
+
class NopLogging(AnyNopLogging[None], AbstractLogging):
|
119
155
|
def _log(self, *args: ta.Any, **kwargs: ta.Any) -> None:
|
120
156
|
pass
|
121
157
|
|
122
158
|
|
159
|
+
class NopAsyncLogging(AnyNopLogging[ta.Awaitable[None]], AbstractAsyncLogging):
|
160
|
+
async def _log(self, *args: ta.Any, **kwargs: ta.Any) -> None:
|
161
|
+
pass
|
162
|
+
|
163
|
+
|
123
164
|
##
|
124
165
|
|
125
166
|
|
@@ -151,8 +192,9 @@ class StdlibLogging(AbstractLogging):
|
|
151
192
|
exc_info: ta.Any = None,
|
152
193
|
extra: ta.Any = None,
|
153
194
|
stack_info: bool = False,
|
195
|
+
_logging_stack_offset: int = 0,
|
154
196
|
) -> None:
|
155
|
-
caller = LoggingCaller.find(stack_info)
|
197
|
+
caller = LoggingCaller.find(_logging_stack_offset, stack_info=stack_info)
|
156
198
|
|
157
199
|
if exc_info:
|
158
200
|
if isinstance(exc_info, BaseException):
|
File without changes
|