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 |
- UselessLoopElseViolation[source]¶
WPS500 — 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.
- full_code: ClassVar[str] = 'WPS500'¶
- summary: ClassVar[str] = 'Forbid ``else`` without ``break`` in a loop.'¶
- UselessFinallyViolation[source]¶
WPS501 — 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.
- full_code: ClassVar[str] = 'WPS501'¶
- summary: ClassVar[str] = 'Forbid ``finally`` in ``try`` block without ``except`` block.'¶
- SimplifiableIfViolation[source]¶
WPS502 — 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.- disabled_since: ClassVar[str | None] = '1.0.0'¶
- full_code: ClassVar[str] = 'WPS502'¶
- summary: ClassVar[str] = 'Forbid simplifiable ``if`` conditions.'¶
- UselessReturningElseViolation[source]¶
WPS503 — 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.- disabled_since: ClassVar[str | None] = '1.0.0'¶
- full_code: ClassVar[str] = 'WPS503'¶
- summary: ClassVar[str] = 'Forbid useless ``else`` cases in returning functions.'¶
- NegatedConditionsViolation[source]¶
WPS504 — 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.- full_code: ClassVar[str] = 'WPS504'¶
- summary: ClassVar[str] = 'Forbid negated conditions together with ``else`` clause.'¶
- NestedTryViolation[source]¶
WPS505 — 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.
- full_code: ClassVar[str] = 'WPS505'¶
- summary: ClassVar[str] = 'Forbid nested ``try`` blocks.'¶
- UselessLambdaViolation[source]¶
WPS506 — 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.
- full_code: ClassVar[str] = 'WPS506'¶
- summary: ClassVar[str] = 'Forbid useless proxy ``lambda`` expressions.'¶
- UselessLenCompareViolation[source]¶
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 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.- disabled_since: ClassVar[str | None] = '1.0.0'¶
- full_code: ClassVar[str] = 'WPS507'¶
- summary: ClassVar[str] = 'Forbid unpythonic zero-length compare.'¶
- NotOperatorWithCompareViolation[source]¶
WPS508 — 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.- disabled_since: ClassVar[str | None] = '1.0.0'¶
- full_code: ClassVar[str] = 'WPS508'¶
- summary: ClassVar[str] = 'Forbid ``not`` with compare expressions.'¶
- NestedTernaryViolation[source]¶
WPS509 — 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.
- full_code: ClassVar[str] = 'WPS509'¶
- summary: ClassVar[str] = 'Forbid nesting ternary expressions in certain places.'¶
- WrongInCompareTypeViolation[source]¶
WPS510 — 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.- disabled_since: ClassVar[str | None] = '1.0.0'¶
- full_code: ClassVar[str] = 'WPS510'¶
- summary: ClassVar[str] = 'Forbid ``in`` with static containers except ``set`` nodes.'¶
- UnmergedIsinstanceCallsViolation[source]¶
WPS511 — 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.- disabled_since: ClassVar[str | None] = '1.0.0'¶
- full_code: ClassVar[str] = 'WPS511'¶
- summary: ClassVar[str] = 'Forbid multiple ``isinstance`` calls on the same variable.'¶
- WrongIsinstanceWithTupleViolation[source]¶
WPS512 — 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.- disabled_since: ClassVar[str | None] = '1.0.0'¶
- full_code: ClassVar[str] = 'WPS512'¶
- summary: ClassVar[str] = 'Forbid multiple ``isinstance`` calls with single-item tuples.'¶
- ImplicitElifViolation[source]¶
WPS513 — 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.
- full_code: ClassVar[str] = 'WPS513'¶
- summary: ClassVar[str] = 'Forbid implicit ``elif`` conditions.'¶
- ImplicitInConditionViolation[source]¶
WPS514 — 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.- disabled_since: ClassVar[str | None] = '1.0.0'¶
- full_code: ClassVar[str] = 'WPS514'¶
- summary: ClassVar[str] = 'Forbid multiple equality comparisons with the same variable.'¶
- OpenWithoutContextManagerViolation[source]¶
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.
- full_code: ClassVar[str] = 'WPS515'¶
- summary: ClassVar[str] = 'Forbid ``open()`` without a context manager.'¶
- TypeCompareViolation[source]¶
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
isinstanceto compare types.
Example:
# Correct: print(something, type(something)) if isinstance(something, int): ... # Wrong: if type(something) == int: ...
Added in version 0.12.0.
- full_code: ClassVar[str] = 'WPS516'¶
- summary: ClassVar[str] = 'Forbid comparing types with ``type()`` function.'¶
- PointlessStarredViolation[source]¶
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, 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.
- full_code: ClassVar[str] = 'WPS517'¶
- summary: ClassVar[str] = 'Forbid useless starred expressions.'¶
- ImplicitEnumerateViolation[source]¶
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.
- full_code: ClassVar[str] = 'WPS518'¶
- summary: ClassVar[str] = 'Forbid implicit ``enumerate()`` calls.'¶
- ImplicitSumViolation[source]¶
WPS519 — 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.
- full_code: ClassVar[str] = 'WPS519'¶
- summary: ClassVar[str] = 'Forbid implicit ``sum()`` calls.'¶
- FalsyConstantCompareViolation[source]¶
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. 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.- full_code: ClassVar[str] = 'WPS520'¶
- summary: ClassVar[str] = 'Forbid comparing with explicit falsy constants.'¶
- WrongIsCompareViolation[source]¶
WPS521 — 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.- 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``.'¶
- ImplicitPrimitiveViolation[source]¶
WPS522 — 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.
- full_code: ClassVar[str] = 'WPS522'¶
- summary: ClassVar[str] = 'Forbid implicit primitives in the form of ``lambda`` functions.'¶
- AlmostSwappedViolation[source]¶
WPS523 — 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.
- full_code: ClassVar[str] = 'WPS523'¶
- summary: ClassVar[str] = 'Forbid unpythonic variable swaps.'¶
- MisrefactoredAssignmentViolation[source]¶
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_CONSTANTSfor full list of math constants that we check for.Added in version 0.13.0.
- full_code: ClassVar[str] = 'WPS524'¶
- summary: ClassVar[str] = 'Forbid misrefactored self assignment.'¶
- InCompareWithSingleItemContainerViolation[source]¶
WPS525 — 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.- 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.'¶
- ImplicitYieldFromViolation[source]¶
WPS526 — 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.- 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``.'¶
- NotATupleArgumentViolation[source]¶
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_METHODSfor full list of methods that we check for.Added in version 0.13.0.
- full_code: ClassVar[str] = 'WPS527'¶
- summary: ClassVar[str] = 'Require tuples as arguments for certain functions.'¶
- ImplicitItemsIteratorViolation[source]¶
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 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.- disabled_since: ClassVar[str | None] = '1.0.0'¶
- full_code: ClassVar[str] = 'WPS528'¶
- summary: ClassVar[str] = 'Forbid implicit ``.items()`` iterator.'¶
- ImplicitDictGetViolation[source]¶
WPS529 — 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.
- full_code: ClassVar[str] = 'WPS529'¶
- summary: ClassVar[str] = 'Forbid implicit ``.get()`` dict method.'¶
- ImplicitNegativeIndexViolation[source]¶
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.
- full_code: ClassVar[str] = 'WPS530'¶
- summary: ClassVar[str] = 'Forbid implicit negative indexes.'¶
- SimplifiableReturningIfViolation[source]¶
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.
Changed in version 1.0.0: No longer produced, kept here for historic reasons. This is covered with
rufflinter. SeeRET505.- 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.'¶
- ChainedIsViolation[source]¶
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.
- full_code: ClassVar[str] = 'WPS532'¶
- summary: ClassVar[str] = "Forbid `ast.Is` in `ast.Compare.ops` when it's size is not zero."¶
- DuplicateIfConditionViolation[source]¶
WPS533 — 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.
- full_code: ClassVar[str] = 'WPS533'¶
- summary: ClassVar[str] = 'Forbid having duplicate conditions in several ``if`` // ``elif`` branches.'¶
- UselessTernaryViolation[source]¶
WPS534 — 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.
- full_code: ClassVar[str] = 'WPS534'¶
- summary: ClassVar[str] = 'Forbid having useless ternary expressions.'¶
- DuplicateCasePatternViolation[source]¶
WPS535 — 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.
- full_code: ClassVar[str] = 'WPS535'¶
- summary: ClassVar[str] = 'Forbid having duplicate ``case`` patterns.'¶
- ExtraMatchSubjectSyntaxViolation[source]¶
WPS536 — 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.
- full_code: ClassVar[str] = 'WPS536'¶
- summary: ClassVar[str] = 'Forbid extra syntax around ``match`` like list, set, or dict.'¶