tina4-python 3.13.6__tar.gz → 3.13.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 (157) hide show
  1. {tina4_python-3.13.6 → tina4_python-3.13.7}/PKG-INFO +1 -1
  2. {tina4_python-3.13.6 → tina4_python-3.13.7}/pyproject.toml +1 -1
  3. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/__init__.py +1 -1
  4. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/core/server.py +33 -4
  5. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/templates/errors/500.twig +1 -1
  6. {tina4_python-3.13.6 → tina4_python-3.13.7}/.gitignore +0 -0
  7. {tina4_python-3.13.6 → tina4_python-3.13.7}/README.md +0 -0
  8. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/CLAUDE.md +0 -0
  9. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/HtmlElement.py +0 -0
  10. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/Testing.py +0 -0
  11. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/ai/__init__.py +0 -0
  12. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/api/__init__.py +0 -0
  13. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/auth/__init__.py +0 -0
  14. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/cache/__init__.py +0 -0
  15. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/cli/__init__.py +0 -0
  16. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/container/__init__.py +0 -0
  17. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/core/__init__.py +0 -0
  18. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/core/cache.py +0 -0
  19. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/core/constants.py +0 -0
  20. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/core/events.py +0 -0
  21. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/core/middleware.py +0 -0
  22. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/core/rate_limiter.py +0 -0
  23. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/core/request.py +0 -0
  24. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/core/response.py +0 -0
  25. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/core/router.py +0 -0
  26. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/crud/__init__.py +0 -0
  27. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/database/__init__.py +0 -0
  28. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/database/adapter.py +0 -0
  29. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/database/connection.py +0 -0
  30. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/database/firebird.py +0 -0
  31. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/database/mongodb.py +0 -0
  32. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/database/mssql.py +0 -0
  33. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/database/mysql.py +0 -0
  34. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/database/odbc.py +0 -0
  35. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/database/postgres.py +0 -0
  36. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/database/sqlite.py +0 -0
  37. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/debug/__init__.py +0 -0
  38. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/debug/error_overlay.py +0 -0
  39. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/dev_admin/__init__.py +0 -0
  40. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/dev_admin/metrics.py +0 -0
  41. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/dev_admin/plan.py +0 -0
  42. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/dev_admin/project_index.py +0 -0
  43. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/docs.py +0 -0
  44. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/dotenv/__init__.py +0 -0
  45. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/env.py +0 -0
  46. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/frond/FROND.md +0 -0
  47. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/frond/__init__.py +0 -0
  48. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/frond/engine.py +0 -0
  49. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/gallery/auth/meta.json +0 -0
  50. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/gallery/auth/src/routes/api/gallery_auth.py +0 -0
  51. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/gallery/database/meta.json +0 -0
  52. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/gallery/database/src/routes/api/gallery_db.py +0 -0
  53. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/gallery/error-overlay/meta.json +0 -0
  54. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/gallery/error-overlay/src/routes/api/gallery_crash.py +0 -0
  55. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/gallery/orm/meta.json +0 -0
  56. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/gallery/orm/src/orm/Product.py +0 -0
  57. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/gallery/orm/src/routes/api/gallery_products.py +0 -0
  58. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/gallery/queue/meta.json +0 -0
  59. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/gallery/queue/src/routes/api/gallery_queue.py +0 -0
  60. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/gallery/rest-api/meta.json +0 -0
  61. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/gallery/rest-api/src/routes/api/gallery_hello.py +0 -0
  62. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/gallery/templates/meta.json +0 -0
  63. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/gallery/templates/src/routes/gallery_page.py +0 -0
  64. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/gallery/templates/src/templates/gallery_page.twig +0 -0
  65. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/graphql/__init__.py +0 -0
  66. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/i18n/__init__.py +0 -0
  67. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/mcp/__init__.py +0 -0
  68. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/mcp/protocol.py +0 -0
  69. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/mcp/tools.py +0 -0
  70. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/messenger/__init__.py +0 -0
  71. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/migration/__init__.py +0 -0
  72. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/migration/runner.py +0 -0
  73. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/orm/__init__.py +0 -0
  74. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/orm/fields.py +0 -0
  75. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/orm/model.py +0 -0
  76. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/public/__feedback/widget.js +0 -0
  77. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/public/css/tina4.css +0 -0
  78. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/public/css/tina4.min.css +0 -0
  79. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/public/favicon.ico +0 -0
  80. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/public/images/logo.svg +0 -0
  81. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/public/images/tina4-logo-icon.webp +0 -0
  82. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/public/js/frond.js +0 -0
  83. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/public/js/frond.min.js +0 -0
  84. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/public/js/tina4-dev-admin.js +0 -0
  85. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/public/js/tina4-dev-admin.min.js +0 -0
  86. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/public/js/tina4.min.js +0 -0
  87. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/public/js/tina4js.min.js +0 -0
  88. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/public/swagger/index.html +0 -0
  89. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/public/swagger/oauth2-redirect.html +0 -0
  90. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/query_builder/__init__.py +0 -0
  91. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/queue/__init__.py +0 -0
  92. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/queue/job.py +0 -0
  93. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/queue/kafka_backend.py +0 -0
  94. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/queue/lite_backend.py +0 -0
  95. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/queue/mongo_backend.py +0 -0
  96. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/queue/rabbitmq_backend.py +0 -0
  97. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/queue_backends/__init__.py +0 -0
  98. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/queue_backends/kafka_backend.py +0 -0
  99. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/queue_backends/mongo_backend.py +0 -0
  100. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/queue_backends/rabbitmq_backend.py +0 -0
  101. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/scss/__init__.py +0 -0
  102. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/scss/tina4css/_alerts.scss +0 -0
  103. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/scss/tina4css/_badges.scss +0 -0
  104. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/scss/tina4css/_buttons.scss +0 -0
  105. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/scss/tina4css/_cards.scss +0 -0
  106. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/scss/tina4css/_forms.scss +0 -0
  107. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/scss/tina4css/_grid.scss +0 -0
  108. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/scss/tina4css/_modals.scss +0 -0
  109. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/scss/tina4css/_nav.scss +0 -0
  110. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/scss/tina4css/_reset.scss +0 -0
  111. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/scss/tina4css/_tables.scss +0 -0
  112. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/scss/tina4css/_typography.scss +0 -0
  113. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/scss/tina4css/_utilities.scss +0 -0
  114. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/scss/tina4css/_variables.scss +0 -0
  115. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/scss/tina4css/base.scss +0 -0
  116. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/scss/tina4css/colors.scss +0 -0
  117. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/scss/tina4css/tina4.scss +0 -0
  118. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/seeder/__init__.py +0 -0
  119. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/service/__init__.py +0 -0
  120. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/session/__init__.py +0 -0
  121. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/session_handlers/__init__.py +0 -0
  122. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/session_handlers/mongodb_handler.py +0 -0
  123. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/session_handlers/redis_handler.py +0 -0
  124. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/session_handlers/valkey_handler.py +0 -0
  125. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/swagger/__init__.py +0 -0
  126. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/templates/components/crud.twig +0 -0
  127. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/templates/docker/distroless/Dockerfile +0 -0
  128. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/templates/docker/poetry/Dockerfile +0 -0
  129. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/templates/docker/python/Dockerfile +0 -0
  130. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/templates/docker/uv/Dockerfile +0 -0
  131. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/templates/errors/302.twig +0 -0
  132. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/templates/errors/401.twig +0 -0
  133. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/templates/errors/403.twig +0 -0
  134. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/templates/errors/404.twig +0 -0
  135. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/templates/errors/502.twig +0 -0
  136. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/templates/errors/503.twig +0 -0
  137. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/templates/errors/base.twig +0 -0
  138. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/templates/frontend/README.md +0 -0
  139. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/templates/readme.md +0 -0
  140. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/test/__init__.py +0 -0
  141. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/test_client/__init__.py +0 -0
  142. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/translations/af/LC_MESSAGES/messages.mo +0 -0
  143. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/translations/af/LC_MESSAGES/messages.po +0 -0
  144. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/translations/en/LC_MESSAGES/messages.mo +0 -0
  145. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/translations/en/LC_MESSAGES/messages.po +0 -0
  146. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/translations/es/LC_MESSAGES/messages.mo +0 -0
  147. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/translations/es/LC_MESSAGES/messages.po +0 -0
  148. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/translations/fr/LC_MESSAGES/messages.mo +0 -0
  149. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/translations/fr/LC_MESSAGES/messages.po +0 -0
  150. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/translations/ja/LC_MESSAGES/messages.mo +0 -0
  151. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/translations/ja/LC_MESSAGES/messages.po +0 -0
  152. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/translations/zh/LC_MESSAGES/messages.mo +0 -0
  153. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/translations/zh/LC_MESSAGES/messages.po +0 -0
  154. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/validator/__init__.py +0 -0
  155. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/websocket/__init__.py +0 -0
  156. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/websocket/backplane.py +0 -0
  157. {tina4_python-3.13.6 → tina4_python-3.13.7}/tina4_python/wsdl/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tina4-python
3
- Version: 3.13.6
3
+ Version: 3.13.7
4
4
  Summary: Tina4 Python v3 — Zero-dependency, lightweight web framework
5
5
  Author-email: Andre van Zuydam <andrevanzuydam@gmail.com>
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tina4-python"
3
- version = "3.13.6"
3
+ version = "3.13.7"
4
4
  description = "Tina4 Python v3 — Zero-dependency, lightweight web framework"
5
5
  authors = [
6
6
  {name = "Andre van Zuydam", email = "andrevanzuydam@gmail.com"}
@@ -8,7 +8,7 @@ Tina4 Python v3.0 — Zero-dependency, lightweight web framework.
8
8
 
9
9
  One import, everything works.
10
10
  """
11
- __version__ = "3.13.6"
11
+ __version__ = "3.13.7"
12
12
 
13
13
  # ── Route decorators ──
14
14
  from tina4_python.core.router import ( # noqa: E402, F401
@@ -1307,9 +1307,38 @@ def _handle_route_error(
1307
1307
  error: Exception, request: Request, response: Response,
1308
1308
  request_id: str, is_dev: bool,
1309
1309
  ) -> Response:
1310
- """Format an error response for a failed route handler."""
1310
+ """Format an error response for a failed route handler.
1311
+
1312
+ Two contracts (v3.13.7):
1313
+
1314
+ 1. Fire ``tina4.request.error`` before rendering, so observers
1315
+ (centralised logging, APM, Sentry) see the failure even though
1316
+ the framework caught it. Payload is a single dict ``{exception,
1317
+ request}`` — the canonical shape mirrored by PHP/Ruby/Node.
1318
+ Listener exceptions are swallowed so a broken listener can't
1319
+ break the 500 page.
1320
+
1321
+ 2. In non-debug mode, never put the stack trace in the response
1322
+ body (CWE-209). The trace is still available via ``Log.error``
1323
+ above and the dev-admin ``BrokenTracker`` in dev mode. The
1324
+ framework's own 500.twig now guards the trace block with
1325
+ ``{% if error_message %}``.
1326
+ """
1311
1327
  Log.error(f"Route error: {error}", path=request.path)
1312
1328
  _write_broken(request, error)
1329
+
1330
+ try:
1331
+ from tina4_python.core.events import emit as _emit
1332
+ _emit("tina4.request.error", {"exception": error, "request": request})
1333
+ except Exception as listener_err:
1334
+ try:
1335
+ Log.warning(
1336
+ f"Listener for tina4.request.error raised: "
1337
+ f"{type(listener_err).__name__}: {listener_err}"
1338
+ )
1339
+ except Exception:
1340
+ pass
1341
+
1313
1342
  if is_dev:
1314
1343
  try:
1315
1344
  import traceback as _tb
@@ -1324,9 +1353,9 @@ def _handle_route_error(
1324
1353
  overlay_html = render_error_overlay(error, request)
1325
1354
  response.status(500).html(overlay_html)
1326
1355
  else:
1327
- import traceback
1328
- tb = traceback.format_exc()
1329
- html = _render_error_page(500, request.path, request_id, tb)
1356
+ # Production: NO traceback in the body. The trace is logged via
1357
+ # Log.error above; clients only see the generic page + request_id.
1358
+ html = _render_error_page(500, request.path, request_id, "")
1330
1359
  if html:
1331
1360
  response.status(500).html(html)
1332
1361
  else:
@@ -27,7 +27,7 @@ body { font-family: system-ui, -apple-system, sans-serif; background: #0f172a; c
27
27
  <div class="error-title">Server Error</div>
28
28
  </div>
29
29
  <div class="error-msg">Something went wrong while processing your request.</div>
30
- <pre class="error-trace">{{ error_message }}</pre>
30
+ {% if error_message %}<pre class="error-trace">{{ error_message }}</pre>{% endif %}
31
31
  <div class="error-footer">
32
32
  <span class="error-hint">Fix the error and save to auto-reload</span>
33
33
  <span class="error-id">{{ request_id }}</span>
File without changes
File without changes