tina4-python 3.10.60__tar.gz → 3.10.65__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.60 → tina4_python-3.10.65}/PKG-INFO +1 -1
  2. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/__init__.py +1 -1
  3. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/dev_admin/metrics.py +56 -22
  4. {tina4_python-3.10.60 → tina4_python-3.10.65}/.gitignore +0 -0
  5. {tina4_python-3.10.60 → tina4_python-3.10.65}/README.md +0 -0
  6. {tina4_python-3.10.60 → tina4_python-3.10.65}/pyproject.toml +0 -0
  7. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/CLAUDE.md +0 -0
  8. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/HtmlElement.py +0 -0
  9. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/Testing.py +0 -0
  10. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/ai/__init__.py +0 -0
  11. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/api/__init__.py +0 -0
  12. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/auth/__init__.py +0 -0
  13. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/cache/__init__.py +0 -0
  14. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/cli/__init__.py +0 -0
  15. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/container/__init__.py +0 -0
  16. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/core/__init__.py +0 -0
  17. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/core/cache.py +0 -0
  18. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/core/constants.py +0 -0
  19. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/core/events.py +0 -0
  20. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/core/middleware.py +0 -0
  21. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/core/request.py +0 -0
  22. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/core/response.py +0 -0
  23. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/core/router.py +0 -0
  24. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/core/server.py +0 -0
  25. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/crud/__init__.py +0 -0
  26. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/database/__init__.py +0 -0
  27. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/database/adapter.py +0 -0
  28. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/database/connection.py +0 -0
  29. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/database/firebird.py +0 -0
  30. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/database/mongodb.py +0 -0
  31. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/database/mssql.py +0 -0
  32. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/database/mysql.py +0 -0
  33. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/database/odbc.py +0 -0
  34. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/database/postgres.py +0 -0
  35. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/database/sqlite.py +0 -0
  36. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/debug/__init__.py +0 -0
  37. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/debug/error_overlay.py +0 -0
  38. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/dev_admin/__init__.py +0 -0
  39. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/dev_reload.py +0 -0
  40. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/dotenv/__init__.py +0 -0
  41. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/frond/FROND.md +0 -0
  42. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/frond/__init__.py +0 -0
  43. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/frond/engine.py +0 -0
  44. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/gallery/auth/meta.json +0 -0
  45. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/gallery/auth/src/routes/api/gallery_auth.py +0 -0
  46. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/gallery/database/meta.json +0 -0
  47. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/gallery/database/src/routes/api/gallery_db.py +0 -0
  48. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/gallery/error-overlay/meta.json +0 -0
  49. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/gallery/error-overlay/src/routes/api/gallery_crash.py +0 -0
  50. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/gallery/orm/meta.json +0 -0
  51. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/gallery/orm/src/orm/Product.py +0 -0
  52. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/gallery/orm/src/routes/api/gallery_products.py +0 -0
  53. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/gallery/queue/meta.json +0 -0
  54. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/gallery/queue/src/routes/api/gallery_queue.py +0 -0
  55. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/gallery/rest-api/meta.json +0 -0
  56. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/gallery/rest-api/src/routes/api/gallery_hello.py +0 -0
  57. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/gallery/templates/meta.json +0 -0
  58. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/gallery/templates/src/routes/gallery_page.py +0 -0
  59. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/gallery/templates/src/templates/gallery_page.twig +0 -0
  60. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/graphql/__init__.py +0 -0
  61. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/i18n/__init__.py +0 -0
  62. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/mcp/__init__.py +0 -0
  63. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/mcp/protocol.py +0 -0
  64. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/mcp/tools.py +0 -0
  65. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/messenger/__init__.py +0 -0
  66. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/migration/__init__.py +0 -0
  67. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/migration/runner.py +0 -0
  68. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/orm/__init__.py +0 -0
  69. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/orm/fields.py +0 -0
  70. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/orm/model.py +0 -0
  71. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/public/css/tina4.css +0 -0
  72. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/public/css/tina4.min.css +0 -0
  73. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/public/favicon.ico +0 -0
  74. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/public/images/logo.svg +0 -0
  75. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/public/images/tina4-logo-icon.webp +0 -0
  76. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/public/js/frond.min.js +0 -0
  77. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/public/js/tina4-dev-admin.min.js +0 -0
  78. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/public/js/tina4.min.js +0 -0
  79. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/public/js/tina4js.min.js +0 -0
  80. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/public/swagger/index.html +0 -0
  81. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/public/swagger/oauth2-redirect.html +0 -0
  82. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/query_builder/__init__.py +0 -0
  83. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/queue/__init__.py +0 -0
  84. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/queue_backends/__init__.py +0 -0
  85. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/queue_backends/kafka_backend.py +0 -0
  86. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/queue_backends/mongo_backend.py +0 -0
  87. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/queue_backends/rabbitmq_backend.py +0 -0
  88. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/scss/__init__.py +0 -0
  89. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/scss/tina4css/_alerts.scss +0 -0
  90. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/scss/tina4css/_badges.scss +0 -0
  91. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/scss/tina4css/_buttons.scss +0 -0
  92. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/scss/tina4css/_cards.scss +0 -0
  93. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/scss/tina4css/_forms.scss +0 -0
  94. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/scss/tina4css/_grid.scss +0 -0
  95. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/scss/tina4css/_modals.scss +0 -0
  96. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/scss/tina4css/_nav.scss +0 -0
  97. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/scss/tina4css/_reset.scss +0 -0
  98. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/scss/tina4css/_tables.scss +0 -0
  99. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/scss/tina4css/_typography.scss +0 -0
  100. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/scss/tina4css/_utilities.scss +0 -0
  101. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/scss/tina4css/_variables.scss +0 -0
  102. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/scss/tina4css/base.scss +0 -0
  103. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/scss/tina4css/colors.scss +0 -0
  104. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/scss/tina4css/tina4.scss +0 -0
  105. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/seeder/__init__.py +0 -0
  106. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/service/__init__.py +0 -0
  107. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/session/__init__.py +0 -0
  108. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/session_handlers/__init__.py +0 -0
  109. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/session_handlers/mongodb_handler.py +0 -0
  110. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/session_handlers/redis_handler.py +0 -0
  111. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/session_handlers/valkey_handler.py +0 -0
  112. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/swagger/__init__.py +0 -0
  113. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/templates/components/crud.twig +0 -0
  114. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/templates/docker/distroless/Dockerfile +0 -0
  115. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/templates/docker/poetry/Dockerfile +0 -0
  116. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/templates/docker/python/Dockerfile +0 -0
  117. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/templates/docker/uv/Dockerfile +0 -0
  118. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/templates/errors/302.twig +0 -0
  119. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/templates/errors/401.twig +0 -0
  120. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/templates/errors/403.twig +0 -0
  121. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/templates/errors/404.twig +0 -0
  122. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/templates/errors/500.twig +0 -0
  123. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/templates/errors/502.twig +0 -0
  124. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/templates/errors/503.twig +0 -0
  125. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/templates/errors/base.twig +0 -0
  126. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/templates/frontend/README.md +0 -0
  127. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/templates/readme.md +0 -0
  128. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/test_client/__init__.py +0 -0
  129. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/translations/af/LC_MESSAGES/messages.mo +0 -0
  130. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/translations/af/LC_MESSAGES/messages.po +0 -0
  131. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/translations/en/LC_MESSAGES/messages.mo +0 -0
  132. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/translations/en/LC_MESSAGES/messages.po +0 -0
  133. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/translations/es/LC_MESSAGES/messages.mo +0 -0
  134. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/translations/es/LC_MESSAGES/messages.po +0 -0
  135. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/translations/fr/LC_MESSAGES/messages.mo +0 -0
  136. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/translations/fr/LC_MESSAGES/messages.po +0 -0
  137. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/translations/ja/LC_MESSAGES/messages.mo +0 -0
  138. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/translations/ja/LC_MESSAGES/messages.po +0 -0
  139. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/translations/zh/LC_MESSAGES/messages.mo +0 -0
  140. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/translations/zh/LC_MESSAGES/messages.po +0 -0
  141. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/validator/__init__.py +0 -0
  142. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/websocket/__init__.py +0 -0
  143. {tina4_python-3.10.60 → tina4_python-3.10.65}/tina4_python/websocket/backplane.py +0 -0
  144. {tina4_python-3.10.60 → tina4_python-3.10.65}/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.60
3
+ Version: 3.10.65
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
@@ -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.60"
11
+ __version__ = "3.10.65"
12
12
 
13
13
  # ── Route decorators ──
14
14
  from tina4_python.core.router import ( # noqa: E402, F401
@@ -105,7 +105,7 @@ def quick_metrics(root: str = "src") -> dict:
105
105
  total_functions += functions
106
106
 
107
107
  file_details.append({
108
- "path": str(f.relative_to(".")),
108
+ "path": str(f.relative_to(root_path)),
109
109
  "loc": loc,
110
110
  "blank": blank,
111
111
  "comment": comment,
@@ -211,7 +211,10 @@ def full_analysis(root: str = "src") -> dict:
211
211
  except (SyntaxError, OSError):
212
212
  continue
213
213
 
214
- rel_path = str(f.relative_to("."))
214
+ try:
215
+ rel_path = str(f.relative_to(root_path))
216
+ except ValueError:
217
+ rel_path = str(f.relative_to(root_path.parent)) if root_path.parent != f else f.name
215
218
  lines = source.splitlines()
216
219
  loc = sum(1 for l in lines if l.strip() and not l.strip().startswith("#"))
217
220
 
@@ -495,34 +498,65 @@ def _count_halstead(node: ast.AST, stats: dict):
495
498
  def _has_matching_test(rel_path: str) -> bool:
496
499
  """Check if a source file has a matching test file.
497
500
 
498
- Looks for common test file patterns and also scans any test file
499
- that imports the module by name.
501
+ Three-stage detection:
502
+ 1. Filename matching test_module.py, module_test.py, module_spec.py
503
+ 2. Path matching — any test file referencing the full import path
504
+ 3. Content matching — any test file mentioning the module or class name
500
505
  """
506
+ import re
507
+
501
508
  p = Path(rel_path)
502
- module = p.stem # e.g. "auth" from "tina4_python/auth/__init__.py"
509
+ module = p.stem # e.g. "sqlite" from "tina4_python/database/sqlite.py"
503
510
  if module == "__init__":
504
511
  module = p.parent.name # use parent dir name
505
- # Check common test file patterns
506
- test_patterns = [
507
- Path("tests") / f"test_{module}.py",
508
- Path("tests") / f"test_{module}s.py",
509
- Path("test") / f"test_{module}.py",
510
- Path("spec") / f"test_{module}.py",
511
- Path("tests") / f"{module}_test.py",
512
+
513
+ # Build the full dotted import path for deeper matching
514
+ # e.g. "tina4_python/database/sqlite.py" "tina4_python.database.sqlite"
515
+ parts = list(p.with_suffix("").parts)
516
+ dotted_path = ".".join(parts) # "tina4_python.database.sqlite"
517
+
518
+ # Also track the parent package name for broader matching
519
+ # e.g. "database" from "tina4_python/database/sqlite.py"
520
+ parent_module = p.parent.name if len(p.parts) > 1 else ""
521
+
522
+ # Stage 1: Filename patterns
523
+ test_dirs = [Path("tests"), Path("test"), Path("spec")]
524
+ for td in test_dirs:
525
+ patterns = [
526
+ td / f"test_{module}.py",
527
+ td / f"test_{module}s.py",
528
+ td / f"{module}_test.py",
529
+ td / f"{module}_spec.py",
530
+ ]
531
+ # Also check parent-named tests (test_database.py covers database/sqlite.py)
532
+ if parent_module and parent_module != module:
533
+ patterns.extend([
534
+ td / f"test_{parent_module}.py",
535
+ td / f"test_{parent_module}s.py",
536
+ td / f"{parent_module}_test.py",
537
+ ])
538
+ if any(tp.exists() for tp in patterns):
539
+ return True
540
+
541
+ # Stage 2+3: Content scan — check if ANY test file references this module
542
+ search_terms = [
543
+ re.compile(rf'\b{re.escape(module)}\b', re.IGNORECASE),
512
544
  ]
513
- if any(tp.exists() for tp in test_patterns):
514
- return True
515
- # Grep-based: check if any test file imports this module
516
- import re
517
- import_patterns = [re.compile(rf'\bimport\s+{re.escape(module)}\b'),
518
- re.compile(rf'\bfrom\s+{re.escape(module)}\b')]
519
- for test_dir in (Path("tests"), Path("test"), Path("spec")):
520
- if not test_dir.is_dir():
545
+ # Add dotted path patterns for import matching
546
+ if dotted_path:
547
+ search_terms.append(re.compile(rf'{re.escape(dotted_path)}'))
548
+ # Add class name guesses (CamelCase from snake_case module name)
549
+ class_name = "".join(w.capitalize() for w in module.split("_"))
550
+ if class_name != module:
551
+ search_terms.append(re.compile(rf'\b{re.escape(class_name)}\b'))
552
+
553
+ for td in test_dirs:
554
+ if not td.is_dir():
521
555
  continue
522
- for test_file in test_dir.glob("*.py"):
556
+ for test_file in td.rglob("*.py"):
523
557
  try:
524
558
  content = test_file.read_text(encoding="utf-8", errors="ignore")
525
- if any(pat.search(content) for pat in import_patterns):
559
+ if any(pat.search(content) for pat in search_terms):
526
560
  return True
527
561
  except OSError:
528
562
  pass
File without changes