tigrbl 0.3.4.dev2__tar.gz → 0.3.5__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 (298) hide show
  1. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/PKG-INFO +257 -14
  2. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/README.md +252 -5
  3. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/pyproject.toml +6 -10
  4. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/__init__.py +14 -3
  5. tigrbl-0.3.5/tigrbl/api/__init__.py +19 -0
  6. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/api/_api.py +49 -7
  7. tigrbl-0.3.5/tigrbl/api/_route.py +119 -0
  8. tigrbl-0.3.5/tigrbl/api/_router.py +271 -0
  9. tigrbl-0.3.5/tigrbl/api/_routing.py +143 -0
  10. tigrbl-0.3.5/tigrbl/api/resolve.py +151 -0
  11. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/api/tigrbl_api.py +49 -4
  12. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/app/_app.py +19 -8
  13. tigrbl-0.3.5/tigrbl/app/_routing_runtime.py +24 -0
  14. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/app/tigrbl_app.py +116 -5
  15. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/api/include.py +6 -1
  16. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/rest/collection.py +3 -3
  17. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/rest/common.py +26 -12
  18. tigrbl-0.3.5/tigrbl/bindings/rest/fastapi.py +52 -0
  19. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/rest/helpers.py +1 -1
  20. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/rest/io.py +4 -1
  21. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/rest/io_headers.py +1 -1
  22. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/rest/member.py +3 -3
  23. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/rest/router.py +50 -4
  24. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/rest/routing.py +11 -4
  25. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/rpc.py +26 -12
  26. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/column/__init__.py +4 -1
  27. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/column/storage_spec.py +13 -0
  28. tigrbl-0.3.5/tigrbl/core/crud/params.py +50 -0
  29. tigrbl-0.3.5/tigrbl/core/resolver.py +81 -0
  30. tigrbl-0.3.5/tigrbl/core/router_runtime.py +164 -0
  31. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/ddl/__init__.py +9 -6
  32. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/deps/__init__.py +10 -5
  33. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/engine/builders.py +14 -5
  34. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/engine/engine_spec.py +7 -4
  35. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/engine/resolver.py +137 -4
  36. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/engine/shortcuts.py +19 -4
  37. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/mixins/_RowBound.py +1 -1
  38. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/mixins/ownable.py +1 -1
  39. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/mixins/tenant_bound.py +1 -1
  40. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/response/__init__.py +16 -0
  41. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/response/shortcuts.py +34 -40
  42. tigrbl-0.3.5/tigrbl/response/stdapi.py +194 -0
  43. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/__init__.py +2 -2
  44. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/response/renderer.py +2 -1
  45. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/response/templates.py +1 -1
  46. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/wire/validate_in.py +2 -1
  47. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/executor/invoke.py +1 -1
  48. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/executor/types.py +1 -3
  49. {tigrbl-0.3.4.dev2/tigrbl/runtime/errors → tigrbl-0.3.5/tigrbl/runtime/status}/__init__.py +3 -1
  50. {tigrbl-0.3.4.dev2/tigrbl/runtime/errors → tigrbl-0.3.5/tigrbl/runtime/status}/converters.py +2 -3
  51. {tigrbl-0.3.4.dev2/tigrbl/runtime/errors → tigrbl-0.3.5/tigrbl/runtime/status}/exceptions.py +26 -1
  52. {tigrbl-0.3.4.dev2/tigrbl/runtime/errors → tigrbl-0.3.5/tigrbl/runtime/status}/mappings.py +23 -0
  53. {tigrbl-0.3.4.dev2/tigrbl/runtime/errors → tigrbl-0.3.5/tigrbl/runtime/status}/utils.py +1 -38
  54. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/system.py +1 -1
  55. tigrbl-0.3.5/tigrbl/security/__init__.py +297 -0
  56. tigrbl-0.3.5/tigrbl/security/dependencies.py +21 -0
  57. tigrbl-0.3.5/tigrbl/system/__init__.py +77 -0
  58. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/system/diagnostics/compat.py +2 -2
  59. tigrbl-0.3.5/tigrbl/system/docs/__init__.py +42 -0
  60. tigrbl-0.3.5/tigrbl/system/docs/lens.py +99 -0
  61. tigrbl-0.3.5/tigrbl/system/docs/openapi/__init__.py +34 -0
  62. tigrbl-0.3.5/tigrbl/system/docs/openapi/helpers.py +204 -0
  63. tigrbl-0.3.5/tigrbl/system/docs/openapi/metadata.py +21 -0
  64. tigrbl-0.3.5/tigrbl/system/docs/openapi/mount.py +30 -0
  65. tigrbl-0.3.5/tigrbl/system/docs/openapi/schema.py +138 -0
  66. {tigrbl-0.3.4.dev2/tigrbl/transport/jsonrpc → tigrbl-0.3.5/tigrbl/system/docs}/openrpc.py +29 -1
  67. tigrbl-0.3.5/tigrbl/system/docs/swagger.py +68 -0
  68. tigrbl-0.3.5/tigrbl/system/favicon/__init__.py +41 -0
  69. tigrbl-0.3.5/tigrbl/transport/__init__.py +121 -0
  70. tigrbl-0.3.5/tigrbl/transport/asgi_wsgi.py +181 -0
  71. tigrbl-0.3.5/tigrbl/transport/background.py +29 -0
  72. tigrbl-0.3.5/tigrbl/transport/httpx.py +25 -0
  73. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/transport/jsonrpc/dispatcher.py +49 -29
  74. tigrbl-0.3.5/tigrbl/transport/jsonrpc/openrpc.py +3 -0
  75. tigrbl-0.3.5/tigrbl/transport/request.py +48 -0
  76. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/transport/rest/__init__.py +10 -1
  77. tigrbl-0.3.5/tigrbl/transport/rest/decorators.py +30 -0
  78. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/types/__init__.py +8 -13
  79. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/types/authn_abc.py +1 -1
  80. tigrbl-0.3.4.dev2/tigrbl/api/__init__.py +0 -6
  81. tigrbl-0.3.4.dev2/tigrbl/bindings/rest/fastapi.py +0 -76
  82. tigrbl-0.3.4.dev2/tigrbl/deps/fastapi.py +0 -41
  83. tigrbl-0.3.4.dev2/tigrbl/deps/starlette.py +0 -36
  84. tigrbl-0.3.4.dev2/tigrbl/system/__init__.py +0 -13
  85. tigrbl-0.3.4.dev2/tigrbl/transport/__init__.py +0 -75
  86. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/LICENSE +0 -0
  87. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/README.md +0 -0
  88. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/api/api_spec.py +0 -0
  89. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/api/mro_collect.py +0 -0
  90. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/api/shortcuts.py +0 -0
  91. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/app/__init__.py +0 -0
  92. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/app/_model_registry.py +0 -0
  93. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/app/app_spec.py +0 -0
  94. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/app/mro_collect.py +0 -0
  95. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/app/shortcuts.py +0 -0
  96. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/__init__.py +0 -0
  97. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/api/__init__.py +0 -0
  98. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/api/common.py +0 -0
  99. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/api/resource_proxy.py +0 -0
  100. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/api/rpc.py +0 -0
  101. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/columns.py +0 -0
  102. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/handlers/__init__.py +0 -0
  103. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/handlers/builder.py +0 -0
  104. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/handlers/ctx.py +0 -0
  105. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/handlers/identifiers.py +0 -0
  106. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/handlers/namespaces.py +0 -0
  107. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/handlers/steps.py +0 -0
  108. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/hooks.py +0 -0
  109. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/model.py +0 -0
  110. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/model_helpers.py +0 -0
  111. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/model_registry.py +0 -0
  112. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/rest/__init__.py +0 -0
  113. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/rest/attach.py +0 -0
  114. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/schemas/__init__.py +0 -0
  115. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/schemas/builder.py +0 -0
  116. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/schemas/defaults.py +0 -0
  117. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/bindings/schemas/utils.py +0 -0
  118. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/column/README.md +0 -0
  119. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/column/_column.py +0 -0
  120. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/column/column_spec.py +0 -0
  121. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/column/field_spec.py +0 -0
  122. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/column/infer/__init__.py +0 -0
  123. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/column/infer/core.py +0 -0
  124. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/column/infer/jsonhints.py +0 -0
  125. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/column/infer/planning.py +0 -0
  126. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/column/infer/types.py +0 -0
  127. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/column/infer/utils.py +0 -0
  128. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/column/io_spec.py +0 -0
  129. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/column/mro_collect.py +0 -0
  130. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/column/shortcuts.py +0 -0
  131. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/config/__init__.py +0 -0
  132. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/config/constants.py +0 -0
  133. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/config/defaults.py +0 -0
  134. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/config/resolver.py +0 -0
  135. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/core/__init__.py +0 -0
  136. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/core/crud/__init__.py +0 -0
  137. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/core/crud/bulk.py +0 -0
  138. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/core/crud/helpers/__init__.py +0 -0
  139. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/core/crud/helpers/db.py +0 -0
  140. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/core/crud/helpers/enum.py +0 -0
  141. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/core/crud/helpers/filters.py +0 -0
  142. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/core/crud/helpers/model.py +0 -0
  143. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/core/crud/helpers/normalize.py +0 -0
  144. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/core/crud/ops.py +0 -0
  145. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/decorators.py +0 -0
  146. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/deps/jinja.py +0 -0
  147. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/deps/pydantic.py +0 -0
  148. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/deps/sqlalchemy.py +0 -0
  149. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/docs/verbosity.md +0 -0
  150. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/engine/__init__.py +0 -0
  151. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/engine/_engine.py +0 -0
  152. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/engine/bind.py +0 -0
  153. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/engine/capabilities.py +0 -0
  154. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/engine/collect.py +0 -0
  155. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/engine/decorators.py +0 -0
  156. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/engine/docs/PLUGINS.md +0 -0
  157. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/engine/plugins.py +0 -0
  158. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/engine/registry.py +0 -0
  159. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/hook/__init__.py +0 -0
  160. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/hook/_hook.py +0 -0
  161. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/hook/decorators.py +0 -0
  162. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/hook/hook_spec.py +0 -0
  163. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/hook/mro_collect.py +0 -0
  164. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/hook/shortcuts.py +0 -0
  165. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/hook/types.py +0 -0
  166. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/op/__init__.py +0 -0
  167. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/op/_op.py +0 -0
  168. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/op/canonical.py +0 -0
  169. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/op/collect.py +0 -0
  170. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/op/decorators.py +0 -0
  171. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/op/model_registry.py +0 -0
  172. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/op/mro_collect.py +0 -0
  173. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/op/resolver.py +0 -0
  174. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/op/types.py +0 -0
  175. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/__init__.py +0 -0
  176. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/mixins/__init__.py +0 -0
  177. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/mixins/bootstrappable.py +0 -0
  178. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/mixins/bound.py +0 -0
  179. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/mixins/edges.py +0 -0
  180. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/mixins/fields.py +0 -0
  181. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/mixins/hierarchy.py +0 -0
  182. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/mixins/key_digest.py +0 -0
  183. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/mixins/lifecycle.py +0 -0
  184. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/mixins/locks.py +0 -0
  185. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/mixins/markers.py +0 -0
  186. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/mixins/operations.py +0 -0
  187. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/mixins/principals.py +0 -0
  188. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/mixins/upsertable.py +0 -0
  189. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/mixins/utils.py +0 -0
  190. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/tables/__init__.py +0 -0
  191. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/tables/_base.py +0 -0
  192. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/tables/audit.py +0 -0
  193. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/tables/client.py +0 -0
  194. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/tables/group.py +0 -0
  195. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/tables/org.py +0 -0
  196. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/tables/rbac.py +0 -0
  197. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/tables/status.py +0 -0
  198. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/tables/tenant.py +0 -0
  199. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/orm/tables/user.py +0 -0
  200. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/response/README.md +0 -0
  201. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/response/bind.py +0 -0
  202. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/response/decorators.py +0 -0
  203. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/response/resolver.py +0 -0
  204. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/response/types.py +0 -0
  205. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/rest/__init__.py +0 -0
  206. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/README.md +0 -0
  207. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/__init__.py +0 -0
  208. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/emit/__init__.py +0 -0
  209. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/emit/paired_post.py +0 -0
  210. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/emit/paired_pre.py +0 -0
  211. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/emit/readtime_alias.py +0 -0
  212. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/out/__init__.py +0 -0
  213. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/out/masking.py +0 -0
  214. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/refresh/__init__.py +0 -0
  215. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/refresh/demand.py +0 -0
  216. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/resolve/__init__.py +0 -0
  217. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/resolve/assemble.py +0 -0
  218. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/resolve/paired_gen.py +0 -0
  219. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/response/__init__.py +0 -0
  220. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/response/headers_from_payload.py +0 -0
  221. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/response/negotiate.py +0 -0
  222. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/response/negotiation.py +0 -0
  223. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/response/render.py +0 -0
  224. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/response/template.py +0 -0
  225. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/schema/__init__.py +0 -0
  226. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/schema/collect_in.py +0 -0
  227. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/schema/collect_out.py +0 -0
  228. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/storage/__init__.py +0 -0
  229. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/storage/to_stored.py +0 -0
  230. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/wire/__init__.py +0 -0
  231. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/wire/build_in.py +0 -0
  232. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/wire/build_out.py +0 -0
  233. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/atoms/wire/dump.py +0 -0
  234. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/context.py +0 -0
  235. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/events.py +0 -0
  236. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/executor/__init__.py +0 -0
  237. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/executor/guards.py +0 -0
  238. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/executor/helpers.py +0 -0
  239. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/kernel.py +0 -0
  240. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/labels.py +0 -0
  241. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/opview.py +0 -0
  242. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/ordering.py +0 -0
  243. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/runtime/trace.py +0 -0
  244. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/schema/__init__.py +0 -0
  245. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/schema/_schema.py +0 -0
  246. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/schema/builder/__init__.py +0 -0
  247. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/schema/builder/build_schema.py +0 -0
  248. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/schema/builder/cache.py +0 -0
  249. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/schema/builder/compat.py +0 -0
  250. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/schema/builder/extras.py +0 -0
  251. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/schema/builder/helpers.py +0 -0
  252. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/schema/builder/list_params.py +0 -0
  253. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/schema/builder/strip_parent_fields.py +0 -0
  254. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/schema/collect.py +0 -0
  255. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/schema/decorators.py +0 -0
  256. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/schema/get_schema.py +0 -0
  257. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/schema/schema_spec.py +0 -0
  258. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/schema/shortcuts.py +0 -0
  259. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/schema/types.py +0 -0
  260. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/schema/utils.py +0 -0
  261. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/session/README.md +0 -0
  262. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/session/__init__.py +0 -0
  263. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/session/abc.py +0 -0
  264. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/session/base.py +0 -0
  265. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/session/decorators.py +0 -0
  266. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/session/default.py +0 -0
  267. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/session/shortcuts.py +0 -0
  268. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/session/spec.py +0 -0
  269. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/shortcuts.py +0 -0
  270. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/specs.py +0 -0
  271. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/system/diagnostics/__init__.py +0 -0
  272. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/system/diagnostics/healthz.py +0 -0
  273. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/system/diagnostics/hookz.py +0 -0
  274. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/system/diagnostics/kernelz.py +0 -0
  275. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/system/diagnostics/methodz.py +0 -0
  276. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/system/diagnostics/router.py +0 -0
  277. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/system/diagnostics/utils.py +0 -0
  278. {tigrbl-0.3.4.dev2/tigrbl/deps → tigrbl-0.3.5/tigrbl/system/favicon/assets}/favicon.svg +0 -0
  279. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/system/uvicorn.py +0 -0
  280. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/table/__init__.py +0 -0
  281. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/table/_base.py +0 -0
  282. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/table/_table.py +0 -0
  283. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/table/mro_collect.py +0 -0
  284. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/table/shortcuts.py +0 -0
  285. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/table/table_spec.py +0 -0
  286. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/transport/jsonrpc/__init__.py +0 -0
  287. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/transport/jsonrpc/helpers.py +0 -0
  288. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/transport/jsonrpc/models.py +0 -0
  289. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/transport/rest/aggregator.py +0 -0
  290. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/types/allow_anon_provider.py +0 -0
  291. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/types/nested_path_provider.py +0 -0
  292. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/types/op.py +0 -0
  293. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/types/op_config_provider.py +0 -0
  294. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/types/op_verb_alias_provider.py +0 -0
  295. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/types/request_extras_provider.py +0 -0
  296. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/types/response_extras_provider.py +0 -0
  297. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/types/table_config_provider.py +0 -0
  298. {tigrbl-0.3.4.dev2 → tigrbl-0.3.5}/tigrbl/types/uuid.py +0 -0
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tigrbl
3
- Version: 0.3.4.dev2
4
- Summary: Automatic API generation tools by Swarmauri.
3
+ Version: 0.3.5
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
7
- Keywords: tigrbl,sdk,standards
8
- Author: Swarmauri Team
9
- Author-email: team@swarmauri.com
7
+ Keywords: tigrbl,sdk,standards,asgi,rest,rpc
8
+ Author: Jacob Stewart
9
+ Author-email: jacob@swarmauri.com
10
10
  Requires-Python: >=3.10,<3.13
11
11
  Classifier: License :: OSI Approved :: Apache Software License
12
12
  Classifier: Development Status :: 3 - Alpha
@@ -21,16 +21,12 @@ Provides-Extra: templates
21
21
  Provides-Extra: tests
22
22
  Requires-Dist: aiosqlite (>=0.19.0)
23
23
  Requires-Dist: asyncpg (>=0.30.0) ; extra == "postgres"
24
- Requires-Dist: fastapi (>=0.100.0)
25
24
  Requires-Dist: greenlet (>=3.2.3)
26
25
  Requires-Dist: httpx (>=0.27.0)
27
26
  Requires-Dist: jinja2 (>=3.1.4) ; extra == "templates"
28
27
  Requires-Dist: psycopg2-binary (>=2.9.9) ; extra == "postgres"
29
28
  Requires-Dist: pydantic (>=2.0.0)
30
29
  Requires-Dist: sqlalchemy (>=2.0)
31
- Requires-Dist: swarmauri_base
32
- Requires-Dist: swarmauri_core
33
- Requires-Dist: swarmauri_standard
34
30
  Requires-Dist: tigrbl-tests ; extra == "tests"
35
31
  Requires-Dist: uvicorn
36
32
  Description-Content-Type: text/markdown
@@ -53,7 +49,7 @@ Description-Content-Type: text/markdown
53
49
  ---
54
50
 
55
51
  # Tigrbl 🐅🐂
56
- A high-leverage meta-framework that turns plain SQLAlchemy models into a fully-featured REST+RPC surface with near-zero boilerplate. 🚀
52
+ A high-leverage ASGI meta-framework that turns plain SQLAlchemy models into a fully-featured REST+RPC surface with near-zero boilerplate. 🚀
57
53
 
58
54
  ## Features ✨
59
55
 
@@ -61,7 +57,7 @@ A high-leverage meta-framework that turns plain SQLAlchemy models into a fully-f
61
57
  - 🔌 Unified REST and RPC endpoints from a single definition
62
58
  - 🪝 Hookable phase system for deep customization
63
59
  - 🧩 Pluggable engine and provider abstractions
64
- - 🚀 Built on FastAPI and Pydantic for modern Python web apps
60
+ - 🚀 Built as an ASGI-native framework with Pydantic-powered schema generation
65
61
 
66
62
  ## Terminology 📚
67
63
 
@@ -402,7 +398,232 @@ control headers, status codes, and optional template rendering. See
402
398
 
403
399
  * SQLAlchemy for ORM integration.
404
400
  * Pydantic for schema generation.
405
- * FastAPI for routing and dependency injection.
401
+ * ASGI-native routing and dependency injection.
402
+
403
+ ## Best Design Practices ✅
404
+
405
+ The following practices are the canonical, production-ready patterns for
406
+ building on Tigrbl. Each rule is explained and demonstrated with
407
+ approved usage. These are not optional—adhering to them keeps the runtime
408
+ predictable, preserves hook lifecycle guarantees, and ensures schema
409
+ consistency across REST and RPC surfaces.
410
+
411
+ ### 1) Never import SQLAlchemy directly or bypass Tigrbl APIs
412
+
413
+ **Why:** Direct imports bypass Tigrbl's compatibility layer and make it
414
+ harder to evolve internal dependencies. Use the Tigrbl exports so your
415
+ code stays aligned with the framework’s versioned ASGI API.
416
+
417
+ ✅ **Preferred:**
418
+ ```python
419
+ from tigrbl import Base, TigrblApp, TigrblApi
420
+ from tigrbl.types import Integer, String, Mapped
421
+ from tigrbl.types import Depends, HTTPException, Request
422
+ ```
423
+
424
+ 🚫 **Avoid:**
425
+ ```python
426
+ from sqlalchemy import Integer, String
427
+ from some_framework import Depends
428
+ ```
429
+
430
+ ### 2) Do not coerce UUIDs manually
431
+
432
+ **Why:** Tigrbl schemas and types already normalize UUIDs. Manual coercion
433
+ creates inconsistent behavior across engines and breaks schema-level
434
+ validation.
435
+
436
+ ✅ **Preferred:**
437
+ ```python
438
+ from tigrbl.types import PgUUID, uuid4, Mapped
439
+
440
+ class Item(Table):
441
+ __tablename__ = "items"
442
+ id: Mapped[PgUUID] = acol(primary_key=True, default=uuid4)
443
+ ```
444
+
445
+ 🚫 **Avoid:**
446
+ ```python
447
+ from uuid import UUID
448
+
449
+ item_id = UUID(str(payload["id"]))
450
+ ```
451
+
452
+ ### 3) Use engine specs for persistence, not ad-hoc engines
453
+
454
+ **Why:** Engine specs make persistence declarative, testable, and
455
+ compatible with engine resolution across app, API, table, and op scopes.
456
+
457
+ ✅ **Preferred:**
458
+ ```python
459
+ from tigrbl.engine.shortcuts import engine_spec
460
+ from tigrbl.engine.decorators import engine_ctx
461
+
462
+ spec = engine_spec(kind="postgres", async_=True, host="db", name="app_db")
463
+
464
+ @engine_ctx(spec)
465
+ class App:
466
+ ...
467
+ ```
468
+
469
+ 🚫 **Avoid:**
470
+ ```python
471
+ from sqlalchemy.ext.asyncio import create_async_engine
472
+
473
+ engine = create_async_engine("postgresql+asyncpg://...")
474
+ ```
475
+
476
+ ### 4) Never call DB session methods directly
477
+
478
+ **Why:** Direct calls bypass the hook lifecycle and the database guards.
479
+ Use model handlers or `app.<Model>.handlers.<op>` so hooks, policies, and
480
+ schema enforcement run consistently.
481
+
482
+ ✅ **Preferred:**
483
+ ```python
484
+ result = await Item.handlers.create(payload, ctx=request_ctx)
485
+ # or from a Tigrbl app instance:
486
+ result = await app.Item.handlers.create(payload, ctx=request_ctx)
487
+ ```
488
+
489
+ 🚫 **Avoid:**
490
+ ```python
491
+ db.add(item)
492
+ await db.execute(statement)
493
+ ```
494
+
495
+ ### 5) Always use encapsulated payloads as inputs and outputs
496
+
497
+ **Why:** Tigrbl expects request/response envelopes to preserve metadata,
498
+ support policy enforcement, and keep REST/RPC in lockstep.
499
+
500
+ ✅ **Preferred:**
501
+ ```python
502
+ from tigrbl import get_schema
503
+
504
+ CreateIn = get_schema(Item, "create", "in")
505
+ CreateOut = get_schema(Item, "create", "out")
506
+
507
+ payload = CreateIn(name="Widget")
508
+ result = await Item.handlers.create(payload, ctx=request_ctx)
509
+ response = CreateOut(result=result)
510
+ ```
511
+
512
+ 🚫 **Avoid:**
513
+ ```python
514
+ payload = {"name": "Widget"}
515
+ result = await Item.handlers.create(payload)
516
+ ```
517
+
518
+ ### 6) Encapsulation must use `get_schema(...)`
519
+
520
+ **Why:** `get_schema` guarantees the envelope is aligned to the configured
521
+ schema and respects schema overrides, request extras, and response extras.
522
+
523
+ ✅ **Preferred:**
524
+ ```python
525
+ ListIn = get_schema(Item, "list", "in")
526
+ ListOut = get_schema(Item, "list", "out")
527
+ ```
528
+
529
+ 🚫 **Avoid:**
530
+ ```python
531
+ from pydantic import BaseModel
532
+
533
+ class ListIn(BaseModel):
534
+ payload: dict
535
+ ```
536
+
537
+ ### 7) `Table` must be the first inherited class for all models
538
+
539
+ **Why:** Tigrbl inspects base classes for lifecycle and configuration.
540
+ Putting `Table` first preserves deterministic MRO behavior.
541
+
542
+ ✅ **Preferred:**
543
+ ```python
544
+ from tigrbl.orm.tables import Table
545
+ from tigrbl.orm.mixins import Timestamped
546
+
547
+ class Item(Table, Timestamped):
548
+ __tablename__ = "items"
549
+ ```
550
+
551
+ 🚫 **Avoid:**
552
+ ```python
553
+ class Item(Timestamped, Table):
554
+ __tablename__ = "items"
555
+ ```
556
+
557
+ ### 8) Never call `db.flush()` or `db.commit()`
558
+
559
+ **Why:** The hook lifecycle owns transactional boundaries. Manual flush or
560
+ commit short-circuits phase guards and can corrupt the request lifecycle.
561
+
562
+ ✅ **Preferred:**
563
+ ```python
564
+ @hook_ctx(ops="create", phase="HANDLER")
565
+ async def handler(ctx):
566
+ await Item.handlers.create(ctx["request"].payload, ctx=ctx)
567
+ ```
568
+
569
+ 🚫 **Avoid:**
570
+ ```python
571
+ db.flush()
572
+ db.commit()
573
+ ```
574
+
575
+ ### 9) Use ops for new REST/RPC methods—never add ad-hoc framework routes
576
+
577
+ **Why:** Ops keep routing, schemas, hooks, and policies unified. Custom
578
+ custom framework routes bypass these guarantees.
579
+
580
+ ✅ **Preferred:**
581
+ ```python
582
+ from tigrbl import op_ctx
583
+
584
+ @op_ctx(name="rotate_keys", method="POST", path="/keys/rotate")
585
+ async def rotate_keys(payload, *, ctx):
586
+ return await Key.handlers.rotate(payload, ctx=ctx)
587
+ ```
588
+
589
+ 🚫 **Avoid:**
590
+ ```python
591
+ from some_framework import APIRouter
592
+
593
+ router = APIRouter()
594
+
595
+ @router.post("/keys/rotate")
596
+ async def rotate_keys(payload):
597
+ ...
598
+ ```
599
+
600
+ ### 10) Use context decorators where appropriate
601
+
602
+ **Why:** Context decorators (`engine_ctx`, `schema_ctx`, `op_ctx`,
603
+ `hook_ctx`) provide explicit, declarative binding of behavior and are
604
+ resolved deterministically by the runtime.
605
+
606
+ ✅ **Preferred:**
607
+ ```python
608
+ from tigrbl import hook_ctx, op_ctx, schema_ctx
609
+ from tigrbl.engine.decorators import engine_ctx
610
+
611
+ @engine_ctx(kind="sqlite", mode="memory")
612
+ class Item(Table):
613
+ __tablename__ = "items"
614
+
615
+ @schema_ctx(ops="create", cfg={"exclude": {"id"}})
616
+ class ItemCreateSchema:
617
+ model = Item
618
+
619
+ @op_ctx(name="export", method="GET", path="/items/export")
620
+ async def export_items(payload, *, ctx):
621
+ return await Item.handlers.list(payload, ctx=ctx)
622
+
623
+ @hook_ctx(ops="create", phase="PRE_HANDLER")
624
+ async def validate(ctx):
625
+ ...
626
+ ```
406
627
 
407
628
  ### Engine & Provider examples 🛠️
408
629
 
@@ -499,6 +720,30 @@ async def decorated_create(payload, *, db=None):
499
720
  ...
500
721
  ```
501
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
+
502
747
  ## Glossary 📖
503
748
 
504
749
  1. Tables
@@ -512,5 +757,3 @@ async def decorated_create(payload, *, db=None):
512
757
  9. Core
513
758
  10. Core\_Raw
514
759
 
515
-
516
-
@@ -16,7 +16,7 @@
16
16
  ---
17
17
 
18
18
  # Tigrbl 🐅🐂
19
- A high-leverage meta-framework that turns plain SQLAlchemy models into a fully-featured REST+RPC surface with near-zero boilerplate. 🚀
19
+ A high-leverage ASGI meta-framework that turns plain SQLAlchemy models into a fully-featured REST+RPC surface with near-zero boilerplate. 🚀
20
20
 
21
21
  ## Features ✨
22
22
 
@@ -24,7 +24,7 @@ A high-leverage meta-framework that turns plain SQLAlchemy models into a fully-f
24
24
  - 🔌 Unified REST and RPC endpoints from a single definition
25
25
  - 🪝 Hookable phase system for deep customization
26
26
  - 🧩 Pluggable engine and provider abstractions
27
- - 🚀 Built on FastAPI and Pydantic for modern Python web apps
27
+ - 🚀 Built as an ASGI-native framework with Pydantic-powered schema generation
28
28
 
29
29
  ## Terminology 📚
30
30
 
@@ -365,7 +365,232 @@ control headers, status codes, and optional template rendering. See
365
365
 
366
366
  * SQLAlchemy for ORM integration.
367
367
  * Pydantic for schema generation.
368
- * FastAPI for routing and dependency injection.
368
+ * ASGI-native routing and dependency injection.
369
+
370
+ ## Best Design Practices ✅
371
+
372
+ The following practices are the canonical, production-ready patterns for
373
+ building on Tigrbl. Each rule is explained and demonstrated with
374
+ approved usage. These are not optional—adhering to them keeps the runtime
375
+ predictable, preserves hook lifecycle guarantees, and ensures schema
376
+ consistency across REST and RPC surfaces.
377
+
378
+ ### 1) Never import SQLAlchemy directly or bypass Tigrbl APIs
379
+
380
+ **Why:** Direct imports bypass Tigrbl's compatibility layer and make it
381
+ harder to evolve internal dependencies. Use the Tigrbl exports so your
382
+ code stays aligned with the framework’s versioned ASGI API.
383
+
384
+ ✅ **Preferred:**
385
+ ```python
386
+ from tigrbl import Base, TigrblApp, TigrblApi
387
+ from tigrbl.types import Integer, String, Mapped
388
+ from tigrbl.types import Depends, HTTPException, Request
389
+ ```
390
+
391
+ 🚫 **Avoid:**
392
+ ```python
393
+ from sqlalchemy import Integer, String
394
+ from some_framework import Depends
395
+ ```
396
+
397
+ ### 2) Do not coerce UUIDs manually
398
+
399
+ **Why:** Tigrbl schemas and types already normalize UUIDs. Manual coercion
400
+ creates inconsistent behavior across engines and breaks schema-level
401
+ validation.
402
+
403
+ ✅ **Preferred:**
404
+ ```python
405
+ from tigrbl.types import PgUUID, uuid4, Mapped
406
+
407
+ class Item(Table):
408
+ __tablename__ = "items"
409
+ id: Mapped[PgUUID] = acol(primary_key=True, default=uuid4)
410
+ ```
411
+
412
+ 🚫 **Avoid:**
413
+ ```python
414
+ from uuid import UUID
415
+
416
+ item_id = UUID(str(payload["id"]))
417
+ ```
418
+
419
+ ### 3) Use engine specs for persistence, not ad-hoc engines
420
+
421
+ **Why:** Engine specs make persistence declarative, testable, and
422
+ compatible with engine resolution across app, API, table, and op scopes.
423
+
424
+ ✅ **Preferred:**
425
+ ```python
426
+ from tigrbl.engine.shortcuts import engine_spec
427
+ from tigrbl.engine.decorators import engine_ctx
428
+
429
+ spec = engine_spec(kind="postgres", async_=True, host="db", name="app_db")
430
+
431
+ @engine_ctx(spec)
432
+ class App:
433
+ ...
434
+ ```
435
+
436
+ 🚫 **Avoid:**
437
+ ```python
438
+ from sqlalchemy.ext.asyncio import create_async_engine
439
+
440
+ engine = create_async_engine("postgresql+asyncpg://...")
441
+ ```
442
+
443
+ ### 4) Never call DB session methods directly
444
+
445
+ **Why:** Direct calls bypass the hook lifecycle and the database guards.
446
+ Use model handlers or `app.<Model>.handlers.<op>` so hooks, policies, and
447
+ schema enforcement run consistently.
448
+
449
+ ✅ **Preferred:**
450
+ ```python
451
+ result = await Item.handlers.create(payload, ctx=request_ctx)
452
+ # or from a Tigrbl app instance:
453
+ result = await app.Item.handlers.create(payload, ctx=request_ctx)
454
+ ```
455
+
456
+ 🚫 **Avoid:**
457
+ ```python
458
+ db.add(item)
459
+ await db.execute(statement)
460
+ ```
461
+
462
+ ### 5) Always use encapsulated payloads as inputs and outputs
463
+
464
+ **Why:** Tigrbl expects request/response envelopes to preserve metadata,
465
+ support policy enforcement, and keep REST/RPC in lockstep.
466
+
467
+ ✅ **Preferred:**
468
+ ```python
469
+ from tigrbl import get_schema
470
+
471
+ CreateIn = get_schema(Item, "create", "in")
472
+ CreateOut = get_schema(Item, "create", "out")
473
+
474
+ payload = CreateIn(name="Widget")
475
+ result = await Item.handlers.create(payload, ctx=request_ctx)
476
+ response = CreateOut(result=result)
477
+ ```
478
+
479
+ 🚫 **Avoid:**
480
+ ```python
481
+ payload = {"name": "Widget"}
482
+ result = await Item.handlers.create(payload)
483
+ ```
484
+
485
+ ### 6) Encapsulation must use `get_schema(...)`
486
+
487
+ **Why:** `get_schema` guarantees the envelope is aligned to the configured
488
+ schema and respects schema overrides, request extras, and response extras.
489
+
490
+ ✅ **Preferred:**
491
+ ```python
492
+ ListIn = get_schema(Item, "list", "in")
493
+ ListOut = get_schema(Item, "list", "out")
494
+ ```
495
+
496
+ 🚫 **Avoid:**
497
+ ```python
498
+ from pydantic import BaseModel
499
+
500
+ class ListIn(BaseModel):
501
+ payload: dict
502
+ ```
503
+
504
+ ### 7) `Table` must be the first inherited class for all models
505
+
506
+ **Why:** Tigrbl inspects base classes for lifecycle and configuration.
507
+ Putting `Table` first preserves deterministic MRO behavior.
508
+
509
+ ✅ **Preferred:**
510
+ ```python
511
+ from tigrbl.orm.tables import Table
512
+ from tigrbl.orm.mixins import Timestamped
513
+
514
+ class Item(Table, Timestamped):
515
+ __tablename__ = "items"
516
+ ```
517
+
518
+ 🚫 **Avoid:**
519
+ ```python
520
+ class Item(Timestamped, Table):
521
+ __tablename__ = "items"
522
+ ```
523
+
524
+ ### 8) Never call `db.flush()` or `db.commit()`
525
+
526
+ **Why:** The hook lifecycle owns transactional boundaries. Manual flush or
527
+ commit short-circuits phase guards and can corrupt the request lifecycle.
528
+
529
+ ✅ **Preferred:**
530
+ ```python
531
+ @hook_ctx(ops="create", phase="HANDLER")
532
+ async def handler(ctx):
533
+ await Item.handlers.create(ctx["request"].payload, ctx=ctx)
534
+ ```
535
+
536
+ 🚫 **Avoid:**
537
+ ```python
538
+ db.flush()
539
+ db.commit()
540
+ ```
541
+
542
+ ### 9) Use ops for new REST/RPC methods—never add ad-hoc framework routes
543
+
544
+ **Why:** Ops keep routing, schemas, hooks, and policies unified. Custom
545
+ custom framework routes bypass these guarantees.
546
+
547
+ ✅ **Preferred:**
548
+ ```python
549
+ from tigrbl import op_ctx
550
+
551
+ @op_ctx(name="rotate_keys", method="POST", path="/keys/rotate")
552
+ async def rotate_keys(payload, *, ctx):
553
+ return await Key.handlers.rotate(payload, ctx=ctx)
554
+ ```
555
+
556
+ 🚫 **Avoid:**
557
+ ```python
558
+ from some_framework import APIRouter
559
+
560
+ router = APIRouter()
561
+
562
+ @router.post("/keys/rotate")
563
+ async def rotate_keys(payload):
564
+ ...
565
+ ```
566
+
567
+ ### 10) Use context decorators where appropriate
568
+
569
+ **Why:** Context decorators (`engine_ctx`, `schema_ctx`, `op_ctx`,
570
+ `hook_ctx`) provide explicit, declarative binding of behavior and are
571
+ resolved deterministically by the runtime.
572
+
573
+ ✅ **Preferred:**
574
+ ```python
575
+ from tigrbl import hook_ctx, op_ctx, schema_ctx
576
+ from tigrbl.engine.decorators import engine_ctx
577
+
578
+ @engine_ctx(kind="sqlite", mode="memory")
579
+ class Item(Table):
580
+ __tablename__ = "items"
581
+
582
+ @schema_ctx(ops="create", cfg={"exclude": {"id"}})
583
+ class ItemCreateSchema:
584
+ model = Item
585
+
586
+ @op_ctx(name="export", method="GET", path="/items/export")
587
+ async def export_items(payload, *, ctx):
588
+ return await Item.handlers.list(payload, ctx=ctx)
589
+
590
+ @hook_ctx(ops="create", phase="PRE_HANDLER")
591
+ async def validate(ctx):
592
+ ...
593
+ ```
369
594
 
370
595
  ### Engine & Provider examples 🛠️
371
596
 
@@ -462,6 +687,30 @@ async def decorated_create(payload, *, db=None):
462
687
  ...
463
688
  ```
464
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
+
465
714
  ## Glossary 📖
466
715
 
467
716
  1. Tables
@@ -474,5 +723,3 @@ async def decorated_create(payload, *, db=None):
474
723
  8. Default Flush
475
724
  9. Core
476
725
  10. Core\_Raw
477
-
478
-
@@ -1,7 +1,7 @@
1
1
  [project]
2
2
  name = "tigrbl"
3
- version = "0.3.4.dev2"
4
- description = "Automatic API generation tools by Swarmauri."
3
+ version = "0.3.5"
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"
7
7
  repository = "http://github.com/swarmauri/swarmauri-sdk"
@@ -16,12 +16,8 @@ classifiers = [
16
16
  "Programming Language :: Python :: 3",
17
17
  "Programming Language :: Python :: 3 :: Only",
18
18
  ]
19
- authors = [{ name = "Swarmauri Team", email = "team@swarmauri.com" }]
19
+ authors = [{ name = "Jacob Stewart", email = "jacob@swarmauri.com" }]
20
20
  dependencies = [
21
- "swarmauri_core",
22
- "swarmauri_base",
23
- "swarmauri_standard",
24
- "fastapi>=0.100.0",
25
21
  "pydantic>=2.0.0",
26
22
  "sqlalchemy>=2.0",
27
23
  "aiosqlite>=0.19.0",
@@ -33,6 +29,9 @@ keywords = [
33
29
  'tigrbl',
34
30
  'sdk',
35
31
  'standards',
32
+ 'asgi',
33
+ 'rest',
34
+ 'rpc',
36
35
  ]
37
36
 
38
37
  [project.optional-dependencies]
@@ -48,9 +47,6 @@ tests = [
48
47
  ]
49
48
 
50
49
  [tool.uv.sources]
51
- swarmauri_core = { workspace = true }
52
- swarmauri_base = { workspace = true }
53
- swarmauri_standard = { workspace = true }
54
50
  tigrbl-tests = { workspace = true }
55
51
 
56
52
  [tool.pytest.ini_options]
@@ -9,7 +9,7 @@ Quick start:
9
9
  from tigrbl import include_model, build_jsonrpc_router, mount_diagnostics
10
10
  from tigrbl import OpSpec, hook_ctx, op_ctx, alias_ctx, schema_ctx, SchemaRef
11
11
 
12
- include_model(api, User, app=fastapi_app)
12
+ include_model(api, User, app=asgi_app)
13
13
  app.include_router(build_jsonrpc_router(api), prefix="/rpc")
14
14
  app.include_router(mount_diagnostics(api), prefix="/system")
15
15
 
@@ -80,12 +80,23 @@ from .api import Api, TigrblApi
80
80
 
81
81
  from .table import Base
82
82
  from .op import Op
83
- from .app._app import App
83
+ from .security import APIKey, HTTPBearer, MutualTLS, OAuth2, OpenIdConnect
84
84
 
85
85
 
86
86
  __all__: list[str] = []
87
87
 
88
- __all__ += ["TigrblApp", "TigrblApi", "Api", "Base", "App", "Op"]
88
+ __all__ += [
89
+ "TigrblApp",
90
+ "TigrblApi",
91
+ "Api",
92
+ "Base",
93
+ "Op",
94
+ "HTTPBearer",
95
+ "APIKey",
96
+ "OAuth2",
97
+ "OpenIdConnect",
98
+ "MutualTLS",
99
+ ]
89
100
 
90
101
  __all__ += [
91
102
  # OpSpec core
@@ -0,0 +1,19 @@
1
+ """Core API surfaces for the Tigrbl package."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ __all__ = ["Api", "TigrblApi"]
8
+
9
+
10
+ def __getattr__(name: str) -> Any:
11
+ if name == "Api":
12
+ from ._api import Api
13
+
14
+ return Api
15
+ if name == "TigrblApi":
16
+ from .tigrbl_api import TigrblApi
17
+
18
+ return TigrblApi
19
+ raise AttributeError(name)