tigrbl 0.3.6.dev1__tar.gz → 0.3.7__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 (309) hide show
  1. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/PKG-INFO +1 -1
  2. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/pyproject.toml +1 -1
  3. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/__init__.py +2 -2
  4. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/api/_router.py +1 -1
  5. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/api/api_spec.py +1 -1
  6. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/app/app_spec.py +1 -1
  7. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/app/tigrbl_app.py +2 -1
  8. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/__init__.py +1 -1
  9. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/rest/common.py +2 -2
  10. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/rest/fastapi.py +4 -4
  11. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/rest/helpers.py +1 -1
  12. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/rest/io.py +1 -1
  13. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/rest/routing.py +1 -1
  14. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/core/resolver.py +1 -1
  15. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/core/router_runtime.py +2 -2
  16. tigrbl-0.3.7/tigrbl/headers/__init__.py +3 -0
  17. tigrbl-0.3.7/tigrbl/headers/_header.py +89 -0
  18. tigrbl-0.3.7/tigrbl/middlewares/__init__.py +27 -0
  19. tigrbl-0.3.7/tigrbl/middlewares/compose.py +17 -0
  20. tigrbl-0.3.7/tigrbl/middlewares/cors.py +123 -0
  21. tigrbl-0.3.7/tigrbl/middlewares/decorators.py +32 -0
  22. tigrbl-0.3.7/tigrbl/middlewares/middleware.py +37 -0
  23. tigrbl-0.3.7/tigrbl/middlewares/spec.py +26 -0
  24. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/op/types.py +1 -1
  25. tigrbl-0.3.7/tigrbl/requests/__init__.py +5 -0
  26. tigrbl-0.3.6.dev1/tigrbl/transport/request.py → tigrbl-0.3.7/tigrbl/requests/_request.py +67 -30
  27. {tigrbl-0.3.6.dev1/tigrbl/response → tigrbl-0.3.7/tigrbl/responses}/__init__.py +16 -18
  28. tigrbl-0.3.6.dev1/tigrbl/response/stdapi.py → tigrbl-0.3.7/tigrbl/responses/_response.py +20 -33
  29. {tigrbl-0.3.6.dev1/tigrbl/response → tigrbl-0.3.7/tigrbl/responses}/shortcuts.py +1 -1
  30. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/response/headers_from_payload.py +1 -1
  31. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/response/renderer.py +2 -2
  32. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/response/templates.py +1 -1
  33. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/executor/types.py +1 -1
  34. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/security/schemes/api_key.py +2 -2
  35. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/security/schemes/http_bearer.py +1 -1
  36. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/system/diagnostics/compat.py +1 -1
  37. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/system/docs/lens.py +1 -1
  38. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/system/docs/openapi/mount.py +1 -1
  39. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/system/docs/openrpc.py +1 -1
  40. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/system/docs/swagger.py +1 -1
  41. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/system/favicon/__init__.py +1 -1
  42. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/table/_base.py +1 -1
  43. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/table/table_spec.py +1 -1
  44. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/transport/asgi_wsgi.py +84 -23
  45. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/transport/jsonrpc/dispatcher.py +36 -10
  46. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/types/__init__.py +2 -2
  47. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/types/authn_abc.py +1 -1
  48. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/LICENSE +0 -0
  49. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/README.md +0 -0
  50. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/README.md +0 -0
  51. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/api/__init__.py +0 -0
  52. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/api/_api.py +0 -0
  53. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/api/_route.py +0 -0
  54. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/api/_routing.py +0 -0
  55. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/api/mro_collect.py +0 -0
  56. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/api/resolve.py +0 -0
  57. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/api/shortcuts.py +0 -0
  58. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/api/tigrbl_api.py +0 -0
  59. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/app/__init__.py +0 -0
  60. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/app/_app.py +0 -0
  61. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/app/_model_registry.py +0 -0
  62. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/app/_routing_runtime.py +0 -0
  63. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/app/mro_collect.py +0 -0
  64. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/app/shortcuts.py +0 -0
  65. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/api/__init__.py +0 -0
  66. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/api/common.py +0 -0
  67. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/api/include.py +0 -0
  68. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/api/resource_proxy.py +0 -0
  69. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/api/rpc.py +0 -0
  70. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/columns.py +0 -0
  71. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/handlers/__init__.py +0 -0
  72. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/handlers/builder.py +0 -0
  73. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/handlers/ctx.py +0 -0
  74. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/handlers/identifiers.py +0 -0
  75. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/handlers/namespaces.py +0 -0
  76. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/handlers/steps.py +0 -0
  77. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/hooks.py +0 -0
  78. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/model.py +0 -0
  79. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/model_helpers.py +0 -0
  80. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/model_registry.py +0 -0
  81. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/rest/__init__.py +0 -0
  82. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/rest/attach.py +0 -0
  83. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/rest/collection.py +0 -0
  84. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/rest/io_headers.py +0 -0
  85. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/rest/member.py +0 -0
  86. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/rest/router.py +0 -0
  87. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/rpc.py +0 -0
  88. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/schemas/__init__.py +0 -0
  89. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/schemas/builder.py +0 -0
  90. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/schemas/defaults.py +0 -0
  91. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/bindings/schemas/utils.py +0 -0
  92. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/column/README.md +0 -0
  93. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/column/__init__.py +0 -0
  94. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/column/_column.py +0 -0
  95. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/column/column_spec.py +0 -0
  96. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/column/field_spec.py +0 -0
  97. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/column/infer/__init__.py +0 -0
  98. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/column/infer/core.py +0 -0
  99. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/column/infer/jsonhints.py +0 -0
  100. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/column/infer/planning.py +0 -0
  101. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/column/infer/types.py +0 -0
  102. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/column/infer/utils.py +0 -0
  103. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/column/io_spec.py +0 -0
  104. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/column/mro_collect.py +0 -0
  105. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/column/shortcuts.py +0 -0
  106. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/column/storage_spec.py +0 -0
  107. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/config/__init__.py +0 -0
  108. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/config/constants.py +0 -0
  109. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/config/defaults.py +0 -0
  110. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/config/resolver.py +0 -0
  111. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/core/__init__.py +0 -0
  112. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/core/crud/__init__.py +0 -0
  113. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/core/crud/bulk.py +0 -0
  114. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/core/crud/helpers/__init__.py +0 -0
  115. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/core/crud/helpers/db.py +0 -0
  116. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/core/crud/helpers/enum.py +0 -0
  117. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/core/crud/helpers/filters.py +0 -0
  118. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/core/crud/helpers/model.py +0 -0
  119. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/core/crud/helpers/normalize.py +0 -0
  120. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/core/crud/ops.py +0 -0
  121. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/core/crud/params.py +0 -0
  122. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/ddl/__init__.py +0 -0
  123. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/decorators.py +0 -0
  124. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/deps/__init__.py +0 -0
  125. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/deps/jinja.py +0 -0
  126. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/deps/pydantic.py +0 -0
  127. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/deps/sqlalchemy.py +0 -0
  128. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/docs/verbosity.md +0 -0
  129. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/engine/__init__.py +0 -0
  130. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/engine/_engine.py +0 -0
  131. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/engine/bind.py +0 -0
  132. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/engine/builders.py +0 -0
  133. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/engine/capabilities.py +0 -0
  134. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/engine/collect.py +0 -0
  135. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/engine/decorators.py +0 -0
  136. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/engine/docs/PLUGINS.md +0 -0
  137. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/engine/engine_spec.py +0 -0
  138. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/engine/plugins.py +0 -0
  139. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/engine/registry.py +0 -0
  140. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/engine/resolver.py +0 -0
  141. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/engine/shortcuts.py +0 -0
  142. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/hook/__init__.py +0 -0
  143. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/hook/_hook.py +0 -0
  144. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/hook/decorators.py +0 -0
  145. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/hook/exceptions.py +0 -0
  146. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/hook/hook_spec.py +0 -0
  147. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/hook/mro_collect.py +0 -0
  148. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/hook/shortcuts.py +0 -0
  149. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/hook/types.py +0 -0
  150. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/op/__init__.py +0 -0
  151. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/op/_op.py +0 -0
  152. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/op/canonical.py +0 -0
  153. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/op/collect.py +0 -0
  154. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/op/decorators.py +0 -0
  155. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/op/model_registry.py +0 -0
  156. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/op/mro_collect.py +0 -0
  157. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/op/resolver.py +0 -0
  158. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/__init__.py +0 -0
  159. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/mixins/_RowBound.py +0 -0
  160. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/mixins/__init__.py +0 -0
  161. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/mixins/bootstrappable.py +0 -0
  162. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/mixins/bound.py +0 -0
  163. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/mixins/edges.py +0 -0
  164. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/mixins/fields.py +0 -0
  165. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/mixins/hierarchy.py +0 -0
  166. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/mixins/key_digest.py +0 -0
  167. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/mixins/lifecycle.py +0 -0
  168. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/mixins/locks.py +0 -0
  169. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/mixins/markers.py +0 -0
  170. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/mixins/operations.py +0 -0
  171. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/mixins/ownable.py +0 -0
  172. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/mixins/principals.py +0 -0
  173. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/mixins/tenant_bound.py +0 -0
  174. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/mixins/upsertable.py +0 -0
  175. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/mixins/utils.py +0 -0
  176. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/tables/__init__.py +0 -0
  177. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/tables/_base.py +0 -0
  178. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/tables/audit.py +0 -0
  179. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/tables/client.py +0 -0
  180. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/tables/group.py +0 -0
  181. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/tables/org.py +0 -0
  182. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/tables/rbac.py +0 -0
  183. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/tables/status.py +0 -0
  184. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/tables/tenant.py +0 -0
  185. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/orm/tables/user.py +0 -0
  186. {tigrbl-0.3.6.dev1/tigrbl/response → tigrbl-0.3.7/tigrbl/responses}/README.md +0 -0
  187. {tigrbl-0.3.6.dev1/tigrbl/response → tigrbl-0.3.7/tigrbl/responses}/bind.py +0 -0
  188. {tigrbl-0.3.6.dev1/tigrbl/response → tigrbl-0.3.7/tigrbl/responses}/decorators.py +0 -0
  189. {tigrbl-0.3.6.dev1/tigrbl/response → tigrbl-0.3.7/tigrbl/responses}/resolver.py +0 -0
  190. {tigrbl-0.3.6.dev1/tigrbl/response → tigrbl-0.3.7/tigrbl/responses}/types.py +0 -0
  191. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/rest/__init__.py +0 -0
  192. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/README.md +0 -0
  193. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/__init__.py +0 -0
  194. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/__init__.py +0 -0
  195. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/emit/__init__.py +0 -0
  196. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/emit/paired_post.py +0 -0
  197. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/emit/paired_pre.py +0 -0
  198. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/emit/readtime_alias.py +0 -0
  199. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/out/__init__.py +0 -0
  200. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/out/masking.py +0 -0
  201. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/refresh/__init__.py +0 -0
  202. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/refresh/demand.py +0 -0
  203. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/resolve/__init__.py +0 -0
  204. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/resolve/assemble.py +0 -0
  205. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/resolve/paired_gen.py +0 -0
  206. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/response/__init__.py +0 -0
  207. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/response/negotiate.py +0 -0
  208. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/response/negotiation.py +0 -0
  209. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/response/render.py +0 -0
  210. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/response/template.py +0 -0
  211. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/schema/__init__.py +0 -0
  212. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/schema/collect_in.py +0 -0
  213. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/schema/collect_out.py +0 -0
  214. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/storage/__init__.py +0 -0
  215. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/storage/to_stored.py +0 -0
  216. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/wire/__init__.py +0 -0
  217. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/wire/build_in.py +0 -0
  218. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/wire/build_out.py +0 -0
  219. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/wire/dump.py +0 -0
  220. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/atoms/wire/validate_in.py +0 -0
  221. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/context.py +0 -0
  222. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/events.py +0 -0
  223. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/executor/__init__.py +0 -0
  224. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/executor/guards.py +0 -0
  225. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/executor/helpers.py +0 -0
  226. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/executor/invoke.py +0 -0
  227. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/kernel.py +0 -0
  228. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/labels.py +0 -0
  229. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/opview.py +0 -0
  230. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/ordering.py +0 -0
  231. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/status/__init__.py +0 -0
  232. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/status/converters.py +0 -0
  233. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/status/exceptions.py +0 -0
  234. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/status/mappings.py +0 -0
  235. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/status/utils.py +0 -0
  236. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/system.py +0 -0
  237. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/runtime/trace.py +0 -0
  238. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/schema/__init__.py +0 -0
  239. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/schema/_schema.py +0 -0
  240. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/schema/builder/__init__.py +0 -0
  241. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/schema/builder/build_schema.py +0 -0
  242. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/schema/builder/cache.py +0 -0
  243. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/schema/builder/compat.py +0 -0
  244. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/schema/builder/extras.py +0 -0
  245. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/schema/builder/helpers.py +0 -0
  246. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/schema/builder/list_params.py +0 -0
  247. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/schema/builder/strip_parent_fields.py +0 -0
  248. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/schema/collect.py +0 -0
  249. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/schema/decorators.py +0 -0
  250. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/schema/get_schema.py +0 -0
  251. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/schema/schema_spec.py +0 -0
  252. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/schema/shortcuts.py +0 -0
  253. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/schema/types.py +0 -0
  254. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/schema/utils.py +0 -0
  255. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/security/__init__.py +0 -0
  256. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/security/dependencies.py +0 -0
  257. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/security/schemes/__init__.py +0 -0
  258. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/security/schemes/_base.py +0 -0
  259. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/security/schemes/mutual_tls.py +0 -0
  260. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/security/schemes/oauth2.py +0 -0
  261. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/security/schemes/openid_connect.py +0 -0
  262. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/session/README.md +0 -0
  263. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/session/__init__.py +0 -0
  264. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/session/abc.py +0 -0
  265. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/session/base.py +0 -0
  266. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/session/decorators.py +0 -0
  267. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/session/default.py +0 -0
  268. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/session/shortcuts.py +0 -0
  269. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/session/spec.py +0 -0
  270. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/shortcuts.py +0 -0
  271. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/specs.py +0 -0
  272. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/system/__init__.py +0 -0
  273. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/system/diagnostics/__init__.py +0 -0
  274. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/system/diagnostics/healthz.py +0 -0
  275. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/system/diagnostics/hookz.py +0 -0
  276. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/system/diagnostics/kernelz.py +0 -0
  277. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/system/diagnostics/methodz.py +0 -0
  278. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/system/diagnostics/router.py +0 -0
  279. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/system/diagnostics/utils.py +0 -0
  280. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/system/docs/__init__.py +0 -0
  281. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/system/docs/openapi/__init__.py +0 -0
  282. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/system/docs/openapi/helpers.py +0 -0
  283. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/system/docs/openapi/metadata.py +0 -0
  284. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/system/docs/openapi/schema.py +0 -0
  285. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/system/favicon/assets/favicon.svg +0 -0
  286. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/system/uvicorn.py +0 -0
  287. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/table/__init__.py +0 -0
  288. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/table/_table.py +0 -0
  289. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/table/mro_collect.py +0 -0
  290. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/table/shortcuts.py +0 -0
  291. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/transport/__init__.py +0 -0
  292. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/transport/background.py +0 -0
  293. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/transport/httpx.py +0 -0
  294. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/transport/jsonrpc/__init__.py +0 -0
  295. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/transport/jsonrpc/helpers.py +0 -0
  296. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/transport/jsonrpc/models.py +0 -0
  297. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/transport/jsonrpc/openrpc.py +0 -0
  298. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/transport/rest/__init__.py +0 -0
  299. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/transport/rest/aggregator.py +0 -0
  300. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/transport/rest/decorators.py +0 -0
  301. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/types/allow_anon_provider.py +0 -0
  302. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/types/nested_path_provider.py +0 -0
  303. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/types/op.py +0 -0
  304. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/types/op_config_provider.py +0 -0
  305. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/types/op_verb_alias_provider.py +0 -0
  306. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/types/request_extras_provider.py +0 -0
  307. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/types/response_extras_provider.py +0 -0
  308. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/types/table_config_provider.py +0 -0
  309. {tigrbl-0.3.6.dev1 → tigrbl-0.3.7}/tigrbl/types/uuid.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tigrbl
3
- Version: 0.3.6.dev1
3
+ Version: 0.3.7
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tigrbl"
3
- version = "0.3.6.dev1"
3
+ version = "0.3.7"
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"
@@ -43,8 +43,8 @@ from .op import alias_ctx, op_ctx, alias, op_alias
43
43
  from .hook import hook_ctx
44
44
  from .engine.decorators import engine_ctx
45
45
  from .schema.decorators import schema_ctx
46
- from .response.decorators import response_ctx
47
- from .response.types import ResponseSpec
46
+ from .responses.decorators import response_ctx
47
+ from .responses.types import ResponseSpec
48
48
 
49
49
  # ── Bindings (model + API orchestration) ───────────────────────────────────────
50
50
  from .bindings import (
@@ -37,7 +37,7 @@ from tigrbl.transport.httpx import ensure_httpx_sync_transport
37
37
  from ._route import Route
38
38
  from ..system.docs.openapi import build_openapi, mount_openapi
39
39
  from ..system.docs.swagger import mount_swagger
40
- from ..transport.request import Request
40
+ from ..requests import Request
41
41
  from ..transport.rest.decorators import (
42
42
  delete as rest_delete,
43
43
  get as rest_get,
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  from dataclasses import dataclass, field
4
4
  from typing import Any, Callable, Optional, Sequence
5
5
  from ..engine.engine_spec import EngineCfg
6
- from ..response.types import ResponseSpec
6
+ from ..responses.types import ResponseSpec
7
7
 
8
8
 
9
9
  @dataclass
@@ -4,7 +4,7 @@ from dataclasses import dataclass, field
4
4
  from typing import Any, Callable, Optional, Sequence
5
5
 
6
6
  from ..engine.engine_spec import EngineCfg
7
- from ..response.types import ResponseSpec
7
+ from ..responses.types import ResponseSpec
8
8
 
9
9
 
10
10
  @dataclass(eq=False)
@@ -106,7 +106,8 @@ class TigrblApp(_App):
106
106
  self.middlewares = tuple(getattr(self, "MIDDLEWARES", ()))
107
107
  self._favicon_path = favicon_path
108
108
  for mw in self.middlewares:
109
- self.add_middleware(mw.__class__, **getattr(mw, "kwargs", {}))
109
+ mw_cls = getattr(mw, "cls", mw.__class__)
110
+ self.add_middleware(mw_cls, **getattr(mw, "kwargs", {}))
110
111
  self._install_favicon()
111
112
  # capture initial routes so refreshes retain ASGI defaults
112
113
  self._base_routes = list(self.router.routes)
@@ -46,7 +46,7 @@ from .hooks import normalize_and_attach as build_hooks
46
46
  from .handlers import build_and_attach as build_handlers
47
47
  from .rpc import register_and_attach as register_rpc
48
48
  from .rest import build_router_and_attach as build_rest
49
- from ..response.bind import bind as bind_response
49
+ from ..responses.bind import bind as bind_response
50
50
 
51
51
  # API facade integration
52
52
  from .api import include_model, include_models, rpc_call
@@ -13,11 +13,11 @@ from pydantic import BaseModel
13
13
 
14
14
  from ...api._api import APIRouter as Router
15
15
  from ...core.crud.params import Body, Path, Query
16
- from ...response.stdapi import Response
16
+ from ...responses import Response
17
17
  from ...runtime.status.exceptions import HTTPException
18
18
  from ...runtime.status.mappings import status as _status
19
19
  from ...security.dependencies import Depends, Security
20
- from ...transport.request import Request
20
+ from ...requests import Request
21
21
  from .helpers import (
22
22
  _Key,
23
23
  _coerce_parent_kw,
@@ -1,9 +1,9 @@
1
1
  """Deprecated compatibility module for REST ASGI-style primitives.
2
2
 
3
3
  Prefer importing directly from:
4
- - ``tigrbl.response`` for response classes
4
+ - ``tigrbl.responses`` for response classes
5
5
  - ``tigrbl.runtime.status`` for ``status`` and ``HTTPException``
6
- - ``tigrbl.api._api`` / ``tigrbl.transport.request`` / ``tigrbl.security.dependencies``
6
+ - ``tigrbl.api._api`` / ``tigrbl.requests`` / ``tigrbl.security.dependencies``
7
7
  """
8
8
 
9
9
  from __future__ import annotations
@@ -21,11 +21,11 @@ from ...response import (
21
21
  )
22
22
  from ...runtime.status import HTTPException, status
23
23
  from ...security.dependencies import Depends, Security
24
- from ...transport.request import Request
24
+ from ...requests import Request
25
25
 
26
26
  warnings.warn(
27
27
  "tigrbl.bindings.rest.asgi is deprecated; import from "
28
- "tigrbl.response, tigrbl.runtime.status, and concrete modules instead.",
28
+ "tigrbl.responses, tigrbl.runtime.status, and concrete modules instead.",
29
29
  DeprecationWarning,
30
30
  stacklevel=2,
31
31
  )
@@ -4,7 +4,7 @@ import logging
4
4
  from types import SimpleNamespace
5
5
  from typing import Any, Awaitable, Callable, Dict, Mapping, Sequence, Tuple
6
6
 
7
- from ...transport.request import Request
7
+ from ...requests import Request
8
8
  from ...op.types import PHASES
9
9
 
10
10
  try:
@@ -12,7 +12,7 @@ from pydantic import BaseModel, Field, create_model
12
12
  from ...core.crud.params import Query
13
13
  from ...runtime.status.exceptions import HTTPException
14
14
  from ...runtime.status.mappings import status as _status
15
- from ...transport.request import Request
15
+ from ...requests import Request
16
16
  from .helpers import _ensure_jsonable
17
17
  from ...op import OpSpec
18
18
 
@@ -9,7 +9,7 @@ from typing import Any, Dict, Optional, Sequence, Tuple
9
9
  from ...runtime.status.exceptions import HTTPException
10
10
  from ...runtime.status.mappings import status as _status
11
11
  from ...security.dependencies import Depends, Security
12
- from ...transport.request import Request
12
+ from ...requests import Request
13
13
  from ...op import OpSpec
14
14
  from ...security import HTTPBearer
15
15
  from ...op.types import CANON
@@ -7,7 +7,7 @@ from typing import Annotated, Any, Iterable, get_args, get_origin
7
7
  from ..core.crud.params import Param
8
8
  from ..runtime.status.exceptions import HTTPException
9
9
  from ..runtime.status.mappings import status
10
- from ..transport.request import Request
10
+ from ..requests import Request
11
11
 
12
12
 
13
13
  def split_annotated(annotation: Any) -> tuple[Any, tuple[Any, ...]]:
@@ -10,10 +10,10 @@ from ..api.resolve import (
10
10
  resolve_handler_kwargs,
11
11
  resolve_route_dependencies,
12
12
  )
13
- from ..response.stdapi import Response
13
+ from ..responses import Response
14
14
  from ..runtime.status.exceptions import HTTPException
15
15
  from ..runtime.status.mappings import status
16
- from ..transport.request import Request
16
+ from ..requests import Request
17
17
 
18
18
 
19
19
  def _is_http_response_like(obj: Any) -> bool:
@@ -0,0 +1,3 @@
1
+ from ._header import HeaderCookies, Headers
2
+
3
+ __all__ = ["Headers", "HeaderCookies"]
@@ -0,0 +1,89 @@
1
+ """Shared case-insensitive HTTP header mapping primitives."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Iterable, Mapping, MutableMapping
6
+ from http.cookies import SimpleCookie
7
+
8
+
9
+ class HeaderCookies(dict[str, str]):
10
+ """Dot-addressable cookie mapping parsed from a Cookie header value."""
11
+
12
+ def __getattr__(self, name: str) -> str:
13
+ try:
14
+ return self[name]
15
+ except KeyError as exc: # pragma: no cover - defensive
16
+ raise AttributeError(name) from exc
17
+
18
+
19
+ class Headers(MutableMapping[str, str]):
20
+ """Case-insensitive header mapping for request/response objects."""
21
+
22
+ def __init__(
23
+ self,
24
+ values: Iterable[tuple[str, str]] | Mapping[str, str] | None = None,
25
+ ) -> None:
26
+ self._data: dict[str, tuple[str, str]] = {}
27
+ if values is None:
28
+ return
29
+ items = values.items() if hasattr(values, "items") else values
30
+ for key, value in items:
31
+ lower = key.lower()
32
+ self._data[lower] = (lower, str(value))
33
+
34
+ @staticmethod
35
+ def _attribute_key(name: str) -> str:
36
+ return name.replace("_", "-").lower()
37
+
38
+ @staticmethod
39
+ def _parse_cookie_header(value: str) -> HeaderCookies:
40
+ parsed = SimpleCookie()
41
+ parsed.load(value)
42
+ return HeaderCookies({name: morsel.value for name, morsel in parsed.items()})
43
+
44
+ def __getitem__(self, key: str) -> str:
45
+ return self._data[key.lower()][1]
46
+
47
+ def __setitem__(self, key: str, value: str) -> None:
48
+ lower = key.lower()
49
+ self._data[lower] = (lower, str(value))
50
+
51
+ def __delitem__(self, key: str) -> None:
52
+ del self._data[key.lower()]
53
+
54
+ def __iter__(self):
55
+ for original, _ in self._data.values():
56
+ yield original
57
+
58
+ def __len__(self) -> int:
59
+ return len(self._data)
60
+
61
+ def items(self):
62
+ return ((k, v) for k, v in self._data.values())
63
+
64
+ def as_list(self) -> list[tuple[str, str]]:
65
+ return list(self.items())
66
+
67
+ def get(self, key: str, default: str | None = None) -> str | None:
68
+ item = self._data.get(key.lower())
69
+ if item is None:
70
+ return default
71
+ return item[1]
72
+
73
+ def __getattr__(self, name: str) -> str | HeaderCookies:
74
+ key = self._attribute_key(name)
75
+ if key not in self._data:
76
+ raise AttributeError(name)
77
+ value = self._data[key][1]
78
+ if key == "cookie":
79
+ return self._parse_cookie_header(value)
80
+ return value
81
+
82
+ def __setattr__(self, name: str, value: str) -> None:
83
+ if name.startswith("_"):
84
+ object.__setattr__(self, name, value)
85
+ return
86
+ self[self._attribute_key(name)] = value
87
+
88
+
89
+ __all__ = ["Headers", "HeaderCookies"]
@@ -0,0 +1,27 @@
1
+ from .spec import (
2
+ ASGIApp,
3
+ ASGIReceive,
4
+ ASGISend,
5
+ MiddlewareSpec,
6
+ WSGIApp,
7
+ WSGIStartResponse,
8
+ )
9
+ from .middleware import Middleware
10
+ from .decorators import MiddlewareConfig, middleware, middlewares
11
+ from .compose import apply_middlewares
12
+ from .cors import CORSMiddleware
13
+
14
+ __all__ = [
15
+ "ASGIApp",
16
+ "ASGIReceive",
17
+ "ASGISend",
18
+ "WSGIApp",
19
+ "WSGIStartResponse",
20
+ "MiddlewareSpec",
21
+ "Middleware",
22
+ "MiddlewareConfig",
23
+ "middleware",
24
+ "middlewares",
25
+ "apply_middlewares",
26
+ "CORSMiddleware",
27
+ ]
@@ -0,0 +1,17 @@
1
+ """Helpers for composing ASGI/WSGI middleware stacks."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+
8
+ def apply_middlewares(
9
+ app: Any, middleware_stack: list[tuple[Any, dict[str, Any]]]
10
+ ) -> Any:
11
+ wrapped = app
12
+ for middleware_class, options in reversed(middleware_stack):
13
+ wrapped = middleware_class(wrapped, **(options or {}))
14
+ return wrapped
15
+
16
+
17
+ __all__ = ["apply_middlewares"]
@@ -0,0 +1,123 @@
1
+ """CORS middleware for ASGI/WSGI adapters."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from tigrbl.headers import Headers
8
+
9
+ from .middleware import Middleware
10
+ from .spec import ASGIReceive, ASGISend, WSGIStartResponse
11
+
12
+
13
+ class CORSMiddleware(Middleware):
14
+ def __init__(
15
+ self,
16
+ app,
17
+ *,
18
+ allow_origin: str = "*",
19
+ allow_methods: str = "GET,POST,PUT,PATCH,DELETE,OPTIONS",
20
+ allow_headers: str = "*",
21
+ allow_credentials: bool = False,
22
+ max_age: int = 600,
23
+ ) -> None:
24
+ super().__init__(
25
+ app,
26
+ allow_origin=allow_origin,
27
+ allow_methods=allow_methods,
28
+ allow_headers=allow_headers,
29
+ allow_credentials=allow_credentials,
30
+ max_age=max_age,
31
+ )
32
+ self.allow_origin = allow_origin
33
+ self.allow_methods = allow_methods
34
+ self.allow_headers = allow_headers
35
+ self.allow_credentials = allow_credentials
36
+ self.max_age = max_age
37
+
38
+ def _cors_headers(self) -> list[tuple[str, str]]:
39
+ headers = [
40
+ ("access-control-allow-origin", self.allow_origin),
41
+ ("access-control-allow-methods", self.allow_methods),
42
+ ("access-control-allow-headers", self.allow_headers),
43
+ ("access-control-max-age", str(self.max_age)),
44
+ ]
45
+ if self.allow_credentials:
46
+ headers.append(("access-control-allow-credentials", "true"))
47
+ return headers
48
+
49
+ async def asgi(
50
+ self,
51
+ scope: dict[str, Any],
52
+ receive: ASGIReceive,
53
+ send: ASGISend,
54
+ ) -> None:
55
+ if scope.get("type") != "http":
56
+ await self.app(scope, receive, send)
57
+ return
58
+
59
+ request_headers = Headers(
60
+ [
61
+ (k.decode("latin-1"), v.decode("latin-1"))
62
+ for k, v in scope.get("headers", [])
63
+ ]
64
+ )
65
+ is_preflight = (
66
+ (scope.get("method") or "").upper() == "OPTIONS"
67
+ and request_headers.get("origin") is not None
68
+ and request_headers.get("access-control-request-method") is not None
69
+ )
70
+ if is_preflight:
71
+ await send(
72
+ {
73
+ "type": "http.response.start",
74
+ "status": 204,
75
+ "headers": [
76
+ (k.encode("latin-1"), v.encode("latin-1"))
77
+ for k, v in self._cors_headers()
78
+ ],
79
+ }
80
+ )
81
+ await send({"type": "http.response.body", "body": b""})
82
+ return
83
+
84
+ async def send_with_cors(message: dict[str, Any]) -> None:
85
+ if message.get("type") == "http.response.start":
86
+ headers = list(message.get("headers", []))
87
+ headers.extend(
88
+ [
89
+ (k.encode("latin-1"), v.encode("latin-1"))
90
+ for k, v in self._cors_headers()
91
+ ]
92
+ )
93
+ message = {**message, "headers": headers}
94
+ await send(message)
95
+
96
+ await self.app(scope, receive, send_with_cors)
97
+
98
+ def wsgi(
99
+ self,
100
+ environ: dict[str, Any],
101
+ start_response: WSGIStartResponse,
102
+ ) -> list[bytes]:
103
+ method = (environ.get("REQUEST_METHOD") or "").upper()
104
+ is_preflight = (
105
+ method == "OPTIONS"
106
+ and environ.get("HTTP_ORIGIN")
107
+ and environ.get("HTTP_ACCESS_CONTROL_REQUEST_METHOD")
108
+ )
109
+
110
+ if is_preflight:
111
+ start_response("204 No Content", self._cors_headers())
112
+ return [b""]
113
+
114
+ def cors_start_response(
115
+ status: str, headers: list[tuple[str, str]], *args: Any
116
+ ):
117
+ merged = list(headers) + self._cors_headers()
118
+ return start_response(status, merged, *args)
119
+
120
+ return self.app(environ, cors_start_response)
121
+
122
+
123
+ __all__ = ["CORSMiddleware"]
@@ -0,0 +1,32 @@
1
+ """Decorators for attaching middleware specs to apps/apis."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import Any
7
+
8
+
9
+ @dataclass(frozen=True)
10
+ class MiddlewareConfig:
11
+ cls: Any
12
+ kwargs: dict[str, Any]
13
+
14
+
15
+ def middleware(middleware_class: Any, /, **kwargs: Any) -> MiddlewareConfig:
16
+ """Build declarative middleware config objects for ``MIDDLEWARES``."""
17
+
18
+ return MiddlewareConfig(cls=middleware_class, kwargs=kwargs)
19
+
20
+
21
+ def middlewares(*configs: MiddlewareConfig):
22
+ """Attach middleware configs to class-level ``MIDDLEWARES``."""
23
+
24
+ def _decorator(target: Any) -> Any:
25
+ current = tuple(getattr(target, "MIDDLEWARES", ()))
26
+ setattr(target, "MIDDLEWARES", current + tuple(configs))
27
+ return target
28
+
29
+ return _decorator
30
+
31
+
32
+ __all__ = ["MiddlewareConfig", "middleware", "middlewares"]
@@ -0,0 +1,37 @@
1
+ """Base middleware implementation supporting ASGI and WSGI."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from .spec import ASGIApp, ASGIReceive, ASGISend, WSGIApp, WSGIStartResponse
8
+
9
+
10
+ class Middleware:
11
+ """Base middleware for composing ASGI/WSGI pipelines."""
12
+
13
+ def __init__(self, app: ASGIApp | WSGIApp, **kwargs: Any) -> None:
14
+ self.app = app
15
+ self.kwargs = kwargs
16
+
17
+ async def asgi(
18
+ self,
19
+ scope: dict[str, Any],
20
+ receive: ASGIReceive,
21
+ send: ASGISend,
22
+ ) -> None:
23
+ await self.app(scope, receive, send)
24
+
25
+ def wsgi(
26
+ self,
27
+ environ: dict[str, Any],
28
+ start_response: WSGIStartResponse,
29
+ ) -> list[bytes]:
30
+ return self.app(environ, start_response)
31
+
32
+ def __call__(self, *args: Any, **kwargs: Any):
33
+ if len(args) == 3 and isinstance(args[0], dict):
34
+ return self.asgi(args[0], args[1], args[2])
35
+ if len(args) == 2 and isinstance(args[0], dict):
36
+ return self.wsgi(args[0], args[1])
37
+ raise TypeError("Invalid middleware invocation")
@@ -0,0 +1,26 @@
1
+ """Middleware protocol and callable type specs."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Awaitable, Callable
6
+ from typing import Any, Protocol
7
+
8
+ ASGIReceive = Callable[[], Awaitable[dict[str, Any]]]
9
+ ASGISend = Callable[[dict[str, Any]], Awaitable[None]]
10
+ ASGIApp = Callable[[dict[str, Any], ASGIReceive, ASGISend], Awaitable[None]]
11
+ WSGIStartResponse = Callable[..., Any]
12
+ WSGIApp = Callable[[dict[str, Any], WSGIStartResponse], list[bytes]]
13
+
14
+
15
+ class MiddlewareSpec(Protocol):
16
+ """Protocol for middleware classes compatible with ASGI and WSGI."""
17
+
18
+ kwargs: dict[str, Any]
19
+
20
+ async def asgi(
21
+ self, scope: dict[str, Any], receive: ASGIReceive, send: ASGISend
22
+ ) -> None: ...
23
+
24
+ def wsgi(
25
+ self, environ: dict[str, Any], start_response: WSGIStartResponse
26
+ ) -> list[bytes]: ...
@@ -8,7 +8,7 @@ from typing import Any, Literal, Mapping, Optional, Tuple, cast
8
8
  from ..config.constants import CANON as CANONICAL_VERB_TUPLE
9
9
  from ..hook.types import PHASE, HookPhase, PHASES, Ctx, StepFn, HookPredicate
10
10
  from ..hook import HookSpec as OpHook
11
- from ..response.types import ResponseSpec
11
+ from ..responses.types import ResponseSpec
12
12
  from ..engine.engine_spec import EngineCfg
13
13
  from typing import TYPE_CHECKING
14
14
 
@@ -0,0 +1,5 @@
1
+ from tigrbl.headers import Headers
2
+
3
+ from ._request import AwaitableValue, Request, URL
4
+
5
+ __all__ = ["Headers", "Request", "AwaitableValue", "URL"]