wemake-services / wemake-python-styleguide Goto Github PK
View Code? Open in Web Editor NEWThe strictest and most opinionated python linter ever!
Home Page: https://wemake-python-styleguide.rtfd.io
License: MIT License
The strictest and most opinionated python linter ever!
Home Page: https://wemake-python-styleguide.rtfd.io
License: MIT License
Names like __some_name
should be forbiden, since there's no single use-case in python for real private variables.
Use public and protected variables instead.
When I do pipenv install -d
on MacOS, the pluggy=0.6.0
dependency isn't getting installed because of the wrong hash: THESE PACKAGES DO NOT MATCH THE HASHES FROM Pipfile.lock!
.
The package version pipenv
tries to install is: https://files.pythonhosted.org/packages/ba/65/ded3bc40bbf8d887f262f150fbe1ae6637765b5c9534bd55690ed2c0b0f7/pluggy-0.6.0-py3-none-any.whl
The problem can be caused by pipenv
itself (see pypa/pipenv#210).
Since I'm not sure I'm asking to verify that on other platforms.
Sometime I can see code like this:
try:
import django # noqa
except ImportError:
pass
This bare noqa
comment covers all possible issues on this line.
That's not what we want. We need to specify exact error numbers:
try:
import django # noqa: F401, Z101
except ImportError:
pass
signal
, because they are evil side effectsBooleanField
with null
, use NullBooleanField
CharField
with null
, use blank=True
with possible ''
as defaultCIEmailField
instead of EmailField
JSONField
other than django.contrib.postgres.fields.JSONField
default={}
inJSONField
, use default=dict
instead*_app
apps.py
and models.py
must be present*_app
folder, whitelist: models
, views
, forms
, admin
, serializers
, apps
, urls
, tasks
, __init__
I fell in love with poetry
. It works like a charm for python
libraries.
Here's an example: https://github.com/mimesis-lab/mimesis-factory
Currently our linter is full of magic constants like:
TODO: config
in the source codeWhat we need is:
0. create a file with default configuration values
setup.cfg
or any other standard flake8
toolsI am not sure that this is checked right now.
This is just a string in python3
, no need to use it.
Resources:
Code samples:
Styleguides:
We need to be sure that it is possible to suppress our warnings with # noqa
comments and other standard flake8
ways to do it.
Reference: http://flake8.pycqa.org/en/3.1.1/user/ignoring-errors.html
Examples of how to do it can be found here: https://github.com/PyCQA/flake8-bugbear/blob/master/bugbear.py#L38
In some cases on line
node_parent = getattr(node, 'parent')
of WrongModuleMetadataVisitor
we get
AttributeError: 'Assign' object has no attribute 'parent'
The bug can be fixed by the correct usage of getattr
:
node_parent = getattr(node, 'parent', None)
The PR with the fix and a regression test will be ready in a day.
I am not sure about these.
__init_subclass__
: class MyClass(MetaClass, option=1)
Side effect inside __init__.py
are nightmares.
We need to restrict any kind of python
code inside __init__.py
except:
Imports should be forbidden. Each separate module should have its own public API.
It is not 100% ready yet. But is very close to it.
https://github.com/Miserlou/JonesComplexity
Original issue: wemake-services/wemake-django-template#218
For example, the following is the only way in Django to inherit the Meta
class:
class Meta(BaseModel.Meta):
pass
But unfortunately it triggers WPS100 Found wrong keyword "pass"
.
More generally, the following should be allowed as it's a common thing to do:
class Foo(BarMixin, FooBase):
pass
Right now the # noqa
comment helps to avoid the warning.
I don't see any reasons why we should use them.
Let's use .format()
instead.
P.S. For a reason we can not forbid %
usage: gforcada/flake8-pep3101#23
We need to be sure that cases like:
class Model(models.Model):
class Meta: ... # error here, needs explicit base class
are covered.
Correct way to write this example is:
class Model(models.Model):
class Meta(object): ...
This should work for all NESTED_CLASSES_WHITELIST
.
As per the docs:
getattr(x, 'foobar')
is equivalent tox.foobar
This may lead a reader to believe that getattr(obj, 'attribute')
will not throw an exception.
x.foobar
getattr(x, 'foobar', None)
getattr(x, some_variable, None)
getattr(x, 'foobar')
We need to check function names length.
This should follow the same length rule as variables.
Variable names like async
and await
will not work in python3.7
.
They should be forbidden even in python3.6
.
In my opinion staticmethod
should not be used.
It is better to use regular methods or regular functions.
There should be nothing in between.
In python2
we had different classes: class Some:
and class Some(object):
were totally different things.
Currently, we don't have this thing in python3
, but since these times I believe that new-styled classes are still better.
object
class Base(object)
and class Child(Base)
vs class Base
and class Child(Base)
So, I believe we should ban classes with old-styled base class.
General rule is: always write super-classes' names
class Philosopher(object):
def __init_subclass__(cls, default_name, **kwargs):
...
class AustralianPhilosopher(Philosopher, default_name="Bruce"):
...
class WithMetaClass(object, metaclass=MyMeta):
...
class Philosopher: ...
class AustralianPhilosopher(default_name="Bruce"): ...
class WithMetaClass(metaclass=MyMeta): ...
Currently we just have a legacy version.py
file with version inside it.
It duplicates the version information from pyproject.toml
.
That's how it should be: python-poetry/poetry#273 (comment)
We need to apply the same rules for functions as we apply for variables.
Related #26
Rules to check and implement:
Meta
as whitelist)len(x) == 0
in if
conditionsTrue
checksraise
(without new exception) not within except
raise NotImplemented
__author__
/
linebrakesreturn
sexec
, eval
, and compile
vars()
, no dir()
print
, pprint
input
globals()
, no locals()
global
, no nonlocal
, no del
, no pass
from some import *
aka star-importfrom .. import some
aka dot import__import__
return
/yield
in __init__
self
overrideself
is not usedcls
or self
if not staticmethod
__init__
+ one other)__del__
None
: class Fixture: some_attribute = None
data
, result
max-file-lines = 600
__init__.py
__{}__
filenames, except __init__
and __main__
x: List[SomeValue] = []
, def cast(element: Element = None) -> str:
As far as I can tell, no fixture triggers the TooShortAttributeNameViolation
(see https://github.com/wemake-services/wemake-python-styleguide/blob/master/tests/test_checkers/test_wrong_variable.py#L20).
If this is an issue, feel free to assign it to me.
We should use annotations to provide types.
The only type comment that is allowed is: # type: ignore
You should not define your API like that. Use naming conventions: public
, _protected
.
And you should not use from some import *
. Use named imports.
So, we should ban this anti-pattern.
There's already a plugin for it! https://github.com/Korijn/flake8-assignexp/blob/master/flake8_assignexp.py
But, it is not a thing until python3.8
.
We need to add handler
to our variable blacklist.
I don't like the idea that some files are excluded from linting.
But, I believe that this might be useful for several cases.
But, we need to do it inside the configuration file, not in a separate file.
Why?
Because it is hard to tell which files are ignored, and which files are not.
In configuration it is pretty visible from the very first sight.
Related #53
When code has a lot of if
, try
, for
, and other branches it is hard to follow what is going on.
We can restrict the number of logic branches allowed for a single function.
That's how it should work:
if
is counted as +1
for the complexity, else
and elif
also counts as +1
for
is counted as +1
, else
is also counted as +1
while
is counted as +1
try
is counted as +1
, each except
case is counted as +1
with
is counted as +1
We need to figure out what number of branches is the most pleasant to have. We can consult pylint
for this.
Currently I am using subprocess
to run tests, that's way to expensive.
What I suggest is:
we need to rewrite tests to be more specific, covering only one issue at a time, here are the examples https://github.com/PyCQA/flake8-bugbear/blob/master/tests/test_bugbear.py and https://github.com/gforcada/flake8-builtins/blob/master/run_tests.py
we still need to run integration tests with subprocess
to be sure, that everything still works. But I feel like one test should be enough.
It is used only for some data-science pacakges, which we obviously do not use.
Other usages of this operator different from matrix multiplications should be banned.
They are not a thing in python3
anymore.
But, we should have a whitelist for things like annotations
and some new features that might come.
I also feel like we should save some more error code for imports and move other errors up a bit.
Are there any other magic method except __del__
to be restricted?
Related #44
We have to check that code like this:
class Test:
def method(self):
with some_manager():
try:
if self.call_method():
return True
except:
return False
raises TooDeepNestingViolation
error.
The optimal nesting level is 4
. So, code under try
should not have any nesting.
We need to check, that nested functions respect NESTED_FUNCTIONS_WHITELIST
values.
It is possible to write something like this:
import os.path
But instead we should write one of the following:
import os
from os import path
You should not use __del__
, as it is non-pythonic, more like cpp.
This method is not even called in several situations.
So, let's forbid it.
def test_call_flake8_version():
"""Checks that module is registered and visible in the meta data."""
output = subprocess.check_output(
['flake8', '--version'],
stderr=subprocess.STDOUT,
)
assert b'wemake-python-styleguide': ' in output
assert
outside of testsAs we have decided to stick to .format()
, we are banning f
strings: #32
But, @vergeev have also suggested to forbid 'string with %s' % some
.
Here's the backstory:
5 % 2
So, this would be valid:
some_variable % 'value1'
5 % 2
This would be invalid:
'format me %s' % 'value2'
Current noqa.py
misses these two rules.
We need to be sure that they are still skippable.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.