[`pylint`] Mark `PLC0207` fixes as unsafe when `*args` unpacking is present (#19679)

## Summary

Fixes #19660
This commit is contained in:
Dan Parizher 2025-08-06 14:19:49 -04:00 committed by GitHub
parent ec5660d786
commit 745742e414
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 59 additions and 7 deletions

View File

@ -182,3 +182,13 @@ kwargs_with_maxsplit = {"maxsplit": 1}
"1,2,3".split(",", **kwargs_with_maxsplit)[0] # TODO: false positive
kwargs_with_maxsplit = {"sep": ",", "maxsplit": 1}
"1,2,3".split(**kwargs_with_maxsplit)[0] # TODO: false positive
## Test unpacked list literal args (starred expressions)
# Errors
"1,2,3".split(",", *[-1])[0]
## Test unpacked list variable args
# Errors
args_list = [-1]
"1,2,3".split(",", *args_list)[0]

View File

@ -38,8 +38,8 @@ use crate::{AlwaysFixableViolation, Applicability, Edit, Fix};
/// ```
///
/// ## Fix Safety
/// This rule's fix is marked as unsafe for `split()`/`rsplit()` calls that contain `**kwargs`, as
/// adding a `maxsplit` keyword to such a call may lead to a duplicate keyword argument error.
/// This rule's fix is marked as unsafe for `split()`/`rsplit()` calls that contain `*args` or `**kwargs` arguments, as
/// adding a `maxsplit` argument to such a call may lead to duplicated arguments.
#[derive(ViolationMetadata)]
pub(crate) struct MissingMaxsplitArg {
actual_split_type: String,
@ -201,8 +201,9 @@ pub(crate) fn missing_maxsplit_arg(checker: &Checker, value: &Expr, slice: &Expr
diagnostic.set_fix(Fix::applicable_edits(
maxsplit_argument_edit,
split_type_edit,
// If keyword.arg is `None` (i.e. if the function call contains `**kwargs`), mark the fix as unsafe
if arguments
// Mark the fix as unsafe, if there are `*args` or `**kwargs`
if arguments.args.iter().any(Expr::is_starred_expr)
|| arguments
.keywords
.iter()
.any(|keyword| keyword.arg.is_none())

View File

@ -676,6 +676,7 @@ missing_maxsplit_arg.py:182:1: PLC0207 [*] Replace with `split(..., maxsplit=1)`
182 |+"1,2,3".split(",", maxsplit=1, **kwargs_with_maxsplit)[0] # TODO: false positive
183 183 | kwargs_with_maxsplit = {"sep": ",", "maxsplit": 1}
184 184 | "1,2,3".split(**kwargs_with_maxsplit)[0] # TODO: false positive
185 185 |
missing_maxsplit_arg.py:184:1: PLC0207 [*] Replace with `split(..., maxsplit=1)`.
|
@ -692,3 +693,43 @@ missing_maxsplit_arg.py:184:1: PLC0207 [*] Replace with `split(..., maxsplit=1)`
183 183 | kwargs_with_maxsplit = {"sep": ",", "maxsplit": 1}
184 |-"1,2,3".split(**kwargs_with_maxsplit)[0] # TODO: false positive
184 |+"1,2,3".split(maxsplit=1, **kwargs_with_maxsplit)[0] # TODO: false positive
185 185 |
186 186 |
187 187 | ## Test unpacked list literal args (starred expressions)
missing_maxsplit_arg.py:189:1: PLC0207 [*] Replace with `split(..., maxsplit=1)`.
|
187 | ## Test unpacked list literal args (starred expressions)
188 | # Errors
189 | "1,2,3".split(",", *[-1])[0]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLC0207
190 |
191 | ## Test unpacked list variable args
|
= help: Pass `maxsplit=1` into `str.split()`
Unsafe fix
186 186 |
187 187 | ## Test unpacked list literal args (starred expressions)
188 188 | # Errors
189 |-"1,2,3".split(",", *[-1])[0]
189 |+"1,2,3".split(",", *[-1], maxsplit=1)[0]
190 190 |
191 191 | ## Test unpacked list variable args
192 192 | # Errors
missing_maxsplit_arg.py:194:1: PLC0207 [*] Replace with `split(..., maxsplit=1)`.
|
192 | # Errors
193 | args_list = [-1]
194 | "1,2,3".split(",", *args_list)[0]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PLC0207
|
= help: Pass `maxsplit=1` into `str.split()`
Unsafe fix
191 191 | ## Test unpacked list variable args
192 192 | # Errors
193 193 | args_list = [-1]
194 |-"1,2,3".split(",", *args_list)[0]
194 |+"1,2,3".split(",", *args_list, maxsplit=1)[0]