Skip to content

Commit 14c3755

Browse files
Fix YTT201 for '!=' comparisons (#18293)
## Summary Closes #18292.
1 parent 83a0369 commit 14c3755

File tree

2 files changed

+20
-9
lines changed

2 files changed

+20
-9
lines changed

crates/ruff_linter/src/rules/flake8_2020/rules/compare.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,20 @@ impl Violation for SysVersionCmpStr3 {
5252

5353
/// ## What it does
5454
/// Checks for equality comparisons against the major version returned by
55-
/// `sys.version_info` (e.g., `sys.version_info[0] == 3`).
55+
/// `sys.version_info` (e.g., `sys.version_info[0] == 3` or `sys.version_info[0] != 3`).
5656
///
5757
/// ## Why is this bad?
5858
/// Using `sys.version_info[0] == 3` to verify that the major version is
5959
/// Python 3 or greater will fail if the major version number is ever
6060
/// incremented (e.g., to Python 4). This is likely unintended, as code
6161
/// that uses this comparison is likely intended to be run on Python 2,
62-
/// but would now run on Python 4 too.
62+
/// but would now run on Python 4 too. Similarly, using `sys.version_info[0] != 3`
63+
/// to check for Python 2 will also fail if the major version number is
64+
/// incremented.
6365
///
6466
/// Instead, use `>=` to check if the major version number is 3 or greater,
65-
/// to future-proof the code.
67+
/// or `<` to check if the major version number is less than 3, to future-proof
68+
/// the code.
6669
///
6770
/// ## Example
6871
/// ```python
@@ -88,12 +91,18 @@ impl Violation for SysVersionCmpStr3 {
8891
/// - [Python documentation: `sys.version`](https://docs.python.org/3/library/sys.html#sys.version)
8992
/// - [Python documentation: `sys.version_info`](https://docs.python.org/3/library/sys.html#sys.version_info)
9093
#[derive(ViolationMetadata)]
91-
pub(crate) struct SysVersionInfo0Eq3;
94+
pub(crate) struct SysVersionInfo0Eq3 {
95+
eq: bool,
96+
}
9297

9398
impl Violation for SysVersionInfo0Eq3 {
9499
#[derive_message_formats]
95100
fn message(&self) -> String {
96-
"`sys.version_info[0] == 3` referenced (python4), use `>=`".to_string()
101+
if self.eq {
102+
"`sys.version_info[0] == 3` referenced (python4), use `>=`".to_string()
103+
} else {
104+
"`sys.version_info[0] != 3` referenced (python4), use `<`".to_string()
105+
}
97106
}
98107
}
99108

@@ -235,7 +244,7 @@ pub(crate) fn compare(checker: &Checker, left: &Expr, ops: &[CmpOp], comparators
235244
{
236245
if *i == 0 {
237246
if let (
238-
[CmpOp::Eq | CmpOp::NotEq],
247+
[operator @ (CmpOp::Eq | CmpOp::NotEq)],
239248
[
240249
Expr::NumberLiteral(ast::ExprNumberLiteral {
241250
value: ast::Number::Int(n),
@@ -246,7 +255,9 @@ pub(crate) fn compare(checker: &Checker, left: &Expr, ops: &[CmpOp], comparators
246255
{
247256
if *n == 3 && checker.enabled(Rule::SysVersionInfo0Eq3) {
248257
checker.report_diagnostic(Diagnostic::new(
249-
SysVersionInfo0Eq3,
258+
SysVersionInfo0Eq3 {
259+
eq: matches!(*operator, CmpOp::Eq),
260+
},
250261
left.range(),
251262
));
252263
}

crates/ruff_linter/src/rules/flake8_2020/snapshots/ruff_linter__rules__flake8_2020__tests__YTT201_YTT201.py.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ YTT201.py:8:7: YTT201 `sys.version_info[0] == 3` referenced (python4), use `>=`
2020
10 | PY2 = version_info[0] != 3
2121
|
2222

23-
YTT201.py:9:7: YTT201 `sys.version_info[0] == 3` referenced (python4), use `>=`
23+
YTT201.py:9:7: YTT201 `sys.version_info[0] != 3` referenced (python4), use `<`
2424
|
2525
7 | PY3 = sys.version_info[0] == 3
2626
8 | PY3 = version_info[0] == 3
@@ -29,7 +29,7 @@ YTT201.py:9:7: YTT201 `sys.version_info[0] == 3` referenced (python4), use `>=`
2929
10 | PY2 = version_info[0] != 3
3030
|
3131

32-
YTT201.py:10:7: YTT201 `sys.version_info[0] == 3` referenced (python4), use `>=`
32+
YTT201.py:10:7: YTT201 `sys.version_info[0] != 3` referenced (python4), use `<`
3333
|
3434
8 | PY3 = version_info[0] == 3
3535
9 | PY2 = sys.version_info[0] != 3

0 commit comments

Comments
 (0)