Implement E401 ("multiple imports on one line") (#1326)

This commit is contained in:
Charlie Marsh 2022-12-21 21:15:57 -05:00 committed by GitHub
parent 40377aa1fc
commit 99657b7d92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 145 additions and 20 deletions

View File

@ -517,6 +517,7 @@ For more, see [pycodestyle](https://pypi.org/project/pycodestyle/2.9.1/) on PyPI
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| E401 | MultipleImportsOnOneLine | Multiple imports on one line | |
| E402 | ModuleImportNotAtTopOfFile | Module level import not at top of file | |
| E501 | LineTooLong | Line too long (89 > 88 characters) | |
| E711 | NoneComparison | Comparison to `None` should be `cond is None` | 🛠 |

View File

@ -0,0 +1,61 @@
#: E401
import os, sys
#: Okay
import os
import sys
from subprocess import Popen, PIPE
from myclass import MyClass
from foo.bar.yourclass import YourClass
import myclass
import foo.bar.yourclass
#: Okay
__all__ = ['abc']
import foo
#: Okay
__version__ = "42"
import foo
#: Okay
__author__ = "Simon Gomizelj"
import foo
#: Okay
try:
import foo
except ImportError:
pass
else:
print('imported foo')
finally:
print('made attempt to import foo')
import bar
#: Okay
with warnings.catch_warnings():
warnings.filterwarnings("ignore", DeprecationWarning)
import foo
import bar
#: Okay
if False:
import foo
elif not True:
import bar
else:
import mwahaha
import bar
#: E402
VERSION = '1.2.3'
import foo
#: E402
import foo
a = 1
import bar

View File

@ -628,6 +628,15 @@ where
}
}
StmtKind::Import { names } => {
if self.settings.enabled.contains(&CheckCode::E401) {
if names.len() > 1 {
self.add_check(Check::new(
CheckKind::MultipleImportsOnOneLine,
Range::from_located(stmt),
));
}
}
if self.settings.enabled.contains(&CheckCode::E402) {
if self.seen_import_boundary && stmt.location.column() == 0 {
self.add_check(Check::new(

View File

@ -33,6 +33,7 @@ use crate::pyupgrade::types::Primitive;
)]
pub enum CheckCode {
// pycodestyle errors
E401,
E402,
E501,
E711,
@ -644,6 +645,7 @@ pub enum CheckKind {
IOError(String),
LineTooLong(usize, usize),
ModuleImportNotAtTopOfFile,
MultipleImportsOnOneLine,
NoneComparison(RejectedCmpop),
NotInTest,
NotIsTest,
@ -978,6 +980,7 @@ impl CheckCode {
pub fn kind(&self) -> CheckKind {
match self {
// pycodestyle errors
CheckCode::E401 => CheckKind::MultipleImportsOnOneLine,
CheckCode::E402 => CheckKind::ModuleImportNotAtTopOfFile,
CheckCode::E501 => CheckKind::LineTooLong(89, 88),
CheckCode::E711 => CheckKind::NoneComparison(RejectedCmpop::Eq),
@ -1462,6 +1465,7 @@ impl CheckCode {
CheckCode::DTZ007 => CheckCategory::Flake8Datetimez,
CheckCode::DTZ011 => CheckCategory::Flake8Datetimez,
CheckCode::DTZ012 => CheckCategory::Flake8Datetimez,
CheckCode::E401 => CheckCategory::Pycodestyle,
CheckCode::E402 => CheckCategory::Pycodestyle,
CheckCode::E501 => CheckCategory::Pycodestyle,
CheckCode::E711 => CheckCategory::Pycodestyle,
@ -1657,6 +1661,7 @@ impl CheckKind {
CheckKind::IsLiteral => &CheckCode::F632,
CheckKind::LateFutureImport => &CheckCode::F404,
CheckKind::LineTooLong(..) => &CheckCode::E501,
CheckKind::MultipleImportsOnOneLine => &CheckCode::E401,
CheckKind::ModuleImportNotAtTopOfFile => &CheckCode::E402,
CheckKind::MultiValueRepeatedKeyLiteral => &CheckCode::F601,
CheckKind::MultiValueRepeatedKeyVariable(_) => &CheckCode::F602,
@ -2016,6 +2021,7 @@ impl CheckKind {
CheckKind::ModuleImportNotAtTopOfFile => {
"Module level import not at top of file".to_string()
}
CheckKind::MultipleImportsOnOneLine => "Multiple imports on one line".to_string(),
CheckKind::MultiValueRepeatedKeyLiteral => {
"Dictionary key literal repeated".to_string()
}

View File

@ -179,6 +179,7 @@ pub enum CheckCodePrefix {
E,
E4,
E40,
E401,
E402,
E5,
E50,
@ -1063,6 +1064,7 @@ impl CheckCodePrefix {
CheckCodePrefix::DTZ011 => vec![CheckCode::DTZ011],
CheckCodePrefix::DTZ012 => vec![CheckCode::DTZ012],
CheckCodePrefix::E => vec![
CheckCode::E401,
CheckCode::E402,
CheckCode::E501,
CheckCode::E711,
@ -1078,8 +1080,9 @@ impl CheckCodePrefix {
CheckCode::E902,
CheckCode::E999,
],
CheckCodePrefix::E4 => vec![CheckCode::E402],
CheckCodePrefix::E40 => vec![CheckCode::E402],
CheckCodePrefix::E4 => vec![CheckCode::E401, CheckCode::E402],
CheckCodePrefix::E40 => vec![CheckCode::E401, CheckCode::E402],
CheckCodePrefix::E401 => vec![CheckCode::E401],
CheckCodePrefix::E402 => vec![CheckCode::E402],
CheckCodePrefix::E5 => vec![CheckCode::E501],
CheckCodePrefix::E50 => vec![CheckCode::E501],
@ -2568,6 +2571,7 @@ impl CheckCodePrefix {
CheckCodePrefix::E => SuffixLength::Zero,
CheckCodePrefix::E4 => SuffixLength::One,
CheckCodePrefix::E40 => SuffixLength::Two,
CheckCodePrefix::E401 => SuffixLength::Three,
CheckCodePrefix::E402 => SuffixLength::Three,
CheckCodePrefix::E5 => SuffixLength::One,
CheckCodePrefix::E50 => SuffixLength::Two,

View File

@ -13,24 +13,26 @@ mod tests {
use crate::linter::test_path;
use crate::settings;
#[test_case(CheckCode::E402, Path::new("E402.py"); "E402")]
#[test_case(CheckCode::E501, Path::new("E501.py"); "E501")]
#[test_case(CheckCode::E711, Path::new("E711.py"); "E711")]
#[test_case(CheckCode::E712, Path::new("E712.py"); "E712")]
#[test_case(CheckCode::E713, Path::new("E713.py"); "E713")]
#[test_case(CheckCode::E714, Path::new("E714.py"); "E714")]
#[test_case(CheckCode::E721, Path::new("E721.py"); "E721")]
#[test_case(CheckCode::E722, Path::new("E722.py"); "E722")]
#[test_case(CheckCode::E731, Path::new("E731.py"); "E731")]
#[test_case(CheckCode::E741, Path::new("E741.py"); "E741")]
#[test_case(CheckCode::E742, Path::new("E742.py"); "E742")]
#[test_case(CheckCode::E743, Path::new("E743.py"); "E743")]
#[test_case(CheckCode::E999, Path::new("E999.py"); "E999")]
#[test_case(CheckCode::W292, Path::new("W292_0.py"); "W292_0")]
#[test_case(CheckCode::W292, Path::new("W292_1.py"); "W292_1")]
#[test_case(CheckCode::W292, Path::new("W292_2.py"); "W292_2")]
#[test_case(CheckCode::W605, Path::new("W605_0.py"); "W605_0")]
#[test_case(CheckCode::W605, Path::new("W605_1.py"); "W605_1")]
#[test_case(CheckCode::E401, Path::new("E40.py"))]
#[test_case(CheckCode::E402, Path::new("E40.py"))]
#[test_case(CheckCode::E402, Path::new("E402.py"))]
#[test_case(CheckCode::E501, Path::new("E501.py"))]
#[test_case(CheckCode::E711, Path::new("E711.py"))]
#[test_case(CheckCode::E712, Path::new("E712.py"))]
#[test_case(CheckCode::E713, Path::new("E713.py"))]
#[test_case(CheckCode::E714, Path::new("E714.py"))]
#[test_case(CheckCode::E721, Path::new("E721.py"))]
#[test_case(CheckCode::E722, Path::new("E722.py"))]
#[test_case(CheckCode::E731, Path::new("E731.py"))]
#[test_case(CheckCode::E741, Path::new("E741.py"))]
#[test_case(CheckCode::E742, Path::new("E742.py"))]
#[test_case(CheckCode::E743, Path::new("E743.py"))]
#[test_case(CheckCode::E999, Path::new("E999.py"))]
#[test_case(CheckCode::W292, Path::new("W292_0.py"))]
#[test_case(CheckCode::W292, Path::new("W292_1.py"))]
#[test_case(CheckCode::W292, Path::new("W292_2.py"))]
#[test_case(CheckCode::W605, Path::new("W605_0.py"))]
#[test_case(CheckCode::W605, Path::new("W605_1.py"))]
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy());
let mut checks = test_path(

View File

@ -0,0 +1,13 @@
---
source: src/pycodestyle/mod.rs
expression: checks
---
- kind: MultipleImportsOnOneLine
location:
row: 2
column: 0
end_location:
row: 2
column: 14
fix: ~

View File

@ -0,0 +1,29 @@
---
source: src/pycodestyle/mod.rs
expression: checks
---
- kind: ModuleImportNotAtTopOfFile
location:
row: 55
column: 0
end_location:
row: 55
column: 10
fix: ~
- kind: ModuleImportNotAtTopOfFile
location:
row: 57
column: 0
end_location:
row: 57
column: 10
fix: ~
- kind: ModuleImportNotAtTopOfFile
location:
row: 61
column: 0
end_location:
row: 61
column: 10
fix: ~