mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-24 13:33:50 +00:00
[pydocstyle
] Add setting to ignore missing documentation for*args
and **kwargs
parameters (D417
) (#15210)
Co-authored-by: Micha Reiser <micha@reiser.io>
This commit is contained in:
parent
3c9021ffcb
commit
cfd6093579
11 changed files with 285 additions and 50 deletions
|
@ -168,3 +168,12 @@ def select_data(
|
|||
database:
|
||||
Which database to connect to ("origin" or "destination").
|
||||
"""
|
||||
|
||||
def f(x, *args, **kwargs):
|
||||
"""Do something.
|
||||
|
||||
Args:
|
||||
x: the value
|
||||
*args: var-arguments
|
||||
"""
|
||||
return x
|
|
@ -37,7 +37,10 @@ mod tests {
|
|||
let diagnostics = test_path(
|
||||
Path::new("pydoclint").join(path).as_path(),
|
||||
&settings::LinterSettings {
|
||||
pydocstyle: pydocstyle::settings::Settings::new(Some(Convention::Google), [], []),
|
||||
pydocstyle: pydocstyle::settings::Settings {
|
||||
convention: Some(Convention::Google),
|
||||
..pydocstyle::settings::Settings::default()
|
||||
},
|
||||
..settings::LinterSettings::for_rule(rule_code)
|
||||
},
|
||||
)?;
|
||||
|
@ -56,7 +59,10 @@ mod tests {
|
|||
let diagnostics = test_path(
|
||||
Path::new("pydoclint").join(path).as_path(),
|
||||
&settings::LinterSettings {
|
||||
pydocstyle: pydocstyle::settings::Settings::new(Some(Convention::Numpy), [], []),
|
||||
pydocstyle: pydocstyle::settings::Settings {
|
||||
convention: Some(Convention::Numpy),
|
||||
..pydocstyle::settings::Settings::default()
|
||||
},
|
||||
..settings::LinterSettings::for_rule(rule_code)
|
||||
},
|
||||
)?;
|
||||
|
|
|
@ -12,11 +12,10 @@ mod tests {
|
|||
|
||||
use crate::registry::Rule;
|
||||
|
||||
use super::settings::{Convention, Settings};
|
||||
use crate::test::test_path;
|
||||
use crate::{assert_messages, settings};
|
||||
|
||||
use super::settings::{Convention, Settings};
|
||||
|
||||
#[test_case(Rule::MissingBlankLineAfterLastSection, Path::new("sections.py"))]
|
||||
#[test_case(Rule::NoBlankLineAfterSection, Path::new("sections.py"))]
|
||||
#[test_case(Rule::MissingBlankLineAfterLastSection, Path::new("D413.py"))]
|
||||
|
@ -100,11 +99,13 @@ mod tests {
|
|||
let diagnostics = test_path(
|
||||
Path::new("pydocstyle").join(path).as_path(),
|
||||
&settings::LinterSettings {
|
||||
pydocstyle: Settings::new(
|
||||
None,
|
||||
["functools.wraps".to_string()],
|
||||
["gi.repository.GObject.Property".to_string()],
|
||||
),
|
||||
pydocstyle: Settings {
|
||||
ignore_decorators: ["functools.wraps".to_string()].into_iter().collect(),
|
||||
property_decorators: ["gi.repository.GObject.Property".to_string()]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
..Settings::default()
|
||||
},
|
||||
..settings::LinterSettings::for_rule(rule_code)
|
||||
},
|
||||
)?;
|
||||
|
@ -137,13 +138,46 @@ mod tests {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn d417_unspecified_ignore_var_parameters() -> Result<()> {
|
||||
let diagnostics = test_path(
|
||||
Path::new("pydocstyle/D417.py"),
|
||||
&settings::LinterSettings {
|
||||
pydocstyle: Settings::default(),
|
||||
..settings::LinterSettings::for_rule(Rule::UndocumentedParam)
|
||||
},
|
||||
)?;
|
||||
assert_messages!(diagnostics);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn d417_google() -> Result<()> {
|
||||
let diagnostics = test_path(
|
||||
Path::new("pydocstyle/D417.py"),
|
||||
&settings::LinterSettings {
|
||||
// With explicit Google convention, we should flag every function.
|
||||
pydocstyle: Settings::new(Some(Convention::Google), [], []),
|
||||
pydocstyle: Settings {
|
||||
convention: Some(Convention::Google),
|
||||
..Settings::default()
|
||||
},
|
||||
..settings::LinterSettings::for_rule(Rule::UndocumentedParam)
|
||||
},
|
||||
)?;
|
||||
assert_messages!(diagnostics);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn d417_google_ignore_var_parameters() -> Result<()> {
|
||||
let diagnostics = test_path(
|
||||
Path::new("pydocstyle/D417.py"),
|
||||
&settings::LinterSettings {
|
||||
pydocstyle: Settings {
|
||||
convention: Some(Convention::Google),
|
||||
ignore_var_parameters: true,
|
||||
..Settings::default()
|
||||
},
|
||||
..settings::LinterSettings::for_rule(Rule::UndocumentedParam)
|
||||
},
|
||||
)?;
|
||||
|
@ -157,7 +191,10 @@ mod tests {
|
|||
Path::new("pydocstyle/D417.py"),
|
||||
&settings::LinterSettings {
|
||||
// With explicit numpy convention, we shouldn't flag anything.
|
||||
pydocstyle: Settings::new(Some(Convention::Numpy), [], []),
|
||||
pydocstyle: Settings {
|
||||
convention: Some(Convention::Numpy),
|
||||
..Settings::default()
|
||||
},
|
||||
..settings::LinterSettings::for_rule(Rule::UndocumentedParam)
|
||||
},
|
||||
)?;
|
||||
|
|
|
@ -1215,6 +1215,7 @@ impl AlwaysFixableViolation for MissingSectionNameColon {
|
|||
///
|
||||
/// ## Options
|
||||
/// - `lint.pydocstyle.convention`
|
||||
/// - `lint.pydocstyle.ignore-var-parameters`
|
||||
///
|
||||
/// ## References
|
||||
/// - [PEP 257 – Docstring Conventions](https://peps.python.org/pep-0257/)
|
||||
|
@ -1810,24 +1811,26 @@ fn missing_args(checker: &mut Checker, docstring: &Docstring, docstrings_args: &
|
|||
|
||||
// Check specifically for `vararg` and `kwarg`, which can be prefixed with a
|
||||
// single or double star, respectively.
|
||||
if let Some(arg) = function.parameters.vararg.as_ref() {
|
||||
let arg_name = arg.name.as_str();
|
||||
let starred_arg_name = format!("*{arg_name}");
|
||||
if !arg_name.starts_with('_')
|
||||
&& !docstrings_args.contains(arg_name)
|
||||
&& !docstrings_args.contains(&starred_arg_name)
|
||||
{
|
||||
missing_arg_names.insert(starred_arg_name);
|
||||
if !checker.settings.pydocstyle.ignore_var_parameters() {
|
||||
if let Some(arg) = function.parameters.vararg.as_ref() {
|
||||
let arg_name = arg.name.as_str();
|
||||
let starred_arg_name = format!("*{arg_name}");
|
||||
if !arg_name.starts_with('_')
|
||||
&& !docstrings_args.contains(arg_name)
|
||||
&& !docstrings_args.contains(&starred_arg_name)
|
||||
{
|
||||
missing_arg_names.insert(starred_arg_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(arg) = function.parameters.kwarg.as_ref() {
|
||||
let arg_name = arg.name.as_str();
|
||||
let starred_arg_name = format!("**{arg_name}");
|
||||
if !arg_name.starts_with('_')
|
||||
&& !docstrings_args.contains(arg_name)
|
||||
&& !docstrings_args.contains(&starred_arg_name)
|
||||
{
|
||||
missing_arg_names.insert(starred_arg_name);
|
||||
if let Some(arg) = function.parameters.kwarg.as_ref() {
|
||||
let arg_name = arg.name.as_str();
|
||||
let starred_arg_name = format!("**{arg_name}");
|
||||
if !arg_name.starts_with('_')
|
||||
&& !docstrings_args.contains(arg_name)
|
||||
&& !docstrings_args.contains(&starred_arg_name)
|
||||
{
|
||||
missing_arg_names.insert(starred_arg_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -87,25 +87,13 @@ impl fmt::Display for Convention {
|
|||
|
||||
#[derive(Debug, Clone, Default, CacheKey)]
|
||||
pub struct Settings {
|
||||
convention: Option<Convention>,
|
||||
ignore_decorators: BTreeSet<String>,
|
||||
property_decorators: BTreeSet<String>,
|
||||
pub convention: Option<Convention>,
|
||||
pub ignore_decorators: BTreeSet<String>,
|
||||
pub property_decorators: BTreeSet<String>,
|
||||
pub ignore_var_parameters: bool,
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
#[must_use]
|
||||
pub fn new(
|
||||
convention: Option<Convention>,
|
||||
ignore_decorators: impl IntoIterator<Item = String>,
|
||||
property_decorators: impl IntoIterator<Item = String>,
|
||||
) -> Self {
|
||||
Self {
|
||||
convention,
|
||||
ignore_decorators: ignore_decorators.into_iter().collect(),
|
||||
property_decorators: property_decorators.into_iter().collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn convention(&self) -> Option<Convention> {
|
||||
self.convention
|
||||
}
|
||||
|
@ -117,6 +105,10 @@ impl Settings {
|
|||
pub fn property_decorators(&self) -> DecoratorIterator {
|
||||
DecoratorIterator::new(&self.property_decorators)
|
||||
}
|
||||
|
||||
pub fn ignore_var_parameters(&self) -> bool {
|
||||
self.ignore_var_parameters
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Settings {
|
||||
|
@ -127,7 +119,8 @@ impl fmt::Display for Settings {
|
|||
fields = [
|
||||
self.convention | optional,
|
||||
self.ignore_decorators | set,
|
||||
self.property_decorators | set
|
||||
self.property_decorators | set,
|
||||
self.ignore_var_parameters
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
@ -72,3 +72,12 @@ D417.py:155:5: D417 Missing argument description in the docstring for `select_da
|
|||
156 | query: str,
|
||||
157 | args: tuple,
|
||||
|
|
||||
|
||||
D417.py:172:5: D417 Missing argument description in the docstring for `f`: `**kwargs`
|
||||
|
|
||||
170 | """
|
||||
171 |
|
||||
172 | def f(x, *args, **kwargs):
|
||||
| ^ D417
|
||||
173 | """Do something.
|
||||
|
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/pydocstyle/mod.rs
|
||||
snapshot_kind: text
|
||||
---
|
||||
D417.py:1:5: D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||
|
|
||||
1 | def f(x, y, z):
|
||||
| ^ D417
|
||||
2 | """Do something.
|
||||
|
|
||||
|
||||
D417.py:14:5: D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||
|
|
||||
14 | def f(x, y, z):
|
||||
| ^ D417
|
||||
15 | """Do something.
|
||||
|
|
||||
|
||||
D417.py:27:5: D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||
|
|
||||
27 | def f(x, y, z):
|
||||
| ^ D417
|
||||
28 | """Do something.
|
||||
|
|
||||
|
||||
D417.py:39:5: D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||
|
|
||||
39 | def f(x, y, z):
|
||||
| ^ D417
|
||||
40 | """Do something.
|
||||
|
|
||||
|
||||
D417.py:52:5: D417 Missing argument description in the docstring for `f`: `y`
|
||||
|
|
||||
52 | def f(x, y, z):
|
||||
| ^ D417
|
||||
53 | """Do something.
|
||||
|
|
||||
|
||||
D417.py:65:5: D417 Missing argument description in the docstring for `f`: `y`
|
||||
|
|
||||
65 | def f(x, y, z):
|
||||
| ^ D417
|
||||
66 | """Do something.
|
||||
|
|
||||
|
||||
D417.py:77:5: D417 Missing argument description in the docstring for `f`: `y`
|
||||
|
|
||||
77 | def f(x, y, z):
|
||||
| ^ D417
|
||||
78 | """Do something.
|
||||
|
|
||||
|
||||
D417.py:98:5: D417 Missing argument description in the docstring for `f`: `x`
|
||||
|
|
||||
98 | def f(x, *args, **kwargs):
|
||||
| ^ D417
|
||||
99 | """Do something.
|
||||
|
|
||||
|
||||
D417.py:155:5: D417 Missing argument description in the docstring for `select_data`: `auto_save`
|
||||
|
|
||||
155 | def select_data(
|
||||
| ^^^^^^^^^^^ D417
|
||||
156 | query: str,
|
||||
157 | args: tuple,
|
||||
|
|
|
@ -72,3 +72,12 @@ D417.py:155:5: D417 Missing argument description in the docstring for `select_da
|
|||
156 | query: str,
|
||||
157 | args: tuple,
|
||||
|
|
||||
|
||||
D417.py:172:5: D417 Missing argument description in the docstring for `f`: `**kwargs`
|
||||
|
|
||||
170 | """
|
||||
171 |
|
||||
172 | def f(x, *args, **kwargs):
|
||||
| ^ D417
|
||||
173 | """Do something.
|
||||
|
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/pydocstyle/mod.rs
|
||||
snapshot_kind: text
|
||||
---
|
||||
D417.py:1:5: D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||
|
|
||||
1 | def f(x, y, z):
|
||||
| ^ D417
|
||||
2 | """Do something.
|
||||
|
|
||||
|
||||
D417.py:14:5: D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||
|
|
||||
14 | def f(x, y, z):
|
||||
| ^ D417
|
||||
15 | """Do something.
|
||||
|
|
||||
|
||||
D417.py:27:5: D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||
|
|
||||
27 | def f(x, y, z):
|
||||
| ^ D417
|
||||
28 | """Do something.
|
||||
|
|
||||
|
||||
D417.py:39:5: D417 Missing argument descriptions in the docstring for `f`: `y`, `z`
|
||||
|
|
||||
39 | def f(x, y, z):
|
||||
| ^ D417
|
||||
40 | """Do something.
|
||||
|
|
||||
|
||||
D417.py:52:5: D417 Missing argument description in the docstring for `f`: `y`
|
||||
|
|
||||
52 | def f(x, y, z):
|
||||
| ^ D417
|
||||
53 | """Do something.
|
||||
|
|
||||
|
||||
D417.py:65:5: D417 Missing argument description in the docstring for `f`: `y`
|
||||
|
|
||||
65 | def f(x, y, z):
|
||||
| ^ D417
|
||||
66 | """Do something.
|
||||
|
|
||||
|
||||
D417.py:77:5: D417 Missing argument description in the docstring for `f`: `y`
|
||||
|
|
||||
77 | def f(x, y, z):
|
||||
| ^ D417
|
||||
78 | """Do something.
|
||||
|
|
||||
|
||||
D417.py:98:5: D417 Missing argument description in the docstring for `f`: `x`
|
||||
|
|
||||
98 | def f(x, *args, **kwargs):
|
||||
| ^ D417
|
||||
99 | """Do something.
|
||||
|
|
||||
|
||||
D417.py:108:5: D417 Missing argument description in the docstring for `f`: `*args`
|
||||
|
|
||||
108 | def f(x, *args, **kwargs):
|
||||
| ^ D417
|
||||
109 | """Do something.
|
||||
|
|
||||
|
||||
D417.py:155:5: D417 Missing argument description in the docstring for `select_data`: `auto_save`
|
||||
|
|
||||
155 | def select_data(
|
||||
| ^^^^^^^^^^^ D417
|
||||
156 | query: str,
|
||||
157 | args: tuple,
|
||||
|
|
||||
|
||||
D417.py:172:5: D417 Missing argument description in the docstring for `f`: `**kwargs`
|
||||
|
|
||||
170 | """
|
||||
171 |
|
||||
172 | def f(x, *args, **kwargs):
|
||||
| ^ D417
|
||||
173 | """Do something.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue