turboapi 0.4.13__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 (146) 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.13 → turboapi-0.4.16}/.github/workflows/release.yml +12 -12
  4. turboapi-0.4.16/ASYNC_FIX_v0_4_15.md +342 -0
  5. turboapi-0.4.16/BENCHMARK_FAQ.md +204 -0
  6. turboapi-0.4.16/BENCHMARK_METHODOLOGY_RESPONSE.md +340 -0
  7. turboapi-0.4.16/BENCHMARK_ONEPAGER.md +140 -0
  8. {turboapi-0.4.13 → turboapi-0.4.16}/Cargo.lock +108 -2
  9. {turboapi-0.4.13 → turboapi-0.4.16}/Cargo.toml +5 -1
  10. turboapi-0.4.16/PHASE_3_COMPLETE.md +489 -0
  11. turboapi-0.4.16/PKG-INFO +423 -0
  12. turboapi-0.4.16/QUICK_RESPONSE_MULTICORE.md +252 -0
  13. turboapi-0.4.16/README.md +388 -0
  14. turboapi-0.4.16/RELEASE_NOTES_v0.4.14.md +412 -0
  15. turboapi-0.4.16/RESPONSE_SUMMARY.md +274 -0
  16. turboapi-0.4.16/TODO_v0.4.15.md +195 -0
  17. turboapi-0.4.16/V0.4.14_SUMMARY.md +312 -0
  18. turboapi-0.4.16/V0.4.15_SUMMARY.md +418 -0
  19. turboapi-0.4.16/assets/architecture.png +0 -0
  20. turboapi-0.4.16/assets/benchmark_latency.png +0 -0
  21. turboapi-0.4.16/assets/benchmark_speedup.png +0 -0
  22. turboapi-0.4.16/assets/benchmark_throughput.png +0 -0
  23. {turboapi-0.4.13 → turboapi-0.4.16}/benches/performance_bench.rs +23 -23
  24. turboapi-0.4.16/benchmarks/README.md +35 -0
  25. turboapi-0.4.16/benchmarks/bench_json.py +209 -0
  26. turboapi-0.4.16/benchmarks/bench_memory.py +192 -0
  27. turboapi-0.4.16/benchmarks/bench_throughput.py +227 -0
  28. turboapi-0.4.16/benchmarks/bench_validation.py +241 -0
  29. turboapi-0.4.16/benchmarks/generate_charts.py +399 -0
  30. turboapi-0.4.16/benchmarks/run_all.sh +31 -0
  31. turboapi-0.4.16/benchmarks/run_benchmarks.py +383 -0
  32. turboapi-0.4.16/docs/ARCHITECTURE_DIAGRAM.md +382 -0
  33. {turboapi-0.4.13 → turboapi-0.4.16}/pyproject.toml +20 -34
  34. turboapi-0.4.16/python/turboapi/__init__.py +141 -0
  35. turboapi-0.4.16/python/turboapi/background.py +51 -0
  36. turboapi-0.4.16/python/turboapi/datastructures.py +262 -0
  37. turboapi-0.4.16/python/turboapi/encoders.py +323 -0
  38. turboapi-0.4.16/python/turboapi/exceptions.py +111 -0
  39. {turboapi-0.4.13 → turboapi-0.4.16/python}/turboapi/main_app.py +59 -4
  40. {turboapi-0.4.13 → turboapi-0.4.16}/python/turboapi/middleware.py +4 -6
  41. {turboapi-0.4.13 → turboapi-0.4.16/python}/turboapi/models.py +15 -33
  42. turboapi-0.4.16/python/turboapi/openapi.py +236 -0
  43. turboapi-0.4.16/python/turboapi/request_handler.py +602 -0
  44. turboapi-0.4.16/python/turboapi/responses.py +209 -0
  45. {turboapi-0.4.13 → turboapi-0.4.16/python}/turboapi/routing.py +2 -1
  46. {turboapi-0.4.13 → turboapi-0.4.16}/python/turboapi/rust_integration.py +111 -20
  47. {turboapi-0.4.13 → turboapi-0.4.16}/python/turboapi/security.py +32 -3
  48. turboapi-0.4.16/python/turboapi/staticfiles.py +91 -0
  49. turboapi-0.4.16/python/turboapi/status.py +104 -0
  50. turboapi-0.4.16/python/turboapi/templating.py +73 -0
  51. turboapi-0.4.16/python/turboapi/testclient.py +321 -0
  52. turboapi-0.4.16/python/turboapi/websockets.py +130 -0
  53. {turboapi-0.4.13 → turboapi-0.4.16}/setup_python313t.sh +0 -0
  54. {turboapi-0.4.13 → turboapi-0.4.16}/src/http2.rs +53 -33
  55. {turboapi-0.4.13 → turboapi-0.4.16}/src/lib.rs +28 -20
  56. {turboapi-0.4.13 → turboapi-0.4.16}/src/micro_bench.rs +43 -32
  57. {turboapi-0.4.13 → turboapi-0.4.16}/src/middleware.rs +157 -104
  58. {turboapi-0.4.13 → turboapi-0.4.16}/src/python_worker.rs +58 -58
  59. {turboapi-0.4.13 → turboapi-0.4.16}/src/response.rs +4 -1
  60. {turboapi-0.4.13 → turboapi-0.4.16}/src/router.rs +49 -17
  61. turboapi-0.4.16/src/server.rs +2287 -0
  62. turboapi-0.4.16/src/simd_json.rs +392 -0
  63. turboapi-0.4.16/src/simd_parse.rs +507 -0
  64. {turboapi-0.4.13 → turboapi-0.4.16}/src/threadpool.rs +71 -30
  65. {turboapi-0.4.13 → turboapi-0.4.16}/src/validation.rs +28 -26
  66. {turboapi-0.4.13 → turboapi-0.4.16}/src/websocket.rs +43 -31
  67. {turboapi-0.4.13 → turboapi-0.4.16}/src/zerocopy.rs +65 -53
  68. {turboapi-0.4.13 → turboapi-0.4.16}/test_package_integrity.py +0 -0
  69. {turboapi-0.4.13 → turboapi-0.4.16}/tests/comparison_before_after.py +7 -7
  70. {turboapi-0.4.13 → turboapi-0.4.16}/tests/quick_body_test.py +3 -3
  71. turboapi-0.4.16/tests/test_async_handlers.py +466 -0
  72. turboapi-0.4.16/tests/test_async_simple.py +89 -0
  73. turboapi-0.4.16/tests/test_comprehensive_parity.py +569 -0
  74. turboapi-0.4.16/tests/test_comprehensive_v0_4_15.py +106 -0
  75. {turboapi-0.4.13 → turboapi-0.4.16}/tests/test_fastapi_compatibility.py +10 -10
  76. turboapi-0.4.16/tests/test_fastapi_parity.py +1080 -0
  77. turboapi-0.4.16/tests/test_performance_regression.py +372 -0
  78. {turboapi-0.4.13 → turboapi-0.4.16}/tests/test_post_body_parsing.py +10 -10
  79. turboapi-0.4.16/tests/test_query_and_headers.py +308 -0
  80. turboapi-0.4.16/tests/test_request_parsing.py +406 -0
  81. turboapi-0.4.16/tests/test_satya_0_4_0_compatibility.py +331 -0
  82. turboapi-0.4.16/tests/test_wrk_regression.py +289 -0
  83. turboapi-0.4.13/.github/workflows/build-and-release.yml +0 -377
  84. turboapi-0.4.13/.github/workflows/build-wheels.yml +0 -212
  85. turboapi-0.4.13/.github/workflows/ci.yml +0 -151
  86. turboapi-0.4.13/PKG-INFO +0 -31
  87. turboapi-0.4.13/README.md +0 -882
  88. turboapi-0.4.13/benchmarks/comprehensive_wrk_benchmark.py +0 -284
  89. turboapi-0.4.13/benchmarks/turboapi_vs_fastapi_benchmark.py +0 -310
  90. turboapi-0.4.13/benchmarks/turboapi_vs_fastapi_simple.py +0 -249
  91. turboapi-0.4.13/benchmarks/wrk_output.txt +0 -0
  92. turboapi-0.4.13/python/pyproject.toml +0 -74
  93. turboapi-0.4.13/python/turboapi/__init__.py +0 -24
  94. turboapi-0.4.13/python/turboapi/main_app.py +0 -314
  95. turboapi-0.4.13/python/turboapi/models.py +0 -148
  96. turboapi-0.4.13/python/turboapi/request_handler.py +0 -277
  97. turboapi-0.4.13/python/turboapi/routing.py +0 -219
  98. turboapi-0.4.13/src/server.rs +0 -1505
  99. turboapi-0.4.13/tests/test_satya_0_4_0_compatibility.py +0 -247
  100. turboapi-0.4.13/turboapi/__init__.py +0 -24
  101. turboapi-0.4.13/turboapi/async_limiter.py +0 -86
  102. turboapi-0.4.13/turboapi/async_pool.py +0 -141
  103. turboapi-0.4.13/turboapi/decorators.py +0 -69
  104. turboapi-0.4.13/turboapi/middleware.py +0 -342
  105. turboapi-0.4.13/turboapi/request_handler.py +0 -277
  106. turboapi-0.4.13/turboapi/rust_integration.py +0 -258
  107. turboapi-0.4.13/turboapi/security.py +0 -542
  108. turboapi-0.4.13/turboapi/server_integration.py +0 -436
  109. turboapi-0.4.13/turboapi/version_check.py +0 -268
  110. {turboapi-0.4.13 → turboapi-0.4.16}/.github/scripts/check_performance_regression.py +0 -0
  111. {turboapi-0.4.13 → turboapi-0.4.16}/.github/scripts/compare_benchmarks.py +0 -0
  112. {turboapi-0.4.13 → turboapi-0.4.16}/.github/workflows/README.md +0 -0
  113. {turboapi-0.4.13 → turboapi-0.4.16}/.github/workflows/benchmark.yml +0 -0
  114. {turboapi-0.4.13 → turboapi-0.4.16}/.gitignore +0 -0
  115. {turboapi-0.4.13 → turboapi-0.4.16}/AGENTS.md +0 -0
  116. {turboapi-0.4.13 → turboapi-0.4.16}/CHANGELOG.md +0 -0
  117. {turboapi-0.4.13 → turboapi-0.4.16}/FASTAPI_COMPATIBILITY.md +0 -0
  118. {turboapi-0.4.13 → turboapi-0.4.16}/LICENSE +0 -0
  119. {turboapi-0.4.13 → turboapi-0.4.16}/Makefile +0 -0
  120. {turboapi-0.4.13 → turboapi-0.4.16}/POST_BODY_PARSING_FIX.md +0 -0
  121. {turboapi-0.4.13 → turboapi-0.4.16}/RELEASE_NOTES_v0.4.13.md +0 -0
  122. {turboapi-0.4.13 → turboapi-0.4.16}/TESTING.md +0 -0
  123. {turboapi-0.4.13 → turboapi-0.4.16}/V0.4.13_SUMMARY.md +0 -0
  124. {turboapi-0.4.13 → turboapi-0.4.16}/benchmark_comparison.png +0 -0
  125. {turboapi-0.4.13 → turboapi-0.4.16}/benchmark_graphs/turbo_vs_fastapi_performance_20250929_025531.png +0 -0
  126. {turboapi-0.4.13 → turboapi-0.4.16}/docs/AUTHENTICATION_GUIDE.md +0 -0
  127. {turboapi-0.4.13 → turboapi-0.4.16}/examples/authentication_demo.py +0 -0
  128. {turboapi-0.4.13 → turboapi-0.4.16}/examples/multi_route_app.py +0 -0
  129. {turboapi-0.4.13 → turboapi-0.4.16}/python/MANIFEST.in +0 -0
  130. {turboapi-0.4.13 → turboapi-0.4.16}/python/setup.py +0 -0
  131. {turboapi-0.4.13 → turboapi-0.4.16}/python/turboapi/async_limiter.py +0 -0
  132. {turboapi-0.4.13 → turboapi-0.4.16}/python/turboapi/async_pool.py +0 -0
  133. {turboapi-0.4.13 → turboapi-0.4.16}/python/turboapi/decorators.py +0 -0
  134. {turboapi-0.4.13 → turboapi-0.4.16}/python/turboapi/server_integration.py +0 -0
  135. {turboapi-0.4.13 → turboapi-0.4.16}/python/turboapi/version_check.py +0 -0
  136. {turboapi-0.4.13 → turboapi-0.4.16}/src/request.rs +0 -0
  137. {turboapi-0.4.13 → turboapi-0.4.16}/test_simple_post.py +0 -0
  138. {turboapi-0.4.13 → turboapi-0.4.16}/tests/README.md +0 -0
  139. {turboapi-0.4.13 → turboapi-0.4.16}/tests/benchmark_comparison.py +0 -0
  140. {turboapi-0.4.13 → turboapi-0.4.16}/tests/fastapi_equivalent.py +0 -0
  141. {turboapi-0.4.13 → turboapi-0.4.16}/tests/quick_test.py +0 -0
  142. {turboapi-0.4.13 → turboapi-0.4.16}/tests/test.py +0 -0
  143. {turboapi-0.4.13 → turboapi-0.4.16}/tests/test_security_features.py +0 -0
  144. {turboapi-0.4.13 → turboapi-0.4.16}/tests/wrk_benchmark.py +0 -0
  145. {turboapi-0.4.13 → turboapi-0.4.16}/tests/wrk_comparison.py +0 -0
  146. {turboapi-0.4.13 → 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