pytest-boorst 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. pytest_boorst-0.1.0/.github/workflows/ci.yml +370 -0
  2. pytest_boorst-0.1.0/.github/workflows/publish.yml +81 -0
  3. pytest_boorst-0.1.0/.gitignore +13 -0
  4. pytest_boorst-0.1.0/.python-version +1 -0
  5. pytest_boorst-0.1.0/CONTRIBUTING.md +64 -0
  6. pytest_boorst-0.1.0/Cargo.lock +132 -0
  7. pytest_boorst-0.1.0/Cargo.toml +21 -0
  8. pytest_boorst-0.1.0/LICENSE +70 -0
  9. pytest_boorst-0.1.0/PKG-INFO +374 -0
  10. pytest_boorst-0.1.0/README.md +357 -0
  11. pytest_boorst-0.1.0/RESULTS.md +168 -0
  12. pytest_boorst-0.1.0/benchmarks/README.md +209 -0
  13. pytest_boorst-0.1.0/benchmarks/assertions.py +151 -0
  14. pytest_boorst-0.1.0/benchmarks/corpus.py +211 -0
  15. pytest_boorst-0.1.0/benchmarks/discovery.py +151 -0
  16. pytest_boorst-0.1.0/benchmarks/memory.py +116 -0
  17. pytest_boorst-0.1.0/benchmarks/results/acceleration-ideas-local.json +459 -0
  18. pytest_boorst-0.1.0/benchmarks/results/alpha2-discovery-ci.json +72 -0
  19. pytest_boorst-0.1.0/benchmarks/results/alpha2-ids-ci.json +409 -0
  20. pytest_boorst-0.1.0/benchmarks/results/alpha2-python314-discovery-ci.json +72 -0
  21. pytest_boorst-0.1.0/benchmarks/results/alpha2-python314-ids-ci.json +409 -0
  22. pytest_boorst-0.1.0/benchmarks/results/alpha4-multiple-directories-local.json +73 -0
  23. pytest_boorst-0.1.0/benchmarks/results/assertion-batches-local.json +120 -0
  24. pytest_boorst-0.1.0/benchmarks/results/batched-reporting-component.json +155 -0
  25. pytest_boorst-0.1.0/benchmarks/results/initial-alpha.json +404 -0
  26. pytest_boorst-0.1.0/benchmarks/results/static-discovery-local.json +181 -0
  27. pytest_boorst-0.1.0/benchmarks/run.py +263 -0
  28. pytest_boorst-0.1.0/benchmarks/static_discovery.py +153 -0
  29. pytest_boorst-0.1.0/pyproject.toml +52 -0
  30. pytest_boorst-0.1.0/python/pytest_boorst/__init__.py +4 -0
  31. pytest_boorst-0.1.0/python/pytest_boorst/__main__.py +15 -0
  32. pytest_boorst-0.1.0/python/pytest_boorst/_assertion_fingerprints.py +92 -0
  33. pytest_boorst-0.1.0/python/pytest_boorst/_assertion_schema.py +424 -0
  34. pytest_boorst-0.1.0/python/pytest_boorst/_assertions.py +663 -0
  35. pytest_boorst-0.1.0/python/pytest_boorst/_discovery.py +208 -0
  36. pytest_boorst-0.1.0/python/pytest_boorst/_ids.py +41 -0
  37. pytest_boorst-0.1.0/python/pytest_boorst/_profile.py +241 -0
  38. pytest_boorst-0.1.0/python/pytest_boorst/_schedule.py +292 -0
  39. pytest_boorst-0.1.0/python/pytest_boorst/_static.py +95 -0
  40. pytest_boorst-0.1.0/python/pytest_boorst/plugin.py +481 -0
  41. pytest_boorst-0.1.0/scripts/build_pure.py +50 -0
  42. pytest_boorst-0.1.0/scripts/prepare_release.py +123 -0
  43. pytest_boorst-0.1.0/scripts/smoke.py +82 -0
  44. pytest_boorst-0.1.0/scripts/try.py +54 -0
  45. pytest_boorst-0.1.0/scripts/verify_trial.py +141 -0
  46. pytest_boorst-0.1.0/src/lib.rs +148 -0
  47. pytest_boorst-0.1.0/src/locations.rs +536 -0
  48. pytest_boorst-0.1.0/tests/conftest.py +1 -0
  49. pytest_boorst-0.1.0/tests/test_assertions.py +710 -0
  50. pytest_boorst-0.1.0/tests/test_corpus.py +104 -0
  51. pytest_boorst-0.1.0/tests/test_discovery.py +369 -0
  52. pytest_boorst-0.1.0/tests/test_ids.py +50 -0
  53. pytest_boorst-0.1.0/tests/test_plugin.py +740 -0
  54. pytest_boorst-0.1.0/tests/test_profile.py +371 -0
  55. pytest_boorst-0.1.0/tests/test_release.py +119 -0
  56. pytest_boorst-0.1.0/tests/test_schedule.py +473 -0
  57. pytest_boorst-0.1.0/tests/test_static.py +288 -0
  58. pytest_boorst-0.1.0/tests/test_trial.py +109 -0
  59. pytest_boorst-0.1.0/uv.lock +431 -0
@@ -0,0 +1,370 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+ workflow_dispatch:
9
+ workflow_call:
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ concurrency:
15
+ group: ci-${{ github.ref }}
16
+ cancel-in-progress: true
17
+
18
+ jobs:
19
+ quality:
20
+ runs-on: ubuntu-24.04
21
+ steps:
22
+ - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
23
+ - uses: astral-sh/setup-uv@94527f2e458b27549849d47d273a16bec83a01e9 # v7
24
+ with:
25
+ version: "0.12.12"
26
+ python-version: "3.12"
27
+ enable-cache: true
28
+ - uses: dtolnay/rust-toolchain@89b12181fb390509a0842a86cc55eeb8eb928c1d # stable
29
+ with:
30
+ components: rustfmt, clippy
31
+ - uses: Swatinem/rust-cache@49a0bdc70d2e1b713ca9e2869b211fcce03d3c1c # v2
32
+ - run: uv sync --locked --no-install-project
33
+ - run: uv run --no-sync ruff check .
34
+ - run: uv run --no-sync ruff format --check .
35
+ - run: cargo fmt --check
36
+ - run: cargo clippy --locked --all-targets -- -D warnings
37
+ - run: cargo test --locked --lib
38
+
39
+ wheels:
40
+ name: Wheel / ${{ matrix.os }} / Python ${{ matrix.python }}
41
+ runs-on: ${{ matrix.os }}
42
+ defaults:
43
+ run:
44
+ shell: bash
45
+ strategy:
46
+ fail-fast: false
47
+ matrix:
48
+ os: [ubuntu-24.04]
49
+ python: ["3.10", "3.11", "3.12", "3.13", "3.14"]
50
+ include:
51
+ - os: macos-14
52
+ python: "3.12"
53
+ - os: windows-latest
54
+ python: "3.12"
55
+ - os: macos-14
56
+ python: "3.14"
57
+ - os: windows-latest
58
+ python: "3.14"
59
+ steps:
60
+ - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
61
+ - uses: astral-sh/setup-uv@94527f2e458b27549849d47d273a16bec83a01e9 # v7
62
+ with:
63
+ version: "0.12.12"
64
+ python-version: ${{ matrix.python }}
65
+ enable-cache: true
66
+ - uses: dtolnay/rust-toolchain@89b12181fb390509a0842a86cc55eeb8eb928c1d # stable
67
+ - uses: Swatinem/rust-cache@49a0bdc70d2e1b713ca9e2869b211fcce03d3c1c # v2
68
+ - run: uv sync --locked --no-install-project
69
+ - run: uv run --no-sync maturin build --release --locked --out dist
70
+ - name: Install the wheel into the clean test environment
71
+ run: |
72
+ uv pip install --only-binary :all: dist/*.whl
73
+ - run: uv run --no-sync pytest -q
74
+ - run: uv run --no-sync python scripts/smoke.py --pytest-version 9.1.1
75
+ - name: Verify portable trial
76
+ if: matrix.os != 'windows-latest'
77
+ run: uv run --no-sync python scripts/verify_trial.py --wheels dist --expect-native
78
+ - name: Verify portable trial in PowerShell
79
+ if: matrix.os == 'windows-latest'
80
+ shell: pwsh
81
+ run: uv run --no-sync python scripts/verify_trial.py --wheels dist --expect-native
82
+ - name: Build the universal fallback wheel
83
+ if: matrix.python == '3.12' && (matrix.os == 'ubuntu-24.04' || matrix.os == 'windows-latest')
84
+ run: uv run --no-sync python scripts/build_pure.py
85
+ - name: Verify the universal fallback trial
86
+ if: matrix.os == 'ubuntu-24.04' && matrix.python == '3.12'
87
+ run: uv run --no-sync python scripts/verify_trial.py --wheels dist/pure
88
+ - name: Verify the universal fallback trial in PowerShell
89
+ if: matrix.os == 'windows-latest' && matrix.python == '3.12'
90
+ shell: pwsh
91
+ run: uv run --no-sync python scripts/verify_trial.py --wheels dist/pure
92
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
93
+ if: matrix.os == 'ubuntu-24.04' && matrix.python == '3.12'
94
+ with:
95
+ name: wheel-universal
96
+ path: dist/pure/*.whl
97
+ if-no-files-found: error
98
+ - name: Preserve legacy pytest versions during normal wheel installation
99
+ if: matrix.os == 'ubuntu-24.04' && matrix.python == '3.10'
100
+ run: |
101
+ legacy_env=".legacy-pytest-6.2.5"
102
+ uv venv --python 3.10 "$legacy_env"
103
+ uv pip install --python "$legacy_env/bin/python" pytest==6.2.5
104
+ uv pip install --python "$legacy_env/bin/python" --only-binary :all: dist/*.whl
105
+ "$legacy_env/bin/python" scripts/smoke.py --expect fallback --pytest-version 6.2.5
106
+ - name: Verify supported pytest versions with the installed wheel
107
+ if: matrix.os == 'ubuntu-24.04'
108
+ run: |
109
+ pytest_versions="7.4.4 8.4.2"
110
+ if [[ "${{ matrix.python }}" == "3.12" ]]; then
111
+ pytest_versions="$pytest_versions 9.0.2 9.0.3"
112
+ fi
113
+ for pytest_version in $pytest_versions; do
114
+ compat_env=".compat-pytest-$pytest_version"
115
+ uv venv --python "${{ matrix.python }}" "$compat_env"
116
+ if [[ "$pytest_version" == 7.* ]]; then
117
+ asyncio_version="0.23.8"
118
+ else
119
+ asyncio_version="1.4.0"
120
+ fi
121
+ uv pip install --python "$compat_env/bin/python" \
122
+ "pytest==$pytest_version" "pytest-asyncio==$asyncio_version" \
123
+ "pytest-cov==7.0.0" "pytest-xdist==3.8.0"
124
+ uv pip install --python "$compat_env/bin/python" --only-binary :all: dist/*.whl
125
+ if [[ "$pytest_version" == 9.* ]]; then
126
+ "$compat_env/bin/python" -m pytest -q
127
+ else
128
+ "$compat_env/bin/python" -m pytest -q tests/test_ids.py tests/test_plugin.py tests/test_profile.py tests/test_schedule.py tests/test_static.py tests/test_assertions.py
129
+ fi
130
+ "$compat_env/bin/python" scripts/smoke.py --pytest-version "$pytest_version"
131
+ done
132
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
133
+ with:
134
+ name: wheel-${{ matrix.os }}-py${{ matrix.python }}
135
+ path: dist/*.whl
136
+ if-no-files-found: error
137
+
138
+ desktop-wheels:
139
+ name: Wheel / ${{ matrix.name }} / Python 3.12
140
+ runs-on: ${{ matrix.os }}
141
+ defaults:
142
+ run:
143
+ shell: bash
144
+ strategy:
145
+ fail-fast: false
146
+ matrix:
147
+ include:
148
+ - name: macos-x86_64
149
+ os: macos-15-intel
150
+ architecture: x64
151
+ target: x86_64-apple-darwin
152
+ bits: 64
153
+ - name: windows-x86
154
+ os: windows-2022
155
+ architecture: x86
156
+ target: i686-pc-windows-msvc
157
+ bits: 32
158
+ - name: windows-arm64
159
+ os: windows-11-arm
160
+ architecture: arm64
161
+ target: aarch64-pc-windows-msvc
162
+ bits: 64
163
+ steps:
164
+ - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
165
+ - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
166
+ with:
167
+ python-version: "3.12"
168
+ architecture: ${{ matrix.architecture }}
169
+ - uses: astral-sh/setup-uv@94527f2e458b27549849d47d273a16bec83a01e9 # v7
170
+ with:
171
+ version: "0.12.12"
172
+ enable-cache: true
173
+ - uses: dtolnay/rust-toolchain@89b12181fb390509a0842a86cc55eeb8eb928c1d # stable
174
+ with:
175
+ targets: ${{ matrix.target }}
176
+ - uses: Swatinem/rust-cache@49a0bdc70d2e1b713ca9e2869b211fcce03d3c1c # v2
177
+ - name: Select the matching Python interpreter
178
+ env:
179
+ EXPECTED_BITS: ${{ matrix.bits }}
180
+ run: |
181
+ python -c 'import os, struct; assert struct.calcsize("P") * 8 == int(os.environ["EXPECTED_BITS"])'
182
+ uv sync --locked --no-install-project --python "$(python -c 'import sys; print(sys.executable)')"
183
+ - name: Build and install the native wheel
184
+ env:
185
+ RUST_TARGET: ${{ matrix.target }}
186
+ run: |
187
+ uv run --no-sync maturin build --release --locked --target "$RUST_TARGET" --interpreter "$(python -c 'import sys; print(sys.executable)')" --out dist
188
+ uv pip install --only-binary :all: dist/*.whl
189
+ - run: uv run --no-sync pytest -q
190
+ - run: uv run --no-sync python scripts/smoke.py --pytest-version 9.1.1
191
+ - name: Verify portable trial
192
+ if: runner.os != 'Windows'
193
+ run: uv run --no-sync python scripts/verify_trial.py --wheels dist --expect-native
194
+ - name: Verify portable trial in PowerShell
195
+ if: runner.os == 'Windows'
196
+ shell: pwsh
197
+ run: uv run --no-sync python scripts/verify_trial.py --wheels dist --expect-native
198
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
199
+ with:
200
+ name: wheel-${{ matrix.name }}
201
+ path: dist/*.whl
202
+ if-no-files-found: error
203
+
204
+ linux-wheels:
205
+ name: Wheel / ${{ matrix.name }} / Python 3.12
206
+ runs-on: ${{ matrix.os }}
207
+ strategy:
208
+ fail-fast: false
209
+ matrix:
210
+ include:
211
+ - name: manylinux-x86_64
212
+ os: ubuntu-24.04
213
+ target: x86_64-unknown-linux-gnu
214
+ compatibility: "2014"
215
+ bits: 64
216
+ image: quay.io/pypa/manylinux2014_x86_64@sha256:ffd6d1f11237599748657996b750db6b3a5b724fea5a81cd9ea65add4f45b6c9
217
+ - name: manylinux-aarch64
218
+ os: ubuntu-24.04-arm
219
+ target: aarch64-unknown-linux-gnu
220
+ compatibility: "2014"
221
+ bits: 64
222
+ image: quay.io/pypa/manylinux2014_aarch64@sha256:9026a55e05e76ad74d9a4e6be814a5abda26cde08b1baa659ea4f7ee16b246e3
223
+ - name: manylinux-i686
224
+ os: ubuntu-24.04
225
+ target: i686-unknown-linux-gnu
226
+ compatibility: "2014"
227
+ bits: 32
228
+ image: quay.io/pypa/manylinux2014_i686@sha256:b82fab2ed4674093372106a6d0c511039bbce3c69a6fc1a7d703d770bb348c2b
229
+ - name: musllinux-x86_64
230
+ os: ubuntu-24.04
231
+ target: x86_64-unknown-linux-musl
232
+ compatibility: musllinux_1_2
233
+ bits: 64
234
+ image: quay.io/pypa/musllinux_1_2_x86_64@sha256:ff786af69d772d7ac3e318c00a2b682428a352cc822d6175f6a0d4b431c0d44d
235
+ - name: musllinux-aarch64
236
+ os: ubuntu-24.04-arm
237
+ target: aarch64-unknown-linux-musl
238
+ compatibility: musllinux_1_2
239
+ bits: 64
240
+ image: quay.io/pypa/musllinux_1_2_aarch64@sha256:09c35642d008faa6d43a45809ff068e22f37bba801f7d75faf19431aefed579d
241
+ - name: musllinux-i686
242
+ os: ubuntu-24.04
243
+ target: i686-unknown-linux-musl
244
+ compatibility: musllinux_1_2
245
+ bits: 32
246
+ image: quay.io/pypa/musllinux_1_2_i686@sha256:1dd91376182cb65bd594fec2043ed7045a0482dee5b4c7685dcc743dc6259a9d
247
+ builder: ghcr.io/rust-cross/rust-musl-cross@sha256:e515546ceeb7fef8a70e7a59198981f5851cbcf16dd8d1adeb28736ea4751e05
248
+ steps:
249
+ - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
250
+ - uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0
251
+ with:
252
+ maturin-version: v1.15.0
253
+ target: ${{ matrix.target }}
254
+ manylinux: ${{ matrix.compatibility }}
255
+ container: ${{ matrix.builder || matrix.image }}
256
+ args: --release --locked --out dist --interpreter python3.12
257
+ - name: Test the wheel in the matching Linux runtime
258
+ env:
259
+ RUNTIME_IMAGE: ${{ matrix.image }}
260
+ EXPECTED_BITS: ${{ matrix.bits }}
261
+ run: |
262
+ docker run --rm --volume "$GITHUB_WORKSPACE:/io" --workdir /io --env EXPECTED_BITS "$RUNTIME_IMAGE" bash -eu -c '
263
+ export PATH=/opt/python/cp312-cp312/bin:$PATH
264
+ python -c "import os, struct; assert struct.calcsize(\"P\") * 8 == int(os.environ[\"EXPECTED_BITS\"])"
265
+ python -m pip install uv==0.12.12
266
+ uv sync --locked --no-install-project --python /opt/python/cp312-cp312/bin/python
267
+ uv pip install --only-binary :all: dist/*.whl
268
+ uv run --no-sync pytest -q
269
+ uv run --no-sync python scripts/smoke.py --pytest-version 9.1.1
270
+ uv run --no-sync python scripts/verify_trial.py --wheels dist --expect-native
271
+ '
272
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
273
+ with:
274
+ name: wheel-${{ matrix.name }}
275
+ path: dist/*.whl
276
+ if-no-files-found: error
277
+
278
+ sdist:
279
+ runs-on: ubuntu-24.04
280
+ steps:
281
+ - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
282
+ - uses: astral-sh/setup-uv@94527f2e458b27549849d47d273a16bec83a01e9 # v7
283
+ with:
284
+ version: "0.12.12"
285
+ python-version: "3.12"
286
+ enable-cache: true
287
+ - uses: dtolnay/rust-toolchain@89b12181fb390509a0842a86cc55eeb8eb928c1d # stable
288
+ - run: uv sync --locked --no-install-project
289
+ - run: uv run --no-sync maturin sdist --out dist
290
+ - name: Build a wheel from the source distribution
291
+ run: uv build dist/*.tar.gz --wheel --out-dir rebuilt
292
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
293
+ with:
294
+ name: source-distribution
295
+ path: dist/*.tar.gz
296
+ if-no-files-found: error
297
+
298
+ distributions:
299
+ needs: [wheels, desktop-wheels, linux-wheels, sdist]
300
+ runs-on: ubuntu-24.04
301
+ steps:
302
+ - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
303
+ - uses: astral-sh/setup-uv@94527f2e458b27549849d47d273a16bec83a01e9 # v7
304
+ with:
305
+ version: "0.12.12"
306
+ python-version: "3.12"
307
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8
308
+ with:
309
+ path: artifacts
310
+ - name: Assemble the canonical tested distributions
311
+ run: |
312
+ release_tag=$(uv run --no-project python -c 'import tomllib; print("v" + tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])')
313
+ uv run --no-project python scripts/prepare_release.py --artifacts artifacts --output dist --tag "$release_tag" --source-commit "$GITHUB_SHA"
314
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
315
+ with:
316
+ name: pypi-dist
317
+ path: dist/*
318
+ if-no-files-found: error
319
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
320
+ with:
321
+ name: release-evidence
322
+ path: release-evidence/*
323
+ if-no-files-found: error
324
+
325
+ benchmark:
326
+ needs: quality
327
+ runs-on: ubuntu-24.04
328
+ steps:
329
+ - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
330
+ - uses: astral-sh/setup-uv@94527f2e458b27549849d47d273a16bec83a01e9 # v7
331
+ with:
332
+ version: "0.12.23"
333
+ python-version: "3.14.8"
334
+ enable-cache: true
335
+ - uses: dtolnay/rust-toolchain@89b12181fb390509a0842a86cc55eeb8eb928c1d # stable
336
+ - uses: Swatinem/rust-cache@49a0bdc70d2e1b713ca9e2869b211fcce03d3c1c # v2
337
+ - run: uv sync --locked --no-install-project
338
+ - run: uv run --no-sync maturin develop --release --locked
339
+ - run: uv run --no-sync python benchmarks/run.py --size 10000 --repeats 3
340
+ - run: uv run --no-sync python benchmarks/memory.py --repeats 3
341
+ - run: uv run --no-sync python benchmarks/discovery.py --repeats 3
342
+ - run: uv run --no-sync python benchmarks/discovery.py --directories 4 --repeats 3 --output benchmark-results-multiple-directories.json
343
+ - run: uv run --no-sync python benchmarks/assertions.py --repeats 3
344
+ - name: Verify target and native helper timings
345
+ run: |
346
+ uv run --no-sync python - <<'PY'
347
+ import json
348
+ result = json.load(open("benchmark-results.json"))
349
+ target = result["scenarios"]["duplicate"]
350
+ times = target["full_run"]["median_seconds"]
351
+ if times["rust"] > times["stock"] * 0.9:
352
+ raise SystemExit(f"Duplicate target not met: {times}")
353
+ component = target["component_median_seconds"]
354
+ if component["rust"] >= component["python"]:
355
+ raise SystemExit(f"Native helper target not met: {component}")
356
+ for control in ("unique", "small"):
357
+ if result["scenarios"][control]["state"]["rust"]["native_calls"] != 0:
358
+ raise SystemExit(f"Native helper unexpectedly used by {control}")
359
+ for filename in ("benchmark-results-discovery.json", "benchmark-results-multiple-directories.json"):
360
+ discovery = json.load(open(filename))
361
+ times = discovery["median_seconds"]
362
+ if times["enabled"] > times["stock"] * 0.95:
363
+ raise SystemExit(f"Directory discovery target not met for {filename}: {times}")
364
+ PY
365
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
366
+ if: always()
367
+ with:
368
+ name: benchmark-evidence
369
+ path: benchmark-results*.json
370
+ if-no-files-found: warn
@@ -0,0 +1,81 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ concurrency:
11
+ group: publish-${{ github.event.release.tag_name }}
12
+ cancel-in-progress: false
13
+
14
+ jobs:
15
+ verify-source:
16
+ runs-on: ubuntu-24.04
17
+ steps:
18
+ - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
19
+ with:
20
+ fetch-depth: 0
21
+ - uses: astral-sh/setup-uv@94527f2e458b27549849d47d273a16bec83a01e9 # v7
22
+ with:
23
+ version: "0.12.12"
24
+ python-version: "3.12"
25
+ - name: Verify the release tag and source
26
+ env:
27
+ RELEASE_TAG: ${{ github.event.release.tag_name }}
28
+ run: |
29
+ git fetch origin main
30
+ git merge-base --is-ancestor "$GITHUB_SHA" origin/main
31
+ uv run --no-project python - <<'PY'
32
+ import os
33
+ import tomllib
34
+ from pathlib import Path
35
+ project = tomllib.loads(Path("pyproject.toml").read_text())
36
+ cargo = tomllib.loads(Path("Cargo.toml").read_text())
37
+ version = project["project"]["version"]
38
+ assert os.environ["RELEASE_TAG"] == f"v{version}"
39
+ assert cargo["package"]["version"].replace("-alpha.", "a") == version
40
+ PY
41
+
42
+ ci:
43
+ needs: verify-source
44
+ uses: ./.github/workflows/ci.yml
45
+
46
+ publish:
47
+ needs: ci
48
+ runs-on: ubuntu-24.04
49
+ environment:
50
+ name: pypi
51
+ url: https://pypi.org/p/pytest-boorst
52
+ permissions:
53
+ id-token: write
54
+ contents: read
55
+ steps:
56
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8
57
+ with:
58
+ name: pypi-dist
59
+ path: dist
60
+ - uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
61
+
62
+ release-assets:
63
+ needs: publish
64
+ runs-on: ubuntu-24.04
65
+ permissions:
66
+ contents: write
67
+ steps:
68
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8
69
+ with:
70
+ name: pypi-dist
71
+ path: assets
72
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8
73
+ with:
74
+ name: release-evidence
75
+ path: assets
76
+ - name: Attach the published distributions and checksums
77
+ env:
78
+ GH_TOKEN: ${{ github.token }}
79
+ GH_REPO: ${{ github.repository }}
80
+ RELEASE_TAG: ${{ github.event.release.tag_name }}
81
+ run: gh release upload "$RELEASE_TAG" assets/*
@@ -0,0 +1,13 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.so
5
+ *.pyd
6
+ .pytest_cache/
7
+ .ruff_cache/
8
+ .coverage*
9
+ htmlcov/
10
+ target/
11
+ dist/
12
+ *.egg-info/
13
+ benchmark-results*.json
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,64 @@
1
+ # Contributing
2
+
3
+ Keep changes focused on measured pytest overhead while preserving observable
4
+ test behavior. Use uv for Python dependencies and Ruff for linting, import sorting,
5
+ and formatting. Keep Rust code formatted and checked with Cargo.
6
+
7
+ Use the development commands in the README. A change to an accelerated operation
8
+ needs differential coverage against stock pytest and a benchmark comparing the
9
+ stock implementation, an optimized Python implementation, and the native helper.
10
+ Confirm that native code was actually exercised and include control workloads.
11
+ Assertion-location changes must also compare generated AST locations, failures and
12
+ fallback behavior. The module-batching path initially supports pytest 9.1.1 on
13
+ GIL-enabled CPython 3.14; retain stock rewriting on other runtimes and modified ASTs.
14
+
15
+ Keep examples synthetic. Publish only sanitized, reproducible benchmark evidence;
16
+ keep project-specific source, configuration, paths, and results outside this repository.
17
+
18
+ Changes are reviewed through pull requests. GitHub CI verifies wheel installation,
19
+ compatibility tests, Rust checks, and source-distribution builds.
20
+ Installation checks use normal dependency resolution over existing pytest versions;
21
+ keep the installed version unchanged and compare fallback behavior with stock pytest.
22
+
23
+ ## Platform wheels
24
+
25
+ CI builds and tests these native wheels with CPython 3.12. The `abi3` wheels also
26
+ support newer GIL-enabled CPython versions; separate compatibility jobs cover
27
+ Python 3.10 through 3.14.
28
+
29
+ | System | Native architectures | Compatibility |
30
+ | --- | --- | --- |
31
+ | macOS | Intel x86-64, Apple ARM64 | Separate architecture wheels |
32
+ | Windows | x86-64, x86, ARM64 | MSVC wheels |
33
+ | Linux with glibc | x86-64, x86, ARM64 | manylinux2014 (glibc 2.17+) |
34
+ | Linux with musl | x86-64, x86, ARM64 | musllinux 1.2 (Alpine and similar) |
35
+
36
+ Every platform job installs its wheel, runs the compatibility suite, compares
37
+ native execution with stock pytest, and verifies `pytest --boorst`, the installed
38
+ module command and portable trial command.
39
+ Linux wheels are tested inside the matching pinned PyPA runtime, including musl.
40
+ ARM64 jobs use native ARM64 runners; x86 jobs run 32-bit Python on x86-64 hosts.
41
+ The universal Python wheel remains available as a fallback. This matrix describes
42
+ CI builds; released files are listed on each release page.
43
+
44
+ ## Publishing
45
+
46
+ Bump the Python version in `pyproject.toml`, `uv.lock` and `scripts/try.py`, the Rust
47
+ version in `Cargo.toml` and `Cargo.lock`, and current release references together.
48
+ Keep historical benchmark labels, receipt filenames and Boorst source links tied to the
49
+ versions they measured.
50
+ After the version change passes PR CI and lands on `main`, publish a GitHub release
51
+ with the exact `v<Python version>` tag. Stable and prerelease publications both
52
+ trigger `.github/workflows/publish.yml`.
53
+
54
+ The workflow checks the tag/version and main-branch ancestry, runs the complete CI
55
+ matrix on the release commit, and selects one tested wheel per platform plus the
56
+ universal wheel and source distribution. Publishing runs in a separate job with
57
+ OIDC permission and the `pypi` environment; it does not check out or execute project
58
+ code. GitHub release assets receive the same distributions and checksum manifest.
59
+
60
+ The one-time PyPI Trusted Publisher configuration must use project `pytest-boorst`,
61
+ owner `dnikolayev`, repository `pytest-boorst`, workflow `publish.yml`, and environment
62
+ `pypi`. Use a pending publisher when creating the project. No API token is needed.
63
+ If a release upload partially fails, inspect the uploaded files before retrying;
64
+ existing distributions are not silently skipped or overwritten.
@@ -0,0 +1,132 @@
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 4
4
+
5
+ [[package]]
6
+ name = "heck"
7
+ version = "0.5.0"
8
+ source = "registry+https://github.com/rust-lang/crates.io-index"
9
+ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
10
+
11
+ [[package]]
12
+ name = "libc"
13
+ version = "0.2.190"
14
+ source = "registry+https://github.com/rust-lang/crates.io-index"
15
+ checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78"
16
+
17
+ [[package]]
18
+ name = "once_cell"
19
+ version = "1.21.4"
20
+ source = "registry+https://github.com/rust-lang/crates.io-index"
21
+ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
22
+
23
+ [[package]]
24
+ name = "portable-atomic"
25
+ version = "1.15.0"
26
+ source = "registry+https://github.com/rust-lang/crates.io-index"
27
+ checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85"
28
+
29
+ [[package]]
30
+ name = "proc-macro2"
31
+ version = "1.0.107"
32
+ source = "registry+https://github.com/rust-lang/crates.io-index"
33
+ checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
34
+ dependencies = [
35
+ "unicode-ident",
36
+ ]
37
+
38
+ [[package]]
39
+ name = "pyo3"
40
+ version = "0.29.3"
41
+ source = "registry+https://github.com/rust-lang/crates.io-index"
42
+ checksum = "700d18fa267b73b9b521fd7e13580e2f446916f176cacee1ab63fcc8191f1655"
43
+ dependencies = [
44
+ "libc",
45
+ "once_cell",
46
+ "portable-atomic",
47
+ "pyo3-build-config",
48
+ "pyo3-ffi",
49
+ "pyo3-macros",
50
+ ]
51
+
52
+ [[package]]
53
+ name = "pyo3-build-config"
54
+ version = "0.29.3"
55
+ source = "registry+https://github.com/rust-lang/crates.io-index"
56
+ checksum = "7b3fc0c4d08f6bb10e71fe39dfb9e2f59c6eb6854e22ec8092f50c69a4499adb"
57
+ dependencies = [
58
+ "target-lexicon",
59
+ ]
60
+
61
+ [[package]]
62
+ name = "pyo3-ffi"
63
+ version = "0.29.3"
64
+ source = "registry+https://github.com/rust-lang/crates.io-index"
65
+ checksum = "dfc0b8e19df29aad7086cf977bb0c2a2f143e30567eb113e9cf72b62ca698330"
66
+ dependencies = [
67
+ "libc",
68
+ "pyo3-build-config",
69
+ ]
70
+
71
+ [[package]]
72
+ name = "pyo3-macros"
73
+ version = "0.29.3"
74
+ source = "registry+https://github.com/rust-lang/crates.io-index"
75
+ checksum = "6100e8a4b5eba53afaa5ed078364851a0b2499c553a44c31026b929049b49dc6"
76
+ dependencies = [
77
+ "proc-macro2",
78
+ "pyo3-macros-backend",
79
+ "quote",
80
+ "syn",
81
+ ]
82
+
83
+ [[package]]
84
+ name = "pyo3-macros-backend"
85
+ version = "0.29.3"
86
+ source = "registry+https://github.com/rust-lang/crates.io-index"
87
+ checksum = "6143877a16e82b5a727b7127ff4cd86858a24a28d745d72f43e6f227c7b1bdb3"
88
+ dependencies = [
89
+ "heck",
90
+ "proc-macro2",
91
+ "quote",
92
+ "syn",
93
+ ]
94
+
95
+ [[package]]
96
+ name = "pytest-boorst"
97
+ version = "0.1.0"
98
+ dependencies = [
99
+ "pyo3",
100
+ ]
101
+
102
+ [[package]]
103
+ name = "quote"
104
+ version = "1.0.47"
105
+ source = "registry+https://github.com/rust-lang/crates.io-index"
106
+ checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
107
+ dependencies = [
108
+ "proc-macro2",
109
+ ]
110
+
111
+ [[package]]
112
+ name = "syn"
113
+ version = "2.0.119"
114
+ source = "registry+https://github.com/rust-lang/crates.io-index"
115
+ checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
116
+ dependencies = [
117
+ "proc-macro2",
118
+ "quote",
119
+ "unicode-ident",
120
+ ]
121
+
122
+ [[package]]
123
+ name = "target-lexicon"
124
+ version = "0.13.5"
125
+ source = "registry+https://github.com/rust-lang/crates.io-index"
126
+ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
127
+
128
+ [[package]]
129
+ name = "unicode-ident"
130
+ version = "1.0.26"
131
+ source = "registry+https://github.com/rust-lang/crates.io-index"
132
+ checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954"
@@ -0,0 +1,21 @@
1
+ [package]
2
+ name = "pytest-boorst"
3
+ version = "0.1.0"
4
+ edition = "2024"
5
+ rust-version = "1.85"
6
+ license = "MIT"
7
+ description = "Native helpers for pytest-boorst"
8
+ repository = "https://github.com/dnikolayev/pytest-boorst"
9
+ readme = "README.md"
10
+
11
+ [lib]
12
+ name = "_native"
13
+ crate-type = ["cdylib", "rlib"]
14
+
15
+ [dependencies]
16
+ pyo3 = { version = "0.29.3", features = ["abi3-py310"] }
17
+
18
+ [profile.release]
19
+ # Avoid misaligned Mach-O string tables from rustc's debuginfo stripping.
20
+ # https://github.com/rust-lang/rust/issues/157750
21
+ strip = "none"