In software development, developers usually work in a collaborative and fast-evolving environment. For this reason, it is highly recommended that they follow common guidelines & coding practices that will ensure efficiency, clarity, easy bug-spotting, and onboarding. After all, code that is properly formatted and documented is more likely to be shared and used by the entire developer community
We propose here a set of Python developer tools that can help you achieve such a target, tested with Python 3.8 versions:
- Black
- Flake8
- Isort
- Mypy
- Pydocstyle
- Darglint
Black
Black is a quick formatting tool that can be used very easily on the command line.
Reformatting your code in black-style allows you to produce clean, readable code, making it easy to spot errors.
In this sample:
Running:
Returns:
And it transforms sample.py:
Recommended configuration
Note: Skip-magic-trailing-comma: to avoid exploding a collection into one item per line
Flake8
Flake8 is a tool that wraps pycodestyle, pyflakes, and mccabe
- Pycodestyle: spots any formatting-related errors in the code related to PEP8 compliance. Below is a non-exhaustive list of errors:
E for error codes and W for warnings
- E1: for indentation errors.
- E2: for whitespace errors.
- E7: for statement errors
- W6: for deprecation warnings
- Pyflakes: spots any incoherency in the code. Below is a non-exhaustive list of errors:
F for error codes
- F4: for imports errors
- F5: for format errors
- F6: for incompatible assignments/comparison errors
- F7: for syntax errors
- F8: for variable related errors
- Mccabe: spots complexity errors.
Error code: C (error thrown always C901 for complexity violation)
In this sample.py:
Running:
Gives you the following errors:
Recommended configuration
We ignore those two errors:
- E203 whitespace: which is related to black tool interaction
- E501 Line : which is to authorise a longer line than PEP8 recommendation of 79 characters
We also have a set of flake8 plugins that you can install:
- flake8-use-fstring: check for % or .format and suggest using f-strings
- flake8-print: check for print statements
- flake8-tidy-imports: write tidier imports (bans imports from parent modules and above, i.e. with more than one .)
Isort
Isort is a tool that provides a command-line utility that sorts your imports (alphabetically and separates sections into standard, third party, first-party, and finally imports from the local folder).
In this sample:
Running:
Transforms sample.py:
Recommended configuration
We need to set the profile to “black” to avoid bad interactions between the two tools.
Mypy
Mypy is a static type checker. You need to type in your functions and variables to use it. You can configure its level of strictness if you still want to resolve the type dynamically in some parts of your code, but keep in mind that having a statically typed project enhances productivity, and clarity adds safety barriers everywhere so that you can spot errors even before executing your code.
In this sample:
Running:
Returns:
Recommended configuration
We choose to only require typing for production code and not for the tests.
For a new codebase, you should add the strict options but for legacy code, you should add mypy options iteratively.
Pydocstyle
Pydocstyle is a tool that verifies the compliance from most of PEP 257 regarding your docstrings. Docstring is an essential tool to document your code. We choose to adopt the Google style convention.
It implements different groups of error:
- D1: for Missing Docstrings
- D2: for Whitespace Issues
- D3: for Quote Issues
- D4: for Docstring Content Issues
Recommended configuration
In the previous undocumented sample:
Running:
Returns:
We should have:
Darglint
Darglint is a tool to verify that the docstring matches the function or method implementation along its whole lifecycle. It avoids having deprecated documentation when the signature has changed. It is better when used in combination with a docstring style checker like pydocstyle.
It implements different groups of errors:
- DAR0: Syntax, formatting, and style
- DAR1: Args section
- DAR2: Returns section
- DAR3: Yields section
- DAR4: Raises section
- DAR5: Variables section
In the previous documented sample:
Running:
Returns:
We should have:
Integration
We would like to gather all these tool configurations into one file. For configuration storage, our recommendation is to use .flake8 + pyproject.toml.
Then if we want to run all of them using only one command, we have different options:
- Sh script or Makefile
We need to define a list of dev dependencies like in requirements-dev.txt.
We create a lint.sh file (darglint is automatically launched by flake8 when installed in the same env so no need to specify it)
And we can run it:
If you want to use a Makefile:
Then run:
- Pre-commit [Preferred]
Pre-commit is another alternative to putting all the tools together and running them inside a dedicated closed environment, so you do not even need them in a dev environment.
Additionally, it can interact with the git hook regarding the modified files on commit, push, etc. before submission to remote code storage and avoid cluttering the CI for lint and style problems.
Recommended configuration
.pre-commit-config.yaml
Conclusion
Once you have converged on a configuration and chosen an integration method, your workflow will be stable and productive. Moreover, they will most likely not evolve much in the future, so maintaining a codebase with such tools is a no-brainer.
In addition, when used from the start of a project, the cost is close to zero, but when applied to an existing codebase, it can take quite some time to solve all errors. The earlier you start, the better!
Featured image by Kuznetcov_Konstantin
Next steps
Try out our products for free. No commitment or credit card required. If you want a custom plan or have questions, we’d be happy to chat.