tina4-python 3.13.26__tar.gz → 3.13.27__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.26 → tina4_python-3.13.27}/PKG-INFO +1 -1
- {tina4_python-3.13.26 → tina4_python-3.13.27}/pyproject.toml +1 -1
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/__init__.py +1 -1
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/frond/engine.py +62 -11
- {tina4_python-3.13.26 → tina4_python-3.13.27}/.gitignore +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/README.md +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/CLAUDE.md +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/HtmlElement.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/Testing.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/ai/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/api/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/auth/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/cache/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/cli/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/container/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/core/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/core/cache.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/core/constants.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/core/events.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/core/middleware.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/core/rate_limiter.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/core/request.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/core/response.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/core/router.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/core/server.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/crud/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/database/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/database/adapter.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/database/connection.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/database/firebird.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/database/mongodb.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/database/mssql.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/database/mysql.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/database/odbc.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/database/postgres.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/database/sqlite.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/debug/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/debug/error_overlay.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/dev_admin/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/dev_admin/metrics.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/dev_admin/plan.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/dev_admin/project_index.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/docs.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/dotenv/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/env.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/frond/FROND.md +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/frond/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/gallery/auth/meta.json +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/gallery/auth/src/routes/api/gallery_auth.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/gallery/database/meta.json +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/gallery/database/src/routes/api/gallery_db.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/gallery/error-overlay/meta.json +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/gallery/error-overlay/src/routes/api/gallery_crash.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/gallery/orm/meta.json +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/gallery/orm/src/orm/Product.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/gallery/orm/src/routes/api/gallery_products.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/gallery/queue/meta.json +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/gallery/queue/src/routes/api/gallery_queue.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/gallery/rest-api/meta.json +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/gallery/rest-api/src/routes/api/gallery_hello.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/gallery/templates/meta.json +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/gallery/templates/src/routes/gallery_page.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/gallery/templates/src/templates/gallery_page.twig +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/graphql/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/i18n/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/mcp/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/mcp/protocol.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/mcp/tools.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/messenger/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/migration/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/migration/runner.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/orm/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/orm/fields.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/orm/model.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/public/__feedback/widget.js +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/public/css/tina4.css +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/public/css/tina4.min.css +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/public/favicon.ico +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/public/images/logo.svg +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/public/images/tina4-logo-icon.webp +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/public/js/frond.js +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/public/js/frond.min.js +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/public/js/tina4-dev-admin.js +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/public/js/tina4-dev-admin.min.js +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/public/js/tina4.min.js +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/public/js/tina4js.min.js +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/public/swagger/index.html +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/public/swagger/oauth2-redirect.html +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/query_builder/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/queue/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/queue/job.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/queue/kafka_backend.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/queue/lite_backend.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/queue/mongo_backend.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/queue/rabbitmq_backend.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/queue_backends/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/queue_backends/kafka_backend.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/queue_backends/mongo_backend.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/queue_backends/rabbitmq_backend.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/scss/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/scss/tina4css/_alerts.scss +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/scss/tina4css/_badges.scss +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/scss/tina4css/_buttons.scss +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/scss/tina4css/_cards.scss +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/scss/tina4css/_forms.scss +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/scss/tina4css/_grid.scss +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/scss/tina4css/_modals.scss +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/scss/tina4css/_nav.scss +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/scss/tina4css/_reset.scss +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/scss/tina4css/_tables.scss +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/scss/tina4css/_typography.scss +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/scss/tina4css/_utilities.scss +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/scss/tina4css/_variables.scss +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/scss/tina4css/base.scss +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/scss/tina4css/colors.scss +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/scss/tina4css/tina4.scss +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/seeder/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/service/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/session/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/session_handlers/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/session_handlers/mongodb_handler.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/session_handlers/redis_handler.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/session_handlers/valkey_handler.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/swagger/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/templates/components/crud.twig +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/templates/docker/distroless/Dockerfile +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/templates/docker/poetry/Dockerfile +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/templates/docker/python/Dockerfile +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/templates/docker/uv/Dockerfile +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/templates/errors/302.twig +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/templates/errors/401.twig +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/templates/errors/403.twig +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/templates/errors/404.twig +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/templates/errors/500.twig +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/templates/errors/502.twig +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/templates/errors/503.twig +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/templates/errors/base.twig +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/templates/frontend/README.md +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/templates/readme.md +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/test/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/test_client/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/translations/af/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/translations/af/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/translations/en/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/translations/en/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/translations/es/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/translations/es/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/translations/fr/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/translations/fr/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/translations/ja/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/translations/ja/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/translations/zh/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/translations/zh/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/validator/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/websocket/__init__.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/websocket/backplane.py +0 -0
- {tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/wsdl/__init__.py +0 -0
|
@@ -989,9 +989,26 @@ def _coerce_arg(s: str):
|
|
|
989
989
|
return s
|
|
990
990
|
|
|
991
991
|
|
|
992
|
+
class _Ref:
|
|
993
|
+
"""A filter argument that was an UNQUOTED bareword — i.e. a variable
|
|
994
|
+
reference (or dotted/bracket path), not a literal. Resolved against the
|
|
995
|
+
render context at apply-time so e.g. `{{ '%.2f' | format(price) }}` binds
|
|
996
|
+
`price` to its value. Quoted literals (`default('fb')`) are kept as plain
|
|
997
|
+
strings and never resolved."""
|
|
998
|
+
|
|
999
|
+
__slots__ = ("name",)
|
|
1000
|
+
|
|
1001
|
+
def __init__(self, name: str):
|
|
1002
|
+
self.name = name
|
|
1003
|
+
|
|
1004
|
+
|
|
992
1005
|
def _parse_args(raw: str) -> list:
|
|
993
|
-
"""Parse filter arguments, respecting quoted strings, braces, and backslash escapes.
|
|
994
|
-
|
|
1006
|
+
"""Parse filter arguments, respecting quoted strings, braces, and backslash escapes.
|
|
1007
|
+
|
|
1008
|
+
Quoted args become literal strings; numbers/bools/null/JSON are coerced to
|
|
1009
|
+
their Python types; an unquoted bareword becomes a `_Ref` (a variable
|
|
1010
|
+
reference resolved against the context when the filter runs)."""
|
|
1011
|
+
tokens = []
|
|
995
1012
|
current = ""
|
|
996
1013
|
in_quote = None
|
|
997
1014
|
depth = 0
|
|
@@ -1006,15 +1023,27 @@ def _parse_args(raw: str) -> list:
|
|
|
1006
1023
|
elif ch in (")", "}", "]") and not in_quote:
|
|
1007
1024
|
depth -= 1
|
|
1008
1025
|
elif ch == "," and not in_quote and depth == 0:
|
|
1009
|
-
|
|
1026
|
+
tokens.append(current.strip())
|
|
1010
1027
|
current = ""
|
|
1011
1028
|
continue
|
|
1012
1029
|
current += ch
|
|
1013
1030
|
|
|
1014
1031
|
if current.strip():
|
|
1015
|
-
|
|
1032
|
+
tokens.append(current.strip())
|
|
1016
1033
|
|
|
1017
|
-
|
|
1034
|
+
out = []
|
|
1035
|
+
for tok in tokens:
|
|
1036
|
+
if len(tok) >= 2 and tok[0] == tok[-1] and tok[0] in ('"', "'"):
|
|
1037
|
+
out.append(_strip_outer_quotes(tok)) # quoted literal → string
|
|
1038
|
+
else:
|
|
1039
|
+
coerced = _coerce_arg(tok)
|
|
1040
|
+
# A bareword that stayed a string is a variable/expression
|
|
1041
|
+
# reference (e.g. `n`, `user.age`) — resolve it at apply-time.
|
|
1042
|
+
if isinstance(coerced, str) and tok:
|
|
1043
|
+
out.append(_Ref(tok))
|
|
1044
|
+
else:
|
|
1045
|
+
out.append(coerced)
|
|
1046
|
+
return out
|
|
1018
1047
|
|
|
1019
1048
|
|
|
1020
1049
|
def _strip_outer_quotes(s: str) -> str:
|
|
@@ -1071,16 +1100,16 @@ _BUILTIN_FILTERS = {
|
|
|
1071
1100
|
"default": lambda v, *a: v if v is not None and v != "" else (a[0] if a else ""),
|
|
1072
1101
|
"raw": lambda v, *a: v, # Mark as safe (no escaping)
|
|
1073
1102
|
"safe": lambda v, *a: v,
|
|
1074
|
-
"escape": lambda v, *a: html.escape(str(v)),
|
|
1075
|
-
"e": lambda v, *a: html.escape(str(v)),
|
|
1103
|
+
"escape": lambda v, *a: SafeString(html.escape(str(v))),
|
|
1104
|
+
"e": lambda v, *a: SafeString(html.escape(str(v))),
|
|
1076
1105
|
"striptags": lambda v, *a: _STRIPTAGS_RE.sub("", str(v)),
|
|
1077
|
-
"nl2br": lambda v, *a: str(v).replace("\n", "<br
|
|
1106
|
+
"nl2br": lambda v, *a: SafeString(html.escape(str(v)).replace("\n", "<br />\n")),
|
|
1078
1107
|
"abs": lambda v, *a: abs(v) if isinstance(v, (int, float)) else v,
|
|
1079
|
-
"round": lambda v, *a: round(float(v), int(a[0]) if a else
|
|
1108
|
+
"round": lambda v, *a: round(float(v), int(a[0])) if a else int(round(float(v))),
|
|
1080
1109
|
"int": lambda v, *a: int(v) if v else 0,
|
|
1081
1110
|
"float": lambda v, *a: float(v) if v else 0.0,
|
|
1082
1111
|
"string": lambda v, *a: str(v),
|
|
1083
|
-
"json_encode": lambda v, *a: json.dumps(v),
|
|
1112
|
+
"json_encode": lambda v, *a: json.dumps(v, separators=(",", ":")),
|
|
1084
1113
|
"to_json": lambda v, *a: SafeString(json.dumps(v, default=str, separators=(",", ":")).replace("<", "\\u003c").replace(">", "\\u003e").replace("&", "\\u0026")),
|
|
1085
1114
|
"tojson": lambda v, *a: SafeString(json.dumps(v, default=str, separators=(",", ":")).replace("<", "\\u003c").replace(">", "\\u003e").replace("&", "\\u0026")),
|
|
1086
1115
|
"js_escape": lambda v, *a: SafeString(str(v).replace("\\", "\\\\").replace("'", "\\'").replace('"', '\\"').replace("\n", "\\n").replace("\r", "\\r")),
|
|
@@ -1633,6 +1662,21 @@ class Frond:
|
|
|
1633
1662
|
|
|
1634
1663
|
def _render_tokens(self, tokens: list, context: dict) -> str:
|
|
1635
1664
|
"""Render a list of tokens to string."""
|
|
1665
|
+
# Whitespace control pre-pass: every {{- / -}} and {%- / -%} marker
|
|
1666
|
+
# trims its neighbouring TEXT token. Doing this up-front over the whole
|
|
1667
|
+
# token list (not per-handler) means the markers on closing tags
|
|
1668
|
+
# (endif/endfor) and the body boundaries are honoured too — a block tag
|
|
1669
|
+
# consumes its own end tag during dispatch, so the inline pass below
|
|
1670
|
+
# never sees it. Idempotent, so recursion into block bodies is safe.
|
|
1671
|
+
for _idx in range(len(tokens)):
|
|
1672
|
+
_tt, _raw = tokens[_idx]
|
|
1673
|
+
if _tt in (VAR, BLOCK):
|
|
1674
|
+
_, _sb, _sa = _strip_tag(_raw)
|
|
1675
|
+
if _sb and _idx > 0 and tokens[_idx - 1][0] == TEXT:
|
|
1676
|
+
tokens[_idx - 1] = (TEXT, tokens[_idx - 1][1].rstrip())
|
|
1677
|
+
if _sa and _idx + 1 < len(tokens) and tokens[_idx + 1][0] == TEXT:
|
|
1678
|
+
tokens[_idx + 1] = (TEXT, tokens[_idx + 1][1].lstrip())
|
|
1679
|
+
|
|
1636
1680
|
output = []
|
|
1637
1681
|
i = 0
|
|
1638
1682
|
|
|
@@ -1835,6 +1879,13 @@ class Frond:
|
|
|
1835
1879
|
is_safe = True
|
|
1836
1880
|
continue
|
|
1837
1881
|
|
|
1882
|
+
# Resolve any unquoted-bareword args against the context (a quoted
|
|
1883
|
+
# literal stays a plain string). Lets `{{ '%.2f' | format(n) }}`
|
|
1884
|
+
# bind `n` to its value instead of the literal text "n".
|
|
1885
|
+
if args and any(isinstance(a, _Ref) for a in args):
|
|
1886
|
+
args = [_eval_expr(a.name, context) if isinstance(a, _Ref) else a
|
|
1887
|
+
for a in args]
|
|
1888
|
+
|
|
1838
1889
|
# Sandbox: check filter access
|
|
1839
1890
|
if self._sandbox and self._allowed_filters is not None:
|
|
1840
1891
|
if fname not in self._allowed_filters:
|
|
@@ -1885,7 +1936,7 @@ class Frond:
|
|
|
1885
1936
|
value = int(value) if value else 0
|
|
1886
1937
|
continue
|
|
1887
1938
|
if fname in ("e", "escape"):
|
|
1888
|
-
value = html.escape(str(value))
|
|
1939
|
+
value = SafeString(html.escape(str(value)))
|
|
1889
1940
|
continue
|
|
1890
1941
|
|
|
1891
1942
|
fn = self._filters.get(fname)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
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.26 → tina4_python-3.13.27}/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.26 → tina4_python-3.13.27}/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.26 → tina4_python-3.13.27}/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
|
{tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/session_handlers/mongodb_handler.py
RENAMED
|
File without changes
|
{tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/session_handlers/redis_handler.py
RENAMED
|
File without changes
|
{tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/session_handlers/valkey_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/templates/docker/distroless/Dockerfile
RENAMED
|
File without changes
|
{tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/templates/docker/poetry/Dockerfile
RENAMED
|
File without changes
|
{tina4_python-3.13.26 → tina4_python-3.13.27}/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.26 → tina4_python-3.13.27}/tina4_python/translations/af/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/translations/af/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/translations/en/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/translations/en/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/translations/es/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/translations/es/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/translations/fr/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/translations/fr/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/translations/ja/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/translations/ja/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/translations/zh/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.13.26 → tina4_python-3.13.27}/tina4_python/translations/zh/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|