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
@@ -9,6 +9,7 @@ from ....io.fdio.handlers import SocketFdioHandler
9
9
  from ....lite.check import check
10
10
  from ....sockets.addresses import SocketAddress
11
11
  from ...handlers import HttpHandler
12
+ from ..io import CoroHttpIo
12
13
  from .server import CoroHttpServer
13
14
 
14
15
 
@@ -24,7 +25,7 @@ class CoroHttpServerConnectionFdioHandler(SocketFdioHandler):
24
25
  *,
25
26
  read_size: int = 0x10000,
26
27
  write_size: int = 0x10000,
27
- log_handler: ta.Optional[ta.Callable[[CoroHttpServer, CoroHttpServer.AnyLogIo], None]] = None,
28
+ log_handler: ta.Optional[ta.Callable[[CoroHttpServer, CoroHttpIo.AnyLogIo], None]] = None,
28
29
  ) -> None:
29
30
  check.state(not sock.getblocking())
30
31
 
@@ -44,13 +45,13 @@ class CoroHttpServerConnectionFdioHandler(SocketFdioHandler):
44
45
  )
45
46
  self._srv_coro: ta.Optional[
46
47
  ta.Generator[
47
- CoroHttpServer.Io,
48
+ CoroHttpIo.Io,
48
49
  ta.Optional[bytes],
49
50
  CoroHttpServer.CoroHandleResult,
50
51
  ],
51
52
  ] = self._coro_srv.coro_handle()
52
53
 
53
- self._cur_io: ta.Optional[CoroHttpServer.Io] = None
54
+ self._cur_io: ta.Optional[CoroHttpIo.Io] = None
54
55
  self._next_io()
55
56
 
56
57
  #
@@ -73,22 +74,22 @@ class CoroHttpServerConnectionFdioHandler(SocketFdioHandler):
73
74
  o = None
74
75
  break
75
76
 
76
- if isinstance(o, CoroHttpServer.AnyLogIo):
77
+ if isinstance(o, CoroHttpIo.AnyLogIo):
77
78
  if self._log_handler is not None:
78
79
  self._log_handler(self._coro_srv, o)
79
80
  o = None
80
81
 
81
- elif isinstance(o, CoroHttpServer.ReadIo):
82
+ elif isinstance(o, CoroHttpIo.ReadIo):
82
83
  if (d := self._read_buf.read(o.sz)) is None:
83
84
  break
84
85
  o = None
85
86
 
86
- elif isinstance(o, CoroHttpServer.ReadLineIo):
87
+ elif isinstance(o, CoroHttpIo.ReadLineIo):
87
88
  if (d := self._read_buf.read_until(b'\n')) is None:
88
89
  break
89
90
  o = None
90
91
 
91
- elif isinstance(o, CoroHttpServer.WriteIo):
92
+ elif isinstance(o, CoroHttpIo.WriteIo):
92
93
  check.none(self._write_buf)
93
94
  self._write_buf = IncrementalWriteBuffer(o.data, write_size=self._write_size)
94
95
  break
@@ -122,11 +123,11 @@ class CoroHttpServerConnectionFdioHandler(SocketFdioHandler):
122
123
 
123
124
  self._read_buf.feed(buf)
124
125
 
125
- if isinstance(self._cur_io, CoroHttpServer.AnyReadIo):
126
+ if isinstance(self._cur_io, CoroHttpIo.AnyReadIo):
126
127
  self._next_io()
127
128
 
128
129
  def on_writable(self) -> None:
129
- check.isinstance(self._cur_io, CoroHttpServer.WriteIo)
130
+ check.isinstance(self._cur_io, CoroHttpIo.WriteIo)
130
131
  wb = check.not_none(self._write_buf)
131
132
  while wb.rem > 0:
132
133
  def send(d: bytes) -> int:
@@ -61,7 +61,6 @@ import textwrap
61
61
  import time
62
62
  import typing as ta
63
63
 
64
- from ....lite.abstract import Abstract
65
64
  from ....lite.check import check
66
65
  from ....sockets.addresses import SocketAddress
67
66
  from ...handlers import HttpHandler
@@ -75,9 +74,10 @@ from ...parsing import ParsedHttpRequest
75
74
  from ...parsing import ParseHttpRequestError
76
75
  from ...versions import HttpProtocolVersion
77
76
  from ...versions import HttpProtocolVersions
77
+ from ..io import CoroHttpIo
78
78
 
79
79
 
80
- CoroHttpServerFactory = ta.Callable[[SocketAddress], 'CoroHttpServer']
80
+ CoroHttpServerFactory = ta.Callable[[SocketAddress], 'CoroHttpServer'] # ta.TypeAlias
81
81
 
82
82
 
83
83
  ##
@@ -380,48 +380,21 @@ class CoroHttpServer:
380
380
 
381
381
  #
382
382
 
383
- class Io(Abstract):
384
- pass
385
-
386
- #
387
-
388
- class AnyLogIo(Io):
389
- pass
390
-
391
383
  @dc.dataclass(frozen=True)
392
- class ParsedRequestLogIo(AnyLogIo):
384
+ class ParsedRequestLogIo(CoroHttpIo.AnyLogIo):
393
385
  request: ParsedHttpRequest
394
386
 
395
387
  @dc.dataclass(frozen=True)
396
- class ErrorLogIo(AnyLogIo):
388
+ class ErrorLogIo(CoroHttpIo.AnyLogIo):
397
389
  error: 'CoroHttpServer.Error'
398
390
 
399
391
  #
400
392
 
401
- class AnyReadIo(Io): # noqa
402
- pass
403
-
404
- @dc.dataclass(frozen=True)
405
- class ReadIo(AnyReadIo):
406
- sz: int
407
-
408
- @dc.dataclass(frozen=True)
409
- class ReadLineIo(AnyReadIo):
410
- sz: int
411
-
412
- #
413
-
414
- @dc.dataclass(frozen=True)
415
- class WriteIo(Io):
416
- data: bytes
417
-
418
- #
419
-
420
393
  @dc.dataclass(frozen=True)
421
394
  class CoroHandleResult:
422
395
  close_reason: ta.Literal['response', 'internal', None] = None
423
396
 
424
- def coro_handle(self) -> ta.Generator[Io, ta.Optional[bytes], CoroHandleResult]:
397
+ def coro_handle(self) -> ta.Generator[CoroHttpIo.Io, ta.Optional[bytes], CoroHandleResult]:
425
398
  return self._coro_run_handler(self._coro_handle_one())
426
399
 
427
400
  class Close(Exception): # noqa
@@ -430,20 +403,20 @@ class CoroHttpServer:
430
403
  def _coro_run_handler(
431
404
  self,
432
405
  gen: ta.Generator[
433
- ta.Union[AnyLogIo, AnyReadIo, _Response],
406
+ ta.Union[CoroHttpIo.AnyLogIo, CoroHttpIo.AnyReadIo, _Response],
434
407
  ta.Optional[bytes],
435
408
  None,
436
409
  ],
437
- ) -> ta.Generator[Io, ta.Optional[bytes], CoroHandleResult]:
410
+ ) -> ta.Generator[CoroHttpIo.Io, ta.Optional[bytes], CoroHandleResult]:
438
411
  i: ta.Optional[bytes]
439
412
  o: ta.Any = next(gen)
440
413
  while True:
441
414
  try:
442
- if isinstance(o, self.AnyLogIo):
415
+ if isinstance(o, CoroHttpIo.AnyLogIo):
443
416
  i = None
444
417
  yield o
445
418
 
446
- elif isinstance(o, self.AnyReadIo):
419
+ elif isinstance(o, CoroHttpIo.AnyReadIo):
447
420
  i = check.isinstance((yield o), bytes)
448
421
 
449
422
  elif isinstance(o, self._Response):
@@ -451,10 +424,10 @@ class CoroHttpServer:
451
424
 
452
425
  r = self._preprocess_response(o)
453
426
  hb = self._build_response_head_bytes(r)
454
- check.none((yield self.WriteIo(hb)))
427
+ check.none((yield CoroHttpIo.WriteIo(hb)))
455
428
 
456
429
  for b in self._yield_response_data(r):
457
- yield self.WriteIo(b)
430
+ yield CoroHttpIo.WriteIo(b)
458
431
 
459
432
  o.close()
460
433
  if o.close_connection:
@@ -482,7 +455,7 @@ class CoroHttpServer:
482
455
  raise
483
456
 
484
457
  def _coro_handle_one(self) -> ta.Generator[
485
- ta.Union[AnyLogIo, AnyReadIo, _Response],
458
+ ta.Union[CoroHttpIo.AnyLogIo, CoroHttpIo.AnyReadIo, _Response],
486
459
  ta.Optional[bytes],
487
460
  None,
488
461
  ]:
@@ -492,7 +465,7 @@ class CoroHttpServer:
492
465
  sz = next(gen)
493
466
  while True:
494
467
  try:
495
- line = check.isinstance((yield self.ReadLineIo(sz)), bytes)
468
+ line = check.isinstance((yield CoroHttpIo.ReadLineIo(sz)), bytes)
496
469
  sz = gen.send(line)
497
470
  except StopIteration as e:
498
471
  parsed = e.value
@@ -531,7 +504,7 @@ class CoroHttpServer:
531
504
 
532
505
  request_data: ta.Optional[bytes]
533
506
  if (cl := parsed.headers.get('Content-Length')) is not None:
534
- request_data = check.isinstance((yield self.ReadIo(int(cl))), bytes)
507
+ request_data = check.isinstance((yield CoroHttpIo.ReadIo(int(cl))), bytes)
535
508
  else:
536
509
  request_data = None
537
510
 
@@ -7,6 +7,7 @@ from ....lite.check import check
7
7
  from ....sockets.addresses import SocketAddress
8
8
  from ....sockets.handlers import SocketHandler_
9
9
  from ....sockets.io import SocketIoPair
10
+ from ..io import CoroHttpIo
10
11
  from .server import CoroHttpServer
11
12
  from .server import CoroHttpServerFactory
12
13
 
@@ -20,7 +21,7 @@ class CoroHttpServerSocketHandler(SocketHandler_):
20
21
  server_factory: CoroHttpServerFactory,
21
22
  *,
22
23
  keep_alive: bool = False,
23
- log_handler: ta.Optional[ta.Callable[[CoroHttpServer, CoroHttpServer.AnyLogIo], None]] = None,
24
+ log_handler: ta.Optional[ta.Callable[[CoroHttpServer, CoroHttpIo.AnyLogIo], None]] = None,
24
25
  ) -> None:
25
26
  super().__init__()
26
27
 
@@ -49,18 +50,18 @@ class CoroHttpServerSocketHandler(SocketHandler_):
49
50
 
50
51
  o = next(gen)
51
52
  while True:
52
- if isinstance(o, CoroHttpServer.AnyLogIo):
53
+ if isinstance(o, CoroHttpIo.AnyLogIo):
53
54
  i = None
54
55
  if self._log_handler is not None:
55
56
  self._log_handler(server, o)
56
57
 
57
- elif isinstance(o, CoroHttpServer.ReadIo):
58
- i = fp.r.read(o.sz)
58
+ elif isinstance(o, CoroHttpIo.ReadIo):
59
+ i = fp.r.read(check.not_none(o.sz))
59
60
 
60
- elif isinstance(o, CoroHttpServer.ReadLineIo):
61
+ elif isinstance(o, CoroHttpIo.ReadLineIo):
61
62
  i = fp.r.readline(o.sz)
62
63
 
63
- elif isinstance(o, CoroHttpServer.WriteIo):
64
+ elif isinstance(o, CoroHttpIo.WriteIo):
64
65
  i = None
65
66
  fp.w.write(o.data)
66
67
  fp.w.flush()
@@ -0,0 +1,40 @@
1
+ from .api import ( # noqa
2
+ Api,
3
+ )
4
+
5
+ from .app import ( # noqa
6
+ AppRunParams,
7
+ AppRunner,
8
+
9
+ ViewFunc,
10
+ BeforeRequestFunc,
11
+ AfterRequestFunc,
12
+ App,
13
+ )
14
+
15
+ from .cvs import ( # noqa
16
+ CvLookupError,
17
+
18
+ Cvs,
19
+ )
20
+
21
+ from .requests import ( # noqa
22
+ Request,
23
+ )
24
+
25
+ from .responses import ( # noqa
26
+ ResponseData,
27
+ ResponseStatus,
28
+ ResponseHeaders,
29
+
30
+ Response,
31
+ )
32
+
33
+ from .routes import ( # noqa
34
+ RouteKey,
35
+ Route,
36
+ )
37
+
38
+ from .types import ( # noqa
39
+ ImmutableMultiDict,
40
+ )
@@ -0,0 +1,2 @@
1
+ def compat(obj):
2
+ return obj
@@ -0,0 +1,82 @@
1
+ import threading
2
+ import typing as ta
3
+
4
+ from ... import lang
5
+ from ._compat import compat
6
+ from .app import App
7
+ from .cvs import Cvs
8
+ from .requests import Request
9
+ from .responses import Response
10
+
11
+
12
+ ##
13
+
14
+
15
+ class Api:
16
+ def __init__(
17
+ self,
18
+ *,
19
+ base_app_cls: type[App] = App,
20
+ ) -> None:
21
+ super().__init__()
22
+
23
+ self._base_app_cls = base_app_cls
24
+
25
+ self._lock = threading.RLock()
26
+
27
+ @property
28
+ def _cls_name_repr(self) -> str:
29
+ return f'{self.__class__.__name__}@{id(self):x}'
30
+
31
+ def __repr__(self) -> str:
32
+ return f'{self._cls_name_repr}()'
33
+
34
+ ##
35
+ # app cls
36
+
37
+ _app_cls: type[App]
38
+
39
+ @property
40
+ def app_cls(self) -> type[App]:
41
+ try:
42
+ return self._app_cls
43
+ except AttributeError:
44
+ pass
45
+
46
+ with self._lock:
47
+ try:
48
+ return self._app_cls
49
+ except AttributeError:
50
+ pass
51
+
52
+ self._app_cls = lang.new_type( # noqa
53
+ f'{self._base_app_cls.__name__}<{self._cls_name_repr}>',
54
+ (self._base_app_cls,),
55
+ {'_api': self},
56
+ )
57
+
58
+ return self._app_cls
59
+
60
+ @property
61
+ @compat
62
+ def Flask(self) -> type[App]: # noqa
63
+ return self.app_cls
64
+
65
+ ##
66
+ # helpers
67
+
68
+ def abort(self, code: int | Response, *args: ta.Any, **kwargs: ta.Any) -> ta.NoReturn:
69
+ raise NotImplementedError
70
+
71
+ ##
72
+ # cv's
73
+
74
+ @property
75
+ @compat
76
+ def request(self) -> Request:
77
+ return Cvs.REQUEST.get()
78
+
79
+ ##
80
+ # type aliases - must be last
81
+
82
+ Response = Response
@@ -0,0 +1,203 @@
1
+ import typing as ta
2
+
3
+ from ... import check
4
+ from ... import dataclasses as dc
5
+ from ._compat import compat
6
+ from .cvs import Cvs
7
+ from .responses import Response
8
+ from .routes import Route
9
+ from .routes import RouteKey
10
+
11
+
12
+ if ta.TYPE_CHECKING:
13
+ from .api import Api
14
+
15
+
16
+ T = ta.TypeVar('T')
17
+
18
+
19
+ ##
20
+
21
+
22
+ @dc.dataclass(frozen=True, kw_only=True)
23
+ class AppRunParams:
24
+ app: 'App'
25
+
26
+ port: int | None = None
27
+
28
+
29
+ AppRunner: ta.TypeAlias = ta.Callable[[AppRunParams], None]
30
+
31
+
32
+ ##
33
+
34
+
35
+ ViewFunc: ta.TypeAlias = ta.Callable[[], str]
36
+
37
+ BeforeRequestFunc: ta.TypeAlias = ta.Callable[[], Response | None]
38
+ AfterRequestFunc: ta.TypeAlias = ta.Callable[[ta.Any], ta.Any]
39
+
40
+
41
+ #
42
+
43
+
44
+ class App:
45
+ _api: ta.ClassVar['Api']
46
+
47
+ def __init__(
48
+ self,
49
+ import_name: str,
50
+ ) -> None:
51
+ check.not_none(self._api)
52
+
53
+ super().__init__()
54
+
55
+ self._import_name = check.non_empty_str(import_name)
56
+
57
+ self._routes: set[Route] = set()
58
+ self._routes_by_key: dict[RouteKey, Route] = {}
59
+
60
+ self._view_funcs_by_endpoint: dict[str, ViewFunc] = {}
61
+
62
+ self._before_request_funcs: list[BeforeRequestFunc] = []
63
+ self._after_request_funcs: list[AfterRequestFunc] = []
64
+
65
+ def __repr__(self) -> str:
66
+ return f'{self.__class__.__name__}@{id(self):x}({self._import_name!r})'
67
+
68
+ @property
69
+ def import_name(self) -> str:
70
+ return self._import_name
71
+
72
+ ##
73
+ # routing
74
+
75
+ @property
76
+ def routes(self) -> ta.AbstractSet[Route]:
77
+ return self._routes
78
+
79
+ @property
80
+ def routes_by_key(self) -> ta.Mapping[RouteKey, Route]:
81
+ return self._routes_by_key
82
+
83
+ @property
84
+ def view_funcs_by_endpoint(self) -> ta.Mapping[str, ViewFunc]:
85
+ return self._view_funcs_by_endpoint
86
+
87
+ @compat
88
+ def get(self, rule: str, **options: ta.Any) -> ta.Callable[[T], T]:
89
+ return self._method_route('GET', rule, **options)
90
+
91
+ @compat
92
+ def post(self, rule: str, **options: ta.Any) -> ta.Callable[[T], T]:
93
+ return self._method_route('POST', rule, **options)
94
+
95
+ @compat
96
+ def put(self, rule: str, **options: ta.Any) -> ta.Callable[[T], T]:
97
+ return self._method_route('PUT', rule, **options)
98
+
99
+ @compat
100
+ def delete(self, rule: str, **options: ta.Any) -> ta.Callable[[T], T]:
101
+ return self._method_route('DELETE', rule, **options)
102
+
103
+ @compat
104
+ def patch(self, rule: str, **options: ta.Any) -> ta.Callable[[T], T]:
105
+ return self._method_route('PATCH', rule, **options)
106
+
107
+ def _method_route(
108
+ self,
109
+ method: str,
110
+ rule: str,
111
+ **options: ta.Any,
112
+ ) -> ta.Callable[[T], T]:
113
+ return self.route(
114
+ rule,
115
+ methods=[method],
116
+ **options,
117
+ )
118
+
119
+ @compat
120
+ def route(
121
+ self,
122
+ rule: str,
123
+ **options: ta.Any,
124
+ ) -> ta.Callable[[T], T]:
125
+ def inner(fn):
126
+ endpoint = options.pop('endpoint', None)
127
+ self.add_url_rule(rule, endpoint, fn, **options)
128
+ return fn
129
+
130
+ return inner
131
+
132
+ @compat
133
+ def add_url_rule(
134
+ self,
135
+ rule: str,
136
+ endpoint: str | None = None,
137
+ view_func: ViewFunc | None = None,
138
+ *,
139
+ methods: ta.Iterable[str] | None = None,
140
+ ) -> None:
141
+ check.arg(check.non_empty_str(rule).startswith('/'))
142
+
143
+ if endpoint is None:
144
+ endpoint = check.not_none(view_func).__name__
145
+
146
+ if methods is None:
147
+ methods = ['GET']
148
+ else:
149
+ methods = [check.non_empty_str(m) for m in check.not_isinstance(methods, str)]
150
+ methods = check.not_empty([s.upper() for s in methods])
151
+
152
+ #
153
+
154
+ route = Route(
155
+ rule=rule,
156
+ endpoint=endpoint,
157
+ methods=frozenset(methods),
158
+ )
159
+
160
+ #
161
+
162
+ for rk in route.keys:
163
+ check.not_in(rk, self._routes_by_key)
164
+
165
+ if view_func is not None:
166
+ check.not_in(endpoint, self._view_funcs_by_endpoint)
167
+
168
+ #
169
+
170
+ self._routes.add(route)
171
+ for rk in route.keys:
172
+ self._routes_by_key[rk] = route
173
+
174
+ if view_func is not None:
175
+ self._view_funcs_by_endpoint[endpoint] = view_func
176
+
177
+ ##
178
+ # hooks
179
+
180
+ @property
181
+ def before_request_funcs(self) -> ta.Sequence[BeforeRequestFunc]:
182
+ return self._before_request_funcs
183
+
184
+ @property
185
+ def after_request_funcs(self) -> ta.Sequence[AfterRequestFunc]:
186
+ return self._after_request_funcs
187
+
188
+ def before_request(self, func: T) -> T: # BeforeRequestFunc
189
+ self._before_request_funcs.append(ta.cast(BeforeRequestFunc, check.callable(func)))
190
+ return func
191
+
192
+ def after_request(self, func: T) -> T: # AfterRequestFunc
193
+ self._after_request_funcs.append(ta.cast(AfterRequestFunc, check.callable(func)))
194
+ return func
195
+
196
+ ##
197
+ # running
198
+
199
+ @compat
200
+ def run(self, **kwargs: ta.Any) -> None:
201
+ params = AppRunParams(app=self, **kwargs)
202
+ runner = Cvs.APP_RUNNER.get()
203
+ check.not_none(runner)(params)
@@ -0,0 +1,59 @@
1
+ import contextlib
2
+ import contextvars
3
+ import typing as ta
4
+
5
+ from ... import dataclasses as dc
6
+ from ... import lang
7
+
8
+
9
+ if ta.TYPE_CHECKING:
10
+ from .app import AppRunner
11
+ from .requests import Request
12
+
13
+
14
+ T = ta.TypeVar('T')
15
+
16
+
17
+ ##
18
+
19
+
20
+ @dc.dataclass()
21
+ class CvLookupError(LookupError):
22
+ cv: 'Cv'
23
+
24
+
25
+ @ta.final
26
+ class Cv(ta.Generic[T]):
27
+ def __init__(self, name: str) -> None:
28
+ self._name = name
29
+ self._var: contextvars.ContextVar[T] = contextvars.ContextVar(name)
30
+
31
+ def __repr__(self) -> str:
32
+ return f'{self.__class__.__name__}({self._name!r})'
33
+
34
+ def get(self) -> T:
35
+ try:
36
+ return self._var.get()
37
+ except LookupError:
38
+ raise CvLookupError(self) from None
39
+
40
+ @contextlib.contextmanager
41
+ def set(self, new: T) -> ta.Iterator[None]:
42
+ tok = self._var.set(new)
43
+ try:
44
+ yield
45
+ finally:
46
+ self._var.reset(tok)
47
+
48
+
49
+ ##
50
+
51
+
52
+ def _cv(name: str) -> Cv:
53
+ return Cv(f'{__name__}.Cvs.{name}')
54
+
55
+
56
+ class Cvs(lang.Namespace, lang.Final):
57
+ APP_RUNNER: Cv['AppRunner'] = _cv('APP_RUNNER')
58
+
59
+ REQUEST: Cv['Request'] = _cv('REQUEST')
@@ -0,0 +1,20 @@
1
+ import typing as ta
2
+
3
+ from ... import dataclasses as dc
4
+ from ._compat import compat
5
+ from .types import ImmutableMultiDict
6
+
7
+
8
+ ##
9
+
10
+
11
+ @compat
12
+ @dc.dataclass(frozen=True, kw_only=True)
13
+ class Request:
14
+ path: str
15
+ method: str
16
+
17
+ form: ImmutableMultiDict[str, str] | None = None
18
+
19
+ def get_json(self) -> ta.Any:
20
+ raise NotImplementedError
@@ -0,0 +1,23 @@
1
+ import http
2
+ import typing as ta
3
+
4
+ from ... import dataclasses as dc
5
+ from ._compat import compat
6
+
7
+
8
+ ResponseData: ta.TypeAlias = str | ta.Iterable[str] | bytes | ta.Iterable[bytes]
9
+ ResponseStatus: ta.TypeAlias = int | str | http.HTTPStatus
10
+ ResponseHeaders: ta.TypeAlias = ta.Mapping[str, str | ta.Iterable[str]] | ta.Iterable[tuple[str, str]]
11
+
12
+
13
+ ##
14
+
15
+
16
+ @compat
17
+ @dc.dataclass(frozen=True)
18
+ class Response:
19
+ response: ResponseData | None = None
20
+ status: ResponseStatus | None = None
21
+ headers: ResponseHeaders | None = None
22
+ mimetype: str | None = None
23
+ content_type: str | None = None
@@ -0,0 +1,23 @@
1
+ import typing as ta
2
+
3
+ from ... import cached
4
+ from ... import dataclasses as dc
5
+
6
+
7
+ ##
8
+
9
+
10
+ class RouteKey(ta.NamedTuple):
11
+ rule: str
12
+ method: str
13
+
14
+
15
+ @dc.dataclass(frozen=True, kw_only=True)
16
+ class Route:
17
+ rule: str
18
+ endpoint: str
19
+ methods: frozenset[str]
20
+
21
+ @cached.property
22
+ def keys(self) -> frozenset[RouteKey]:
23
+ return frozenset(RouteKey(self.rule, m) for m in self.methods)