Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix pytest-parametrize-names-wrong-type (PT006) to edit both argnames and argvalues if both of them are single-element tuples/lists #14699

Merged
merged 23 commits into from
Dec 9, 2024

Conversation

harupy
Copy link
Contributor

@harupy harupy commented Dec 1, 2024

Summary

Close #11243. Fix pytest-parametrize-names-wrong-type (PT006) to edit both argnames and argvalues if both of them are single-element tuples/lists.

# Before fix
@pytest.mark.parametrize(("x",), [(1,), (2,)])
def test_foo(x):
    ...

# After fix:
@pytest.mark.parametrize("x", [1, 2])
def test_foo(x):
    ...

Test Plan

New test cases

Copy link
Contributor

github-actions bot commented Dec 2, 2024

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

@charliermarsh
Copy link
Member

I'm sure you're right, but can you expand on why that's a problem? (Should we not be raising a diagnostic at all?)

@harupy
Copy link
Contributor Author

harupy commented Dec 2, 2024

@charliermarsh Thanks for the comment!

Should we not be raising a diagnostic at all?

This is another option.

@harupy
Copy link
Contributor Author

harupy commented Dec 2, 2024

I just found #11243. Should we unpack each item in argvalues as a fix?

@charliermarsh
Copy link
Member

In this case, would this be correct?

@pytest.mark.parametrize("x,", [(1,), (2,)])

With the comma inside the string? I don't know enough about pytest.

@harupy
Copy link
Contributor Author

harupy commented Dec 2, 2024

@charliermarsh Let me check.


import pytest


@pytest.mark.parametrize("x,", [(1,), (2,)])
def test_foo(x):
    assert isinstance(x, int)
_____________________________________________________________________________________________________ test_foo[x0] ______________________________________________________________________________________________________

x = (1,)

    @pytest.mark.parametrize("x,", [(1,), (2,)])
    def test_foo(x):
>       assert isinstance(x, int)
E       assert False
E        +  where False = isinstance((1,), int)

a.py:6: AssertionError
_____________________________________________________________________________________________________ test_foo[x1] ______________________________________________________________________________________________________

x = (2,)

    @pytest.mark.parametrize("x,", [(1,), (2,)])
    def test_foo(x):
>       assert isinstance(x, int)
E       assert False
E        +  where False = isinstance((2,), int)

a.py:6: AssertionError

@pytest.mark.parametrize("x,", [(1,), (2,)]) is equivalent to @pytest.mark.parametrize("x", [(1,), (2,)]).

@MichaReiser
Copy link
Member

Source of the relevant pytest code

https://github.com/pytest-dev/pytest/blob/9d4f36d87dae9a968fb527e2cb87e8a507b0beb3/src/_pytest/mark/structures.py#L124-L135

According to the rule. How should a user rewrite your example?

@pytest.mark.parametrize(("x",), [(1,), (2,)])
                       # ^^^^^^
def test_foo(x):
    ...

@harupy
Copy link
Contributor Author

harupy commented Dec 3, 2024

@MichaReiser

@pytest.mark.parametrize(("x",), [(1,), (2,)])
def test_foo(x):
    ...

should be rewritten to:

@pytest.mark.parametrize("x", [1, 2])
def test_foo(x):
    ...

# I'd prefer this style because I don't need to wonder what x is (tuple vs. int)

Both argnames and items in argvalues need to be fixed. PT006 only fixes argnames now.

(I implemented a fix to fix argvalues as well but didn't push it yet).

@harupy harupy changed the title Fix pytest-parametrize-names-wrong-type (PT006) not to suggest a fix if both argnames and argvalues are single-element sequences Fix pytest-parametrize-names-wrong-type (PT006) to edit argnames and argvalues as a fix Dec 3, 2024
@harupy harupy changed the title Fix pytest-parametrize-names-wrong-type (PT006) to edit argnames and argvalues as a fix Fix pytest-parametrize-names-wrong-type (PT006) to edit both argnames and argvalues if both of them are single-element tuples/lists Dec 3, 2024
@MichaReiser
Copy link
Member

(I implemented a fix to fix argvalues as well but didn't push it yet).

That sounds great. I'll have a look when you push the change

@MichaReiser MichaReiser added bug Something isn't working fixes Related to suggested fixes for violations labels Dec 4, 2024
@harupy harupy requested a review from MichaReiser December 4, 2024 11:10
// def test_foo(x):
// assert isinstance(x, int) # fails because `x` is a tuple, not an int
// ```
unpack_single_element_items(checker, argvalues),
Copy link
Contributor Author

@harupy harupy Dec 4, 2024

Choose a reason for hiding this comment

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

Should I add a test to ensure this doesn't conflict with PT007 which may also edit argvalues?

Copy link
Member

Choose a reason for hiding this comment

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

This sounds like a great idea if we're concerned about whether the rules play nicely together.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@MichaReiser Manually confirmed PT006 and PT007 don't conflicts:

> cargo run -p ruff -- check --no-cache --select PT007,PT006 a.py --unsafe-fixes --fix
--- a.py
+++ a.py
@@ -1,6 +1,6 @@
 import pytest
 
 
-@pytest.mark.parametrize(("param",), [[1], [2], [3]])
+@pytest.mark.parametrize("param", [1, 2, 3])
 def test_foo(param):
     ...

Would fix 1 error.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a test case for this.

// def test_foo(x):
// assert isinstance(x, int) # fails because `x` is a tuple, not an int
// ```
unpack_single_element_items(checker, argvalues),
Copy link
Member

Choose a reason for hiding this comment

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

This sounds like a great idea if we're concerned about whether the rules play nicely together.

@harupy harupy requested a review from MichaReiser December 5, 2024 14:14
@harupy harupy requested a review from MichaReiser December 7, 2024 03:19
Copy link
Member

@MichaReiser MichaReiser left a comment

Choose a reason for hiding this comment

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

This is great. Thank you for following it thourgh

@MichaReiser MichaReiser merged commit 3d9ac53 into astral-sh:main Dec 9, 2024
21 checks passed
@harupy harupy deleted the fix-PT006-single-element branch December 9, 2024 12:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working fixes Related to suggested fixes for violations
Projects
None yet
Development

Successfully merging this pull request may close these issues.

PT006 breaks test by removing tuple from parametrize
3 participants