mirror of https://github.com/astral-sh/ruff
[`flake8-self`] Add Plugin and Rule `SLF001` (#2470)
This commit is contained in:
parent
b032f50775
commit
9e59c99133
5
LICENSE
5
LICENSE
|
|
@ -1030,3 +1030,8 @@ are:
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
- flake8-self, licensed as follows:
|
||||||
|
"""
|
||||||
|
Freely Distributable
|
||||||
|
"""
|
||||||
|
|
|
||||||
11
README.md
11
README.md
|
|
@ -158,6 +158,7 @@ This README is also available as [documentation](https://beta.ruff.rs/docs/).
|
||||||
1. [Pylint (PL)](#pylint-pl)
|
1. [Pylint (PL)](#pylint-pl)
|
||||||
1. [tryceratops (TRY)](#tryceratops-try)
|
1. [tryceratops (TRY)](#tryceratops-try)
|
||||||
1. [flake8-raise (RSE)](#flake8-raise-rse)
|
1. [flake8-raise (RSE)](#flake8-raise-rse)
|
||||||
|
1. [flake8-self (SLF)](#flake8-self-slf)
|
||||||
1. [Ruff-specific rules (RUF)](#ruff-specific-rules-ruf)<!-- End auto-generated table of contents. -->
|
1. [Ruff-specific rules (RUF)](#ruff-specific-rules-ruf)<!-- End auto-generated table of contents. -->
|
||||||
1. [Editor Integrations](#editor-integrations)
|
1. [Editor Integrations](#editor-integrations)
|
||||||
1. [FAQ](#faq)
|
1. [FAQ](#faq)
|
||||||
|
|
@ -1368,6 +1369,14 @@ For more, see [flake8-raise](https://pypi.org/project/flake8-raise/) on PyPI.
|
||||||
| ---- | ---- | ------- | --- |
|
| ---- | ---- | ------- | --- |
|
||||||
| RSE102 | unnecessary-paren-on-raise-exception | Unnecessary parentheses on raised exception | |
|
| RSE102 | unnecessary-paren-on-raise-exception | Unnecessary parentheses on raised exception | |
|
||||||
|
|
||||||
|
### flake8-self (SLF)
|
||||||
|
|
||||||
|
For more, see [flake8-self](https://pypi.org/project/flake8-self/) on PyPI.
|
||||||
|
|
||||||
|
| Code | Name | Message | Fix |
|
||||||
|
| ---- | ---- | ------- | --- |
|
||||||
|
| SLF001 | private-member-access | Private member accessed: `{access}` | |
|
||||||
|
|
||||||
### Ruff-specific rules (RUF)
|
### Ruff-specific rules (RUF)
|
||||||
|
|
||||||
| Code | Name | Message | Fix |
|
| Code | Name | Message | Fix |
|
||||||
|
|
@ -1661,6 +1670,7 @@ natively, including:
|
||||||
- [flake8-quotes](https://pypi.org/project/flake8-quotes/)
|
- [flake8-quotes](https://pypi.org/project/flake8-quotes/)
|
||||||
- [flake8-raise](https://pypi.org/project/flake8-raise/)
|
- [flake8-raise](https://pypi.org/project/flake8-raise/)
|
||||||
- [flake8-return](https://pypi.org/project/flake8-return/)
|
- [flake8-return](https://pypi.org/project/flake8-return/)
|
||||||
|
- [flake8-self](https://pypi.org/project/flake8-self/)
|
||||||
- [flake8-simplify](https://pypi.org/project/flake8-simplify/) ([#998](https://github.com/charliermarsh/ruff/issues/998))
|
- [flake8-simplify](https://pypi.org/project/flake8-simplify/) ([#998](https://github.com/charliermarsh/ruff/issues/998))
|
||||||
- [flake8-super](https://pypi.org/project/flake8-super/)
|
- [flake8-super](https://pypi.org/project/flake8-super/)
|
||||||
- [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/)
|
- [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/)
|
||||||
|
|
@ -1750,6 +1760,7 @@ Today, Ruff can be used to replace Flake8 when used with any of the following pl
|
||||||
- [flake8-quotes](https://pypi.org/project/flake8-quotes/)
|
- [flake8-quotes](https://pypi.org/project/flake8-quotes/)
|
||||||
- [flake8-raise](https://pypi.org/project/flake8-raise/)
|
- [flake8-raise](https://pypi.org/project/flake8-raise/)
|
||||||
- [flake8-return](https://pypi.org/project/flake8-return/)
|
- [flake8-return](https://pypi.org/project/flake8-return/)
|
||||||
|
- [flake8-self](https://pypi.org/project/flake8-self/)
|
||||||
- [flake8-simplify](https://pypi.org/project/flake8-simplify/) ([#998](https://github.com/charliermarsh/ruff/issues/998))
|
- [flake8-simplify](https://pypi.org/project/flake8-simplify/) ([#998](https://github.com/charliermarsh/ruff/issues/998))
|
||||||
- [flake8-super](https://pypi.org/project/flake8-super/)
|
- [flake8-super](https://pypi.org/project/flake8-super/)
|
||||||
- [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/)
|
- [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
class Foo:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.public_thing = "foo"
|
||||||
|
self._private_thing = "bar"
|
||||||
|
self.__really_private_thing = "baz"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "foo"
|
||||||
|
|
||||||
|
def public_func(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _private_func(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __really_private_func(self, arg):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
foo = Foo()
|
||||||
|
|
||||||
|
print(foo.public_thing)
|
||||||
|
print(foo.public_func())
|
||||||
|
print(foo.__dict__)
|
||||||
|
print(foo.__str__())
|
||||||
|
|
||||||
|
print(foo._private_thing) # SLF001
|
||||||
|
print(foo.__really_private_thing) # SLF001
|
||||||
|
print(foo._private_func()) # SLF001
|
||||||
|
print(foo.__really_private_func(1)) # SLF001
|
||||||
|
|
@ -1828,6 +1828,10 @@
|
||||||
"SIM4",
|
"SIM4",
|
||||||
"SIM40",
|
"SIM40",
|
||||||
"SIM401",
|
"SIM401",
|
||||||
|
"SLF",
|
||||||
|
"SLF0",
|
||||||
|
"SLF00",
|
||||||
|
"SLF001",
|
||||||
"T",
|
"T",
|
||||||
"T1",
|
"T1",
|
||||||
"T10",
|
"T10",
|
||||||
|
|
|
||||||
|
|
@ -36,10 +36,10 @@ use crate::rules::{
|
||||||
flake8_2020, flake8_annotations, flake8_bandit, flake8_blind_except, flake8_boolean_trap,
|
flake8_2020, flake8_annotations, flake8_bandit, flake8_blind_except, flake8_boolean_trap,
|
||||||
flake8_bugbear, flake8_builtins, flake8_comprehensions, flake8_datetimez, flake8_debugger,
|
flake8_bugbear, flake8_builtins, flake8_comprehensions, flake8_datetimez, flake8_debugger,
|
||||||
flake8_errmsg, flake8_implicit_str_concat, flake8_import_conventions, flake8_logging_format,
|
flake8_errmsg, flake8_implicit_str_concat, flake8_import_conventions, flake8_logging_format,
|
||||||
flake8_pie, flake8_print, flake8_pytest_style, flake8_raise, flake8_return, flake8_simplify,
|
flake8_pie, flake8_print, flake8_pytest_style, flake8_raise, flake8_return, flake8_self,
|
||||||
flake8_tidy_imports, flake8_type_checking, flake8_unused_arguments, flake8_use_pathlib, mccabe,
|
flake8_simplify, flake8_tidy_imports, flake8_type_checking, flake8_unused_arguments,
|
||||||
pandas_vet, pep8_naming, pycodestyle, pydocstyle, pyflakes, pygrep_hooks, pylint, pyupgrade,
|
flake8_use_pathlib, mccabe, pandas_vet, pep8_naming, pycodestyle, pydocstyle, pyflakes,
|
||||||
ruff, tryceratops,
|
pygrep_hooks, pylint, pyupgrade, ruff, tryceratops,
|
||||||
};
|
};
|
||||||
use crate::settings::types::PythonVersion;
|
use crate::settings::types::PythonVersion;
|
||||||
use crate::settings::{flags, Settings};
|
use crate::settings::{flags, Settings};
|
||||||
|
|
@ -2148,6 +2148,9 @@ where
|
||||||
if self.settings.rules.enabled(&Rule::BannedApi) {
|
if self.settings.rules.enabled(&Rule::BannedApi) {
|
||||||
flake8_tidy_imports::banned_api::banned_attribute_access(self, expr);
|
flake8_tidy_imports::banned_api::banned_attribute_access(self, expr);
|
||||||
}
|
}
|
||||||
|
if self.settings.rules.enabled(&Rule::PrivateMemberAccess) {
|
||||||
|
flake8_self::rules::private_member_access(self, expr);
|
||||||
|
}
|
||||||
pandas_vet::rules::check_attr(self, attr, value, expr);
|
pandas_vet::rules::check_attr(self, attr, value, expr);
|
||||||
}
|
}
|
||||||
ExprKind::Call {
|
ExprKind::Call {
|
||||||
|
|
|
||||||
|
|
@ -484,6 +484,8 @@ ruff_macros::define_rule_mapping!(
|
||||||
G202 => rules::flake8_logging_format::violations::LoggingRedundantExcInfo,
|
G202 => rules::flake8_logging_format::violations::LoggingRedundantExcInfo,
|
||||||
// flake8-raise
|
// flake8-raise
|
||||||
RSE102 => rules::flake8_raise::rules::UnnecessaryParenOnRaiseException,
|
RSE102 => rules::flake8_raise::rules::UnnecessaryParenOnRaiseException,
|
||||||
|
// flake8-self
|
||||||
|
SLF001 => rules::flake8_self::rules::PrivateMemberAccess,
|
||||||
// ruff
|
// ruff
|
||||||
RUF001 => violations::AmbiguousUnicodeCharacterString,
|
RUF001 => violations::AmbiguousUnicodeCharacterString,
|
||||||
RUF002 => violations::AmbiguousUnicodeCharacterDocstring,
|
RUF002 => violations::AmbiguousUnicodeCharacterDocstring,
|
||||||
|
|
@ -616,6 +618,9 @@ pub enum Linter {
|
||||||
/// [flake8-raise](https://pypi.org/project/flake8-raise/)
|
/// [flake8-raise](https://pypi.org/project/flake8-raise/)
|
||||||
#[prefix = "RSE"]
|
#[prefix = "RSE"]
|
||||||
Flake8Raise,
|
Flake8Raise,
|
||||||
|
/// [flake8-self](https://pypi.org/project/flake8-self/)
|
||||||
|
#[prefix = "SLF"]
|
||||||
|
Flake8Self,
|
||||||
/// Ruff-specific rules
|
/// Ruff-specific rules
|
||||||
#[prefix = "RUF"]
|
#[prefix = "RUF"]
|
||||||
Ruff,
|
Ruff,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
//! Rules from [flake8-self](https://pypi.org/project/flake8-self/).
|
||||||
|
pub(crate) mod rules;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::convert::AsRef;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use test_case::test_case;
|
||||||
|
|
||||||
|
use crate::registry::Rule;
|
||||||
|
use crate::test::test_path;
|
||||||
|
use crate::{assert_yaml_snapshot, settings};
|
||||||
|
|
||||||
|
#[test_case(Rule::PrivateMemberAccess, Path::new("SLF001.py"); "SLF001")]
|
||||||
|
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
|
||||||
|
let snapshot = format!("{}_{}", rule_code.as_ref(), path.to_string_lossy());
|
||||||
|
let diagnostics = test_path(
|
||||||
|
Path::new("flake8_self").join(path).as_path(),
|
||||||
|
&settings::Settings::for_rule(rule_code),
|
||||||
|
)?;
|
||||||
|
assert_yaml_snapshot!(snapshot, diagnostics);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
pub use private_member_access::{private_member_access, PrivateMemberAccess};
|
||||||
|
|
||||||
|
mod private_member_access;
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
use ruff_macros::derive_message_formats;
|
||||||
|
|
||||||
|
use crate::ast::types::Range;
|
||||||
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::define_violation;
|
||||||
|
use crate::registry::Diagnostic;
|
||||||
|
use crate::violation::Violation;
|
||||||
|
use rustpython_ast::{Expr, ExprKind};
|
||||||
|
|
||||||
|
define_violation!(
|
||||||
|
pub struct PrivateMemberAccess {
|
||||||
|
pub access: String,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
impl Violation for PrivateMemberAccess {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
let PrivateMemberAccess { access } = self;
|
||||||
|
format!("Private member accessed: `{access}`")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const VALID_IDS: [&str; 3] = ["self", "cls", "mcs"];
|
||||||
|
|
||||||
|
/// SLF001
|
||||||
|
pub fn private_member_access(checker: &mut Checker, expr: &Expr) {
|
||||||
|
if let ExprKind::Attribute { value, attr, .. } = &expr.node {
|
||||||
|
if !attr.ends_with("__") && (attr.starts_with('_') || attr.starts_with("__")) {
|
||||||
|
let ExprKind::Name { id, .. } = &value.node else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if !VALID_IDS.contains(&id.as_str()) {
|
||||||
|
checker.diagnostics.push(Diagnostic::new(
|
||||||
|
PrivateMemberAccess {
|
||||||
|
access: format!("{}.{}", id, attr),
|
||||||
|
},
|
||||||
|
Range::from_located(expr),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
---
|
||||||
|
source: src/rules/flake8_self/mod.rs
|
||||||
|
expression: diagnostics
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
PrivateMemberAccess: ~
|
||||||
|
location:
|
||||||
|
row: 28
|
||||||
|
column: 6
|
||||||
|
end_location:
|
||||||
|
row: 28
|
||||||
|
column: 24
|
||||||
|
fix: ~
|
||||||
|
parent: ~
|
||||||
|
- kind:
|
||||||
|
PrivateMemberAccess: ~
|
||||||
|
location:
|
||||||
|
row: 29
|
||||||
|
column: 6
|
||||||
|
end_location:
|
||||||
|
row: 29
|
||||||
|
column: 32
|
||||||
|
fix: ~
|
||||||
|
parent: ~
|
||||||
|
- kind:
|
||||||
|
PrivateMemberAccess: ~
|
||||||
|
location:
|
||||||
|
row: 30
|
||||||
|
column: 6
|
||||||
|
end_location:
|
||||||
|
row: 30
|
||||||
|
column: 23
|
||||||
|
fix: ~
|
||||||
|
parent: ~
|
||||||
|
- kind:
|
||||||
|
PrivateMemberAccess: ~
|
||||||
|
location:
|
||||||
|
row: 31
|
||||||
|
column: 6
|
||||||
|
end_location:
|
||||||
|
row: 31
|
||||||
|
column: 31
|
||||||
|
fix: ~
|
||||||
|
parent: ~
|
||||||
|
|
||||||
|
|
@ -23,6 +23,7 @@ pub mod flake8_pytest_style;
|
||||||
pub mod flake8_quotes;
|
pub mod flake8_quotes;
|
||||||
pub mod flake8_raise;
|
pub mod flake8_raise;
|
||||||
pub mod flake8_return;
|
pub mod flake8_return;
|
||||||
|
pub mod flake8_self;
|
||||||
pub mod flake8_simplify;
|
pub mod flake8_simplify;
|
||||||
pub mod flake8_tidy_imports;
|
pub mod flake8_tidy_imports;
|
||||||
pub mod flake8_type_checking;
|
pub mod flake8_type_checking;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue