Rename, etc.

This commit is contained in:
Charlie Marsh 2023-03-02 15:50:10 -05:00
parent 2558384817
commit ea86edf12e
9 changed files with 67 additions and 25 deletions

View File

@ -1,2 +1,7 @@
isinstance(1, (int, float))
issubclass("yes", (int, float, str))
isinstance(1, (int, float)) # UP038
issubclass("yes", (int, float, str)) # UP038
isinstance(1, int) # OK
issubclass("yes", int) # OK
isinstance(1, int | float) # OK
issubclass("yes", int | str) # OK

View File

@ -2584,7 +2584,7 @@ where
if self.settings.rules.enabled(&Rule::OSErrorAlias) {
pyupgrade::rules::os_error_alias(self, &expr);
}
if self.settings.rules.enabled(&Rule::IsInstanceTypingUnion) {
if self.settings.rules.enabled(&Rule::IsinstanceWithTuple) {
pyupgrade::rules::use_pep604_isinstance(self, expr, func, args);
}

View File

@ -344,7 +344,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<Rule> {
(Pyupgrade, "035") => Rule::ImportReplacements,
(Pyupgrade, "036") => Rule::OutdatedVersionBlock,
(Pyupgrade, "037") => Rule::QuotedAnnotation,
(Pyupgrade, "038") => Rule::IsInstanceTypingUnion,
(Pyupgrade, "038") => Rule::IsinstanceWithTuple,
// pydocstyle
(Pydocstyle, "100") => Rule::PublicModule,

View File

@ -331,7 +331,7 @@ ruff_macros::register_rules!(
rules::pyupgrade::rules::ImportReplacements,
rules::pyupgrade::rules::OutdatedVersionBlock,
rules::pyupgrade::rules::QuotedAnnotation,
rules::pyupgrade::rules::IsInstanceTypingUnion,
rules::pyupgrade::rules::IsinstanceWithTuple,
// pydocstyle
rules::pydocstyle::rules::PublicModule,
rules::pydocstyle::rules::PublicClass,

View File

@ -66,7 +66,7 @@ mod tests {
#[test_case(Rule::OutdatedVersionBlock, Path::new("UP036_3.py"); "UP036_3")]
#[test_case(Rule::OutdatedVersionBlock, Path::new("UP036_4.py"); "UP036_4")]
#[test_case(Rule::QuotedAnnotation, Path::new("UP037.py"); "UP037")]
#[test_case(Rule::IsInstanceTypingUnion, Path::new("UP038.py"); "UP038")]
#[test_case(Rule::IsinstanceWithTuple, Path::new("UP038.py"); "UP038")]
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
let snapshot = path.to_string_lossy().to_string();
let diagnostics = test_path(

View File

@ -39,7 +39,7 @@ pub(crate) use unnecessary_future_import::{unnecessary_future_import, Unnecessar
pub(crate) use unpack_list_comprehension::{unpack_list_comprehension, RewriteListComprehension};
pub(crate) use use_pep585_annotation::{use_pep585_annotation, DeprecatedCollectionType};
pub(crate) use use_pep604_annotation::{use_pep604_annotation, TypingUnion};
pub(crate) use use_pep604_isinstance::{use_pep604_isinstance, IsInstanceTypingUnion};
pub(crate) use use_pep604_isinstance::{use_pep604_isinstance, IsinstanceWithTuple};
pub(crate) use useless_metaclass_type::{useless_metaclass_type, UselessMetaclassType};
pub(crate) use useless_object_inheritance::{useless_object_inheritance, UselessObjectInheritance};

View File

@ -1,5 +1,7 @@
use ruff_macros::{define_violation, derive_message_formats};
use rustpython_parser::ast::{Expr, ExprKind, Location, Operator};
use serde::{Deserialize, Serialize};
use std::fmt;
use crate::ast::helpers::unparse_expr;
use crate::ast::types::Range;
@ -8,14 +10,41 @@ use crate::fix::Fix;
use crate::registry::Diagnostic;
use crate::violation::AlwaysAutofixableViolation;
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum CallKind {
Isinstance,
Issubclass,
}
impl fmt::Display for CallKind {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match self {
CallKind::Isinstance => fmt.write_str("isinstance"),
CallKind::Issubclass => fmt.write_str("issubclass"),
}
}
}
impl CallKind {
pub fn from_name(name: &str) -> Option<Self> {
match name {
"isinstance" => Some(CallKind::Isinstance),
"issubclass" => Some(CallKind::Issubclass),
_ => None,
}
}
}
define_violation!(
// TODO: document referencing [PEP 604]: https://peps.python.org/pep-0604/
pub struct IsInstanceTypingUnion;
pub struct IsinstanceWithTuple {
pub kind: CallKind,
}
);
impl AlwaysAutofixableViolation for IsInstanceTypingUnion {
impl AlwaysAutofixableViolation for IsinstanceWithTuple {
#[derive_message_formats]
fn message(&self) -> String {
format!("Use `X | Y` for type annotations")
format!("Use `X | Y` in `{}` call instead of `(X, Y)`", self.kind)
}
fn autofix_title(&self) -> String {
@ -41,20 +70,24 @@ fn union(elts: &[Expr]) -> Expr {
pub fn use_pep604_isinstance(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
if let ExprKind::Name { id, .. } = &func.node {
if (id == "isinstance" || id == "issubclass") && checker.is_builtin(id) {
if let Some(types) = args.get(1) {
if let ExprKind::Tuple { elts, .. } = &types.node {
let mut diagnostic =
Diagnostic::new(IsInstanceTypingUnion, Range::from_located(expr));
if checker.patch(diagnostic.kind.rule()) {
diagnostic.amend(Fix::replacement(
unparse_expr(&union(elts), checker.stylist),
types.location,
types.end_location.unwrap(),
));
}
checker.diagnostics.push(diagnostic);
let Some(kind) = CallKind::from_name(id) else {
return;
};
if !checker.is_builtin(id) {
return;
};
if let Some(types) = args.get(1) {
if let ExprKind::Tuple { elts, .. } = &types.node {
let mut diagnostic =
Diagnostic::new(IsinstanceWithTuple { kind }, Range::from_located(expr));
if checker.patch(diagnostic.kind.rule()) {
diagnostic.amend(Fix::replacement(
unparse_expr(&union(elts), checker.stylist),
types.location,
types.end_location.unwrap(),
));
}
checker.diagnostics.push(diagnostic);
}
}
}

View File

@ -3,7 +3,8 @@ source: crates/ruff/src/rules/pyupgrade/mod.rs
expression: diagnostics
---
- kind:
IsInstanceTypingUnion: ~
IsinstanceWithTuple:
kind: Isinstance
location:
row: 1
column: 0
@ -20,7 +21,8 @@ expression: diagnostics
column: 26
parent: ~
- kind:
IsInstanceTypingUnion: ~
IsinstanceWithTuple:
kind: Issubclass
location:
row: 2
column: 0

View File

@ -206,6 +206,8 @@ Options:
Run in watch mode by re-running whenever files change
--fix-only
Fix any fixable lint violations, but don't report on leftover violations. Implies `--fix`
--ignore-noqa
Ignore any `# noqa` comments
--format <FORMAT>
Output serialization format for violations [env: RUFF_FORMAT=] [possible values: text, json, junit, grouped, github, gitlab, pylint]
--target-version <TARGET_VERSION>