Compare commits

..

11 Commits

Author SHA1 Message Date
Charlie Marsh
cf0d198365 Bump version to 0.0.79 2022-10-16 21:39:01 -04:00
Charlie Marsh
08b14ed77e Remove leading 'or' from fixable match 2022-10-16 21:38:22 -04:00
Charlie Marsh
6ee3075867 Bump version to 0.0.78 2022-10-16 21:28:25 -04:00
Charlie Marsh
cc8a945cbf Tweak messages for flake8-comprehensions rules (#444) 2022-10-16 21:27:13 -04:00
Charlie Marsh
1a1922b3fc Re-add the fix icon to README.md (#443) 2022-10-16 21:21:30 -04:00
Charlie Marsh
48bd766298 Implement autofixes for more docstring rules (#442) 2022-10-16 21:16:57 -04:00
Charlie Marsh
1ece3873cd Implement autofix for newline-related docstring rules (#441) 2022-10-16 19:40:38 -04:00
Charlie Marsh
472d902486 Rename docstring_plugins.rs to plugins.rs 2022-10-16 18:39:08 -04:00
Charlie Marsh
4ac6a18d40 Remove some Vec arguments 2022-10-16 18:17:10 -04:00
Charlie Marsh
8a47ea91ba Use CheckCategory to drive default rules 2022-10-16 18:07:03 -04:00
Charlie Marsh
bd4394aa89 Capitalize pep8-naming messages 2022-10-16 17:58:26 -04:00
36 changed files with 773 additions and 480 deletions

2
Cargo.lock generated
View File

@@ -2045,7 +2045,7 @@ dependencies = [
[[package]]
name = "ruff"
version = "0.0.77"
version = "0.0.79"
dependencies = [
"anyhow",
"assert_cmd",

View File

@@ -1,6 +1,6 @@
[package]
name = "ruff"
version = "0.0.77"
version = "0.0.79"
edition = "2021"
[lib]

294
README.md
View File

@@ -77,7 +77,7 @@ Ruff also works with [pre-commit](https://pre-commit.com):
```yaml
repos:
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.77
rev: v0.0.79
hooks:
- id: lint
```
@@ -222,180 +222,182 @@ add `noqa` directives to all failing lines, with the appropriate error codes.**
By default, Ruff enables all `E`, `W`, and `F` error codes, which correspond to those built-in to
Flake8.
The 🛠 emoji indicates that a rule is automatically fixable by the `--fix` command-line option.
### Pyflakes
| Code | Name | Message |
| ---- | ---- | ------- |
| F401 | UnusedImport | `...` imported but unused |
| F402 | ImportShadowedByLoopVar | Import `...` from line 1 shadowed by loop variable |
| F403 | ImportStarUsed | `from ... import *` used; unable to detect undefined names |
| F404 | LateFutureImport | `from __future__` imports must occur at the beginning of the file |
| F405 | ImportStarUsage | `...` may be undefined, or defined from star imports: `...` |
| F406 | ImportStarNotPermitted | `from ... import *` only allowed at module level |
| F407 | FutureFeatureNotDefined | Future feature `...` is not defined |
| F541 | FStringMissingPlaceholders | f-string without any placeholders |
| F601 | MultiValueRepeatedKeyLiteral | Dictionary key literal repeated |
| F602 | MultiValueRepeatedKeyVariable | Dictionary key `...` repeated |
| F621 | ExpressionsInStarAssignment | Too many expressions in star-unpacking assignment |
| F622 | TwoStarredExpressions | Two starred expressions in assignment |
| F631 | AssertTuple | Assert test is a non-empty tuple, which is always `True` |
| F632 | IsLiteral | Use `==` and `!=` to compare constant literals |
| F633 | InvalidPrintSyntax | Use of `>>` is invalid with `print` function |
| F634 | IfTuple | If test is a tuple, which is always `True` |
| F701 | BreakOutsideLoop | `break` outside loop |
| F702 | ContinueOutsideLoop | `continue` not properly in loop |
| F704 | YieldOutsideFunction | `yield` or `yield from` statement outside of a function/method |
| F706 | ReturnOutsideFunction | `return` statement outside of a function/method |
| F707 | DefaultExceptNotLast | An `except:` block as not the last exception handler |
| F722 | ForwardAnnotationSyntaxError | Syntax error in forward annotation: `...` |
| F821 | UndefinedName | Undefined name `...` |
| F822 | UndefinedExport | Undefined name `...` in `__all__` |
| F823 | UndefinedLocal | Local variable `...` referenced before assignment |
| F831 | DuplicateArgumentName | Duplicate argument name in function definition |
| F841 | UnusedVariable | Local variable `...` is assigned to but never used |
| F901 | RaiseNotImplemented | `raise NotImplemented` should be `raise NotImplementedError` |
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| F401 | UnusedImport | `...` imported but unused | 🛠 |
| F402 | ImportShadowedByLoopVar | Import `...` from line 1 shadowed by loop variable | |
| F403 | ImportStarUsed | `from ... import *` used; unable to detect undefined names | |
| F404 | LateFutureImport | `from __future__` imports must occur at the beginning of the file | |
| F405 | ImportStarUsage | `...` may be undefined, or defined from star imports: `...` | |
| F406 | ImportStarNotPermitted | `from ... import *` only allowed at module level | |
| F407 | FutureFeatureNotDefined | Future feature `...` is not defined | |
| F541 | FStringMissingPlaceholders | f-string without any placeholders | |
| F601 | MultiValueRepeatedKeyLiteral | Dictionary key literal repeated | |
| F602 | MultiValueRepeatedKeyVariable | Dictionary key `...` repeated | |
| F621 | ExpressionsInStarAssignment | Too many expressions in star-unpacking assignment | |
| F622 | TwoStarredExpressions | Two starred expressions in assignment | |
| F631 | AssertTuple | Assert test is a non-empty tuple, which is always `True` | |
| F632 | IsLiteral | Use `==` and `!=` to compare constant literals | |
| F633 | InvalidPrintSyntax | Use of `>>` is invalid with `print` function | |
| F634 | IfTuple | If test is a tuple, which is always `True` | |
| F701 | BreakOutsideLoop | `break` outside loop | |
| F702 | ContinueOutsideLoop | `continue` not properly in loop | |
| F704 | YieldOutsideFunction | `yield` or `yield from` statement outside of a function/method | |
| F706 | ReturnOutsideFunction | `return` statement outside of a function/method | |
| F707 | DefaultExceptNotLast | An `except:` block as not the last exception handler | |
| F722 | ForwardAnnotationSyntaxError | Syntax error in forward annotation: `...` | |
| F821 | UndefinedName | Undefined name `...` | |
| F822 | UndefinedExport | Undefined name `...` in `__all__` | |
| F823 | UndefinedLocal | Local variable `...` referenced before assignment | |
| F831 | DuplicateArgumentName | Duplicate argument name in function definition | |
| F841 | UnusedVariable | Local variable `...` is assigned to but never used | |
| F901 | RaiseNotImplemented | `raise NotImplemented` should be `raise NotImplementedError` | |
### pycodestyle
| Code | Name | Message |
| ---- | ---- | ------- |
| E402 | ModuleImportNotAtTopOfFile | Module level import not at top of file |
| E501 | LineTooLong | Line too long (89 > 88 characters) |
| E711 | NoneComparison | Comparison to `None` should be `cond is None` |
| E712 | TrueFalseComparison | Comparison to `True` should be `cond is True` |
| E713 | NotInTest | Test for membership should be `not in` |
| E714 | NotIsTest | Test for object identity should be `is not` |
| E721 | TypeComparison | Do not compare types, use `isinstance()` |
| E722 | DoNotUseBareExcept | Do not use bare `except` |
| E731 | DoNotAssignLambda | Do not assign a lambda expression, use a def |
| E741 | AmbiguousVariableName | Ambiguous variable name: `...` |
| E742 | AmbiguousClassName | Ambiguous class name: `...` |
| E743 | AmbiguousFunctionName | Ambiguous function name: `...` |
| E902 | IOError | IOError: `...` |
| E999 | SyntaxError | SyntaxError: `...` |
| W292 | NoNewLineAtEndOfFile | No newline at end of file |
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| E402 | ModuleImportNotAtTopOfFile | Module level import not at top of file | |
| E501 | LineTooLong | Line too long (89 > 88 characters) | |
| E711 | NoneComparison | Comparison to `None` should be `cond is None` | |
| E712 | TrueFalseComparison | Comparison to `True` should be `cond is True` | |
| E713 | NotInTest | Test for membership should be `not in` | |
| E714 | NotIsTest | Test for object identity should be `is not` | |
| E721 | TypeComparison | Do not compare types, use `isinstance()` | |
| E722 | DoNotUseBareExcept | Do not use bare `except` | |
| E731 | DoNotAssignLambda | Do not assign a lambda expression, use a def | |
| E741 | AmbiguousVariableName | Ambiguous variable name: `...` | |
| E742 | AmbiguousClassName | Ambiguous class name: `...` | |
| E743 | AmbiguousFunctionName | Ambiguous function name: `...` | |
| E902 | IOError | IOError: `...` | |
| E999 | SyntaxError | SyntaxError: `...` | |
| W292 | NoNewLineAtEndOfFile | No newline at end of file | |
### pydocstyle
| Code | Name | Message |
| ---- | ---- | ------- |
| D100 | PublicModule | Missing docstring in public module |
| D101 | PublicClass | Missing docstring in public class |
| D102 | PublicMethod | Missing docstring in public method |
| D103 | PublicFunction | Missing docstring in public function |
| D104 | PublicPackage | Missing docstring in public package |
| D105 | MagicMethod | Missing docstring in magic method |
| D106 | PublicNestedClass | Missing docstring in public nested class |
| D107 | PublicInit | Missing docstring in `__init__` |
| D200 | FitsOnOneLine | One-line docstring should fit on one line |
| D201 | NoBlankLineBeforeFunction | No blank lines allowed before function docstring (found 1) |
| D202 | NoBlankLineAfterFunction | No blank lines allowed after function docstring (found 1) |
| D203 | OneBlankLineBeforeClass | 1 blank line required before class docstring |
| D204 | OneBlankLineAfterClass | 1 blank line required after class docstring |
| D205 | NoBlankLineAfterSummary | 1 blank line required between summary line and description |
| D206 | IndentWithSpaces | Docstring should be indented with spaces, not tabs |
| D207 | NoUnderIndentation | Docstring is under-indented |
| D208 | NoOverIndentation | Docstring is over-indented |
| D209 | NewLineAfterLastParagraph | Multi-line docstring closing quotes should be on a separate line |
| D210 | NoSurroundingWhitespace | No whitespaces allowed surrounding docstring text |
| D211 | NoBlankLineBeforeClass | No blank lines allowed before class docstring |
| D212 | MultiLineSummaryFirstLine | Multi-line docstring summary should start at the first line |
| D213 | MultiLineSummarySecondLine | Multi-line docstring summary should start at the second line |
| D214 | SectionNotOverIndented | Section is over-indented ("Returns") |
| D215 | SectionUnderlineNotOverIndented | Section underline is over-indented ("Returns") |
| D300 | UsesTripleQuotes | Use """triple double quotes""" |
| D400 | EndsInPeriod | First line should end with a period |
| D402 | NoSignature | First line should not be the function's 'signature' |
| D403 | FirstLineCapitalized | First word of the first line should be properly capitalized |
| D404 | NoThisPrefix | First word of the docstring should not be `This` |
| D405 | CapitalizeSectionName | Section name should be properly capitalized ("returns") |
| D406 | NewLineAfterSectionName | Section name should end with a newline ("Returns") |
| D407 | DashedUnderlineAfterSection | Missing dashed underline after section ("Returns") |
| D408 | SectionUnderlineAfterName | Section underline should be in the line following the section's name ("Returns") |
| D409 | SectionUnderlineMatchesSectionLength | Section underline should match the length of its name ("Returns") |
| D410 | BlankLineAfterSection | Missing blank line after section ("Returns") |
| D411 | BlankLineBeforeSection | Missing blank line before section ("Returns") |
| D412 | NoBlankLinesBetweenHeaderAndContent | No blank lines allowed between a section header and its content ("Returns") |
| D413 | BlankLineAfterLastSection | Missing blank line after last section ("Returns") |
| D414 | NonEmptySection | Section has no content ("Returns") |
| D415 | EndsInPunctuation | First line should end with a period, question mark, or exclamation point |
| D416 | SectionNameEndsInColon | Section name should end with a colon ("Returns") |
| D417 | DocumentAllArguments | Missing argument descriptions in the docstring: `x`, `y` |
| D418 | SkipDocstring | Function decorated with @overload shouldn't contain a docstring |
| D419 | NonEmpty | Docstring is empty |
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| D100 | PublicModule | Missing docstring in public module | |
| D101 | PublicClass | Missing docstring in public class | |
| D102 | PublicMethod | Missing docstring in public method | |
| D103 | PublicFunction | Missing docstring in public function | |
| D104 | PublicPackage | Missing docstring in public package | |
| D105 | MagicMethod | Missing docstring in magic method | |
| D106 | PublicNestedClass | Missing docstring in public nested class | |
| D107 | PublicInit | Missing docstring in `__init__` | |
| D200 | FitsOnOneLine | One-line docstring should fit on one line | |
| D201 | NoBlankLineBeforeFunction | No blank lines allowed before function docstring (found 1) | 🛠 |
| D202 | NoBlankLineAfterFunction | No blank lines allowed after function docstring (found 1) | 🛠 |
| D203 | OneBlankLineBeforeClass | 1 blank line required before class docstring | 🛠 |
| D204 | OneBlankLineAfterClass | 1 blank line required after class docstring | 🛠 |
| D205 | NoBlankLineAfterSummary | 1 blank line required between summary line and description | 🛠 |
| D206 | IndentWithSpaces | Docstring should be indented with spaces, not tabs | |
| D207 | NoUnderIndentation | Docstring is under-indented | |
| D208 | NoOverIndentation | Docstring is over-indented | |
| D209 | NewLineAfterLastParagraph | Multi-line docstring closing quotes should be on a separate line | 🛠 |
| D210 | NoSurroundingWhitespace | No whitespaces allowed surrounding docstring text | 🛠 |
| D211 | NoBlankLineBeforeClass | No blank lines allowed before class docstring | 🛠 |
| D212 | MultiLineSummaryFirstLine | Multi-line docstring summary should start at the first line | |
| D213 | MultiLineSummarySecondLine | Multi-line docstring summary should start at the second line | |
| D214 | SectionNotOverIndented | Section is over-indented ("Returns") | |
| D215 | SectionUnderlineNotOverIndented | Section underline is over-indented ("Returns") | |
| D300 | UsesTripleQuotes | Use """triple double quotes""" | |
| D400 | EndsInPeriod | First line should end with a period | |
| D402 | NoSignature | First line should not be the function's 'signature' | |
| D403 | FirstLineCapitalized | First word of the first line should be properly capitalized | |
| D404 | NoThisPrefix | First word of the docstring should not be `This` | |
| D405 | CapitalizeSectionName | Section name should be properly capitalized ("returns") | |
| D406 | NewLineAfterSectionName | Section name should end with a newline ("Returns") | |
| D407 | DashedUnderlineAfterSection | Missing dashed underline after section ("Returns") | |
| D408 | SectionUnderlineAfterName | Section underline should be in the line following the section's name ("Returns") | |
| D409 | SectionUnderlineMatchesSectionLength | Section underline should match the length of its name ("Returns") | |
| D410 | BlankLineAfterSection | Missing blank line after section ("Returns") | 🛠 |
| D411 | BlankLineBeforeSection | Missing blank line before section ("Returns") | |
| D412 | NoBlankLinesBetweenHeaderAndContent | No blank lines allowed between a section header and its content ("Returns") | |
| D413 | BlankLineAfterLastSection | Missing blank line after last section ("Returns") | 🛠 |
| D414 | NonEmptySection | Section has no content ("Returns") | |
| D415 | EndsInPunctuation | First line should end with a period, question mark, or exclamation point | |
| D416 | SectionNameEndsInColon | Section name should end with a colon ("Returns") | |
| D417 | DocumentAllArguments | Missing argument descriptions in the docstring: `x`, `y` | |
| D418 | SkipDocstring | Function decorated with @overload shouldn't contain a docstring | |
| D419 | NonEmpty | Docstring is empty | |
### pyupgrade
| Code | Name | Message |
| ---- | ---- | ------- |
| U001 | UselessMetaclassType | `__metaclass__ = type` is implied |
| U002 | UnnecessaryAbspath | `abspath(__file__)` is unnecessary in Python 3.9 and later |
| U003 | TypeOfPrimitive | Use `str` instead of `type(...)` |
| U004 | UselessObjectInheritance | Class `...` inherits from object |
| U005 | DeprecatedUnittestAlias | `assertEquals` is deprecated, use `assertEqual` instead |
| U006 | UsePEP585Annotation | Use `list` instead of `List` for type annotations |
| U007 | UsePEP604Annotation | Use `X \| Y` for type annotations |
| U008 | SuperCallWithParameters | Use `super()` instead of `super(__class__, self)` |
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| U001 | UselessMetaclassType | `__metaclass__ = type` is implied | 🛠 |
| U002 | UnnecessaryAbspath | `abspath(__file__)` is unnecessary in Python 3.9 and later | 🛠 |
| U003 | TypeOfPrimitive | Use `str` instead of `type(...)` | 🛠 |
| U004 | UselessObjectInheritance | Class `...` inherits from object | 🛠 |
| U005 | DeprecatedUnittestAlias | `assertEquals` is deprecated, use `assertEqual` instead | 🛠 |
| U006 | UsePEP585Annotation | Use `list` instead of `List` for type annotations | 🛠 |
| U007 | UsePEP604Annotation | Use `X \| Y` for type annotations | 🛠 |
| U008 | SuperCallWithParameters | Use `super()` instead of `super(__class__, self)` | 🛠 |
### pep8-naming
| Code | Name | Message |
| ---- | ---- | ------- |
| N801 | InvalidClassName | class name `...` should use CapWords convention |
| N802 | InvalidFunctionName | function name `...` should be lowercase |
| N803 | InvalidArgumentName | argument name `...` should be lowercase |
| N804 | InvalidFirstArgumentNameForClassMethod | first argument of a classmethod should be named `cls` |
| N805 | InvalidFirstArgumentNameForMethod | first argument of a method should be named `self` |
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| N801 | InvalidClassName | Class name `...` should use CapWords convention | |
| N802 | InvalidFunctionName | Function name `...` should be lowercase | |
| N803 | InvalidArgumentName | Argument name `...` should be lowercase | |
| N804 | InvalidFirstArgumentNameForClassMethod | First argument of a class method should be named `cls` | |
| N805 | InvalidFirstArgumentNameForMethod | First argument of a method should be named `self` | |
### flake8-comprehensions
| Code | Name | Message |
| ---- | ---- | ------- |
| C400 | UnnecessaryGeneratorList | Unnecessary generator - rewrite as a list comprehension |
| C401 | UnnecessaryGeneratorSet | Unnecessary generator - rewrite as a set comprehension |
| C402 | UnnecessaryGeneratorDict | Unnecessary generator - rewrite as a dict comprehension |
| C403 | UnnecessaryListComprehensionSet | Unnecessary list comprehension - rewrite as a set comprehension |
| C404 | UnnecessaryListComprehensionDict | Unnecessary list comprehension - rewrite as a dict comprehension |
| C405 | UnnecessaryLiteralSet | Unnecessary <list/tuple> literal - rewrite as a set literal |
| C406 | UnnecessaryLiteralDict | Unnecessary <list/tuple> literal - rewrite as a dict literal |
| C408 | UnnecessaryCollectionCall | Unnecessary <dict/list/tuple> call - rewrite as a literal |
| C409 | UnnecessaryLiteralWithinTupleCall | Unnecessary <list/tuple> literal passed to tuple() - remove the outer call to tuple() |
| C410 | UnnecessaryLiteralWithinListCall | Unnecessary <list/tuple> literal passed to list() - rewrite as a list literal |
| C411 | UnnecessaryListCall | Unnecessary list call - remove the outer call to list() |
| C413 | UnnecessaryCallAroundSorted | Unnecessary <list/reversed> call around sorted() |
| C414 | UnnecessaryDoubleCastOrProcess | Unnecessary <list/reversed/set/sorted/tuple> call within <list/set/sorted/tuple>(). |
| C415 | UnnecessarySubscriptReversal | Unnecessary subscript reversal of iterable within <reversed/set/sorted>() |
| C416 | UnnecessaryComprehension | Unnecessary <list/set> comprehension - rewrite using <list/set>() |
| C417 | UnnecessaryMap | Unnecessary map usage - rewrite using a <list/set/dict> comprehension |
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| C400 | UnnecessaryGeneratorList | Unnecessary generator (rewrite as a `list` comprehension) | |
| C401 | UnnecessaryGeneratorSet | Unnecessary generator (rewrite as a `set` comprehension) | |
| C402 | UnnecessaryGeneratorDict | Unnecessary generator (rewrite as a `dict` comprehension) | |
| C403 | UnnecessaryListComprehensionSet | Unnecessary `list` comprehension (rewrite as a `set` comprehension) | |
| C404 | UnnecessaryListComprehensionDict | Unnecessary `list` comprehension (rewrite as a `dict` comprehension) | |
| C405 | UnnecessaryLiteralSet | Unnecessary `(list\|tuple)` literal (rewrite as a `set` literal) | |
| C406 | UnnecessaryLiteralDict | Unnecessary `(list\|tuple)` literal (rewrite as a `dict` literal) | |
| C408 | UnnecessaryCollectionCall | Unnecessary `(dict\|list\|tuple)` call (rewrite as a literal) | |
| C409 | UnnecessaryLiteralWithinTupleCall | Unnecessary `(list\|tuple)` literal passed to `tuple()` (remove the outer call to `tuple()`) | |
| C410 | UnnecessaryLiteralWithinListCall | Unnecessary `(list\|tuple)` literal passed to `list()` (rewrite as a `list` literal) | |
| C411 | UnnecessaryListCall | Unnecessary `list` call (remove the outer call to `list()`) | |
| C413 | UnnecessaryCallAroundSorted | Unnecessary `(list\|reversed)` call around `sorted()` | |
| C414 | UnnecessaryDoubleCastOrProcess | Unnecessary `(list\|reversed\|set\|sorted\|tuple)` call within `(list\|set\|sorted\|tuple)()` | |
| C415 | UnnecessarySubscriptReversal | Unnecessary subscript reversal of iterable within `(reversed\|set\|sorted)()` | |
| C416 | UnnecessaryComprehension | Unnecessary `(list\|set)` comprehension (rewrite using `(list\|set)()`) | |
| C417 | UnnecessaryMap | Unnecessary `map` usage (rewrite using a `(list\|set\|dict)` comprehension) | |
### flake8-bugbear
| Code | Name | Message |
| ---- | ---- | ------- |
| B011 | DoNotAssertFalse | Do not `assert False` (`python -O` removes these calls), raise `AssertionError()` |
| B014 | DuplicateHandlerException | Exception handler with duplicate exception: `ValueError` |
| B025 | DuplicateTryBlockException | try-except block with duplicate exception `Exception` |
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| B011 | DoNotAssertFalse | Do not `assert False` (`python -O` removes these calls), raise `AssertionError()` | 🛠 |
| B014 | DuplicateHandlerException | Exception handler with duplicate exception: `ValueError` | 🛠 |
| B025 | DuplicateTryBlockException | try-except block with duplicate exception `Exception` | |
### flake8-builtins
| Code | Name | Message |
| ---- | ---- | ------- |
| A001 | BuiltinVariableShadowing | Variable `...` is shadowing a python builtin |
| A002 | BuiltinArgumentShadowing | Argument `...` is shadowing a python builtin |
| A003 | BuiltinAttributeShadowing | Class attribute `...` is shadowing a python builtin |
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| A001 | BuiltinVariableShadowing | Variable `...` is shadowing a python builtin | |
| A002 | BuiltinArgumentShadowing | Argument `...` is shadowing a python builtin | |
| A003 | BuiltinAttributeShadowing | Class attribute `...` is shadowing a python builtin | |
### flake8-print
| Code | Name | Message |
| ---- | ---- | ------- |
| T201 | PrintFound | `print` found |
| T203 | PPrintFound | `pprint` found |
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| T201 | PrintFound | `print` found | 🛠 |
| T203 | PPrintFound | `pprint` found | 🛠 |
### Meta rules
| Code | Name | Message |
| ---- | ---- | ------- |
| M001 | UnusedNOQA | Unused `noqa` directive |
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| M001 | UnusedNOQA | Unused `noqa` directive | 🛠 |
## Editor Integrations

View File

@@ -9,16 +9,18 @@ fn main() {
println!("### {}", check_category.title());
println!();
println!("| Code | Name | Message |");
println!("| ---- | ---- | ------- |");
println!("| Code | Name | Message | Fix |");
println!("| ---- | ---- | ------- | --- |");
for check_code in CheckCode::iter() {
if check_code.category() == check_category {
let check_kind = check_code.kind();
let fix_token = if check_kind.fixable() { "🛠" } else { "" };
println!(
"| {} | {} | {} |",
"| {} | {} | {} | {} |",
check_kind.code().as_ref(),
check_kind.as_ref(),
check_kind.body().replace("|", r"\|")
check_kind.body().replace("|", r"\|"),
fix_token
);
}
}

View File

@@ -118,7 +118,7 @@ pub fn do_not_assign_lambda(value: &Expr, location: Range) -> Option<Check> {
}
/// Check UselessMetaclassType compliance.
pub fn useless_metaclass_type(targets: &Vec<Expr>, value: &Expr, location: Range) -> Option<Check> {
pub fn useless_metaclass_type(targets: &[Expr], value: &Expr, location: Range) -> Option<Check> {
if targets.len() == 1 {
if let ExprKind::Name { id, .. } = targets.first().map(|expr| &expr.node).unwrap() {
if id == "__metaclass__" {
@@ -134,7 +134,7 @@ pub fn useless_metaclass_type(targets: &Vec<Expr>, value: &Expr, location: Range
}
/// Check UnnecessaryAbspath compliance.
pub fn unnecessary_abspath(func: &Expr, args: &Vec<Expr>, location: Range) -> Option<Check> {
pub fn unnecessary_abspath(func: &Expr, args: &[Expr], location: Range) -> Option<Check> {
// Validate the arguments.
if args.len() == 1 {
if let ExprKind::Name { id, .. } = &args[0].node {
@@ -190,7 +190,7 @@ impl Primitive {
}
/// Check TypeOfPrimitive compliance.
pub fn type_of_primitive(func: &Expr, args: &Vec<Expr>, location: Range) -> Option<Check> {
pub fn type_of_primitive(func: &Expr, args: &[Expr], location: Range) -> Option<Check> {
// Validate the arguments.
if args.len() == 1 {
match &func.node {
@@ -279,7 +279,7 @@ pub fn useless_object_inheritance(name: &str, bases: &[Expr], scope: &Scope) ->
}
/// Check DefaultExceptNotLast compliance.
pub fn default_except_not_last(handlers: &Vec<Excepthandler>) -> Option<Check> {
pub fn default_except_not_last(handlers: &[Excepthandler]) -> Option<Check> {
for (idx, handler) in handlers.iter().enumerate() {
let ExcepthandlerKind::ExceptHandler { type_, .. } = &handler.node;
if type_.is_none() && idx < handlers.len() - 1 {
@@ -370,7 +370,7 @@ fn convert_to_value(expr: &Expr) -> Option<DictionaryKey> {
/// Check MultiValueRepeatedKeyLiteral and MultiValueRepeatedKeyVariable compliance.
pub fn repeated_keys(
keys: &Vec<Expr>,
keys: &[Expr],
check_repeated_literals: bool,
check_repeated_variables: bool,
locator: &dyn CheckLocator,
@@ -411,8 +411,8 @@ pub fn repeated_keys(
/// Check TrueFalseComparison and NoneComparison compliance.
pub fn literal_comparisons(
left: &Expr,
ops: &Vec<Cmpop>,
comparators: &Vec<Expr>,
ops: &[Cmpop],
comparators: &[Expr],
check_none_comparisons: bool,
check_true_false_comparisons: bool,
locator: &dyn CheckLocator,
@@ -540,12 +540,7 @@ fn is_constant_non_singleton(expr: &Expr) -> bool {
}
/// Check IsLiteral compliance.
pub fn is_literal(
left: &Expr,
ops: &Vec<Cmpop>,
comparators: &Vec<Expr>,
location: Range,
) -> Vec<Check> {
pub fn is_literal(left: &Expr, ops: &[Cmpop], comparators: &[Expr], location: Range) -> Vec<Check> {
let mut checks: Vec<Check> = vec![];
let mut left = left;
@@ -562,7 +557,7 @@ pub fn is_literal(
}
/// Check TypeComparison compliance.
pub fn type_comparison(ops: &Vec<Cmpop>, comparators: &Vec<Expr>, location: Range) -> Vec<Check> {
pub fn type_comparison(ops: &[Cmpop], comparators: &[Expr], location: Range) -> Vec<Check> {
let mut checks: Vec<Check> = vec![];
for (op, right) in izip!(ops, comparators) {
@@ -734,7 +729,7 @@ pub fn builtin_shadowing(name: &str, location: Range, node_type: ShadowingType)
// flake8-comprehensions
/// Check `list(generator)` compliance.
pub fn unnecessary_generator_list(expr: &Expr, func: &Expr, args: &Vec<Expr>) -> Option<Check> {
pub fn unnecessary_generator_list(expr: &Expr, func: &Expr, args: &[Expr]) -> Option<Check> {
if args.len() == 1 {
if let ExprKind::Name { id, .. } = &func.node {
if id == "list" {
@@ -751,7 +746,7 @@ pub fn unnecessary_generator_list(expr: &Expr, func: &Expr, args: &Vec<Expr>) ->
}
/// Check `set(generator)` compliance.
pub fn unnecessary_generator_set(expr: &Expr, func: &Expr, args: &Vec<Expr>) -> Option<Check> {
pub fn unnecessary_generator_set(expr: &Expr, func: &Expr, args: &[Expr]) -> Option<Check> {
if args.len() == 1 {
if let ExprKind::Name { id, .. } = &func.node {
if id == "set" {
@@ -768,7 +763,7 @@ pub fn unnecessary_generator_set(expr: &Expr, func: &Expr, args: &Vec<Expr>) ->
}
/// Check `dict((x, y) for x, y in iterable)` compliance.
pub fn unnecessary_generator_dict(expr: &Expr, func: &Expr, args: &Vec<Expr>) -> Option<Check> {
pub fn unnecessary_generator_dict(expr: &Expr, func: &Expr, args: &[Expr]) -> Option<Check> {
if args.len() == 1 {
if let ExprKind::Name { id, .. } = &func.node {
if id == "dict" {
@@ -793,7 +788,7 @@ pub fn unnecessary_generator_dict(expr: &Expr, func: &Expr, args: &Vec<Expr>) ->
pub fn unnecessary_list_comprehension_set(
expr: &Expr,
func: &Expr,
args: &Vec<Expr>,
args: &[Expr],
) -> Option<Check> {
if args.len() == 1 {
if let ExprKind::Name { id, .. } = &func.node {
@@ -814,7 +809,7 @@ pub fn unnecessary_list_comprehension_set(
pub fn unnecessary_list_comprehension_dict(
expr: &Expr,
func: &Expr,
args: &Vec<Expr>,
args: &[Expr],
) -> Option<Check> {
if args.len() == 1 {
if let ExprKind::Name { id, .. } = &func.node {
@@ -837,7 +832,7 @@ pub fn unnecessary_list_comprehension_dict(
}
/// Check `set([1, 2])` compliance.
pub fn unnecessary_literal_set(expr: &Expr, func: &Expr, args: &Vec<Expr>) -> Option<Check> {
pub fn unnecessary_literal_set(expr: &Expr, func: &Expr, args: &[Expr]) -> Option<Check> {
if args.len() == 1 {
if let ExprKind::Name { id, .. } = &func.node {
if id == "set" {
@@ -863,7 +858,7 @@ pub fn unnecessary_literal_set(expr: &Expr, func: &Expr, args: &Vec<Expr>) -> Op
}
/// Check `dict([(1, 2)])` compliance.
pub fn unnecessary_literal_dict(expr: &Expr, func: &Expr, args: &Vec<Expr>) -> Option<Check> {
pub fn unnecessary_literal_dict(expr: &Expr, func: &Expr, args: &[Expr]) -> Option<Check> {
if args.len() == 1 {
if let ExprKind::Name { id, .. } = &func.node {
if id == "dict" {
@@ -919,8 +914,8 @@ pub fn unnecessary_literal_dict(expr: &Expr, func: &Expr, args: &Vec<Expr>) -> O
pub fn unnecessary_collection_call(
expr: &Expr,
func: &Expr,
args: &Vec<Expr>,
keywords: &Vec<Located<KeywordData>>,
args: &[Expr],
keywords: &[Located<KeywordData>],
) -> Option<Check> {
if args.is_empty() {
if let ExprKind::Name { id, .. } = &func.node {
@@ -1142,8 +1137,8 @@ pub fn unnecessary_subscript_reversal(expr: &Expr, func: &Expr, args: &[Expr]) -
pub fn unnecessary_comprehension(
expr: &Expr,
elt: &Located<ExprKind>,
generators: &Vec<Comprehension>,
elt: &Expr,
generators: &[Comprehension],
) -> Option<Check> {
if generators.len() == 1 {
let generator = &generators[0];
@@ -1240,7 +1235,7 @@ pub fn super_args(
parents: &[&Stmt],
expr: &Expr,
func: &Expr,
args: &Vec<Expr>,
args: &[Expr],
) -> Option<Check> {
if !helpers::is_super_call_with_arguments(func, args) {
return None;
@@ -1255,7 +1250,7 @@ pub fn super_args(
// For a `super` invocation to be unnecessary, the first argument needs to match the enclosing
// class, and the second argument needs to match the first argument to the enclosing function.
if let [first_arg, second_arg] = args.as_slice() {
if let [first_arg, second_arg] = args {
// Find the enclosing function definition (if any).
if let Some(StmtKind::FunctionDef {
args: parent_args, ..

View File

@@ -123,7 +123,7 @@ pub fn extract_handler_names(handlers: &[Excepthandler]) -> Vec<String> {
}
/// Returns `true` if a call is an argumented `super` invocation.
pub fn is_super_call_with_arguments(func: &Expr, args: &Vec<Expr>) -> bool {
pub fn is_super_call_with_arguments(func: &Expr, args: &[Expr]) -> bool {
// Check: is this a `super` call?
if let ExprKind::Name { id, .. } = &func.node {
id == "super" && !args.is_empty()

View File

@@ -20,8 +20,7 @@ use crate::ast::visitor::{walk_excepthandler, Visitor};
use crate::ast::{checkers, helpers, operations, visitor};
use crate::autofix::{fixer, fixes};
use crate::checks::{Check, CheckCode, CheckKind};
use crate::docstrings::docstring_plugins;
use crate::docstrings::types::{Definition, DefinitionKind, Documentable};
use crate::docstrings::definition::{Definition, DefinitionKind, Documentable};
use crate::python::builtins::{BUILTINS, MAGIC_GLOBALS};
use crate::python::future::ALL_FEATURE_NAMES;
use crate::settings::{PythonVersion, Settings};
@@ -290,11 +289,7 @@ where
);
}
StmtKind::Return { .. } => {
if self
.settings
.enabled
.contains(CheckKind::ReturnOutsideFunction.code())
{
if self.settings.enabled.contains(&CheckCode::F706) {
if let Some(scope_index) = self.scope_stack.last().cloned() {
match self.scopes[scope_index].kind {
ScopeKind::Class | ScopeKind::Module => {
@@ -352,17 +347,13 @@ where
self.push_scope(Scope::new(ScopeKind::Class))
}
StmtKind::Import { names } => {
if self
.settings
.enabled
.contains(CheckKind::ModuleImportNotAtTopOfFile.code())
&& self.seen_import_boundary
&& stmt.location.column() == 1
{
self.checks.push(Check::new(
CheckKind::ModuleImportNotAtTopOfFile,
self.locate_check(Range::from_located(stmt)),
));
if self.seen_import_boundary && stmt.location.column() == 1 {
if self.settings.enabled.contains(&CheckCode::E402) {
self.checks.push(Check::new(
CheckKind::ModuleImportNotAtTopOfFile,
self.locate_check(Range::from_located(stmt)),
));
}
}
for alias in names {
@@ -413,17 +404,13 @@ where
module,
level,
} => {
if self
.settings
.enabled
.contains(CheckKind::ModuleImportNotAtTopOfFile.code())
&& self.seen_import_boundary
&& stmt.location.column() == 1
{
self.checks.push(Check::new(
CheckKind::ModuleImportNotAtTopOfFile,
self.locate_check(Range::from_located(stmt)),
));
if self.seen_import_boundary && stmt.location.column() == 1 {
if self.settings.enabled.contains(&CheckCode::E402) {
self.checks.push(Check::new(
CheckKind::ModuleImportNotAtTopOfFile,
self.locate_check(Range::from_located(stmt)),
));
}
}
for alias in names {
@@ -941,32 +928,27 @@ where
}
ExprKind::Yield { .. } | ExprKind::YieldFrom { .. } | ExprKind::Await { .. } => {
let scope = self.current_scope();
if self
.settings
.enabled
.contains(CheckKind::YieldOutsideFunction.code())
&& matches!(scope.kind, ScopeKind::Class | ScopeKind::Module)
{
self.checks.push(Check::new(
CheckKind::YieldOutsideFunction,
self.locate_check(Range::from_located(expr)),
));
if self.settings.enabled.contains(&CheckCode::F704) {
if matches!(scope.kind, ScopeKind::Class | ScopeKind::Module) {
self.checks.push(Check::new(
CheckKind::YieldOutsideFunction,
self.locate_check(Range::from_located(expr)),
));
}
}
}
ExprKind::JoinedStr { values } => {
if self.in_f_string.is_none()
&& self
.settings
.enabled
.contains(CheckKind::FStringMissingPlaceholders.code())
&& !values
.iter()
.any(|value| matches!(value.node, ExprKind::FormattedValue { .. }))
{
self.checks.push(Check::new(
CheckKind::FStringMissingPlaceholders,
self.locate_check(Range::from_located(expr)),
));
if self.settings.enabled.contains(&CheckCode::F541) {
if self.in_f_string.is_none()
&& !values
.iter()
.any(|value| matches!(value.node, ExprKind::FormattedValue { .. }))
{
self.checks.push(Check::new(
CheckKind::FStringMissingPlaceholders,
self.locate_check(Range::from_located(expr)),
));
}
}
self.in_f_string = Some(Range::from_located(expr));
}
@@ -1961,66 +1943,66 @@ impl<'a> Checker<'a> {
fn check_docstrings(&mut self) {
while let Some((docstring, visibility)) = self.docstrings.pop() {
if !docstring_plugins::not_empty(self, &docstring) {
if !docstrings::plugins::not_empty(self, &docstring) {
continue;
}
if !docstring_plugins::not_missing(self, &docstring, &visibility) {
if !docstrings::plugins::not_missing(self, &docstring, &visibility) {
continue;
}
if self.settings.enabled.contains(&CheckCode::D200) {
docstring_plugins::one_liner(self, &docstring);
docstrings::plugins::one_liner(self, &docstring);
}
if self.settings.enabled.contains(&CheckCode::D201)
|| self.settings.enabled.contains(&CheckCode::D202)
{
docstring_plugins::blank_before_after_function(self, &docstring);
docstrings::plugins::blank_before_after_function(self, &docstring);
}
if self.settings.enabled.contains(&CheckCode::D203)
|| self.settings.enabled.contains(&CheckCode::D204)
|| self.settings.enabled.contains(&CheckCode::D211)
{
docstring_plugins::blank_before_after_class(self, &docstring);
docstrings::plugins::blank_before_after_class(self, &docstring);
}
if self.settings.enabled.contains(&CheckCode::D205) {
docstring_plugins::blank_after_summary(self, &docstring);
docstrings::plugins::blank_after_summary(self, &docstring);
}
if self.settings.enabled.contains(&CheckCode::D206)
|| self.settings.enabled.contains(&CheckCode::D207)
|| self.settings.enabled.contains(&CheckCode::D208)
{
docstring_plugins::indent(self, &docstring);
docstrings::plugins::indent(self, &docstring);
}
if self.settings.enabled.contains(&CheckCode::D209) {
docstring_plugins::newline_after_last_paragraph(self, &docstring);
docstrings::plugins::newline_after_last_paragraph(self, &docstring);
}
if self.settings.enabled.contains(&CheckCode::D210) {
docstring_plugins::no_surrounding_whitespace(self, &docstring);
docstrings::plugins::no_surrounding_whitespace(self, &docstring);
}
if self.settings.enabled.contains(&CheckCode::D212)
|| self.settings.enabled.contains(&CheckCode::D213)
{
docstring_plugins::multi_line_summary_start(self, &docstring);
docstrings::plugins::multi_line_summary_start(self, &docstring);
}
if self.settings.enabled.contains(&CheckCode::D300) {
docstring_plugins::triple_quotes(self, &docstring);
docstrings::plugins::triple_quotes(self, &docstring);
}
if self.settings.enabled.contains(&CheckCode::D400) {
docstring_plugins::ends_with_period(self, &docstring);
docstrings::plugins::ends_with_period(self, &docstring);
}
if self.settings.enabled.contains(&CheckCode::D402) {
docstring_plugins::no_signature(self, &docstring);
docstrings::plugins::no_signature(self, &docstring);
}
if self.settings.enabled.contains(&CheckCode::D403) {
docstring_plugins::capitalized(self, &docstring);
docstrings::plugins::capitalized(self, &docstring);
}
if self.settings.enabled.contains(&CheckCode::D404) {
docstring_plugins::starts_with_this(self, &docstring);
docstrings::plugins::starts_with_this(self, &docstring);
}
if self.settings.enabled.contains(&CheckCode::D415) {
docstring_plugins::ends_with_punctuation(self, &docstring);
docstrings::plugins::ends_with_punctuation(self, &docstring);
}
if self.settings.enabled.contains(&CheckCode::D418) {
docstring_plugins::if_needed(self, &docstring);
docstrings::plugins::if_needed(self, &docstring);
}
if self.settings.enabled.contains(&CheckCode::D212)
|| self.settings.enabled.contains(&CheckCode::D214)
@@ -2038,7 +2020,7 @@ impl<'a> Checker<'a> {
|| self.settings.enabled.contains(&CheckCode::D416)
|| self.settings.enabled.contains(&CheckCode::D417)
{
docstring_plugins::sections(self, &docstring);
docstrings::plugins::sections(self, &docstring);
}
}
}

View File

@@ -8,55 +8,6 @@ use strum_macros::{AsRefStr, EnumIter, EnumString};
use crate::ast::checkers::Primitive;
use crate::ast::types::Range;
pub const DEFAULT_CHECK_CODES: [CheckCode; 43] = [
// pycodestyle errors
CheckCode::E402,
CheckCode::E501,
CheckCode::E711,
CheckCode::E712,
CheckCode::E713,
CheckCode::E714,
CheckCode::E721,
CheckCode::E722,
CheckCode::E731,
CheckCode::E741,
CheckCode::E742,
CheckCode::E743,
CheckCode::E902,
CheckCode::E999,
// pycodestyle warnings
CheckCode::W292,
// pyflakes
CheckCode::F401,
CheckCode::F402,
CheckCode::F403,
CheckCode::F404,
CheckCode::F405,
CheckCode::F406,
CheckCode::F407,
CheckCode::F541,
CheckCode::F601,
CheckCode::F602,
CheckCode::F621,
CheckCode::F622,
CheckCode::F631,
CheckCode::F632,
CheckCode::F633,
CheckCode::F634,
CheckCode::F701,
CheckCode::F702,
CheckCode::F704,
CheckCode::F706,
CheckCode::F707,
CheckCode::F722,
CheckCode::F821,
CheckCode::F822,
CheckCode::F823,
CheckCode::F831,
CheckCode::F841,
CheckCode::F901,
];
#[derive(
AsRefStr,
EnumIter,
@@ -216,7 +167,7 @@ pub enum CheckCategory {
Pycodestyle,
Pydocstyle,
Pyupgrade,
Pep8Naming,
PEP8Naming,
Flake8Comprehensions,
Flake8Bugbear,
Flake8Builtins,
@@ -235,7 +186,7 @@ impl CheckCategory {
CheckCategory::Flake8Print => "flake8-print",
CheckCategory::Pyupgrade => "pyupgrade",
CheckCategory::Pydocstyle => "pydocstyle",
CheckCategory::Pep8Naming => "pep8-naming",
CheckCategory::PEP8Naming => "pep8-naming",
CheckCategory::Meta => "Meta rules",
}
}
@@ -468,30 +419,30 @@ impl CheckCode {
CheckCode::C402 => CheckKind::UnnecessaryGeneratorDict,
CheckCode::C403 => CheckKind::UnnecessaryListComprehensionSet,
CheckCode::C404 => CheckKind::UnnecessaryListComprehensionDict,
CheckCode::C405 => CheckKind::UnnecessaryLiteralSet("<list/tuple>".to_string()),
CheckCode::C406 => CheckKind::UnnecessaryLiteralDict("<list/tuple>".to_string()),
CheckCode::C405 => CheckKind::UnnecessaryLiteralSet("(list|tuple)".to_string()),
CheckCode::C406 => CheckKind::UnnecessaryLiteralDict("(list|tuple)".to_string()),
CheckCode::C408 => {
CheckKind::UnnecessaryCollectionCall("<dict/list/tuple>".to_string())
CheckKind::UnnecessaryCollectionCall("(dict|list|tuple)".to_string())
}
CheckCode::C409 => {
CheckKind::UnnecessaryLiteralWithinTupleCall("<list/tuple>".to_string())
CheckKind::UnnecessaryLiteralWithinTupleCall("(list|tuple)".to_string())
}
CheckCode::C410 => {
CheckKind::UnnecessaryLiteralWithinListCall("<list/tuple>".to_string())
CheckKind::UnnecessaryLiteralWithinListCall("(list|tuple)".to_string())
}
CheckCode::C411 => CheckKind::UnnecessaryListCall,
CheckCode::C413 => {
CheckKind::UnnecessaryCallAroundSorted("<list/reversed>".to_string())
CheckKind::UnnecessaryCallAroundSorted("(list|reversed)".to_string())
}
CheckCode::C414 => CheckKind::UnnecessaryDoubleCastOrProcess(
"<list/reversed/set/sorted/tuple>".to_string(),
"<list/set/sorted/tuple>".to_string(),
"(list|reversed|set|sorted|tuple)".to_string(),
"(list|set|sorted|tuple)".to_string(),
),
CheckCode::C415 => {
CheckKind::UnnecessarySubscriptReversal("<reversed/set/sorted>".to_string())
CheckKind::UnnecessarySubscriptReversal("(reversed|set|sorted)".to_string())
}
CheckCode::C416 => CheckKind::UnnecessaryComprehension("<list/set>".to_string()),
CheckCode::C417 => CheckKind::UnnecessaryMap("<list/set/dict>".to_string()),
CheckCode::C416 => CheckKind::UnnecessaryComprehension("(list|set)".to_string()),
CheckCode::C417 => CheckKind::UnnecessaryMap("(list|set|dict)".to_string()),
// flake8-print
CheckCode::T201 => CheckKind::PrintFound,
CheckCode::T203 => CheckKind::PPrintFound,
@@ -690,11 +641,11 @@ impl CheckCode {
CheckCode::D417 => CheckCategory::Pydocstyle,
CheckCode::D418 => CheckCategory::Pydocstyle,
CheckCode::D419 => CheckCategory::Pydocstyle,
CheckCode::N801 => CheckCategory::Pep8Naming,
CheckCode::N802 => CheckCategory::Pep8Naming,
CheckCode::N803 => CheckCategory::Pep8Naming,
CheckCode::N804 => CheckCategory::Pep8Naming,
CheckCode::N805 => CheckCategory::Pep8Naming,
CheckCode::N801 => CheckCategory::PEP8Naming,
CheckCode::N802 => CheckCategory::PEP8Naming,
CheckCode::N803 => CheckCategory::PEP8Naming,
CheckCode::N804 => CheckCategory::PEP8Naming,
CheckCode::N805 => CheckCategory::PEP8Naming,
CheckCode::M001 => CheckCategory::Meta,
}
}
@@ -1004,71 +955,71 @@ impl CheckKind {
}
// flake8-comprehensions
CheckKind::UnnecessaryGeneratorList => {
"Unnecessary generator - rewrite as a list comprehension".to_string()
"Unnecessary generator (rewrite as a `list` comprehension)".to_string()
}
CheckKind::UnnecessaryGeneratorSet => {
"Unnecessary generator - rewrite as a set comprehension".to_string()
"Unnecessary generator (rewrite as a `set` comprehension)".to_string()
}
CheckKind::UnnecessaryGeneratorDict => {
"Unnecessary generator - rewrite as a dict comprehension".to_string()
"Unnecessary generator (rewrite as a `dict` comprehension)".to_string()
}
CheckKind::UnnecessaryListComprehensionSet => {
"Unnecessary list comprehension - rewrite as a set comprehension".to_string()
"Unnecessary `list` comprehension (rewrite as a `set` comprehension)".to_string()
}
CheckKind::UnnecessaryListComprehensionDict => {
"Unnecessary list comprehension - rewrite as a dict comprehension".to_string()
"Unnecessary `list` comprehension (rewrite as a `dict` comprehension)".to_string()
}
CheckKind::UnnecessaryLiteralSet(obj_type) => {
format!("Unnecessary {obj_type} literal - rewrite as a set literal")
format!("Unnecessary `{obj_type}` literal (rewrite as a `set` literal)")
}
CheckKind::UnnecessaryLiteralDict(obj_type) => {
format!("Unnecessary {obj_type} literal - rewrite as a dict literal")
format!("Unnecessary `{obj_type}` literal (rewrite as a `dict` literal)")
}
CheckKind::UnnecessaryCollectionCall(obj_type) => {
format!("Unnecessary {obj_type} call - rewrite as a literal")
format!("Unnecessary `{obj_type}` call (rewrite as a literal)")
}
CheckKind::UnnecessaryLiteralWithinTupleCall(literal) => {
if literal == "list" {
format!(
"Unnecessary {literal} literal passed to tuple() - rewrite as a tuple literal"
"Unnecessary `{literal}` literal passed to `tuple()` (rewrite as a `tuple` literal)"
)
} else {
format!(
"Unnecessary {literal} literal passed to tuple() - remove the outer call to tuple()"
"Unnecessary `{literal}` literal passed to `tuple()` (remove the outer call to `tuple()`)"
)
}
}
CheckKind::UnnecessaryLiteralWithinListCall(literal) => {
if literal == "list" {
format!(
"Unnecessary {literal} literal passed to list() - remove the outer call to list()"
"Unnecessary `{literal}` literal passed to `list()` (remove the outer call to `list()`)"
)
} else {
format!(
"Unnecessary {literal} literal passed to list() - rewrite as a list literal"
"Unnecessary `{literal}` literal passed to `list()` (rewrite as a `list` literal)"
)
}
}
CheckKind::UnnecessaryListCall => {
"Unnecessary list call - remove the outer call to list()".to_string()
"Unnecessary `list` call (remove the outer call to `list()`)".to_string()
}
CheckKind::UnnecessaryCallAroundSorted(func) => {
format!("Unnecessary {func} call around sorted()")
format!("Unnecessary `{func}` call around `sorted()`")
}
CheckKind::UnnecessaryDoubleCastOrProcess(inner, outer) => {
format!("Unnecessary {inner} call within {outer}().")
format!("Unnecessary `{inner}` call within `{outer}()`")
}
CheckKind::UnnecessarySubscriptReversal(func) => {
format!("Unnecessary subscript reversal of iterable within {func}()")
format!("Unnecessary subscript reversal of iterable within `{func}()`")
}
CheckKind::UnnecessaryComprehension(obj_type) => {
format!(" Unnecessary {obj_type} comprehension - rewrite using {obj_type}()")
format!(" Unnecessary `{obj_type}` comprehension (rewrite using `{obj_type}()`)")
}
CheckKind::UnnecessaryMap(obj_type) => {
if obj_type == "generator" {
"Unnecessary map usage - rewrite using a generator expression".to_string()
"Unnecessary `map` usage (rewrite using a generator expression)".to_string()
} else {
format!("Unnecessary map usage - rewrite using a {obj_type} comprehension")
format!("Unnecessary `map` usage (rewrite using a `{obj_type}` comprehension)")
}
}
// flake8-print
@@ -1213,19 +1164,19 @@ impl CheckKind {
CheckKind::NoOverIndentation => "Docstring is over-indented".to_string(),
// pep8-naming
CheckKind::InvalidClassName(name) => {
format!("class name `{name}` should use CapWords convention ")
format!("Class name `{name}` should use CapWords convention ")
}
CheckKind::InvalidFunctionName(name) => {
format!("function name `{name}` should be lowercase")
format!("Function name `{name}` should be lowercase")
}
CheckKind::InvalidArgumentName(name) => {
format!("argument name `{name}` should be lowercase")
format!("Argument name `{name}` should be lowercase")
}
CheckKind::InvalidFirstArgumentNameForClassMethod => {
"first argument of a classmethod should be named `cls`".to_string()
"First argument of a class method should be named `cls`".to_string()
}
CheckKind::InvalidFirstArgumentNameForMethod => {
"first argument of a method should be named `self`".to_string()
"First argument of a method should be named `self`".to_string()
}
// Meta
CheckKind::UnusedNOQA(codes) => match codes {
@@ -1251,9 +1202,19 @@ impl CheckKind {
pub fn fixable(&self) -> bool {
matches!(
self,
CheckKind::DeprecatedUnittestAlias(_, _)
CheckKind::BlankLineAfterLastSection(_)
| CheckKind::BlankLineAfterSection(_)
| CheckKind::DeprecatedUnittestAlias(_, _)
| CheckKind::DoNotAssertFalse
| CheckKind::DuplicateHandlerException(_)
| CheckKind::NewLineAfterLastParagraph
| CheckKind::NoBlankLineAfterFunction(_)
| CheckKind::NoBlankLineAfterSummary
| CheckKind::NoBlankLineBeforeClass(_)
| CheckKind::NoBlankLineBeforeFunction(_)
| CheckKind::NoSurroundingWhitespace
| CheckKind::OneBlankLineAfterClass(_)
| CheckKind::OneBlankLineBeforeClass(_)
| CheckKind::PPrintFound
| CheckKind::PrintFound
| CheckKind::SuperCallWithParameters
@@ -1261,10 +1222,10 @@ impl CheckKind {
| CheckKind::UnnecessaryAbspath
| CheckKind::UnusedImport(_)
| CheckKind::UnusedNOQA(_)
| CheckKind::UselessMetaclassType
| CheckKind::UselessObjectInheritance(_)
| CheckKind::UsePEP585Annotation(_)
| CheckKind::UsePEP604Annotation
| CheckKind::UselessMetaclassType
| CheckKind::UselessObjectInheritance(_)
)
}
}
@@ -1277,6 +1238,35 @@ pub struct Fix {
pub applied: bool,
}
impl Fix {
pub fn deletion(start: Location, end: Location) -> Self {
Self {
content: "".to_string(),
location: start,
end_location: end,
applied: false,
}
}
pub fn replacement(content: String, start: Location, end: Location) -> Self {
Self {
content,
location: start,
end_location: end,
applied: false,
}
}
pub fn insertion(content: String, at: Location) -> Self {
Self {
content,
location: at,
end_location: at,
applied: false,
}
}
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct Check {
pub kind: CheckKind,
@@ -1286,11 +1276,11 @@ pub struct Check {
}
impl Check {
pub fn new(kind: CheckKind, span: Range) -> Self {
pub fn new(kind: CheckKind, rage: Range) -> Self {
Self {
kind,
location: span.location,
end_location: span.end_location,
location: rage.location,
end_location: rage.end_location,
fix: None,
}
}

View File

@@ -103,9 +103,9 @@ impl fmt::Display for Warnable {
/// Warn the user if they attempt to enable a code that won't be respected.
pub fn warn_on(
flag: Warnable,
codes: &Vec<CheckCode>,
cli_ignore: &Vec<CheckCode>,
cli_extend_ignore: &Vec<CheckCode>,
codes: &[CheckCode],
cli_ignore: &[CheckCode],
cli_extend_ignore: &[CheckCode],
pyproject_settings: &RawSettings,
pyproject_path: &Option<PathBuf>,
) {

View File

@@ -1,8 +1,8 @@
pub mod docstring_plugins;
pub mod definition;
pub mod extraction;
mod google;
mod helpers;
mod numpy;
pub mod plugins;
pub mod sections;
mod styles;
pub mod types;

View File

@@ -2,7 +2,7 @@
use rustpython_ast::{Constant, Expr, ExprKind, Stmt, StmtKind};
use crate::docstrings::types::{Definition, DefinitionKind, Documentable};
use crate::docstrings::definition::{Definition, DefinitionKind, Documentable};
use crate::visibility::{Modifier, VisibleScope};
/// Extract a docstring from a function or class body.

View File

@@ -8,10 +8,10 @@ use regex::Regex;
use crate::check_ast::Checker;
use crate::checks::{Check, CheckCode, CheckKind};
use crate::docstrings::definition::Definition;
use crate::docstrings::sections;
use crate::docstrings::sections::SectionContext;
use crate::docstrings::styles::SectionStyle;
use crate::docstrings::types::Definition;
pub(crate) static GOOGLE_SECTION_NAMES: Lazy<BTreeSet<&'static str>> = Lazy::new(|| {
BTreeSet::from([

View File

@@ -3,6 +3,12 @@ use rustpython_ast::{Expr, Location};
use crate::ast::types::Range;
use crate::check_ast::Checker;
pub const TRIPLE_QUOTE_PREFIXES: &[&str] = &[
"ur\"\"\"", "ur'''", "u\"\"\"", "u'''", "r\"\"\"", "r'''", "\"\"\"", "'''",
];
pub const SINGLE_QUOTE_PREFIXES: &[&str] = &["ur\"", "ur'", "u\"", "u'", "r\"", "r'", "\"", "'"];
/// Extract the leading words from a line of text.
pub fn leading_words(line: &str) -> String {
line.trim()

View File

@@ -7,9 +7,9 @@ use once_cell::sync::Lazy;
use crate::check_ast::Checker;
use crate::checks::{Check, CheckCode, CheckKind};
use crate::docstrings::definition::Definition;
use crate::docstrings::sections::SectionContext;
use crate::docstrings::styles::SectionStyle;
use crate::docstrings::types::Definition;
use crate::docstrings::{helpers, sections};
pub(crate) static LOWERCASE_NUMPY_SECTION_NAMES: Lazy<BTreeSet<&'static str>> = Lazy::new(|| {

View File

@@ -5,14 +5,17 @@ use regex::Regex;
use rustpython_ast::{Constant, ExprKind, Location, StmtKind};
use crate::ast::types::Range;
use crate::autofix::fixer;
use crate::check_ast::Checker;
use crate::checks::{Check, CheckCode, CheckKind};
use crate::checks::{Check, CheckCode, CheckKind, Fix};
use crate::docstrings::definition::{Definition, DefinitionKind};
use crate::docstrings::google::check_google_section;
use crate::docstrings::helpers::{indentation, leading_space};
use crate::docstrings::helpers::{
indentation, leading_space, SINGLE_QUOTE_PREFIXES, TRIPLE_QUOTE_PREFIXES,
};
use crate::docstrings::numpy::check_numpy_section;
use crate::docstrings::sections::section_contexts;
use crate::docstrings::styles::SectionStyle;
use crate::docstrings::types::{Definition, DefinitionKind};
use crate::visibility::{is_init, is_magic, is_overload, Visibility};
/// D100, D101, D102, D103, D104, D105, D106, D107
@@ -174,35 +177,57 @@ pub fn blank_before_after_function(checker: &mut Checker, definition: &Definitio
.take_while(|line| line.trim().is_empty())
.count();
if blank_lines_before != 0 {
checker.add_check(Check::new(
let mut check = Check::new(
CheckKind::NoBlankLineBeforeFunction(blank_lines_before),
Range::from_located(docstring),
));
);
if matches!(checker.autofix, fixer::Mode::Generate | fixer::Mode::Apply) {
check.amend(Fix::deletion(
Location::new(docstring.location.row() - blank_lines_before, 1),
Location::new(docstring.location.row(), 1),
));
}
checker.add_check(check);
}
}
if checker.settings.enabled.contains(&CheckCode::D202) {
let all_blank_after = after
.lines()
.skip(1)
.all(|line| line.trim().is_empty() || COMMENT_REGEX.is_match(line));
if all_blank_after {
return;
}
let blank_lines_after = after
.lines()
.skip(1)
.take_while(|line| line.trim().is_empty())
.count();
let all_blank_after = after
.lines()
.skip(1)
.all(|line| line.trim().is_empty() || COMMENT_REGEX.is_match(line));
// Report a D202 violation if the docstring is followed by a blank line
// and the blank line is not itself followed by an inner function or
// class.
if !all_blank_after
&& blank_lines_after != 0
&& !(blank_lines_after == 1
&& INNER_FUNCTION_OR_CLASS_REGEX.is_match(after))
{
checker.add_check(Check::new(
// Report a D202 violation if the docstring is followed by a blank line and the
// blank line is not itself followed by an inner function or class.
let expected_blank_lines_after =
if INNER_FUNCTION_OR_CLASS_REGEX.is_match(after) {
1
} else {
0
};
if blank_lines_after != expected_blank_lines_after {
let mut check = Check::new(
CheckKind::NoBlankLineAfterFunction(blank_lines_after),
Range::from_located(docstring),
));
);
if matches!(checker.autofix, fixer::Mode::Generate | fixer::Mode::Apply) {
check.amend(Fix::deletion(
Location::new(
docstring.location.row() + 1 + expected_blank_lines_after,
1,
),
Location::new(docstring.location.row() + 1 + blank_lines_after, 1),
));
}
checker.add_check(check);
}
}
}
@@ -235,39 +260,71 @@ pub fn blank_before_after_class(checker: &mut Checker, definition: &Definition)
.skip(1)
.take_while(|line| line.trim().is_empty())
.count();
if blank_lines_before != 0
&& checker.settings.enabled.contains(&CheckCode::D211)
{
checker.add_check(Check::new(
CheckKind::NoBlankLineBeforeClass(blank_lines_before),
Range::from_located(docstring),
));
if checker.settings.enabled.contains(&CheckCode::D211) {
if blank_lines_before != 0 {
let mut check = Check::new(
CheckKind::NoBlankLineBeforeClass(blank_lines_before),
Range::from_located(docstring),
);
if matches!(checker.autofix, fixer::Mode::Generate | fixer::Mode::Apply)
{
check.amend(Fix::deletion(
Location::new(docstring.location.row() - blank_lines_before, 1),
Location::new(docstring.location.row(), 1),
));
}
checker.add_check(check);
}
}
if blank_lines_before != 1
&& checker.settings.enabled.contains(&CheckCode::D203)
{
checker.add_check(Check::new(
CheckKind::OneBlankLineBeforeClass(blank_lines_before),
Range::from_located(docstring),
));
if checker.settings.enabled.contains(&CheckCode::D203) {
if blank_lines_before != 1 {
let mut check = Check::new(
CheckKind::OneBlankLineBeforeClass(blank_lines_before),
Range::from_located(docstring),
);
if matches!(checker.autofix, fixer::Mode::Generate | fixer::Mode::Apply)
{
check.amend(Fix::replacement(
"\n".to_string(),
Location::new(docstring.location.row() - blank_lines_before, 1),
Location::new(docstring.location.row(), 1),
));
}
checker.add_check(check);
}
}
}
if checker.settings.enabled.contains(&CheckCode::D204) {
let all_blank_after = after
.lines()
.skip(1)
.all(|line| line.trim().is_empty() || COMMENT_REGEX.is_match(line));
if all_blank_after {
return;
}
let blank_lines_after = after
.lines()
.skip(1)
.take_while(|line| line.trim().is_empty())
.count();
let all_blank_after = after
.lines()
.skip(1)
.all(|line| line.trim().is_empty() || COMMENT_REGEX.is_match(line));
if !all_blank_after && blank_lines_after != 1 {
checker.add_check(Check::new(
if blank_lines_after != 1 {
let mut check = Check::new(
CheckKind::OneBlankLineAfterClass(blank_lines_after),
Range::from_located(docstring),
));
);
if matches!(checker.autofix, fixer::Mode::Generate | fixer::Mode::Apply) {
check.amend(Fix::replacement(
"\n".to_string(),
Location::new(docstring.end_location.row() + 1, 1),
Location::new(
docstring.end_location.row() + 1 + blank_lines_after,
1,
),
));
}
checker.add_check(check);
}
}
}
@@ -294,10 +351,18 @@ pub fn blank_after_summary(checker: &mut Checker, definition: &Definition) {
}
}
if lines_count > 1 && blanks_count != 1 {
checker.add_check(Check::new(
let mut check = Check::new(
CheckKind::NoBlankLineAfterSummary,
Range::from_located(docstring),
));
);
if matches!(checker.autofix, fixer::Mode::Generate | fixer::Mode::Apply) {
check.amend(Fix::replacement(
"\n".to_string(),
Location::new(docstring.location.row() + 1, 1),
Location::new(docstring.location.row() + 1 + blanks_count, 1),
));
}
checker.add_check(check);
}
}
}
@@ -403,13 +468,26 @@ pub fn newline_after_last_paragraph(checker: &mut Checker, definition: &Definiti
let content = checker
.locator
.slice_source_code_range(&Range::from_located(docstring));
if let Some(line) = content.lines().last() {
let line = line.trim();
if line != "\"\"\"" && line != "'''" {
checker.add_check(Check::new(
if let Some(last_line) = content.lines().last().map(|line| line.trim()) {
if last_line != "\"\"\"" && last_line != "'''" {
let mut check = Check::new(
CheckKind::NewLineAfterLastParagraph,
Range::from_located(docstring),
));
);
if matches!(checker.autofix, fixer::Mode::Generate | fixer::Mode::Apply)
{
// Insert a newline just before the end-quote(s).
let mut content = "\n".to_string();
content.push_str(indentation(checker, docstring));
check.amend(Fix::insertion(
content,
Location::new(
docstring.end_location.row(),
docstring.end_location.column() - "\"\"\"".len(),
),
));
}
checker.add_check(check);
}
}
return;
@@ -429,14 +507,45 @@ pub fn no_surrounding_whitespace(checker: &mut Checker, definition: &Definition)
{
let mut lines = string.lines();
if let Some(line) = lines.next() {
if line.trim().is_empty() {
let trimmed = line.trim();
if trimmed.is_empty() {
return;
}
if line.starts_with(' ') || (matches!(lines.next(), None) && line.ends_with(' ')) {
checker.add_check(Check::new(
if line != trimmed {
let mut check = Check::new(
CheckKind::NoSurroundingWhitespace,
Range::from_located(docstring),
));
);
if matches!(checker.autofix, fixer::Mode::Generate | fixer::Mode::Apply) {
if let Some(first_line) = checker
.locator
.slice_source_code_range(&Range::from_located(docstring))
.lines()
.next()
.map(|line| line.to_lowercase())
{
for pattern in TRIPLE_QUOTE_PREFIXES.iter().chain(SINGLE_QUOTE_PREFIXES)
{
if first_line.starts_with(pattern) {
check.amend(Fix::replacement(
trimmed.to_string(),
Location::new(
docstring.location.row(),
docstring.location.column() + pattern.len(),
),
Location::new(
docstring.location.row(),
docstring.location.column()
+ pattern.len()
+ line.chars().count(),
),
));
break;
}
}
}
}
checker.add_check(check);
}
}
}
@@ -452,20 +561,14 @@ pub fn multi_line_summary_start(checker: &mut Checker, definition: &Definition)
} = &docstring.node
{
if string.lines().nth(1).is_some() {
let content = checker
if let Some(first_line) = checker
.locator
.slice_source_code_range(&Range::from_located(docstring));
if let Some(first_line) = content.lines().next() {
let first_line = first_line.trim().to_lowercase();
let starts_with_triple = first_line == "\"\"\""
|| first_line == "'''"
|| first_line == "u\"\"\""
|| first_line == "u'''"
|| first_line == "r\"\"\""
|| first_line == "r'''"
|| first_line == "ur\"\"\""
|| first_line == "ur'''";
if starts_with_triple {
.slice_source_code_range(&Range::from_located(docstring))
.lines()
.next()
.map(|line| line.to_lowercase())
{
if TRIPLE_QUOTE_PREFIXES.contains(&first_line.as_str()) {
if checker.settings.enabled.contains(&CheckCode::D212) {
checker.add_check(Check::new(
CheckKind::MultiLineSummaryFirstLine,
@@ -494,11 +597,13 @@ pub fn triple_quotes(checker: &mut Checker, definition: &Definition) {
..
} = &docstring.node
{
let content = checker
if let Some(first_line) = checker
.locator
.slice_source_code_range(&Range::from_located(docstring));
if let Some(first_line) = content.lines().next() {
let first_line = first_line.trim().to_lowercase();
.slice_source_code_range(&Range::from_located(docstring))
.lines()
.next()
.map(|line| line.to_lowercase())
{
let starts_with_triple = if string.contains("\"\"\"") {
first_line.starts_with("'''")
|| first_line.starts_with("u'''")

View File

@@ -1,15 +1,16 @@
use std::collections::BTreeSet;
use itertools::Itertools;
use rustpython_ast::{Arg, StmtKind};
use rustpython_ast::{Arg, Location, StmtKind};
use titlecase::titlecase;
use crate::ast::types::Range;
use crate::autofix::fixer;
use crate::check_ast::Checker;
use crate::checks::{Check, CheckCode, CheckKind};
use crate::checks::{Check, CheckCode, CheckKind, Fix};
use crate::docstrings::definition::{Definition, DefinitionKind};
use crate::docstrings::helpers;
use crate::docstrings::styles::SectionStyle;
use crate::docstrings::types::{Definition, DefinitionKind};
use crate::visibility::is_static;
#[derive(Debug)]
@@ -282,17 +283,43 @@ pub(crate) fn check_common_section(
{
if context.is_last_section {
if checker.settings.enabled.contains(&CheckCode::D413) {
checker.add_check(Check::new(
let mut check = Check::new(
CheckKind::BlankLineAfterLastSection(context.section_name.to_string()),
Range::from_located(docstring),
))
);
if matches!(checker.autofix, fixer::Mode::Generate | fixer::Mode::Apply) {
check.amend(Fix::insertion(
"\n".to_string(),
Location::new(
docstring.location.row()
+ context.original_index
+ 1
+ context.following_lines.len(),
1,
),
))
}
checker.add_check(check);
}
} else {
if checker.settings.enabled.contains(&CheckCode::D410) {
checker.add_check(Check::new(
let mut check = Check::new(
CheckKind::BlankLineAfterSection(context.section_name.to_string()),
Range::from_located(docstring),
))
);
if matches!(checker.autofix, fixer::Mode::Generate | fixer::Mode::Apply) {
check.amend(Fix::insertion(
"\n".to_string(),
Location::new(
docstring.location.row()
+ context.original_index
+ 1
+ context.following_lines.len(),
1,
),
))
}
checker.add_check(check);
}
}
}

View File

@@ -78,7 +78,7 @@ pub(crate) fn check_path(
if !ignores.is_empty() {
return Ok(checks
.into_iter()
.filter(|check| !ignores.contains(check.kind.code()))
.filter(|check| !ignores.contains(&check.kind.code()))
.collect());
}
}

View File

@@ -81,7 +81,7 @@ pub fn extract_noqa_line_for(lxr: &[LexResult]) -> Vec<usize> {
}
fn add_noqa_inner(
checks: &Vec<Check>,
checks: &[Check],
contents: &str,
noqa_line_for: &[usize],
) -> Result<(usize, String)> {
@@ -138,7 +138,7 @@ fn add_noqa_inner(
}
pub fn add_noqa(
checks: &Vec<Check>,
checks: &[Check],
contents: &str,
noqa_line_for: &[usize],
path: &Path,

View File

@@ -24,7 +24,7 @@ fn type_pattern(elts: Vec<&Expr>) -> Expr {
pub fn duplicate_handler_exceptions(
checker: &mut Checker,
expr: &Expr,
elts: &Vec<Expr>,
elts: &[Expr],
) -> BTreeSet<String> {
let mut seen: BTreeSet<String> = Default::default();
let mut duplicates: BTreeSet<String> = Default::default();

View File

@@ -4,12 +4,7 @@ use crate::ast::{checkers, helpers};
use crate::autofix::{fixer, fixes};
use crate::check_ast::Checker;
pub fn super_call_with_parameters(
checker: &mut Checker,
expr: &Expr,
func: &Expr,
args: &Vec<Expr>,
) {
pub fn super_call_with_parameters(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
// Only bother going through the super check at all if we're in a `super` call.
// (We check this in `check_super_args` too, so this is just an optimization.)
if helpers::is_super_call_with_arguments(func, args) {

View File

@@ -6,7 +6,7 @@ use crate::autofix::fixer;
use crate::check_ast::Checker;
use crate::checks::{CheckKind, Fix};
pub fn type_of_primitive(checker: &mut Checker, expr: &Expr, func: &Expr, args: &Vec<Expr>) {
pub fn type_of_primitive(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
if let Some(mut check) =
checkers::type_of_primitive(func, args, checker.locate_check(Range::from_located(expr)))
{

View File

@@ -6,7 +6,7 @@ use crate::autofix::fixer;
use crate::check_ast::Checker;
use crate::checks::Fix;
pub fn unnecessary_abspath(checker: &mut Checker, expr: &Expr, func: &Expr, args: &Vec<Expr>) {
pub fn unnecessary_abspath(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
if let Some(mut check) =
checkers::unnecessary_abspath(func, args, checker.locate_check(Range::from_located(expr)))
{

View File

@@ -6,12 +6,7 @@ use crate::ast::types::{CheckLocator, Range};
use crate::autofix::{fixer, fixes};
use crate::check_ast::Checker;
pub fn useless_metaclass_type(
checker: &mut Checker,
stmt: &Stmt,
value: &Expr,
targets: &Vec<Expr>,
) {
pub fn useless_metaclass_type(checker: &mut Checker, stmt: &Stmt, value: &Expr, targets: &[Expr]) {
if let Some(mut check) = checkers::useless_metaclass_type(
targets,
value,

View File

@@ -50,14 +50,14 @@ impl Printer {
serde_json::to_string_pretty(
&messages
.iter()
.map(|m| ExpandedMessage {
kind: &m.kind,
code: m.kind.code(),
message: m.kind.body(),
fixed: m.fixed,
location: m.location,
end_location: m.end_location,
filename: &m.filename,
.map(|message| ExpandedMessage {
kind: &message.kind,
code: message.kind.code(),
message: message.kind.body(),
fixed: message.fixed,
location: message.location,
end_location: message.end_location,
filename: &message.filename,
})
.collect::<Vec<_>>()
)?

View File

@@ -8,8 +8,9 @@ use glob::Pattern;
use once_cell::sync::Lazy;
use regex::Regex;
use serde::{Deserialize, Serialize};
use strum::IntoEnumIterator;
use crate::checks::{CheckCode, DEFAULT_CHECK_CODES};
use crate::checks::{CheckCategory, CheckCode};
use crate::fs;
use crate::pyproject::{load_config, StrCheckCodePair};
@@ -153,9 +154,16 @@ impl RawSettings {
.map(|path| FilePattern::from_user(path, project_root))
.collect(),
extend_ignore: config.extend_ignore,
select: config
.select
.unwrap_or_else(|| DEFAULT_CHECK_CODES.to_vec()),
select: config.select.unwrap_or_else(|| {
CheckCode::iter()
.filter(|code| {
matches!(
code.category(),
CheckCategory::Pycodestyle | CheckCategory::Pyflakes
)
})
.collect()
}),
extend_select: config.extend_select,
ignore: config.ignore,
line_length: config.line_length.unwrap_or(88),

View File

@@ -10,7 +10,15 @@ expression: checks
end_location:
row: 132
column: 25
fix: ~
fix:
content: ""
location:
row: 131
column: 1
end_location:
row: 132
column: 1
applied: false
- kind:
NoBlankLineBeforeFunction: 1
location:
@@ -19,5 +27,13 @@ expression: checks
end_location:
row: 146
column: 38
fix: ~
fix:
content: ""
location:
row: 145
column: 1
end_location:
row: 146
column: 1
applied: false

View File

@@ -2,6 +2,23 @@
source: src/linter.rs
expression: checks
---
- kind:
NoBlankLineAfterFunction: 0
location:
row: 79
column: 5
end_location:
row: 79
column: 33
fix:
content: ""
location:
row: 81
column: 1
end_location:
row: 80
column: 1
applied: false
- kind:
NoBlankLineAfterFunction: 1
location:
@@ -10,7 +27,15 @@ expression: checks
end_location:
row: 137
column: 25
fix: ~
fix:
content: ""
location:
row: 138
column: 1
end_location:
row: 139
column: 1
applied: false
- kind:
NoBlankLineAfterFunction: 1
location:
@@ -19,5 +44,30 @@ expression: checks
end_location:
row: 146
column: 38
fix: ~
fix:
content: ""
location:
row: 147
column: 1
end_location:
row: 148
column: 1
applied: false
- kind:
NoBlankLineAfterFunction: 0
location:
row: 453
column: 5
end_location:
row: 453
column: 24
fix:
content: ""
location:
row: 455
column: 1
end_location:
row: 454
column: 1
applied: false

View File

@@ -10,7 +10,15 @@ expression: checks
end_location:
row: 156
column: 33
fix: ~
fix:
content: "\n"
location:
row: 156
column: 1
end_location:
row: 156
column: 1
applied: false
- kind:
OneBlankLineBeforeClass: 0
location:
@@ -19,7 +27,15 @@ expression: checks
end_location:
row: 187
column: 46
fix: ~
fix:
content: "\n"
location:
row: 187
column: 1
end_location:
row: 187
column: 1
applied: false
- kind:
OneBlankLineBeforeClass: 0
location:
@@ -28,5 +44,13 @@ expression: checks
end_location:
row: 527
column: 8
fix: ~
fix:
content: "\n"
location:
row: 521
column: 1
end_location:
row: 521
column: 1
applied: false

View File

@@ -10,7 +10,15 @@ expression: checks
end_location:
row: 176
column: 25
fix: ~
fix:
content: "\n"
location:
row: 177
column: 1
end_location:
row: 177
column: 1
applied: false
- kind:
OneBlankLineAfterClass: 0
location:
@@ -19,5 +27,13 @@ expression: checks
end_location:
row: 187
column: 46
fix: ~
fix:
content: "\n"
location:
row: 188
column: 1
end_location:
row: 188
column: 1
applied: false

View File

@@ -9,7 +9,15 @@ expression: checks
end_location:
row: 198
column: 8
fix: ~
fix:
content: "\n"
location:
row: 196
column: 1
end_location:
row: 196
column: 1
applied: false
- kind: NoBlankLineAfterSummary
location:
row: 205
@@ -17,5 +25,13 @@ expression: checks
end_location:
row: 210
column: 8
fix: ~
fix:
content: "\n"
location:
row: 206
column: 1
end_location:
row: 208
column: 1
applied: false

View File

@@ -9,5 +9,13 @@ expression: checks
end_location:
row: 278
column: 20
fix: ~
fix:
content: "\n "
location:
row: 278
column: 17
end_location:
row: 278
column: 17
applied: false

View File

@@ -9,7 +9,15 @@ expression: checks
end_location:
row: 283
column: 34
fix: ~
fix:
content: Whitespace at the end.
location:
row: 283
column: 8
end_location:
row: 283
column: 31
applied: false
- kind: NoSurroundingWhitespace
location:
row: 288
@@ -17,7 +25,15 @@ expression: checks
end_location:
row: 288
column: 38
fix: ~
fix:
content: Whitespace at everywhere.
location:
row: 288
column: 8
end_location:
row: 288
column: 35
applied: false
- kind: NoSurroundingWhitespace
location:
row: 294
@@ -25,5 +41,13 @@ expression: checks
end_location:
row: 297
column: 8
fix: ~
fix:
content: Whitespace at the beginning.
location:
row: 294
column: 8
end_location:
row: 294
column: 37
applied: false

View File

@@ -10,7 +10,15 @@ expression: checks
end_location:
row: 165
column: 30
fix: ~
fix:
content: ""
location:
row: 164
column: 1
end_location:
row: 165
column: 1
applied: false
- kind:
NoBlankLineBeforeClass: 1
location:
@@ -19,5 +27,13 @@ expression: checks
end_location:
row: 176
column: 25
fix: ~
fix:
content: ""
location:
row: 175
column: 1
end_location:
row: 176
column: 1
applied: false

View File

@@ -10,7 +10,15 @@ expression: checks
end_location:
row: 78
column: 8
fix: ~
fix:
content: "\n"
location:
row: 71
column: 1
end_location:
row: 71
column: 1
applied: false
- kind:
BlankLineAfterSection: Returns
location:
@@ -19,5 +27,13 @@ expression: checks
end_location:
row: 221
column: 8
fix: ~
fix:
content: "\n"
location:
row: 218
column: 1
end_location:
row: 218
column: 1
applied: false

View File

@@ -5,7 +5,7 @@ use std::path::Path;
use rustpython_ast::{Stmt, StmtKind};
use crate::ast::helpers::match_name_or_attr;
use crate::docstrings::types::Documentable;
use crate::docstrings::definition::Documentable;
#[derive(Debug, Clone)]
pub enum Modifier {