tigrbl 0.3.0.dev4__tar.gz → 0.3.2__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.0.dev4 → tigrbl-0.3.2}/PKG-INFO +19 -4
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/README.md +9 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/pyproject.toml +20 -2
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/api/_api.py +26 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/api/tigrbl_api.py +6 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/app/_app.py +26 -1
- tigrbl-0.3.2/tigrbl/app/_model_registry.py +41 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/app/tigrbl_app.py +6 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/api/__init__.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/api/common.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/api/include.py +14 -2
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/api/resource_proxy.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/api/rpc.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/handlers/__init__.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/handlers/builder.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/handlers/ctx.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/handlers/identifiers.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/handlers/namespaces.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/handlers/steps.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/rest/collection.py +24 -3
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/rest/common.py +4 -0
- tigrbl-0.3.2/tigrbl/bindings/rest/io_headers.py +49 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/rest/member.py +19 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/rest/router.py +4 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/rest/routing.py +21 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/schemas/__init__.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/schemas/builder.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/schemas/defaults.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/schemas/utils.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/column/io_spec.py +3 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/core/crud/bulk.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/core/crud/helpers/db.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/core/crud/helpers/enum.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/core/crud/helpers/filters.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/core/crud/helpers/model.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/core/crud/helpers/normalize.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/core/crud/ops.py +0 -1
- tigrbl-0.3.2/tigrbl/docs/verbosity.md +35 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/engine/__init__.py +19 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/engine/_engine.py +14 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/engine/builders.py +0 -1
- tigrbl-0.3.2/tigrbl/engine/capabilities.py +29 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/engine/decorators.py +3 -1
- tigrbl-0.3.2/tigrbl/engine/docs/PLUGINS.md +49 -0
- tigrbl-0.3.2/tigrbl/engine/engine_spec.py +355 -0
- tigrbl-0.3.2/tigrbl/engine/plugins.py +52 -0
- tigrbl-0.3.2/tigrbl/engine/registry.py +36 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/engine/resolver.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/mixins/upsertable.py +7 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/response/shortcuts.py +31 -4
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/__init__.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/response/__init__.py +2 -0
- tigrbl-0.3.2/tigrbl/runtime/atoms/response/headers_from_payload.py +57 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/kernel.py +27 -11
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/opview.py +5 -3
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/schema/collect.py +26 -3
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/schema/decorators.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/schema/get_schema.py +0 -1
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/schema/utils.py +0 -1
- tigrbl-0.3.2/tigrbl/session/README.md +14 -0
- tigrbl-0.3.2/tigrbl/session/__init__.py +28 -0
- tigrbl-0.3.2/tigrbl/session/abc.py +76 -0
- tigrbl-0.3.2/tigrbl/session/base.py +151 -0
- tigrbl-0.3.2/tigrbl/session/decorators.py +43 -0
- tigrbl-0.3.2/tigrbl/session/default.py +118 -0
- tigrbl-0.3.2/tigrbl/session/shortcuts.py +50 -0
- tigrbl-0.3.2/tigrbl/session/spec.py +112 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/system/__init__.py +2 -1
- tigrbl-0.3.2/tigrbl/system/uvicorn.py +60 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/table/_base.py +39 -5
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/types/__init__.py +3 -7
- tigrbl-0.3.2/tigrbl/types/uuid.py +55 -0
- tigrbl-0.3.0.dev4/tigrbl/engine/engine_spec.py +0 -261
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/LICENSE +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/README.md +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/api/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/api/api_spec.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/api/mro_collect.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/api/shortcuts.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/app/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/app/app_spec.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/app/mro_collect.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/app/shortcuts.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/columns.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/hooks.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/model.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/model_helpers.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/model_registry.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/rest/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/rest/attach.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/rest/fastapi.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/rest/helpers.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/rest/io.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/bindings/rpc.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/column/README.md +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/column/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/column/_column.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/column/column_spec.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/column/field_spec.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/column/infer/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/column/infer/core.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/column/infer/jsonhints.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/column/infer/planning.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/column/infer/types.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/column/infer/utils.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/column/mro_collect.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/column/shortcuts.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/column/storage_spec.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/config/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/config/constants.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/config/defaults.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/config/resolver.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/core/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/core/crud/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/core/crud/helpers/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/ddl/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/decorators.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/deps/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/deps/fastapi.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/deps/favicon.svg +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/deps/jinja.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/deps/pydantic.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/deps/sqlalchemy.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/deps/starlette.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/engine/bind.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/engine/collect.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/engine/shortcuts.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/hook/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/hook/_hook.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/hook/decorators.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/hook/hook_spec.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/hook/mro_collect.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/hook/shortcuts.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/hook/types.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/op/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/op/_op.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/op/canonical.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/op/collect.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/op/decorators.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/op/model_registry.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/op/mro_collect.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/op/resolver.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/op/types.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/mixins/_RowBound.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/mixins/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/mixins/bootstrappable.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/mixins/bound.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/mixins/edges.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/mixins/fields.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/mixins/hierarchy.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/mixins/key_digest.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/mixins/lifecycle.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/mixins/locks.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/mixins/markers.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/mixins/operations.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/mixins/ownable.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/mixins/principals.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/mixins/tenant_bound.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/mixins/utils.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/tables/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/tables/_base.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/tables/audit.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/tables/client.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/tables/group.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/tables/org.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/tables/rbac.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/tables/status.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/tables/tenant.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/orm/tables/user.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/response/README.md +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/response/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/response/bind.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/response/decorators.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/response/resolver.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/response/types.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/rest/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/README.md +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/emit/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/emit/paired_post.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/emit/paired_pre.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/emit/readtime_alias.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/out/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/out/masking.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/refresh/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/refresh/demand.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/resolve/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/resolve/assemble.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/resolve/paired_gen.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/response/negotiate.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/response/negotiation.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/response/render.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/response/renderer.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/response/template.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/response/templates.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/schema/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/schema/collect_in.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/schema/collect_out.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/storage/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/storage/to_stored.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/wire/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/wire/build_in.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/wire/build_out.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/wire/dump.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/atoms/wire/validate_in.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/context.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/errors/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/errors/converters.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/errors/exceptions.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/errors/mappings.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/errors/utils.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/events.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/executor/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/executor/guards.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/executor/helpers.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/executor/invoke.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/executor/types.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/labels.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/ordering.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/system.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/runtime/trace.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/schema/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/schema/_schema.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/schema/builder/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/schema/builder/build_schema.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/schema/builder/cache.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/schema/builder/compat.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/schema/builder/extras.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/schema/builder/helpers.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/schema/builder/list_params.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/schema/builder/strip_parent_fields.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/schema/schema_spec.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/schema/shortcuts.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/schema/types.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/shortcuts.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/specs.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/system/diagnostics/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/system/diagnostics/compat.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/system/diagnostics/healthz.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/system/diagnostics/hookz.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/system/diagnostics/kernelz.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/system/diagnostics/methodz.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/system/diagnostics/router.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/system/diagnostics/utils.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/table/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/table/_table.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/table/mro_collect.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/table/shortcuts.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/table/table_spec.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/transport/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/transport/jsonrpc/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/transport/jsonrpc/dispatcher.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/transport/jsonrpc/helpers.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/transport/jsonrpc/models.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/transport/rest/__init__.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/transport/rest/aggregator.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/types/allow_anon_provider.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/types/authn_abc.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/types/nested_path_provider.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/types/op.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/types/op_config_provider.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/types/op_verb_alias_provider.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/types/request_extras_provider.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/types/response_extras_provider.py +0 -0
- {tigrbl-0.3.0.dev4 → tigrbl-0.3.2}/tigrbl/types/table_config_provider.py +0 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: tigrbl
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: Automatic API generation tools by Swarmauri.
|
|
5
|
-
License: Apache-2.0
|
|
5
|
+
License-Expression: Apache-2.0
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Keywords: tigrbl,sdk,standards
|
|
6
8
|
Author: Swarmauri Team
|
|
7
9
|
Author-email: team@swarmauri.com
|
|
8
10
|
Requires-Python: >=3.10,<3.13
|
|
@@ -11,8 +13,12 @@ Classifier: Development Status :: 3 - Alpha
|
|
|
11
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
12
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
13
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
14
19
|
Provides-Extra: postgres
|
|
15
20
|
Provides-Extra: templates
|
|
21
|
+
Provides-Extra: tests
|
|
16
22
|
Requires-Dist: aiosqlite (>=0.19.0)
|
|
17
23
|
Requires-Dist: asyncpg (>=0.30.0) ; extra == "postgres"
|
|
18
24
|
Requires-Dist: fastapi (>=0.100.0)
|
|
@@ -25,10 +31,11 @@ Requires-Dist: sqlalchemy (>=2.0)
|
|
|
25
31
|
Requires-Dist: swarmauri_base
|
|
26
32
|
Requires-Dist: swarmauri_core
|
|
27
33
|
Requires-Dist: swarmauri_standard
|
|
34
|
+
Requires-Dist: tigrbl-tests ; extra == "tests"
|
|
28
35
|
Requires-Dist: uvicorn
|
|
29
36
|
Description-Content-Type: text/markdown
|
|
30
37
|
|
|
31
|
-

|
|
32
39
|
|
|
33
40
|
<p align="center">
|
|
34
41
|
<a href="https://pypi.org/project/tigrbl/">
|
|
@@ -48,6 +55,14 @@ Description-Content-Type: text/markdown
|
|
|
48
55
|
# Tigrbl 🐅🐂
|
|
49
56
|
A high-leverage meta-framework that turns plain SQLAlchemy models into a fully-featured REST+RPC surface with near-zero boilerplate. 🚀
|
|
50
57
|
|
|
58
|
+
## Features ✨
|
|
59
|
+
|
|
60
|
+
- ⚡ Zero-boilerplate CRUD for SQLAlchemy models
|
|
61
|
+
- 🔌 Unified REST and RPC endpoints from a single definition
|
|
62
|
+
- 🪝 Hookable phase system for deep customization
|
|
63
|
+
- 🧩 Pluggable engine and provider abstractions
|
|
64
|
+
- 🚀 Built on FastAPI and Pydantic for modern Python web apps
|
|
65
|
+
|
|
51
66
|
## Terminology 📚
|
|
52
67
|
|
|
53
68
|
- **Tenant** 🏢 – a namespace used to group related resources.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-

|
|
2
2
|
|
|
3
3
|
<p align="center">
|
|
4
4
|
<a href="https://pypi.org/project/tigrbl/">
|
|
@@ -18,6 +18,14 @@
|
|
|
18
18
|
# Tigrbl 🐅🐂
|
|
19
19
|
A high-leverage meta-framework that turns plain SQLAlchemy models into a fully-featured REST+RPC surface with near-zero boilerplate. 🚀
|
|
20
20
|
|
|
21
|
+
## Features ✨
|
|
22
|
+
|
|
23
|
+
- ⚡ Zero-boilerplate CRUD for SQLAlchemy models
|
|
24
|
+
- 🔌 Unified REST and RPC endpoints from a single definition
|
|
25
|
+
- 🪝 Hookable phase system for deep customization
|
|
26
|
+
- 🧩 Pluggable engine and provider abstractions
|
|
27
|
+
- 🚀 Built on FastAPI and Pydantic for modern Python web apps
|
|
28
|
+
|
|
21
29
|
## Terminology 📚
|
|
22
30
|
|
|
23
31
|
- **Tenant** 🏢 – a namespace used to group related resources.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "tigrbl"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.2"
|
|
4
4
|
description = "Automatic API generation tools by Swarmauri."
|
|
5
5
|
license = "Apache-2.0"
|
|
6
6
|
readme = "README.md"
|
|
@@ -12,6 +12,9 @@ classifiers = [
|
|
|
12
12
|
"Programming Language :: Python :: 3.10",
|
|
13
13
|
"Programming Language :: Python :: 3.11",
|
|
14
14
|
"Programming Language :: Python :: 3.12",
|
|
15
|
+
"Programming Language :: Python",
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
15
18
|
]
|
|
16
19
|
authors = [{ name = "Swarmauri Team", email = "team@swarmauri.com" }]
|
|
17
20
|
dependencies = [
|
|
@@ -26,6 +29,11 @@ dependencies = [
|
|
|
26
29
|
"greenlet>=3.2.3",
|
|
27
30
|
"uvicorn",
|
|
28
31
|
]
|
|
32
|
+
keywords = [
|
|
33
|
+
'tigrbl',
|
|
34
|
+
'sdk',
|
|
35
|
+
'standards',
|
|
36
|
+
]
|
|
29
37
|
|
|
30
38
|
[project.optional-dependencies]
|
|
31
39
|
postgres = [
|
|
@@ -35,14 +43,19 @@ postgres = [
|
|
|
35
43
|
templates = [
|
|
36
44
|
"jinja2>=3.1.4",
|
|
37
45
|
]
|
|
46
|
+
tests = [
|
|
47
|
+
"tigrbl-tests",
|
|
48
|
+
]
|
|
38
49
|
|
|
39
50
|
[tool.uv.sources]
|
|
40
51
|
swarmauri_core = { workspace = true }
|
|
41
52
|
swarmauri_base = { workspace = true }
|
|
42
53
|
swarmauri_standard = { workspace = true }
|
|
54
|
+
tigrbl-tests = { workspace = true }
|
|
43
55
|
|
|
44
56
|
[tool.pytest.ini_options]
|
|
45
57
|
norecursedirs = ["combined", "scripts"]
|
|
58
|
+
testpaths = ["../tigrbl_tests/tests"]
|
|
46
59
|
markers = [
|
|
47
60
|
"test: standard test",
|
|
48
61
|
"unit: Unit tests",
|
|
@@ -65,6 +78,11 @@ asyncio_default_fixture_loop_scope = "function"
|
|
|
65
78
|
requires = ["poetry-core>=1.0.0"]
|
|
66
79
|
build-backend = "poetry.core.masonry.api"
|
|
67
80
|
|
|
81
|
+
[tool.poetry]
|
|
82
|
+
packages = [
|
|
83
|
+
{ include = "tigrbl" },
|
|
84
|
+
]
|
|
85
|
+
|
|
68
86
|
[dependency-groups]
|
|
69
87
|
dev = [
|
|
70
88
|
"pytest>=8.0",
|
|
@@ -79,4 +97,4 @@ dev = [
|
|
|
79
97
|
"pytest-benchmark>=4.0.0",
|
|
80
98
|
"asyncpg>=0.30.0",
|
|
81
99
|
"psycopg2-binary>=2.9.9",
|
|
82
|
-
]
|
|
100
|
+
]
|
|
@@ -6,7 +6,9 @@ from types import SimpleNamespace
|
|
|
6
6
|
from ..deps.fastapi import APIRouter as ApiRouter
|
|
7
7
|
from ..engine.engine_spec import EngineCfg
|
|
8
8
|
from ..engine import install_from_objects
|
|
9
|
+
from ..ddl import initialize as _ddl_initialize
|
|
9
10
|
from ..engine import resolver as _resolver
|
|
11
|
+
from ..app._model_registry import initialize_model_registry
|
|
10
12
|
from .api_spec import APISpec
|
|
11
13
|
|
|
12
14
|
|
|
@@ -41,7 +43,7 @@ class Api(APISpec, ApiRouter):
|
|
|
41
43
|
self.deps = tuple(getattr(self, "DEPS", ()))
|
|
42
44
|
self.response = getattr(self, "RESPONSE", None)
|
|
43
45
|
# ``models`` is expected to be a dict at runtime for registry lookups.
|
|
44
|
-
self.models
|
|
46
|
+
self.models = initialize_model_registry(getattr(self, "MODELS", ()))
|
|
45
47
|
|
|
46
48
|
ApiRouter.__init__(
|
|
47
49
|
self,
|
|
@@ -70,3 +72,26 @@ class Api(APISpec, ApiRouter):
|
|
|
70
72
|
install_from_objects(app=self, api=a, models=models)
|
|
71
73
|
else:
|
|
72
74
|
install_from_objects(app=self, api=None, models=models)
|
|
75
|
+
|
|
76
|
+
def _collect_tables(self) -> list[Any]:
|
|
77
|
+
seen = set()
|
|
78
|
+
tables = []
|
|
79
|
+
for model in self.models.values():
|
|
80
|
+
if not hasattr(model, "__table__"):
|
|
81
|
+
try: # pragma: no cover - defensive remap
|
|
82
|
+
from ..table import Base
|
|
83
|
+
from ..table._base import _materialize_colspecs_to_sqla
|
|
84
|
+
|
|
85
|
+
_materialize_colspecs_to_sqla(model)
|
|
86
|
+
Base.registry.map_declaratively(model)
|
|
87
|
+
except Exception:
|
|
88
|
+
pass
|
|
89
|
+
table = getattr(model, "__table__", None)
|
|
90
|
+
if table is not None and not table.columns:
|
|
91
|
+
continue
|
|
92
|
+
if table is not None and table not in seen:
|
|
93
|
+
seen.add(table)
|
|
94
|
+
tables.append(table)
|
|
95
|
+
return tables
|
|
96
|
+
|
|
97
|
+
initialize = _ddl_initialize
|
|
@@ -32,6 +32,7 @@ from ..bindings.rest import build_router_and_attach as _build_router_and_attach
|
|
|
32
32
|
from ..transport import mount_jsonrpc as _mount_jsonrpc
|
|
33
33
|
from ..system import mount_diagnostics as _mount_diagnostics
|
|
34
34
|
from ..op import get_registry, OpSpec
|
|
35
|
+
from ..app._model_registry import initialize_model_registry
|
|
35
36
|
|
|
36
37
|
|
|
37
38
|
class TigrblApi(_Api):
|
|
@@ -73,7 +74,7 @@ class TigrblApi(_Api):
|
|
|
73
74
|
self.system_prefix = system_prefix
|
|
74
75
|
|
|
75
76
|
# public containers (mirrors used by bindings.api)
|
|
76
|
-
self.models
|
|
77
|
+
self.models = initialize_model_registry(getattr(self, "MODELS", ()))
|
|
77
78
|
self.schemas = SimpleNamespace()
|
|
78
79
|
self.handlers = SimpleNamespace()
|
|
79
80
|
self.hooks = SimpleNamespace()
|
|
@@ -231,6 +232,8 @@ class TigrblApi(_Api):
|
|
|
231
232
|
) -> None:
|
|
232
233
|
if authn is not None:
|
|
233
234
|
self._authn = authn
|
|
235
|
+
if allow_anon is None:
|
|
236
|
+
allow_anon = False
|
|
234
237
|
if allow_anon is not None:
|
|
235
238
|
self._allow_anon = bool(allow_anon)
|
|
236
239
|
if authorize is not None:
|
|
@@ -270,6 +273,8 @@ class TigrblApi(_Api):
|
|
|
270
273
|
tables = []
|
|
271
274
|
for m in self.models.values():
|
|
272
275
|
t = getattr(m, "__table__", None)
|
|
276
|
+
if t is not None and not t.columns:
|
|
277
|
+
continue
|
|
273
278
|
if t is not None and t not in seen:
|
|
274
279
|
seen.add(t)
|
|
275
280
|
tables.append(t)
|
|
@@ -6,6 +6,8 @@ from ..deps.fastapi import FastAPI
|
|
|
6
6
|
from ..engine.engine_spec import EngineCfg
|
|
7
7
|
from ..engine import resolver as _resolver
|
|
8
8
|
from ..engine import install_from_objects
|
|
9
|
+
from ..ddl import initialize as _ddl_initialize
|
|
10
|
+
from ._model_registry import initialize_model_registry
|
|
9
11
|
from .app_spec import AppSpec
|
|
10
12
|
|
|
11
13
|
|
|
@@ -23,7 +25,7 @@ class App(AppSpec, FastAPI):
|
|
|
23
25
|
self.ops = tuple(getattr(self, "OPS", ()))
|
|
24
26
|
# Runtime registries use mutable containers (dict/namespace), but the
|
|
25
27
|
# dataclass fields expect sequences. Storing a dict here satisfies both.
|
|
26
|
-
self.models =
|
|
28
|
+
self.models = initialize_model_registry(getattr(self, "MODELS", ()))
|
|
27
29
|
self.schemas = tuple(getattr(self, "SCHEMAS", ()))
|
|
28
30
|
self.hooks = tuple(getattr(self, "HOOKS", ()))
|
|
29
31
|
self.security_deps = tuple(getattr(self, "SECURITY_DEPS", ()))
|
|
@@ -59,3 +61,26 @@ class App(AppSpec, FastAPI):
|
|
|
59
61
|
install_from_objects(app=self, api=a, models=models)
|
|
60
62
|
else:
|
|
61
63
|
install_from_objects(app=self, api=None, models=models)
|
|
64
|
+
|
|
65
|
+
def _collect_tables(self) -> list[Any]:
|
|
66
|
+
seen = set()
|
|
67
|
+
tables = []
|
|
68
|
+
for model in self.models.values():
|
|
69
|
+
if not hasattr(model, "__table__"):
|
|
70
|
+
try: # pragma: no cover - defensive remap
|
|
71
|
+
from ..table import Base
|
|
72
|
+
from ..table._base import _materialize_colspecs_to_sqla
|
|
73
|
+
|
|
74
|
+
_materialize_colspecs_to_sqla(model)
|
|
75
|
+
Base.registry.map_declaratively(model)
|
|
76
|
+
except Exception:
|
|
77
|
+
pass
|
|
78
|
+
table = getattr(model, "__table__", None)
|
|
79
|
+
if table is not None and not table.columns:
|
|
80
|
+
continue
|
|
81
|
+
if table is not None and table not in seen:
|
|
82
|
+
seen.add(table)
|
|
83
|
+
tables.append(table)
|
|
84
|
+
return tables
|
|
85
|
+
|
|
86
|
+
initialize = _ddl_initialize
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""Utilities for initializing model registries on App and API facades."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, Iterable
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def initialize_model_registry(models: Iterable[Any]) -> dict[str, Any]:
|
|
9
|
+
"""Build the default ``models`` mapping for an App or Api instance.
|
|
10
|
+
|
|
11
|
+
``defineAppSpec``/``defineApiSpec`` allow authors to declare default models
|
|
12
|
+
using bare model classes or ``("alias", Model)`` tuples. Runtime facades,
|
|
13
|
+
however, expect ``self.models`` to be a dictionary keyed by model name so
|
|
14
|
+
that lookups like ``app.models["Widget"]`` Just Work.
|
|
15
|
+
|
|
16
|
+
This helper normalizes the declared sequence into that dictionary shape and
|
|
17
|
+
preserves declaration order. When an alias is provided we register both the
|
|
18
|
+
alias and the model's ``__name__`` so either lookup style succeeds.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
registry: dict[str, Any] = {}
|
|
22
|
+
|
|
23
|
+
for entry in models or ():
|
|
24
|
+
# Support ``("Alias", Model)`` declarations in addition to bare models.
|
|
25
|
+
if isinstance(entry, tuple) and len(entry) == 2 and isinstance(entry[0], str):
|
|
26
|
+
alias, model = entry
|
|
27
|
+
registry[alias] = model
|
|
28
|
+
model_name = getattr(model, "__name__", alias)
|
|
29
|
+
registry.setdefault(model_name, model)
|
|
30
|
+
continue
|
|
31
|
+
|
|
32
|
+
model = entry
|
|
33
|
+
model_name = getattr(model, "__name__", None)
|
|
34
|
+
if model_name is None:
|
|
35
|
+
model_name = str(model)
|
|
36
|
+
registry[model_name] = model
|
|
37
|
+
|
|
38
|
+
return registry
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
__all__ = ["initialize_model_registry"]
|
|
@@ -32,6 +32,7 @@ from ..bindings.rest import build_router_and_attach as _build_router_and_attach
|
|
|
32
32
|
from ..transport import mount_jsonrpc as _mount_jsonrpc
|
|
33
33
|
from ..system import mount_diagnostics as _mount_diagnostics
|
|
34
34
|
from ..op import get_registry, OpSpec
|
|
35
|
+
from ._model_registry import initialize_model_registry
|
|
35
36
|
|
|
36
37
|
|
|
37
38
|
# optional compat: legacy transactional decorator
|
|
@@ -93,7 +94,7 @@ class TigrblApp(_App):
|
|
|
93
94
|
self.system_prefix = system_prefix
|
|
94
95
|
|
|
95
96
|
# public containers (mirrors used by bindings.api)
|
|
96
|
-
self.models
|
|
97
|
+
self.models = initialize_model_registry(getattr(self, "MODELS", ()))
|
|
97
98
|
self.schemas = SimpleNamespace()
|
|
98
99
|
self.handlers = SimpleNamespace()
|
|
99
100
|
self.hooks = SimpleNamespace()
|
|
@@ -262,6 +263,8 @@ class TigrblApp(_App):
|
|
|
262
263
|
) -> None:
|
|
263
264
|
if authn is not None:
|
|
264
265
|
self._authn = authn
|
|
266
|
+
if allow_anon is None:
|
|
267
|
+
allow_anon = False
|
|
265
268
|
if allow_anon is not None:
|
|
266
269
|
self._allow_anon = bool(allow_anon)
|
|
267
270
|
if authorize is not None:
|
|
@@ -301,6 +304,8 @@ class TigrblApp(_App):
|
|
|
301
304
|
tables = []
|
|
302
305
|
for m in self.models.values():
|
|
303
306
|
t = getattr(m, "__table__", None)
|
|
307
|
+
if t is not None and not t.columns:
|
|
308
|
+
continue
|
|
304
309
|
if t is not None and t not in seen:
|
|
305
310
|
seen.add(t)
|
|
306
311
|
tables.append(t)
|
|
@@ -5,7 +5,6 @@ from .common import AttrDict, _default_prefix, _mount_router # noqa: F401
|
|
|
5
5
|
from .include import include_model, include_models, _seed_security_and_deps # noqa: F401
|
|
6
6
|
from .rpc import rpc_call
|
|
7
7
|
|
|
8
|
-
logging.getLogger("uvicorn").setLevel(logging.DEBUG)
|
|
9
8
|
logger = logging.getLogger("uvicorn")
|
|
10
9
|
logger.debug("Loaded module v3/bindings/api/__init__")
|
|
11
10
|
|
|
@@ -24,11 +24,23 @@ from ...config.constants import (
|
|
|
24
24
|
)
|
|
25
25
|
from ...engine import resolver as _resolver
|
|
26
26
|
|
|
27
|
-
logging.getLogger("uvicorn").setLevel(logging.DEBUG)
|
|
28
27
|
logger = logging.getLogger("uvicorn")
|
|
29
28
|
logger.debug("Loaded module v3/bindings/api/include")
|
|
30
29
|
|
|
31
30
|
|
|
31
|
+
def _coerce_model_columns(columns: Any) -> Tuple[str, ...]:
|
|
32
|
+
if isinstance(columns, SimpleNamespace):
|
|
33
|
+
return tuple(columns.__dict__.keys())
|
|
34
|
+
if isinstance(columns, dict):
|
|
35
|
+
return tuple(columns.keys())
|
|
36
|
+
if isinstance(columns, str):
|
|
37
|
+
return (columns,)
|
|
38
|
+
try:
|
|
39
|
+
return tuple(columns)
|
|
40
|
+
except TypeError:
|
|
41
|
+
return ()
|
|
42
|
+
|
|
43
|
+
|
|
32
44
|
# --- keep as helper, no behavior change to transports/kernel ---
|
|
33
45
|
def _seed_security_and_deps(api: Any, model: type) -> None:
|
|
34
46
|
"""
|
|
@@ -132,7 +144,7 @@ def _attach_to_api(api: ApiLike, model: type) -> None:
|
|
|
132
144
|
)
|
|
133
145
|
|
|
134
146
|
# Table metadata (introspection only)
|
|
135
|
-
api.columns[mname] =
|
|
147
|
+
api.columns[mname] = _coerce_model_columns(getattr(model, "columns", ()))
|
|
136
148
|
api.table_config[mname] = dict(getattr(model, "table_config", {}) or {})
|
|
137
149
|
|
|
138
150
|
# Core helper proxies (now aware of API for DB resolution precedence)
|
|
@@ -8,7 +8,6 @@ from ..rpc import _coerce_payload, _get_phase_chains, _validate_input, _serializ
|
|
|
8
8
|
from ...runtime import executor as _executor
|
|
9
9
|
from ...engine import resolver as _resolver
|
|
10
10
|
|
|
11
|
-
logging.getLogger("uvicorn").setLevel(logging.DEBUG)
|
|
12
11
|
logger = logging.getLogger("uvicorn")
|
|
13
12
|
logger.debug("Loaded module v3/bindings/api/resource_proxy")
|
|
14
13
|
|
|
@@ -8,7 +8,6 @@ from .common import ApiLike, _ensure_api_ns
|
|
|
8
8
|
from ...engine import resolver as _resolver
|
|
9
9
|
from ...core.crud.helpers.model import _single_pk_name
|
|
10
10
|
|
|
11
|
-
logging.getLogger("uvicorn").setLevel(logging.DEBUG)
|
|
12
11
|
logger = logging.getLogger("uvicorn")
|
|
13
12
|
logger.debug("Loaded module v3/bindings/api/rpc")
|
|
14
13
|
|
|
@@ -9,7 +9,6 @@ from ...op.types import StepFn
|
|
|
9
9
|
from .namespaces import _ensure_alias_handlers_ns, _ensure_alias_hooks_ns
|
|
10
10
|
from .steps import _wrap_core, _wrap_custom
|
|
11
11
|
|
|
12
|
-
logging.getLogger("uvicorn").setLevel(logging.DEBUG)
|
|
13
12
|
logger = logging.getLogger("uvicorn")
|
|
14
13
|
logger.debug("Loaded module v3/bindings/handlers/builder")
|
|
15
14
|
|
|
@@ -13,7 +13,6 @@ from ...runtime.executor import _Ctx
|
|
|
13
13
|
from .ctx import _ctx_db, _ctx_payload, _ctx_request
|
|
14
14
|
from .identifiers import _resolve_ident
|
|
15
15
|
|
|
16
|
-
logging.getLogger("uvicorn").setLevel(logging.DEBUG)
|
|
17
16
|
logger = logging.getLogger("uvicorn")
|
|
18
17
|
logger.debug("Loaded module v3/bindings/handlers/steps")
|
|
19
18
|
|
|
@@ -35,6 +35,8 @@ from .common import (
|
|
|
35
35
|
_status_for,
|
|
36
36
|
)
|
|
37
37
|
|
|
38
|
+
from .io_headers import _make_header_dep
|
|
39
|
+
|
|
38
40
|
from ...runtime.executor.types import _Ctx
|
|
39
41
|
|
|
40
42
|
|
|
@@ -103,6 +105,7 @@ def _make_collection_endpoint(
|
|
|
103
105
|
) -> Callable[..., Awaitable[Any]]:
|
|
104
106
|
alias, target, nested_vars = sp.alias, sp.target, list(nested_vars or [])
|
|
105
107
|
status_code = _status_for(sp)
|
|
108
|
+
hdr_dep = _make_header_dep(model, alias)
|
|
106
109
|
|
|
107
110
|
if target in {"list", "clear"}:
|
|
108
111
|
list_dep = _make_list_query_dep(model, alias) if target == "list" else None
|
|
@@ -110,6 +113,7 @@ def _make_collection_endpoint(
|
|
|
110
113
|
async def _endpoint(
|
|
111
114
|
request: Request,
|
|
112
115
|
db: Any = Depends(db_dep),
|
|
116
|
+
h: Mapping[str, Any] = Depends(hdr_dep),
|
|
113
117
|
q: Mapping[str, Any] | None = None,
|
|
114
118
|
**kw: Any,
|
|
115
119
|
):
|
|
@@ -120,6 +124,8 @@ def _make_collection_endpoint(
|
|
|
120
124
|
payload = _validate_query(model, alias, target, query)
|
|
121
125
|
else:
|
|
122
126
|
payload = dict(parent_kw)
|
|
127
|
+
if isinstance(h, Mapping):
|
|
128
|
+
payload = {**payload, **dict(h)}
|
|
123
129
|
ctx = _ctx(model, alias, target, request, db, payload, parent_kw, api)
|
|
124
130
|
ctx["response_serializer"] = lambda r: _serialize_output(
|
|
125
131
|
model, alias, target, sp, r
|
|
@@ -154,16 +160,20 @@ def _make_collection_endpoint(
|
|
|
154
160
|
inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
|
155
161
|
annotation=Annotated[Any, Depends(db_dep)],
|
|
156
162
|
),
|
|
163
|
+
inspect.Parameter(
|
|
164
|
+
"h",
|
|
165
|
+
inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
|
166
|
+
annotation=Annotated[Mapping[str, Any], Depends(hdr_dep)],
|
|
167
|
+
),
|
|
157
168
|
]
|
|
158
169
|
)
|
|
159
170
|
if target == "list":
|
|
160
|
-
params.
|
|
161
|
-
len(nested_vars) + 1,
|
|
171
|
+
params.append(
|
|
162
172
|
inspect.Parameter(
|
|
163
173
|
"q",
|
|
164
174
|
inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
|
165
175
|
annotation=Annotated[Mapping[str, Any], Depends(list_dep)],
|
|
166
|
-
)
|
|
176
|
+
)
|
|
167
177
|
)
|
|
168
178
|
_endpoint.__signature__ = inspect.Signature(params)
|
|
169
179
|
else:
|
|
@@ -192,12 +202,18 @@ def _make_collection_endpoint(
|
|
|
192
202
|
async def _endpoint(
|
|
193
203
|
request: Request,
|
|
194
204
|
db: Any = Depends(db_dep),
|
|
205
|
+
h: Mapping[str, Any] = Depends(hdr_dep),
|
|
195
206
|
body=Body(...),
|
|
196
207
|
**kw: Any,
|
|
197
208
|
):
|
|
198
209
|
parent_kw = {k: kw[k] for k in nested_vars if k in kw}
|
|
199
210
|
_coerce_parent_kw(model, parent_kw)
|
|
200
211
|
payload = _validate_body(model, alias, target, body)
|
|
212
|
+
if isinstance(h, Mapping):
|
|
213
|
+
if isinstance(payload, Mapping):
|
|
214
|
+
payload = {**payload, **dict(h)}
|
|
215
|
+
else:
|
|
216
|
+
payload = [{**dict(item), **dict(h)} for item in payload]
|
|
201
217
|
is_seq = (
|
|
202
218
|
target in {"create", "update", "replace", "merge"}
|
|
203
219
|
and isinstance(payload, Sequence)
|
|
@@ -248,6 +264,11 @@ def _make_collection_endpoint(
|
|
|
248
264
|
inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
|
249
265
|
annotation=Annotated[Any, Depends(db_dep)],
|
|
250
266
|
),
|
|
267
|
+
inspect.Parameter(
|
|
268
|
+
"h",
|
|
269
|
+
inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
|
270
|
+
annotation=Annotated[Mapping[str, Any], Depends(hdr_dep)],
|
|
271
|
+
),
|
|
251
272
|
inspect.Parameter(
|
|
252
273
|
"body",
|
|
253
274
|
inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
|
@@ -45,6 +45,8 @@ from .routing import (
|
|
|
45
45
|
_default_path_suffix,
|
|
46
46
|
_normalize_deps,
|
|
47
47
|
_normalize_secdeps,
|
|
48
|
+
_require_auth_header,
|
|
49
|
+
_requires_auth_header,
|
|
48
50
|
_path_for_spec,
|
|
49
51
|
_request_model_for,
|
|
50
52
|
_response_model_for,
|
|
@@ -106,6 +108,8 @@ __all__ = [
|
|
|
106
108
|
"_optionalize_list_in_model",
|
|
107
109
|
"_normalize_deps",
|
|
108
110
|
"_normalize_secdeps",
|
|
111
|
+
"_require_auth_header",
|
|
112
|
+
"_requires_auth_header",
|
|
109
113
|
"_status_for",
|
|
110
114
|
"_RESPONSES_META",
|
|
111
115
|
"_DEFAULT_METHODS",
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import inspect
|
|
4
|
+
from typing import Mapping, Any
|
|
5
|
+
|
|
6
|
+
from fastapi import Header
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _build_signature_with_header_params(
|
|
10
|
+
hdr_fields: list[tuple[str, str, bool]],
|
|
11
|
+
) -> inspect.Signature:
|
|
12
|
+
params: list[inspect.Parameter] = []
|
|
13
|
+
for _field, header, required in hdr_fields:
|
|
14
|
+
param = header.lower().replace("-", "_")
|
|
15
|
+
default = Header(... if required else None, alias=header)
|
|
16
|
+
params.append(
|
|
17
|
+
inspect.Parameter(
|
|
18
|
+
name=param,
|
|
19
|
+
kind=inspect.Parameter.KEYWORD_ONLY,
|
|
20
|
+
default=default,
|
|
21
|
+
annotation=str | None,
|
|
22
|
+
)
|
|
23
|
+
)
|
|
24
|
+
return inspect.Signature(parameters=params, return_annotation=Mapping[str, object])
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _make_header_dep(model: type, alias: str):
|
|
28
|
+
hdr_fields: list[tuple[str, str, bool]] = []
|
|
29
|
+
for name, spec in getattr(model, "__tigrbl_cols__", {}).items():
|
|
30
|
+
io = getattr(spec, "io", None)
|
|
31
|
+
if not io or not getattr(io, "header_in", None):
|
|
32
|
+
continue
|
|
33
|
+
if alias not in set(getattr(io, "in_verbs", ()) or ()): # honor IO.in_verbs
|
|
34
|
+
continue
|
|
35
|
+
hdr_fields.append(
|
|
36
|
+
(name, io.header_in, bool(getattr(io, "header_required_in", False)))
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
async def _dep(**kw: Any) -> Mapping[str, object]:
|
|
40
|
+
out: dict[str, object] = {}
|
|
41
|
+
for field, header, _req in hdr_fields:
|
|
42
|
+
param = header.lower().replace("-", "_")
|
|
43
|
+
v = kw.get(param)
|
|
44
|
+
if v is not None:
|
|
45
|
+
out[field] = v
|
|
46
|
+
return out
|
|
47
|
+
|
|
48
|
+
_dep.__signature__ = _build_signature_with_header_params(hdr_fields)
|
|
49
|
+
return _dep
|