tigrbl 0.3.16.dev4__tar.gz → 0.3.16.dev5__tar.gz
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.
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/PKG-INFO +17 -17
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/README.md +16 -16
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/pyproject.toml +1 -1
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/README.md +1 -1
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/__init__.py +10 -23
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/app/_app.py +41 -27
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/app/_model_registry.py +33 -7
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/app/app_spec.py +4 -2
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/app/mro_collect.py +6 -6
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/app/shortcuts.py +3 -3
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/app/tigrbl_app.py +211 -111
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/__init__.py +13 -13
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/handlers/steps.py +3 -1
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/hooks.py +16 -16
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/model.py +17 -6
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/model_registry.py +10 -2
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/rest/attach.py +4 -4
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/rest/collection.py +40 -55
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/rest/common.py +2 -2
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/rest/io.py +19 -6
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/rest/member.py +38 -87
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/rest/router.py +4 -4
- {tigrbl-0.3.16.dev4/tigrbl/bindings/api → tigrbl-0.3.16.dev5/tigrbl/bindings/router}/__init__.py +7 -3
- {tigrbl-0.3.16.dev4/tigrbl/bindings/api → tigrbl-0.3.16.dev5/tigrbl/bindings/router}/common.py +11 -11
- {tigrbl-0.3.16.dev4/tigrbl/bindings/api → tigrbl-0.3.16.dev5/tigrbl/bindings/router}/include.py +77 -73
- {tigrbl-0.3.16.dev4/tigrbl/bindings/api → tigrbl-0.3.16.dev5/tigrbl/bindings/router}/resource_proxy.py +22 -48
- {tigrbl-0.3.16.dev4/tigrbl/bindings/api → tigrbl-0.3.16.dev5/tigrbl/bindings/router}/rpc.py +9 -7
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/rpc.py +12 -74
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/config/__init__.py +3 -3
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/config/constants.py +3 -3
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/config/defaults.py +3 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/config/resolver.py +8 -4
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/core/crud/__init__.py +7 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/core/crud/params.py +1 -1
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/ddl/__init__.py +1 -1
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/deps/__init__.py +2 -4
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/engine/bind.py +10 -5
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/engine/collect.py +14 -9
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/engine/decorators.py +4 -4
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/engine/resolver.py +28 -26
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/middlewares/decorators.py +1 -1
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/op/__init__.py +4 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/op/_op.py +2 -2
- tigrbl-0.3.16.dev5/tigrbl/op/alias.py +42 -0
- tigrbl-0.3.16.dev5/tigrbl/op/alias_spec.py +35 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/op/decorators.py +23 -38
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/op/mro_collect.py +30 -32
- tigrbl-0.3.16.dev5/tigrbl/op/op_spec.py +90 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/op/types.py +3 -68
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/requests/_request.py +1 -1
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/responses/shortcuts.py +1 -1
- tigrbl-0.3.16.dev5/tigrbl/router/__init__.py +23 -0
- {tigrbl-0.3.16.dev4/tigrbl/api → tigrbl-0.3.16.dev5/tigrbl/router}/_router.py +101 -169
- {tigrbl-0.3.16.dev4/tigrbl/api → tigrbl-0.3.16.dev5/tigrbl/router}/_routing.py +2 -2
- tigrbl-0.3.16.dev5/tigrbl/router/decorators.py +115 -0
- {tigrbl-0.3.16.dev4/tigrbl/api → tigrbl-0.3.16.dev5/tigrbl/router}/mro_collect.py +11 -9
- tigrbl-0.3.16.dev4/tigrbl/api/api_spec.py → tigrbl-0.3.16.dev5/tigrbl/router/router_spec.py +6 -6
- tigrbl-0.3.16.dev5/tigrbl/router/shortcuts.py +56 -0
- tigrbl-0.3.16.dev4/tigrbl/api/tigrbl_api.py → tigrbl-0.3.16.dev5/tigrbl/router/tigrbl_router.py +36 -35
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/__init__.py +2 -0
- tigrbl-0.3.16.dev5/tigrbl/runtime/atoms/dep/__init__.py +15 -0
- tigrbl-0.3.16.dev5/tigrbl/runtime/atoms/dep/extra.py +21 -0
- tigrbl-0.3.16.dev5/tigrbl/runtime/atoms/dep/security.py +21 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/events.py +55 -13
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/executor/invoke.py +2 -2
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/executor/types.py +1 -1
- tigrbl-0.3.16.dev5/tigrbl/runtime/kernel/__init__.py +44 -0
- tigrbl-0.3.16.dev5/tigrbl/runtime/kernel/atoms.py +189 -0
- tigrbl-0.3.16.dev5/tigrbl/runtime/kernel/cache.py +85 -0
- tigrbl-0.3.16.dev5/tigrbl/runtime/kernel/core.py +226 -0
- tigrbl-0.3.16.dev5/tigrbl/runtime/kernel/models.py +27 -0
- tigrbl-0.3.16.dev5/tigrbl/runtime/kernel/opview_compiler.py +93 -0
- tigrbl-0.3.16.dev5/tigrbl/runtime/kernel/payload.py +74 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/opview.py +2 -2
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/ordering.py +2 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/session/README.md +1 -1
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/session/decorators.py +1 -1
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/session/spec.py +1 -1
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/shortcuts.py +3 -3
- tigrbl-0.3.16.dev5/tigrbl/system/diagnostics/compat.py +8 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/system/diagnostics/hookz.py +2 -2
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/system/diagnostics/methodz.py +2 -2
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/system/diagnostics/router.py +9 -8
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/system/diagnostics/utils.py +2 -2
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/system/docs/lens.py +1 -1
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/system/docs/openapi/helpers.py +2 -2
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/system/docs/openapi/mount.py +1 -1
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/system/docs/openapi/schema.py +1 -1
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/system/docs/openrpc.py +54 -20
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/system/docs/swagger.py +14 -8
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/system/favicon/__init__.py +52 -26
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/table/_base.py +1 -1
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/table/_table.py +3 -3
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/table/table_spec.py +12 -3
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/transport/__init__.py +8 -8
- tigrbl-0.3.16.dev5/tigrbl/transport/dispatch.py +175 -0
- tigrbl-0.3.16.dev5/tigrbl/transport/jsonrpc/__init__.py +20 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/transport/jsonrpc/dispatcher.py +101 -95
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/transport/jsonrpc/helpers.py +13 -34
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/transport/rest/__init__.py +7 -11
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/transport/rest/aggregator.py +16 -30
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/types/__init__.py +23 -20
- tigrbl-0.3.16.dev4/tigrbl/api/__init__.py +0 -19
- tigrbl-0.3.16.dev4/tigrbl/api/_api.py +0 -150
- tigrbl-0.3.16.dev4/tigrbl/api/shortcuts.py +0 -56
- tigrbl-0.3.16.dev4/tigrbl/bindings/rest/fastapi.py +0 -52
- tigrbl-0.3.16.dev4/tigrbl/runtime/kernel.py +0 -644
- tigrbl-0.3.16.dev4/tigrbl/system/diagnostics/compat.py +0 -31
- tigrbl-0.3.16.dev4/tigrbl/transport/jsonrpc/__init__.py +0 -23
- tigrbl-0.3.16.dev4/tigrbl/transport/jsonrpc/openrpc.py +0 -3
- tigrbl-0.3.16.dev4/tigrbl/transport/rest/decorators.py +0 -30
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/LICENSE +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/app/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/app/transport.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/columns.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/handlers/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/handlers/builder.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/handlers/ctx.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/handlers/identifiers.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/handlers/namespaces.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/model_helpers.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/rest/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/rest/helpers.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/rest/io_headers.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/rest/routing.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/schemas/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/schemas/builder.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/schemas/defaults.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/bindings/schemas/utils.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/column/README.md +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/column/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/column/_column.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/column/column_spec.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/column/field_spec.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/column/infer/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/column/infer/core.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/column/infer/jsonhints.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/column/infer/planning.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/column/infer/types.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/column/infer/utils.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/column/io_spec.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/column/mro_collect.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/column/shortcuts.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/column/storage_spec.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/core/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/core/crud/bulk.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/core/crud/helpers/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/core/crud/helpers/db.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/core/crud/helpers/enum.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/core/crud/helpers/filters.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/core/crud/helpers/model.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/core/crud/helpers/normalize.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/core/crud/ops.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/core/resolver.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/decorators.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/deps/jinja.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/deps/pydantic.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/deps/sqlalchemy.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/docs/verbosity.md +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/engine/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/engine/_engine.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/engine/builders.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/engine/capabilities.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/engine/docs/PLUGINS.md +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/engine/engine_spec.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/engine/plugins.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/engine/registry.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/engine/shortcuts.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/headers/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/headers/_header.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/hook/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/hook/_hook.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/hook/decorators.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/hook/exceptions.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/hook/hook_spec.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/hook/mro_collect.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/hook/shortcuts.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/hook/types.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/middlewares/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/middlewares/base.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/middlewares/compose.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/middlewares/cors.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/middlewares/middleware.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/middlewares/spec.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/op/canonical.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/op/collect.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/op/model_registry.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/op/resolver.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/mixins/_RowBound.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/mixins/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/mixins/bootstrappable.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/mixins/bound.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/mixins/edges.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/mixins/fields.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/mixins/hierarchy.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/mixins/key_digest.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/mixins/lifecycle.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/mixins/locks.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/mixins/markers.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/mixins/operations.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/mixins/ownable.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/mixins/principals.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/mixins/tenant_bound.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/mixins/upsertable.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/mixins/utils.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/tables/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/tables/_base.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/tables/audit.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/tables/client.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/tables/group.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/tables/org.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/tables/rbac.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/tables/status.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/tables/tenant.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/orm/tables/user.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/requests/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/requests/adapters.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/responses/README.md +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/responses/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/responses/_response.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/responses/_transport.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/responses/bind.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/responses/decorators.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/responses/resolver.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/responses/types.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/rest/__init__.py +0 -0
- {tigrbl-0.3.16.dev4/tigrbl/api → tigrbl-0.3.16.dev5/tigrbl/router}/_route.py +0 -0
- {tigrbl-0.3.16.dev4/tigrbl/api → tigrbl-0.3.16.dev5/tigrbl/router}/resolve.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/README.md +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/emit/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/emit/paired_post.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/emit/paired_pre.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/emit/readtime_alias.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/out/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/out/masking.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/refresh/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/refresh/demand.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/resolve/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/resolve/assemble.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/resolve/paired_gen.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/response/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/response/headers_from_payload.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/response/negotiate.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/response/negotiation.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/response/render.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/response/renderer.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/response/template.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/response/templates.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/schema/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/schema/collect_in.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/schema/collect_out.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/storage/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/storage/to_stored.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/wire/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/wire/build_in.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/wire/build_out.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/wire/dump.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/atoms/wire/validate_in.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/context.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/executor/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/executor/guards.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/executor/helpers.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/labels.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/status/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/status/converters.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/status/exceptions.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/status/mappings.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/status/utils.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/system.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/runtime/trace.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/schema/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/schema/_schema.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/schema/builder/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/schema/builder/build_schema.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/schema/builder/cache.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/schema/builder/compat.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/schema/builder/extras.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/schema/builder/helpers.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/schema/builder/list_params.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/schema/builder/strip_parent_fields.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/schema/collect.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/schema/decorators.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/schema/get_schema.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/schema/schema_spec.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/schema/shortcuts.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/schema/types.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/schema/utils.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/security/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/security/dependencies.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/security/schemes/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/security/schemes/_base.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/security/schemes/api_key.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/security/schemes/http_bearer.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/security/schemes/mutual_tls.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/security/schemes/oauth2.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/security/schemes/openid_connect.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/session/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/session/abc.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/session/base.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/session/default.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/session/shortcuts.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/specs.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/system/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/system/diagnostics/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/system/diagnostics/healthz.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/system/diagnostics/kernelz.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/system/docs/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/system/docs/openapi/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/system/docs/openapi/metadata.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/system/favicon/assets/favicon.svg +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/system/uvicorn.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/table/__init__.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/table/mro_collect.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/table/shortcuts.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/transport/background.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/transport/httpx.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/transport/jsonrpc/models.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/types/allow_anon_provider.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/types/authn_abc.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/types/nested_path_provider.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/types/op.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/types/op_config_provider.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/types/op_verb_alias_provider.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/types/request_extras_provider.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/types/response_extras_provider.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/types/table_config_provider.py +0 -0
- {tigrbl-0.3.16.dev4 → tigrbl-0.3.16.dev5}/tigrbl/types/uuid.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tigrbl
|
|
3
|
-
Version: 0.3.16.
|
|
3
|
+
Version: 0.3.16.dev5
|
|
4
4
|
Summary: A modern pure ASGI/WSGI Python framework for building schema-first REST and JSON-RPC APIs with SQLAlchemy models, typed validation, lifecycle hooks, and engine extension support.
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
License-File: LICENSE
|
|
@@ -63,7 +63,7 @@ A high-leverage ASGI meta-framework that turns plain SQLAlchemy models into a fu
|
|
|
63
63
|
|
|
64
64
|
- **Tenant** 🏢 – a namespace used to group related resources.
|
|
65
65
|
- **Principal** 👤 – an owner of resources, such as an individual user or an organization.
|
|
66
|
-
- **Resource** 📦 – a logical collection of data or functionality exposed by the
|
|
66
|
+
- **Resource** 📦 – a logical collection of data or functionality exposed by the router.
|
|
67
67
|
- **Engine** ⚙️ – the database connection and transaction manager backing a resource.
|
|
68
68
|
- **Model / Table** 🧱 – the ORM or database representation of a resource's records.
|
|
69
69
|
- **Column** 📏 – a field on a model that maps to a table column.
|
|
@@ -310,7 +310,7 @@ increasing order of precedence:
|
|
|
310
310
|
|
|
311
311
|
1. defaults
|
|
312
312
|
2. app config
|
|
313
|
-
3.
|
|
313
|
+
3. router config
|
|
314
314
|
4. table config
|
|
315
315
|
5. column config
|
|
316
316
|
6. operation spec
|
|
@@ -318,7 +318,7 @@ increasing order of precedence:
|
|
|
318
318
|
|
|
319
319
|
Later entries override earlier ones, so request overrides win over all other
|
|
320
320
|
sources. This can be summarized as
|
|
321
|
-
`overrides > opspec > colspecs > tabspec >
|
|
321
|
+
`overrides > opspec > colspecs > tabspec > routerspec > appspec > defaults`.
|
|
322
322
|
|
|
323
323
|
### Schema Config Precedence 🧬
|
|
324
324
|
|
|
@@ -327,7 +327,7 @@ Later layers override earlier ones, with the precedence order:
|
|
|
327
327
|
|
|
328
328
|
1. defaults (lowest)
|
|
329
329
|
2. app configuration
|
|
330
|
-
3.
|
|
330
|
+
3. router configuration
|
|
331
331
|
4. table configuration
|
|
332
332
|
5. column-level `cfg` values
|
|
333
333
|
6. op-specific `cfg`
|
|
@@ -367,7 +367,7 @@ This hierarchy ensures that the most specific settings always win. 🥇
|
|
|
367
367
|
When assembling values for persistence, defaults are resolved in this order:
|
|
368
368
|
|
|
369
369
|
1. Client-supplied value
|
|
370
|
-
2.
|
|
370
|
+
2. router `default_factory`
|
|
371
371
|
3. ORM default
|
|
372
372
|
4. Database `server_default`
|
|
373
373
|
5. HTTP 422 if the field is required and still missing
|
|
@@ -408,15 +408,15 @@ approved usage. These are not optional—adhering to them keeps the runtime
|
|
|
408
408
|
predictable, preserves hook lifecycle guarantees, and ensures schema
|
|
409
409
|
consistency across REST and RPC surfaces.
|
|
410
410
|
|
|
411
|
-
### 1) Never import SQLAlchemy directly or bypass Tigrbl
|
|
411
|
+
### 1) Never import SQLAlchemy directly or bypass Tigrbl routers
|
|
412
412
|
|
|
413
413
|
**Why:** Direct imports bypass Tigrbl's compatibility layer and make it
|
|
414
414
|
harder to evolve internal dependencies. Use the Tigrbl exports so your
|
|
415
|
-
code stays aligned with the framework’s versioned ASGI
|
|
415
|
+
code stays aligned with the framework’s versioned ASGI router.
|
|
416
416
|
|
|
417
417
|
✅ **Preferred:**
|
|
418
418
|
```python
|
|
419
|
-
from tigrbl import Base, TigrblApp,
|
|
419
|
+
from tigrbl import Base, TigrblApp, TigrblRouter
|
|
420
420
|
from tigrbl.types import Integer, String, Mapped
|
|
421
421
|
from tigrbl.types import Depends, HTTPException, Request
|
|
422
422
|
```
|
|
@@ -452,7 +452,7 @@ item_id = UUID(str(payload["id"]))
|
|
|
452
452
|
### 3) Use engine specs for persistence, not ad-hoc engines
|
|
453
453
|
|
|
454
454
|
**Why:** Engine specs make persistence declarative, testable, and
|
|
455
|
-
compatible with engine resolution across app,
|
|
455
|
+
compatible with engine resolution across app, router, table, and op scopes.
|
|
456
456
|
|
|
457
457
|
✅ **Preferred:**
|
|
458
458
|
```python
|
|
@@ -588,9 +588,9 @@ async def rotate_keys(payload, *, ctx):
|
|
|
588
588
|
|
|
589
589
|
🚫 **Avoid:**
|
|
590
590
|
```python
|
|
591
|
-
from some_framework import
|
|
591
|
+
from some_framework import routerRouter
|
|
592
592
|
|
|
593
|
-
router =
|
|
593
|
+
router = routerRouter()
|
|
594
594
|
|
|
595
595
|
@router.post("/keys/rotate")
|
|
596
596
|
async def rotate_keys(payload):
|
|
@@ -664,8 +664,8 @@ When engine contexts are declared at multiple scopes, Tigrbl resolves them
|
|
|
664
664
|
with strict precedence:
|
|
665
665
|
|
|
666
666
|
1. **Op level** – bindings attached directly to an operation take highest priority.
|
|
667
|
-
2. **Table/Model level** – definitions on a model or table override
|
|
668
|
-
3. **
|
|
667
|
+
2. **Table/Model level** – definitions on a model or table override router and app defaults.
|
|
668
|
+
3. **router level** – bindings on the router class apply when no model-specific context exists.
|
|
669
669
|
4. **App level** – the default engine supplied to the application is used last.
|
|
670
670
|
|
|
671
671
|
This ordering ensures that the most specific engine context always wins.
|
|
@@ -679,7 +679,7 @@ from tigrbl.engine.shortcuts import prov, engine
|
|
|
679
679
|
app = SimpleNamespace(db=prov(kind="sqlite", mode="memory"))
|
|
680
680
|
alt = SimpleNamespace(db=engine(kind="sqlite", mode="memory"))
|
|
681
681
|
|
|
682
|
-
class
|
|
682
|
+
class router:
|
|
683
683
|
db = {"kind": "sqlite", "memory": True}
|
|
684
684
|
|
|
685
685
|
class Item:
|
|
@@ -708,7 +708,7 @@ class App:
|
|
|
708
708
|
pass
|
|
709
709
|
|
|
710
710
|
@engine_ctx(engine(kind="sqlite", mode="memory"))
|
|
711
|
-
class
|
|
711
|
+
class Decoratedrouter:
|
|
712
712
|
pass
|
|
713
713
|
|
|
714
714
|
@engine_ctx(kind="sqlite", mode="memory")
|
|
@@ -735,7 +735,7 @@ The bridge examples cover two integration styles:
|
|
|
735
735
|
* A Swarmauri `Factory` invocation during `PRE_HANDLER` via `hook_ctx`.
|
|
736
736
|
* Tigrbl default verbs (`create`, `get`, `list`, `update`, `delete`) plus a custom op.
|
|
737
737
|
* `engine_ctx` at model and operation scope.
|
|
738
|
-
* Generated
|
|
738
|
+
* Generated Openrouter and OpenRPC documents mounted from the same model bindings.
|
|
739
739
|
|
|
740
740
|
* **Smoother direct-model flow** (`swarmauri_tigrbl_bridge_smooth.py`)
|
|
741
741
|
* Uses hooks + default `create` persistence to normalize Swarmauri payloads.
|
|
@@ -30,7 +30,7 @@ A high-leverage ASGI meta-framework that turns plain SQLAlchemy models into a fu
|
|
|
30
30
|
|
|
31
31
|
- **Tenant** 🏢 – a namespace used to group related resources.
|
|
32
32
|
- **Principal** 👤 – an owner of resources, such as an individual user or an organization.
|
|
33
|
-
- **Resource** 📦 – a logical collection of data or functionality exposed by the
|
|
33
|
+
- **Resource** 📦 – a logical collection of data or functionality exposed by the router.
|
|
34
34
|
- **Engine** ⚙️ – the database connection and transaction manager backing a resource.
|
|
35
35
|
- **Model / Table** 🧱 – the ORM or database representation of a resource's records.
|
|
36
36
|
- **Column** 📏 – a field on a model that maps to a table column.
|
|
@@ -277,7 +277,7 @@ increasing order of precedence:
|
|
|
277
277
|
|
|
278
278
|
1. defaults
|
|
279
279
|
2. app config
|
|
280
|
-
3.
|
|
280
|
+
3. router config
|
|
281
281
|
4. table config
|
|
282
282
|
5. column config
|
|
283
283
|
6. operation spec
|
|
@@ -285,7 +285,7 @@ increasing order of precedence:
|
|
|
285
285
|
|
|
286
286
|
Later entries override earlier ones, so request overrides win over all other
|
|
287
287
|
sources. This can be summarized as
|
|
288
|
-
`overrides > opspec > colspecs > tabspec >
|
|
288
|
+
`overrides > opspec > colspecs > tabspec > routerspec > appspec > defaults`.
|
|
289
289
|
|
|
290
290
|
### Schema Config Precedence 🧬
|
|
291
291
|
|
|
@@ -294,7 +294,7 @@ Later layers override earlier ones, with the precedence order:
|
|
|
294
294
|
|
|
295
295
|
1. defaults (lowest)
|
|
296
296
|
2. app configuration
|
|
297
|
-
3.
|
|
297
|
+
3. router configuration
|
|
298
298
|
4. table configuration
|
|
299
299
|
5. column-level `cfg` values
|
|
300
300
|
6. op-specific `cfg`
|
|
@@ -334,7 +334,7 @@ This hierarchy ensures that the most specific settings always win. 🥇
|
|
|
334
334
|
When assembling values for persistence, defaults are resolved in this order:
|
|
335
335
|
|
|
336
336
|
1. Client-supplied value
|
|
337
|
-
2.
|
|
337
|
+
2. router `default_factory`
|
|
338
338
|
3. ORM default
|
|
339
339
|
4. Database `server_default`
|
|
340
340
|
5. HTTP 422 if the field is required and still missing
|
|
@@ -375,15 +375,15 @@ approved usage. These are not optional—adhering to them keeps the runtime
|
|
|
375
375
|
predictable, preserves hook lifecycle guarantees, and ensures schema
|
|
376
376
|
consistency across REST and RPC surfaces.
|
|
377
377
|
|
|
378
|
-
### 1) Never import SQLAlchemy directly or bypass Tigrbl
|
|
378
|
+
### 1) Never import SQLAlchemy directly or bypass Tigrbl routers
|
|
379
379
|
|
|
380
380
|
**Why:** Direct imports bypass Tigrbl's compatibility layer and make it
|
|
381
381
|
harder to evolve internal dependencies. Use the Tigrbl exports so your
|
|
382
|
-
code stays aligned with the framework’s versioned ASGI
|
|
382
|
+
code stays aligned with the framework’s versioned ASGI router.
|
|
383
383
|
|
|
384
384
|
✅ **Preferred:**
|
|
385
385
|
```python
|
|
386
|
-
from tigrbl import Base, TigrblApp,
|
|
386
|
+
from tigrbl import Base, TigrblApp, TigrblRouter
|
|
387
387
|
from tigrbl.types import Integer, String, Mapped
|
|
388
388
|
from tigrbl.types import Depends, HTTPException, Request
|
|
389
389
|
```
|
|
@@ -419,7 +419,7 @@ item_id = UUID(str(payload["id"]))
|
|
|
419
419
|
### 3) Use engine specs for persistence, not ad-hoc engines
|
|
420
420
|
|
|
421
421
|
**Why:** Engine specs make persistence declarative, testable, and
|
|
422
|
-
compatible with engine resolution across app,
|
|
422
|
+
compatible with engine resolution across app, router, table, and op scopes.
|
|
423
423
|
|
|
424
424
|
✅ **Preferred:**
|
|
425
425
|
```python
|
|
@@ -555,9 +555,9 @@ async def rotate_keys(payload, *, ctx):
|
|
|
555
555
|
|
|
556
556
|
🚫 **Avoid:**
|
|
557
557
|
```python
|
|
558
|
-
from some_framework import
|
|
558
|
+
from some_framework import routerRouter
|
|
559
559
|
|
|
560
|
-
router =
|
|
560
|
+
router = routerRouter()
|
|
561
561
|
|
|
562
562
|
@router.post("/keys/rotate")
|
|
563
563
|
async def rotate_keys(payload):
|
|
@@ -631,8 +631,8 @@ When engine contexts are declared at multiple scopes, Tigrbl resolves them
|
|
|
631
631
|
with strict precedence:
|
|
632
632
|
|
|
633
633
|
1. **Op level** – bindings attached directly to an operation take highest priority.
|
|
634
|
-
2. **Table/Model level** – definitions on a model or table override
|
|
635
|
-
3. **
|
|
634
|
+
2. **Table/Model level** – definitions on a model or table override router and app defaults.
|
|
635
|
+
3. **router level** – bindings on the router class apply when no model-specific context exists.
|
|
636
636
|
4. **App level** – the default engine supplied to the application is used last.
|
|
637
637
|
|
|
638
638
|
This ordering ensures that the most specific engine context always wins.
|
|
@@ -646,7 +646,7 @@ from tigrbl.engine.shortcuts import prov, engine
|
|
|
646
646
|
app = SimpleNamespace(db=prov(kind="sqlite", mode="memory"))
|
|
647
647
|
alt = SimpleNamespace(db=engine(kind="sqlite", mode="memory"))
|
|
648
648
|
|
|
649
|
-
class
|
|
649
|
+
class router:
|
|
650
650
|
db = {"kind": "sqlite", "memory": True}
|
|
651
651
|
|
|
652
652
|
class Item:
|
|
@@ -675,7 +675,7 @@ class App:
|
|
|
675
675
|
pass
|
|
676
676
|
|
|
677
677
|
@engine_ctx(engine(kind="sqlite", mode="memory"))
|
|
678
|
-
class
|
|
678
|
+
class Decoratedrouter:
|
|
679
679
|
pass
|
|
680
680
|
|
|
681
681
|
@engine_ctx(kind="sqlite", mode="memory")
|
|
@@ -702,7 +702,7 @@ The bridge examples cover two integration styles:
|
|
|
702
702
|
* A Swarmauri `Factory` invocation during `PRE_HANDLER` via `hook_ctx`.
|
|
703
703
|
* Tigrbl default verbs (`create`, `get`, `list`, `update`, `delete`) plus a custom op.
|
|
704
704
|
* `engine_ctx` at model and operation scope.
|
|
705
|
-
* Generated
|
|
705
|
+
* Generated Openrouter and OpenRPC documents mounted from the same model bindings.
|
|
706
706
|
|
|
707
707
|
* **Smoother direct-model flow** (`swarmauri_tigrbl_bridge_smooth.py`)
|
|
708
708
|
* Uses hooks + default `create` persistence to normalize Swarmauri payloads.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "tigrbl"
|
|
3
|
-
version = "0.3.16.
|
|
3
|
+
version = "0.3.16.dev5"
|
|
4
4
|
description = "A modern pure ASGI/WSGI Python framework for building schema-first REST and JSON-RPC APIs with SQLAlchemy models, typed validation, lifecycle hooks, and engine extension support."
|
|
5
5
|
license = "Apache-2.0"
|
|
6
6
|
readme = "README.md"
|
|
@@ -86,7 +86,7 @@ Some objects also expose optional helpers:
|
|
|
86
86
|
| Column | `column_spec.py` | `_column.py` | — | `shortcuts.py` | `collect.py` | — | — |
|
|
87
87
|
| Engine | `engine_spec.py` | `_engine.py` | `decorators.py` | `shortcuts.py` | `collect.py` | `resolver.py` | `builders.py` |
|
|
88
88
|
| Op | `types.py` | `_op.py` | `decorators.py` | — | `collect.py` | — | — |
|
|
89
|
-
|
|
|
89
|
+
| Router | `router_spec.py` | `_router.py` | — | `shortcuts.py` | — | — | — |
|
|
90
90
|
| App | `app_spec.py` | `_app.py` | — | `shortcuts.py` | — | — | — |
|
|
91
91
|
| Table | `table_spec.py` | `_table.py` | — | `shortcuts.py` | — | — | — |
|
|
92
92
|
|
|
@@ -5,20 +5,6 @@ Tigrbl – public API
|
|
|
5
5
|
OpSpec-centric building blocks to bind models, wire schemas/handlers/hooks,
|
|
6
6
|
register RPC & REST, and (optionally) mount JSON-RPC and diagnostics.
|
|
7
7
|
|
|
8
|
-
Quick start:
|
|
9
|
-
from tigrbl import include_model, build_jsonrpc_router, mount_diagnostics
|
|
10
|
-
from tigrbl import OpSpec, hook_ctx, op_ctx, alias_ctx, schema_ctx, SchemaRef
|
|
11
|
-
|
|
12
|
-
include_model(api, User, app=asgi_app)
|
|
13
|
-
app.include_router(build_jsonrpc_router(api), prefix="/rpc")
|
|
14
|
-
app.include_router(mount_diagnostics(api), prefix="/system")
|
|
15
|
-
|
|
16
|
-
# Example: custom op using an existing schema
|
|
17
|
-
@op_ctx(alias="search", target="custom", arity="collection",
|
|
18
|
-
request_schema=SchemaRef("Search", "in"),
|
|
19
|
-
response_schema=SchemaRef("Search", "out"))
|
|
20
|
-
def search(cls, ctx):
|
|
21
|
-
...
|
|
22
8
|
"""
|
|
23
9
|
|
|
24
10
|
from __future__ import annotations
|
|
@@ -46,7 +32,7 @@ from .schema.decorators import schema_ctx
|
|
|
46
32
|
from .responses.decorators import response_ctx
|
|
47
33
|
from .responses.types import ResponseSpec
|
|
48
34
|
|
|
49
|
-
# ── Bindings (model +
|
|
35
|
+
# ── Bindings (model + Router orchestration) ───────────────────────────────────────
|
|
50
36
|
from .bindings import (
|
|
51
37
|
bind,
|
|
52
38
|
rebind,
|
|
@@ -55,8 +41,8 @@ from .bindings import (
|
|
|
55
41
|
build_handlers,
|
|
56
42
|
register_rpc,
|
|
57
43
|
build_rest,
|
|
58
|
-
|
|
59
|
-
|
|
44
|
+
include_table,
|
|
45
|
+
include_tables,
|
|
60
46
|
rpc_call,
|
|
61
47
|
)
|
|
62
48
|
|
|
@@ -76,19 +62,19 @@ from .ddl import ensure_schemas, register_sqlite_attach, bootstrap_dbschema
|
|
|
76
62
|
# ── Config constants (defaults used by REST) ───────────────────────────────────
|
|
77
63
|
from .config.constants import DEFAULT_HTTP_METHODS
|
|
78
64
|
from .app.tigrbl_app import TigrblApp
|
|
79
|
-
from .
|
|
65
|
+
from .router import Router, TigrblRouter, route_ctx
|
|
66
|
+
|
|
80
67
|
|
|
81
68
|
from .table import Base
|
|
82
69
|
from .op import Op
|
|
83
70
|
from .security import APIKey, HTTPBearer, MutualTLS, OAuth2, OpenIdConnect
|
|
84
71
|
|
|
85
|
-
|
|
86
72
|
__all__: list[str] = []
|
|
87
73
|
|
|
88
74
|
__all__ += [
|
|
89
75
|
"TigrblApp",
|
|
90
|
-
"
|
|
91
|
-
"
|
|
76
|
+
"TigrblRouter",
|
|
77
|
+
"Router",
|
|
92
78
|
"Base",
|
|
93
79
|
"Op",
|
|
94
80
|
"HTTPBearer",
|
|
@@ -114,6 +100,7 @@ __all__ += [
|
|
|
114
100
|
# Ctx-only decorators
|
|
115
101
|
"alias_ctx",
|
|
116
102
|
"op_ctx",
|
|
103
|
+
"route_ctx",
|
|
117
104
|
"hook_ctx",
|
|
118
105
|
"schema_ctx",
|
|
119
106
|
"response_ctx",
|
|
@@ -129,8 +116,8 @@ __all__ += [
|
|
|
129
116
|
"build_handlers",
|
|
130
117
|
"register_rpc",
|
|
131
118
|
"build_rest",
|
|
132
|
-
"
|
|
133
|
-
"
|
|
119
|
+
"include_table",
|
|
120
|
+
"include_tables",
|
|
134
121
|
"rpc_call",
|
|
135
122
|
# Runtime
|
|
136
123
|
"_invoke",
|
|
@@ -1,23 +1,25 @@
|
|
|
1
|
-
# tigrbl/tigrbl/
|
|
1
|
+
# tigrbl/tigrbl/app/_app.py
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
from typing import Any
|
|
4
4
|
|
|
5
|
-
from ..
|
|
5
|
+
from ..router._routing import include_router
|
|
6
|
+
from ..router._router import Router
|
|
6
7
|
from ..engine.engine_spec import EngineCfg
|
|
7
8
|
from ..engine import resolver as _resolver
|
|
8
9
|
from ..engine import install_from_objects
|
|
9
10
|
from ..ddl import initialize as _ddl_initialize
|
|
10
|
-
from ._model_registry import
|
|
11
|
+
from ._model_registry import initialize_table_registry
|
|
11
12
|
from .app_spec import AppSpec
|
|
12
13
|
|
|
13
14
|
|
|
14
|
-
class App(AppSpec
|
|
15
|
+
class App(AppSpec):
|
|
15
16
|
TITLE = "Tigrbl"
|
|
17
|
+
DESCRIPTION = None
|
|
16
18
|
VERSION = "0.1.0"
|
|
17
19
|
LIFESPAN = None
|
|
18
|
-
|
|
20
|
+
ROUTERS = ()
|
|
19
21
|
OPS = ()
|
|
20
|
-
|
|
22
|
+
TABLES = ()
|
|
21
23
|
SCHEMAS = ()
|
|
22
24
|
HOOKS = ()
|
|
23
25
|
SECURITY_DEPS = ()
|
|
@@ -33,6 +35,9 @@ class App(AppSpec, APIRouter):
|
|
|
33
35
|
title = asgi_kwargs.pop("title", None)
|
|
34
36
|
if title is not None:
|
|
35
37
|
self.TITLE = title
|
|
38
|
+
description = asgi_kwargs.pop("description", None)
|
|
39
|
+
if description is not None:
|
|
40
|
+
self.DESCRIPTION = description
|
|
36
41
|
version = asgi_kwargs.pop("version", None)
|
|
37
42
|
if version is not None:
|
|
38
43
|
self.VERSION = version
|
|
@@ -43,13 +48,15 @@ class App(AppSpec, APIRouter):
|
|
|
43
48
|
if get_db is not None:
|
|
44
49
|
self.get_db = get_db
|
|
45
50
|
self.title = self.TITLE
|
|
51
|
+
self.description = getattr(self, "DESCRIPTION", None)
|
|
46
52
|
self.version = self.VERSION
|
|
47
53
|
self.engine = engine if engine is not None else getattr(self, "ENGINE", None)
|
|
48
|
-
self.
|
|
54
|
+
self.routers = tuple(getattr(self, "ROUTERS", ()))
|
|
49
55
|
self.ops = tuple(getattr(self, "OPS", ()))
|
|
50
56
|
# Runtime registries use mutable containers (dict/namespace), but the
|
|
51
57
|
# dataclass fields expect sequences. Storing a dict here satisfies both.
|
|
52
|
-
self.
|
|
58
|
+
self.tables = initialize_table_registry(getattr(self, "TABLES", ()))
|
|
59
|
+
self.models = self.tables
|
|
53
60
|
self.schemas = tuple(getattr(self, "SCHEMAS", ()))
|
|
54
61
|
self.hooks = tuple(getattr(self, "HOOKS", ()))
|
|
55
62
|
self.security_deps = tuple(getattr(self, "SECURITY_DEPS", ()))
|
|
@@ -59,34 +66,47 @@ class App(AppSpec, APIRouter):
|
|
|
59
66
|
self.system_prefix = getattr(self, "SYSTEM_PREFIX", "/system")
|
|
60
67
|
self.lifespan = self.LIFESPAN
|
|
61
68
|
|
|
62
|
-
|
|
63
|
-
self,
|
|
69
|
+
self.router = Router(
|
|
64
70
|
title=self.title,
|
|
65
71
|
version=self.version,
|
|
72
|
+
description=self.description,
|
|
66
73
|
include_docs=True,
|
|
67
74
|
**asgi_kwargs,
|
|
68
75
|
)
|
|
76
|
+
self.openapi_url = self.router.openapi_url
|
|
77
|
+
self.docs_url = self.router.docs_url
|
|
78
|
+
self.swagger_ui_version = self.router.swagger_ui_version
|
|
69
79
|
_engine_ctx = self.engine
|
|
70
80
|
if _engine_ctx is not None:
|
|
71
81
|
_resolver.set_default(_engine_ctx)
|
|
72
82
|
_resolver.resolve_provider()
|
|
73
83
|
|
|
84
|
+
def include_router(self, other: Any, **kwargs: Any) -> None:
|
|
85
|
+
return include_router(self.router, other, **kwargs)
|
|
86
|
+
|
|
87
|
+
def add_route(self, path: str, endpoint: Any, **kwargs: Any) -> None:
|
|
88
|
+
self.router.add_route(path, endpoint, **kwargs)
|
|
89
|
+
|
|
90
|
+
def route(self, path: str, *, methods: Any, **kwargs: Any):
|
|
91
|
+
return self.router.route(path, methods=methods, **kwargs)
|
|
92
|
+
|
|
74
93
|
def install_engines(
|
|
75
|
-
self, *,
|
|
94
|
+
self, *, router: Any = None, tables: tuple[Any, ...] | None = None
|
|
76
95
|
) -> None:
|
|
77
|
-
# If class declared
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
96
|
+
# If class declared ROUTERS/TABLES, use them unless explicit args are passed.
|
|
97
|
+
routers = (router,) if router is not None else self.ROUTERS
|
|
98
|
+
tables = tables if tables is not None else self.TABLES
|
|
99
|
+
app_target = self.__class__
|
|
100
|
+
if routers:
|
|
101
|
+
for entry in routers:
|
|
102
|
+
install_from_objects(app=app_target, router=entry, tables=tables)
|
|
83
103
|
else:
|
|
84
|
-
install_from_objects(app=
|
|
104
|
+
install_from_objects(app=app_target, router=None, tables=tables)
|
|
85
105
|
|
|
86
106
|
def _collect_tables(self) -> list[Any]:
|
|
87
107
|
seen = set()
|
|
88
108
|
tables = []
|
|
89
|
-
for model in self.models.values():
|
|
109
|
+
for model in self.router.models.values():
|
|
90
110
|
if not hasattr(model, "__table__"):
|
|
91
111
|
try: # pragma: no cover - defensive remap
|
|
92
112
|
from ..table import Base
|
|
@@ -104,16 +124,10 @@ class App(AppSpec, APIRouter):
|
|
|
104
124
|
tables.append(table)
|
|
105
125
|
return tables
|
|
106
126
|
|
|
107
|
-
def _wsgi_app(self, environ: dict[str, Any], start_response: Any) -> list[bytes]:
|
|
108
|
-
return super()._wsgi_app(environ, start_response)
|
|
109
|
-
|
|
110
|
-
async def _asgi_app(self, scope: dict[str, Any], receive: Any, send: Any) -> None:
|
|
111
|
-
await super()._asgi_app(scope, receive, send)
|
|
112
|
-
|
|
113
127
|
async def _dispatch(self, req: Any):
|
|
114
|
-
return await
|
|
128
|
+
return await self.router._dispatch(req)
|
|
115
129
|
|
|
116
130
|
async def _call_handler(self, route: Any, req: Any):
|
|
117
|
-
return await
|
|
131
|
+
return await self.router._call_handler(route, req)
|
|
118
132
|
|
|
119
133
|
initialize = _ddl_initialize
|
|
@@ -1,14 +1,28 @@
|
|
|
1
|
-
"""Utilities for initializing model registries on App and
|
|
1
|
+
"""Utilities for initializing model registries on App and Router facades."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import warnings
|
|
5
6
|
from typing import Any, Iterable
|
|
6
7
|
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
"""
|
|
9
|
+
class RegistryDict(dict[str, Any]):
|
|
10
|
+
"""Dict with attribute-style access used by registry containers."""
|
|
11
|
+
|
|
12
|
+
def __getattr__(self, name: str) -> Any:
|
|
13
|
+
try:
|
|
14
|
+
return self[name]
|
|
15
|
+
except KeyError as exc:
|
|
16
|
+
raise AttributeError(name) from exc
|
|
17
|
+
|
|
18
|
+
def __setattr__(self, name: str, value: Any) -> None:
|
|
19
|
+
self[name] = value
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def initialize_table_registry(tables: Iterable[Any]) -> dict[str, Any]:
|
|
23
|
+
"""Build the default ``tables`` mapping for an App or Router instance.
|
|
10
24
|
|
|
11
|
-
``defineAppSpec``/``
|
|
25
|
+
``defineAppSpec``/``defineRouterSpec`` allow authors to declare default models
|
|
12
26
|
using bare model classes or ``("alias", Model)`` tuples. Runtime facades,
|
|
13
27
|
however, expect ``self.models`` to be a dictionary keyed by model name so
|
|
14
28
|
that lookups like ``app.models["Widget"]`` Just Work.
|
|
@@ -18,9 +32,9 @@ def initialize_model_registry(models: Iterable[Any]) -> dict[str, Any]:
|
|
|
18
32
|
alias and the model's ``__name__`` so either lookup style succeeds.
|
|
19
33
|
"""
|
|
20
34
|
|
|
21
|
-
registry:
|
|
35
|
+
registry: RegistryDict = RegistryDict()
|
|
22
36
|
|
|
23
|
-
for entry in
|
|
37
|
+
for entry in tables or ():
|
|
24
38
|
# Support ``("Alias", Model)`` declarations in addition to bare models.
|
|
25
39
|
if isinstance(entry, tuple) and len(entry) == 2 and isinstance(entry[0], str):
|
|
26
40
|
alias, model = entry
|
|
@@ -38,4 +52,16 @@ def initialize_model_registry(models: Iterable[Any]) -> dict[str, Any]:
|
|
|
38
52
|
return registry
|
|
39
53
|
|
|
40
54
|
|
|
41
|
-
|
|
55
|
+
def initialize_model_registry(models: Iterable[Any]) -> dict[str, Any]:
|
|
56
|
+
"""Deprecated alias for :func:`initialize_table_registry`."""
|
|
57
|
+
|
|
58
|
+
warnings.warn(
|
|
59
|
+
"initialize_model_registry() is deprecated and will be removed in a "
|
|
60
|
+
"future release; use initialize_table_registry() instead.",
|
|
61
|
+
DeprecationWarning,
|
|
62
|
+
stacklevel=2,
|
|
63
|
+
)
|
|
64
|
+
return initialize_table_registry(models)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
__all__ = ["initialize_table_registry", "initialize_model_registry"]
|
|
@@ -14,15 +14,17 @@ class AppSpec:
|
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
16
|
title: str = "Tigrbl"
|
|
17
|
+
description: str | None = None
|
|
17
18
|
version: str = "0.1.0"
|
|
18
19
|
engine: Optional[EngineCfg] = None
|
|
19
20
|
|
|
20
|
-
# NEW: multi-
|
|
21
|
-
|
|
21
|
+
# NEW: multi-Router composition (store Router classes or instances)
|
|
22
|
+
routers: Sequence[Any] = field(default_factory=tuple)
|
|
22
23
|
|
|
23
24
|
# NEW: orchestration/topology knobs
|
|
24
25
|
ops: Sequence[Any] = field(default_factory=tuple) # op descriptors or specs
|
|
25
26
|
models: Sequence[Any] = field(default_factory=tuple) # ORM classes
|
|
27
|
+
tables: Sequence[Any] = field(default_factory=tuple) # table refs owned by app
|
|
26
28
|
schemas: Sequence[Any] = field(default_factory=tuple) # schema classes/defs
|
|
27
29
|
hooks: Sequence[Callable[..., Any]] = field(default_factory=tuple)
|
|
28
30
|
|
|
@@ -77,19 +77,19 @@ def mro_collect_app_spec(app: type) -> AppSpec:
|
|
|
77
77
|
if lifespan is sentinel:
|
|
78
78
|
lifespan = None
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
include_inherited_routers = "ROUTERS" not in app.__dict__
|
|
81
81
|
spec = AppSpec(
|
|
82
82
|
title=title,
|
|
83
83
|
version=version,
|
|
84
84
|
engine=engine,
|
|
85
|
-
|
|
85
|
+
routers=_merge_seq_attr(
|
|
86
86
|
app,
|
|
87
|
-
"
|
|
88
|
-
include_inherited=
|
|
89
|
-
reverse=
|
|
87
|
+
"ROUTERS",
|
|
88
|
+
include_inherited=include_inherited_routers,
|
|
89
|
+
reverse=include_inherited_routers,
|
|
90
90
|
),
|
|
91
91
|
ops=_merge_seq_attr(app, "OPS"),
|
|
92
|
-
models=_merge_seq_attr(app, "
|
|
92
|
+
models=_merge_seq_attr(app, "TABLES"),
|
|
93
93
|
schemas=_merge_seq_attr(app, "SCHEMAS"),
|
|
94
94
|
hooks=_merge_seq_attr(app, "HOOKS"),
|
|
95
95
|
security_deps=_merge_seq_attr(app, "SECURITY_DEPS"),
|
|
@@ -13,7 +13,7 @@ def defineAppSpec(
|
|
|
13
13
|
version: str = "0.1.0",
|
|
14
14
|
engine: Any = None,
|
|
15
15
|
# composition
|
|
16
|
-
|
|
16
|
+
routers: Sequence[Any] = (),
|
|
17
17
|
ops: Sequence[Any] = (),
|
|
18
18
|
models: Sequence[Any] = (),
|
|
19
19
|
schemas: Sequence[Any] = (),
|
|
@@ -41,9 +41,9 @@ def defineAppSpec(
|
|
|
41
41
|
TITLE=title,
|
|
42
42
|
VERSION=version,
|
|
43
43
|
ENGINE=engine,
|
|
44
|
-
|
|
44
|
+
ROUTERS=tuple(routers or ()),
|
|
45
45
|
OPS=tuple(ops or ()),
|
|
46
|
-
|
|
46
|
+
TABLES=tuple(models or ()),
|
|
47
47
|
SCHEMAS=tuple(schemas or ()),
|
|
48
48
|
HOOKS=tuple(hooks or ()),
|
|
49
49
|
SECURITY_DEPS=tuple(security_deps or ()),
|