Skip to content

Commit 3a42dbf

Browse files
committed
Merge branch 'master' into ivana/toxgen/ray
2 parents 7b9c68f + e110151 commit 3a42dbf

File tree

6 files changed

+117
-213
lines changed

6 files changed

+117
-213
lines changed

.github/workflows/test-integrations-web-2.yml

Lines changed: 0 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -22,101 +22,6 @@ env:
2222
CACHED_BUILD_PATHS: |
2323
${{ github.workspace }}/dist-serverless
2424
jobs:
25-
test-web_2-latest:
26-
name: Web 2 (latest)
27-
timeout-minutes: 30
28-
runs-on: ${{ matrix.os }}
29-
strategy:
30-
fail-fast: false
31-
matrix:
32-
python-version: ["3.9","3.12","3.13"]
33-
# python3.6 reached EOL and is no longer being supported on
34-
# new versions of hosted runners on Github Actions
35-
# ubuntu-20.04 is the last version that supported python3.6
36-
# see https://github.com/actions/setup-python/issues/544#issuecomment-1332535877
37-
os: [ubuntu-22.04]
38-
# Use Docker container only for Python 3.6
39-
container: ${{ matrix.python-version == '3.6' && 'python:3.6' || null }}
40-
steps:
41-
- uses: actions/checkout@v5.0.0
42-
- uses: actions/setup-python@v6
43-
if: ${{ matrix.python-version != '3.6' }}
44-
with:
45-
python-version: ${{ matrix.python-version }}
46-
allow-prereleases: true
47-
- name: Setup Test Env
48-
run: |
49-
pip install "coverage[toml]" tox
50-
- name: Erase coverage
51-
run: |
52-
coverage erase
53-
- name: Test aiohttp latest
54-
run: |
55-
set -x # print commands that are executed
56-
./scripts/runtox.sh "py${{ matrix.python-version }}-aiohttp-latest"
57-
- name: Test asgi latest
58-
run: |
59-
set -x # print commands that are executed
60-
./scripts/runtox.sh "py${{ matrix.python-version }}-asgi-latest"
61-
- name: Test bottle latest
62-
run: |
63-
set -x # print commands that are executed
64-
./scripts/runtox.sh "py${{ matrix.python-version }}-bottle-latest"
65-
- name: Test falcon latest
66-
run: |
67-
set -x # print commands that are executed
68-
./scripts/runtox.sh "py${{ matrix.python-version }}-falcon-latest"
69-
- name: Test litestar latest
70-
run: |
71-
set -x # print commands that are executed
72-
./scripts/runtox.sh "py${{ matrix.python-version }}-litestar-latest"
73-
- name: Test pyramid latest
74-
run: |
75-
set -x # print commands that are executed
76-
./scripts/runtox.sh "py${{ matrix.python-version }}-pyramid-latest"
77-
- name: Test quart latest
78-
run: |
79-
set -x # print commands that are executed
80-
./scripts/runtox.sh "py${{ matrix.python-version }}-quart-latest"
81-
- name: Test sanic latest
82-
run: |
83-
set -x # print commands that are executed
84-
./scripts/runtox.sh "py${{ matrix.python-version }}-sanic-latest"
85-
- name: Test starlite latest
86-
run: |
87-
set -x # print commands that are executed
88-
./scripts/runtox.sh "py${{ matrix.python-version }}-starlite-latest"
89-
- name: Test tornado latest
90-
run: |
91-
set -x # print commands that are executed
92-
./scripts/runtox.sh "py${{ matrix.python-version }}-tornado-latest"
93-
- name: Generate coverage XML (Python 3.6)
94-
if: ${{ !cancelled() && matrix.python-version == '3.6' }}
95-
run: |
96-
export COVERAGE_RCFILE=.coveragerc36
97-
coverage combine .coverage-sentry-*
98-
coverage xml --ignore-errors
99-
- name: Generate coverage XML
100-
if: ${{ !cancelled() && matrix.python-version != '3.6' }}
101-
run: |
102-
coverage combine .coverage-sentry-*
103-
coverage xml
104-
- name: Upload coverage to Codecov
105-
if: ${{ !cancelled() }}
106-
uses: codecov/codecov-action@v5.5.1
107-
with:
108-
token: ${{ secrets.CODECOV_TOKEN }}
109-
files: coverage.xml
110-
# make sure no plugins alter our coverage reports
111-
plugins: noop
112-
verbose: true
113-
- name: Upload test results to Codecov
114-
if: ${{ !cancelled() }}
115-
uses: codecov/test-results-action@v1
116-
with:
117-
token: ${{ secrets.CODECOV_TOKEN }}
118-
files: .junitxml
119-
verbose: true
12025
test-web_2-pinned:
12126
name: Web 2 (pinned)
12227
timeout-minutes: 30

scripts/populate_tox/README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ then determining which versions make sense to test to get good coverage.
1818

1919
The lowest supported and latest version of a framework are always tested, with
2020
a number of releases in between:
21-
- If the package has majors, we pick the highest version of each major. For the
22-
latest major, we also pick the lowest version in that major.
21+
- If the package has majors, we pick the highest version of each major.
2322
- If the package doesn't have multiple majors, we pick two versions in between
2423
lowest and highest.
2524

@@ -46,6 +45,8 @@ integration_name: {
4645
},
4746
"python": python_version_specifier,
4847
"include": package_version_specifier,
48+
"integration_name": integration_name,
49+
"num_versions": int,
4950
}
5051
```
5152

@@ -161,6 +162,10 @@ of which are actually testing the `openai` integration. If this is the case, you
161162

162163
Linking an integration to a test suite allows the script to access integration configuration like for example the minimum version defined in `sentry_sdk/integrations/__init__.py`.
163164

165+
### `num_versions`
166+
167+
With this option you can tweak the default version picking behavior by specifying how many package versions should be tested. It accepts an integer equal to or greater than 2, as the oldest and latest supported versions will always be picked. Additionally, if there is a recent prerelease, it'll also always be picked (this doesn't count towards `num_versions`).
168+
164169

165170
## How-Tos
166171

scripts/populate_tox/config.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,9 @@
224224
"openfeature": {
225225
"package": "openfeature-sdk",
226226
},
227+
"pure_eval": {
228+
"package": "pure_eval",
229+
},
227230
"pymongo": {
228231
"package": "pymongo",
229232
"deps": {
@@ -253,13 +256,24 @@
253256
"ray": {
254257
"package": "ray",
255258
"python": ">=3.9",
259+
"num_versions": 2,
256260
},
257261
"redis_py_cluster_legacy": {
258262
"package": "redis-py-cluster",
259263
},
260264
"requests": {
261265
"package": "requests",
262266
},
267+
"sanic": {
268+
"package": "sanic",
269+
"deps": {
270+
"*": ["websockets<11.0", "aiohttp"],
271+
">=22": ["sanic-testing"],
272+
"py3.6": ["aiocontextvars==0.2.1"],
273+
"py3.8": ["tracerite<1.1.2"],
274+
},
275+
"num_versions": 4,
276+
},
263277
"spark": {
264278
"package": "pyspark",
265279
"python": ">=3.8",

scripts/populate_tox/populate_tox.py

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,9 @@
7070
# of these from the IGNORE list
7171
"gcp",
7272
"httpx",
73-
"pure_eval",
7473
"redis",
7574
"requests",
7675
"rq",
77-
"sanic",
7876
}
7977

8078

@@ -258,47 +256,48 @@ def _supports_lowest(release: Version) -> bool:
258256

259257

260258
def pick_releases_to_test(
261-
releases: list[Version], last_prerelease: Optional[Version]
259+
integration: str, releases: list[Version], last_prerelease: Optional[Version]
262260
) -> list[Version]:
263261
"""Pick a handful of releases to test from a sorted list of supported releases."""
264262
# If the package has majors (or major-like releases, even if they don't do
265-
# semver), we want to make sure we're testing them all. If not, we just pick
266-
# the oldest, the newest, and a couple in between.
263+
# semver), we want to make sure we're testing them all (unless there's too
264+
# many). If not, we just pick the oldest, the newest, and a couple
265+
# in between.
267266
#
268267
# If there is a relevant prerelease, also test that in addition to the above.
269-
has_majors = len(set([v.major for v in releases])) > 1
268+
num_versions = TEST_SUITE_CONFIG[integration].get("num_versions")
269+
if num_versions is not None and (
270+
not isinstance(num_versions, int) or num_versions < 2
271+
):
272+
print(" Integration has invalid `num_versions`: must be an int >= 2")
273+
num_versions = None
274+
275+
has_majors = len({v.major for v in releases}) > 1
270276
filtered_releases = set()
271277

272278
if has_majors:
273279
# Always check the very first supported release
274280
filtered_releases.add(releases[0])
275281

276-
# Find out the min and max release by each major
282+
# Find out the max release by each major
277283
releases_by_major = {}
278284
for release in releases:
279-
if release.major not in releases_by_major:
280-
releases_by_major[release.major] = [release, release]
281-
if release < releases_by_major[release.major][0]:
282-
releases_by_major[release.major][0] = release
283-
if release > releases_by_major[release.major][1]:
284-
releases_by_major[release.major][1] = release
285-
286-
for i, (min_version, max_version) in enumerate(releases_by_major.values()):
285+
if (
286+
release.major not in releases_by_major
287+
or release > releases_by_major[release.major]
288+
):
289+
releases_by_major[release.major] = release
290+
291+
# Add the highest release in each major
292+
for max_version in releases_by_major.values():
287293
filtered_releases.add(max_version)
288-
if i == len(releases_by_major) - 1:
289-
# If this is the latest major release, also check the lowest
290-
# version of this version
291-
filtered_releases.add(min_version)
294+
295+
# If num_versions was provided, slim down the selection
296+
if num_versions is not None:
297+
filtered_releases = _pick_releases(sorted(filtered_releases), num_versions)
292298

293299
else:
294-
filtered_releases = {
295-
releases[0], # oldest version supported
296-
releases[len(releases) // 3],
297-
releases[
298-
len(releases) // 3 * 2
299-
], # two releases in between, roughly evenly spaced
300-
releases[-1], # latest
301-
}
300+
filtered_releases = _pick_releases(releases, num_versions)
302301

303302
filtered_releases = sorted(filtered_releases)
304303
if last_prerelease is not None:
@@ -307,6 +306,25 @@ def pick_releases_to_test(
307306
return filtered_releases
308307

309308

309+
def _pick_releases(
310+
releases: list[Version], num_versions: Optional[int]
311+
) -> set[Version]:
312+
num_versions = num_versions or 4
313+
314+
versions = {
315+
releases[0], # oldest version supported
316+
releases[-1], # latest
317+
}
318+
319+
for i in range(1, num_versions - 1):
320+
try:
321+
versions.add(releases[len(releases) // (num_versions - 1) * i])
322+
except IndexError:
323+
pass
324+
325+
return versions
326+
327+
310328
def supported_python_versions(
311329
package_python_versions: Union[SpecifierSet, list[Version]],
312330
custom_supported_versions: Optional[SpecifierSet] = None,
@@ -438,7 +456,7 @@ def _render_dependencies(integration: str, releases: list[Version]) -> list[str]
438456
for dep in deps:
439457
rendered.append(f"{{{constraint}}}-{integration}: {dep}")
440458
else:
441-
restriction = SpecifierSet(constraint)
459+
restriction = SpecifierSet(constraint, prereleases=True)
442460
for release in releases:
443461
if release in restriction:
444462
for dep in deps:
@@ -631,7 +649,9 @@ def main(fail_on_changes: bool = False) -> None:
631649
# Pick a handful of the supported releases to actually test against
632650
# and fetch the PyPI data for each to determine which Python versions
633651
# to test it on
634-
test_releases = pick_releases_to_test(releases, latest_prerelease)
652+
test_releases = pick_releases_to_test(
653+
integration, releases, latest_prerelease
654+
)
635655

636656
for release in test_releases:
637657
_add_python_versions_to_release(integration, package, release)

scripts/populate_tox/tox.jinja

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,6 @@ envlist =
6161
# OpenTelemetry Experimental (POTel)
6262
{py3.8,py3.9,py3.10,py3.11,py3.12,py3.13}-potel
6363

64-
# pure_eval
65-
{py3.6,py3.12,py3.13}-pure_eval
66-
6764
# Redis
6865
{py3.6,py3.8}-redis-v{3}
6966
{py3.7,py3.8,py3.11}-redis-v{4}
@@ -80,12 +77,6 @@ envlist =
8077
{py3.7,py3.11,py3.12}-rq-v{1.15,1.16}
8178
{py3.7,py3.12,py3.13}-rq-latest
8279

83-
# Sanic
84-
{py3.6,py3.7}-sanic-v{0.8}
85-
{py3.6,py3.8}-sanic-v{20}
86-
{py3.8,py3.11,py3.12}-sanic-v{24.6}
87-
{py3.9,py3.12,py3.13}-sanic-latest
88-
8980
# === Integrations - Auto-generated ===
9081
# These come from the populate_tox.py script. Eventually we should move all
9182
# integration tests there.
@@ -173,9 +164,6 @@ deps =
173164
# OpenTelemetry Experimental (POTel)
174165
potel: -e .[opentelemetry-experimental]
175166
176-
# pure_eval
177-
pure_eval: pure_eval
178-
179167
# Redis
180168
redis: fakeredis!=1.7.4
181169
redis: pytest<8.0.0
@@ -208,18 +196,6 @@ deps =
208196
rq-v1.16: rq~=1.16.0
209197
rq-latest: rq
210198
211-
# Sanic
212-
sanic: websockets<11.0
213-
sanic: aiohttp
214-
sanic-v{24.6}: sanic_testing
215-
sanic-latest: sanic_testing
216-
{py3.6}-sanic: aiocontextvars==0.2.1
217-
{py3.8}-sanic: tracerite<1.1.2
218-
sanic-v0.8: sanic~=0.8.0
219-
sanic-v20: sanic~=20.0
220-
sanic-v24.6: sanic~=24.6.0
221-
sanic-latest: sanic
222-
223199
# === Integrations - Auto-generated ===
224200
# These come from the populate_tox.py script. Eventually we should move all
225201
# integration tests there.

0 commit comments

Comments
 (0)