tina4-python 3.13.76__tar.gz → 3.13.77__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.76 → tina4_python-3.13.77}/PKG-INFO +1 -1
- {tina4_python-3.13.76 → tina4_python-3.13.77}/pyproject.toml +4 -1
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/core/server.py +60 -26
- {tina4_python-3.13.76 → tina4_python-3.13.77}/.gitignore +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/README.md +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/CLAUDE.md +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/HtmlElement.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/Testing.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/ai/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/api/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/auth/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/cache/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/cli/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/container/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/context/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/context/chunker.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/core/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/core/cache.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/core/constants.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/core/events.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/core/middleware.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/core/rate_limiter.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/core/request.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/core/response.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/core/router.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/crud/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/database/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/database/adapter.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/database/connection.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/database/firebird.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/database/mongodb.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/database/mssql.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/database/mysql.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/database/odbc.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/database/postgres.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/database/sqlite.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/debug/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/debug/error_overlay.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/dev_admin/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/dev_admin/metrics.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/dev_admin/plan.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/dev_admin/project_index.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/docs.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/docstore/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/dotenv/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/env.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/frond/FROND.md +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/frond/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/frond/engine.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/gallery/auth/meta.json +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/gallery/auth/src/routes/api/gallery_auth.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/gallery/database/meta.json +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/gallery/database/src/routes/api/gallery_db.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/gallery/error-overlay/meta.json +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/gallery/error-overlay/src/routes/api/gallery_crash.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/gallery/orm/meta.json +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/gallery/orm/src/orm/Product.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/gallery/orm/src/routes/api/gallery_products.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/gallery/queue/meta.json +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/gallery/queue/src/routes/api/gallery_queue.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/gallery/rest-api/meta.json +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/gallery/rest-api/src/routes/api/gallery_hello.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/gallery/templates/meta.json +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/gallery/templates/src/routes/gallery_page.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/gallery/templates/src/templates/gallery_page.twig +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/graphql/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/i18n/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/mcp/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/mcp/protocol.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/mcp/tools.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/messenger/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/migration/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/migration/runner.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/orm/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/orm/fields.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/orm/model.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/public/__feedback/widget.js +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/public/css/tina4.css +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/public/css/tina4.min.css +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/public/favicon.ico +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/public/images/logo.svg +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/public/images/tina4-logo-icon.webp +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/public/js/frond.js +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/public/js/frond.min.js +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/public/js/tina4-dev-admin.js +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/public/js/tina4-dev-admin.min.js +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/public/js/tina4.min.js +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/public/js/tina4js.min.js +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/public/swagger/index.html +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/public/swagger/oauth2-redirect.html +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/query_builder/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/queue/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/queue/job.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/queue/kafka_backend.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/queue/lite_backend.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/queue/mongo_backend.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/queue/rabbitmq_backend.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/queue_backends/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/queue_backends/kafka_backend.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/queue_backends/mongo_backend.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/queue_backends/rabbitmq_backend.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/realtime/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/realtime/models/Attachment.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/realtime/models/Channel.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/realtime/models/ChannelMember.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/realtime/models/Message.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/realtime/models/Workspace.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/realtime/models/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/realtime/storage.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/scss/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/scss/tina4css/_alerts.scss +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/scss/tina4css/_badges.scss +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/scss/tina4css/_buttons.scss +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/scss/tina4css/_cards.scss +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/scss/tina4css/_forms.scss +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/scss/tina4css/_grid.scss +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/scss/tina4css/_modals.scss +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/scss/tina4css/_nav.scss +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/scss/tina4css/_reset.scss +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/scss/tina4css/_tables.scss +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/scss/tina4css/_typography.scss +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/scss/tina4css/_utilities.scss +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/scss/tina4css/_variables.scss +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/scss/tina4css/base.scss +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/scss/tina4css/colors.scss +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/scss/tina4css/tina4.scss +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/seeder/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/service/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/session/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/session_handlers/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/session_handlers/mongodb_handler.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/session_handlers/redis_handler.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/session_handlers/valkey_handler.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/swagger/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/templates/components/crud.twig +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/templates/docker/distroless/Dockerfile +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/templates/docker/poetry/Dockerfile +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/templates/docker/python/Dockerfile +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/templates/docker/uv/Dockerfile +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/templates/errors/302.twig +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/templates/errors/401.twig +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/templates/errors/403.twig +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/templates/errors/404.twig +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/templates/errors/500.twig +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/templates/errors/502.twig +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/templates/errors/503.twig +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/templates/errors/base.twig +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/templates/frontend/README.md +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/templates/readme.md +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/test/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/test_client/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/translations/af/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/translations/af/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/translations/en/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/translations/en/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/translations/es/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/translations/es/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/translations/fr/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/translations/fr/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/translations/ja/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/translations/ja/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/translations/zh/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/translations/zh/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/validator/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/websocket/__init__.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/websocket/backplane.py +0 -0
- {tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/wsdl/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "tina4-python"
|
|
3
|
-
version = "3.13.
|
|
3
|
+
version = "3.13.77"
|
|
4
4
|
description = "Tina4 Python v3 — Zero-dependency, lightweight web framework"
|
|
5
5
|
authors = [
|
|
6
6
|
{name = "Andre van Zuydam", email = "andrevanzuydam@gmail.com"}
|
|
@@ -64,6 +64,9 @@ tina4python = "tina4_python.cli:main"
|
|
|
64
64
|
[tool.pytest.ini_options]
|
|
65
65
|
asyncio_mode = "auto"
|
|
66
66
|
testpaths = ["tests"]
|
|
67
|
+
markers = [
|
|
68
|
+
"slow: a test that needs real wall-clock time to reproduce a timing bug (deselect with -m 'not slow')",
|
|
69
|
+
]
|
|
67
70
|
|
|
68
71
|
[tool.ruff]
|
|
69
72
|
target-version = "py312"
|
|
@@ -49,6 +49,58 @@ def background(callback, interval: float = 1.0):
|
|
|
49
49
|
_background_tasks.append({"callback": callback, "interval": interval})
|
|
50
50
|
|
|
51
51
|
|
|
52
|
+
async def background_tick_loop(callback, interval: float, executor, shutdown):
|
|
53
|
+
"""Run one registered background task on its interval until shutdown.
|
|
54
|
+
|
|
55
|
+
A task NEVER overlaps itself: each run is awaited to completion before the
|
|
56
|
+
interval sleep and the next tick. That is the only sound reading of an
|
|
57
|
+
interval scheduler, and it is what makes the one-worker-per-task pool sizing
|
|
58
|
+
in `_serve` safe.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
callback: The registered callable (sync or async, no arguments).
|
|
62
|
+
interval: Seconds to sleep between runs.
|
|
63
|
+
executor: ThreadPoolExecutor used for sync callbacks.
|
|
64
|
+
shutdown: asyncio.Event that ends the loop when set.
|
|
65
|
+
"""
|
|
66
|
+
timeout = max(interval * 2, 5.0)
|
|
67
|
+
loop = asyncio.get_running_loop()
|
|
68
|
+
while not shutdown.is_set():
|
|
69
|
+
try:
|
|
70
|
+
if asyncio.iscoroutinefunction(callback):
|
|
71
|
+
# A coroutine IS cancellable, so the timeout really interrupts it.
|
|
72
|
+
await asyncio.wait_for(callback(), timeout=timeout)
|
|
73
|
+
else:
|
|
74
|
+
# Run sync callback in a thread pool — never blocks the event loop.
|
|
75
|
+
#
|
|
76
|
+
# A callable already running in a ThreadPoolExecutor CANNOT be
|
|
77
|
+
# cancelled: Future.cancel() returns False once it has started and
|
|
78
|
+
# there is no way to interrupt the thread. So this must NOT use
|
|
79
|
+
# wait_for() — that abandons the wrapper future while the thread
|
|
80
|
+
# keeps running, and the next tick then starts a SECOND copy
|
|
81
|
+
# alongside the first (silent double-execution of a slow sweep,
|
|
82
|
+
# with every later tick piling on another). Wait for the run to
|
|
83
|
+
# finish and only WARN about the overrun.
|
|
84
|
+
fut = loop.run_in_executor(executor, callback)
|
|
85
|
+
done, _pending = await asyncio.wait({fut}, timeout=timeout)
|
|
86
|
+
if not done:
|
|
87
|
+
Log.warning(
|
|
88
|
+
f"Background task is still running after {timeout:.1f}s. "
|
|
89
|
+
f"The next run is deferred until it finishes (a running sync "
|
|
90
|
+
f"task cannot be interrupted). Use non-blocking calls "
|
|
91
|
+
f"(e.g. queue.pop() instead of queue.consume())."
|
|
92
|
+
)
|
|
93
|
+
await fut # never overlap; re-raises the callback's error
|
|
94
|
+
except asyncio.TimeoutError:
|
|
95
|
+
Log.warning(
|
|
96
|
+
f"Background task exceeded {timeout:.1f}s timeout and was interrupted. "
|
|
97
|
+
f"Use non-blocking calls (e.g. queue.pop() instead of queue.consume())."
|
|
98
|
+
)
|
|
99
|
+
except Exception as e:
|
|
100
|
+
Log.error(f"Background task error: {e}")
|
|
101
|
+
await asyncio.sleep(interval)
|
|
102
|
+
|
|
103
|
+
|
|
52
104
|
# module_name → source-file mtime at the last (re)import. Drives the
|
|
53
105
|
# changed-file detection in ``_auto_discover``: a file whose mtime is newer
|
|
54
106
|
# than the recorded value is re-executed in place, so editing an existing
|
|
@@ -2743,7 +2795,9 @@ def run(host: str | None = None, port: int | None = None, no_browser: bool = Fal
|
|
|
2743
2795
|
|
|
2744
2796
|
# Start registered background tasks as asyncio tasks.
|
|
2745
2797
|
# Sync callbacks run in a thread pool so they CANNOT block the event loop.
|
|
2746
|
-
#
|
|
2798
|
+
# max_workers is one per registered task — sound only because a task never
|
|
2799
|
+
# overlaps itself (see background_tick_loop), so tasks cannot starve each
|
|
2800
|
+
# other of workers.
|
|
2747
2801
|
import concurrent.futures
|
|
2748
2802
|
_executor = concurrent.futures.ThreadPoolExecutor(
|
|
2749
2803
|
max_workers=max(len(_background_tasks), 2),
|
|
@@ -2751,31 +2805,11 @@ def run(host: str | None = None, port: int | None = None, no_browser: bool = Fal
|
|
|
2751
2805
|
)
|
|
2752
2806
|
bg_tasks = []
|
|
2753
2807
|
for task_def in _background_tasks:
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
while not shutdown.is_set():
|
|
2760
|
-
try:
|
|
2761
|
-
if asyncio.iscoroutinefunction(_cb):
|
|
2762
|
-
await asyncio.wait_for(_cb(), timeout=timeout)
|
|
2763
|
-
else:
|
|
2764
|
-
# Run sync callback in thread pool — never blocks the event loop
|
|
2765
|
-
await asyncio.wait_for(
|
|
2766
|
-
loop.run_in_executor(_executor, _cb),
|
|
2767
|
-
timeout=timeout,
|
|
2768
|
-
)
|
|
2769
|
-
except asyncio.TimeoutError:
|
|
2770
|
-
Log.warning(
|
|
2771
|
-
f"Background task exceeded {timeout:.1f}s timeout and was interrupted. "
|
|
2772
|
-
f"Use non-blocking calls (e.g. queue.pop() instead of queue.consume())."
|
|
2773
|
-
)
|
|
2774
|
-
except Exception as e:
|
|
2775
|
-
Log.error(f"Background task error: {e}")
|
|
2776
|
-
await asyncio.sleep(_iv)
|
|
2777
|
-
|
|
2778
|
-
bg_tasks.append(asyncio.create_task(_tick_loop()))
|
|
2808
|
+
bg_tasks.append(asyncio.create_task(
|
|
2809
|
+
background_tick_loop(
|
|
2810
|
+
task_def["callback"], task_def["interval"], _executor, shutdown,
|
|
2811
|
+
)
|
|
2812
|
+
))
|
|
2779
2813
|
|
|
2780
2814
|
await shutdown.wait()
|
|
2781
2815
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
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.76 → tina4_python-3.13.77}/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.76 → tina4_python-3.13.77}/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.76 → tina4_python-3.13.77}/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.76 → tina4_python-3.13.77}/tina4_python/session_handlers/mongodb_handler.py
RENAMED
|
File without changes
|
{tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/session_handlers/redis_handler.py
RENAMED
|
File without changes
|
{tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/session_handlers/valkey_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/templates/docker/distroless/Dockerfile
RENAMED
|
File without changes
|
{tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/templates/docker/poetry/Dockerfile
RENAMED
|
File without changes
|
{tina4_python-3.13.76 → tina4_python-3.13.77}/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.76 → tina4_python-3.13.77}/tina4_python/translations/af/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/translations/af/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/translations/en/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/translations/en/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/translations/es/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/translations/es/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/translations/fr/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/translations/fr/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/translations/ja/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/translations/ja/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/translations/zh/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.76 → tina4_python-3.13.77}/tina4_python/translations/zh/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|