[flake8-self] Add Plugin and Rule SLF001 (#2470)

This commit is contained in:
Maksudul Haque 2023-02-02 18:58:14 +06:00 committed by GitHub
parent b032f50775
commit 9e59c99133
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 181 additions and 4 deletions

View file

@ -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
"""

View file

@ -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/)

View 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

View file

@ -1828,6 +1828,10 @@
"SIM4",
"SIM40",
"SIM401",
"SLF",
"SLF0",
"SLF00",
"SLF001",
"T",
"T1",
"T10",

View file

@ -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 {

View file

@ -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,

View 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(())
}
}

View file

@ -0,0 +1,3 @@
pub use private_member_access::{private_member_access, PrivateMemberAccess};
mod private_member_access;

View 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),
));
}
}
}
}

View file

@ -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: ~

View file

@ -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;