Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions .github/workflows/test-uv.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
name: test uv
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would all-around be better if we could integrate this into the main workflow file, just controlling it with a matrix option (environment variables).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I got it correctly in the main test workflow.


on:
push:
branches:
- main
- "[0-9]+.[0-9]+.x"
- "test-me-*"
tags:
- "[0-9]+.[0-9]+.[0-9]+"
- "[0-9]+.[0-9]+.[0-9]+rc[0-9]+"

pull_request:
branches:
- main
- "[0-9]+.[0-9]+.x"
types:
- opened # default
- synchronize # default
- reopened # default
- ready_for_review # used in PRs created from the release workflow

workflow_dispatch: # allows manual triggering of the workflow

env:
PYTEST_ADDOPTS: "--color=yes"

# Cancel running jobs for the same workflow and branch.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

# Set permissions at the job level.
permissions: {}

jobs:
package:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
persist-credentials: false
- name: Build and Check Package
uses: hynek/build-and-inspect-python-package@efb823f52190ad02594531168b7a2d5790e66516

build:
needs: [package]

runs-on: ${{ matrix.os }}
timeout-minutes: 45
permissions:
contents: read

strategy:
fail-fast: false
matrix:
name: [
"windows-py310",

"ubuntu-py310",

"macos-py310",
]

include:
- name: "windows-py310"
python: "3.10"
os: windows-latest
tox_env: "py310"

- name: "ubuntu-py310"
python: "3.10"
os: ubuntu-latest
tox_env: "py310"

- name: "macos-py310"
python: "3.10"
os: macos-latest
tox_env: "py310"
xfail: true

continue-on-error: ${{ matrix.xfail && true || false }}

steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
persist-credentials: false

- name: Download Package
uses: actions/download-artifact@v5
with:
name: Packages
path: dist

- name: Set up Python ${{ matrix.python }}
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python }}
check-latest: true
allow-prereleases: true

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install tox coverage
- name: Test
shell: bash
run: tox -c tox-uv.ini run -e ${{ matrix.tox_env }} --installpkg `find dist/*.tar.gz`

check: # This job does nothing and is only used for the branch protection
if: always()

needs:
- build

runs-on: ubuntu-latest

steps:
- name: Decide whether the needed jobs succeeded or failed
uses: re-actors/alls-green@2765efec08f0fd63e83ad900f5fd75646be69ff6
with:
jobs: ${{ toJSON(needs) }}
20 changes: 10 additions & 10 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,21 +47,21 @@ dynamic = [
]
dependencies = [
"colorama>=0.4; sys_platform=='win32'",
"exceptiongroup>=1; python_version<'3.11'",
"iniconfig>=1.0.1",
"exceptiongroup>=1.1; python_version<'3.11'",
"iniconfig>=2",
"packaging>=22",
"pluggy>=1.5,<2",
"pygments>=2.7.2",
"pygments>=2.14",
"tomli>=1; python_version<'3.11'",
]
optional-dependencies.dev = [
"argcomplete",
"attrs>=19.2",
"hypothesis>=3.56",
"mock",
"requests",
"setuptools",
"xmlschema",
"argcomplete>=3.5",
"attrs>=21",
"hypothesis>=5",
"mock>=5",
"requests>=2.26",
"setuptools>=80",
"xmlschema>=3",
]
Comment on lines 48 to 65
Copy link
Member

@bluetech bluetech Oct 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these changes needed? Is it from testing with lowest-direct?

For the dev deps I don't mind much, perhaps except for attrs and mock which we use for testing pytest integration features so being able to test with older versions is somewhat useful.

But for the runtime dependencies, how did you determine the lower bounds?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's correct, lowest-direct showed that the oldest version it could get were sometimes using obsolete APIs.

My first tries were to slowly bump the versions of the dependencies that were posing problems. Since some of them were a bit less cooperative, I went to check which years the packages had releases around Python 3.10 initial release. So, in the absolute, I would say it's worth revisiting them to ensure I did not miss something.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your method sounds good to me (cc @RonnyPfannschmidt on iniconfig).

Could you add a packaging changelog entry detailing the changes to the lower bounds of exceptiongroup, iniconfig and pygments?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done but I may have been a bit short

urls.Changelog = "https://docs.pytest.org/en/stable/changelog.html"
urls.Contact = "https://docs.pytest.org/en/stable/contact.html"
Expand Down
21 changes: 18 additions & 3 deletions testing/acceptance_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1642,12 +1642,27 @@ def test_fail_call():
result = pytester.runpytest()
assert result.ret == ExitCode.TESTS_FAILED
result.assert_outcomes(failed=1, passed=1, errors=2)

result.stdout.fnmatch_lines(
[
"=* short test summary info =*",
"FAILED test_it.py::test_fail_call - StopIteration: 3",
"ERROR test_it.py::test_fail_setup - StopIteration: 1",
"ERROR test_it.py::test_fail_teardown - StopIteration: 2",
"=* 1 failed, 1 passed, 2 errors in * =*",
]
)

runtime_errors = {
"FAILED test_it.py::test_fail_call - RuntimeError: generator raised StopIteration",
"ERROR test_it.py::test_fail_setup - RuntimeError: generator raised StopIteration",
"ERROR test_it.py::test_fail_teardown - RuntimeError: generator raised StopIte...",
}
got_runtime_errors = runtime_errors.issubset(result.outlines)

stopiteration_errors = {
"FAILED test_it.py::test_fail_call - StopIteration: 3",
"ERROR test_it.py::test_fail_setup - StopIteration: 1",
"ERROR test_it.py::test_fail_teardown - StopIteration: 2",
}

got_stopiteration_errors = stopiteration_errors.issubset(result.outlines)

assert got_runtime_errors or got_stopiteration_errors
28 changes: 28 additions & 0 deletions tox-uv.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[tox]
requires =
tox>=4
tox-uv>=1
isolated_build = True
distshare = {homedir}/.tox/uv-distshare
envlist =
py310

[testenv]
description =
run the tests
under `{basepython}`
uv_resolution = lowest-direct
uv_python_preference = only-managed
commands =
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest {posargs:{env:_PYTEST_TOX_DEFAULT_POSARGS:}} --maxfail=1 --pdb
passenv =
PYTEST_ADDOPTS
TERM
SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PYTEST
CI
setenv =
_PYTEST_TOX_DEFAULT_POSARGS={env:_PYTEST_TOX_POSARGS_DOCTESTING:} {env:_PYTEST_TOX_POSARGS_LSOF:} {env:_PYTEST_TOX_POSARGS_XDIST:} {env:_PYTEST_FILES:}

extras = dev
deps =
{env:_PYTEST_TOX_EXTRA_DEP:}