Refactoring

These checks ensure that you don’t have patterns that can be refactored.

There are so many ways of doing the same thing in Python. Here we collect know patterns that can be rewritten into much easier or just more pythonic version.

Summary

UselessLoopElseViolation

WPS500 — Forbid else without break in a loop.

UselessFinallyViolation

WPS501 — Forbid finally in try block without except block.

SimplifiableIfViolation

WPS502 — Forbid simplifiable if conditions.

UselessReturningElseViolation

WPS503 — Forbid useless else cases in returning functions.

NegatedConditionsViolation

WPS504 — Forbid negated conditions together with else clause.

NestedTryViolation

WPS505 — Forbid nested try blocks.

UselessLambdaViolation

WPS506 — Forbid useless proxy lambda expressions.

UselessLenCompareViolation

WPS507 — Forbid unpythonic zero-length compare.

NotOperatorWithCompareViolation

WPS508 — Forbid not with compare expressions.

NestedTernaryViolation

WPS509 — Forbid nesting ternary expressions in certain places.

WrongInCompareTypeViolation

WPS510 — Forbid in with static containers except set nodes.

UnmergedIsinstanceCallsViolation

WPS511 — Forbid multiple isinstance calls on the same variable.

WrongIsinstanceWithTupleViolation

WPS512 — Forbid multiple isinstance calls with single-item tuples.

ImplicitElifViolation

WPS513 — Forbid implicit elif conditions.

ImplicitInConditionViolation

WPS514 — Forbid multiple equality comparisons with the same variable.

OpenWithoutContextManagerViolation

WPS515 — Forbid open() without a context manager.

TypeCompareViolation

WPS516 — Forbid comparing types with type() function.

PointlessStarredViolation

WPS517 — Forbid useless starred expressions.

ImplicitEnumerateViolation

WPS518 — Forbid implicit enumerate() calls.

ImplicitSumViolation

WPS519 — Forbid implicit sum() calls.

FalsyConstantCompareViolation

WPS520 — Forbid comparing with explicit falsy constants.

WrongIsCompareViolation

WPS521 — Forbid comparing values with constants using is or is not.

ImplicitPrimitiveViolation

WPS522 — Forbid implicit primitives in the form of lambda functions.

AlmostSwappedViolation

WPS523 — Forbid unpythonic variable swaps.

MisrefactoredAssignmentViolation

WPS524 — Forbid misrefactored self assignment.

InCompareWithSingleItemContainerViolation

WPS525 — Forbid comparisons where in is compared with single item container.

ImplicitYieldFromViolation

WPS526 — Forbid yield inside for loop instead of yield from.

NotATupleArgumentViolation

WPS527 — Require tuples as arguments for certain functions.

ImplicitItemsIteratorViolation

WPS528 — Forbid implicit .items() iterator.

ImplicitDictGetViolation

WPS529 — Forbid implicit .get() dict method.

ImplicitNegativeIndexViolation

WPS530 — Forbid implicit negative indexes.

SimplifiableReturningIfViolation

WPS531 — Forbid if statements that simply return booleans in functions or methods.

ChainedIsViolation

WPS532 — Forbid ast.Is in ast.Compare.ops when it's size is not zero.

Refactoring opportunities

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

Bases: ASTViolation

WPS500 — Forbid else without break in a loop.

We use the same logic for for and while loops.

Reasoning:

When there’s no break keyword in loop’s body it means that else will always be called. This rule will reduce complexity, improve readability, and protect from possible errors.

Solution:

Refactor your else case logic to be inside the loop’s body. Or right after it.

Example:

# Correct:
for letter in 'abc':
    if letter == 'b':
        break
else:
    print('"b" is not found')

for letter in 'abc':
    print(letter)
print('always called')

# Wrong:
for letter in 'abc':
    print(letter)
else:
    print('always called')

Added in version 0.3.0.

Changed in version 0.11.0.

error_template: ClassVar[str] = 'Found `else` in a loop without `break`'
code: ClassVar[int] = 500
previous_codes: ClassVar[Set[int]] = {436}
full_code: ClassVar[str] = 'WPS500'
summary: ClassVar[str] = 'Forbid ``else`` without ``break`` in a loop.'
class UselessFinallyViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS501 — Forbid finally in try block without except block.

However, we allow to use try with just finally block when function or method is decorated. Because we cannot control what is going on in this decorator. It might be @contextmanager or similar thing that requires this API.

Reasoning:

This rule will reduce complexity and improve readability.

Solution:

Refactor your try logic. Replace the try-finally statement with a with statement.

Example:

# Correct:
with open("filename") as f:
    f.write(...)

# Wrong:
try:
    f = open("filename")
    f.write(...)
finally:
    f.close()

Added in version 0.3.0.

Changed in version 0.11.0.

Changed in version 0.14.0.

error_template: ClassVar[str] = 'Found `finally` in `try` block without `except`'
code: ClassVar[int] = 501
previous_codes: ClassVar[Set[int]] = {437}
full_code: ClassVar[str] = 'WPS501'
summary: ClassVar[str] = 'Forbid ``finally`` in ``try`` block without ``except`` block.'
class SimplifiableIfViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS502 — Forbid simplifiable if conditions.

Reasoning:

These complex constructions can cause frustration among other developers. They are longer, more verbose, and more complex.

Solution:

Either use bool() to convert test values to boolean values, or just leave it as it is in case your test already returns a boolean value. Use can also use not keyword to switch boolean values.

Example:

# Correct:
my_bool = bool(some_call())
other_value = 8 if some_call() else None

# Wrong:
my_bool = True if some_call() else False

We only check if nodes where True and False values are used. We check both if nodes and if expressions.

Added in version 0.7.0.

Changed in version 0.11.0.

error_template: ClassVar[str] = 'Found simplifiable `if` condition'
code: ClassVar[int] = 502
previous_codes: ClassVar[Set[int]] = {451}
full_code: ClassVar[str] = 'WPS502'
summary: ClassVar[str] = 'Forbid simplifiable ``if`` conditions.'
class UselessReturningElseViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS503 — Forbid useless else cases in returning functions.

We check single if, for, while, and try statements that all contain return, raise, continue, or break statements with this rule.

Reasoning:

Using extra else creates a situation when the whole node could and should be dropped without any changes in logic. So, we prefer to have less code than more code.

Solution:

Remove useless else case.

Example:

# Correct:
def some_function():
    if some_call():
        return 'yeap'
    return 'nope'

# Wrong:
def some_function():
    if some_call():
        raise ValueError('yeap')
    else:
        raise ValueError('nope')

Added in version 0.7.0.

Changed in version 0.11.0.

Changed in version 0.15.1.

error_template: ClassVar[str] = 'Found useless returning `else` statement'
code: ClassVar[int] = 503
previous_codes: ClassVar[Set[int]] = {457}
full_code: ClassVar[str] = 'WPS503'
summary: ClassVar[str] = 'Forbid useless ``else`` cases in returning functions.'
class NegatedConditionsViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS504 — Forbid negated conditions together with else clause.

Reasoning:

It easier to read and name regular conditions. Not negated ones.

Solution:

Move actions from the negated if condition to the else condition.

Example:

# Correct:
if some == 1:
     ...
else:
     ...

if not some:
     ...

if not some:
    ...
elif other:
    ...

# Wrong:
if not some:
     ...
else:
     ...

Added in version 0.8.0.

Changed in version 0.11.0.

error_template: ClassVar[str] = 'Found negated condition'
code: ClassVar[int] = 504
previous_codes: ClassVar[Set[int]] = {463}
full_code: ClassVar[str] = 'WPS504'
summary: ClassVar[str] = 'Forbid negated conditions together with ``else`` clause.'
class NestedTryViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS505 — Forbid nested try blocks.

Notice, we check all possible slots for try block: 1. the try block itself 2. all except cases 3. else case 4. and finally case

Reasoning:

Nesting try blocks indicates that something really bad happens to your logic. Why does it require two separate exception handlers? It is a perfect case to refactor your code.

Solution:

Collapse two exception handlers together. Or create a separate function that will handle this second nested case.

Example:

# Wrong:
try:
    try:
        ...
    except SomeException:
        ...
except SomeOtherException:
    ...

try:
    ...
except SomeOtherException:
    try:
        ...
    except SomeException:
        ...

Added in version 0.8.0.

Changed in version 0.11.0.

error_template: ClassVar[str] = 'Found nested `try` block'
code: ClassVar[int] = 505
previous_codes: ClassVar[Set[int]] = {464}
full_code: ClassVar[str] = 'WPS505'
summary: ClassVar[str] = 'Forbid nested ``try`` blocks.'
class UselessLambdaViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS506 — Forbid useless proxy lambda expressions.

Reasoning:

Sometimes developers tend to overuse lambda expressions and they wrap code that can be passed as is, without extra wrapping. The code without extra lambda is easier to read and is more performant.

Solution:

Remove wrapping lambda declaration, use just the internal function.

Example:

# Correct:
numbers = map(int, ['1', '2'])

# Wrong:
numbers = map(lambda string: int(string), ['1', '2'])

Added in version 0.10.0.

Changed in version 0.11.0.

error_template: ClassVar[str] = 'Found useless lambda declaration'
code: ClassVar[int] = 506
previous_codes: ClassVar[Set[int]] = {467}
full_code: ClassVar[str] = 'WPS506'
summary: ClassVar[str] = 'Forbid useless proxy ``lambda`` expressions.'
class UselessLenCompareViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS507 — Forbid unpythonic zero-length compare.

Note, that we allow to check arbitrary length, like len(arr) == 3.

Reasoning:

Python’s structures like dicts, lists, sets, and tuples all have __bool__ method to checks their length. So, there’s no point in wrapping them into len(...) and checking that it is bigger that 0 or less then 1, etc.

Solution:

Remove extra len() call.

Example:

# Correct:
if some_array or not other_array or len(third_array) == 1:
    ...

# Wrong:
if len(some_array) > 0 or len(other_array) < 1:
    ...

Added in version 0.10.0.

Changed in version 0.11.0.

error_template: ClassVar[str] = 'Found useless `len()` compare'
code: ClassVar[int] = 507
previous_codes: ClassVar[Set[int]] = {468}
full_code: ClassVar[str] = 'WPS507'
summary: ClassVar[str] = 'Forbid unpythonic zero-length compare.'
class NotOperatorWithCompareViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS508 — Forbid not with compare expressions.

Reasoning:

This version of not operator is unreadable.

Solution:

Refactor the expression without not operator. Change the compare signs.

Example:

# Correct:
if x <= 5:
    ...

# Wrong:
if not x > 5:
    ...

Added in version 0.10.0.

Changed in version 0.11.0.

error_template: ClassVar[str] = 'Found incorrect `not` with compare usage'
code: ClassVar[int] = 508
previous_codes: ClassVar[Set[int]] = {470}
full_code: ClassVar[str] = 'WPS508'
summary: ClassVar[str] = 'Forbid ``not`` with compare expressions.'
class NestedTernaryViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS509 — Forbid nesting ternary expressions in certain places.

Note, that we restrict to nest ternary expressions inside:

  • if conditions

  • boolean and binary operations like and or +

  • unary operators

Reasoning:

Nesting ternary in random places can lead to very hard debug and testing problems.

Solution:

Refactor the ternary expression to be either a new variable, or nested if statement, or a new function.

Example:

# Correct:
some = x if cond() else y

# Wrong:
if x if cond() else y:
    ...

Added in version 0.10.0.

Changed in version 0.11.0.

error_template: ClassVar[str] = 'Found incorrectly nested ternary'
code: ClassVar[int] = 509
previous_codes: ClassVar[Set[int]] = {472}
full_code: ClassVar[str] = 'WPS509'
summary: ClassVar[str] = 'Forbid nesting ternary expressions in certain places.'
class WrongInCompareTypeViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS510 — Forbid in with static containers except set nodes.

We enforce people to use sets as a static containers. You can also use variables, calls, methods, etc. Dynamic values are not checked.

Reasoning:

Using static list, tuple, or dict elements to check that some element is inside the container is a bad practice. Because we need to iterate all over the container to find the element. Sets are the best suit for this task. Moreover, it makes your code consistent.

Solution:

Use set elements or comprehensions to check that something is contained in a container.

Example:

# Correct:
print(needle in {'one', 'two'})

# Wrong:
print(needle in ['one', 'two'])

Added in version 0.10.0.

Changed in version 0.11.0.

Changed in version 0.14.0.

error_template: ClassVar[str] = 'Found `in` used with a non-set container'
code: ClassVar[int] = 510
previous_codes: ClassVar[Set[int]] = {473}
full_code: ClassVar[str] = 'WPS510'
summary: ClassVar[str] = 'Forbid ``in`` with static containers except ``set`` nodes.'
class UnmergedIsinstanceCallsViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS511 — Forbid multiple isinstance calls on the same variable.

Reasoning:

The best practice is to use isinstance with tuple as the second argument, instead of multiple conditions joined with or.

Solution:

Use tuple of types as the second argument.

Example:

# Correct:
isinstance(some, (int, float))

# Wrong:
isinstance(some, int) or isinstance(some, float)

Added in version 0.10.0.

Changed in version 0.11.0.

error_template: ClassVar[str] = 'Found separate `isinstance` calls that can be merged for: {0}'
code: ClassVar[int] = 511
previous_codes: ClassVar[Set[int]] = {474}
full_code: ClassVar[str] = 'WPS511'
summary: ClassVar[str] = 'Forbid multiple ``isinstance`` calls on the same variable.'
class WrongIsinstanceWithTupleViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS512 — Forbid multiple isinstance calls with single-item tuples.

Reasoning:

There’s no need to use tuples with single elements. You can use single variables or tuples with multiple elements.

Solution:

Use tuples with multiple elements or a single variable.

Example:

# Correct:
isinstance(some, (int, float))
isinstance(some, int)

# Wrong:
isinstance(some, (int, ))

See: https://docs.python.org/3/library/functions.html#isinstance

Added in version 0.10.0.

Changed in version 0.11.0.

error_template: ClassVar[str] = 'Found `isinstance` call with a single element tuple'
code: ClassVar[int] = 512
previous_codes: ClassVar[Set[int]] = {475}
full_code: ClassVar[str] = 'WPS512'
summary: ClassVar[str] = 'Forbid multiple ``isinstance`` calls with single-item tuples.'
class ImplicitElifViolation(node, text=None, baseline=None)[source]

Bases: TokenizeViolation

WPS513 — Forbid implicit elif conditions.

Reasoning:

Nested if in else cases are bad for readability because of the nesting level.

Solution:

Use elif on the same level.

Example:

# Correct:
if some:
    ...
elif other:
    ...

# Wrong:
if some:
    ...
else:
    if other:
        ...

Added in version 0.12.0.

error_template: ClassVar[str] = 'Found implicit `elif` condition'
code: ClassVar[int] = 513
full_code: ClassVar[str] = 'WPS513'
summary: ClassVar[str] = 'Forbid implicit ``elif`` conditions.'
class ImplicitInConditionViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS514 — Forbid multiple equality comparisons with the same variable.

Reasoning:

Using double+ equality compare with or or double+ non-equality compare with and indicates that you have implicit in or not in condition. It is just hidden from you.

Solution:

Refactor compares to use in or not in clauses.

Example:

# Correct:
print(some in {'first', 'second'})
print(some not in {'first', 'second'})

# Wrong:
print(some == 'first' or some == 'second')
print(some != 'first' and some != 'second')

Added in version 0.10.0.

Changed in version 0.12.0.

code: ClassVar[int] = 514
error_template: ClassVar[str] = 'Found implicit `in` condition: {0}'
previous_codes: ClassVar[Set[int]] = {336}
full_code: ClassVar[str] = 'WPS514'
summary: ClassVar[str] = 'Forbid multiple equality comparisons with the same variable.'
class OpenWithoutContextManagerViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS515 — Forbid open() without a context manager.

Reasoning:

When you open() something, you need to close it. When using a context manager - it is automatically done for you. When not using it - you might find yourself in a situation when file is not closed and is not accessible anymore.

Solution:

Refactor open() call to use with.

Example:

# Correct:
with open(filename) as file_obj:
    ...

# Wrong:
file_obj = open(filename)

Added in version 0.12.0.

code: ClassVar[int] = 515
error_template: ClassVar[str] = 'Found `open()` used without a context manager'
full_code: ClassVar[str] = 'WPS515'
summary: ClassVar[str] = 'Forbid ``open()`` without a context manager.'
class TypeCompareViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS516 — Forbid comparing types with type() function.

Reasoning:

When you compare types with type() function call it means that you break polymorphism and disallow child classes of a node to work here. That’s incorrect.

Solution:

Use isinstance to compare types.

Example:

# Correct:
print(something, type(something))

if isinstance(something, int):
    ...

# Wrong:
if type(something) == int:
    ...

Added in version 0.12.0.

code: ClassVar[int] = 516
error_template: ClassVar[str] = 'Found `type()` used to compare types'
full_code: ClassVar[str] = 'WPS516'
summary: ClassVar[str] = 'Forbid comparing types with ``type()`` function.'
class PointlessStarredViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS517 — Forbid useless starred expressions.

Reasoning:

Using starred expression with constants is useless. This piece of code can be rewritten to be flat. Eg.: print(*[1, 2, 3]) is print(1, 2, 3).

Solution:

Refactor your code not to use starred expressions with list, dict, tuple, and set constants. Use regular argument passing instead.

Example:

# Correct:
my_list = [1, 2, 3, *other_iterable]

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

Added in version 0.12.0.

code: ClassVar[int] = 517
error_template: ClassVar[str] = 'Found pointless starred expression'
full_code: ClassVar[str] = 'WPS517'
summary: ClassVar[str] = 'Forbid useless starred expressions.'
class ImplicitEnumerateViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS518 — Forbid implicit enumerate() calls.

Reasoning:

Using range(len(...)) is not pythonic. Python uses collection iterators, not index-based loops.

Solution:

Use enumerate(...) instead of range(len(...)).

Example:

# Correct:
for index, person in enumerate(people):
    ...

# Wrong:
for index in range(len(people)):
    ...

Added in version 0.12.0.

code: ClassVar[int] = 518
error_template: ClassVar[str] = 'Found implicit `enumerate()` call'
full_code: ClassVar[str] = 'WPS518'
summary: ClassVar[str] = 'Forbid implicit ``enumerate()`` calls.'
class ImplicitSumViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS519 — Forbid implicit sum() calls.

When summing types different from numbers, you might need to provide the second argument to the sum function: sum([[1], [2], [3]], [])

You might also use str.join to join iterable of strings.

Reasoning:

Using for loops with += assign inside indicates that you iteratively sum things inside your collection. That’s what sum() builtin function does.

Solution:

Use sum(...) instead of a loop with += operation.

Example:

# Correct:
sum_result = sum(get_elements())

# Wrong:
sum_result = 0
for to_sum in get_elements():
    sum_result += to_sum

Added in version 0.12.0.

code: ClassVar[int] = 519
error_template: ClassVar[str] = 'Found implicit `sum()` call'
full_code: ClassVar[str] = 'WPS519'
summary: ClassVar[str] = 'Forbid implicit ``sum()`` calls.'
class FalsyConstantCompareViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS520 — Forbid comparing with explicit falsy constants.

We allow to compare with falsy numbers, strings, booleans, None. We disallow complex constants like tuple, dicts, and lists.

Reasoning:

When comparing something with explicit falsy constants what we really mean is not something.

Solution:

Use not with your variable. Fix your data types.

Example:

# Correct:
if not my_check:
    ...

if some_other is None:
    ...

if some_num == 0:
    ...

# Wrong:
if my_check == []:
    ...

Added in version 0.12.0.

code: ClassVar[int] = 520
error_template: ClassVar[str] = 'Found compare with falsy constant'
full_code: ClassVar[str] = 'WPS520'
summary: ClassVar[str] = 'Forbid comparing with explicit falsy constants.'
class WrongIsCompareViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS521 — Forbid comparing values with constants using is or is not.

However, we allow to compare with None and booleans.

Reasoning:

is compares might not do what you want them to do. Firstly, they check for the same object, not equality. Secondly, they behave unexpectedly even with the simple values like 257.

Solution:

Use == to compare with constants.

Example:

# Correct:
if my_check == [1, 2, 3]:
    ...

# Wrong:
if my_check is [1, 2, 3]:
    ...

Added in version 0.12.0.

code: ClassVar[int] = 521
error_template: ClassVar[str] = 'Found wrong `is` compare'
full_code: ClassVar[str] = 'WPS521'
summary: ClassVar[str] = 'Forbid comparing values with constants using ``is`` or ``is not``.'
class ImplicitPrimitiveViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS522 — Forbid implicit primitives in the form of lambda functions.

Reasoning:

When you use lambda that returns a primitive value and takes no arguments, it means that you should use a primitive type instead.

Solution:

Replace lambda with int, float, list, or any other primitive.

Example:

# Correct:
defaultdict(int)

# Wrong:
defaultdict(lambda: 0)

Added in version 0.13.0.

code: ClassVar[int] = 522
error_template: ClassVar[str] = 'Found implicit primitive in a form of `lambda`'
full_code: ClassVar[str] = 'WPS522'
summary: ClassVar[str] = 'Forbid implicit primitives in the form of ``lambda`` functions.'
class AlmostSwappedViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS523 — Forbid unpythonic variable swaps.

We check for a = b; b = a sequences.

Reasoning:

This looks like a failed attempt to swap.

Solution:

Use standard way to swap two variables.

Example:

# Correct:
a, b = b, a

# Wrong:
a = b
b = a

temp = a
a = b
b = temp

Added in version 0.13.0.

error_template: ClassVar[str] = 'Found incorrectly swapped variables'
code: ClassVar[int] = 523
full_code: ClassVar[str] = 'WPS523'
summary: ClassVar[str] = 'Forbid unpythonic variable swaps.'
class MisrefactoredAssignmentViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS524 — Forbid misrefactored self assignment.

Reasoning:

Self assignment does not need to have the same operand on the left hand side and on the right hand side.

Solution:

Refactor your code to use multiple self assignments or fix your code.

Example:

# Correct:
test += 1
test *= 2

# Wrong:
test += test + 1

See MATH_APPROXIMATE_CONSTANTS for full list of math constants that we check for.

Added in version 0.13.0.

error_template: ClassVar[str] = 'Found self assignment  with refactored assignment'
code: ClassVar[int] = 524
full_code: ClassVar[str] = 'WPS524'
summary: ClassVar[str] = 'Forbid misrefactored self assignment.'
class InCompareWithSingleItemContainerViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS525 — Forbid comparisons where in is compared with single item container.

Reasoning:

in comparison with a container which contains only one item looks like overhead and unneeded complexity.

Solution:

Refactor your code to use == instead in.

Example:

# Correct:
a == 's'

# Wrong:
a in {'s'}

Added in version 0.13.0.

error_template: ClassVar[str] = 'Found wrong `in` compare with single item container'
code: ClassVar[int] = 525
full_code: ClassVar[str] = 'WPS525'
summary: ClassVar[str] = 'Forbid comparisons where ``in`` is compared with single item container.'
class ImplicitYieldFromViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS526 — Forbid yield inside for loop instead of yield from.

Reasoning:

It is known that yield from is a semantically identical to a for loop with a yield inside. But, it is way more readable.

Solution:

Use yield from some iterable directly instead iterating over it inside a loop and yield it one by one.

Example:

# Correct:
yield from some()

yield from (
    value[index:index + chunk_size]
    for index in range(0, len(value), chunk_size)
)

# Wrong:
for index in chunk:
    yield index

Added in version 0.13.0.

error_template: ClassVar[str] = 'Found implicit `yield from` usage'
code: ClassVar[int] = 526
full_code: ClassVar[str] = 'WPS526'
summary: ClassVar[str] = 'Forbid ``yield`` inside ``for`` loop instead of ``yield from``.'
class NotATupleArgumentViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS527 — Require tuples as arguments for certain functions.

Reasoning:

For some functions, it is better to use tuples instead of another iterable types (list, sets,…) as arguments.

Solution:

Use tuples as arguments.

Example:

# Correct:
a = frozenset((2,))

# Wrong:
a = frozenset([2])

See TUPLE_ARGUMENTS_METHODS for full list of methods that we check for.

Added in version 0.13.0.

error_template: ClassVar[str] = 'Found not a tuple used as an argument'
code: ClassVar[int] = 527
full_code: ClassVar[str] = 'WPS527'
summary: ClassVar[str] = 'Require tuples as arguments for certain functions.'
class ImplicitItemsIteratorViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS528 — Forbid implicit .items() iterator.

Reasoning:

When iterating over collection it is easy to forget to use .items() when you need to access both keys and values. So, when you access the iterable with the key inside a for loop, that’s a sign to refactor your code.

Solution:

Use .items() with direct keys and values when you need them.

Example:

# Correct:
for some_key, some_value in collection.items():
    print(some_key, some_value)

# Wrong:
for some_key in collection:
    print(some_key, collection[some_key])

Added in version 0.13.0.

error_template: ClassVar[str] = 'Found implicit `.items()` usage'
code: ClassVar[int] = 528
full_code: ClassVar[str] = 'WPS528'
summary: ClassVar[str] = 'Forbid implicit ``.items()`` iterator.'
class ImplicitDictGetViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS529 — Forbid implicit .get() dict method.

Reasoning:

When using in with a dict key it is hard to keep the code clean. It is more convenient to use .get() and check for None later.

Solution:

Use .get() with the key you need. Check for None in case you need it, or just act with the default value of the same type.

Example:

# Correct:
value = collection.get(key)
if value is not None:
    print(value)

# Wrong:
if key in collection:
    print(collection[key])

Added in version 0.13.0.

error_template: ClassVar[str] = 'Found implicit `.get()` dict usage'
code: ClassVar[int] = 529
full_code: ClassVar[str] = 'WPS529'
summary: ClassVar[str] = 'Forbid implicit ``.get()`` dict method.'
class ImplicitNegativeIndexViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS530 — Forbid implicit negative indexes.

Reasoning:

There’s no need in getting the length of an iterable and then having a negative offset, when you can specify negative indexes in the first place.

Solution:

Use negative indexes.

Example:

# Correct:
some_list[-1]

# Wrong:
some_list[len(some_list) - 1]

Added in version 0.13.0.

error_template: ClassVar[str] = 'Found implicit negative index'
code: ClassVar[int] = 530
full_code: ClassVar[str] = 'WPS530'
summary: ClassVar[str] = 'Forbid implicit negative indexes.'
class SimplifiableReturningIfViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS531 — Forbid if statements that simply return booleans in functions or methods.

Reasoning:

There is no need to test a condition and simply return a boolean depending on its outcome if there is not going to be any additional code.

Solution:

Instead of testing the condition and returning a boolean, return the condition itself. This applies to early returning ifs too.

Example:

# Correct:
def some_function():
    return some_condition

# Wrong:
def some_function():
    if some_condition:
        return True
    else:
        return False

Added in version 0.15.0.

error_template: ClassVar[str] = 'Found simplifiable returning `if` condition in a function'
code: ClassVar[int] = 531
full_code: ClassVar[str] = 'WPS531'
summary: ClassVar[str] = 'Forbid if statements that simply return booleans in functions or methods.'
class ChainedIsViolation(node, text=None, baseline=None)[source]

Bases: ASTViolation

WPS532 — Forbid ast.Is in ast.Compare.ops when it’s size is not zero.

Reasoning:

From the AST perspective, is is an operator and can be chained. That can lead to unexpected results when the author wanted to compare the result of a is b operation. Instead, Python will chain the operations and compare the last argument of the previous operation.

Solution:

Who knows at this point.

Example::
Correct:

a is b and b is None

Wrong:

a is b is None

Added in version 0.18.0.

error_template: ClassVar[str] = 'Found chained `is` operators in an expression'
code: ClassVar[int] = 532
full_code: ClassVar[str] = 'WPS532'
summary: ClassVar[str] = "Forbid `ast.Is` in `ast.Compare.ops` when it's size is not zero."