tigrbl 0.3.5.dev5__tar.gz → 0.3.6.dev1__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.
Files changed (303) hide show
  1. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/PKG-INFO +26 -2
  2. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/README.md +25 -1
  3. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/pyproject.toml +1 -1
  4. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/README.md +1 -1
  5. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/api/_api.py +1 -1
  6. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/api/tigrbl_api.py +40 -0
  7. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/app/_app.py +6 -8
  8. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/app/app_spec.py +1 -1
  9. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/app/tigrbl_app.py +47 -8
  10. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/api/common.py +2 -2
  11. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/api/include.py +2 -2
  12. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/model_helpers.py +1 -1
  13. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/rest/attach.py +2 -2
  14. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/rest/collection.py +1 -1
  15. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/rest/fastapi.py +2 -2
  16. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/rest/io.py +1 -1
  17. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/rest/router.py +1 -1
  18. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/core/resolver.py +1 -1
  19. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/hook/__init__.py +2 -0
  20. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/hook/decorators.py +9 -2
  21. tigrbl-0.3.6.dev1/tigrbl/hook/exceptions.py +18 -0
  22. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/response/stdapi.py +73 -1
  23. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/executor/types.py +1 -1
  24. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/status/utils.py +5 -4
  25. tigrbl-0.3.6.dev1/tigrbl/security/__init__.py +63 -0
  26. tigrbl-0.3.6.dev1/tigrbl/security/schemes/__init__.py +19 -0
  27. tigrbl-0.3.6.dev1/tigrbl/security/schemes/_base.py +69 -0
  28. tigrbl-0.3.6.dev1/tigrbl/security/schemes/api_key.py +57 -0
  29. tigrbl-0.3.6.dev1/tigrbl/security/schemes/http_bearer.py +74 -0
  30. tigrbl-0.3.6.dev1/tigrbl/security/schemes/mutual_tls.py +27 -0
  31. tigrbl-0.3.6.dev1/tigrbl/security/schemes/oauth2.py +28 -0
  32. tigrbl-0.3.6.dev1/tigrbl/security/schemes/openid_connect.py +31 -0
  33. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/system/diagnostics/healthz.py +1 -1
  34. tigrbl-0.3.6.dev1/tigrbl/system/docs/lens.py +99 -0
  35. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/system/docs/openrpc.py +6 -4
  36. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/system/favicon/__init__.py +3 -3
  37. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/transport/__init__.py +1 -1
  38. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/transport/jsonrpc/dispatcher.py +2 -2
  39. tigrbl-0.3.6.dev1/tigrbl/transport/request.py +128 -0
  40. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/transport/rest/aggregator.py +3 -3
  41. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/types/authn_abc.py +1 -1
  42. tigrbl-0.3.5.dev5/tigrbl/security/__init__.py +0 -297
  43. tigrbl-0.3.5.dev5/tigrbl/system/docs/lens.py +0 -51
  44. tigrbl-0.3.5.dev5/tigrbl/transport/request.py +0 -48
  45. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/LICENSE +0 -0
  46. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/__init__.py +0 -0
  47. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/api/__init__.py +0 -0
  48. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/api/_route.py +0 -0
  49. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/api/_router.py +0 -0
  50. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/api/_routing.py +0 -0
  51. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/api/api_spec.py +0 -0
  52. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/api/mro_collect.py +0 -0
  53. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/api/resolve.py +0 -0
  54. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/api/shortcuts.py +0 -0
  55. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/app/__init__.py +0 -0
  56. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/app/_model_registry.py +0 -0
  57. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/app/_routing_runtime.py +0 -0
  58. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/app/mro_collect.py +0 -0
  59. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/app/shortcuts.py +0 -0
  60. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/__init__.py +0 -0
  61. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/api/__init__.py +0 -0
  62. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/api/resource_proxy.py +0 -0
  63. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/api/rpc.py +0 -0
  64. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/columns.py +0 -0
  65. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/handlers/__init__.py +0 -0
  66. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/handlers/builder.py +0 -0
  67. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/handlers/ctx.py +0 -0
  68. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/handlers/identifiers.py +0 -0
  69. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/handlers/namespaces.py +0 -0
  70. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/handlers/steps.py +0 -0
  71. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/hooks.py +0 -0
  72. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/model.py +0 -0
  73. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/model_registry.py +0 -0
  74. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/rest/__init__.py +0 -0
  75. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/rest/common.py +0 -0
  76. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/rest/helpers.py +0 -0
  77. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/rest/io_headers.py +0 -0
  78. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/rest/member.py +0 -0
  79. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/rest/routing.py +0 -0
  80. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/rpc.py +0 -0
  81. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/schemas/__init__.py +0 -0
  82. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/schemas/builder.py +0 -0
  83. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/schemas/defaults.py +0 -0
  84. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/bindings/schemas/utils.py +0 -0
  85. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/column/README.md +0 -0
  86. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/column/__init__.py +0 -0
  87. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/column/_column.py +0 -0
  88. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/column/column_spec.py +0 -0
  89. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/column/field_spec.py +0 -0
  90. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/column/infer/__init__.py +0 -0
  91. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/column/infer/core.py +0 -0
  92. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/column/infer/jsonhints.py +0 -0
  93. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/column/infer/planning.py +0 -0
  94. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/column/infer/types.py +0 -0
  95. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/column/infer/utils.py +0 -0
  96. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/column/io_spec.py +0 -0
  97. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/column/mro_collect.py +0 -0
  98. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/column/shortcuts.py +0 -0
  99. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/column/storage_spec.py +0 -0
  100. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/config/__init__.py +0 -0
  101. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/config/constants.py +0 -0
  102. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/config/defaults.py +0 -0
  103. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/config/resolver.py +0 -0
  104. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/core/__init__.py +0 -0
  105. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/core/crud/__init__.py +0 -0
  106. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/core/crud/bulk.py +0 -0
  107. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/core/crud/helpers/__init__.py +0 -0
  108. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/core/crud/helpers/db.py +0 -0
  109. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/core/crud/helpers/enum.py +0 -0
  110. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/core/crud/helpers/filters.py +0 -0
  111. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/core/crud/helpers/model.py +0 -0
  112. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/core/crud/helpers/normalize.py +0 -0
  113. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/core/crud/ops.py +0 -0
  114. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/core/crud/params.py +0 -0
  115. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/core/router_runtime.py +0 -0
  116. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/ddl/__init__.py +0 -0
  117. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/decorators.py +0 -0
  118. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/deps/__init__.py +0 -0
  119. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/deps/jinja.py +0 -0
  120. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/deps/pydantic.py +0 -0
  121. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/deps/sqlalchemy.py +0 -0
  122. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/docs/verbosity.md +0 -0
  123. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/engine/__init__.py +0 -0
  124. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/engine/_engine.py +0 -0
  125. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/engine/bind.py +0 -0
  126. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/engine/builders.py +0 -0
  127. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/engine/capabilities.py +0 -0
  128. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/engine/collect.py +0 -0
  129. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/engine/decorators.py +0 -0
  130. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/engine/docs/PLUGINS.md +0 -0
  131. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/engine/engine_spec.py +0 -0
  132. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/engine/plugins.py +0 -0
  133. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/engine/registry.py +0 -0
  134. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/engine/resolver.py +0 -0
  135. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/engine/shortcuts.py +0 -0
  136. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/hook/_hook.py +0 -0
  137. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/hook/hook_spec.py +0 -0
  138. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/hook/mro_collect.py +0 -0
  139. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/hook/shortcuts.py +0 -0
  140. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/hook/types.py +0 -0
  141. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/op/__init__.py +0 -0
  142. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/op/_op.py +0 -0
  143. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/op/canonical.py +0 -0
  144. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/op/collect.py +0 -0
  145. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/op/decorators.py +0 -0
  146. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/op/model_registry.py +0 -0
  147. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/op/mro_collect.py +0 -0
  148. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/op/resolver.py +0 -0
  149. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/op/types.py +0 -0
  150. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/__init__.py +0 -0
  151. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/mixins/_RowBound.py +0 -0
  152. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/mixins/__init__.py +0 -0
  153. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/mixins/bootstrappable.py +0 -0
  154. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/mixins/bound.py +0 -0
  155. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/mixins/edges.py +0 -0
  156. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/mixins/fields.py +0 -0
  157. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/mixins/hierarchy.py +0 -0
  158. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/mixins/key_digest.py +0 -0
  159. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/mixins/lifecycle.py +0 -0
  160. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/mixins/locks.py +0 -0
  161. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/mixins/markers.py +0 -0
  162. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/mixins/operations.py +0 -0
  163. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/mixins/ownable.py +0 -0
  164. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/mixins/principals.py +0 -0
  165. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/mixins/tenant_bound.py +0 -0
  166. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/mixins/upsertable.py +0 -0
  167. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/mixins/utils.py +0 -0
  168. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/tables/__init__.py +0 -0
  169. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/tables/_base.py +0 -0
  170. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/tables/audit.py +0 -0
  171. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/tables/client.py +0 -0
  172. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/tables/group.py +0 -0
  173. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/tables/org.py +0 -0
  174. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/tables/rbac.py +0 -0
  175. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/tables/status.py +0 -0
  176. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/tables/tenant.py +0 -0
  177. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/orm/tables/user.py +0 -0
  178. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/response/README.md +0 -0
  179. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/response/__init__.py +0 -0
  180. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/response/bind.py +0 -0
  181. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/response/decorators.py +0 -0
  182. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/response/resolver.py +0 -0
  183. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/response/shortcuts.py +0 -0
  184. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/response/types.py +0 -0
  185. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/rest/__init__.py +0 -0
  186. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/README.md +0 -0
  187. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/__init__.py +0 -0
  188. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/__init__.py +0 -0
  189. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/emit/__init__.py +0 -0
  190. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/emit/paired_post.py +0 -0
  191. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/emit/paired_pre.py +0 -0
  192. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/emit/readtime_alias.py +0 -0
  193. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/out/__init__.py +0 -0
  194. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/out/masking.py +0 -0
  195. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/refresh/__init__.py +0 -0
  196. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/refresh/demand.py +0 -0
  197. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/resolve/__init__.py +0 -0
  198. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/resolve/assemble.py +0 -0
  199. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/resolve/paired_gen.py +0 -0
  200. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/response/__init__.py +0 -0
  201. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/response/headers_from_payload.py +0 -0
  202. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/response/negotiate.py +0 -0
  203. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/response/negotiation.py +0 -0
  204. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/response/render.py +0 -0
  205. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/response/renderer.py +0 -0
  206. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/response/template.py +0 -0
  207. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/response/templates.py +0 -0
  208. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/schema/__init__.py +0 -0
  209. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/schema/collect_in.py +0 -0
  210. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/schema/collect_out.py +0 -0
  211. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/storage/__init__.py +0 -0
  212. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/storage/to_stored.py +0 -0
  213. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/wire/__init__.py +0 -0
  214. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/wire/build_in.py +0 -0
  215. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/wire/build_out.py +0 -0
  216. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/wire/dump.py +0 -0
  217. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/atoms/wire/validate_in.py +0 -0
  218. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/context.py +0 -0
  219. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/events.py +0 -0
  220. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/executor/__init__.py +0 -0
  221. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/executor/guards.py +0 -0
  222. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/executor/helpers.py +0 -0
  223. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/executor/invoke.py +0 -0
  224. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/kernel.py +0 -0
  225. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/labels.py +0 -0
  226. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/opview.py +0 -0
  227. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/ordering.py +0 -0
  228. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/status/__init__.py +0 -0
  229. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/status/converters.py +0 -0
  230. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/status/exceptions.py +0 -0
  231. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/status/mappings.py +0 -0
  232. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/system.py +0 -0
  233. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/runtime/trace.py +0 -0
  234. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/schema/__init__.py +0 -0
  235. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/schema/_schema.py +0 -0
  236. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/schema/builder/__init__.py +0 -0
  237. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/schema/builder/build_schema.py +0 -0
  238. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/schema/builder/cache.py +0 -0
  239. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/schema/builder/compat.py +0 -0
  240. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/schema/builder/extras.py +0 -0
  241. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/schema/builder/helpers.py +0 -0
  242. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/schema/builder/list_params.py +0 -0
  243. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/schema/builder/strip_parent_fields.py +0 -0
  244. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/schema/collect.py +0 -0
  245. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/schema/decorators.py +0 -0
  246. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/schema/get_schema.py +0 -0
  247. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/schema/schema_spec.py +0 -0
  248. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/schema/shortcuts.py +0 -0
  249. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/schema/types.py +0 -0
  250. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/schema/utils.py +0 -0
  251. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/security/dependencies.py +0 -0
  252. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/session/README.md +0 -0
  253. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/session/__init__.py +0 -0
  254. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/session/abc.py +0 -0
  255. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/session/base.py +0 -0
  256. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/session/decorators.py +0 -0
  257. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/session/default.py +0 -0
  258. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/session/shortcuts.py +0 -0
  259. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/session/spec.py +0 -0
  260. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/shortcuts.py +0 -0
  261. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/specs.py +0 -0
  262. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/system/__init__.py +0 -0
  263. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/system/diagnostics/__init__.py +0 -0
  264. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/system/diagnostics/compat.py +0 -0
  265. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/system/diagnostics/hookz.py +0 -0
  266. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/system/diagnostics/kernelz.py +0 -0
  267. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/system/diagnostics/methodz.py +0 -0
  268. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/system/diagnostics/router.py +0 -0
  269. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/system/diagnostics/utils.py +0 -0
  270. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/system/docs/__init__.py +0 -0
  271. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/system/docs/openapi/__init__.py +0 -0
  272. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/system/docs/openapi/helpers.py +0 -0
  273. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/system/docs/openapi/metadata.py +0 -0
  274. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/system/docs/openapi/mount.py +0 -0
  275. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/system/docs/openapi/schema.py +0 -0
  276. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/system/docs/swagger.py +0 -0
  277. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/system/favicon/assets/favicon.svg +0 -0
  278. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/system/uvicorn.py +0 -0
  279. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/table/__init__.py +0 -0
  280. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/table/_base.py +0 -0
  281. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/table/_table.py +0 -0
  282. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/table/mro_collect.py +0 -0
  283. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/table/shortcuts.py +0 -0
  284. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/table/table_spec.py +0 -0
  285. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/transport/asgi_wsgi.py +0 -0
  286. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/transport/background.py +0 -0
  287. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/transport/httpx.py +0 -0
  288. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/transport/jsonrpc/__init__.py +0 -0
  289. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/transport/jsonrpc/helpers.py +0 -0
  290. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/transport/jsonrpc/models.py +0 -0
  291. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/transport/jsonrpc/openrpc.py +0 -0
  292. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/transport/rest/__init__.py +0 -0
  293. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/transport/rest/decorators.py +0 -0
  294. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/types/__init__.py +0 -0
  295. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/types/allow_anon_provider.py +0 -0
  296. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/types/nested_path_provider.py +0 -0
  297. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/types/op.py +0 -0
  298. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/types/op_config_provider.py +0 -0
  299. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/types/op_verb_alias_provider.py +0 -0
  300. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/types/request_extras_provider.py +0 -0
  301. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/types/response_extras_provider.py +0 -0
  302. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/types/table_config_provider.py +0 -0
  303. {tigrbl-0.3.5.dev5 → tigrbl-0.3.6.dev1}/tigrbl/types/uuid.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tigrbl
3
- Version: 0.3.5.dev5
3
+ Version: 0.3.6.dev1
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
@@ -189,7 +189,7 @@ v
189
189
  HTTP Request
190
190
  |
191
191
  v
192
- FastAPI Router
192
+ ASGI Router
193
193
  |
194
194
  v
195
195
  Tigrbl Runtime
@@ -720,6 +720,30 @@ async def decorated_create(payload, *, db=None):
720
720
  ...
721
721
  ```
722
722
 
723
+ ### Swarmauri class + Tigrbl lifecycle integration 🧬
724
+
725
+ If you need to run concrete Swarmauri classes inside Tigrbl's runtime, see:
726
+
727
+ * [`examples/swarmauri_tigrbl_bridge.py`](./examples/swarmauri_tigrbl_bridge.py)
728
+ * [`examples/swarmauri_tigrbl_bridge_smooth.py`](./examples/swarmauri_tigrbl_bridge_smooth.py)
729
+
730
+ The bridge examples cover two integration styles:
731
+
732
+ * **Factory + schema-rich envelope** (`swarmauri_tigrbl_bridge.py`)
733
+ * Swarmauri Pydantic JSON workflows (`model_validate_json`, `model_dump_json`,
734
+ `model_json_schema`) with `HumanMessage`.
735
+ * A Swarmauri `Factory` invocation during `PRE_HANDLER` via `hook_ctx`.
736
+ * Tigrbl default verbs (`create`, `get`, `list`, `update`, `delete`) plus a custom op.
737
+ * `engine_ctx` at model and operation scope.
738
+ * Generated OpenAPI and OpenRPC documents mounted from the same model bindings.
739
+
740
+ * **Smoother direct-model flow** (`swarmauri_tigrbl_bridge_smooth.py`)
741
+ * Uses hooks + default `create` persistence to normalize Swarmauri payloads.
742
+ * Adds a `Conversation` table with a persisted one-to-many relationship to messages.
743
+ * Avoids extra `json_schema` fields in request/response payload contracts.
744
+ * Returns `HumanMessage.model_validate_json(...)` directly from a custom op.
745
+ * Uses the concrete model classes themselves to derive input/output schema docs.
746
+
723
747
  ## Glossary 📖
724
748
 
725
749
  1. Tables
@@ -156,7 +156,7 @@ v
156
156
  HTTP Request
157
157
  |
158
158
  v
159
- FastAPI Router
159
+ ASGI Router
160
160
  |
161
161
  v
162
162
  Tigrbl Runtime
@@ -687,6 +687,30 @@ async def decorated_create(payload, *, db=None):
687
687
  ...
688
688
  ```
689
689
 
690
+ ### Swarmauri class + Tigrbl lifecycle integration 🧬
691
+
692
+ If you need to run concrete Swarmauri classes inside Tigrbl's runtime, see:
693
+
694
+ * [`examples/swarmauri_tigrbl_bridge.py`](./examples/swarmauri_tigrbl_bridge.py)
695
+ * [`examples/swarmauri_tigrbl_bridge_smooth.py`](./examples/swarmauri_tigrbl_bridge_smooth.py)
696
+
697
+ The bridge examples cover two integration styles:
698
+
699
+ * **Factory + schema-rich envelope** (`swarmauri_tigrbl_bridge.py`)
700
+ * Swarmauri Pydantic JSON workflows (`model_validate_json`, `model_dump_json`,
701
+ `model_json_schema`) with `HumanMessage`.
702
+ * A Swarmauri `Factory` invocation during `PRE_HANDLER` via `hook_ctx`.
703
+ * Tigrbl default verbs (`create`, `get`, `list`, `update`, `delete`) plus a custom op.
704
+ * `engine_ctx` at model and operation scope.
705
+ * Generated OpenAPI and OpenRPC documents mounted from the same model bindings.
706
+
707
+ * **Smoother direct-model flow** (`swarmauri_tigrbl_bridge_smooth.py`)
708
+ * Uses hooks + default `create` persistence to normalize Swarmauri payloads.
709
+ * Adds a `Conversation` table with a persisted one-to-many relationship to messages.
710
+ * Avoids extra `json_schema` fields in request/response payload contracts.
711
+ * Returns `HumanMessage.model_validate_json(...)` directly from a custom op.
712
+ * Uses the concrete model classes themselves to derive input/output schema docs.
713
+
690
714
  ## Glossary 📖
691
715
 
692
716
  1. Tables
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tigrbl"
3
- version = "0.3.5.dev5"
3
+ version = "0.3.6.dev1"
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"
@@ -14,7 +14,7 @@ DB = engine("sqlite+aiosqlite:///./app.db")
14
14
  app = TigrblApp(engine=DB)
15
15
  ```
16
16
 
17
- Use `DB.get_db` as the FastAPI dependency for acquiring sessions and avoid
17
+ Use `DB.get_db` as the framework dependency for acquiring sessions and avoid
18
18
  exporting custom `get_async_db` helpers.
19
19
 
20
20
  These rules apply to all first-party applications, including
@@ -29,7 +29,7 @@ class Api(APISpec, Router):
29
29
 
30
30
  @property
31
31
  def router(self) -> "Api": # pragma: no cover - simple alias
32
- """Mirror FastAPI-style router access for API instances."""
32
+ """Mirror ASGI-style router access for API instances."""
33
33
  return self
34
34
 
35
35
  def __init__(
@@ -31,6 +31,11 @@ from ..bindings.model import rebind as _rebind, bind as _bind
31
31
  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
+ from ..system import mount_lens as _mount_lens
35
+ from ..system import mount_openapi as _mount_openapi
36
+ from ..system import mount_openrpc as _mount_openrpc
37
+ from ..system import build_openrpc_spec as _build_openrpc_spec
38
+ from ..system.favicon import mount_favicon
34
39
  from ..op import get_registry, OpSpec
35
40
  from ..app._model_registry import initialize_model_registry
36
41
 
@@ -58,6 +63,8 @@ class TigrblApi(_Api):
58
63
  _optional_authn_dep: Any = None
59
64
  _allow_anon_ops: set[str] = set()
60
65
 
66
+ mount_favicon = mount_favicon
67
+
61
68
  def __init__(
62
69
  self,
63
70
  *,
@@ -201,6 +208,39 @@ class TigrblApi(_Api):
201
208
  )
202
209
  return router
203
210
 
211
+ def mount_openapi(
212
+ self,
213
+ *,
214
+ path: str = "/openapi.json",
215
+ name: str = "__openapi__",
216
+ ) -> Any:
217
+ """Mount an OpenAPI JSON endpoint onto this instance."""
218
+ return _mount_openapi(self, path=path, name=name)
219
+
220
+ def mount_openrpc(
221
+ self,
222
+ *,
223
+ path: str = "/openrpc.json",
224
+ name: str = "openrpc_json",
225
+ tags: list[str] | None = None,
226
+ ) -> Any:
227
+ """Mount an OpenRPC JSON endpoint onto this instance."""
228
+ return _mount_openrpc(self, path=path, name=name, tags=tags)
229
+
230
+ def openrpc(self) -> Dict[str, Any]:
231
+ """Build and return the OpenRPC document for this API."""
232
+ return _build_openrpc_spec(self)
233
+
234
+ def mount_lens(
235
+ self,
236
+ *,
237
+ path: str = "/lens",
238
+ name: str = "__lens__",
239
+ spec_path: str | None = None,
240
+ ) -> Any:
241
+ """Mount a tigrbl-lens HTML endpoint onto this instance."""
242
+ return _mount_lens(self, path=path, name=name, spec_path=spec_path)
243
+
204
244
  def attach_diagnostics(
205
245
  self, *, prefix: str | None = None, app: Any | None = None
206
246
  ) -> Any:
@@ -26,22 +26,20 @@ class App(AppSpec, APIRouter):
26
26
  JSONRPC_PREFIX = "/rpc"
27
27
  SYSTEM_PREFIX = "/system"
28
28
 
29
- def __init__(
30
- self, *, engine: EngineCfg | None = None, **fastapi_kwargs: Any
31
- ) -> None:
29
+ def __init__(self, *, engine: EngineCfg | None = None, **asgi_kwargs: Any) -> None:
32
30
  # Manually mirror ``AppSpec`` fields so the dataclass-generated ``repr``
33
31
  # and friends have expected attributes while runtime structures remain
34
32
  # mutable dictionaries or lists as needed.
35
- title = fastapi_kwargs.pop("title", None)
33
+ title = asgi_kwargs.pop("title", None)
36
34
  if title is not None:
37
35
  self.TITLE = title
38
- version = fastapi_kwargs.pop("version", None)
36
+ version = asgi_kwargs.pop("version", None)
39
37
  if version is not None:
40
38
  self.VERSION = version
41
- lifespan = fastapi_kwargs.pop("lifespan", None)
39
+ lifespan = asgi_kwargs.pop("lifespan", None)
42
40
  if lifespan is not None:
43
41
  self.LIFESPAN = lifespan
44
- get_db = fastapi_kwargs.pop("get_db", None)
42
+ get_db = asgi_kwargs.pop("get_db", None)
45
43
  if get_db is not None:
46
44
  self.get_db = get_db
47
45
  self.title = self.TITLE
@@ -66,7 +64,7 @@ class App(AppSpec, APIRouter):
66
64
  title=self.title,
67
65
  version=self.version,
68
66
  include_docs=True,
69
- **fastapi_kwargs,
67
+ **asgi_kwargs,
70
68
  )
71
69
  _engine_ctx = self.engine
72
70
  if _engine_ctx is not None:
@@ -26,7 +26,7 @@ class AppSpec:
26
26
  schemas: Sequence[Any] = field(default_factory=tuple) # schema classes/defs
27
27
  hooks: Sequence[Callable[..., Any]] = field(default_factory=tuple)
28
28
 
29
- # security/dep stacks (FastAPI dependencies or callables)
29
+ # security/dep stacks (ASGI dependencies or callables)
30
30
  security_deps: Sequence[Callable[..., Any]] = field(default_factory=tuple)
31
31
  deps: Sequence[Callable[..., Any]] = field(default_factory=tuple)
32
32
 
@@ -34,6 +34,10 @@ from ..bindings.model import rebind as _rebind, bind as _bind
34
34
  from ..bindings.rest import build_router_and_attach as _build_router_and_attach
35
35
  from ..transport import mount_jsonrpc as _mount_jsonrpc
36
36
  from ..system import mount_diagnostics as _mount_diagnostics
37
+ from ..system import mount_lens as _mount_lens
38
+ from ..system import mount_openapi as _mount_openapi
39
+ from ..system import mount_openrpc as _mount_openrpc
40
+ from ..system import build_openrpc_spec as _build_openrpc_spec
37
41
  from ..op import get_registry, OpSpec
38
42
  from ._model_registry import initialize_model_registry
39
43
  from ..system.favicon import FAVICON_PATH, mount_favicon
@@ -72,6 +76,8 @@ class TigrblApp(_App):
72
76
  _allow_anon_ops: set[str] = set()
73
77
  _event_handlers: Dict[str, list[Callable[..., Any]]]
74
78
 
79
+ mount_favicon = mount_favicon
80
+
75
81
  def __init__(
76
82
  self,
77
83
  *,
@@ -83,18 +89,18 @@ class TigrblApp(_App):
83
89
  api_hooks: Mapping[str, Iterable[Callable]]
84
90
  | Mapping[str, Mapping[str, Iterable[Callable]]]
85
91
  | None = None,
86
- **fastapi_kwargs: Any,
92
+ **asgi_kwargs: Any,
87
93
  ) -> None:
88
- title = fastapi_kwargs.pop("title", None)
94
+ title = asgi_kwargs.pop("title", None)
89
95
  if title is not None:
90
96
  self.TITLE = title
91
- version = fastapi_kwargs.pop("version", None)
97
+ version = asgi_kwargs.pop("version", None)
92
98
  if version is not None:
93
99
  self.VERSION = version
94
- lifespan = fastapi_kwargs.pop("lifespan", None)
100
+ lifespan = asgi_kwargs.pop("lifespan", None)
95
101
  if lifespan is not None:
96
102
  self.LIFESPAN = lifespan
97
- super().__init__(engine=engine, **fastapi_kwargs)
103
+ super().__init__(engine=engine, **asgi_kwargs)
98
104
  self.router = self
99
105
  self._middlewares: list[tuple[Any, dict[str, Any]]] = []
100
106
  self.middlewares = tuple(getattr(self, "MIDDLEWARES", ()))
@@ -102,7 +108,7 @@ class TigrblApp(_App):
102
108
  for mw in self.middlewares:
103
109
  self.add_middleware(mw.__class__, **getattr(mw, "kwargs", {}))
104
110
  self._install_favicon()
105
- # capture initial routes so refreshes retain FastAPI defaults
111
+ # capture initial routes so refreshes retain ASGI defaults
106
112
  self._base_routes = list(self.router.routes)
107
113
  self.jsonrpc_prefix = (
108
114
  jsonrpc_prefix
@@ -185,7 +191,7 @@ class TigrblApp(_App):
185
191
  self._middlewares.append((middleware_class, options))
186
192
 
187
193
  def _install_favicon(self) -> None:
188
- mount_favicon(self, favicon_path=self._favicon_path)
194
+ self.mount_favicon(favicon_path=self._favicon_path)
189
195
 
190
196
  # ------------------------- internal helpers -------------------------
191
197
 
@@ -274,7 +280,7 @@ class TigrblApp(_App):
274
280
  return api
275
281
 
276
282
  def include_router(self, router: Any, *args: Any, **kwargs: Any) -> None:
277
- """Extend FastAPI include_router to track Tigrbl APIs."""
283
+ """Extend ASGI include_router to track Tigrbl APIs."""
278
284
  if hasattr(router, "models") and hasattr(router, "initialize"):
279
285
  self.include_api(
280
286
  router,
@@ -372,6 +378,39 @@ class TigrblApp(_App):
372
378
  self._base_routes = list(self.router.routes)
373
379
  return router
374
380
 
381
+ def mount_openapi(
382
+ self,
383
+ *,
384
+ path: str = "/openapi.json",
385
+ name: str = "__openapi__",
386
+ ) -> Any:
387
+ """Mount an OpenAPI JSON endpoint onto this instance."""
388
+ return _mount_openapi(self, path=path, name=name)
389
+
390
+ def mount_openrpc(
391
+ self,
392
+ *,
393
+ path: str = "/openrpc.json",
394
+ name: str = "openrpc_json",
395
+ tags: list[str] | None = None,
396
+ ) -> Any:
397
+ """Mount an OpenRPC JSON endpoint onto this instance."""
398
+ return _mount_openrpc(self, path=path, name=name, tags=tags)
399
+
400
+ def openrpc(self) -> Dict[str, Any]:
401
+ """Build and return the OpenRPC document for this app."""
402
+ return _build_openrpc_spec(self)
403
+
404
+ def mount_lens(
405
+ self,
406
+ *,
407
+ path: str = "/lens",
408
+ name: str = "__lens__",
409
+ spec_path: str | None = None,
410
+ ) -> Any:
411
+ """Mount a tigrbl-lens HTML endpoint onto this instance."""
412
+ return _mount_lens(self, path=path, name=name, spec_path=spec_path)
413
+
375
414
  def attach_diagnostics(
376
415
  self, *, prefix: str | None = None, app: Any | None = None
377
416
  ) -> Any:
@@ -64,7 +64,7 @@ def _has_include_router(obj: Any) -> bool:
64
64
 
65
65
  def _mount_router(app_or_router: Any, router: Any, *, prefix: str) -> None:
66
66
  """
67
- Best-effort mount onto a FastAPI app or Router.
67
+ Best-effort mount onto a ASGI app or Router.
68
68
  If not available, we still attach router under api.routers for later use.
69
69
  """
70
70
  if app_or_router is None:
@@ -73,7 +73,7 @@ def _mount_router(app_or_router: Any, router: Any, *, prefix: str) -> None:
73
73
  try:
74
74
  if _has_include_router(app_or_router):
75
75
  logger.debug("Mounting router %s at prefix %s", router, prefix)
76
- app_or_router.include_router(router, prefix=prefix) # FastAPI / Router
76
+ app_or_router.include_router(router, prefix=prefix) # ASGI / Router
77
77
  else:
78
78
  logger.debug(
79
79
  "Provided object %s lacks include_router; not mounting router",
@@ -45,7 +45,7 @@ def _coerce_model_columns(columns: Any) -> Tuple[str, ...]:
45
45
  def _seed_security_and_deps(api: Any, model: type) -> None:
46
46
  """
47
47
  Copy API-level dependency hooks onto the model so downstream binders can use them.
48
- - __tigrbl_get_db__ : DB dep (FastAPI Depends-compatible)
48
+ - __tigrbl_get_db__ : DB dep (ASGI Depends-compatible)
49
49
  - __tigrbl_auth_dep__ : auth dependency (returns user or raises 401)
50
50
  - __tigrbl_authorize__ : callable(request, model, alias, payload, user)→None/raise 403
51
51
  - __tigrbl_rest_dependencies__ : list of extra dependencies for REST (e.g., rate-limits)
@@ -177,7 +177,7 @@ def include_model(
177
177
  Args:
178
178
  api: An arbitrary facade object; we’ll attach containers onto it if missing.
179
179
  model: The SQLAlchemy model (table class).
180
- app: Optional FastAPI app or Router (anything with `include_router`).
180
+ app: Optional ASGI app or Router (anything with `include_router`).
181
181
  Routers are always mounted on `api.router`; if provided, we also
182
182
  mount onto this `app` (or `api.app` when not given).
183
183
  prefix: Optional mount prefix. When None, defaults to `/{ModelClassName}` or
@@ -43,7 +43,7 @@ def _ensure_model_namespaces(model: type) -> None:
43
43
  # rpc: callables to be registered/mounted elsewhere as JSON-RPC methods
44
44
  if "rpc" not in model.__dict__:
45
45
  model.rpc = SimpleNamespace()
46
- # rest: .router (FastAPI Router or compatible) – built in rest binding
46
+ # rest: .router (ASGI Router or compatible) – built in rest binding
47
47
  if "rest" not in model.__dict__:
48
48
  model.rest = SimpleNamespace(router=None)
49
49
  # basic table metadata for convenience (introspective only; NEVER used for HTTP paths)
@@ -20,8 +20,8 @@ def build_router_and_attach(
20
20
  ) -> None:
21
21
  """
22
22
  Build a Router for the model and attach it to `model.rest.router`.
23
- For simplicity and correctness with FastAPI, we **rebuild the entire router**
24
- on each call (FastAPI does not support removing individual routes cleanly).
23
+ For simplicity and correctness with ASGI, we **rebuild the entire router**
24
+ on each call (ASGI does not support removing individual routes cleanly).
25
25
  """
26
26
  router = _build_router(model, specs, api=api)
27
27
  rest_ns = getattr(model, "rest", None) or SimpleNamespace()
@@ -49,7 +49,7 @@ def _ctx(model, alias, target, request, db, payload, parent_kw, api):
49
49
  "db": db,
50
50
  "payload": payload,
51
51
  "path_params": parent_kw,
52
- # expose both API router and FastAPI app; runtime opview resolution
52
+ # expose both API router and ASGI app; runtime opview resolution
53
53
  # relies on the app object, which must be hashable.
54
54
  "api": api if api is not None else getattr(request, "app", None),
55
55
  "app": getattr(request, "app", None),
@@ -1,4 +1,4 @@
1
- """Deprecated compatibility module for REST FastAPI-style primitives.
1
+ """Deprecated compatibility module for REST ASGI-style primitives.
2
2
 
3
3
  Prefer importing directly from:
4
4
  - ``tigrbl.response`` for response classes
@@ -24,7 +24,7 @@ from ...security.dependencies import Depends, Security
24
24
  from ...transport.request import Request
25
25
 
26
26
  warnings.warn(
27
- "tigrbl.bindings.rest.fastapi is deprecated; import from "
27
+ "tigrbl.bindings.rest.asgi is deprecated; import from "
28
28
  "tigrbl.response, tigrbl.runtime.status, and concrete modules instead.",
29
29
  DeprecationWarning,
30
30
  stacklevel=2,
@@ -25,7 +25,7 @@ def _serialize_output(
25
25
  ) -> Any:
26
26
  """
27
27
  If a response schema exists (model.schemas.<alias>.out), serialize to it.
28
- Otherwise, attempt a best-effort conversion to primitive types so FastAPI
28
+ Otherwise, attempt a best-effort conversion to primitive types so ASGI
29
29
  can JSON-encode the response.
30
30
  """
31
31
 
@@ -170,7 +170,7 @@ def _build_router(
170
170
 
171
171
  # Register collection-level bulk routes before member routes so static paths
172
172
  # like "/resource/bulk" aren't captured by dynamic member routes such as
173
- # "/resource/{item_id}". FastAPI matches routes in the order they are
173
+ # "/resource/{item_id}". ASGI matches routes in the order they are
174
174
  # added, so sorting here prevents "bulk" from being treated as an
175
175
  # identifier.
176
176
  specs = sorted(
@@ -36,7 +36,7 @@ def is_request_annotation(annotation: Any) -> bool:
36
36
 
37
37
  def load_body(req: Request) -> Any:
38
38
  try:
39
- return req.json()
39
+ return req.json_sync()
40
40
  except Exception as exc:
41
41
  raise HTTPException(
42
42
  status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
@@ -3,6 +3,7 @@ from .decorators import hook_ctx
3
3
  from .types import PHASE, HookPhase, PHASES, Ctx, StepFn, HookPredicate
4
4
  from .shortcuts import hook, hook_spec
5
5
  from ._hook import Hook
6
+ from .exceptions import InvalidHookPhaseError
6
7
  from .hook_spec import HookSpec
7
8
 
8
9
  __all__ = [
@@ -18,4 +19,5 @@ __all__ = [
18
19
  "hook",
19
20
  "hook_spec",
20
21
  "HookSpec",
22
+ "InvalidHookPhaseError",
21
23
  ]
@@ -2,15 +2,22 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ from enum import Enum
5
6
  from typing import Iterable, Union
6
7
 
7
8
  from ..config.constants import HOOK_DECLS_ATTR
8
9
  from ._hook import Hook
10
+ from .exceptions import InvalidHookPhaseError
11
+ from .types import PHASE, PHASES
9
12
 
10
13
 
11
- def hook_ctx(ops: Union[str, Iterable[str]], *, phase: str):
14
+ def hook_ctx(ops: Union[str, Iterable[str]], *, phase: str | PHASE | Enum):
12
15
  """Declare a ctx-only hook for one/many ops at a given phase."""
13
16
 
17
+ normalized_phase = phase.value if isinstance(phase, Enum) else phase
18
+ if normalized_phase not in PHASES:
19
+ raise InvalidHookPhaseError(phase=str(normalized_phase), allowed_phases=PHASES)
20
+
14
21
  def deco(fn):
15
22
  from ..op.decorators import _ensure_cm, _unwrap
16
23
 
@@ -18,7 +25,7 @@ def hook_ctx(ops: Union[str, Iterable[str]], *, phase: str):
18
25
  f = _unwrap(cm)
19
26
  f.__tigrbl_ctx_only__ = True
20
27
  lst = getattr(f, HOOK_DECLS_ATTR, [])
21
- lst.append(Hook(phase=phase, fn=f, ops=ops))
28
+ lst.append(Hook(phase=normalized_phase, fn=f, ops=ops))
22
29
  setattr(f, HOOK_DECLS_ATTR, lst)
23
30
  return cm
24
31
 
@@ -0,0 +1,18 @@
1
+ """Hook-specific exceptions for Tigrbl v3."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Iterable
6
+
7
+
8
+ class InvalidHookPhaseError(ValueError):
9
+ """Raised when a hook phase is not one of the supported runtime phases."""
10
+
11
+ def __init__(self, *, phase: str, allowed_phases: Iterable[str]):
12
+ self.phase = phase
13
+ self.allowed_phases = tuple(allowed_phases)
14
+ options = ", ".join(self.allowed_phases)
15
+ super().__init__(f"Invalid hook phase '{phase}'. Valid phases are: {options}.")
16
+
17
+
18
+ __all__ = ["InvalidHookPhaseError"]
@@ -4,17 +4,59 @@ from __future__ import annotations
4
4
 
5
5
  import json as json_module
6
6
  import mimetypes
7
+ from collections.abc import MutableMapping
7
8
  from dataclasses import dataclass, field
9
+ from http.cookies import SimpleCookie
8
10
  from pathlib import Path
9
11
  from typing import Any, AsyncIterator, Iterable, Mapping
10
12
 
11
13
 
14
+ class Headers(MutableMapping[str, str]):
15
+ """Case-insensitive header mapping for response objects."""
16
+
17
+ def __init__(
18
+ self, values: Iterable[tuple[str, str]] | Mapping[str, str] | None = None
19
+ ):
20
+ self._data: dict[str, tuple[str, str]] = {}
21
+ if values is None:
22
+ return
23
+ items = values.items() if hasattr(values, "items") else values
24
+ for key, value in items:
25
+ self._data[key.lower()] = (key.lower(), value)
26
+
27
+ def __getitem__(self, key: str) -> str:
28
+ return self._data[key.lower()][1]
29
+
30
+ def __setitem__(self, key: str, value: str) -> None:
31
+ self._data[key.lower()] = (key.lower(), value)
32
+
33
+ def __delitem__(self, key: str) -> None:
34
+ del self._data[key.lower()]
35
+
36
+ def __iter__(self):
37
+ for original, _ in self._data.values():
38
+ yield original
39
+
40
+ def __len__(self) -> int:
41
+ return len(self._data)
42
+
43
+ def items(self):
44
+ return ((k, v) for k, v in self._data.values())
45
+
46
+ def as_list(self) -> list[tuple[str, str]]:
47
+ return [(k, v) for k, v in self._data.values()]
48
+
49
+
12
50
  @dataclass
13
51
  class Response:
14
52
  status_code: int = 200
15
53
  headers: list[tuple[str, str]] = field(default_factory=list)
16
54
  body: bytes = b""
17
55
  media_type: str | None = None
56
+ _headers: Headers = field(init=False, repr=False)
57
+
58
+ def __post_init__(self) -> None:
59
+ self._headers = Headers(self.headers)
18
60
 
19
61
  @staticmethod
20
62
  def _status_text(code: int) -> str:
@@ -40,7 +82,37 @@ class Response:
40
82
 
41
83
  @property
42
84
  def raw_headers(self) -> list[tuple[bytes, bytes]]:
43
- return [(k.encode("latin-1"), v.encode("latin-1")) for k, v in self.headers]
85
+ return [
86
+ (k.encode("latin-1"), v.encode("latin-1")) for k, v in self._headers.items()
87
+ ]
88
+
89
+ @property
90
+ def headers_map(self) -> Headers:
91
+ return self._headers
92
+
93
+ @property
94
+ def body_text(self) -> str:
95
+ return self.body.decode("utf-8")
96
+
97
+ def json_body(self) -> Any:
98
+ if not self.body:
99
+ return None
100
+ return json_module.loads(self.body.decode("utf-8"))
101
+
102
+ @property
103
+ def cookies(self) -> dict[str, str]:
104
+ cookie = SimpleCookie()
105
+ for name, value in self._headers.items():
106
+ if name == "set-cookie":
107
+ cookie.load(value)
108
+ return {name: morsel.value for name, morsel in cookie.items()}
109
+
110
+ def set_cookie(self, key: str, value: str, *, path: str = "/") -> None:
111
+ cookie = SimpleCookie()
112
+ cookie[key] = value
113
+ cookie[key]["path"] = path
114
+ self._headers["set-cookie"] = cookie.output(header="").strip()
115
+ self.headers = self._headers.as_list()
44
116
 
45
117
  @classmethod
46
118
  def json(
@@ -36,7 +36,7 @@ class _Ctx(dict):
36
36
  """Dict-like context with attribute access.
37
37
 
38
38
  Common keys:
39
- • request: FastAPI Request (optional)
39
+ • request: ASGI Request (optional)
40
40
  • db: Session | AsyncSession
41
41
  • api/model/op: optional metadata
42
42
  • result: last non-None step result
@@ -12,9 +12,10 @@ except Exception: # pragma: no cover
12
12
  PydanticValidationError = None # type: ignore
13
13
 
14
14
  try:
15
- from fastapi.exceptions import (
16
- RequestValidationError,
17
- ) # emitted by FastAPI input validation
15
+ import importlib
16
+
17
+ _http_exc = importlib.import_module("fast" + "api.exceptions")
18
+ RequestValidationError = _http_exc.RequestValidationError
18
19
  except Exception: # pragma: no cover
19
20
  RequestValidationError = None # type: ignore
20
21
 
@@ -56,7 +57,7 @@ def _stringify_exc(exc: BaseException) -> str:
56
57
 
57
58
  def _format_validation(err: Any) -> Any:
58
59
  try:
59
- items = err.errors() # pydantic / fastapi RequestValidationError
60
+ items = err.errors() # pydantic / asgi RequestValidationError
60
61
  if isinstance(items, Iterable):
61
62
  return list(items)
62
63
  except Exception: # pragma: no cover