turboapi 0.4.15__tar.gz → 0.4.16__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. turboapi-0.4.16/.github/workflows/build-and-release.yml +199 -0
  2. turboapi-0.4.16/.github/workflows/ci.yml +179 -0
  3. {turboapi-0.4.15 → turboapi-0.4.16}/.github/workflows/release.yml +12 -12
  4. {turboapi-0.4.15 → turboapi-0.4.16}/Cargo.lock +108 -2
  5. {turboapi-0.4.15 → turboapi-0.4.16}/Cargo.toml +5 -1
  6. turboapi-0.4.16/PKG-INFO +423 -0
  7. turboapi-0.4.16/README.md +388 -0
  8. turboapi-0.4.16/assets/architecture.png +0 -0
  9. turboapi-0.4.16/assets/benchmark_latency.png +0 -0
  10. turboapi-0.4.16/assets/benchmark_speedup.png +0 -0
  11. turboapi-0.4.16/assets/benchmark_throughput.png +0 -0
  12. {turboapi-0.4.15 → turboapi-0.4.16}/benches/performance_bench.rs +23 -23
  13. turboapi-0.4.16/benchmarks/README.md +35 -0
  14. turboapi-0.4.16/benchmarks/bench_json.py +209 -0
  15. turboapi-0.4.16/benchmarks/bench_memory.py +192 -0
  16. turboapi-0.4.16/benchmarks/bench_throughput.py +227 -0
  17. turboapi-0.4.16/benchmarks/bench_validation.py +241 -0
  18. turboapi-0.4.16/benchmarks/generate_charts.py +399 -0
  19. turboapi-0.4.16/benchmarks/run_all.sh +31 -0
  20. turboapi-0.4.16/benchmarks/run_benchmarks.py +383 -0
  21. {turboapi-0.4.15 → turboapi-0.4.16}/pyproject.toml +20 -34
  22. turboapi-0.4.16/python/turboapi/__init__.py +141 -0
  23. turboapi-0.4.16/python/turboapi/background.py +51 -0
  24. turboapi-0.4.16/python/turboapi/datastructures.py +262 -0
  25. turboapi-0.4.16/python/turboapi/encoders.py +323 -0
  26. turboapi-0.4.16/python/turboapi/exceptions.py +111 -0
  27. {turboapi-0.4.15 → turboapi-0.4.16}/python/turboapi/main_app.py +59 -4
  28. {turboapi-0.4.15 → turboapi-0.4.16}/python/turboapi/middleware.py +4 -6
  29. {turboapi-0.4.15 → turboapi-0.4.16/python}/turboapi/models.py +15 -33
  30. turboapi-0.4.16/python/turboapi/openapi.py +236 -0
  31. {turboapi-0.4.15 → turboapi-0.4.16/python}/turboapi/request_handler.py +172 -32
  32. turboapi-0.4.16/python/turboapi/responses.py +209 -0
  33. {turboapi-0.4.15 → turboapi-0.4.16/python}/turboapi/routing.py +2 -1
  34. {turboapi-0.4.15 → turboapi-0.4.16}/python/turboapi/rust_integration.py +111 -20
  35. {turboapi-0.4.15 → turboapi-0.4.16/python}/turboapi/security.py +32 -3
  36. turboapi-0.4.16/python/turboapi/staticfiles.py +91 -0
  37. turboapi-0.4.16/python/turboapi/status.py +104 -0
  38. turboapi-0.4.16/python/turboapi/templating.py +73 -0
  39. turboapi-0.4.16/python/turboapi/testclient.py +321 -0
  40. turboapi-0.4.16/python/turboapi/websockets.py +130 -0
  41. {turboapi-0.4.15 → turboapi-0.4.16}/setup_python313t.sh +0 -0
  42. {turboapi-0.4.15 → turboapi-0.4.16}/src/http2.rs +53 -33
  43. {turboapi-0.4.15 → turboapi-0.4.16}/src/lib.rs +28 -20
  44. {turboapi-0.4.15 → turboapi-0.4.16}/src/micro_bench.rs +43 -32
  45. {turboapi-0.4.15 → turboapi-0.4.16}/src/middleware.rs +157 -104
  46. {turboapi-0.4.15 → turboapi-0.4.16}/src/python_worker.rs +58 -58
  47. {turboapi-0.4.15 → turboapi-0.4.16}/src/response.rs +4 -1
  48. {turboapi-0.4.15 → turboapi-0.4.16}/src/router.rs +49 -17
  49. {turboapi-0.4.15 → turboapi-0.4.16}/src/server.rs +1228 -467
  50. turboapi-0.4.16/src/simd_json.rs +392 -0
  51. turboapi-0.4.16/src/simd_parse.rs +507 -0
  52. {turboapi-0.4.15 → turboapi-0.4.16}/src/threadpool.rs +71 -30
  53. {turboapi-0.4.15 → turboapi-0.4.16}/src/validation.rs +28 -26
  54. {turboapi-0.4.15 → turboapi-0.4.16}/src/websocket.rs +43 -31
  55. {turboapi-0.4.15 → turboapi-0.4.16}/src/zerocopy.rs +65 -53
  56. {turboapi-0.4.15 → turboapi-0.4.16}/test_package_integrity.py +0 -0
  57. {turboapi-0.4.15 → turboapi-0.4.16}/tests/comparison_before_after.py +7 -7
  58. {turboapi-0.4.15 → turboapi-0.4.16}/tests/quick_body_test.py +3 -3
  59. {turboapi-0.4.15 → turboapi-0.4.16}/tests/test_async_handlers.py +12 -0
  60. {turboapi-0.4.15 → turboapi-0.4.16}/tests/test_async_simple.py +0 -0
  61. turboapi-0.4.16/tests/test_comprehensive_parity.py +569 -0
  62. {turboapi-0.4.15 → turboapi-0.4.16}/tests/test_comprehensive_v0_4_15.py +0 -0
  63. {turboapi-0.4.15 → turboapi-0.4.16}/tests/test_fastapi_compatibility.py +10 -10
  64. turboapi-0.4.16/tests/test_fastapi_parity.py +1080 -0
  65. {turboapi-0.4.15 → turboapi-0.4.16}/tests/test_performance_regression.py +15 -0
  66. {turboapi-0.4.15 → turboapi-0.4.16}/tests/test_post_body_parsing.py +10 -10
  67. {turboapi-0.4.15 → turboapi-0.4.16}/tests/test_query_and_headers.py +8 -0
  68. {turboapi-0.4.15 → turboapi-0.4.16}/tests/test_request_parsing.py +10 -1
  69. turboapi-0.4.16/tests/test_satya_0_4_0_compatibility.py +331 -0
  70. {turboapi-0.4.15 → turboapi-0.4.16}/tests/test_wrk_regression.py +0 -0
  71. turboapi-0.4.15/.github/workflows/build-and-release.yml +0 -377
  72. turboapi-0.4.15/.github/workflows/build-wheels.yml +0 -212
  73. turboapi-0.4.15/.github/workflows/ci.yml +0 -151
  74. turboapi-0.4.15/PKG-INFO +0 -31
  75. turboapi-0.4.15/README.md +0 -929
  76. turboapi-0.4.15/benchmarks/comprehensive_wrk_benchmark.py +0 -284
  77. turboapi-0.4.15/benchmarks/turboapi_vs_fastapi_benchmark.py +0 -310
  78. turboapi-0.4.15/benchmarks/turboapi_vs_fastapi_simple.py +0 -249
  79. turboapi-0.4.15/benchmarks/wrk_output.txt +0 -0
  80. turboapi-0.4.15/python/pyproject.toml +0 -74
  81. turboapi-0.4.15/python/turboapi/__init__.py +0 -24
  82. turboapi-0.4.15/python/turboapi/models.py +0 -148
  83. turboapi-0.4.15/python/turboapi/request_handler.py +0 -462
  84. turboapi-0.4.15/python/turboapi/routing.py +0 -219
  85. turboapi-0.4.15/python/turboapi/security.py +0 -542
  86. turboapi-0.4.15/tests/test_satya_0_4_0_compatibility.py +0 -247
  87. turboapi-0.4.15/turboapi/__init__.py +0 -24
  88. turboapi-0.4.15/turboapi/async_limiter.py +0 -86
  89. turboapi-0.4.15/turboapi/async_pool.py +0 -141
  90. turboapi-0.4.15/turboapi/decorators.py +0 -69
  91. turboapi-0.4.15/turboapi/main_app.py +0 -314
  92. turboapi-0.4.15/turboapi/middleware.py +0 -342
  93. turboapi-0.4.15/turboapi/rust_integration.py +0 -258
  94. turboapi-0.4.15/turboapi/server_integration.py +0 -436
  95. turboapi-0.4.15/turboapi/version_check.py +0 -268
  96. {turboapi-0.4.15 → turboapi-0.4.16}/.github/scripts/check_performance_regression.py +0 -0
  97. {turboapi-0.4.15 → turboapi-0.4.16}/.github/scripts/compare_benchmarks.py +0 -0
  98. {turboapi-0.4.15 → turboapi-0.4.16}/.github/workflows/README.md +0 -0
  99. {turboapi-0.4.15 → turboapi-0.4.16}/.github/workflows/benchmark.yml +0 -0
  100. {turboapi-0.4.15 → turboapi-0.4.16}/.gitignore +0 -0
  101. {turboapi-0.4.15 → turboapi-0.4.16}/AGENTS.md +0 -0
  102. {turboapi-0.4.15 → turboapi-0.4.16}/ASYNC_FIX_v0_4_15.md +0 -0
  103. {turboapi-0.4.15 → turboapi-0.4.16}/BENCHMARK_FAQ.md +0 -0
  104. {turboapi-0.4.15 → turboapi-0.4.16}/BENCHMARK_METHODOLOGY_RESPONSE.md +0 -0
  105. {turboapi-0.4.15 → turboapi-0.4.16}/BENCHMARK_ONEPAGER.md +0 -0
  106. {turboapi-0.4.15 → turboapi-0.4.16}/CHANGELOG.md +0 -0
  107. {turboapi-0.4.15 → turboapi-0.4.16}/FASTAPI_COMPATIBILITY.md +0 -0
  108. {turboapi-0.4.15 → turboapi-0.4.16}/LICENSE +0 -0
  109. {turboapi-0.4.15 → turboapi-0.4.16}/Makefile +0 -0
  110. {turboapi-0.4.15 → turboapi-0.4.16}/PHASE_3_COMPLETE.md +0 -0
  111. {turboapi-0.4.15 → turboapi-0.4.16}/POST_BODY_PARSING_FIX.md +0 -0
  112. {turboapi-0.4.15 → turboapi-0.4.16}/QUICK_RESPONSE_MULTICORE.md +0 -0
  113. {turboapi-0.4.15 → turboapi-0.4.16}/RELEASE_NOTES_v0.4.13.md +0 -0
  114. {turboapi-0.4.15 → turboapi-0.4.16}/RELEASE_NOTES_v0.4.14.md +0 -0
  115. {turboapi-0.4.15 → turboapi-0.4.16}/RESPONSE_SUMMARY.md +0 -0
  116. {turboapi-0.4.15 → turboapi-0.4.16}/TESTING.md +0 -0
  117. {turboapi-0.4.15 → turboapi-0.4.16}/TODO_v0.4.15.md +0 -0
  118. {turboapi-0.4.15 → turboapi-0.4.16}/V0.4.13_SUMMARY.md +0 -0
  119. {turboapi-0.4.15 → turboapi-0.4.16}/V0.4.14_SUMMARY.md +0 -0
  120. {turboapi-0.4.15 → turboapi-0.4.16}/V0.4.15_SUMMARY.md +0 -0
  121. {turboapi-0.4.15 → turboapi-0.4.16}/benchmark_comparison.png +0 -0
  122. {turboapi-0.4.15 → turboapi-0.4.16}/benchmark_graphs/turbo_vs_fastapi_performance_20250929_025531.png +0 -0
  123. {turboapi-0.4.15 → turboapi-0.4.16}/docs/ARCHITECTURE_DIAGRAM.md +0 -0
  124. {turboapi-0.4.15 → turboapi-0.4.16}/docs/AUTHENTICATION_GUIDE.md +0 -0
  125. {turboapi-0.4.15 → turboapi-0.4.16}/examples/authentication_demo.py +0 -0
  126. {turboapi-0.4.15 → turboapi-0.4.16}/examples/multi_route_app.py +0 -0
  127. {turboapi-0.4.15 → turboapi-0.4.16}/python/MANIFEST.in +0 -0
  128. {turboapi-0.4.15 → turboapi-0.4.16}/python/setup.py +0 -0
  129. {turboapi-0.4.15 → turboapi-0.4.16}/python/turboapi/async_limiter.py +0 -0
  130. {turboapi-0.4.15 → turboapi-0.4.16}/python/turboapi/async_pool.py +0 -0
  131. {turboapi-0.4.15 → turboapi-0.4.16}/python/turboapi/decorators.py +0 -0
  132. {turboapi-0.4.15 → turboapi-0.4.16}/python/turboapi/server_integration.py +0 -0
  133. {turboapi-0.4.15 → turboapi-0.4.16}/python/turboapi/version_check.py +0 -0
  134. {turboapi-0.4.15 → turboapi-0.4.16}/src/request.rs +0 -0
  135. {turboapi-0.4.15 → turboapi-0.4.16}/test_simple_post.py +0 -0
  136. {turboapi-0.4.15 → turboapi-0.4.16}/tests/README.md +0 -0
  137. {turboapi-0.4.15 → turboapi-0.4.16}/tests/benchmark_comparison.py +0 -0
  138. {turboapi-0.4.15 → turboapi-0.4.16}/tests/fastapi_equivalent.py +0 -0
  139. {turboapi-0.4.15 → turboapi-0.4.16}/tests/quick_test.py +0 -0
  140. {turboapi-0.4.15 → turboapi-0.4.16}/tests/test.py +0 -0
  141. {turboapi-0.4.15 → turboapi-0.4.16}/tests/test_security_features.py +0 -0
  142. {turboapi-0.4.15 → turboapi-0.4.16}/tests/wrk_benchmark.py +0 -0
  143. {turboapi-0.4.15 → turboapi-0.4.16}/tests/wrk_comparison.py +0 -0
  144. {turboapi-0.4.15 → turboapi-0.4.16}/turbo_vs_fastapi_benchmark_20250929_025526.json +0 -0
@@ -0,0 +1,199 @@
1
+ name: Build & Publish
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ tags: ['v*']
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: write
11
+ id-token: write
12
+
13
+ jobs:
14
+ check-version:
15
+ name: Check if version is new
16
+ runs-on: ubuntu-latest
17
+ outputs:
18
+ should_publish: ${{ steps.check.outputs.should_publish }}
19
+ version: ${{ steps.check.outputs.version }}
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+ - name: Check PyPI for existing version
23
+ id: check
24
+ run: |
25
+ VERSION=$(grep -m1 'version = "' Cargo.toml | sed 's/.*"\(.*\)"/\1/')
26
+ echo "version=$VERSION" >> $GITHUB_OUTPUT
27
+ if [[ "$GITHUB_REF" == refs/tags/v* ]]; then
28
+ echo "should_publish=true" >> $GITHUB_OUTPUT
29
+ echo "Tag push detected, will publish v$VERSION"
30
+ exit 0
31
+ fi
32
+ HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://pypi.org/pypi/turboapi/$VERSION/json")
33
+ if [ "$HTTP_STATUS" = "404" ]; then
34
+ echo "should_publish=true" >> $GITHUB_OUTPUT
35
+ echo "Version $VERSION not on PyPI, will publish"
36
+ else
37
+ echo "should_publish=false" >> $GITHUB_OUTPUT
38
+ echo "Version $VERSION already on PyPI, skipping"
39
+ fi
40
+
41
+ linux:
42
+ runs-on: ubuntu-latest
43
+ needs: [check-version]
44
+ if: needs.check-version.outputs.should_publish == 'true'
45
+ strategy:
46
+ matrix:
47
+ target: [x86_64, aarch64]
48
+ fail-fast: false
49
+ steps:
50
+ - uses: actions/checkout@v4
51
+ - uses: actions/setup-python@v5
52
+ with:
53
+ python-version: |
54
+ 3.13
55
+ - name: Build wheels
56
+ uses: PyO3/maturin-action@v1
57
+ with:
58
+ target: ${{ matrix.target }}
59
+ args: --release --out dist --find-interpreter
60
+ sccache: 'true'
61
+ manylinux: auto
62
+ - uses: actions/upload-artifact@v4
63
+ with:
64
+ name: wheels-linux-${{ matrix.target }}
65
+ path: dist
66
+
67
+ windows:
68
+ runs-on: windows-latest
69
+ needs: [check-version]
70
+ if: needs.check-version.outputs.should_publish == 'true'
71
+ strategy:
72
+ matrix:
73
+ target: [x64]
74
+ fail-fast: false
75
+ steps:
76
+ - uses: actions/checkout@v4
77
+ - uses: actions/setup-python@v5
78
+ with:
79
+ python-version: |
80
+ 3.13
81
+ - name: Build wheels
82
+ uses: PyO3/maturin-action@v1
83
+ with:
84
+ args: --release --out dist --find-interpreter
85
+ sccache: 'true'
86
+ - uses: actions/upload-artifact@v4
87
+ with:
88
+ name: wheels-windows-${{ matrix.target }}
89
+ path: dist
90
+
91
+ macos:
92
+ runs-on: macos-latest
93
+ needs: [check-version]
94
+ if: needs.check-version.outputs.should_publish == 'true'
95
+ strategy:
96
+ matrix:
97
+ target: [x86_64-apple-darwin, aarch64-apple-darwin]
98
+ fail-fast: false
99
+ steps:
100
+ - uses: actions/checkout@v4
101
+ - uses: actions/setup-python@v5
102
+ with:
103
+ python-version: |
104
+ 3.13
105
+ - name: Build wheels
106
+ uses: PyO3/maturin-action@v1
107
+ with:
108
+ target: ${{ matrix.target }}
109
+ args: --release --out dist --find-interpreter
110
+ sccache: 'true'
111
+ - uses: actions/upload-artifact@v4
112
+ with:
113
+ name: wheels-macos-${{ matrix.target }}
114
+ path: dist
115
+
116
+ sdist:
117
+ runs-on: ubuntu-latest
118
+ needs: [check-version]
119
+ if: needs.check-version.outputs.should_publish == 'true'
120
+ steps:
121
+ - uses: actions/checkout@v4
122
+ - name: Build sdist
123
+ uses: PyO3/maturin-action@v1
124
+ with:
125
+ command: sdist
126
+ args: --out dist
127
+ - uses: actions/upload-artifact@v4
128
+ with:
129
+ name: sdist
130
+ path: dist
131
+
132
+ publish:
133
+ name: Publish to PyPI
134
+ runs-on: ubuntu-latest
135
+ needs: [linux, windows, macos, sdist]
136
+ steps:
137
+ - uses: actions/download-artifact@v4
138
+ with:
139
+ pattern: '{wheels-*,sdist}'
140
+ path: dist
141
+ merge-multiple: true
142
+ - name: Publish to PyPI
143
+ uses: pypa/gh-action-pypi-publish@release/v1
144
+ with:
145
+ password: ${{ secrets.PYPI_API_TOKEN }}
146
+ skip-existing: true
147
+
148
+ release:
149
+ name: Create GitHub Release
150
+ runs-on: ubuntu-latest
151
+ needs: [check-version, publish]
152
+ if: startsWith(github.ref, 'refs/tags/v')
153
+ steps:
154
+ - uses: actions/checkout@v4
155
+ with:
156
+ fetch-depth: 0
157
+ - uses: actions/download-artifact@v4
158
+ with:
159
+ pattern: '{wheels-*,sdist}'
160
+ path: dist
161
+ merge-multiple: true
162
+ - name: Create Release
163
+ uses: softprops/action-gh-release@v2
164
+ with:
165
+ files: dist/*
166
+ generate_release_notes: true
167
+
168
+ tag-and-release:
169
+ name: Tag new version
170
+ runs-on: ubuntu-latest
171
+ needs: [check-version, publish]
172
+ if: github.ref == 'refs/heads/main' && needs.check-version.outputs.should_publish == 'true'
173
+ steps:
174
+ - uses: actions/checkout@v4
175
+ with:
176
+ fetch-depth: 0
177
+ token: ${{ secrets.GITHUB_TOKEN }}
178
+ - name: Configure git
179
+ run: |
180
+ git config user.email "action@github.com"
181
+ git config user.name "GitHub Action"
182
+ - name: Create tag
183
+ env:
184
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
185
+ run: |
186
+ VERSION="${{ needs.check-version.outputs.version }}"
187
+ git tag "v${VERSION}"
188
+ git push origin "v${VERSION}"
189
+ - uses: actions/download-artifact@v4
190
+ with:
191
+ pattern: '{wheels-*,sdist}'
192
+ path: dist
193
+ merge-multiple: true
194
+ - name: Create GitHub Release
195
+ uses: softprops/action-gh-release@v2
196
+ with:
197
+ tag_name: v${{ needs.check-version.outputs.version }}
198
+ files: dist/*
199
+ generate_release_notes: true
@@ -0,0 +1,179 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ env:
10
+ CARGO_TERM_COLOR: always
11
+
12
+ jobs:
13
+ lint:
14
+ name: Lint
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Install Rust
20
+ uses: dtolnay/rust-toolchain@stable
21
+ with:
22
+ components: rustfmt, clippy
23
+
24
+ - name: Cache Rust dependencies
25
+ uses: Swatinem/rust-cache@v2
26
+
27
+ - name: Check formatting
28
+ run: cargo fmt --all -- --check
29
+
30
+ - name: Run clippy
31
+ run: cargo clippy --all-targets -- -W warnings 2>&1 || true
32
+
33
+ test-rust:
34
+ name: Test Rust
35
+ runs-on: ${{ matrix.os }}
36
+ strategy:
37
+ matrix:
38
+ os: [ubuntu-latest, macos-latest, windows-latest]
39
+ fail-fast: false
40
+ steps:
41
+ - uses: actions/checkout@v4
42
+
43
+ - name: Install Rust
44
+ uses: dtolnay/rust-toolchain@stable
45
+
46
+ - name: Cache Rust dependencies
47
+ uses: Swatinem/rust-cache@v2
48
+
49
+ - name: Check Rust compilation
50
+ run: cargo check --all-targets
51
+
52
+ test-python:
53
+ name: "test (Python ${{ matrix.python-version }})"
54
+ runs-on: ${{ matrix.os }}
55
+ strategy:
56
+ matrix:
57
+ os: [ubuntu-latest, macos-latest]
58
+ python-version: ['3.13']
59
+ fail-fast: false
60
+ steps:
61
+ - uses: actions/checkout@v4
62
+
63
+ - name: Set up Python ${{ matrix.python-version }}
64
+ uses: actions/setup-python@v5
65
+ with:
66
+ python-version: ${{ matrix.python-version }}
67
+ allow-prereleases: true
68
+
69
+ - name: Install Rust
70
+ uses: dtolnay/rust-toolchain@stable
71
+
72
+ - name: Cache Rust dependencies
73
+ uses: Swatinem/rust-cache@v2
74
+
75
+ - name: Install dependencies
76
+ run: |
77
+ python -m pip install --upgrade pip
78
+ pip install maturin pytest pytest-asyncio requests
79
+
80
+ - name: Build and install turboapi
81
+ run: |
82
+ maturin build --release -i python --out dist
83
+ pip install dist/*.whl
84
+ # dhi is installed as a dependency automatically
85
+
86
+ - name: Run tests
87
+ run: python -m pytest $GITHUB_WORKSPACE/tests/ -v --tb=short
88
+
89
+ test-free-threaded:
90
+ name: "test (${{ matrix.python-version }} free-threaded)"
91
+ runs-on: ${{ matrix.os }}
92
+ strategy:
93
+ matrix:
94
+ os: [ubuntu-latest, macos-latest]
95
+ python-version: ['3.13t']
96
+ fail-fast: false
97
+ steps:
98
+ - uses: actions/checkout@v4
99
+
100
+ - name: Set up Python ${{ matrix.python-version }} (free-threaded)
101
+ uses: actions/setup-python@v5
102
+ with:
103
+ python-version: ${{ matrix.python-version }}
104
+ allow-prereleases: true
105
+
106
+ - name: Install Rust
107
+ uses: dtolnay/rust-toolchain@stable
108
+
109
+ - name: Cache Rust dependencies
110
+ uses: Swatinem/rust-cache@v2
111
+
112
+ - name: Install dependencies
113
+ run: |
114
+ python -m pip install --upgrade pip
115
+ pip install maturin pytest pytest-asyncio requests
116
+
117
+ - name: Build and install turboapi (free-threaded)
118
+ run: |
119
+ maturin build --release -i python --out dist
120
+ pip install dist/*.whl
121
+ # dhi is installed as a dependency automatically
122
+
123
+ - name: Run tests (free-threaded)
124
+ run: python -m pytest $GITHUB_WORKSPACE/tests/ -v --tb=short
125
+
126
+ - name: Run thread-safety smoke test
127
+ run: |
128
+ python -c "
129
+ import threading, concurrent.futures
130
+ from turboapi import TurboAPI, TurboRequest, TurboResponse
131
+
132
+ def create_app_and_routes(thread_id):
133
+ app = TurboAPI(title=f'App {thread_id}')
134
+ for i in range(100):
135
+ @app.get(f'/t{thread_id}/route{i}')
136
+ def handler(tid=thread_id, idx=i):
137
+ return {'thread': tid, 'route': idx}
138
+ return thread_id
139
+
140
+ with concurrent.futures.ThreadPoolExecutor(max_workers=8) as pool:
141
+ futures = [pool.submit(create_app_and_routes, t) for t in range(8)]
142
+ results = [f.result() for f in futures]
143
+ assert len(results) == 8
144
+ print('Free-threaded smoke test: 8 threads x 100 routes = OK')
145
+ "
146
+
147
+ build-check:
148
+ name: "build (${{ matrix.target }})"
149
+ runs-on: ${{ matrix.os }}
150
+ strategy:
151
+ matrix:
152
+ include:
153
+ - os: ubuntu-latest
154
+ target: x86_64
155
+ - os: macos-latest
156
+ target: aarch64-apple-darwin
157
+ - os: windows-latest
158
+ target: x64
159
+ fail-fast: false
160
+ steps:
161
+ - uses: actions/checkout@v4
162
+
163
+ - uses: actions/setup-python@v5
164
+ with:
165
+ python-version: '3.13'
166
+
167
+ - name: Build wheels
168
+ uses: PyO3/maturin-action@v1
169
+ with:
170
+ target: ${{ matrix.target }}
171
+ args: --release --out dist --find-interpreter
172
+ sccache: 'true'
173
+ manylinux: auto
174
+
175
+ - name: Upload wheels
176
+ uses: actions/upload-artifact@v4
177
+ with:
178
+ name: wheels-${{ matrix.os }}-${{ matrix.target }}
179
+ path: dist
@@ -51,32 +51,32 @@ jobs:
51
51
  run: |
52
52
  # Install bump2version if not available
53
53
  pip install bump2version
54
-
55
- # Extract current version from python/pyproject.toml
56
- CURRENT_VERSION=$(grep -Po '(?<=version = ")[^"]*' python/pyproject.toml)
54
+
55
+ # Extract current version from pyproject.toml (root)
56
+ CURRENT_VERSION=$(grep -Po '(?<=version = ")[^"]*' pyproject.toml | head -1)
57
57
  echo "Current version: $CURRENT_VERSION"
58
-
58
+
59
59
  # Create .bumpversion.cfg for coordinated version bumping
60
60
  cat > .bumpversion.cfg << EOF
61
61
  [bumpversion]
62
62
  current_version = $CURRENT_VERSION
63
63
  commit = False
64
64
  tag = False
65
-
66
- [bumpversion:file:python/pyproject.toml]
65
+
66
+ [bumpversion:file:pyproject.toml]
67
67
  search = version = "{current_version}"
68
68
  replace = version = "{new_version}"
69
-
69
+
70
70
  [bumpversion:file:Cargo.toml]
71
71
  search = version = "{current_version}"
72
72
  replace = version = "{new_version}"
73
73
  EOF
74
-
75
- # Bump version in both python/pyproject.toml and Cargo.toml
74
+
75
+ # Bump version in both pyproject.toml and Cargo.toml
76
76
  bump2version ${{ github.event.inputs.version_bump }} --allow-dirty
77
-
77
+
78
78
  # Get new version
79
- NEW_VERSION=$(grep -Po '(?<=version = ")[^"]*' python/pyproject.toml)
79
+ NEW_VERSION=$(grep -Po '(?<=version = ")[^"]*' pyproject.toml | head -1)
80
80
  echo "New version: $NEW_VERSION"
81
81
  echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
82
82
 
@@ -108,7 +108,7 @@ jobs:
108
108
  - name: Commit version bump and create tag
109
109
  id: create_tag
110
110
  run: |
111
- git add python/pyproject.toml Cargo.toml CHANGELOG.md .bumpversion.cfg
111
+ git add pyproject.toml Cargo.toml CHANGELOG.md .bumpversion.cfg
112
112
  git commit -m "Bump version to v${{ steps.bump_version.outputs.new_version }}"
113
113
  git tag -a "v${{ steps.bump_version.outputs.new_version }}" -m "Release v${{ steps.bump_version.outputs.new_version }}"
114
114
  git push && git push --tags
@@ -17,6 +17,18 @@ version = "2.0.1"
17
17
  source = "registry+https://github.com/rust-lang/crates.io-index"
18
18
  checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
19
19
 
20
+ [[package]]
21
+ name = "ahash"
22
+ version = "0.8.12"
23
+ source = "registry+https://github.com/rust-lang/crates.io-index"
24
+ checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
25
+ dependencies = [
26
+ "cfg-if",
27
+ "once_cell",
28
+ "version_check",
29
+ "zerocopy",
30
+ ]
31
+
20
32
  [[package]]
21
33
  name = "aho-corasick"
22
34
  version = "1.1.3"
@@ -26,6 +38,12 @@ dependencies = [
26
38
  "memchr",
27
39
  ]
28
40
 
41
+ [[package]]
42
+ name = "allocator-api2"
43
+ version = "0.2.21"
44
+ source = "registry+https://github.com/rust-lang/crates.io-index"
45
+ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
46
+
29
47
  [[package]]
30
48
  name = "anes"
31
49
  version = "0.1.6"
@@ -357,6 +375,15 @@ version = "1.0.2"
357
375
  source = "registry+https://github.com/rust-lang/crates.io-index"
358
376
  checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
359
377
 
378
+ [[package]]
379
+ name = "float-cmp"
380
+ version = "0.10.0"
381
+ source = "registry+https://github.com/rust-lang/crates.io-index"
382
+ checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8"
383
+ dependencies = [
384
+ "num-traits",
385
+ ]
386
+
360
387
  [[package]]
361
388
  name = "fnv"
362
389
  version = "1.0.7"
@@ -469,8 +496,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
469
496
  checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
470
497
  dependencies = [
471
498
  "cfg-if",
499
+ "js-sys",
472
500
  "libc",
473
501
  "wasi",
502
+ "wasm-bindgen",
474
503
  ]
475
504
 
476
505
  [[package]]
@@ -508,6 +537,26 @@ dependencies = [
508
537
  "crunchy",
509
538
  ]
510
539
 
540
+ [[package]]
541
+ name = "halfbrown"
542
+ version = "0.2.5"
543
+ source = "registry+https://github.com/rust-lang/crates.io-index"
544
+ checksum = "8588661a8607108a5ca69cab034063441a0413a0b041c13618a7dd348021ef6f"
545
+ dependencies = [
546
+ "hashbrown 0.14.5",
547
+ "serde",
548
+ ]
549
+
550
+ [[package]]
551
+ name = "hashbrown"
552
+ version = "0.14.5"
553
+ source = "registry+https://github.com/rust-lang/crates.io-index"
554
+ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
555
+ dependencies = [
556
+ "ahash",
557
+ "allocator-api2",
558
+ ]
559
+
511
560
  [[package]]
512
561
  name = "hashbrown"
513
562
  version = "0.16.0"
@@ -628,7 +677,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
628
677
  checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5"
629
678
  dependencies = [
630
679
  "equivalent",
631
- "hashbrown",
680
+ "hashbrown 0.16.0",
632
681
  ]
633
682
 
634
683
  [[package]]
@@ -1037,6 +1086,26 @@ dependencies = [
1037
1086
  "bitflags",
1038
1087
  ]
1039
1088
 
1089
+ [[package]]
1090
+ name = "ref-cast"
1091
+ version = "1.0.25"
1092
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1093
+ checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d"
1094
+ dependencies = [
1095
+ "ref-cast-impl",
1096
+ ]
1097
+
1098
+ [[package]]
1099
+ name = "ref-cast-impl"
1100
+ version = "1.0.25"
1101
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1102
+ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"
1103
+ dependencies = [
1104
+ "proc-macro2",
1105
+ "quote",
1106
+ "syn",
1107
+ ]
1108
+
1040
1109
  [[package]]
1041
1110
  name = "regex"
1042
1111
  version = "1.11.3"
@@ -1171,6 +1240,27 @@ dependencies = [
1171
1240
  "libc",
1172
1241
  ]
1173
1242
 
1243
+ [[package]]
1244
+ name = "simd-json"
1245
+ version = "0.14.3"
1246
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1247
+ checksum = "aa2bcf6c6e164e81bc7a5d49fc6988b3d515d9e8c07457d7b74ffb9324b9cd40"
1248
+ dependencies = [
1249
+ "getrandom",
1250
+ "halfbrown",
1251
+ "ref-cast",
1252
+ "serde",
1253
+ "serde_json",
1254
+ "simdutf8",
1255
+ "value-trait",
1256
+ ]
1257
+
1258
+ [[package]]
1259
+ name = "simdutf8"
1260
+ version = "0.1.5"
1261
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1262
+ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
1263
+
1174
1264
  [[package]]
1175
1265
  name = "slab"
1176
1266
  version = "0.4.11"
@@ -1439,7 +1529,7 @@ dependencies = [
1439
1529
 
1440
1530
  [[package]]
1441
1531
  name = "turbonet"
1442
- version = "0.4.15"
1532
+ version = "0.4.16"
1443
1533
  dependencies = [
1444
1534
  "anyhow",
1445
1535
  "bytes",
@@ -1450,13 +1540,17 @@ dependencies = [
1450
1540
  "http-body-util",
1451
1541
  "hyper",
1452
1542
  "hyper-util",
1543
+ "itoa",
1544
+ "memchr",
1453
1545
  "num_cpus",
1454
1546
  "pin-project-lite",
1455
1547
  "pyo3",
1456
1548
  "pyo3-async-runtimes",
1457
1549
  "rayon",
1550
+ "ryu",
1458
1551
  "serde",
1459
1552
  "serde_json",
1553
+ "simd-json",
1460
1554
  "tokio",
1461
1555
  "tokio-test",
1462
1556
  "tokio-tungstenite",
@@ -1494,6 +1588,18 @@ version = "0.1.1"
1494
1588
  source = "registry+https://github.com/rust-lang/crates.io-index"
1495
1589
  checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
1496
1590
 
1591
+ [[package]]
1592
+ name = "value-trait"
1593
+ version = "0.10.1"
1594
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1595
+ checksum = "9170e001f458781e92711d2ad666110f153e4e50bfd5cbd02db6547625714187"
1596
+ dependencies = [
1597
+ "float-cmp",
1598
+ "halfbrown",
1599
+ "itoa",
1600
+ "ryu",
1601
+ ]
1602
+
1497
1603
  [[package]]
1498
1604
  name = "version_check"
1499
1605
  version = "0.9.5"
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "turbonet"
3
- version = "0.4.15"
3
+ version = "0.4.16"
4
4
  edition = "2021"
5
5
  authors = ["Rach Pradhan <rach@turboapi.dev>"]
6
6
  description = "High-performance Python web framework core - Rust-powered HTTP server with Python 3.14 free-threading support, FastAPI-compatible security and middleware"
@@ -40,6 +40,10 @@ futures = "0.3"
40
40
  rayon = "1.8"
41
41
  crossbeam = "0.8"
42
42
  num_cpus = "1.16"
43
+ memchr = "2.7"
44
+ simd-json = "0.14"
45
+ itoa = "1.0"
46
+ ryu = "1.0"
43
47
 
44
48
  [dev-dependencies]
45
49
  criterion = { version = "0.5", features = ["html_reports"] }