feat: Implement `InvalidPrintSyntax` (`F633`)

This commit is contained in:
Dmitry Dygalo 2022-09-14 01:04:13 +02:00
parent 53a7758248
commit 6d3abdf1d6
No known key found for this signature in database
GPG Key ID: 0D78E60518FE18BB
4 changed files with 59 additions and 1 deletions

4
resources/test/fixtures/F633.py vendored Normal file
View File

@ -0,0 +1,4 @@
from __future__ import print_function
import sys
print >> sys.stderr, "Hello"

View File

@ -3,7 +3,7 @@ use std::path::Path;
use rustpython_parser::ast::{
Arg, Arguments, Constant, Excepthandler, ExcepthandlerKind, Expr, ExprContext, ExprKind,
KeywordData, Location, Stmt, StmtKind, Suite,
KeywordData, Location, Operator, Stmt, StmtKind, Suite,
};
use rustpython_parser::parser;
@ -668,6 +668,28 @@ where
}
self.in_f_string = true;
}
ExprKind::BinOp {
left,
op: Operator::RShift,
..
} => {
if self.settings.select.contains(&CheckCode::F633) {
if let ExprKind::Name { id, .. } = &left.node {
if id == "print" {
let scope = &self.scopes
[*(self.scope_stack.last().expect("No current scope found."))];
if let Some(Binding {
kind: BindingKind::Builtin,
..
}) = scope.values.get("print")
{
self.checks
.push(Check::new(CheckKind::InvalidPrintSyntax, left.location));
}
}
}
}
}
ExprKind::UnaryOp { op, operand } => {
let check_not_in = self.settings.select.contains(&CheckCode::E713);
let check_not_is = self.settings.select.contains(&CheckCode::E714);

View File

@ -31,6 +31,7 @@ pub enum CheckCode {
F621,
F622,
F631,
F633,
F634,
F701,
F702,
@ -76,6 +77,7 @@ impl FromStr for CheckCode {
"F621" => Ok(CheckCode::F621),
"F622" => Ok(CheckCode::F622),
"F631" => Ok(CheckCode::F631),
"F633" => Ok(CheckCode::F633),
"F634" => Ok(CheckCode::F634),
"F701" => Ok(CheckCode::F701),
"F702" => Ok(CheckCode::F702),
@ -121,6 +123,7 @@ impl CheckCode {
CheckCode::F621 => "F621",
CheckCode::F622 => "F622",
CheckCode::F631 => "F631",
CheckCode::F633 => "F633",
CheckCode::F634 => "F634",
CheckCode::F701 => "F701",
CheckCode::F702 => "F702",
@ -179,6 +182,7 @@ pub enum CheckKind {
FutureFeatureNotDefined(String),
IOError(String),
IfTuple,
InvalidPrintSyntax,
ImportStarNotPermitted(String),
ImportStarUsage(String),
LateFutureImport,
@ -223,6 +227,7 @@ impl CheckKind {
CheckKind::FutureFeatureNotDefined(_) => "FutureFeatureNotDefined",
CheckKind::IOError(_) => "IOError",
CheckKind::IfTuple => "IfTuple",
CheckKind::InvalidPrintSyntax => "InvalidPrintSyntax",
CheckKind::ImportStarNotPermitted(_) => "ImportStarNotPermitted",
CheckKind::ImportStarUsage(_) => "ImportStarUsage",
CheckKind::LateFutureImport => "LateFutureImport",
@ -269,6 +274,7 @@ impl CheckKind {
CheckKind::FutureFeatureNotDefined(_) => &CheckCode::F407,
CheckKind::IOError(_) => &CheckCode::E902,
CheckKind::IfTuple => &CheckCode::F634,
CheckKind::InvalidPrintSyntax => &CheckCode::F633,
CheckKind::ImportStarNotPermitted(_) => &CheckCode::F406,
CheckKind::ImportStarUsage(_) => &CheckCode::F403,
CheckKind::LateFutureImport => &CheckCode::F404,
@ -335,6 +341,7 @@ impl CheckKind {
format!("No such file or directory: `{name}`")
}
CheckKind::IfTuple => "If test is a tuple, which is always `True`".to_string(),
CheckKind::InvalidPrintSyntax => "use of >> is invalid with print function".to_string(),
CheckKind::ImportStarNotPermitted(name) => {
format!("`from {name} import *` only allowed at module level")
}

View File

@ -851,6 +851,31 @@ mod tests {
Ok(())
}
#[test]
fn f633() -> Result<()> {
let mut actual = check_path(
Path::new("./resources/test/fixtures/F633.py"),
&settings::Settings {
line_length: 88,
exclude: vec![],
select: BTreeSet::from([CheckCode::F633]),
},
&fixer::Mode::Generate,
)?;
actual.sort_by_key(|check| check.location);
let expected = vec![Check {
kind: CheckKind::InvalidPrintSyntax,
location: Location::new(4, 1),
fix: None,
}];
assert_eq!(actual.len(), expected.len());
for i in 0..actual.len() {
assert_eq!(actual[i], expected[i]);
}
Ok(())
}
#[test]
fn f634() -> Result<()> {
let mut actual = check_path(