tina4-python 3.13.120__tar.gz → 3.13.121__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.120 → tina4_python-3.13.121}/PKG-INFO +1 -1
- {tina4_python-3.13.120 → tina4_python-3.13.121}/pyproject.toml +1 -1
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/__init__.py +1 -1
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/cli/__init__.py +37 -6
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/mcp/tools.py +93 -15
- {tina4_python-3.13.120 → tina4_python-3.13.121}/.gitignore +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/README.md +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/CLAUDE.md +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/HtmlElement.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/Testing.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/_import_helper.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/ai/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/ai/client.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/api/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/auth/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/cache/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/container/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/context/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/context/chunker.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/core/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/core/cache.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/core/constants.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/core/events.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/core/middleware.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/core/port_takeover.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/core/rate_limiter.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/core/request.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/core/response.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/core/router.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/core/server.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/crud/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/database/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/database/adapter.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/database/connection.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/database/database_url.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/database/firebird.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/database/mongodb.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/database/mssql.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/database/mysql.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/database/odbc.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/database/postgres.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/database/sql_translator.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/database/sqlite.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/debug/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/debug/error_overlay.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/dev_admin/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/dev_admin/metrics.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/dev_admin/plan.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/dev_admin/project_index.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/docs.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/docstore/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/dotenv/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/env.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/frond/FROND.md +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/frond/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/frond/compiler.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/frond/engine.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/frond/parser.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/gallery/auth/meta.json +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/gallery/auth/src/routes/api/gallery_auth.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/gallery/database/meta.json +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/gallery/database/src/routes/api/gallery_db.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/gallery/error-overlay/meta.json +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/gallery/error-overlay/src/routes/api/gallery_crash.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/gallery/orm/meta.json +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/gallery/orm/src/orm/Product.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/gallery/orm/src/routes/api/gallery_products.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/gallery/queue/meta.json +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/gallery/queue/src/routes/api/gallery_queue.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/gallery/rest-api/meta.json +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/gallery/rest-api/src/routes/api/gallery_hello.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/gallery/templates/meta.json +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/gallery/templates/src/routes/gallery_page.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/gallery/templates/src/templates/gallery_page.twig +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/graph/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/graph/adapter.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/graph/adapters/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/graph/adapters/arango.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/graph/adapters/bolt.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/graph/adapters/ultipa.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/graph/graph_url.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/graphql/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/i18n/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/mcp/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/mcp/protocol.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/messenger/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/migration/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/migration/runner.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/mqtt/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/mqtt/message.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/orm/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/orm/fields.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/orm/model.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/orm/point.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/public/__feedback/widget.js +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/public/css/tina4.css +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/public/css/tina4.min.css +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/public/favicon.ico +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/public/images/logo.svg +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/public/images/tina4-logo-icon.webp +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/public/js/frond.js +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/public/js/frond.min.js +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/public/js/tina4-dev-admin.min.js +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/public/js/tina4.min.js +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/public/js/tina4js.min.js +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/public/swagger/index.html +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/public/swagger/oauth2-redirect.html +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/query_builder/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/queue/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/queue/amqp_url.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/queue/job.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/queue/kafka_backend.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/queue/lite_backend.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/queue/mongo_backend.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/queue/rabbitmq_backend.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/queue_backends/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/queue_backends/kafka_backend.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/queue_backends/mongo_backend.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/queue_backends/rabbitmq_backend.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/realtime/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/realtime/models/Attachment.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/realtime/models/Channel.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/realtime/models/ChannelMember.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/realtime/models/Message.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/realtime/models/Workspace.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/realtime/models/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/realtime/storage.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/seeder/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/service/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/session/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/session_handlers/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/session_handlers/memcached_handler.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/session_handlers/mongodb_handler.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/session_handlers/redis_handler.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/session_handlers/valkey_handler.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/sso.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/swagger/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/templates/components/crud.twig +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/templates/docker/distroless/Dockerfile +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/templates/docker/poetry/Dockerfile +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/templates/docker/python/Dockerfile +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/templates/docker/uv/Dockerfile +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/templates/errors/302.twig +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/templates/errors/401.twig +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/templates/errors/403.twig +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/templates/errors/404.twig +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/templates/errors/500.twig +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/templates/errors/502.twig +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/templates/errors/503.twig +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/templates/errors/base.twig +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/templates/frontend/README.md +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/templates/readme.md +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/test/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/test_client/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/translations/af/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/translations/af/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/translations/en/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/translations/en/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/translations/es/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/translations/es/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/translations/fr/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/translations/fr/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/translations/ja/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/translations/ja/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/translations/zh/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/translations/zh/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/validator/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/websocket/__init__.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/websocket/backplane.py +0 -0
- {tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/wsdl/__init__.py +0 -0
|
@@ -732,14 +732,35 @@ def _migrate(args):
|
|
|
732
732
|
|
|
733
733
|
|
|
734
734
|
def _migrate_create(args):
|
|
735
|
-
"""Create a new migration file.
|
|
735
|
+
"""Create a new migration file.
|
|
736
|
+
|
|
737
|
+
Thin delegation to `_emit_resolution("migration", ...)` — the same code
|
|
738
|
+
path `tina4python generate migration <desc>` takes — so both CLI surfaces
|
|
739
|
+
emit the SAME ADR-0063 `generate_v1_1` envelope, the SAME `tina4:edit`
|
|
740
|
+
markers in the file, and the SAME next-steps block. The only intentional
|
|
741
|
+
difference is that `migrate:create` never co-emits a test file (a private
|
|
742
|
+
`_no_test` marker on the flags dict suppresses the test-emit path in
|
|
743
|
+
`_gen_migration` and drops `test_paths[]` in the resolution), preserving
|
|
744
|
+
the "just a migration, no test" contract of `migrate:create`. Neither
|
|
745
|
+
surface is deprecated; both stay first-class producers of the envelope.
|
|
746
|
+
|
|
747
|
+
The Python API `create_migration()` in `tina4_python.migration.runner` is
|
|
748
|
+
unchanged and still callable directly.
|
|
749
|
+
"""
|
|
736
750
|
if not args:
|
|
737
751
|
print("Usage: tina4python migrate:create <description>")
|
|
738
752
|
sys.exit(1)
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
753
|
+
# Split flags vs positional so `--json` / `--dry-run` flow through the
|
|
754
|
+
# envelope emitter (bare word args form the description).
|
|
755
|
+
flags, positional = _parse_flags(list(args))
|
|
756
|
+
if not positional:
|
|
757
|
+
print("Usage: tina4python migrate:create <description>")
|
|
758
|
+
sys.exit(1)
|
|
759
|
+
desc = " ".join(positional)
|
|
760
|
+
# Private marker read by _gen_migration + _resolve_generation to suppress
|
|
761
|
+
# the co-emitted test — see the `migrate:create` contract above.
|
|
762
|
+
flags["_no_test"] = True
|
|
763
|
+
_emit_resolution("migration", desc, flags)
|
|
743
764
|
|
|
744
765
|
|
|
745
766
|
def _migrate_rollback(args):
|
|
@@ -1189,6 +1210,10 @@ def _resolve_generation(target: str, name: str, flags: dict,
|
|
|
1189
1210
|
table = _to_snake(table)
|
|
1190
1211
|
filename = f"{ts}_{name}.sql"
|
|
1191
1212
|
is_create = name.startswith("create_")
|
|
1213
|
+
# Private `_no_test` marker (set by `migrate:create`, which is a
|
|
1214
|
+
# single-file operation): drop `test_paths[]` so the envelope
|
|
1215
|
+
# matches the on-disk effect. `_gen_migration` reads the same flag.
|
|
1216
|
+
want_test = is_create and not flags.get("_no_test")
|
|
1192
1217
|
return {
|
|
1193
1218
|
"class_name": None,
|
|
1194
1219
|
"table_name": table,
|
|
@@ -1196,7 +1221,7 @@ def _resolve_generation(target: str, name: str, flags: dict,
|
|
|
1196
1221
|
"migration_path": f"migrations/{filename}",
|
|
1197
1222
|
"transformations": [],
|
|
1198
1223
|
"routes": [],
|
|
1199
|
-
"test_paths": [f"tests/test_{table}_migration.py"] if
|
|
1224
|
+
"test_paths": [f"tests/test_{table}_migration.py"] if want_test else [],
|
|
1200
1225
|
}
|
|
1201
1226
|
|
|
1202
1227
|
if target == "middleware":
|
|
@@ -1862,6 +1887,12 @@ def _gen_migration(name: str, flags: dict = None, *,
|
|
|
1862
1887
|
# snapshotted timestamp; if it was supplied via the private `_timestamp`
|
|
1863
1888
|
# flag, honour it so envelope and disk agree byte-for-byte.
|
|
1864
1889
|
timestamp = flags.get("_timestamp") or now.strftime("%Y%m%d%H%M%S")
|
|
1890
|
+
# Private `_no_test` marker (set by `migrate:create`, which is a
|
|
1891
|
+
# single-file operation): suppress the co-emitted test regardless of the
|
|
1892
|
+
# keyword default. `_resolve_generation` reads the same marker so the
|
|
1893
|
+
# envelope's `test_paths[]` and the on-disk effect stay in agreement.
|
|
1894
|
+
if flags.get("_no_test"):
|
|
1895
|
+
emit_test = False
|
|
1865
1896
|
target = Path("migrations")
|
|
1866
1897
|
target.mkdir(parents=True, exist_ok=True)
|
|
1867
1898
|
|
|
@@ -506,28 +506,63 @@ def register_dev_tools(server):
|
|
|
506
506
|
return status(db)
|
|
507
507
|
|
|
508
508
|
def migration_create(description: str) -> dict:
|
|
509
|
-
"""Create a new migration file
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
same
|
|
514
|
-
|
|
509
|
+
"""Create a new migration file AND return the ADR-0063 `generate_v1_1`
|
|
510
|
+
envelope so an agent gets the SAME edit_hints[]/next[] guidance a CLI
|
|
511
|
+
user gets.
|
|
512
|
+
|
|
513
|
+
Delegates to the same resolution-aware code path the CLI's
|
|
514
|
+
`tina4python migrate:create` / `tina4python generate migration` uses.
|
|
515
|
+
The private `_no_test` flag matches the migrate:create contract (no
|
|
516
|
+
co-emitted test file — a migration is a single-file operation).
|
|
517
|
+
|
|
518
|
+
Refuses to create a duplicate for a description whose slug already
|
|
519
|
+
exists in migrations/ — returns `{"ok": False, "existing": [...]}`
|
|
520
|
+
so the AI edits the existing file instead of spawning a second
|
|
521
|
+
migration for the same schema change. On collision the envelope is
|
|
522
|
+
NOT emitted (the operation did not run).
|
|
523
|
+
|
|
524
|
+
Return shape (MCP wire contract):
|
|
525
|
+
{"ok": True, "created": "<relative-path>", "resolution": <envelope>}
|
|
526
|
+
— success. `created` is the primary UP file path (preserves
|
|
527
|
+
the historical MCP field). `resolution` is the full CLI
|
|
528
|
+
envelope with `command`, `target`, `input`, nested
|
|
529
|
+
`resolution` (edit_hints + next + file_path), actions_taken,
|
|
530
|
+
dry_run.
|
|
531
|
+
{"ok": False, "error": "...", "existing": [...]}
|
|
532
|
+
— refused collision. No file was written. Envelope omitted.
|
|
533
|
+
"""
|
|
534
|
+
import contextlib
|
|
535
|
+
import io
|
|
515
536
|
import re as _re
|
|
537
|
+
from datetime import datetime as _dt
|
|
538
|
+
|
|
539
|
+
# Slug the description before delegating so the on-disk filename is
|
|
540
|
+
# well-formed even when the caller passed a natural-language phrase
|
|
541
|
+
# ("add users"). Matches the historical `create_migration()` behaviour
|
|
542
|
+
# this tool used to delegate to.
|
|
516
543
|
slug = _re.sub(r"[^a-z0-9]+", "_", (description or "").lower()).strip("_")
|
|
544
|
+
if not slug:
|
|
545
|
+
return {
|
|
546
|
+
"ok": False,
|
|
547
|
+
"error": "description is empty; provide a short snake_case name",
|
|
548
|
+
}
|
|
549
|
+
|
|
517
550
|
mig_dir = project_root / "migrations"
|
|
518
|
-
if mig_dir.is_dir()
|
|
519
|
-
# Compare against existing migration slugs (strip the
|
|
520
|
-
#
|
|
521
|
-
#
|
|
551
|
+
if mig_dir.is_dir():
|
|
552
|
+
# Compare against existing migration slugs (strip the leading
|
|
553
|
+
# timestamp and .sql/.down.sql extension). Reuse if an exact
|
|
554
|
+
# slug OR a clearly-equivalent slug exists.
|
|
522
555
|
existing: list[str] = []
|
|
523
556
|
for p in sorted(mig_dir.glob("*.sql")):
|
|
524
|
-
|
|
557
|
+
fname = p.name
|
|
525
558
|
# Files look like "20260417175842_create_contact_messages_table.sql".
|
|
526
559
|
# Strip the timestamp prefix (14 digits + underscore) and the suffix.
|
|
527
|
-
after = _re.sub(r"^\d{14}_", "",
|
|
560
|
+
after = _re.sub(r"^\d{14}_", "", fname)
|
|
528
561
|
after = _re.sub(r"\.(down\.)?sql$", "", after)
|
|
529
562
|
existing_slug = _re.sub(r"[^a-z0-9]+", "_", after.lower()).strip("_")
|
|
530
|
-
if existing_slug == slug
|
|
563
|
+
if (existing_slug == slug
|
|
564
|
+
or existing_slug == slug + "_table"
|
|
565
|
+
or slug == existing_slug + "_table"):
|
|
531
566
|
existing.append(str(p.relative_to(project_root)))
|
|
532
567
|
if existing:
|
|
533
568
|
return {
|
|
@@ -538,9 +573,52 @@ def register_dev_tools(server):
|
|
|
538
573
|
),
|
|
539
574
|
"existing": existing,
|
|
540
575
|
}
|
|
541
|
-
|
|
576
|
+
|
|
577
|
+
# Delegate to the same resolution-aware helpers the CLI uses so both
|
|
578
|
+
# surfaces produce byte-for-byte equivalent envelopes (modulo timestamp
|
|
579
|
+
# + file paths). Imported lazily to avoid pulling the CLI into every
|
|
580
|
+
# MCP tool-registration path.
|
|
581
|
+
from tina4_python.cli import (
|
|
582
|
+
_actions_from_resolution,
|
|
583
|
+
_gen_migration,
|
|
584
|
+
_hint_paths_from_resolution,
|
|
585
|
+
_input_fields,
|
|
586
|
+
_next_steps_for,
|
|
587
|
+
_resolve_generation,
|
|
588
|
+
_scan_edit_hints,
|
|
589
|
+
)
|
|
590
|
+
|
|
591
|
+
flags = {"_no_test": True}
|
|
592
|
+
# Lock the timestamp so `resolution.file_path` and the on-disk filename
|
|
593
|
+
# agree byte-for-byte (threaded to `_gen_migration` via `_timestamp`).
|
|
594
|
+
timestamp = _dt.now().strftime("%Y%m%d%H%M%S")
|
|
595
|
+
resolution = _resolve_generation("migration", slug, flags, timestamp=timestamp)
|
|
596
|
+
|
|
597
|
+
generator_flags = dict(flags)
|
|
598
|
+
generator_flags["_timestamp"] = timestamp
|
|
599
|
+
# Swallow the generator's own " ✓ Created …" prints — MCP returns
|
|
600
|
+
# JSON to the caller, never text on stdout.
|
|
601
|
+
with contextlib.redirect_stdout(io.StringIO()):
|
|
602
|
+
_gen_migration(slug, generator_flags)
|
|
603
|
+
|
|
604
|
+
actions_taken = _actions_from_resolution("migration", resolution)
|
|
605
|
+
hint_paths = _hint_paths_from_resolution("migration", resolution)
|
|
606
|
+
edit_hints = _scan_edit_hints(project_root, hint_paths)
|
|
607
|
+
next_steps = _next_steps_for("migration", slug, resolution, flags)
|
|
608
|
+
resolution["edit_hints"] = edit_hints
|
|
609
|
+
resolution["next"] = next_steps
|
|
610
|
+
|
|
611
|
+
envelope = {
|
|
612
|
+
"command": "generate",
|
|
613
|
+
"target": "migration",
|
|
614
|
+
"input": {"name": slug, "fields": _input_fields(flags)},
|
|
615
|
+
"resolution": resolution,
|
|
616
|
+
"actions_taken": actions_taken,
|
|
617
|
+
"dry_run": False,
|
|
618
|
+
}
|
|
619
|
+
filename = resolution["file_path"] # "migrations/{ts}_{slug}.sql"
|
|
542
620
|
_record_plan_action("migration", filename, note=description)
|
|
543
|
-
return {"created": filename}
|
|
621
|
+
return {"ok": True, "created": filename, "resolution": envelope}
|
|
544
622
|
|
|
545
623
|
def _record_plan_action(action: str, path: str, note: str = "") -> None:
|
|
546
624
|
"""Forward a file event to the active plan's execution ledger.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
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.120 → tina4_python-3.13.121}/tina4_python/gallery/error-overlay/meta.json
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
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/public/images/tina4-logo-icon.webp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/public/js/tina4-dev-admin.min.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/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
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/queue_backends/kafka_backend.py
RENAMED
|
File without changes
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/queue_backends/mongo_backend.py
RENAMED
|
File without changes
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/queue_backends/rabbitmq_backend.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/realtime/models/ChannelMember.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
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/session_handlers/memcached_handler.py
RENAMED
|
File without changes
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/session_handlers/mongodb_handler.py
RENAMED
|
File without changes
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/session_handlers/redis_handler.py
RENAMED
|
File without changes
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/session_handlers/valkey_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/templates/docker/distroless/Dockerfile
RENAMED
|
File without changes
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/templates/docker/poetry/Dockerfile
RENAMED
|
File without changes
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/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.120 → tina4_python-3.13.121}/tina4_python/translations/af/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/translations/af/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/translations/en/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/translations/en/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/translations/es/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/translations/es/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/translations/fr/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/translations/fr/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/translations/ja/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/translations/ja/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/translations/zh/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.120 → tina4_python-3.13.121}/tina4_python/translations/zh/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|