Thanks for your interest in our project. Contributions are always welcome!
We are committed to fostering a welcoming, respectful, and harassment-free environment. Be kind!
If you have questions, ideas or want to report a bug, feel free to open an issue. Or go ahead and open a pull request to contribute code. In order to reduce the burden on our maintainers, please make sure that your code follows our style guidelines outlined below.
We recommend that you develop inside of a virtual environment. After you have set it up, simply run the unit tests to verify that everything is set up correctly:
pytest
We additionally recommend that you set up your editor / IDE as follows.
Indent with 4 spaces per level of indentation
Maximum line length of 79 (add a ruler / thin line / highlighting / ...)
If you use Visual Studio Code: Consider using a platform which supports third-party language servers more easily, and continue with the next point.
Otherwise, set up the editor to run
black,pylintandmypywhen saving. To enable automatic import sorting withisort, add the following to yoursettings.json:"[python]": { "editor.codeActionsOnSave": { "source.organizeImports": true } }
Note that the Pylance language server is not recommended, as it occasionally causes false-positive errors for perfectly valid code.
If you do not use VSC: Set up your editor to use the python-lsp-server, and make sure that the relevant plugins are installed. You can install everything that's needed into the virtualenv with pip:
pip install "python-lsp-server[pylint]" python-lsp-black pyls-isort pylsp-mypy
This will provide as-you-type linting as well as automatic formatting on save. Language server clients are available for a wide range of editors, from Vim/Emacs to PyCharm/IDEA.
We base our code style on a modified version of the Google style guide for Python code. The key differences are:
Docstrings: The Numpy style guide applies here.
Overridden methods: If the documentation did not change from the base class (i.e. the base class' method's docstring still applies without modification), do not add a short docstring á la "See base class". This lets automated tools pick up the full base class docstring instead, and is therefore more useful in IDEs etc.
Linting: Use pylint for static code analysis, and mypy for static type checking.
Formatting: Use black as code auto-formatter. The maximum line length is 79, as per PEP-8. This setting should be automatically picked up from the
pyproject.tomlfile. The reason for the shorter line length is that it avoids wrapping and overflows in side-by-side split views (e.g. diffs) if there's also information displayed to the side of it (e.g. a tree view of the modified files).Be aware of the different line length of 72 for docstrings. We currently do not have a satisfactory solution to automatically apply or enforce this.
Note that, while you're encouraged to do so in general, it is not a hard requirement to break up long strings into smaller parts. Additionally, never break up strings that are presented to the user in e.g. log messages, as that makes it significantly harder to grep for them.
Use isort for automatic sorting of imports. Its settings should automatically be picked up from the
pyproject.tomlfile as well.Typing: We do not make an exception for
typingimports. Instead of writingfrom typing import SomeName, useimport typing as tand access typing related classes liket.TypedDict.Use the new syntax and classes for typing introduced with Python 3.10.
- Instead of
t.Tuple,t.Listetc. use the builtin classestuple,listetc. - For classes that are not builtin (e.g.
Iterable),import collections.abc as cabcand then use them likecabc.Iterable. - Use PEP-604-style unions, e.g.
int | floatinstead oft.Union[int, float]. - Use
... | None(withNonealways as the last union member) instead oft.Optional[...]and always explicitly annotate whereNoneis possible.
- Instead of
Python style rules: For conflicting parts, the Black code style wins. If you have set up black correctly, you don't need to worry about this though :)
When working with
dicts, consider usingt.TypedDictinstead of a more genericdict[str, float|int|str]-like annotation where possible, as the latter is much less precise (often requiring additionalasserts orisinstancechecks to pass) and can grow unwieldy very quickly.Prefer
t.NamedTupleovercollections.namedtuple, because the former uses a more convenientclass ...:syntax and also supports type annotations.