pytest-async-benchmark 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pytest_async_benchmark-0.1.1/.github/workflows/ci.yml +51 -0
- pytest_async_benchmark-0.1.1/.github/workflows/release.yml +346 -0
- pytest_async_benchmark-0.1.1/.github/workflows/test-publish.yml +141 -0
- pytest_async_benchmark-0.1.1/.gitignore +174 -0
- pytest_async_benchmark-0.1.1/.pre-commit-config.yaml +28 -0
- pytest_async_benchmark-0.1.1/LICENSE +21 -0
- pytest_async_benchmark-0.1.1/PKG-INFO +518 -0
- pytest_async_benchmark-0.1.1/PYPI_SETUP.md +141 -0
- pytest_async_benchmark-0.1.1/README.md +486 -0
- pytest_async_benchmark-0.1.1/RELEASE_GUIDE.md +271 -0
- pytest_async_benchmark-0.1.1/examples/comparison_examples.py +217 -0
- pytest_async_benchmark-0.1.1/examples/pytest_examples.py +158 -0
- pytest_async_benchmark-0.1.1/examples/quart_api_comparison.py +336 -0
- pytest_async_benchmark-0.1.1/pyproject.toml +61 -0
- pytest_async_benchmark-0.1.1/screenshot.png +0 -0
- pytest_async_benchmark-0.1.1/scripts/quality-check.py +56 -0
- pytest_async_benchmark-0.1.1/scripts/release-check.py +412 -0
- pytest_async_benchmark-0.1.1/src/pytest_async_benchmark/__init__.py +31 -0
- pytest_async_benchmark-0.1.1/src/pytest_async_benchmark/analytics.py +49 -0
- pytest_async_benchmark-0.1.1/src/pytest_async_benchmark/comparison.py +241 -0
- pytest_async_benchmark-0.1.1/src/pytest_async_benchmark/display.py +169 -0
- pytest_async_benchmark-0.1.1/src/pytest_async_benchmark/plugin.py +91 -0
- pytest_async_benchmark-0.1.1/src/pytest_async_benchmark/runner.py +56 -0
- pytest_async_benchmark-0.1.1/src/pytest_async_benchmark/stats.py +36 -0
- pytest_async_benchmark-0.1.1/src/pytest_async_benchmark/utils.py +30 -0
- pytest_async_benchmark-0.1.1/tests/conftest.py +16 -0
- pytest_async_benchmark-0.1.1/tests/test_async_bench.py +61 -0
- pytest_async_benchmark-0.1.1/tests/test_comparison.py +272 -0
- pytest_async_benchmark-0.1.1/tests/test_demo.py +48 -0
- pytest_async_benchmark-0.1.1/uv.lock +1274 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, develop]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.9", "3.10", "3.11", "3.12"]
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Install uv
|
|
20
|
+
uses: astral-sh/setup-uv@v3
|
|
21
|
+
with:
|
|
22
|
+
version: "latest"
|
|
23
|
+
|
|
24
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
25
|
+
run: uv python install ${{ matrix.python-version }}
|
|
26
|
+
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: |
|
|
29
|
+
uv sync --all-extras --dev
|
|
30
|
+
|
|
31
|
+
- name: Run linting
|
|
32
|
+
run: |
|
|
33
|
+
uv run ruff check .
|
|
34
|
+
uv run ruff format --check .
|
|
35
|
+
|
|
36
|
+
- name: Run tests
|
|
37
|
+
run: |
|
|
38
|
+
uv run pytest tests/ -v --tb=short
|
|
39
|
+
|
|
40
|
+
- name: Test examples
|
|
41
|
+
run: |
|
|
42
|
+
uv run python -m pytest examples/pytest_examples.py -v
|
|
43
|
+
uv run python examples/comparison_examples.py
|
|
44
|
+
|
|
45
|
+
- name: Test package build
|
|
46
|
+
run: |
|
|
47
|
+
uv build
|
|
48
|
+
# Verify the package can be installed
|
|
49
|
+
uv pip install dist/*.whl
|
|
50
|
+
# Test that the plugin is discoverable
|
|
51
|
+
uv run python -c "import pytest_async_benchmark; print('✅ Package imports successfully')"
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
name: Release to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
release:
|
|
8
|
+
types: [published]
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
inputs:
|
|
11
|
+
version:
|
|
12
|
+
description: "Version to release (must match git tag)"
|
|
13
|
+
required: true
|
|
14
|
+
type: string
|
|
15
|
+
|
|
16
|
+
env:
|
|
17
|
+
PYTHON_VERSION: "3.11"
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
validate-release:
|
|
21
|
+
name: Validate Release
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
outputs:
|
|
24
|
+
version: ${{ steps.get-version.outputs.version }}
|
|
25
|
+
is-prerelease: ${{ steps.check-prerelease.outputs.is-prerelease }}
|
|
26
|
+
|
|
27
|
+
steps:
|
|
28
|
+
- name: Checkout repository
|
|
29
|
+
uses: actions/checkout@v4
|
|
30
|
+
with:
|
|
31
|
+
fetch-depth: 0
|
|
32
|
+
|
|
33
|
+
- name: Set up Python
|
|
34
|
+
uses: actions/setup-python@v5
|
|
35
|
+
with:
|
|
36
|
+
python-version: ${{ env.PYTHON_VERSION }}
|
|
37
|
+
|
|
38
|
+
- name: Install uv
|
|
39
|
+
uses: astral-sh/setup-uv@v4
|
|
40
|
+
with:
|
|
41
|
+
enable-cache: true
|
|
42
|
+
|
|
43
|
+
- name: Get version from tag or input
|
|
44
|
+
id: get-version
|
|
45
|
+
run: |
|
|
46
|
+
if [ "${{ github.event_name }}" == "release" ]; then
|
|
47
|
+
VERSION="${{ github.event.release.tag_name }}"
|
|
48
|
+
elif [ "${{ github.event_name }}" == "push" ] && [ "${{ github.ref_type }}" == "tag" ]; then
|
|
49
|
+
VERSION="${{ github.ref_name }}"
|
|
50
|
+
elif [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
|
|
51
|
+
VERSION="${{ github.event.inputs.version }}"
|
|
52
|
+
else
|
|
53
|
+
echo "❌ Unable to determine version from event: ${{ github.event_name }}"
|
|
54
|
+
exit 1
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
VERSION=${VERSION#v}
|
|
58
|
+
|
|
59
|
+
echo "Event: ${{ github.event_name }}"
|
|
60
|
+
echo "Ref type: ${{ github.ref_type }}"
|
|
61
|
+
echo "Ref name: ${{ github.ref_name }}"
|
|
62
|
+
echo "Detected version: $VERSION"
|
|
63
|
+
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
64
|
+
|
|
65
|
+
- name: Verify version consistency
|
|
66
|
+
run: |
|
|
67
|
+
VERSION="${{ steps.get-version.outputs.version }}"
|
|
68
|
+
|
|
69
|
+
# Check pyproject.toml version
|
|
70
|
+
PYPROJECT_VERSION=$(grep '^version = ' pyproject.toml | sed 's/version = "\(.*\)"/\1/')
|
|
71
|
+
|
|
72
|
+
# Check __init__.py version
|
|
73
|
+
INIT_VERSION=$(grep '^__version__ = ' src/pytest_async_benchmark/__init__.py | sed 's/__version__ = "\(.*\)"/\1/')
|
|
74
|
+
|
|
75
|
+
echo "Tag/Input version: $VERSION"
|
|
76
|
+
echo "pyproject.toml version: $PYPROJECT_VERSION"
|
|
77
|
+
echo "__init__.py version: $INIT_VERSION"
|
|
78
|
+
|
|
79
|
+
if [ "$VERSION" != "$PYPROJECT_VERSION" ]; then
|
|
80
|
+
echo "❌ Version mismatch: tag ($VERSION) != pyproject.toml ($PYPROJECT_VERSION)"
|
|
81
|
+
exit 1
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
if [ "$VERSION" != "$INIT_VERSION" ]; then
|
|
85
|
+
echo "❌ Version mismatch: tag ($VERSION) != __init__.py ($INIT_VERSION)"
|
|
86
|
+
exit 1
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
echo "✅ All versions are consistent: $VERSION"
|
|
90
|
+
|
|
91
|
+
- name: Check if prerelease
|
|
92
|
+
id: check-prerelease
|
|
93
|
+
run: |
|
|
94
|
+
VERSION="${{ steps.get-version.outputs.version }}"
|
|
95
|
+
if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
96
|
+
echo "is-prerelease=false" >> $GITHUB_OUTPUT
|
|
97
|
+
echo "✅ Stable release version: $VERSION"
|
|
98
|
+
else
|
|
99
|
+
echo "is-prerelease=true" >> $GITHUB_OUTPUT
|
|
100
|
+
echo "🧪 Pre-release version: $VERSION"
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
- name: Run comprehensive tests
|
|
104
|
+
run: |
|
|
105
|
+
echo "🔍 Running comprehensive release checks..."
|
|
106
|
+
|
|
107
|
+
if [ "${{ github.event_name }}" == "push" ] && [ "${{ github.ref_type }}" == "tag" ]; then
|
|
108
|
+
echo "ℹ️ Tag-triggered release detected, running basic checks only..."
|
|
109
|
+
|
|
110
|
+
# Run basic checks without tag validation
|
|
111
|
+
uv run pytest tests/ -v --tb=short
|
|
112
|
+
uv run ruff check .
|
|
113
|
+
uv run ruff format --check .
|
|
114
|
+
|
|
115
|
+
echo "✅ Basic checks passed for tag-triggered release"
|
|
116
|
+
else
|
|
117
|
+
# Full release check for manual triggers
|
|
118
|
+
python scripts/release-check.py
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
test-matrix:
|
|
122
|
+
name: Test on Python ${{ matrix.python-version }}
|
|
123
|
+
runs-on: ubuntu-latest
|
|
124
|
+
needs: validate-release
|
|
125
|
+
strategy:
|
|
126
|
+
fail-fast: false
|
|
127
|
+
matrix:
|
|
128
|
+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
|
|
129
|
+
|
|
130
|
+
steps:
|
|
131
|
+
- name: Checkout repository
|
|
132
|
+
uses: actions/checkout@v4
|
|
133
|
+
|
|
134
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
135
|
+
uses: actions/setup-python@v5
|
|
136
|
+
with:
|
|
137
|
+
python-version: ${{ matrix.python-version }}
|
|
138
|
+
|
|
139
|
+
- name: Install uv
|
|
140
|
+
uses: astral-sh/setup-uv@v4
|
|
141
|
+
with:
|
|
142
|
+
enable-cache: true
|
|
143
|
+
|
|
144
|
+
- name: Install dependencies and run tests
|
|
145
|
+
run: |
|
|
146
|
+
echo "🧪 Testing on Python ${{ matrix.python-version }}..."
|
|
147
|
+
uv sync --dev
|
|
148
|
+
uv run pytest tests/ -v --tb=short
|
|
149
|
+
|
|
150
|
+
echo "📝 Testing examples..."
|
|
151
|
+
uv run python -m pytest examples/pytest_examples.py -v
|
|
152
|
+
|
|
153
|
+
echo "🔍 Testing plugin discovery..."
|
|
154
|
+
uv run python -c "import pytest_async_benchmark; print(f'✅ Plugin imported successfully - version: {pytest_async_benchmark.__version__}')"
|
|
155
|
+
|
|
156
|
+
build-and-publish:
|
|
157
|
+
name: Build and Publish to PyPI
|
|
158
|
+
runs-on: ubuntu-latest
|
|
159
|
+
needs: [validate-release, test-matrix]
|
|
160
|
+
environment: release
|
|
161
|
+
|
|
162
|
+
permissions:
|
|
163
|
+
contents: read
|
|
164
|
+
id-token: write # Required for trusted publishing to PyPI
|
|
165
|
+
attestations: write # Required for package attestations
|
|
166
|
+
|
|
167
|
+
steps:
|
|
168
|
+
- name: Checkout repository
|
|
169
|
+
uses: actions/checkout@v4
|
|
170
|
+
with:
|
|
171
|
+
fetch-depth: 0
|
|
172
|
+
|
|
173
|
+
- name: Set up Python
|
|
174
|
+
uses: actions/setup-python@v5
|
|
175
|
+
with:
|
|
176
|
+
python-version: ${{ env.PYTHON_VERSION }}
|
|
177
|
+
|
|
178
|
+
- name: Install uv
|
|
179
|
+
uses: astral-sh/setup-uv@v4
|
|
180
|
+
with:
|
|
181
|
+
enable-cache: true
|
|
182
|
+
|
|
183
|
+
- name: Build package
|
|
184
|
+
run: |
|
|
185
|
+
echo "🔨 Building package for release..."
|
|
186
|
+
uv build
|
|
187
|
+
|
|
188
|
+
echo "📦 Built packages:"
|
|
189
|
+
ls -la dist/
|
|
190
|
+
|
|
191
|
+
echo "📋 Package contents:"
|
|
192
|
+
for file in dist/*; do
|
|
193
|
+
echo "=== $file ==="
|
|
194
|
+
if [[ $file == *.whl ]]; then
|
|
195
|
+
python -m zipfile -l "$file"
|
|
196
|
+
elif [[ $file == *.tar.gz ]]; then
|
|
197
|
+
tar -tzf "$file" | head -20
|
|
198
|
+
fi
|
|
199
|
+
echo ""
|
|
200
|
+
done
|
|
201
|
+
|
|
202
|
+
- name: Generate package attestations
|
|
203
|
+
uses: actions/attest-build-provenance@v1
|
|
204
|
+
with:
|
|
205
|
+
subject-path: "dist/*"
|
|
206
|
+
|
|
207
|
+
- name: Publish to PyPI
|
|
208
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
209
|
+
with:
|
|
210
|
+
verbose: true
|
|
211
|
+
print-hash: true
|
|
212
|
+
attestations: true
|
|
213
|
+
|
|
214
|
+
- name: Upload release artifacts
|
|
215
|
+
uses: actions/upload-artifact@v4
|
|
216
|
+
with:
|
|
217
|
+
name: release-dist-${{ needs.validate-release.outputs.version }}
|
|
218
|
+
path: dist/
|
|
219
|
+
retention-days: 90
|
|
220
|
+
|
|
221
|
+
create-github-release:
|
|
222
|
+
name: Create GitHub Release
|
|
223
|
+
runs-on: ubuntu-latest
|
|
224
|
+
needs: [validate-release, build-and-publish]
|
|
225
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
|
226
|
+
|
|
227
|
+
permissions:
|
|
228
|
+
contents: write
|
|
229
|
+
|
|
230
|
+
steps:
|
|
231
|
+
- name: Checkout repository
|
|
232
|
+
uses: actions/checkout@v4
|
|
233
|
+
|
|
234
|
+
- name: Create Release
|
|
235
|
+
uses: actions/create-release@v1
|
|
236
|
+
env:
|
|
237
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
238
|
+
with:
|
|
239
|
+
tag_name: ${{ github.ref_name }}
|
|
240
|
+
release_name: "Release ${{ github.ref_name }}"
|
|
241
|
+
draft: false
|
|
242
|
+
prerelease: ${{ needs.validate-release.outputs.is-prerelease == 'true' }}
|
|
243
|
+
body: |
|
|
244
|
+
## 🚀 pytest-async-benchmark ${{ github.ref_name }}
|
|
245
|
+
|
|
246
|
+
### 📦 Installation
|
|
247
|
+
```bash
|
|
248
|
+
pip install pytest-async-benchmark==${{ needs.validate-release.outputs.version }}
|
|
249
|
+
# or
|
|
250
|
+
uv add pytest-async-benchmark==${{ needs.validate-release.outputs.version }}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### 🔗 Links
|
|
254
|
+
- **PyPI:** https://pypi.org/project/pytest-async-benchmark/${{ needs.validate-release.outputs.version }}/
|
|
255
|
+
- **Documentation:** https://github.com/${{ github.repository }}#readme
|
|
256
|
+
|
|
257
|
+
For detailed changes, see the commit history.
|
|
258
|
+
|
|
259
|
+
post-release:
|
|
260
|
+
name: Post-Release Tasks
|
|
261
|
+
runs-on: ubuntu-latest
|
|
262
|
+
needs: [validate-release, build-and-publish]
|
|
263
|
+
if: always() && needs.build-and-publish.result == 'success'
|
|
264
|
+
|
|
265
|
+
steps:
|
|
266
|
+
- name: Wait for PyPI availability
|
|
267
|
+
run: |
|
|
268
|
+
VERSION="${{ needs.validate-release.outputs.version }}"
|
|
269
|
+
echo "⏳ Waiting for package to be available on PyPI..."
|
|
270
|
+
|
|
271
|
+
for i in {1..10}; do
|
|
272
|
+
echo "🔍 Attempt $i: Checking PyPI availability..."
|
|
273
|
+
if curl -s "https://pypi.org/pypi/pytest-async-benchmark/$VERSION/json" | grep -q '"version"'; then
|
|
274
|
+
echo "✅ Package is available on PyPI!"
|
|
275
|
+
break
|
|
276
|
+
else
|
|
277
|
+
if [ $i -eq 10 ]; then
|
|
278
|
+
echo "⚠️ Package may not be immediately available on PyPI"
|
|
279
|
+
else
|
|
280
|
+
echo "⏳ Not available yet, waiting 30 seconds..."
|
|
281
|
+
sleep 30
|
|
282
|
+
fi
|
|
283
|
+
fi
|
|
284
|
+
done
|
|
285
|
+
|
|
286
|
+
- name: Test installation from PyPI
|
|
287
|
+
run: |
|
|
288
|
+
VERSION="${{ needs.validate-release.outputs.version }}"
|
|
289
|
+
echo "📥 Testing installation from PyPI..."
|
|
290
|
+
|
|
291
|
+
# Create fresh environment for testing
|
|
292
|
+
python -m venv test-env
|
|
293
|
+
source test-env/bin/activate
|
|
294
|
+
|
|
295
|
+
# Install from PyPI
|
|
296
|
+
pip install pytest-async-benchmark==$VERSION
|
|
297
|
+
|
|
298
|
+
# Test basic functionality
|
|
299
|
+
python -c "
|
|
300
|
+
import pytest_async_benchmark
|
|
301
|
+
print(f'✅ Successfully installed from PyPI - version: {pytest_async_benchmark.__version__}')
|
|
302
|
+
|
|
303
|
+
# Test pytest plugin
|
|
304
|
+
import pytest
|
|
305
|
+
from pytest_async_benchmark.plugin import pytest_configure
|
|
306
|
+
print('✅ Pytest plugin can be imported')
|
|
307
|
+
|
|
308
|
+
# Test basic runner functionality
|
|
309
|
+
import asyncio
|
|
310
|
+
from pytest_async_benchmark.runner import AsyncBenchmarkRunner
|
|
311
|
+
|
|
312
|
+
async def test_func():
|
|
313
|
+
await asyncio.sleep(0.001)
|
|
314
|
+
return 'test'
|
|
315
|
+
|
|
316
|
+
async def main():
|
|
317
|
+
runner = AsyncBenchmarkRunner(rounds=2, iterations=3)
|
|
318
|
+
result = await runner.run(test_func)
|
|
319
|
+
print(f'✅ Basic benchmark test passed: {result[\"mean\"]:.4f}s average')
|
|
320
|
+
|
|
321
|
+
asyncio.run(main())
|
|
322
|
+
"
|
|
323
|
+
|
|
324
|
+
- name: Create release summary
|
|
325
|
+
run: |
|
|
326
|
+
VERSION="${{ needs.validate-release.outputs.version }}"
|
|
327
|
+
IS_PRERELEASE="${{ needs.validate-release.outputs.is-prerelease }}"
|
|
328
|
+
|
|
329
|
+
echo "## 🚀 Release Summary" >> $GITHUB_STEP_SUMMARY
|
|
330
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
331
|
+
echo "- **Version:** \`$VERSION\`" >> $GITHUB_STEP_SUMMARY
|
|
332
|
+
echo "- **Type:** $([ "$IS_PRERELEASE" == "true" ] && echo "Pre-release 🧪" || echo "Stable Release ✅")" >> $GITHUB_STEP_SUMMARY
|
|
333
|
+
echo "- **PyPI URL:** https://pypi.org/project/pytest-async-benchmark/$VERSION/" >> $GITHUB_STEP_SUMMARY
|
|
334
|
+
echo "- **Documentation:** https://github.com/${{ github.repository }}#readme" >> $GITHUB_STEP_SUMMARY
|
|
335
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
336
|
+
echo "### 📦 Installation" >> $GITHUB_STEP_SUMMARY
|
|
337
|
+
echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY
|
|
338
|
+
echo "pip install pytest-async-benchmark==$VERSION" >> $GITHUB_STEP_SUMMARY
|
|
339
|
+
echo "# or" >> $GITHUB_STEP_SUMMARY
|
|
340
|
+
echo "uv add pytest-async-benchmark==$VERSION" >> $GITHUB_STEP_SUMMARY
|
|
341
|
+
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
|
|
342
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
343
|
+
echo "### 🎉 What's New" >> $GITHUB_STEP_SUMMARY
|
|
344
|
+
echo "Check the [release notes](https://github.com/${{ github.repository }}/releases/tag/v$VERSION) for detailed changes." >> $GITHUB_STEP_SUMMARY
|
|
345
|
+
|
|
346
|
+
echo "🎉 Successfully released pytest-async-benchmark v$VERSION to PyPI!"
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
name: Test Publish to TestPyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths:
|
|
7
|
+
- "src/**"
|
|
8
|
+
- "pyproject.toml"
|
|
9
|
+
- ".github/workflows/test-publish.yml"
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
inputs:
|
|
12
|
+
test_version:
|
|
13
|
+
description: "Test version suffix (e.g., rc1, beta1)"
|
|
14
|
+
required: false
|
|
15
|
+
default: "dev"
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
test-publish:
|
|
19
|
+
name: Test Publish to TestPyPI
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
|
|
22
|
+
permissions:
|
|
23
|
+
contents: read
|
|
24
|
+
id-token: write
|
|
25
|
+
|
|
26
|
+
steps:
|
|
27
|
+
- name: Checkout repository
|
|
28
|
+
uses: actions/checkout@v4
|
|
29
|
+
with:
|
|
30
|
+
fetch-depth: 0
|
|
31
|
+
|
|
32
|
+
- name: Set up Python
|
|
33
|
+
uses: actions/setup-python@v5
|
|
34
|
+
with:
|
|
35
|
+
python-version: "3.11"
|
|
36
|
+
|
|
37
|
+
- name: Install uv
|
|
38
|
+
uses: astral-sh/setup-uv@v4
|
|
39
|
+
with:
|
|
40
|
+
enable-cache: true
|
|
41
|
+
|
|
42
|
+
- name: Verify release readiness
|
|
43
|
+
run: |
|
|
44
|
+
echo "🔍 Running release readiness checks..."
|
|
45
|
+
python scripts/release-check.py
|
|
46
|
+
|
|
47
|
+
- name: Create test version
|
|
48
|
+
run: |
|
|
49
|
+
CURRENT_VERSION=$(grep '^version = ' pyproject.toml | sed 's/version = "\(.*\)"/\1/')
|
|
50
|
+
|
|
51
|
+
TIMESTAMP=$(date +%Y%m%d%H%M%S)
|
|
52
|
+
TEST_SUFFIX="${{ github.event.inputs.test_version || 'dev' }}"
|
|
53
|
+
TEST_VERSION="${CURRENT_VERSION}.${TEST_SUFFIX}${TIMESTAMP}"
|
|
54
|
+
|
|
55
|
+
echo "Current version: $CURRENT_VERSION"
|
|
56
|
+
echo "Test version: $TEST_VERSION"
|
|
57
|
+
echo "TEST_VERSION=$TEST_VERSION" >> $GITHUB_ENV
|
|
58
|
+
|
|
59
|
+
sed -i "s/version = \"$CURRENT_VERSION\"/version = \"$TEST_VERSION\"/" pyproject.toml
|
|
60
|
+
sed -i "s/__version__ = \"$CURRENT_VERSION\"/__version__ = \"$TEST_VERSION\"/" src/pytest_async_benchmark/__init__.py
|
|
61
|
+
|
|
62
|
+
- name: Build package
|
|
63
|
+
run: |
|
|
64
|
+
echo "🔨 Building package with test version $TEST_VERSION..."
|
|
65
|
+
uv build
|
|
66
|
+
|
|
67
|
+
echo "📦 Built packages:"
|
|
68
|
+
ls -la dist/
|
|
69
|
+
|
|
70
|
+
find dist/ -name "*-py3-none-any.whl" ! -name "*$TEST_VERSION*" -delete
|
|
71
|
+
find dist/ -name "*.tar.gz" ! -name "*$TEST_VERSION*" -delete
|
|
72
|
+
|
|
73
|
+
echo "📦 Final packages for upload:"
|
|
74
|
+
ls -la dist/
|
|
75
|
+
|
|
76
|
+
- name: Publish to TestPyPI
|
|
77
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
78
|
+
with:
|
|
79
|
+
repository-url: https://test.pypi.org/legacy/
|
|
80
|
+
verbose: true
|
|
81
|
+
print-hash: true
|
|
82
|
+
|
|
83
|
+
- name: Test installation from TestPyPI
|
|
84
|
+
run: |
|
|
85
|
+
echo "⏳ Waiting for package to be available on TestPyPI..."
|
|
86
|
+
sleep 30
|
|
87
|
+
|
|
88
|
+
echo "📥 Testing installation from TestPyPI..."
|
|
89
|
+
|
|
90
|
+
# Install from TestPyPI with retries
|
|
91
|
+
for i in {1..5}; do
|
|
92
|
+
if pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ pytest-async-benchmark==$TEST_VERSION; then
|
|
93
|
+
echo "✅ Successfully installed from TestPyPI"
|
|
94
|
+
break
|
|
95
|
+
else
|
|
96
|
+
echo "⏳ Attempt $i failed, retrying in 30 seconds..."
|
|
97
|
+
sleep 30
|
|
98
|
+
if [ $i -eq 5 ]; then
|
|
99
|
+
echo "❌ Failed to install after 5 attempts"
|
|
100
|
+
exit 1
|
|
101
|
+
fi
|
|
102
|
+
fi
|
|
103
|
+
done
|
|
104
|
+
|
|
105
|
+
# Test basic import and version
|
|
106
|
+
python -c "
|
|
107
|
+
import pytest_async_benchmark
|
|
108
|
+
print(f'✅ Import successful - version: {pytest_async_benchmark.__version__}')
|
|
109
|
+
assert pytest_async_benchmark.__version__ == '$TEST_VERSION', f'Version mismatch: expected $TEST_VERSION, got {pytest_async_benchmark.__version__}'
|
|
110
|
+
print('✅ Version verification passed')
|
|
111
|
+
"
|
|
112
|
+
|
|
113
|
+
# Test pytest plugin discovery
|
|
114
|
+
python -c "
|
|
115
|
+
import pytest
|
|
116
|
+
from pytest_async_benchmark.plugin import pytest_configure
|
|
117
|
+
print('✅ Pytest plugin can be imported and configured')
|
|
118
|
+
"
|
|
119
|
+
|
|
120
|
+
# Test that the fixture is available
|
|
121
|
+
echo 'def test_fixture_available(async_benchmark): pass' > test_temp.py
|
|
122
|
+
python -m pytest test_temp.py --collect-only | grep "async_benchmark" && echo "✅ async_benchmark fixture is discoverable" || echo "⚠️ Fixture discovery test failed"
|
|
123
|
+
rm -f test_temp.py
|
|
124
|
+
|
|
125
|
+
- name: Upload build artifacts
|
|
126
|
+
uses: actions/upload-artifact@v4
|
|
127
|
+
if: always()
|
|
128
|
+
with:
|
|
129
|
+
name: test-dist-packages
|
|
130
|
+
path: dist/
|
|
131
|
+
retention-days: 7
|
|
132
|
+
|
|
133
|
+
- name: Summary
|
|
134
|
+
run: |
|
|
135
|
+
echo "## 🧪 Test Publish Summary" >> $GITHUB_STEP_SUMMARY
|
|
136
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
137
|
+
echo "- **Test Version:** \`$TEST_VERSION\`" >> $GITHUB_STEP_SUMMARY
|
|
138
|
+
echo "- **TestPyPI URL:** https://test.pypi.org/project/pytest-async-benchmark/$TEST_VERSION/" >> $GITHUB_STEP_SUMMARY
|
|
139
|
+
echo "- **Install Command:** \`pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ pytest-async-benchmark==$TEST_VERSION\`" >> $GITHUB_STEP_SUMMARY
|
|
140
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
141
|
+
echo "✅ Package successfully published to TestPyPI for testing!" >> $GITHUB_STEP_SUMMARY
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py,cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
#Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# UV
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
#uv.lock
|
|
102
|
+
|
|
103
|
+
# poetry
|
|
104
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
105
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
106
|
+
# commonly ignored for libraries.
|
|
107
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
108
|
+
#poetry.lock
|
|
109
|
+
|
|
110
|
+
# pdm
|
|
111
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
112
|
+
#pdm.lock
|
|
113
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
114
|
+
# in version control.
|
|
115
|
+
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
|
116
|
+
.pdm.toml
|
|
117
|
+
.pdm-python
|
|
118
|
+
.pdm-build/
|
|
119
|
+
|
|
120
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
121
|
+
__pypackages__/
|
|
122
|
+
|
|
123
|
+
# Celery stuff
|
|
124
|
+
celerybeat-schedule
|
|
125
|
+
celerybeat.pid
|
|
126
|
+
|
|
127
|
+
# SageMath parsed files
|
|
128
|
+
*.sage.py
|
|
129
|
+
|
|
130
|
+
# Environments
|
|
131
|
+
.env
|
|
132
|
+
.venv
|
|
133
|
+
env/
|
|
134
|
+
venv/
|
|
135
|
+
ENV/
|
|
136
|
+
env.bak/
|
|
137
|
+
venv.bak/
|
|
138
|
+
|
|
139
|
+
# Spyder project settings
|
|
140
|
+
.spyderproject
|
|
141
|
+
.spyproject
|
|
142
|
+
|
|
143
|
+
# Rope project settings
|
|
144
|
+
.ropeproject
|
|
145
|
+
|
|
146
|
+
# mkdocs documentation
|
|
147
|
+
/site
|
|
148
|
+
|
|
149
|
+
# mypy
|
|
150
|
+
.mypy_cache/
|
|
151
|
+
.dmypy.json
|
|
152
|
+
dmypy.json
|
|
153
|
+
|
|
154
|
+
# Pyre type checker
|
|
155
|
+
.pyre/
|
|
156
|
+
|
|
157
|
+
# pytype static type analyzer
|
|
158
|
+
.pytype/
|
|
159
|
+
|
|
160
|
+
# Cython debug symbols
|
|
161
|
+
cython_debug/
|
|
162
|
+
|
|
163
|
+
# PyCharm
|
|
164
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
165
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
166
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
167
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
168
|
+
#.idea/
|
|
169
|
+
|
|
170
|
+
# Ruff stuff:
|
|
171
|
+
.ruff_cache/
|
|
172
|
+
|
|
173
|
+
# PyPI configuration file
|
|
174
|
+
.pypirc
|