[pylint] Add allow-dunder-method-names setting for bad-dunder-method-name (PLW3201) (#8812)

closes #8732

I noticed that the reference to the setting in the rule docs doesn't
work, but there seem to be something wrong with pylint settings in
general in the docs - the "For related settings, see ...." is also
missing there.
This commit is contained in:
Adrian 2023-11-22 00:44:23 +01:00 committed by GitHub
parent f1ed0f27c2
commit 948094e691
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 55 additions and 3 deletions

View file

@ -83,6 +83,10 @@ class Apples:
def _(self): def _(self):
pass pass
# Allow custom dunder names (via setting).
def __special_custom_magic__(self):
pass
def __foo_bar__(): # this is not checked by the [bad-dunder-name] rule def __foo_bar__(): # this is not checked by the [bad-dunder-name] rule
... ...

View file

@ -9,6 +9,7 @@ mod tests {
use anyhow::Result; use anyhow::Result;
use regex::Regex; use regex::Regex;
use rustc_hash::FxHashSet;
use test_case::test_case; use test_case::test_case;
use crate::assert_messages; use crate::assert_messages;
@ -157,7 +158,15 @@ mod tests {
let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy()); let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy());
let diagnostics = test_path( let diagnostics = test_path(
Path::new("pylint").join(path).as_path(), Path::new("pylint").join(path).as_path(),
&LinterSettings::for_rule(rule_code), &LinterSettings {
pylint: pylint::settings::Settings {
allow_dunder_method_names: FxHashSet::from_iter([
"__special_custom_magic__".to_string()
]),
..pylint::settings::Settings::default()
},
..LinterSettings::for_rule(rule_code)
},
)?; )?;
assert_messages!(snapshot, diagnostics); assert_messages!(snapshot, diagnostics);
Ok(()) Ok(())

View file

@ -22,6 +22,9 @@ use crate::checkers::ast::Checker;
/// one underscore (e.g., `_str_`), but ignores known dunder methods (like /// one underscore (e.g., `_str_`), but ignores known dunder methods (like
/// `__init__`), as well as methods that are marked with `@override`. /// `__init__`), as well as methods that are marked with `@override`.
/// ///
/// Additional dunder methods names can be allowed via the
/// [`pylint.allow-dunder-method-names`] setting.
///
/// ## Example /// ## Example
/// ```python /// ```python
/// class Foo: /// class Foo:
@ -35,6 +38,9 @@ use crate::checkers::ast::Checker;
/// def __init__(self): /// def __init__(self):
/// ... /// ...
/// ``` /// ```
///
/// ## Options
/// - `pylint.allow-dunder-method-names`
#[violation] #[violation]
pub struct BadDunderMethodName { pub struct BadDunderMethodName {
name: String, name: String,
@ -54,7 +60,14 @@ pub(crate) fn bad_dunder_method_name(checker: &mut Checker, class_body: &[Stmt])
.iter() .iter()
.filter_map(ruff_python_ast::Stmt::as_function_def_stmt) .filter_map(ruff_python_ast::Stmt::as_function_def_stmt)
.filter(|method| { .filter(|method| {
if is_known_dunder_method(&method.name) || matches!(method.name.as_str(), "_") { if is_known_dunder_method(&method.name)
|| checker
.settings
.pylint
.allow_dunder_method_names
.contains(method.name.as_str())
|| matches!(method.name.as_str(), "_")
{
return false; return false;
} }
method.name.starts_with('_') && method.name.ends_with('_') method.name.starts_with('_') && method.name.ends_with('_')

View file

@ -1,5 +1,6 @@
//! Settings for the `pylint` plugin. //! Settings for the `pylint` plugin.
use rustc_hash::FxHashSet;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use ruff_macros::CacheKey; use ruff_macros::CacheKey;
@ -36,6 +37,7 @@ impl ConstantType {
#[derive(Debug, CacheKey)] #[derive(Debug, CacheKey)]
pub struct Settings { pub struct Settings {
pub allow_magic_value_types: Vec<ConstantType>, pub allow_magic_value_types: Vec<ConstantType>,
pub allow_dunder_method_names: FxHashSet<String>,
pub max_args: usize, pub max_args: usize,
pub max_returns: usize, pub max_returns: usize,
pub max_bool_expr: usize, pub max_bool_expr: usize,
@ -48,6 +50,7 @@ impl Default for Settings {
fn default() -> Self { fn default() -> Self {
Self { Self {
allow_magic_value_types: vec![ConstantType::Str, ConstantType::Bytes], allow_magic_value_types: vec![ConstantType::Str, ConstantType::Bytes],
allow_dunder_method_names: FxHashSet::default(),
max_args: 5, max_args: 5,
max_returns: 6, max_returns: 6,
max_bool_expr: 5, max_bool_expr: 5,

View file

@ -2573,6 +2573,17 @@ pub struct PylintOptions {
)] )]
pub allow_magic_value_types: Option<Vec<ConstantType>>, pub allow_magic_value_types: Option<Vec<ConstantType>>,
/// Dunder methods name to allow, in addition to the default set from the
/// Python standard library (see: `PLW3201`).
#[option(
default = r#"[]"#,
value_type = r#"list[str]"#,
example = r#"
allow-dunder-method-names = ["__tablename__", "__table_args__"]
"#
)]
pub allow_dunder_method_names: Option<FxHashSet<String>>,
/// Maximum number of branches allowed for a function or method body (see: /// Maximum number of branches allowed for a function or method body (see:
/// `PLR0912`). /// `PLR0912`).
#[option(default = r"12", value_type = "int", example = r"max-branches = 12")] #[option(default = r"12", value_type = "int", example = r"max-branches = 12")]
@ -2614,6 +2625,7 @@ impl PylintOptions {
allow_magic_value_types: self allow_magic_value_types: self
.allow_magic_value_types .allow_magic_value_types
.unwrap_or(defaults.allow_magic_value_types), .unwrap_or(defaults.allow_magic_value_types),
allow_dunder_method_names: self.allow_dunder_method_names.unwrap_or_default(),
max_args: self.max_args.unwrap_or(defaults.max_args), max_args: self.max_args.unwrap_or(defaults.max_args),
max_bool_expr: self.max_bool_expr.unwrap_or(defaults.max_bool_expr), max_bool_expr: self.max_bool_expr.unwrap_or(defaults.max_bool_expr),
max_returns: self.max_returns.unwrap_or(defaults.max_returns), max_returns: self.max_returns.unwrap_or(defaults.max_returns),

11
ruff.schema.json generated
View file

@ -2307,6 +2307,17 @@
"PylintOptions": { "PylintOptions": {
"type": "object", "type": "object",
"properties": { "properties": {
"allow-dunder-method-names": {
"description": "Dunder methods name to allow, in addition to the default set from the Python standard library (see: `PLW3201`).",
"type": [
"array",
"null"
],
"items": {
"type": "string"
},
"uniqueItems": true
},
"allow-magic-value-types": { "allow-magic-value-types": {
"description": "Constant types to ignore when used as \"magic values\" (see: `PLR2004`).", "description": "Constant types to ignore when used as \"magic values\" (see: `PLR2004`).",
"type": [ "type": [