Unify helpers modules (#18835)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks-instrumented (push) Blocked by required conditions
CI / benchmarks-walltime (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run

A little bit of cleanup for consistency's sake: we move all the helpers
modules to a consistent location, and update the import paths when
needed. In the case of `refurb` there were two helpers modules, so we
just merged them.

Happy to revert the last commit if people are okay with `super::super` I
just thought it looked a little silly.
This commit is contained in:
Dylan 2025-06-20 16:03:01 -05:00 committed by GitHub
parent ef785d2e74
commit 2d224e6096
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
85 changed files with 133 additions and 137 deletions

View file

@ -8,7 +8,7 @@ use crate::checkers::ast::LintContext;
use crate::settings::LinterSettings;
use crate::{Edit, Fix, FixAvailability, Violation};
use super::super::detection::comment_contains_code;
use crate::rules::eradicate::detection::comment_contains_code;
/// ## What it does
/// Checks for commented-out Python code.

View file

@ -6,7 +6,7 @@ use crate::Violation;
use crate::checkers::ast::Checker;
use crate::registry::Rule;
use super::super::helpers::is_sys;
use crate::rules::flake8_2020::helpers::is_sys;
/// ## What it does
/// Checks for comparisons that test `sys.version` against string literals,

View file

@ -6,7 +6,7 @@ use ruff_text_size::Ranged;
use crate::Violation;
use crate::checkers::ast::Checker;
use super::super::helpers::{matches_password_name, string_literal};
use crate::rules::flake8_bandit::helpers::{matches_password_name, string_literal};
/// ## What it does
/// Checks for potential uses of hardcoded passwords in function argument

View file

@ -6,7 +6,7 @@ use ruff_text_size::Ranged;
use crate::Violation;
use crate::checkers::ast::Checker;
use super::super::helpers::{matches_password_name, string_literal};
use crate::rules::flake8_bandit::helpers::{matches_password_name, string_literal};
/// ## What it does
/// Checks for potential uses of hardcoded passwords in function calls.

View file

@ -5,7 +5,7 @@ use ruff_text_size::Ranged;
use crate::Violation;
use crate::checkers::ast::Checker;
use super::super::helpers::{matches_password_name, string_literal};
use crate::rules::flake8_bandit::helpers::{matches_password_name, string_literal};
/// ## What it does
/// Checks for potential uses of hardcoded passwords in strings.

View file

@ -7,7 +7,7 @@ use ruff_text_size::Ranged;
use crate::Violation;
use crate::checkers::ast::Checker;
use super::super::helpers::string_literal;
use crate::rules::flake8_bandit::helpers::string_literal;
/// ## What it does
/// Checks for uses of weak or broken cryptographic hash functions in

View file

@ -6,7 +6,7 @@ use ruff_text_size::Ranged;
use crate::Violation;
use crate::checkers::ast::Checker;
use super::super::helpers::at_last_top_level_expression_in_cell;
use crate::rules::flake8_bugbear::helpers::at_last_top_level_expression_in_cell;
/// ## What it does
/// Checks for useless comparisons.

View file

@ -6,7 +6,7 @@ use ruff_text_size::Ranged;
use crate::Violation;
use crate::checkers::ast::Checker;
use super::super::helpers::at_last_top_level_expression_in_cell;
use crate::rules::flake8_bugbear::helpers::at_last_top_level_expression_in_cell;
/// ## What it does
/// Checks for useless expressions.

View file

@ -6,7 +6,7 @@ use ruff_text_size::Ranged;
use crate::Violation;
use crate::checkers::ast::Checker;
use super::super::helpers::shadows_builtin;
use crate::rules::flake8_builtins::helpers::shadows_builtin;
/// ## What it does
/// Checks for function arguments that use the same names as builtins.

View file

@ -1,5 +1,6 @@
//! Rules from [flake8-comprehensions](https://pypi.org/project/flake8-comprehensions/).
mod fixes;
mod helpers;
pub(crate) mod rules;
pub mod settings;

View file

@ -18,7 +18,6 @@ pub(crate) use unnecessary_literal_within_tuple_call::*;
pub(crate) use unnecessary_map::*;
pub(crate) use unnecessary_subscript_reversal::*;
mod helpers;
mod unnecessary_call_around_sorted;
mod unnecessary_collection_call;
mod unnecessary_comprehension;

View file

@ -7,7 +7,7 @@ use crate::{AlwaysFixableViolation, Fix};
use crate::rules::flake8_comprehensions::fixes;
use super::helpers;
use crate::rules::flake8_comprehensions::helpers;
/// ## What it does
/// Checks for unnecessary generators that can be rewritten as dict

View file

@ -9,7 +9,7 @@ use ruff_text_size::{Ranged, TextRange, TextSize};
use crate::checkers::ast::Checker;
use crate::{AlwaysFixableViolation, Edit, Fix};
use super::helpers;
use crate::rules::flake8_comprehensions::helpers;
/// ## What it does
/// Checks for unnecessary generators that can be rewritten as list

View file

@ -10,7 +10,7 @@ use crate::checkers::ast::Checker;
use crate::rules::flake8_comprehensions::fixes::{pad_end, pad_start};
use crate::{AlwaysFixableViolation, Edit, Fix};
use super::helpers;
use crate::rules::flake8_comprehensions::helpers;
/// ## What it does
/// Checks for unnecessary generators that can be rewritten as set

View file

@ -7,7 +7,7 @@ use crate::checkers::ast::Checker;
use crate::rules::flake8_comprehensions::fixes;
use crate::{AlwaysFixableViolation, Fix};
use super::helpers;
use crate::rules::flake8_comprehensions::helpers;
/// ## What it does
/// Checks for unnecessary `list()` calls around list comprehensions.

View file

@ -6,7 +6,7 @@ use crate::checkers::ast::Checker;
use crate::rules::flake8_comprehensions::fixes;
use crate::{AlwaysFixableViolation, Fix};
use super::helpers;
use crate::rules::flake8_comprehensions::helpers;
/// ## What it does
/// Checks for unnecessary list comprehensions.

View file

@ -8,7 +8,7 @@ use crate::checkers::ast::Checker;
use crate::rules::flake8_comprehensions::fixes::{pad_end, pad_start};
use crate::{AlwaysFixableViolation, Edit, Fix};
use super::helpers;
use crate::rules::flake8_comprehensions::helpers;
/// ## What it does
/// Checks for unnecessary list comprehensions.

View file

@ -6,7 +6,7 @@ use crate::checkers::ast::Checker;
use crate::rules::flake8_comprehensions::fixes;
use crate::{AlwaysFixableViolation, Fix};
use super::helpers;
use crate::rules::flake8_comprehensions::helpers;
/// ## What it does
/// Checks for unnecessary list or tuple literals.

View file

@ -6,7 +6,7 @@ use crate::checkers::ast::Checker;
use crate::rules::flake8_comprehensions::fixes::{pad_end, pad_start};
use crate::{AlwaysFixableViolation, Edit, Fix};
use super::helpers;
use crate::rules::flake8_comprehensions::helpers;
/// ## What it does
/// Checks for `set()` calls that take unnecessary list or tuple literals

View file

@ -8,7 +8,7 @@ use ruff_text_size::Ranged;
use crate::checkers::ast::Checker;
use crate::{AlwaysFixableViolation, Edit, Fix};
use super::helpers;
use crate::rules::flake8_comprehensions::helpers;
/// ## What it does
/// Checks for `dict()` calls that take unnecessary dict literals or dict

View file

@ -5,7 +5,7 @@ use ruff_text_size::{Ranged, TextSize};
use crate::checkers::ast::Checker;
use crate::{AlwaysFixableViolation, Edit, Fix};
use super::helpers;
use crate::rules::flake8_comprehensions::helpers;
/// ## What it does
/// Checks for `list()` calls that take unnecessary list or tuple literals as

View file

@ -9,7 +9,7 @@ use crate::preview::is_check_comprehensions_in_tuple_call_enabled;
use crate::rules::flake8_comprehensions::fixes;
use crate::{AlwaysFixableViolation, Edit, Fix};
use super::helpers;
use crate::rules::flake8_comprehensions::helpers;
/// ## What it does
/// Checks for `tuple` calls that take unnecessary list or tuple literals as

View file

@ -1,4 +1,5 @@
//! Rules from [flake8-datetimez](https://pypi.org/project/flake8-datetimez/).
mod helpers;
pub(crate) mod rules;
#[cfg(test)]

View file

@ -6,7 +6,7 @@ use ruff_python_semantic::Modules;
use crate::Violation;
use crate::checkers::ast::Checker;
use super::helpers::{self, DatetimeModuleAntipattern};
use crate::rules::flake8_datetimez::helpers::{self, DatetimeModuleAntipattern};
/// ## What it does
/// Checks for usage of `datetime.datetime.fromtimestamp()` that do not specify

View file

@ -6,7 +6,7 @@ use ruff_python_semantic::Modules;
use crate::Violation;
use crate::checkers::ast::Checker;
use super::helpers::{self, DatetimeModuleAntipattern};
use crate::rules::flake8_datetimez::helpers::{self, DatetimeModuleAntipattern};
/// ## What it does
/// Checks for usages of `datetime.datetime.now()` that do not specify a timezone.

View file

@ -5,7 +5,7 @@ use ruff_python_semantic::Modules;
use crate::Violation;
use crate::checkers::ast::Checker;
use super::helpers::DatetimeModuleAntipattern;
use crate::rules::flake8_datetimez::helpers::DatetimeModuleAntipattern;
/// ## What it does
/// Checks for uses of `datetime.datetime.strptime()` that lead to naive

View file

@ -7,7 +7,7 @@ use ruff_python_semantic::Modules;
use crate::Violation;
use crate::checkers::ast::Checker;
use super::helpers;
use crate::rules::flake8_datetimez::helpers;
/// ## What it does
/// Checks for usage of `datetime.datetime.today()`.

View file

@ -7,7 +7,7 @@ use ruff_python_semantic::Modules;
use crate::Violation;
use crate::checkers::ast::Checker;
use super::helpers;
use crate::rules::flake8_datetimez::helpers;
/// ## What it does
/// Checks for usage of `datetime.datetime.utcfromtimestamp()`.

View file

@ -7,7 +7,7 @@ use ruff_python_semantic::Modules;
use crate::Violation;
use crate::checkers::ast::Checker;
use super::helpers;
use crate::rules::flake8_datetimez::helpers;
/// ## What it does
/// Checks for usage of `datetime.datetime.utcnow()`.

View file

@ -6,7 +6,7 @@ use ruff_python_semantic::Modules;
use crate::Violation;
use crate::checkers::ast::Checker;
use super::helpers::{self, DatetimeModuleAntipattern};
use crate::rules::flake8_datetimez::helpers::{self, DatetimeModuleAntipattern};
/// ## What it does
/// Checks for `datetime` instantiations that do not specify a timezone.

View file

@ -19,4 +19,3 @@ mod call_datetime_utcfromtimestamp;
mod call_datetime_utcnow;
mod call_datetime_without_tzinfo;
mod datetime_min_max;
mod helpers;

View file

@ -1,4 +1,5 @@
//! Rules from [django-flake8](https://pypi.org/project/flake8-django/)
mod helpers;
pub(crate) mod rules;
#[cfg(test)]

View file

@ -5,7 +5,7 @@ use ruff_text_size::Ranged;
use crate::Violation;
use crate::checkers::ast::Checker;
use crate::rules::flake8_django::rules::helpers::is_model_form;
use crate::rules::flake8_django::helpers::is_model_form;
/// ## What it does
/// Checks for the use of `fields = "__all__"` in Django `ModelForm`

View file

@ -5,7 +5,7 @@ use ruff_text_size::Ranged;
use crate::Violation;
use crate::checkers::ast::Checker;
use crate::rules::flake8_django::rules::helpers::is_model_form;
use crate::rules::flake8_django::helpers::is_model_form;
/// ## What it does
/// Checks for the use of `exclude` in Django `ModelForm` classes.

View file

@ -8,7 +8,6 @@ pub(crate) use unordered_body_content_in_model::*;
mod all_with_model_form;
mod exclude_with_model_form;
mod helpers;
mod locals_in_render_function;
mod model_without_dunder_str;
mod non_leading_receiver_decorator;

View file

@ -7,7 +7,7 @@ use ruff_python_semantic::{Modules, SemanticModel, analyze};
use crate::Violation;
use crate::checkers::ast::Checker;
use super::helpers;
use crate::rules::flake8_django::helpers;
/// ## What it does
/// Checks that a `__str__` method is defined in Django models.

View file

@ -8,7 +8,7 @@ use ruff_text_size::Ranged;
use crate::Violation;
use crate::checkers::ast::Checker;
use super::helpers;
use crate::rules::flake8_django::helpers;
/// ## What it does
/// Checks nullable string-based fields (like `CharField` and `TextField`)

View file

@ -9,7 +9,7 @@ use ruff_text_size::Ranged;
use crate::Violation;
use crate::checkers::ast::Checker;
use super::helpers;
use crate::rules::flake8_django::helpers;
/// ## What it does
/// Checks for the order of Model's inner classes, methods, and fields as per

View file

@ -1,4 +1,5 @@
//! Rules from [flake8-logging](https://pypi.org/project/flake8-logging/).
mod helpers;
pub(crate) mod rules;
#[cfg(test)]

View file

@ -7,7 +7,7 @@ use ruff_text_size::Ranged;
use crate::checkers::ast::Checker;
use crate::fix::edits::{Parentheses, remove_argument};
use crate::rules::flake8_logging::rules::helpers::outside_handlers;
use crate::rules::flake8_logging::helpers::outside_handlers;
use crate::{Fix, FixAvailability, Violation};
/// ## What it does

View file

@ -4,7 +4,7 @@ use ruff_python_semantic::analyze::logging;
use ruff_text_size::Ranged;
use crate::checkers::ast::Checker;
use crate::rules::flake8_logging::rules::helpers::outside_handlers;
use crate::rules::flake8_logging::helpers::outside_handlers;
use crate::{Edit, Fix, FixAvailability, Violation};
/// ## What it does

View file

@ -9,7 +9,6 @@ pub(crate) use undocumented_warn::*;
mod direct_logger_instantiation;
mod exc_info_outside_except_handler;
mod exception_without_exc_info;
mod helpers;
mod invalid_get_logger_argument;
mod log_exception_outside_except_handler;
mod root_logger_call;

View file

@ -1,4 +1,5 @@
//! Rules from [flake8-pytest-style](https://pypi.org/project/flake8-pytest-style/).
mod helpers;
pub(crate) mod rules;
pub mod settings;
pub mod types;

View file

@ -5,7 +5,7 @@ use ruff_text_size::Ranged;
use crate::Violation;
use crate::checkers::ast::Checker;
use super::helpers::{is_empty_or_null_string, is_pytest_fail};
use crate::rules::flake8_pytest_style::helpers::{is_empty_or_null_string, is_pytest_fail};
/// ## What it does
/// Checks for `pytest.fail` calls without a message.

View file

@ -19,7 +19,7 @@ use crate::registry::Rule;
use crate::{AlwaysFixableViolation, Violation};
use crate::{Edit, Fix};
use super::helpers::{
use crate::rules::flake8_pytest_style::helpers::{
Parentheses, get_mark_decorators, is_pytest_fixture, is_pytest_yield_fixture,
keyword_is_literal,
};

View file

@ -8,7 +8,7 @@ use crate::checkers::ast::Checker;
use crate::registry::Rule;
use crate::{AlwaysFixableViolation, Edit, Fix};
use super::helpers::{Parentheses, get_mark_decorators};
use crate::rules::flake8_pytest_style::helpers::{Parentheses, get_mark_decorators};
/// ## What it does
/// Checks for argument-free `@pytest.mark.<marker>()` decorators with or

View file

@ -12,7 +12,6 @@ pub(crate) use warns::*;
mod assertion;
mod fail;
mod fixture;
mod helpers;
mod imports;
mod marks;
mod parametrize;

View file

@ -13,8 +13,8 @@ use crate::checkers::ast::Checker;
use crate::registry::Rule;
use crate::{Edit, Fix, FixAvailability, Violation};
use super::super::types;
use super::helpers::{is_pytest_parametrize, split_names};
use crate::rules::flake8_pytest_style::helpers::{is_pytest_parametrize, split_names};
use crate::rules::flake8_pytest_style::types;
/// ## What it does
/// Checks for the type of parameter names passed to `pytest.mark.parametrize`.

View file

@ -8,7 +8,7 @@ use crate::Violation;
use crate::checkers::ast::Checker;
use crate::registry::Rule;
use super::helpers::is_empty_or_null_string;
use crate::rules::flake8_pytest_style::helpers::is_empty_or_null_string;
/// ## What it does
/// Checks for `pytest.raises` context managers with multiple statements.

View file

@ -1,5 +1,5 @@
use crate::checkers::ast::Checker;
use crate::rules::flake8_pytest_style::rules::helpers::is_likely_pytest_test;
use crate::rules::flake8_pytest_style::helpers::is_likely_pytest_test;
use crate::{Edit, Fix, Violation};
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::StmtFunctionDef;

View file

@ -8,7 +8,7 @@ use crate::Violation;
use crate::checkers::ast::Checker;
use crate::registry::Rule;
use super::helpers::is_empty_or_null_string;
use crate::rules::flake8_pytest_style::helpers::is_empty_or_null_string;
/// ## What it does
/// Checks for `pytest.warns` context managers with multiple statements.

View file

@ -7,7 +7,7 @@ use crate::checkers::ast::Checker;
use crate::registry::Rule;
use crate::{AlwaysFixableViolation, Edit, Fix, FixAvailability, Violation};
use super::super::settings::Quote;
use crate::rules::flake8_quotes::settings::Quote;
/// ## What it does
/// Checks for inline strings that use single quotes or double quotes,

View file

@ -7,7 +7,7 @@ use ruff_text_size::{Ranged, TextRange};
use crate::checkers::ast::Checker;
use crate::{AlwaysFixableViolation, Edit, Fix};
use super::super::helpers::{contains_escaped_quote, raw_contents, unescape_string};
use crate::rules::flake8_quotes::helpers::{contains_escaped_quote, raw_contents, unescape_string};
/// ## What it does
/// Checks for strings that include unnecessarily escaped quotes.

View file

@ -22,9 +22,9 @@ use crate::rules::flake8_return::helpers::end_of_last_statement;
use crate::{AlwaysFixableViolation, FixAvailability, Violation};
use crate::{Edit, Fix};
use super::super::branch::Branch;
use super::super::helpers::result_exists;
use super::super::visitor::{ReturnVisitor, Stack};
use crate::rules::flake8_return::branch::Branch;
use crate::rules::flake8_return::helpers::result_exists;
use crate::rules::flake8_return::visitor::{ReturnVisitor, Stack};
/// ## What it does
/// Checks for the presence of a `return None` statement when `None` is the only

View file

@ -1,4 +1,5 @@
//! Rules from [flake8-slots](https://pypi.org/project/flake8-slots/).
mod helpers;
pub(crate) mod rules;
#[cfg(test)]

View file

@ -2,7 +2,6 @@ pub(crate) use no_slots_in_namedtuple_subclass::*;
pub(crate) use no_slots_in_str_subclass::*;
pub(crate) use no_slots_in_tuple_subclass::*;
mod helpers;
mod no_slots_in_namedtuple_subclass;
mod no_slots_in_str_subclass;
mod no_slots_in_tuple_subclass;

View file

@ -6,7 +6,7 @@ use ruff_python_semantic::SemanticModel;
use crate::Violation;
use crate::checkers::ast::Checker;
use crate::rules::flake8_slots::rules::helpers::has_slots;
use crate::rules::flake8_slots::helpers::has_slots;
/// ## What it does
/// Checks for subclasses of `collections.namedtuple` or `typing.NamedTuple`

View file

@ -5,7 +5,7 @@ use ruff_python_semantic::{SemanticModel, analyze::class::is_enumeration};
use crate::Violation;
use crate::checkers::ast::Checker;
use crate::rules::flake8_slots::rules::helpers::has_slots;
use crate::rules::flake8_slots::helpers::has_slots;
/// ## What it does
/// Checks for subclasses of `str` that lack a `__slots__` definition.

View file

@ -6,7 +6,7 @@ use ruff_python_ast::identifier::Identifier;
use crate::Violation;
use crate::checkers::ast::Checker;
use crate::rules::flake8_slots::rules::helpers::has_slots;
use crate::rules::flake8_slots::helpers::has_slots;
/// ## What it does
/// Checks for subclasses of `tuple` that lack a `__slots__` definition.

View file

@ -10,14 +10,14 @@ use ruff_python_trivia::{PythonWhitespace, leading_indentation, textwrap::indent
use ruff_source_file::{LineRanges, UniversalNewlines};
use ruff_text_size::{Ranged, TextRange};
use super::super::block::Block;
use super::super::{comments, format_imports};
use crate::Locator;
use crate::checkers::ast::LintContext;
use crate::line_width::LineWidthBuilder;
use crate::package::PackageRoot;
use crate::preview::is_full_path_match_source_strategy_enabled;
use crate::rules::isort::block::Block;
use crate::rules::isort::categorize::MatchSourceStrategy;
use crate::rules::isort::{comments, format_imports};
use crate::settings::LinterSettings;
use crate::{Edit, Fix, FixAvailability, Violation};

View file

@ -10,12 +10,12 @@ use ruff_text_size::{Ranged, TextRange};
use crate::checkers::ast::Checker;
use crate::{AlwaysFixableViolation, Fix, FixAvailability, Violation};
use super::super::cformat::CFormatSummary;
use super::super::fixes::{
use crate::rules::pyflakes::cformat::CFormatSummary;
use crate::rules::pyflakes::fixes::{
remove_unused_format_arguments_from_dict, remove_unused_keyword_arguments_from_format_call,
remove_unused_positional_arguments_from_format_call,
};
use super::super::format::FormatSummary;
use crate::rules::pyflakes::format::FormatSummary;
/// ## What it does
/// Checks for invalid `printf`-style format strings.

View file

@ -6,7 +6,7 @@ use crate::checkers::ast::Checker;
use crate::fix::edits::pad;
use crate::{Edit, Fix, FixAvailability, Violation};
use super::super::types::Primitive;
use crate::rules::pyupgrade::types::Primitive;
/// ## What it does
/// Checks for uses of `type` that take a primitive as an argument.

View file

@ -1,5 +1,7 @@
use std::borrow::Cow;
use ruff_python_ast::name::Name;
use ruff_python_ast::{self as ast, Expr};
use ruff_python_ast::{self as ast, Expr, parenthesize::parenthesized_range};
use ruff_python_codegen::Generator;
use ruff_python_semantic::{BindingId, ResolvedReference, SemanticModel};
use ruff_text_size::{Ranged, TextRange};
@ -306,3 +308,57 @@ fn match_open_mode(mode: &Expr) -> Option<OpenMode> {
_ => None,
}
}
/// A helper function that extracts the `iter` from a [`ast::StmtFor`] node and
/// adds parentheses if needed.
///
/// These cases are okay and will not be modified:
///
/// - `for x in z: ...` -> `"z"`
/// - `for x in (y, z): ...` -> `"(y, z)"`
/// - `for x in [y, z]: ...` -> `"[y, z]"`
///
/// While these cases require parentheses:
///
/// - `for x in y, z: ...` -> `"(y, z)"`
/// - `for x in lambda: 0: ...` -> `"(lambda: 0)"`
/// - `for x in (1,) if True else (2,): ...` -> `"((1,) if True else (2,))"`
pub(super) fn parenthesize_loop_iter_if_necessary<'a>(
for_stmt: &'a ast::StmtFor,
checker: &'a Checker,
location: IterLocation,
) -> Cow<'a, str> {
let locator = checker.locator();
let iter = for_stmt.iter.as_ref();
let original_parenthesized_range = parenthesized_range(
iter.into(),
for_stmt.into(),
checker.comment_ranges(),
checker.source(),
);
if let Some(range) = original_parenthesized_range {
return Cow::Borrowed(locator.slice(range));
}
let iter_in_source = locator.slice(iter);
match iter {
ast::Expr::Tuple(tuple) if !tuple.parenthesized => {
Cow::Owned(format!("({iter_in_source})"))
}
ast::Expr::Lambda(_) | ast::Expr::If(_)
if matches!(location, IterLocation::Comprehension) =>
{
Cow::Owned(format!("({iter_in_source})"))
}
_ => Cow::Borrowed(iter_in_source),
}
}
#[derive(Copy, Clone)]
pub(super) enum IterLocation {
Call,
Comprehension,
}

View file

@ -3,10 +3,10 @@ use ruff_python_ast::{Expr, Stmt, StmtFor};
use ruff_python_semantic::analyze::typing;
use crate::checkers::ast::Checker;
use crate::rules::refurb::rules::helpers::IterLocation;
use crate::rules::refurb::helpers::IterLocation;
use crate::{AlwaysFixableViolation, Applicability, Edit, Fix};
use super::helpers::parenthesize_loop_iter_if_necessary;
use crate::rules::refurb::helpers::parenthesize_loop_iter_if_necessary;
/// ## What it does
/// Checks for code that updates a set with the contents of an iterable by

View file

@ -5,10 +5,10 @@ use ruff_python_semantic::{Binding, ScopeId, SemanticModel, TypingOnlyBindingsSt
use ruff_text_size::{Ranged, TextRange, TextSize};
use crate::checkers::ast::Checker;
use crate::rules::refurb::rules::helpers::IterLocation;
use crate::rules::refurb::helpers::IterLocation;
use crate::{AlwaysFixableViolation, Applicability, Edit, Fix};
use super::helpers::parenthesize_loop_iter_if_necessary;
use crate::rules::refurb::helpers::parenthesize_loop_iter_if_necessary;
/// ## What it does
/// Checks for the use of `IOBase.write` in a for loop.

View file

@ -1,59 +0,0 @@
use std::borrow::Cow;
use ruff_python_ast::{self as ast, parenthesize::parenthesized_range};
use crate::checkers::ast::Checker;
/// A helper function that extracts the `iter` from a [`ast::StmtFor`] node and
/// adds parentheses if needed.
///
/// These cases are okay and will not be modified:
///
/// - `for x in z: ...` -> `"z"`
/// - `for x in (y, z): ...` -> `"(y, z)"`
/// - `for x in [y, z]: ...` -> `"[y, z]"`
///
/// While these cases require parentheses:
///
/// - `for x in y, z: ...` -> `"(y, z)"`
/// - `for x in lambda: 0: ...` -> `"(lambda: 0)"`
/// - `for x in (1,) if True else (2,): ...` -> `"((1,) if True else (2,))"`
pub(super) fn parenthesize_loop_iter_if_necessary<'a>(
for_stmt: &'a ast::StmtFor,
checker: &'a Checker,
location: IterLocation,
) -> Cow<'a, str> {
let locator = checker.locator();
let iter = for_stmt.iter.as_ref();
let original_parenthesized_range = parenthesized_range(
iter.into(),
for_stmt.into(),
checker.comment_ranges(),
checker.source(),
);
if let Some(range) = original_parenthesized_range {
return Cow::Borrowed(locator.slice(range));
}
let iter_in_source = locator.slice(iter);
match iter {
ast::Expr::Tuple(tuple) if !tuple.parenthesized => {
Cow::Owned(format!("({iter_in_source})"))
}
ast::Expr::Lambda(_) | ast::Expr::If(_)
if matches!(location, IterLocation::Comprehension) =>
{
Cow::Owned(format!("({iter_in_source})"))
}
_ => Cow::Borrowed(iter_in_source),
}
}
#[derive(Copy, Clone)]
pub(super) enum IterLocation {
Call,
Comprehension,
}

View file

@ -44,7 +44,6 @@ mod fromisoformat_replace_z;
mod fstring_number_format;
mod hardcoded_string_charset;
mod hashlib_digest_hex;
mod helpers;
mod if_exp_instead_of_or_operator;
mod if_expr_min_max;
mod implicit_cwd;

View file

@ -8,7 +8,7 @@ use crate::Violation;
use crate::checkers::ast::Checker;
use crate::fix::snippet::SourceCodeSnippet;
use super::super::helpers::{FileOpen, find_file_opens};
use crate::rules::refurb::helpers::{FileOpen, find_file_opens};
/// ## What it does
/// Checks for uses of `open` and `read` that can be replaced by `pathlib`

View file

@ -9,7 +9,7 @@ use crate::Violation;
use crate::checkers::ast::Checker;
use crate::fix::snippet::SourceCodeSnippet;
use super::super::helpers::{FileOpen, find_file_opens};
use crate::rules::refurb::helpers::{FileOpen, find_file_opens};
/// ## What it does
/// Checks for uses of `open` and `write` that can be replaced by `pathlib`

View file

@ -1,5 +1,6 @@
//! Ruff-specific rules.
mod helpers;
pub(crate) mod rules;
pub mod settings;
pub(crate) mod typing;

View file

@ -4,7 +4,7 @@ use ruff_python_semantic::analyze::class::is_enumeration;
use crate::Violation;
use crate::checkers::ast::Checker;
use crate::rules::ruff::rules::helpers::{DataclassKind, dataclass_kind};
use crate::rules::ruff::helpers::{DataclassKind, dataclass_kind};
/// ## What it does
/// Checks for enum classes which are also decorated with `@dataclass`.

View file

@ -9,7 +9,7 @@ use ruff_text_size::Ranged;
use crate::Violation;
use crate::checkers::ast::Checker;
use crate::rules::ruff::rules::helpers::{
use crate::rules::ruff::helpers::{
AttrsAutoAttribs, DataclassKind, dataclass_kind, is_class_var_annotation, is_dataclass_field,
is_descriptor_class,
};

View file

@ -5,7 +5,7 @@ use ruff_text_size::Ranged;
use crate::Violation;
use crate::checkers::ast::Checker;
use crate::rules::ruff::rules::helpers::{DataclassKind, dataclass_kind};
use crate::rules::ruff::helpers::{DataclassKind, dataclass_kind};
/// ## What it does
/// Checks for implicit class variables in dataclasses.

View file

@ -13,7 +13,7 @@ use crate::{Edit, Fix, FixAvailability, Violation};
use ruff_python_ast::PythonVersion;
use super::super::typing::type_hint_explicitly_allows_none;
use crate::rules::ruff::typing::type_hint_explicitly_allows_none;
/// ## What it does
/// Checks for the use of implicit `Optional` in type annotations when the

View file

@ -74,7 +74,6 @@ mod default_factory_kwarg;
mod explicit_f_string_type_conversion;
mod falsy_dict_get_fallback;
mod function_call_in_dataclass_default;
mod helpers;
mod if_key_in_dict_del;
mod implicit_classvar_in_dataclass;
mod implicit_optional;

View file

@ -6,7 +6,7 @@ use ruff_text_size::Ranged;
use crate::Violation;
use crate::checkers::ast::Checker;
use crate::rules::ruff::rules::helpers::{
use crate::rules::ruff::helpers::{
dataclass_kind, has_default_copy_semantics, is_class_var_annotation, is_final_annotation,
is_special_attribute,
};

View file

@ -6,7 +6,7 @@ use ruff_text_size::Ranged;
use crate::Violation;
use crate::checkers::ast::Checker;
use crate::rules::ruff::rules::helpers::{dataclass_kind, is_class_var_annotation};
use crate::rules::ruff::helpers::{dataclass_kind, is_class_var_annotation};
/// ## What it does
/// Checks for mutable default values in dataclass attributes.

View file

@ -10,7 +10,7 @@ use ruff_text_size::Ranged;
use crate::{Edit, Fix, FixAvailability, Violation};
use crate::{checkers::ast::Checker, importer::ImportRequest};
use super::helpers::{DataclassKind, dataclass_kind};
use crate::rules::ruff::helpers::{DataclassKind, dataclass_kind};
/// ## What it does
/// Checks for `__post_init__` dataclass methods with parameter defaults.