Skip to content

Commit 954e2a0

Browse files
committed
[pyupgrade] Ignore Optional[None] in UP045/UP007
1 parent 86e5a31 commit 954e2a0

File tree

3 files changed

+17
-3
lines changed

3 files changed

+17
-3
lines changed

crates/ruff_linter/resources/test/fixtures/pyupgrade/UP045.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,8 @@ class ServiceRefOrValue:
4242
# Regression test for: https://github.com/astral-sh/ruff/issues/7201
4343
class ServiceRefOrValue:
4444
service_specification: Optional[str]is not True = None
45+
46+
47+
# Test for: https://github.com/astral-sh/ruff/issues/18508
48+
# Optional[None] should be ignored
49+
foo: Optional[None] = None

crates/ruff_linter/src/rules/pyupgrade/rules/use_pep604_annotation.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ impl Violation for NonPEP604AnnotationUnion {
7474
/// ## What it does
7575
/// Check for `typing.Optional` annotations that can be rewritten based on [PEP 604] syntax.
7676
///
77+
/// `Optional[None]` is exempt from this rule, as the intention is unclear.
78+
///
7779
/// ## Why is this bad?
7880
/// [PEP 604] introduced a new syntax for union type annotations based on the
7981
/// `|` operator. This syntax is more concise and readable than the previous
@@ -100,8 +102,8 @@ impl Violation for NonPEP604AnnotationUnion {
100102
/// ```
101103
///
102104
/// ## Fix safety
103-
/// This rule's fix is marked as unsafe, as it may lead to runtime errors when
104-
/// alongside libraries that rely on runtime type annotations, like Pydantic,
105+
/// This rule's fix is marked as unsafe, as it may lead to runtime errors
106+
/// using libraries that rely on runtime type annotations, like Pydantic,
105107
/// on Python versions prior to Python 3.10. It may also lead to runtime errors
106108
/// in unusual and likely incorrect type annotations where the type does not
107109
/// support the `|` operator.
@@ -140,6 +142,11 @@ pub(crate) fn non_pep604_annotation(
140142
&& !checker.semantic().in_complex_string_type_definition()
141143
&& is_allowed_value(slice);
142144

145+
if matches!(operator, Pep604Operator::Optional) && matches!(slice, Expr::NoneLiteral(_)) {
146+
// `Optional[None]` is exempt from this rule.
147+
return;
148+
}
149+
143150
let applicability = if checker.target_version() >= PythonVersion::PY310 {
144151
Applicability::Safe
145152
} else {

crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP045.py.snap

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
---
22
source: crates/ruff_linter/src/rules/pyupgrade/mod.rs
3-
snapshot_kind: text
43
---
54
UP045.py:5:10: UP007 [*] Use `X | Y` for type annotations
65
|
@@ -149,3 +148,6 @@ UP045.py:44:28: UP007 [*] Use `X | Y` for type annotations
149148
43 43 | class ServiceRefOrValue:
150149
44 |- service_specification: Optional[str]is not True = None
151150
44 |+ service_specification: str | None is not True = None
151+
45 45 |
152+
46 46 |
153+
47 47 | # Test for: https://github.com/astral-sh/ruff/issues/18508

0 commit comments

Comments
 (0)