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.
- omlish/{.manifests.json → .omlish-manifests.json} +12 -0
- omlish/__about__.py +21 -18
- omlish/argparse/all.py +17 -9
- omlish/argparse/cli.py +16 -3
- omlish/argparse/utils.py +21 -0
- omlish/asyncs/all.py +0 -13
- omlish/asyncs/asyncio/rlock.py +110 -0
- omlish/asyncs/asyncio/subprocesses.py +2 -2
- omlish/asyncs/asyncio/sync.py +43 -0
- omlish/asyncs/asyncio/utils.py +2 -0
- omlish/asyncs/ioproxy/proxy.py +1 -1
- omlish/asyncs/sync.py +25 -0
- omlish/bootstrap/_marshal.py +1 -1
- omlish/bootstrap/diag.py +12 -21
- omlish/bootstrap/main.py +2 -5
- omlish/bootstrap/sys.py +27 -28
- omlish/c3.py +4 -1
- omlish/cexts/include/omlish/omlish.hh +1 -0
- omlish/collections/__init__.py +13 -1
- omlish/collections/attrregistry.py +210 -0
- omlish/collections/cache/impl.py +3 -2
- omlish/collections/identity.py +1 -0
- omlish/collections/mappings.py +28 -0
- omlish/collections/trie.py +5 -1
- omlish/collections/utils.py +77 -0
- omlish/concurrent/__init__.py +0 -11
- omlish/concurrent/all.py +18 -0
- omlish/concurrent/futures.py +25 -0
- omlish/concurrent/threadlets.py +1 -1
- omlish/configs/processing/flattening.py +1 -1
- omlish/configs/processing/merging.py +8 -6
- omlish/configs/types.py +1 -1
- omlish/daemons/__init__.py +70 -0
- omlish/daemons/daemon.py +2 -2
- omlish/daemons/launching.py +2 -2
- omlish/daemons/reparent.py +2 -3
- omlish/daemons/spawning.py +2 -3
- omlish/dataclasses/__init__.py +5 -5
- omlish/dataclasses/errors.py +1 -1
- omlish/dataclasses/impl/api/classes/decorator.py +3 -0
- omlish/dataclasses/impl/api/classes/make.py +4 -1
- omlish/dataclasses/impl/concerns/doc.py +1 -1
- omlish/dataclasses/impl/concerns/repr.py +15 -2
- omlish/dataclasses/impl/configs.py +97 -36
- omlish/dataclasses/impl/generation/compilation.py +21 -19
- omlish/dataclasses/impl/generation/globals.py +1 -0
- omlish/dataclasses/impl/generation/ops.py +1 -0
- omlish/dataclasses/impl/generation/processor.py +105 -24
- omlish/dataclasses/impl/processing/base.py +8 -0
- omlish/dataclasses/impl/processing/driving.py +8 -8
- omlish/dataclasses/specs.py +34 -2
- omlish/dataclasses/tools/as_.py +0 -12
- omlish/dataclasses/tools/modifiers.py +5 -0
- omlish/dataclasses/tools/static.py +1 -1
- omlish/diag/_pycharm/runhack.py +1 -1
- omlish/diag/{lslocks.py → cmds/lslocks.py} +6 -6
- omlish/diag/{lsof.py → cmds/lsof.py} +6 -6
- omlish/diag/{ps.py → cmds/ps.py} +6 -6
- omlish/diag/procfs.py +4 -4
- omlish/diag/pycharm.py +16 -2
- omlish/diag/pydevd.py +58 -40
- omlish/diag/replserver/console.py +3 -3
- omlish/diag/replserver/server.py +2 -2
- omlish/dispatch/__init__.py +18 -12
- omlish/dispatch/methods.py +50 -140
- omlish/dom/rendering.py +1 -1
- omlish/formats/dotenv.py +8 -8
- omlish/formats/json/stream/__init__.py +18 -3
- omlish/formats/json/stream/building.py +2 -2
- omlish/formats/json/stream/lexing.py +401 -67
- omlish/formats/json/stream/parsing.py +32 -10
- omlish/formats/json/stream/rendering.py +6 -6
- omlish/formats/json/stream/utils.py +132 -30
- omlish/formats/json5/literals.py +7 -4
- omlish/formats/json5/parsing.py +33 -79
- omlish/formats/json5/stream.py +77 -0
- omlish/formats/logfmt.py +8 -2
- omlish/funcs/genmachine.py +2 -2
- omlish/funcs/guard.py +225 -0
- omlish/graphs/dot/rendering.py +1 -1
- omlish/http/all.py +122 -53
- omlish/http/asgi.py +2 -2
- omlish/http/clients/__init__.py +0 -34
- omlish/http/clients/asyncs.py +153 -0
- omlish/http/clients/base.py +63 -122
- omlish/http/clients/coro/sync.py +171 -0
- omlish/http/clients/default.py +209 -30
- omlish/http/clients/executor.py +56 -0
- omlish/http/clients/httpx.py +78 -13
- omlish/http/clients/middleware.py +181 -0
- omlish/http/clients/sync.py +151 -0
- omlish/http/clients/syncasync.py +49 -0
- omlish/http/clients/urllib.py +8 -5
- omlish/http/coro/client/{client.py → connection.py} +43 -37
- omlish/http/coro/client/headers.py +5 -5
- omlish/http/coro/client/response.py +37 -38
- omlish/http/coro/client/status.py +4 -4
- omlish/http/coro/{client/io.py → io.py} +19 -2
- omlish/http/coro/server/fdio.py +10 -9
- omlish/http/coro/server/server.py +14 -41
- omlish/http/coro/server/sockets.py +7 -6
- omlish/http/flasky/__init__.py +40 -0
- omlish/http/flasky/_compat.py +2 -0
- omlish/http/flasky/api.py +82 -0
- omlish/http/flasky/app.py +203 -0
- omlish/http/flasky/cvs.py +59 -0
- omlish/http/flasky/requests.py +20 -0
- omlish/http/flasky/responses.py +23 -0
- omlish/http/flasky/routes.py +23 -0
- omlish/http/flasky/types.py +15 -0
- omlish/http/handlers.py +3 -2
- omlish/http/headers.py +69 -35
- omlish/http/sse.py +1 -1
- omlish/http/urls.py +67 -0
- omlish/inject/__init__.py +173 -126
- omlish/inject/_dataclasses.py +4986 -0
- omlish/inject/binder.py +10 -49
- omlish/inject/elements.py +27 -0
- omlish/inject/{utils.py → helpers/constfn.py} +3 -3
- omlish/inject/{tags.py → helpers/id.py} +2 -2
- omlish/inject/helpers/multis.py +143 -0
- omlish/inject/helpers/wrappers.py +54 -0
- omlish/inject/impl/elements.py +52 -22
- omlish/inject/impl/injector.py +76 -49
- omlish/inject/impl/inspect.py +11 -1
- omlish/inject/impl/maysync.py +43 -0
- omlish/inject/impl/multis.py +10 -7
- omlish/inject/impl/privates.py +8 -8
- omlish/inject/impl/providers.py +23 -34
- omlish/inject/impl/providersmap.py +43 -0
- omlish/inject/impl/proxy.py +0 -2
- omlish/inject/impl/scopes.py +19 -23
- omlish/inject/impl/sync.py +41 -0
- omlish/inject/injector.py +37 -8
- omlish/inject/inspect.py +35 -0
- omlish/inject/listeners.py +4 -4
- omlish/inject/managed.py +54 -18
- omlish/inject/maysync.py +27 -0
- omlish/inject/multis.py +8 -0
- omlish/inject/overrides.py +3 -3
- omlish/inject/privates.py +6 -0
- omlish/inject/providers.py +8 -1
- omlish/inject/scopes.py +40 -12
- omlish/inject/sync.py +49 -0
- omlish/io/buffers.py +119 -1
- omlish/io/readers.py +29 -0
- omlish/iterators/__init__.py +28 -20
- omlish/iterators/transforms.py +204 -0
- omlish/lang/__init__.py +240 -129
- omlish/lang/_asyncs.cc +186 -0
- omlish/lang/asyncs.py +67 -43
- omlish/lang/{attrs.py → attrstorage.py} +15 -15
- omlish/lang/cached/property.py +2 -2
- omlish/lang/casing.py +11 -0
- omlish/lang/classes/bindable.py +2 -3
- omlish/lang/classes/restrict.py +8 -0
- omlish/lang/classes/simple.py +26 -4
- omlish/lang/collections.py +1 -1
- omlish/lang/contextmanagers.py +59 -9
- omlish/lang/functions.py +31 -33
- omlish/lang/imports/_capture.cc +103 -0
- omlish/lang/imports/capture.py +902 -0
- omlish/lang/imports/lazy.py +0 -25
- omlish/lang/imports/proxy.py +559 -0
- omlish/lang/iterables.py +2 -2
- omlish/lang/lazyglobals.py +49 -14
- omlish/lang/maybes.py +2 -1
- omlish/lang/maysync.py +2 -2
- omlish/lang/params.py +17 -0
- omlish/lang/recursion.py +0 -1
- omlish/lang/resources.py +1 -1
- omlish/lang/sequences.py +124 -0
- omlish/lifecycles/contextmanagers.py +1 -2
- omlish/lifecycles/controller.py +1 -2
- omlish/lite/abstract.py +54 -24
- omlish/lite/asyncs.py +146 -0
- omlish/lite/attrops.py +415 -0
- omlish/lite/cached.py +57 -1
- omlish/lite/contextmanagers.py +4 -4
- omlish/lite/dataclasses.py +55 -0
- omlish/lite/inject.py +5 -4
- omlish/lite/marshal.py +1 -0
- omlish/lite/maybes.py +10 -2
- omlish/lite/maysync.py +22 -5
- omlish/lite/pycharm.py +1 -1
- omlish/lite/strings.py +0 -7
- omlish/lite/timing.py +6 -3
- omlish/lite/typing.py +6 -0
- omlish/logs/_amalg.py +8 -0
- omlish/logs/all.py +59 -31
- omlish/logs/base.py +204 -0
- omlish/logs/contexts.py +171 -0
- omlish/logs/formatters.py +13 -0
- omlish/logs/infos.py +377 -0
- omlish/logs/levels.py +97 -0
- omlish/logs/modules.py +13 -0
- omlish/logs/protocols.py +32 -0
- omlish/logs/standard.py +20 -15
- omlish/logs/std/configs.py +29 -0
- omlish/logs/{filters.py → std/filters.py} +1 -1
- omlish/logs/std/formatters.py +25 -0
- omlish/logs/std/handlers.py +19 -0
- omlish/logs/{json.py → std/json.py} +2 -2
- omlish/logs/std/loggers.py +48 -0
- omlish/logs/{proxy.py → std/proxy.py} +3 -3
- omlish/logs/std/records.py +671 -0
- omlish/logs/typed/bindings.py +108 -37
- omlish/logs/typed/types.py +17 -1
- omlish/logs/typed/values.py +2 -2
- omlish/logs/utils.py +60 -4
- omlish/logs/warnings.py +8 -0
- omlish/manifests/loading.py +8 -1
- omlish/marshal/__init__.py +54 -22
- omlish/marshal/_dataclasses.py +2774 -0
- omlish/marshal/base/configs.py +12 -0
- omlish/marshal/base/contexts.py +36 -21
- omlish/marshal/base/funcs.py +8 -11
- omlish/marshal/base/options.py +8 -0
- omlish/marshal/base/registries.py +146 -44
- omlish/marshal/base/types.py +40 -16
- omlish/marshal/composite/iterables.py +33 -20
- omlish/marshal/composite/literals.py +20 -18
- omlish/marshal/composite/mappings.py +36 -23
- omlish/marshal/composite/maybes.py +29 -19
- omlish/marshal/composite/newtypes.py +16 -16
- omlish/marshal/composite/optionals.py +14 -14
- omlish/marshal/composite/special.py +15 -15
- omlish/marshal/composite/unions/literals.py +93 -0
- omlish/marshal/composite/unions/primitives.py +103 -0
- omlish/marshal/factories/invalidate.py +18 -68
- omlish/marshal/factories/method.py +26 -0
- omlish/marshal/factories/moduleimport/factories.py +22 -65
- omlish/marshal/factories/multi.py +13 -25
- omlish/marshal/factories/recursive.py +42 -56
- omlish/marshal/factories/typecache.py +29 -74
- omlish/marshal/factories/typemap.py +42 -43
- omlish/marshal/objects/dataclasses.py +129 -106
- omlish/marshal/objects/marshal.py +18 -14
- omlish/marshal/objects/namedtuples.py +48 -42
- omlish/marshal/objects/unmarshal.py +19 -15
- omlish/marshal/polymorphism/marshal.py +9 -11
- omlish/marshal/polymorphism/metadata.py +16 -5
- omlish/marshal/polymorphism/standard.py +13 -1
- omlish/marshal/polymorphism/unions.py +15 -105
- omlish/marshal/polymorphism/unmarshal.py +9 -10
- omlish/marshal/singular/enums.py +14 -18
- omlish/marshal/standard.py +10 -6
- omlish/marshal/trivial/any.py +1 -1
- omlish/marshal/trivial/forbidden.py +21 -26
- omlish/math/fixed.py +2 -2
- omlish/metadata.py +23 -1
- omlish/os/atomics.py +2 -2
- omlish/os/forkhooks.py +4 -0
- omlish/os/journald.py +3 -3
- omlish/os/pidfiles/pinning.py +2 -2
- omlish/reflect/ops.py +9 -0
- omlish/reflect/types.py +44 -8
- omlish/secrets/marshal.py +1 -1
- omlish/secrets/secrets.py +6 -3
- omlish/sockets/addresses.py +1 -1
- omlish/sockets/server/handlers.py +2 -2
- omlish/sockets/server/server.py +4 -3
- omlish/sockets/server/ssl.py +2 -2
- omlish/specs/jmespath/__init__.py +12 -3
- omlish/specs/jmespath/_dataclasses.py +2893 -0
- omlish/specs/jmespath/ast.py +1 -1
- omlish/specs/jsonrpc/__init__.py +13 -0
- omlish/specs/jsonrpc/_marshal.py +32 -23
- omlish/specs/jsonrpc/conns.py +10 -7
- omlish/specs/jsonschema/_marshal.py +1 -1
- omlish/specs/jsonschema/keywords/__init__.py +7 -0
- omlish/specs/jsonschema/keywords/_dataclasses.py +1644 -0
- omlish/specs/openapi/_marshal.py +31 -22
- omlish/sql/__init__.py +15 -20
- omlish/sql/{tabledefs/alchemy.py → alchemy/tabledefs.py} +2 -2
- omlish/sql/queries/_marshal.py +3 -3
- omlish/sql/queries/params.py +1 -1
- omlish/sql/queries/rendering.py +1 -1
- omlish/sql/tabledefs/_marshal.py +1 -1
- omlish/subprocesses/all.py +135 -0
- omlish/subprocesses/base.py +8 -3
- omlish/subprocesses/editor.py +1 -1
- omlish/sync.py +181 -20
- omlish/term/alt.py +60 -0
- omlish/term/confirm.py +8 -8
- omlish/term/pager.py +235 -0
- omlish/term/terminfo.py +935 -0
- omlish/term/termstate.py +67 -0
- omlish/term/vt100/terminal.py +0 -3
- omlish/testing/pytest/plugins/asyncs/fixtures.py +4 -1
- omlish/testing/pytest/plugins/skips.py +2 -5
- omlish/testing/unittest/main.py +3 -3
- omlish/text/docwrap/__init__.py +3 -0
- omlish/text/docwrap/__main__.py +11 -0
- omlish/text/docwrap/api.py +83 -0
- omlish/text/docwrap/cli.py +86 -0
- omlish/text/docwrap/groups.py +84 -0
- omlish/text/docwrap/lists.py +167 -0
- omlish/text/docwrap/parts.py +146 -0
- omlish/text/docwrap/reflowing.py +106 -0
- omlish/text/docwrap/rendering.py +151 -0
- omlish/text/docwrap/utils.py +11 -0
- omlish/text/docwrap/wrapping.py +59 -0
- omlish/text/filecache.py +2 -2
- omlish/text/lorem.py +6 -0
- omlish/text/parts.py +2 -2
- omlish/text/textwrap.py +51 -0
- omlish/typedvalues/__init__.py +1 -1
- omlish/typedvalues/marshal.py +85 -59
- omlish/typedvalues/values.py +2 -1
- {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev484.dist-info}/METADATA +36 -38
- {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev484.dist-info}/RECORD +323 -385
- omlish/asyncs/bluelet/LICENSE +0 -6
- omlish/asyncs/bluelet/all.py +0 -67
- omlish/asyncs/bluelet/api.py +0 -23
- omlish/asyncs/bluelet/core.py +0 -178
- omlish/asyncs/bluelet/events.py +0 -79
- omlish/asyncs/bluelet/files.py +0 -80
- omlish/asyncs/bluelet/runner.py +0 -417
- omlish/asyncs/bluelet/sockets.py +0 -216
- omlish/asyncs/bridge.py +0 -359
- omlish/asyncs/utils.py +0 -18
- omlish/dataclasses/impl/generation/mangling.py +0 -18
- omlish/defs.py +0 -216
- omlish/dispatch/_dispatch2.py +0 -69
- omlish/dispatch/_dispatch3.py +0 -108
- omlish/dynamic.py +0 -219
- omlish/formats/json/Json.g4 +0 -77
- omlish/formats/json/_antlr/JsonLexer.py +0 -109
- omlish/formats/json/_antlr/JsonListener.py +0 -61
- omlish/formats/json/_antlr/JsonParser.py +0 -457
- omlish/formats/json/_antlr/JsonVisitor.py +0 -42
- omlish/formats/json5/Json5.g4 +0 -168
- omlish/formats/json5/_antlr/Json5Lexer.py +0 -354
- omlish/formats/json5/_antlr/Json5Listener.py +0 -79
- omlish/formats/json5/_antlr/Json5Parser.py +0 -617
- omlish/formats/json5/_antlr/Json5Visitor.py +0 -52
- omlish/funcs/match.py +0 -227
- omlish/io/trampoline.py +0 -289
- omlish/lang/imports/proxyinit.py +0 -665
- omlish/lite/logs.py +0 -4
- omlish/lite/reprs.py +0 -85
- omlish/logs/abc.py +0 -319
- omlish/logs/callers.py +0 -67
- omlish/logs/color.py +0 -27
- omlish/logs/configs.py +0 -29
- omlish/logs/handlers.py +0 -17
- omlish/logs/protocol.py +0 -218
- omlish/logs/timing.py +0 -58
- omlish/marshal/factories/match.py +0 -34
- omlish/marshal/factories/simple.py +0 -28
- omlish/specs/irc/messages/base.py +0 -49
- omlish/specs/irc/messages/formats.py +0 -92
- omlish/specs/irc/messages/messages.py +0 -774
- omlish/specs/irc/messages/parsing.py +0 -98
- omlish/specs/irc/numerics/formats.py +0 -97
- omlish/specs/irc/numerics/numerics.py +0 -865
- omlish/specs/irc/numerics/types.py +0 -59
- omlish/specs/irc/protocol/LICENSE +0 -11
- omlish/specs/irc/protocol/__init__.py +0 -61
- omlish/specs/irc/protocol/consts.py +0 -6
- omlish/specs/irc/protocol/errors.py +0 -30
- omlish/specs/irc/protocol/message.py +0 -21
- omlish/specs/irc/protocol/nuh.py +0 -55
- omlish/specs/irc/protocol/parsing.py +0 -158
- omlish/specs/irc/protocol/rendering.py +0 -153
- omlish/specs/irc/protocol/tags.py +0 -102
- omlish/specs/irc/protocol/utils.py +0 -30
- omlish/specs/proto/Protobuf3.g4 +0 -396
- omlish/specs/proto/__init__.py +0 -0
- omlish/specs/proto/_antlr/Protobuf3Lexer.py +0 -340
- omlish/specs/proto/_antlr/Protobuf3Listener.py +0 -448
- omlish/specs/proto/_antlr/Protobuf3Parser.py +0 -3909
- omlish/specs/proto/_antlr/Protobuf3Visitor.py +0 -257
- omlish/specs/proto/_antlr/__init__.py +0 -0
- omlish/specs/proto/nodes.py +0 -54
- omlish/specs/proto/parsing.py +0 -97
- omlish/sql/parsing/Minisql.g4 +0 -292
- omlish/sql/parsing/__init__.py +0 -0
- omlish/sql/parsing/_antlr/MinisqlLexer.py +0 -322
- omlish/sql/parsing/_antlr/MinisqlListener.py +0 -511
- omlish/sql/parsing/_antlr/MinisqlParser.py +0 -3763
- omlish/sql/parsing/_antlr/MinisqlVisitor.py +0 -292
- omlish/sql/parsing/_antlr/__init__.py +0 -0
- omlish/sql/parsing/parsing.py +0 -119
- omlish/text/antlr/__init__.py +0 -3
- omlish/text/antlr/_runtime/BufferedTokenStream.py +0 -305
- omlish/text/antlr/_runtime/CommonTokenFactory.py +0 -64
- omlish/text/antlr/_runtime/CommonTokenStream.py +0 -90
- omlish/text/antlr/_runtime/FileStream.py +0 -30
- omlish/text/antlr/_runtime/InputStream.py +0 -90
- omlish/text/antlr/_runtime/IntervalSet.py +0 -183
- omlish/text/antlr/_runtime/LICENSE.txt +0 -28
- omlish/text/antlr/_runtime/LL1Analyzer.py +0 -176
- omlish/text/antlr/_runtime/Lexer.py +0 -332
- omlish/text/antlr/_runtime/ListTokenSource.py +0 -147
- omlish/text/antlr/_runtime/Parser.py +0 -583
- omlish/text/antlr/_runtime/ParserInterpreter.py +0 -173
- omlish/text/antlr/_runtime/ParserRuleContext.py +0 -189
- omlish/text/antlr/_runtime/PredictionContext.py +0 -632
- omlish/text/antlr/_runtime/Recognizer.py +0 -150
- omlish/text/antlr/_runtime/RuleContext.py +0 -230
- omlish/text/antlr/_runtime/StdinStream.py +0 -14
- omlish/text/antlr/_runtime/Token.py +0 -158
- omlish/text/antlr/_runtime/TokenStreamRewriter.py +0 -258
- omlish/text/antlr/_runtime/Utils.py +0 -36
- omlish/text/antlr/_runtime/__init__.py +0 -2
- omlish/text/antlr/_runtime/_all.py +0 -24
- omlish/text/antlr/_runtime/_pygrun.py +0 -174
- omlish/text/antlr/_runtime/atn/ATN.py +0 -135
- omlish/text/antlr/_runtime/atn/ATNConfig.py +0 -162
- omlish/text/antlr/_runtime/atn/ATNConfigSet.py +0 -215
- omlish/text/antlr/_runtime/atn/ATNDeserializationOptions.py +0 -27
- omlish/text/antlr/_runtime/atn/ATNDeserializer.py +0 -449
- omlish/text/antlr/_runtime/atn/ATNSimulator.py +0 -50
- omlish/text/antlr/_runtime/atn/ATNState.py +0 -267
- omlish/text/antlr/_runtime/atn/ATNType.py +0 -20
- omlish/text/antlr/_runtime/atn/LexerATNSimulator.py +0 -573
- omlish/text/antlr/_runtime/atn/LexerAction.py +0 -301
- omlish/text/antlr/_runtime/atn/LexerActionExecutor.py +0 -146
- omlish/text/antlr/_runtime/atn/ParserATNSimulator.py +0 -1664
- omlish/text/antlr/_runtime/atn/PredictionMode.py +0 -502
- omlish/text/antlr/_runtime/atn/SemanticContext.py +0 -333
- omlish/text/antlr/_runtime/atn/Transition.py +0 -271
- omlish/text/antlr/_runtime/atn/__init__.py +0 -4
- omlish/text/antlr/_runtime/dfa/DFA.py +0 -136
- omlish/text/antlr/_runtime/dfa/DFASerializer.py +0 -76
- omlish/text/antlr/_runtime/dfa/DFAState.py +0 -129
- omlish/text/antlr/_runtime/dfa/__init__.py +0 -4
- omlish/text/antlr/_runtime/error/DiagnosticErrorListener.py +0 -111
- omlish/text/antlr/_runtime/error/ErrorListener.py +0 -75
- omlish/text/antlr/_runtime/error/ErrorStrategy.py +0 -712
- omlish/text/antlr/_runtime/error/Errors.py +0 -176
- omlish/text/antlr/_runtime/error/__init__.py +0 -4
- omlish/text/antlr/_runtime/tree/Chunk.py +0 -33
- omlish/text/antlr/_runtime/tree/ParseTreeMatch.py +0 -121
- omlish/text/antlr/_runtime/tree/ParseTreePattern.py +0 -75
- omlish/text/antlr/_runtime/tree/ParseTreePatternMatcher.py +0 -377
- omlish/text/antlr/_runtime/tree/RuleTagToken.py +0 -53
- omlish/text/antlr/_runtime/tree/TokenTagToken.py +0 -50
- omlish/text/antlr/_runtime/tree/Tree.py +0 -194
- omlish/text/antlr/_runtime/tree/Trees.py +0 -114
- omlish/text/antlr/_runtime/tree/__init__.py +0 -2
- omlish/text/antlr/_runtime/xpath/XPath.py +0 -278
- omlish/text/antlr/_runtime/xpath/XPathLexer.py +0 -98
- omlish/text/antlr/_runtime/xpath/__init__.py +0 -4
- omlish/text/antlr/delimit.py +0 -109
- omlish/text/antlr/dot.py +0 -41
- omlish/text/antlr/errors.py +0 -14
- omlish/text/antlr/input.py +0 -96
- omlish/text/antlr/parsing.py +0 -54
- omlish/text/antlr/runtime.py +0 -102
- omlish/text/antlr/utils.py +0 -38
- /omlish/{asyncs/bluelet → cexts}/__init__.py +0 -0
- /omlish/{formats/json/_antlr → diag/cmds}/__init__.py +0 -0
- /omlish/{formats/json5/_antlr → http/clients/coro}/__init__.py +0 -0
- /omlish/{specs/irc → inject/helpers}/__init__.py +0 -0
- /omlish/{specs/irc/messages → logs/std}/__init__.py +0 -0
- /omlish/logs/{noisy.py → std/noisy.py} +0 -0
- /omlish/{specs/irc/numerics → marshal/composite/unions}/__init__.py +0 -0
- {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev484.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev484.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev484.dist-info}/licenses/LICENSE +0 -0
- {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev484.dist-info}/top_level.txt +0 -0
omlish/http/coro/server/fdio.py
CHANGED
|
@@ -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,
|
|
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
|
-
|
|
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[
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
415
|
+
if isinstance(o, CoroHttpIo.AnyLogIo):
|
|
443
416
|
i = None
|
|
444
417
|
yield o
|
|
445
418
|
|
|
446
|
-
elif isinstance(o,
|
|
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
|
|
427
|
+
check.none((yield CoroHttpIo.WriteIo(hb)))
|
|
455
428
|
|
|
456
429
|
for b in self._yield_response_data(r):
|
|
457
|
-
yield
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
61
|
+
elif isinstance(o, CoroHttpIo.ReadLineIo):
|
|
61
62
|
i = fp.r.readline(o.sz)
|
|
62
63
|
|
|
63
|
-
elif isinstance(o,
|
|
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,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)
|