Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 9 commits into from
Dec 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)` | 🛠 |
Expand All @@ -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)

Expand Down
12 changes: 12 additions & 0 deletions resources/test/fixtures/pyupgrade/UP021.py
Original file line number Diff line number Diff line change
@@ -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)
1 change: 1 addition & 0 deletions ruff.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,7 @@
"UP019",
"UP02",
"UP020",
"UP021",
"W",
"W2",
"W29",
Expand Down
3 changes: 3 additions & 0 deletions src/checkers/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
13 changes: 11 additions & 2 deletions src/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ pub enum CheckCode {
UP018,
UP019,
UP020,
UP021,
// pydocstyle
D100,
D101,
Expand Down Expand Up @@ -841,6 +842,7 @@ pub enum CheckKind {
DatetimeTimezoneUTC,
NativeLiterals,
OpenAlias,
ReplaceUniversalNewlines,
// pydocstyle
BlankLineAfterLastSection(String),
BlankLineAfterSection(String),
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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")
}
Expand Down Expand Up @@ -3023,6 +3031,7 @@ impl CheckKind {
| CheckKind::NativeLiterals
| CheckKind::OpenAlias
| CheckKind::NewLineAfterLastParagraph
| CheckKind::ReplaceUniversalNewlines
| CheckKind::NewLineAfterSectionName(..)
| CheckKind::NoBlankLineAfterFunction(..)
| CheckKind::NoBlankLineBeforeClass(..)
Expand Down
9 changes: 8 additions & 1 deletion src/checks_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,7 @@ pub enum CheckCodePrefix {
UP019,
UP02,
UP020,
UP021,
W,
W2,
W29,
Expand Down Expand Up @@ -2107,6 +2108,7 @@ impl CheckCodePrefix {
CheckCode::UP018,
CheckCode::UP019,
CheckCode::UP020,
CheckCode::UP021,
]
}
CheckCodePrefix::U0 => {
Expand Down Expand Up @@ -2136,6 +2138,7 @@ impl CheckCodePrefix {
CheckCode::UP018,
CheckCode::UP019,
CheckCode::UP020,
CheckCode::UP021,
]
}
CheckCodePrefix::U00 => {
Expand Down Expand Up @@ -2349,6 +2352,7 @@ impl CheckCodePrefix {
CheckCode::UP018,
CheckCode::UP019,
CheckCode::UP020,
CheckCode::UP021,
],
CheckCodePrefix::UP0 => vec![
CheckCode::UP001,
Expand All @@ -2370,6 +2374,7 @@ impl CheckCodePrefix {
CheckCode::UP018,
CheckCode::UP019,
CheckCode::UP020,
CheckCode::UP021,
],
CheckCodePrefix::UP00 => vec![
CheckCode::UP001,
Expand Down Expand Up @@ -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],
Expand Down Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions src/pyupgrade/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
2 changes: 2 additions & 0 deletions src/pyupgrade/plugins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
36 changes: 36 additions & 0 deletions src/pyupgrade/plugins/replace_universal_newlines.rs
Original file line number Diff line number Diff line change
@@ -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(),
colin99d marked this conversation as resolved.
Show resolved Hide resolved
),
};
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);
}
}
Original file line number Diff line number Diff line change
@@ -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