tina4-python 3.11.10__tar.gz → 3.11.12__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.11.10 → tina4_python-3.11.12}/PKG-INFO +1 -1
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/__init__.py +1 -1
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/core/server.py +11 -3
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/database/connection.py +55 -15
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/orm/fields.py +33 -2
- {tina4_python-3.11.10 → tina4_python-3.11.12}/.gitignore +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/README.md +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/pyproject.toml +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/CLAUDE.md +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/HtmlElement.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/Testing.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/ai/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/api/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/auth/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/cache/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/cli/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/container/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/core/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/core/cache.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/core/constants.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/core/events.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/core/middleware.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/core/rate_limiter.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/core/request.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/core/response.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/core/router.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/crud/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/database/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/database/adapter.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/database/firebird.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/database/mongodb.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/database/mssql.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/database/mysql.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/database/odbc.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/database/postgres.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/database/sqlite.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/debug/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/debug/error_overlay.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/dev_admin/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/dev_admin/metrics.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/dotenv/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/frond/FROND.md +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/frond/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/frond/engine.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/gallery/auth/meta.json +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/gallery/auth/src/routes/api/gallery_auth.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/gallery/database/meta.json +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/gallery/database/src/routes/api/gallery_db.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/gallery/error-overlay/meta.json +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/gallery/error-overlay/src/routes/api/gallery_crash.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/gallery/orm/meta.json +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/gallery/orm/src/orm/Product.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/gallery/orm/src/routes/api/gallery_products.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/gallery/queue/meta.json +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/gallery/queue/src/routes/api/gallery_queue.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/gallery/rest-api/meta.json +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/gallery/rest-api/src/routes/api/gallery_hello.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/gallery/templates/meta.json +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/gallery/templates/src/routes/gallery_page.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/gallery/templates/src/templates/gallery_page.twig +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/graphql/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/i18n/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/mcp/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/mcp/protocol.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/mcp/tools.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/messenger/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/migration/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/migration/runner.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/orm/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/orm/model.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/public/css/tina4.css +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/public/css/tina4.min.css +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/public/favicon.ico +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/public/images/logo.svg +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/public/images/tina4-logo-icon.webp +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/public/js/frond.min.js +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/public/js/tina4-dev-admin.js +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/public/js/tina4-dev-admin.min.js +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/public/js/tina4.min.js +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/public/js/tina4js.min.js +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/public/swagger/index.html +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/public/swagger/oauth2-redirect.html +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/query_builder/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/queue/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/queue/job.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/queue/kafka_backend.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/queue/lite_backend.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/queue/mongo_backend.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/queue/rabbitmq_backend.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/queue_backends/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/queue_backends/kafka_backend.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/queue_backends/mongo_backend.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/queue_backends/rabbitmq_backend.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/scss/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/scss/tina4css/_alerts.scss +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/scss/tina4css/_badges.scss +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/scss/tina4css/_buttons.scss +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/scss/tina4css/_cards.scss +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/scss/tina4css/_forms.scss +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/scss/tina4css/_grid.scss +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/scss/tina4css/_modals.scss +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/scss/tina4css/_nav.scss +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/scss/tina4css/_reset.scss +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/scss/tina4css/_tables.scss +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/scss/tina4css/_typography.scss +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/scss/tina4css/_utilities.scss +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/scss/tina4css/_variables.scss +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/scss/tina4css/base.scss +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/scss/tina4css/colors.scss +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/scss/tina4css/tina4.scss +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/seeder/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/service/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/session/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/session_handlers/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/session_handlers/mongodb_handler.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/session_handlers/redis_handler.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/session_handlers/valkey_handler.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/swagger/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/templates/components/crud.twig +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/templates/docker/distroless/Dockerfile +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/templates/docker/poetry/Dockerfile +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/templates/docker/python/Dockerfile +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/templates/docker/uv/Dockerfile +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/templates/errors/302.twig +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/templates/errors/401.twig +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/templates/errors/403.twig +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/templates/errors/404.twig +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/templates/errors/500.twig +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/templates/errors/502.twig +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/templates/errors/503.twig +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/templates/errors/base.twig +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/templates/frontend/README.md +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/templates/readme.md +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/test_client/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/af/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/af/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/en/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/en/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/es/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/es/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/fr/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/fr/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/ja/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/ja/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/zh/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/zh/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/validator/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/websocket/__init__.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/websocket/backplane.py +0 -0
- {tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/wsdl/__init__.py +0 -0
|
@@ -73,12 +73,20 @@ def _auto_discover(root_dir: str = "src"):
|
|
|
73
73
|
|
|
74
74
|
|
|
75
75
|
def _ensure_folders():
|
|
76
|
-
"""Create project folders if missing (auto-repair).
|
|
76
|
+
"""Create project folders if missing (auto-repair).
|
|
77
|
+
|
|
78
|
+
Note: ``migrations/`` lives at the project root (matches the CLI's
|
|
79
|
+
``migrations`` default and the documented project structure), never
|
|
80
|
+
under ``src/``. Don't add ``src/migrations`` here — it creates an
|
|
81
|
+
empty directory that the migration runner ignores and confuses users.
|
|
82
|
+
"""
|
|
77
83
|
folders = [
|
|
78
|
-
"src/routes", "src/orm", "src/
|
|
84
|
+
"src/routes", "src/orm", "src/seeds",
|
|
79
85
|
"src/templates", "src/templates/errors",
|
|
80
86
|
"src/public", "src/public/js", "src/public/css", "src/public/icons",
|
|
81
|
-
"src/locales",
|
|
87
|
+
"src/locales",
|
|
88
|
+
"migrations",
|
|
89
|
+
"data", "data/.broken", "logs", "secrets", "tests",
|
|
82
90
|
]
|
|
83
91
|
for folder in folders:
|
|
84
92
|
Path(folder).mkdir(parents=True, exist_ok=True)
|
|
@@ -195,27 +195,67 @@ class Database:
|
|
|
195
195
|
return _DRIVERS[scheme]()
|
|
196
196
|
|
|
197
197
|
def _connection_path(self) -> str:
|
|
198
|
-
"""Extract connection-specific path/params from the URL.
|
|
198
|
+
"""Extract connection-specific path/params from the URL.
|
|
199
|
+
|
|
200
|
+
SQLite URL convention (matches PHP and the Python CLAUDE.md docs):
|
|
201
|
+
|
|
202
|
+
sqlite::memory: → in-memory database
|
|
203
|
+
sqlite:///:memory: → in-memory database (URL form)
|
|
204
|
+
sqlite:///app.db → ./app.db (relative to cwd)
|
|
205
|
+
sqlite:///data/app.db → ./data/app.db (relative)
|
|
206
|
+
sqlite:///./data/app.db → ./data/app.db (relative, explicit)
|
|
207
|
+
sqlite:////absolute/path.db → /absolute/path.db (absolute)
|
|
208
|
+
sqlite:///C:/Users/app.db → C:/Users/app.db (Windows absolute)
|
|
209
|
+
|
|
210
|
+
Directories are auto-created ONLY when the resolved path is
|
|
211
|
+
inside the current working directory (the project root). We
|
|
212
|
+
never try to ``os.makedirs`` at root (``/data``, ``C:\\data``)
|
|
213
|
+
— that's both hostile on read-only filesystems and not what
|
|
214
|
+
any project actually wants.
|
|
215
|
+
"""
|
|
199
216
|
parsed = urlparse(self.url)
|
|
200
217
|
|
|
201
|
-
if parsed.scheme.startswith("sqlite"):
|
|
202
|
-
#
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
218
|
+
if not parsed.scheme.startswith("sqlite"):
|
|
219
|
+
# For other drivers, return the full URL (adapter parses it)
|
|
220
|
+
return self.url
|
|
221
|
+
|
|
222
|
+
# In-memory forms — passthrough
|
|
223
|
+
raw_path = parsed.path
|
|
224
|
+
if raw_path in (":memory:", "/:memory:"):
|
|
225
|
+
return ":memory:"
|
|
209
226
|
|
|
210
|
-
|
|
227
|
+
# Strip exactly one leading "/" — the URL "/"-delimiter between the
|
|
228
|
+
# empty netloc and the start of the path.
|
|
229
|
+
if raw_path.startswith("/"):
|
|
230
|
+
stripped = raw_path[1:]
|
|
231
|
+
else:
|
|
232
|
+
stripped = raw_path
|
|
233
|
+
|
|
234
|
+
# Windows absolute path (drive-letter form): C:/... or C:\...
|
|
235
|
+
is_windows_abs = (
|
|
236
|
+
len(stripped) >= 3
|
|
237
|
+
and stripped[0].isalpha()
|
|
238
|
+
and stripped[1] == ":"
|
|
239
|
+
and stripped[2] in ("/", "\\")
|
|
240
|
+
)
|
|
241
|
+
# Unix absolute path: urlparse("sqlite:////abs/app.db").path == "//abs/app.db"
|
|
242
|
+
# After one strip it's still "/abs/app.db" → still starts with "/".
|
|
243
|
+
is_unix_abs = stripped.startswith("/")
|
|
244
|
+
|
|
245
|
+
if is_windows_abs or is_unix_abs:
|
|
246
|
+
path = stripped
|
|
247
|
+
# Don't auto-create directories outside cwd. If the user gave
|
|
248
|
+
# an absolute path, they're responsible for it existing.
|
|
249
|
+
else:
|
|
250
|
+
# Relative — resolve under the project root (cwd).
|
|
251
|
+
cwd = os.getcwd()
|
|
252
|
+
path = os.path.join(cwd, stripped)
|
|
253
|
+
# Only auto-create subdirectories *inside* cwd.
|
|
211
254
|
directory = os.path.dirname(path)
|
|
212
|
-
if directory:
|
|
255
|
+
if directory and os.path.commonpath([os.path.abspath(directory), cwd]) == cwd:
|
|
213
256
|
os.makedirs(directory, exist_ok=True)
|
|
214
257
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
# For other drivers, return the full URL (adapter parses it)
|
|
218
|
-
return self.url
|
|
258
|
+
return path
|
|
219
259
|
|
|
220
260
|
# ── Query Cache ──────────────────────────────────────────────
|
|
221
261
|
|
|
@@ -58,10 +58,41 @@ class Field:
|
|
|
58
58
|
raise ValueError(f"Field '{self.name}' is required")
|
|
59
59
|
return self.default
|
|
60
60
|
|
|
61
|
-
# Type coercion
|
|
61
|
+
# Type coercion.
|
|
62
|
+
#
|
|
63
|
+
# `validate()` runs on BOTH the write path (user input from routes/forms)
|
|
64
|
+
# and the read path (rows coming back from the database driver). Drivers
|
|
65
|
+
# return values in different shapes per engine:
|
|
66
|
+
#
|
|
67
|
+
# engine datetime column bool column numeric column
|
|
68
|
+
# -------- ---------------- ----------- --------------
|
|
69
|
+
# SQLite str int (0/1) float / int
|
|
70
|
+
# PostgreSQL datetime bool Decimal
|
|
71
|
+
# MySQL datetime int (0/1) Decimal
|
|
72
|
+
# MSSQL datetime bool Decimal
|
|
73
|
+
# Firebird datetime int (0/1) Decimal
|
|
74
|
+
#
|
|
75
|
+
# So the rule is: if the driver already handed us the right type,
|
|
76
|
+
# accept it as-is. Otherwise coerce. This avoids the classic crash
|
|
77
|
+
# `datetime(datetime_instance)` that hit every PostgreSQL ORM read.
|
|
78
|
+
#
|
|
79
|
+
# Care is needed around `bool` being a subclass of `int` in Python —
|
|
80
|
+
# we handle those two paths explicitly before the generic fast path.
|
|
62
81
|
try:
|
|
63
|
-
|
|
82
|
+
# BooleanField receiving an int (e.g. SQLite 0/1) → cast to bool
|
|
83
|
+
if self.field_type is bool and isinstance(value, int) and not isinstance(value, bool):
|
|
64
84
|
value = bool(value)
|
|
85
|
+
# IntegerField receiving a bool → cast to int (preserve legacy behaviour
|
|
86
|
+
# where True/False round-trip as 1/0 in numeric columns)
|
|
87
|
+
elif self.field_type is int and isinstance(value, bool):
|
|
88
|
+
value = int(value)
|
|
89
|
+
# DateTimeField receiving an ISO-8601 string (SQLite default) → parse
|
|
90
|
+
elif self.field_type is datetime and isinstance(value, str):
|
|
91
|
+
value = datetime.fromisoformat(value)
|
|
92
|
+
# Fast path: driver already handed us the correct type. Don't re-coerce —
|
|
93
|
+
# `datetime(datetime_instance)` etc. raises TypeError otherwise.
|
|
94
|
+
elif isinstance(value, self.field_type):
|
|
95
|
+
pass
|
|
65
96
|
else:
|
|
66
97
|
value = self.field_type(value)
|
|
67
98
|
except (TypeError, ValueError) as e:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
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.11.10 → tina4_python-3.11.12}/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
|
{tina4_python-3.11.10 → tina4_python-3.11.12}/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.11.10 → tina4_python-3.11.12}/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.11.10 → tina4_python-3.11.12}/tina4_python/session_handlers/mongodb_handler.py
RENAMED
|
File without changes
|
{tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/session_handlers/redis_handler.py
RENAMED
|
File without changes
|
{tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/session_handlers/valkey_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/templates/docker/distroless/Dockerfile
RENAMED
|
File without changes
|
{tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/templates/docker/poetry/Dockerfile
RENAMED
|
File without changes
|
{tina4_python-3.11.10 → tina4_python-3.11.12}/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
|
{tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/af/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/af/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/en/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/en/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/es/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/es/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/fr/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/fr/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/ja/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/ja/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/zh/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.11.10 → tina4_python-3.11.12}/tina4_python/translations/zh/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|