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