tina4-python 3.13.72__tar.gz → 3.13.74__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.72 → tina4_python-3.13.74}/PKG-INFO +1 -1
- {tina4_python-3.13.72 → tina4_python-3.13.74}/pyproject.toml +1 -1
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/CLAUDE.md +1 -1
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/dev_admin/__init__.py +1 -1
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/migration/runner.py +32 -28
- {tina4_python-3.13.72 → tina4_python-3.13.74}/.gitignore +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/README.md +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/HtmlElement.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/Testing.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/ai/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/api/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/auth/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/cache/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/cli/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/container/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/context/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/context/chunker.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/core/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/core/cache.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/core/constants.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/core/events.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/core/middleware.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/core/rate_limiter.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/core/request.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/core/response.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/core/router.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/core/server.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/crud/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/database/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/database/adapter.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/database/connection.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/database/firebird.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/database/mongodb.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/database/mssql.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/database/mysql.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/database/odbc.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/database/postgres.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/database/sqlite.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/debug/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/debug/error_overlay.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/dev_admin/metrics.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/dev_admin/plan.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/dev_admin/project_index.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/docs.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/docstore/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/dotenv/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/env.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/frond/FROND.md +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/frond/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/frond/engine.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/gallery/auth/meta.json +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/gallery/auth/src/routes/api/gallery_auth.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/gallery/database/meta.json +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/gallery/database/src/routes/api/gallery_db.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/gallery/error-overlay/meta.json +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/gallery/error-overlay/src/routes/api/gallery_crash.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/gallery/orm/meta.json +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/gallery/orm/src/orm/Product.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/gallery/orm/src/routes/api/gallery_products.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/gallery/queue/meta.json +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/gallery/queue/src/routes/api/gallery_queue.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/gallery/rest-api/meta.json +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/gallery/rest-api/src/routes/api/gallery_hello.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/gallery/templates/meta.json +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/gallery/templates/src/routes/gallery_page.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/gallery/templates/src/templates/gallery_page.twig +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/graphql/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/i18n/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/mcp/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/mcp/protocol.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/mcp/tools.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/messenger/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/migration/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/orm/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/orm/fields.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/orm/model.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/public/__feedback/widget.js +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/public/css/tina4.css +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/public/css/tina4.min.css +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/public/favicon.ico +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/public/images/logo.svg +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/public/images/tina4-logo-icon.webp +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/public/js/frond.js +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/public/js/frond.min.js +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/public/js/tina4-dev-admin.js +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/public/js/tina4-dev-admin.min.js +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/public/js/tina4.min.js +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/public/js/tina4js.min.js +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/public/swagger/index.html +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/public/swagger/oauth2-redirect.html +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/query_builder/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/queue/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/queue/job.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/queue/kafka_backend.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/queue/lite_backend.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/queue/mongo_backend.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/queue/rabbitmq_backend.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/queue_backends/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/queue_backends/kafka_backend.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/queue_backends/mongo_backend.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/queue_backends/rabbitmq_backend.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/realtime/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/realtime/models/Attachment.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/realtime/models/Channel.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/realtime/models/ChannelMember.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/realtime/models/Message.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/realtime/models/Workspace.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/realtime/models/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/realtime/storage.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/scss/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/scss/tina4css/_alerts.scss +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/scss/tina4css/_badges.scss +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/scss/tina4css/_buttons.scss +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/scss/tina4css/_cards.scss +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/scss/tina4css/_forms.scss +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/scss/tina4css/_grid.scss +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/scss/tina4css/_modals.scss +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/scss/tina4css/_nav.scss +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/scss/tina4css/_reset.scss +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/scss/tina4css/_tables.scss +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/scss/tina4css/_typography.scss +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/scss/tina4css/_utilities.scss +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/scss/tina4css/_variables.scss +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/scss/tina4css/base.scss +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/scss/tina4css/colors.scss +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/scss/tina4css/tina4.scss +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/seeder/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/service/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/session/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/session_handlers/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/session_handlers/mongodb_handler.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/session_handlers/redis_handler.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/session_handlers/valkey_handler.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/swagger/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/templates/components/crud.twig +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/templates/docker/distroless/Dockerfile +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/templates/docker/poetry/Dockerfile +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/templates/docker/python/Dockerfile +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/templates/docker/uv/Dockerfile +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/templates/errors/302.twig +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/templates/errors/401.twig +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/templates/errors/403.twig +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/templates/errors/404.twig +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/templates/errors/500.twig +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/templates/errors/502.twig +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/templates/errors/503.twig +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/templates/errors/base.twig +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/templates/frontend/README.md +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/templates/readme.md +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/test/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/test_client/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/translations/af/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/translations/af/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/translations/en/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/translations/en/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/translations/es/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/translations/es/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/translations/fr/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/translations/fr/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/translations/ja/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/translations/ja/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/translations/zh/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/translations/zh/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/validator/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/websocket/__init__.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/websocket/backplane.py +0 -0
- {tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/wsdl/__init__.py +0 -0
|
@@ -961,7 +961,7 @@ uv run tina4python migrate
|
|
|
961
961
|
|
|
962
962
|
- SQL files live in `migrations/` folder, named `NNNNNN_description.sql` (6-digit sequence)
|
|
963
963
|
- Files are executed in **numeric-prefix order** (`9_` before `10_`) and split on the `;` delimiter. A file without a numeric/timestamp prefix logs a warning — its order is undefined
|
|
964
|
-
- State is tracked
|
|
964
|
+
- State is tracked in the `tina4_migration` table (auto-created per engine, canonical columns `id, migration_name VARCHAR(500) NOT NULL UNIQUE, description VARCHAR(500), batch INTEGER NOT NULL DEFAULT 1, executed_at VARCHAR(50) NOT NULL, passed INTEGER NOT NULL DEFAULT 1` — identical across all four frameworks). A migration is **applied** when a row exists for it with `passed = 1` (the applied-read is `WHERE passed = 1`). `migrate()` writes **only `passed = 1` rows**: on a failure the file's transaction is rolled back and **no row is written** for it (it is NOT recorded as `passed=0`), and `migrate()` raises. The public `record_migration(name, batch, passed=...)` API can write a `passed=0` row; any `passed=0` row (including one carried over from a v2 table) is treated as **not applied**, so it is reported pending. A leftover `passed=0` row (a prior failure or a v2 carry-over) **re-applies cleanly**: on the next `migrate()` the success path deletes any existing row for that `migration_name` before writing the fresh `passed=1` row, so the migration runs again instead of colliding on the unique `migration_name` — the bookkeeping table holds at most one row per migration with its latest state. The v2->v3 upgrade logs a warning naming any `passed=0` rows so you know which ones will re-run.
|
|
965
965
|
- **Each migration FILE is wrapped in its own transaction**: on a failure the file rolls back and `migrate()` **raises** (it does not write `passed=0`, delete anything, or `sys.exit`). Already-applied files stay applied — fix the bad file and re-run. The explicit `tina4 migrate` CLI surfaces the raise as a non-zero exit; startup auto-migration logs it and the service still boots (see TINA4_AUTO_MIGRATE above).
|
|
966
966
|
- **Atomicity caveat:** per-file transactions are truly atomic only on engines with **transactional DDL (PostgreSQL)**. MySQL, Firebird, and SQLite auto-commit DDL, so a multi-statement migration that fails midway on those engines leaves earlier statements applied — keep one logical change per file. CREATE TABLE / ALTER-ADD are made idempotent on Firebird/MSSQL (existence-checked) so a re-run doesn't error.
|
|
967
967
|
|
|
@@ -1792,7 +1792,7 @@ async def _api_connections_test(request, response):
|
|
|
1792
1792
|
if not url:
|
|
1793
1793
|
return response({"success": False, "error": "No connection URL provided"})
|
|
1794
1794
|
try:
|
|
1795
|
-
from tina4_python.
|
|
1795
|
+
from tina4_python.database import Database
|
|
1796
1796
|
db = Database(url, username, password)
|
|
1797
1797
|
version = ""
|
|
1798
1798
|
table_count = 0
|
|
@@ -265,7 +265,7 @@ def _upgrade_v2_to_v3(db, migration_folder: str | None) -> None:
|
|
|
265
265
|
logger.error(f"v2→v3 upgrade: failed to backfill {desc!r}: {e}")
|
|
266
266
|
|
|
267
267
|
note = (
|
|
268
|
-
f" ({failed_in_v2} were marked passed=0 in v2
|
|
268
|
+
f" ({failed_in_v2} were marked passed=0 in v2 and will re-apply on the next migrate)"
|
|
269
269
|
if failed_in_v2
|
|
270
270
|
else ""
|
|
271
271
|
)
|
|
@@ -629,6 +629,32 @@ def _should_skip_create_table(db, stmt: str) -> str | None:
|
|
|
629
629
|
return None
|
|
630
630
|
|
|
631
631
|
|
|
632
|
+
def _record_applied(db, name: str, desc: str, batch: int, passed: int = 1) -> None:
|
|
633
|
+
"""Write (or overwrite) the tracking row for a migration.
|
|
634
|
+
|
|
635
|
+
Deletes any existing row for this migration_name first, so a leftover
|
|
636
|
+
passed=0 row (a prior failure, or a v2 carry-over) is superseded and the
|
|
637
|
+
migration re-applies cleanly instead of colliding on the UNIQUE
|
|
638
|
+
migration_name. DELETE+INSERT is portable across every engine (no UPSERT
|
|
639
|
+
dialect variance), leaving at most one row per migration_name with the
|
|
640
|
+
latest recorded state.
|
|
641
|
+
"""
|
|
642
|
+
now = datetime.now(timezone.utc).isoformat()
|
|
643
|
+
db.execute("DELETE FROM tina4_migration WHERE migration_name = ?", [name])
|
|
644
|
+
if _is_firebird(db):
|
|
645
|
+
row = db.fetch_one("SELECT GEN_ID(GEN_TINA4_MIGRATION_ID, 1) AS next_id FROM RDB$DATABASE")
|
|
646
|
+
next_id = row["next_id"] if row else 1
|
|
647
|
+
db.execute(
|
|
648
|
+
"INSERT INTO tina4_migration (id, migration_name, description, batch, executed_at, passed) VALUES (?, ?, ?, ?, ?, ?)",
|
|
649
|
+
[next_id, name, desc, batch, now, passed],
|
|
650
|
+
)
|
|
651
|
+
else:
|
|
652
|
+
db.execute(
|
|
653
|
+
"INSERT INTO tina4_migration (migration_name, description, batch, executed_at, passed) VALUES (?, ?, ?, ?, ?)",
|
|
654
|
+
[name, desc, batch, now, passed],
|
|
655
|
+
)
|
|
656
|
+
|
|
657
|
+
|
|
632
658
|
def _migrate(db, migration_folder: str = "migrations", delimiter: str = ";") -> list[str]:
|
|
633
659
|
"""Run all pending migrations (internal implementation).
|
|
634
660
|
|
|
@@ -688,21 +714,11 @@ def _migrate(db, migration_folder: str = "migrations", delimiter: str = ";") ->
|
|
|
688
714
|
if db.execute(stmt) is False:
|
|
689
715
|
raise RuntimeError(f"Migration failed: {db.get_error() or stmt[:80]}")
|
|
690
716
|
|
|
691
|
-
# Record as passed
|
|
692
|
-
|
|
717
|
+
# Record as passed — supersede any leftover row for this migration
|
|
718
|
+
# (a prior passed=0 failure or a v2 carry-over) so it re-applies
|
|
719
|
+
# cleanly instead of colliding on the UNIQUE migration_name.
|
|
693
720
|
desc = re.sub(r"^\d+_", "", migration_name, count=1).replace("_", " ")
|
|
694
|
-
|
|
695
|
-
row = db.fetch_one("SELECT GEN_ID(GEN_TINA4_MIGRATION_ID, 1) AS next_id FROM RDB$DATABASE")
|
|
696
|
-
next_id = row["next_id"] if row else 1
|
|
697
|
-
db.execute(
|
|
698
|
-
"INSERT INTO tina4_migration (id, migration_name, description, batch, executed_at, passed) VALUES (?, ?, ?, ?, ?, 1)",
|
|
699
|
-
[next_id, migration_name, desc, batch, now],
|
|
700
|
-
)
|
|
701
|
-
else:
|
|
702
|
-
db.execute(
|
|
703
|
-
"INSERT INTO tina4_migration (migration_name, description, batch, executed_at, passed) VALUES (?, ?, ?, ?, 1)",
|
|
704
|
-
[migration_name, desc, batch, now],
|
|
705
|
-
)
|
|
721
|
+
_record_applied(db, migration_name, desc, batch, passed=1)
|
|
706
722
|
db.commit()
|
|
707
723
|
ran.append(mig_file.name)
|
|
708
724
|
|
|
@@ -912,20 +928,8 @@ class Migration:
|
|
|
912
928
|
passed: 1 if the migration succeeded (default), 0 if it failed.
|
|
913
929
|
"""
|
|
914
930
|
_ensure_tracking_table(self._db, self._dir)
|
|
915
|
-
now = datetime.now(timezone.utc).isoformat()
|
|
916
931
|
desc = re.sub(r"^\d+_", "", name, count=1).replace("_", " ")
|
|
917
|
-
|
|
918
|
-
row = self._db.fetch_one("SELECT GEN_ID(GEN_TINA4_MIGRATION_ID, 1) AS next_id FROM RDB$DATABASE")
|
|
919
|
-
next_id = row["next_id"] if row else 1
|
|
920
|
-
self._db.execute(
|
|
921
|
-
"INSERT INTO tina4_migration (id, migration_name, description, batch, executed_at, passed) VALUES (?, ?, ?, ?, ?, ?)",
|
|
922
|
-
[next_id, name, desc, batch, now, passed],
|
|
923
|
-
)
|
|
924
|
-
else:
|
|
925
|
-
self._db.execute(
|
|
926
|
-
"INSERT INTO tina4_migration (migration_name, description, batch, executed_at, passed) VALUES (?, ?, ?, ?, ?)",
|
|
927
|
-
[name, desc, batch, now, passed],
|
|
928
|
-
)
|
|
932
|
+
_record_applied(self._db, name, desc, batch, passed=passed)
|
|
929
933
|
|
|
930
934
|
def remove_migration_record(self, name: str) -> None:
|
|
931
935
|
"""Delete a migration record from the tracking table by migration ID.
|
|
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.72 → tina4_python-3.13.74}/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.72 → tina4_python-3.13.74}/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.72 → tina4_python-3.13.74}/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.72 → tina4_python-3.13.74}/tina4_python/session_handlers/mongodb_handler.py
RENAMED
|
File without changes
|
{tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/session_handlers/redis_handler.py
RENAMED
|
File without changes
|
{tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/session_handlers/valkey_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/templates/docker/distroless/Dockerfile
RENAMED
|
File without changes
|
{tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/templates/docker/poetry/Dockerfile
RENAMED
|
File without changes
|
{tina4_python-3.13.72 → tina4_python-3.13.74}/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.72 → tina4_python-3.13.74}/tina4_python/translations/af/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/translations/af/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/translations/en/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/translations/en/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/translations/es/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/translations/es/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/translations/fr/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/translations/fr/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/translations/ja/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/translations/ja/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/translations/zh/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.72 → tina4_python-3.13.74}/tina4_python/translations/zh/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|