tina4-python 3.13.6__tar.gz → 3.13.8__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.
- {tina4_python-3.13.6 → tina4_python-3.13.8}/PKG-INFO +1 -1
- {tina4_python-3.13.6 → tina4_python-3.13.8}/pyproject.toml +1 -1
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/__init__.py +1 -1
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/core/server.py +33 -4
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/database/postgres.py +81 -8
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/templates/errors/500.twig +1 -1
- {tina4_python-3.13.6 → tina4_python-3.13.8}/.gitignore +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/README.md +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/CLAUDE.md +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/HtmlElement.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/Testing.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/ai/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/api/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/auth/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/cache/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/cli/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/container/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/core/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/core/cache.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/core/constants.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/core/events.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/core/middleware.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/core/rate_limiter.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/core/request.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/core/response.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/core/router.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/crud/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/database/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/database/adapter.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/database/connection.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/database/firebird.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/database/mongodb.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/database/mssql.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/database/mysql.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/database/odbc.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/database/sqlite.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/debug/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/debug/error_overlay.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/dev_admin/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/dev_admin/metrics.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/dev_admin/plan.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/dev_admin/project_index.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/docs.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/dotenv/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/env.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/frond/FROND.md +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/frond/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/frond/engine.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/gallery/auth/meta.json +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/gallery/auth/src/routes/api/gallery_auth.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/gallery/database/meta.json +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/gallery/database/src/routes/api/gallery_db.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/gallery/error-overlay/meta.json +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/gallery/error-overlay/src/routes/api/gallery_crash.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/gallery/orm/meta.json +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/gallery/orm/src/orm/Product.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/gallery/orm/src/routes/api/gallery_products.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/gallery/queue/meta.json +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/gallery/queue/src/routes/api/gallery_queue.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/gallery/rest-api/meta.json +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/gallery/rest-api/src/routes/api/gallery_hello.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/gallery/templates/meta.json +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/gallery/templates/src/routes/gallery_page.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/gallery/templates/src/templates/gallery_page.twig +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/graphql/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/i18n/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/mcp/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/mcp/protocol.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/mcp/tools.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/messenger/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/migration/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/migration/runner.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/orm/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/orm/fields.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/orm/model.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/public/__feedback/widget.js +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/public/css/tina4.css +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/public/css/tina4.min.css +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/public/favicon.ico +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/public/images/logo.svg +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/public/images/tina4-logo-icon.webp +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/public/js/frond.js +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/public/js/frond.min.js +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/public/js/tina4-dev-admin.js +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/public/js/tina4-dev-admin.min.js +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/public/js/tina4.min.js +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/public/js/tina4js.min.js +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/public/swagger/index.html +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/public/swagger/oauth2-redirect.html +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/query_builder/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/queue/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/queue/job.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/queue/kafka_backend.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/queue/lite_backend.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/queue/mongo_backend.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/queue/rabbitmq_backend.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/queue_backends/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/queue_backends/kafka_backend.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/queue_backends/mongo_backend.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/queue_backends/rabbitmq_backend.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/scss/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/scss/tina4css/_alerts.scss +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/scss/tina4css/_badges.scss +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/scss/tina4css/_buttons.scss +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/scss/tina4css/_cards.scss +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/scss/tina4css/_forms.scss +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/scss/tina4css/_grid.scss +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/scss/tina4css/_modals.scss +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/scss/tina4css/_nav.scss +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/scss/tina4css/_reset.scss +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/scss/tina4css/_tables.scss +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/scss/tina4css/_typography.scss +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/scss/tina4css/_utilities.scss +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/scss/tina4css/_variables.scss +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/scss/tina4css/base.scss +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/scss/tina4css/colors.scss +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/scss/tina4css/tina4.scss +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/seeder/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/service/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/session/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/session_handlers/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/session_handlers/mongodb_handler.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/session_handlers/redis_handler.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/session_handlers/valkey_handler.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/swagger/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/templates/components/crud.twig +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/templates/docker/distroless/Dockerfile +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/templates/docker/poetry/Dockerfile +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/templates/docker/python/Dockerfile +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/templates/docker/uv/Dockerfile +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/templates/errors/302.twig +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/templates/errors/401.twig +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/templates/errors/403.twig +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/templates/errors/404.twig +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/templates/errors/502.twig +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/templates/errors/503.twig +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/templates/errors/base.twig +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/templates/frontend/README.md +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/templates/readme.md +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/test/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/test_client/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/af/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/af/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/en/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/en/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/es/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/es/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/fr/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/fr/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/ja/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/ja/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/zh/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/zh/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/validator/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/websocket/__init__.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/websocket/backplane.py +0 -0
- {tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/wsdl/__init__.py +0 -0
|
@@ -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
|
-
|
|
1328
|
-
|
|
1329
|
-
html = _render_error_page(500, request.path, request_id,
|
|
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:
|
|
@@ -49,6 +49,60 @@ class PostgreSQLAdapter(DatabaseAdapter):
|
|
|
49
49
|
else:
|
|
50
50
|
cursor.execute(sql)
|
|
51
51
|
|
|
52
|
+
def _heal_aborted_txn(self):
|
|
53
|
+
"""Issue #46 follow-on (v3.13.8): pre-flight rollback if the
|
|
54
|
+
connection arrived in an aborted-transaction state.
|
|
55
|
+
|
|
56
|
+
v3.13.6 added auto-rollback inside :meth:`_on_query_error` — that
|
|
57
|
+
clears the abort *on* a failure the wrapper catches. But the
|
|
58
|
+
connection can still arrive poisoned from elsewhere:
|
|
59
|
+
|
|
60
|
+
- A boot-time query that failed before request handling started
|
|
61
|
+
(migration probe, ORM ``information_schema`` lookup, etc.)
|
|
62
|
+
- A failure inside an explicit transaction where the user owned
|
|
63
|
+
the rollback but never issued one
|
|
64
|
+
- A direct ``cursor.execute`` call in another adapter method
|
|
65
|
+
(e.g. the ``SELECT lastval()`` SAVEPOINT probe) that managed to
|
|
66
|
+
leave the txn dirty
|
|
67
|
+
|
|
68
|
+
In all those cases the *next* query — even one routed through
|
|
69
|
+
our wrapper — hits ``InFailedSqlTransaction`` immediately, and
|
|
70
|
+
the cascade message buries whatever the original cause was.
|
|
71
|
+
|
|
72
|
+
Healing fix: before executing, ask psycopg2 whether the
|
|
73
|
+
connection is in ``TRANSACTION_STATUS_INERROR`` and rollback if
|
|
74
|
+
so. Only when NOT inside an explicit transaction — explicit txns
|
|
75
|
+
stay under the caller's control.
|
|
76
|
+
|
|
77
|
+
Reported by Schalk (24rent) against v3.13.7.
|
|
78
|
+
"""
|
|
79
|
+
if self._in_transaction or self._conn is None:
|
|
80
|
+
return
|
|
81
|
+
try:
|
|
82
|
+
import psycopg2.extensions as _ext
|
|
83
|
+
status = self._conn.info.transaction_status
|
|
84
|
+
except Exception:
|
|
85
|
+
return
|
|
86
|
+
if status != _ext.TRANSACTION_STATUS_INERROR:
|
|
87
|
+
return
|
|
88
|
+
try:
|
|
89
|
+
self._conn.rollback()
|
|
90
|
+
except Exception:
|
|
91
|
+
# If even the heal-rollback fails, fall through — the next
|
|
92
|
+
# cursor.execute will raise with the real psycopg2 error and
|
|
93
|
+
# _on_query_error will pick it up. Better than masking.
|
|
94
|
+
return
|
|
95
|
+
try:
|
|
96
|
+
from tina4_python.debug import Log
|
|
97
|
+
Log.warning(
|
|
98
|
+
"PostgreSQL connection arrived in aborted-transaction "
|
|
99
|
+
"state — issued pre-flight ROLLBACK so the next query "
|
|
100
|
+
"starts clean. Look back in the log for the original "
|
|
101
|
+
"PostgreSQL query failed entry."
|
|
102
|
+
)
|
|
103
|
+
except Exception:
|
|
104
|
+
pass
|
|
105
|
+
|
|
52
106
|
def _exec_with_handling(self, cursor, sql: str, params=None):
|
|
53
107
|
"""Run a query through :meth:`_safe_execute` and surface failures.
|
|
54
108
|
|
|
@@ -59,18 +113,23 @@ class PostgreSQLAdapter(DatabaseAdapter):
|
|
|
59
113
|
block``, *far* from the actual cause. Without framework-side
|
|
60
114
|
logging, the original SQL + error never reach the user.
|
|
61
115
|
|
|
62
|
-
|
|
116
|
+
This method:
|
|
63
117
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
118
|
+
0. (v3.13.8) Pre-flight heal — if the connection arrived in an
|
|
119
|
+
aborted-transaction state from anywhere outside this wrapper,
|
|
120
|
+
rollback first so this query starts on a clean txn.
|
|
121
|
+
1. Logs failures via ``Log.error`` with SQL+params context
|
|
122
|
+
2. Stores them on ``self.last_error``
|
|
123
|
+
3. Auto-rollbacks on failure when NOT inside an explicit
|
|
124
|
+
transaction (so the next caller gets a clean connection)
|
|
68
125
|
4. Re-raises so callers still see the failure
|
|
69
126
|
|
|
70
|
-
Inside an explicit transaction we do NOT rollback — the
|
|
71
|
-
that transaction (could be running a SAVEPOINT/retry
|
|
72
|
-
still log + store ``last_error`` so they can
|
|
127
|
+
Inside an explicit transaction we do NOT auto-rollback — the
|
|
128
|
+
user owns that transaction (could be running a SAVEPOINT/retry
|
|
129
|
+
pattern). We still log + store ``last_error`` so they can
|
|
130
|
+
diagnose, and the heal step also defers to explicit txns.
|
|
73
131
|
"""
|
|
132
|
+
self._heal_aborted_txn()
|
|
74
133
|
try:
|
|
75
134
|
self._safe_execute(cursor, sql, params)
|
|
76
135
|
except Exception as e:
|
|
@@ -208,6 +267,12 @@ class PostgreSQLAdapter(DatabaseAdapter):
|
|
|
208
267
|
|
|
209
268
|
sql = self._translate_sql(sql)
|
|
210
269
|
|
|
270
|
+
# v3.13.8: heal first so the COUNT probe below doesn't open on a
|
|
271
|
+
# poisoned connection — the probe uses raw _safe_execute (it's
|
|
272
|
+
# allowed to fail without polluting last_error) so it bypasses
|
|
273
|
+
# _exec_with_handling's heal step.
|
|
274
|
+
self._heal_aborted_txn()
|
|
275
|
+
|
|
211
276
|
cursor = self._conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
|
|
212
277
|
|
|
213
278
|
# Count total rows
|
|
@@ -217,6 +282,14 @@ class PostgreSQLAdapter(DatabaseAdapter):
|
|
|
217
282
|
total = cursor.fetchone()["cnt"]
|
|
218
283
|
except Exception:
|
|
219
284
|
total = 0
|
|
285
|
+
# If the probe failed because the connection arrived (or
|
|
286
|
+
# became) aborted, roll back so the real pagination query
|
|
287
|
+
# below sees a clean txn. Without this we'd cascade.
|
|
288
|
+
if not self._in_transaction and self._conn is not None:
|
|
289
|
+
try:
|
|
290
|
+
self._conn.rollback()
|
|
291
|
+
except Exception:
|
|
292
|
+
pass
|
|
220
293
|
|
|
221
294
|
# Apply pagination — the real query, so use the error-handling
|
|
222
295
|
# wrapper. The count probe above is best-effort and stays on
|
|
@@ -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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/gallery/auth/src/routes/api/gallery_auth.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/public/swagger/oauth2-redirect.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/session_handlers/mongodb_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/templates/docker/distroless/Dockerfile
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/af/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/af/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/en/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/en/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/es/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/es/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/fr/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/fr/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/ja/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/ja/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/zh/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.6 → tina4_python-3.13.8}/tina4_python/translations/zh/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|