Best practices¶
These checks ensures that you follow the best practices.
It also
Note
Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Readability counts. Special cases aren’t special enough to break the rules. In the face of ambiguity, refuse the temptation to guess. There should be one– and preferably only one –obvious way to do it.
Summary¶
WrongMagicCommentViolation |
Restricts to use several control (or magic) comments. |
WrongDocCommentViolation |
Forbids to use empty doc 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. |
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. |
Comments¶
-
class
WrongMagicCommentViolation
(node=None, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.SimpleViolation
Restricts to use several control (or magic) comments.
We do not allow to use:
# noqa
comment without specified violations# type: some_type
comments to specify a type fortyped_ast
- Reasoning:
- We cover several different use-cases in a single rule.
# noqa
comment is restricted because it can hide other violations.# type: some_type
comment is restricted because we can already use type annotations instead. - Solution:
- Use
# noqa
comments with specified error types. Use type annotations to specify types.
We still allow to use
# type: ignore
comment. Since sometimes it is totally required.Example:
# Correct: type = MyClass.get_type() # noqa: A001 coordinate: int = 10 some.int_field = 'text' # type: ignore # Wrong: type = MyClass.get_type() # noqa coordinate = 10 # type: int
Note
Returns Z400 as error code
-
class
WrongDocCommentViolation
(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.TokenizeViolation
Forbids to use empty doc comments (
#:
).- Reasoning:
- Doc comments are used to provide a documentation. But supling 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
pycodestyle
checks.Example:
# Correct: #: List of allowed names: NAMES_WHITELIST = ['feature', 'bug', 'research'] # Wrong: #: NAMES_WHITELIST = ['feature', 'bug', 'research']
Note
Returns Z401 as error code
Modules¶
-
class
WrongModuleMetadataViolation
(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids 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_resources
if you need to import this data into your app.
See
BAD_MODULE_METADATA_VARIABLES
for full list of bad names.Example:
# Wrong: __author__ = 'Nikita Sobolev' __version__ = 0.1.2
Note
Returns Z410 as error code
-
class
EmptyModuleViolation
(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids to have empty modules.
- Reasoning:
- Why is it even there? Do not polute 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
Note
Returns Z411 as error code
-
class
InitModuleHasLogicViolation
(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids 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
Note
Returns Z412 as error code
Builtins¶
-
class
WrongKeywordViolation
(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids to use some keywords from
python
.- Reasoning:
- We believe, tha some keywords are anti-patterns.
They promote bad-practices like
global
andpass
, or just not user-friendly likedel
. - Solution:
- Solutions differ from keyword to keyword.
pass
should be replaced with docstring orcontextlib.suppress
.del
should be replaced with specialized methods like.pop()
.global
andnonlocal
usages should be refactored.
Example:
# Wrong: pass del nonlocal global
Note
Returns Z420 as error code
-
class
WrongFunctionCallViolation
(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids to call some built-in functions.
- Reasoning:
- Some functions are only suitable for very specific usecases, we forbid to use them in a free manner.
See
BAD_FUNCTIONS
for the full list of blacklisted functions.Note
Returns Z421 as error code
-
class
FutureImportViolation
(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids to use
__future__
imports.- Reasoning:
- Almost all
__future__
imports are legacypython2
compatibility tools that are no longer required. - Solution:
- Remove them. Drop
python2
support.
Except, there are some new ones for
python4
support. SeeFUTURE_IMPORTS_WHITELIST
for the full list of allowed future imports.Example:
# Correct: from __future__ import annotations # Wrong: from __future__ import print_function
Note
Returns Z422 as error code
-
class
RaiseNotImplementedViolation
(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids to use
NotImplemented
error.- Reasoning:
- These two violations look so similar.
But, these violations have different use cases.
Use cases of
NotImplemented
is too limited to be generally available. - Solution:
- Use
NotImplementedError
.
Example:
# Correct: raise NotImplementedError('To be done') # Wrong: raise NotImplemented
Note
Returns Z423 as error code
Design¶
-
class
NestedFunctionViolation
(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids 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
lambda
functions.See
NESTED_FUNCTIONS_WHITELIST
for the whole list of whitelisted names.Example:
# Correct: def do_some(): ... def other(): ... # Wrong: def do_some(): def inner(): ...
Note
Returns Z430 as error code
-
class
NestedClassViolation
(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids 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_WHITELIST
for the full list of whitelisted names.Example:
# Correct: class Some(object): ... class Other(object): ... # Wrong: class Some(object): class Inner(object): ...
Note
Returns Z431 as error code
-
class
MagicNumberViolation
(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids 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, givin 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 number that we exclude from this check? Any numbers that are assigned to a variable, array, dictionary, or keyword arguments inside a function.
int
numbers that are in range[-10, 10]
and some other common numbers, that are defined inMAGIC_NUMBERS_WHITELIST
Note
Returns Z432 as error code
-
class
StaticMethodViolation
(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids to use
@staticmethod
decorator.- Reasoning:
- Static methods are not required to be inside the class. Because it even does not an access to the current instance.
- Solution:
- Use instance methods,
@classmethod
, or functions instead.
Note
Returns Z433 as error code
-
class
BadMagicMethodViolation
(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids to use some magic methods.
- Reasoning:
- We forbid to use magic methods related to the forbidden language parts.
Like, we forbid to use
del
keyword, so we forbid to use all magic methods related to it. - Solution:
- Refactor you code to use custom methods instead. It will give more context to your app.
See
BAD_MAGIC_METHODS
for the full blacklist of the magic methods.Note
Returns Z434 as error code
-
class
NestedImportViolation
(node, text=None)[source]¶ Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids 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 you design.
- Solution:
- You don’t need nested imports, you need to refactor your code. Introduce a new module, a find another way to do what you want to do. Rething 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
Note
Returns Z435 as error code
-
class
WrongMagicCommentViolation
(node=None, text=None)[source] Bases:
wemake_python_styleguide.violations.base.SimpleViolation
Restricts to use several control (or magic) comments.
We do not allow to use:
# noqa
comment without specified violations# type: some_type
comments to specify a type fortyped_ast
- Reasoning:
- We cover several different use-cases in a single rule.
# noqa
comment is restricted because it can hide other violations.# type: some_type
comment is restricted because we can already use type annotations instead. - Solution:
- Use
# noqa
comments with specified error types. Use type annotations to specify types.
We still allow to use
# type: ignore
comment. Since sometimes it is totally required.Example:
# Correct: type = MyClass.get_type() # noqa: A001 coordinate: int = 10 some.int_field = 'text' # type: ignore # Wrong: type = MyClass.get_type() # noqa coordinate = 10 # type: int
Note
Returns Z400 as error code
-
error_template
= 'Found wrong magic comment: {0}'¶ Error message shown to the user.
-
class
WrongDocCommentViolation
(node, text=None)[source] Bases:
wemake_python_styleguide.violations.base.TokenizeViolation
Forbids to use empty doc comments (
#:
).- Reasoning:
- Doc comments are used to provide a documentation. But supling 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
pycodestyle
checks.Example:
# Correct: #: List of allowed names: NAMES_WHITELIST = ['feature', 'bug', 'research'] # Wrong: #: NAMES_WHITELIST = ['feature', 'bug', 'research']
Note
Returns Z401 as error code
-
error_template
= 'Found wrong doc comment'¶ Error message shown to the user.
-
class
WrongModuleMetadataViolation
(node, text=None)[source] Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids 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_resources
if you need to import this data into your app.
See
BAD_MODULE_METADATA_VARIABLES
for full list of bad names.Example:
# Wrong: __author__ = 'Nikita Sobolev' __version__ = 0.1.2
Note
Returns Z410 as error code
-
error_template
= 'Found wrong metadata variable {0}'¶ Error message shown to the user.
-
class
EmptyModuleViolation
(node, text=None)[source] Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids to have empty modules.
- Reasoning:
- Why is it even there? Do not polute 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
Note
Returns Z411 as error code
-
error_template
= 'Found empty module'¶ Error message shown to the user.
-
class
InitModuleHasLogicViolation
(node, text=None)[source] Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids 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
Note
Returns Z412 as error code
-
error_template
= 'Found `__init__` module with logic'¶ Error message shown to the user.
-
class
WrongKeywordViolation
(node, text=None)[source] Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids to use some keywords from
python
.- Reasoning:
- We believe, tha some keywords are anti-patterns.
They promote bad-practices like
global
andpass
, or just not user-friendly likedel
. - Solution:
- Solutions differ from keyword to keyword.
pass
should be replaced with docstring orcontextlib.suppress
.del
should be replaced with specialized methods like.pop()
.global
andnonlocal
usages should be refactored.
Example:
# Wrong: pass del nonlocal global
Note
Returns Z420 as error code
-
error_template
= 'Found wrong keyword "{0}"'¶ Error message shown to the user.
-
class
WrongFunctionCallViolation
(node, text=None)[source] Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids to call some built-in functions.
- Reasoning:
- Some functions are only suitable for very specific usecases, we forbid to use them in a free manner.
See
BAD_FUNCTIONS
for the full list of blacklisted functions.Note
Returns Z421 as error code
-
error_template
= 'Found wrong function call "{0}"'¶ Error message shown to the user.
-
class
FutureImportViolation
(node, text=None)[source] Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids to use
__future__
imports.- Reasoning:
- Almost all
__future__
imports are legacypython2
compatibility tools that are no longer required. - Solution:
- Remove them. Drop
python2
support.
Except, there are some new ones for
python4
support. SeeFUTURE_IMPORTS_WHITELIST
for the full list of allowed future imports.Example:
# Correct: from __future__ import annotations # Wrong: from __future__ import print_function
Note
Returns Z422 as error code
-
error_template
= 'Found future import "{0}"'¶ Error message shown to the user.
-
class
RaiseNotImplementedViolation
(node, text=None)[source] Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids to use
NotImplemented
error.- Reasoning:
- These two violations look so similar.
But, these violations have different use cases.
Use cases of
NotImplemented
is too limited to be generally available. - Solution:
- Use
NotImplementedError
.
Example:
# Correct: raise NotImplementedError('To be done') # Wrong: raise NotImplemented
Note
Returns Z423 as error code
-
error_template
= 'Found raise NotImplemented'¶ Error message shown to the user.
-
class
NestedFunctionViolation
(node, text=None)[source] Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids 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
lambda
functions.See
NESTED_FUNCTIONS_WHITELIST
for the whole list of whitelisted names.Example:
# Correct: def do_some(): ... def other(): ... # Wrong: def do_some(): def inner(): ...
Note
Returns Z430 as error code
-
error_template
= 'Found nested function "{0}"'¶ Error message shown to the user.
-
class
NestedClassViolation
(node, text=None)[source] Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids 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_WHITELIST
for the full list of whitelisted names.Example:
# Correct: class Some(object): ... class Other(object): ... # Wrong: class Some(object): class Inner(object): ...
Note
Returns Z431 as error code
-
error_template
= 'Found nested class "{0}"'¶ Error message shown to the user.
-
class
MagicNumberViolation
(node, text=None)[source] Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids 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, givin 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 number that we exclude from this check? Any numbers that are assigned to a variable, array, dictionary, or keyword arguments inside a function.
int
numbers that are in range[-10, 10]
and some other common numbers, that are defined inMAGIC_NUMBERS_WHITELIST
Note
Returns Z432 as error code
-
error_template
= 'Found magic number: {0}'¶ Error message shown to the user.
-
class
StaticMethodViolation
(node, text=None)[source] Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids to use
@staticmethod
decorator.- Reasoning:
- Static methods are not required to be inside the class. Because it even does not an access to the current instance.
- Solution:
- Use instance methods,
@classmethod
, or functions instead.
Note
Returns Z433 as error code
-
error_template
= 'Found using `@staticmethod`'¶ Error message shown to the user.
-
class
BadMagicMethodViolation
(node, text=None)[source] Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids to use some magic methods.
- Reasoning:
- We forbid to use magic methods related to the forbidden language parts.
Like, we forbid to use
del
keyword, so we forbid to use all magic methods related to it. - Solution:
- Refactor you code to use custom methods instead. It will give more context to your app.
See
BAD_MAGIC_METHODS
for the full blacklist of the magic methods.Note
Returns Z434 as error code
-
error_template
= 'Found using restricted magic method "{0}"'¶ Error message shown to the user.
-
class
NestedImportViolation
(node, text=None)[source] Bases:
wemake_python_styleguide.violations.base.ASTViolation
Forbids 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 you design.
- Solution:
- You don’t need nested imports, you need to refactor your code. Introduce a new module, a find another way to do what you want to do. Rething 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
Note
Returns Z435 as error code
-
error_template
= 'Found nested import "{0}"'¶ Error message shown to the user.