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. |
|
WPS533 — Forbid having duplicate conditions in several |
|
WPS534 — Forbid having useless ternary expressions. |
|
WPS535 — Forbid having duplicate |
|
WPS536 — Forbid extra syntax around |
Refactoring opportunities¶
- final class UselessLoopElseViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS500 — Forbid
elsewithoutbreakin a loop.We use the same logic for
forandwhileloops.- Reasoning:
When there’s no
breakkeyword in loop’s body it means thatelsewill always be called. This rule will reduce complexity, improve readability, and protect from possible errors.- Solution:
Refactor your
elsecase 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¶
- full_code: ClassVar[str] = 'WPS500'¶
- summary: ClassVar[str] = 'Forbid ``else`` without ``break`` in a loop.'¶
- final class UselessFinallyViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS501 — Forbid
finallyintryblock withoutexceptblock.However, we allow to use
trywith justfinallyblock when function or method is decorated. Because we cannot control what is going on in this decorator. It might be@contextmanageror similar thing that requires this API.- Reasoning:
This rule will reduce complexity and improve readability.
- Solution:
Refactor your
trylogic. Replace thetry-finallystatement with awithstatement.
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¶
- full_code: ClassVar[str] = 'WPS501'¶
- summary: ClassVar[str] = 'Forbid ``finally`` in ``try`` block without ``except`` block.'¶
- final class SimplifiableIfViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS502 — Forbid simplifiable
ifconditions.- 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 usenotkeyword 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
ifnodes whereTrueandFalsevalues are used. We check bothifnodes andifexpressions.Added in version 0.7.0.
Changed in version 0.11.0.
Changed in version 1.0.0: No longer produced, kept here for historic reasons. This is covered with
rufflinter. SeeSIM108andSIM210.- error_template: ClassVar[str] = 'Found simplifiable `if` condition'¶
- code: ClassVar[int] = 502¶
- disabled_since: ClassVar[str | None] = '1.0.0'¶
- full_code: ClassVar[str] = 'WPS502'¶
- summary: ClassVar[str] = 'Forbid simplifiable ``if`` conditions.'¶
- final class UselessReturningElseViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS503 — Forbid useless
elsecases in returning functions.We check single
if,for,while, andtrystatements that all containreturn,raise,continue, orbreakstatements with this rule.- Reasoning:
Using extra
elsecreates 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
elsecase.
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.
Changed in version 1.0.0: No longer produced, kept here for historic reasons. This is covered with
rufflinter. SeeRET505.- error_template: ClassVar[str] = 'Found useless returning `else` statement'¶
- code: ClassVar[int] = 503¶
- disabled_since: ClassVar[str | None] = '1.0.0'¶
- full_code: ClassVar[str] = 'WPS503'¶
- summary: ClassVar[str] = 'Forbid useless ``else`` cases in returning functions.'¶
- final class NegatedConditionsViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS504 — Forbid negated conditions together with
elseclause.- Reasoning:
It easier to read and name regular conditions. Not negated ones.
- Solution:
Move actions from the negated
ifcondition to theelsecondition.
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.
Changed in version 1.0.0: We now also detect
is notandnot inas negated conditions.We now allow using all negated conditions in
if/elif/elsecases.- error_template: ClassVar[str] = 'Found negated condition'¶
- code: ClassVar[int] = 504¶
- full_code: ClassVar[str] = 'WPS504'¶
- summary: ClassVar[str] = 'Forbid negated conditions together with ``else`` clause.'¶
- final class NestedTryViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS505 — Forbid nested
tryblocks.Notice, we check all possible slots for
tryblock: 1. thetryblock itself 2. allexceptcases 3.elsecase 4. andfinallycase- Reasoning:
Nesting
tryblocks 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¶
- full_code: ClassVar[str] = 'WPS505'¶
- summary: ClassVar[str] = 'Forbid nested ``try`` blocks.'¶
- final class UselessLambdaViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS506 — Forbid useless proxy
lambdaexpressions.- Reasoning:
Sometimes developers tend to overuse
lambdaexpressions and they wrap code that can be passed as is, without extra wrapping. The code without extralambdais easier to read and is more performant.- Solution:
Remove wrapping
lambdadeclaration, 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¶
- full_code: ClassVar[str] = 'WPS506'¶
- summary: ClassVar[str] = 'Forbid useless proxy ``lambda`` expressions.'¶
- final class UselessLenCompareViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS507 — 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 that0or 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.
Changed in version 1.0.0: No longer produced, kept here for historic reasons. This is covered with
ruffandpylintlinters. SeePLC1802.- error_template: ClassVar[str] = 'Found useless `len()` compare'¶
- code: ClassVar[int] = 507¶
- disabled_since: ClassVar[str | None] = '1.0.0'¶
- full_code: ClassVar[str] = 'WPS507'¶
- summary: ClassVar[str] = 'Forbid unpythonic zero-length compare.'¶
- final class NotOperatorWithCompareViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS508 — Forbid
notwith compare expressions.- Reasoning:
This version of
notoperator is unreadable.- Solution:
Refactor the expression without
notoperator. 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.
Changed in version 1.0.0: No longer produced, kept here for historic reasons. This is covered with
rufflinter. SeeSIM201.- error_template: ClassVar[str] = 'Found incorrect `not` with compare usage'¶
- code: ClassVar[int] = 508¶
- disabled_since: ClassVar[str | None] = '1.0.0'¶
- full_code: ClassVar[str] = 'WPS508'¶
- summary: ClassVar[str] = 'Forbid ``not`` with compare expressions.'¶
- final class NestedTernaryViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS509 — Forbid nesting ternary expressions in certain places.
Note, that we restrict to nest ternary expressions inside:
ifconditionsboolean and binary operations like
andor+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
ifstatement, 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¶
- full_code: ClassVar[str] = 'WPS509'¶
- summary: ClassVar[str] = 'Forbid nesting ternary expressions in certain places.'¶
- final class WrongInCompareTypeViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS510 — Forbid
inwith static containers exceptsetnodes.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, ordictelements 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
setelements 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.
Changed in version 1.0.0: No longer produced, kept here for historic reasons. This is covered with
ruffandpylintlinters. SeePLR6201.- error_template: ClassVar[str] = 'Found `in` used with a non-set container'¶
- code: ClassVar[int] = 510¶
- disabled_since: ClassVar[str | None] = '1.0.0'¶
- full_code: ClassVar[str] = 'WPS510'¶
- summary: ClassVar[str] = 'Forbid ``in`` with static containers except ``set`` nodes.'¶
- final class UnmergedIsinstanceCallsViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS511 — Forbid multiple
isinstancecalls on the same variable.- Reasoning:
The best practice is to use
isinstancewith 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.
Changed in version 1.0.0: No longer produced, kept here for historic reasons. This is covered with
ruffformatter. SeeSIM101.- error_template: ClassVar[str] = 'Found separate `isinstance` calls that can be merged for: {0}'¶
- code: ClassVar[int] = 511¶
- disabled_since: ClassVar[str | None] = '1.0.0'¶
- full_code: ClassVar[str] = 'WPS511'¶
- summary: ClassVar[str] = 'Forbid multiple ``isinstance`` calls on the same variable.'¶
- final class WrongIsinstanceWithTupleViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS512 — Forbid multiple
isinstancecalls 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.
Changed in version 1.0.0: No longer produced, kept here for historic reasons. This is covered with
rufflinter. SeeUP038.- error_template: ClassVar[str] = 'Found `isinstance` call with a single element tuple'¶
- code: ClassVar[int] = 512¶
- disabled_since: ClassVar[str | None] = '1.0.0'¶
- full_code: ClassVar[str] = 'WPS512'¶
- summary: ClassVar[str] = 'Forbid multiple ``isinstance`` calls with single-item tuples.'¶
- final class ImplicitElifViolation(node, text=None, baseline=None)[source]¶
Bases:
TokenizeViolationWPS513 — Forbid implicit
elifconditions.- Reasoning:
Nested
ifinelsecases are bad for readability because of the nesting level.- Solution:
Use
elifon 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.'¶
- final class ImplicitInConditionViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS514 — Forbid multiple equality comparisons with the same variable.
- Reasoning:
Using double+ equality compare with
oror double+ non-equality compare withandindicates that you have implicitinornot incondition. It is just hidden from you.- Solution:
Refactor compares to use
inornot inclauses.
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.
Changed in version 1.0.0: No longer produced, kept here for historic reasons. This is covered with
ruffandpylintlinters. SeePLR1714.- code: ClassVar[int] = 514¶
- error_template: ClassVar[str] = 'Found implicit `in` condition: {0}'¶
- disabled_since: ClassVar[str | None] = '1.0.0'¶
- full_code: ClassVar[str] = 'WPS514'¶
- summary: ClassVar[str] = 'Forbid multiple equality comparisons with the same variable.'¶
- final class OpenWithoutContextManagerViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS515 — 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.'¶
- final class TypeCompareViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS516 — 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
isinstanceto 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.'¶
- final class PointlessStarredViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS517 — 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, andsetconstants. 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.'¶
- final class ImplicitEnumerateViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS518 — 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.'¶
- final class ImplicitSumViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS519 — Forbid implicit
sum()calls.When summing types different from numbers, you might need to provide the second argument to the
sumfunction:sum([[1], [2], [3]], [])You might also use
str.jointo join iterable of strings.- Reasoning:
Using
forloops 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.'¶
- final class FalsyConstantCompareViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS520 — 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. We also allow to compare any values insideassertstatements.- Reasoning:
When comparing
somethingwith explicit falsy constants what we really mean isnot something.- Solution:
Use
notwith 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.
Changed in version 1.0.0: Allows any compares in
assertstatements.- 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.'¶
- final class WrongIsCompareViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS521 — Forbid comparing values with constants using
isoris not.However, we allow to compare with
Noneand booleans.- Reasoning:
iscompares 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.
Changed in version 1.0.0: No longer produced, kept here for historic reasons. This is covered with
rufflinter. SeeF632.- code: ClassVar[int] = 521¶
- error_template: ClassVar[str] = 'Found wrong `is` compare'¶
- disabled_since: ClassVar[str | None] = '1.0.0'¶
- full_code: ClassVar[str] = 'WPS521'¶
- summary: ClassVar[str] = 'Forbid comparing values with constants using ``is`` or ``is not``.'¶
- final class ImplicitPrimitiveViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS522 — Forbid implicit primitives in the form of
lambdafunctions.- Reasoning:
When you use
lambdathat returns a primitive value and takes no arguments, it means that you should use a primitive type instead.- Solution:
Replace
lambdawithint,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.'¶
- final class AlmostSwappedViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS523 — Forbid unpythonic variable swaps.
We check for
a = b; b = asequences.- 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.'¶
- final class MisrefactoredAssignmentViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS524 — 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_CONSTANTSfor 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.'¶
- final class InCompareWithSingleItemContainerViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS525 — Forbid comparisons where
inis compared with single item container.- Reasoning:
incomparison 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.
Changed in version 1.0.0: No longer produced, kept here for historic reasons. This is covered with
rufflinter. SeeFURB171.- error_template: ClassVar[str] = 'Found wrong `in` compare with single item container'¶
- code: ClassVar[int] = 525¶
- disabled_since: ClassVar[str | None] = '1.0.0'¶
- full_code: ClassVar[str] = 'WPS525'¶
- summary: ClassVar[str] = 'Forbid comparisons where ``in`` is compared with single item container.'¶
- final class ImplicitYieldFromViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS526 — Forbid
yieldinsideforloop instead ofyield from.- Reasoning:
It is known that
yield fromis a semantically identical to aforloop with ayieldinside. But, it is way more readable.- Solution:
Use
yield fromsome iterable directly instead iterating over it inside a loop andyieldit 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.
Changed in version 1.0.0: No longer produced, kept here for historic reasons. This is covered with
rufflinter. SeeUP028.- error_template: ClassVar[str] = 'Found implicit `yield from` usage'¶
- code: ClassVar[int] = 526¶
- disabled_since: ClassVar[str | None] = '1.0.0'¶
- full_code: ClassVar[str] = 'WPS526'¶
- summary: ClassVar[str] = 'Forbid ``yield`` inside ``for`` loop instead of ``yield from``.'¶
- final class NotATupleArgumentViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS527 — 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_METHODSfor 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.'¶
- final class ImplicitItemsIteratorViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS528 — 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 aforloop, 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.
Changed in version 1.0.0: No longer produced, kept here for historic reasons. This is covered with
ruffandpylintlinters. SeePLC0206.- error_template: ClassVar[str] = 'Found implicit `.items()` usage'¶
- code: ClassVar[int] = 528¶
- disabled_since: ClassVar[str | None] = '1.0.0'¶
- full_code: ClassVar[str] = 'WPS528'¶
- summary: ClassVar[str] = 'Forbid implicit ``.items()`` iterator.'¶
- final class ImplicitDictGetViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS529 — Forbid implicit
.get()dict method.- Reasoning:
When using
inwith a dict key it is hard to keep the code clean. It is more convenient to use.get()and check forNonelater.- Solution:
Use
.get()with the key you need. Check forNonein 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.'¶
- final class ImplicitNegativeIndexViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS530 — 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.'¶
- final class SimplifiableReturningIfViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS531 — 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.
Changed in version 1.0.0: No longer produced, kept here for historic reasons. This is covered with
rufflinter. SeeRET505.- error_template: ClassVar[str] = 'Found simplifiable returning `if` condition in a function'¶
- code: ClassVar[int] = 531¶
- disabled_since: ClassVar[str | None] = '1.0.0'¶
- full_code: ClassVar[str] = 'WPS531'¶
- summary: ClassVar[str] = 'Forbid if statements that simply return booleans in functions or methods.'¶
- final class ChainedIsViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS532 — 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."¶
- final class DuplicateIfConditionViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS533 — Forbid having duplicate conditions in several
if//elifbranches.- Reasoning:
It is likely an error to have multiple same condition in
if/elifstatements. Only the first one will always work.- Solution:
Change the condition.
Example:
# Correct: if something: ... elif other: ... # Wrong: if something: ... elif something: ...
Added in version 1.0.0.
- error_template: ClassVar[str] = 'Found duplicate condition in `if`: {0}'¶
- code: ClassVar[int] = 533¶
- full_code: ClassVar[str] = 'WPS533'¶
- summary: ClassVar[str] = 'Forbid having duplicate conditions in several ``if`` // ``elif`` branches.'¶
- final class UselessTernaryViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS534 — Forbid having useless ternary expressions.
- Reasoning:
When ternary expression can be replaced with a single name, it is way more readable and more performant.
- Solution:
Remove the ternary expression.
Example:
# Correct: first if some_condition else second # Wrong: a if a is not None else None b if a == b else a
Added in version 1.0.0.
- error_template: ClassVar[str] = 'Found useless ternary expression'¶
- code: ClassVar[int] = 534¶
- full_code: ClassVar[str] = 'WPS534'¶
- summary: ClassVar[str] = 'Forbid having useless ternary expressions.'¶
- final class DuplicateCasePatternViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS535 — Forbid having duplicate
casepatterns.- Reasoning:
It is likely an error to have multiple same int
casepatterns. Only the first one will always work.- Solution:
Change the pattern.
Example:
# Correct: match some: case SomeClass(field) if field > 0: ... case OtherClass(): ... # Wrong: match some: case SomeClass(field): ... case SomeClass(field): ...
Added in version 1.0.0.
- error_template: ClassVar[str] = 'Found duplicate `case` pattern: {0}'¶
- code: ClassVar[int] = 535¶
- full_code: ClassVar[str] = 'WPS535'¶
- summary: ClassVar[str] = 'Forbid having duplicate ``case`` patterns.'¶
- final class ExtraMatchSubjectSyntaxViolation(node, text=None, baseline=None)[source]¶
Bases:
ASTViolationWPS536 — Forbid extra syntax around
matchlike list, set, or dict.- Reasoning:
Adding extra lists / sets / dicts around your
matchsubjects is just adding more complexity.- Solution:
Use raw values or tuples instead.
Example:
# Correct: match some: case SomeClass(): ... match (first, second): case (1, 2): ... # Wrong: match [first, second]: case [1, 2]: ...
Added in version 1.0.0.
- error_template: ClassVar[str] = 'Found `match` subject with extra syntax: {0}'¶
- code: ClassVar[int] = 536¶
- full_code: ClassVar[str] = 'WPS536'¶
- summary: ClassVar[str] = 'Forbid extra syntax around ``match`` like list, set, or dict.'¶