tigrbl-concrete 0.4.5.dev1__tar.gz → 0.4.5.dev6__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 (149) hide show
  1. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/PKG-INFO +8 -8
  2. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/README.md +5 -5
  3. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/pyproject.toml +4 -3
  4. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/__init__.py +14 -0
  5. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/__init__.py +3 -2
  6. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_app.py +171 -38
  7. tigrbl_concrete-0.4.5.dev6/tigrbl_concrete/_concrete/_column.py +31 -0
  8. tigrbl_concrete-0.4.5.dev1/tigrbl_concrete/_concrete/_session.py → tigrbl_concrete-0.4.5.dev6/tigrbl_concrete/_concrete/_engine_session.py +36 -20
  9. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_op.py +7 -0
  10. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_route.py +176 -105
  11. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_router.py +72 -4
  12. tigrbl_concrete-0.4.5.dev6/tigrbl_concrete/_concrete/_session.py +17 -0
  13. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_table.py +57 -22
  14. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/tigrbl_app.py +32 -13
  15. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_decorators/op.py +121 -6
  16. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_decorators/session.py +6 -6
  17. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_mapping/appspec/path_lowering.py +97 -0
  18. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_mapping/model.py +125 -6
  19. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_mapping/router/rpc.py +2 -35
  20. tigrbl_concrete-0.4.5.dev6/tigrbl_concrete/_runtime_services.py +11 -0
  21. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/ddl/__init__.py +26 -11
  22. tigrbl_concrete-0.4.5.dev6/tigrbl_concrete/factories/__init__.py +28 -0
  23. tigrbl_concrete-0.4.5.dev6/tigrbl_concrete/factories/activation.py +66 -0
  24. tigrbl_concrete-0.4.5.dev6/tigrbl_concrete/factories/column.py +98 -0
  25. tigrbl_concrete-0.4.5.dev6/tigrbl_concrete/factories/op.py +95 -0
  26. tigrbl_concrete-0.4.5.dev6/tigrbl_concrete/factories/router.py +52 -0
  27. tigrbl_concrete-0.4.5.dev6/tigrbl_concrete/factories/table.py +136 -0
  28. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/factories/webhook.py +4 -2
  29. tigrbl_concrete-0.4.5.dev6/tigrbl_concrete/records.py +218 -0
  30. tigrbl_concrete-0.4.5.dev6/tigrbl_concrete/shortcuts/webhook.py +3 -0
  31. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/docs/openapi/helpers.py +58 -3
  32. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/docs/openapi/schema.py +33 -19
  33. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/docs/openrpc.py +12 -6
  34. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/docs/runtime_ops.py +49 -18
  35. tigrbl_concrete-0.4.5.dev1/tigrbl_concrete/_concrete/_column.py +0 -10
  36. tigrbl_concrete-0.4.5.dev1/tigrbl_concrete/_mapping/rpc.py +0 -11
  37. tigrbl_concrete-0.4.5.dev1/tigrbl_concrete/factories/__init__.py +0 -4
  38. tigrbl_concrete-0.4.5.dev1/tigrbl_concrete/shortcuts/webhook.py +0 -13
  39. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/LICENSE +0 -0
  40. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/NOTICE +0 -0
  41. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_alias.py +0 -0
  42. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_allow_anon.py +0 -0
  43. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_background.py +0 -0
  44. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_binding.py +0 -0
  45. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_body.py +0 -0
  46. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_cors_middleware.py +0 -0
  47. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_engine.py +0 -0
  48. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_event_stream_response.py +0 -0
  49. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_execution_backend.py +0 -0
  50. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_file_response.py +0 -0
  51. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_headers.py +0 -0
  52. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_hook.py +0 -0
  53. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_html_response.py +0 -0
  54. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_httpx.py +0 -0
  55. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_json_response.py +0 -0
  56. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_middleware.py +0 -0
  57. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_op_registry.py +0 -0
  58. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_plain_text_response.py +0 -0
  59. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_redirect_response.py +0 -0
  60. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_request.py +0 -0
  61. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_request_adapters.py +0 -0
  62. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_response.py +0 -0
  63. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_schema.py +0 -0
  64. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_security/__init__.py +0 -0
  65. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_security/api_key.py +0 -0
  66. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_security/http_basic.py +0 -0
  67. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_security/http_bearer.py +0 -0
  68. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_security/mutual_tls.py +0 -0
  69. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_security/oauth2.py +0 -0
  70. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_security/openid_connect.py +0 -0
  71. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_storage.py +0 -0
  72. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_streaming_response.py +0 -0
  73. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_table_registry.py +0 -0
  74. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_webhook.py +0 -0
  75. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/_websocket.py +0 -0
  76. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/dependencies.py +0 -0
  77. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/engine_resolver.py +0 -0
  78. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_concrete/tigrbl_router.py +0 -0
  79. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_decorators/__init__.py +0 -0
  80. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_decorators/allow_anon.py +0 -0
  81. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_decorators/engine.py +0 -0
  82. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_decorators/eventful.py +0 -0
  83. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_decorators/hook.py +0 -0
  84. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_decorators/middlewares.py +0 -0
  85. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_decorators/response.py +0 -0
  86. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_decorators/rest.py +0 -0
  87. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_decorators/schema.py +0 -0
  88. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_decorators/webhook.py +0 -0
  89. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_mapping/__init__.py +0 -0
  90. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_mapping/appspec/__init__.py +0 -0
  91. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_mapping/appspec/docs_lowering.py +0 -0
  92. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_mapping/appspec/engine_lowering.py +0 -0
  93. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_mapping/column_mro_collect.py +0 -0
  94. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_mapping/core_resolver.py +0 -0
  95. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_mapping/invoke.py +0 -0
  96. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_mapping/model_helpers.py +0 -0
  97. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_mapping/op_resolver.py +0 -0
  98. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_mapping/router/__init__.py +0 -0
  99. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_mapping/router/common.py +0 -0
  100. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_mapping/router/include.py +0 -0
  101. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/_mapping/router/resource_proxy.py +0 -0
  102. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/decorators.py +0 -0
  103. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/engine/__init__.py +0 -0
  104. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/engine/bind.py +0 -0
  105. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/engine/builders.py +0 -0
  106. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/engine/capabilities.py +0 -0
  107. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/engine/collect.py +0 -0
  108. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/engine/plugins.py +0 -0
  109. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/engine/registry.py +0 -0
  110. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/engine/resolver.py +0 -0
  111. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/factories/app.py +0 -0
  112. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/resolve/__init__.py +0 -0
  113. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/resolve/handlers.py +0 -0
  114. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/schema/__init__.py +0 -0
  115. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/schema/jsonrpc.py +0 -0
  116. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/security/__init__.py +0 -0
  117. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/security/dependencies.py +0 -0
  118. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/shortcuts/__init__.py +0 -0
  119. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/shortcuts/app.py +0 -0
  120. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/shortcuts/rest.py +0 -0
  121. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/__init__.py +0 -0
  122. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/diagnostics/__init__.py +0 -0
  123. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/diagnostics/healthz.py +0 -0
  124. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/diagnostics/hookz.py +0 -0
  125. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/diagnostics/kernelz.py +0 -0
  126. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/diagnostics/methodz.py +0 -0
  127. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/diagnostics/router.py +0 -0
  128. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/diagnostics/utils.py +0 -0
  129. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/docs/__init__.py +0 -0
  130. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/docs/json_schema.py +0 -0
  131. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/docs/lens.py +0 -0
  132. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/docs/openapi/__init__.py +0 -0
  133. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/docs/openapi/metadata.py +0 -0
  134. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/docs/openapi/mount.py +0 -0
  135. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/docs/surface.py +0 -0
  136. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/docs/swagger.py +0 -0
  137. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/favicon/__init__.py +0 -0
  138. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/favicon/assets/favicon.svg +0 -0
  139. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/static.py +0 -0
  140. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/uvicorn.py +0 -0
  141. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/system/well_known.py +0 -0
  142. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/transport/__init__.py +0 -0
  143. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/transport/_deprecation.py +0 -0
  144. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/transport/jsonrpc/__init__.py +0 -0
  145. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/transport/jsonrpc/helpers.py +0 -0
  146. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/transport/jsonrpc/models.py +0 -0
  147. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/transport/rest/__init__.py +0 -0
  148. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/transport/rest/aggregator.py +0 -0
  149. {tigrbl_concrete-0.4.5.dev1 → tigrbl_concrete-0.4.5.dev6}/tigrbl_concrete/webhooks.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tigrbl-concrete
3
- Version: 0.4.5.dev1
3
+ Version: 0.4.5.dev6
4
4
  Summary: Concrete Tigrbl implementations for reusable framework behavior, sessions, routes, responses, and base abstraction adapters.
5
5
  License: Apache License
6
6
  Version 2.0, January 2004
@@ -235,14 +235,14 @@ Requires-Dist: tigrbl-ops-olap
235
235
  Requires-Dist: tigrbl-ops-oltp
236
236
  Requires-Dist: tigrbl-ops-realtime
237
237
  Requires-Dist: tigrbl-ops-webtransport
238
- Requires-Dist: tigrbl-runtime
238
+ Requires-Dist: tigrbl-runtime (>=0.4.5.dev5)
239
239
  Requires-Dist: tigrbl-typing
240
240
  Requires-Dist: uvicorn
241
241
  Project-URL: Discord, https://discord.gg/K4YTAPapjR
242
242
  Project-URL: Homepage, https://github.com/tigrbl/tigrbl
243
243
  Project-URL: Issues, https://github.com/tigrbl/tigrbl/issues
244
244
  Project-URL: Organization, https://github.com/tigrbl
245
- Project-URL: Repository, https://github.com/tigrbl/tigrbl/tree/master/pkgs/core/tigrbl_concrete
245
+ Project-URL: Repository, https://github.com/tigrbl/tigrbl/tree/master/pkgs/70_concrete/tigrbl_concrete
246
246
  Description-Content-Type: text/markdown
247
247
 
248
248
  <div align="center">
@@ -252,7 +252,7 @@ Description-Content-Type: text/markdown
252
252
  <a href="https://pypi.org/project/tigrbl-concrete/"><img src="https://img.shields.io/pypi/v/tigrbl-concrete?label=PyPI" alt="PyPI version for tigrbl-concrete"/></a>
253
253
  <a href="https://pypi.org/project/tigrbl-concrete/"><img src="https://static.pepy.tech/badge/tigrbl-concrete" alt="Downloads for tigrbl-concrete"/></a>
254
254
  <a href="https://discord.gg/K4YTAPapjR"><img src="https://img.shields.io/badge/Discord-Join%20chat-5865F2?logo=discord&logoColor=white" alt="Discord community for tigrbl-concrete"/></a>
255
- <a href="https://github.com/tigrbl/tigrbl/blob/master/pkgs/core/tigrbl_concrete/README.md"><img src="https://hits.sh/github.com/tigrbl/tigrbl/blob/master/pkgs/core/tigrbl_concrete/README.md.svg?label=hits" alt="Repository hits for tigrbl-concrete README"/></a>
255
+ <a href="https://github.com/tigrbl/tigrbl/blob/master/pkgs/70_concrete/tigrbl_concrete/README.md"><img src="https://hits.sh/github.com/tigrbl/tigrbl/blob/master/pkgs/70_concrete/tigrbl_concrete/README.md.svg?label=hits" alt="Repository hits for tigrbl-concrete README"/></a>
256
256
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-525252" alt="Apache 2.0 license"/></a>
257
257
  <a href="pyproject.toml"><img src="https://img.shields.io/badge/python-3.10%2C%203.11%2C%203.12%2C%203.13%2C%203.14-3776ab" alt="Python versions 3.10 | 3.11 | 3.12 | 3.13 | 3.14 for tigrbl-concrete"/></a>
258
258
  <a href="https://github.com/tigrbl/tigrbl/blob/master/docs/README.md"><img src="https://img.shields.io/badge/workspace-core-1f6feb" alt="Workspace group for tigrbl-concrete"/></a>
@@ -276,7 +276,7 @@ Framework maintainers, extension authors, and advanced users composing Tigrbl fr
276
276
 
277
277
  ## Where does tigrbl-concrete fit?
278
278
 
279
- `tigrbl-concrete` lives at `pkgs/core/tigrbl_concrete` and serves a focused layer in the split Tigrbl framework.
279
+ `tigrbl-concrete` lives at `pkgs/70_concrete/tigrbl_concrete` and serves a focused layer in the split Tigrbl framework.
280
280
 
281
281
  ## How does tigrbl-concrete work?
282
282
 
@@ -298,7 +298,7 @@ pip install tigrbl-concrete
298
298
  | Surface | Value |
299
299
  |---|---|
300
300
  | PyPI package | [`tigrbl-concrete`](https://pypi.org/project/tigrbl-concrete/) |
301
- | Repository path | [`pkgs/core/tigrbl_concrete`](https://github.com/tigrbl/tigrbl/tree/master/pkgs/core/tigrbl_concrete) |
301
+ | Repository path | [`pkgs/70_concrete/tigrbl_concrete`](https://github.com/tigrbl/tigrbl/tree/master/pkgs/70_concrete/tigrbl_concrete) |
302
302
  | Python import root | `tigrbl_concrete` |
303
303
  | Console scripts | none declared |
304
304
  | Entry points | `tigrbl.engine_plugins` |
@@ -482,7 +482,7 @@ Choose `tigrbl-concrete` when the quick-answer table matches your use case. Choo
482
482
 
483
483
  - Community: [Discord](https://discord.gg/K4YTAPapjR).
484
484
  - Issues: [GitHub Issues](https://github.com/tigrbl/tigrbl/issues).
485
- - Repository: [pkgs/core/tigrbl_concrete](https://github.com/tigrbl/tigrbl/tree/master/pkgs/core/tigrbl_concrete).
485
+ - Repository: [pkgs/70_concrete/tigrbl_concrete](https://github.com/tigrbl/tigrbl/tree/master/pkgs/70_concrete/tigrbl_concrete).
486
486
 
487
487
  ## Package-local Boundary
488
488
 
@@ -493,7 +493,7 @@ This file is a package-local distribution entry point. This README is the packag
493
493
  - Package status: governed package in the `tigrbl/tigrbl` workspace.
494
494
  - Governance source: [SSOT registry](https://github.com/tigrbl/tigrbl/blob/master/.ssot/registry.json).
495
495
  - Release evidence: [publish workflow](https://github.com/tigrbl/tigrbl/actions/workflows/publish.yml) validates package builds, tests, GitHub release assets, and PyPI publication for managed packages.
496
- - Local certification guard: `pkgs/core/tigrbl_tests/tests/unit/test_package_badges_and_notices.py` verifies every package README keeps the Discord badge, Apache 2.0 badge, explicit Python-version badge, `LICENSE`, and `NOTICE`.
496
+ - Local certification guard: `pkgs/97_tests/tigrbl_tests/tests/unit/test_package_badges_and_notices.py` verifies every package README keeps the Discord badge, Apache 2.0 badge, explicit Python-version badge, `LICENSE`, and `NOTICE`.
497
497
  - Scope note: this README documents the package boundary. Runtime feature support remains governed by `.ssot/` entities and the conformance docs linked below.
498
498
 
499
499
  ## License
@@ -5,7 +5,7 @@
5
5
  <a href="https://pypi.org/project/tigrbl-concrete/"><img src="https://img.shields.io/pypi/v/tigrbl-concrete?label=PyPI" alt="PyPI version for tigrbl-concrete"/></a>
6
6
  <a href="https://pypi.org/project/tigrbl-concrete/"><img src="https://static.pepy.tech/badge/tigrbl-concrete" alt="Downloads for tigrbl-concrete"/></a>
7
7
  <a href="https://discord.gg/K4YTAPapjR"><img src="https://img.shields.io/badge/Discord-Join%20chat-5865F2?logo=discord&logoColor=white" alt="Discord community for tigrbl-concrete"/></a>
8
- <a href="https://github.com/tigrbl/tigrbl/blob/master/pkgs/core/tigrbl_concrete/README.md"><img src="https://hits.sh/github.com/tigrbl/tigrbl/blob/master/pkgs/core/tigrbl_concrete/README.md.svg?label=hits" alt="Repository hits for tigrbl-concrete README"/></a>
8
+ <a href="https://github.com/tigrbl/tigrbl/blob/master/pkgs/70_concrete/tigrbl_concrete/README.md"><img src="https://hits.sh/github.com/tigrbl/tigrbl/blob/master/pkgs/70_concrete/tigrbl_concrete/README.md.svg?label=hits" alt="Repository hits for tigrbl-concrete README"/></a>
9
9
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-525252" alt="Apache 2.0 license"/></a>
10
10
  <a href="pyproject.toml"><img src="https://img.shields.io/badge/python-3.10%2C%203.11%2C%203.12%2C%203.13%2C%203.14-3776ab" alt="Python versions 3.10 | 3.11 | 3.12 | 3.13 | 3.14 for tigrbl-concrete"/></a>
11
11
  <a href="https://github.com/tigrbl/tigrbl/blob/master/docs/README.md"><img src="https://img.shields.io/badge/workspace-core-1f6feb" alt="Workspace group for tigrbl-concrete"/></a>
@@ -29,7 +29,7 @@ Framework maintainers, extension authors, and advanced users composing Tigrbl fr
29
29
 
30
30
  ## Where does tigrbl-concrete fit?
31
31
 
32
- `tigrbl-concrete` lives at `pkgs/core/tigrbl_concrete` and serves a focused layer in the split Tigrbl framework.
32
+ `tigrbl-concrete` lives at `pkgs/70_concrete/tigrbl_concrete` and serves a focused layer in the split Tigrbl framework.
33
33
 
34
34
  ## How does tigrbl-concrete work?
35
35
 
@@ -51,7 +51,7 @@ pip install tigrbl-concrete
51
51
  | Surface | Value |
52
52
  |---|---|
53
53
  | PyPI package | [`tigrbl-concrete`](https://pypi.org/project/tigrbl-concrete/) |
54
- | Repository path | [`pkgs/core/tigrbl_concrete`](https://github.com/tigrbl/tigrbl/tree/master/pkgs/core/tigrbl_concrete) |
54
+ | Repository path | [`pkgs/70_concrete/tigrbl_concrete`](https://github.com/tigrbl/tigrbl/tree/master/pkgs/70_concrete/tigrbl_concrete) |
55
55
  | Python import root | `tigrbl_concrete` |
56
56
  | Console scripts | none declared |
57
57
  | Entry points | `tigrbl.engine_plugins` |
@@ -235,7 +235,7 @@ Choose `tigrbl-concrete` when the quick-answer table matches your use case. Choo
235
235
 
236
236
  - Community: [Discord](https://discord.gg/K4YTAPapjR).
237
237
  - Issues: [GitHub Issues](https://github.com/tigrbl/tigrbl/issues).
238
- - Repository: [pkgs/core/tigrbl_concrete](https://github.com/tigrbl/tigrbl/tree/master/pkgs/core/tigrbl_concrete).
238
+ - Repository: [pkgs/70_concrete/tigrbl_concrete](https://github.com/tigrbl/tigrbl/tree/master/pkgs/70_concrete/tigrbl_concrete).
239
239
 
240
240
  ## Package-local Boundary
241
241
 
@@ -246,7 +246,7 @@ This file is a package-local distribution entry point. This README is the packag
246
246
  - Package status: governed package in the `tigrbl/tigrbl` workspace.
247
247
  - Governance source: [SSOT registry](https://github.com/tigrbl/tigrbl/blob/master/.ssot/registry.json).
248
248
  - Release evidence: [publish workflow](https://github.com/tigrbl/tigrbl/actions/workflows/publish.yml) validates package builds, tests, GitHub release assets, and PyPI publication for managed packages.
249
- - Local certification guard: `pkgs/core/tigrbl_tests/tests/unit/test_package_badges_and_notices.py` verifies every package README keeps the Discord badge, Apache 2.0 badge, explicit Python-version badge, `LICENSE`, and `NOTICE`.
249
+ - Local certification guard: `pkgs/97_tests/tigrbl_tests/tests/unit/test_package_badges_and_notices.py` verifies every package README keeps the Discord badge, Apache 2.0 badge, explicit Python-version badge, `LICENSE`, and `NOTICE`.
250
250
  - Scope note: this README documents the package boundary. Runtime feature support remains governed by `.ssot/` entities and the conformance docs linked below.
251
251
 
252
252
  ## License
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tigrbl-concrete"
3
- version = "0.4.5.dev1"
3
+ version = "0.4.5.dev6"
4
4
  description = "Concrete Tigrbl implementations for reusable framework behavior, sessions, routes, responses, and base abstraction adapters."
5
5
  readme = "README.md"
6
6
  license = { file = "LICENSE" }
@@ -51,7 +51,7 @@ dependencies = [
51
51
  "tigrbl-ops-oltp",
52
52
  "tigrbl-ops-realtime",
53
53
  "tigrbl-ops-webtransport",
54
- "tigrbl-runtime",
54
+ "tigrbl-runtime>=0.4.5.dev5",
55
55
  "tigrbl-typing",
56
56
  "uvicorn",
57
57
  ]
@@ -61,7 +61,7 @@ dependencies = [
61
61
  Organization = "https://github.com/tigrbl"
62
62
  Discord = "https://discord.gg/K4YTAPapjR"
63
63
  Homepage = "https://github.com/tigrbl/tigrbl"
64
- Repository = "https://github.com/tigrbl/tigrbl/tree/master/pkgs/core/tigrbl_concrete"
64
+ Repository = "https://github.com/tigrbl/tigrbl/tree/master/pkgs/70_concrete/tigrbl_concrete"
65
65
  Issues = "https://github.com/tigrbl/tigrbl/issues"
66
66
 
67
67
  [tool.uv.sources]
@@ -88,6 +88,7 @@ packages = [
88
88
  [dependency-groups]
89
89
  dev = [
90
90
  "pytest>=8.0",
91
+ "pytest-asyncio>=0.24.0",
91
92
  "ruff>=0.9",
92
93
  ]
93
94
 
@@ -14,16 +14,30 @@ _COMPAT_ALIASES = {
14
14
  'security': 'tigrbl.security',
15
15
  }
16
16
 
17
+ _COLUMN_EXPORTS = {
18
+ 'Column': 'tigrbl_concrete._concrete',
19
+ 'acol': 'tigrbl_concrete.factories.column',
20
+ 'makeColumn': 'tigrbl_concrete.factories.column',
21
+ 'makeVirtualColumn': 'tigrbl_concrete.factories.column',
22
+ 'vcol': 'tigrbl_concrete.factories.column',
23
+ }
24
+
17
25
  __all__ = [
18
26
  'build_handlers',
19
27
  'build_hooks',
20
28
  'build_schemas',
21
29
  'build_rest_router',
30
+ *_COLUMN_EXPORTS,
22
31
  *_COMPAT_ALIASES,
23
32
  ]
24
33
 
25
34
 
26
35
  def __getattr__(name: str) -> Any:
36
+ if name in _COLUMN_EXPORTS:
37
+ module = import_module(_COLUMN_EXPORTS[name])
38
+ value = getattr(module, name)
39
+ globals()[name] = value
40
+ return value
27
41
  if name in _COMPAT_ALIASES:
28
42
  module = import_module(_COMPAT_ALIASES[name])
29
43
  globals()[name] = module
@@ -55,7 +55,8 @@ _EXPORTS = {
55
55
  "PlainTextResponse": "_plain_text_response",
56
56
  "StreamingResponse": "_streaming_response",
57
57
  "EventStreamResponse": "_event_stream_response",
58
- "DefaultSession": "_session",
58
+ "EngineSession": "_engine_session",
59
+ "EngineSession": "_session",
59
60
  "FileResponse": "_file_response",
60
61
  "RedirectResponse": "_redirect_response",
61
62
  "Request": "_request",
@@ -73,7 +74,7 @@ _EXPORTS = {
73
74
  "TigrblApp": "tigrbl_app",
74
75
  "TigrblRouter": "tigrbl_router",
75
76
  "BackgroundTask": "_background",
76
- "wrap_sessionmaker": "_session",
77
+ "wrap_sessionmaker": "_engine_session",
77
78
  "allow_anon": "_allow_anon",
78
79
  "Middleware": "_middleware",
79
80
  "CORSMiddleware": "_cors_middleware",
@@ -1,17 +1,19 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from dataclasses import replace
4
- from typing import Any
4
+ from pathlib import Path
5
+ from typing import Any, Sequence
5
6
 
6
7
  from ._table_registry import TableRegistry
7
- from ._websocket import WebSocket
8
8
  from ._request import Request
9
9
  from tigrbl_base._base import AppBase
10
10
  from tigrbl_concrete.ddl import initialize as _ddl_initialize
11
11
  from ._engine import Engine
12
12
  from tigrbl_concrete._concrete import engine_resolver as _resolver
13
13
  from tigrbl_core._spec.app_spec import AppSpec
14
+ from tigrbl_core._spec.binding_spec import Exchange, TransportBindingSpec
14
15
  from tigrbl_core._spec.engine_spec import EngineCfg
16
+ from tigrbl_core._spec.op_spec import TxScope
15
17
  from ._route import (
16
18
  ROUTE_OPS_MODEL_NAME,
17
19
  add_route as _add_route_impl,
@@ -175,8 +177,67 @@ class App(AppBase):
175
177
  if callable(invalidate):
176
178
  invalidate(self)
177
179
 
178
- def add_route(self, path: str, endpoint: Any, *, methods: list[str] | tuple[str, ...], **kwargs: Any) -> None:
179
- _add_route_impl(self, path, endpoint, methods=methods, **kwargs)
180
+ def add_route(
181
+ self,
182
+ path: str,
183
+ endpoint: Any,
184
+ *,
185
+ methods: Sequence[str],
186
+ name: str | None = None,
187
+ summary: str | None = None,
188
+ description: str | None = None,
189
+ tags: Sequence[str] | None = None,
190
+ deprecated: bool = False,
191
+ request_schema: dict[str, Any] | None = None,
192
+ response_schema: dict[str, Any] | None = None,
193
+ path_param_schemas: dict[str, dict[str, Any]] | None = None,
194
+ query_param_schemas: dict[str, dict[str, Any]] | None = None,
195
+ include_in_schema: bool = True,
196
+ operation_id: str | None = None,
197
+ response_model: Any | None = None,
198
+ request_model: Any | None = None,
199
+ responses: dict[int, dict[str, Any]] | None = None,
200
+ status_code: int | None = None,
201
+ dependencies: list[Any] | None = None,
202
+ security_dependencies: list[Any] | None = None,
203
+ inherit_owner_dependencies: bool = True,
204
+ tigrbl_model: Any | None = None,
205
+ tigrbl_alias: str | None = None,
206
+ tigrbl_binding: TransportBindingSpec | None = None,
207
+ tigrbl_exchange: Exchange | None = None,
208
+ tigrbl_tx_scope: TxScope | None = None,
209
+ tigrbl_default_root: bool = False,
210
+ ) -> None:
211
+ _add_route_impl(
212
+ self,
213
+ path,
214
+ endpoint,
215
+ methods=methods,
216
+ name=name,
217
+ summary=summary,
218
+ description=description,
219
+ tags=tags,
220
+ deprecated=deprecated,
221
+ request_schema=request_schema,
222
+ response_schema=response_schema,
223
+ path_param_schemas=path_param_schemas,
224
+ query_param_schemas=query_param_schemas,
225
+ include_in_schema=include_in_schema,
226
+ operation_id=operation_id,
227
+ response_model=response_model,
228
+ request_model=request_model,
229
+ responses=responses,
230
+ status_code=status_code,
231
+ dependencies=dependencies,
232
+ security_dependencies=security_dependencies,
233
+ inherit_owner_dependencies=inherit_owner_dependencies,
234
+ tigrbl_model=tigrbl_model,
235
+ tigrbl_alias=tigrbl_alias,
236
+ tigrbl_binding=tigrbl_binding,
237
+ tigrbl_exchange=tigrbl_exchange,
238
+ tigrbl_tx_scope=tigrbl_tx_scope,
239
+ tigrbl_default_root=tigrbl_default_root,
240
+ )
180
241
  self._bump_runtime_plan_revision()
181
242
 
182
243
  def route(self, path: str, *, methods: Any, **kwargs: Any):
@@ -197,28 +258,52 @@ class App(AppBase):
197
258
  def delete(self, path: str, **kwargs: Any):
198
259
  return self.route(path, methods=["DELETE"], **kwargs)
199
260
 
200
- def mount_openapi(self, *, path: str = "/openapi.json", name: str = "__openapi__") -> Any:
201
- from tigrbl_concrete.system.docs.openapi.mount import mount_openapi as _mount_openapi
261
+ def mount_openapi(
262
+ self, *, path: str = "/openapi.json", name: str = "__openapi__"
263
+ ) -> Any:
264
+ from tigrbl_concrete.system.docs.openapi.mount import (
265
+ mount_openapi as _mount_openapi,
266
+ )
267
+
202
268
  return _mount_openapi(self, path=path, name=name)
203
269
 
204
- def mount_swagger(self, *, path: str = "/docs", openapi_url: str | None = None, title: str | None = None) -> Any:
270
+ def mount_swagger(
271
+ self,
272
+ *,
273
+ path: str = "/docs",
274
+ openapi_url: str | None = None,
275
+ title: str | None = None,
276
+ ) -> Any:
205
277
  from tigrbl_concrete.system.docs.swagger import mount_swagger as _mount_swagger
278
+
206
279
  return _mount_swagger(self, path=path, openapi_url=openapi_url, title=title)
207
280
 
208
- def mount_openrpc(self, *, path: str = "/openrpc.json", name: str = "openrpc_json") -> Any:
281
+ def mount_openrpc(
282
+ self, *, path: str = "/openrpc.json", name: str = "openrpc_json"
283
+ ) -> Any:
209
284
  from tigrbl_concrete.system.docs.openrpc import mount_openrpc as _mount_openrpc
285
+
210
286
  return _mount_openrpc(self, path=path, name=name)
211
287
 
212
- def mount_lens(self, *, path: str = "/lens", openrpc_url: str | None = None, title: str | None = None) -> Any:
288
+ def mount_lens(
289
+ self,
290
+ *,
291
+ path: str = "/lens",
292
+ openrpc_url: str | None = None,
293
+ title: str | None = None,
294
+ ) -> Any:
213
295
  from tigrbl_concrete.system.docs.lens import mount_lens as _mount_lens
296
+
214
297
  return _mount_lens(self, path=path, openrpc_url=openrpc_url, title=title)
215
298
 
216
299
  def mount_json_schema(self, *, path: str = "/schemas.json") -> Any:
217
300
  from tigrbl_concrete.system.docs.json_schema import _mount_json_schema
301
+
218
302
  return _mount_json_schema(self, path=path)
219
303
 
220
304
  def mount_static(self, *, directory: str | Path, path: str = "/static") -> Any:
221
305
  from tigrbl_concrete.system.static import _mount_static
306
+
222
307
  return _mount_static(self, directory=directory, path=path)
223
308
 
224
309
  def mount_app(self, *, app: Any, path: str) -> Any:
@@ -249,9 +334,7 @@ class App(AppBase):
249
334
  handler=handler,
250
335
  name=route_name,
251
336
  protocol=str(kwargs.get("protocol", kwargs.get("proto", "ws"))),
252
- exchange=str(
253
- kwargs.get("exchange", "bidirectional_stream")
254
- ),
337
+ exchange=str(kwargs.get("exchange", "bidirectional_stream")),
255
338
  framing=str(framing),
256
339
  summary=kwargs.get("summary"),
257
340
  description=kwargs.get("description"),
@@ -272,6 +355,7 @@ class App(AppBase):
272
355
  if callable(bump):
273
356
  bump()
274
357
  return handler
358
+
275
359
  return _decorator
276
360
 
277
361
  @property
@@ -279,6 +363,7 @@ class App(AppBase):
279
363
  runtime = getattr(self, "_runtime_instance", None)
280
364
  if runtime is None:
281
365
  from tigrbl_runtime.runtime import Runtime
366
+
282
367
  runtime = Runtime(default_executor=self._runtime_default_executor)
283
368
  self._runtime_instance = runtime
284
369
  return runtime
@@ -422,19 +507,42 @@ class App(AppBase):
422
507
  wt_state = {}
423
508
  scope_state["tigrbl_webtransport"] = wt_state
424
509
 
425
- while wt_state.get("closed") is not True:
426
- env = GwRawEnvelope(kind="asgi3", scope=scope, receive=receive, send=send)
427
- await self.invoke(env)
428
- trace = wt_state.get("trace")
429
- if isinstance(trace, list):
430
- self._webtransport_trace_latest = list(trace)
431
- snapshots = getattr(self, "_webtransport_trace_snapshots", None)
432
- if not isinstance(snapshots, list):
433
- snapshots = []
434
- self._webtransport_trace_snapshots = snapshots
435
- snapshots.append(list(trace))
436
- if wt_state.get("closed") is True or wt_state.get("disconnected") is True:
437
- break
510
+ try:
511
+ while wt_state.get("closed") is not True:
512
+ env = GwRawEnvelope(kind="asgi3", scope=scope, receive=receive, send=send)
513
+ await self.invoke(env)
514
+ trace = wt_state.get("trace")
515
+ if isinstance(trace, list):
516
+ self._webtransport_trace_latest = list(trace)
517
+ snapshots = getattr(self, "_webtransport_trace_snapshots", None)
518
+ if not isinstance(snapshots, list):
519
+ snapshots = []
520
+ self._webtransport_trace_snapshots = snapshots
521
+ snapshots.append(list(trace))
522
+ if wt_state.get("closed") is True or wt_state.get("disconnected") is True:
523
+ break
524
+ finally:
525
+ session_id = scope.get("session_id")
526
+ extensions = scope.get("extensions")
527
+ if session_id is None and isinstance(extensions, dict):
528
+ extension = extensions.get("webtransport")
529
+ if isinstance(extension, dict):
530
+ session_id = extension.get("session_id")
531
+ callbacks = []
532
+ broker = getattr(self, "__realtime_broker__", None)
533
+ if session_id is not None and callable(
534
+ getattr(broker, "unsubscribe_session", None)
535
+ ):
536
+ callbacks.append(
537
+ lambda: broker.unsubscribe_session(str(session_id))
538
+ )
539
+ hub = getattr(self, "__presentation_hub__", None)
540
+ if session_id is not None and callable(getattr(hub, "disconnect", None)):
541
+ callbacks.append(lambda: hub.disconnect(str(session_id)))
542
+ session_plan = wt_state.get("session_plan")
543
+ cleanup = getattr(session_plan, "cleanup", None)
544
+ if callable(cleanup):
545
+ await cleanup(*callbacks)
438
546
 
439
547
  async def _handle_lifespan(
440
548
  self, _scope: dict[str, Any], receive: Any, send: Any
@@ -516,7 +624,9 @@ class App(AppBase):
516
624
  _prefix_model_bindings(model, normalized_prefix)
517
625
  if name == ROUTE_OPS_MODEL_NAME and name in self.tables:
518
626
  hooks = getattr(model, "hooks", None)
519
- for spec in tuple(getattr(getattr(model, "ops", None), "all", ()) or ()):
627
+ for spec in tuple(
628
+ getattr(getattr(model, "ops", None), "all", ()) or ()
629
+ ):
520
630
  handler_step = None
521
631
  alias_hooks = getattr(hooks, str(getattr(spec, "alias", "")), None)
522
632
  if alias_hooks is not None:
@@ -529,16 +639,31 @@ class App(AppBase):
529
639
  for ws_route in list(getattr(routed, "websocket_routes", ()) or []):
530
640
  path_template = ws_route.path_template
531
641
  if normalized_prefix:
532
- path_template = f"{normalized_prefix}{path_template}" if path_template != "/" else normalized_prefix
642
+ path_template = (
643
+ f"{normalized_prefix}{path_template}"
644
+ if path_template != "/"
645
+ else normalized_prefix
646
+ )
533
647
  pattern, param_names = compile_path(path_template)
534
648
  self.websocket_routes.append(
535
- replace(ws_route, path_template=path_template, pattern=pattern, param_names=param_names)
649
+ replace(
650
+ ws_route,
651
+ path_template=path_template,
652
+ pattern=pattern,
653
+ param_names=param_names,
654
+ )
536
655
  )
537
656
  for mount in list(getattr(routed, "_static_mounts", ()) or []):
538
657
  static_path = mount.get("path", "/static")
539
658
  if normalized_prefix:
540
- static_path = f"{normalized_prefix}{static_path}" if static_path != "/" else normalized_prefix
541
- self._static_mounts.append({"path": static_path, "directory": mount["directory"]})
659
+ static_path = (
660
+ f"{normalized_prefix}{static_path}"
661
+ if static_path != "/"
662
+ else normalized_prefix
663
+ )
664
+ self._static_mounts.append(
665
+ {"path": static_path, "directory": mount["directory"]}
666
+ )
542
667
  routed_mounted_apps = list(getattr(routed, "_mounted_apps", ()) or ())
543
668
  if routed_mounted_apps:
544
669
  owner_mounted_apps = list(getattr(self, "_mounted_apps", []) or [])
@@ -550,9 +675,7 @@ class App(AppBase):
550
675
  if mount_path != "/"
551
676
  else normalized_prefix
552
677
  )
553
- owner_mounted_apps.append(
554
- {"path": mount_path, "app": mount.get("app")}
555
- )
678
+ owner_mounted_apps.append({"path": mount_path, "app": mount.get("app")})
556
679
  self._mounted_apps = owner_mounted_apps
557
680
  routed_jsonrpc_mounts = getattr(routed, "_jsonrpc_endpoint_mounts", None)
558
681
  if isinstance(routed_jsonrpc_mounts, dict):
@@ -563,8 +686,14 @@ class App(AppBase):
563
686
  for mount_path, endpoint in routed_jsonrpc_mounts.items():
564
687
  path = mount_path
565
688
  if normalized_prefix:
566
- path = f"{normalized_prefix}{path}" if path != "/" else normalized_prefix
567
- normalized_path = (path if path.startswith("/") else f"/{path}").rstrip("/") or "/"
689
+ path = (
690
+ f"{normalized_prefix}{path}"
691
+ if path != "/"
692
+ else normalized_prefix
693
+ )
694
+ normalized_path = (path if path.startswith("/") else f"/{path}").rstrip(
695
+ "/"
696
+ ) or "/"
568
697
  owner_mounts[normalized_path] = endpoint
569
698
  if normalized_path != "/":
570
699
  owner_mounts[f"{normalized_path}/"] = endpoint
@@ -585,13 +714,17 @@ def _serve_mounted_app(host: Any, scope: dict[str, Any], receive: Any, send: Any
585
714
  mounted_app = mount.get("app")
586
715
  if mounted_app is None:
587
716
  continue
588
- remainder = request_path[len(mount_path) :] if mount_path != "/" else request_path
589
- nested_path = (remainder or "/")
717
+ remainder = (
718
+ request_path[len(mount_path) :] if mount_path != "/" else request_path
719
+ )
720
+ nested_path = remainder or "/"
590
721
  if not str(nested_path).startswith("/"):
591
722
  nested_path = f"/{nested_path}"
592
723
  nested_scope = dict(scope)
593
724
  nested_scope["path"] = nested_path
594
- nested_scope["root_path"] = f"{str(scope.get('root_path', '') or '').rstrip('/')}{mount_path}"
725
+ nested_scope["root_path"] = (
726
+ f"{str(scope.get('root_path', '') or '').rstrip('/')}{mount_path}"
727
+ )
595
728
  raw_path = scope.get("raw_path")
596
729
  if isinstance(raw_path, (bytes, bytearray)):
597
730
  nested_scope["raw_path"] = nested_path.encode("utf-8")
@@ -0,0 +1,31 @@
1
+ from __future__ import annotations
2
+
3
+ from tigrbl_base._base import ColumnBase
4
+ from tigrbl_core._spec.field_spec import FieldSpec
5
+ from tigrbl_core._spec.io_spec import IOSpec
6
+ from tigrbl_core._spec.storage_spec import StorageSpec
7
+
8
+
9
+ class Column(ColumnBase):
10
+ """Concrete SQLAlchemy column implementing a :class:`ColumnSpec`."""
11
+
12
+ S = StorageSpec
13
+ F = FieldSpec
14
+ IO = IOSpec
15
+
16
+ @classmethod
17
+ def make(cls, **kwargs):
18
+ """Construct a concrete column through the canonical factory."""
19
+ from tigrbl_concrete.factories.column import makeColumn
20
+
21
+ return makeColumn(**kwargs)
22
+
23
+ @classmethod
24
+ def make_virtual(cls, **kwargs):
25
+ """Construct a virtual column through the canonical factory."""
26
+ from tigrbl_concrete.factories.column import makeVirtualColumn
27
+
28
+ return makeVirtualColumn(**kwargs)
29
+
30
+
31
+ __all__ = ["Column"]