mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 02:12:22 +00:00
[flake8-self
] Add Plugin and Rule SLF001
(#2470)
This commit is contained in:
parent
b032f50775
commit
9e59c99133
11 changed files with 181 additions and 4 deletions
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
|
||||
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. [tryceratops (TRY)](#tryceratops-try)
|
||||
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. [Editor Integrations](#editor-integrations)
|
||||
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 | |
|
||||
|
||||
### 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)
|
||||
|
||||
| Code | Name | Message | Fix |
|
||||
|
@ -1661,6 +1670,7 @@ natively, including:
|
|||
- [flake8-quotes](https://pypi.org/project/flake8-quotes/)
|
||||
- [flake8-raise](https://pypi.org/project/flake8-raise/)
|
||||
- [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-super](https://pypi.org/project/flake8-super/)
|
||||
- [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-raise](https://pypi.org/project/flake8-raise/)
|
||||
- [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-super](https://pypi.org/project/flake8-super/)
|
||||
- [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/)
|
||||
|
|
31
resources/test/fixtures/flake8_self/SLF001.py
vendored
Normal file
31
resources/test/fixtures/flake8_self/SLF001.py
vendored
Normal file
|
@ -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",
|
||||
"SIM40",
|
||||
"SIM401",
|
||||
"SLF",
|
||||
"SLF0",
|
||||
"SLF00",
|
||||
"SLF001",
|
||||
"T",
|
||||
"T1",
|
||||
"T10",
|
||||
|
|
|
@ -36,10 +36,10 @@ use crate::rules::{
|
|||
flake8_2020, flake8_annotations, flake8_bandit, flake8_blind_except, flake8_boolean_trap,
|
||||
flake8_bugbear, flake8_builtins, flake8_comprehensions, flake8_datetimez, flake8_debugger,
|
||||
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_tidy_imports, flake8_type_checking, flake8_unused_arguments, flake8_use_pathlib, mccabe,
|
||||
pandas_vet, pep8_naming, pycodestyle, pydocstyle, pyflakes, pygrep_hooks, pylint, pyupgrade,
|
||||
ruff, tryceratops,
|
||||
flake8_pie, flake8_print, flake8_pytest_style, flake8_raise, flake8_return, flake8_self,
|
||||
flake8_simplify, flake8_tidy_imports, flake8_type_checking, flake8_unused_arguments,
|
||||
flake8_use_pathlib, mccabe, pandas_vet, pep8_naming, pycodestyle, pydocstyle, pyflakes,
|
||||
pygrep_hooks, pylint, pyupgrade, ruff, tryceratops,
|
||||
};
|
||||
use crate::settings::types::PythonVersion;
|
||||
use crate::settings::{flags, Settings};
|
||||
|
@ -2148,6 +2148,9 @@ where
|
|||
if self.settings.rules.enabled(&Rule::BannedApi) {
|
||||
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);
|
||||
}
|
||||
ExprKind::Call {
|
||||
|
|
|
@ -484,6 +484,8 @@ ruff_macros::define_rule_mapping!(
|
|||
G202 => rules::flake8_logging_format::violations::LoggingRedundantExcInfo,
|
||||
// flake8-raise
|
||||
RSE102 => rules::flake8_raise::rules::UnnecessaryParenOnRaiseException,
|
||||
// flake8-self
|
||||
SLF001 => rules::flake8_self::rules::PrivateMemberAccess,
|
||||
// ruff
|
||||
RUF001 => violations::AmbiguousUnicodeCharacterString,
|
||||
RUF002 => violations::AmbiguousUnicodeCharacterDocstring,
|
||||
|
@ -616,6 +618,9 @@ pub enum Linter {
|
|||
/// [flake8-raise](https://pypi.org/project/flake8-raise/)
|
||||
#[prefix = "RSE"]
|
||||
Flake8Raise,
|
||||
/// [flake8-self](https://pypi.org/project/flake8-self/)
|
||||
#[prefix = "SLF"]
|
||||
Flake8Self,
|
||||
/// Ruff-specific rules
|
||||
#[prefix = "RUF"]
|
||||
Ruff,
|
||||
|
|
26
src/rules/flake8_self/mod.rs
Normal file
26
src/rules/flake8_self/mod.rs
Normal file
|
@ -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(())
|
||||
}
|
||||
}
|
3
src/rules/flake8_self/rules/mod.rs
Normal file
3
src/rules/flake8_self/rules/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
pub use private_member_access::{private_member_access, PrivateMemberAccess};
|
||||
|
||||
mod private_member_access;
|
43
src/rules/flake8_self/rules/private_member_access.rs
Normal file
43
src/rules/flake8_self/rules/private_member_access.rs
Normal file
|
@ -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_raise;
|
||||
pub mod flake8_return;
|
||||
pub mod flake8_self;
|
||||
pub mod flake8_simplify;
|
||||
pub mod flake8_tidy_imports;
|
||||
pub mod flake8_type_checking;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue