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¶
Restricts to use several control (or magic) comments. |
|
Forbids to use empty doc comments ( |
|
Forbids to use too many |
|
Forbids to use too many |
|
Forbids to use complex defaults. |
|
Forbids to use anything rather than |
|
Forbids to use anything rather than |
|
Forbids mutable constants on a module level. |
|
Forbids to use the same logical conditions in one expression. |
|
Forbids to heterogenous operators in one compare. |
|
Forbids to have some module level variables. |
|
Forbids to have empty modules. |
|
Forbids to have logic inside |
|
Forbids to use |
|
Forbids to have tuple unpacking with side-effects. |
|
Forbids to have the same exception class in multiple |
|
Forbids to have |
|
Forbids to have duplicate items in hashes. |
|
Forbids to have duplicate items in |
|
Forbids to use multiple returning paths with |
|
Forbids to use some |
|
Forbids to call some built-in functions. |
|
Forbids to use |
|
Forbids to use |
|
Forbids to use |
|
Forbids to pass booleans as non-keyword parameters. |
|
Forbids to use |
|
Forbids to have unreachable code. |
|
Forbids to have statements that do nothing. |
|
Forbids to have multiple assignments on the same line. |
|
Forbids to have nested functions. |
|
Forbids to use nested classes. |
|
Forbids to use magic numbers in your code. |
|
Forbids to have nested imports in functions. |
|
Forbids to assign variable to itself. |
|
Forbids to multiply lists. |
|
Forbids to import protected modules. |
|
Forbids to use protected attributes and methods. |
|
Forbids to raise |
|
Forbids to use unicode escape sequences in binary strings. |
|
Forbids to local and block variables to overlap. |
|
Forbids to use control variables after the block body. |
|
Forbids to shadow variables from outer scopes. |
|
Forbids to use exlicit unhashable types as set items and dict keys. |
|
Forbids to use exlicit falsly-evaluated conditions with several keywords. |
|
Forbids to have wrong named keywords in starred dicts. |
|
Forbids to use approximate constants. |
|
Forbid to use alphabet as a string. |
|
Forbids the use of incorrect order of |
|
Forbids to define and use |
|
Forbids to import protected objects from modules. |
|
Forbids to use positional only or |
|
Forbids to use |
|
Forbids to execute the file with shebang incorrectly set. |
Best practices¶
-
class
WrongMagicCommentViolation(node=None, text=None, baseline=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
This violation is reported at the top of the module, so it cannot be locally ignored.
- 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: WPS125 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, baseline=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, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.SimpleViolationForbids to use too many
# noqacomments.We count it on a per-module basis.
- Reasoning:
Having too many
# noqacomments make your code less readable and clearly indicates that there’s something wrong with it.- Solution:
Refactor your code to match our style. Or use a config file to switch off some checks.
- Configuration:
This rule is configurable with
--max-noqa-comments. Default: 10
New in version 0.7.0.
-
error_template= 'Found `noqa` comments overuse: {0}'¶
-
code= 402¶
-
class
OveruseOfNoCoverCommentViolation(node=None, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.SimpleViolationForbids to use too many
# pragma: no covercomments.We count it on a per-module basis. We use 5 as a default value.
- Reasoning:
Having too many
# pragma: no covercomments clearly indicates that there’s something wrong with it. Moreover, it makes your tests useless, since they do not cover a big partion of your code.- Solution:
Refactor your code to much the style. Or use a config file to switch off some checks.
New in version 0.8.0.
-
error_template= 'Found `noqa` comments overuse: {0}'¶
-
code= 403¶
-
class
ComplexDefaultValueViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use complex defaults.
Anything that is not a
ast.Name,ast.Attribute,ast.Str,ast.NameConstant,ast.Tuple,ast.Bytes,ast.Numorast.Ellipsisshould be moved out from defaults.- Reasoning:
It can be tricky. Nothing stops you from making database calls or http requests in such expressions. It is also not readable for us.
- Solution:
Move the expression out from default value.
Example:
# Correct: SHOULD_USE_DOCTEST = 'PYFLAKES_DOCTEST' in os.environ def __init__(self, with_doctest=SHOULD_USE_DOCTEST): # Wrong: def __init__(self, with_doctest='PYFLAKES_DOCTEST' in os.environ):
New in version 0.8.0.
Changed in version 0.11.0.
-
error_template= 'Found complex default value'¶
-
code= 404¶
-
previous_codes= {459}¶
-
class
LoopVariableDefinitionViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use anything rather than
ast.Nameto define loop variables.- Reasoning:
When defining a
forloop with attributes, indexes, calls, or any other nodes it does dirty things inside.- Solution:
Use regular
ast.Namevariables. Or tuple ofast.Namevariables. Star names are also fine.
Example:
# Correct: for person in database.people(): ... # Wrong: for context['person'] in database.people(): ...
New in version 0.8.0.
Changed in version 0.11.0.
-
error_template= 'Found wrong `for` loop variable definition'¶
-
code= 405¶
-
previous_codes= {460}¶
-
class
ContextManagerVariableDefinitionViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use anything rather than
ast.Nameto define contexts.- Reasoning:
When defining a
withcontext managers with attributes, indexes, calls, or any other nodes it does dirty things inside.- Solution:
Use regular
ast.Namevariables. Or tuple ofast.Namevariables. Star names are also fine.
Example:
# Correct: with open('README.md') as readme: ... # Wrong: with open('README.md') as files['readme']: ...
New in version 0.8.0.
Changed in version 0.11.0.
-
error_template= 'Found wrong context manager variable definition'¶
-
code= 406¶
-
previous_codes= {461}¶
-
class
MutableModuleConstantViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids mutable constants on a module level.
- Reasoning:
Constants should be immutable.
- Solution:
Use immutable types for constants.
We only treat
ast.Set,ast.Dict,ast.List, and comprehensions as mutable things. All other nodes are still fine.Example:
# Correct: import types CONST1 = frozenset((1, 2, 3)) CONST2 = (1, 2, 3) CONST3 = types.MappingProxyType({'key': 'value'}) # Wrong: CONST1 = {1, 2, 3} CONST2 = [x for x in some()] CONST3 = {'key': 'value'}
New in version 0.10.0.
Changed in version 0.11.0.
-
error_template= 'Found mutable module constant'¶
-
code= 407¶
-
previous_codes= {466}¶
-
class
SameElementsInConditionViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use the same logical conditions in one expression.
- Reasoning:
Using the same name in logical condition more that once indicates that you are either making a logical mistake, or just over-complicating your design.
- Solution:
Remove the duplicating condition.
Example:
# Correct: if some_value or other_value: ... # Wrong: if some_value or some_value: ...
New in version 0.10.0.
Changed in version 0.11.0.
Changed in version 0.13.0.
-
error_template= 'Found duplicate logical condition'¶
-
code= 408¶
-
previous_codes= {469}¶
-
class
HeterogenousCompareViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to heterogenous operators in one compare.
Note, that we allow to mix
>with>=and<with<=operators.- Reasoning:
This is hard to read and understand.
- Solution:
Refactor the expression to have separate parts joined with
andboolean operator.
Example:
# Correct: if x == y == z: ... if x > y >= z: ... # Wrong: if x > y == 5: ... if x == y != z: ...
New in version 0.10.0.
Changed in version 0.11.0.
-
error_template= 'Found heterogenous compare'¶
-
code= 409¶
-
previous_codes= {471}¶
-
class
WrongModuleMetadataViolation(node, text=None, baseline=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. Useimportlib.metadata(orimportlib_metadataon python < 3.8) if 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, baseline=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, baseline=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-codeand--i-dont-control-code. Default: True
New in version 0.1.0.
-
error_template= 'Found `__init__.py` module with logic'¶
-
code= 412¶
-
class
BadMagicModuleFunctionViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use
__getattr__and__dir__module magic methods.- Reasoning:
It does not bring any features, only making it harder to understand what is going on.
- Solution:
Refactor your code to use custom methods instead.
- Configuration:
This rule is configurable with
--i-control-codeand--i-dont-control-code. Default: True
New in version 0.9.0.
-
error_template= 'Found bad magic module function: {0}'¶
-
code= 413¶
-
class
WrongUnpackingViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to have tuple unpacking with side-effects.
- 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.
Changed in version 0.11.0.
-
error_template= 'Found incorrect unpacking target'¶
-
code= 414¶
-
previous_codes= {446}¶
-
class
DuplicateExceptionViolation(node, text=None, baseline=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.
Changed in version 0.11.0.
-
error_template= 'Found duplicate exception: {0}'¶
-
code= 415¶
-
previous_codes= {447}¶
-
class
YieldInComprehensionViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to have
yieldkeyword inside comprehensions.This is a
SyntaxErrorstarting frompython3.8.- 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') # Will resilt in: ['a', None, 'b', None] list([(yield letter) for letter in 'ab']) # Will result in: ['a', 'b']
New in version 0.7.0.
Changed in version 0.11.0.
-
error_template= 'Found `yield` inside comprehension'¶
-
code= 416¶
-
previous_codes= {448}¶
-
class
NonUniqueItemsInHashViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to have duplicate items in hashes.
- Reasoning:
When you explicitly put duplicate items in
setliterals or indictkeys it just does not make any sense. Since hashes cannot contain duplicate items and they will be removed anyway.- Solution:
Remove 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
New in version 0.7.0.
Changed in version 0.11.0.
Changed in version 0.12.0.
-
error_template= 'Found non-unique item in hash: {0}'¶
-
code= 417¶
-
previous_codes= {449}¶
-
class
BaseExceptionSubclassViolation(node, text=None, baseline=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.
Changed in version 0.11.0.
-
error_template= 'Found exception inherited from `BaseException`'¶
-
code= 418¶
-
previous_codes= {450}¶
-
class
TryExceptMultipleReturnPathViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use multiple returning paths with
try/exceptcase.Note, that we check for any
return,break, orraisenodes.- 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:
# Correct: try: return 1 except YourException: ... finally: clear_things_up() # 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.
Changed in version 0.11.0.
Changed in version 0.12.0.
-
error_template= 'Found `try`/`else`/`finally` with multiple return paths'¶
-
code= 419¶
-
previous_codes= {458}¶
-
class
WrongKeywordViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use some
pythonkeywords.- Reasoning:
Using some keywords generally gives you more pain that relieve.
delkeyword is not composable with other functions, you cannot pass it as a regular function. It is also quite error-prone due to__del__magic method complexity and thatdelis actually used to nullify variables and delete them from the execution scope. Moreover, it has a lot of substitutions. You won’t miss it!passkeyword is just useless by design. There’s no usecase for it. Because it does literally nothing.globalandnonlocalpromote bad-practices of having an external mutable state somewhere. This solution does not scale. And leads to multiple possible mistakes in the future.- 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.
New in version 0.1.0.
-
error_template= 'Found wrong keyword: {0}'¶
-
code= 420¶
-
class
WrongFunctionCallViolation(node, text=None, baseline=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, baseline=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, baseline=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, baseline=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, baseline=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. The only exception from this rule is passing booleans as non-keyword argument when it is the only passed argument.
- Solution:
Pass booleans as keywords only. This will help you to save extra context on what’s going on.
Example:
# Correct: UserRepository.update(True) UsersRepository.add(user, cache=True) # Wrong: UsersRepository.add(user, True)
New in version 0.6.0.
-
error_template= 'Found boolean non-keyword argument: {0}'¶
-
code= 425¶
-
class
LambdaInsideLoopViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use
lambdainside loops.We check
while,for, andasync forloop bodies. We also check comprehension value parts.- 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.
Changed in version 0.11.0.
Changed in version 0.14.0.
-
error_template= "Found `lambda` in loop's body"¶
-
code= 426¶
-
previous_codes= {442}¶
-
class
UnreachableCodeViolation(node, text=None, baseline=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 cannot 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.
Changed in version 0.11.0.
-
error_template= 'Found unreachable code'¶
-
code= 427¶
-
previous_codes= {443}¶
-
class
StatementHasNoEffectViolation(node, text=None, baseline=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.
Changed in version 0.11.0.
-
error_template= 'Found statement that has no effect'¶
-
code= 428¶
-
previous_codes= {444}¶
-
class
MultipleAssignmentsViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to have multiple assignments on the same line.
- 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.
Changed in version 0.11.0.
-
error_template= 'Found multiple assign targets'¶
-
code= 429¶
-
previous_codes= {445}¶
-
class
NestedFunctionViolation(node, text=None, baseline=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, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use nested classes.
- Reasoning:
Nested classes are really hard to manage. You cannot 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).
- Configuration:
This rule is configurable with
--nested-classes-whitelist. Default: (‘Meta’, ‘Params’)
Example:
# Correct: class Some(object): ... class Other(object): ... # Wrong: class Some(object): class Inner(object): ...
New in version 0.1.0.
Changed in version 0.13.0.
-
error_template= 'Found nested class: {0}'¶
-
code= 431¶
-
class
MagicNumberViolation(node, text=None, baseline=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
NestedImportViolation(node, text=None, baseline=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.
Changed in version 0.11.0.
-
error_template= 'Found nested import'¶
-
code= 433¶
-
previous_codes= {435}¶
-
class
ReassigningVariableToItselfViolation(node, text=None, baseline=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.
Changed in version 0.11.0.
-
error_template= 'Found reassigning variable to itself: {0}'¶
-
code= 434¶
-
previous_codes= {438}¶
-
class
ListMultiplyViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to multiply lists.
- Reasoning:
When you multiply lists - it does not create new values, it creates references to the existing value. It is not what people mean in 99.9% of cases.
- Solution:
Use list comprehension or loop instead.
Example:
# Wrong: my_list = [1, 2, 3] * 3
New in version 0.12.0.
-
error_template= 'Found list multiply'¶
-
code= 435¶
-
class
ProtectedModuleViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to import protected modules.
Related to
ProtectedModuleMemberViolation.- 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 protected modules. Respect the encapsulation.
Example:
# Correct: import public_module from some.public.module import FooClass # Wrong: import _compat from some._protected.module import BarClass
New in version 0.3.0.
Changed in version 0.11.0.
Changed in version 0.14.0.
-
error_template= 'Found protected module import: {0}'¶
-
code= 436¶
-
previous_codes= {440}¶
-
class
ProtectedAttributeViolation(node, text=None, baseline=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() super()._protected() # Wrong: print(some._protected) instance._hidden() self.container._internal = 10
Note, that it is possible to use protected attributes with
self,cls, andsuper()as 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.
Changed in version 0.11.0.
-
error_template= 'Found protected attribute usage: {0}'¶
-
code= 437¶
-
previous_codes= {441}¶
-
class
StopIterationInsideGeneratorViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to raise
StopIterationinside generators.- Reasoning:
StopIterationshould not be raised explicitly in generators.- Solution:
Use return statement to get out of a generator.
Example:
# Correct: def some_generator(): if some_value: return yield 1 # Wrong: def some_generator(): if some_value: raise StopIteration yield 1
New in version 0.12.0.
-
error_template= 'Found `StopIteration` raising inside generator'¶
-
code= 438¶
-
class
WrongUnicodeEscapeViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.TokenizeViolationForbids to use unicode escape sequences in binary strings.
- Reasoning:
Binary strings do not work with unicode. Having unicode escape characters in there means that you have an error in your code.
- Solution:
Use regular strings when escaping unicode strings.
Example:
# Correct: escaped = '\u0041' # equals to 'A' # Wrong: escaped = b'\u0040' # equals to b'\\u0040'
New in version 0.12.0.
-
error_template= 'Found unicode escape in a binary string: {0}'¶
-
code= 439¶
-
class
BlockAndLocalOverlapViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to local and block variables to overlap.
What we call local variables:
Assigns and annotations
Function arguments (they are local to the function body)
What we call block variables:
Imports
Functions and async functions definitions
Classes, methods, and async methods definitions
For and async for loops variables
Except block exception aliases
We allow local variables to overlap theirselfs, we forbid block varibals to overlap theirselfs.
- Reasoning:
A lot of complex errors might happen when you shadow local varibales with block variables or when you shadow block variables with local variables.
- Solution:
Use names that do not overlap.
Example:
# Correct: my_value = 1 my_value = my_value + 1 # Wrong: import my_value my_value = 1 # overlaps with import
New in version 0.12.0.
-
error_template= 'Found block variables overlap: {0}'¶
-
code= 440¶
-
class
ControlVarUsedAfterBlockViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use control variables after the block body.
What we call block control variables:
forloop unpacked variableswithcontext variables
- Reasoning:
Variables leaking from the blocks can damage your logic. It might not contain what you think they contain.
- Solution:
Use names inside the scope they are defined. Create new functions to return values in case you need to use block variables: when searching for a value, etc.
Example:
# Correct: for my_item in collection: print(my_item) # Wrong: for my_item in collection: ... print(my_item)
New in version 0.12.0.
Changed in version 0.14.0.
-
error_template= 'Found control variable used after block: {0}'¶
-
code= 441¶
-
class
OuterScopeShadowingViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to shadow variables from outer scopes.
We check function, method, and module scopes. While we do not check class scope. Because class level constants are not available via regular name, and they are scope to
ClassName.var_name.- Reasoning:
Shadowing can lead you to a big pile of strage and unexpected bugs.
- Solution:
Use different names and do not allow scoping.
Example:
# Correct: def test(): ... def other(): test1 = 1 # Wrong: def test(): ... def other(): test = 1 # shadows `test()` function
New in version 0.12.0.
-
error_template= 'Found outer scope names shadowing: {0}'¶
-
code= 442¶
-
class
UnhashableTypeInHashViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use exlicit unhashable types as set items and dict keys.
- Reasoning:
This will resolve in
TypeErrorin runtime.- Solution:
Use hashable types to define set items and dict keys.
Example:
# Correct: my_dict = {1: {}, (1, 2): [], (2, 3): {1, 2}} # Wrong: my_dict = {[1, 2]: [], {2, 3}: {1, 2}}
New in version 0.12.0.
-
error_template= 'Found unhashable item'¶
-
code= 443¶
-
class
WrongKeywordConditionViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use exlicit falsly-evaluated conditions with several keywords.
We check:
ast.Whileast.Assert
We do not check variables, attributes, calls, bool and bin operators, etc. We disallow constants and some expressions.
- Reasoning:
Some conditions clearly tell us that this node won’t work correctly. So, we need to check that we can fix that.
- Solution:
Remove the unreachable node, or change the condition item.
Example:
# Correct: assert some_variable while True: ... # Wrong: assert [] while False: ...
New in version 0.12.0.
Changed in version 0.13.0.
-
error_template= 'Found wrong keyword condition'¶
-
code= 444¶
-
class
WrongNamedKeywordViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to have wrong named keywords in starred dicts.
- Reasoning:
Using wrong keywords in starred dict. Eg.:
print(**{'@': 1}).- Solution:
Don’t use incorrect identifiers for keywords.
Example:
# Correct: print(**{'end': '|'}) # Wrong: print(**{'3end': '|'})
New in version 0.13.0.
-
code= 445¶
-
error_template= 'Found wrong named keyword in starred dict'¶
-
class
ApproximateConstantViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use approximate constants.
- Reasoning:
Some constants are already defined. No need to write them again, use existing values. We just compare numbers as strings and raise this violation when they start with the same chars.
- Solution:
Use pre-defined constants.
Example:
# Correct: from math import pi random_number = 3.15 too_short = 3.1 # Wrong: pi = 3.14
See
MATH_APPROXIMATE_CONSTANTSfor full list of math constants that we check for.New in version 0.13.0.
-
code= 446¶
-
error_template= 'Found approximate constant: {0}'¶
-
class
StringConstantRedefinedViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbid to use alphabet as a string.
- Reasoning:
Some constants are already defined. No need to write them again, use existing values. We just compare strings and raise this violation when they have exactly the same chars.
- Solution:
Use pre-defined constants.
Example:
# Correct: import string UPPERCASE_ALPH = string.ascii_uppercase LOWERCASE_ALPH = string.ascii_lowercase # Wrong: GUESS_MY_NAME = "abcde...WXYZ" UPPERCASE_ALPH = "ABCD...WXYZ" LOWERCASE_ALPH = "abcd...wxyz"
New in version 0.13.0.
-
error_template= 'Found alphabet as strings: {0}'¶
-
code= 447¶
-
class
IncorrectExceptOrderViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids the use of incorrect order of
except.Note, we only check for built-in exceptions. Because we cannot statically identify the inheritance order of custom ones.
- Reasoning:
Using incorrect order of exceptions is error-prone, since you end up with some unreachable exception clauses.
- Solution:
Use correct order of exceptions.
Example:
# Correct: try: ... except ValueError: ... except Exception: ... # Wrong: try: ... except Exception: ... except ValueError: ...
See also
New in version 0.13.0.
-
error_template= 'Found incorrect exception order'¶
-
code= 448¶
-
class
FloatKeyViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to define and use
floatkeys.- Reasoning:
floatis a very ugly data type. It has a lot of “precision” errors. When we usefloatas keys we can hit this wall. We also cannot usefloatkeys with lists by design.- Solution:
Use other data types: integers, decimals, or use fuzzy logic.
Example:
# Correct: some = {1: 'a'} some[1] # Wrong: some = {1.0: 'a'} some[1.0]
New in version 0.13.0.
-
error_template= 'Found float used as a key'¶
-
code= 449¶
-
class
ProtectedModuleMemberViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to import protected objects from modules.
Related to
ProtectedModuleViolation.- Reasoning:
When importing protected modules’ members 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 protected objects from modules. Respect the encapsulation.
Example:
# Correct: from some.public.module import FooClass # Wrong: from some.module import _protected from some.module import _protected as not_protected
New in version 0.14.0.
-
error_template= 'Found protected object import: {0}'¶
-
code= 450¶
-
class
PositionalOnlyArgumentsViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use positional only or
/arguments.This violation is only raised for
python3.8+, earlier versions do not have this concept.- Reasoning:
This is a very rare case. Almost exclusively used by C code and stdlib. There’s no point in declaring your own parameters as positional only. It will break your code!
- Solution:
Use regular arguments. In case you are working with C, then this violation can be ignored.
Example:
# Correct: def my_function(first, second): ... # Wrong: def my_function(first, /, second): ...
New in version 0.14.0.
-
error_template= 'Found positional-only argument'¶
-
code= 451¶
-
class
LoopControlFinallyViolation(node, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolationForbids to use
breakandcontinueinfinallycase.Related to
TryExceptMultipleReturnPathViolation.- Reasoning:
Putting any control statements in finally is a terrible practice, because finally is implicitly called and can cause damage to your logic with its implicitness. We should not allow it.
- Solution:
Remove
breakandcontinuefromfinallyblocks.
Example:
# Correct: try: ... finally: ... # Wrong: try: ... finally: break try: ... finally: continue
New in version 0.14.0.
-
error_template= 'Found `break` or `continue` in `finally` block'¶
-
code= 452¶
-
class
ShebangViolation(node=None, text=None, baseline=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.SimpleViolationForbids to execute the file with shebang incorrectly set.
- A violation is raised in these cases :
Shebang is present but the file is not executable.
The file is executable but no shebang is present.
Shebang is present but does not contain “python”.
There is whitespace before shebang.
There are blank or comment lines before shebang.
- Reasoning:
Setting the shebang incorrectly causes executable mismatch.
- Solution:
Ensure the shebang is present on the first line, contains “python”, and there is no whitespace before.
Example:
# Correct: #!/usr/bin/env python # Wrong: #!/usr/bin/env #!/usr/bin/env python
New in version 0.14.0.
-
error_template= 'Found executable mismatch: {0}'¶
-
code= 453¶