Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement PLE0206 #1005

Merged
merged 4 commits into from
Dec 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,7 @@ For more, see [Pylint](https://pypi.org/project/pylint/2.15.7/) on PyPI.

| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| PLE0206 | PropertyWithParameters | Cannot have defined parameters for properties | |
| PLE1142 | AwaitOutsideAsync | `await` should be used within an async function | |

### Ruff-specific rules
Expand Down
30 changes: 30 additions & 0 deletions resources/test/fixtures/pylint/property_with_parameters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# pylint: disable=missing-docstring, too-few-public-methods
from abc import ABCMeta, abstractmethod


class Cls:
@property
def attribute(self, param, param1): # [property-with-parameters]
return param + param1

@property
def attribute_keyword_only(self, *, param, param1): # [property-with-parameters]
return param + param1

@property
def attribute_positional_only(self, param, param1, /): # [property-with-parameters]
return param + param1


class MyClassBase(metaclass=ABCMeta):
"""MyClassBase."""

@property
@abstractmethod
def example(self):
"""Getter."""

@example.setter
@abstractmethod
def example(self, value):
"""Setter."""
4 changes: 4 additions & 0 deletions src/check_ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,10 @@ where
);
}

if self.settings.enabled.contains(&CheckCode::PLE0206) {
pylint::plugins::property_with_parameters(self, stmt, decorator_list, args)
}

self.check_builtin_shadowing(name, Range::from_located(stmt), true);

// Visit the decorators and arguments, but avoid the body, which will be
Expand Down
8 changes: 8 additions & 0 deletions src/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ pub enum CheckCode {
F841,
F901,
// pylint errors
PLE0206,
PLE1142,
// flake8-builtins
A001,
Expand Down Expand Up @@ -540,6 +541,7 @@ pub enum CheckKind {
UnusedVariable(String),
YieldOutsideFunction(DeferralKeyword),
// pylint errors
PropertyWithParameters,
AwaitOutsideAsync,
// flake8-builtins
BuiltinVariableShadowing(String),
Expand Down Expand Up @@ -825,6 +827,7 @@ impl CheckCode {
CheckCode::F841 => CheckKind::UnusedVariable("...".to_string()),
CheckCode::F901 => CheckKind::RaiseNotImplemented,
// pylint errors
CheckCode::PLE0206 => CheckKind::PropertyWithParameters,
CheckCode::PLE1142 => CheckKind::AwaitOutsideAsync,
// flake8-builtins
CheckCode::A001 => CheckKind::BuiltinVariableShadowing("...".to_string()),
Expand Down Expand Up @@ -1237,6 +1240,7 @@ impl CheckCode {
CheckCode::N817 => CheckCategory::PEP8Naming,
CheckCode::N818 => CheckCategory::PEP8Naming,
CheckCode::PGH001 => CheckCategory::PygrepHooks,
CheckCode::PLE0206 => CheckCategory::Pylint,
CheckCode::PLE1142 => CheckCategory::Pylint,
CheckCode::Q000 => CheckCategory::Flake8Quotes,
CheckCode::Q001 => CheckCategory::Flake8Quotes,
Expand Down Expand Up @@ -1350,6 +1354,7 @@ impl CheckKind {
CheckKind::NoNewLineAtEndOfFile => &CheckCode::W292,
CheckKind::InvalidEscapeSequence(_) => &CheckCode::W605,
// pylint errors
CheckKind::PropertyWithParameters => &CheckCode::PLE0206,
CheckKind::AwaitOutsideAsync => &CheckCode::PLE1142,
// flake8-builtins
CheckKind::BuiltinVariableShadowing(_) => &CheckCode::A001,
Expand Down Expand Up @@ -1723,6 +1728,9 @@ impl CheckKind {
format!("Invalid escape sequence: '\\{char}'")
}
// pylint errors
CheckKind::PropertyWithParameters => {
"Cannot have defined parameters for properties".to_string()
}
CheckKind::AwaitOutsideAsync => {
"`await` should be used within an async function".to_string()
}
Expand Down
14 changes: 13 additions & 1 deletion src/checks_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,10 @@ pub enum CheckCodePrefix {
PGH00,
PGH001,
PLE,
PLE0,
PLE02,
PLE020,
PLE0206,
PLE1,
PLE11,
PLE114,
Expand Down Expand Up @@ -1156,7 +1160,11 @@ impl CheckCodePrefix {
CheckCodePrefix::PGH0 => vec![CheckCode::PGH001],
CheckCodePrefix::PGH00 => vec![CheckCode::PGH001],
CheckCodePrefix::PGH001 => vec![CheckCode::PGH001],
CheckCodePrefix::PLE => vec![CheckCode::PLE1142],
CheckCodePrefix::PLE => vec![CheckCode::PLE0206, CheckCode::PLE1142],
CheckCodePrefix::PLE0 => vec![CheckCode::PLE0206],
CheckCodePrefix::PLE02 => vec![CheckCode::PLE0206],
CheckCodePrefix::PLE020 => vec![CheckCode::PLE0206],
CheckCodePrefix::PLE0206 => vec![CheckCode::PLE0206],
CheckCodePrefix::PLE1 => vec![CheckCode::PLE1142],
CheckCodePrefix::PLE11 => vec![CheckCode::PLE1142],
CheckCodePrefix::PLE114 => vec![CheckCode::PLE1142],
Expand Down Expand Up @@ -1628,6 +1636,10 @@ impl CheckCodePrefix {
CheckCodePrefix::PGH00 => SuffixLength::Two,
CheckCodePrefix::PGH001 => SuffixLength::Three,
CheckCodePrefix::PLE => SuffixLength::Zero,
CheckCodePrefix::PLE0 => SuffixLength::One,
CheckCodePrefix::PLE02 => SuffixLength::Two,
CheckCodePrefix::PLE020 => SuffixLength::Three,
CheckCodePrefix::PLE0206 => SuffixLength::Four,
CheckCodePrefix::PLE1 => SuffixLength::One,
CheckCodePrefix::PLE11 => SuffixLength::Two,
CheckCodePrefix::PLE114 => SuffixLength::Three,
Expand Down
7 changes: 4 additions & 3 deletions src/pylint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ mod tests {
use crate::linter::test_path;
use crate::Settings;

#[test_case(Path::new("await_outside_async.py"))]
fn checks(path: &Path) -> Result<()> {
#[test_case(CheckCode::PLE0206, Path::new("property_with_parameters.py"); "PLE0206")]
#[test_case(CheckCode::PLE1142, Path::new("await_outside_async.py"); "PLE1142")]
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
let snapshot = format!("{}", path.to_string_lossy());
let mut checks = test_path(
Path::new("./resources/test/fixtures/pylint")
.join(path)
.as_path(),
&Settings::for_rules(vec![CheckCode::PLE1142]),
&Settings::for_rules(vec![check_code]),
true,
)?;
checks.sort_by_key(|check| check.location);
Expand Down
30 changes: 29 additions & 1 deletion src/pylint/plugins.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,38 @@
use rustpython_ast::Expr;
use rustpython_ast::{Arguments, Expr, ExprKind, Stmt};

use crate::ast::types::{FunctionScope, Range, ScopeKind};
use crate::check_ast::Checker;
use crate::checks::CheckKind;
use crate::Check;

/// PLE0206
pub fn property_with_parameters(
checker: &mut Checker,
stmt: &Stmt,
decorator_list: &[Expr],
args: &Arguments,
) {
if decorator_list.iter().any(|d| match &d.node {
ExprKind::Name { id, .. } if id == "property" => true,
_ => false,
}) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also check checker.is_builtin(property)?

if checker.is_builtin("property")
&& args
.args
.iter()
.chain(args.posonlyargs.iter())
.chain(args.kwonlyargs.iter())
.count()
> 1
{
checker.add_check(Check::new(
CheckKind::PropertyWithParameters,
Range::from_located(stmt),
));
}
}
}

/// PLE1142
pub fn await_outside_async(checker: &mut Checker, expr: &Expr) {
if !checker
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
source: src/pylint/mod.rs
expression: checks
---
- kind: PropertyWithParameters
location:
row: 7
column: 4
end_location:
row: 10
column: 4
fix: ~
- kind: PropertyWithParameters
location:
row: 11
column: 4
end_location:
row: 14
column: 4
fix: ~
- kind: PropertyWithParameters
location:
row: 15
column: 4
end_location:
row: 19
column: 0
fix: ~