tina4-python 3.10.65__tar.gz → 3.10.67__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.
Files changed (144) hide show
  1. {tina4_python-3.10.65 → tina4_python-3.10.67}/PKG-INFO +1 -1
  2. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/CLAUDE.md +8 -3
  3. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/__init__.py +1 -1
  4. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/core/request.py +1 -3
  5. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/dev_admin/metrics.py +14 -0
  6. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/orm/model.py +14 -4
  7. {tina4_python-3.10.65 → tina4_python-3.10.67}/.gitignore +0 -0
  8. {tina4_python-3.10.65 → tina4_python-3.10.67}/README.md +0 -0
  9. {tina4_python-3.10.65 → tina4_python-3.10.67}/pyproject.toml +0 -0
  10. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/HtmlElement.py +0 -0
  11. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/Testing.py +0 -0
  12. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/ai/__init__.py +0 -0
  13. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/api/__init__.py +0 -0
  14. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/auth/__init__.py +0 -0
  15. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/cache/__init__.py +0 -0
  16. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/cli/__init__.py +0 -0
  17. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/container/__init__.py +0 -0
  18. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/core/__init__.py +0 -0
  19. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/core/cache.py +0 -0
  20. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/core/constants.py +0 -0
  21. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/core/events.py +0 -0
  22. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/core/middleware.py +0 -0
  23. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/core/response.py +0 -0
  24. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/core/router.py +0 -0
  25. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/core/server.py +0 -0
  26. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/crud/__init__.py +0 -0
  27. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/database/__init__.py +0 -0
  28. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/database/adapter.py +0 -0
  29. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/database/connection.py +0 -0
  30. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/database/firebird.py +0 -0
  31. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/database/mongodb.py +0 -0
  32. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/database/mssql.py +0 -0
  33. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/database/mysql.py +0 -0
  34. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/database/odbc.py +0 -0
  35. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/database/postgres.py +0 -0
  36. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/database/sqlite.py +0 -0
  37. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/debug/__init__.py +0 -0
  38. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/debug/error_overlay.py +0 -0
  39. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/dev_admin/__init__.py +0 -0
  40. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/dev_reload.py +0 -0
  41. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/dotenv/__init__.py +0 -0
  42. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/frond/FROND.md +0 -0
  43. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/frond/__init__.py +0 -0
  44. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/frond/engine.py +0 -0
  45. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/gallery/auth/meta.json +0 -0
  46. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/gallery/auth/src/routes/api/gallery_auth.py +0 -0
  47. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/gallery/database/meta.json +0 -0
  48. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/gallery/database/src/routes/api/gallery_db.py +0 -0
  49. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/gallery/error-overlay/meta.json +0 -0
  50. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/gallery/error-overlay/src/routes/api/gallery_crash.py +0 -0
  51. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/gallery/orm/meta.json +0 -0
  52. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/gallery/orm/src/orm/Product.py +0 -0
  53. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/gallery/orm/src/routes/api/gallery_products.py +0 -0
  54. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/gallery/queue/meta.json +0 -0
  55. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/gallery/queue/src/routes/api/gallery_queue.py +0 -0
  56. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/gallery/rest-api/meta.json +0 -0
  57. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/gallery/rest-api/src/routes/api/gallery_hello.py +0 -0
  58. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/gallery/templates/meta.json +0 -0
  59. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/gallery/templates/src/routes/gallery_page.py +0 -0
  60. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/gallery/templates/src/templates/gallery_page.twig +0 -0
  61. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/graphql/__init__.py +0 -0
  62. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/i18n/__init__.py +0 -0
  63. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/mcp/__init__.py +0 -0
  64. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/mcp/protocol.py +0 -0
  65. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/mcp/tools.py +0 -0
  66. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/messenger/__init__.py +0 -0
  67. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/migration/__init__.py +0 -0
  68. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/migration/runner.py +0 -0
  69. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/orm/__init__.py +0 -0
  70. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/orm/fields.py +0 -0
  71. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/public/css/tina4.css +0 -0
  72. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/public/css/tina4.min.css +0 -0
  73. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/public/favicon.ico +0 -0
  74. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/public/images/logo.svg +0 -0
  75. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/public/images/tina4-logo-icon.webp +0 -0
  76. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/public/js/frond.min.js +0 -0
  77. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/public/js/tina4-dev-admin.min.js +0 -0
  78. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/public/js/tina4.min.js +0 -0
  79. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/public/js/tina4js.min.js +0 -0
  80. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/public/swagger/index.html +0 -0
  81. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/public/swagger/oauth2-redirect.html +0 -0
  82. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/query_builder/__init__.py +0 -0
  83. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/queue/__init__.py +0 -0
  84. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/queue_backends/__init__.py +0 -0
  85. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/queue_backends/kafka_backend.py +0 -0
  86. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/queue_backends/mongo_backend.py +0 -0
  87. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/queue_backends/rabbitmq_backend.py +0 -0
  88. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/scss/__init__.py +0 -0
  89. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/scss/tina4css/_alerts.scss +0 -0
  90. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/scss/tina4css/_badges.scss +0 -0
  91. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/scss/tina4css/_buttons.scss +0 -0
  92. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/scss/tina4css/_cards.scss +0 -0
  93. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/scss/tina4css/_forms.scss +0 -0
  94. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/scss/tina4css/_grid.scss +0 -0
  95. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/scss/tina4css/_modals.scss +0 -0
  96. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/scss/tina4css/_nav.scss +0 -0
  97. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/scss/tina4css/_reset.scss +0 -0
  98. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/scss/tina4css/_tables.scss +0 -0
  99. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/scss/tina4css/_typography.scss +0 -0
  100. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/scss/tina4css/_utilities.scss +0 -0
  101. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/scss/tina4css/_variables.scss +0 -0
  102. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/scss/tina4css/base.scss +0 -0
  103. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/scss/tina4css/colors.scss +0 -0
  104. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/scss/tina4css/tina4.scss +0 -0
  105. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/seeder/__init__.py +0 -0
  106. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/service/__init__.py +0 -0
  107. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/session/__init__.py +0 -0
  108. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/session_handlers/__init__.py +0 -0
  109. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/session_handlers/mongodb_handler.py +0 -0
  110. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/session_handlers/redis_handler.py +0 -0
  111. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/session_handlers/valkey_handler.py +0 -0
  112. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/swagger/__init__.py +0 -0
  113. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/templates/components/crud.twig +0 -0
  114. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/templates/docker/distroless/Dockerfile +0 -0
  115. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/templates/docker/poetry/Dockerfile +0 -0
  116. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/templates/docker/python/Dockerfile +0 -0
  117. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/templates/docker/uv/Dockerfile +0 -0
  118. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/templates/errors/302.twig +0 -0
  119. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/templates/errors/401.twig +0 -0
  120. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/templates/errors/403.twig +0 -0
  121. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/templates/errors/404.twig +0 -0
  122. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/templates/errors/500.twig +0 -0
  123. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/templates/errors/502.twig +0 -0
  124. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/templates/errors/503.twig +0 -0
  125. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/templates/errors/base.twig +0 -0
  126. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/templates/frontend/README.md +0 -0
  127. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/templates/readme.md +0 -0
  128. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/test_client/__init__.py +0 -0
  129. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/translations/af/LC_MESSAGES/messages.mo +0 -0
  130. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/translations/af/LC_MESSAGES/messages.po +0 -0
  131. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/translations/en/LC_MESSAGES/messages.mo +0 -0
  132. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/translations/en/LC_MESSAGES/messages.po +0 -0
  133. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/translations/es/LC_MESSAGES/messages.mo +0 -0
  134. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/translations/es/LC_MESSAGES/messages.po +0 -0
  135. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/translations/fr/LC_MESSAGES/messages.mo +0 -0
  136. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/translations/fr/LC_MESSAGES/messages.po +0 -0
  137. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/translations/ja/LC_MESSAGES/messages.mo +0 -0
  138. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/translations/ja/LC_MESSAGES/messages.po +0 -0
  139. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/translations/zh/LC_MESSAGES/messages.mo +0 -0
  140. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/translations/zh/LC_MESSAGES/messages.po +0 -0
  141. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/validator/__init__.py +0 -0
  142. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/websocket/__init__.py +0 -0
  143. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/websocket/backplane.py +0 -0
  144. {tina4_python-3.10.65 → tina4_python-3.10.67}/tina4_python/wsdl/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tina4-python
3
- Version: 3.10.65
3
+ Version: 3.10.67
4
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
@@ -820,9 +820,14 @@ orm_bind(Database("sqlite:///app.db")) # Assigns DB to all ORM subclasses
820
820
  user = User({"name": "Alice", "email": "alice@example.com"})
821
821
  user.save()
822
822
 
823
- # Load (returns bool, populates the instance)
824
- user = User()
825
- if user.load("email = ?", ["alice@example.com"]):
823
+ # Load — alias for select_one (class method, returns instance or None)
824
+ user = User.load("SELECT * FROM users WHERE email = ?", ["alice@example.com"])
825
+ if user:
826
+ print(user.name)
827
+
828
+ # Find by primary key
829
+ user = User.find(1)
830
+ if user:
826
831
  print(user.name)
827
832
 
828
833
  # Update
@@ -8,7 +8,7 @@ Tina4 Python v3.0 — Zero-dependency, lightweight web framework.
8
8
 
9
9
  One import, everything works.
10
10
  """
11
- __version__ = "3.10.65"
11
+ __version__ = "3.10.67"
12
12
 
13
13
  # ── Route decorators ──
14
14
  from tina4_python.core.router import ( # noqa: E402, F401
@@ -86,9 +86,7 @@ class Request:
86
86
  fields = {}
87
87
  for key, value in req.body.items():
88
88
  if isinstance(value, dict) and "filename" in value:
89
- # Base64-encode file content for safe transport
90
- import base64
91
- value["content"] = base64.b64encode(value["content"]).decode()
89
+ # Content stays as raw bytes — no base64 encoding
92
90
  files[key] = value
93
91
  else:
94
92
  fields[key] = value
@@ -15,6 +15,11 @@ import hashlib
15
15
  from pathlib import Path
16
16
 
17
17
 
18
+ # ── Scan root tracking ────────────────────────────────────────
19
+ # Stores the resolved root so file_detail() can locate framework files.
20
+ _last_scan_root: str = ""
21
+
22
+
18
23
  # ── Quick Metrics ──────────────────────────────────────────────
19
24
 
20
25
 
@@ -24,12 +29,15 @@ def _resolve_root(root: str = "src") -> str:
24
29
  If src/ has Python files, scan the user's project code.
25
30
  Otherwise, scan the framework itself — so the bubble chart is never empty.
26
31
  """
32
+ global _last_scan_root
27
33
  src = Path(root)
28
34
  if src.exists() and list(src.rglob("*.py")):
35
+ _last_scan_root = str(Path(root).resolve())
29
36
  return root
30
37
  # Fallback: scan the framework package
31
38
  import tina4_python
32
39
  framework_dir = str(Path(tina4_python.__file__).parent)
40
+ _last_scan_root = framework_dir
33
41
  return framework_dir
34
42
 
35
43
 
@@ -330,6 +338,12 @@ def full_analysis(root: str = "src") -> dict:
330
338
  def file_detail(file_path: str) -> dict:
331
339
  """Detailed metrics for a single file."""
332
340
  p = Path(file_path)
341
+ if not p.exists() and _last_scan_root:
342
+ # Try resolving relative to the last scan root (framework mode)
343
+ candidate = Path(_last_scan_root) / file_path
344
+ if candidate.exists():
345
+ p = candidate
346
+ file_path = str(p)
333
347
  if not p.exists():
334
348
  return {"error": f"File not found: {file_path}"}
335
349
 
@@ -370,10 +370,20 @@ class ORM(metaclass=ORMMeta):
370
370
  """Alias for find_by_id()."""
371
371
  return cls.find_by_id(pk_value, include)
372
372
 
373
- @classmethod
374
- def load(cls, pk_value, include: list[str] = None):
375
- """Alias for find_by_id()."""
376
- return cls.find_by_id(pk_value, include)
373
+ def load(self, sql: str, params: list = None, include: list[str] = None) -> bool:
374
+ """Load a record into this instance via selectOne.
375
+
376
+ Returns True if a record was found and loaded, False otherwise.
377
+ """
378
+ cls = type(self)
379
+ result = cls.select_one(sql, params, include=include)
380
+ if result is None:
381
+ return False
382
+ for key, value in result.to_dict().items():
383
+ if hasattr(self, key):
384
+ setattr(self, key, value)
385
+ self._persisted = True
386
+ return True
377
387
 
378
388
  @classmethod
379
389
  def find_or_fail(cls, pk_value):
File without changes