omlish 0.0.0.dev1__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.
Potentially problematic release.
This version of omlish might be problematic. Click here for more details.
- omlish/__about__.py +7 -0
- omlish/__init__.py +0 -0
- omlish/argparse.py +223 -0
- omlish/asyncs/__init__.py +17 -0
- omlish/asyncs/anyio.py +23 -0
- omlish/asyncs/asyncio.py +19 -0
- omlish/asyncs/asyncs.py +76 -0
- omlish/asyncs/futures.py +179 -0
- omlish/asyncs/trio.py +11 -0
- omlish/c3.py +173 -0
- omlish/cached.py +9 -0
- omlish/check.py +231 -0
- omlish/collections/__init__.py +63 -0
- omlish/collections/_abc.py +156 -0
- omlish/collections/_io_abc.py +78 -0
- omlish/collections/cache/__init__.py +11 -0
- omlish/collections/cache/descriptor.py +188 -0
- omlish/collections/cache/impl.py +485 -0
- omlish/collections/cache/types.py +37 -0
- omlish/collections/coerce.py +337 -0
- omlish/collections/frozen.py +148 -0
- omlish/collections/identity.py +106 -0
- omlish/collections/indexed.py +75 -0
- omlish/collections/mappings.py +127 -0
- omlish/collections/ordered.py +81 -0
- omlish/collections/persistent.py +36 -0
- omlish/collections/skiplist.py +193 -0
- omlish/collections/sorted.py +126 -0
- omlish/collections/treap.py +228 -0
- omlish/collections/treapmap.py +144 -0
- omlish/collections/unmodifiable.py +174 -0
- omlish/collections/utils.py +110 -0
- omlish/configs/__init__.py +0 -0
- omlish/configs/flattening.py +147 -0
- omlish/configs/props.py +64 -0
- omlish/dataclasses/__init__.py +83 -0
- omlish/dataclasses/impl/__init__.py +6 -0
- omlish/dataclasses/impl/api.py +260 -0
- omlish/dataclasses/impl/as_.py +76 -0
- omlish/dataclasses/impl/exceptions.py +2 -0
- omlish/dataclasses/impl/fields.py +148 -0
- omlish/dataclasses/impl/frozen.py +55 -0
- omlish/dataclasses/impl/hashing.py +85 -0
- omlish/dataclasses/impl/init.py +173 -0
- omlish/dataclasses/impl/internals.py +118 -0
- omlish/dataclasses/impl/main.py +150 -0
- omlish/dataclasses/impl/metaclass.py +126 -0
- omlish/dataclasses/impl/metadata.py +74 -0
- omlish/dataclasses/impl/order.py +47 -0
- omlish/dataclasses/impl/params.py +150 -0
- omlish/dataclasses/impl/processing.py +16 -0
- omlish/dataclasses/impl/reflect.py +173 -0
- omlish/dataclasses/impl/replace.py +40 -0
- omlish/dataclasses/impl/repr.py +34 -0
- omlish/dataclasses/impl/simple.py +92 -0
- omlish/dataclasses/impl/slots.py +80 -0
- omlish/dataclasses/impl/utils.py +167 -0
- omlish/defs.py +193 -0
- omlish/dispatch/__init__.py +3 -0
- omlish/dispatch/dispatch.py +137 -0
- omlish/dispatch/functions.py +52 -0
- omlish/dispatch/methods.py +162 -0
- omlish/docker.py +149 -0
- omlish/dynamic.py +220 -0
- omlish/graphs/__init__.py +0 -0
- omlish/graphs/dot/__init__.py +19 -0
- omlish/graphs/dot/items.py +162 -0
- omlish/graphs/dot/rendering.py +147 -0
- omlish/graphs/dot/utils.py +30 -0
- omlish/graphs/trees.py +249 -0
- omlish/http/__init__.py +0 -0
- omlish/http/consts.py +20 -0
- omlish/http/wsgi.py +34 -0
- omlish/inject/__init__.py +85 -0
- omlish/inject/binder.py +12 -0
- omlish/inject/bindings.py +49 -0
- omlish/inject/eagers.py +21 -0
- omlish/inject/elements.py +43 -0
- omlish/inject/exceptions.py +49 -0
- omlish/inject/impl/__init__.py +0 -0
- omlish/inject/impl/bindings.py +19 -0
- omlish/inject/impl/elements.py +154 -0
- omlish/inject/impl/injector.py +182 -0
- omlish/inject/impl/inspect.py +98 -0
- omlish/inject/impl/private.py +109 -0
- omlish/inject/impl/providers.py +132 -0
- omlish/inject/impl/scopes.py +198 -0
- omlish/inject/injector.py +40 -0
- omlish/inject/inspect.py +14 -0
- omlish/inject/keys.py +43 -0
- omlish/inject/managed.py +24 -0
- omlish/inject/overrides.py +18 -0
- omlish/inject/private.py +29 -0
- omlish/inject/providers.py +111 -0
- omlish/inject/proxy.py +48 -0
- omlish/inject/scopes.py +84 -0
- omlish/inject/types.py +21 -0
- omlish/iterators.py +184 -0
- omlish/json.py +194 -0
- omlish/lang/__init__.py +112 -0
- omlish/lang/cached.py +267 -0
- omlish/lang/classes/__init__.py +24 -0
- omlish/lang/classes/abstract.py +74 -0
- omlish/lang/classes/restrict.py +137 -0
- omlish/lang/classes/simple.py +120 -0
- omlish/lang/classes/test/__init__.py +0 -0
- omlish/lang/classes/test/test_abstract.py +89 -0
- omlish/lang/classes/test/test_restrict.py +71 -0
- omlish/lang/classes/test/test_simple.py +58 -0
- omlish/lang/classes/test/test_virtual.py +72 -0
- omlish/lang/classes/virtual.py +130 -0
- omlish/lang/clsdct.py +67 -0
- omlish/lang/cmp.py +63 -0
- omlish/lang/contextmanagers.py +249 -0
- omlish/lang/datetimes.py +67 -0
- omlish/lang/descriptors.py +52 -0
- omlish/lang/functions.py +126 -0
- omlish/lang/imports.py +153 -0
- omlish/lang/iterables.py +54 -0
- omlish/lang/maybes.py +136 -0
- omlish/lang/objects.py +103 -0
- omlish/lang/resolving.py +50 -0
- omlish/lang/strings.py +128 -0
- omlish/lang/typing.py +92 -0
- omlish/libc.py +532 -0
- omlish/logs/__init__.py +9 -0
- omlish/logs/_abc.py +247 -0
- omlish/logs/configs.py +62 -0
- omlish/logs/filters.py +9 -0
- omlish/logs/formatters.py +67 -0
- omlish/logs/utils.py +20 -0
- omlish/marshal/__init__.py +52 -0
- omlish/marshal/any.py +25 -0
- omlish/marshal/base.py +201 -0
- omlish/marshal/base64.py +25 -0
- omlish/marshal/dataclasses.py +115 -0
- omlish/marshal/datetimes.py +90 -0
- omlish/marshal/enums.py +43 -0
- omlish/marshal/exceptions.py +7 -0
- omlish/marshal/factories.py +129 -0
- omlish/marshal/global_.py +33 -0
- omlish/marshal/iterables.py +57 -0
- omlish/marshal/mappings.py +66 -0
- omlish/marshal/naming.py +17 -0
- omlish/marshal/objects.py +106 -0
- omlish/marshal/optionals.py +49 -0
- omlish/marshal/polymorphism.py +147 -0
- omlish/marshal/primitives.py +43 -0
- omlish/marshal/registries.py +57 -0
- omlish/marshal/standard.py +80 -0
- omlish/marshal/utils.py +23 -0
- omlish/marshal/uuids.py +29 -0
- omlish/marshal/values.py +30 -0
- omlish/math.py +184 -0
- omlish/os.py +32 -0
- omlish/reflect.py +359 -0
- omlish/replserver/__init__.py +5 -0
- omlish/replserver/__main__.py +4 -0
- omlish/replserver/console.py +247 -0
- omlish/replserver/server.py +146 -0
- omlish/runmodule.py +28 -0
- omlish/stats.py +342 -0
- omlish/term.py +222 -0
- omlish/testing/__init__.py +7 -0
- omlish/testing/pydevd.py +225 -0
- omlish/testing/pytest/__init__.py +8 -0
- omlish/testing/pytest/helpers.py +35 -0
- omlish/testing/pytest/inject/__init__.py +1 -0
- omlish/testing/pytest/inject/harness.py +159 -0
- omlish/testing/pytest/plugins/__init__.py +20 -0
- omlish/testing/pytest/plugins/_registry.py +6 -0
- omlish/testing/pytest/plugins/logging.py +13 -0
- omlish/testing/pytest/plugins/pycharm.py +54 -0
- omlish/testing/pytest/plugins/repeat.py +19 -0
- omlish/testing/pytest/plugins/skips.py +32 -0
- omlish/testing/pytest/plugins/spacing.py +19 -0
- omlish/testing/pytest/plugins/switches.py +70 -0
- omlish/testing/testing.py +102 -0
- omlish/text/__init__.py +0 -0
- omlish/text/delimit.py +171 -0
- omlish/text/indent.py +50 -0
- omlish/text/parts.py +265 -0
- omlish-0.0.0.dev1.dist-info/LICENSE +21 -0
- omlish-0.0.0.dev1.dist-info/METADATA +17 -0
- omlish-0.0.0.dev1.dist-info/RECORD +187 -0
- omlish-0.0.0.dev1.dist-info/WHEEL +5 -0
- omlish-0.0.0.dev1.dist-info/top_level.txt +1 -0
omlish/logs/_abc.py
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import types
|
|
2
|
+
import typing as ta
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
Level: ta.TypeAlias = int
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
ExceptionInfo: ta.TypeAlias = tuple[type[BaseException], BaseException, types.TracebackType]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class LogRecord:
|
|
15
|
+
name: str
|
|
16
|
+
msg: str
|
|
17
|
+
args: tuple
|
|
18
|
+
levelname: str
|
|
19
|
+
levelno: Level
|
|
20
|
+
pathname: str
|
|
21
|
+
filename: str
|
|
22
|
+
module: str
|
|
23
|
+
exc_info: ExceptionInfo | None
|
|
24
|
+
exc_text: str | None
|
|
25
|
+
stack_info: str | None
|
|
26
|
+
lineno: int
|
|
27
|
+
funcName: str
|
|
28
|
+
created: float
|
|
29
|
+
msecs: float
|
|
30
|
+
relativeCreated: float
|
|
31
|
+
thread: int
|
|
32
|
+
threadName: str
|
|
33
|
+
processName: str
|
|
34
|
+
process: int
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
##
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class Formatter(ta.Protocol):
|
|
41
|
+
default_time_format: ta.ClassVar[str]
|
|
42
|
+
default_msec_format: ta.ClassVar[str]
|
|
43
|
+
|
|
44
|
+
def formatTime(self, record: LogRecord, datefmt: str | None = None) -> str: ...
|
|
45
|
+
|
|
46
|
+
def formatException(self, ei: ExceptionInfo) -> str: ...
|
|
47
|
+
|
|
48
|
+
def usesTime(self) -> bool: ...
|
|
49
|
+
|
|
50
|
+
def formatMessage(self, record: LogRecord) -> str: ...
|
|
51
|
+
|
|
52
|
+
def formatStack(self, stack_info: str) -> str: ...
|
|
53
|
+
|
|
54
|
+
def format(self, record: LogRecord) -> str: ...
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class BufferingFormatter(ta.Protocol):
|
|
58
|
+
def formatHeader(self, records: ta.Sequence[LogRecord]) -> str: ...
|
|
59
|
+
|
|
60
|
+
def formatFooter(self, records: ta.Sequence[LogRecord]) -> str: ...
|
|
61
|
+
|
|
62
|
+
def format(self, records: ta.Sequence[LogRecord]) -> str: ...
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
##
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class Filter(ta.Protocol):
|
|
69
|
+
def filter(self, record: LogRecord) -> bool: ...
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class Filterer(ta.Protocol):
|
|
73
|
+
def addFilter(self, filter: Filter) -> None: ...
|
|
74
|
+
|
|
75
|
+
def removeFilter(self, filter: Filter) -> None: ...
|
|
76
|
+
|
|
77
|
+
def filter(self, record: LogRecord) -> bool: ...
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
##
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class Handler(ta.Protocol):
|
|
84
|
+
level: Level
|
|
85
|
+
|
|
86
|
+
def get_name(self) -> str: ...
|
|
87
|
+
|
|
88
|
+
def set_name(self, name: str) -> None: ...
|
|
89
|
+
|
|
90
|
+
name: str
|
|
91
|
+
|
|
92
|
+
def createLock(self) -> None: ...
|
|
93
|
+
|
|
94
|
+
def acquire(self) -> None: ...
|
|
95
|
+
|
|
96
|
+
def release(self) -> None: ...
|
|
97
|
+
|
|
98
|
+
def setLevel(self, level: Level) -> None: ...
|
|
99
|
+
|
|
100
|
+
def format(self, record: LogRecord) -> str: ...
|
|
101
|
+
|
|
102
|
+
def emit(self, record: LogRecord) -> None: ...
|
|
103
|
+
|
|
104
|
+
def handle(self, record: LogRecord) -> bool: ...
|
|
105
|
+
|
|
106
|
+
def setFormatter(self, fmt: Formatter) -> None: ...
|
|
107
|
+
|
|
108
|
+
def flush(self) -> None: ...
|
|
109
|
+
|
|
110
|
+
def close(self) -> None: ...
|
|
111
|
+
|
|
112
|
+
def handleError(self, record: LogRecord) -> None: ...
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class Stream(ta.Protocol):
|
|
116
|
+
def write(self, s: str) -> None: ...
|
|
117
|
+
|
|
118
|
+
def flush(self) -> None: ... # OPTIONAL METHOD
|
|
119
|
+
|
|
120
|
+
def close(self) -> None: ... # OPTIONAL METHOD
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class StreamHandler(Handler):
|
|
124
|
+
terminator: ta.ClassVar[str]
|
|
125
|
+
|
|
126
|
+
stream: Stream
|
|
127
|
+
|
|
128
|
+
def flush(self) -> None: ...
|
|
129
|
+
|
|
130
|
+
def emit(self, record: LogRecord) -> None: ...
|
|
131
|
+
|
|
132
|
+
def setStream(self, stream: Stream) -> None: ...
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
##
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class Manager(ta.Protocol):
|
|
139
|
+
root: 'Logger'
|
|
140
|
+
|
|
141
|
+
disable: Level
|
|
142
|
+
|
|
143
|
+
def getLogger(self, name: str) -> 'Logger': ...
|
|
144
|
+
|
|
145
|
+
def setLoggerClass(self, klass: type['Logger']) -> None: ...
|
|
146
|
+
|
|
147
|
+
def setLogRecordFactory(self, factory: ta.Callable[..., LogRecord]) -> None: ... # UNREFERENCED?
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
##
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
Caller: ta.TypeAlias = tuple[
|
|
154
|
+
str, # filename
|
|
155
|
+
int, # lineno
|
|
156
|
+
str, # name
|
|
157
|
+
str, # formatted
|
|
158
|
+
]
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
class Logger(Filterer, ta.Protocol):
|
|
162
|
+
name: str
|
|
163
|
+
level: Level
|
|
164
|
+
parent: ta.Optional['Logger']
|
|
165
|
+
propagate: bool
|
|
166
|
+
handlers: list[Handler]
|
|
167
|
+
disabled: bool
|
|
168
|
+
|
|
169
|
+
manager: Manager
|
|
170
|
+
|
|
171
|
+
def setLevel(self, level: Level) -> None: ...
|
|
172
|
+
|
|
173
|
+
def debug(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> None: ...
|
|
174
|
+
def info(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> None: ...
|
|
175
|
+
def warning(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> None: ...
|
|
176
|
+
def warn(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> None: ...
|
|
177
|
+
def error(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> None: ...
|
|
178
|
+
def exception(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> None: ...
|
|
179
|
+
def critical(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> None: ...
|
|
180
|
+
def fatal(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> None: ...
|
|
181
|
+
|
|
182
|
+
def log(self, level: Level, msg: str, *args: ta.Any, **kwargs: ta.Any) -> None: ...
|
|
183
|
+
|
|
184
|
+
def findCaller(self, stack_info: bool = False, stacklevel: int = 1) -> Caller: ... #
|
|
185
|
+
|
|
186
|
+
def makeRecord(
|
|
187
|
+
self,
|
|
188
|
+
name,
|
|
189
|
+
level,
|
|
190
|
+
fn,
|
|
191
|
+
lno,
|
|
192
|
+
msg,
|
|
193
|
+
args,
|
|
194
|
+
exc_info,
|
|
195
|
+
func: str | None = None,
|
|
196
|
+
extra: ta.Mapping[str, ta.Any] | None = None,
|
|
197
|
+
sinfo: str | None = None,
|
|
198
|
+
) -> LogRecord: ...
|
|
199
|
+
|
|
200
|
+
def handle(self, record: LogRecord) -> None: ...
|
|
201
|
+
|
|
202
|
+
def addHandler(self, hdlr: Handler) -> None: ...
|
|
203
|
+
|
|
204
|
+
def removeHandler(self, hdlr: Handler) -> None: ...
|
|
205
|
+
|
|
206
|
+
def hasHandlers(self) -> bool: ...
|
|
207
|
+
|
|
208
|
+
def callHandlers(self, record: LogRecord) -> None: ...
|
|
209
|
+
|
|
210
|
+
def getEffectiveLevel(self) -> Level: ...
|
|
211
|
+
|
|
212
|
+
def isEnabledFor(self, level: Level) -> bool: ...
|
|
213
|
+
|
|
214
|
+
def getChild(self, suffix: str) -> 'Logger': ...
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
##
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
class LoggerAdapter(ta.Protocol):
|
|
221
|
+
logger: Logger
|
|
222
|
+
extra: ta.Mapping[str, ta.Any]
|
|
223
|
+
|
|
224
|
+
def process(self, msg: str, kwargs: dict[str, ta.Any]) -> tuple[str, dict[str, ta.Any]]: ...
|
|
225
|
+
|
|
226
|
+
def debug(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> None: ...
|
|
227
|
+
def info(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> None: ...
|
|
228
|
+
def warning(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> None: ...
|
|
229
|
+
def warn(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> None: ...
|
|
230
|
+
def error(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> None: ...
|
|
231
|
+
def exception(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> None: ...
|
|
232
|
+
def critical(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> None: ...
|
|
233
|
+
def fatal(self, msg: str, *args: ta.Any, **kwargs: ta.Any) -> None: ...
|
|
234
|
+
|
|
235
|
+
def log(self, level: Level, msg: str, *args: ta.Any, **kwargs: ta.Any) -> None: ...
|
|
236
|
+
|
|
237
|
+
def isEnabledFor(self, level: Level) -> bool: ...
|
|
238
|
+
|
|
239
|
+
def setLevel(self, level: Level) -> None: ...
|
|
240
|
+
|
|
241
|
+
def getEffectiveLevel(self) -> Level: ...
|
|
242
|
+
|
|
243
|
+
def hasHandlers(self) -> bool: ...
|
|
244
|
+
|
|
245
|
+
manager: Manager
|
|
246
|
+
|
|
247
|
+
name: str
|
omlish/logs/configs.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import dataclasses as dc
|
|
2
|
+
import logging
|
|
3
|
+
import typing as ta
|
|
4
|
+
|
|
5
|
+
from .filters import TidFilter
|
|
6
|
+
from .formatters import StandardLogFormatter
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
NOISY_LOGGERS: set[str] = {
|
|
10
|
+
'boto3.resources.action',
|
|
11
|
+
'datadog.dogstatsd',
|
|
12
|
+
'elasticsearch',
|
|
13
|
+
'kazoo.client',
|
|
14
|
+
'requests.packages.urllib3.connectionpool',
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dc.dataclass()
|
|
19
|
+
class DictConfig:
|
|
20
|
+
version: int = 1
|
|
21
|
+
incremental: bool = False
|
|
22
|
+
disable_existing_loggers: bool = False
|
|
23
|
+
filters: dict[str, 'FilterConfig'] = dc.field(default_factory=dict)
|
|
24
|
+
formatters: dict[str, 'FormatterConfig'] = dc.field(default_factory=dict)
|
|
25
|
+
handlers: dict[str, 'HandlerConfig'] = dc.field(default_factory=dict)
|
|
26
|
+
loggers: dict[str, 'LoggerConfig'] = dc.field(default_factory=dict)
|
|
27
|
+
root: ta.Optional['LoggerConfig'] = None
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
FilterConfig = dict[str, ta.Any]
|
|
31
|
+
FormatterConfig = dict[str, ta.Any]
|
|
32
|
+
HandlerConfig = dict[str, ta.Any]
|
|
33
|
+
LoggerConfig = dict[str, ta.Any]
|
|
34
|
+
|
|
35
|
+
STANDARD_LOG_FORMAT_PARTS = [
|
|
36
|
+
('asctime', '%(asctime)-15s'),
|
|
37
|
+
('process', 'pid=%(process)-6s'),
|
|
38
|
+
('thread', 'tid=%(thread)-16s'),
|
|
39
|
+
('levelname', '%(levelname)-8s'),
|
|
40
|
+
('name', '%(name)s'),
|
|
41
|
+
('separator', '::'),
|
|
42
|
+
('message', '%(message)s'),
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def build_log_format(parts: ta.Iterable[tuple[str, str]]) -> str:
|
|
47
|
+
return ' '.join(v for k, v in parts)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def configure_standard_logging(level: ta.Any = None) -> logging.Handler:
|
|
51
|
+
handler = logging.StreamHandler()
|
|
52
|
+
handler.setFormatter(StandardLogFormatter(build_log_format(STANDARD_LOG_FORMAT_PARTS)))
|
|
53
|
+
handler.addFilter(TidFilter())
|
|
54
|
+
logging.root.addHandler(handler)
|
|
55
|
+
|
|
56
|
+
if level is not None:
|
|
57
|
+
logging.root.setLevel(level)
|
|
58
|
+
|
|
59
|
+
for noisy_logger in NOISY_LOGGERS:
|
|
60
|
+
logging.getLogger(noisy_logger).setLevel(logging.WARNING)
|
|
61
|
+
|
|
62
|
+
return handler
|
omlish/logs/filters.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import logging
|
|
3
|
+
|
|
4
|
+
from .. import json
|
|
5
|
+
from .. import term
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class StandardLogFormatter(logging.Formatter):
|
|
9
|
+
|
|
10
|
+
converter = datetime.datetime.fromtimestamp # type: ignore
|
|
11
|
+
|
|
12
|
+
def formatTime(self, record, datefmt=None):
|
|
13
|
+
ct = self.converter(record.created) # type: ignore
|
|
14
|
+
if datefmt:
|
|
15
|
+
return ct.strftime(datefmt) # noqa
|
|
16
|
+
else:
|
|
17
|
+
t = ct.strftime("%Y-%m-%d %H:%M:%S") # noqa
|
|
18
|
+
return '%s.%03d' % (t, record.msecs)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ColorLogFormatter(StandardLogFormatter):
|
|
22
|
+
|
|
23
|
+
LEVEL_COLORS = {
|
|
24
|
+
logging.WARNING: term.SGRs.FG.BRIGHT_YELLOW,
|
|
25
|
+
logging.ERROR: term.SGRs.FG.BRIGHT_RED,
|
|
26
|
+
logging.CRITICAL: term.SGRs.FG.BRIGHT_RED,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
def formatMessage(self, record):
|
|
30
|
+
buf = super().formatMessage(record)
|
|
31
|
+
try:
|
|
32
|
+
c = self.LEVEL_COLORS[record.levelno]
|
|
33
|
+
except KeyError:
|
|
34
|
+
pass
|
|
35
|
+
else:
|
|
36
|
+
buf = term.SGR(c) + buf + term.SGR(term.SGRs.RESET)
|
|
37
|
+
return buf
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class JsonLogFormatter(logging.Formatter):
|
|
41
|
+
|
|
42
|
+
KEYS = {
|
|
43
|
+
'name': False,
|
|
44
|
+
'msg': False,
|
|
45
|
+
'args': False,
|
|
46
|
+
'levelname': False,
|
|
47
|
+
'levelno': False,
|
|
48
|
+
'pathname': False,
|
|
49
|
+
'filename': False,
|
|
50
|
+
'module': False,
|
|
51
|
+
'exc_info': True,
|
|
52
|
+
'exc_text': True,
|
|
53
|
+
'stack_info': True,
|
|
54
|
+
'lineno': False,
|
|
55
|
+
'funcName': False,
|
|
56
|
+
'created': False,
|
|
57
|
+
'msecs': False,
|
|
58
|
+
'relativeCreated': False,
|
|
59
|
+
'thread': False,
|
|
60
|
+
'threadName': False,
|
|
61
|
+
'processName': False,
|
|
62
|
+
'process': False,
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
def format(self, record: logging.LogRecord) -> str:
|
|
66
|
+
dct = {k: v for k, o in self.KEYS.items() for v in [getattr(record, k)] if not (o and v is None)}
|
|
67
|
+
return json.dumps_compact(dct)
|
omlish/logs/utils.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
import logging
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
log = logging.getLogger(__name__)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def error_logging(log=log):
|
|
9
|
+
def outer(fn):
|
|
10
|
+
@functools.wraps(fn)
|
|
11
|
+
def inner(*args, **kwargs):
|
|
12
|
+
try:
|
|
13
|
+
return fn(*args, **kwargs)
|
|
14
|
+
except Exception:
|
|
15
|
+
log.exception(f'Error in {fn!r}')
|
|
16
|
+
raise
|
|
17
|
+
|
|
18
|
+
return inner
|
|
19
|
+
|
|
20
|
+
return outer
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from .base import ( # noqa
|
|
2
|
+
Marshaler,
|
|
3
|
+
Unmarshaler,
|
|
4
|
+
|
|
5
|
+
MarshalerFactory,
|
|
6
|
+
UnmarshalerFactory,
|
|
7
|
+
|
|
8
|
+
FuncMarshaler,
|
|
9
|
+
FuncUnmarshaler,
|
|
10
|
+
|
|
11
|
+
BaseContext,
|
|
12
|
+
MarshalContext,
|
|
13
|
+
UnmarshalContext,
|
|
14
|
+
|
|
15
|
+
RecursiveMarshalerFactory,
|
|
16
|
+
RecursiveUnmarshalerFactory,
|
|
17
|
+
|
|
18
|
+
SetType,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
from .naming import ( # noqa
|
|
22
|
+
Naming,
|
|
23
|
+
translate_name,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
from .global_ import ( # noqa
|
|
27
|
+
marshal,
|
|
28
|
+
unmarshal,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
from .objects import ( # noqa
|
|
32
|
+
FieldMetadata,
|
|
33
|
+
ObjectMetadata,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
from .polymorphism import ( # noqa
|
|
37
|
+
Impl,
|
|
38
|
+
Polymorphism,
|
|
39
|
+
polymorphism_from_subclasses,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
from .registries import ( # noqa
|
|
43
|
+
Registry,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
from .standard import ( # noqa
|
|
47
|
+
STANDARD_MARSHALER_FACTORIES,
|
|
48
|
+
new_standard_marshaler_factory,
|
|
49
|
+
|
|
50
|
+
STANDARD_UNMARSHALER_FACTORIES,
|
|
51
|
+
new_standard_unmarshaler_factory,
|
|
52
|
+
)
|
omlish/marshal/any.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
3
|
+
from .base import MarshalContext
|
|
4
|
+
from .base import Marshaler
|
|
5
|
+
from .base import MarshalerFactory
|
|
6
|
+
from .base import UnmarshalContext
|
|
7
|
+
from .base import Unmarshaler
|
|
8
|
+
from .base import UnmarshalerFactory
|
|
9
|
+
from .factories import TypeMapFactory
|
|
10
|
+
from .values import Value
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class AnyMarshalerUnmarshaler(Marshaler, Unmarshaler):
|
|
14
|
+
|
|
15
|
+
def marshal(self, ctx: MarshalContext, o: ta.Any) -> Value:
|
|
16
|
+
return ctx.make(type(o)).marshal(ctx, o)
|
|
17
|
+
|
|
18
|
+
def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any:
|
|
19
|
+
return v
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
ANY_MARSHALER_UNMARSHALER = AnyMarshalerUnmarshaler()
|
|
23
|
+
|
|
24
|
+
ANY_MARSHALER_FACTORY: MarshalerFactory = TypeMapFactory({ta.Any: ANY_MARSHALER_UNMARSHALER}) # type: ignore
|
|
25
|
+
ANY_UNMARSHALER_FACTORY: UnmarshalerFactory = TypeMapFactory({ta.Any: ANY_MARSHALER_UNMARSHALER}) # type: ignore
|
omlish/marshal/base.py
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TODO:
|
|
3
|
+
- mappings
|
|
4
|
+
- redacted
|
|
5
|
+
- strongly typed Composite/Cached Marshaler/Unmarshaler factories - footgun
|
|
6
|
+
- streaming? Start/EndObject, etc..
|
|
7
|
+
|
|
8
|
+
https://github.com/python-attrs/cattrs:
|
|
9
|
+
*
|
|
10
|
+
|
|
11
|
+
Jackson:
|
|
12
|
+
- USE_ANNOTATIONS
|
|
13
|
+
- AUTO_DETECT_CREATORS
|
|
14
|
+
- AUTO_DETECT_FIELDS
|
|
15
|
+
- AUTO_DETECT_GETTERS
|
|
16
|
+
- AUTO_DETECT_IS_GETTERS
|
|
17
|
+
- AUTO_DETECT_SETTERS
|
|
18
|
+
- REQUIRE_SETTERS_FOR_GETTERS
|
|
19
|
+
- USE_GETTERS_AS_SETTERS
|
|
20
|
+
- INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES
|
|
21
|
+
- INFER_PROPERTY_MUTATORS
|
|
22
|
+
- ALLOW_FINAL_FIELDS_AS_MUTATORS
|
|
23
|
+
- ALLOW_VOID_VALUED_PROPERTIES
|
|
24
|
+
- CAN_OVERRIDE_ACCESS_MODIFIERS
|
|
25
|
+
- OVERRIDE_PUBLIC_ACCESS_MODIFIERS
|
|
26
|
+
- SORT_PROPERTIES_ALPHABETICALLY
|
|
27
|
+
- USE_WRAPPER_NAME_AS_PROPERTY_NAME
|
|
28
|
+
- ACCEPT_CASE_INSENSITIVE_ENUMS
|
|
29
|
+
- ACCEPT_CASE_INSENSITIVE_PROPERTIES
|
|
30
|
+
- ACCEPT_CASE_INSENSITIVE_VALUES
|
|
31
|
+
- ALLOW_EXPLICIT_PROPERTY_RENAMING
|
|
32
|
+
- USE_STD_BEAN_NAMING
|
|
33
|
+
- ALLOW_COERCION_OF_SCALARS
|
|
34
|
+
- DEFAULT_VIEW_INCLUSION
|
|
35
|
+
- IGNORE_DUPLICATE_MODULE_REGISTRATIONS
|
|
36
|
+
- IGNORE_MERGE_FOR_UNMERGEABLE
|
|
37
|
+
- USE_BASE_TYPE_AS_DEFAULT_IMPL
|
|
38
|
+
- USE_STATIC_TYPING
|
|
39
|
+
- BLOCK_UNSAFE_POLYMORPHIC_BASE_TYPES
|
|
40
|
+
|
|
41
|
+
https://github.com/yukinarit/pyserde
|
|
42
|
+
- datatypes
|
|
43
|
+
- typing.Union
|
|
44
|
+
- typing.NewType for primitive types
|
|
45
|
+
- typing.Any
|
|
46
|
+
- typing.Literal
|
|
47
|
+
- typing.Generic
|
|
48
|
+
- typing.ClassVar
|
|
49
|
+
- dataclasses.InitVar
|
|
50
|
+
- Enum and IntEnum
|
|
51
|
+
- pathlib.Path
|
|
52
|
+
- decimal.Decimal
|
|
53
|
+
- uuid.UUID
|
|
54
|
+
- datetime.date, datetime.time, datetime.datetime
|
|
55
|
+
- ipaddress
|
|
56
|
+
- numpy types
|
|
57
|
+
- Class Attributes
|
|
58
|
+
- Field Attributes
|
|
59
|
+
- Decorators
|
|
60
|
+
- Type Check
|
|
61
|
+
- Union Representation
|
|
62
|
+
- Forward reference
|
|
63
|
+
- PEP563 Postponed Evaluation of Annotations
|
|
64
|
+
- PEP585 Type Hinting Generics In Standard Collections
|
|
65
|
+
- PEP604 Allow writing union types as X | Y
|
|
66
|
+
- PEP681 Data Class Transform
|
|
67
|
+
- Case Conversion
|
|
68
|
+
- Rename
|
|
69
|
+
- Alias
|
|
70
|
+
- Skip (de)serialization (skip, skip_if, skip_if_false, skip_if_default)
|
|
71
|
+
- Custom field (de)serializer
|
|
72
|
+
- Custom class (de)serializer
|
|
73
|
+
- Custom global (de)serializer
|
|
74
|
+
- Flatten
|
|
75
|
+
"""
|
|
76
|
+
import abc
|
|
77
|
+
import dataclasses as dc
|
|
78
|
+
import typing as ta
|
|
79
|
+
|
|
80
|
+
from .. import check
|
|
81
|
+
from .. import collections as col
|
|
82
|
+
from .. import lang
|
|
83
|
+
from .. import reflect as rfl
|
|
84
|
+
from .exceptions import UnhandledTypeException
|
|
85
|
+
from .factories import Factory
|
|
86
|
+
from .factories import RecursiveTypeFactory
|
|
87
|
+
from .registries import Registry
|
|
88
|
+
from .registries import RegistryItem
|
|
89
|
+
from .utils import _Proxy
|
|
90
|
+
from .values import Value
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
##
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class Marshaler(lang.Abstract):
|
|
97
|
+
@abc.abstractmethod
|
|
98
|
+
def marshal(self, ctx: 'MarshalContext', o: ta.Any) -> Value:
|
|
99
|
+
raise NotImplementedError
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class Unmarshaler(lang.Abstract):
|
|
103
|
+
@abc.abstractmethod
|
|
104
|
+
def unmarshal(self, ctx: 'UnmarshalContext', v: Value) -> ta.Any:
|
|
105
|
+
raise NotImplementedError
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
MarshalerFactory = Factory[Marshaler, 'MarshalContext', rfl.Type]
|
|
109
|
+
UnmarshalerFactory = Factory[Unmarshaler, 'UnmarshalContext', rfl.Type]
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
##
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
@dc.dataclass(frozen=True)
|
|
116
|
+
class FuncMarshaler(Marshaler, lang.Final):
|
|
117
|
+
fn: ta.Callable[['MarshalContext', ta.Any], Value]
|
|
118
|
+
|
|
119
|
+
def marshal(self, ctx: 'MarshalContext', o: ta.Any) -> Value:
|
|
120
|
+
return self.fn(ctx, o)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
@dc.dataclass(frozen=True)
|
|
124
|
+
class FuncUnmarshaler(Unmarshaler, lang.Final):
|
|
125
|
+
fn: ta.Callable[['UnmarshalContext', Value], ta.Any]
|
|
126
|
+
|
|
127
|
+
def unmarshal(self, ctx: 'UnmarshalContext', v: Value) -> ta.Any:
|
|
128
|
+
return self.fn(ctx, v)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
##
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class Option:
|
|
135
|
+
pass
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
##
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
@dc.dataclass(frozen=True)
|
|
142
|
+
class BaseContext(lang.Abstract):
|
|
143
|
+
registry: Registry
|
|
144
|
+
options: col.TypeMap[Option] = col.TypeMap()
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
@dc.dataclass(frozen=True)
|
|
148
|
+
class MarshalContext(BaseContext, lang.Final):
|
|
149
|
+
factory: ta.Optional[MarshalerFactory] = None
|
|
150
|
+
|
|
151
|
+
def make(self, o: ta.Any) -> Marshaler:
|
|
152
|
+
rty = rfl.type_(o)
|
|
153
|
+
if (m := check.not_none(self.factory)(self, rty)) is not None: # noqa
|
|
154
|
+
return m
|
|
155
|
+
raise UnhandledTypeException(rty)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
@dc.dataclass(frozen=True)
|
|
159
|
+
class UnmarshalContext(BaseContext, lang.Final):
|
|
160
|
+
factory: ta.Optional[UnmarshalerFactory] = None
|
|
161
|
+
|
|
162
|
+
def make(self, o: ta.Any) -> Unmarshaler:
|
|
163
|
+
rty = rfl.type_(o)
|
|
164
|
+
if (m := check.not_none(self.factory)(self, rty)) is not None: # noqa
|
|
165
|
+
return m
|
|
166
|
+
raise UnhandledTypeException(rty)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
##
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class _ProxyMarshaler(_Proxy[Marshaler], Marshaler):
|
|
173
|
+
def marshal(self, ctx: MarshalContext, o: ta.Any) -> Value:
|
|
174
|
+
return self._obj.marshal(ctx, o)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
class RecursiveMarshalerFactory(RecursiveTypeFactory[Marshaler, MarshalContext], lang.Final):
|
|
178
|
+
def __init__(self, f: MarshalerFactory) -> None:
|
|
179
|
+
super().__init__(f, _ProxyMarshaler._new) # noqa
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
class _ProxyUnmarshaler(_Proxy[Unmarshaler], Unmarshaler):
|
|
183
|
+
def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any:
|
|
184
|
+
return self._obj.unmarshal(ctx, v)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
class RecursiveUnmarshalerFactory(RecursiveTypeFactory[Unmarshaler, UnmarshalContext], lang.Final):
|
|
188
|
+
def __init__(self, f: UnmarshalerFactory) -> None:
|
|
189
|
+
super().__init__(f, _ProxyUnmarshaler._new) # noqa
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
##
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
@dc.dataclass(frozen=True)
|
|
196
|
+
class SetType(RegistryItem, lang.Final):
|
|
197
|
+
marshaler: ta.Optional[Marshaler] = None
|
|
198
|
+
marshaler_factory: ta.Optional[MarshalerFactory] = None
|
|
199
|
+
|
|
200
|
+
unmarshaler: ta.Optional[Unmarshaler] = None
|
|
201
|
+
unmarshaler_factory: ta.Optional[UnmarshalerFactory] = None
|
omlish/marshal/base64.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
|
|
3
|
+
from .. import check
|
|
4
|
+
from .base import MarshalContext
|
|
5
|
+
from .base import Marshaler
|
|
6
|
+
from .base import MarshalerFactory
|
|
7
|
+
from .base import UnmarshalContext
|
|
8
|
+
from .base import Unmarshaler
|
|
9
|
+
from .base import UnmarshalerFactory
|
|
10
|
+
from .factories import TypeMapFactory
|
|
11
|
+
from .values import Value
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Base64MarshalerUnmarshaler(Marshaler, Unmarshaler):
|
|
15
|
+
def marshal(self, ctx: MarshalContext, o: bytes) -> str:
|
|
16
|
+
return base64.b64encode(o).decode()
|
|
17
|
+
|
|
18
|
+
def unmarshal(self, ctx: UnmarshalContext, v: Value) -> bytes:
|
|
19
|
+
return base64.b64decode(check.isinstance(v, str).encode())
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
BASE64_MARSHALER_UNMARSHALER = Base64MarshalerUnmarshaler()
|
|
23
|
+
|
|
24
|
+
BASE64_MARSHALER_FACTORY: MarshalerFactory = TypeMapFactory({bytes: BASE64_MARSHALER_UNMARSHALER})
|
|
25
|
+
BASE64_UNMARSHALER_FACTORY: UnmarshalerFactory = TypeMapFactory({bytes: BASE64_MARSHALER_UNMARSHALER})
|