Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
27 changes: 8 additions & 19 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ jobs:
python: "3.10"
os: windows-latest
tox_env: "py310-pluggymain-pylib-xdist"
xfail: true

- name: "windows-py310-xdist"
python: "3.10"
Expand All @@ -132,6 +133,7 @@ jobs:
python: "3.13"
os: windows-latest
tox_env: "py313"
xfail: true

- name: "windows-py314"
python: "3.14"
Expand Down Expand Up @@ -167,11 +169,13 @@ jobs:
python: "3.10"
os: ubuntu-latest
tox_env: "py310-pluggymain-pylib-xdist"
xfail: true

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

- name: "ubuntu-py310-xdist"
python: "3.10"
Expand All @@ -195,6 +199,7 @@ jobs:
os: ubuntu-latest
tox_env: "py313-pexpect"
use_coverage: true
xfail: true

- name: "ubuntu-py314"
python: "3.14"
Expand All @@ -212,6 +217,7 @@ jobs:
python: "3.10"
os: macos-latest
tox_env: "py310-xdist"
xfail: true

- name: "macos-py312"
python: "3.12"
Expand All @@ -222,6 +228,7 @@ jobs:
python: "3.13"
os: macos-latest
tox_env: "py313-xdist"
xfail: true

- name: "macos-py314"
python: "3.14"
Expand All @@ -240,25 +247,7 @@ jobs:
tox_env: "doctesting"
use_coverage: true

continue-on-error: >-
${{
contains(
fromJSON(
'[
"windows-py310-pluggy",
"windows-py313",
"ubuntu-py310-pluggy",
"ubuntu-py310-freeze",
"ubuntu-py313",
"macos-py310",
"macos-py313"
]'
),
matrix.name
)
&& true
|| false
}}
continue-on-error: ${{ matrix.xfail && true || false }}

steps:
- uses: actions/checkout@v5
Expand Down
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.12.12"
rev: "v0.13.0"
hooks:
- id: ruff
args: ["--fix"]
Expand All @@ -12,7 +12,7 @@ repos:
- id: end-of-file-fixer
- id: check-yaml
- repo: https://github.com/woodruffw/zizmor-pre-commit
rev: v1.12.1
rev: v1.13.0
hooks:
- id: zizmor
- repo: https://github.com/adamchainz/blacken-docs
Expand All @@ -32,7 +32,7 @@ repos:
hooks:
- id: python-use-type-annotations
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.17.1
rev: v1.18.1
hooks:
- id: mypy
files: ^(src/|testing/|scripts/)
Expand Down
1 change: 1 addition & 0 deletions doc/en/example/.ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ignore = ["RUF059"]
2 changes: 1 addition & 1 deletion src/_pytest/_code/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def getstatementrange(self, lineno: int) -> tuple[int, int]:
which containing the given lineno."""
if not (0 <= lineno < len(self)):
raise IndexError("lineno out of range")
ast, start, end = getstatementrange_ast(lineno, self)
_ast, start, end = getstatementrange_ast(lineno, self)
return start, end

def deindent(self) -> Source:
Expand Down
2 changes: 1 addition & 1 deletion src/_pytest/_py/path.py
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ def new(self, **kw):
if not kw:
obj.strpath = self.strpath
return obj
drive, dirname, basename, purebasename, ext = self._getbyspec(
drive, dirname, _basename, purebasename, ext = self._getbyspec(
"drive,dirname,basename,purebasename,ext"
)
if "basename" in kw:
Expand Down
6 changes: 3 additions & 3 deletions src/_pytest/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1217,7 +1217,7 @@ def pytest_load_initial_conftests(self, early_config: Config) -> None:
# early_config.args it not set yet. But we need it for
# discovering the initial conftests. So "pre-run" the logic here.
# It will be done for real in `parse()`.
args, args_source = early_config._decide_args(
args, _args_source = early_config._decide_args(
args=early_config.known_args_namespace.file_or_dir,
pyargs=early_config.known_args_namespace.pyargs,
testpaths=early_config.getini("testpaths"),
Expand Down Expand Up @@ -1273,7 +1273,7 @@ def _consider_importhook(self, args: Sequence[str]) -> None:
and find all the installed plugins to mark them for rewriting
by the importhook.
"""
ns, unknown_args = self._parser.parse_known_and_unknown_args(args)
ns, _unknown_args = self._parser.parse_known_and_unknown_args(args)
mode = getattr(ns, "assertmode", "plain")

disable_autoload = getattr(ns, "disable_plugin_autoload", False) or bool(
Expand Down Expand Up @@ -1630,7 +1630,7 @@ def _getini_unknown_type(self, name: str, type: str, value: object):

def _getini(self, name: str):
try:
description, type, default = self._parser._inidict[name]
_description, type, default = self._parser._inidict[name]
except KeyError as e:
raise ValueError(f"unknown configuration value: {name!r}") from e
override_value = self._get_override_ini_value(name)
Expand Down
2 changes: 1 addition & 1 deletion src/_pytest/helpconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ def showhelp(config: Config) -> None:
indent_len = 24 # based on argparse's max_help_position=24
indent = " " * indent_len
for name in config._parser._ininames:
help, type, default = config._parser._inidict[name]
help, type, _default = config._parser._inidict[name]
if type is None:
type = "string"
if help is None:
Expand Down
2 changes: 1 addition & 1 deletion src/_pytest/mark/structures.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def get_empty_parameterset_mark(

argslisting = ", ".join(argnames)

fs, lineno = getfslineno(func)
_fs, lineno = getfslineno(func)
reason = f"got empty parameter set for ({argslisting})"
requested_mark = config.getini(EMPTY_PARAMETERSET_OPTION)
if requested_mark in ("", None, "skip"):
Expand Down
6 changes: 3 additions & 3 deletions src/_pytest/raises.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ def _parse_exc(
issubclass(origin_exc, BaseExceptionGroup)
and exc_type in (BaseException, Any)
):
if not isinstance(exc, Exception):
if not issubclass(origin_exc, ExceptionGroup):
self.is_baseexception = True
return cast(type[BaseExcT_1], origin_exc)
else:
Expand All @@ -465,9 +465,9 @@ def _parse_exc(
)
# unclear if the Type/ValueError distinction is even helpful here
msg = f"expected exception must be {expected}, not "
if isinstance(exc, type):
if isinstance(exc, type): # type: ignore[unreachable]
Copy link
Member

Choose a reason for hiding this comment

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

Why not change the type in the method signature and rely on these to perform type narrowing?

Copy link
Member

Choose a reason for hiding this comment

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

I tried to play with it but couldn't get it right TBH.

Copy link
Member

Choose a reason for hiding this comment

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

the method is not supposed to accept these types, these error messages are explicitly for if a user is not using type checking and sending invalid types into the method.

raise ValueError(msg + f"{exc.__name__!r}")
if isinstance(exc, BaseException):
if isinstance(exc, BaseException): # type: ignore[unreachable]
raise TypeError(msg + f"an exception instance ({type(exc).__name__})")
raise TypeError(msg + repr(type(exc).__name__))

Expand Down
2 changes: 1 addition & 1 deletion src/_pytest/reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ def head_line(self) -> str | None:
even in patch releases.
"""
if self.location is not None:
fspath, lineno, domain = self.location
_fspath, _lineno, domain = self.location
return domain
return None

Expand Down
3 changes: 2 additions & 1 deletion testing/_py/test_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
from unittest import mock
import warnings

from py import error
from py.path import local

from py import error
Copy link
Member

Choose a reason for hiding this comment

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

This doesn't seem right. Why does ruff want inverse sort inhere?

Copy link
Member

Choose a reason for hiding this comment

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

No idea TBH 🤷‍♂️

I don't care too much as long as it is consistent in different machines/computers.


import pytest


Expand Down
5 changes: 2 additions & 3 deletions testing/acceptance_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -644,18 +644,17 @@ def test_invoke_with_invalid_type(self) -> None:
):
pytest.main("-h") # type: ignore[arg-type]

def test_invoke_with_path(self, pytester: Pytester, capsys) -> None:
def test_invoke_with_path(self, pytester: Pytester) -> None:
retcode = pytest.main([str(pytester.path)])
assert retcode == ExitCode.NO_TESTS_COLLECTED
out, err = capsys.readouterr()

def test_invoke_plugin_api(self, capsys) -> None:
class MyPlugin:
def pytest_addoption(self, parser):
parser.addoption("--myopt")

pytest.main(["-h"], plugins=[MyPlugin()])
out, err = capsys.readouterr()
out, _err = capsys.readouterr()
assert "--myopt" in out

def test_pyargs_importerror(self, pytester: Pytester, monkeypatch) -> None:
Expand Down
4 changes: 2 additions & 2 deletions testing/code/test_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ def test_unicode_handling() -> None:
value = "ąć".encode()

def f() -> None:
raise Exception(value)
raise ValueError(value)

excinfo = pytest.raises(Exception, f)
excinfo = pytest.raises(ValueError, f)
str(excinfo)


Expand Down
2 changes: 1 addition & 1 deletion testing/code/test_excinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ def do_stuff() -> None:
def reraise_me() -> None:
import sys

exc, val, tb = sys.exc_info()
_exc, val, tb = sys.exc_info()
assert val is not None
raise val.with_traceback(tb)

Expand Down
4 changes: 2 additions & 2 deletions testing/code/test_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ def getstatement(lineno: int, source) -> Source:
from _pytest._code.source import getstatementrange_ast

src = Source(source)
ast, start, end = getstatementrange_ast(lineno, src)
_ast, start, end = getstatementrange_ast(lineno, src)
return src[start:end]


Expand All @@ -418,7 +418,7 @@ def test_comment_and_no_newline_at_end() -> None:
"# vim: filetype=pyopencl:fdm=marker",
]
)
ast, start, end = getstatementrange_ast(1, source)
_ast, _start, end = getstatementrange_ast(1, source)
assert end == 2


Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# mypy: allow-untyped-defs
from __future__ import annotations

from _pytest.fixtures import FixtureLookupError
import pytest


@pytest.fixture
def arg2(request):
pytest.raises(Exception, request.getfixturevalue, "arg1")
with pytest.raises(FixtureLookupError):
request.getfixturevalue("arg1")
6 changes: 3 additions & 3 deletions testing/python/collect.py
Original file line number Diff line number Diff line change
Expand Up @@ -1273,10 +1273,10 @@ def test_bar(self):
)
classcol = pytester.collect_by_name(modcol, "TestClass")
assert isinstance(classcol, Class)
path, lineno, msg = classcol.reportinfo()
_path, _lineno, _msg = classcol.reportinfo()
func = next(iter(classcol.collect()))
assert isinstance(func, Function)
path, lineno, msg = func.reportinfo()
_path, _lineno, _msg = func.reportinfo()


def test_customized_python_discovery(pytester: Pytester) -> None:
Expand Down Expand Up @@ -1489,7 +1489,7 @@ def test_package_collection_init_given_as_argument(pytester: Pytester) -> None:
Module, not the entire package.
"""
p = pytester.copy_example("collect/package_init_given_as_arg")
items, hookrecorder = pytester.inline_genitems(p / "pkg" / "__init__.py")
items, _hookrecorder = pytester.inline_genitems(p / "pkg" / "__init__.py")
assert len(items) == 1
assert items[0].name == "test_init"

Expand Down
2 changes: 1 addition & 1 deletion testing/python/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -1150,7 +1150,7 @@ def test_session_scoped_unavailable_attributes(self, session_request, name):

class TestRequestMarking:
def test_applymarker(self, pytester: Pytester) -> None:
item1, item2 = pytester.getitems(
item1, _item2 = pytester.getitems(
"""
import pytest

Expand Down
4 changes: 2 additions & 2 deletions testing/python/integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ def wrap(f):
def wrapped_func(x, y, z):
pass

fs, lineno = getfslineno(wrapped_func)
fs2, lineno2 = getfslineno(wrap)
_fs, lineno = getfslineno(wrapped_func)
_fs2, lineno2 = getfslineno(wrap)
assert lineno > lineno2, "getfslineno does not unwrap correctly"


Expand Down
2 changes: 1 addition & 1 deletion testing/python/metafunc.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def func(x, y):
with pytest.raises(pytest.Collector.CollectError):
metafunc.parametrize("y", [5, 6])

with pytest.raises(TypeError, match="^ids must be a callable or an iterable$"):
with pytest.raises(TypeError, match=r"^ids must be a callable or an iterable$"):
metafunc.parametrize("y", [5, 6], ids=42) # type: ignore[arg-type]

def test_parametrize_error_iterator(self) -> None:
Expand Down
10 changes: 10 additions & 0 deletions testing/python/raises_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -1325,6 +1325,16 @@ def test_annotated_group() -> None:
with RaisesExc(BaseExceptionGroup[BaseException]):
raise BaseExceptionGroup("", [KeyboardInterrupt()])

# assure AbstractRaises.is_baseexception is set properly
assert (
RaisesGroup(ExceptionGroup[Exception]).expected_type()
== "ExceptionGroup(ExceptionGroup)"
)
assert (
RaisesGroup(BaseExceptionGroup[BaseException]).expected_type()
== "BaseExceptionGroup(BaseExceptionGroup)"
)


def test_tuples() -> None:
# raises has historically supported one of several exceptions being raised
Expand Down
Loading
Loading