Consistency

These checks limit Python’s inconsistencies.

We can do the same things differently in Python. For example, there are three ways to format a string. There are several ways to write the same number.

We like our code to be consistent. It is easier to work with your code base if you follow these rules.

So, we choose a single way to do things. It does not mean that we choose the best way to do it. But, we value consistency more than being 100% right and we are ready to suffer all trade-offs that might come.

Once again, these rules are highly subjective, but we love them.

Summary

LocalFolderImportViolation

WPS300 — Forbid imports relative to the current folder.

DottedRawImportViolation

WPS301 — Forbid imports like import os.path.

UnicodeStringViolation

WPS302 — Forbid u string prefix.

UnderscoredNumberViolation

WPS303 — Forbid underscores (_) in numbers.

PartialFloatViolation

WPS304 — Forbid partial floats like .05 or 23..

FormattedStringViolation

WPS305 — Forbid f strings.

ExplicitObjectBaseClassViolation

WPS306 — Forbid writing explicit object base class.

MultipleIfsInComprehensionViolation

WPS307 — Forbid multiple if statements inside list comprehensions.

ConstantCompareViolation

WPS308 — Forbid comparing between two literals.

CompareOrderViolation

WPS309 — Forbid comparisons where the argument doesn't come first.

BadNumberSuffixViolation

WPS310 — Forbid uppercase X, O, B, and E in numbers.

MultipleInCompareViolation

WPS311 — Forbid comparisons with multiple in checks.

UselessCompareViolation

WPS312 — Forbid comparisons of a variable to itself.

MissingSpaceBetweenKeywordAndParenViolation

WPS313 — Enforce separation of parenthesis from keywords with spaces.

ConstantConditionViolation

WPS314 — Forbid using if statements that use invalid conditionals.

ObjectInBaseClassesListViolation

WPS315 — Forbid extra object in parent classes list.

MultipleContextManagerAssignmentsViolation

WPS316 — Forbid multiple assignment targets for context managers.

ParametersIndentationViolation

WPS317 — Forbid incorrect indentation for parameters.

ExtraIndentationViolation

WPS318 — Forbid extra indentation.

WrongBracketPositionViolation

WPS319 — Forbid brackets in the wrong position.

MultilineFunctionAnnotationViolation

WPS320 — Forbid multi-line function type annotations.

UppercaseStringModifierViolation

WPS321 — Forbid uppercase string modifiers.

WrongMultilineStringViolation

WPS322 — Forbid triple quotes for singleline strings.

ModuloStringFormatViolation

WPS323 — Forbid % formatting on strings.

InconsistentReturnViolation

WPS324 — Enforce consistent return statements.

InconsistentYieldViolation

WPS325 — Enforce consistent yield statements.

ImplicitStringConcatenationViolation

WPS326 — Forbid implicit string concatenation.

UselessContinueViolation

WPS327 — Forbid meaningless continue in loops.

UselessNodeViolation

WPS328 — Forbid meaningless nodes.

UselessExceptCaseViolation

WPS329 — Forbid meaningless except cases.

UselessOperatorsViolation

WPS330 — Forbid unnecessary operators in your code.

InconsistentReturnVariableViolation

WPS331 — Forbid local variables that are only used in return statements.

WalrusViolation

WPS332 — Forbid walrus operator.

ImplicitComplexCompareViolation

WPS333 — Forbid implicit complex comparison expressions.

ReversedComplexCompareViolation

WPS334 — Forbid reversed order complex comparison expressions.

WrongLoopIterTypeViolation

WPS335 — Forbid wrong for loop iter targets.

ExplicitStringConcatViolation

WPS336 — Forbid explicit string concatanation in favour of .format method.

MultilineConditionsViolation

WPS337 — Forbid multiline conditions.

WrongMethodOrderViolation

WPS338 — Forbid incorrect order of methods inside a class.

NumberWithMeaninglessZeroViolation

WPS339 — Forbid meaningless zeros.

PositiveExponentViolation

WPS340 — Forbid extra + signs in the exponent.

WrongHexNumberCaseViolation

WPS341 — Forbid letters as hex numbers.

ImplicitRawStringViolation

WPS342 — Forbid \\ escape sequences inside regular strings.

BadComplexNumberSuffixViolation

WPS343 — Forbid uppercase complex number suffix.

ZeroDivisionViolation

WPS344 — Forbid explicit division (or modulo) by zero.

MeaninglessNumberOperationViolation

WPS345 — Forbid meaningless math operations with 0 and 1.

OperationSignNegationViolation

WPS346 — Forbid double minus operations.

VagueImportViolation

WPS347 — Forbid imports that may cause confusion outside of the module.

LineStartsWithDotViolation

WPS348 — Forbid starting lines with a dot.

RedundantSubscriptViolation

WPS349 — Forbid redundant components in a subscript's slice.

AugmentedAssignPatternViolation

WPS350 — Enforce using augmented assign pattern.

UnnecessaryLiteralsViolation

WPS351 — Forbid unnecessary literals in your code.

MultilineLoopViolation

WPS352 — Forbid multiline loops.

IncorrectYieldFromTargetViolation

WPS353 — Forbid yield from with several nodes.

ConsecutiveYieldsViolation

WPS354 — Forbid consecutive yield expressions.

BracketBlankLineViolation

WPS355 — Forbid useless blank lines before and after brackets.

IterableUnpackingViolation

WPS356 — Forbid unnecessary iterable unpacking.

LineCompriseCarriageReturnViolation

WPS357 — Forbid using \r (carriage return) in line breaks.

FloatZeroViolation

WPS358 — Forbid using float zeros: 0.0.

UnpackingIterableToListViolation

WPS359 — Forbids to unpack iterable objects to lists.

RawStringNotNeededViolation

WPS360 — Forbid the use of raw strings when there is no backslash in the string.

InconsistentComprehensionViolation

WPS361 — Forbids inconsistent newlines in comprehensions.

AssignToSliceViolation

WPS362 — Forbid assignment to a subscript slice.

Consistency checks

class LocalFolderImportViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS300 — Forbid imports relative to the current folder.

Reasoning:

We should pick one style and stick to it. We have decided to use the explicit one.

Solution:

Refactor your imports to use the absolute path.

Example:

# Correct:
from my_package.version import get_version

# Wrong:
from .version import get_version
from ..drivers import MySQLDriver

Added in version 0.1.0.

error_template: ClassVar[str] = 'Found local folder import'
code: ClassVar[int] = 300
full_code: ClassVar[str] = 'WPS300'
summary: ClassVar[str] = 'Forbid imports relative to the current folder.'
class DottedRawImportViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS301 — Forbid imports like import os.path.

Reasoning:

There are too many ways to import something. We should pick one style and stick to it. We have decided to use the readable one.

Solution:

Refactor your import statement.

Example:

# Correct:
from os import path

# Wrong:
import os.path

Added in version 0.1.0.

error_template: ClassVar[str] = 'Found dotted raw import: {0}'
code: ClassVar[int] = 301
full_code: ClassVar[str] = 'WPS301'
summary: ClassVar[str] = 'Forbid imports like ``import os.path``.'
class UnicodeStringViolation(node, text=None, baseline=None)[source]

Bases: TokenizeViolation

WPS302 — Forbid u string prefix.

Reasoning:

We haven’t needed this prefix since python2, but it is still possible to find it in a codebase.

Solution:

Remove this prefix.

Example:

# Correct:
nickname = 'sobolevn'
file_contents = b'aabbcc'

# Wrong:
nickname = u'sobolevn'

Added in version 0.1.0.

code: ClassVar[int] = 302
error_template: ClassVar[str] = 'Found unicode string prefix: {0}'
full_code: ClassVar[str] = 'WPS302'
summary: ClassVar[str] = 'Forbid ``u`` string prefix.'
class UnderscoredNumberViolation(node, text=None, baseline=None)[source]

Bases: TokenizeViolation

WPS303 — Forbid underscores (_) in numbers.

Reasoning:

It is possible to write 1000 in three different ways: 1_000, 10_00, and 100_0. And it would be still the same number. Count how many ways there are to write bigger numbers. Currently, it all depends on the cultural habits of the author. We enforce a single way to write numbers: without the underscore.

Solution:

Numbers should be written as numbers: 1000. If you have a very big number with a lot of zeros, use multiplication.

Example:

# Correct:
phone = 88313443
million = 1000000

# Wrong:
phone = 8_83_134_43
million = 100_00_00

Added in version 0.1.0.

code: ClassVar[int] = 303
error_template: ClassVar[str] = 'Found underscored number: {0}'
full_code: ClassVar[str] = 'WPS303'
summary: ClassVar[str] = 'Forbid underscores (``_``) in numbers.'
class PartialFloatViolation(node, text=None, baseline=None)[source]

Bases: TokenizeViolation

WPS304 — Forbid partial floats like .05 or 23..

Reasoning:

Partial numbers are hard to read and they can be confused with other numbers. For example, it is really easy to confuse 0.5 and .05 when reading through the source code.

Solution:

Use full versions with leading and trailing zeros.

Example:

# Correct:
half = 0.5
ten_float = 10.0

# Wrong:
half = .5
ten_float = 10.

Added in version 0.1.0.

code: ClassVar[int] = 304
error_template: ClassVar[str] = 'Found partial float: {0}'
full_code: ClassVar[str] = 'WPS304'
summary: ClassVar[str] = 'Forbid partial floats like ``.05`` or ``23.``.'
class FormattedStringViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS305 — Forbid f strings.

Reasoning:

f strings implicitly rely on the context around them. Imagine that you have a string that breaks when you move it two lines above. That’s not how a string should behave. Also, they promote a bad practice: putting your logic inside the template. Moreover, they do two things at once: declare a template and format it in a single action.

Solution:

Use .format() with indexed params instead.

Example:

# Correct:
'Result is: {0}'.format(2 + 2)
'Hey {user}! How are you?'.format(user='sobolevn')

# Wrong:
f'Result is: {2 + 2}'

Added in version 0.1.0.

error_template: ClassVar[str] = 'Found `f` string'
code: ClassVar[int] = 305
full_code: ClassVar[str] = 'WPS305'
summary: ClassVar[str] = 'Forbid ``f`` strings.'
class ExplicitObjectBaseClassViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS306 — Forbid writing explicit object base class.

Reasoning:

Adding object base class does not have any effect in most cases. However, PEP695 adds new syntax to define classes: class Some[T]: which is equivalent to: class Some(Generic[T]):. If object is added to class Some[T](object): it will be a runtime error: it won’t be possible to create a proper MRO.

We don’t want to promote feature that can cause troubles.

This feature also has some legacy Python2 connotations.

Solution:

Remove object base class.

Example:

# Correct:
class Some: ...

# Wrong:
class Some(object): ...

Added in version 0.1.0.

Changed in version 0.19.0: Now the rule is inverted: we require no explicit object base class. See PEP695 for extra reasoning.

error_template: ClassVar[str] = 'Found explicit `object` base class: {0}'
code: ClassVar[int] = 306
full_code: ClassVar[str] = 'WPS306'
summary: ClassVar[str] = 'Forbid writing explicit `object` base class.'
class MultipleIfsInComprehensionViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS307 — Forbid multiple if statements inside list comprehensions.

Reasoning:

It is very hard to read multiple if statements inside a list comprehension. Since it is even hard to tell all of them should pass or fail.

Solution:

Use a single if statement inside list comprehensions. Use filter() if you have complicated logic.

Example:

# Correct:
nodes = [node for node in html if node not in {'b', 'i'}]

# Wrong:
nodes = [node for node in html if node != 'b' if node != 'i']

Added in version 0.1.0.

error_template: ClassVar[str] = 'Found list comprehension with multiple `if`s'
code: ClassVar[int] = 307
full_code: ClassVar[str] = 'WPS307'
summary: ClassVar[str] = 'Forbid multiple ``if`` statements inside list comprehensions.'
class ConstantCompareViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS308 — Forbid comparing between two literals.

Reasoning:

When two constants are compared it is typically an indication of a mistake, since the Boolean value of the comparison, will always be the same.

Solution:

Remove the constant comparison and any associated dead code.

Example:

# Correct:
do_something_else()

# Wrong:
if 60 * 60 < 1000:
    do_something()
else:
    do_something_else()

Added in version 0.3.0.

error_template: ClassVar[str] = 'Found constant comparison'
code: ClassVar[int] = 308
full_code: ClassVar[str] = 'WPS308'
summary: ClassVar[str] = 'Forbid comparing between two literals.'
class CompareOrderViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS309 — Forbid comparisons where the argument doesn’t come first.

Reasoning:

It is hard to read the code when you have to shuffle the ordering of the arguments all the time. Bring consistency to the comparison!

Solution:

Refactor your comparison expression, place the argument first.

Example:

# Correct:
if some_x > 3:
if 3 < some_x < 10:

# Wrong:
if 3 < some_x:

Added in version 0.3.0.

error_template: ClassVar[str] = 'Found reversed compare order'
code: ClassVar[int] = 309
full_code: ClassVar[str] = 'WPS309'
summary: ClassVar[str] = "Forbid comparisons where the argument doesn't come first."
class BadNumberSuffixViolation(node, text=None, baseline=None)[source]

Bases: TokenizeViolation

WPS310 — Forbid uppercase X, O, B, and E in numbers.

Reasoning:

Octal, hex, binary and scientific notation suffixes could be written in two possible notations: lowercase and uppercase which brings confusion and decreases code consistency and readability. We enforce a single way to write numbers with suffixes: suffix with lowercase chars.

Solution:

Octal, hex, binary and scientific notation suffixes in numbers should be written in lowercase.

Example:

# Correct:
hex_number = 0xFF
octal_number = 0o11
binary_number = 0b1001
number_with_scientific_notation = 1.5e+10

# Wrong:
hex_number = 0XFF
octal_number = 0O11
binary_number = 0B1001
number_with_scientific_notation = 1.5E+10

Added in version 0.3.0.

error_template: ClassVar[str] = 'Found bad number suffix: {0}'
code: ClassVar[int] = 310
full_code: ClassVar[str] = 'WPS310'
summary: ClassVar[str] = 'Forbid uppercase ``X``, ``O``, ``B``, and ``E`` in numbers.'
class MultipleInCompareViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS311 — Forbid comparisons with multiple in checks.

Reasoning:

Using multiple in checks is unreadable.

Solution:

Refactor your comparison expression to use several and conditions or separate if statements in cases where it is appropriate.

Example:

# Correct:
if item in bucket and bucket in master_list_of_buckets:
if x_coord not in line and line not in square:

# Wrong:
if item in bucket in master_list_of_buckets:
if x_cord not in line not in square:

Added in version 0.3.0.

Changed in version 0.10.0.

error_template: ClassVar[str] = 'Found multiple `in` compares'
code: ClassVar[int] = 311
full_code: ClassVar[str] = 'WPS311'
summary: ClassVar[str] = 'Forbid comparisons with multiple ``in`` checks.'
class UselessCompareViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS312 — Forbid comparisons of a variable to itself.

Reasoning:

When a variable is compared to itself, it is typically an indication of a mistake since the Boolean value of the comparison will always be the same.

Solution:

Remove the comparison and any associated dead code.

Example:

# Correct:
do_something()

# Wrong:
if a < a:
    do_something()
else:
    do_something_else()

Added in version 0.3.0.

error_template: ClassVar[str] = 'Found comparison of a variable to itself'
code: ClassVar[int] = 312
full_code: ClassVar[str] = 'WPS312'
summary: ClassVar[str] = 'Forbid comparisons of a variable to itself.'
class MissingSpaceBetweenKeywordAndParenViolation(node, text=None, baseline=None)[source]

Bases: TokenizeViolation

WPS313 — Enforce separation of parenthesis from keywords with spaces.

Reasoning:

Some people use return and yield keywords as functions. The same happened to good old print in Python2.

Solution:

Insert space symbol between the keyword and opening parenthesis.

Example:

# Correct:
def func():
    a = 1
    del (a, b)
    yield (1, 2, 3)

# Wrong:
def func():
    a = 1
    b = 2
    del(a, b)
    yield(1, 2, 3)

Added in version 0.3.0.

error_template: ClassVar[str] = 'Found parenthesis immediately after a keyword'
code: ClassVar[int] = 313
full_code: ClassVar[str] = 'WPS313'
summary: ClassVar[str] = 'Enforce separation of parenthesis from keywords with spaces.'
class ConstantConditionViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS314 — Forbid using if statements that use invalid conditionals.

Reasoning:

When invalid conditional arguments are used it is typically an indication of a mistake, since the value of the conditional result will always be the same.

Solution:

Remove the conditional and any associated dead code.

Example:

# Correct:
if value is True: ...

# Wrong:
if True: ...

Added in version 0.3.0.

error_template: ClassVar[str] = 'Found conditional that always evaluates the same'
code: ClassVar[int] = 314
full_code: ClassVar[str] = 'WPS314'
summary: ClassVar[str] = 'Forbid using ``if`` statements that use invalid conditionals.'
class ObjectInBaseClassesListViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS315 — Forbid extra object in parent classes list.

Reasoning:

We should allow object only when we explicitly use it as a single parent class. When there is another class or there are multiple parents - we should not allow it for the consistency reasons.

Solution:

Remove extra object parent class from the list.

Example:

# Correct:
class SomeClassName: ...
class SomeClassName(FirstParentClass, SecondParentClass): ...

# Wrong:
class SomeClassName(FirstParentClass, SecondParentClass, object): ...

Added in version 0.3.0.

error_template: ClassVar[str] = 'Found extra `object` in parent classes list: {0}'
code: ClassVar[int] = 315
full_code: ClassVar[str] = 'WPS315'
summary: ClassVar[str] = 'Forbid extra ``object`` in parent classes list.'
class MultipleContextManagerAssignmentsViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS316 — Forbid multiple assignment targets for context managers.

Reasoning:

It is hard to distinguish whether as should unpack into a tuple or if we are just using two context managers.

Solution:

Use several context managers or explicit brackets.

Example:

# Correct:
with open('') as first:
    with second:
        ...

with some_context as (first, second):
    ...

# Wrong:
with open('') as first, second:
    ...

Added in version 0.6.0.

error_template: ClassVar[str] = 'Found context manager with too many assignments'
code: ClassVar[int] = 316
full_code: ClassVar[str] = 'WPS316'
summary: ClassVar[str] = 'Forbid multiple assignment targets for context managers.'
class ParametersIndentationViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS317 — Forbid incorrect indentation for parameters.

Reasoning:

It is really easy to spoil your perfect, readable code with incorrect multi-line parameters indentation. Since it is really easy to style them in any of 100 possible ways. We enforce a strict rule about how it is possible to write these multi-line parameters.

Solution:

Use consistent multi-line parameters indentation.

Example:

# Correct:
def my_function(arg1, arg2, arg3) -> None:
    return None

print(1, 2, 3, 4, 5, 6)

def my_function(
    arg1, arg2, arg3,
) -> None:
    return None

print(
    1, 2, 3, 4, 5, 6,
)

def my_function(
    arg1,
    arg2,
    arg3,
) -> None:
    return None

print(
    first_variable,
    2,
    third_value,
    4,
    5,
    last_item,
)

# Special case:

print('some text', 'description', [
    first_variable,
    second_variable,
    third_variable,
    last_item,
], end='')

# Correct complex case:

@pytest.mark.parametrize(('boolean_arg', 'string_arg'), [
     (True, "string"),
     (False, "another string"),
])

Everything else is considered a violation. This rule checks: lists, sets, tuples, dicts, calls, functions, methods, and classes.

Added in version 0.6.0.

error_template: ClassVar[str] = 'Found incorrect multi-line parameters'
code: ClassVar[int] = 317
full_code: ClassVar[str] = 'WPS317'
summary: ClassVar[str] = 'Forbid incorrect indentation for parameters.'
class ExtraIndentationViolation(node, text=None, baseline=None)[source]

Bases: TokenizeViolation

WPS318 — Forbid extra indentation.

Reasoning:

You can use extra indentation for lines of code. Python allows you to do that in case you want to keep the indentation level equal for this specific node, but that’s insane!

Solution:

We should stick to 4 spaces for an indentation block. Each next block level should be indented by just 4 extra spaces.

Example:

# Correct:
def test():
    print('test')

# Wrong:
def test():
            print('test')

This rule is consistent with the “Vertical Hanging Indent” option for multi_line_output setting of isort. To avoid conflicting rules, you should set multi_line_output = 3 in the isort settings.

Added in version 0.6.0.

error_template: ClassVar[str] = 'Found extra indentation'
code: ClassVar[int] = 318
full_code: ClassVar[str] = 'WPS318'
summary: ClassVar[str] = 'Forbid extra indentation.'
class WrongBracketPositionViolation(node, text=None, baseline=None)[source]

Bases: TokenizeViolation

WPS319 — Forbid brackets in the wrong position.

Reasoning:

You can do bizarre things with bracket positioning in python. We require all brackets to be consistent.

Solution:

Place bracket on the same line, in case of a single line expression. Or place the bracket on a new line in case of a multi-line expression.

Example:

# Correct:
print([
    1, 2, 3,
])

print(
    1,
    2,
)

def _annotate_brackets(
    tokens: List[tokenize.TokenInfo],
) -> TokenLines:
    ...

# Wrong:
print([
    1, 2, 3],
)

print(
    1,
    2)

def _annotate_brackets(
    tokens: List[tokenize.TokenInfo]) -> TokenLines:
    ...

We check round, square, and curly brackets.

Added in version 0.6.0.

error_template: ClassVar[str] = 'Found bracket in wrong position'
code: ClassVar[int] = 319
full_code: ClassVar[str] = 'WPS319'
summary: ClassVar[str] = 'Forbid brackets in the wrong position.'
class MultilineFunctionAnnotationViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS320 — Forbid multi-line function type annotations.

Reasoning:

Functions with multi-line type annotations are unreadable.

Solution:

Use type annotations that fit into a single line to annotate functions. If your annotation is too long, then use type aliases.

Example:

# Correct:
def create_list(length: int) -> List[int]:
    ...

# Wrong:
def create_list(length: int) -> List[
    int,
]:
    ...

This rule checks argument and return type annotations.

Added in version 0.6.0.

error_template: ClassVar[str] = 'Found multi-line function type annotation'
code: ClassVar[int] = 320
full_code: ClassVar[str] = 'WPS320'
summary: ClassVar[str] = 'Forbid multi-line function type annotations.'
class UppercaseStringModifierViolation(node, text=None, baseline=None)[source]

Bases: TokenizeViolation

WPS321 — Forbid uppercase string modifiers.

Reasoning:

String modifiers should be consistent.

Solution:

Use lowercase string modifiers.

Example:

# Correct:
some_string = r'/regex/'
some_bytes = b'123'

# Wrong:
some_string = R'/regex/'
some_bytes = B'123'

Added in version 0.6.0.

error_template: ClassVar[str] = 'Found uppercase string modifier: {0}'
code: ClassVar[int] = 321
full_code: ClassVar[str] = 'WPS321'
summary: ClassVar[str] = 'Forbid uppercase string modifiers.'
class WrongMultilineStringViolation(node, text=None, baseline=None)[source]

Bases: TokenizeViolation

WPS322 — Forbid triple quotes for singleline strings.

Reasoning:

String quotes should be consistent.

Solution:

Use single quotes for single-line strings. Triple quotes are only allowed for real multiline strings.

Example:

# Correct:
single_line = 'abc'
multiline = """
    one
    two
"""

# Wrong:
some_string = """abc"""
some_bytes = b"""123"""

Docstrings are ignored from this rule. You must use triple quotes strings for docstrings.

Is not reported for f-strings on python3.12+

Added in version 0.7.0.

error_template: ClassVar[str] = 'Found incorrect multi-line string'
code: ClassVar[int] = 322
full_code: ClassVar[str] = 'WPS322'
summary: ClassVar[str] = 'Forbid triple quotes for singleline strings.'
class ModuloStringFormatViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS323 — Forbid % formatting on strings.

We check for string formatting. We try not to issue false positives. It is better for us to ignore a real (but hard to detect) case, then marking a valid one as incorrect.

Internally we check for this pattern in string definitions:

%[(name)] [flags] [width] [.precision] [{h | l}] type

This is a C format specification. Related to FormattedStringViolation and solves the same problem.

Reasoning:

You must use a single formatting method across your project.

Solution:

We enforce to use string .format() method for this task.

Example:

# Correct:
'some string', 'your name: {0}', 'data: {data}'

# Wrong:
'my name is: %s', 'data: %(data)d'

It might be a good idea to disable this rule and switch to flake8-pep3101 in case your project has a lot of false-positives due to some specific string chars that uses % a lot.

Added in version 0.14.0.

error_template: ClassVar[str] = 'Found `%` string formatting'
code: ClassVar[int] = 323
full_code: ClassVar[str] = 'WPS323'
summary: ClassVar[str] = 'Forbid ``%`` formatting on strings.'
class InconsistentReturnViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS324 — Enforce consistent return statements.

Rules are: 1. If any return has a value, all return nodes should have a value 2. Do not place return without a value at the end of a function 3. Do not use return None where just return is good enough

This rule respects mypy style of placing return statements. There should be no conflict with these two checks.

Reasoning:

This is done for pure consistency and readability of your code. Eventually, this rule may also find some bugs in your code.

Solution:

Add or remove values from the return statements to make them consistent. Remove return statement from the function end.

Example:

# Correct:
def function():
    if some:
        return 2
    return 1

# Wrong:
def function():
    if some:
        return
    return 1

Added in version 0.7.0.

Changed in version 0.16.0.

error_template: ClassVar[str] = 'Found inconsistent `return` statement'
code: ClassVar[int] = 324
full_code: ClassVar[str] = 'WPS324'
summary: ClassVar[str] = 'Enforce consistent ``return`` statements.'
class InconsistentYieldViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS325 — Enforce consistent yield statements.

Rules are: 1. if any yield has a value, all yield nodes should have a value 2. Use yield instead of yield None where possible

This rule respects mypy style of placing yield statements. There should be no conflict with these two checks.

Reasoning:

This is done for pure consistency and readability of your code. Eventually, this rule may also find some bugs in your code.

Solution:

Add or remove values from the yield statements to make them consistent.

Example:

# Correct:
def function():
    if some:
        yield 2
    yield 1

# Wrong:
def function():
    if some:
        yield
    yield 1

Added in version 0.7.0.

Changed in version 0.16.0.

error_template: ClassVar[str] = 'Found inconsistent `yield` statement'
code: ClassVar[int] = 325
full_code: ClassVar[str] = 'WPS325'
summary: ClassVar[str] = 'Enforce consistent ``yield`` statements.'
class ImplicitStringConcatenationViolation(node, text=None, baseline=None)[source]

Bases: TokenizeViolation

WPS326 — Forbid implicit string concatenation.

Reasoning:

This is error-prone, since you can possibly miss a comma in a collection of strings and get an implicit concatenation. And because there are safer ways to do the same thing it is better to use them instead.

Solution:

Use + or .format() to join strings.

Example:

# Correct:
text = 'first' + 'second'

# Wrong:
text = 'first' 'second'

Added in version 0.7.0.

error_template: ClassVar[str] = 'Found implicit string concatenation'
code: ClassVar[int] = 326
full_code: ClassVar[str] = 'WPS326'
summary: ClassVar[str] = 'Forbid implicit string concatenation.'
class UselessContinueViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS327 — Forbid meaningless continue in loops.

Reasoning:

Placing this keyword at the end of any loop won’t make any difference to your code. And we prefer not to have meaningless constructs in our code.

Solution:

Remove useless continue from the loop.

Example:

# Correct:
for number in [1, 2, 3]:
    if number < 2:
        continue
    print(number)

for number in [1, 2, 3]:
    with suppress(Exception):
        do_smth(some_obj)

# Wrong:
for number in [1, 2, 3]:
    print(number)
    continue

for number in [1, 2, 3]:
    try:
        do_smth(some_obj)
    except Exception:
        continue

Added in version 0.7.0.

error_template: ClassVar[str] = 'Found useless `continue` at the end of the loop'
code: ClassVar[int] = 327
full_code: ClassVar[str] = 'WPS327'
summary: ClassVar[str] = 'Forbid meaningless ``continue`` in loops.'
class UselessNodeViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS328 — Forbid meaningless nodes.

Reasoning:

Some nodes might be completely useless. They will literally do nothing. Sometimes they are hard to find, because this situation can be caused by a recent refactoring or just by accident. This might be also an overuse of syntax.

Solution:

Remove node or make sure it makes sense.

Example:

# Wrong:
for number in [1, 2, 3]:
    break

Added in version 0.7.0.

error_template: ClassVar[str] = 'Found useless node: {0}'
code: ClassVar[int] = 328
full_code: ClassVar[str] = 'WPS328'
summary: ClassVar[str] = 'Forbid meaningless nodes.'
class UselessExceptCaseViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS329 — Forbid meaningless except cases.

Reasoning:

Using except cases that just reraise the same exception is error-prone. You can increase your stacktrace, silence some potential exceptions, and screw things up. It also does not make any sense to do so.

Solution:

Remove except case or make sure it makes sense.

Example:

# Correct:
try:
    ...
except IndexError:
    sentry.log()
    raise ValueError()

try:
    ...
except ValueError as exc:
    raise CustomReadableException from exc

# Wrong:
try:
    ...
except TypeError:
    raise

Added in version 0.7.0.

error_template: ClassVar[str] = 'Found useless `except` case'
code: ClassVar[int] = 329
full_code: ClassVar[str] = 'WPS329'
summary: ClassVar[str] = 'Forbid meaningless ``except`` cases.'
class UselessOperatorsViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS330 — Forbid unnecessary operators in your code.

You can write: 5.4 and +5.4. There’s no need to use the second version. Similarly --5.4, ---5.4, not not foo, and ~~42 contain unnecessary operators.

Reasoning:

This is done for consistency reasons.

Solution:

Omit unnecessary operators.

Example:

# Correct:
profit = 3.33
profit = -3.33
inverse = ~5
complement = not foo

# Wrong:
profit = +3.33
profit = --3.33
profit = ---3.33
number = ~~42
bar = not not foo

Added in version 0.8.0.

code: ClassVar[int] = 330
error_template: ClassVar[str] = 'Found unnecessary operator: {0}'
full_code: ClassVar[str] = 'WPS330'
summary: ClassVar[str] = 'Forbid unnecessary operators in your code.'
class InconsistentReturnVariableViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS331 — Forbid local variables that are only used in return statements.

We also allow cases when a variable is assigned, then there are some other statements without direct variable access and the variable is returned. We reserve this use-case to be able to do some extra work before the function returns.

We also allow the return of partial, sorted, or modified tuple items that are defined just above.

Reasoning:

This is done for consistency and more readable source code.

Solution:

Return the expression itself, instead of creating a temporary variable.

Example:

# Correct:
def some_function():
    return 1

def other_function():
    some_value = 1
    do_something(some_value)
    return some_value

# Wrong:
def some_function():
    some_value = 1
    return some_value

Added in version 0.9.0.

Changed in version 0.14.0.

error_template: ClassVar[str] = 'Found variables that are only used for `return`: {0}'
code: ClassVar[int] = 331
full_code: ClassVar[str] = 'WPS331'
summary: ClassVar[str] = 'Forbid local variables that are only used in ``return`` statements.'
class WalrusViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS332 — Forbid walrus operator.

Reasoning:

Code with := is hardly readable. It has big problems with scoping and reading order. And it can lead to a huge mess inside your code. Python is not expression-based.

Solution:

Don’t use fancy stuff, use good old assignments.

Example:

# Correct:
some = call()
if some:
    print(some)

# Wrong:
if some := call():
    print(some)

Added in version 0.14.0.

error_template: ClassVar[str] = 'Found walrus operator'
code: ClassVar[int] = 332
full_code: ClassVar[str] = 'WPS332'
summary: ClassVar[str] = 'Forbid walrus operator.'
class ImplicitComplexCompareViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS333 — Forbid implicit complex comparison expressions.

Reasoning:

Two comparisons in python that are joined with and operator mean that you have a complex comparison with tree operators.

Solution:

Refactor your comparison without and but with the third operator. Notice that you might have to change the ordering.

Example:

# Correct:
if three < two < one:
    ...

# Wrong:
if one > two and two > three:
    ...

Added in version 0.10.0.

code: ClassVar[int] = 333
error_template: ClassVar[str] = 'Found implicit complex compare'
full_code: ClassVar[str] = 'WPS333'
summary: ClassVar[str] = 'Forbid implicit complex comparison expressions.'
class ReversedComplexCompareViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS334 — Forbid reversed order complex comparison expressions.

Reasoning:

Comparisons where comparators start from the lowest element are easier to read than one that start from the biggest one. It is also possible to write the same expression in two separate way, which is inconsistent.

Solution:

Reverse the order, so the smallest element comes first and the biggest one comes last.

Example:

# Correct:
if three < two < one:
    ...

# Wrong:
if one > two > three:
    ...

Added in version 0.10.0.

code: ClassVar[int] = 334
error_template: ClassVar[str] = 'Found reversed complex comparison'
full_code: ClassVar[str] = 'WPS334'
summary: ClassVar[str] = 'Forbid reversed order complex comparison expressions.'
class WrongLoopIterTypeViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS335 — Forbid wrong for loop iter targets.

We forbid to use:

  • Lists and list comprehensions

  • Sets and set comprehensions

  • Dicts and dict comprehensions

  • Generator expressions

  • Empty tuples

Reasoning:

Using lists, dicts, and sets do not make much sense. You can use tuples instead. Using comprehensions implicitly creates a two level loop, that is hard to read and deal with.

Solution:

Use tuples to create explicit iterables for for loops. In case you are using a comprehension, create a new variable.

Example:

# Correct:
for person in ('Kim', 'Nick'):
    ...

# Wrong:
for person in ['Kim', 'Nick']:
    ...

Added in version 0.10.0.

Changed in version 0.12.0.

code: ClassVar[int] = 335
error_template: ClassVar[str] = 'Found incorrect `for` loop iter type'
full_code: ClassVar[str] = 'WPS335'
summary: ClassVar[str] = 'Forbid wrong ``for`` loop iter targets.'
class ExplicitStringConcatViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS336 — Forbid explicit string concatanation in favour of .format method.

However, we still allow multiline string concatanation as a way to write long strings that does not fit the 80-chars rule.

Reasoning:

When formatting strings one must use .format and not any other formatting methods like %, +, or f. This is done for consistency reasons.

Solution:

Join strings together if you can, or use .format method.

Example:

# Correct:
x = 'ab: {0}'.format(some_data)

# Wrong:
x = 'a' + 'b: ' + some_data

Added in version 0.12.0.

code: ClassVar[int] = 336
error_template: ClassVar[str] = 'Found explicit string concatenation'
full_code: ClassVar[str] = 'WPS336'
summary: ClassVar[str] = 'Forbid explicit string concatanation in favour of ``.format`` method.'
class MultilineConditionsViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS337 — Forbid multiline conditions.

Reasoning:

This way of writing conditions hides the inner complexity this line has and it decreases readability of the code.

Solution:

Divide multiline conditions to some if condition or use variables.

Example:

# Correct:
if isinstance(node.test, ast.UnaryOp):
    if isinstance(node.test.op, ast.Not):
        ...

# Wrong:
if isinstance(node.test, ast.UnaryOp) and isinstance(
    node.test.op,
    ast.Not,
):
    ...

Added in version 0.9.0.

Changed in version 0.11.0.

error_template: ClassVar[str] = 'Found multiline conditions'
code: ClassVar[int] = 337
previous_codes: ClassVar[Set[int]] = {465}
full_code: ClassVar[str] = 'WPS337'
summary: ClassVar[str] = 'Forbid multiline conditions.'
class WrongMethodOrderViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS338 — Forbid incorrect order of methods inside a class.

We follow the same ordering:

  • __init_subclass__

  • __new__

  • __init__

  • __call__

  • __await__

  • public and magic methods

  • protected methods

  • private methods (we discourage using them)

We follow “Newspaper order” where the most important things come first.

Reasoning:

It is hard to read classes where API declarations are bloated with implementation details. We need to see the important stuff first, then we can go deeper in case we are interested.

Solution:

Reorder methods inside your class to match our format.

Added in version 0.12.0.

error_template: ClassVar[str] = 'Found incorrect order of methods in a class'
code: ClassVar[int] = 338
full_code: ClassVar[str] = 'WPS338'
summary: ClassVar[str] = 'Forbid incorrect order of methods inside a class.'
class NumberWithMeaninglessZeroViolation(node, text=None, baseline=None)[source]

Bases: TokenizeViolation

WPS339 — Forbid meaningless zeros.

We discourage using meaningless zeros in float, binary, octal, hex, and exponential numbers.

Reasoning:

There are ~infinite ways to write these numbers by adding meaningless leading zeros to the number itself. 0b1 is the same as 0b01 and 0b001. How can a language be called consistent if you can write numbers in an infinite ways? It hurts readability and understanding of your code.

Solution:

Remove meaningless leading zeros.

Example:

# Correct:
numbers = [1.5, 0b1, 0o2, 0x5, 10e10]

# Wrong:
numbers = [1.50, 0b00000001, 0o0002, 0x05, 10e010]

Added in version 0.12.0.

error_template: ClassVar[str] = 'Found number with meaningless zeros: {0}'
code: ClassVar[int] = 339
full_code: ClassVar[str] = 'WPS339'
summary: ClassVar[str] = 'Forbid meaningless zeros.'
class PositiveExponentViolation(node, text=None, baseline=None)[source]

Bases: TokenizeViolation

WPS340 — Forbid extra + signs in the exponent.

Reasoning:

Positive exponent is positive by default, there’s no need to write an extra + sign. We enforce consistency with this rule.

Solution:

Remove meaningless + sign from the exponent.

Example:

# Correct:
number = 1e1 + 1e-1

# Wrong:
number = 1e+1

Added in version 0.12.0.

error_template: ClassVar[str] = 'Found exponent number with positive exponent: {0}'
code: ClassVar[int] = 340
full_code: ClassVar[str] = 'WPS340'
summary: ClassVar[str] = 'Forbid extra ``+`` signs in the exponent.'
class WrongHexNumberCaseViolation(node, text=None, baseline=None)[source]

Bases: TokenizeViolation

WPS341 — Forbid letters as hex numbers.

Reasoning:

One can write 0xA and 0xa which is inconsistent. This rule enforces upper-case letters in hex numbers.

Solution:

Use uppercase letters in hex numbers.

Example:

# Correct:
number = 0xABCDEF

# Wrong:
number = 0xabcdef

Added in version 0.12.0.

error_template: ClassVar[str] = 'Found wrong hex number case: {0}'
code: ClassVar[int] = 341
full_code: ClassVar[str] = 'WPS341'
summary: ClassVar[str] = 'Forbid letters as hex numbers.'
class ImplicitRawStringViolation(node, text=None, baseline=None)[source]

Bases: TokenizeViolation

WPS342 — Forbid \\ escape sequences inside regular strings.

Reasoning:

It is hard to read escape sequences inside regular strings, because they use \\ double backslash for a single character escape.

Solution:

Use raw strings r'' to rewrite the escape sequence with a \ single backslash.

Example:

# Correct:
escaped = [r'\n', '\n']

# Wrong:
escaped = '\\n'

Is not reported for f-strings on python3.12+

Added in version 0.12.0.

error_template: ClassVar[str] = 'Found implicit raw string: {0}'
code: ClassVar[int] = 342
full_code: ClassVar[str] = 'WPS342'
summary: ClassVar[str] = 'Forbid ``\\\\`` escape sequences inside regular strings.'
class BadComplexNumberSuffixViolation(node, text=None, baseline=None)[source]

Bases: TokenizeViolation

WPS343 — Forbid uppercase complex number suffix.

Reasoning:

Numbers should be consistent.

Solution:

Use lowercase suffix for imaginary part.

Example:

# Correct:
complex_number = 1j

# Wrong:
complex_number = 1J

Added in version 0.12.0.

error_template: ClassVar[str] = 'Found wrong complex number suffix: {0}'
code: ClassVar[int] = 343
full_code: ClassVar[str] = 'WPS343'
summary: ClassVar[str] = 'Forbid uppercase complex number suffix.'
class ZeroDivisionViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS344 — Forbid explicit division (or modulo) by zero.

Reasoning:

This will just throw ZeroDivisionError. If that’s what you need: just throw it. No need to use undefined math behaviours. Or it might be just a typo / mistake, then fix it.

Solution:

Use ZeroDivisionError or make your number something besides 0.

Example:

# Correct:
raise ZeroDivisionError()

# Wrong:
1 / 0
1 % 0

Added in version 0.12.0.

error_template: ClassVar[str] = 'Found explicit zero division'
code: ClassVar[int] = 344
full_code: ClassVar[str] = 'WPS344'
summary: ClassVar[str] = 'Forbid explicit division (or modulo) by zero.'
class MeaninglessNumberOperationViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS345 — Forbid meaningless math operations with 0 and 1.

Reasoning:

Adding and subtracting zero does not change the value. There’s no need to do that. Multiplying by zero is also redundant: it can be replaced with explicit 0 assign. Multiplying and dividing by 1 is also meaningless. Likewise, using | or ^ with 0, and using the % operator with 1 are unnecessary.

Solution:

Remove useless operations.

Example:

# Correct:
number = 1
zero = 0
one = 1
three = 3

# Wrong:
number = 1 + 0 * 1
zero = some * 0 / 1
one = some ** 0 ** 1
three = 3 ^ 0
three = 3 | 0
three = 3 % 1

Added in version 0.12.0.

Changed in version 0.15.0.

error_template: ClassVar[str] = 'Found meaningless number operation'
code: ClassVar[int] = 345
full_code: ClassVar[str] = 'WPS345'
summary: ClassVar[str] = 'Forbid meaningless math operations with ``0`` and ``1``.'
class OperationSignNegationViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS346 — Forbid double minus operations.

Reasoning:

Having two operations is harder than having just one. Two negations are harder than one positive expression. Two negations equal to one positive expression. Positive and negative equal to one negative.

Solution:

Replace double minus operation to a single one with plus. Replace ‘plus-minus’ operation to a single one with minus.

Example:

# Correct:
number = 3 + 1
number += 6
number -= 2

# Wrong:
number = 3 - -1
number -= -6
number += -2

Added in version 0.12.0.

error_template: ClassVar[str] = 'Found wrong operation sign'
code: ClassVar[int] = 346
full_code: ClassVar[str] = 'WPS346'
summary: ClassVar[str] = 'Forbid double minus operations.'
class VagueImportViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS347 — Forbid imports that may cause confusion outside of the module.

Names that we forbid to import:

  • Common names like dumps and loads

  • Names starting with to_ and from_

  • Too short names like Q or F, but we are fine with _

Reasoning:

See datetime.* in code? You know that it’s from datetime. See BaseView in a Django project? You know where it is from. See loads? It can be anything: yaml, toml, json, etc. We are also enforcing consistency with our naming too-short rules here.

Solution:

Use package level imports or import aliases.

See VAGUE_IMPORTS_BLACKLIST for the full list of bad import names.

Example:

# Correct:
import json
import dumps  # package names are not checked
from json import loads as json_loads

# Wrong:
from json import loads

Added in version 0.13.0.

Changed in version 0.14.0.

error_template: ClassVar[str] = 'Found vague import that may cause confusion: {0}'
code: ClassVar[int] = 347
full_code: ClassVar[str] = 'WPS347'
summary: ClassVar[str] = 'Forbid imports that may cause confusion outside of the module.'
class LineStartsWithDotViolation(node, text=None, baseline=None)[source]

Bases: TokenizeViolation

WPS348 — Forbid starting lines with a dot.

Reasoning:

We enforce strict consistency rules about how to break lines. We also enforce strict rules about multi-line parameters. Starting new lines with the dot means that this rule is broken.

Solution:

Use () to break lines in a complex expression.

Example:

# Correct:
some = MyModel.objects.filter(
    ...,
).exclude(
    ...,
).annotate(
    ...,
)

# Wrong:
some = (
    MyModel.objects.filter(...)
        .exclude(...)
        .annotate(...)
)

Added in version 0.13.0.

error_template: ClassVar[str] = 'Found a line that starts with a dot'
code: ClassVar[int] = 348
full_code: ClassVar[str] = 'WPS348'
summary: ClassVar[str] = 'Forbid starting lines with a dot.'
class RedundantSubscriptViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS349 — Forbid redundant components in a subscript’s slice.

Reasoning:

We do it for consistency reasons.

Example:

# Correct:
array[:7]
array[3:]

# Wrong:
x[0:7]
x[3:None]

Added in version 0.13.0.

error_template: ClassVar[str] = 'Found redundant subscript slice'
code: ClassVar[int] = 349
full_code: ClassVar[str] = 'WPS349'
summary: ClassVar[str] = "Forbid redundant components in a subscript's slice."
class AugmentedAssignPatternViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS350 — Enforce using augmented assign pattern.

Reasoning:

a += b is short and correct version of a = a + b. Why not using the short version?

Example:

# Correct:
a += b

# Wrong:
a = a + b

Added in version 0.13.0.

error_template: ClassVar[str] = 'Found usable augmented assign pattern'
code: ClassVar[int] = 350
full_code: ClassVar[str] = 'WPS350'
summary: ClassVar[str] = 'Enforce using augmented assign pattern.'
class UnnecessaryLiteralsViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS351 — Forbid unnecessary literals in your code.

Reasoning:

We discourage using primitive calls to get default type values. There are better ways to get these values.

Solution:

Use direct default values of the given type

Example:

# Correct:
default = 0

# Wrong:
default = int()

Added in version 0.13.0.

error_template: ClassVar[str] = 'Found unnecessary literals'
code: ClassVar[int] = 351
full_code: ClassVar[str] = 'WPS351'
summary: ClassVar[str] = 'Forbid unnecessary literals in your code.'
class MultilineLoopViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS352 — Forbid multiline loops.

Reasoning:

It decreased the readability of the code.

Solution:

Use single line loops and create new variables in case you need to fit too many logic inside the loop definition.

Example:

# Correct:
for num in some_function(arg1, arg2):
    ...

# Wrong:
for num in range(
    arg1,
    arg2,
):
    ...

Added in version 0.13.0.

error_template: ClassVar[str] = 'Found multiline loop'
code: ClassVar[int] = 352
full_code: ClassVar[str] = 'WPS352'
summary: ClassVar[str] = 'Forbid multiline loops.'
class IncorrectYieldFromTargetViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS353 — Forbid yield from with several nodes.

We allow to yield from tuples, names, attributes, calls, and subscripts.

Reasoning:

We enforce consistency when yielding values from tuple instead of any other types. It also might be an error when you try to yield from something that is not iterable.

Solution:

Use allowed node types with yield from.

Example:

# Correct:
yield from (1, 2, 3)
yield from some

# Wrong:
yield from [1, 2, 3]

Added in version 0.13.0.

error_template: ClassVar[str] = 'Found incorrect `yield from` target'
code: ClassVar[int] = 353
full_code: ClassVar[str] = 'WPS353'
summary: ClassVar[str] = 'Forbid ``yield from`` with several nodes.'
class ConsecutiveYieldsViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS354 — Forbid consecutive yield expressions.

We raise this violation when we find at least two consecutive yield expressions.

Reasoning:

One can write multiple yield nodes in a row. That’s inconsistent. Because we have yield from form.

Solution:

It can be easily changed to yield from (...) format.

Added in version 0.13.0.

error_template: ClassVar[str] = 'Found consecutive `yield` expressions'
code: ClassVar[int] = 354
full_code: ClassVar[str] = 'WPS354'
summary: ClassVar[str] = 'Forbid consecutive ``yield`` expressions.'
class BracketBlankLineViolation(node, text=None, baseline=None)[source]

Bases: TokenizeViolation

WPS355 — Forbid useless blank lines before and after brackets.

Reasoning:

We do this for consistency.

Solution:

Remove blank lines from the start and from the end of a collection.

Example:

# Correct:
arr = [
    1,
    2,
]

# Wrong:
arr = [

    1,
    2,

]

Added in version 0.13.0.

error_template: ClassVar[str] = 'Found an unnecessary blank line before a bracket'
code: ClassVar[int] = 355
full_code: ClassVar[str] = 'WPS355'
summary: ClassVar[str] = 'Forbid useless blank lines before and after brackets.'
class IterableUnpackingViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS356 — Forbid unnecessary iterable unpacking.

Reasoning:

We do this for consistency.

Solution:

Do not use iterable unpacking when it’s not necessary.

Example:

# Correct:
[1, *numbers, 99]
{*iterable, *other_iterable}
list(iterable)
first, *iterable = other_iterable
GenericTuple = tuple[*Shape]

# Wrong:
[*iterable]
*iterable, = other_iterable

Added in version 0.13.0.

Changed in version 0.19.3: Allow using TypeVarTuple unpacking in generic types. As a side-effect we now allow all unpackings in ast.Subscript.

error_template: ClassVar[str] = 'Found an unnecessary iterable unpacking'
code: ClassVar[int] = 356
full_code: ClassVar[str] = 'WPS356'
summary: ClassVar[str] = 'Forbid unnecessary iterable unpacking.'
class LineCompriseCarriageReturnViolation(node, text=None, baseline=None)[source]

Bases: TokenizeViolation

WPS357 — Forbid using \r (carriage return) in line breaks.

Reasoning:

We enforce Unix-style newlines. We only use newlines (\n), not carriage returns. So \r line breaks not allowed in code.

Solution:

Use only \n (not \r\n or \r) to break lines.

Added in version 0.14.0.

error_template: ClassVar[str] = 'Found a ``\\r`` (carriage return) line break'
code: ClassVar[int] = 357
full_code: ClassVar[str] = 'WPS357'
summary: ClassVar[str] = 'Forbid using ``\\r`` (carriage return) in line breaks.'
class FloatZeroViolation(node, text=None, baseline=None)[source]

Bases: TokenizeViolation

WPS358 — Forbid using float zeros: 0.0.

Reasoning:

Float zeros can be used as variable values which may lead to typing bugs when trying to perform an operation between an int number and the float zero.

Solution:

Use int zeros (0). If a float is needed, it should be cast explicitly.

Example:

# Correct:
zero = 0

# Wrong:
zero = 0.0

Added in version 0.15.0.

code: ClassVar[int] = 358
error_template: ClassVar[str] = 'Found a float zero (0.0)'
full_code: ClassVar[str] = 'WPS358'
summary: ClassVar[str] = 'Forbid using float zeros: ``0.0``.'
class UnpackingIterableToListViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS359 — Forbids to unpack iterable objects to lists.

Reasoning:

We do this for consistency.

Solution:

Do not unpack iterables to lists, use tuples for that.

Example:

# Correct:
first, second = (7, 4)
first, *iterable = other_iterable

# Wrong:
[first, second] = (7, 4)
[first, *iterable] = other_iterable

Added in version 0.15.0.

error_template: ClassVar[str] = 'Found an iterable unpacking to list'
code: ClassVar[int] = 359
full_code: ClassVar[str] = 'WPS359'
summary: ClassVar[str] = 'Forbids to unpack iterable objects to lists.'
class RawStringNotNeededViolation(node, text=None, baseline=None)[source]

Bases: TokenizeViolation

WPS360 — Forbid the use of raw strings when there is no backslash in the string.

Reasoning:

Raw string are only needed when dealing with \ in the string.

Solution:

Do not prefix the string with r. Use a normal string instead.

Example:

# Correct:
r'This is a correct use \n'

# Wrong:
r'This string should not be prefixed with r.'

Is not reported for f-strings on python3.12+

Added in version 0.15.0.

error_template: ClassVar[str] = 'Found an unnecessary use of a raw string: {0}'
code: ClassVar[int] = 360
full_code: ClassVar[str] = 'WPS360'
summary: ClassVar[str] = 'Forbid the use of raw strings when there is no backslash in the string.'
class InconsistentComprehensionViolation(node, text=None, baseline=None)[source]

Bases: TokenizeViolation

WPS361 — Forbids inconsistent newlines in comprehensions.

Reasoning:

We do this for consistency.

Solution:

Either place comprehension on a single line or ensure that action, for loops, and condition are all on different lines.

Example:

# Correct:
list = [some(number) for number in numbers]

list = [
   some(number)
   for numbers in matrix
   for number in numbers
   if number > 0
]

# Wrong:
list = [
    some(number) for number in numbers
    if number > 0
]

Added in version 0.15.0.

error_template: ClassVar[str] = 'Found an inconsistently structured comprehension'
code: ClassVar[int] = 361
full_code: ClassVar[str] = 'WPS361'
summary: ClassVar[str] = 'Forbids inconsistent newlines in comprehensions.'
class AssignToSliceViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS362 — Forbid assignment to a subscript slice.

Reasoning:

Assignment to a slice may lead to a list changing its size implicitly and strangely which makes it hard to spot bugs.

Solution:

Use explicit index assignment in place of slice assignment.

Why you may disable or inline-ignore this rule?

The quite common and useful example which violates this rule is inplace list replacement via [:] - this helps to keep the same object reference while it content could be completely erased or replaced with the new one.

One more thing: slice assignment is the only way for inplace array multiple replacement when you need that.

Example:

# Correct:
a[5] = 1

# Wrong:
a[1:3] = [1, 2]
a[slice(1)] = [1, 3]

Added in version 0.15.0.

error_template: ClassVar[str] = 'Found assignment to a subscript slice'
code: ClassVar[int] = 362
full_code: ClassVar[str] = 'WPS362'
summary: ClassVar[str] = 'Forbid assignment to a subscript slice.'