mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-04 18:58:04 +00:00
Add missing rule code comments (#18906)
<!-- Thank you for contributing to Ruff/ty! To help us out with reviewing, please consider the following: - Does this pull request include a summary of the change? (See below.) - Does this pull request include a descriptive title? (Please prefix with `[ty]` for ty pull requests.) - Does this pull request include references to any relevant issues? --> ## Summary <!-- What's the purpose of the change? What does it do, and why? --> While making some of my other changes, I noticed some of the lints were missing comments with their lint code/had the wrong numbered lint code. These comments are super useful since they allow for very easily and quickly finding the source code of a lint, so I decided to try and normalize them. Most of them were fairly straightforward, just adding a doc comment/comment in the appropriate place. I decided to make all of the `Pylint` rules have the `PL` prefix. Previously it was split between no prefix and having prefix, but I decided to normalize to with prefix since that's what's in the docs, and the with prefix will show up on no prefix searches, while the reverse is not true. I also ran into a lot of rules with implementations in "non-standard" places (where "standard" means inside a file matching the glob `crates/ruff_linter/rules/*/rules/**/*.rs` and/or the same rule file where the rule `struct`/`ViolationMetadata` is defined). I decided to move all the implementations out of `crates/ruff_linter/src/checkers/ast/analyze/deferred_scopes.rs` and into their own files, since that is what the rest of the rules in `deferred_scopes.rs` did, and those were just the outliers. There were several rules which I did not end up moving, which you can see as the extra paths I had to add to my python code besides the "standard" glob. These rules are generally the error-type rules that just wrap an error from the parser, and have very small implementations/are very tightly linked to the module they are in, and generally every rule of that type was implemented in module instead of in the "standard" place. Resolving that requires answering a question I don't think I'm equipped to handle: Is the point of these comments to give quick access to the rule definition/docs, or the rule implementation? For all the rules with implementations in the "standard" location this isn't a problem, as they are the same, but it is an issue for all of these error type rules. In the end I chose to leave the implementations where they were, but I'm not sure if that was the right choice. <details> <summary>Python script I wrote to find missing comments</summary> This script assumes it is placed in the top level `ruff` directory (ie next to `.git`/`crates`/`README.md`) ```py import re from copy import copy from pathlib import Path linter_to_code_prefix = { "Airflow": "AIR", "Eradicate": "ERA", "FastApi": "FAST", "Flake82020": "YTT", "Flake8Annotations": "ANN", "Flake8Async": "ASYNC", "Flake8Bandit": "S", "Flake8BlindExcept": "BLE", "Flake8BooleanTrap": "FBT", "Flake8Bugbear": "B", "Flake8Builtins": "A", "Flake8Commas": "COM", "Flake8Comprehensions": "C4", "Flake8Copyright": "CPY", "Flake8Datetimez": "DTZ", "Flake8Debugger": "T10", "Flake8Django": "DJ", "Flake8ErrMsg": "EM", "Flake8Executable": "EXE", "Flake8Fixme": "FIX", "Flake8FutureAnnotations": "FA", "Flake8GetText": "INT", "Flake8ImplicitStrConcat": "ISC", "Flake8ImportConventions": "ICN", "Flake8Logging": "LOG", "Flake8LoggingFormat": "G", "Flake8NoPep420": "INP", "Flake8Pie": "PIE", "Flake8Print": "T20", "Flake8Pyi": "PYI", "Flake8PytestStyle": "PT", "Flake8Quotes": "Q", "Flake8Raise": "RSE", "Flake8Return": "RET", "Flake8Self": "SLF", "Flake8Simplify": "SIM", "Flake8Slots": "SLOT", "Flake8TidyImports": "TID", "Flake8Todos": "TD", "Flake8TypeChecking": "TC", "Flake8UnusedArguments": "ARG", "Flake8UsePathlib": "PTH", "Flynt": "FLY", "Isort": "I", "McCabe": "C90", "Numpy": "NPY", "PandasVet": "PD", "PEP8Naming": "N", "Perflint": "PERF", "Pycodestyle": "", "Pydoclint": "DOC", "Pydocstyle": "D", "Pyflakes": "F", "PygrepHooks": "PGH", "Pylint": "PL", "Pyupgrade": "UP", "Refurb": "FURB", "Ruff": "RUF", "Tryceratops": "TRY", } ruff = Path(__file__).parent / "crates" ruff_linter = ruff / "ruff_linter" / "src" code_to_rule_name = {} with open(ruff_linter / "codes.rs") as codes_file: for linter, code, rule_name in re.findall( # The (?<! skips ruff test rules # Only Preview|Stable rules are checked r"(?<!#\[cfg\(any\(feature = \"test-rules\", test\)\)\]\n) \((\w+), \"(\w+)\"\) => \(RuleGroup::(?:Preview|Stable), [\w:]+::(\w+)\)", codes_file.read(), ): code_to_rule_name[linter_to_code_prefix[linter] + code] = (rule_name, []) ruff_linter_rules = ruff_linter / "rules" for rule_file_path in [ *ruff_linter_rules.rglob("*/rules/**/*.rs"), ruff / "ruff_python_parser" / "src" / "semantic_errors.rs", ruff_linter / "pyproject_toml.rs", ruff_linter / "checkers" / "noqa.rs", ruff_linter / "checkers" / "ast" / "mod.rs", ruff_linter / "checkers" / "ast" / "analyze" / "unresolved_references.rs", ruff_linter / "checkers" / "ast" / "analyze" / "expression.rs", ruff_linter / "checkers" / "ast" / "analyze" / "statement.rs", ]: with open(rule_file_path, encoding="utf-8") as f: rule_file_content = f.read() for code, (rule, _) in copy(code_to_rule_name).items(): if rule in rule_file_content: if f"// {code}" in rule_file_content or f", {code}" in rule_file_content: del code_to_rule_name[code] else: code_to_rule_name[code][1].append(rule_file_path) for code, rule in code_to_rule_name.items(): print(code, rule[0]) for path in rule[1]: print(path) ``` </details> ## Test Plan <!-- How was it tested? --> N/A, no tests/functionality affected.
This commit is contained in:
parent
62975b3ab2
commit
90f47e9b7b
46 changed files with 66 additions and 15 deletions
|
@ -93,6 +93,7 @@ pub(crate) fn deferred_scopes(checker: &Checker) {
|
|||
pyflakes::rules::undefined_local(checker, scope_id, scope);
|
||||
}
|
||||
|
||||
// PLW0602
|
||||
if checker.is_rule_enabled(Rule::GlobalVariableNotAssigned) {
|
||||
for (name, binding_id) in scope.bindings() {
|
||||
let binding = checker.semantic.binding(binding_id);
|
||||
|
@ -123,6 +124,7 @@ pub(crate) fn deferred_scopes(checker: &Checker) {
|
|||
}
|
||||
}
|
||||
|
||||
// PLR1704
|
||||
if checker.is_rule_enabled(Rule::RedefinedArgumentFromLocal) {
|
||||
for (name, binding_id) in scope.bindings() {
|
||||
for shadow in checker.semantic.shadowed_bindings(scope_id, binding_id) {
|
||||
|
@ -156,6 +158,7 @@ pub(crate) fn deferred_scopes(checker: &Checker) {
|
|||
}
|
||||
}
|
||||
|
||||
// F402
|
||||
if checker.is_rule_enabled(Rule::ImportShadowedByLoopVar) {
|
||||
for (name, binding_id) in scope.bindings() {
|
||||
for shadow in checker.semantic.shadowed_bindings(scope_id, binding_id) {
|
||||
|
@ -197,6 +200,7 @@ pub(crate) fn deferred_scopes(checker: &Checker) {
|
|||
}
|
||||
}
|
||||
|
||||
// F811
|
||||
if checker.is_rule_enabled(Rule::RedefinedWhileUnused) {
|
||||
// Index the redefined bindings by statement.
|
||||
let mut redefinitions = FxHashMap::default();
|
||||
|
|
|
@ -539,6 +539,7 @@ pub(crate) fn expression(expr: &Expr, checker: &Checker) {
|
|||
let location = expr.range();
|
||||
match pyflakes::format::FormatSummary::try_from(string_value.to_str()) {
|
||||
Err(e) => {
|
||||
// F521
|
||||
if checker.is_rule_enabled(Rule::StringDotFormatInvalidFormat) {
|
||||
checker.report_diagnostic(
|
||||
pyflakes::rules::StringDotFormatInvalidFormat {
|
||||
|
@ -1315,6 +1316,7 @@ pub(crate) fn expression(expr: &Expr, checker: &Checker) {
|
|||
typ: CFormatErrorType::UnsupportedFormatChar(c),
|
||||
..
|
||||
}) => {
|
||||
// F509
|
||||
if checker
|
||||
.is_rule_enabled(Rule::PercentFormatUnsupportedFormatCharacter)
|
||||
{
|
||||
|
@ -1327,6 +1329,7 @@ pub(crate) fn expression(expr: &Expr, checker: &Checker) {
|
|||
}
|
||||
}
|
||||
Err(e) => {
|
||||
// F501
|
||||
if checker.is_rule_enabled(Rule::PercentFormatInvalidFormat) {
|
||||
checker.report_diagnostic(
|
||||
pyflakes::rules::PercentFormatInvalidFormat {
|
||||
|
|
|
@ -828,6 +828,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
pyflakes::rules::future_feature_not_defined(checker, alias);
|
||||
}
|
||||
} else if &alias.name == "*" {
|
||||
// F406
|
||||
if checker.is_rule_enabled(Rule::UndefinedLocalWithNestedImportStarUsage) {
|
||||
if !matches!(checker.semantic.current_scope().kind, ScopeKind::Module) {
|
||||
checker.report_diagnostic(
|
||||
|
@ -838,6 +839,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
);
|
||||
}
|
||||
}
|
||||
// F403
|
||||
if checker.is_rule_enabled(Rule::UndefinedLocalWithImportStar) {
|
||||
checker.report_diagnostic(
|
||||
pyflakes::rules::UndefinedLocalWithImportStar {
|
||||
|
|
|
@ -13,6 +13,7 @@ pub(crate) fn unresolved_references(checker: &Checker) {
|
|||
|
||||
for reference in checker.semantic.unresolved_references() {
|
||||
if reference.is_wildcard_import() {
|
||||
// F406
|
||||
if checker.is_rule_enabled(Rule::UndefinedLocalWithImportStarUsage) {
|
||||
checker.report_diagnostic(
|
||||
pyflakes::rules::UndefinedLocalWithImportStarUsage {
|
||||
|
@ -22,6 +23,7 @@ pub(crate) fn unresolved_references(checker: &Checker) {
|
|||
);
|
||||
}
|
||||
} else {
|
||||
// F821
|
||||
if checker.is_rule_enabled(Rule::UndefinedName) {
|
||||
if checker.semantic.in_no_type_check() {
|
||||
continue;
|
||||
|
|
|
@ -625,6 +625,7 @@ impl SemanticSyntaxContext for Checker<'_> {
|
|||
fn report_semantic_error(&self, error: SemanticSyntaxError) {
|
||||
match error.kind {
|
||||
SemanticSyntaxErrorKind::LateFutureImport => {
|
||||
// F404
|
||||
if self.is_rule_enabled(Rule::LateFutureImport) {
|
||||
self.report_diagnostic(LateFutureImport, error.range);
|
||||
}
|
||||
|
@ -646,6 +647,7 @@ impl SemanticSyntaxContext for Checker<'_> {
|
|||
}
|
||||
}
|
||||
SemanticSyntaxErrorKind::ReturnOutsideFunction => {
|
||||
// F706
|
||||
if self.is_rule_enabled(Rule::ReturnOutsideFunction) {
|
||||
self.report_diagnostic(ReturnOutsideFunction, error.range);
|
||||
}
|
||||
|
@ -2808,6 +2810,7 @@ impl<'a> Checker<'a> {
|
|||
Err(parse_error) => {
|
||||
self.semantic.restore(snapshot);
|
||||
|
||||
// F722
|
||||
if self.is_rule_enabled(Rule::ForwardAnnotationSyntaxError) {
|
||||
self.report_type_diagnostic(
|
||||
pyflakes::rules::ForwardAnnotationSyntaxError {
|
||||
|
@ -2955,6 +2958,7 @@ impl<'a> Checker<'a> {
|
|||
self.semantic.flags -= SemanticModelFlags::DUNDER_ALL_DEFINITION;
|
||||
} else {
|
||||
if self.semantic.global_scope().uses_star_imports() {
|
||||
// F405
|
||||
if self.is_rule_enabled(Rule::UndefinedLocalWithImportStarUsage) {
|
||||
self.report_diagnostic(
|
||||
pyflakes::rules::UndefinedLocalWithImportStarUsage {
|
||||
|
@ -2965,6 +2969,7 @@ impl<'a> Checker<'a> {
|
|||
.set_parent(definition.start());
|
||||
}
|
||||
} else {
|
||||
// F822
|
||||
if self.is_rule_enabled(Rule::UndefinedExport) {
|
||||
if is_undefined_export_in_dunder_init_enabled(self.settings())
|
||||
|| !self.path.ends_with("__init__.py")
|
||||
|
|
|
@ -22,6 +22,7 @@ use crate::{Edit, Fix, Locator};
|
|||
|
||||
use super::ast::LintContext;
|
||||
|
||||
/// RUF100
|
||||
pub(crate) fn check_noqa(
|
||||
context: &mut LintContext,
|
||||
path: &Path,
|
||||
|
|
|
@ -11,6 +11,7 @@ use crate::registry::Rule;
|
|||
use crate::rules::ruff::rules::InvalidPyprojectToml;
|
||||
use crate::settings::LinterSettings;
|
||||
|
||||
/// RUF200
|
||||
pub fn lint_pyproject_toml(
|
||||
source_file: &SourceFile,
|
||||
settings: &LinterSettings,
|
||||
|
|
|
@ -738,6 +738,7 @@ pub(crate) fn definition(
|
|||
.suppress_none_returning
|
||||
&& is_none_returning(body)
|
||||
) {
|
||||
// ANN206
|
||||
if is_method && visibility::is_classmethod(decorator_list, checker.semantic()) {
|
||||
if checker.is_rule_enabled(Rule::MissingReturnTypeClassMethod) {
|
||||
let return_type = if is_stub_function(function, checker) {
|
||||
|
@ -765,6 +766,7 @@ pub(crate) fn definition(
|
|||
diagnostics.push(diagnostic);
|
||||
}
|
||||
} else if is_method && visibility::is_staticmethod(decorator_list, checker.semantic()) {
|
||||
// ANN205
|
||||
if checker.is_rule_enabled(Rule::MissingReturnTypeStaticMethod) {
|
||||
let return_type = if is_stub_function(function, checker) {
|
||||
None
|
||||
|
@ -791,6 +793,7 @@ pub(crate) fn definition(
|
|||
diagnostics.push(diagnostic);
|
||||
}
|
||||
} else if is_method && visibility::is_init(name) {
|
||||
// ANN204
|
||||
// Allow omission of return annotation in `__init__` functions, as long as at
|
||||
// least one argument is typed.
|
||||
if checker.is_rule_enabled(Rule::MissingReturnTypeSpecialMethod) {
|
||||
|
|
|
@ -51,6 +51,7 @@ impl Violation for BooleanPositionalValueInCall {
|
|||
}
|
||||
}
|
||||
|
||||
/// FBT003
|
||||
pub(crate) fn boolean_positional_value_in_call(checker: &Checker, call: &ast::ExprCall) {
|
||||
if allow_boolean_trap(call, checker) {
|
||||
return;
|
||||
|
|
|
@ -46,7 +46,7 @@ impl Violation for StaticKeyDictComprehension {
|
|||
}
|
||||
}
|
||||
|
||||
/// RUF011
|
||||
/// B035, RUF011
|
||||
pub(crate) fn static_key_dict_comprehension(checker: &Checker, dict_comp: &ast::ExprDictComp) {
|
||||
// Collect the bound names in the comprehension's generators.
|
||||
let names = {
|
||||
|
|
|
@ -58,6 +58,7 @@ impl Violation for CallDateFromtimestamp {
|
|||
}
|
||||
}
|
||||
|
||||
/// DTZ012
|
||||
pub(crate) fn call_date_fromtimestamp(checker: &Checker, func: &Expr, location: TextRange) {
|
||||
if !checker.semantic().seen_module(Modules::DATETIME) {
|
||||
return;
|
||||
|
|
|
@ -57,6 +57,7 @@ impl Violation for CallDateToday {
|
|||
}
|
||||
}
|
||||
|
||||
/// DTZ011
|
||||
pub(crate) fn call_date_today(checker: &Checker, func: &Expr, location: TextRange) {
|
||||
if !checker.semantic().seen_module(Modules::DATETIME) {
|
||||
return;
|
||||
|
|
|
@ -69,6 +69,7 @@ impl Violation for CallDatetimeFromtimestamp {
|
|||
}
|
||||
}
|
||||
|
||||
/// DTZ006
|
||||
pub(crate) fn call_datetime_fromtimestamp(checker: &Checker, call: &ast::ExprCall) {
|
||||
if !checker.semantic().seen_module(Modules::DATETIME) {
|
||||
return;
|
||||
|
|
|
@ -67,6 +67,7 @@ impl Violation for CallDatetimeNowWithoutTzinfo {
|
|||
}
|
||||
}
|
||||
|
||||
/// DTZ005
|
||||
pub(crate) fn call_datetime_now_without_tzinfo(checker: &Checker, call: &ast::ExprCall) {
|
||||
if !checker.semantic().seen_module(Modules::DATETIME) {
|
||||
return;
|
||||
|
|
|
@ -56,6 +56,7 @@ impl Violation for CallDatetimeToday {
|
|||
}
|
||||
}
|
||||
|
||||
/// DTZ002
|
||||
pub(crate) fn call_datetime_today(checker: &Checker, func: &Expr, location: TextRange) {
|
||||
if !checker.semantic().seen_module(Modules::DATETIME) {
|
||||
return;
|
||||
|
|
|
@ -60,6 +60,7 @@ impl Violation for CallDatetimeUtcfromtimestamp {
|
|||
}
|
||||
}
|
||||
|
||||
/// DTZ004
|
||||
pub(crate) fn call_datetime_utcfromtimestamp(checker: &Checker, func: &Expr, location: TextRange) {
|
||||
if !checker.semantic().seen_module(Modules::DATETIME) {
|
||||
return;
|
||||
|
|
|
@ -63,6 +63,7 @@ impl Violation for CallDatetimeWithoutTzinfo {
|
|||
}
|
||||
}
|
||||
|
||||
/// DTZ001
|
||||
pub(crate) fn call_datetime_without_tzinfo(checker: &Checker, call: &ast::ExprCall) {
|
||||
if !checker.semantic().seen_module(Modules::DATETIME) {
|
||||
return;
|
||||
|
|
|
@ -46,6 +46,7 @@ impl Violation for Debugger {
|
|||
}
|
||||
}
|
||||
|
||||
/// T100
|
||||
/// Checks for the presence of a debugger call.
|
||||
pub(crate) fn debugger_call(checker: &Checker, expr: &Expr, func: &Expr) {
|
||||
if let Some(using_type) =
|
||||
|
@ -64,6 +65,7 @@ pub(crate) fn debugger_call(checker: &Checker, expr: &Expr, func: &Expr) {
|
|||
}
|
||||
}
|
||||
|
||||
/// T100
|
||||
/// Checks for the presence of a debugger import.
|
||||
pub(crate) fn debugger_import(checker: &Checker, stmt: &Stmt, module: Option<&str>, name: &str) {
|
||||
if let Some(module) = module {
|
||||
|
|
|
@ -59,6 +59,7 @@ impl Violation for ExcInfoOutsideExceptHandler {
|
|||
}
|
||||
}
|
||||
|
||||
/// LOG014
|
||||
pub(crate) fn exc_info_outside_except_handler(checker: &Checker, call: &ExprCall) {
|
||||
let semantic = checker.semantic();
|
||||
|
||||
|
|
|
@ -171,7 +171,7 @@ pub(crate) fn logging_call(checker: &Checker, call: &ast::ExprCall) {
|
|||
_ => return,
|
||||
};
|
||||
|
||||
// G001 - G004
|
||||
// G001, G002, G003, G004
|
||||
let msg_pos = usize::from(matches!(logging_call_type, LoggingCallType::LogCall));
|
||||
if let Some(format_arg) = call.arguments.find_argument_value("msg", msg_pos) {
|
||||
check_msg(checker, format_arg);
|
||||
|
|
|
@ -55,6 +55,7 @@ impl Violation for PytestFailWithoutMessage {
|
|||
}
|
||||
}
|
||||
|
||||
/// PT016
|
||||
pub(crate) fn fail_call(checker: &Checker, call: &ast::ExprCall) {
|
||||
if is_pytest_fail(&call.func, checker.semantic()) {
|
||||
// Allow either `pytest.fail(reason="...")` (introduced in pytest 7.0) or
|
||||
|
|
|
@ -225,6 +225,7 @@ fn check_useless_usefixtures(checker: &Checker, decorator: &Decorator, marker: &
|
|||
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_deletion(decorator.range())));
|
||||
}
|
||||
|
||||
/// PT023, PT026
|
||||
pub(crate) fn marks(checker: &Checker, decorators: &[Decorator]) {
|
||||
let enforce_parentheses = checker.is_rule_enabled(Rule::PytestIncorrectMarkParenthesesStyle);
|
||||
let enforce_useless_usefixtures =
|
||||
|
|
|
@ -170,6 +170,7 @@ const fn is_non_trivial_with_body(body: &[Stmt]) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
/// PT010
|
||||
pub(crate) fn raises_call(checker: &Checker, call: &ast::ExprCall) {
|
||||
if is_pytest_raises(&call.func, checker.semantic()) {
|
||||
if checker.is_rule_enabled(Rule::PytestRaisesWithoutException) {
|
||||
|
@ -205,6 +206,7 @@ pub(crate) fn raises_call(checker: &Checker, call: &ast::ExprCall) {
|
|||
}
|
||||
}
|
||||
|
||||
/// PT012
|
||||
pub(crate) fn complex_raises(checker: &Checker, stmt: &Stmt, items: &[WithItem], body: &[Stmt]) {
|
||||
let raises_called = items.iter().any(|item| match &item.context_expr {
|
||||
Expr::Call(ast::ExprCall { func, .. }) => is_pytest_raises(func, checker.semantic()),
|
||||
|
|
|
@ -154,6 +154,7 @@ fn get_complexity_number(stmts: &[Stmt]) -> usize {
|
|||
complexity
|
||||
}
|
||||
|
||||
/// C901
|
||||
pub(crate) fn function_is_too_complex(
|
||||
checker: &Checker,
|
||||
stmt: &Stmt,
|
||||
|
|
|
@ -181,15 +181,19 @@ pub(crate) fn call(checker: &Checker, func: &Expr) {
|
|||
|
||||
let range = func.range();
|
||||
match attr.as_str() {
|
||||
// PD003
|
||||
"isnull" if checker.is_rule_enabled(Rule::PandasUseOfDotIsNull) => {
|
||||
checker.report_diagnostic(PandasUseOfDotIsNull, range);
|
||||
}
|
||||
// PD004
|
||||
"notnull" if checker.is_rule_enabled(Rule::PandasUseOfDotNotNull) => {
|
||||
checker.report_diagnostic(PandasUseOfDotNotNull, range);
|
||||
}
|
||||
// PD010
|
||||
"pivot" | "unstack" if checker.is_rule_enabled(Rule::PandasUseOfDotPivotOrUnstack) => {
|
||||
checker.report_diagnostic(PandasUseOfDotPivotOrUnstack, range);
|
||||
}
|
||||
// PD013
|
||||
"stack" if checker.is_rule_enabled(Rule::PandasUseOfDotStack) => {
|
||||
checker.report_diagnostic(PandasUseOfDotStack, range);
|
||||
}
|
||||
|
|
|
@ -163,12 +163,15 @@ pub(crate) fn subscript(checker: &Checker, value: &Expr, expr: &Expr) {
|
|||
let range = expr.range();
|
||||
|
||||
match attr.as_str() {
|
||||
// PD007
|
||||
"ix" if checker.is_rule_enabled(Rule::PandasUseOfDotIx) => {
|
||||
checker.report_diagnostic(PandasUseOfDotIx, range)
|
||||
}
|
||||
// PD008
|
||||
"at" if checker.is_rule_enabled(Rule::PandasUseOfDotAt) => {
|
||||
checker.report_diagnostic(PandasUseOfDotAt, range)
|
||||
}
|
||||
// PD009
|
||||
"iat" if checker.is_rule_enabled(Rule::PandasUseOfDotIat) => {
|
||||
checker.report_diagnostic(PandasUseOfDotIat, range)
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ impl Violation for FutureFeatureNotDefined {
|
|||
}
|
||||
}
|
||||
|
||||
/// F407
|
||||
pub(crate) fn future_feature_not_defined(checker: &Checker, alias: &Alias) {
|
||||
if is_feature_name(&alias.name) {
|
||||
return;
|
||||
|
|
|
@ -276,6 +276,7 @@ fn find_dunder_all_exprs<'a>(semantic: &'a SemanticModel) -> Vec<&'a ast::Expr>
|
|||
.collect()
|
||||
}
|
||||
|
||||
/// F401
|
||||
/// For some unused binding in an import statement...
|
||||
///
|
||||
/// __init__.py ∧ 1stpty → safe, if one __all__, add to __all__
|
||||
|
|
|
@ -73,7 +73,7 @@ impl Violation for EqWithoutHash {
|
|||
}
|
||||
}
|
||||
|
||||
/// W1641
|
||||
/// PLW1641
|
||||
pub(crate) fn object_without_hash_method(checker: &Checker, class: &StmtClassDef) {
|
||||
if checker.source_type.is_stub() {
|
||||
return;
|
||||
|
|
|
@ -80,7 +80,7 @@ impl Violation for IfStmtMinMax {
|
|||
}
|
||||
}
|
||||
|
||||
/// R1730, R1731
|
||||
/// PLR1730, PLR1731
|
||||
pub(crate) fn if_stmt_min_max(checker: &Checker, stmt_if: &ast::StmtIf) {
|
||||
let ast::StmtIf {
|
||||
test,
|
||||
|
|
|
@ -55,7 +55,7 @@ impl Violation for ImportOutsideTopLevel {
|
|||
}
|
||||
}
|
||||
|
||||
/// C0415
|
||||
/// PLC0415
|
||||
pub(crate) fn import_outside_top_level(checker: &Checker, stmt: &Stmt) {
|
||||
if checker.semantic().current_scope().kind.is_module() {
|
||||
// "Top-level" imports are allowed
|
||||
|
|
|
@ -48,7 +48,7 @@ impl Violation for InvalidHashReturnType {
|
|||
}
|
||||
}
|
||||
|
||||
/// E0309
|
||||
/// PLE0309
|
||||
pub(crate) fn invalid_hash_return(checker: &Checker, function_def: &ast::StmtFunctionDef) {
|
||||
if function_def.name.as_str() != "__hash__" {
|
||||
return;
|
||||
|
|
|
@ -50,7 +50,7 @@ impl Violation for InvalidIndexReturnType {
|
|||
}
|
||||
}
|
||||
|
||||
/// E0305
|
||||
/// PLE0305
|
||||
pub(crate) fn invalid_index_return(checker: &Checker, function_def: &ast::StmtFunctionDef) {
|
||||
if function_def.name.as_str() != "__index__" {
|
||||
return;
|
||||
|
|
|
@ -49,7 +49,7 @@ impl Violation for InvalidLengthReturnType {
|
|||
}
|
||||
}
|
||||
|
||||
/// E0303
|
||||
/// PLE0303
|
||||
pub(crate) fn invalid_length_return(checker: &Checker, function_def: &ast::StmtFunctionDef) {
|
||||
if function_def.name.as_str() != "__len__" {
|
||||
return;
|
||||
|
|
|
@ -44,7 +44,7 @@ impl Violation for InvalidStrReturnType {
|
|||
}
|
||||
}
|
||||
|
||||
/// E0307
|
||||
/// PLE0307
|
||||
pub(crate) fn invalid_str_return(checker: &Checker, function_def: &ast::StmtFunctionDef) {
|
||||
if function_def.name.as_str() != "__str__" {
|
||||
return;
|
||||
|
|
|
@ -53,7 +53,7 @@ impl Violation for NonlocalAndGlobal {
|
|||
}
|
||||
}
|
||||
|
||||
/// E115
|
||||
/// PLE0115
|
||||
pub(crate) fn nonlocal_and_global(checker: &Checker, nonlocal: &ast::StmtNonlocal) {
|
||||
// Determine whether any of the newly declared `nonlocal` variables are already declared as
|
||||
// `global`.
|
||||
|
|
|
@ -35,6 +35,7 @@ impl Violation for RepeatedKeywordArgument {
|
|||
}
|
||||
}
|
||||
|
||||
/// PLE1132
|
||||
pub(crate) fn repeated_keyword_argument(checker: &Checker, call: &ExprCall) {
|
||||
let ExprCall { arguments, .. } = call;
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ impl Violation for SelfOrClsAssignment {
|
|||
}
|
||||
}
|
||||
|
||||
/// PLW0127
|
||||
/// PLW0642
|
||||
pub(crate) fn self_or_cls_assignment(checker: &Checker, target: &Expr) {
|
||||
let ScopeKind::Function(ast::StmtFunctionDef {
|
||||
name,
|
||||
|
|
|
@ -58,7 +58,7 @@ impl Violation for SingledispatchMethod {
|
|||
}
|
||||
}
|
||||
|
||||
/// E1519
|
||||
/// PLE1519
|
||||
pub(crate) fn singledispatch_method(checker: &Checker, scope: &Scope) {
|
||||
let Some(func) = scope.kind.as_function() else {
|
||||
return;
|
||||
|
|
|
@ -56,7 +56,7 @@ impl Violation for SingledispatchmethodFunction {
|
|||
}
|
||||
}
|
||||
|
||||
/// E1520
|
||||
/// PLE1520
|
||||
pub(crate) fn singledispatchmethod_function(checker: &Checker, scope: &Scope) {
|
||||
let Some(func) = scope.kind.as_function() else {
|
||||
return;
|
||||
|
|
|
@ -99,7 +99,7 @@ impl Violation for TooManyPublicMethods {
|
|||
}
|
||||
}
|
||||
|
||||
/// R0904
|
||||
/// PLR0904
|
||||
pub(crate) fn too_many_public_methods(
|
||||
checker: &Checker,
|
||||
class_def: &ast::StmtClassDef,
|
||||
|
|
|
@ -64,6 +64,7 @@ impl AlwaysFixableViolation for IntOnSlicedStr {
|
|||
}
|
||||
}
|
||||
|
||||
/// FURB166
|
||||
pub(crate) fn int_on_sliced_str(checker: &Checker, call: &ExprCall) {
|
||||
// Verify that the function is `int`.
|
||||
if !checker.semantic().match_builtin_expr(&call.func, "int") {
|
||||
|
|
|
@ -114,6 +114,7 @@ impl PytestContextType {
|
|||
}
|
||||
}
|
||||
|
||||
/// RUF061
|
||||
pub(crate) fn legacy_raises_warns_deprecated_call(checker: &Checker, call: &ast::ExprCall) {
|
||||
let semantic = checker.semantic();
|
||||
let Some(context_type) = PytestContextType::from_expr_name(&call.func, semantic) else {
|
||||
|
|
|
@ -158,6 +158,7 @@ pub(crate) fn sort_dunder_all_ann_assign(checker: &Checker, node: &ast::StmtAnnA
|
|||
}
|
||||
}
|
||||
|
||||
/// RUF022
|
||||
/// Sort a tuple or list that defines or mutates the global variable `__all__`.
|
||||
///
|
||||
/// This routine checks whether the tuple or list is sorted, and emits a
|
||||
|
|
|
@ -105,6 +105,7 @@ impl Violation for UnsortedDunderSlots {
|
|||
|
||||
const SORTING_STYLE: SortingStyle = SortingStyle::Natural;
|
||||
|
||||
/// RUF023
|
||||
/// Sort a tuple, list, dict or set that defines `__slots__` in a class scope.
|
||||
///
|
||||
/// This routine checks whether the display is sorted, and emits a
|
||||
|
|
|
@ -74,7 +74,7 @@ impl Violation for UnnecessaryNestedLiteral {
|
|||
}
|
||||
}
|
||||
|
||||
/// RUF039
|
||||
/// RUF041
|
||||
pub(crate) fn unnecessary_nested_literal<'a>(checker: &Checker, literal_expr: &'a Expr) {
|
||||
let mut is_nested = false;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue