tina4-python 3.13.132__tar.gz → 3.13.133__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.132 → tina4_python-3.13.133}/PKG-INFO +1 -1
- {tina4_python-3.13.132 → tina4_python-3.13.133}/pyproject.toml +1 -1
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/__init__.py +1 -1
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/swagger/__init__.py +227 -175
- {tina4_python-3.13.132 → tina4_python-3.13.133}/.gitignore +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/README.md +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/CLAUDE.md +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/HtmlElement.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/Testing.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/_import_helper.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/ai/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/ai/client.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/api/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/auth/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/cache/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/cli/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/container/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/context/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/context/chunker.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/core/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/core/cache.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/core/constants.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/core/events.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/core/middleware.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/core/port_takeover.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/core/rate_limiter.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/core/request.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/core/response.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/core/router.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/core/server.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/crud/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/database/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/database/adapter.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/database/connection.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/database/database_url.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/database/firebird.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/database/mongodb.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/database/mssql.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/database/mysql.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/database/odbc.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/database/postgres.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/database/sql_translator.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/database/sqlite.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/debug/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/debug/error_overlay.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/dev_admin/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/dev_admin/metrics.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/dev_admin/plan.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/dev_admin/project_index.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/docs.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/docstore/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/dotenv/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/env.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/frond/FROND.md +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/frond/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/frond/compiler.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/frond/engine.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/frond/parser.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/gallery/auth/meta.json +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/gallery/auth/src/routes/api/gallery_auth.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/gallery/database/meta.json +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/gallery/database/src/routes/api/gallery_db.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/gallery/error-overlay/meta.json +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/gallery/error-overlay/src/routes/api/gallery_crash.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/gallery/orm/meta.json +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/gallery/orm/src/orm/Product.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/gallery/orm/src/routes/api/gallery_products.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/gallery/queue/meta.json +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/gallery/queue/src/routes/api/gallery_queue.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/gallery/rest-api/meta.json +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/gallery/rest-api/src/routes/api/gallery_hello.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/gallery/templates/meta.json +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/gallery/templates/src/routes/gallery_page.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/gallery/templates/src/templates/gallery_page.twig +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/graph/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/graph/adapter.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/graph/adapters/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/graph/adapters/arango.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/graph/adapters/bolt.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/graph/adapters/ultipa.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/graph/graph_url.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/graphql/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/i18n/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/mcp/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/mcp/protocol.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/mcp/tools.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/messenger/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/migration/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/migration/runner.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/mqtt/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/mqtt/message.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/orm/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/orm/collection.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/orm/fields.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/orm/model.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/orm/point.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/public/__feedback/widget.js +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/public/css/tina4.css +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/public/css/tina4.min.css +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/public/favicon.ico +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/public/images/logo.svg +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/public/images/tina4-logo-icon.webp +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/public/js/frond.js +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/public/js/frond.min.js +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/public/js/tina4-dev-admin.min.js +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/public/js/tina4.min.js +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/public/js/tina4js.min.js +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/public/swagger/index.html +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/public/swagger/oauth2-redirect.html +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/query_builder/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/queue/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/queue/amqp_url.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/queue/job.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/queue/kafka_backend.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/queue/lite_backend.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/queue/mongo_backend.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/queue/rabbitmq_backend.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/queue_backends/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/queue_backends/kafka_backend.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/queue_backends/mongo_backend.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/queue_backends/rabbitmq_backend.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/realtime/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/realtime/models/Attachment.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/realtime/models/Channel.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/realtime/models/ChannelMember.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/realtime/models/Message.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/realtime/models/Workspace.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/realtime/models/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/realtime/storage.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/seeder/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/service/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/session/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/session_handlers/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/session_handlers/memcached_handler.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/session_handlers/mongodb_handler.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/session_handlers/redis_handler.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/session_handlers/valkey_handler.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/sso.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/templates/components/crud.twig +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/templates/docker/distroless/Dockerfile +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/templates/docker/poetry/Dockerfile +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/templates/docker/python/Dockerfile +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/templates/docker/uv/Dockerfile +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/templates/errors/302.twig +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/templates/errors/401.twig +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/templates/errors/403.twig +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/templates/errors/404.twig +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/templates/errors/500.twig +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/templates/errors/502.twig +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/templates/errors/503.twig +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/templates/errors/base.twig +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/templates/frontend/README.md +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/templates/readme.md +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/test/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/test_client/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/translations/af/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/translations/af/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/translations/en/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/translations/en/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/translations/es/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/translations/es/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/translations/fr/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/translations/fr/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/translations/ja/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/translations/ja/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/translations/zh/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/translations/zh/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/validator/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/websocket/__init__.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/websocket/backplane.py +0 -0
- {tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/wsdl/__init__.py +0 -0
|
@@ -469,27 +469,10 @@ class Swagger:
|
|
|
469
469
|
Each route dict should have:
|
|
470
470
|
method, path, handler, auth_required (optional)
|
|
471
471
|
"""
|
|
472
|
-
info = {
|
|
473
|
-
"title": self.title,
|
|
474
|
-
"version": self.version,
|
|
475
|
-
"description": self.description,
|
|
476
|
-
}
|
|
477
|
-
contact = {}
|
|
478
|
-
if self.contact_team:
|
|
479
|
-
contact["name"] = self.contact_team
|
|
480
|
-
if self.contact_url:
|
|
481
|
-
contact["url"] = self.contact_url
|
|
482
|
-
if self.contact_email:
|
|
483
|
-
contact["email"] = self.contact_email
|
|
484
|
-
if contact:
|
|
485
|
-
info["contact"] = contact
|
|
486
|
-
if self.license_name:
|
|
487
|
-
info["license"] = {"name": self.license_name}
|
|
488
|
-
|
|
489
472
|
schemes = self._security_schemes()
|
|
490
473
|
spec = {
|
|
491
474
|
"openapi": self.openapi_version,
|
|
492
|
-
"info":
|
|
475
|
+
"info": self._build_info(),
|
|
493
476
|
"servers": self._servers(),
|
|
494
477
|
"paths": {},
|
|
495
478
|
"components": {
|
|
@@ -507,182 +490,251 @@ class Swagger:
|
|
|
507
490
|
continue
|
|
508
491
|
path = self._openapi_path(route["path"])
|
|
509
492
|
method = route["method"].lower()
|
|
510
|
-
handler = route.get("handler")
|
|
511
|
-
|
|
512
493
|
if path not in spec["paths"]:
|
|
513
494
|
spec["paths"][path] = {}
|
|
514
495
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
"200": {"description": "Successful response"},
|
|
519
|
-
},
|
|
520
|
-
}
|
|
496
|
+
spec["paths"][path][method] = self._build_operation(
|
|
497
|
+
route, path, method, schemes, models, ref_schemas, used_tags, seen_ids
|
|
498
|
+
)
|
|
521
499
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
500
|
+
self._build_component_schemas(spec, models, ref_schemas)
|
|
501
|
+
|
|
502
|
+
# top-level tags[] (name-only is valid OpenAPI; descriptions optional)
|
|
503
|
+
if used_tags:
|
|
504
|
+
spec["tags"] = [{"name": t} for t in used_tags]
|
|
505
|
+
|
|
506
|
+
return spec
|
|
507
|
+
|
|
508
|
+
# ── generate() building blocks ─────────────────────────────────
|
|
509
|
+
# generate() is a thin orchestrator; each cohesive slice of the spec
|
|
510
|
+
# (info block, one path operation, components) is built by one helper so
|
|
511
|
+
# the top-level function stays readable. The emitted document is unchanged.
|
|
512
|
+
|
|
513
|
+
def _build_info(self) -> dict:
|
|
514
|
+
"""Build the OpenAPI info block: title/version/description plus the
|
|
515
|
+
optional contact and license blocks (each key present only when set)."""
|
|
516
|
+
info = {
|
|
517
|
+
"title": self.title,
|
|
518
|
+
"version": self.version,
|
|
519
|
+
"description": self.description,
|
|
520
|
+
}
|
|
521
|
+
contact = {}
|
|
522
|
+
if self.contact_team:
|
|
523
|
+
contact["name"] = self.contact_team
|
|
524
|
+
if self.contact_url:
|
|
525
|
+
contact["url"] = self.contact_url
|
|
526
|
+
if self.contact_email:
|
|
527
|
+
contact["email"] = self.contact_email
|
|
528
|
+
if contact:
|
|
529
|
+
info["contact"] = contact
|
|
530
|
+
if self.license_name:
|
|
531
|
+
info["license"] = {"name": self.license_name}
|
|
532
|
+
return info
|
|
533
|
+
|
|
534
|
+
def _build_operation(self, route: dict, path: str, method: str, schemes: dict,
|
|
535
|
+
models: dict, ref_schemas: set, used_tags: list,
|
|
536
|
+
seen_ids: set) -> dict:
|
|
537
|
+
"""Build the OpenAPI operation object for one route (method + path).
|
|
538
|
+
|
|
539
|
+
Accumulators (models/ref_schemas/used_tags/seen_ids) are threaded through
|
|
540
|
+
and mutated in place, exactly as the inline loop did.
|
|
541
|
+
"""
|
|
542
|
+
handler = route.get("handler")
|
|
543
|
+
|
|
544
|
+
operation = {
|
|
545
|
+
"operationId": self._unique_operation_id(method, path, seen_ids),
|
|
546
|
+
"responses": {
|
|
547
|
+
"200": {"description": "Successful response"},
|
|
548
|
+
},
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
model = getattr(handler, "_swagger_model", None) if handler else None
|
|
552
|
+
ref = None
|
|
553
|
+
if model is not None and hasattr(model, "_fields"):
|
|
554
|
+
models[model.__name__] = model
|
|
555
|
+
ref = f"#/components/schemas/{model.__name__}"
|
|
556
|
+
|
|
557
|
+
self._operation_summary_tags(operation, route, method, handler, used_tags)
|
|
558
|
+
|
|
559
|
+
# Extract metadata from handler decorators
|
|
560
|
+
if handler:
|
|
561
|
+
self._operation_metadata(operation, handler)
|
|
562
|
+
self._operation_request_body(operation, handler, method, ref, ref_schemas)
|
|
563
|
+
self._operation_responses(operation, handler, ref)
|
|
564
|
+
self._operation_response_schemas(operation, handler, ref_schemas)
|
|
565
|
+
|
|
566
|
+
self._operation_parameters(operation, route, handler)
|
|
567
|
+
self._operation_security(operation, route, handler, schemes)
|
|
568
|
+
return operation
|
|
569
|
+
|
|
570
|
+
def _operation_summary_tags(self, operation: dict, route: dict, method: str,
|
|
571
|
+
handler, used_tags: list) -> None:
|
|
572
|
+
"""Populate summary + tags (SWAG-SHAPE-DRIFT, ADR-0004) — always present.
|
|
573
|
+
|
|
574
|
+
An explicit @summary/@tags wins; otherwise a "METHOD /path" summary and a
|
|
575
|
+
first-path-segment tag match the other three frameworks' fallback. Each
|
|
576
|
+
used tag is recorded (insertion-ordered) for the top-level tags[] array.
|
|
577
|
+
"""
|
|
578
|
+
operation["summary"] = (
|
|
579
|
+
getattr(handler, "_swagger_summary", None) if handler else None
|
|
580
|
+
) or f"{method.upper()} {route['path']}"
|
|
581
|
+
op_tags = (
|
|
582
|
+
getattr(handler, "_swagger_tags", None) if handler else None
|
|
583
|
+
) or [self._infer_tag(route["path"])]
|
|
584
|
+
operation["tags"] = op_tags
|
|
585
|
+
for t in op_tags:
|
|
586
|
+
if t not in used_tags:
|
|
587
|
+
used_tags.append(t)
|
|
588
|
+
|
|
589
|
+
@staticmethod
|
|
590
|
+
def _operation_metadata(operation: dict, handler) -> None:
|
|
591
|
+
"""Apply @description(+detail) and @deprecated decorator metadata."""
|
|
592
|
+
desc = getattr(handler, "_swagger_description", None)
|
|
593
|
+
detail = getattr(handler, "_swagger_detail", None)
|
|
594
|
+
if desc is not None or detail:
|
|
595
|
+
operation["description"] = "\n\n".join(
|
|
596
|
+
p for p in (desc, detail) if p
|
|
597
|
+
)
|
|
598
|
+
if hasattr(handler, "_swagger_deprecated"):
|
|
599
|
+
operation["deprecated"] = True
|
|
600
|
+
|
|
601
|
+
def _operation_request_body(self, operation: dict, handler, method: str,
|
|
602
|
+
ref, ref_schemas: set) -> None:
|
|
603
|
+
"""Build requestBody for write methods — a $ref to a registered request
|
|
604
|
+
schema (preferred), else the model schema, else an inferred schema from
|
|
605
|
+
@example. application/json unless the example declares multipart/form-data."""
|
|
606
|
+
if method not in ("post", "put", "patch"):
|
|
607
|
+
return
|
|
608
|
+
req_schema = getattr(handler, "_swagger_request_schema", None)
|
|
609
|
+
ct = getattr(handler, "_swagger_example_content_type", "application/json")
|
|
610
|
+
ex = getattr(handler, "_swagger_example", None)
|
|
611
|
+
media: dict = {}
|
|
612
|
+
if req_schema is not None:
|
|
613
|
+
sname, sct = req_schema
|
|
614
|
+
ct = sct or ct
|
|
615
|
+
ref_schemas.add(sname)
|
|
616
|
+
media["schema"] = {"$ref": f"#/components/schemas/{sname}"}
|
|
617
|
+
elif ref is not None:
|
|
618
|
+
media["schema"] = {"$ref": ref}
|
|
619
|
+
elif ex is not None:
|
|
620
|
+
media["schema"] = self._infer_schema(ex)
|
|
621
|
+
if ex is not None:
|
|
622
|
+
media["example"] = ex
|
|
623
|
+
if media:
|
|
624
|
+
operation["requestBody"] = {"content": {ct: media}}
|
|
625
|
+
|
|
626
|
+
def _operation_responses(self, operation: dict, handler, ref) -> None:
|
|
627
|
+
"""Populate responses: model $ref (single or list), then any per-status
|
|
628
|
+
@example_response entries (explicit wins), then the legacy single-example."""
|
|
629
|
+
if ref is not None:
|
|
630
|
+
is_list = getattr(handler, "_swagger_model_list", False)
|
|
631
|
+
schema = ({"type": "array", "items": {"$ref": ref}} if is_list
|
|
632
|
+
else {"$ref": ref})
|
|
633
|
+
operation["responses"]["200"] = {
|
|
634
|
+
"description": "Successful response",
|
|
635
|
+
"content": {"application/json": {"schema": schema}},
|
|
636
|
+
}
|
|
637
|
+
resp_examples = getattr(handler, "_swagger_example_responses", None)
|
|
638
|
+
if resp_examples:
|
|
639
|
+
for status_code, body in resp_examples.items():
|
|
640
|
+
operation["responses"][str(status_code)] = {
|
|
641
|
+
"description": "Successful response" if str(status_code).startswith("2") else "Response",
|
|
642
|
+
"content": {
|
|
643
|
+
"application/json": {
|
|
644
|
+
"schema": self._infer_schema(body),
|
|
645
|
+
"example": body,
|
|
598
646
|
}
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
647
|
+
},
|
|
648
|
+
}
|
|
649
|
+
elif hasattr(handler, "_swagger_example_response") and ref is None:
|
|
650
|
+
# Legacy single-example back-compat (no per-status dict).
|
|
651
|
+
ex = handler._swagger_example_response
|
|
652
|
+
operation["responses"]["200"] = {
|
|
653
|
+
"description": "Successful response",
|
|
654
|
+
"content": {
|
|
655
|
+
"application/json": {
|
|
656
|
+
"schema": self._infer_schema(ex),
|
|
657
|
+
"example": ex,
|
|
610
658
|
}
|
|
659
|
+
},
|
|
660
|
+
}
|
|
611
661
|
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
662
|
+
@staticmethod
|
|
663
|
+
def _operation_response_schemas(operation: dict, handler, ref_schemas: set) -> None:
|
|
664
|
+
"""Apply registered response schemas ($ref) — explicit and authoritative.
|
|
665
|
+
swagger response_schemas: {status: (name, is_list)}."""
|
|
666
|
+
resp_schemas = getattr(handler, "_swagger_response_schemas", None)
|
|
667
|
+
if not resp_schemas:
|
|
668
|
+
return
|
|
669
|
+
for status_code, (sname, is_list) in resp_schemas.items():
|
|
670
|
+
ref_schemas.add(sname)
|
|
671
|
+
sref = f"#/components/schemas/{sname}"
|
|
672
|
+
schema = ({"type": "array", "items": {"$ref": sref}} if is_list
|
|
673
|
+
else {"$ref": sref})
|
|
674
|
+
operation["responses"][str(status_code)] = {
|
|
675
|
+
"description": "Successful response" if str(status_code).startswith("2") else "Response",
|
|
676
|
+
"content": {"application/json": {"schema": schema}},
|
|
677
|
+
}
|
|
624
678
|
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
679
|
+
def _operation_parameters(self, operation: dict, route: dict, handler) -> None:
|
|
680
|
+
"""Build parameters: path params (+ types) then query params from
|
|
681
|
+
@description(query=). Path-param descriptions come from @description(params=)."""
|
|
682
|
+
params = self._extract_path_params(route["path"])
|
|
683
|
+
if handler:
|
|
684
|
+
pdocs = getattr(handler, "_swagger_params", None) or {}
|
|
685
|
+
for p in params:
|
|
686
|
+
if p["name"] in pdocs:
|
|
687
|
+
p["description"] = str(pdocs[p["name"]])
|
|
688
|
+
qdocs = getattr(handler, "_swagger_query", None) or {}
|
|
689
|
+
for qname, qdesc in qdocs.items():
|
|
690
|
+
params.append({
|
|
691
|
+
"name": qname,
|
|
692
|
+
"in": "query",
|
|
693
|
+
"required": False,
|
|
694
|
+
"description": str(qdesc),
|
|
695
|
+
"schema": {"type": "string"},
|
|
696
|
+
})
|
|
697
|
+
if params:
|
|
698
|
+
operation["parameters"] = params
|
|
699
|
+
|
|
700
|
+
def _operation_security(self, operation: dict, route: dict, handler,
|
|
701
|
+
schemes: dict) -> None:
|
|
702
|
+
"""Merge the per-route security requirement.
|
|
703
|
+
|
|
704
|
+
Explicit @security wins (an empty list = explicitly public); otherwise a
|
|
705
|
+
secured route gets the default scheme. A secured operation documents a 401
|
|
706
|
+
(SWAG-401-SHAPE, ADR-0004) — setdefault so an explicit
|
|
707
|
+
@example_response(401, ...) is never clobbered.
|
|
708
|
+
"""
|
|
709
|
+
sec = getattr(handler, "_swagger_security", None) if handler else None
|
|
710
|
+
if sec is not None:
|
|
711
|
+
operation["security"] = self._sanitize_security(sec, schemes) if sec else []
|
|
712
|
+
elif route.get("auth_required", False):
|
|
713
|
+
requirements = [{self.default_scheme: []}]
|
|
714
|
+
if self.default_scheme == "bearerAuth" and "ssoSession" in schemes:
|
|
715
|
+
requirements.append({"ssoSession": []})
|
|
716
|
+
operation["security"] = self._sanitize_security(
|
|
717
|
+
requirements, schemes
|
|
718
|
+
)
|
|
719
|
+
|
|
720
|
+
if operation.get("security"):
|
|
721
|
+
operation["responses"].setdefault("401", {"description": "Unauthorized"})
|
|
722
|
+
|
|
723
|
+
def _build_component_schemas(self, spec: dict, models: dict,
|
|
724
|
+
ref_schemas: set) -> None:
|
|
725
|
+
"""Add components.schemas from referenced ORM models, then any registered
|
|
726
|
+
component schemas referenced via @request_schema/@response_schema."""
|
|
668
727
|
if models:
|
|
669
728
|
schemas = spec["components"].setdefault("schemas", {})
|
|
670
729
|
for name, model_class in models.items():
|
|
671
730
|
schemas[name] = self._model_schema(model_class)
|
|
672
731
|
|
|
673
|
-
# Registered component schemas referenced via @request_schema/@response_schema.
|
|
674
732
|
if ref_schemas:
|
|
675
733
|
schemas = spec["components"].setdefault("schemas", {})
|
|
676
734
|
for name in ref_schemas:
|
|
677
735
|
if name in _REGISTERED_SCHEMAS and name not in schemas:
|
|
678
736
|
schemas[name] = _REGISTERED_SCHEMAS[name]
|
|
679
737
|
|
|
680
|
-
# top-level tags[] (name-only is valid OpenAPI; descriptions optional)
|
|
681
|
-
if used_tags:
|
|
682
|
-
spec["tags"] = [{"name": t} for t in used_tags]
|
|
683
|
-
|
|
684
|
-
return spec
|
|
685
|
-
|
|
686
738
|
def generate_json(self, routes: list[dict]) -> str:
|
|
687
739
|
"""Generate OpenAPI spec as JSON string."""
|
|
688
740
|
return json.dumps(self.generate(routes), indent=2)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
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.132 → tina4_python-3.13.133}/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
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/public/images/tina4-logo-icon.webp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.13.132 → tina4_python-3.13.133}/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.132 → tina4_python-3.13.133}/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.132 → tina4_python-3.13.133}/tina4_python/queue_backends/kafka_backend.py
RENAMED
|
File without changes
|
{tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/queue_backends/mongo_backend.py
RENAMED
|
File without changes
|
{tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/queue_backends/rabbitmq_backend.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.13.132 → tina4_python-3.13.133}/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.132 → tina4_python-3.13.133}/tina4_python/session_handlers/memcached_handler.py
RENAMED
|
File without changes
|
{tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/session_handlers/mongodb_handler.py
RENAMED
|
File without changes
|
{tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/session_handlers/redis_handler.py
RENAMED
|
File without changes
|
{tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/session_handlers/valkey_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/templates/docker/distroless/Dockerfile
RENAMED
|
File without changes
|
{tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/templates/docker/poetry/Dockerfile
RENAMED
|
File without changes
|
{tina4_python-3.13.132 → tina4_python-3.13.133}/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.132 → tina4_python-3.13.133}/tina4_python/translations/af/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/translations/af/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/translations/en/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/translations/en/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/translations/es/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/translations/es/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/translations/fr/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/translations/fr/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/translations/ja/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/translations/ja/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/translations/zh/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.132 → tina4_python-3.13.133}/tina4_python/translations/zh/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|