tina4-python 3.13.74__tar.gz → 3.13.76__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.74 → tina4_python-3.13.76}/PKG-INFO +1 -1
- {tina4_python-3.13.74 → tina4_python-3.13.76}/pyproject.toml +1 -1
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/core/server.py +32 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/migration/runner.py +33 -11
- {tina4_python-3.13.74 → tina4_python-3.13.76}/.gitignore +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/README.md +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/CLAUDE.md +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/HtmlElement.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/Testing.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/ai/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/api/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/auth/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/cache/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/cli/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/container/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/context/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/context/chunker.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/core/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/core/cache.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/core/constants.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/core/events.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/core/middleware.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/core/rate_limiter.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/core/request.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/core/response.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/core/router.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/crud/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/database/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/database/adapter.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/database/connection.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/database/firebird.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/database/mongodb.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/database/mssql.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/database/mysql.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/database/odbc.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/database/postgres.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/database/sqlite.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/debug/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/debug/error_overlay.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/dev_admin/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/dev_admin/metrics.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/dev_admin/plan.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/dev_admin/project_index.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/docs.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/docstore/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/dotenv/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/env.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/frond/FROND.md +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/frond/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/frond/engine.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/gallery/auth/meta.json +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/gallery/auth/src/routes/api/gallery_auth.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/gallery/database/meta.json +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/gallery/database/src/routes/api/gallery_db.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/gallery/error-overlay/meta.json +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/gallery/error-overlay/src/routes/api/gallery_crash.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/gallery/orm/meta.json +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/gallery/orm/src/orm/Product.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/gallery/orm/src/routes/api/gallery_products.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/gallery/queue/meta.json +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/gallery/queue/src/routes/api/gallery_queue.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/gallery/rest-api/meta.json +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/gallery/rest-api/src/routes/api/gallery_hello.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/gallery/templates/meta.json +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/gallery/templates/src/routes/gallery_page.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/gallery/templates/src/templates/gallery_page.twig +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/graphql/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/i18n/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/mcp/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/mcp/protocol.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/mcp/tools.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/messenger/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/migration/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/orm/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/orm/fields.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/orm/model.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/public/__feedback/widget.js +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/public/css/tina4.css +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/public/css/tina4.min.css +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/public/favicon.ico +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/public/images/logo.svg +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/public/images/tina4-logo-icon.webp +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/public/js/frond.js +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/public/js/frond.min.js +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/public/js/tina4-dev-admin.js +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/public/js/tina4-dev-admin.min.js +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/public/js/tina4.min.js +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/public/js/tina4js.min.js +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/public/swagger/index.html +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/public/swagger/oauth2-redirect.html +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/query_builder/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/queue/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/queue/job.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/queue/kafka_backend.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/queue/lite_backend.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/queue/mongo_backend.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/queue/rabbitmq_backend.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/queue_backends/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/queue_backends/kafka_backend.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/queue_backends/mongo_backend.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/queue_backends/rabbitmq_backend.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/realtime/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/realtime/models/Attachment.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/realtime/models/Channel.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/realtime/models/ChannelMember.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/realtime/models/Message.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/realtime/models/Workspace.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/realtime/models/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/realtime/storage.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/scss/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/scss/tina4css/_alerts.scss +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/scss/tina4css/_badges.scss +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/scss/tina4css/_buttons.scss +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/scss/tina4css/_cards.scss +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/scss/tina4css/_forms.scss +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/scss/tina4css/_grid.scss +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/scss/tina4css/_modals.scss +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/scss/tina4css/_nav.scss +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/scss/tina4css/_reset.scss +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/scss/tina4css/_tables.scss +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/scss/tina4css/_typography.scss +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/scss/tina4css/_utilities.scss +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/scss/tina4css/_variables.scss +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/scss/tina4css/base.scss +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/scss/tina4css/colors.scss +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/scss/tina4css/tina4.scss +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/seeder/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/service/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/session/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/session_handlers/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/session_handlers/mongodb_handler.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/session_handlers/redis_handler.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/session_handlers/valkey_handler.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/swagger/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/templates/components/crud.twig +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/templates/docker/distroless/Dockerfile +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/templates/docker/poetry/Dockerfile +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/templates/docker/python/Dockerfile +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/templates/docker/uv/Dockerfile +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/templates/errors/302.twig +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/templates/errors/401.twig +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/templates/errors/403.twig +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/templates/errors/404.twig +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/templates/errors/500.twig +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/templates/errors/502.twig +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/templates/errors/503.twig +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/templates/errors/base.twig +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/templates/frontend/README.md +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/templates/readme.md +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/test/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/test_client/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/af/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/af/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/en/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/en/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/es/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/es/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/fr/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/fr/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/ja/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/ja/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/zh/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/zh/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/validator/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/websocket/__init__.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/websocket/backplane.py +0 -0
- {tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/wsdl/__init__.py +0 -0
|
@@ -12,6 +12,7 @@ import asyncio
|
|
|
12
12
|
import contextvars
|
|
13
13
|
import importlib
|
|
14
14
|
import uuid
|
|
15
|
+
from email.utils import formatdate, parsedate_to_datetime
|
|
15
16
|
from pathlib import Path
|
|
16
17
|
|
|
17
18
|
from tina4_python.core.request import Request
|
|
@@ -1975,6 +1976,25 @@ async def app(scope: dict, receive, send):
|
|
|
1975
1976
|
await send({"type": "http.response.body", "body": b""})
|
|
1976
1977
|
return
|
|
1977
1978
|
|
|
1979
|
+
# If-Modified-Since -> 304, for responses carrying a Last-Modified (static
|
|
1980
|
+
# assets). If-None-Match takes precedence (RFC 9110 13.1.3), so this only
|
|
1981
|
+
# runs when the client sent no ETag validator.
|
|
1982
|
+
if not if_none_match:
|
|
1983
|
+
if_modified_since = request.headers.get("if-modified-since", "")
|
|
1984
|
+
last_modified = ""
|
|
1985
|
+
for name, value in headers:
|
|
1986
|
+
if name == b"last-modified":
|
|
1987
|
+
last_modified = value.decode()
|
|
1988
|
+
break
|
|
1989
|
+
if if_modified_since and last_modified:
|
|
1990
|
+
try:
|
|
1991
|
+
if parsedate_to_datetime(last_modified) <= parsedate_to_datetime(if_modified_since):
|
|
1992
|
+
await send({"type": "http.response.start", "status": 304, "headers": []})
|
|
1993
|
+
await send({"type": "http.response.body", "body": b""})
|
|
1994
|
+
return
|
|
1995
|
+
except (TypeError, ValueError):
|
|
1996
|
+
pass # Unparseable date -> serve the body (never 304 on garbage).
|
|
1997
|
+
|
|
1978
1998
|
await send({"type": "http.response.start", "status": response.status_code, "headers": headers})
|
|
1979
1999
|
await send({"type": "http.response.body", "body": response.content})
|
|
1980
2000
|
|
|
@@ -2010,6 +2030,18 @@ def _try_static(path: str) -> Response | None:
|
|
|
2010
2030
|
if file_path.is_file():
|
|
2011
2031
|
resp = Response()
|
|
2012
2032
|
resp.file(str(file_path))
|
|
2033
|
+
# Static assets may be cached but must be revalidated on every use,
|
|
2034
|
+
# so a redeployed file reaches the browser on the next load without a
|
|
2035
|
+
# manual hard refresh. The response already carries an ETag
|
|
2036
|
+
# (build_headers) and the pipeline answers If-None-Match with a 304,
|
|
2037
|
+
# so revalidation is a cheap round-trip, not a re-download. A
|
|
2038
|
+
# Last-Modified is added too (pipeline honours If-Modified-Since ->
|
|
2039
|
+
# 304) so the validators match the other frameworks.
|
|
2040
|
+
resp.header("cache-control", "no-cache, must-revalidate")
|
|
2041
|
+
resp.header(
|
|
2042
|
+
"last-modified",
|
|
2043
|
+
formatdate(file_path.stat().st_mtime, usegmt=True),
|
|
2044
|
+
)
|
|
2013
2045
|
return resp
|
|
2014
2046
|
return None
|
|
2015
2047
|
|
|
@@ -296,7 +296,11 @@ def _ensure_tracking_table(db, migration_folder: str | None = None):
|
|
|
296
296
|
# and copy the values across so already-applied migrations are still seen as
|
|
297
297
|
# applied — without this the `migration_name`-based read below finds nothing
|
|
298
298
|
# and every migration re-runs. The old `migration_id` column is left in
|
|
299
|
-
# place (
|
|
299
|
+
# place: it cannot be dropped portably (SQLite cannot drop a NOT NULL or a
|
|
300
|
+
# column without a full table rebuild). It is ignored on READS, but it is
|
|
301
|
+
# NOT ignorable on WRITES — it is NOT NULL on that table, so
|
|
302
|
+
# `_record_applied` must keep populating it (see there). Leaving it unwritten
|
|
303
|
+
# is what broke every migration on an upgraded database in 3.13.55-3.13.75.
|
|
300
304
|
if "migration_id" in cols and "migration_name" not in cols:
|
|
301
305
|
col_type = "VARCHAR(500)" if _is_firebird(db) else "TEXT"
|
|
302
306
|
try:
|
|
@@ -641,18 +645,36 @@ def _record_applied(db, name: str, desc: str, batch: int, passed: int = 1) -> No
|
|
|
641
645
|
"""
|
|
642
646
|
now = datetime.now(timezone.utc).isoformat()
|
|
643
647
|
db.execute("DELETE FROM tina4_migration WHERE migration_name = ?", [name])
|
|
648
|
+
|
|
649
|
+
# Build the column list from the columns that ACTUALLY exist on this table,
|
|
650
|
+
# so a legacy column an earlier in-place upgrade left behind is populated
|
|
651
|
+
# rather than defaulted to NULL. A table created by v3 <= 3.13.54 carries
|
|
652
|
+
# `migration_id NOT NULL UNIQUE`; the rename upgrade adds `migration_name`
|
|
653
|
+
# beside it but cannot drop the NOT NULL portably (SQLite cannot drop it at
|
|
654
|
+
# all without a table rebuild), so this insert has to satisfy it or every
|
|
655
|
+
# migration on that database fails and none can ever apply.
|
|
656
|
+
cols = _column_names(db)
|
|
657
|
+
insert_cols = ["migration_name", "description", "batch", "executed_at", "passed"]
|
|
658
|
+
values = [name, desc, batch, now, passed]
|
|
659
|
+
|
|
660
|
+
# v3 <= 3.13.54: `migration_id` held exactly the value `migration_name` holds
|
|
661
|
+
# now, so writing `name` restores that invariant. Safe against its UNIQUE:
|
|
662
|
+
# the DELETE above removed this migration's own row first, so a re-run
|
|
663
|
+
# replaces its row instead of colliding.
|
|
664
|
+
if "migration_id" in cols:
|
|
665
|
+
insert_cols.append("migration_id")
|
|
666
|
+
values.append(name)
|
|
667
|
+
|
|
644
668
|
if _is_firebird(db):
|
|
645
669
|
row = db.fetch_one("SELECT GEN_ID(GEN_TINA4_MIGRATION_ID, 1) AS next_id FROM RDB$DATABASE")
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
[name, desc, batch, now, passed],
|
|
655
|
-
)
|
|
670
|
+
insert_cols.insert(0, "id")
|
|
671
|
+
values.insert(0, row["next_id"] if row else 1)
|
|
672
|
+
|
|
673
|
+
placeholders = ", ".join("?" for _ in insert_cols)
|
|
674
|
+
db.execute(
|
|
675
|
+
f"INSERT INTO tina4_migration ({', '.join(insert_cols)}) VALUES ({placeholders})",
|
|
676
|
+
values,
|
|
677
|
+
)
|
|
656
678
|
|
|
657
679
|
|
|
658
680
|
def _migrate(db, migration_folder: str = "migrations", delimiter: str = ";") -> list[str]:
|
|
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
|
|
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.74 → tina4_python-3.13.76}/tina4_python/public/images/tina4-logo-icon.webp
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
|
{tina4_python-3.13.74 → tina4_python-3.13.76}/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
|
{tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/queue_backends/rabbitmq_backend.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
|
{tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/session_handlers/mongodb_handler.py
RENAMED
|
File without changes
|
{tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/session_handlers/redis_handler.py
RENAMED
|
File without changes
|
{tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/session_handlers/valkey_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/templates/docker/distroless/Dockerfile
RENAMED
|
File without changes
|
{tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/templates/docker/poetry/Dockerfile
RENAMED
|
File without changes
|
{tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/templates/docker/python/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
|
{tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/af/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/af/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/en/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/en/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/es/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/es/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/fr/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/fr/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/ja/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/ja/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/zh/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.74 → tina4_python-3.13.76}/tina4_python/translations/zh/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|