Best practices¶
These checks ensure that you follow the best practices.
The source for these best practices is hidden inside countless hours we have spent debugging software or reviewing it.
How do we find inspiration for new rules? We find some ugly code during code reviews and audits. Then we forbid to use this bad code forever. So, this error will never return to our codebase.
Summary¶
WrongMagicCommentViolation |
Restricts to use several control (or magic) comments. |
WrongDocCommentViolation |
Forbids to use empty doc comments (#:). |
OveruseOfNoqaCommentViolation |
Forbids to use too many # noqa comments. |
WrongModuleMetadataViolation |
Forbids to have some module level variables. |
EmptyModuleViolation |
Forbids to have empty modules. |
InitModuleHasLogicViolation |
Forbids to have logic inside __init__ module. |
WrongKeywordViolation |
Forbids to use some keywords from python. |
WrongFunctionCallViolation |
Forbids to call some built-in functions. |
FutureImportViolation |
Forbids to use __future__ imports. |
RaiseNotImplementedViolation |
Forbids to use NotImplemented error. |
BaseExceptionViolation |
Forbids to use BaseException exception. |
BooleanPositionalArgumentViolation |
Forbids to pass booleans as non-keyword parameters. |
NestedFunctionViolation |
Forbids to have nested functions. |
NestedClassViolation |
Forbids to use nested classes. |
MagicNumberViolation |
Forbids to use magic numbers in your code. |
StaticMethodViolation |
Forbids to use @staticmethod decorator. |
BadMagicMethodViolation |
Forbids to use some magic methods. |
NestedImportViolation |
Forbids to have nested imports in functions. |
RedundantLoopElseViolation |
Forbids to use else without break in a loop. |
RedundantFinallyViolation |
Forbids to use finally in try block without except block. |
ReassigningVariableToItselfViolation |
Forbids to assign variable to itself. |
YieldInsideInitViolation |
Forbids to use yield inside of __init__ method. |
ProtectedModuleViolation |
Forbids to import protected modules. |
ProtectedAttributeViolation |
Forbids to use protected attributes and methods. |
LambdaInsideLoopViolation |
Forbids to use lambda inside loops. |
UnreachableCodeViolation |
Forbids to have unreachable code. |
StatementHasNoEffectViolation |
Forbids to have statements that do nothing. |
MultipleAssignmentsViolation |
Forbids to have statements that do nothing. |
IncorrectUnpackingViolation |
Forbids to have statements that do nothing. |
DuplicateExceptionViolation |
Forbids to have the same exception class in multiple except blocks. |
YieldInComprehensionViolation |
Forbids to have yield keyword inside comprehensions. |
NonUniqueItemsInSetViolation |
Forbids to have duplicate items in set literals. |
BaseExceptionSubclassViolation |
Forbids to have duplicate items in set literals. |
SimplifiableIfViolation |
Forbids to have simplifiable if conditions. |
IncorrectClassBodyContentViolation |
Forbids to use incorrect nodes inside class definitions. |
MethodWithoutArgumentsViolation |
Forbids to have methods without any arguments. |
IncorrectBaseClassViolation |
Forbids to have methods without any arguments. |
IncorrectSlotsViolation |
Forbids to have incorrect __slots__ definition. |
IncorrectSuperCallViolation |
Forbids to use super() with parameters or outside of methods. |
RedundantReturningElseViolation |
Forbids to use redundant else cases in returning functions. |
TryExceptMultipleReturnPathViolation |
Forbids to use multiple return path with try / except case. |
Comments¶
-
class
WrongMagicCommentViolation(node=None, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.SimpleViolationRestricts to use several control (or magic) comments.
We do not allow to use:
# noqacomment without specified violations# type: some_typecomments to specify a type fortyped_ast
- Reasoning:
- We cover several different use-cases in a single rule.
# noqacomment is restricted because it can hide other violations.# type: some_typecomment is restricted because we can already use type annotations instead. - Solution:
- Use
# noqacomments with specified error types. Use type annotations to specify types.
We still allow to use
# type: ignorecomment. Since sometimes it is totally required.Example:
# Correct: type = MyClass.get_type() # noqa: A001 coordinate: int = 10 some.int_field = 'text' # type: ignore number: int for number in some_untyped_iterable(): ... # Wrong: type = MyClass.get_type() # noqa coordinate = 10 # type: int
New in version 0.1.0.
-
code= 400¶
-
error_template= 'Found wrong magic comment: {0}'¶
-
class
WrongDocCommentViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.TokenizeViolationForbids to use empty doc comments (
#:).- Reasoning:
- Doc comments are used to provide a documentation. But supplying empty doc comments breaks this use-case. It is unclear why they can be used with no contents.
- Solution:
- Add some documentation to this comment. Or remove it.
Empty doc comments are not caught by the default
pycodestylechecks.Example:
# Correct: #: List of allowed names: NAMES_WHITELIST = ['feature', 'bug', 'research'] # Wrong: #: NAMES_WHITELIST = ['feature', 'bug', 'research']
New in version 0.1.0.
-
code= 401¶
-
error_template= 'Found wrong doc comment'¶
-
class
OveruseOfNoqaCommentViolation(node=None, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.SimpleViolationForbids to use too many
# noqacomments.We check this count on a per-module basis. We use 10 as a default value.
- Reasoning:
- Having too many
# noqacomments with make your code less readable and clearly indicates that there’s something wrong with it. - Solution:
- Refactor your code to much the style. Or use a config file to switch off some checks.
New in version 0.7.0.
-
error_template= 'Found `noqa` comments overuse: {0}'¶
-
code= 402¶
Modules¶
-
class
WrongModuleMetadataViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to have some module level variables.
- Reasoning:
- We discourage using module variables like
__author__, because code should not contain any metadata. - Solution:
- Place all the metadata in
setup.py,setup.cfg, orpyproject.toml. Use proper docstrings and packaging classifiers. Usepkg_resourcesif you need to import this data into your app.
See
MODULE_METADATA_VARIABLES_BLACKLISTfor full list of bad names.Example:
# Wrong: __author__ = 'Nikita Sobolev' __version__ = 0.1.2
New in version 0.1.0.
-
error_template= 'Found wrong metadata variable: {0}'¶
-
code= 410¶
-
class
EmptyModuleViolation(node=None, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.SimpleViolationForbids to have empty modules.
- Reasoning:
- Why is it even there? Do not pollute your project with empty files.
- Solution:
If you have an empty module there are two ways to handle that:
- delete it
- drop some documentation in it, so you will explain why it is there
New in version 0.1.0.
-
error_template= 'Found empty module'¶
-
code= 411¶
-
class
InitModuleHasLogicViolation(node=None, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.SimpleViolationForbids to have logic inside
__init__module.- Reasoning:
If you have logic inside the
__init__module it means several things:- you are keeping some outdated stuff there, you need to refactor
- you are placing this logic into the wrong file, just create another one
- you are doing some dark magic, and you should not do that
- Solution:
- Put your code in other modules.
However, we allow to have some contents inside the
__init__module:- comments, since they are dropped before AST comes in play
- docs string, because sometimes it is required to state something
It is also fine when you have different users that use your code. And you do not want to break everything for them. In this case this rule can be configured.
- Configuration:
- This rule is configurable with
--i-control-code. Default: True
New in version 0.1.0.
-
error_template= 'Found `__init__.py` module with logic'¶
-
code= 412¶
Builtins¶
-
class
WrongKeywordViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use some keywords from
python.- Reasoning:
- We believe that some keywords are anti-patterns.
They promote bad-practices like
globalandpass, or just not user-friendly likedel. - Solution:
- Solutions differ from keyword to keyword.
passshould be replaced with docstring orcontextlib.suppress.delshould be replaced with specialized methods like.pop().globalandnonlocalusages should be refactored.
Example:
# Wrong: pass del nonlocal global
New in version 0.1.0.
-
error_template= 'Found wrong keyword: {0}'¶
-
code= 420¶
-
class
WrongFunctionCallViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to call some built-in functions.
- Reasoning:
- Some functions are only suitable for very specific use cases, we forbid to use them in a free manner.
See
FUNCTIONS_BLACKLISTfor the full list of blacklisted functions.New in version 0.1.0.
-
error_template= 'Found wrong function call: {0}'¶
-
code= 421¶
-
class
FutureImportViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use
__future__imports.- Reasoning:
- Almost all
__future__imports are legacypython2compatibility tools that are no longer required. - Solution:
- Remove them. Drop
python2support.
Except, there are some new ones for
python4support. SeeFUTURE_IMPORTS_WHITELISTfor the full list of allowed future imports.Example:
# Correct: from __future__ import annotations # Wrong: from __future__ import print_function
New in version 0.1.0.
-
error_template= 'Found future import: {0}'¶
-
code= 422¶
-
class
RaiseNotImplementedViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use
NotImplementederror.- Reasoning:
- These two violations look so similar.
But, these violations have different use cases.
Use cases of
NotImplementedis too limited to be generally available. - Solution:
- Use
NotImplementedError.
Example:
# Correct: raise NotImplementedError('To be done') # Wrong: raise NotImplemented
New in version 0.1.0.
-
error_template= 'Found raise NotImplemented'¶
-
code= 423¶
-
class
BaseExceptionViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use
BaseExceptionexception.- Reasoning:
- We can silence system exit and keyboard interrupt with this exception
handler. It is almost the same as raw
except:block. - Solution:
- Handle
Exception,KeyboardInterrupt,GeneratorExit, andSystemExitseparately. Do not use the plainexcept:keyword.
Example:
# Correct: except Exception as ex: ... # Wrong: except BaseException as ex: ...
New in version 0.3.0.
See also
https://docs.python.org/3/library/exceptions.html#exception-hierarchy https://help.semmle.com/wiki/pages/viewpage.action?pageId=1608527
-
error_template= 'Found except `BaseException`'¶
-
code= 424¶
-
class
BooleanPositionalArgumentViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to pass booleans as non-keyword parameters.
- Reasoning:
- Passing boolean as regular positional parameters is very non-descriptive. It is almost impossible to tell, what does this parameter means. And you almost always have to look up the implementation to tell what is going on.
- Solution:
- Pass booleans as keywords only. This will help you to save extra context on what’s going on.
Example:
# Correct: UsersRepository.update(cache=True) # Wrong: UsersRepository.update(True)
New in version 0.6.0.
-
error_template= 'Found boolean non-keyword argument: {0}'¶
-
code= 425¶
Design¶
-
class
NestedFunctionViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to have nested functions.
- Reasoning:
- Nesting functions is a bad practice. It is hard to test them, it is hard then to separate them. People tend to overuse closures, so it’s hard to manage the dataflow.
- Solution:
- Just write flat functions, there’s no need to nest them. Pass parameters as normal arguments, do not use closures. Until you need them for decorators or factories.
We also disallow to nest
lambdaandasyncfunctions.See
NESTED_FUNCTIONS_WHITELISTfor the whole list of whitelisted names.Example:
# Correct: def do_some(): ... def other(): ... # Wrong: def do_some(): def inner(): ...
New in version 0.1.0.
-
error_template= 'Found nested function: {0}'¶
-
code= 430¶
-
class
NestedClassViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use nested classes.
- Reasoning:
- Nested classes are really hard to manage. You can not even create an instance of this class in many cases. Testing them is also really hard.
- Solution:
- Just write flat classes, there’s no need nest them. If you are nesting classes inside a function for parametrization, then you will probably need to use different design (or metaclasses).
See
NESTED_CLASSES_WHITELISTfor the full list of whitelisted names.Example:
# Correct: class Some(object): ... class Other(object): ... # Wrong: class Some(object): class Inner(object): ...
New in version 0.1.0.
-
error_template= 'Found nested class: {0}'¶
-
code= 431¶
-
class
MagicNumberViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use magic numbers in your code.
What we call a “magic number”? Well, it is actually any number that appears in your code out of nowhere. Like
42. Or0.32.- Reasoning:
- It is very hard to remember what these numbers actually mean.
Why were they used? Should they ever be changed?
Or are they eternal like
3.14? - Solution:
- Give these numbers a name! Move them to a separate variable, giving more context to the reader. And by moving things into new variables you will trigger other complexity checks.
Example:
# Correct: price_in_euro = 3.33 # could be changed later total = get_items_from_cart() * price_in_euro # Wrong: total = get_items_from_cart() * 3.33
What are numbers that we exclude from this check? Any numbers that are assigned to a variable, array, dictionary, or keyword arguments inside a function.
intnumbers that are in range[-10, 10]and some other common numbers, that are defined inMAGIC_NUMBERS_WHITELISTNew in version 0.1.0.
-
code= 432¶
-
error_template= 'Found magic number: {0}'¶
-
class
StaticMethodViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use
@staticmethoddecorator.- Reasoning:
- Static methods are not required to be inside the class. Because they even do not have access to the current instance.
- Solution:
- Use instance methods,
@classmethod, or functions instead.
New in version 0.1.0.
-
error_template= 'Found using `@staticmethod`'¶
-
code= 433¶
-
class
BadMagicMethodViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use some magic methods.
- Reasoning:
- We forbid to use magic methods related to the forbidden language parts.
Likewise, we forbid to use
delkeyword, so we forbid to use all magic methods related to it. - Solution:
- Refactor your code to use custom methods instead. It will give more context to your app.
See
MAGIC_METHODS_BLACKLISTfor the full blacklist of the magic methods.New in version 0.1.0.
-
error_template= 'Found using restricted magic method: {0}'¶
-
code= 434¶
-
class
NestedImportViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to have nested imports in functions.
- Reasoning:
- Usually, nested imports are used to fix the import cycle. So, nested imports show that there’s an issue with your design.
- Solution:
- You don’t need nested imports, you need to refactor your code. Introduce a new module or find another way to do what you want to do. Rethink how your layered architecture should look like.
Example:
# Correct: from my_module import some_function def some(): ... # Wrong: def some(): from my_module import some_function
New in version 0.1.0.
-
error_template= 'Found nested import'¶
-
code= 435¶
-
class
RedundantLoopElseViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use
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')
New in version 0.3.0.
-
error_template= 'Found `else` in a loop without `break`'¶
-
code= 436¶
-
class
RedundantFinallyViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use
finallyintryblock withoutexceptblock.- 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()
New in version 0.3.0.
-
error_template= 'Found `finally` in `try` block without `except`'¶
-
code= 437¶
-
class
ReassigningVariableToItselfViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to assign variable to itself.
- Reasoning:
- There is no need to do that. Generally, it is an indication of some errors or just dead code.
Example:
# Correct: some = some + 1 x_coord, y_coord = y_coord, x_coord # Wrong: some = some x_coord, y_coord = x_coord, y_coord
New in version 0.3.0.
-
error_template= 'Found reassigning variable to itself'¶
-
code= 438¶
-
class
YieldInsideInitViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use
yieldinside of__init__method.- Reasoning:
__init__should be used to initialize new objects. It shouldn’tyieldanything because it should returnNoneby the convention.
Example:
# Correct: class Example(object): def __init__(self): self._public_items_count = 0 # Wrong: class Example(object): def __init__(self): yield 10
New in version 0.3.0.
-
error_template= 'Found `yield` inside `__init__` method'¶
-
code= 439¶
-
class
ProtectedModuleViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to import protected modules.
- Reasoning:
- When importing protected modules we break a contract that authors of this module enforce. This way we are not respecting encapsulation and it may break our code at any moment.
- Solution:
- Do not import anything from protected modules. Respect the encapsulation.
Example:
# Correct: from some.public.module import FooClass # Wrong: import _compat from some._protected.module import BarClass from some.module import _protected
New in version 0.3.0.
-
error_template= 'Found protected module import'¶
-
code= 440¶
-
class
ProtectedAttributeViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use protected attributes and methods.
- Reasoning:
- When using protected attributes and method we break a contract that authors of this class enforce. This way we are not respecting encapsulation and it may break our code at any moment.
- Solution:
- Do not use protected attributes and methods. Respect the encapsulation.
Example:
# Correct: self._protected = 1 cls._hidden_method() some.public() # Wrong: print(some._protected) instance._hidden() self.container._internal = 10
Note, that it is possible to use protected attributes with
selfandclsas base names. We allow this so you can create and use protected attributes and methods inside the class context. This is how protected attributes should be used.New in version 0.3.0.
-
error_template= 'Found protected attribute usage: {0}'¶
-
code= 441¶
-
class
LambdaInsideLoopViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use
lambdainside loops.- Reasoning:
- It is error-prone to use
lambdainsideforandwhileloops due to the famous late-binding. - Solution:
- Use regular functions, factory functions, or
partialfunctions. Save yourself from possible confusion.
Example:
# Correct: for index in range(10): some.append(partial_function(index)) # Wrong: for index in range(10): some.append(lambda index=index: index * 10)) other.append(lambda: index * 10))
New in version 0.5.0.
-
error_template= "Found `lambda` in loop's body"¶
-
code= 442¶
-
class
UnreachableCodeViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to have unreachable code.
What is unreachable code? It is some lines of code that cannot be executed by python’s interpreter.
This is probably caused by
returnorraisestatements. However, we can not cover 100% of truly unreachable code by this rule. This happens due to the dynamic nature of python. For example, detecting that1 / some_valuewould sometimes raise an exception is too complicated and is out of the scope of this rule.- Reasoning:
- Having dead code in your project is an indicator that you do not care about your code base at all. It dramatically reduces code quality and readability. It also demotivates team members.
- Solution:
- Delete any unreachable code you have. Or refactor it, if this happens by your mistake.
Example:
# Correct: def some_function(): print('This line is reachable, all good') return 5 # Wrong: def some_function(): return 5 print('This line is unreachable')
New in version 0.5.0.
-
error_template= 'Found unreachable code'¶
-
code= 443¶
-
class
StatementHasNoEffectViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to have statements that do nothing.
- Reasoning:
- Statements that just access the value or expressions used as statements indicate that your code contains deadlines. They just pollute your codebase and do nothing.
- Solution:
- Refactor your code in case it was a typo or error. Or just delete this code.
Example:
# Correct: def some_function(): price = 8 + 2 return price # Wrong: def some_function(): 8 + 2 print
New in version 0.5.0.
-
error_template= 'Found statement that has no effect'¶
-
code= 444¶
-
class
MultipleAssignmentsViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to have statements that do nothing.
- Reasoning:
- Multiple assignments on the same line might not do what you think they do. They can also grown pretty long. And you will not notice the rising complexity of your code.
- Solution:
- Use separate lines for each assignment.
Example:
# Correct: a = 1 b = 1 # Wrong: a = b = 1
New in version 0.6.0.
-
error_template= 'Found multiple assign targets'¶
-
code= 445¶
-
class
IncorrectUnpackingViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to have statements that do nothing.
- Reasoning:
- Having unpacking with side-effects is very dirty. You might get in serious and very hard-to-debug troubles because of this technique. So, do not use it.
- Solution:
- Use unpacking with only variables, not any other entities.
Example:
# Correct: first, second = some() # Wrong: first, some_dict['alias'] = some()
New in version 0.6.0.
-
error_template= 'Found incorrect unpacking target'¶
-
code= 446¶
-
class
DuplicateExceptionViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to have the same exception class in multiple
exceptblocks.- Reasoning:
- Having the same exception name in different blocks means that something is not right: since only one branch will work. Other one will always be ignored. So, that is clearly an error.
- Solution:
- Use unique exception handling rules.
Example:
# Correct: try: ... except ValueError: ... # Wrong: try: ... except ValueError: ... except ValueError: ...
New in version 0.6.0.
-
error_template= 'Found duplicate exception: {0}'¶
-
code= 447¶
-
class
YieldInComprehensionViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to have
yieldkeyword inside comprehensions.- Reasoning:
- Having the
yieldkeyword inside comprehensions is error-prone. You can shoot yourself in a foot by an inaccurate usage of this feature. - Solution:
- Use regular
forloops withyieldkeywords. Or create a separate generator function.
Example:
# Wrong: >>> list((yield letter) for letter in 'ab') ['a', None, 'b', None] >>> list([(yield letter) for letter in 'ab']) ['a', 'b']
New in version 0.7.0.
-
error_template= 'Found `yield` inside comprehension'¶
-
code= 448¶
-
class
NonUniqueItemsInSetViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to have duplicate items in
setliterals.- Reasoning:
- When you explicitly put duplicate items in
setliterals it just does not make any sense. Sincesetcan not contain duplicate items and they will be removed anyway. - Solution:
- Remove the duplicate items.
Example:
# Correct: some_set = {'a', variable1} some_set = {make_call(), make_call()} # Wrong: some_set = {'a', 'a', variable1, variable1}
Things that we consider duplicates: builtins and variables. These nodes are not checked because they may return different results:
- function and method calls
- comprehensions
- attributes
- subscribe operations
- containers: lists, dicts, tuples, sets
New in version 0.7.0.
-
error_template= 'Found non-unique item in `set` literal: {0}'¶
-
code= 449¶
-
class
BaseExceptionSubclassViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to have duplicate items in
setliterals.- Reasoning:
BaseExceptionis a special case: it is not designed to be extended by users. A lot of yourexcept Exceptioncases won’t work. That’s incorrect and dangerous.- Solution:
- Change the base class to
Exception.
Example:
# Correct: class MyException(Exception): ... # Wrong: class MyException(BaseException): ...
New in version 0.7.0.
-
error_template= 'Found exception inherited from `BaseException`'¶
-
code= 450¶
-
class
SimplifiableIfViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to have simplifiable
ifconditions.- Reasoning:
- This complex construction can cause frustration among other developers. It is longer, more verbose, and more complex.
- Solution:
- Use
bool()to convert test values to boolean values. Or just leave it as it is in case when 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.New in version 0.7.0.
-
error_template= 'Found simplifiable `if` condition'¶
-
code= 451¶
-
class
IncorrectClassBodyContentViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use incorrect nodes inside
classdefinitions.- Reasoning:
- Python allows us to have conditions, context managers,
and even infinite loops inside
classdefinitions. On the other hand, only methods, attributes, and docstrings make sense. So, we discourage using anything except these nodes in class bodies. - Solution:
- If you have complex logic inside your class definition, most likely that you do something wrong. There are different options to refactor this mess. You can try metaclasses, decorators, builders, and other patterns.
Example:
# Wrong: class Test(object): for _ in range(10): print('What?!')
We also allow some nested classes, check out
NestedClassViolationfor more information.New in version 0.7.0.
-
error_template= 'Found incorrect node inside `class` body'¶
-
code= 452¶
-
class
MethodWithoutArgumentsViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to have methods without any arguments.
- Reasoning:
- Methods withour arguments are allowed to be defined,
but almost impossible to use.
Furthermore, they don’t have an access to
self, so can not access the inner state of the object. It might be an intentional design or just a typo. - Solution:
- Move any methods with arguments to raw functions. Or just add an argument if it is actually required.
Example:
# Correct: class Test(object): def method(self): ... # Wrong: class Test(object): def method(): ...
New in version 0.7.0.
-
error_template= 'Found method without arguments: {0}'¶
-
code= 453¶
-
class
IncorrectBaseClassViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to have methods without any arguments.
- Reasoning:
- In Python you can specify anything in the base classes slot. In runtime this expression will be evaluated and executed. We need to prevent dirty hacks in this field.
- Solution:
- Use only attributes, names, and types to be your base classes.
Example:
# Correct: class Test(module.ObjectName, MixinName, keyword=True): ... class GenericClass(Generic[ValueType]): ... # Wrong: class Test((lambda: object)()): ...
New in version 0.7.0.
Changed in version 0.7.1.
-
error_template= 'Found incorrect base class'¶
-
code= 454¶
-
class
IncorrectSlotsViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to have incorrect
__slots__definition.- Reasoning:
__slots__is a very special attribute. It completely changes your class. So, we need to be careful with it. We should not allow anything rather than tuples to define slots, we also need to check that fields defined in__slots__are unique.- Solution:
- Use tuples with unique elements to define
__slots__attribute.
Example:
# Correct: class Test(object): __slots__ = ('field1', 'field2') class Other(Test): __slots__ = Test.__slots__ + ('child',) # Wrong: class Test(object): __slots__ = ['field1', 'field2', 'field2']
Note, that we do ignore all complex expressions for this field. So, we only check raw literals.
New in version 0.7.0.
-
error_template= 'Found incorrect `__slots__` syntax'¶
-
code= 455¶
-
class
IncorrectSuperCallViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use
super()with parameters or outside of methods.- Reasoning:
super()is a very special function. It implicitly relies on the context where it is used and parameters passed to it. So, we should be very careful with parameters and context.- Solution:
- Use
super()without arguments and only inside methods.
Example:
# Correct: super().__init__() # Wrong: super(ClassName, self).__init__()
New in version 0.7.0.
-
error_template= 'Found incorrect `super()` call: {0}'¶
-
code= 456¶
-
class
RedundantReturningElseViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use redundant
elsecases in returning functions.We check single
ifstatements that all containreturnorraiseorbreakstatements with this rule. We do not checkifstatements withelifcases.- 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 redundant
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')
New in version 0.7.0.
-
error_template= 'Found redundant returning `else` statement'¶
-
code= 457¶
-
class
TryExceptMultipleReturnPathViolation(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use multiple
returnpath withtry/exceptcase.- Reasoning:
- The problem with
returninelseandfinallyis that it is impossible to say what value is going to be actually returned without looking up the implementation details. Why? Becausereturndoes not expect that some other code will be executed after it. But,finallyis always executed, even afterreturn. Andelsewill not be executed when there are no exceptions intrycase and areturnstatement. - Solution:
- Remove
returnfrom one of the cases.
Example:
# Wrong: try: return 1 # this line will never return except Exception: ... finally: return 2 # this line will actually return try: return 1 # this line will actually return except ZeroDivisionError: ... else: return 0 # this line will never return
New in version 0.7.0.
-
error_template= 'Found `try`/`else`/`finally` with multiple return paths'¶
-
code= 458¶