Reorganize some flake8-pyi rules (#5472)

This commit is contained in:
Charlie Marsh 2023-07-03 00:39:22 -04:00 committed by GitHub
parent 93b2bd7184
commit 94ac2c4e1b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 257 additions and 284 deletions

View file

@ -1,17 +1,6 @@
import sys
from sys import platform, version_info
if sys.version == 'Python 2.7.10': ... # PYI002
if 'linux' == sys.platform: ... # PYI002
if hasattr(sys, 'maxint'): ... # PYI002
if sys.maxsize == 42: ... # PYI002
if (2, 7) < sys.version_info < (3, 5): ... # PYI002
if sys.version[0] == 'P': ... # PYI002
if False: ... # PYI002
if version_info[0] == 2: ...
if sys.version_info < (3, 5): ...
if version_info >= (3, 5): ...
if sys.version_info[:2] == (2, 7): ...
if sys.version_info[:1] == (2,): ...
if platform == 'linux': ...
if sys.version == 'Python 2.7.10': ... # Y002 If test must be a simple comparison against sys.platform or sys.version_info
if 'linux' == sys.platform: ... # Y002 If test must be a simple comparison against sys.platform or sys.version_info
if hasattr(sys, 'maxint'): ... # Y002 If test must be a simple comparison against sys.platform or sys.version_info
if sys.maxsize == 42: ... # Y002 If test must be a simple comparison against sys.platform or sys.version_info

View file

@ -1,17 +1,6 @@
import sys
from sys import platform, version_info
if sys.version == 'Python 2.7.10': ... # PYI002
if 'linux' == sys.platform: ... # PYI002
if hasattr(sys, 'maxint'): ... # PYI002
if sys.maxsize == 42: ... # PYI002
if (2, 7) < sys.version_info < (3, 5): ... # PYI002
if sys.version[0] == 'P': ... # PYI002
if False: ... # PYI002
if version_info[0] == 2: ...
if sys.version_info < (3, 5): ...
if version_info >= (3, 5): ...
if sys.version_info[:2] == (2, 7): ...
if sys.version_info[:1] == (2,): ...
if platform == 'linux': ...
if sys.version == 'Python 2.7.10': ... # Y002 If test must be a simple comparison against sys.platform or sys.version_info
if 'linux' == sys.platform: ... # Y002 If test must be a simple comparison against sys.platform or sys.version_info
if hasattr(sys, 'maxint'): ... # Y002 If test must be a simple comparison against sys.platform or sys.version_info
if sys.maxsize == 42: ... # Y002 If test must be a simple comparison against sys.platform or sys.version_info

View file

@ -1373,12 +1373,47 @@ where
}
if self.is_stub {
if self.any_enabled(&[
Rule::ComplexIfStatementInStub,
Rule::UnrecognizedVersionInfoCheck,
Rule::PatchVersionComparison,
Rule::WrongTupleLengthVersionComparison,
]) {
flake8_pyi::rules::version_info(self, test);
if let Expr::BoolOp(ast::ExprBoolOp { values, .. }) = test.as_ref() {
for value in values {
flake8_pyi::rules::unrecognized_version_info(self, value);
}
} else {
flake8_pyi::rules::unrecognized_version_info(self, test);
}
}
if self.any_enabled(&[
Rule::UnrecognizedPlatformCheck,
Rule::UnrecognizedPlatformName,
]) {
if let Expr::BoolOp(ast::ExprBoolOp { values, .. }) = test.as_ref() {
for value in values {
flake8_pyi::rules::unrecognized_platform(self, value);
}
} else {
flake8_pyi::rules::unrecognized_platform(self, test);
}
}
if self.enabled(Rule::BadVersionInfoComparison) {
if let Expr::BoolOp(ast::ExprBoolOp { values, .. }) = test.as_ref() {
for value in values {
flake8_pyi::rules::bad_version_info_comparison(self, value);
}
} else {
flake8_pyi::rules::bad_version_info_comparison(self, test);
}
}
if self.enabled(Rule::ComplexIfStatementInStub) {
if let Expr::BoolOp(ast::ExprBoolOp { values, .. }) = test.as_ref() {
for value in values {
flake8_pyi::rules::complex_if_statement_in_stub(self, value);
}
} else {
flake8_pyi::rules::complex_if_statement_in_stub(self, test);
}
}
}
}
@ -3223,29 +3258,6 @@ where
if self.enabled(Rule::YodaConditions) {
flake8_simplify::rules::yoda_conditions(self, expr, left, ops, comparators);
}
if self.is_stub {
if self.any_enabled(&[
Rule::UnrecognizedPlatformCheck,
Rule::UnrecognizedPlatformName,
]) {
flake8_pyi::rules::unrecognized_platform(
self,
expr,
left,
ops,
comparators,
);
}
if self.enabled(Rule::BadVersionInfoComparison) {
flake8_pyi::rules::bad_version_info_comparison(
self,
expr,
left,
ops,
comparators,
);
}
}
}
Expr::Constant(ast::ExprConstant {
value: Constant::Int(_) | Constant::Float(_) | Constant::Complex { .. },

View file

@ -1,4 +1,4 @@
use rustpython_parser::ast::{CmpOp, Expr, Ranged};
use rustpython_parser::ast::{self, CmpOp, Expr, Ranged};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -57,14 +57,18 @@ impl Violation for BadVersionInfoComparison {
}
/// PYI006
pub(crate) fn bad_version_info_comparison(
checker: &mut Checker,
expr: &Expr,
left: &Expr,
ops: &[CmpOp],
comparators: &[Expr],
) {
let ([op], [_right]) = (ops, comparators) else {
pub(crate) fn bad_version_info_comparison(checker: &mut Checker, test: &Expr) {
let Expr::Compare(ast::ExprCompare {
left,
ops,
comparators,
..
}) = test
else {
return;
};
let ([op], [_right]) = (ops.as_slice(), comparators.as_slice()) else {
return;
};
@ -82,6 +86,7 @@ pub(crate) fn bad_version_info_comparison(
return;
}
let diagnostic = Diagnostic::new(BadVersionInfoComparison, expr.range());
checker.diagnostics.push(diagnostic);
checker
.diagnostics
.push(Diagnostic::new(BadVersionInfoComparison, test.range()));
}

View file

@ -0,0 +1,80 @@
use rustpython_parser::ast::{self, Expr, Ranged};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
use crate::checkers::ast::Checker;
/// ## What it does
/// Checks for `if` statements with complex conditionals in stubs.
///
/// ## Why is this bad?
/// Stub files support simple conditionals to test for differences in Python
/// versions and platforms. However, type checkers only understand a limited
/// subset of these conditionals; complex conditionals may result in false
/// positives or false negatives.
///
/// ## Example
/// ```python
/// import sys
///
/// if (2, 7) < sys.version_info < (3, 5):
/// ...
/// ```
///
/// Use instead:
/// ```python
/// import sys
///
/// if sys.version_info < (3, 5):
/// ...
/// ```
#[violation]
pub struct ComplexIfStatementInStub;
impl Violation for ComplexIfStatementInStub {
#[derive_message_formats]
fn message(&self) -> String {
format!(
"`if`` test must be a simple comparison against `sys.platform` or `sys.version_info`"
)
}
}
/// PYI002
pub(crate) fn complex_if_statement_in_stub(checker: &mut Checker, test: &Expr) {
let Expr::Compare(ast::ExprCompare {
left, comparators, ..
}) = test
else {
checker
.diagnostics
.push(Diagnostic::new(ComplexIfStatementInStub, test.range()));
return;
};
if comparators.len() != 1 {
checker
.diagnostics
.push(Diagnostic::new(ComplexIfStatementInStub, test.range()));
return;
}
if left.is_subscript_expr() {
return;
}
if checker
.semantic()
.resolve_call_path(left)
.map_or(false, |call_path| {
matches!(call_path.as_slice(), ["sys", "version_info" | "platform"])
})
{
return;
}
checker
.diagnostics
.push(Diagnostic::new(ComplexIfStatementInStub, test.range()));
}

View file

@ -1,6 +1,7 @@
pub(crate) use any_eq_ne_annotation::*;
pub(crate) use bad_version_info_comparison::*;
pub(crate) use collections_named_tuple::*;
pub(crate) use complex_if_statement_in_stub::*;
pub(crate) use docstring_in_stubs::*;
pub(crate) use duplicate_union_member::*;
pub(crate) use ellipsis_in_non_empty_class_body::*;
@ -22,11 +23,12 @@ pub(crate) use type_alias_naming::*;
pub(crate) use type_comment_in_stub::*;
pub(crate) use unaliased_collections_abc_set_import::*;
pub(crate) use unrecognized_platform::*;
pub(crate) use version_info::*;
pub(crate) use unrecognized_version_info::*;
mod any_eq_ne_annotation;
mod bad_version_info_comparison;
mod collections_named_tuple;
mod complex_if_statement_in_stub;
mod docstring_in_stubs;
mod duplicate_union_member;
mod ellipsis_in_non_empty_class_body;
@ -48,4 +50,4 @@ mod type_alias_naming;
mod type_comment_in_stub;
mod unaliased_collections_abc_set_import;
mod unrecognized_platform;
mod version_info;
mod unrecognized_version_info;

View file

@ -89,19 +89,21 @@ impl Violation for UnrecognizedPlatformName {
}
/// PYI007, PYI008
pub(crate) fn unrecognized_platform(
checker: &mut Checker,
expr: &Expr,
left: &Expr,
ops: &[CmpOp],
comparators: &[Expr],
) {
let ([op], [right]) = (ops, comparators) else {
pub(crate) fn unrecognized_platform(checker: &mut Checker, test: &Expr) {
let Expr::Compare(ast::ExprCompare {
left,
ops,
comparators,
..
}) = test
else {
return;
};
let ([op], [right]) = (ops.as_slice(), comparators.as_slice()) else {
return;
};
let diagnostic_unrecognized_platform_check =
Diagnostic::new(UnrecognizedPlatformCheck, expr.range());
if !checker
.semantic()
.resolve_call_path(left)
@ -113,23 +115,24 @@ pub(crate) fn unrecognized_platform(
}
// "in" might also make sense but we don't currently have one.
if !matches!(op, CmpOp::Eq | CmpOp::NotEq) && checker.enabled(Rule::UnrecognizedPlatformCheck) {
checker
.diagnostics
.push(diagnostic_unrecognized_platform_check);
if !matches!(op, CmpOp::Eq | CmpOp::NotEq) {
if checker.enabled(Rule::UnrecognizedPlatformCheck) {
checker
.diagnostics
.push(Diagnostic::new(UnrecognizedPlatformCheck, test.range()));
}
return;
}
match right {
Expr::Constant(ast::ExprConstant {
value: Constant::Str(value),
..
}) => {
// Other values are possible but we don't need them right now.
// This protects against typos.
if !["linux", "win32", "cygwin", "darwin"].contains(&value.as_str())
&& checker.enabled(Rule::UnrecognizedPlatformName)
{
if let Expr::Constant(ast::ExprConstant {
value: Constant::Str(value),
..
}) = right
{
// Other values are possible but we don't need them right now.
// This protects against typos.
if checker.enabled(Rule::UnrecognizedPlatformName) {
if !matches!(value.as_str(), "linux" | "win32" | "cygwin" | "darwin") {
checker.diagnostics.push(Diagnostic::new(
UnrecognizedPlatformName {
platform: value.clone(),
@ -138,12 +141,11 @@ pub(crate) fn unrecognized_platform(
));
}
}
_ => {
if checker.enabled(Rule::UnrecognizedPlatformCheck) {
checker
.diagnostics
.push(diagnostic_unrecognized_platform_check);
}
} else {
if checker.enabled(Rule::UnrecognizedPlatformCheck) {
checker
.diagnostics
.push(Diagnostic::new(UnrecognizedPlatformCheck, test.range()));
}
}
}

View file

@ -1,50 +1,14 @@
use num_bigint::BigInt;
use num_traits::{One, Zero};
use rustpython_parser::ast::{self, CmpOp, Constant, Expr, Ranged};
use smallvec::SmallVec;
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::helpers::map_subscript;
use crate::checkers::ast::Checker;
use crate::registry::Rule;
/// ## What it does
/// Checks for `if` statements with complex conditionals in stubs.
///
/// ## Why is this bad?
/// Stub files support simple conditionals to test for differences in Python
/// versions and platforms. However, type checkers only understand a limited
/// subset of these conditionals; complex conditionals may result in false
/// positives or false negatives.
///
/// ## Example
/// ```python
/// import sys
///
/// if (2, 7) < sys.version_info < (3, 5):
/// ...
/// ```
///
/// Use instead:
/// ```python
/// import sys
///
/// if sys.version_info < (3, 5):
/// ...
/// ```
#[violation]
pub struct ComplexIfStatementInStub;
impl Violation for ComplexIfStatementInStub {
#[derive_message_formats]
fn message(&self) -> String {
format!(
"`if`` test must be a simple comparison against `sys.platform` or `sys.version_info`"
)
}
}
/// ## What it does
/// Checks for problematic `sys.version_info`-related conditions in stubs.
///
@ -150,104 +114,57 @@ pub struct WrongTupleLengthVersionComparison {
impl Violation for WrongTupleLengthVersionComparison {
#[derive_message_formats]
fn message(&self) -> String {
format!(
"Version comparison must be against a length-{} tuple.",
self.expected_length
)
let WrongTupleLengthVersionComparison { expected_length } = self;
format!("Version comparison must be against a length-{expected_length} tuple")
}
}
#[derive(Copy, Clone, Eq, PartialEq)]
enum ExpectedComparator {
MajorDigit,
MajorTuple,
MajorMinorTuple,
AnyTuple,
}
/// PYI002, PYI003, PYI004, PYI005
pub(crate) fn version_info(checker: &mut Checker, test: &Expr) {
if let Expr::BoolOp(ast::ExprBoolOp { values, .. }) = test {
for value in values {
version_info(checker, value);
}
return;
}
let Some((left, op, comparator, is_platform)) = compare_expr_components(checker, test) else {
if checker.enabled(Rule::ComplexIfStatementInStub) {
checker
.diagnostics
.push(Diagnostic::new(ComplexIfStatementInStub, test.range()));
}
/// PYI003, PYI004, PYI005
pub(crate) fn unrecognized_version_info(checker: &mut Checker, test: &Expr) {
let Expr::Compare(ast::ExprCompare {
left,
ops,
comparators,
..
}) = test
else {
return;
};
// Already covered by PYI007.
if is_platform {
let ([op], [comparator]) = (ops.as_slice(), comparators.as_slice()) else {
return;
};
if !checker
.semantic()
.resolve_call_path(map_subscript(left))
.map_or(false, |call_path| {
matches!(call_path.as_slice(), ["sys", "version_info"])
})
{
return;
}
let Ok(expected_comparator) = ExpectedComparator::try_from(left) else {
if let Some(expected) = ExpectedComparator::try_from(left) {
version_check(checker, expected, test, *op, comparator);
} else {
if checker.enabled(Rule::UnrecognizedVersionInfoCheck) {
checker
.diagnostics
.push(Diagnostic::new(UnrecognizedVersionInfoCheck, test.range()));
}
return;
};
check_version_check(checker, expected_comparator, test, op, comparator);
}
}
/// Extracts relevant components of the if test.
fn compare_expr_components<'a>(
checker: &Checker,
test: &'a Expr,
) -> Option<(&'a Expr, CmpOp, &'a Expr, bool)> {
test.as_compare_expr().and_then(|cmp| {
let ast::ExprCompare {
left,
ops,
comparators,
..
} = cmp;
if comparators.len() != 1 {
return None;
}
let name_expr = if let Expr::Subscript(ast::ExprSubscript { value, .. }) = left.as_ref() {
value
} else {
left
};
// The only valid comparisons are against sys.platform and sys.version_info.
let is_platform = match checker
.semantic()
.resolve_call_path(name_expr)
.as_ref()
.map(SmallVec::as_slice)
{
Some(["sys", "platform"]) => true,
Some(["sys", "version_info"]) => false,
_ => return None,
};
Some((left.as_ref(), ops[0], &comparators[0], is_platform))
})
}
fn check_version_check(
fn version_check(
checker: &mut Checker,
expected_comparator: ExpectedComparator,
expected: ExpectedComparator,
test: &Expr,
op: CmpOp,
comparator: &Expr,
) {
// Single digit comparison, e.g., `sys.version_info[0] == 2`.
if expected_comparator == ExpectedComparator::MajorDigit {
if expected == ExpectedComparator::MajorDigit {
if !is_int_constant(comparator) {
if checker.enabled(Rule::UnrecognizedVersionInfoCheck) {
checker
@ -288,7 +205,7 @@ fn check_version_check(
if checker.enabled(Rule::WrongTupleLengthVersionComparison) {
if op == CmpOp::Eq || op == CmpOp::NotEq {
let expected_length = match expected_comparator {
let expected_length = match expected {
ExpectedComparator::MajorTuple => 1,
ExpectedComparator::MajorMinorTuple => 2,
_ => return,
@ -304,32 +221,40 @@ fn check_version_check(
}
}
impl TryFrom<&Expr> for ExpectedComparator {
type Error = ();
#[derive(Copy, Clone, Eq, PartialEq)]
enum ExpectedComparator {
MajorDigit,
MajorTuple,
MajorMinorTuple,
AnyTuple,
}
fn try_from(value: &Expr) -> Result<Self, Self::Error> {
let Expr::Subscript(ast::ExprSubscript { slice, .. }) = value else {
return Ok(ExpectedComparator::AnyTuple)
impl ExpectedComparator {
/// Returns the expected comparator for the given expression, if any.
fn try_from(expr: &Expr) -> Option<Self> {
let Expr::Subscript(ast::ExprSubscript { slice, .. }) = expr else {
return Some(ExpectedComparator::AnyTuple);
};
// Only allow simple slices of the form [:n] or explicit indexing into the first element
// Only allow: (1) simple slices of the form `[:n]`, or (2) explicit indexing into the first
// element (major version) of the tuple.
match slice.as_ref() {
Expr::Slice(ast::ExprSlice {
lower: None,
upper: Some(n),
upper: Some(upper),
step: None,
..
}) => {
if let Expr::Constant(ast::ExprConstant {
value: Constant::Int(n),
value: Constant::Int(upper),
..
}) = n.as_ref()
}) = upper.as_ref()
{
if *n == BigInt::one() {
return Ok(ExpectedComparator::MajorTuple);
if *upper == BigInt::one() {
return Some(ExpectedComparator::MajorTuple);
}
if *n == BigInt::from(2) {
return Ok(ExpectedComparator::MajorMinorTuple);
if *upper == BigInt::from(2) {
return Some(ExpectedComparator::MajorMinorTuple);
}
}
}
@ -337,15 +262,16 @@ impl TryFrom<&Expr> for ExpectedComparator {
value: Constant::Int(n),
..
}) if n.is_zero() => {
return Ok(ExpectedComparator::MajorDigit);
return Some(ExpectedComparator::MajorDigit);
}
_ => (),
}
Err(())
None
}
}
/// Returns `true` if the given expression is an integer constant.
fn is_int_constant(expr: &Expr) -> bool {
matches!(
expr,

View file

@ -1,72 +1,40 @@
---
source: crates/ruff/src/rules/flake8_pyi/mod.rs
---
PYI002.pyi:3:4: PYI002 `if`` test must be a simple comparison against `sys.platform` or `sys.version_info`
|
1 | import sys
2 |
3 | if sys.version == 'Python 2.7.10': ... # Y002 If test must be a simple comparison against sys.platform or sys.version_info
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI002
4 | if 'linux' == sys.platform: ... # Y002 If test must be a simple comparison against sys.platform or sys.version_info
5 | if hasattr(sys, 'maxint'): ... # Y002 If test must be a simple comparison against sys.platform or sys.version_info
|
PYI002.pyi:4:4: PYI002 `if`` test must be a simple comparison against `sys.platform` or `sys.version_info`
|
2 | from sys import platform, version_info
3 |
4 | if sys.version == 'Python 2.7.10': ... # PYI002
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI002
5 | if 'linux' == sys.platform: ... # PYI002
6 | if hasattr(sys, 'maxint'): ... # PYI002
3 | if sys.version == 'Python 2.7.10': ... # Y002 If test must be a simple comparison against sys.platform or sys.version_info
4 | if 'linux' == sys.platform: ... # Y002 If test must be a simple comparison against sys.platform or sys.version_info
| ^^^^^^^^^^^^^^^^^^^^^^^ PYI002
5 | if hasattr(sys, 'maxint'): ... # Y002 If test must be a simple comparison against sys.platform or sys.version_info
6 | if sys.maxsize == 42: ... # Y002 If test must be a simple comparison against sys.platform or sys.version_info
|
PYI002.pyi:5:4: PYI002 `if`` test must be a simple comparison against `sys.platform` or `sys.version_info`
|
4 | if sys.version == 'Python 2.7.10': ... # PYI002
5 | if 'linux' == sys.platform: ... # PYI002
| ^^^^^^^^^^^^^^^^^^^^^^^ PYI002
6 | if hasattr(sys, 'maxint'): ... # PYI002
7 | if sys.maxsize == 42: ... # PYI002
3 | if sys.version == 'Python 2.7.10': ... # Y002 If test must be a simple comparison against sys.platform or sys.version_info
4 | if 'linux' == sys.platform: ... # Y002 If test must be a simple comparison against sys.platform or sys.version_info
5 | if hasattr(sys, 'maxint'): ... # Y002 If test must be a simple comparison against sys.platform or sys.version_info
| ^^^^^^^^^^^^^^^^^^^^^^ PYI002
6 | if sys.maxsize == 42: ... # Y002 If test must be a simple comparison against sys.platform or sys.version_info
|
PYI002.pyi:6:4: PYI002 `if`` test must be a simple comparison against `sys.platform` or `sys.version_info`
|
4 | if sys.version == 'Python 2.7.10': ... # PYI002
5 | if 'linux' == sys.platform: ... # PYI002
6 | if hasattr(sys, 'maxint'): ... # PYI002
| ^^^^^^^^^^^^^^^^^^^^^^ PYI002
7 | if sys.maxsize == 42: ... # PYI002
8 | if (2, 7) < sys.version_info < (3, 5): ... # PYI002
|
PYI002.pyi:7:4: PYI002 `if`` test must be a simple comparison against `sys.platform` or `sys.version_info`
|
5 | if 'linux' == sys.platform: ... # PYI002
6 | if hasattr(sys, 'maxint'): ... # PYI002
7 | if sys.maxsize == 42: ... # PYI002
4 | if 'linux' == sys.platform: ... # Y002 If test must be a simple comparison against sys.platform or sys.version_info
5 | if hasattr(sys, 'maxint'): ... # Y002 If test must be a simple comparison against sys.platform or sys.version_info
6 | if sys.maxsize == 42: ... # Y002 If test must be a simple comparison against sys.platform or sys.version_info
| ^^^^^^^^^^^^^^^^^ PYI002
8 | if (2, 7) < sys.version_info < (3, 5): ... # PYI002
9 | if sys.version[0] == 'P': ... # PYI002
|
PYI002.pyi:8:4: PYI002 `if`` test must be a simple comparison against `sys.platform` or `sys.version_info`
|
6 | if hasattr(sys, 'maxint'): ... # PYI002
7 | if sys.maxsize == 42: ... # PYI002
8 | if (2, 7) < sys.version_info < (3, 5): ... # PYI002
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI002
9 | if sys.version[0] == 'P': ... # PYI002
10 | if False: ... # PYI002
|
PYI002.pyi:9:4: PYI002 `if`` test must be a simple comparison against `sys.platform` or `sys.version_info`
|
7 | if sys.maxsize == 42: ... # PYI002
8 | if (2, 7) < sys.version_info < (3, 5): ... # PYI002
9 | if sys.version[0] == 'P': ... # PYI002
| ^^^^^^^^^^^^^^^^^^^^^ PYI002
10 | if False: ... # PYI002
|
PYI002.pyi:10:4: PYI002 `if`` test must be a simple comparison against `sys.platform` or `sys.version_info`
|
8 | if (2, 7) < sys.version_info < (3, 5): ... # PYI002
9 | if sys.version[0] == 'P': ... # PYI002
10 | if False: ... # PYI002
| ^^^^^ PYI002
11 |
12 | if version_info[0] == 2: ...
|

View file

@ -1,7 +1,7 @@
---
source: crates/ruff/src/rules/flake8_pyi/mod.rs
---
PYI005.pyi:4:4: PYI005 Version comparison must be against a length-1 tuple.
PYI005.pyi:4:4: PYI005 Version comparison must be against a length-1 tuple
|
2 | from sys import platform, version_info
3 |
@ -10,7 +10,7 @@ PYI005.pyi:4:4: PYI005 Version comparison must be against a length-1 tuple.
5 | if sys.version_info[:2] == (2,): ... # Y005
|
PYI005.pyi:5:4: PYI005 Version comparison must be against a length-2 tuple.
PYI005.pyi:5:4: PYI005 Version comparison must be against a length-2 tuple
|
4 | if sys.version_info[:1] == (2, 7): ... # Y005
5 | if sys.version_info[:2] == (2,): ... # Y005