omlish 0.0.0.dev423__py3-none-any.whl → 0.0.0.dev484__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.

Files changed (464) hide show
  1. omlish/{.manifests.json → .omlish-manifests.json} +12 -0
  2. omlish/__about__.py +21 -18
  3. omlish/argparse/all.py +17 -9
  4. omlish/argparse/cli.py +16 -3
  5. omlish/argparse/utils.py +21 -0
  6. omlish/asyncs/all.py +0 -13
  7. omlish/asyncs/asyncio/rlock.py +110 -0
  8. omlish/asyncs/asyncio/subprocesses.py +2 -2
  9. omlish/asyncs/asyncio/sync.py +43 -0
  10. omlish/asyncs/asyncio/utils.py +2 -0
  11. omlish/asyncs/ioproxy/proxy.py +1 -1
  12. omlish/asyncs/sync.py +25 -0
  13. omlish/bootstrap/_marshal.py +1 -1
  14. omlish/bootstrap/diag.py +12 -21
  15. omlish/bootstrap/main.py +2 -5
  16. omlish/bootstrap/sys.py +27 -28
  17. omlish/c3.py +4 -1
  18. omlish/cexts/include/omlish/omlish.hh +1 -0
  19. omlish/collections/__init__.py +13 -1
  20. omlish/collections/attrregistry.py +210 -0
  21. omlish/collections/cache/impl.py +3 -2
  22. omlish/collections/identity.py +1 -0
  23. omlish/collections/mappings.py +28 -0
  24. omlish/collections/trie.py +5 -1
  25. omlish/collections/utils.py +77 -0
  26. omlish/concurrent/__init__.py +0 -11
  27. omlish/concurrent/all.py +18 -0
  28. omlish/concurrent/futures.py +25 -0
  29. omlish/concurrent/threadlets.py +1 -1
  30. omlish/configs/processing/flattening.py +1 -1
  31. omlish/configs/processing/merging.py +8 -6
  32. omlish/configs/types.py +1 -1
  33. omlish/daemons/__init__.py +70 -0
  34. omlish/daemons/daemon.py +2 -2
  35. omlish/daemons/launching.py +2 -2
  36. omlish/daemons/reparent.py +2 -3
  37. omlish/daemons/spawning.py +2 -3
  38. omlish/dataclasses/__init__.py +5 -5
  39. omlish/dataclasses/errors.py +1 -1
  40. omlish/dataclasses/impl/api/classes/decorator.py +3 -0
  41. omlish/dataclasses/impl/api/classes/make.py +4 -1
  42. omlish/dataclasses/impl/concerns/doc.py +1 -1
  43. omlish/dataclasses/impl/concerns/repr.py +15 -2
  44. omlish/dataclasses/impl/configs.py +97 -36
  45. omlish/dataclasses/impl/generation/compilation.py +21 -19
  46. omlish/dataclasses/impl/generation/globals.py +1 -0
  47. omlish/dataclasses/impl/generation/ops.py +1 -0
  48. omlish/dataclasses/impl/generation/processor.py +105 -24
  49. omlish/dataclasses/impl/processing/base.py +8 -0
  50. omlish/dataclasses/impl/processing/driving.py +8 -8
  51. omlish/dataclasses/specs.py +34 -2
  52. omlish/dataclasses/tools/as_.py +0 -12
  53. omlish/dataclasses/tools/modifiers.py +5 -0
  54. omlish/dataclasses/tools/static.py +1 -1
  55. omlish/diag/_pycharm/runhack.py +1 -1
  56. omlish/diag/{lslocks.py → cmds/lslocks.py} +6 -6
  57. omlish/diag/{lsof.py → cmds/lsof.py} +6 -6
  58. omlish/diag/{ps.py → cmds/ps.py} +6 -6
  59. omlish/diag/procfs.py +4 -4
  60. omlish/diag/pycharm.py +16 -2
  61. omlish/diag/pydevd.py +58 -40
  62. omlish/diag/replserver/console.py +3 -3
  63. omlish/diag/replserver/server.py +2 -2
  64. omlish/dispatch/__init__.py +18 -12
  65. omlish/dispatch/methods.py +50 -140
  66. omlish/dom/rendering.py +1 -1
  67. omlish/formats/dotenv.py +8 -8
  68. omlish/formats/json/stream/__init__.py +18 -3
  69. omlish/formats/json/stream/building.py +2 -2
  70. omlish/formats/json/stream/lexing.py +401 -67
  71. omlish/formats/json/stream/parsing.py +32 -10
  72. omlish/formats/json/stream/rendering.py +6 -6
  73. omlish/formats/json/stream/utils.py +132 -30
  74. omlish/formats/json5/literals.py +7 -4
  75. omlish/formats/json5/parsing.py +33 -79
  76. omlish/formats/json5/stream.py +77 -0
  77. omlish/formats/logfmt.py +8 -2
  78. omlish/funcs/genmachine.py +2 -2
  79. omlish/funcs/guard.py +225 -0
  80. omlish/graphs/dot/rendering.py +1 -1
  81. omlish/http/all.py +122 -53
  82. omlish/http/asgi.py +2 -2
  83. omlish/http/clients/__init__.py +0 -34
  84. omlish/http/clients/asyncs.py +153 -0
  85. omlish/http/clients/base.py +63 -122
  86. omlish/http/clients/coro/sync.py +171 -0
  87. omlish/http/clients/default.py +209 -30
  88. omlish/http/clients/executor.py +56 -0
  89. omlish/http/clients/httpx.py +78 -13
  90. omlish/http/clients/middleware.py +181 -0
  91. omlish/http/clients/sync.py +151 -0
  92. omlish/http/clients/syncasync.py +49 -0
  93. omlish/http/clients/urllib.py +8 -5
  94. omlish/http/coro/client/{client.py → connection.py} +43 -37
  95. omlish/http/coro/client/headers.py +5 -5
  96. omlish/http/coro/client/response.py +37 -38
  97. omlish/http/coro/client/status.py +4 -4
  98. omlish/http/coro/{client/io.py → io.py} +19 -2
  99. omlish/http/coro/server/fdio.py +10 -9
  100. omlish/http/coro/server/server.py +14 -41
  101. omlish/http/coro/server/sockets.py +7 -6
  102. omlish/http/flasky/__init__.py +40 -0
  103. omlish/http/flasky/_compat.py +2 -0
  104. omlish/http/flasky/api.py +82 -0
  105. omlish/http/flasky/app.py +203 -0
  106. omlish/http/flasky/cvs.py +59 -0
  107. omlish/http/flasky/requests.py +20 -0
  108. omlish/http/flasky/responses.py +23 -0
  109. omlish/http/flasky/routes.py +23 -0
  110. omlish/http/flasky/types.py +15 -0
  111. omlish/http/handlers.py +3 -2
  112. omlish/http/headers.py +69 -35
  113. omlish/http/sse.py +1 -1
  114. omlish/http/urls.py +67 -0
  115. omlish/inject/__init__.py +173 -126
  116. omlish/inject/_dataclasses.py +4986 -0
  117. omlish/inject/binder.py +10 -49
  118. omlish/inject/elements.py +27 -0
  119. omlish/inject/{utils.py → helpers/constfn.py} +3 -3
  120. omlish/inject/{tags.py → helpers/id.py} +2 -2
  121. omlish/inject/helpers/multis.py +143 -0
  122. omlish/inject/helpers/wrappers.py +54 -0
  123. omlish/inject/impl/elements.py +52 -22
  124. omlish/inject/impl/injector.py +76 -49
  125. omlish/inject/impl/inspect.py +11 -1
  126. omlish/inject/impl/maysync.py +43 -0
  127. omlish/inject/impl/multis.py +10 -7
  128. omlish/inject/impl/privates.py +8 -8
  129. omlish/inject/impl/providers.py +23 -34
  130. omlish/inject/impl/providersmap.py +43 -0
  131. omlish/inject/impl/proxy.py +0 -2
  132. omlish/inject/impl/scopes.py +19 -23
  133. omlish/inject/impl/sync.py +41 -0
  134. omlish/inject/injector.py +37 -8
  135. omlish/inject/inspect.py +35 -0
  136. omlish/inject/listeners.py +4 -4
  137. omlish/inject/managed.py +54 -18
  138. omlish/inject/maysync.py +27 -0
  139. omlish/inject/multis.py +8 -0
  140. omlish/inject/overrides.py +3 -3
  141. omlish/inject/privates.py +6 -0
  142. omlish/inject/providers.py +8 -1
  143. omlish/inject/scopes.py +40 -12
  144. omlish/inject/sync.py +49 -0
  145. omlish/io/buffers.py +119 -1
  146. omlish/io/readers.py +29 -0
  147. omlish/iterators/__init__.py +28 -20
  148. omlish/iterators/transforms.py +204 -0
  149. omlish/lang/__init__.py +240 -129
  150. omlish/lang/_asyncs.cc +186 -0
  151. omlish/lang/asyncs.py +67 -43
  152. omlish/lang/{attrs.py → attrstorage.py} +15 -15
  153. omlish/lang/cached/property.py +2 -2
  154. omlish/lang/casing.py +11 -0
  155. omlish/lang/classes/bindable.py +2 -3
  156. omlish/lang/classes/restrict.py +8 -0
  157. omlish/lang/classes/simple.py +26 -4
  158. omlish/lang/collections.py +1 -1
  159. omlish/lang/contextmanagers.py +59 -9
  160. omlish/lang/functions.py +31 -33
  161. omlish/lang/imports/_capture.cc +103 -0
  162. omlish/lang/imports/capture.py +902 -0
  163. omlish/lang/imports/lazy.py +0 -25
  164. omlish/lang/imports/proxy.py +559 -0
  165. omlish/lang/iterables.py +2 -2
  166. omlish/lang/lazyglobals.py +49 -14
  167. omlish/lang/maybes.py +2 -1
  168. omlish/lang/maysync.py +2 -2
  169. omlish/lang/params.py +17 -0
  170. omlish/lang/recursion.py +0 -1
  171. omlish/lang/resources.py +1 -1
  172. omlish/lang/sequences.py +124 -0
  173. omlish/lifecycles/contextmanagers.py +1 -2
  174. omlish/lifecycles/controller.py +1 -2
  175. omlish/lite/abstract.py +54 -24
  176. omlish/lite/asyncs.py +146 -0
  177. omlish/lite/attrops.py +415 -0
  178. omlish/lite/cached.py +57 -1
  179. omlish/lite/contextmanagers.py +4 -4
  180. omlish/lite/dataclasses.py +55 -0
  181. omlish/lite/inject.py +5 -4
  182. omlish/lite/marshal.py +1 -0
  183. omlish/lite/maybes.py +10 -2
  184. omlish/lite/maysync.py +22 -5
  185. omlish/lite/pycharm.py +1 -1
  186. omlish/lite/strings.py +0 -7
  187. omlish/lite/timing.py +6 -3
  188. omlish/lite/typing.py +6 -0
  189. omlish/logs/_amalg.py +8 -0
  190. omlish/logs/all.py +59 -31
  191. omlish/logs/base.py +204 -0
  192. omlish/logs/contexts.py +171 -0
  193. omlish/logs/formatters.py +13 -0
  194. omlish/logs/infos.py +377 -0
  195. omlish/logs/levels.py +97 -0
  196. omlish/logs/modules.py +13 -0
  197. omlish/logs/protocols.py +32 -0
  198. omlish/logs/standard.py +20 -15
  199. omlish/logs/std/configs.py +29 -0
  200. omlish/logs/{filters.py → std/filters.py} +1 -1
  201. omlish/logs/std/formatters.py +25 -0
  202. omlish/logs/std/handlers.py +19 -0
  203. omlish/logs/{json.py → std/json.py} +2 -2
  204. omlish/logs/std/loggers.py +48 -0
  205. omlish/logs/{proxy.py → std/proxy.py} +3 -3
  206. omlish/logs/std/records.py +671 -0
  207. omlish/logs/typed/bindings.py +108 -37
  208. omlish/logs/typed/types.py +17 -1
  209. omlish/logs/typed/values.py +2 -2
  210. omlish/logs/utils.py +60 -4
  211. omlish/logs/warnings.py +8 -0
  212. omlish/manifests/loading.py +8 -1
  213. omlish/marshal/__init__.py +54 -22
  214. omlish/marshal/_dataclasses.py +2774 -0
  215. omlish/marshal/base/configs.py +12 -0
  216. omlish/marshal/base/contexts.py +36 -21
  217. omlish/marshal/base/funcs.py +8 -11
  218. omlish/marshal/base/options.py +8 -0
  219. omlish/marshal/base/registries.py +146 -44
  220. omlish/marshal/base/types.py +40 -16
  221. omlish/marshal/composite/iterables.py +33 -20
  222. omlish/marshal/composite/literals.py +20 -18
  223. omlish/marshal/composite/mappings.py +36 -23
  224. omlish/marshal/composite/maybes.py +29 -19
  225. omlish/marshal/composite/newtypes.py +16 -16
  226. omlish/marshal/composite/optionals.py +14 -14
  227. omlish/marshal/composite/special.py +15 -15
  228. omlish/marshal/composite/unions/literals.py +93 -0
  229. omlish/marshal/composite/unions/primitives.py +103 -0
  230. omlish/marshal/factories/invalidate.py +18 -68
  231. omlish/marshal/factories/method.py +26 -0
  232. omlish/marshal/factories/moduleimport/factories.py +22 -65
  233. omlish/marshal/factories/multi.py +13 -25
  234. omlish/marshal/factories/recursive.py +42 -56
  235. omlish/marshal/factories/typecache.py +29 -74
  236. omlish/marshal/factories/typemap.py +42 -43
  237. omlish/marshal/objects/dataclasses.py +129 -106
  238. omlish/marshal/objects/marshal.py +18 -14
  239. omlish/marshal/objects/namedtuples.py +48 -42
  240. omlish/marshal/objects/unmarshal.py +19 -15
  241. omlish/marshal/polymorphism/marshal.py +9 -11
  242. omlish/marshal/polymorphism/metadata.py +16 -5
  243. omlish/marshal/polymorphism/standard.py +13 -1
  244. omlish/marshal/polymorphism/unions.py +15 -105
  245. omlish/marshal/polymorphism/unmarshal.py +9 -10
  246. omlish/marshal/singular/enums.py +14 -18
  247. omlish/marshal/standard.py +10 -6
  248. omlish/marshal/trivial/any.py +1 -1
  249. omlish/marshal/trivial/forbidden.py +21 -26
  250. omlish/math/fixed.py +2 -2
  251. omlish/metadata.py +23 -1
  252. omlish/os/atomics.py +2 -2
  253. omlish/os/forkhooks.py +4 -0
  254. omlish/os/journald.py +3 -3
  255. omlish/os/pidfiles/pinning.py +2 -2
  256. omlish/reflect/ops.py +9 -0
  257. omlish/reflect/types.py +44 -8
  258. omlish/secrets/marshal.py +1 -1
  259. omlish/secrets/secrets.py +6 -3
  260. omlish/sockets/addresses.py +1 -1
  261. omlish/sockets/server/handlers.py +2 -2
  262. omlish/sockets/server/server.py +4 -3
  263. omlish/sockets/server/ssl.py +2 -2
  264. omlish/specs/jmespath/__init__.py +12 -3
  265. omlish/specs/jmespath/_dataclasses.py +2893 -0
  266. omlish/specs/jmespath/ast.py +1 -1
  267. omlish/specs/jsonrpc/__init__.py +13 -0
  268. omlish/specs/jsonrpc/_marshal.py +32 -23
  269. omlish/specs/jsonrpc/conns.py +10 -7
  270. omlish/specs/jsonschema/_marshal.py +1 -1
  271. omlish/specs/jsonschema/keywords/__init__.py +7 -0
  272. omlish/specs/jsonschema/keywords/_dataclasses.py +1644 -0
  273. omlish/specs/openapi/_marshal.py +31 -22
  274. omlish/sql/__init__.py +15 -20
  275. omlish/sql/{tabledefs/alchemy.py → alchemy/tabledefs.py} +2 -2
  276. omlish/sql/queries/_marshal.py +3 -3
  277. omlish/sql/queries/params.py +1 -1
  278. omlish/sql/queries/rendering.py +1 -1
  279. omlish/sql/tabledefs/_marshal.py +1 -1
  280. omlish/subprocesses/all.py +135 -0
  281. omlish/subprocesses/base.py +8 -3
  282. omlish/subprocesses/editor.py +1 -1
  283. omlish/sync.py +181 -20
  284. omlish/term/alt.py +60 -0
  285. omlish/term/confirm.py +8 -8
  286. omlish/term/pager.py +235 -0
  287. omlish/term/terminfo.py +935 -0
  288. omlish/term/termstate.py +67 -0
  289. omlish/term/vt100/terminal.py +0 -3
  290. omlish/testing/pytest/plugins/asyncs/fixtures.py +4 -1
  291. omlish/testing/pytest/plugins/skips.py +2 -5
  292. omlish/testing/unittest/main.py +3 -3
  293. omlish/text/docwrap/__init__.py +3 -0
  294. omlish/text/docwrap/__main__.py +11 -0
  295. omlish/text/docwrap/api.py +83 -0
  296. omlish/text/docwrap/cli.py +86 -0
  297. omlish/text/docwrap/groups.py +84 -0
  298. omlish/text/docwrap/lists.py +167 -0
  299. omlish/text/docwrap/parts.py +146 -0
  300. omlish/text/docwrap/reflowing.py +106 -0
  301. omlish/text/docwrap/rendering.py +151 -0
  302. omlish/text/docwrap/utils.py +11 -0
  303. omlish/text/docwrap/wrapping.py +59 -0
  304. omlish/text/filecache.py +2 -2
  305. omlish/text/lorem.py +6 -0
  306. omlish/text/parts.py +2 -2
  307. omlish/text/textwrap.py +51 -0
  308. omlish/typedvalues/__init__.py +1 -1
  309. omlish/typedvalues/marshal.py +85 -59
  310. omlish/typedvalues/values.py +2 -1
  311. {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev484.dist-info}/METADATA +36 -38
  312. {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev484.dist-info}/RECORD +323 -385
  313. omlish/asyncs/bluelet/LICENSE +0 -6
  314. omlish/asyncs/bluelet/all.py +0 -67
  315. omlish/asyncs/bluelet/api.py +0 -23
  316. omlish/asyncs/bluelet/core.py +0 -178
  317. omlish/asyncs/bluelet/events.py +0 -79
  318. omlish/asyncs/bluelet/files.py +0 -80
  319. omlish/asyncs/bluelet/runner.py +0 -417
  320. omlish/asyncs/bluelet/sockets.py +0 -216
  321. omlish/asyncs/bridge.py +0 -359
  322. omlish/asyncs/utils.py +0 -18
  323. omlish/dataclasses/impl/generation/mangling.py +0 -18
  324. omlish/defs.py +0 -216
  325. omlish/dispatch/_dispatch2.py +0 -69
  326. omlish/dispatch/_dispatch3.py +0 -108
  327. omlish/dynamic.py +0 -219
  328. omlish/formats/json/Json.g4 +0 -77
  329. omlish/formats/json/_antlr/JsonLexer.py +0 -109
  330. omlish/formats/json/_antlr/JsonListener.py +0 -61
  331. omlish/formats/json/_antlr/JsonParser.py +0 -457
  332. omlish/formats/json/_antlr/JsonVisitor.py +0 -42
  333. omlish/formats/json5/Json5.g4 +0 -168
  334. omlish/formats/json5/_antlr/Json5Lexer.py +0 -354
  335. omlish/formats/json5/_antlr/Json5Listener.py +0 -79
  336. omlish/formats/json5/_antlr/Json5Parser.py +0 -617
  337. omlish/formats/json5/_antlr/Json5Visitor.py +0 -52
  338. omlish/funcs/match.py +0 -227
  339. omlish/io/trampoline.py +0 -289
  340. omlish/lang/imports/proxyinit.py +0 -665
  341. omlish/lite/logs.py +0 -4
  342. omlish/lite/reprs.py +0 -85
  343. omlish/logs/abc.py +0 -319
  344. omlish/logs/callers.py +0 -67
  345. omlish/logs/color.py +0 -27
  346. omlish/logs/configs.py +0 -29
  347. omlish/logs/handlers.py +0 -17
  348. omlish/logs/protocol.py +0 -218
  349. omlish/logs/timing.py +0 -58
  350. omlish/marshal/factories/match.py +0 -34
  351. omlish/marshal/factories/simple.py +0 -28
  352. omlish/specs/irc/messages/base.py +0 -49
  353. omlish/specs/irc/messages/formats.py +0 -92
  354. omlish/specs/irc/messages/messages.py +0 -774
  355. omlish/specs/irc/messages/parsing.py +0 -98
  356. omlish/specs/irc/numerics/formats.py +0 -97
  357. omlish/specs/irc/numerics/numerics.py +0 -865
  358. omlish/specs/irc/numerics/types.py +0 -59
  359. omlish/specs/irc/protocol/LICENSE +0 -11
  360. omlish/specs/irc/protocol/__init__.py +0 -61
  361. omlish/specs/irc/protocol/consts.py +0 -6
  362. omlish/specs/irc/protocol/errors.py +0 -30
  363. omlish/specs/irc/protocol/message.py +0 -21
  364. omlish/specs/irc/protocol/nuh.py +0 -55
  365. omlish/specs/irc/protocol/parsing.py +0 -158
  366. omlish/specs/irc/protocol/rendering.py +0 -153
  367. omlish/specs/irc/protocol/tags.py +0 -102
  368. omlish/specs/irc/protocol/utils.py +0 -30
  369. omlish/specs/proto/Protobuf3.g4 +0 -396
  370. omlish/specs/proto/__init__.py +0 -0
  371. omlish/specs/proto/_antlr/Protobuf3Lexer.py +0 -340
  372. omlish/specs/proto/_antlr/Protobuf3Listener.py +0 -448
  373. omlish/specs/proto/_antlr/Protobuf3Parser.py +0 -3909
  374. omlish/specs/proto/_antlr/Protobuf3Visitor.py +0 -257
  375. omlish/specs/proto/_antlr/__init__.py +0 -0
  376. omlish/specs/proto/nodes.py +0 -54
  377. omlish/specs/proto/parsing.py +0 -97
  378. omlish/sql/parsing/Minisql.g4 +0 -292
  379. omlish/sql/parsing/__init__.py +0 -0
  380. omlish/sql/parsing/_antlr/MinisqlLexer.py +0 -322
  381. omlish/sql/parsing/_antlr/MinisqlListener.py +0 -511
  382. omlish/sql/parsing/_antlr/MinisqlParser.py +0 -3763
  383. omlish/sql/parsing/_antlr/MinisqlVisitor.py +0 -292
  384. omlish/sql/parsing/_antlr/__init__.py +0 -0
  385. omlish/sql/parsing/parsing.py +0 -119
  386. omlish/text/antlr/__init__.py +0 -3
  387. omlish/text/antlr/_runtime/BufferedTokenStream.py +0 -305
  388. omlish/text/antlr/_runtime/CommonTokenFactory.py +0 -64
  389. omlish/text/antlr/_runtime/CommonTokenStream.py +0 -90
  390. omlish/text/antlr/_runtime/FileStream.py +0 -30
  391. omlish/text/antlr/_runtime/InputStream.py +0 -90
  392. omlish/text/antlr/_runtime/IntervalSet.py +0 -183
  393. omlish/text/antlr/_runtime/LICENSE.txt +0 -28
  394. omlish/text/antlr/_runtime/LL1Analyzer.py +0 -176
  395. omlish/text/antlr/_runtime/Lexer.py +0 -332
  396. omlish/text/antlr/_runtime/ListTokenSource.py +0 -147
  397. omlish/text/antlr/_runtime/Parser.py +0 -583
  398. omlish/text/antlr/_runtime/ParserInterpreter.py +0 -173
  399. omlish/text/antlr/_runtime/ParserRuleContext.py +0 -189
  400. omlish/text/antlr/_runtime/PredictionContext.py +0 -632
  401. omlish/text/antlr/_runtime/Recognizer.py +0 -150
  402. omlish/text/antlr/_runtime/RuleContext.py +0 -230
  403. omlish/text/antlr/_runtime/StdinStream.py +0 -14
  404. omlish/text/antlr/_runtime/Token.py +0 -158
  405. omlish/text/antlr/_runtime/TokenStreamRewriter.py +0 -258
  406. omlish/text/antlr/_runtime/Utils.py +0 -36
  407. omlish/text/antlr/_runtime/__init__.py +0 -2
  408. omlish/text/antlr/_runtime/_all.py +0 -24
  409. omlish/text/antlr/_runtime/_pygrun.py +0 -174
  410. omlish/text/antlr/_runtime/atn/ATN.py +0 -135
  411. omlish/text/antlr/_runtime/atn/ATNConfig.py +0 -162
  412. omlish/text/antlr/_runtime/atn/ATNConfigSet.py +0 -215
  413. omlish/text/antlr/_runtime/atn/ATNDeserializationOptions.py +0 -27
  414. omlish/text/antlr/_runtime/atn/ATNDeserializer.py +0 -449
  415. omlish/text/antlr/_runtime/atn/ATNSimulator.py +0 -50
  416. omlish/text/antlr/_runtime/atn/ATNState.py +0 -267
  417. omlish/text/antlr/_runtime/atn/ATNType.py +0 -20
  418. omlish/text/antlr/_runtime/atn/LexerATNSimulator.py +0 -573
  419. omlish/text/antlr/_runtime/atn/LexerAction.py +0 -301
  420. omlish/text/antlr/_runtime/atn/LexerActionExecutor.py +0 -146
  421. omlish/text/antlr/_runtime/atn/ParserATNSimulator.py +0 -1664
  422. omlish/text/antlr/_runtime/atn/PredictionMode.py +0 -502
  423. omlish/text/antlr/_runtime/atn/SemanticContext.py +0 -333
  424. omlish/text/antlr/_runtime/atn/Transition.py +0 -271
  425. omlish/text/antlr/_runtime/atn/__init__.py +0 -4
  426. omlish/text/antlr/_runtime/dfa/DFA.py +0 -136
  427. omlish/text/antlr/_runtime/dfa/DFASerializer.py +0 -76
  428. omlish/text/antlr/_runtime/dfa/DFAState.py +0 -129
  429. omlish/text/antlr/_runtime/dfa/__init__.py +0 -4
  430. omlish/text/antlr/_runtime/error/DiagnosticErrorListener.py +0 -111
  431. omlish/text/antlr/_runtime/error/ErrorListener.py +0 -75
  432. omlish/text/antlr/_runtime/error/ErrorStrategy.py +0 -712
  433. omlish/text/antlr/_runtime/error/Errors.py +0 -176
  434. omlish/text/antlr/_runtime/error/__init__.py +0 -4
  435. omlish/text/antlr/_runtime/tree/Chunk.py +0 -33
  436. omlish/text/antlr/_runtime/tree/ParseTreeMatch.py +0 -121
  437. omlish/text/antlr/_runtime/tree/ParseTreePattern.py +0 -75
  438. omlish/text/antlr/_runtime/tree/ParseTreePatternMatcher.py +0 -377
  439. omlish/text/antlr/_runtime/tree/RuleTagToken.py +0 -53
  440. omlish/text/antlr/_runtime/tree/TokenTagToken.py +0 -50
  441. omlish/text/antlr/_runtime/tree/Tree.py +0 -194
  442. omlish/text/antlr/_runtime/tree/Trees.py +0 -114
  443. omlish/text/antlr/_runtime/tree/__init__.py +0 -2
  444. omlish/text/antlr/_runtime/xpath/XPath.py +0 -278
  445. omlish/text/antlr/_runtime/xpath/XPathLexer.py +0 -98
  446. omlish/text/antlr/_runtime/xpath/__init__.py +0 -4
  447. omlish/text/antlr/delimit.py +0 -109
  448. omlish/text/antlr/dot.py +0 -41
  449. omlish/text/antlr/errors.py +0 -14
  450. omlish/text/antlr/input.py +0 -96
  451. omlish/text/antlr/parsing.py +0 -54
  452. omlish/text/antlr/runtime.py +0 -102
  453. omlish/text/antlr/utils.py +0 -38
  454. /omlish/{asyncs/bluelet → cexts}/__init__.py +0 -0
  455. /omlish/{formats/json/_antlr → diag/cmds}/__init__.py +0 -0
  456. /omlish/{formats/json5/_antlr → http/clients/coro}/__init__.py +0 -0
  457. /omlish/{specs/irc → inject/helpers}/__init__.py +0 -0
  458. /omlish/{specs/irc/messages → logs/std}/__init__.py +0 -0
  459. /omlish/logs/{noisy.py → std/noisy.py} +0 -0
  460. /omlish/{specs/irc/numerics → marshal/composite/unions}/__init__.py +0 -0
  461. {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev484.dist-info}/WHEEL +0 -0
  462. {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev484.dist-info}/entry_points.txt +0 -0
  463. {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev484.dist-info}/licenses/LICENSE +0 -0
  464. {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev484.dist-info}/top_level.txt +0 -0
omlish/logs/infos.py ADDED
@@ -0,0 +1,377 @@
1
+ # ruff: noqa: UP006 UP007 UP045
2
+ # @omlish-lite
3
+ """
4
+ TODO:
5
+ - remove redundant info fields only present for std adaptation (Level.name, ...)
6
+ """
7
+ import collections.abc
8
+ import io
9
+ import logging
10
+ import os.path
11
+ import sys
12
+ import threading
13
+ import time
14
+ import traceback
15
+ import types
16
+ import typing as ta
17
+
18
+ from .levels import NamedLogLevel
19
+ from .warnings import LoggingSetupWarning
20
+
21
+
22
+ LoggingMsgFn = ta.Callable[[], ta.Union[str, tuple]] # ta.TypeAlias
23
+
24
+ LoggingExcInfoTuple = ta.Tuple[ta.Type[BaseException], BaseException, ta.Optional[types.TracebackType]] # ta.TypeAlias
25
+ LoggingExcInfo = ta.Union[BaseException, LoggingExcInfoTuple] # ta.TypeAlias
26
+ LoggingExcInfoArg = ta.Union[LoggingExcInfo, bool, None] # ta.TypeAlias
27
+
28
+ LoggingContextInfo = ta.Any # ta.TypeAlias
29
+
30
+
31
+ ##
32
+
33
+
34
+ def logging_context_info(cls):
35
+ return cls
36
+
37
+
38
+ @ta.final
39
+ class LoggingContextInfos:
40
+ def __new__(cls, *args, **kwargs): # noqa
41
+ raise TypeError
42
+
43
+ #
44
+
45
+ @logging_context_info
46
+ @ta.final
47
+ class Name(ta.NamedTuple):
48
+ name: str
49
+
50
+ @logging_context_info
51
+ @ta.final
52
+ class Level(ta.NamedTuple):
53
+ level: NamedLogLevel
54
+ name: str
55
+
56
+ @classmethod
57
+ def build(cls, level: int) -> 'LoggingContextInfos.Level':
58
+ nl: NamedLogLevel = level if level.__class__ is NamedLogLevel else NamedLogLevel(level) # type: ignore[assignment] # noqa
59
+ return cls(
60
+ level=nl,
61
+ name=logging.getLevelName(nl),
62
+ )
63
+
64
+ @logging_context_info
65
+ @ta.final
66
+ class Msg(ta.NamedTuple):
67
+ msg: str
68
+ args: ta.Union[tuple, ta.Mapping[ta.Any, ta.Any], None]
69
+
70
+ @classmethod
71
+ def build(
72
+ cls,
73
+ msg: ta.Union[str, tuple, LoggingMsgFn],
74
+ *args: ta.Any,
75
+ ) -> 'LoggingContextInfos.Msg':
76
+ s: str
77
+ a: ta.Any
78
+
79
+ if callable(msg):
80
+ if args:
81
+ raise TypeError(f'Must not provide both a message function and args: {msg=} {args=}')
82
+ x = msg()
83
+ if isinstance(x, str):
84
+ s, a = x, ()
85
+ elif isinstance(x, tuple):
86
+ if x:
87
+ s, a = x[0], x[1:]
88
+ else:
89
+ s, a = '', ()
90
+ else:
91
+ raise TypeError(x)
92
+
93
+ elif isinstance(msg, tuple):
94
+ if args:
95
+ raise TypeError(f'Must not provide both a tuple message and args: {msg=} {args=}')
96
+ if msg:
97
+ s, a = msg[0], msg[1:]
98
+ else:
99
+ s, a = '', ()
100
+
101
+ elif isinstance(msg, str):
102
+ s, a = msg, args
103
+
104
+ else:
105
+ raise TypeError(msg)
106
+
107
+ # https://github.com/python/cpython/blob/e709361fc87d0d9ab9c58033a0a7f2fef0ad43d2/Lib/logging/__init__.py#L307 # noqa
108
+ if a and len(a) == 1 and isinstance(a[0], collections.abc.Mapping) and a[0]:
109
+ a = a[0]
110
+
111
+ return cls(
112
+ msg=s,
113
+ args=a,
114
+ )
115
+
116
+ @logging_context_info
117
+ @ta.final
118
+ class Extra(ta.NamedTuple):
119
+ extra: ta.Mapping[ta.Any, ta.Any]
120
+
121
+ @logging_context_info
122
+ @ta.final
123
+ class Time(ta.NamedTuple):
124
+ ns: int
125
+ secs: float
126
+ msecs: float
127
+ relative_secs: float
128
+
129
+ @classmethod
130
+ def get_std_start_ns(cls) -> int:
131
+ x: ta.Any = logging._startTime # type: ignore[attr-defined] # noqa
132
+
133
+ # Before 3.13.0b1 this will be `time.time()`, a float of seconds. After that, it will be `time.time_ns()`,
134
+ # an int.
135
+ #
136
+ # See:
137
+ # - https://github.com/python/cpython/commit/1316692e8c7c1e1f3b6639e51804f9db5ed892ea
138
+ #
139
+ if isinstance(x, float):
140
+ return int(x * 1e9)
141
+ else:
142
+ return x
143
+
144
+ @classmethod
145
+ def build(
146
+ cls,
147
+ ns: int,
148
+ *,
149
+ start_ns: ta.Optional[int] = None,
150
+ ) -> 'LoggingContextInfos.Time':
151
+ # https://github.com/python/cpython/commit/1316692e8c7c1e1f3b6639e51804f9db5ed892ea
152
+ secs = ns / 1e9 # ns to float seconds
153
+
154
+ # Get the number of whole milliseconds (0-999) in the fractional part of seconds.
155
+ # Eg: 1_677_903_920_999_998_503 ns --> 999_998_503 ns--> 999 ms
156
+ # Convert to float by adding 0.0 for historical reasons. See gh-89047
157
+ msecs = (ns % 1_000_000_000) // 1_000_000 + 0.0
158
+
159
+ # https://github.com/python/cpython/commit/1500a23f33f5a6d052ff1ef6383d9839928b8ff1
160
+ if msecs == 999.0 and int(secs) != ns // 1_000_000_000:
161
+ # ns -> sec conversion can round up, e.g:
162
+ # 1_677_903_920_999_999_900 ns --> 1_677_903_921.0 sec
163
+ msecs = 0.0
164
+
165
+ if start_ns is None:
166
+ start_ns = cls.get_std_start_ns()
167
+ relative_secs = (ns - start_ns) / 1e6
168
+
169
+ return cls(
170
+ ns=ns,
171
+ secs=secs,
172
+ msecs=msecs,
173
+ relative_secs=relative_secs,
174
+ )
175
+
176
+ @logging_context_info
177
+ @ta.final
178
+ class Exc(ta.NamedTuple):
179
+ info: LoggingExcInfo
180
+ info_tuple: LoggingExcInfoTuple
181
+
182
+ @classmethod
183
+ def build(
184
+ cls,
185
+ arg: LoggingExcInfoArg = False,
186
+ ) -> ta.Optional['LoggingContextInfos.Exc']:
187
+ if arg is True:
188
+ sys_exc_info = sys.exc_info()
189
+ if sys_exc_info[0] is not None:
190
+ arg = sys_exc_info
191
+ else:
192
+ arg = None
193
+ elif arg is False:
194
+ arg = None
195
+ if arg is None:
196
+ return None
197
+
198
+ info: LoggingExcInfo = arg
199
+ if isinstance(info, BaseException):
200
+ info_tuple: LoggingExcInfoTuple = (type(info), info, info.__traceback__) # noqa
201
+ else:
202
+ info_tuple = info
203
+
204
+ return cls(
205
+ info=info,
206
+ info_tuple=info_tuple,
207
+ )
208
+
209
+ @logging_context_info
210
+ @ta.final
211
+ class Caller(ta.NamedTuple):
212
+ file_path: str
213
+ line_no: int
214
+ func_name: str
215
+ stack_info: ta.Optional[str]
216
+
217
+ @classmethod
218
+ def is_internal_frame(cls, frame: types.FrameType) -> bool:
219
+ file_path = os.path.normcase(frame.f_code.co_filename)
220
+
221
+ # Yes, really.
222
+ # https://github.com/python/cpython/blob/e709361fc87d0d9ab9c58033a0a7f2fef0ad43d2/Lib/logging/__init__.py#L204 # noqa
223
+ # https://github.com/python/cpython/commit/5ca6d7469be53960843df39bb900e9c3359f127f
224
+ if 'importlib' in file_path and '_bootstrap' in file_path:
225
+ return True
226
+
227
+ return False
228
+
229
+ @classmethod
230
+ def find_frame(cls, stack_offset: int = 0) -> ta.Optional[types.FrameType]:
231
+ f: ta.Optional[types.FrameType] = sys._getframe(2 + stack_offset) # noqa
232
+
233
+ while f is not None:
234
+ # NOTE: We don't check __file__ like stdlib since we may be running amalgamated - we rely on careful,
235
+ # manual stack_offset management.
236
+ if hasattr(f, 'f_code'):
237
+ return f
238
+
239
+ f = f.f_back
240
+
241
+ return None
242
+
243
+ @classmethod
244
+ def build(
245
+ cls,
246
+ stack_offset: int = 0,
247
+ *,
248
+ stack_info: bool = False,
249
+ ) -> ta.Optional['LoggingContextInfos.Caller']:
250
+ if (f := cls.find_frame(stack_offset + 1)) is None:
251
+ return None
252
+
253
+ # https://github.com/python/cpython/blob/08e9794517063c8cd92c48714071b1d3c60b71bd/Lib/logging/__init__.py#L1616-L1623 # noqa
254
+ sinfo = None
255
+ if stack_info:
256
+ sio = io.StringIO()
257
+ traceback.print_stack(f, file=sio)
258
+ sinfo = sio.getvalue()
259
+ sio.close()
260
+ if sinfo[-1] == '\n':
261
+ sinfo = sinfo[:-1]
262
+
263
+ return cls(
264
+ file_path=f.f_code.co_filename,
265
+ line_no=f.f_lineno or 0,
266
+ func_name=f.f_code.co_name,
267
+ stack_info=sinfo,
268
+ )
269
+
270
+ @logging_context_info
271
+ @ta.final
272
+ class SourceFile(ta.NamedTuple):
273
+ file_name: str
274
+ module: str
275
+
276
+ @classmethod
277
+ def build(cls, caller_file_path: ta.Optional[str]) -> ta.Optional['LoggingContextInfos.SourceFile']:
278
+ if caller_file_path is None:
279
+ return None
280
+
281
+ # https://github.com/python/cpython/blob/e709361fc87d0d9ab9c58033a0a7f2fef0ad43d2/Lib/logging/__init__.py#L331-L336 # noqa
282
+ try:
283
+ file_name = os.path.basename(caller_file_path)
284
+ module = os.path.splitext(file_name)[0]
285
+ except (TypeError, ValueError, AttributeError):
286
+ return None
287
+
288
+ return cls(
289
+ file_name=file_name,
290
+ module=module,
291
+ )
292
+
293
+ @logging_context_info
294
+ @ta.final
295
+ class Thread(ta.NamedTuple):
296
+ ident: int
297
+ native_id: ta.Optional[int]
298
+ name: str
299
+
300
+ @classmethod
301
+ def build(cls) -> 'LoggingContextInfos.Thread':
302
+ return cls(
303
+ ident=threading.get_ident(),
304
+ native_id=threading.get_native_id() if hasattr(threading, 'get_native_id') else None,
305
+ name=threading.current_thread().name,
306
+ )
307
+
308
+ @logging_context_info
309
+ @ta.final
310
+ class Process(ta.NamedTuple):
311
+ pid: int
312
+
313
+ @classmethod
314
+ def build(cls) -> 'LoggingContextInfos.Process':
315
+ return cls(
316
+ pid=os.getpid(),
317
+ )
318
+
319
+ @logging_context_info
320
+ @ta.final
321
+ class Multiprocessing(ta.NamedTuple):
322
+ process_name: str
323
+
324
+ @classmethod
325
+ def build(cls) -> ta.Optional['LoggingContextInfos.Multiprocessing']:
326
+ # https://github.com/python/cpython/blob/e709361fc87d0d9ab9c58033a0a7f2fef0ad43d2/Lib/logging/__init__.py#L355-L364 # noqa
327
+ if (mp := sys.modules.get('multiprocessing')) is None:
328
+ return None
329
+
330
+ return cls(
331
+ process_name=mp.current_process().name,
332
+ )
333
+
334
+ @logging_context_info
335
+ @ta.final
336
+ class AsyncioTask(ta.NamedTuple):
337
+ name: str
338
+
339
+ @classmethod
340
+ def build(cls) -> ta.Optional['LoggingContextInfos.AsyncioTask']:
341
+ # https://github.com/python/cpython/blob/e709361fc87d0d9ab9c58033a0a7f2fef0ad43d2/Lib/logging/__init__.py#L372-L377 # noqa
342
+ if (asyncio := sys.modules.get('asyncio')) is None:
343
+ return None
344
+
345
+ try:
346
+ task = asyncio.current_task()
347
+ except Exception: # noqa
348
+ return None
349
+
350
+ if task is None:
351
+ return None
352
+
353
+ return cls(
354
+ name=task.get_name(), # Always non-None
355
+ )
356
+
357
+
358
+ ##
359
+
360
+
361
+ class UnexpectedLoggingStartTimeWarning(LoggingSetupWarning):
362
+ pass
363
+
364
+
365
+ def _check_logging_start_time() -> None:
366
+ if (x := LoggingContextInfos.Time.get_std_start_ns()) < (t := time.time()):
367
+ import warnings # noqa
368
+
369
+ warnings.warn(
370
+ f'Unexpected logging start time detected: '
371
+ f'get_std_start_ns={x}, '
372
+ f'time.time()={t}',
373
+ UnexpectedLoggingStartTimeWarning,
374
+ )
375
+
376
+
377
+ _check_logging_start_time()
omlish/logs/levels.py CHANGED
@@ -1,7 +1,104 @@
1
+ # ruff: noqa: UP006 UP045
1
2
  # @omlish-lite
3
+ import logging
4
+ import typing as ta
2
5
 
3
6
 
4
7
  LogLevel = int # ta.TypeAlias
5
8
 
6
9
 
7
10
  ##
11
+
12
+
13
+ @ta.final
14
+ class NamedLogLevel(int):
15
+ # logging.getLevelNamesMapping (or, as that is unavailable <3.11, logging._nameToLevel) includes the deprecated
16
+ # aliases.
17
+ _NAMES_BY_INT: ta.ClassVar[ta.Mapping[LogLevel, str]] = dict(sorted(logging._levelToName.items(), key=lambda t: -t[0])) # noqa
18
+
19
+ _INTS_BY_NAME: ta.ClassVar[ta.Mapping[str, LogLevel]] = {v: k for k, v in _NAMES_BY_INT.items()}
20
+
21
+ _NAME_INT_PAIRS: ta.ClassVar[ta.Sequence[ta.Tuple[str, LogLevel]]] = list(_INTS_BY_NAME.items())
22
+
23
+ #
24
+
25
+ _CACHE: ta.ClassVar[ta.MutableMapping[int, 'NamedLogLevel']] = {}
26
+
27
+ @ta.overload
28
+ def __new__(cls, name: str, offset: int = 0, /) -> 'NamedLogLevel':
29
+ ...
30
+
31
+ @ta.overload
32
+ def __new__(cls, i: int, /) -> 'NamedLogLevel':
33
+ ...
34
+
35
+ def __new__(cls, x, offset=0, /):
36
+ if isinstance(x, str):
37
+ return cls(cls._INTS_BY_NAME[x.upper()] + offset)
38
+ elif not offset and (c := cls._CACHE.get(x)) is not None:
39
+ return c
40
+ else:
41
+ return super().__new__(cls, x + offset)
42
+
43
+ #
44
+
45
+ _name_and_offset: ta.Tuple[str, int]
46
+
47
+ @property
48
+ def name_and_offset(self) -> ta.Tuple[str, int]:
49
+ try:
50
+ return self._name_and_offset
51
+ except AttributeError:
52
+ pass
53
+
54
+ if (n := self._NAMES_BY_INT.get(self)) is not None:
55
+ t = (n, 0)
56
+ else:
57
+ for n, i in self._NAME_INT_PAIRS: # noqa
58
+ if self >= i:
59
+ t = (n, (self - i))
60
+ break
61
+ else:
62
+ t = ('NOTSET', int(self))
63
+
64
+ self._name_and_offset = t
65
+ return t
66
+
67
+ @property
68
+ def exact_name(self) -> ta.Optional[str]:
69
+ n, o = self.name_and_offset
70
+ return n if not o else None
71
+
72
+ @property
73
+ def effective_name(self) -> str:
74
+ n, _ = self.name_and_offset
75
+ return n
76
+
77
+ #
78
+
79
+ def __str__(self) -> str:
80
+ return self.exact_name or f'{self.effective_name}{int(self):+}'
81
+
82
+ def __repr__(self) -> str:
83
+ n, o = self.name_and_offset
84
+ return f'{self.__class__.__name__}({n!r}{f", {int(o)}" if o else ""})'
85
+
86
+ #
87
+
88
+ CRITICAL: ta.ClassVar['NamedLogLevel']
89
+ ERROR: ta.ClassVar['NamedLogLevel']
90
+ WARNING: ta.ClassVar['NamedLogLevel']
91
+ INFO: ta.ClassVar['NamedLogLevel']
92
+ DEBUG: ta.ClassVar['NamedLogLevel']
93
+ NOTSET: ta.ClassVar['NamedLogLevel']
94
+
95
+
96
+ NamedLogLevel.CRITICAL = NamedLogLevel(logging.CRITICAL)
97
+ NamedLogLevel.ERROR = NamedLogLevel(logging.ERROR)
98
+ NamedLogLevel.WARNING = NamedLogLevel(logging.WARNING)
99
+ NamedLogLevel.INFO = NamedLogLevel(logging.INFO)
100
+ NamedLogLevel.DEBUG = NamedLogLevel(logging.DEBUG)
101
+ NamedLogLevel.NOTSET = NamedLogLevel(logging.NOTSET)
102
+
103
+
104
+ NamedLogLevel._CACHE.update({i: NamedLogLevel(i) for i in NamedLogLevel._NAMES_BY_INT}) # noqa
omlish/logs/modules.py ADDED
@@ -0,0 +1,13 @@
1
+ # @omlish-lite
2
+ import logging
3
+ import typing as ta
4
+
5
+ from .base import Logger
6
+ from .std.loggers import StdLogger
7
+
8
+
9
+ ##
10
+
11
+
12
+ def get_module_logger(mod_globals: ta.Mapping[str, ta.Any]) -> Logger:
13
+ return StdLogger(logging.getLogger(mod_globals.get('__name__'))) # noqa
@@ -0,0 +1,32 @@
1
+ # @omlish-lite
2
+ import typing as ta
3
+
4
+ from .levels import LogLevel
5
+
6
+
7
+ ##
8
+
9
+
10
+ @ta.runtime_checkable
11
+ class LoggerLike(ta.Protocol):
12
+ """Satisfied by both our Logger and stdlib logging.Logger."""
13
+
14
+ def isEnabledFor(self, level: LogLevel) -> bool: ... # noqa
15
+
16
+ def getEffectiveLevel(self) -> LogLevel: ... # noqa
17
+
18
+ #
19
+
20
+ def log(self, level: LogLevel, msg: str, /, *args: ta.Any, **kwargs: ta.Any) -> None: ... # noqa
21
+
22
+ def debug(self, msg: str, /, *args: ta.Any, **kwargs: ta.Any) -> None: ... # noqa
23
+
24
+ def info(self, msg: str, /, *args: ta.Any, **kwargs: ta.Any) -> None: ... # noqa
25
+
26
+ def warning(self, msg: str, /, *args: ta.Any, **kwargs: ta.Any) -> None: ... # noqa
27
+
28
+ def error(self, msg: str, /, *args: ta.Any, **kwargs: ta.Any) -> None: ... # noqa
29
+
30
+ def exception(self, msg: str, /, *args: ta.Any, **kwargs: ta.Any) -> None: ... # noqa
31
+
32
+ def critical(self, msg: str, /, *args: ta.Any, **kwargs: ta.Any) -> None: ... # noqa
omlish/logs/standard.py CHANGED
@@ -2,6 +2,7 @@
2
2
  # @omlish-lite
3
3
  """
4
4
  TODO:
5
+ - !! move to std !!
5
6
  - structured
6
7
  - prefixed
7
8
  - debug
@@ -12,9 +13,9 @@ import datetime
12
13
  import logging
13
14
  import typing as ta
14
15
 
15
- from .filters import TidLogFilter
16
- from .json import JsonLogFormatter
17
- from .proxy import ProxyLogHandler
16
+ from .std.filters import TidLoggingFilter
17
+ from .std.json import JsonLoggingFormatter
18
+ from .std.proxy import ProxyLoggingHandler
18
19
 
19
20
 
20
21
  ##
@@ -31,7 +32,7 @@ STANDARD_LOG_FORMAT_PARTS = [
31
32
  ]
32
33
 
33
34
 
34
- class StandardLogFormatter(logging.Formatter):
35
+ class StandardLoggingFormatter(logging.Formatter):
35
36
  @staticmethod
36
37
  def build_log_format(parts: ta.Iterable[ta.Tuple[str, str]]) -> str:
37
38
  return ' '.join(v for k, v in parts)
@@ -50,7 +51,7 @@ class StandardLogFormatter(logging.Formatter):
50
51
  ##
51
52
 
52
53
 
53
- class StandardConfiguredLogHandler(ProxyLogHandler):
54
+ class StandardConfiguredLoggingHandler(ProxyLoggingHandler):
54
55
  def __init_subclass__(cls, **kwargs):
55
56
  raise TypeError('This class serves only as a marker and should not be subclassed.')
56
57
 
@@ -79,11 +80,15 @@ def _locking_logging_module_lock() -> ta.Iterator[None]:
79
80
  def configure_standard_logging(
80
81
  level: ta.Union[int, str] = logging.INFO,
81
82
  *,
82
- json: bool = False,
83
83
  target: ta.Optional[logging.Logger] = None,
84
+
84
85
  force: bool = False,
86
+
85
87
  handler_factory: ta.Optional[ta.Callable[[], logging.Handler]] = None,
86
- ) -> ta.Optional[StandardConfiguredLogHandler]:
88
+
89
+ formatter: ta.Optional[logging.Formatter] = None, # noqa
90
+ json: bool = False,
91
+ ) -> ta.Optional[StandardConfiguredLoggingHandler]:
87
92
  with _locking_logging_module_lock():
88
93
  if target is None:
89
94
  target = logging.root
@@ -91,7 +96,7 @@ def configure_standard_logging(
91
96
  #
92
97
 
93
98
  if not force:
94
- if any(isinstance(h, StandardConfiguredLogHandler) for h in list(target.handlers)):
99
+ if any(isinstance(h, StandardConfiguredLoggingHandler) for h in list(target.handlers)):
95
100
  return None
96
101
 
97
102
  #
@@ -103,16 +108,16 @@ def configure_standard_logging(
103
108
 
104
109
  #
105
110
 
106
- formatter: logging.Formatter
107
- if json:
108
- formatter = JsonLogFormatter()
109
- else:
110
- formatter = StandardLogFormatter(StandardLogFormatter.build_log_format(STANDARD_LOG_FORMAT_PARTS))
111
+ if formatter is None:
112
+ if json:
113
+ formatter = JsonLoggingFormatter()
114
+ else:
115
+ formatter = StandardLoggingFormatter(StandardLoggingFormatter.build_log_format(STANDARD_LOG_FORMAT_PARTS)) # noqa
111
116
  handler.setFormatter(formatter)
112
117
 
113
118
  #
114
119
 
115
- handler.addFilter(TidLogFilter())
120
+ handler.addFilter(TidLoggingFilter())
116
121
 
117
122
  #
118
123
 
@@ -125,4 +130,4 @@ def configure_standard_logging(
125
130
 
126
131
  #
127
132
 
128
- return StandardConfiguredLogHandler(handler)
133
+ return StandardConfiguredLoggingHandler(handler)
@@ -0,0 +1,29 @@
1
+ # ruff: noqa: UP006 UP045
2
+ # @omlish-lite
3
+ """
4
+ https://docs.python.org/3/howto/logging.html#configuring-logging
5
+ https://docs.python.org/3/library/logging.config.html#logging-config-dictschema
6
+ """
7
+ import dataclasses as dc
8
+ import typing as ta
9
+
10
+
11
+ FilterDictLoggingConfig = ta.Dict[str, ta.Any] # ta.TypeAlias
12
+ FormatterDictLoggingConfig = ta.Dict[str, ta.Any] # ta.TypeAlias
13
+ HandlerDictLoggingConfig = ta.Dict[str, ta.Any] # ta.TypeAlias
14
+ LoggerDictLoggingConfig = ta.Dict[str, ta.Any] # ta.TypeAlias
15
+
16
+
17
+ ##
18
+
19
+
20
+ @dc.dataclass()
21
+ class DictLoggingConfig:
22
+ version: int = 1
23
+ incremental: bool = False
24
+ disable_existing_loggers: bool = False
25
+ filters: ta.Dict[str, FilterDictLoggingConfig] = dc.field(default_factory=dict)
26
+ formatters: ta.Dict[str, FormatterDictLoggingConfig] = dc.field(default_factory=dict)
27
+ handlers: ta.Dict[str, HandlerDictLoggingConfig] = dc.field(default_factory=dict)
28
+ loggers: ta.Dict[str, LoggerDictLoggingConfig] = dc.field(default_factory=dict)
29
+ root: ta.Optional[LoggerDictLoggingConfig] = None
@@ -7,7 +7,7 @@ import threading
7
7
  ##
8
8
 
9
9
 
10
- class TidLogFilter(logging.Filter):
10
+ class TidLoggingFilter(logging.Filter):
11
11
  def filter(self, record):
12
12
  # FIXME: handle better - missing from wasm and cosmos
13
13
  if hasattr(threading, 'get_native_id'):
@@ -0,0 +1,25 @@
1
+ import logging
2
+ import typing as ta
3
+
4
+ from ..formatters import LoggingContextFormatter
5
+ from .records import LoggingContextLogRecord
6
+ from .records import LogRecordLoggingContext
7
+
8
+
9
+ ##
10
+
11
+
12
+ @ta.final
13
+ class StdLoggingFormatter(logging.Formatter):
14
+ def __init__(self, ctx_formatter: LoggingContextFormatter) -> None:
15
+ super().__init__()
16
+
17
+ self._ctx_formatter = ctx_formatter
18
+
19
+ def format(self, rec: logging.LogRecord) -> str:
20
+ if isinstance(rec, LoggingContextLogRecord):
21
+ ctx = rec._logging_context # noqa
22
+ else:
23
+ ctx = LogRecordLoggingContext(rec)
24
+
25
+ return self._ctx_formatter.format(ctx)