From 58c383401c8a286307e6b348fcfef8fecab612a7 Mon Sep 17 00:00:00 2001 From: Colin Delahunty <72827203+colin99d@users.noreply.github.com> Date: Tue, 27 Dec 2022 00:55:41 +0000 Subject: [PATCH] Replace `typing.Text` with `str` (#1391) --- README.md | 1 + resources/test/fixtures/pyupgrade/UP019.py | 20 ++++++ ruff.schema.json | 2 + src/checkers/ast.rs | 7 ++ src/checks.rs | 9 +++ src/checks_gen.rs | 20 ++++++ src/pyupgrade/checks.rs | 2 +- src/pyupgrade/mod.rs | 1 + src/pyupgrade/plugins/mod.rs | 2 + .../plugins/typing_text_str_alias.rs | 28 ++++++++ ...uff__pyupgrade__tests__UP019_UP019.py.snap | 65 +++++++++++++++++++ 11 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 resources/test/fixtures/pyupgrade/UP019.py create mode 100644 src/pyupgrade/plugins/typing_text_str_alias.rs create mode 100644 src/pyupgrade/snapshots/ruff__pyupgrade__tests__UP019_UP019.py.snap diff --git a/README.md b/README.md index e8d603fcd7..60020b6cd2 100644 --- a/README.md +++ b/README.md @@ -653,6 +653,7 @@ For more, see [pyupgrade](https://pypi.org/project/pyupgrade/3.2.0/) on PyPI. | UP016 | RemoveSixCompat | Unnecessary `six` compatibility usage | 🛠 | | UP017 | DatetimeTimezoneUTC | Use `datetime.UTC` alias | 🛠 | | UP018 | NativeLiterals | Unnecessary call to `str` and `bytes` | 🛠 | +| UP019 | TypingTextStrAlias | `typing.Text` is deprecated, use `str` | 🛠 | ### pep8-naming (N) diff --git a/resources/test/fixtures/pyupgrade/UP019.py b/resources/test/fixtures/pyupgrade/UP019.py new file mode 100644 index 0000000000..64c616ede5 --- /dev/null +++ b/resources/test/fixtures/pyupgrade/UP019.py @@ -0,0 +1,20 @@ +import typing +import typing as Hello +from typing import Text +from typing import Text as Goodbye + + +def print_word(word: Text) -> None: + print(word) + + +def print_second_word(word: typing.Text) -> None: + print(word) + + +def print_third_word(word: Hello.Text) -> None: + print(word) + + +def print_fourth_word(word: Goodbye) -> None: + print(word) diff --git a/ruff.schema.json b/ruff.schema.json index 423c9fcccf..9fe1a910ae 100644 --- a/ruff.schema.json +++ b/ruff.schema.json @@ -842,6 +842,7 @@ "U015", "U016", "U017", + "U019", "UP", "UP0", "UP00", @@ -863,6 +864,7 @@ "UP016", "UP017", "UP018", + "UP019", "W", "W2", "W29", diff --git a/src/checkers/ast.rs b/src/checkers/ast.rs index 4a649ea1b4..a29ae40b6f 100644 --- a/src/checkers/ast.rs +++ b/src/checkers/ast.rs @@ -1487,6 +1487,10 @@ where ExprKind::Name { id, ctx } => { match ctx { ExprContext::Load => { + if self.settings.enabled.contains(&CheckCode::UP019) { + pyupgrade::plugins::typing_text_str_alias(self, expr); + } + // Ex) List[...] if !self.in_deferred_string_type_definition && self.settings.enabled.contains(&CheckCode::UP006) @@ -1543,6 +1547,9 @@ where pyupgrade::plugins::use_pep585_annotation(self, expr, attr); } + if self.settings.enabled.contains(&CheckCode::UP019) { + pyupgrade::plugins::typing_text_str_alias(self, expr); + } if self.settings.enabled.contains(&CheckCode::UP016) { pyupgrade::plugins::remove_six_compat(self, expr); } diff --git a/src/checks.rs b/src/checks.rs index d4df2acb29..628ecc8d23 100644 --- a/src/checks.rs +++ b/src/checks.rs @@ -226,6 +226,7 @@ pub enum CheckCode { UP016, UP017, UP018, + UP019, // pydocstyle D100, D101, @@ -822,6 +823,7 @@ pub enum CheckKind { // pyupgrade TypeOfPrimitive(Primitive), UselessMetaclassType, + TypingTextStrAlias, DeprecatedUnittestAlias(String, String), UselessObjectInheritance(String), UsePEP585Annotation(String), @@ -1212,6 +1214,7 @@ impl CheckCode { CheckCode::UP016 => CheckKind::RemoveSixCompat, CheckCode::UP017 => CheckKind::DatetimeTimezoneUTC, CheckCode::UP018 => CheckKind::NativeLiterals, + CheckCode::UP019 => CheckKind::TypingTextStrAlias, // pydocstyle CheckCode::D100 => CheckKind::PublicModule, CheckCode::D101 => CheckKind::PublicClass, @@ -1631,6 +1634,7 @@ impl CheckCode { CheckCode::UP016 => CheckCategory::Pyupgrade, CheckCode::UP017 => CheckCategory::Pyupgrade, CheckCode::UP018 => CheckCategory::Pyupgrade, + CheckCode::UP019 => CheckCategory::Pyupgrade, CheckCode::W292 => CheckCategory::Pycodestyle, CheckCode::W605 => CheckCategory::Pycodestyle, CheckCode::YTT101 => CheckCategory::Flake82020, @@ -1843,6 +1847,7 @@ impl CheckKind { CheckKind::RemoveSixCompat => &CheckCode::UP016, CheckKind::DatetimeTimezoneUTC => &CheckCode::UP017, CheckKind::NativeLiterals => &CheckCode::UP018, + CheckKind::TypingTextStrAlias => &CheckCode::UP019, // pydocstyle CheckKind::BlankLineAfterLastSection(..) => &CheckCode::D413, CheckKind::BlankLineAfterSection(..) => &CheckCode::D410, @@ -2533,6 +2538,7 @@ impl CheckKind { format!("Use `{}` instead of `type(...)`", primitive.builtin()) } 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") } @@ -3042,6 +3048,7 @@ impl CheckKind { | CheckKind::SuperCallWithParameters | CheckKind::TrueFalseComparison(..) | CheckKind::TypeOfPrimitive(..) + | CheckKind::TypingTextStrAlias | CheckKind::UnnecessaryCallAroundSorted(..) | CheckKind::UnnecessaryCollectionCall(..) | CheckKind::UnnecessaryComprehension(..) @@ -3116,6 +3123,7 @@ pub static PREFIX_REDIRECTS: Lazy> = La ("U015", CheckCodePrefix::UP015), ("U016", CheckCodePrefix::UP016), ("U017", CheckCodePrefix::UP017), + ("U019", CheckCodePrefix::UP019), // TODO(charlie): Remove by 2023-02-01. ("I252", CheckCodePrefix::TID252), ("M001", CheckCodePrefix::RUF100), @@ -3191,6 +3199,7 @@ pub static CODE_REDIRECTS: Lazy> = Lazy::new( ("U015", CheckCode::UP015), ("U016", CheckCode::UP016), ("U017", CheckCode::UP017), + ("U019", CheckCode::UP019), // TODO(charlie): Remove by 2023-02-01. ("I252", CheckCode::TID252), ("M001", CheckCode::RUF100), diff --git a/src/checks_gen.rs b/src/checks_gen.rs index 79d0aafb51..476daa18a1 100644 --- a/src/checks_gen.rs +++ b/src/checks_gen.rs @@ -504,6 +504,7 @@ pub enum CheckCodePrefix { U015, U016, U017, + U019, UP, UP0, UP00, @@ -525,6 +526,7 @@ pub enum CheckCodePrefix { UP016, UP017, UP018, + UP019, W, W2, W29, @@ -2101,6 +2103,7 @@ impl CheckCodePrefix { CheckCode::UP016, CheckCode::UP017, CheckCode::UP018, + CheckCode::UP019, ] } CheckCodePrefix::U0 => { @@ -2128,6 +2131,7 @@ impl CheckCodePrefix { CheckCode::UP016, CheckCode::UP017, CheckCode::UP018, + CheckCode::UP019, ] } CheckCodePrefix::U00 => { @@ -2237,6 +2241,7 @@ impl CheckCodePrefix { CheckCode::UP016, CheckCode::UP017, CheckCode::UP018, + CheckCode::UP019, ] } CheckCodePrefix::U010 => { @@ -2311,6 +2316,15 @@ impl CheckCodePrefix { ); vec![CheckCode::UP017] } + CheckCodePrefix::U019 => { + one_time_warning!( + "{}{} {}", + "warning".yellow().bold(), + ":".bold(), + "`U019` has been remapped to `UP019`".bold() + ); + vec![CheckCode::UP019] + } CheckCodePrefix::UP => vec![ CheckCode::UP001, CheckCode::UP003, @@ -2329,6 +2343,7 @@ impl CheckCodePrefix { CheckCode::UP016, CheckCode::UP017, CheckCode::UP018, + CheckCode::UP019, ], CheckCodePrefix::UP0 => vec![ CheckCode::UP001, @@ -2348,6 +2363,7 @@ impl CheckCodePrefix { CheckCode::UP016, CheckCode::UP017, CheckCode::UP018, + CheckCode::UP019, ], CheckCodePrefix::UP00 => vec![ CheckCode::UP001, @@ -2377,6 +2393,7 @@ impl CheckCodePrefix { CheckCode::UP016, CheckCode::UP017, CheckCode::UP018, + CheckCode::UP019, ], CheckCodePrefix::UP010 => vec![CheckCode::UP010], CheckCodePrefix::UP011 => vec![CheckCode::UP011], @@ -2387,6 +2404,7 @@ impl CheckCodePrefix { CheckCodePrefix::UP016 => vec![CheckCode::UP016], CheckCodePrefix::UP017 => vec![CheckCode::UP017], CheckCodePrefix::UP018 => vec![CheckCode::UP018], + CheckCodePrefix::UP019 => vec![CheckCode::UP019], CheckCodePrefix::W => vec![CheckCode::W292, CheckCode::W605], CheckCodePrefix::W2 => vec![CheckCode::W292], CheckCodePrefix::W29 => vec![CheckCode::W292], @@ -2922,6 +2940,7 @@ impl CheckCodePrefix { CheckCodePrefix::U015 => SuffixLength::Three, CheckCodePrefix::U016 => SuffixLength::Three, CheckCodePrefix::U017 => SuffixLength::Three, + CheckCodePrefix::U019 => SuffixLength::Three, CheckCodePrefix::UP => SuffixLength::Zero, CheckCodePrefix::UP0 => SuffixLength::One, CheckCodePrefix::UP00 => SuffixLength::Two, @@ -2943,6 +2962,7 @@ impl CheckCodePrefix { CheckCodePrefix::UP016 => SuffixLength::Three, CheckCodePrefix::UP017 => SuffixLength::Three, CheckCodePrefix::UP018 => SuffixLength::Three, + CheckCodePrefix::UP019 => SuffixLength::Three, CheckCodePrefix::W => SuffixLength::Zero, CheckCodePrefix::W2 => SuffixLength::One, CheckCodePrefix::W29 => SuffixLength::Two, diff --git a/src/pyupgrade/checks.rs b/src/pyupgrade/checks.rs index 3202ee13fc..5463acd195 100644 --- a/src/pyupgrade/checks.rs +++ b/src/pyupgrade/checks.rs @@ -4,7 +4,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; use rustpython_ast::{Constant, KeywordData, Location}; use rustpython_parser::ast::{ArgData, Expr, ExprKind, Stmt, StmtKind}; -use crate::ast::helpers; +use crate::ast::helpers::{self}; use crate::ast::types::{Binding, BindingKind, Range, Scope, ScopeKind}; use crate::autofix::Fix; use crate::checks::{Check, CheckKind}; diff --git a/src/pyupgrade/mod.rs b/src/pyupgrade/mod.rs index aabb47074f..1c79efbeac 100644 --- a/src/pyupgrade/mod.rs +++ b/src/pyupgrade/mod.rs @@ -38,6 +38,7 @@ mod tests { #[test_case(CheckCode::UP015, Path::new("UP015.py"); "UP015")] #[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")] fn checks(check_code: CheckCode, path: &Path) -> Result<()> { let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy()); let mut checks = test_path( diff --git a/src/pyupgrade/plugins/mod.rs b/src/pyupgrade/plugins/mod.rs index 8dfd47a2ea..132933b552 100644 --- a/src/pyupgrade/plugins/mod.rs +++ b/src/pyupgrade/plugins/mod.rs @@ -7,6 +7,7 @@ pub use redundant_open_modes::redundant_open_modes; pub use remove_six_compat::remove_six_compat; 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; pub use unnecessary_encode_utf8::unnecessary_encode_utf8; pub use unnecessary_future_import::unnecessary_future_import; pub use unnecessary_lru_cache_params::unnecessary_lru_cache_params; @@ -24,6 +25,7 @@ mod redundant_open_modes; mod remove_six_compat; mod super_call_with_parameters; mod type_of_primitive; +mod typing_text_str_alias; mod unnecessary_encode_utf8; mod unnecessary_future_import; mod unnecessary_lru_cache_params; diff --git a/src/pyupgrade/plugins/typing_text_str_alias.rs b/src/pyupgrade/plugins/typing_text_str_alias.rs new file mode 100644 index 0000000000..e2bba83516 --- /dev/null +++ b/src/pyupgrade/plugins/typing_text_str_alias.rs @@ -0,0 +1,28 @@ +use rustpython_ast::Expr; + +use crate::ast::helpers::match_module_member; +use crate::ast::types::Range; +use crate::autofix::Fix; +use crate::checkers::ast::Checker; +use crate::checks::{Check, CheckKind}; + +/// UP019 +pub fn typing_text_str_alias(checker: &mut Checker, expr: &Expr) { + if match_module_member( + expr, + "typing", + "Text", + &checker.from_imports, + &checker.import_aliases, + ) { + let mut check = Check::new(CheckKind::TypingTextStrAlias, Range::from_located(expr)); + if checker.patch(check.kind.code()) { + check.amend(Fix::replacement( + "str".to_string(), + expr.location, + expr.end_location.unwrap(), + )); + } + checker.add_check(check); + } +} diff --git a/src/pyupgrade/snapshots/ruff__pyupgrade__tests__UP019_UP019.py.snap b/src/pyupgrade/snapshots/ruff__pyupgrade__tests__UP019_UP019.py.snap new file mode 100644 index 0000000000..dcfec93194 --- /dev/null +++ b/src/pyupgrade/snapshots/ruff__pyupgrade__tests__UP019_UP019.py.snap @@ -0,0 +1,65 @@ +--- +source: src/pyupgrade/mod.rs +expression: checks +--- +- kind: TypingTextStrAlias + location: + row: 7 + column: 21 + end_location: + row: 7 + column: 25 + fix: + content: str + location: + row: 7 + column: 21 + end_location: + row: 7 + column: 25 +- kind: TypingTextStrAlias + location: + row: 11 + column: 28 + end_location: + row: 11 + column: 39 + fix: + content: str + location: + row: 11 + column: 28 + end_location: + row: 11 + column: 39 +- kind: TypingTextStrAlias + location: + row: 15 + column: 27 + end_location: + row: 15 + column: 37 + fix: + content: str + location: + row: 15 + column: 27 + end_location: + row: 15 + column: 37 +- kind: TypingTextStrAlias + location: + row: 19 + column: 28 + end_location: + row: 19 + column: 35 + fix: + content: str + location: + row: 19 + column: 28 + end_location: + row: 19 + column: 35 +