mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-28 04:44:51 +00:00
Reduce indents (#1116)
This commit is contained in:
parent
92b9ab3010
commit
c5451cd8ad
27 changed files with 594 additions and 561 deletions
19
src/cache.rs
19
src/cache.rs
|
@ -139,20 +139,21 @@ pub fn get(
|
|||
return None;
|
||||
};
|
||||
|
||||
if let Ok(encoded) = read_sync(cache_key(path, settings, autofix)) {
|
||||
match bincode::deserialize::<CheckResult>(&encoded[..]) {
|
||||
let encoded = read_sync(cache_key(path, settings, autofix)).ok()?;
|
||||
let (mtime, messages) = match bincode::deserialize::<CheckResult>(&encoded[..]) {
|
||||
Ok(CheckResult {
|
||||
metadata: CacheMetadata { mtime },
|
||||
messages,
|
||||
}) => {
|
||||
if FileTime::from_last_modification_time(metadata).unix_seconds() == mtime {
|
||||
return Some(messages);
|
||||
}) => (mtime, messages),
|
||||
Err(e) => {
|
||||
error!("Failed to deserialize encoded cache entry: {e:?}");
|
||||
return None;
|
||||
}
|
||||
};
|
||||
if FileTime::from_last_modification_time(metadata).unix_seconds() != mtime {
|
||||
return None;
|
||||
}
|
||||
Err(e) => error!("Failed to deserialize encoded cache entry: {e:?}"),
|
||||
}
|
||||
}
|
||||
None
|
||||
Some(messages)
|
||||
}
|
||||
|
||||
/// Set a value in the cache.
|
||||
|
|
|
@ -142,15 +142,16 @@ impl<'a> Checker<'a> {
|
|||
// If we're in an f-string, override the location. RustPython doesn't produce
|
||||
// reliable locations for expressions within f-strings, so we use the
|
||||
// span of the f-string itself as a best-effort default.
|
||||
if let Some(range) = self.in_f_string {
|
||||
self.checks.push(Check {
|
||||
let check = if let Some(range) = self.in_f_string {
|
||||
Check {
|
||||
location: range.location,
|
||||
end_location: range.end_location,
|
||||
..check
|
||||
});
|
||||
} else {
|
||||
self.checks.push(check);
|
||||
}
|
||||
} else {
|
||||
check
|
||||
};
|
||||
self.checks.push(check);
|
||||
}
|
||||
|
||||
/// Add multiple `Check` items to the `Checker`.
|
||||
|
|
|
@ -20,19 +20,18 @@ static URL_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"^https?://\S+$").unwra
|
|||
|
||||
/// Whether the given line is too long and should be reported.
|
||||
fn should_enforce_line_length(line: &str, length: usize, limit: usize) -> bool {
|
||||
if length > limit {
|
||||
if length <= limit {
|
||||
return false;
|
||||
}
|
||||
let mut chunks = line.split_whitespace();
|
||||
if let (Some(first), Some(_)) = (chunks.next(), chunks.next()) {
|
||||
let (Some(first), Some(_)) = (chunks.next(), chunks.next()) else {
|
||||
// Single word / no printable chars - no way to make the line shorter
|
||||
return false;
|
||||
};
|
||||
|
||||
// Do not enforce the line length for commented lines that end with a URL
|
||||
// or contain only a single word.
|
||||
!(first == "#" && chunks.last().map_or(true, |c| URL_REGEX.is_match(c)))
|
||||
} else {
|
||||
// Single word / no printable chars - no way to make the line shorter
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_lines(
|
||||
|
|
|
@ -93,7 +93,10 @@ pub fn extract_isort_directives(lxr: &[LexResult], locator: &SourceCodeLocator)
|
|||
continue;
|
||||
}
|
||||
|
||||
if matches!(tok, Tok::Comment) {
|
||||
if !matches!(tok, Tok::Comment) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO(charlie): Modify RustPython to include the comment text in the token.
|
||||
let comment_text = locator.slice_source_code_range(&Range {
|
||||
location: start,
|
||||
|
@ -121,7 +124,6 @@ pub fn extract_isort_directives(lxr: &[LexResult], locator: &SourceCodeLocator)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if skip_file {
|
||||
// Enforce `isort: skip_file`.
|
||||
if let Some(end) = last {
|
||||
|
|
|
@ -25,13 +25,15 @@ impl TryFrom<&str> for CFormatSummary {
|
|||
let mut keywords = FxHashSet::default();
|
||||
|
||||
for format_part in format_string.parts {
|
||||
if let CFormatPart::Spec(CFormatSpec {
|
||||
let CFormatPart::Spec(CFormatSpec {
|
||||
mapping_key,
|
||||
min_field_width,
|
||||
precision,
|
||||
..
|
||||
}) = format_part.1
|
||||
}) = format_part.1 else
|
||||
{
|
||||
continue;
|
||||
};
|
||||
match mapping_key {
|
||||
Some(k) => {
|
||||
keywords.insert(k);
|
||||
|
@ -49,7 +51,6 @@ impl TryFrom<&str> for CFormatSummary {
|
|||
starred = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(CFormatSummary {
|
||||
starred,
|
||||
|
|
|
@ -77,8 +77,9 @@ pub(crate) fn percent_format_extra_named_arguments(
|
|||
if summary.num_positional > 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
if let ExprKind::Dict { keys, values } = &right.node {
|
||||
let ExprKind::Dict { keys, values } = &right.node else {
|
||||
return None;
|
||||
};
|
||||
if values.len() > keys.len() {
|
||||
return None; // contains **x splat
|
||||
}
|
||||
|
@ -102,18 +103,13 @@ pub(crate) fn percent_format_extra_named_arguments(
|
|||
.collect();
|
||||
|
||||
if missing.is_empty() {
|
||||
None
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(Check::new(
|
||||
CheckKind::PercentFormatExtraNamedArguments(
|
||||
missing.iter().map(|&s| s.clone()).collect(),
|
||||
),
|
||||
CheckKind::PercentFormatExtraNamedArguments(missing.iter().map(|&s| s.clone()).collect()),
|
||||
location,
|
||||
))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// F505
|
||||
|
|
|
@ -43,12 +43,13 @@ impl TryFrom<&str> for FormatSummary {
|
|||
let mut keywords = FxHashSet::default();
|
||||
|
||||
for format_part in format_string.format_parts {
|
||||
if let FormatPart::Field {
|
||||
let FormatPart::Field {
|
||||
field_name,
|
||||
format_spec,
|
||||
..
|
||||
} = format_part
|
||||
{
|
||||
} = format_part else {
|
||||
continue;
|
||||
};
|
||||
let parsed = FieldName::parse(&field_name)?;
|
||||
match parsed.field_type {
|
||||
FieldType::Auto => autos.insert(autos.len()),
|
||||
|
@ -58,7 +59,9 @@ impl TryFrom<&str> for FormatSummary {
|
|||
|
||||
let nested = FormatString::from_str(&format_spec)?;
|
||||
for nested_part in nested.format_parts {
|
||||
if let FormatPart::Field { field_name, .. } = nested_part {
|
||||
let FormatPart::Field { field_name, .. } = nested_part else {
|
||||
continue;
|
||||
};
|
||||
let parsed = FieldName::parse(&field_name)?;
|
||||
match parsed.field_type {
|
||||
FieldType::Auto => autos.insert(autos.len()),
|
||||
|
@ -67,8 +70,6 @@ impl TryFrom<&str> for FormatSummary {
|
|||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(FormatSummary {
|
||||
autos,
|
||||
|
|
|
@ -6,19 +6,22 @@ use crate::checks::{Check, CheckKind};
|
|||
|
||||
/// F633
|
||||
pub fn invalid_print_syntax(checker: &mut Checker, left: &Expr) {
|
||||
if let ExprKind::Name { id, .. } = &left.node {
|
||||
if id == "print" {
|
||||
let ExprKind::Name { id, .. } = &left.node else {
|
||||
return;
|
||||
};
|
||||
if id != "print" {
|
||||
return;
|
||||
}
|
||||
let scope = checker.current_scope();
|
||||
if let Some(Binding {
|
||||
let Some(Binding {
|
||||
kind: BindingKind::Builtin,
|
||||
..
|
||||
}) = scope.values.get("print")
|
||||
}) = scope.values.get("print") else
|
||||
{
|
||||
return;
|
||||
};
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::InvalidPrintSyntax,
|
||||
Range::from_located(left),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,9 @@ fn match_not_implemented(expr: &Expr) -> Option<&Expr> {
|
|||
|
||||
/// F901
|
||||
pub fn raise_not_implemented(checker: &mut Checker, expr: &Expr) {
|
||||
if let Some(expr) = match_not_implemented(expr) {
|
||||
let Some(expr) = match_not_implemented(expr) else {
|
||||
return;
|
||||
};
|
||||
let mut check = Check::new(CheckKind::RaiseNotImplemented, Range::from_located(expr));
|
||||
if checker.patch(check.kind.code()) {
|
||||
check.amend(Fix::replacement(
|
||||
|
@ -36,5 +38,4 @@ pub fn raise_not_implemented(checker: &mut Checker, expr: &Expr) {
|
|||
));
|
||||
}
|
||||
checker.add_check(check);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,11 +5,14 @@ use crate::check_ast::Checker;
|
|||
use crate::checks::{Check, CheckKind};
|
||||
|
||||
pub fn no_eval(checker: &mut Checker, func: &Expr) {
|
||||
if let ExprKind::Name { id, .. } = &func.node {
|
||||
if id == "eval" {
|
||||
if checker.is_builtin("eval") {
|
||||
let ExprKind::Name { id, .. } = &func.node else {
|
||||
return;
|
||||
};
|
||||
if id != "eval" {
|
||||
return;
|
||||
}
|
||||
if !checker.is_builtin("eval") {
|
||||
return;
|
||||
}
|
||||
checker.add_check(Check::new(CheckKind::NoEval, Range::from_located(func)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,9 +20,15 @@ pub fn consider_merging_isinstance(
|
|||
|
||||
let mut obj_to_types: FxHashMap<String, (usize, FxHashSet<String>)> = FxHashMap::default();
|
||||
for value in values {
|
||||
if let ExprKind::Call { func, args, .. } = &value.node {
|
||||
if matches!(&func.node, ExprKind::Name { id, .. } if id == "isinstance") {
|
||||
if let [obj, types] = &args[..] {
|
||||
let ExprKind::Call { func, args, .. } = &value.node else {
|
||||
continue;
|
||||
};
|
||||
if !matches!(&func.node, ExprKind::Name { id, .. } if id == "isinstance") {
|
||||
continue;
|
||||
}
|
||||
let [obj, types] = &args[..] else {
|
||||
continue;
|
||||
};
|
||||
let (num_calls, matches) = obj_to_types
|
||||
.entry(obj.to_string())
|
||||
.or_insert_with(|| (0, FxHashSet::default()));
|
||||
|
@ -37,9 +43,6 @@ pub fn consider_merging_isinstance(
|
|||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (obj, (num_calls, types)) in obj_to_types {
|
||||
if num_calls > 1 && types.len() > 1 {
|
||||
|
|
|
@ -7,14 +7,17 @@ use crate::Check;
|
|||
|
||||
/// PLR0402
|
||||
pub fn consider_using_from_import(checker: &mut Checker, alias: &Alias) {
|
||||
if let Some(asname) = &alias.node.asname {
|
||||
if let Some((module, name)) = alias.node.name.rsplit_once('.') {
|
||||
if name == asname {
|
||||
let Some(asname) = &alias.node.asname else {
|
||||
return;
|
||||
};
|
||||
let Some((module, name)) = alias.node.name.rsplit_once('.') else {
|
||||
return;
|
||||
};
|
||||
if name != asname {
|
||||
return;
|
||||
}
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::ConsiderUsingFromImport(module.to_string(), name.to_string()),
|
||||
Range::from_located(alias),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,17 +61,22 @@ fn get_member_import_name_alias(checker: &Checker, module: &str, member: &str) -
|
|||
|
||||
/// RUF004
|
||||
pub fn consider_using_sys_exit(checker: &mut Checker, func: &Expr) {
|
||||
if let ExprKind::Name { id, .. } = &func.node {
|
||||
let ExprKind::Name { id, .. } = &func.node else {
|
||||
return;
|
||||
};
|
||||
for name in ["exit", "quit"] {
|
||||
if id == name {
|
||||
if !(name == "exit" && is_module_star_imported(checker, "sys"))
|
||||
&& checker.is_builtin(name)
|
||||
{
|
||||
let mut check =
|
||||
Check::new(CheckKind::ConsiderUsingSysExit, Range::from_located(func));
|
||||
if id != name {
|
||||
continue;
|
||||
}
|
||||
if name == "exit" && is_module_star_imported(checker, "sys") {
|
||||
continue;
|
||||
}
|
||||
if !checker.is_builtin(name) {
|
||||
continue;
|
||||
}
|
||||
let mut check = Check::new(CheckKind::ConsiderUsingSysExit, Range::from_located(func));
|
||||
if checker.patch(check.kind.code()) {
|
||||
if let Some(content) = get_member_import_name_alias(checker, "sys", "exit")
|
||||
{
|
||||
if let Some(content) = get_member_import_name_alias(checker, "sys", "exit") {
|
||||
check.amend(Fix::replacement(
|
||||
content,
|
||||
func.location,
|
||||
|
@ -81,7 +86,4 @@ pub fn consider_using_sys_exit(checker: &mut Checker, func: &Expr) {
|
|||
}
|
||||
checker.add_check(check);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,13 +14,23 @@ pub fn misplaced_comparison_constant(
|
|||
ops: &[Cmpop],
|
||||
comparators: &[Expr],
|
||||
) {
|
||||
if let ([op], [right]) = (ops, comparators) {
|
||||
if matches!(
|
||||
let ([op], [right]) = (ops, comparators) else {
|
||||
return;
|
||||
};
|
||||
|
||||
if !matches!(
|
||||
op,
|
||||
Cmpop::Eq | Cmpop::NotEq | Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE,
|
||||
) && matches!(&left.node, &ExprKind::Constant { .. })
|
||||
&& !matches!(&right.node, &ExprKind::Constant { .. })
|
||||
{
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if !matches!(&left.node, &ExprKind::Constant { .. }) {
|
||||
return;
|
||||
}
|
||||
if matches!(&right.node, &ExprKind::Constant { .. }) {
|
||||
return;
|
||||
}
|
||||
|
||||
let reversed_op = match op {
|
||||
Cmpop::Eq => "==",
|
||||
Cmpop::NotEq => "!=",
|
||||
|
@ -43,6 +53,4 @@ pub fn misplaced_comparison_constant(
|
|||
));
|
||||
}
|
||||
checker.add_check(check);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,10 +12,12 @@ pub fn property_with_parameters(
|
|||
decorator_list: &[Expr],
|
||||
args: &Arguments,
|
||||
) {
|
||||
if decorator_list
|
||||
if !decorator_list
|
||||
.iter()
|
||||
.any(|d| matches!(&d.node, ExprKind::Name { id, .. } if id == "property"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if checker.is_builtin("property")
|
||||
&& args
|
||||
.args
|
||||
|
@ -30,5 +32,4 @@ pub fn property_with_parameters(
|
|||
Range::from_located(stmt),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,8 +8,16 @@ use crate::Check;
|
|||
|
||||
/// PLC0414
|
||||
pub fn useless_import_alias(checker: &mut Checker, alias: &Alias) {
|
||||
if let Some(asname) = &alias.node.asname {
|
||||
if !alias.node.name.contains('.') && &alias.node.name == asname {
|
||||
let Some(asname) = &alias.node.asname else {
|
||||
return;
|
||||
};
|
||||
if alias.node.name.contains('.') {
|
||||
return;
|
||||
}
|
||||
if &alias.node.name != asname {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut check = Check::new(CheckKind::UselessImportAlias, Range::from_located(alias));
|
||||
if checker.patch(check.kind.code()) {
|
||||
check.amend(Fix::replacement(
|
||||
|
@ -19,6 +27,4 @@ pub fn useless_import_alias(checker: &mut Checker, alias: &Alias) {
|
|||
));
|
||||
}
|
||||
checker.add_check(check);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,9 +113,16 @@ pub fn remove_super_arguments(locator: &SourceCodeLocator, expr: &Expr) -> Optio
|
|||
|
||||
let mut tree = libcst_native::parse_module(&contents, None).ok()?;
|
||||
|
||||
if let Some(Statement::Simple(body)) = tree.body.first_mut() {
|
||||
if let Some(SmallStatement::Expr(body)) = body.body.first_mut() {
|
||||
if let Expression::Call(body) = &mut body.value {
|
||||
let Statement::Simple(body) = tree.body.first_mut()? else {
|
||||
return None;
|
||||
};
|
||||
let SmallStatement::Expr(body) = body.body.first_mut()? else {
|
||||
return None;
|
||||
};
|
||||
let Expression::Call(body) = &mut body.value else {
|
||||
return None;
|
||||
};
|
||||
|
||||
body.args = vec![];
|
||||
body.whitespace_before_args = ParenthesizableWhitespace::default();
|
||||
body.whitespace_after_func = ParenthesizableWhitespace::default();
|
||||
|
@ -123,16 +130,11 @@ pub fn remove_super_arguments(locator: &SourceCodeLocator, expr: &Expr) -> Optio
|
|||
let mut state = CodegenState::default();
|
||||
tree.codegen(&mut state);
|
||||
|
||||
return Some(Fix::replacement(
|
||||
Some(Fix::replacement(
|
||||
state.to_string(),
|
||||
range.location,
|
||||
range.end_location,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
))
|
||||
}
|
||||
|
||||
/// UP010
|
||||
|
|
|
@ -17,27 +17,27 @@ fn match_named_tuple_assign<'a>(
|
|||
targets: &'a [Expr],
|
||||
value: &'a Expr,
|
||||
) -> Option<(&'a str, &'a [Expr], &'a [Keyword], &'a ExprKind)> {
|
||||
if let Some(target) = targets.get(0) {
|
||||
if let ExprKind::Name { id: typename, .. } = &target.node {
|
||||
if let ExprKind::Call {
|
||||
let target = targets.get(0)?;
|
||||
let ExprKind::Name { id: typename, .. } = &target.node else {
|
||||
return None;
|
||||
};
|
||||
let ExprKind::Call {
|
||||
func,
|
||||
args,
|
||||
keywords,
|
||||
} = &value.node
|
||||
{
|
||||
if match_module_member(
|
||||
} = &value.node else {
|
||||
return None;
|
||||
};
|
||||
if !match_module_member(
|
||||
func,
|
||||
"typing",
|
||||
"NamedTuple",
|
||||
&checker.from_imports,
|
||||
&checker.import_aliases,
|
||||
) {
|
||||
return Some((typename, args, keywords, &func.node));
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
Some((typename, args, keywords, &func.node))
|
||||
}
|
||||
|
||||
/// Generate a `StmtKind::AnnAssign` representing the provided property
|
||||
|
@ -78,13 +78,14 @@ fn create_property_assignment_stmt(
|
|||
|
||||
/// Match the `defaults` keyword in a `NamedTuple(...)` call.
|
||||
fn match_defaults(keywords: &[Keyword]) -> Result<&[Expr]> {
|
||||
match keywords.iter().find(|keyword| {
|
||||
let defaults = keywords.iter().find(|keyword| {
|
||||
if let Some(arg) = &keyword.node.arg {
|
||||
arg.as_str() == "defaults"
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}) {
|
||||
});
|
||||
match defaults {
|
||||
Some(defaults) => match &defaults.node.value.node {
|
||||
ExprKind::List { elts, .. } => Ok(elts),
|
||||
ExprKind::Tuple { elts, .. } => Ok(elts),
|
||||
|
@ -96,8 +97,13 @@ fn match_defaults(keywords: &[Keyword]) -> Result<&[Expr]> {
|
|||
|
||||
/// Create a list of property assignments from the `NamedTuple` arguments.
|
||||
fn create_properties_from_args(args: &[Expr], defaults: &[Expr]) -> Result<Vec<Stmt>> {
|
||||
if let Some(fields) = args.get(1) {
|
||||
if let ExprKind::List { elts, .. } = &fields.node {
|
||||
let Some(fields) = args.get(1) else {
|
||||
return Ok(vec![]);
|
||||
};
|
||||
let ExprKind::List { elts, .. } = &fields.node else {
|
||||
bail!("Expected argument to be `ExprKind::List`");
|
||||
};
|
||||
|
||||
let padded_defaults = if elts.len() >= defaults.len() {
|
||||
std::iter::repeat(None)
|
||||
.take(elts.len() - defaults.len())
|
||||
|
@ -108,41 +114,28 @@ fn create_properties_from_args(args: &[Expr], defaults: &[Expr]) -> Result<Vec<S
|
|||
elts.iter()
|
||||
.zip(padded_defaults)
|
||||
.map(|(field, default)| {
|
||||
if let ExprKind::Tuple { elts, .. } = &field.node {
|
||||
if let [field_name, annotation] = elts.as_slice() {
|
||||
if let ExprKind::Constant {
|
||||
let ExprKind::Tuple { elts, .. } = &field.node else {
|
||||
bail!("Expected `field` to be `ExprKind::Tuple`")
|
||||
};
|
||||
let [field_name, annotation] = elts.as_slice() else {
|
||||
bail!("Expected `elts` to have exactly two elements")
|
||||
};
|
||||
let ExprKind::Constant {
|
||||
value: Constant::Str(property),
|
||||
..
|
||||
} = &field_name.node
|
||||
{
|
||||
if IDENTIFIER_REGEX.is_match(property)
|
||||
&& !KWLIST.contains(&property.as_str())
|
||||
{
|
||||
} = &field_name.node else {
|
||||
bail!("Expected `field_name` to be `Constant::Str`")
|
||||
};
|
||||
if !IDENTIFIER_REGEX.is_match(property) || KWLIST.contains(&property.as_str()) {
|
||||
bail!("Invalid property name: {}", property)
|
||||
}
|
||||
Ok(create_property_assignment_stmt(
|
||||
property,
|
||||
&annotation.node,
|
||||
default.map(|d| &d.node),
|
||||
))
|
||||
} else {
|
||||
bail!("Invalid property name: {}", property)
|
||||
}
|
||||
} else {
|
||||
bail!("Expected `field_name` to be `Constant::Str`")
|
||||
}
|
||||
} else {
|
||||
bail!("Expected `elts` to have exactly two elements")
|
||||
}
|
||||
} else {
|
||||
bail!("Expected `field` to be `ExprKind::Tuple`")
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
bail!("Expected argument to be `ExprKind::List`")
|
||||
}
|
||||
} else {
|
||||
Ok(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate a `StmtKind:ClassDef` statement based on the provided body and
|
||||
|
@ -188,9 +181,11 @@ pub fn convert_named_tuple_functional_to_class(
|
|||
targets: &[Expr],
|
||||
value: &Expr,
|
||||
) {
|
||||
if let Some((typename, args, keywords, base_class)) =
|
||||
match_named_tuple_assign(checker, targets, value)
|
||||
let Some((typename, args, keywords, base_class)) =
|
||||
match_named_tuple_assign(checker, targets, value) else
|
||||
{
|
||||
return;
|
||||
};
|
||||
match match_defaults(keywords) {
|
||||
Ok(defaults) => {
|
||||
if let Ok(properties) = create_properties_from_args(args, defaults) {
|
||||
|
@ -209,5 +204,4 @@ pub fn convert_named_tuple_functional_to_class(
|
|||
}
|
||||
Err(err) => error!("Failed to parse defaults: {err}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,27 +20,27 @@ fn match_typed_dict_assign<'a>(
|
|||
targets: &'a [Expr],
|
||||
value: &'a Expr,
|
||||
) -> Option<(&'a str, &'a [Expr], &'a [Keyword], &'a ExprKind)> {
|
||||
if let Some(target) = targets.get(0) {
|
||||
if let ExprKind::Name { id: class_name, .. } = &target.node {
|
||||
if let ExprKind::Call {
|
||||
let target = targets.get(0)?;
|
||||
let ExprKind::Name { id: class_name, .. } = &target.node else {
|
||||
return None;
|
||||
};
|
||||
let ExprKind::Call {
|
||||
func,
|
||||
args,
|
||||
keywords,
|
||||
} = &value.node
|
||||
{
|
||||
if match_module_member(
|
||||
} = &value.node else {
|
||||
return None;
|
||||
};
|
||||
if !match_module_member(
|
||||
func,
|
||||
"typing",
|
||||
"TypedDict",
|
||||
&checker.from_imports,
|
||||
&checker.import_aliases,
|
||||
) {
|
||||
return Some((class_name, args, keywords, &func.node));
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
Some((class_name, args, keywords, &func.node))
|
||||
}
|
||||
|
||||
/// Generate a `StmtKind::AnnAssign` representing the provided property
|
||||
|
@ -127,15 +127,13 @@ fn get_properties_from_dict_literal(keys: &[Expr], values: &[Expr]) -> Result<Ve
|
|||
}
|
||||
|
||||
fn get_properties_from_dict_call(func: &Expr, keywords: &[Keyword]) -> Result<Vec<Stmt>> {
|
||||
if let ExprKind::Name { id, .. } = &func.node {
|
||||
if id == "dict" {
|
||||
get_properties_from_keywords(keywords)
|
||||
} else {
|
||||
let ExprKind::Name { id, .. } = &func.node else {
|
||||
bail!("Expected `func` to be `ExprKind::Name`")
|
||||
};
|
||||
if id != "dict" {
|
||||
bail!("Expected `id` to be `\"dict\"`")
|
||||
}
|
||||
} else {
|
||||
bail!("Expected `func` to be `ExprKind::Name`")
|
||||
}
|
||||
get_properties_from_keywords(keywords)
|
||||
}
|
||||
|
||||
// Deprecated in Python 3.11, removed in Python 3.13.
|
||||
|
@ -158,15 +156,11 @@ fn get_properties_from_keywords(keywords: &[Keyword]) -> Result<Vec<Stmt>> {
|
|||
// The only way to have the `total` keyword is to use the args version, like:
|
||||
// (`TypedDict('name', {'a': int}, total=True)`)
|
||||
fn get_total_from_only_keyword(keywords: &[Keyword]) -> Option<&KeywordData> {
|
||||
match keywords.get(0) {
|
||||
Some(keyword) => match &keyword.node.arg {
|
||||
Some(arg) => match arg.as_str() {
|
||||
let keyword = keywords.get(0)?;
|
||||
let arg = &keyword.node.arg.as_ref()?;
|
||||
match arg.as_str() {
|
||||
"total" => Some(&keyword.node),
|
||||
_ => None,
|
||||
},
|
||||
None => None,
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -225,12 +219,18 @@ pub fn convert_typed_dict_functional_to_class(
|
|||
targets: &[Expr],
|
||||
value: &Expr,
|
||||
) {
|
||||
if let Some((class_name, args, keywords, base_class)) =
|
||||
match_typed_dict_assign(checker, targets, value)
|
||||
let Some((class_name, args, keywords, base_class)) =
|
||||
match_typed_dict_assign(checker, targets, value) else
|
||||
{
|
||||
match get_properties_and_total(args, keywords) {
|
||||
Err(err) => error!("Failed to parse TypedDict: {err}"),
|
||||
Ok((body, total_keyword)) => {
|
||||
return;
|
||||
};
|
||||
let (body, total_keyword) = match get_properties_and_total(args, keywords) {
|
||||
Err(err) => {
|
||||
error!("Failed to parse TypedDict: {err}");
|
||||
return;
|
||||
}
|
||||
Ok(args) => args,
|
||||
};
|
||||
let mut check = Check::new(
|
||||
CheckKind::ConvertTypedDictFunctionalToClass(class_name.to_string()),
|
||||
Range::from_located(stmt),
|
||||
|
@ -242,7 +242,4 @@ pub fn convert_typed_dict_functional_to_class(
|
|||
};
|
||||
}
|
||||
checker.add_check(check);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,10 +29,18 @@ static DEPRECATED_ALIASES: Lazy<FxHashMap<&'static str, &'static str>> = Lazy::n
|
|||
|
||||
/// UP005
|
||||
pub fn deprecated_unittest_alias(checker: &mut Checker, expr: &Expr) {
|
||||
if let ExprKind::Attribute { value, attr, .. } = &expr.node {
|
||||
if let Some(&target) = DEPRECATED_ALIASES.get(attr.as_str()) {
|
||||
if let ExprKind::Name { id, .. } = &value.node {
|
||||
if id == "self" {
|
||||
let ExprKind::Attribute { value, attr, .. } = &expr.node else {
|
||||
return;
|
||||
};
|
||||
let Some(&target) = DEPRECATED_ALIASES.get(attr.as_str()) else {
|
||||
return;
|
||||
};
|
||||
let ExprKind::Name { id, .. } = &value.node else {
|
||||
return;
|
||||
};
|
||||
if id != "self" {
|
||||
return;
|
||||
}
|
||||
let mut check = Check::new(
|
||||
CheckKind::DeprecatedUnittestAlias(attr.to_string(), target.to_string()),
|
||||
Range::from_located(expr),
|
||||
|
@ -45,8 +53,4 @@ pub fn deprecated_unittest_alias(checker: &mut Checker, expr: &Expr) {
|
|||
));
|
||||
}
|
||||
checker.add_check(check);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,20 +9,22 @@ use crate::pyupgrade::checks;
|
|||
pub fn super_call_with_parameters(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
|
||||
// Only bother going through the super check at all if we're in a `super` call.
|
||||
// (We check this in `check_super_args` too, so this is just an optimization.)
|
||||
if helpers::is_super_call_with_arguments(func, args) {
|
||||
if !helpers::is_super_call_with_arguments(func, args) {
|
||||
return;
|
||||
}
|
||||
let scope = checker.current_scope();
|
||||
let parents: Vec<&Stmt> = checker
|
||||
.parent_stack
|
||||
.iter()
|
||||
.map(|index| checker.parents[*index])
|
||||
.collect();
|
||||
if let Some(mut check) = checks::super_args(scope, &parents, expr, func, args) {
|
||||
let Some(mut check) = checks::super_args(scope, &parents, expr, func, args) else {
|
||||
return;
|
||||
};
|
||||
if checker.patch(check.kind.code()) {
|
||||
if let Some(fix) = pyupgrade::fixes::remove_super_arguments(checker.locator, expr) {
|
||||
check.amend(fix);
|
||||
}
|
||||
}
|
||||
checker.add_check(check);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,9 @@ use crate::pyupgrade::checks;
|
|||
|
||||
/// UP003
|
||||
pub fn type_of_primitive(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
|
||||
if let Some(mut check) = checks::type_of_primitive(func, args, Range::from_located(expr)) {
|
||||
let Some(mut check) = checks::type_of_primitive(func, args, Range::from_located(expr)) else {
|
||||
return;
|
||||
};
|
||||
if checker.patch(check.kind.code()) {
|
||||
if let CheckKind::TypeOfPrimitive(primitive) = &check.kind {
|
||||
check.amend(Fix::replacement(
|
||||
|
@ -19,5 +21,4 @@ pub fn type_of_primitive(checker: &mut Checker, expr: &Expr, func: &Expr, args:
|
|||
}
|
||||
}
|
||||
checker.add_check(check);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,17 +9,17 @@ use crate::source_code_locator::SourceCodeLocator;
|
|||
const UTF8_LITERALS: &[&str] = &["utf-8", "utf8", "utf_8", "u8", "utf", "cp65001"];
|
||||
|
||||
fn match_encoded_variable(func: &Expr) -> Option<&Expr> {
|
||||
if let ExprKind::Attribute {
|
||||
let ExprKind::Attribute {
|
||||
value: variable,
|
||||
attr,
|
||||
..
|
||||
} = &func.node
|
||||
{
|
||||
if attr == "encode" {
|
||||
return Some(variable);
|
||||
} = &func.node else {
|
||||
return None;
|
||||
};
|
||||
if attr != "encode" {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
None
|
||||
Some(variable)
|
||||
}
|
||||
|
||||
fn is_utf8_encoding_arg(arg: &Expr) -> bool {
|
||||
|
@ -109,7 +109,9 @@ pub fn unnecessary_encode_utf8(
|
|||
args: &Vec<Expr>,
|
||||
kwargs: &Vec<Keyword>,
|
||||
) {
|
||||
if let Some(variable) = match_encoded_variable(func) {
|
||||
let Some(variable) = match_encoded_variable(func) else {
|
||||
return;
|
||||
};
|
||||
match &variable.node {
|
||||
ExprKind::Constant {
|
||||
value: Constant::Str(literal),
|
||||
|
@ -154,5 +156,4 @@ pub fn unnecessary_encode_utf8(
|
|||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,11 +49,11 @@ pub fn unnecessary_future_import(checker: &mut Checker, stmt: &Stmt, names: &[Lo
|
|||
}
|
||||
}
|
||||
|
||||
if !removable_index.is_empty() {
|
||||
if removable_index.is_empty() {
|
||||
return;
|
||||
}
|
||||
let mut check = Check::new(
|
||||
CheckKind::UnnecessaryFutureImport(
|
||||
removable_names.into_iter().map(String::from).collect(),
|
||||
),
|
||||
CheckKind::UnnecessaryFutureImport(removable_names.into_iter().map(String::from).collect()),
|
||||
Range::from_located(stmt),
|
||||
);
|
||||
if checker.patch(check.kind.code()) {
|
||||
|
@ -80,5 +80,4 @@ pub fn unnecessary_future_import(checker: &mut Checker, stmt: &Stmt, names: &[Lo
|
|||
}
|
||||
}
|
||||
checker.add_check(check);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,15 +6,16 @@ use crate::pyupgrade::checks;
|
|||
|
||||
/// UP011
|
||||
pub fn unnecessary_lru_cache_params(checker: &mut Checker, decorator_list: &[Expr]) {
|
||||
if let Some(mut check) = checks::unnecessary_lru_cache_params(
|
||||
let Some(mut check) = checks::unnecessary_lru_cache_params(
|
||||
decorator_list,
|
||||
checker.settings.target_version,
|
||||
&checker.from_imports,
|
||||
&checker.import_aliases,
|
||||
) {
|
||||
) else {
|
||||
return;
|
||||
};
|
||||
if checker.patch(check.kind.code()) {
|
||||
check.amend(Fix::deletion(check.location, check.end_location));
|
||||
}
|
||||
checker.add_check(check);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,9 +8,10 @@ use crate::pyupgrade::checks;
|
|||
|
||||
/// UP001
|
||||
pub fn useless_metaclass_type(checker: &mut Checker, stmt: &Stmt, value: &Expr, targets: &[Expr]) {
|
||||
if let Some(mut check) =
|
||||
checks::useless_metaclass_type(targets, value, Range::from_located(stmt))
|
||||
{
|
||||
let Some(mut check) =
|
||||
checks::useless_metaclass_type(targets, value, Range::from_located(stmt)) else {
|
||||
return;
|
||||
};
|
||||
if checker.patch(check.kind.code()) {
|
||||
let context = checker.binding_context();
|
||||
let deleted: Vec<&Stmt> = checker
|
||||
|
@ -34,5 +35,4 @@ pub fn useless_metaclass_type(checker: &mut Checker, stmt: &Stmt, value: &Expr,
|
|||
}
|
||||
}
|
||||
checker.add_check(check);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,9 @@ pub fn useless_object_inheritance(
|
|||
keywords: &[Keyword],
|
||||
) {
|
||||
let scope = checker.current_scope();
|
||||
if let Some(mut check) = checks::useless_object_inheritance(name, bases, scope) {
|
||||
let Some(mut check) = checks::useless_object_inheritance(name, bases, scope) else {
|
||||
return;
|
||||
};
|
||||
if checker.patch(check.kind.code()) {
|
||||
if let Some(fix) = pyupgrade::fixes::remove_class_def_base(
|
||||
checker.locator,
|
||||
|
@ -26,5 +28,4 @@ pub fn useless_object_inheritance(
|
|||
}
|
||||
}
|
||||
checker.add_check(check);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue