Contributing#
This file is describing our code style and some other documentation about contributions. You must read it before your first contribution.
Also note that this all is just recommendations, you can use anything in some cases, if it will be better than solution that we propose here. However, we will prefer these recommendations when we will review your contribution.
Language#
All contributions, all code, all comments, all commits and everything else must be in English.
make test
#
This “magic” command collects almost all of our CI. If you’re on Windows, try Chocolatey to
run make
.
Also, because of conflict between pytest-testmon
and pytest-cov
we use option --no-cov
in pytest
, so in this
way we give prioritize to pytest-testmon
. If you want to generate a report with pytest-cov
, use make test ci=1
.
pre-commit
#
Furthermore, you can bind make test
(plus some additional useful checks) to run on every commit, so you will always
sure that CI will never fail. Just run pre-commit install
.
Commit naming style#
Every commit must have one small change. We also use the Tim Pope commit message template for commits’ messages.
If you worry about clean git log
- just don’t. We use squash strategy for merging PRs.
Code Style#
We use black
for almost all style control. We’re also trying to use formatters instead of linters, where it is
possible.
Furthermore, we also have some rules that black
doesn’t cover. It includes:
Imports#
We have isort
and pycln
for imports control. The first used for sorting imports, and second, to remove unused
imports. All other rules are not covered by linters/formatters etc. You should check those yourself.
You should use import module
and from package import module
whenever it’s possible, but sometimes
from module import ...
way is more useful. For example:
from dataclasses import dataclass
If you’re using only one variable from a module, and it’s readable without its parent name, you should use
from module import ...
. But if you’re using many variables from module, better would be
import module
/from package import module
:
from functools import cached_property
And can you use as
? You must not use as
when alias will be the same as actual name because in that way type checker
add import statement to auto-generated __all__
variable.
# some/file.py
from some import more as more
# some/main.py
from some import file
file.more(...) # no error!
You maybe notice that import module
and from package import module
are written with /
, this is because you must
use first one, if no package exist. But if there is a package - you must use from package import module
. Look at
these examples:
import os
from my_project import config
from my_project import models
Notice that there aren’t any relative imports, you can’t use it here.
Also, you must specify __all__
variable in all __init__.py
files with any code (not one docstring). Reason of this
limitation is that pycln
and docs can’t know exactly, do you want to add imports as alias, or this import is for using
in code which in this file. pycln
will ignore these imports, and docs will duplicate documentation for anything that
you will import.
Docstrings#
We’re using flake8
for checking docstrings presence and their quality. They later in API documentation. You must write
docstrings everywhere, except __init__
methods (not the same as __init__.py
files) because those will not go to
documentation.
I also recommend reading Google styleguide about docstrings because we’re using Google style in docstrings.
Markup#
Because of Sphinx’s limitations, we must use ReST markup in docstrings. This allows us to use cross-references to other functions or even projects.
Read more about ReST markup and Sphinx’s cross-references.
__init__.py
docstrings#
They describe a package (folder) with modules (.py
files).
Module, function, class, method based docstrings#
It is a short description of an item. They must follow Google styleguide about docstrings.
Variable-based docstrings#
They must follow in format:
some_variable = "abc"
"""This ``some`` variable used in :class:`.SomeClass`."""
This applies for the module level, and class attributes in
dataclasses/classes generated by attrs.
This won’t work in __init__
methods because they don’t actually go to documentation. Attributes should be documented
in class-based docstring, in Attributes
section.
At now, linter doesn’t detect them. Better sometimes check that all in API documentation actually documented.
pyproject.toml
#
In this file, we configure only poetry
(except for black
, it supports only pyproject.toml
file for
configuration).
Groups#
Since poetry
1.2 a new feature appeared - groups. It allows downloading only those groups of packages, which you will
need. We have four groups - make
, tests
, docs
and github_hooks
. Every of them answers about their function with
name.
make
: All required dependencies for make test.tests
: All required dependencies for tests.docs
: All required dependencies for building documentation.github_hooks
: All required dependencies for GitHub hooks.
Please see Managing dependencies in poetry.
Versions#
All versions must follow in format X.Y.z
(absolute version) or (~X.Y
). Last one will compile in >=X.Y.0,<X.Y+1.0
.
So for example we have last version for abstract dependency 1.2.3
, we specify its version to ~1.2
, so it will
compile to >=1.2.0,<1.3.0
(any patch version for 1.2
is accepted, but not 1.3
+). If 1.3.0
will be released -
dependabot will create PR for it.
Read more about Semantic Versions and Dependency specification in poetry.
Documentation#
We use Sphinx for documentation and docstrings for API documentation. At now, there is no actual styles
here, except doc8
.
Other Help#
You can contribute by spreading a word about this library. It would also be a huge contribution to write a short article on how you are using this project. You can also share your best practices with us.