turboapi 0.4.16__cp313-cp313-macosx_10_12_x86_64.whl → 0.5.21__cp313-cp313-macosx_10_12_x86_64.whl

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.
@@ -229,9 +229,12 @@ class RequestBodyParser:
229
229
  """
230
230
  if not body:
231
231
  return {}
232
-
232
+
233
233
  try:
234
- json_data = json.loads(body.decode('utf-8'))
234
+ # CRITICAL: Make a defensive copy immediately using bytearray to force real copy
235
+ # Free-threaded Python with Metal/MLX can have concurrent memory access issues
236
+ body_copy = bytes(bytearray(body))
237
+ json_data = json.loads(body_copy.decode('utf-8'))
235
238
  except (json.JSONDecodeError, UnicodeDecodeError) as e:
236
239
  raise ValueError(f"Invalid JSON body: {e}")
237
240
 
@@ -348,9 +351,16 @@ class ResponseHandler:
348
351
  try:
349
352
  import json
350
353
  body = json.loads(body.decode('utf-8'))
351
- except (json.JSONDecodeError, UnicodeDecodeError):
352
- # Keep as string for HTML/Text responses
353
- body = body.decode('utf-8')
354
+ except json.JSONDecodeError:
355
+ # Not JSON, try as plain text
356
+ try:
357
+ body = body.decode('utf-8')
358
+ except UnicodeDecodeError:
359
+ # Binary data (audio, image, etc.) - keep as bytes
360
+ pass
361
+ except UnicodeDecodeError:
362
+ # Binary data (audio, image, etc.) - keep as bytes
363
+ pass
354
364
  return body, result.status_code
355
365
 
356
366
  # Handle tuple returns: (content, status_code)
@@ -394,6 +404,13 @@ class ResponseHandler:
394
404
  def make_serializable(obj):
395
405
  if isinstance(obj, Model):
396
406
  return obj.model_dump()
407
+ elif isinstance(obj, bytes):
408
+ # Binary data - try to decode as UTF-8, otherwise base64 encode
409
+ try:
410
+ return obj.decode('utf-8')
411
+ except UnicodeDecodeError:
412
+ import base64
413
+ return base64.b64encode(obj).decode('ascii')
397
414
  elif isinstance(obj, dict):
398
415
  return {k: make_serializable(v) for k, v in obj.items()}
399
416
  elif isinstance(obj, (list, tuple)):
@@ -491,7 +508,7 @@ def create_enhanced_handler(original_handler, route_definition):
491
508
 
492
509
  # Call original async handler and await it
493
510
  result = await original_handler(**filtered_kwargs)
494
-
511
+
495
512
  # Normalize response
496
513
  content, status_code = ResponseHandler.normalize_response(result)
497
514
 
@@ -20,16 +20,15 @@ from .version_check import CHECK_MARK, CROSS_MARK, ROCKET
20
20
 
21
21
 
22
22
  def classify_handler(handler, route) -> tuple[str, dict[str, str], dict]:
23
- """Classify a handler for fast dispatch (Phase 3).
23
+ """Classify a handler for fast dispatch (Phase 3 + Phase 4 async).
24
24
 
25
25
  Returns:
26
26
  (handler_type, param_types, model_info) where:
27
- - handler_type: "simple_sync" | "body_sync" | "model_sync" | "enhanced"
27
+ - handler_type: "simple_sync" | "body_sync" | "model_sync" | "simple_async" | "body_async" | "enhanced"
28
28
  - param_types: dict mapping param_name -> type hint string
29
29
  - model_info: dict with "param_name" and "model_class" for model handlers
30
30
  """
31
- if inspect.iscoroutinefunction(handler):
32
- return "enhanced", {}, {}
31
+ is_async = inspect.iscoroutinefunction(handler)
33
32
 
34
33
  sig = inspect.signature(handler)
35
34
  param_types = {}
@@ -42,8 +41,12 @@ def classify_handler(handler, route) -> tuple[str, dict[str, str], dict]:
42
41
  # Check for dhi/Pydantic BaseModel
43
42
  try:
44
43
  if BaseModel is not None and inspect.isclass(annotation) and issubclass(annotation, BaseModel):
45
- # Found a model parameter - use fast model path
44
+ # Found a model parameter - use fast model path (sync only for now)
46
45
  model_info = {"param_name": param_name, "model_class": annotation}
46
+ # For async handlers, model parsing needs the enhanced path
47
+ # since Rust-side model parsing only supports sync handlers
48
+ if is_async:
49
+ needs_body = True
47
50
  continue # Don't add to param_types
48
51
  except TypeError:
49
52
  pass
@@ -64,13 +67,23 @@ def classify_handler(handler, route) -> tuple[str, dict[str, str], dict]:
64
67
  elif annotation is str or annotation is inspect.Parameter.empty:
65
68
  param_types[param_name] = "str"
66
69
 
67
- # Model handlers use fast model path (simd-json + model_validate)
68
- if model_info:
69
- method = route.method.value.upper() if hasattr(route, "method") else "GET"
70
+ method = route.method.value.upper() if hasattr(route, "method") else "GET"
71
+
72
+ # Model handlers use fast model path (simd-json + model_validate) - sync only
73
+ if model_info and not is_async:
70
74
  if method in ("POST", "PUT", "PATCH", "DELETE"):
71
75
  return "model_sync", param_types, model_info
72
76
 
73
- method = route.method.value.upper() if hasattr(route, "method") else "GET"
77
+ # Async handlers - Phase 4 async fast paths via Tokio
78
+ if is_async:
79
+ if method in ("POST", "PUT", "PATCH", "DELETE"):
80
+ if needs_body:
81
+ # Complex body types still need enhanced path
82
+ return "enhanced", param_types, {}
83
+ return "body_async", param_types, {}
84
+ return "simple_async", param_types, {}
85
+
86
+ # Sync handlers - Phase 3 sync fast paths
74
87
  if method in ("POST", "PUT", "PATCH", "DELETE"):
75
88
  if needs_body:
76
89
  return "enhanced", param_types, {}
@@ -207,8 +220,7 @@ class RustIntegratedTurboAPI(TurboAPI):
207
220
  )
208
221
  print(f"{CHECK_MARK} [model_sync] {route.method.value} {route.path}")
209
222
  elif handler_type in ("simple_sync", "body_sync"):
210
- # FAST PATH: Register with metadata for Rust-side parsing
211
- # Enhanced handler is fallback, original handler is for direct call
223
+ # SYNC FAST PATH: Register with metadata for Rust-side parsing
212
224
  enhanced_handler = create_enhanced_handler(route.handler, route)
213
225
  param_types_json = json.dumps(param_types)
214
226
 
@@ -221,6 +233,20 @@ class RustIntegratedTurboAPI(TurboAPI):
221
233
  route.handler, # Original unwrapped handler
222
234
  )
223
235
  print(f"{CHECK_MARK} [{handler_type}] {route.method.value} {route.path}")
236
+ elif handler_type in ("simple_async", "body_async"):
237
+ # ASYNC FAST PATH: Register with Tokio async runtime
238
+ enhanced_handler = create_enhanced_handler(route.handler, route)
239
+ param_types_json = json.dumps(param_types)
240
+
241
+ self.rust_server.add_route_async_fast(
242
+ route.method.value,
243
+ route.path,
244
+ enhanced_handler, # Fallback wrapper
245
+ handler_type,
246
+ param_types_json,
247
+ route.handler, # Original async handler
248
+ )
249
+ print(f"{CHECK_MARK} [{handler_type}] {route.method.value} {route.path}")
224
250
  else:
225
251
  # ENHANCED PATH: Full Python wrapper needed
226
252
  enhanced_handler = create_enhanced_handler(route.handler, route)
Binary file
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: turboapi
3
- Version: 0.4.16
3
+ Version: 0.5.21
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -11,7 +11,7 @@ Classifier: Programming Language :: Rust
11
11
  Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
12
12
  Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
13
13
  Classifier: Framework :: FastAPI
14
- Requires-Dist: dhi>=1.1.3
14
+ Requires-Dist: dhi>=1.1.15
15
15
  Requires-Dist: matplotlib>=3.5.0 ; extra == 'benchmark'
16
16
  Requires-Dist: requests>=2.25.0 ; extra == 'benchmark'
17
17
  Requires-Dist: pytest>=7.0.0 ; extra == 'dev'
@@ -42,11 +42,19 @@ Project-URL: Repository, https://github.com/justrach/turboAPI
42
42
  <strong>The FastAPI you know. The speed you deserve.</strong>
43
43
  </p>
44
44
 
45
+ <p align="center">
46
+ <a href="https://pypi.org/project/turboapi/"><img src="https://img.shields.io/pypi/v/turboapi.svg" alt="PyPI version"></a>
47
+ <a href="https://github.com/justrach/turboAPI/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License"></a>
48
+ <a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.13+-blue.svg" alt="Python 3.13+"></a>
49
+ <a href="https://deepwiki.com/justrach/turboAPI"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
50
+ </p>
51
+
45
52
  <p align="center">
46
53
  <a href="#the-problem">The Problem</a> •
47
54
  <a href="#the-solution">The Solution</a> •
48
55
  <a href="#quick-start">Quick Start</a> •
49
56
  <a href="#benchmarks">Benchmarks</a> •
57
+ <a href="#async-support">Async Support</a> •
50
58
  <a href="#migration-guide">Migration Guide</a>
51
59
  </p>
52
60
 
@@ -64,7 +72,7 @@ You've optimized your database queries. Added caching. Switched to async. Still
64
72
 
65
73
  ## The Solution
66
74
 
67
- **TurboAPI** is FastAPI with a Rust-powered engine. Same API. Same syntax. 2-3x faster.
75
+ **TurboAPI** is FastAPI with a Rust-powered engine. Same API. Same syntax. **1.3-1.8x faster**.
68
76
 
69
77
  ```python
70
78
  # This is all you change
@@ -82,9 +90,10 @@ Everything else stays exactly the same.
82
90
  | What FastAPI Does | What TurboAPI Does | Speedup |
83
91
  |-------------------|-------------------|---------|
84
92
  | HTTP parsing in Python | HTTP parsing in Rust (Hyper/Tokio) | 3x |
85
- | JSON with `json.dumps()` | JSON with SIMD-accelerated Rust | 2x |
93
+ | JSON with `json.dumps()` | SIMD-accelerated JSON (simd-json) | 2x |
86
94
  | GIL-bound threading | Python 3.13 free-threading | 2x |
87
95
  | dict-based routing | Radix tree with O(log n) lookup | 1.5x |
96
+ | Async via asyncio | Async via Tokio work-stealing | 1.2x |
88
97
 
89
98
  The result? Your existing FastAPI code runs faster without changing a single line of business logic.
90
99
 
@@ -116,6 +125,30 @@ app.run()
116
125
 
117
126
  That's it. Your first TurboAPI server is running at `http://localhost:8000`.
118
127
 
128
+ ### Async Handlers (New!)
129
+
130
+ TurboAPI now supports **true async** with Tokio-powered execution:
131
+
132
+ ```python
133
+ from turboapi import TurboAPI
134
+ import asyncio
135
+
136
+ app = TurboAPI()
137
+
138
+ @app.get("/sync")
139
+ def sync_handler():
140
+ return {"type": "sync", "message": "Fast!"}
141
+
142
+ @app.get("/async")
143
+ async def async_handler():
144
+ await asyncio.sleep(0.001) # Simulated I/O
145
+ return {"type": "async", "message": "Even faster under load!"}
146
+
147
+ app.run()
148
+ ```
149
+
150
+ Async handlers are automatically detected and routed through Tokio's work-stealing scheduler for optimal concurrency.
151
+
119
152
  ### For Maximum Performance
120
153
 
121
154
  Run with Python's free-threading mode:
@@ -132,9 +165,18 @@ This unlocks the full power of TurboAPI's Rust core by removing the GIL bottlene
132
165
 
133
166
  Real numbers matter. Here's TurboAPI vs FastAPI on identical hardware:
134
167
 
135
- <p align="center">
136
- <img src="assets/benchmark_throughput.png" alt="Throughput Comparison" width="800"/>
137
- </p>
168
+ ### Latest Benchmark Results
169
+
170
+ | Endpoint | TurboAPI | FastAPI | Improvement |
171
+ |----------|----------|---------|-------------|
172
+ | **Sequential Latency** |
173
+ | GET / | 0.76ms | 1.05ms | **1.4x faster** |
174
+ | GET /benchmark/simple | 0.61ms | 0.81ms | **1.3x faster** |
175
+ | GET /benchmark/medium | 0.61ms | 0.77ms | **1.3x faster** |
176
+ | GET /benchmark/json | 0.72ms | 1.04ms | **1.4x faster** |
177
+ | **Concurrent Latency** |
178
+ | GET / | 2.05ms | 2.53ms | **1.2x faster** |
179
+ | GET /benchmark/json | 2.17ms | 3.90ms | **1.8x faster** |
138
180
 
139
181
  ### Throughput (requests/second)
140
182
 
@@ -144,34 +186,89 @@ Real numbers matter. Here's TurboAPI vs FastAPI on identical hardware:
144
186
  | GET /json (object) | **20,592** | 7,882 | 2.6x |
145
187
  | GET /users/{id} (path params) | **18,428** | 7,344 | 2.5x |
146
188
  | POST /items (model validation) | **19,255** | 6,312 | **3.1x** |
147
- | GET /status201 (custom status) | **15,698** | 8,608 | 1.8x |
148
-
149
- ### Latency (lower is better)
150
189
 
151
- <p align="center">
152
- <img src="assets/benchmark_latency.png" alt="Latency Comparison" width="800"/>
153
- </p>
190
+ ### Async Handler Performance
154
191
 
155
- | Endpoint | TurboAPI (avg/p99) | FastAPI (avg/p99) |
156
- |----------|-------------------|-------------------|
157
- | GET / | 5.1ms / 11.6ms | 12.0ms / 18.6ms |
158
- | GET /json | 4.9ms / 11.8ms | 12.7ms / 17.6ms |
159
- | POST /items | **5.3ms / 13.1ms** | 16.2ms / 43.9ms |
192
+ | Metric | Sync Handler | Async Handler | Notes |
193
+ |--------|--------------|---------------|-------|
194
+ | Sequential (100 req) | 0.66ms | 0.76ms | Similar performance |
195
+ | Concurrent (200 req) | 108ms batch | 139ms batch | Sync faster for CPU-bound |
196
+ | I/O Wait (1ms sleep) | 2.22ms | 2.06ms | **Async wins for I/O** |
160
197
 
161
- *Benchmarked with wrk, 4 threads, 100 connections, 10 seconds. Python 3.13t free-threading mode.*
198
+ **Key Insight:** Use async handlers when you have actual I/O operations (database, network). For pure CPU work, sync handlers are slightly faster.
162
199
 
163
200
  ### Run Your Own Benchmarks
164
201
 
165
202
  ```bash
166
- # Install wrk (macOS)
167
- brew install wrk
203
+ # Quick benchmark
204
+ python benches/python_benchmark.py
168
205
 
169
- # Run the benchmark suite
170
- pip install matplotlib # for charts
171
- PYTHON_GIL=0 python benchmarks/run_benchmarks.py
206
+ # Full comparison with FastAPI
207
+ python tests/benchmark_comparison.py
172
208
 
173
- # Generate charts
174
- python benchmarks/generate_charts.py
209
+ # Async vs Sync comparison
210
+ python benches/async_comparison_bench.py
211
+ ```
212
+
213
+ ---
214
+
215
+ ## Async Support
216
+
217
+ ### How Async Works in TurboAPI
218
+
219
+ TurboAPI uses a **hybrid async architecture**:
220
+
221
+ ```
222
+ ┌─────────────────────────────────────────────────────────┐
223
+ │ Your Python Handlers │
224
+ │ @app.get("/sync") @app.get("/async") │
225
+ │ def handler(): async def handler(): │
226
+ ├─────────────────────────────────────────────────────────┤
227
+ │ Handler Classification │
228
+ │ simple_sync │ body_sync │ simple_async │ body_async │
229
+ ├─────────────────────────────────────────────────────────┤
230
+ │ Tokio Runtime (Rust) │
231
+ │ Work-stealing scheduler • 14 workers │
232
+ ├─────────────────────────────────────────────────────────┤
233
+ │ pyo3-async-runtimes │
234
+ │ Python coroutines ↔ Rust futures conversion │
235
+ └─────────────────────────────────────────────────────────┘
236
+ ```
237
+
238
+ ### Handler Types
239
+
240
+ TurboAPI automatically classifies handlers for optimal dispatch:
241
+
242
+ | Handler Type | Description | Use Case |
243
+ |--------------|-------------|----------|
244
+ | `simple_sync` | Sync, no body | GET endpoints |
245
+ | `body_sync` | Sync, with body | POST/PUT without complex types |
246
+ | `model_sync` | Sync, with model validation | POST with dhi models |
247
+ | `simple_async` | Async, no body | GET with I/O operations |
248
+ | `body_async` | Async, with body | POST/PUT with I/O operations |
249
+ | `enhanced` | Full Python wrapper | Complex dependencies |
250
+
251
+ ### When to Use Async
252
+
253
+ ```python
254
+ # Use sync for pure computation
255
+ @app.get("/compute")
256
+ def compute():
257
+ result = sum(i * i for i in range(1000))
258
+ return {"result": result}
259
+
260
+ # Use async for I/O operations
261
+ @app.get("/fetch-data")
262
+ async def fetch_data():
263
+ async with aiohttp.ClientSession() as session:
264
+ async with session.get("https://api.example.com/data") as resp:
265
+ return await resp.json()
266
+
267
+ # Use async for database operations
268
+ @app.get("/users/{user_id}")
269
+ async def get_user(user_id: int):
270
+ user = await database.fetch_one(query, values={"id": user_id})
271
+ return {"user": user}
175
272
  ```
176
273
 
177
274
  ---
@@ -234,6 +331,7 @@ Everything you use in FastAPI works in TurboAPI:
234
331
  | Query parameters | ✅ | With validation |
235
332
  | Request body (JSON) | ✅ | SIMD-accelerated |
236
333
  | Response models | ✅ | Full support |
334
+ | **Async handlers** | ✅ | **Tokio-powered** |
237
335
  | Dependency injection | ✅ | `Depends()` with caching |
238
336
  | OAuth2 authentication | ✅ | Password & AuthCode flows |
239
337
  | HTTP Basic/Bearer auth | ✅ | Full implementation |
@@ -241,7 +339,7 @@ Everything you use in FastAPI works in TurboAPI:
241
339
  | CORS middleware | ✅ | Rust-accelerated |
242
340
  | GZip middleware | ✅ | Configurable |
243
341
  | Background tasks | ✅ | Async-compatible |
244
- | WebSocket | ✅ | Basic support |
342
+ | WebSocket | ✅ | HTTP upgrade support |
245
343
  | APIRouter | ✅ | Prefixes and tags |
246
344
  | HTTPException | ✅ | With custom headers |
247
345
  | Custom responses | ✅ | JSON, HTML, Redirect, etc. |
@@ -266,6 +364,27 @@ def get_current_user(token: str = Depends(oauth2_scheme)):
266
364
  return {"user": "authenticated", "token": token}
267
365
  ```
268
366
 
367
+ ### Async Database Access
368
+
369
+ ```python
370
+ from turboapi import TurboAPI
371
+ import asyncpg
372
+
373
+ app = TurboAPI()
374
+ pool = None
375
+
376
+ @app.on_event("startup")
377
+ async def startup():
378
+ global pool
379
+ pool = await asyncpg.create_pool("postgresql://localhost/mydb")
380
+
381
+ @app.get("/users/{user_id}")
382
+ async def get_user(user_id: int):
383
+ async with pool.acquire() as conn:
384
+ row = await conn.fetchrow("SELECT * FROM users WHERE id = $1", user_id)
385
+ return dict(row) if row else {"error": "Not found"}
386
+ ```
387
+
269
388
  ### Request Validation
270
389
 
271
390
  ```python
@@ -297,47 +416,33 @@ app.add_middleware(
297
416
  app.add_middleware(GZipMiddleware, minimum_size=1000)
298
417
  ```
299
418
 
300
- ### API Router
301
-
302
- ```python
303
- from turboapi import APIRouter
304
-
305
- router = APIRouter(prefix="/api/v1", tags=["users"])
306
-
307
- @router.get("/users")
308
- def list_users():
309
- return {"users": []}
310
-
311
- @router.get("/users/{user_id}")
312
- def get_user(user_id: int):
313
- return {"user_id": user_id}
314
-
315
- app.include_router(router)
316
- ```
317
-
318
419
  ---
319
420
 
320
- ## How It Works
421
+ ## Architecture
321
422
 
322
423
  TurboAPI's secret is a hybrid architecture:
323
424
 
324
425
  ```
325
- ┌──────────────────────────────────────────────────────┐
326
- │ Your Python Application
327
- (exactly like FastAPI code)
328
- ├──────────────────────────────────────────────────────┤
329
- TurboAPI (FastAPI-compatible layer)
330
- Routing • Validation • Dependency Injection
331
- ├──────────────────────────────────────────────────────┤
332
- PyO3 Bridge (zero-copy)
333
- Rust Python with minimal overhead
334
- ├──────────────────────────────────────────────────────┤
335
- TurboNet (Rust HTTP Core)
336
- Hyper + Tokio async runtime
337
- │ • SIMD-accelerated JSON (simd-json) │
338
- Radix tree routing
339
- Zero-copy response buffers
340
- └──────────────────────────────────────────────────────┘
426
+ ┌──────────────────────────────────────────────────────────┐
427
+ │ Your Python Application
428
+ (exactly like FastAPI code)
429
+ ├──────────────────────────────────────────────────────────┤
430
+ TurboAPI (FastAPI-compatible layer)
431
+ Routing • Validation • Dependency Injection
432
+ ├──────────────────────────────────────────────────────────┤
433
+ Handler Classification (Phase 3+4)
434
+ simple_sync body_sync simple_async body_async │
435
+ ├──────────────────────────────────────────────────────────┤
436
+ PyO3 Bridge (zero-copy)
437
+ Rust Python with minimal overhead
438
+ ├──────────────────────────────────────────────────────────┤
439
+ TurboNet (Rust HTTP Core)
440
+ Hyper + Tokio async runtime (14 worker threads)
441
+ │ • SIMD-accelerated JSON (simd-json) │
442
+ │ • Radix tree routing │
443
+ │ • Zero-copy response buffers │
444
+ │ • pyo3-async-runtimes for async handler support │
445
+ └──────────────────────────────────────────────────────────┘
341
446
  ```
342
447
 
343
448
  **Python handles the logic you care about.** Routes, validation rules, business logic—all in Python.
@@ -369,6 +474,10 @@ pip install -e ./python
369
474
 
370
475
  # Run tests
371
476
  PYTHON_GIL=0 python -m pytest tests/ -v
477
+
478
+ # Run benchmarks
479
+ python benches/python_benchmark.py
480
+ python tests/benchmark_comparison.py
372
481
  ```
373
482
 
374
483
  ---
@@ -383,20 +492,21 @@ PYTHON_GIL=0 python -m pytest tests/ -v
383
492
  - [x] FastAPI feature parity (OAuth2, Depends, Middleware)
384
493
  - [x] Radix tree routing with path parameters
385
494
  - [x] Handler classification for optimized fast paths
495
+ - [x] **Async handler optimization (Tokio + pyo3-async-runtimes)**
496
+ - [x] **WebSocket HTTP upgrade support**
386
497
 
387
498
  ### In Progress 🚧
388
499
 
389
- - [ ] Async handler optimization (pure Tokio)
390
- - [ ] WebSocket performance improvements
391
500
  - [ ] HTTP/2 with server push
501
+ - [ ] OpenAPI/Swagger auto-generation
392
502
 
393
503
  ### Planned 📋
394
504
 
395
- - [ ] OpenAPI/Swagger auto-generation
396
505
  - [ ] GraphQL support
397
506
  - [ ] Database connection pooling
398
507
  - [ ] Prometheus metrics
399
508
  - [ ] Distributed tracing
509
+ - [ ] gRPC support
400
510
 
401
511
  ---
402
512
 
@@ -404,6 +514,7 @@ PYTHON_GIL=0 python -m pytest tests/ -v
404
514
 
405
515
  - **Issues & Features**: [GitHub Issues](https://github.com/justrach/turboAPI/issues)
406
516
  - **Discussions**: [GitHub Discussions](https://github.com/justrach/turboAPI/discussions)
517
+ - **Documentation**: [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/justrach/turboAPI)
407
518
 
408
519
  ---
409
520
 
@@ -10,20 +10,20 @@ turboapi/main_app.py,sha256=5w6x1DX_XChPCcZf24b4CC8qe24XFyGY3BRuR71qkCM,13411
10
10
  turboapi/middleware.py,sha256=3G5zhPKiHm07b_xv_dOsO88W1PfO78SGMySJe4d9nb4,10737
11
11
  turboapi/models.py,sha256=OzyDTEl97zcXa6DTrsR_hZZjj8Lr9QwsD0BrC74BE5o,4476
12
12
  turboapi/openapi.py,sha256=wwS4akekFns-OYQUh7bjKBzRqdg9Z7z5MFo27LlFkEY,7281
13
- turboapi/request_handler.py,sha256=aADbJdFQp5f3zzWD5fv0Jrtk6W46RzG7rGhlZrFL5tA,23768
13
+ turboapi/request_handler.py,sha256=YHfJFqQJI_mZdczpARprOkpsNnCIojTrlW_vLgTdPQw,24593
14
14
  turboapi/responses.py,sha256=wiYkG53NNwXu1RDyRlZFF-8jxx51xL6LOTUj5TG__2c,6052
15
15
  turboapi/routing.py,sha256=-39IUSfsMswCLR-zJ6c4Ri0tYd7_UjYnQyioT4a1W_Q,7601
16
- turboapi/rust_integration.py,sha256=wvZzNJMDnkRMu-GRtItT9paZeMXSSfjCHcVbEuRiCzc,14251
16
+ turboapi/rust_integration.py,sha256=StR_4PHIzz1Qk9T-MG5veu3qerwKohoXFeOagk6Be6E,15543
17
17
  turboapi/security.py,sha256=U2ZQSMWK9a6YzSk5F39TgeZriJ7JtDNZo3RldVPphKI,17493
18
18
  turboapi/server_integration.py,sha256=cnyT4Eqrw3lkZjdVkDvN2qMH5yXh68LJhC2w9ccH9Qc,17904
19
19
  turboapi/staticfiles.py,sha256=MLSvPeYUQGPEL4_mVQ2z3ItREZxUTEN-awQrNxPAgsM,2861
20
20
  turboapi/status.py,sha256=7qVEXVQ3AVFcgEKbmdq6dTypCP275qIbk51hMUQztXA,3049
21
21
  turboapi/templating.py,sha256=YlZeesNAuAcqkdUhkE1xGzTY0w_-nhbG5bJWntYe2AM,2087
22
22
  turboapi/testclient.py,sha256=TBuRPms8G9MncARfwtvCKvqrtfthraTcy0TkPmweMao,10669
23
- turboapi/turbonet.cpython-313-darwin.so,sha256=EOg7BGIPvUb8ufbWQw_OjbCVRYth6B1NqAkXeriUAXU,4334200
23
+ turboapi/turbonet.cpython-313-darwin.so,sha256=qaOvLmIwboqv7_subdCl-6q5I38tMZ6VLxRSLo_Ba5Q,5669784
24
24
  turboapi/version_check.py,sha256=NmKEt9Qloi5NrGYvVusjFTDhMhZzZfazuXyjcOPO2vc,9357
25
25
  turboapi/websockets.py,sha256=7Ao_dKfGWHu2nMU5pm9X20E9P0qnh4lJOykHFmzc5tc,4226
26
- turboapi-0.4.16.dist-info/METADATA,sha256=QRA-pJvH2qesLSCW-_7YT0ora9YIjuBS5cLfOqq4hiE,12289
27
- turboapi-0.4.16.dist-info/WHEEL,sha256=y-bBezkr9XqWB_KK0tUa5PfJn4Rf73obH4dbo4t0ZEc,107
28
- turboapi-0.4.16.dist-info/licenses/LICENSE,sha256=09pmQi_FlhCpUCJ8bMQQoax_oOooJS3FKezznBBU8OQ,1068
29
- turboapi-0.4.16.dist-info/RECORD,,
26
+ turboapi-0.5.21.dist-info/METADATA,sha256=8q-P0UJmWeRKs9E3YJpaOLNJeZc9OK_elGvCvNjcunM,17556
27
+ turboapi-0.5.21.dist-info/WHEEL,sha256=y-bBezkr9XqWB_KK0tUa5PfJn4Rf73obH4dbo4t0ZEc,107
28
+ turboapi-0.5.21.dist-info/licenses/LICENSE,sha256=09pmQi_FlhCpUCJ8bMQQoax_oOooJS3FKezznBBU8OQ,1068
29
+ turboapi-0.5.21.dist-info/RECORD,,