tina4-python 3.10.40__tar.gz → 3.10.41__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.10.40 → tina4_python-3.10.41}/PKG-INFO +53 -36
- {tina4_python-3.10.40 → tina4_python-3.10.41}/README.md +51 -34
- {tina4_python-3.10.40 → tina4_python-3.10.41}/pyproject.toml +2 -2
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/CLAUDE.md +2 -2
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/orm/model.py +7 -8
- {tina4_python-3.10.40 → tina4_python-3.10.41}/.gitignore +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/HtmlElement.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/Testing.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/ai/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/api/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/auth/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/cache/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/cli/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/container/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/core/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/core/cache.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/core/constants.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/core/events.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/core/middleware.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/core/request.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/core/response.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/core/router.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/core/server.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/crud/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/database/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/database/adapter.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/database/connection.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/database/firebird.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/database/mssql.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/database/mysql.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/database/odbc.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/database/postgres.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/database/sqlite.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/debug/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/debug/error_overlay.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/dev_admin/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/dev_admin/metrics.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/dev_reload.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/dotenv/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/frond/FROND.md +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/frond/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/frond/engine.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/gallery/auth/meta.json +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/gallery/auth/src/routes/api/gallery_auth.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/gallery/database/meta.json +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/gallery/database/src/routes/api/gallery_db.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/gallery/error-overlay/meta.json +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/gallery/error-overlay/src/routes/api/gallery_crash.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/gallery/orm/meta.json +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/gallery/orm/src/orm/Product.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/gallery/orm/src/routes/api/gallery_products.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/gallery/queue/meta.json +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/gallery/queue/src/routes/api/gallery_queue.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/gallery/rest-api/meta.json +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/gallery/rest-api/src/routes/api/gallery_hello.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/gallery/templates/meta.json +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/gallery/templates/src/routes/gallery_page.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/gallery/templates/src/templates/gallery_page.twig +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/graphql/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/i18n/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/mcp/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/mcp/protocol.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/mcp/tools.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/messenger/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/migration/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/migration/runner.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/orm/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/orm/fields.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/public/css/tina4.css +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/public/css/tina4.min.css +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/public/favicon.ico +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/public/images/logo.svg +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/public/images/tina4-logo-icon.webp +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/public/js/frond.min.js +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/public/js/tina4-dev-admin.min.js +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/public/js/tina4.min.js +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/public/js/tina4js.min.js +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/public/swagger/index.html +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/public/swagger/oauth2-redirect.html +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/query_builder/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/queue/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/queue_backends/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/queue_backends/kafka_backend.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/queue_backends/mongo_backend.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/queue_backends/rabbitmq_backend.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/scss/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/scss/tina4css/_alerts.scss +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/scss/tina4css/_badges.scss +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/scss/tina4css/_buttons.scss +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/scss/tina4css/_cards.scss +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/scss/tina4css/_forms.scss +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/scss/tina4css/_grid.scss +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/scss/tina4css/_modals.scss +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/scss/tina4css/_nav.scss +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/scss/tina4css/_reset.scss +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/scss/tina4css/_tables.scss +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/scss/tina4css/_typography.scss +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/scss/tina4css/_utilities.scss +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/scss/tina4css/_variables.scss +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/scss/tina4css/base.scss +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/scss/tina4css/colors.scss +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/scss/tina4css/tina4.scss +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/seeder/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/service/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/session/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/session_handlers/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/session_handlers/mongodb_handler.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/session_handlers/redis_handler.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/session_handlers/valkey_handler.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/swagger/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/templates/components/crud.twig +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/templates/docker/distroless/Dockerfile +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/templates/docker/poetry/Dockerfile +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/templates/docker/python/Dockerfile +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/templates/docker/uv/Dockerfile +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/templates/errors/302.twig +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/templates/errors/401.twig +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/templates/errors/403.twig +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/templates/errors/404.twig +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/templates/errors/500.twig +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/templates/errors/502.twig +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/templates/errors/503.twig +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/templates/errors/base.twig +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/templates/frontend/README.md +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/templates/readme.md +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/test_client/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/translations/af/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/translations/af/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/translations/en/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/translations/en/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/translations/es/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/translations/es/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/translations/fr/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/translations/fr/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/translations/ja/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/translations/ja/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/translations/zh/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/translations/zh/LC_MESSAGES/messages.po +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/validator/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/websocket/__init__.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/websocket/backplane.py +0 -0
- {tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/wsdl/__init__.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tina4-python
|
|
3
|
-
Version: 3.10.
|
|
4
|
-
Summary: Tina4 Python
|
|
3
|
+
Version: 3.10.41
|
|
4
|
+
Summary: Tina4 for Python — 54 built-in features, zero dependencies
|
|
5
5
|
Author-email: Andre van Zuydam <andrevanzuydam@gmail.com>
|
|
6
6
|
License: MIT
|
|
7
7
|
Requires-Python: >=3.12
|
|
@@ -35,16 +35,15 @@ Description-Content-Type: text/markdown
|
|
|
35
35
|
</p>
|
|
36
36
|
|
|
37
37
|
<h1 align="center">Tina4 Python</h1>
|
|
38
|
-
<h3 align="center">This Is Now A 4Framework</h3>
|
|
39
38
|
|
|
40
39
|
<p align="center">
|
|
41
|
-
|
|
40
|
+
54 built-in features. Zero dependencies. One import, everything works.
|
|
42
41
|
</p>
|
|
43
42
|
|
|
44
43
|
<p align="center">
|
|
45
44
|
<a href="https://pypi.org/project/tina4-python/"><img src="https://img.shields.io/pypi/v/tina4-python?color=7b1fa2&label=PyPI" alt="PyPI"></a>
|
|
46
|
-
<img src="https://img.shields.io/badge/tests-
|
|
47
|
-
<img src="https://img.shields.io/badge/features-
|
|
45
|
+
<img src="https://img.shields.io/badge/tests-2%2C066%20passing-brightgreen" alt="Tests">
|
|
46
|
+
<img src="https://img.shields.io/badge/features-54-blue" alt="Features">
|
|
48
47
|
<img src="https://img.shields.io/badge/dependencies-0-brightgreen" alt="Zero Deps">
|
|
49
48
|
<a href="https://tina4.com"><img src="https://img.shields.io/badge/docs-tina4.com-7b1fa2" alt="Docs"></a>
|
|
50
49
|
</p>
|
|
@@ -54,6 +53,7 @@ Description-Content-Type: text/markdown
|
|
|
54
53
|
<a href="#getting-started">Getting Started</a> •
|
|
55
54
|
<a href="#features">Features</a> •
|
|
56
55
|
<a href="#cli-reference">CLI Reference</a> •
|
|
56
|
+
<a href="#cross-framework-parity">Parity</a> •
|
|
57
57
|
<a href="https://tina4.com">tina4.com</a>
|
|
58
58
|
</p>
|
|
59
59
|
|
|
@@ -102,27 +102,24 @@ Open http://localhost:7145
|
|
|
102
102
|
|
|
103
103
|
---
|
|
104
104
|
|
|
105
|
-
## What's
|
|
105
|
+
## What's Built In (54 Features)
|
|
106
106
|
|
|
107
107
|
Every feature is built from scratch -- no pip install, no node_modules, no third-party runtime dependencies in core.
|
|
108
108
|
|
|
109
109
|
| Category | Features |
|
|
110
110
|
|----------|----------|
|
|
111
|
-
| **HTTP** |
|
|
112
|
-
| **
|
|
113
|
-
| **ORM** | Active Record
|
|
114
|
-
| **
|
|
115
|
-
| **
|
|
116
|
-
| **API** |
|
|
117
|
-
| **Background** |
|
|
118
|
-
| **
|
|
119
|
-
| **
|
|
120
|
-
| **
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
| **Other** | REST client, localization (6 languages), cache (memory/Redis/file), event system, inline testing, messenger (.env driven), configurable error pages, HTML element builder |
|
|
124
|
-
|
|
125
|
-
**1,633 tests across 38 built-in features. Zero dependencies. All Carbonah benchmarks rated A+.**
|
|
111
|
+
| **Core HTTP** (7) | Router with path params (`{id:int}`, `{p:path}`), Server, Request/Response, Middleware pipeline, Static file serving, CORS |
|
|
112
|
+
| **Database** (6) | SQLite, PostgreSQL, MySQL, MSSQL, Firebird — unified adapter, connection pooling, query cache, transactions, race-safe ID generation, SQL dialect translation |
|
|
113
|
+
| **ORM** (7) | Active Record with typed fields, relationships (`has_one`/`has_many`/`belongs_to`), soft delete, QueryBuilder + MongoDB support, Auto-CRUD generator, migrations with rollback |
|
|
114
|
+
| **Auth & Security** (5) | JWT (HS256/RS256), password hashing (PBKDF2-SHA256), API key validation, rate limiting, CSRF form tokens |
|
|
115
|
+
| **Templating** (3) | Frond engine (Twig/Jinja2-compatible, pre-compiled 2.8x faster), SCSS auto-compilation, built-in CSS (~24 KB) |
|
|
116
|
+
| **API & Integration** (5) | HTTP client (zero-dep), GraphQL with ORM auto-schema + GraphiQL IDE, WSDL/SOAP with auto WSDL, WebSocket (RFC 6455) + Redis backplane, MCP server (24 dev tools) |
|
|
117
|
+
| **Background** (3) | Job queue (File/RabbitMQ/Kafka/MongoDB) with priority, delay, retry, dead letters — service runner — event system (on/emit/once/off) |
|
|
118
|
+
| **Data & Storage** (4) | Session (File/Redis/Valkey/MongoDB/DB), response cache (LRU, TTL), seeder + 50+ fake data generators, messenger (SMTP/IMAP) |
|
|
119
|
+
| **Developer Tools** (7) | Dev dashboard (11 tabs), dev toolbar, error overlay (Catppuccin Mocha), dev mailbox, hot reload + CSS hot-reload, code metrics (complexity, coupling, maintainability), AI context installer (7 tools) |
|
|
120
|
+
| **Utilities** (7) | DI container (transient + singleton), HtmlElement builder, inline testing (`@tests` decorator), i18n (6 languages), Swagger/OpenAPI auto-generation, CLI scaffolding (`generate model/route/migration/middleware`), structured logging |
|
|
121
|
+
|
|
122
|
+
**2,066 tests. Zero dependencies. Full parity across Python, PHP, Ruby, and Node.js.**
|
|
126
123
|
|
|
127
124
|
For full documentation visit **[tina4.com](https://tina4.com)**.
|
|
128
125
|
|
|
@@ -712,23 +709,43 @@ tina4python ai --all # Install for ALL supported tools
|
|
|
712
709
|
|
|
713
710
|
Supported: Claude Code, Cursor, GitHub Copilot, Windsurf, Aider, Cline, OpenAI Codex CLI. Generates framework-aware context so AI assistants understand Tina4's conventions.
|
|
714
711
|
|
|
715
|
-
##
|
|
712
|
+
## Performance
|
|
716
713
|
|
|
717
|
-
|
|
714
|
+
Benchmarked with `wrk` — 5,000 requests, 50 concurrent, median of 3 runs:
|
|
718
715
|
|
|
719
|
-
|
|
|
720
|
-
|
|
721
|
-
|
|
|
722
|
-
|
|
|
723
|
-
|
|
|
724
|
-
|
|
|
725
|
-
|
|
|
726
|
-
| Plaintext Response | 0.000377 | A+ |
|
|
727
|
-
| CRUD Cycle | 0.000456 | A+ |
|
|
728
|
-
| Paginated Query | 0.000990 | A+ |
|
|
729
|
-
| Framework Startup | 0.000801 | A+ |
|
|
716
|
+
| Framework | JSON req/s | Deps | Features |
|
|
717
|
+
|-----------|-----------|------|----------|
|
|
718
|
+
| **Tina4 Python** | **6,508** | 0 | 54 |
|
|
719
|
+
| FastAPI | 12,652 | 12+ | ~8 |
|
|
720
|
+
| Flask | 4,928 | 6+ | ~7 |
|
|
721
|
+
| Bottle | 4,355 | 0 | ~5 |
|
|
722
|
+
| Django | 4,050 | 20+ | ~22 |
|
|
730
723
|
|
|
731
|
-
|
|
724
|
+
Tina4 Python delivers competitive throughput with **zero dependencies and 54 features** — frameworks with higher req/s have a fraction of the functionality and require dozens of third-party packages.
|
|
725
|
+
|
|
726
|
+
**Across all 4 Tina4 implementations:**
|
|
727
|
+
|
|
728
|
+
| | Python | PHP | Ruby | Node.js |
|
|
729
|
+
|---|--------|-----|------|---------|
|
|
730
|
+
| **JSON req/s** | 6,508 | 29,293 | 10,243 | 84,771 |
|
|
731
|
+
| **Dependencies** | 0 | 0 | 0 | 0 |
|
|
732
|
+
| **Features** | 54 | 54 | 54 | 54 |
|
|
733
|
+
|
|
734
|
+
Run benchmarks locally: `python benchmarks/benchmark.py --python`
|
|
735
|
+
|
|
736
|
+
---
|
|
737
|
+
|
|
738
|
+
## Cross-Framework Parity
|
|
739
|
+
|
|
740
|
+
Tina4 ships identical features across four languages — same architecture, same conventions, same 54 features:
|
|
741
|
+
|
|
742
|
+
| | Python | PHP | Ruby | Node.js |
|
|
743
|
+
|---|--------|-----|------|---------|
|
|
744
|
+
| **Package** | `tina4-python` | `tina4stack/tina4php` | `tina4ruby` | `tina4-nodejs` |
|
|
745
|
+
| **Tests** | 2,066 | 1,427 | 1,793 | 1,950 |
|
|
746
|
+
| **Default port** | 7145 | 7146 | 7147 | 7148 |
|
|
747
|
+
|
|
748
|
+
**7,236 tests** across all 4 frameworks. See [tina4.com](https://tina4.com).
|
|
732
749
|
|
|
733
750
|
---
|
|
734
751
|
|
|
@@ -3,16 +3,15 @@
|
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<h1 align="center">Tina4 Python</h1>
|
|
6
|
-
<h3 align="center">This Is Now A 4Framework</h3>
|
|
7
6
|
|
|
8
7
|
<p align="center">
|
|
9
|
-
|
|
8
|
+
54 built-in features. Zero dependencies. One import, everything works.
|
|
10
9
|
</p>
|
|
11
10
|
|
|
12
11
|
<p align="center">
|
|
13
12
|
<a href="https://pypi.org/project/tina4-python/"><img src="https://img.shields.io/pypi/v/tina4-python?color=7b1fa2&label=PyPI" alt="PyPI"></a>
|
|
14
|
-
<img src="https://img.shields.io/badge/tests-
|
|
15
|
-
<img src="https://img.shields.io/badge/features-
|
|
13
|
+
<img src="https://img.shields.io/badge/tests-2%2C066%20passing-brightgreen" alt="Tests">
|
|
14
|
+
<img src="https://img.shields.io/badge/features-54-blue" alt="Features">
|
|
16
15
|
<img src="https://img.shields.io/badge/dependencies-0-brightgreen" alt="Zero Deps">
|
|
17
16
|
<a href="https://tina4.com"><img src="https://img.shields.io/badge/docs-tina4.com-7b1fa2" alt="Docs"></a>
|
|
18
17
|
</p>
|
|
@@ -22,6 +21,7 @@
|
|
|
22
21
|
<a href="#getting-started">Getting Started</a> •
|
|
23
22
|
<a href="#features">Features</a> •
|
|
24
23
|
<a href="#cli-reference">CLI Reference</a> •
|
|
24
|
+
<a href="#cross-framework-parity">Parity</a> •
|
|
25
25
|
<a href="https://tina4.com">tina4.com</a>
|
|
26
26
|
</p>
|
|
27
27
|
|
|
@@ -70,27 +70,24 @@ Open http://localhost:7145
|
|
|
70
70
|
|
|
71
71
|
---
|
|
72
72
|
|
|
73
|
-
## What's
|
|
73
|
+
## What's Built In (54 Features)
|
|
74
74
|
|
|
75
75
|
Every feature is built from scratch -- no pip install, no node_modules, no third-party runtime dependencies in core.
|
|
76
76
|
|
|
77
77
|
| Category | Features |
|
|
78
78
|
|----------|----------|
|
|
79
|
-
| **HTTP** |
|
|
80
|
-
| **
|
|
81
|
-
| **ORM** | Active Record
|
|
82
|
-
| **
|
|
83
|
-
| **
|
|
84
|
-
| **API** |
|
|
85
|
-
| **Background** |
|
|
86
|
-
| **
|
|
87
|
-
| **
|
|
88
|
-
| **
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
| **Other** | REST client, localization (6 languages), cache (memory/Redis/file), event system, inline testing, messenger (.env driven), configurable error pages, HTML element builder |
|
|
92
|
-
|
|
93
|
-
**1,633 tests across 38 built-in features. Zero dependencies. All Carbonah benchmarks rated A+.**
|
|
79
|
+
| **Core HTTP** (7) | Router with path params (`{id:int}`, `{p:path}`), Server, Request/Response, Middleware pipeline, Static file serving, CORS |
|
|
80
|
+
| **Database** (6) | SQLite, PostgreSQL, MySQL, MSSQL, Firebird — unified adapter, connection pooling, query cache, transactions, race-safe ID generation, SQL dialect translation |
|
|
81
|
+
| **ORM** (7) | Active Record with typed fields, relationships (`has_one`/`has_many`/`belongs_to`), soft delete, QueryBuilder + MongoDB support, Auto-CRUD generator, migrations with rollback |
|
|
82
|
+
| **Auth & Security** (5) | JWT (HS256/RS256), password hashing (PBKDF2-SHA256), API key validation, rate limiting, CSRF form tokens |
|
|
83
|
+
| **Templating** (3) | Frond engine (Twig/Jinja2-compatible, pre-compiled 2.8x faster), SCSS auto-compilation, built-in CSS (~24 KB) |
|
|
84
|
+
| **API & Integration** (5) | HTTP client (zero-dep), GraphQL with ORM auto-schema + GraphiQL IDE, WSDL/SOAP with auto WSDL, WebSocket (RFC 6455) + Redis backplane, MCP server (24 dev tools) |
|
|
85
|
+
| **Background** (3) | Job queue (File/RabbitMQ/Kafka/MongoDB) with priority, delay, retry, dead letters — service runner — event system (on/emit/once/off) |
|
|
86
|
+
| **Data & Storage** (4) | Session (File/Redis/Valkey/MongoDB/DB), response cache (LRU, TTL), seeder + 50+ fake data generators, messenger (SMTP/IMAP) |
|
|
87
|
+
| **Developer Tools** (7) | Dev dashboard (11 tabs), dev toolbar, error overlay (Catppuccin Mocha), dev mailbox, hot reload + CSS hot-reload, code metrics (complexity, coupling, maintainability), AI context installer (7 tools) |
|
|
88
|
+
| **Utilities** (7) | DI container (transient + singleton), HtmlElement builder, inline testing (`@tests` decorator), i18n (6 languages), Swagger/OpenAPI auto-generation, CLI scaffolding (`generate model/route/migration/middleware`), structured logging |
|
|
89
|
+
|
|
90
|
+
**2,066 tests. Zero dependencies. Full parity across Python, PHP, Ruby, and Node.js.**
|
|
94
91
|
|
|
95
92
|
For full documentation visit **[tina4.com](https://tina4.com)**.
|
|
96
93
|
|
|
@@ -680,23 +677,43 @@ tina4python ai --all # Install for ALL supported tools
|
|
|
680
677
|
|
|
681
678
|
Supported: Claude Code, Cursor, GitHub Copilot, Windsurf, Aider, Cline, OpenAI Codex CLI. Generates framework-aware context so AI assistants understand Tina4's conventions.
|
|
682
679
|
|
|
683
|
-
##
|
|
680
|
+
## Performance
|
|
684
681
|
|
|
685
|
-
|
|
682
|
+
Benchmarked with `wrk` — 5,000 requests, 50 concurrent, median of 3 runs:
|
|
686
683
|
|
|
687
|
-
|
|
|
688
|
-
|
|
689
|
-
|
|
|
690
|
-
|
|
|
691
|
-
|
|
|
692
|
-
|
|
|
693
|
-
|
|
|
694
|
-
| Plaintext Response | 0.000377 | A+ |
|
|
695
|
-
| CRUD Cycle | 0.000456 | A+ |
|
|
696
|
-
| Paginated Query | 0.000990 | A+ |
|
|
697
|
-
| Framework Startup | 0.000801 | A+ |
|
|
684
|
+
| Framework | JSON req/s | Deps | Features |
|
|
685
|
+
|-----------|-----------|------|----------|
|
|
686
|
+
| **Tina4 Python** | **6,508** | 0 | 54 |
|
|
687
|
+
| FastAPI | 12,652 | 12+ | ~8 |
|
|
688
|
+
| Flask | 4,928 | 6+ | ~7 |
|
|
689
|
+
| Bottle | 4,355 | 0 | ~5 |
|
|
690
|
+
| Django | 4,050 | 20+ | ~22 |
|
|
698
691
|
|
|
699
|
-
|
|
692
|
+
Tina4 Python delivers competitive throughput with **zero dependencies and 54 features** — frameworks with higher req/s have a fraction of the functionality and require dozens of third-party packages.
|
|
693
|
+
|
|
694
|
+
**Across all 4 Tina4 implementations:**
|
|
695
|
+
|
|
696
|
+
| | Python | PHP | Ruby | Node.js |
|
|
697
|
+
|---|--------|-----|------|---------|
|
|
698
|
+
| **JSON req/s** | 6,508 | 29,293 | 10,243 | 84,771 |
|
|
699
|
+
| **Dependencies** | 0 | 0 | 0 | 0 |
|
|
700
|
+
| **Features** | 54 | 54 | 54 | 54 |
|
|
701
|
+
|
|
702
|
+
Run benchmarks locally: `python benchmarks/benchmark.py --python`
|
|
703
|
+
|
|
704
|
+
---
|
|
705
|
+
|
|
706
|
+
## Cross-Framework Parity
|
|
707
|
+
|
|
708
|
+
Tina4 ships identical features across four languages — same architecture, same conventions, same 54 features:
|
|
709
|
+
|
|
710
|
+
| | Python | PHP | Ruby | Node.js |
|
|
711
|
+
|---|--------|-----|------|---------|
|
|
712
|
+
| **Package** | `tina4-python` | `tina4stack/tina4php` | `tina4ruby` | `tina4-nodejs` |
|
|
713
|
+
| **Tests** | 2,066 | 1,427 | 1,793 | 1,950 |
|
|
714
|
+
| **Default port** | 7145 | 7146 | 7147 | 7148 |
|
|
715
|
+
|
|
716
|
+
**7,236 tests** across all 4 frameworks. See [tina4.com](https://tina4.com).
|
|
700
717
|
|
|
701
718
|
---
|
|
702
719
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "tina4-python"
|
|
3
|
-
version = "3.10.
|
|
4
|
-
description = "Tina4 Python
|
|
3
|
+
version = "3.10.41"
|
|
4
|
+
description = "Tina4 for Python — 54 built-in features, zero dependencies"
|
|
5
5
|
authors = [
|
|
6
6
|
{name = "Andre van Zuydam", email = "andrevanzuydam@gmail.com"}
|
|
7
7
|
]
|
|
@@ -1762,8 +1762,8 @@ async def dashboard(request, response):
|
|
|
1762
1762
|
|
|
1763
1763
|
## v3 Features Summary
|
|
1764
1764
|
|
|
1765
|
-
- **
|
|
1766
|
-
- **
|
|
1765
|
+
- **54 built-in features**, zero third-party dependencies
|
|
1766
|
+
- **2,066 tests** passing across all modules
|
|
1767
1767
|
- **Production server auto-detect**: `tina4python serve --production` auto-installs uvicorn
|
|
1768
1768
|
- **`tina4python generate`**: model, route, migration, middleware scaffolding
|
|
1769
1769
|
- **Database**: 5 engines (SQLite, PostgreSQL, MySQL, MSSQL, Firebird), query caching (`TINA4_DB_CACHE=true`, `cache_stats()`, `cache_clear()`)
|
|
@@ -325,7 +325,6 @@ class ORM(metaclass=ORMMeta):
|
|
|
325
325
|
pk_value: Primary key value.
|
|
326
326
|
include: List of relationship names to eager-load.
|
|
327
327
|
"""
|
|
328
|
-
db = cls._get_db()
|
|
329
328
|
pk = cls._get_pk()
|
|
330
329
|
table = cls._get_table()
|
|
331
330
|
pk_col = cls.field_mapping.get(pk, cls._fields[pk].column)
|
|
@@ -334,13 +333,7 @@ class ORM(metaclass=ORMMeta):
|
|
|
334
333
|
if cls.soft_delete:
|
|
335
334
|
sql += " AND deleted_at IS NULL"
|
|
336
335
|
|
|
337
|
-
|
|
338
|
-
if row is None:
|
|
339
|
-
return None
|
|
340
|
-
instance = cls(row)
|
|
341
|
-
if include:
|
|
342
|
-
cls._eager_load([instance], include)
|
|
343
|
-
return instance
|
|
336
|
+
return cls.select_one(sql, [pk_value], include=include)
|
|
344
337
|
|
|
345
338
|
@classmethod
|
|
346
339
|
def find(cls, pk_value, include: list[str] = None):
|
|
@@ -395,6 +388,12 @@ class ORM(metaclass=ORMMeta):
|
|
|
395
388
|
cls._eager_load(instances, include)
|
|
396
389
|
return instances, result.count
|
|
397
390
|
|
|
391
|
+
@classmethod
|
|
392
|
+
def select_one(cls, sql: str, params: list = None, include: list[str] = None):
|
|
393
|
+
"""Return a single ORM instance for a raw SQL query, or None if no rows match."""
|
|
394
|
+
instances, _ = cls.select(sql, params, limit=1, offset=0, include=include)
|
|
395
|
+
return instances[0] if instances else None
|
|
396
|
+
|
|
398
397
|
@classmethod
|
|
399
398
|
def where(cls, filter_sql: str, params: list = None, limit: int = 20, offset: int = 0,
|
|
400
399
|
include: list[str] = None):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
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.10.40 → tina4_python-3.10.41}/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
|
{tina4_python-3.10.40 → tina4_python-3.10.41}/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
|
{tina4_python-3.10.40 → tina4_python-3.10.41}/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.10.40 → tina4_python-3.10.41}/tina4_python/session_handlers/mongodb_handler.py
RENAMED
|
File without changes
|
{tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/session_handlers/redis_handler.py
RENAMED
|
File without changes
|
{tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/session_handlers/valkey_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/templates/docker/distroless/Dockerfile
RENAMED
|
File without changes
|
{tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/templates/docker/poetry/Dockerfile
RENAMED
|
File without changes
|
{tina4_python-3.10.40 → tina4_python-3.10.41}/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.10.40 → tina4_python-3.10.41}/tina4_python/translations/af/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/translations/af/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/translations/en/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/translations/en/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/translations/es/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/translations/es/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/translations/fr/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/translations/fr/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/translations/ja/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/translations/ja/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/translations/zh/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-3.10.40 → tina4_python-3.10.41}/tina4_python/translations/zh/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|