tachyon-api 1.2.0__tar.gz → 1.3.0__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 (168) hide show
  1. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/PKG-INFO +158 -56
  2. tachyon_api-1.3.0/README.md +436 -0
  3. tachyon_api-1.3.0/pyproject.toml +75 -0
  4. tachyon_api-1.3.0/setup.py +55 -0
  5. tachyon_api-1.3.0/tachyon_api/app/_404.py +17 -0
  6. tachyon_api-1.3.0/tachyon_api/app/_405.py +7 -0
  7. tachyon_api-1.3.0/tachyon_api/app/__init__.py +239 -0
  8. tachyon_api-1.3.0/tachyon_api/app/_asgi_entry.py +33 -0
  9. tachyon_api-1.3.0/tachyon_api/app/_asgi_handler.py +14 -0
  10. tachyon_api-1.3.0/tachyon_api/app/_docs_routes.py +43 -0
  11. tachyon_api-1.3.0/tachyon_api/app/_docs_schemas.py +43 -0
  12. tachyon_api-1.3.0/tachyon_api/app/_exception_table.py +66 -0
  13. tachyon_api-1.3.0/tachyon_api/app/_exception_table.pyx +74 -0
  14. tachyon_api-1.3.0/tachyon_api/app/_fast_asgi_factory.py +61 -0
  15. tachyon_api-1.3.0/tachyon_api/app/_handler_factory.py +69 -0
  16. tachyon_api-1.3.0/tachyon_api/app/_http_dispatch.py +20 -0
  17. tachyon_api-1.3.0/tachyon_api/app/_mw_stack.py +27 -0
  18. tachyon_api-1.3.0/tachyon_api/app/_registry.py +20 -0
  19. tachyon_api-1.3.0/tachyon_api/app/_route_installer.py +41 -0
  20. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/core/websocket.py +3 -1
  21. tachyon_api-1.3.0/tachyon_api/openapi/__init__.py +28 -0
  22. tachyon_api-1.3.0/tachyon_api/openapi/_config.py +51 -0
  23. tachyon_api-1.3.0/tachyon_api/openapi/_factory.py +56 -0
  24. tachyon_api-1.3.0/tachyon_api/openapi/_format_map.py +12 -0
  25. tachyon_api-1.3.0/tachyon_api/openapi/_generator.py +60 -0
  26. tachyon_api-1.3.0/tachyon_api/openapi/_info.py +52 -0
  27. tachyon_api-1.3.0/tachyon_api/openapi/_param_schemas.py +40 -0
  28. tachyon_api-1.3.0/tachyon_api/openapi/_redoc_html.py +37 -0
  29. tachyon_api-1.3.0/tachyon_api/openapi/_route_builder.py +174 -0
  30. tachyon_api-1.3.0/tachyon_api/openapi/_safe_json.py +15 -0
  31. tachyon_api-1.3.0/tachyon_api/openapi/_scalar_html.py +39 -0
  32. tachyon_api-1.3.0/tachyon_api/openapi/_server.py +16 -0
  33. tachyon_api-1.3.0/tachyon_api/openapi/_struct_schemas.py +81 -0
  34. tachyon_api-1.3.0/tachyon_api/openapi/_swagger_html.py +46 -0
  35. tachyon_api-1.3.0/tachyon_api/processing/_extractors/__init__.py +28 -0
  36. tachyon_api-1.3.0/tachyon_api/processing/_extractors/_base.py +16 -0
  37. tachyon_api-1.3.0/tachyon_api/processing/_extractors/_missing.py +16 -0
  38. tachyon_api-1.3.0/tachyon_api/processing/_extractors/_missing.pyx +19 -0
  39. tachyon_api-1.3.0/tachyon_api/processing/_extractors/body.pxd +15 -0
  40. tachyon_api-1.3.0/tachyon_api/processing/_extractors/body.py +61 -0
  41. tachyon_api-1.3.0/tachyon_api/processing/_extractors/body.pyx +60 -0
  42. tachyon_api-1.3.0/tachyon_api/processing/_extractors/body_limit.pxd +10 -0
  43. tachyon_api-1.3.0/tachyon_api/processing/_extractors/body_limit.py +36 -0
  44. tachyon_api-1.3.0/tachyon_api/processing/_extractors/body_limit.pyx +38 -0
  45. tachyon_api-1.3.0/tachyon_api/processing/_extractors/cookie.pxd +6 -0
  46. tachyon_api-1.3.0/tachyon_api/processing/_extractors/cookie.py +18 -0
  47. tachyon_api-1.3.0/tachyon_api/processing/_extractors/cookie.pyx +14 -0
  48. tachyon_api-1.3.0/tachyon_api/processing/_extractors/file.pxd +6 -0
  49. tachyon_api-1.3.0/tachyon_api/processing/_extractors/file.py +26 -0
  50. tachyon_api-1.3.0/tachyon_api/processing/_extractors/file.pyx +23 -0
  51. tachyon_api-1.3.0/tachyon_api/processing/_extractors/form.pxd +6 -0
  52. tachyon_api-1.3.0/tachyon_api/processing/_extractors/form.py +17 -0
  53. tachyon_api-1.3.0/tachyon_api/processing/_extractors/form.pyx +14 -0
  54. tachyon_api-1.3.0/tachyon_api/processing/_extractors/header.pxd +12 -0
  55. tachyon_api-1.3.0/tachyon_api/processing/_extractors/header.py +18 -0
  56. tachyon_api-1.3.0/tachyon_api/processing/_extractors/header.pyx +18 -0
  57. tachyon_api-1.3.0/tachyon_api/processing/_extractors/path.pxd +6 -0
  58. tachyon_api-1.3.0/tachyon_api/processing/_extractors/path.py +40 -0
  59. tachyon_api-1.3.0/tachyon_api/processing/_extractors/path.pyx +91 -0
  60. tachyon_api-1.3.0/tachyon_api/processing/_extractors/query.pxd +6 -0
  61. tachyon_api-1.3.0/tachyon_api/processing/_extractors/query.py +26 -0
  62. tachyon_api-1.3.0/tachyon_api/processing/_extractors/query.pyx +80 -0
  63. tachyon_api-1.3.0/tachyon_api/processing/_extractors/query_list.pxd +6 -0
  64. tachyon_api-1.3.0/tachyon_api/processing/_extractors/query_list.py +53 -0
  65. tachyon_api-1.3.0/tachyon_api/processing/_extractors/query_list.pyx +54 -0
  66. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/processing/compiler.py +10 -2
  67. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/processing/compiler.pyx +21 -4
  68. tachyon_api-1.3.0/tachyon_api/processing/dependencies/__init__.py +6 -0
  69. tachyon_api-1.3.0/tachyon_api/processing/dependencies/_callable_factory.py +55 -0
  70. tachyon_api-1.3.0/tachyon_api/processing/dependencies/_circular_detector.py +23 -0
  71. tachyon_api-1.3.0/tachyon_api/processing/dependencies/_circular_detector.pyx +25 -0
  72. tachyon_api-1.3.0/tachyon_api/processing/dependencies/_class_factory.py +32 -0
  73. tachyon_api-1.3.0/tachyon_api/processing/dependencies/_class_factory.pyx +35 -0
  74. tachyon_api-1.3.0/tachyon_api/processing/dependencies/_override_lookup.py +30 -0
  75. tachyon_api-1.3.0/tachyon_api/processing/dependencies/_override_lookup.pyx +31 -0
  76. tachyon_api-1.3.0/tachyon_api/processing/dependencies/_resolver.py +101 -0
  77. tachyon_api-1.3.0/tachyon_api/processing/dependencies/_resolver.pyx +89 -0
  78. tachyon_api-1.3.0/tachyon_api/processing/dependencies/_scope_cache.py +45 -0
  79. tachyon_api-1.3.0/tachyon_api/processing/dependencies/_scope_cache.pyx +36 -0
  80. tachyon_api-1.3.0/tachyon_api/processing/dependencies/_sig_cache.py +20 -0
  81. tachyon_api-1.3.0/tachyon_api/processing/parameters.py +145 -0
  82. tachyon_api-1.3.0/tachyon_api/processing/parameters.pyx +186 -0
  83. tachyon_api-1.3.0/tachyon_api/responses/__init__.py +44 -0
  84. tachyon_api-1.3.0/tachyon_api/responses/_bytes_response.py +32 -0
  85. tachyon_api-1.3.0/tachyon_api/responses/_bytes_response.pyx +41 -0
  86. tachyon_api-1.3.0/tachyon_api/responses/_caches.py +29 -0
  87. tachyon_api-1.3.0/tachyon_api/responses/_constants.py +9 -0
  88. tachyon_api-1.3.0/tachyon_api/responses/_error.py +25 -0
  89. tachyon_api-1.3.0/tachyon_api/responses/_internal_error.py +51 -0
  90. tachyon_api-1.3.0/tachyon_api/responses/_internal_error.pyx +53 -0
  91. tachyon_api-1.3.0/tachyon_api/responses/_json_response.py +44 -0
  92. tachyon_api-1.3.0/tachyon_api/responses/_json_response.pyx +55 -0
  93. tachyon_api-1.3.0/tachyon_api/responses/_success.py +10 -0
  94. tachyon_api-1.3.0/tachyon_api/responses/_validation.py +33 -0
  95. tachyon_api-1.3.0/tachyon_api/responses/_wire.py +26 -0
  96. tachyon_api-1.3.0/tachyon_api/security/__init__.py +21 -0
  97. tachyon_api-1.3.0/tachyon_api/security/_api_key_base.py +30 -0
  98. tachyon_api-1.3.0/tachyon_api/security/_api_key_cookie.py +16 -0
  99. tachyon_api-1.3.0/tachyon_api/security/_api_key_header.py +16 -0
  100. tachyon_api-1.3.0/tachyon_api/security/_api_key_query.py +21 -0
  101. tachyon_api-1.3.0/tachyon_api/security/_basic_credentials.py +11 -0
  102. tachyon_api-1.3.0/tachyon_api/security/_bearer_credentials.py +11 -0
  103. tachyon_api-1.3.0/tachyon_api/security/_bearer_parser.py +16 -0
  104. tachyon_api-1.3.0/tachyon_api/security/_bearer_parser.pyx +29 -0
  105. tachyon_api-1.3.0/tachyon_api/security/_http_basic.py +50 -0
  106. tachyon_api-1.3.0/tachyon_api/security/_http_bearer.py +29 -0
  107. tachyon_api-1.3.0/tachyon_api/security/_oauth2_bearer.py +32 -0
  108. tachyon_api-1.2.0/README.md +0 -337
  109. tachyon_api-1.2.0/pyproject.toml +0 -46
  110. tachyon_api-1.2.0/setup.py +0 -78
  111. tachyon_api-1.2.0/tachyon_api/_server_fast.c +0 -9232
  112. tachyon_api-1.2.0/tachyon_api/app.py +0 -477
  113. tachyon_api-1.2.0/tachyon_api/openapi.py +0 -500
  114. tachyon_api-1.2.0/tachyon_api/processing/dependencies.py +0 -132
  115. tachyon_api-1.2.0/tachyon_api/processing/parameters.py +0 -266
  116. tachyon_api-1.2.0/tachyon_api/processing/parameters.pyx +0 -351
  117. tachyon_api-1.2.0/tachyon_api/responses.py +0 -209
  118. tachyon_api-1.2.0/tachyon_api/security.py +0 -169
  119. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/LICENSE +0 -0
  120. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/MANIFEST.in +0 -0
  121. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/__init__.py +0 -0
  122. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/_server_fast.pyx +0 -0
  123. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/background.py +0 -0
  124. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/cache.py +0 -0
  125. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/cli/__init__.py +0 -0
  126. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/cli/__main__.py +0 -0
  127. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/cli/commands/__init__.py +0 -0
  128. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/cli/commands/generate.py +0 -0
  129. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/cli/commands/lint.py +0 -0
  130. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/cli/commands/new.py +0 -0
  131. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/cli/commands/openapi.py +0 -0
  132. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/cli/commands/routes.py +0 -0
  133. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/cli/commands/run.py +0 -0
  134. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/cli/commands/skill.py +0 -0
  135. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/cli/main.py +0 -0
  136. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/cli/templates/__init__.py +0 -0
  137. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/cli/templates/ai_skill.py +0 -0
  138. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/cli/templates/project.py +0 -0
  139. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/cli/templates/service.py +0 -0
  140. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/cli/utils.py +0 -0
  141. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/core/__init__.py +0 -0
  142. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/core/lifecycle.py +0 -0
  143. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/di.py +0 -0
  144. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/exceptions.py +0 -0
  145. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/files.py +0 -0
  146. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/middlewares/__init__.py +0 -0
  147. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/middlewares/core.py +0 -0
  148. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/middlewares/cors.py +0 -0
  149. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/middlewares/logger.py +0 -0
  150. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/middlewares/security_headers.py +0 -0
  151. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/models.py +0 -0
  152. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/params.py +0 -0
  153. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/processing/__init__.py +0 -0
  154. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/processing/dispatch.py +0 -0
  155. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/processing/dispatch.pyx +0 -0
  156. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/processing/response_processor.py +0 -0
  157. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/processing/response_processor.pyx +0 -0
  158. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/processing/scope.py +0 -0
  159. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/processing/scope.pyx +0 -0
  160. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/router.py +0 -0
  161. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/routing/__init__.py +0 -0
  162. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/routing/trie.py +0 -0
  163. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/routing/trie.pyx +0 -0
  164. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/server.py +0 -0
  165. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/testing.py +0 -0
  166. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/utils/__init__.py +0 -0
  167. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/utils/type_converter.py +0 -0
  168. {tachyon_api-1.2.0 → tachyon_api-1.3.0}/tachyon_api/utils/type_utils.py +0 -0
@@ -1,8 +1,9 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: tachyon-api
3
- Version: 1.2.0
3
+ Version: 1.3.0
4
4
  Summary: A lightweight, FastAPI-inspired web framework
5
5
  License: GPL-3.0-or-later
6
+ License-File: LICENSE
6
7
  Author: Juan Manuel Panozzo Zénere
7
8
  Author-email: jm.panozzozenere@gmail.com
8
9
  Requires-Python: >=3.10,<4.0
@@ -12,7 +13,9 @@ Classifier: Programming Language :: Python :: 3.10
12
13
  Classifier: Programming Language :: Python :: 3.11
13
14
  Classifier: Programming Language :: Python :: 3.12
14
15
  Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
15
17
  Provides-Extra: fast
18
+ Requires-Dist: httptools (>=0.6.0)
16
19
  Requires-Dist: msgspec (>=0.19.0,<0.20.0)
17
20
  Requires-Dist: orjson (>=3.11.1,<4.0.0)
18
21
  Requires-Dist: python-multipart (>=0.0.20,<0.0.21)
@@ -23,10 +26,10 @@ Description-Content-Type: text/markdown
23
26
 
24
27
  # 🚀 Tachyon API
25
28
 
26
- ![Version](https://img.shields.io/badge/version-1.1.0-blue.svg)
29
+ ![Version](https://img.shields.io/badge/version-1.2.x-blue.svg)
27
30
  ![Python](https://img.shields.io/badge/python-3.10+-brightgreen.svg)
28
31
  ![License](https://img.shields.io/badge/license-GPL--3.0-orange.svg)
29
- ![Tests](https://img.shields.io/badge/tests-233%20passed-brightgreen.svg)
32
+ ![Tests](https://img.shields.io/badge/tests-370%20passed-brightgreen.svg)
30
33
  ![Status](https://img.shields.io/badge/status-stable-brightgreen.svg)
31
34
 
32
35
  **A lightweight, high-performance API framework for Python with the elegance of FastAPI and the speed of light.**
@@ -59,7 +62,7 @@ def search(q: str = Query(...), limit: int = Query(10)):
59
62
 
60
63
  ```bash
61
64
  pip install tachyon-api
62
- uvicorn app:app --reload
65
+ tachyon run # uvloop + httptools + reload, served at :8000
63
66
  ```
64
67
 
65
68
  📖 **Docs:** http://localhost:8000/docs
@@ -68,37 +71,55 @@ uvicorn app:app --reload
68
71
 
69
72
  ## ⚡ Performance
70
73
 
71
- Benchmarked against **FastAPI 0.136.1 (Pydantic v2)** · 1 worker · 100 concurrent connections · uvloop + httptools · Cython extensions compiled
74
+ Benchmarked against **FastAPI 0.136.1 (Pydantic v2)** · 1 worker · 100 concurrent connections · uvloop + httptools · precompiled Cython extensions (shipped by default — see below)
72
75
 
73
76
  | Scenario | FastAPI | Tachyon | Speedup |
74
77
  |---|---:|---:|---:|
75
- | Hello World | 10,378 req/s | **49,521 req/s** | **4.77x** |
76
- | Path + query params | 7,294 req/s | **37,991 req/s** | **5.21x** |
77
- | Body validation (Struct) | 8,533 req/s | **41,507 req/s** | **4.86x** |
78
- | Nested body (complex Struct) | 8,205 req/s | **40,816 req/s** | **4.97x** |
79
- | Response model serialization | 6,766 req/s | **47,777 req/s** | **7.06x** |
80
- | Header param + auth | 8,705 req/s | **46,013 req/s** | **5.29x** |
81
- | Dependency injection | 6,491 req/s | **46,940 req/s** | **7.23x** |
82
- | Multiple query params | 6,325 req/s | **34,481 req/s** | **5.45x** |
83
- | **Total throughput** | **62,697 req/s** | **345,046 req/s** | **5.50x** |
78
+ | Hello World | 10,314 req/s | **49,755 req/s** | **4.82x** |
79
+ | Path + query params | 7,166 req/s | **37,598 req/s** | **5.25x** |
80
+ | Body validation (Struct) | 8,371 req/s | **40,916 req/s** | **4.89x** |
81
+ | Nested body (complex Struct) | 8,027 req/s | **39,994 req/s** | **4.98x** |
82
+ | Response model serialization | 6,343 req/s | **47,561 req/s** | **7.50x** |
83
+ | Header param + auth | 8,701 req/s | **45,415 req/s** | **5.22x** |
84
+ | Dependency injection | 6,449 req/s | **45,610 req/s** | **7.07x** |
85
+ | Multiple query params | 6,264 req/s | **34,111 req/s** | **5.45x** |
86
+ | **Total throughput** | **61,635 req/s** | **340,960 req/s** | **5.53x** |
84
87
 
85
88
  **Latency:** ~2.3ms (Tachyon) vs ~13ms (FastAPI) on average.
86
89
 
87
90
  > Benchmark code in [`benchmark/`](./benchmark/). Run with `bash benchmark/run_benchmark.sh`.
88
91
 
89
- ### Optional: Cython compilation
92
+ ### Precompiled wheels — zero setup
90
93
 
91
- Install with Cython extensions for additional speedup on the request hot path:
94
+ `pip install tachyon-api` ships **prebuilt wheels with all 27 Cython extensions already compiled** for:
92
95
 
93
- ```bash
94
- pip install tachyon-api[fast] # installs cython dependency
95
- python setup.py build_ext --inplace # compile extensions (required step)
96
- ```
96
+ | Platform | Architectures | CPython |
97
+ |---|---|---|
98
+ | Linux | x86_64, aarch64 | 3.10 · 3.11 · 3.12 · 3.13 |
99
+ | macOS | arm64 (Apple Silicon) | 3.10 · 3.11 · 3.12 · 3.13 |
100
+ | Windows | x86_64 | 3.10 · 3.11 · 3.12 · 3.13 |
101
+
102
+ No manual build step. No Cython required. The numbers above are what you get out of the box.
103
+
104
+ > **Not on the list?** (macOS Intel, Alpine, etc.) `pip` falls back to the sdist and compiles from `.pyx` source — requires a C compiler and `pip install tachyon-api[fast]` (which pulls in Cython). If compilation fails, the framework still works: runtime falls back to the pure-Python siblings of every `.pyx` module automatically.
97
105
 
98
- > **Note:** `pip install tachyon-api[fast]` installs the `cython` package but does **not**
99
- > auto-compile the extensions. Run `python setup.py build_ext --inplace` manually after install.
100
- > Falls back to pure Python automatically when `.so` is not present — no code changes needed.
101
- > Numbers above reflect the compiled version (~11% faster Python hot path).
106
+ ### Compiled vs pure-Python delta
107
+
108
+ Same code, same workload — the only difference is whether the 27 Cython `.so` extensions are loaded:
109
+
110
+ | Scenario | Compiled | Pure-Python | Δ |
111
+ |---|---:|---:|---:|
112
+ | Hello World | 49,755 req/s | 47,899 req/s | +3.9% |
113
+ | Path + query params | 37,598 req/s | 31,901 req/s | **+17.9%** |
114
+ | Body — simple Struct | 40,916 req/s | 35,623 req/s | **+14.9%** |
115
+ | Body — nested Struct | 39,994 req/s | 35,204 req/s | **+13.6%** |
116
+ | Response model | 47,561 req/s | 40,604 req/s | **+17.1%** |
117
+ | Header param + auth | 45,415 req/s | 39,380 req/s | **+15.3%** |
118
+ | **Dependency injection** | 45,610 req/s | 38,552 req/s | **+18.3%** |
119
+ | Multiple query params | 34,111 req/s | 29,803 req/s | **+14.5%** |
120
+ | **TOTAL** | **340,960 req/s** | **298,966 req/s** | **+14.0%** |
121
+
122
+ The biggest wins concentrate on real framework work — DI resolution (+18.3%), path/query parsing (+17.9%), response model (+17.1%), and validation (+13–15%). Hello-world barely moves (+3.9%): the framework is already a tiny slice of that request.
102
123
 
103
124
  ### Why is Tachyon faster?
104
125
 
@@ -118,15 +139,16 @@ python setup.py build_ext --inplace # compile extensions (required step)
118
139
  | Category | Features |
119
140
  |----------|----------|
120
141
  | **Core** | Decorators API, Routers, Middlewares, ASGI compatible |
121
- | **Parameters** | Path, Query, Body, Header, Cookie, Form, File (all with `alias=`) |
122
- | **Validation** | msgspec Struct (ultra-fast), automatic 422 errors, body size limit |
123
- | **DI** | `@injectable` (implicit), `Depends()` (explicit), circular dep detection |
124
- | **Security** | HTTPBearer, HTTPBasic, OAuth2, API Keys |
125
- | **Async** | Background Tasks, WebSockets |
126
- | **Performance** | orjson serialization, `@cache` decorator, endpoint pre-compilation |
127
- | **Docs** | OpenAPI 3.0, Scalar UI, Swagger, ReDoc (XSS-safe HTML generation) |
128
- | **CLI** | Project scaffolding, code generation, linting |
129
- | **Testing** | `TachyonTestClient`, `dependency_overrides` |
142
+ | **Parameters** | Path, Query, Body (incl. `Body(List[Struct])`), Header, Cookie, Form, File (all with `alias=`) |
143
+ | **Validation** | msgspec Struct (ultra-fast), automatic 422 errors, configurable body size limit (default 2 MB) |
144
+ | **DI** | `@injectable` (3 scopes: singleton / **request** / **transient**), `Depends()` (sync + async), circular dep detection |
145
+ | **Security** | HTTPBearer, HTTPBasic, OAuth2, API Keys (Header / Query / Cookie), `SecurityHeadersMiddleware` (X-Frame-Options, CSP, HSTS, …) |
146
+ | **Async** | Background Tasks (failures logged, not silenced), WebSockets with **typed path params + DI** |
147
+ | **Performance** | orjson serialization, `@cache` decorator, endpoint pre-compilation, 27 precompiled Cython extensions (shipped by default) |
148
+ | **Docs** | OpenAPI 3.0 (incl. `List[Struct]` arrays + `multipart/form-data`), Scalar UI, Swagger, ReDoc (XSS-safe HTML generation) |
149
+ | **CLI** | Project scaffolding, code generation, linting, AI-agent skill installer |
150
+ | **Testing** | `TachyonTestClient` (sync), `create_client()` (async, full httpx kwargs), `dependency_overrides` |
151
+ | **Architecture** | Atomic SRP modules across `app/`, `processing/`, `responses/`, `openapi/`, `security/` — 27 compiled to `.so` for the hot path (v1.2.x refactor + v1.2.9 Cython sprint) |
130
152
 
131
153
  ---
132
154
 
@@ -149,6 +171,7 @@ python setup.py build_ext --inplace # compile extensions (required step)
149
171
  | [Request Lifecycle](./docs/13-request-lifecycle.md) | How requests are processed |
150
172
  | [Migration from FastAPI](./docs/14-migration-fastapi.md) | Migration guide |
151
173
  | [Best Practices](./docs/15-best-practices.md) | Recommended patterns |
174
+ | [Cython Build](./docs/16-cython-build.md) | Precompiled wheels, source builds, and the `.py`/`.pyx` fallback model |
152
175
 
153
176
  ---
154
177
 
@@ -159,16 +182,19 @@ A complete example demonstrating all Tachyon features is available in [`example/
159
182
  ```bash
160
183
  cd example
161
184
  pip install -r requirements.txt
162
- uvicorn example.app:app --reload
185
+ tachyon run example.app:app
163
186
  ```
164
187
 
165
- The KYC Demo implements:
166
- - 🔐 JWT Authentication
167
- - 👤 Customer CRUD
188
+ The KYC Demo exercises every v1.2.x feature:
189
+ - 🔐 JWT Authentication + API Keys
190
+ - 👤 Customer CRUD + bulk endpoint (`Body(List[Struct])`)
168
191
  - 📋 KYC Verification with Background Tasks
169
- - 📁 Document Uploads
170
- - 🌐 WebSocket Notifications
171
- - 🧪 12 Tests with Mocks
192
+ - 📁 Document Uploads (`multipart/form-data`)
193
+ - 🌐 WebSocket — legacy plain-string + modern DI-injected with `room_id: uuid.UUID`
194
+ - 💉 DI scopes — `singleton` (services), `request` (correlation context), `transient` (ID generator)
195
+ - 🛡️ Security headers + opt-in CORS allow-list
196
+ - 🚨 Custom exception handler for the `KYCException` hierarchy
197
+ - 🧪 17 tests (`pytest example/tests/`), including async tests via `create_client`
172
198
 
173
199
  **Demo credentials:** `demo@example.com` / `demo123`
174
200
 
@@ -187,19 +213,71 @@ The KYC Demo implements:
187
213
 
188
214
  ---
189
215
 
216
+ ## 🏛️ Architecture
217
+
218
+ Tachyon's request hot path is a thin chain of composed collaborators — every
219
+ piece is single-responsibility and ready for Cython compilation:
220
+
221
+ ```
222
+ client
223
+ │
224
+ ├─→ Tachyon.__call__ (ASGI entry — sets scope["app"])
225
+ │ │
226
+ │ ├─→ ASGIEntry lazy build of HTTP app
227
+ │ │
228
+ │ ├─→ HTTPDispatcher HTTP → trie · WS/lifespan → Starlette
229
+ │ │
230
+ │ ├─→ MiddlewareStack user-registered middlewares (CORS, Security…)
231
+ │ │
232
+ │ └─→ TachyonDispatcher (Cython cdef) ← radix trie match O(k)
233
+ │ │
234
+ │ ├─→ _ASGIHandler (no-param fast path, 2 sends only)
235
+ │ │
236
+ │ └─→ handler closure
237
+ │ ├─→ ParameterPipeline → 8 atomic extractors
238
+ │ │ (body / query / query-list / header / cookie / form / file / path)
239
+ │ ├─→ DependencyResolver → OverrideLookup / ScopeCache /
240
+ │ │ ClassFactory / CallableFactory
241
+ │ ├─→ ResponseProcessor (msgspec encode if Struct)
242
+ │ └─→ ExceptionTable (walks subclass handlers)
243
+ │
244
+ └─→ TachyonJSONResponse | TachyonBytesResponse | _InternalErrorResponse
245
+ (pre-built ASGI dicts, zero extra allocations per response)
246
+ ```
247
+
248
+ The v1.2.x SRP refactor decomposed the monolithic hot path into atomic modules
249
+ with `__slots__` and full type hints — direct `cdef class` candidates. The
250
+ v1.2.9 Cython sprint then compiled 27 of them to `.so`, keeping every `.py`
251
+ sibling as a transparent fallback (Python prefers `.so` automatically).
252
+
253
+ 👉 [Full architecture documentation](./docs/02-architecture.md)
254
+
255
+ ---
256
+
190
257
  ## 💉 Dependency Injection
191
258
 
192
259
  ```python
193
260
  from tachyon_api import injectable, Depends
194
261
 
195
- @injectable
196
- class UserService:
197
- def get_user(self, id: str):
198
- return {"id": id}
262
+ @injectable # singleton (default) — one per app
263
+ class DB:
264
+ def __init__(self):
265
+ self.pool = "..."
266
+
267
+ @injectable(scope="request") # one per HTTP request
268
+ class RequestContext:
269
+ def __init__(self):
270
+ import uuid
271
+ self.correlation_id = str(uuid.uuid4())
272
+
273
+ @injectable(scope="transient") # new instance every time it's injected
274
+ class IdGenerator:
275
+ def __init__(self):
276
+ self._seq = 0
199
277
 
200
278
  @app.get("/users/{id}")
201
- def get_user(id: str, service: UserService = Depends()):
202
- return service.get_user(id)
279
+ def get_user(id: str, db: DB = Depends(), ctx: RequestContext = Depends()):
280
+ return {"id": id, "trace": ctx.correlation_id}
203
281
  ```
204
282
 
205
283
  👉 [Full DI documentation](./docs/03-dependency-injection.md)
@@ -240,11 +318,22 @@ def notify(background_tasks: BackgroundTasks):
240
318
  ## 🌐 WebSockets
241
319
 
242
320
  ```python
243
- @app.websocket("/ws")
244
- async def websocket(ws):
245
- await ws.accept()
246
- data = await ws.receive_text()
247
- await ws.send_text(f"Echo: {data}")
321
+ import uuid
322
+ from tachyon_api import injectable, Depends
323
+
324
+ @injectable
325
+ class RoomBroadcaster:
326
+ async def join(self, ws, room_key: str): ...
327
+
328
+ @app.websocket("/ws/rooms/{room_id}") # typed UUID path param
329
+ async def room(
330
+ websocket,
331
+ room_id: uuid.UUID, # auto-converted; 1008 on mismatch
332
+ broadcaster: RoomBroadcaster = Depends(), # @injectable DI in WS
333
+ ):
334
+ await broadcaster.join(websocket, str(room_id))
335
+ while True:
336
+ await websocket.send_json({"room": str(room_id)})
248
337
  ```
249
338
 
250
339
  👉 [Full WebSockets documentation](./docs/10-websockets.md)
@@ -295,12 +384,23 @@ Installs knowledge about `Body()` requirement, `Struct` vs BaseModel, DI pattern
295
384
  ## 🧪 Testing
296
385
 
297
386
  ```python
387
+ # Sync — Starlette TestClient compatible
298
388
  from tachyon_api.testing import TachyonTestClient
299
389
 
300
390
  def test_hello():
301
391
  client = TachyonTestClient(app)
302
- response = client.get("/")
303
- assert response.status_code == 200
392
+ assert client.get("/").status_code == 200
393
+
394
+
395
+ # Async — httpx.AsyncClient over ASGI transport
396
+ import pytest
397
+ from tachyon_api.testing import create_client
398
+
399
+ @pytest.mark.asyncio
400
+ async def test_hello_async():
401
+ async with create_client(app, headers={"X-Trace": "abc"}) as client:
402
+ response = await client.get("/")
403
+ assert response.status_code == 200
304
404
  ```
305
405
 
306
406
  ```bash
@@ -315,8 +415,8 @@ pytest tests/ -v
315
415
 
316
416
  | Feature | Tachyon | FastAPI |
317
417
  |---------|---------|---------|
318
- | **Throughput** | ~336k req/s total | ~60k req/s total |
319
- | **Latency** | ~2.1ms avg | ~14ms avg |
418
+ | **Throughput** | ~341k req/s total | ~62k req/s total |
419
+ | **Latency** | ~2.3ms avg | ~14ms avg |
320
420
  | **Routing** | Radix trie O(k) | Regex scan O(N) |
321
421
  | **Serialization** | msgspec + orjson | Pydantic v2 |
322
422
  | **Request compilation** | Once at startup | Per request |
@@ -354,6 +454,8 @@ Upcoming:
354
454
  - Response streaming
355
455
  - GraphQL support
356
456
  - Multi-worker benchmarks
457
+ - Benchmark suite vs Litestar / BlackSheep / Robyn
458
+ - SQLAlchemy async integration guide
357
459
 
358
460
  ---
359
461