Add support for top-level quoted annotations in RUF013 (#5235)

## Summary

This PR adds support for autofixing annotations like:

```python
def f(x: "int" = None):
    ...
```

However, we don't yet support nested quotes, like:

```python
def f(x: Union["int", "str"] = None):
    ...
```

Closes #5231.
This commit is contained in:
Charlie Marsh 2023-06-21 10:23:37 -04:00 committed by GitHub
parent 44156f6962
commit 10885d09a1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 288 additions and 158 deletions

View file

@ -18,19 +18,19 @@ def f(arg: object = None):
pass
def f(arg: int = None): # RUF011
def f(arg: int = None): # RUF013
pass
def f(arg: str = None): # RUF011
def f(arg: str = None): # RUF013
pass
def f(arg: typing.List[str] = None): # RUF011
def f(arg: typing.List[str] = None): # RUF013
pass
def f(arg: Tuple[str] = None): # RUF011
def f(arg: Tuple[str] = None): # RUF013
pass
@ -64,15 +64,15 @@ def f(arg: Union[int, str, Any] = None):
pass
def f(arg: Union = None): # RUF011
def f(arg: Union = None): # RUF013
pass
def f(arg: Union[int, str] = None): # RUF011
def f(arg: Union[int, str] = None): # RUF013
pass
def f(arg: typing.Union[int, str] = None): # RUF011
def f(arg: typing.Union[int, str] = None): # RUF013
pass
@ -91,11 +91,11 @@ def f(arg: int | float | str | None = None):
pass
def f(arg: int | float = None): # RUF011
def f(arg: int | float = None): # RUF013
pass
def f(arg: int | float | str | bytes = None): # RUF011
def f(arg: int | float | str | bytes = None): # RUF013
pass
@ -110,11 +110,11 @@ def f(arg: Literal[1, 2, None, 3] = None):
pass
def f(arg: Literal[1, "foo"] = None): # RUF011
def f(arg: Literal[1, "foo"] = None): # RUF013
pass
def f(arg: typing.Literal[1, "foo", True] = None): # RUF011
def f(arg: typing.Literal[1, "foo", True] = None): # RUF013
pass
@ -133,11 +133,11 @@ def f(arg: Annotated[Any, ...] = None):
pass
def f(arg: Annotated[int, ...] = None): # RUF011
def f(arg: Annotated[int, ...] = None): # RUF013
pass
def f(arg: Annotated[Annotated[int | str, ...], ...] = None): # RUF011
def f(arg: Annotated[Annotated[int | str, ...], ...] = None): # RUF013
pass
@ -153,9 +153,9 @@ def f(
def f(
arg1: int = None, # RUF011
arg2: Union[int, float] = None, # RUF011
arg3: Literal[1, 2, 3] = None, # RUF011
arg1: int = None, # RUF013
arg2: Union[int, float] = None, # RUF013
arg3: Literal[1, 2, 3] = None, # RUF013
):
pass
@ -183,20 +183,32 @@ def f(arg: Union[Annotated[int, ...], Annotated[Optional[float], ...]] = None):
pass
def f(arg: Union[Annotated[int, ...], Union[str, bytes]] = None): # RUF011
def f(arg: Union[Annotated[int, ...], Union[str, bytes]] = None): # RUF013
pass
# Quoted
def f(arg: "int" = None):
def f(arg: "int" = None): # RUF013
pass
def f(arg: "str" = None):
def f(arg: "str" = None): # RUF013
pass
def f(arg: "st" "r" = None): # RUF013
pass
def f(arg: "Optional[int]" = None):
pass
def f(arg: Union["int", "str"] = None): # False negative
pass
def f(arg: Union["int", "None"] = None):
pass

View file

@ -4,9 +4,10 @@ use anyhow::Result;
use ruff_text_size::TextRange;
use rustpython_parser::ast::{self, ArgWithDefault, Arguments, Constant, Expr, Operator, Ranged};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::helpers::is_const_none;
use ruff_python_ast::typing::parse_type_annotation;
use ruff_python_semantic::SemanticModel;
use crate::checkers::ast::Checker;
@ -65,14 +66,16 @@ pub struct ImplicitOptional {
conversion_type: ConversionType,
}
impl AlwaysAutofixableViolation for ImplicitOptional {
impl Violation for ImplicitOptional {
const AUTOFIX: AutofixKind = AutofixKind::Sometimes;
#[derive_message_formats]
fn message(&self) -> String {
format!("PEP 484 prohibits implicit `Optional`")
}
fn autofix_title(&self) -> String {
format!("Convert to `{}`", self.conversion_type)
fn autofix_title(&self) -> Option<String> {
Some(format!("Convert to `{}`", self.conversion_type))
}
}
@ -229,7 +232,7 @@ impl<'a> TypingTarget<'a> {
_ => new_target.contains_none(semantic),
}
}
// TODO(charlie): Add support for forward references (quoted annotations).
// TODO(charlie): Add support for nested forward references (e.g., `Union["A", "B"]`).
TypingTarget::ForwardReference => true,
}
}
@ -333,15 +336,42 @@ pub(crate) fn implicit_optional(checker: &mut Checker, arguments: &Arguments) {
let Some(annotation) = &def.annotation else {
continue
};
let Some(expr) = type_hint_explicitly_allows_none(annotation, checker.semantic()) else {
continue;
};
let conversion_type = checker.settings.target_version.into();
let mut diagnostic = Diagnostic::new(ImplicitOptional { conversion_type }, expr.range());
if checker.patch(diagnostic.kind.rule()) {
diagnostic.try_set_fix(|| generate_fix(checker, conversion_type, expr));
if let Expr::Constant(ast::ExprConstant {
range,
value: Constant::Str(value),
..
}) = annotation.as_ref()
{
// Quoted annotation.
if let Ok((annotation, kind)) = parse_type_annotation(value, *range, checker.locator) {
let Some(expr) = type_hint_explicitly_allows_none(&annotation, checker.semantic()) else {
continue;
};
let conversion_type = checker.settings.target_version.into();
let mut diagnostic =
Diagnostic::new(ImplicitOptional { conversion_type }, expr.range());
if checker.patch(diagnostic.kind.rule()) {
if kind.is_simple() {
diagnostic.try_set_fix(|| generate_fix(checker, conversion_type, expr));
}
}
checker.diagnostics.push(diagnostic);
}
} else {
// Unquoted annotation.
let Some(expr) = type_hint_explicitly_allows_none(annotation, checker.semantic()) else {
continue;
};
let conversion_type = checker.settings.target_version.into();
let mut diagnostic =
Diagnostic::new(ImplicitOptional { conversion_type }, expr.range());
if checker.patch(diagnostic.kind.rule()) {
diagnostic.try_set_fix(|| generate_fix(checker, conversion_type, expr));
}
checker.diagnostics.push(diagnostic);
}
checker.diagnostics.push(diagnostic);
}
}

View file

@ -3,7 +3,7 @@ source: crates/ruff/src/rules/ruff/mod.rs
---
RUF013_0.py:21:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
21 | def f(arg: int = None): # RUF011
21 | def f(arg: int = None): # RUF013
| ^^^ RUF013
22 | pass
|
@ -13,15 +13,15 @@ RUF013_0.py:21:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
18 18 | pass
19 19 |
20 20 |
21 |-def f(arg: int = None): # RUF011
21 |+def f(arg: Optional[int] = None): # RUF011
21 |-def f(arg: int = None): # RUF013
21 |+def f(arg: Optional[int] = None): # RUF013
22 22 | pass
23 23 |
24 24 |
RUF013_0.py:25:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
25 | def f(arg: str = None): # RUF011
25 | def f(arg: str = None): # RUF013
| ^^^ RUF013
26 | pass
|
@ -31,15 +31,15 @@ RUF013_0.py:25:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
22 22 | pass
23 23 |
24 24 |
25 |-def f(arg: str = None): # RUF011
25 |+def f(arg: Optional[str] = None): # RUF011
25 |-def f(arg: str = None): # RUF013
25 |+def f(arg: Optional[str] = None): # RUF013
26 26 | pass
27 27 |
28 28 |
RUF013_0.py:29:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
29 | def f(arg: typing.List[str] = None): # RUF011
29 | def f(arg: typing.List[str] = None): # RUF013
| ^^^^^^^^^^^^^^^^ RUF013
30 | pass
|
@ -49,15 +49,15 @@ RUF013_0.py:29:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
26 26 | pass
27 27 |
28 28 |
29 |-def f(arg: typing.List[str] = None): # RUF011
29 |+def f(arg: Optional[typing.List[str]] = None): # RUF011
29 |-def f(arg: typing.List[str] = None): # RUF013
29 |+def f(arg: Optional[typing.List[str]] = None): # RUF013
30 30 | pass
31 31 |
32 32 |
RUF013_0.py:33:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
33 | def f(arg: Tuple[str] = None): # RUF011
33 | def f(arg: Tuple[str] = None): # RUF013
| ^^^^^^^^^^ RUF013
34 | pass
|
@ -67,15 +67,15 @@ RUF013_0.py:33:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
30 30 | pass
31 31 |
32 32 |
33 |-def f(arg: Tuple[str] = None): # RUF011
33 |+def f(arg: Optional[Tuple[str]] = None): # RUF011
33 |-def f(arg: Tuple[str] = None): # RUF013
33 |+def f(arg: Optional[Tuple[str]] = None): # RUF013
34 34 | pass
35 35 |
36 36 |
RUF013_0.py:67:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
67 | def f(arg: Union = None): # RUF011
67 | def f(arg: Union = None): # RUF013
| ^^^^^ RUF013
68 | pass
|
@ -85,15 +85,15 @@ RUF013_0.py:67:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
64 64 | pass
65 65 |
66 66 |
67 |-def f(arg: Union = None): # RUF011
67 |+def f(arg: Optional[Union] = None): # RUF011
67 |-def f(arg: Union = None): # RUF013
67 |+def f(arg: Optional[Union] = None): # RUF013
68 68 | pass
69 69 |
70 70 |
RUF013_0.py:71:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
71 | def f(arg: Union[int, str] = None): # RUF011
71 | def f(arg: Union[int, str] = None): # RUF013
| ^^^^^^^^^^^^^^^ RUF013
72 | pass
|
@ -103,15 +103,15 @@ RUF013_0.py:71:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
68 68 | pass
69 69 |
70 70 |
71 |-def f(arg: Union[int, str] = None): # RUF011
71 |+def f(arg: Optional[Union[int, str]] = None): # RUF011
71 |-def f(arg: Union[int, str] = None): # RUF013
71 |+def f(arg: Optional[Union[int, str]] = None): # RUF013
72 72 | pass
73 73 |
74 74 |
RUF013_0.py:75:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
75 | def f(arg: typing.Union[int, str] = None): # RUF011
75 | def f(arg: typing.Union[int, str] = None): # RUF013
| ^^^^^^^^^^^^^^^^^^^^^^ RUF013
76 | pass
|
@ -121,15 +121,15 @@ RUF013_0.py:75:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
72 72 | pass
73 73 |
74 74 |
75 |-def f(arg: typing.Union[int, str] = None): # RUF011
75 |+def f(arg: Optional[typing.Union[int, str]] = None): # RUF011
75 |-def f(arg: typing.Union[int, str] = None): # RUF013
75 |+def f(arg: Optional[typing.Union[int, str]] = None): # RUF013
76 76 | pass
77 77 |
78 78 |
RUF013_0.py:94:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
94 | def f(arg: int | float = None): # RUF011
94 | def f(arg: int | float = None): # RUF013
| ^^^^^^^^^^^ RUF013
95 | pass
|
@ -139,15 +139,15 @@ RUF013_0.py:94:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
91 91 | pass
92 92 |
93 93 |
94 |-def f(arg: int | float = None): # RUF011
94 |+def f(arg: Optional[int | float] = None): # RUF011
94 |-def f(arg: int | float = None): # RUF013
94 |+def f(arg: Optional[int | float] = None): # RUF013
95 95 | pass
96 96 |
97 97 |
RUF013_0.py:98:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
98 | def f(arg: int | float | str | bytes = None): # RUF011
98 | def f(arg: int | float | str | bytes = None): # RUF013
| ^^^^^^^^^^^^^^^^^^^^^^^^^ RUF013
99 | pass
|
@ -157,15 +157,15 @@ RUF013_0.py:98:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
95 95 | pass
96 96 |
97 97 |
98 |-def f(arg: int | float | str | bytes = None): # RUF011
98 |+def f(arg: Optional[int | float | str | bytes] = None): # RUF011
98 |-def f(arg: int | float | str | bytes = None): # RUF013
98 |+def f(arg: Optional[int | float | str | bytes] = None): # RUF013
99 99 | pass
100 100 |
101 101 |
RUF013_0.py:113:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
113 | def f(arg: Literal[1, "foo"] = None): # RUF011
113 | def f(arg: Literal[1, "foo"] = None): # RUF013
| ^^^^^^^^^^^^^^^^^ RUF013
114 | pass
|
@ -175,15 +175,15 @@ RUF013_0.py:113:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
110 110 | pass
111 111 |
112 112 |
113 |-def f(arg: Literal[1, "foo"] = None): # RUF011
113 |+def f(arg: Optional[Literal[1, "foo"]] = None): # RUF011
113 |-def f(arg: Literal[1, "foo"] = None): # RUF013
113 |+def f(arg: Optional[Literal[1, "foo"]] = None): # RUF013
114 114 | pass
115 115 |
116 116 |
RUF013_0.py:117:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
117 | def f(arg: typing.Literal[1, "foo", True] = None): # RUF011
117 | def f(arg: typing.Literal[1, "foo", True] = None): # RUF013
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF013
118 | pass
|
@ -193,15 +193,15 @@ RUF013_0.py:117:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
114 114 | pass
115 115 |
116 116 |
117 |-def f(arg: typing.Literal[1, "foo", True] = None): # RUF011
117 |+def f(arg: Optional[typing.Literal[1, "foo", True]] = None): # RUF011
117 |-def f(arg: typing.Literal[1, "foo", True] = None): # RUF013
117 |+def f(arg: Optional[typing.Literal[1, "foo", True]] = None): # RUF013
118 118 | pass
119 119 |
120 120 |
RUF013_0.py:136:22: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
136 | def f(arg: Annotated[int, ...] = None): # RUF011
136 | def f(arg: Annotated[int, ...] = None): # RUF013
| ^^^ RUF013
137 | pass
|
@ -211,15 +211,15 @@ RUF013_0.py:136:22: RUF013 [*] PEP 484 prohibits implicit `Optional`
133 133 | pass
134 134 |
135 135 |
136 |-def f(arg: Annotated[int, ...] = None): # RUF011
136 |+def f(arg: Annotated[Optional[int], ...] = None): # RUF011
136 |-def f(arg: Annotated[int, ...] = None): # RUF013
136 |+def f(arg: Annotated[Optional[int], ...] = None): # RUF013
137 137 | pass
138 138 |
139 139 |
RUF013_0.py:140:32: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
140 | def f(arg: Annotated[Annotated[int | str, ...], ...] = None): # RUF011
140 | def f(arg: Annotated[Annotated[int | str, ...], ...] = None): # RUF013
| ^^^^^^^^^ RUF013
141 | pass
|
@ -229,8 +229,8 @@ RUF013_0.py:140:32: RUF013 [*] PEP 484 prohibits implicit `Optional`
137 137 | pass
138 138 |
139 139 |
140 |-def f(arg: Annotated[Annotated[int | str, ...], ...] = None): # RUF011
140 |+def f(arg: Annotated[Annotated[Optional[int | str], ...], ...] = None): # RUF011
140 |-def f(arg: Annotated[Annotated[int | str, ...], ...] = None): # RUF013
140 |+def f(arg: Annotated[Annotated[Optional[int | str], ...], ...] = None): # RUF013
141 141 | pass
142 142 |
143 143 |
@ -238,10 +238,10 @@ RUF013_0.py:140:32: RUF013 [*] PEP 484 prohibits implicit `Optional`
RUF013_0.py:156:11: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
155 | def f(
156 | arg1: int = None, # RUF011
156 | arg1: int = None, # RUF013
| ^^^ RUF013
157 | arg2: Union[int, float] = None, # RUF011
158 | arg3: Literal[1, 2, 3] = None, # RUF011
157 | arg2: Union[int, float] = None, # RUF013
158 | arg3: Literal[1, 2, 3] = None, # RUF013
|
= help: Convert to `Optional[T]`
@ -249,19 +249,19 @@ RUF013_0.py:156:11: RUF013 [*] PEP 484 prohibits implicit `Optional`
153 153 |
154 154 |
155 155 | def f(
156 |- arg1: int = None, # RUF011
156 |+ arg1: Optional[int] = None, # RUF011
157 157 | arg2: Union[int, float] = None, # RUF011
158 158 | arg3: Literal[1, 2, 3] = None, # RUF011
156 |- arg1: int = None, # RUF013
156 |+ arg1: Optional[int] = None, # RUF013
157 157 | arg2: Union[int, float] = None, # RUF013
158 158 | arg3: Literal[1, 2, 3] = None, # RUF013
159 159 | ):
RUF013_0.py:157:11: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
155 | def f(
156 | arg1: int = None, # RUF011
157 | arg2: Union[int, float] = None, # RUF011
156 | arg1: int = None, # RUF013
157 | arg2: Union[int, float] = None, # RUF013
| ^^^^^^^^^^^^^^^^^ RUF013
158 | arg3: Literal[1, 2, 3] = None, # RUF011
158 | arg3: Literal[1, 2, 3] = None, # RUF013
159 | ):
|
= help: Convert to `Optional[T]`
@ -269,18 +269,18 @@ RUF013_0.py:157:11: RUF013 [*] PEP 484 prohibits implicit `Optional`
Suggested fix
154 154 |
155 155 | def f(
156 156 | arg1: int = None, # RUF011
157 |- arg2: Union[int, float] = None, # RUF011
157 |+ arg2: Optional[Union[int, float]] = None, # RUF011
158 158 | arg3: Literal[1, 2, 3] = None, # RUF011
156 156 | arg1: int = None, # RUF013
157 |- arg2: Union[int, float] = None, # RUF013
157 |+ arg2: Optional[Union[int, float]] = None, # RUF013
158 158 | arg3: Literal[1, 2, 3] = None, # RUF013
159 159 | ):
160 160 | pass
RUF013_0.py:158:11: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
156 | arg1: int = None, # RUF011
157 | arg2: Union[int, float] = None, # RUF011
158 | arg3: Literal[1, 2, 3] = None, # RUF011
156 | arg1: int = None, # RUF013
157 | arg2: Union[int, float] = None, # RUF013
158 | arg3: Literal[1, 2, 3] = None, # RUF013
| ^^^^^^^^^^^^^^^^ RUF013
159 | ):
160 | pass
@ -289,17 +289,17 @@ RUF013_0.py:158:11: RUF013 [*] PEP 484 prohibits implicit `Optional`
Suggested fix
155 155 | def f(
156 156 | arg1: int = None, # RUF011
157 157 | arg2: Union[int, float] = None, # RUF011
158 |- arg3: Literal[1, 2, 3] = None, # RUF011
158 |+ arg3: Optional[Literal[1, 2, 3]] = None, # RUF011
156 156 | arg1: int = None, # RUF013
157 157 | arg2: Union[int, float] = None, # RUF013
158 |- arg3: Literal[1, 2, 3] = None, # RUF013
158 |+ arg3: Optional[Literal[1, 2, 3]] = None, # RUF013
159 159 | ):
160 160 | pass
161 161 |
RUF013_0.py:186:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
186 | def f(arg: Union[Annotated[int, ...], Union[str, bytes]] = None): # RUF011
186 | def f(arg: Union[Annotated[int, ...], Union[str, bytes]] = None): # RUF013
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF013
187 | pass
|
@ -309,10 +309,54 @@ RUF013_0.py:186:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
183 183 | pass
184 184 |
185 185 |
186 |-def f(arg: Union[Annotated[int, ...], Union[str, bytes]] = None): # RUF011
186 |+def f(arg: Optional[Union[Annotated[int, ...], Union[str, bytes]]] = None): # RUF011
186 |-def f(arg: Union[Annotated[int, ...], Union[str, bytes]] = None): # RUF013
186 |+def f(arg: Optional[Union[Annotated[int, ...], Union[str, bytes]]] = None): # RUF013
187 187 | pass
188 188 |
189 189 |
RUF013_0.py:193:13: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
193 | def f(arg: "int" = None): # RUF013
| ^^^ RUF013
194 | pass
|
= help: Convert to `Optional[T]`
Suggested fix
190 190 | # Quoted
191 191 |
192 192 |
193 |-def f(arg: "int" = None): # RUF013
193 |+def f(arg: "Optional[int]" = None): # RUF013
194 194 | pass
195 195 |
196 196 |
RUF013_0.py:197:13: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
197 | def f(arg: "str" = None): # RUF013
| ^^^ RUF013
198 | pass
|
= help: Convert to `Optional[T]`
Suggested fix
194 194 | pass
195 195 |
196 196 |
197 |-def f(arg: "str" = None): # RUF013
197 |+def f(arg: "Optional[str]" = None): # RUF013
198 198 | pass
199 199 |
200 200 |
RUF013_0.py:201:12: RUF013 PEP 484 prohibits implicit `Optional`
|
201 | def f(arg: "st" "r" = None): # RUF013
| ^^^^^^^^ RUF013
202 | pass
|
= help: Convert to `Optional[T]`

View file

@ -3,7 +3,7 @@ source: crates/ruff/src/rules/ruff/mod.rs
---
RUF013_0.py:21:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
21 | def f(arg: int = None): # RUF011
21 | def f(arg: int = None): # RUF013
| ^^^ RUF013
22 | pass
|
@ -13,15 +13,15 @@ RUF013_0.py:21:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
18 18 | pass
19 19 |
20 20 |
21 |-def f(arg: int = None): # RUF011
21 |+def f(arg: int | None = None): # RUF011
21 |-def f(arg: int = None): # RUF013
21 |+def f(arg: int | None = None): # RUF013
22 22 | pass
23 23 |
24 24 |
RUF013_0.py:25:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
25 | def f(arg: str = None): # RUF011
25 | def f(arg: str = None): # RUF013
| ^^^ RUF013
26 | pass
|
@ -31,15 +31,15 @@ RUF013_0.py:25:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
22 22 | pass
23 23 |
24 24 |
25 |-def f(arg: str = None): # RUF011
25 |+def f(arg: str | None = None): # RUF011
25 |-def f(arg: str = None): # RUF013
25 |+def f(arg: str | None = None): # RUF013
26 26 | pass
27 27 |
28 28 |
RUF013_0.py:29:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
29 | def f(arg: typing.List[str] = None): # RUF011
29 | def f(arg: typing.List[str] = None): # RUF013
| ^^^^^^^^^^^^^^^^ RUF013
30 | pass
|
@ -49,15 +49,15 @@ RUF013_0.py:29:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
26 26 | pass
27 27 |
28 28 |
29 |-def f(arg: typing.List[str] = None): # RUF011
29 |+def f(arg: typing.List[str] | None = None): # RUF011
29 |-def f(arg: typing.List[str] = None): # RUF013
29 |+def f(arg: typing.List[str] | None = None): # RUF013
30 30 | pass
31 31 |
32 32 |
RUF013_0.py:33:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
33 | def f(arg: Tuple[str] = None): # RUF011
33 | def f(arg: Tuple[str] = None): # RUF013
| ^^^^^^^^^^ RUF013
34 | pass
|
@ -67,15 +67,15 @@ RUF013_0.py:33:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
30 30 | pass
31 31 |
32 32 |
33 |-def f(arg: Tuple[str] = None): # RUF011
33 |+def f(arg: Tuple[str] | None = None): # RUF011
33 |-def f(arg: Tuple[str] = None): # RUF013
33 |+def f(arg: Tuple[str] | None = None): # RUF013
34 34 | pass
35 35 |
36 36 |
RUF013_0.py:67:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
67 | def f(arg: Union = None): # RUF011
67 | def f(arg: Union = None): # RUF013
| ^^^^^ RUF013
68 | pass
|
@ -85,15 +85,15 @@ RUF013_0.py:67:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
64 64 | pass
65 65 |
66 66 |
67 |-def f(arg: Union = None): # RUF011
67 |+def f(arg: Union | None = None): # RUF011
67 |-def f(arg: Union = None): # RUF013
67 |+def f(arg: Union | None = None): # RUF013
68 68 | pass
69 69 |
70 70 |
RUF013_0.py:71:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
71 | def f(arg: Union[int, str] = None): # RUF011
71 | def f(arg: Union[int, str] = None): # RUF013
| ^^^^^^^^^^^^^^^ RUF013
72 | pass
|
@ -103,15 +103,15 @@ RUF013_0.py:71:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
68 68 | pass
69 69 |
70 70 |
71 |-def f(arg: Union[int, str] = None): # RUF011
71 |+def f(arg: Union[int, str] | None = None): # RUF011
71 |-def f(arg: Union[int, str] = None): # RUF013
71 |+def f(arg: Union[int, str] | None = None): # RUF013
72 72 | pass
73 73 |
74 74 |
RUF013_0.py:75:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
75 | def f(arg: typing.Union[int, str] = None): # RUF011
75 | def f(arg: typing.Union[int, str] = None): # RUF013
| ^^^^^^^^^^^^^^^^^^^^^^ RUF013
76 | pass
|
@ -121,15 +121,15 @@ RUF013_0.py:75:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
72 72 | pass
73 73 |
74 74 |
75 |-def f(arg: typing.Union[int, str] = None): # RUF011
75 |+def f(arg: typing.Union[int, str] | None = None): # RUF011
75 |-def f(arg: typing.Union[int, str] = None): # RUF013
75 |+def f(arg: typing.Union[int, str] | None = None): # RUF013
76 76 | pass
77 77 |
78 78 |
RUF013_0.py:94:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
94 | def f(arg: int | float = None): # RUF011
94 | def f(arg: int | float = None): # RUF013
| ^^^^^^^^^^^ RUF013
95 | pass
|
@ -139,15 +139,15 @@ RUF013_0.py:94:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
91 91 | pass
92 92 |
93 93 |
94 |-def f(arg: int | float = None): # RUF011
94 |+def f(arg: int | float | None = None): # RUF011
94 |-def f(arg: int | float = None): # RUF013
94 |+def f(arg: int | float | None = None): # RUF013
95 95 | pass
96 96 |
97 97 |
RUF013_0.py:98:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
98 | def f(arg: int | float | str | bytes = None): # RUF011
98 | def f(arg: int | float | str | bytes = None): # RUF013
| ^^^^^^^^^^^^^^^^^^^^^^^^^ RUF013
99 | pass
|
@ -157,15 +157,15 @@ RUF013_0.py:98:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
95 95 | pass
96 96 |
97 97 |
98 |-def f(arg: int | float | str | bytes = None): # RUF011
98 |+def f(arg: int | float | str | bytes | None = None): # RUF011
98 |-def f(arg: int | float | str | bytes = None): # RUF013
98 |+def f(arg: int | float | str | bytes | None = None): # RUF013
99 99 | pass
100 100 |
101 101 |
RUF013_0.py:113:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
113 | def f(arg: Literal[1, "foo"] = None): # RUF011
113 | def f(arg: Literal[1, "foo"] = None): # RUF013
| ^^^^^^^^^^^^^^^^^ RUF013
114 | pass
|
@ -175,15 +175,15 @@ RUF013_0.py:113:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
110 110 | pass
111 111 |
112 112 |
113 |-def f(arg: Literal[1, "foo"] = None): # RUF011
113 |+def f(arg: Literal[1, "foo"] | None = None): # RUF011
113 |-def f(arg: Literal[1, "foo"] = None): # RUF013
113 |+def f(arg: Literal[1, "foo"] | None = None): # RUF013
114 114 | pass
115 115 |
116 116 |
RUF013_0.py:117:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
117 | def f(arg: typing.Literal[1, "foo", True] = None): # RUF011
117 | def f(arg: typing.Literal[1, "foo", True] = None): # RUF013
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF013
118 | pass
|
@ -193,15 +193,15 @@ RUF013_0.py:117:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
114 114 | pass
115 115 |
116 116 |
117 |-def f(arg: typing.Literal[1, "foo", True] = None): # RUF011
117 |+def f(arg: typing.Literal[1, "foo", True] | None = None): # RUF011
117 |-def f(arg: typing.Literal[1, "foo", True] = None): # RUF013
117 |+def f(arg: typing.Literal[1, "foo", True] | None = None): # RUF013
118 118 | pass
119 119 |
120 120 |
RUF013_0.py:136:22: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
136 | def f(arg: Annotated[int, ...] = None): # RUF011
136 | def f(arg: Annotated[int, ...] = None): # RUF013
| ^^^ RUF013
137 | pass
|
@ -211,15 +211,15 @@ RUF013_0.py:136:22: RUF013 [*] PEP 484 prohibits implicit `Optional`
133 133 | pass
134 134 |
135 135 |
136 |-def f(arg: Annotated[int, ...] = None): # RUF011
136 |+def f(arg: Annotated[int | None, ...] = None): # RUF011
136 |-def f(arg: Annotated[int, ...] = None): # RUF013
136 |+def f(arg: Annotated[int | None, ...] = None): # RUF013
137 137 | pass
138 138 |
139 139 |
RUF013_0.py:140:32: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
140 | def f(arg: Annotated[Annotated[int | str, ...], ...] = None): # RUF011
140 | def f(arg: Annotated[Annotated[int | str, ...], ...] = None): # RUF013
| ^^^^^^^^^ RUF013
141 | pass
|
@ -229,8 +229,8 @@ RUF013_0.py:140:32: RUF013 [*] PEP 484 prohibits implicit `Optional`
137 137 | pass
138 138 |
139 139 |
140 |-def f(arg: Annotated[Annotated[int | str, ...], ...] = None): # RUF011
140 |+def f(arg: Annotated[Annotated[int | str | None, ...], ...] = None): # RUF011
140 |-def f(arg: Annotated[Annotated[int | str, ...], ...] = None): # RUF013
140 |+def f(arg: Annotated[Annotated[int | str | None, ...], ...] = None): # RUF013
141 141 | pass
142 142 |
143 143 |
@ -238,10 +238,10 @@ RUF013_0.py:140:32: RUF013 [*] PEP 484 prohibits implicit `Optional`
RUF013_0.py:156:11: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
155 | def f(
156 | arg1: int = None, # RUF011
156 | arg1: int = None, # RUF013
| ^^^ RUF013
157 | arg2: Union[int, float] = None, # RUF011
158 | arg3: Literal[1, 2, 3] = None, # RUF011
157 | arg2: Union[int, float] = None, # RUF013
158 | arg3: Literal[1, 2, 3] = None, # RUF013
|
= help: Convert to `T | None`
@ -249,19 +249,19 @@ RUF013_0.py:156:11: RUF013 [*] PEP 484 prohibits implicit `Optional`
153 153 |
154 154 |
155 155 | def f(
156 |- arg1: int = None, # RUF011
156 |+ arg1: int | None = None, # RUF011
157 157 | arg2: Union[int, float] = None, # RUF011
158 158 | arg3: Literal[1, 2, 3] = None, # RUF011
156 |- arg1: int = None, # RUF013
156 |+ arg1: int | None = None, # RUF013
157 157 | arg2: Union[int, float] = None, # RUF013
158 158 | arg3: Literal[1, 2, 3] = None, # RUF013
159 159 | ):
RUF013_0.py:157:11: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
155 | def f(
156 | arg1: int = None, # RUF011
157 | arg2: Union[int, float] = None, # RUF011
156 | arg1: int = None, # RUF013
157 | arg2: Union[int, float] = None, # RUF013
| ^^^^^^^^^^^^^^^^^ RUF013
158 | arg3: Literal[1, 2, 3] = None, # RUF011
158 | arg3: Literal[1, 2, 3] = None, # RUF013
159 | ):
|
= help: Convert to `T | None`
@ -269,18 +269,18 @@ RUF013_0.py:157:11: RUF013 [*] PEP 484 prohibits implicit `Optional`
Suggested fix
154 154 |
155 155 | def f(
156 156 | arg1: int = None, # RUF011
157 |- arg2: Union[int, float] = None, # RUF011
157 |+ arg2: Union[int, float] | None = None, # RUF011
158 158 | arg3: Literal[1, 2, 3] = None, # RUF011
156 156 | arg1: int = None, # RUF013
157 |- arg2: Union[int, float] = None, # RUF013
157 |+ arg2: Union[int, float] | None = None, # RUF013
158 158 | arg3: Literal[1, 2, 3] = None, # RUF013
159 159 | ):
160 160 | pass
RUF013_0.py:158:11: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
156 | arg1: int = None, # RUF011
157 | arg2: Union[int, float] = None, # RUF011
158 | arg3: Literal[1, 2, 3] = None, # RUF011
156 | arg1: int = None, # RUF013
157 | arg2: Union[int, float] = None, # RUF013
158 | arg3: Literal[1, 2, 3] = None, # RUF013
| ^^^^^^^^^^^^^^^^ RUF013
159 | ):
160 | pass
@ -289,17 +289,17 @@ RUF013_0.py:158:11: RUF013 [*] PEP 484 prohibits implicit `Optional`
Suggested fix
155 155 | def f(
156 156 | arg1: int = None, # RUF011
157 157 | arg2: Union[int, float] = None, # RUF011
158 |- arg3: Literal[1, 2, 3] = None, # RUF011
158 |+ arg3: Literal[1, 2, 3] | None = None, # RUF011
156 156 | arg1: int = None, # RUF013
157 157 | arg2: Union[int, float] = None, # RUF013
158 |- arg3: Literal[1, 2, 3] = None, # RUF013
158 |+ arg3: Literal[1, 2, 3] | None = None, # RUF013
159 159 | ):
160 160 | pass
161 161 |
RUF013_0.py:186:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
186 | def f(arg: Union[Annotated[int, ...], Union[str, bytes]] = None): # RUF011
186 | def f(arg: Union[Annotated[int, ...], Union[str, bytes]] = None): # RUF013
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF013
187 | pass
|
@ -309,10 +309,54 @@ RUF013_0.py:186:12: RUF013 [*] PEP 484 prohibits implicit `Optional`
183 183 | pass
184 184 |
185 185 |
186 |-def f(arg: Union[Annotated[int, ...], Union[str, bytes]] = None): # RUF011
186 |+def f(arg: Union[Annotated[int, ...], Union[str, bytes]] | None = None): # RUF011
186 |-def f(arg: Union[Annotated[int, ...], Union[str, bytes]] = None): # RUF013
186 |+def f(arg: Union[Annotated[int, ...], Union[str, bytes]] | None = None): # RUF013
187 187 | pass
188 188 |
189 189 |
RUF013_0.py:193:13: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
193 | def f(arg: "int" = None): # RUF013
| ^^^ RUF013
194 | pass
|
= help: Convert to `T | None`
Suggested fix
190 190 | # Quoted
191 191 |
192 192 |
193 |-def f(arg: "int" = None): # RUF013
193 |+def f(arg: "int | None" = None): # RUF013
194 194 | pass
195 195 |
196 196 |
RUF013_0.py:197:13: RUF013 [*] PEP 484 prohibits implicit `Optional`
|
197 | def f(arg: "str" = None): # RUF013
| ^^^ RUF013
198 | pass
|
= help: Convert to `T | None`
Suggested fix
194 194 | pass
195 195 |
196 196 |
197 |-def f(arg: "str" = None): # RUF013
197 |+def f(arg: "str | None" = None): # RUF013
198 198 | pass
199 199 |
200 200 |
RUF013_0.py:201:12: RUF013 PEP 484 prohibits implicit `Optional`
|
201 | def f(arg: "st" "r" = None): # RUF013
| ^^^^^^^^ RUF013
202 | pass
|
= help: Convert to `T | None`