Pyupgrade: converts `universal_newlines` to `text` in `subprocess.run` (#1403)

This commit is contained in:
Colin Delahunty 2022-12-27 17:01:27 +00:00 committed by GitHub
parent 7632d7eda7
commit c59035139c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 142 additions and 5 deletions

View File

@ -644,7 +644,7 @@ For more, see [pyupgrade](https://pypi.org/project/pyupgrade/3.2.0/) on PyPI.
| UP001 | UselessMetaclassType | `__metaclass__ = type` is implied | 🛠 |
| UP003 | TypeOfPrimitive | Use `str` instead of `type(...)` | 🛠 |
| UP004 | UselessObjectInheritance | Class `...` inherits from object | 🛠 |
| UP005 | DeprecatedUnittestAlias | `assertEquals` is deprecated, use `assertEqual` instead | 🛠 |
| UP005 | DeprecatedUnittestAlias | `assertEquals` is deprecated, use `assertEqual` | 🛠 |
| UP006 | UsePEP585Annotation | Use `list` instead of `List` for type annotations | 🛠 |
| UP007 | UsePEP604Annotation | Use `X \| Y` for type annotations | 🛠 |
| UP008 | SuperCallWithParameters | Use `super()` instead of `super(__class__, self)` | 🛠 |
@ -659,7 +659,8 @@ For more, see [pyupgrade](https://pypi.org/project/pyupgrade/3.2.0/) on PyPI.
| UP017 | DatetimeTimezoneUTC | Use `datetime.UTC` alias | 🛠 |
| UP018 | NativeLiterals | Unnecessary call to `str` and `bytes` | 🛠 |
| UP019 | TypingTextStrAlias | `typing.Text` is deprecated, use `str` | 🛠 |
| UP020 | OpenAlias | Use builtin `open` instead | 🛠 |
| UP020 | OpenAlias | Use builtin `open` | 🛠 |
| UP021 | ReplaceUniversalNewlines | `universal_newlines` is deprecated, use `text` | 🛠 |
### pep8-naming (N)

View File

@ -0,0 +1,12 @@
import subprocess
import subprocess as somename
from subprocess import run
from subprocess import run as anothername
subprocess.run(["foo"], universal_newlines=True, check=True)
somename.run(["foo"], universal_newlines=True)
run(["foo"], universal_newlines=True, check=False)
anothername(["foo"], universal_newlines=True)
subprocess.run(["foo"], check=True)

View File

@ -878,6 +878,7 @@
"UP019",
"UP02",
"UP020",
"UP021",
"W",
"W2",
"W29",

View File

@ -1654,6 +1654,9 @@ where
if self.settings.enabled.contains(&CheckCode::UP018) {
pyupgrade::plugins::native_literals(self, expr, func, args, keywords);
}
if self.settings.enabled.contains(&CheckCode::UP021) {
pyupgrade::plugins::replace_universal_newlines(self, expr, keywords);
}
// flake8-super
if self.settings.enabled.contains(&CheckCode::UP008) {

View File

@ -228,6 +228,7 @@ pub enum CheckCode {
UP018,
UP019,
UP020,
UP021,
// pydocstyle
D100,
D101,
@ -841,6 +842,7 @@ pub enum CheckKind {
DatetimeTimezoneUTC,
NativeLiterals,
OpenAlias,
ReplaceUniversalNewlines,
// pydocstyle
BlankLineAfterLastSection(String),
BlankLineAfterSection(String),
@ -1218,6 +1220,7 @@ impl CheckCode {
CheckCode::UP018 => CheckKind::NativeLiterals,
CheckCode::UP019 => CheckKind::TypingTextStrAlias,
CheckCode::UP020 => CheckKind::OpenAlias,
CheckCode::UP021 => CheckKind::ReplaceUniversalNewlines,
// pydocstyle
CheckCode::D100 => CheckKind::PublicModule,
CheckCode::D101 => CheckKind::PublicClass,
@ -1639,6 +1642,7 @@ impl CheckCode {
CheckCode::UP018 => CheckCategory::Pyupgrade,
CheckCode::UP019 => CheckCategory::Pyupgrade,
CheckCode::UP020 => CheckCategory::Pyupgrade,
CheckCode::UP021 => CheckCategory::Pyupgrade,
CheckCode::W292 => CheckCategory::Pycodestyle,
CheckCode::W605 => CheckCategory::Pycodestyle,
CheckCode::YTT101 => CheckCategory::Flake82020,
@ -1853,6 +1857,7 @@ impl CheckKind {
CheckKind::NativeLiterals => &CheckCode::UP018,
CheckKind::TypingTextStrAlias => &CheckCode::UP019,
CheckKind::OpenAlias => &CheckCode::UP020,
CheckKind::ReplaceUniversalNewlines => &CheckCode::UP021,
// pydocstyle
CheckKind::BlankLineAfterLastSection(..) => &CheckCode::D413,
CheckKind::BlankLineAfterSection(..) => &CheckCode::D410,
@ -2545,7 +2550,7 @@ impl CheckKind {
CheckKind::UselessMetaclassType => "`__metaclass__ = type` is implied".to_string(),
CheckKind::TypingTextStrAlias => "`typing.Text` is deprecated, use `str`".to_string(),
CheckKind::DeprecatedUnittestAlias(alias, target) => {
format!("`{alias}` is deprecated, use `{target}` instead")
format!("`{alias}` is deprecated, use `{target}`")
}
CheckKind::UselessObjectInheritance(name) => {
format!("Class `{name}` inherits from object")
@ -2578,10 +2583,13 @@ impl CheckKind {
CheckKind::RemoveSixCompat => "Unnecessary `six` compatibility usage".to_string(),
CheckKind::DatetimeTimezoneUTC => "Use `datetime.UTC` alias".to_string(),
CheckKind::NativeLiterals => "Unnecessary call to `str` and `bytes`".to_string(),
CheckKind::OpenAlias => "Use builtin `open` instead".to_string(),
CheckKind::OpenAlias => "Use builtin `open`".to_string(),
CheckKind::ConvertTypedDictFunctionalToClass(name) => {
format!("Convert `{name}` from `TypedDict` functional to class syntax")
}
CheckKind::ReplaceUniversalNewlines => {
"`universal_newlines` is deprecated, use `text`".to_string()
}
CheckKind::ConvertNamedTupleFunctionalToClass(name) => {
format!("Convert `{name}` from `NamedTuple` functional to class syntax")
}
@ -3023,6 +3031,7 @@ impl CheckKind {
| CheckKind::NativeLiterals
| CheckKind::OpenAlias
| CheckKind::NewLineAfterLastParagraph
| CheckKind::ReplaceUniversalNewlines
| CheckKind::NewLineAfterSectionName(..)
| CheckKind::NoBlankLineAfterFunction(..)
| CheckKind::NoBlankLineBeforeClass(..)

View File

@ -529,6 +529,7 @@ pub enum CheckCodePrefix {
UP019,
UP02,
UP020,
UP021,
W,
W2,
W29,
@ -2107,6 +2108,7 @@ impl CheckCodePrefix {
CheckCode::UP018,
CheckCode::UP019,
CheckCode::UP020,
CheckCode::UP021,
]
}
CheckCodePrefix::U0 => {
@ -2136,6 +2138,7 @@ impl CheckCodePrefix {
CheckCode::UP018,
CheckCode::UP019,
CheckCode::UP020,
CheckCode::UP021,
]
}
CheckCodePrefix::U00 => {
@ -2349,6 +2352,7 @@ impl CheckCodePrefix {
CheckCode::UP018,
CheckCode::UP019,
CheckCode::UP020,
CheckCode::UP021,
],
CheckCodePrefix::UP0 => vec![
CheckCode::UP001,
@ -2370,6 +2374,7 @@ impl CheckCodePrefix {
CheckCode::UP018,
CheckCode::UP019,
CheckCode::UP020,
CheckCode::UP021,
],
CheckCodePrefix::UP00 => vec![
CheckCode::UP001,
@ -2411,8 +2416,9 @@ impl CheckCodePrefix {
CheckCodePrefix::UP017 => vec![CheckCode::UP017],
CheckCodePrefix::UP018 => vec![CheckCode::UP018],
CheckCodePrefix::UP019 => vec![CheckCode::UP019],
CheckCodePrefix::UP02 => vec![CheckCode::UP020],
CheckCodePrefix::UP02 => vec![CheckCode::UP020, CheckCode::UP021],
CheckCodePrefix::UP020 => vec![CheckCode::UP020],
CheckCodePrefix::UP021 => vec![CheckCode::UP021],
CheckCodePrefix::W => vec![CheckCode::W292, CheckCode::W605],
CheckCodePrefix::W2 => vec![CheckCode::W292],
CheckCodePrefix::W29 => vec![CheckCode::W292],
@ -2973,6 +2979,7 @@ impl CheckCodePrefix {
CheckCodePrefix::UP019 => SuffixLength::Three,
CheckCodePrefix::UP02 => SuffixLength::Two,
CheckCodePrefix::UP020 => SuffixLength::Three,
CheckCodePrefix::UP021 => SuffixLength::Three,
CheckCodePrefix::W => SuffixLength::Zero,
CheckCodePrefix::W2 => SuffixLength::One,
CheckCodePrefix::W29 => SuffixLength::Two,

View File

@ -39,6 +39,7 @@ mod tests {
#[test_case(CheckCode::UP016, Path::new("UP016.py"); "UP016")]
#[test_case(CheckCode::UP018, Path::new("UP018.py"); "UP018")]
#[test_case(CheckCode::UP019, Path::new("UP019.py"); "UP019")]
#[test_case(CheckCode::UP021, Path::new("UP021.py"); "UP021")]
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

@ -6,6 +6,7 @@ pub use native_literals::native_literals;
pub use open_alias::open_alias;
pub use redundant_open_modes::redundant_open_modes;
pub use remove_six_compat::remove_six_compat;
pub use replace_universal_newlines::replace_universal_newlines;
pub use super_call_with_parameters::super_call_with_parameters;
pub use type_of_primitive::type_of_primitive;
pub use typing_text_str_alias::typing_text_str_alias;
@ -25,6 +26,7 @@ mod native_literals;
mod open_alias;
mod redundant_open_modes;
mod remove_six_compat;
mod replace_universal_newlines;
mod super_call_with_parameters;
mod type_of_primitive;
mod typing_text_str_alias;

View File

@ -0,0 +1,36 @@
use rustpython_ast::{Expr, Keyword, Location};
use crate::ast::helpers::{find_keyword, match_module_member};
use crate::ast::types::Range;
use crate::autofix::Fix;
use crate::checkers::ast::Checker;
use crate::checks::{Check, CheckKind};
/// UP021
pub fn replace_universal_newlines(checker: &mut Checker, expr: &Expr, kwargs: &[Keyword]) {
if match_module_member(
expr,
"subprocess",
"run",
&checker.from_imports,
&checker.import_aliases,
) {
let Some(kwarg) = find_keyword(kwargs, "universal_newlines") else { return; };
let range = Range {
location: kwarg.location,
end_location: Location::new(
kwarg.location.row(),
kwarg.location.column() + "universal_newlines".len(),
),
};
let mut check = Check::new(CheckKind::ReplaceUniversalNewlines, range);
if checker.patch(check.kind.code()) {
check.amend(Fix::replacement(
"text".to_string(),
range.location,
range.end_location,
));
}
checker.add_check(check);
}
}

View File

@ -0,0 +1,65 @@
---
source: src/pyupgrade/mod.rs
expression: checks
---
- kind: ReplaceUniversalNewlines
location:
row: 6
column: 24
end_location:
row: 6
column: 42
fix:
content: text
location:
row: 6
column: 24
end_location:
row: 6
column: 42
- kind: ReplaceUniversalNewlines
location:
row: 7
column: 22
end_location:
row: 7
column: 40
fix:
content: text
location:
row: 7
column: 22
end_location:
row: 7
column: 40
- kind: ReplaceUniversalNewlines
location:
row: 9
column: 13
end_location:
row: 9
column: 31
fix:
content: text
location:
row: 9
column: 13
end_location:
row: 9
column: 31
- kind: ReplaceUniversalNewlines
location:
row: 10
column: 21
end_location:
row: 10
column: 39
fix:
content: text
location:
row: 10
column: 21
end_location:
row: 10
column: 39