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/lang/_asyncs.cc ADDED
@@ -0,0 +1,186 @@
1
+ // @omlish-cext
2
+ #define PY_SSIZE_T_CLEAN
3
+ #include <Python.h>
4
+
5
+ //
6
+
7
+ #define _MODULE_NAME "_asyncs"
8
+ #define _PACKAGE_NAME "omlish.lang"
9
+ #define _MODULE_FULL_NAME _PACKAGE_NAME "." _MODULE_NAME
10
+
11
+ //
12
+
13
+ typedef struct {
14
+ PyObject *SyncAwaitCoroutineNotTerminatedError;
15
+ PyObject *str_close;
16
+ PyObject *str___await__;
17
+ } module_state;
18
+
19
+ static module_state *
20
+ get_module_state(PyObject *module)
21
+ {
22
+ return (module_state *) PyModule_GetState(module);
23
+ }
24
+
25
+ //
26
+
27
+ static void
28
+ suppress_close(PyObject *iter, module_state *state)
29
+ {
30
+ PyObject *res = PyObject_CallMethodNoArgs(iter, state->str_close);
31
+ if (!res) {
32
+ PyErr_Clear();
33
+ } else {
34
+ Py_DECREF(res);
35
+ }
36
+ }
37
+
38
+ static PyObject *
39
+ sync_await(PyObject *module, PyObject *aw)
40
+ {
41
+ module_state *state = get_module_state(module);
42
+ PyObject *await_meth = NULL;
43
+ PyObject *iter = NULL;
44
+ PyObject *result = NULL;
45
+ PySendResult sres;
46
+
47
+ await_meth = PyObject_GetAttr(aw, state->str___await__);
48
+ if (await_meth == NULL) {
49
+ if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
50
+ PyErr_SetString(PyExc_TypeError, "object is not awaitable (no __await__)");
51
+ }
52
+ goto error;
53
+ }
54
+
55
+ iter = PyObject_CallNoArgs(await_meth);
56
+ Py_DECREF(await_meth);
57
+ await_meth = NULL;
58
+
59
+ if (iter == NULL) {
60
+ goto error;
61
+ }
62
+
63
+ if (!PyIter_Check(iter)) {
64
+ Py_DECREF(iter);
65
+ PyErr_SetString(PyExc_TypeError, "__await__() must return an iterator");
66
+ goto error;
67
+ }
68
+
69
+ sres = PyIter_Send(iter, Py_None, &result);
70
+ if (sres == PYGEN_ERROR) {
71
+ Py_DECREF(iter);
72
+ goto error;
73
+ }
74
+ if (sres == PYGEN_NEXT) {
75
+ Py_XDECREF(result);
76
+ suppress_close(iter, state);
77
+ Py_DECREF(iter);
78
+ PyErr_SetString(state->SyncAwaitCoroutineNotTerminatedError, "Not terminated");
79
+ goto error;
80
+ }
81
+
82
+ Py_DECREF(iter);
83
+ return result;
84
+
85
+ error:
86
+ return NULL;
87
+ }
88
+
89
+ //
90
+
91
+ static PyMethodDef mod_methods[] = {
92
+ {"sync_await", sync_await, METH_O, "sync_await"},
93
+ {NULL, NULL, 0, NULL}
94
+ };
95
+
96
+ static int
97
+ module_traverse(PyObject *module, visitproc visit, void *arg)
98
+ {
99
+ module_state *state = get_module_state(module);
100
+ Py_VISIT(state->SyncAwaitCoroutineNotTerminatedError);
101
+ Py_VISIT(state->str_close);
102
+ Py_VISIT(state->str___await__);
103
+ return 0;
104
+ }
105
+
106
+ static int
107
+ module_clear(PyObject *module)
108
+ {
109
+ module_state *state = get_module_state(module);
110
+ Py_CLEAR(state->SyncAwaitCoroutineNotTerminatedError);
111
+ Py_CLEAR(state->str_close);
112
+ Py_CLEAR(state->str___await__);
113
+ return 0;
114
+ }
115
+
116
+ static void
117
+ module_free(void *module)
118
+ {
119
+ module_clear((PyObject *) module);
120
+ }
121
+
122
+ static int
123
+ module_exec(PyObject *module)
124
+ {
125
+ module_state *state = get_module_state(module);
126
+
127
+ state->str_close = PyUnicode_InternFromString("close");
128
+ if (!state->str_close) {
129
+ return -1;
130
+ }
131
+
132
+ state->str___await__ = PyUnicode_InternFromString("__await__");
133
+ if (!state->str___await__) {
134
+ return -1;
135
+ }
136
+
137
+ PyObject *asyncs_module = PyImport_ImportModule("omlish.lite.asyncs");
138
+ if (!asyncs_module) {
139
+ return -1;
140
+ }
141
+
142
+ state->SyncAwaitCoroutineNotTerminatedError = PyObject_GetAttrString(
143
+ asyncs_module,
144
+ "SyncAwaitCoroutineNotTerminatedError"
145
+ );
146
+ Py_DECREF(asyncs_module);
147
+
148
+ if (!state->SyncAwaitCoroutineNotTerminatedError) {
149
+ return -1;
150
+ }
151
+
152
+ return 0;
153
+ }
154
+
155
+ //
156
+
157
+ PyDoc_STRVAR(module_doc, _MODULE_NAME);
158
+
159
+ static PyModuleDef_Slot module_slots[] = {
160
+ {Py_mod_exec, (void *) module_exec},
161
+ {Py_mod_gil, Py_MOD_GIL_NOT_USED},
162
+ {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
163
+ {0, NULL}
164
+ };
165
+
166
+ static PyModuleDef module_def = {
167
+ .m_base = PyModuleDef_HEAD_INIT,
168
+ .m_name = _MODULE_NAME,
169
+ .m_doc = module_doc,
170
+ .m_size = sizeof(module_state),
171
+ .m_methods = mod_methods,
172
+ .m_slots = module_slots,
173
+ .m_traverse = module_traverse,
174
+ .m_clear = module_clear,
175
+ .m_free = module_free,
176
+ };
177
+
178
+ extern "C" {
179
+
180
+ PyMODINIT_FUNC
181
+ PyInit__asyncs(void)
182
+ {
183
+ return PyModuleDef_Init(&module_def);
184
+ }
185
+
186
+ }
omlish/lang/asyncs.py CHANGED
@@ -1,73 +1,97 @@
1
+ import abc
2
+ import functools
1
3
  import typing as ta
2
4
 
5
+ from ..lite.abstract import Abstract
6
+ from ..lite.asyncs import sync_await as _sync_await
7
+ from ..lite.maybes import Maybe
3
8
 
9
+
10
+ O = ta.TypeVar('O')
11
+ I = ta.TypeVar('I')
12
+ R = ta.TypeVar('R')
4
13
  T = ta.TypeVar('T')
14
+ P = ta.ParamSpec('P')
5
15
 
6
16
 
7
17
  ##
8
18
 
9
19
 
10
- async def async_list(
11
- ai: ta.AsyncIterable[T],
12
- ) -> list[T]:
13
- """Simply eagerly reads the full contents of a function call returning an async iterator."""
20
+ def as_async(fn: ta.Callable[P, T], *, wrap: bool = False) -> ta.Callable[P, ta.Awaitable[T]]:
21
+ async def inner(*args, **kwargs):
22
+ return fn(*args, **kwargs)
14
23
 
15
- return [v async for v in ai]
24
+ return functools.wraps(fn)(inner) if wrap else inner
16
25
 
17
26
 
18
27
  ##
19
28
 
20
29
 
21
- def sync_await(
22
- aw: ta.Awaitable[T],
23
- ) -> T:
24
- """
25
- Allows for the synchronous execution of async functions which will never actually *externally* await anything. These
26
- functions are allowed to await any number of other functions - including contextmanagers and generators - so long as
27
- nothing ever actually 'leaks' out of the function, presumably to an event loop.
28
- """
30
+ class AsyncGeneratorWithReturn(ta.AsyncGenerator[O, I], Abstract, ta.Generic[O, I, R]):
31
+ @property
32
+ @abc.abstractmethod
33
+ def value(self) -> Maybe[R]:
34
+ raise NotImplementedError
35
+
36
+
37
+ @ta.final
38
+ class _AsyncGeneratorWithReturn(AsyncGeneratorWithReturn[O, I, R]):
39
+ def __init__(self, ag: ta.AsyncGenerator[O, I]) -> None:
40
+ if isinstance(ag, _AsyncGeneratorWithReturn):
41
+ raise TypeError(ag)
42
+ self._ag = ag
43
+
44
+ def __repr__(self) -> str:
45
+ return f'{self.__class__.__name__}({self._ag!r})'
46
+
47
+ _v: Maybe[R] = Maybe.empty()
29
48
 
30
- ret = missing = object()
49
+ @property
50
+ def value(self) -> Maybe[R]:
51
+ return self._v
31
52
 
32
- async def gate():
33
- nonlocal ret
53
+ def _set_value(self, v: R) -> None:
54
+ if self._v.present:
55
+ raise TypeError('Return value already set')
56
+ self._v = Maybe.just(v)
34
57
 
35
- ret = await aw
58
+ def __anext__(self):
59
+ return self._ag.__anext__()
36
60
 
37
- cr = gate()
38
- try:
39
- try:
40
- cr.send(None)
41
- except StopIteration:
42
- pass
61
+ def asend(self, value):
62
+ return self._ag.asend(value)
43
63
 
44
- if ret is missing or cr.cr_await is not None or cr.cr_running:
45
- raise TypeError('Not terminated')
64
+ def athrow(self, typ, val=None, tb=None):
65
+ return self._ag.athrow(typ, val, tb)
46
66
 
47
- finally:
48
- cr.close()
67
+ def aclose(self):
68
+ return self._ag.aclose()
49
69
 
50
- return ta.cast(T, ret)
51
70
 
71
+ def async_generator_with_return(
72
+ fn: ta.Callable[ta.Concatenate[ta.Callable[[R], None], P], ta.AsyncGenerator[O, I]],
73
+ ) -> ta.Callable[P, AsyncGeneratorWithReturn[O, I, R]]:
74
+ @functools.wraps(fn)
75
+ def inner(*args, **kwargs):
76
+ def set_value(v):
77
+ x._set_value(v) # noqa
52
78
 
53
- def sync_async_list(
54
- ai: ta.AsyncIterable[T],
55
- ) -> list[T]:
56
- """
57
- Uses `sync_await` to synchronously read the full contents of a function call returning an async iterator, given that
58
- the function never externally awaits anything.
59
- """
79
+ return (x := _AsyncGeneratorWithReturn(fn(set_value, *args, **kwargs))) # type: ignore[var-annotated]
80
+
81
+ return inner
82
+
83
+
84
+ ##
60
85
 
61
- lst: list[T] | None = None
62
86
 
63
- async def inner():
64
- nonlocal lst
87
+ sync_await = _sync_await
65
88
 
66
- lst = [v async for v in ai]
67
89
 
68
- sync_await(inner())
90
+ try:
91
+ from . import _asyncs as cext # type: ignore
69
92
 
70
- if not isinstance(lst, list):
71
- raise TypeError(lst)
93
+ except ImportError:
94
+ pass
72
95
 
73
- return lst
96
+ else:
97
+ sync_await = cext.sync_await
@@ -76,7 +76,7 @@ def set_attr(
76
76
  ##
77
77
 
78
78
 
79
- class AttrOps(Abstract):
79
+ class AttrStorage(Abstract):
80
80
  class NOT_SET: # noqa
81
81
  def __new__(cls, *args, **kwargs): # noqa
82
82
  raise TypeError
@@ -97,9 +97,9 @@ class AttrOps(Abstract):
97
97
  #
98
98
 
99
99
 
100
- class StdAttrOps(AttrOps):
101
- def getattr(self, obj: ta.Any, name: str, default: ta.Any = AttrOps.NOT_SET) -> ta.Any:
102
- if default is AttrOps.NOT_SET:
100
+ class StdAttrStorage(AttrStorage):
101
+ def getattr(self, obj: ta.Any, name: str, default: ta.Any = AttrStorage.NOT_SET) -> ta.Any:
102
+ if default is AttrStorage.NOT_SET:
103
103
  return getattr(obj, name)
104
104
  else:
105
105
  return getattr(obj, name, default)
@@ -111,13 +111,13 @@ class StdAttrOps(AttrOps):
111
111
  delattr(obj, name)
112
112
 
113
113
 
114
- STD_ATTR_OPS = StdAttrOps()
114
+ STD_ATTR_STORAGE = StdAttrStorage()
115
115
 
116
116
 
117
117
  #
118
118
 
119
119
 
120
- class DictAttrOps(AttrOps):
120
+ class DictAttrStorage(AttrStorage):
121
121
  def __init__(self, dct: ta.MutableMapping[str, ta.Any] | None = None) -> None:
122
122
  super().__init__()
123
123
 
@@ -125,11 +125,11 @@ class DictAttrOps(AttrOps):
125
125
  dct = {}
126
126
  self._dct = dct
127
127
 
128
- def getattr(self, obj: ta.Any, name: str, default: ta.Any = AttrOps.NOT_SET) -> ta.Any:
128
+ def getattr(self, obj: ta.Any, name: str, default: ta.Any = AttrStorage.NOT_SET) -> ta.Any:
129
129
  try:
130
130
  return self._dct[name]
131
131
  except KeyError:
132
- if default is not AttrOps.NOT_SET:
132
+ if default is not AttrStorage.NOT_SET:
133
133
  return default
134
134
  raise AttributeError(name) from None
135
135
 
@@ -205,13 +205,13 @@ def _get_object_transient_dict(obj: ta.Any) -> TransientDict:
205
205
  return obj.__dict__.setdefault(_TRANSIENT_DICT_ATTR, TransientDict())
206
206
 
207
207
 
208
- class TransientAttrOps(AttrOps):
209
- def getattr(self, obj: ta.Any, name: str, default: ta.Any = AttrOps.NOT_SET) -> ta.Any:
208
+ class TransientAttrStorage(AttrStorage):
209
+ def getattr(self, obj: ta.Any, name: str, default: ta.Any = AttrStorage.NOT_SET) -> ta.Any:
210
210
  td = _get_object_transient_dict(obj)
211
211
  try:
212
212
  return td[name]
213
213
  except KeyError:
214
- if default is not AttrOps.NOT_SET:
214
+ if default is not AttrStorage.NOT_SET:
215
215
  return default
216
216
  raise AttributeError(name) from None
217
217
 
@@ -227,8 +227,8 @@ class TransientAttrOps(AttrOps):
227
227
  raise AttributeError(name) from None
228
228
 
229
229
 
230
- TRANSIENT_ATTR_OPS = TransientAttrOps()
230
+ TRANSIENT_ATTR_STORAGE = TransientAttrStorage()
231
231
 
232
- transient_getattr = TRANSIENT_ATTR_OPS.getattr
233
- transient_setattr = TRANSIENT_ATTR_OPS.setattr
234
- transient_delattr = TRANSIENT_ATTR_OPS.delattr
232
+ transient_getattr = TRANSIENT_ATTR_STORAGE.getattr
233
+ transient_setattr = TRANSIENT_ATTR_STORAGE.setattr
234
+ transient_delattr = TRANSIENT_ATTR_STORAGE.delattr
@@ -2,8 +2,8 @@ import abc
2
2
  import functools
3
3
  import typing as ta
4
4
 
5
- from ..attrs import transient_getattr
6
- from ..attrs import transient_setattr
5
+ from ..attrstorage import transient_getattr
6
+ from ..attrstorage import transient_setattr
7
7
  from ..classes.abstract import Abstract
8
8
 
9
9
 
omlish/lang/casing.py CHANGED
@@ -50,6 +50,13 @@ class StringCasing(Abstract):
50
50
 
51
51
  raise NotImplementedError
52
52
 
53
+ #
54
+
55
+ def to(self, other: 'StringCasing') -> ta.Callable[[str], str]:
56
+ def inner(s: str) -> str:
57
+ return other.join(*self.split(s))
58
+ return inner
59
+
53
60
 
54
61
  #
55
62
 
@@ -167,6 +174,10 @@ snake_case = SNAKE_CASE.join
167
174
  up_snake_case = UP_SNAKE_CASE.join
168
175
 
169
176
 
177
+ camel_to_snake = CAMEL_CASE.to(SNAKE_CASE)
178
+ snake_to_camel = SNAKE_CASE.to(CAMEL_CASE)
179
+
180
+
170
181
  ##
171
182
 
172
183
 
@@ -7,10 +7,9 @@ T = ta.TypeVar('T')
7
7
  ##
8
8
 
9
9
 
10
+ @ta.final
10
11
  class _ClassOrInstanceMethod:
11
12
  def __init__(self, func):
12
- super().__init__()
13
-
14
13
  self.__func__ = func
15
14
 
16
15
  def __get__(self, instance, owner=None):
@@ -19,7 +18,7 @@ class _ClassOrInstanceMethod:
19
18
 
20
19
  class BindableClass(ta.Generic[T]):
21
20
  # FIXME: apparently can't have TypeVars in ClassVars, but could stick in a @classmethod (which gets transformed)...
22
- _bound: ta.ClassVar[type[T] | None] = None # type: ignore[misc]
21
+ _bound: ta.ClassVar[type[T] | None] = None
23
22
 
24
23
  def __init__(self, *, _bound):
25
24
  super().__init__()
@@ -32,6 +32,14 @@ class Final(Abstract):
32
32
  elif Final in base.__mro__:
33
33
  raise FinalTypeError(base)
34
34
 
35
+ # Per `ta.final`:
36
+ try:
37
+ cls.__final__ = True # type: ignore[attr-defined]
38
+ except (AttributeError, TypeError):
39
+ # Skip the attribute silently if it is not writable. AttributeError happens if the object has __slots__ or
40
+ # a read-only property, TypeError if it's a builtin class.
41
+ pass
42
+
35
43
 
36
44
  ##
37
45
 
@@ -63,7 +63,6 @@ class Marker(NotInstantiable, metaclass=_MarkerMeta):
63
63
 
64
64
 
65
65
  _SINGLETON_INSTANCE_ATTR = '__singleton_instance__'
66
- _SINGLETON_LOCK = threading.RLock()
67
66
 
68
67
 
69
68
  def _set_singleton_instance(inst):
@@ -85,7 +84,24 @@ def _set_singleton_instance(inst):
85
84
  return inst
86
85
 
87
86
 
88
- class Singleton:
87
+ class _AnySingleton:
88
+ def __init__(self) -> None:
89
+ try:
90
+ type(self).__dict__[_SINGLETON_INSTANCE_ATTR]
91
+ except KeyError:
92
+ pass
93
+ else:
94
+ raise TypeError(f'Must not re-instantiate singleton {type(self)}')
95
+
96
+ super().__init__()
97
+
98
+ @ta.final
99
+ def __reduce__(self):
100
+ return (type(self), ())
101
+
102
+
103
+ class Singleton(_AnySingleton):
104
+ @ta.final
89
105
  def __new__(cls):
90
106
  return cls.__dict__[_SINGLETON_INSTANCE_ATTR]
91
107
 
@@ -95,15 +111,21 @@ class Singleton:
95
111
  _set_singleton_instance(super().__new__(cls)) # noqa
96
112
 
97
113
 
98
- class LazySingleton:
114
+ _LAZY_SINGLETON_LOCK = threading.RLock()
115
+
116
+
117
+ class LazySingleton(_AnySingleton):
118
+ @ta.final
99
119
  def __new__(cls):
100
120
  try:
101
121
  return cls.__dict__[_SINGLETON_INSTANCE_ATTR]
102
122
  except KeyError:
103
123
  pass
104
- with _SINGLETON_LOCK:
124
+
125
+ with _LAZY_SINGLETON_LOCK:
105
126
  try:
106
127
  return cls.__dict__[_SINGLETON_INSTANCE_ATTR]
107
128
  except KeyError:
108
129
  pass
130
+
109
131
  return _set_singleton_instance(super().__new__(cls))
@@ -9,7 +9,7 @@ V = ta.TypeVar('V')
9
9
  ##
10
10
 
11
11
 
12
- def yield_dict_init(*args: ta.Any, **kwargs: ta.Any) -> ta.Iterable[tuple[ta.Any, ta.Any]]:
12
+ def yield_dict_init(*args: ta.Any, **kwargs: ta.Any) -> ta.Iterator[tuple[ta.Any, ta.Any]]:
13
13
  if len(args) > 1:
14
14
  raise TypeError
15
15
 
@@ -20,6 +20,8 @@ T = ta.TypeVar('T')
20
20
  K = ta.TypeVar('K')
21
21
  V = ta.TypeVar('V')
22
22
 
23
+ P = ta.ParamSpec('P')
24
+
23
25
 
24
26
  ##
25
27
 
@@ -165,6 +167,30 @@ def maybe_managing(obj: T) -> ta.Iterator[T]:
165
167
  yield obj
166
168
 
167
169
 
170
+ @contextlib.asynccontextmanager
171
+ async def async_maybe_managing(obj: T) -> ta.AsyncGenerator[T]:
172
+ if isinstance(obj, ta.AsyncContextManager):
173
+ async with obj:
174
+ yield obj
175
+ else:
176
+ yield obj
177
+
178
+
179
+ @contextlib.asynccontextmanager
180
+ async def async_or_sync_maybe_managing(obj: T) -> ta.AsyncGenerator[T]:
181
+ if isinstance(obj, ta.AsyncContextManager):
182
+ async with obj:
183
+ yield obj
184
+ elif isinstance(obj, ta.ContextManager):
185
+ with obj:
186
+ yield obj
187
+ else:
188
+ yield obj
189
+
190
+
191
+ ##
192
+
193
+
168
194
  @contextlib.contextmanager
169
195
  def disposing(obj: T, attr: str = 'dispose') -> ta.Iterator[T]:
170
196
  try:
@@ -194,15 +220,6 @@ def context_var_setting(var: contextvars.ContextVar[T], val: T) -> ta.Iterator[T
194
220
  ##
195
221
 
196
222
 
197
- @contextlib.asynccontextmanager
198
- async def as_async_context_manager(cm: ta.ContextManager[T]) -> ta.AsyncIterator[T]:
199
- with cm as v:
200
- yield v
201
-
202
-
203
- ##
204
-
205
-
206
223
  ContextWrappable: ta.TypeAlias = ta.ContextManager | str | ta.Callable[..., ta.ContextManager]
207
224
 
208
225
 
@@ -382,3 +399,36 @@ def double_check_setdefault(
382
399
  v = fn()
383
400
  dct[k] = v
384
401
  return v
402
+
403
+
404
+ ##
405
+
406
+
407
+ def call_with_exit_stack(
408
+ fn: ta.Callable[ta.Concatenate[contextlib.ExitStack, P], T],
409
+ *args: P.args,
410
+ **kwargs: P.kwargs,
411
+ ) -> T:
412
+ with contextlib.ExitStack() as es:
413
+ return fn(es, *args, **kwargs)
414
+
415
+
416
+ async def call_with_async_exit_stack(
417
+ fn: ta.Callable[ta.Concatenate[contextlib.AsyncExitStack, P], ta.Awaitable[T]],
418
+ *args: P.args,
419
+ **kwargs: P.kwargs,
420
+ ) -> T:
421
+ async with contextlib.AsyncExitStack() as aes:
422
+ return await fn(aes, *args, **kwargs)
423
+
424
+
425
+ def with_exit_stack(
426
+ fn: ta.Callable[ta.Concatenate[contextlib.ExitStack, P], T],
427
+ ) -> ta.Callable[P, T]:
428
+ return functools.partial(call_with_exit_stack, fn)
429
+
430
+
431
+ def with_async_exit_stack(
432
+ fn: ta.Callable[ta.Concatenate[contextlib.AsyncExitStack, P], ta.Awaitable[T]],
433
+ ) -> ta.Callable[P, ta.Awaitable[T]]:
434
+ return functools.partial(call_with_async_exit_stack, fn)