Rules
Ruff supports over 500 lint rules, many of which are inspired by popular tools like Flake8,
isort, pyupgrade, and others. Regardless of the rule's origin, Ruff re-implements every rule in
Rust as a first-party feature.
By default, Ruff enables Flake8's E
and F
rules. Ruff supports all rules from the F
category,
and a subset of the E
category, omitting those
stylistic rules made obsolete by the use of an autoformatter, like
Black.
If you're just getting started with Ruff, the default rule set is a great place to start: it
catches a wide variety of common errors (like unused imports) with zero configuration.
The 🛠emoji indicates that a rule is automatically fixable by the --fix
command-line option.
Pyflakes (F)
For more, see Pyflakes on PyPI.
Code |
Name |
Message |
Fix |
F401 |
unused-import |
{name} imported but unused; consider adding to __all__ or using a redundant alias |
🛠|
F402 |
import-shadowed-by-loop-var |
Import {name} from line {line} shadowed by loop variable |
|
F403 |
import-star |
from {name} import * used; unable to detect undefined names |
|
F404 |
late-future-import |
from __future__ imports must occur at the beginning of the file |
|
F405 |
import-star-usage |
{name} may be undefined, or defined from star imports: |
|
F406 |
import-star-not-permitted |
from {name} import * only allowed at module level |
|
F407 |
future-feature-not-defined |
Future feature {name} is not defined |
|
F501 |
percent-format-invalid-format |
% -format string has invalid format string: |
|
F502 |
percent-format-expected-mapping |
% -format string expected mapping but got sequence |
|
F503 |
percent-format-expected-sequence |
% -format string expected sequence but got mapping |
|
F504 |
percent-format-extra-named-arguments |
% -format string has unused named argument(s): |
🛠|
F505 |
percent-format-missing-argument |
% -format string is missing argument(s) for placeholder(s): |
|
F506 |
percent-format-mixed-positional-and-named |
% -format string has mixed positional and named placeholders |
|
F507 |
percent-format-positional-count-mismatch |
% -format string has {wanted} placeholder(s) but {got} substitution(s) |
|
F508 |
percent-format-star-requires-sequence |
% -format string * specifier requires sequence |
|
F509 |
percent-format-unsupported-format-character |
% -format string has unsupported format character {char} |
|
F521 |
string-dot-format-invalid-format |
.format call has invalid format string: |
|
F522 |
string-dot-format-extra-named-arguments |
.format call has unused named argument(s): |
🛠|
F523 |
string-dot-format-extra-positional-arguments |
.format call has unused arguments at position(s): |
|
F524 |
string-dot-format-missing-arguments |
.format call is missing argument(s) for placeholder(s): |
|
F525 |
string-dot-format-mixing-automatic |
.format string mixes automatic and manual numbering |
|
F541 |
f-string-missing-placeholders |
f-string without any placeholders |
🛠|
F601 |
multi-value-repeated-key-literal |
Dictionary key literal {name} repeated |
🛠|
F602 |
multi-value-repeated-key-variable |
Dictionary key {name} repeated |
🛠|
F621 |
expressions-in-star-assignment |
Too many expressions in star-unpacking assignment |
|
F622 |
two-starred-expressions |
Two starred expressions in assignment |
|
F631 |
assert-tuple |
Assert test is a non-empty tuple, which is always True |
|
F632 |
is-literal |
Use == to compare constant literals |
🛠|
F633 |
invalid-print-syntax |
Use of >> is invalid with print function |
|
F634 |
if-tuple |
If test is a tuple, which is always True |
|
F701 |
break-outside-loop |
break outside loop |
|
F702 |
continue-outside-loop |
continue not properly in loop |
|
F704 |
yield-outside-function |
{keyword} statement outside of a function |
|
F706 |
return-outside-function |
return statement outside of a function/method |
|
F707 |
default-except-not-last |
An except block as not the last exception handler |
|
F722 |
forward-annotation-syntax-error |
Syntax error in forward annotation: {body} |
|
F811 |
redefined-while-unused |
Redefinition of unused {name} from line |
|
F821 |
undefined-name |
Undefined name {name} |
|
F822 |
undefined-export |
Undefined name {name} in __all__ |
|
F823 |
undefined-local |
Local variable {name} referenced before assignment |
|
F841 |
unused-variable |
Local variable {name} is assigned to but never used |
🛠|
F842 |
unused-annotation |
Local variable {name} is annotated but never used |
|
F901 |
raise-not-implemented |
raise NotImplemented should be raise NotImplementedError |
🛠|
pycodestyle (E, W)
For more, see pycodestyle on PyPI.
Error (E)
Warning (W)
mccabe (C90)
For more, see mccabe on PyPI.
Code |
Name |
Message |
Fix |
C901 |
complex-structure |
{name} is too complex ({complexity} > {max_complexity}) |
|
isort (I)
For more, see isort on PyPI.
pep8-naming (N)
For more, see pep8-naming on PyPI.
pydocstyle (D)
For more, see pydocstyle on PyPI.
Code |
Name |
Message |
Fix |
D100 |
public-module |
Missing docstring in public module |
|
D101 |
public-class |
Missing docstring in public class |
|
D102 |
public-method |
Missing docstring in public method |
|
D103 |
public-function |
Missing docstring in public function |
|
D104 |
public-package |
Missing docstring in public package |
|
D105 |
magic-method |
Missing docstring in magic method |
|
D106 |
public-nested-class |
Missing docstring in public nested class |
|
D107 |
public-init |
Missing docstring in __init__ |
|
D200 |
fits-on-one-line |
One-line docstring should fit on one line |
🛠|
D201 |
no-blank-line-before-function |
No blank lines allowed before function docstring (found {num_lines}) |
🛠|
D202 |
no-blank-line-after-function |
No blank lines allowed after function docstring (found {num_lines}) |
🛠|
D203 |
one-blank-line-before-class |
1 blank line required before class docstring |
🛠|
D204 |
one-blank-line-after-class |
1 blank line required after class docstring |
🛠|
D205 |
blank-line-after-summary |
1 blank line required between summary line and description |
🛠|
D206 |
indent-with-spaces |
Docstring should be indented with spaces, not tabs |
|
D207 |
no-under-indentation |
Docstring is under-indented |
🛠|
D208 |
no-over-indentation |
Docstring is over-indented |
🛠|
D209 |
new-line-after-last-paragraph |
Multi-line docstring closing quotes should be on a separate line |
🛠|
D210 |
no-surrounding-whitespace |
No whitespaces allowed surrounding docstring text |
🛠|
D211 |
no-blank-line-before-class |
No blank lines allowed before class docstring |
🛠|
D212 |
multi-line-summary-first-line |
Multi-line docstring summary should start at the first line |
🛠|
D213 |
multi-line-summary-second-line |
Multi-line docstring summary should start at the second line |
🛠|
D214 |
section-not-over-indented |
Section is over-indented ("{name}") |
🛠|
D215 |
section-underline-not-over-indented |
Section underline is over-indented ("{name}") |
🛠|
D300 |
triple-single-quotes |
Use triple double quotes """ |
|
D301 |
escape-sequence-in-docstring |
Use r""" if any backslashes in a docstring |
|
D400 |
ends-in-period |
First line should end with a period |
🛠|
D401 |
non-imperative-mood |
First line of docstring should be in imperative mood: "{first_line}" |
|
D402 |
no-signature |
First line should not be the function's signature |
|
D403 |
first-line-capitalized |
First word of the first line should be properly capitalized |
|
D404 |
docstring-starts-with-this |
First word of the docstring should not be "This" |
|
D405 |
capitalize-section-name |
Section name should be properly capitalized ("{name}") |
🛠|
D406 |
new-line-after-section-name |
Section name should end with a newline ("{name}") |
🛠|
D407 |
dashed-underline-after-section |
Missing dashed underline after section ("{name}") |
🛠|
D408 |
section-underline-after-name |
Section underline should be in the line following the section's name ("{name}") |
🛠|
D409 |
section-underline-matches-section-length |
Section underline should match the length of its name ("{name}") |
🛠|
D410 |
blank-line-after-section |
Missing blank line after section ("{name}") |
🛠|
D411 |
blank-line-before-section |
Missing blank line before section ("{name}") |
🛠|
D412 |
no-blank-lines-between-header-and-content |
No blank lines allowed between a section header and its content ("{name}") |
🛠|
D413 |
blank-line-after-last-section |
Missing blank line after last section ("{name}") |
🛠|
D414 |
empty-docstring-section |
Section has no content ("{name}") |
|
D415 |
ends-in-punctuation |
First line should end with a period, question mark, or exclamation point |
🛠|
D416 |
section-name-ends-in-colon |
Section name should end with a colon ("{name}") |
🛠|
D417 |
undocumented-param |
Missing argument description in the docstring: {name} |
|
D418 |
overload-with-docstring |
Function decorated with @overload shouldn't contain a docstring |
|
D419 |
empty-docstring |
Docstring is empty |
|
pyupgrade (UP)
For more, see pyupgrade on PyPI.
Code |
Name |
Message |
Fix |
UP001 |
useless-metaclass-type |
__metaclass__ = type is implied |
🛠|
UP003 |
type-of-primitive |
Use {} instead of type(...) |
🛠|
UP004 |
useless-object-inheritance |
Class {name} inherits from object |
🛠|
UP005 |
deprecated-unittest-alias |
{alias} is deprecated, use {target} |
🛠|
UP006 |
deprecated-collection-type |
Use {} instead of {} for type annotations |
🛠|
UP007 |
typing-union |
Use X \| Y for type annotations |
🛠|
UP008 |
super-call-with-parameters |
Use super() instead of super(__class__, self) |
🛠|
UP009 |
utf8-encoding-declaration |
UTF-8 encoding declaration is unnecessary |
🛠|
UP010 |
unnecessary-future-import |
Unnecessary __future__ import {import} for target Python version |
🛠|
UP011 |
lru-cache-without-parameters |
Unnecessary parameters to functools.lru_cache |
🛠|
UP012 |
unnecessary-encode-utf8 |
Unnecessary call to encode as UTF-8 |
🛠|
UP013 |
convert-typed-dict-functional-to-class |
Convert {name} from TypedDict functional to class syntax |
🛠|
UP014 |
convert-named-tuple-functional-to-class |
Convert {name} from NamedTuple functional to class syntax |
🛠|
UP015 |
redundant-open-modes |
Unnecessary open mode parameters |
🛠|
UP017 |
datetime-timezone-utc |
Use datetime.UTC alias |
🛠|
UP018 |
native-literals |
Unnecessary call to {literal_type} |
🛠|
UP019 |
typing-text-str-alias |
typing.Text is deprecated, use str |
🛠|
UP020 |
open-alias |
Use builtin open |
🛠|
UP021 |
replace-universal-newlines |
universal_newlines is deprecated, use text |
🛠|
UP022 |
replace-stdout-stderr |
Sending stdout and stderr to pipe is deprecated, use capture_output |
🛠|
UP023 |
rewrite-c-element-tree |
cElementTree is deprecated, use ElementTree |
🛠|
UP024 |
os-error-alias |
Replace aliased errors with OSError |
🛠|
UP025 |
rewrite-unicode-literal |
Remove unicode literals from strings |
🛠|
UP026 |
rewrite-mock-import |
mock is deprecated, use unittest.mock |
🛠|
UP027 |
rewrite-list-comprehension |
Replace unpacked list comprehension with a generator expression |
🛠|
UP028 |
rewrite-yield-from |
Replace yield over for loop with yield from |
🛠|
UP029 |
unnecessary-builtin-import |
Unnecessary builtin import: {import} |
🛠|
UP030 |
format-literals |
Use implicit references for positional format fields |
🛠|
UP031 |
printf-string-formatting |
Use format specifiers instead of percent format |
🛠|
UP032 |
f-string |
Use f-string instead of format call |
🛠|
UP033 |
functools-cache |
Use @functools.cache instead of @functools.lru_cache(maxsize=None) |
🛠|
UP034 |
extraneous-parentheses |
Avoid extraneous parentheses |
🛠|
UP035 |
deprecated-import |
Import from {target} instead: |
🛠|
UP036 |
outdated-version-block |
Version block is outdated for minimum Python version |
🛠|
UP037 |
quoted-annotation |
Remove quotes from type annotation |
🛠|
UP038 |
isinstance-with-tuple |
Use X \| Y in {} call instead of (X, Y) |
🛠|
flake8-2020 (YTT)
For more, see flake8-2020 on PyPI.
Code |
Name |
Message |
Fix |
YTT101 |
sys-version-slice3-referenced |
sys.version[:3] referenced (python3.10), use sys.version_info |
|
YTT102 |
sys-version2-referenced |
sys.version[2] referenced (python3.10), use sys.version_info |
|
YTT103 |
sys-version-cmp-str3 |
sys.version compared to string (python3.10), use sys.version_info |
|
YTT201 |
sys-version-info0-eq3-referenced |
sys.version_info[0] == 3 referenced (python4), use >= |
|
YTT202 |
six-py3-referenced |
six.PY3 referenced (python4), use not six.PY2 |
|
YTT203 |
sys-version-info1-cmp-int |
sys.version_info[1] compared to integer (python4), compare sys.version_info to tuple |
|
YTT204 |
sys-version-info-minor-cmp-int |
sys.version_info.minor compared to integer (python4), compare sys.version_info to tuple |
|
YTT301 |
sys-version0-referenced |
sys.version[0] referenced (python10), use sys.version_info |
|
YTT302 |
sys-version-cmp-str10 |
sys.version compared to string (python10), use sys.version_info |
|
YTT303 |
sys-version-slice1-referenced |
sys.version[:1] referenced (python10), use sys.version_info |
|
flake8-annotations (ANN)
For more, see flake8-annotations on PyPI.
flake8-bandit (S)
For more, see flake8-bandit on PyPI.
Code |
Name |
Message |
Fix |
S101 |
assert |
Use of assert detected |
|
S102 |
exec-builtin |
Use of exec detected |
|
S103 |
bad-file-permissions |
os.chmod setting a permissive mask {mask:#o} on file or directory |
|
S104 |
hardcoded-bind-all-interfaces |
Possible binding to all interfaces |
|
S105 |
hardcoded-password-string |
Possible hardcoded password: "{}" |
|
S106 |
hardcoded-password-func-arg |
Possible hardcoded password: "{}" |
|
S107 |
hardcoded-password-default |
Possible hardcoded password: "{}" |
|
S108 |
hardcoded-temp-file |
Probable insecure usage of temporary file or directory: "{}" |
|
S110 |
try-except-pass |
try -except -pass detected, consider logging the exception |
|
S112 |
try-except-continue |
try -except -continue detected, consider logging the exception |
|
S113 |
request-without-timeout |
Probable use of requests call with timeout set to {value} |
|
S324 |
hashlib-insecure-hash-function |
Probable use of insecure hash functions in hashlib : {string} |
|
S501 |
request-with-no-cert-validation |
Probable use of {string} call with verify=False disabling SSL certificate checks |
|
S506 |
unsafe-yaml-load |
Probable use of unsafe loader {name} with yaml.load . Allows instantiation of arbitrary objects. Consider yaml.safe_load . |
|
S508 |
snmp-insecure-version |
The use of SNMPv1 and SNMPv2 is insecure. Use SNMPv3 if able. |
|
S509 |
snmp-weak-cryptography |
You should not use SNMPv3 without encryption. noAuthNoPriv & authNoPriv is insecure. |
|
S608 |
hardcoded-sql-expression |
Possible SQL injection vector through string-based query construction |
|
S612 |
logging-config-insecure-listen |
Use of insecure logging.config.listen detected |
|
S701 |
jinja2-autoescape-false |
Using jinja2 templates with autoescape=False is dangerous and can lead to XSS. Ensure autoescape=True or use the select_autoescape function. |
|
flake8-blind-except (BLE)
For more, see flake8-blind-except on PyPI.
Code |
Name |
Message |
Fix |
BLE001 |
blind-except |
Do not catch blind exception: {name} |
|
flake8-boolean-trap (FBT)
For more, see flake8-boolean-trap on PyPI.
Code |
Name |
Message |
Fix |
FBT001 |
boolean-positional-arg-in-function-definition |
Boolean positional arg in function definition |
|
FBT002 |
boolean-default-value-in-function-definition |
Boolean default value in function definition |
|
FBT003 |
boolean-positional-value-in-function-call |
Boolean positional value in function call |
|
flake8-bugbear (B)
For more, see flake8-bugbear on PyPI.
Code |
Name |
Message |
Fix |
B002 |
unary-prefix-increment |
Python does not support the unary prefix increment |
|
B003 |
assignment-to-os-environ |
Assigning to os.environ doesn't clear the environment |
|
B004 |
unreliable-callable-check |
Using hasattr(x, '__call__') to test if x is callable is unreliable. Use callable(x) for consistent results. |
|
B005 |
strip-with-multi-characters |
Using .strip() with multi-character strings is misleading the reader |
|
B006 |
mutable-argument-default |
Do not use mutable data structures for argument defaults |
|
B007 |
unused-loop-control-variable |
Loop control variable {name} not used within loop body |
🛠|
B008 |
function-call-argument-default |
Do not perform function call {name} in argument defaults |
|
B009 |
get-attr-with-constant |
Do not call getattr with a constant attribute value. It is not any safer than normal property access. |
🛠|
B010 |
set-attr-with-constant |
Do not call setattr with a constant attribute value. It is not any safer than normal property access. |
🛠|
B011 |
assert-false |
Do not assert False (python -O removes these calls), raise AssertionError() |
🛠|
B012 |
jump-statement-in-finally |
{name} inside finally blocks cause exceptions to be silenced |
|
B013 |
redundant-tuple-in-exception-handler |
A length-one tuple literal is redundant. Write except {name} instead of except ({name},) . |
🛠|
B014 |
duplicate-handler-exception |
Exception handler with duplicate exception: {name} |
🛠|
B015 |
useless-comparison |
Pointless comparison. This comparison does nothing but waste CPU instructions. Either prepend assert or remove it. |
|
B016 |
cannot-raise-literal |
Cannot raise a literal. Did you intend to return it or raise an Exception? |
|
B017 |
assert-raises-exception |
assertRaises(Exception) should be considered evil |
|
B018 |
useless-expression |
Found useless expression. Either assign it to a variable or remove it. |
|
B019 |
cached-instance-method |
Use of functools.lru_cache or functools.cache on methods can lead to memory leaks |
|
B020 |
loop-variable-overrides-iterator |
Loop control variable {name} overrides iterable it iterates |
|
B021 |
f-string-docstring |
f-string used as docstring. This will be interpreted by python as a joined string rather than a docstring. |
|
B022 |
useless-contextlib-suppress |
No arguments passed to contextlib.suppress . No exceptions will be suppressed and therefore this context manager is redundant |
|
B023 |
function-uses-loop-variable |
Function definition does not bind loop variable {name} |
|
B024 |
abstract-base-class-without-abstract-method |
{name} is an abstract base class, but it has no abstract methods |
|
B025 |
duplicate-try-block-exception |
try-except block with duplicate exception {name} |
|
B026 |
star-arg-unpacking-after-keyword-arg |
Star-arg unpacking after a keyword argument is strongly discouraged |
|
B027 |
empty-method-without-abstract-decorator |
{name} is an empty method in an abstract base class, but has no abstract decorator |
|
B028 |
no-explicit-stacklevel |
No explicit stacklevel keyword argument found |
|
B029 |
except-with-empty-tuple |
Using except (): with an empty tuple does not handle/catch anything. Add exceptions to handle. |
|
B030 |
except-with-non-exception-classes |
except handlers should only be exception classes or tuples of exception classes |
|
B032 |
unintentional-type-annotation |
Possible unintentional type annotation (using : ). Did you mean to assign (using = )? |
|
B904 |
raise-without-from-inside-except |
Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling |
|
B905 |
zip-without-explicit-strict |
zip() without an explicit strict= parameter |
|
flake8-builtins (A)
For more, see flake8-builtins on PyPI.
flake8-commas (COM)
For more, see flake8-commas on PyPI.
Code |
Name |
Message |
Fix |
COM812 |
trailing-comma-missing |
Trailing comma missing |
🛠|
COM818 |
trailing-comma-on-bare-tuple-prohibited |
Trailing comma on bare tuple prohibited |
|
COM819 |
trailing-comma-prohibited |
Trailing comma prohibited |
🛠|
flake8-comprehensions (C4)
For more, see flake8-comprehensions on PyPI.
Code |
Name |
Message |
Fix |
C400 |
unnecessary-generator-list |
Unnecessary generator (rewrite as a list comprehension) |
🛠|
C401 |
unnecessary-generator-set |
Unnecessary generator (rewrite as a set comprehension) |
🛠|
C402 |
unnecessary-generator-dict |
Unnecessary generator (rewrite as a dict comprehension) |
🛠|
C403 |
unnecessary-list-comprehension-set |
Unnecessary list comprehension (rewrite as a set comprehension) |
🛠|
C404 |
unnecessary-list-comprehension-dict |
Unnecessary list comprehension (rewrite as a dict comprehension) |
🛠|
C405 |
unnecessary-literal-set |
Unnecessary {obj_type} literal (rewrite as a set literal) |
🛠|
C406 |
unnecessary-literal-dict |
Unnecessary {obj_type} literal (rewrite as a dict literal) |
🛠|
C408 |
unnecessary-collection-call |
Unnecessary {obj_type} call (rewrite as a literal) |
🛠|
C409 |
unnecessary-literal-within-tuple-call |
Unnecessary {literal} literal passed to tuple() (rewrite as a tuple literal) |
🛠|
C410 |
unnecessary-literal-within-list-call |
Unnecessary {literal} literal passed to list() (remove the outer call to list() ) |
🛠|
C411 |
unnecessary-list-call |
Unnecessary list call (remove the outer call to list() ) |
🛠|
C413 |
unnecessary-call-around-sorted |
Unnecessary {func} call around sorted() |
🛠|
C414 |
unnecessary-double-cast-or-process |
Unnecessary {inner} call within {outer}() |
🛠|
C415 |
unnecessary-subscript-reversal |
Unnecessary subscript reversal of iterable within {func}() |
|
C416 |
unnecessary-comprehension |
Unnecessary {obj_type} comprehension (rewrite using {obj_type}() ) |
🛠|
C417 |
unnecessary-map |
Unnecessary map usage (rewrite using a generator expression) |
🛠|
flake8-datetimez (DTZ)
For more, see flake8-datetimez on PyPI.
Code |
Name |
Message |
Fix |
DTZ001 |
call-datetime-without-tzinfo |
The use of datetime.datetime() without tzinfo argument is not allowed |
|
DTZ002 |
call-datetime-today |
The use of datetime.datetime.today() is not allowed, use datetime.datetime.now(tz=) instead |
|
DTZ003 |
call-datetime-utcnow |
The use of datetime.datetime.utcnow() is not allowed, use datetime.datetime.now(tz=) instead |
|
DTZ004 |
call-datetime-utcfromtimestamp |
The use of datetime.datetime.utcfromtimestamp() is not allowed, use datetime.datetime.fromtimestamp(ts, tz=) instead |
|
DTZ005 |
call-datetime-now-without-tzinfo |
The use of datetime.datetime.now() without tz argument is not allowed |
|
DTZ006 |
call-datetime-fromtimestamp |
The use of datetime.datetime.fromtimestamp() without tz argument is not allowed |
|
DTZ007 |
call-datetime-strptime-without-zone |
The use of datetime.datetime.strptime() without %z must be followed by .replace(tzinfo=) or .astimezone() |
|
DTZ011 |
call-date-today |
The use of datetime.date.today() is not allowed, use datetime.datetime.now(tz=).date() instead |
|
DTZ012 |
call-date-fromtimestamp |
The use of datetime.date.fromtimestamp() is not allowed, use datetime.datetime.fromtimestamp(ts, tz=).date() instead |
|
flake8-debugger (T10)
For more, see flake8-debugger on PyPI.
Code |
Name |
Message |
Fix |
T100 |
debugger |
Trace found: {name} used |
|
flake8-django (DJ)
For more, see flake8-django on PyPI.
flake8-errmsg (EM)
For more, see flake8-errmsg on PyPI.
flake8-executable (EXE)
For more, see flake8-executable on PyPI.
Code |
Name |
Message |
Fix |
EXE001 |
shebang-not-executable |
Shebang is present but file is not executable |
|
EXE002 |
shebang-missing-executable-file |
The file is executable but no shebang is present |
|
EXE003 |
shebang-python |
Shebang should contain python |
|
EXE004 |
shebang-whitespace |
Avoid whitespace before shebang |
🛠|
EXE005 |
shebang-newline |
Shebang should be at the beginning of the file |
|
flake8-implicit-str-concat (ISC)
For more, see flake8-implicit-str-concat on PyPI.
flake8-import-conventions (ICN)
For more, see flake8-import-conventions on GitHub.
For more, see flake8-logging-format on PyPI.
Code |
Name |
Message |
Fix |
G001 |
logging-string-format |
Logging statement uses string.format() |
|
G002 |
logging-percent-format |
Logging statement uses % |
|
G003 |
logging-string-concat |
Logging statement uses + |
|
G004 |
logging-f-string |
Logging statement uses f-string |
|
G010 |
logging-warn |
Logging statement uses warn instead of warning |
🛠|
G101 |
logging-extra-attr-clash |
Logging statement uses an extra field that clashes with a LogRecord field: {key} |
|
G201 |
logging-exc-info |
Logging .exception(...) should be used instead of .error(..., exc_info=True) |
|
G202 |
logging-redundant-exc-info |
Logging statement has redundant exc_info |
|
flake8-no-pep420 (INP)
For more, see flake8-no-pep420 on PyPI.
Code |
Name |
Message |
Fix |
INP001 |
implicit-namespace-package |
File {filename} is part of an implicit namespace package. Add an __init__.py . |
|
flake8-pie (PIE)
For more, see flake8-pie on PyPI.
Code |
Name |
Message |
Fix |
PIE790 |
unnecessary-pass |
Unnecessary pass statement |
🛠|
PIE794 |
dupe-class-field-definitions |
Class field {name} is defined multiple times |
🛠|
PIE796 |
prefer-unique-enums |
Enum contains duplicate value: {value} |
|
PIE800 |
unnecessary-spread |
Unnecessary spread ** |
|
PIE802 |
unnecessary-comprehension-any-all |
Unnecessary list comprehension. |
🛠|
PIE804 |
unnecessary-dict-kwargs |
Unnecessary dict kwargs |
|
PIE807 |
prefer-list-builtin |
Prefer list over useless lambda |
🛠|
PIE810 |
single-starts-ends-with |
Call {attr} once with a tuple |
🛠|
flake8-print (T20)
For more, see flake8-print on PyPI.
Code |
Name |
Message |
Fix |
T201 |
print-found |
print found |
|
T203 |
p-print-found |
pprint found |
|
flake8-pyi (PYI)
For more, see flake8-pyi on PyPI.
Code |
Name |
Message |
Fix |
PYI001 |
prefix-type-params |
Name of private {kind} must start with _ |
|
PYI006 |
bad-version-info-comparison |
Use < or >= for version info comparisons |
|
PYI007 |
unrecognized-platform-check |
Unrecognized sys.platform check |
|
PYI008 |
unrecognized-platform-name |
Unrecognized platform {platform} |
|
PYI009 |
pass-statement-stub-body |
Empty body should contain ... , not pass |
|
PYI010 |
non-empty-stub-body |
Function body must contain only ... |
|
PYI011 |
typed-argument-simple-defaults |
Only simple default values allowed for typed arguments |
🛠|
PYI014 |
argument-simple-defaults |
Only simple default values allowed for arguments |
|
PYI021 |
docstring-in-stub |
Docstrings should not be included in stubs |
|
PYI033 |
type-comment-in-stub |
Don't use type comments in stub file |
|
flake8-pytest-style (PT)
For more, see flake8-pytest-style on PyPI.
Code |
Name |
Message |
Fix |
PT001 |
incorrect-fixture-parentheses-style |
Use @pytest.fixture{expected_parens} over @pytest.fixture{actual_parens} |
🛠|
PT002 |
fixture-positional-args |
Configuration for fixture {function} specified via positional args, use kwargs |
|
PT003 |
extraneous-scope-function |
scope='function' is implied in @pytest.fixture() |
🛠|
PT004 |
missing-fixture-name-underscore |
Fixture {function} does not return anything, add leading underscore |
|
PT005 |
incorrect-fixture-name-underscore |
Fixture {function} returns a value, remove leading underscore |
|
PT006 |
parametrize-names-wrong-type |
Wrong name(s) type in @pytest.mark.parametrize , expected {expected} |
🛠|
PT007 |
parametrize-values-wrong-type |
Wrong values type in @pytest.mark.parametrize expected {values} of {row} |
|
PT008 |
patch-with-lambda |
Use return_value= instead of patching with lambda |
|
PT009 |
unittest-assertion |
Use a regular assert instead of unittest-style {assertion} |
🛠|
PT010 |
raises-without-exception |
set the expected exception in pytest.raises() |
|
PT011 |
raises-too-broad |
pytest.raises({exception}) is too broad, set the match parameter or use a more specific exception |
|
PT012 |
raises-with-multiple-statements |
pytest.raises() block should contain a single simple statement |
|
PT013 |
incorrect-pytest-import |
Found incorrect import of pytest, use simple import pytest instead |
|
PT015 |
assert-always-false |
Assertion always fails, replace with pytest.fail() |
|
PT016 |
fail-without-message |
No message passed to pytest.fail() |
|
PT017 |
assert-in-except |
Found assertion on exception {name} in except block, use pytest.raises() instead |
|
PT018 |
composite-assertion |
Assertion should be broken down into multiple parts |
🛠|
PT019 |
fixture-param-without-value |
Fixture {name} without value is injected as parameter, use @pytest.mark.usefixtures instead |
|
PT020 |
deprecated-yield-fixture |
@pytest.yield_fixture is deprecated, use @pytest.fixture |
|
PT021 |
fixture-finalizer-callback |
Use yield instead of request.addfinalizer |
|
PT022 |
useless-yield-fixture |
No teardown in fixture {name} , use return instead of yield |
🛠|
PT023 |
incorrect-mark-parentheses-style |
Use @pytest.mark.{mark_name}{expected_parens} over @pytest.mark.{mark_name}{actual_parens} |
🛠|
PT024 |
unnecessary-asyncio-mark-on-fixture |
pytest.mark.asyncio is unnecessary for fixtures |
🛠|
PT025 |
erroneous-use-fixtures-on-fixture |
pytest.mark.usefixtures has no effect on fixtures |
🛠|
PT026 |
use-fixtures-without-parameters |
Useless pytest.mark.usefixtures without parameters |
🛠|
flake8-quotes (Q)
For more, see flake8-quotes on PyPI.
flake8-raise (RSE)
For more, see flake8-raise on PyPI.
Code |
Name |
Message |
Fix |
RSE102 |
unnecessary-paren-on-raise-exception |
Unnecessary parentheses on raised exception |
🛠|
flake8-return (RET)
For more, see flake8-return on PyPI.
Code |
Name |
Message |
Fix |
RET501 |
unnecessary-return-none |
Do not explicitly return None in function if it is the only possible return value |
🛠|
RET502 |
implicit-return-value |
Do not implicitly return None in function able to return non-None value |
🛠|
RET503 |
implicit-return |
Missing explicit return at the end of function able to return non-None value |
🛠|
RET504 |
unnecessary-assign |
Unnecessary variable assignment before return statement |
|
RET505 |
superfluous-else-return |
Unnecessary {branch} after return statement |
|
RET506 |
superfluous-else-raise |
Unnecessary {branch} after raise statement |
|
RET507 |
superfluous-else-continue |
Unnecessary {branch} after continue statement |
|
RET508 |
superfluous-else-break |
Unnecessary {branch} after break statement |
|
flake8-self (SLF)
For more, see flake8-self on PyPI.
flake8-simplify (SIM)
For more, see flake8-simplify on PyPI.
Code |
Name |
Message |
Fix |
SIM101 |
duplicate-isinstance-call |
Multiple isinstance calls for {name} , merge into a single call |
🛠|
SIM102 |
collapsible-if |
Use a single if statement instead of nested if statements |
🛠|
SIM103 |
needless-bool |
Return the condition {condition} directly |
🛠|
SIM105 |
use-contextlib-suppress |
Use contextlib.suppress({exception}) instead of try-except-pass |
|
SIM107 |
return-in-try-except-finally |
Don't use return in try /except and finally |
|
SIM108 |
use-ternary-operator |
Use ternary operator {contents} instead of if -else -block |
🛠|
SIM109 |
compare-with-tuple |
Use {replacement} instead of multiple equality comparisons |
🛠|
SIM110 |
reimplemented-builtin |
Use {repl} instead of for loop |
🛠|
SIM112 |
use-capital-environment-variables |
Use capitalized environment variable {expected} instead of {original} |
🛠|
SIM114 |
if-with-same-arms |
Combine if branches using logical or operator |
|
SIM115 |
open-file-with-context-handler |
Use context handler for opening files |
|
SIM116 |
manual-dict-lookup |
Use a dictionary instead of consecutive if statements |
|
SIM117 |
multiple-with-statements |
Use a single with statement with multiple contexts instead of nested with statements |
🛠|
SIM118 |
key-in-dict |
Use {key} in {dict} instead of {key} in {dict}.keys() |
🛠|
SIM201 |
negate-equal-op |
Use {left} != {right} instead of not {left} == {right} |
🛠|
SIM202 |
negate-not-equal-op |
Use {left} == {right} instead of not {left} != {right} |
🛠|
SIM208 |
double-negation |
Use {expr} instead of not (not {expr}) |
🛠|
SIM210 |
if-expr-with-true-false |
Use bool({expr}) instead of True if {expr} else False |
🛠|
SIM211 |
if-expr-with-false-true |
Use not {expr} instead of False if {expr} else True |
🛠|
SIM212 |
if-expr-with-twisted-arms |
Use {expr_else} if {expr_else} else {expr_body} instead of {expr_body} if not {expr_else} else {expr_else} |
🛠|
SIM220 |
expr-and-not-expr |
Use False instead of {name} and not {name} |
🛠|
SIM221 |
expr-or-not-expr |
Use True instead of {name} or not {name} |
🛠|
SIM222 |
expr-or-true |
Use True instead of ... or True |
🛠|
SIM223 |
expr-and-false |
Use False instead of ... and False |
🛠|
SIM300 |
yoda-conditions |
Yoda conditions are discouraged, use {suggestion} instead |
🛠|
SIM401 |
dict-get-with-default |
Use {contents} instead of an if block |
🛠|
flake8-tidy-imports (TID)
For more, see flake8-tidy-imports on PyPI.
Code |
Name |
Message |
Fix |
TID251 |
banned-api |
{name} is banned: |
|
TID252 |
relative-imports |
Relative imports from parent modules are banned |
🛠|
flake8-type-checking (TCH)
For more, see flake8-type-checking on PyPI.
Code |
Name |
Message |
Fix |
TCH001 |
typing-only-first-party-import |
Move application import {} into a type-checking block |
|
TCH002 |
typing-only-third-party-import |
Move third-party import {} into a type-checking block |
|
TCH003 |
typing-only-standard-library-import |
Move standard library import {} into a type-checking block |
|
TCH004 |
runtime-import-in-type-checking-block |
Move import {} out of type-checking block. Import is used for more than type hinting. |
|
TCH005 |
empty-type-checking-block |
Found empty type-checking block |
🛠|
flake8-unused-arguments (ARG)
For more, see flake8-unused-arguments on PyPI.
Code |
Name |
Message |
Fix |
ARG001 |
unused-function-argument |
Unused function argument: {name} |
|
ARG002 |
unused-method-argument |
Unused method argument: {name} |
|
ARG003 |
unused-class-method-argument |
Unused class method argument: {name} |
|
ARG004 |
unused-static-method-argument |
Unused static method argument: {name} |
|
ARG005 |
unused-lambda-argument |
Unused lambda argument: {name} |
|
flake8-use-pathlib (PTH)
For more, see flake8-use-pathlib on PyPI.
Code |
Name |
Message |
Fix |
PTH100 |
pathlib-abspath |
os.path.abspath() should be replaced by Path.resolve() |
|
PTH101 |
pathlib-chmod |
os.chmod() should be replaced by Path.chmod() |
|
PTH102 |
pathlib-mkdir |
os.mkdir() should be replaced by Path.mkdir() |
|
PTH103 |
pathlib-makedirs |
os.makedirs() should be replaced by Path.mkdir(parents=True) |
|
PTH104 |
pathlib-rename |
os.rename() should be replaced by Path.rename() |
|
PTH105 |
pathlib-replace |
os.replace() should be replaced by Path.replace() |
|
PTH106 |
pathlib-rmdir |
os.rmdir() should be replaced by Path.rmdir() |
|
PTH107 |
pathlib-remove |
os.remove() should be replaced by Path.unlink() |
|
PTH108 |
pathlib-unlink |
os.unlink() should be replaced by Path.unlink() |
|
PTH109 |
pathlib-getcwd |
os.getcwd() should be replaced by Path.cwd() |
|
PTH110 |
pathlib-exists |
os.path.exists() should be replaced by Path.exists() |
|
PTH111 |
pathlib-expanduser |
os.path.expanduser() should be replaced by Path.expanduser() |
|
PTH112 |
pathlib-is-dir |
os.path.isdir() should be replaced by Path.is_dir() |
|
PTH113 |
pathlib-is-file |
os.path.isfile() should be replaced by Path.is_file() |
|
PTH114 |
pathlib-is-link |
os.path.islink() should be replaced by Path.is_symlink() |
|
PTH115 |
pathlib-readlink |
os.readlink() should be replaced by Path.readlink() |
|
PTH116 |
pathlib-stat |
os.stat() should be replaced by Path.stat() , Path.owner() , or Path.group() |
|
PTH117 |
pathlib-is-abs |
os.path.isabs() should be replaced by Path.is_absolute() |
|
PTH118 |
pathlib-join |
os.path.join() should be replaced by Path with / operator |
|
PTH119 |
pathlib-basename |
os.path.basename() should be replaced by Path.name |
|
PTH120 |
pathlib-dirname |
os.path.dirname() should be replaced by Path.parent |
|
PTH121 |
pathlib-samefile |
os.path.samefile() should be replaced by Path.samefile() |
|
PTH122 |
pathlib-splitext |
os.path.splitext() should be replaced by Path.suffix |
|
PTH123 |
pathlib-open |
open() should be replaced by Path.open() |
|
PTH124 |
pathlib-py-path |
py.path is in maintenance mode, use pathlib instead |
|
eradicate (ERA)
For more, see eradicate on PyPI.
pandas-vet (PD)
For more, see pandas-vet on PyPI.
Code |
Name |
Message |
Fix |
PD002 |
use-of-inplace-argument |
inplace=True should be avoided; it has inconsistent behavior |
🛠|
PD003 |
use-of-dot-is-null |
.isna is preferred to .isnull ; functionality is equivalent |
|
PD004 |
use-of-dot-not-null |
.notna is preferred to .notnull ; functionality is equivalent |
|
PD007 |
use-of-dot-ix |
.ix is deprecated; use more explicit .loc or .iloc |
|
PD008 |
use-of-dot-at |
Use .loc instead of .at . If speed is important, use numpy. |
|
PD009 |
use-of-dot-iat |
Use .iloc instead of .iat . If speed is important, use numpy. |
|
PD010 |
use-of-dot-pivot-or-unstack |
.pivot_table is preferred to .pivot or .unstack ; provides same functionality |
|
PD011 |
use-of-dot-values |
Use .to_numpy() instead of .values |
|
PD012 |
use-of-dot-read-table |
.read_csv is preferred to .read_table ; provides same functionality |
|
PD013 |
use-of-dot-stack |
.melt is preferred to .stack ; provides same functionality |
|
PD015 |
use-of-pd-merge |
Use .merge method instead of pd.merge function. They have equivalent functionality. |
|
PD901 |
df-is-a-bad-variable-name |
df is a bad variable name. Be kinder to your future self. |
|
pygrep-hooks (PGH)
For more, see pygrep-hooks on GitHub.
Code |
Name |
Message |
Fix |
PGH001 |
no-eval |
No builtin eval() allowed |
|
PGH002 |
deprecated-log-warn |
warn is deprecated in favor of warning |
|
PGH003 |
blanket-type-ignore |
Use specific rule codes when ignoring type issues |
|
PGH004 |
blanket-noqa |
Use specific rule codes when using noqa |
|
Pylint (PL)
For more, see Pylint on PyPI.
Convention (PLC)
Code |
Name |
Message |
Fix |
PLC0414 |
useless-import-alias |
Import alias does not rename original package |
🛠|
PLC1901 |
compare-to-empty-string |
{} can be simplified to {} as an empty string is falsey |
|
PLC3002 |
unnecessary-direct-lambda-call |
Lambda expression called directly. Execute the expression inline instead. |
|
Error (PLE)
Code |
Name |
Message |
Fix |
PLE0100 |
yield-in-init |
__init__ method is a generator |
|
PLE0101 |
return-in-init |
Explicit return in __init__ |
|
PLE0116 |
continue-in-finally |
continue not supported inside finally clause |
|
PLE0117 |
nonlocal-without-binding |
Nonlocal name {name} found without binding |
|
PLE0118 |
used-prior-global-declaration |
Name {name} is used prior to global declaration on line |
|
PLE0604 |
invalid-all-object |
Invalid object in __all__ , must contain only strings |
|
PLE0605 |
invalid-all-format |
Invalid format for __all__ , must be tuple or list |
|
PLE1142 |
await-outside-async |
await should be used within an async function |
|
PLE1205 |
logging-too-many-args |
Too many arguments for logging format string |
|
PLE1206 |
logging-too-few-args |
Not enough arguments for logging format string |
|
PLE1307 |
bad-string-format-type |
Format type does not match argument type |
|
PLE1310 |
bad-str-strip-call |
String {strip} call contains duplicate characters (did you mean {removal} ?) |
|
PLE1507 |
invalid-envvar-value |
Invalid type for initial os.getenv argument; expected str |
|
PLE2502 |
bidirectional-unicode |
Contains control characters that can permit obfuscated code |
|
PLE2510 |
invalid-character-backspace |
Invalid unescaped character backspace, use "\b" instead |
🛠|
PLE2512 |
invalid-character-sub |
Invalid unescaped character SUB, use "\x1A" instead |
🛠|
PLE2513 |
invalid-character-esc |
Invalid unescaped character ESC, use "\x1B" instead |
🛠|
PLE2514 |
invalid-character-nul |
Invalid unescaped character NUL, use "\0" instead |
🛠|
PLE2515 |
invalid-character-zero-width-space |
Invalid unescaped character zero-width-space, use "\u200B" instead |
🛠|
Refactor (PLR)
Code |
Name |
Message |
Fix |
PLR0133 |
comparison-of-constant |
Two constants compared in a comparison, consider replacing {left_constant} {op} {right_constant} |
|
PLR0206 |
property-with-parameters |
Cannot have defined parameters for properties |
|
PLR0402 |
consider-using-from-import |
Use from {module} import {name} in lieu of alias |
🛠|
PLR0911 |
too-many-return-statements |
Too many return statements ({returns} > {max_returns}) |
|
PLR0912 |
too-many-branches |
Too many branches ({branches} > {max_branches}) |
|
PLR0913 |
too-many-arguments |
Too many arguments to function call ({c_args} > {max_args}) |
|
PLR0915 |
too-many-statements |
Too many statements ({statements} > {max_statements}) |
|
PLR1701 |
consider-merging-isinstance |
Merge these isinstance calls: isinstance({obj}, ({types})) |
|
PLR1711 |
useless-return |
Useless return statement at end of function |
🛠|
PLR1722 |
consider-using-sys-exit |
Use sys.exit() instead of {name} |
🛠|
PLR2004 |
magic-value-comparison |
Magic value used in comparison, consider replacing {value} with a constant variable |
|
PLR5501 |
collapsible-else-if |
Consider using elif instead of else then if to remove one indentation level |
|
Warning (PLW)
Code |
Name |
Message |
Fix |
PLW0120 |
useless-else-on-loop |
else clause on loop without a break statement; remove the else and de-indent all the code inside it |
|
PLW0602 |
global-variable-not-assigned |
Using global for {name} but no assignment is done |
|
PLW0603 |
global-statement |
Using the global statement to update {name} is discouraged |
|
PLW1508 |
invalid-envvar-default |
Invalid type for environment variable default; expected str or None |
|
PLW2901 |
redefined-loop-name |
Outer {outer_kind} variable {name} overwritten by inner {inner_kind} target |
|
tryceratops (TRY)
For more, see tryceratops on PyPI.
Code |
Name |
Message |
Fix |
TRY002 |
raise-vanilla-class |
Create your own exception |
|
TRY003 |
raise-vanilla-args |
Avoid specifying long messages outside the exception class |
|
TRY004 |
prefer-type-error |
Prefer TypeError exception for invalid type |
|
TRY200 |
reraise-no-cause |
Use raise from to specify exception cause |
|
TRY201 |
verbose-raise |
Use raise without specifying exception name |
|
TRY300 |
try-consider-else |
Consider moving this statement to an else block |
|
TRY301 |
raise-within-try |
Abstract raise to an inner function |
|
TRY400 |
error-instead-of-exception |
Use logging.exception instead of logging.error |
|
TRY401 |
verbose-log-message |
Redundant exception object included in logging.exception call |
|
NumPy-specific rules (NPY)
Ruff-specific rules (RUF)
Code |
Name |
Message |
Fix |
RUF001 |
ambiguous-unicode-character-string |
String contains ambiguous unicode character {confusable} (did you mean {representant} ?) |
🛠|
RUF002 |
ambiguous-unicode-character-docstring |
Docstring contains ambiguous unicode character {confusable} (did you mean {representant} ?) |
🛠|
RUF003 |
ambiguous-unicode-character-comment |
Comment contains ambiguous unicode character {confusable} (did you mean {representant} ?) |
🛠|
RUF005 |
unpack-instead-of-concatenating-to-collection-literal |
Consider {expr} instead of concatenation |
🛠|
RUF006 |
asyncio-dangling-task |
Store a reference to the return value of asyncio.{method} |
|
RUF007 |
pairwise-over-zipped |
Prefer itertools.pairwise() over zip() when iterating over successive pairs |
|
RUF100 |
unused-noqa |
Unused noqa directive |
🛠|