Skip to content

Conversation

@bluetech
Copy link
Member

Looks like the new ruff errors are like this one:

RUF059 Unpacked variable `a` is never used
   --> doc/en/example/assertion/failure_demo.py:182:9
    |
180 |         items = [1, 2, 3]
181 |         print(f"items is {items!r}")
182 |         a, b = items.pop()
    |         ^
183 |
184 |     def test_some_error(self):
    |
help: Prefix it with an underscore or any other dummy variable pattern

I find this a bit annoying, wouldn't feel bad about disabling this one, though it might potentially catch a real problem.

@nicoddemus
Copy link
Member

I like it, after experiencing it in Rust. I have fixed that in execnet and pytest-xdist. I would vote to keep it.

If nobody strongly opposes keeping it, I will fix this later.

@Pierre-Sassoulas
Copy link
Member

We can also enable unused-variable /unused-argument from pylint if we do

@nicoddemus nicoddemus force-pushed the pre-commit-ci-update-config branch from acfd898 to 7a0aa3d Compare September 16, 2025 13:26
@nicoddemus
Copy link
Member

Fixed the linting errors, but I'm not sure about these mypy failures:

src/_pytest/raises.py:455: error: Subclass of "GenericAlias" and "Exception" cannot exist: have distinct disjoint bases  [unreachable]
src/_pytest/raises.py:468: error: Subclass of "GenericAlias" and "type" cannot exist: have distinct disjoint bases  [unreachable]
src/_pytest/raises.py:470: error: Subclass of "GenericAlias" and "BaseException" cannot exist: have distinct disjoint bases  [unreachable]

@bluetech
Copy link
Member

bluetech commented Sep 16, 2025

At least the first error (line 455) seems correct to me. From my reading of the code the else branch of this if can provably never happen, so is either not needed or confused. I haven't checked the other errors but probably related.

Maybe @jakkdl is willing to take a look? If not, I can look into it more.

@jakkdl
Copy link
Member

jakkdl commented Sep 19, 2025

L468 and L470 are correct errors and need to be type: ignored - they're for error messages when the user passes invalid types.

L455 does have coverage issues, so there's a bug there! Possibly misjuggling of exc/orig_exc/exc_type
https://app.codecov.io/gh/pytest-dev/pytest/blob/main/src%2F_pytest%2Fraises.py#L455

edit: I think it should be orig_exc, but should write a test for it to make sure it works properly.

@jakkdl
Copy link
Member

jakkdl commented Sep 19, 2025

It seems like I don't have push permissions to the branch this PR is based on, so here's the patch:

From 1b67c4bdcb1af8b96a529e837c9922b38c231f61 Mon Sep 17 00:00:00 2001
From: jakkdl <[email protected]>
Date: Fri, 19 Sep 2025 17:16:07 +0200
Subject: [PATCH] fix type failures in raises.py and add tests

---
 src/_pytest/raises.py          |  6 +++---
 testing/python/raises_group.py | 10 ++++++++++
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/src/_pytest/raises.py b/src/_pytest/raises.py
index 9066779a8..2a53a5a14 100644
--- a/src/_pytest/raises.py
+++ b/src/_pytest/raises.py
@@ -452,7 +452,7 @@ class AbstractRaises(ABC, Generic[BaseExcT_co]):
                 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:
@@ -465,9 +465,9 @@ class AbstractRaises(ABC, Generic[BaseExcT_co]):
                 )
         # 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]
             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__))
 
diff --git a/testing/python/raises_group.py b/testing/python/raises_group.py
index 6b9f98201..e911ba52c 100644
--- a/testing/python/raises_group.py
+++ b/testing/python/raises_group.py
@@ -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
-- 
2.51.0

@nicoddemus nicoddemus force-pushed the pre-commit-ci-update-config branch 4 times, most recently from 34d79ce to b863ca9 Compare September 20, 2025 11:14
@nicoddemus
Copy link
Member

Thanks @jakkdl, applied! Also rebased the branch.

@nicoddemus nicoddemus force-pushed the pre-commit-ci-update-config branch from b863ca9 to bd2cb21 Compare September 20, 2025 11:16
Copy link
Member

@jakkdl jakkdl left a comment

Choose a reason for hiding this comment

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

just some small nitpicks, looks good!

@nicoddemus nicoddemus force-pushed the pre-commit-ci-update-config branch 3 times, most recently from 38eb0a6 to 96cf552 Compare September 20, 2025 13:27
@nicoddemus
Copy link
Member

nicoddemus commented Sep 20, 2025

zizmor was failing with:

help[obfuscation]: obfuscated usage of GitHub Actions features
   --> .github/workflows/test.yml:246:11
    |
246 | /           fromJSON(
247 | |             '[
248 | |               "windows-py310-pluggy",
249 | |               "windows-py313",
...   |
255 | |             ]'
256 | |           ),
    | |___________^ can be reduced to a constant
    |
    = note: audit confidence → High
    = note: this finding has an auto-fix

24 findings (23 suppressed, 1 fixable): 0 unknown, 0 informational, 1 low, 0 medium, 0 high

I tried its autofix feature and it changed to:

diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 41a0773e1..fe930b8d8 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -243,17 +243,7 @@ jobs:
     continue-on-error: >-
       ${{
         contains(
-          fromJSON(
-            '[
-              "windows-py310-pluggy",
-              "windows-py313",
-              "ubuntu-py310-pluggy",
-              "ubuntu-py310-freeze",
-              "ubuntu-py313",
-              "macos-py310",
-              "macos-py313"
-            ]'
-          ),
+          Array,
           matrix.name
         )
         && true

Which is clearly incorrect.

I then tried using:

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

But this also fails with:

(Line: 243, Col: 24): Unexpected symbol: '['. Located at position 10 within expression: contains(['windows-py310-pluggy','windows-py313','ubuntu-py310-pluggy','ubuntu-py310-freeze','ubuntu-py313','macos-py310','macos-py313'], matrix.name ) && true || false, (Line: 243, Col: 24): Unexpected value '${{ contains(['windows-py310-pluggy','windows-py313','ubuntu-py310-pluggy','ubuntu-py310-freeze','ubuntu-py313','macos-py310','macos-py313'], matrix.name ) && true || false }}'

I went with an ignore comment, but suggestions are welcome.

@nicoddemus
Copy link
Member

Actually it seems the comment was also not welcome...

@webknjaz any suggestions?

@webknjaz
Copy link
Member

@nicoddemus it must be wrapped with fromJSON because GHA doesn't allow the [] syntax. In fact, this is what they explicitly demo in the docs.

As for zizmor, you can add an ignore for that rule I suppose, if you insist on using this approach. I believe @woodruffw would advise the same.


Though, the docs also demonstrate an example of adding an additional factor to the matrix and just using that in the conditional. This would be cleaner and easier to follow in general. I've started calling that factor xfail, in my workflows and it's rather handy to have it: https://github.com/cherrypy/cheroot/blob/ac9b6e5543278439312404aa7a0d83f6b5f80981/.github/workflows/ci-cd.yml#L758-L762. Then, the conditional can be more generic: https://github.com/tox-dev/workflow/blob/208490c75f7f6b81e2698cc959f24d264c462d57/.github/workflows/reusable-tox.yml#L193-L202

Having that flag keeps data bundled in one place (the matrix definition) while the logic is disconnected and acts on that data.

use_coverage: true

continue-on-error: >-
continue-on-error: | # zizmor: ignore[obfuscation]
Copy link
Member

Choose a reason for hiding this comment

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

# 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.

@pytest.fixture
def arg2(request):
pytest.raises(Exception, request.getfixturevalue, "arg1")
pytest.raises(Exception, request.getfixturevalue, "arg1") # noqa: B017
Copy link
Member

Choose a reason for hiding this comment

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

For linters that don't have human-readable rule identifiers, it'd be a good idea to add a code comment explaining what the suppressions hide and when they can be dropped.

Copy link
Member

Choose a reason for hiding this comment

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

Changed to the concrete exception (FixtureLookupError) and removed noqa. 👍

nicoddemus added a commit that referenced this pull request Sep 20, 2025
…alue

zizmor complains that the previous approach was considered "obfuscation".

Using a matrix value instead as suggested in #13733 (comment).
@nicoddemus nicoddemus force-pushed the pre-commit-ci-update-config branch from 96cf552 to 05324ab Compare September 20, 2025 13:53
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.

nicoddemus added a commit that referenced this pull request Sep 20, 2025
…alue

zizmor complains that the previous approach was considered "obfuscation".

Using a matrix value instead as suggested in #13733 (comment).
@nicoddemus nicoddemus force-pushed the pre-commit-ci-update-config branch from 8963f13 to b96a0b7 Compare September 20, 2025 15:20
@woodruffw
Copy link

Hmm, that constexpr evaluation is definitely a bug on our part. Thanks for the ping!

(Array is the correct string evaluation of an arbitrary JSON array value, but that's not correct in a subexpression context like this one.)

pre-commit-ci bot and others added 4 commits September 21, 2025 13:47
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.12.12 → v0.13.0](astral-sh/ruff-pre-commit@v0.12.12...v0.13.0)
- [github.com/woodruffw/zizmor-pre-commit: v1.12.1 → v1.13.0](zizmorcore/zizmor-pre-commit@v1.12.1...v1.13.0)
- [github.com/pre-commit/mirrors-mypy: v1.17.1 → v1.18.1](pre-commit/mirrors-mypy@v1.17.1...v1.18.1)
Fix typing failures after mypy 1.18 update.
…alue

zizmor complains that the previous approach was considered "obfuscation".

Using a matrix value instead as suggested in #13733 (comment).
@nicoddemus nicoddemus force-pushed the pre-commit-ci-update-config branch from b96a0b7 to b290db3 Compare September 21, 2025 16:47
@nicoddemus nicoddemus merged commit b8e93b9 into main Sep 21, 2025
33 checks passed
@nicoddemus nicoddemus deleted the pre-commit-ci-update-config branch September 21, 2025 17:56
@woodruffw
Copy link

Just following up: I've fixed that consteval bug on zizmor's side in the release that's coming out now, please let me know if you hit any other problems there!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants