Fix pytest.mark.parametrize rules to check calls instead of decorators#14515
Fix pytest.mark.parametrize rules to check calls instead of decorators#14515MichaReiser merged 10 commits intoastral-sh:mainfrom
pytest.mark.parametrize rules to check calls instead of decorators#14515Conversation
|
The upstream rule also checks calls: def visit_Call(self, node: ast.Call) -> None:
if is_parametrize_call(node):
self._check_parametrize_call(node) |
crates/ruff_linter/src/rules/flake8_pytest_style/rules/parametrize.rs
Outdated
Show resolved
Hide resolved
|
| code | total | + violation | - violation | + fix | - fix |
|---|---|---|---|---|---|
| PT006 | 49 | 49 | 0 | 0 | 0 |
| PT007 | 1 | 1 | 0 | 0 | 0 |
fda25ed to
3f385b6
Compare
crates/ruff_linter/src/rules/flake8_pytest_style/rules/parametrize.rs
Outdated
Show resolved
Hide resolved
…rize.rs Co-authored-by: Micha Reiser <micha@reiser.io>
| } | ||
| } | ||
| pub(crate) fn parametrize(checker: &mut Checker, call: &ExprCall) { | ||
| if !is_pytest_parametrize(call, checker.semantic()) { |
There was a problem hiding this comment.
Unrelated to this PR, but PT rules don't have a seen_module guard. Shoud we add it?
There was a problem hiding this comment.
Sounds like a nice good first issue.
| if checker.enabled(Rule::PytestParametrizeNamesWrongType) { | ||
| if let Some(names) = call.arguments.find_argument("argnames", 0) { | ||
| check_names(checker, call, names); | ||
| } | ||
| } | ||
| if checker.enabled(Rule::PytestParametrizeValuesWrongType) { | ||
| let names = call.arguments.find_argument("argnames", 0); | ||
| let values = call.arguments.find_argument("argvalues", 1); | ||
| if let (Some(names), Some(values)) = (names, values) { | ||
| check_values(checker, names, values); | ||
| } | ||
| } | ||
| if checker.enabled(Rule::PytestDuplicateParametrizeTestCases) { | ||
| if let Some(values) = call.arguments.find_argument("argvalues", 1) { | ||
| check_duplicates(checker, values); |
There was a problem hiding this comment.
This aligns with the upstream implementation:
def extract_parametrize_call_args(node: ast.Call) -> Optional[ParametrizeArgs]:
"""Extracts argnames, argvalues and ids from a parametrize call."""
args = get_simple_call_args(node)
names_arg = args.get_argument('argnames', 0)
if names_arg is None:
return None
values_arg = args.get_argument('argvalues', 1)
ids_arg = args.get_argument('ids')
return ParametrizeArgs(names_arg, values_arg, ids_arg)|
Thanks for the how-to-guide and API reference. That helps a lot with building the required context to review the rule. I really appreciate it :) |
MichaReiser
left a comment
There was a problem hiding this comment.
This is great. Did you already look through the ecosystem changes? I can do it, if you haven't.
I think we should gate this change behind preview mode because I consider this a "significant increase in scope" and we should only make such changes in minor releases.
|
@MichaReiser Thanks for the comment. This PR has the two changes. Do we want to gate both of them?
|
|
Oh right. Making 1. preview-only for now seems more important to me than 2. We can have a look at the ecosystem change to understand how much impact 2 has but I think it's fine to not gate 2. |
|
For Airflow, 2 has more impacts (more changes) than 1. |
|
Right, I should have taken a closer look at the ecosystem results. We should then probably make 2 a preview style change as well. It's a bit annoying codewise but feels most in line with our versioning policy |
2f3d825 to
509c5c6
Compare
Summary
Currently, rules for
pytest.mark.parametrize(e.g./pytest-parametrize-names-wrong-type (PT006)) only check decorators, butpytest.mark.parametrizecan appear as a function call as show below.Test Plan
Existing tests and a new test case to ensure the fix is valid.