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¶
WPS500 — Forbid |
|
WPS501 — Forbid |
|
WPS502 — Forbid simplifiable |
|
WPS503 — Forbid useless |
|
WPS504 — Forbid negated conditions together with |
|
WPS505 — Forbid nested |
|
WPS506 — Forbid useless proxy |
|
WPS507 — Forbid unpythonic zero-length compare. |
|
WPS508 — Forbid |
|
WPS509 — Forbid nesting ternary expressions in certain places. |
|
WPS510 — Forbid |
|
WPS511 — Forbid multiple |
|
WPS512 — Forbid multiple |
|
WPS513 — Forbid implicit |
|
WPS514 — Forbid multiple equality comparisons with the same variable. |
|
WPS515 — Forbid |
|
WPS516 — Forbid comparing types with |
|
WPS517 — Forbid useless starred expressions. |
|
WPS518 — Forbid implicit |
|
WPS519 — Forbid implicit |
|
WPS520 — Forbid comparing with explicit falsy constants. |
|
WPS521 — Forbid comparing values with constants using |
|
WPS522 — Forbid implicit primitives in the form of |
|
WPS523 — Forbid unpythonic variable swaps. |
|
WPS524 — Forbid misrefactored self assignment. |
|
WPS525 — Forbid comparisons where |
|
WPS526 — Forbid |
|
WPS527 — Require tuples as arguments for certain functions. |
|
WPS528 — Forbid implicit |
|
WPS529 — Forbid implicit |
|
WPS530 — Forbid implicit negative indexes. |
|
WPS531 — Forbid if statements that simply return booleans in functions or methods. |
|
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
withoutbreak
in a loop.We use the same logic for
for
andwhile
loops.- Reasoning:
When there’s no
break
keyword in loop’s body it means thatelse
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
intry
block withoutexcept
block.However, we allow to use
try
with justfinally
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 thetry-finally
statement with awith
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 usenot
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 whereTrue
andFalse
values are used. We check bothif
nodes andif
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
, andtry
statements that all containreturn
,raise
,continue
, orbreak
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 theelse
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. thetry
block itself 2. allexcept
cases 3.else
case 4. andfinally
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 extralambda
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 intolen(...)
and checking that it is bigger that0
or less then1
, 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
conditionsboolean 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 exceptset
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
, ordict
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 withor
.- 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
inelse
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 withand
indicates that you have implicitin
ornot in
condition. It is just hidden from you.- Solution:
Refactor compares to use
in
ornot 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 usewith
.
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])
isprint(1, 2, 3)
.- Solution:
Refactor your code not to use starred expressions with
list
,dict
,tuple
, andset
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 ofrange(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 whatsum()
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
See also
https://docs.python.org/3/library/functions.html#sum https://docs.python.org/3/library/stdtypes.html#str.join
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 isnot 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
oris 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 like257
.- 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
withint
,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
==
insteadin
.
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
insidefor
loop instead ofyield from
.- Reasoning:
It is known that
yield from
is a semantically identical to afor
loop with ayield
inside. But, it is way more readable.- Solution:
Use
yield from
some iterable directly instead iterating over it inside a loop andyield
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 afor
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 forNone
later.- Solution:
Use
.get()
with the key you need. Check forNone
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."¶