CleanPython
A Python3 project template with several useful, standard, integrated batteries included to help you to write clean, tested, quality code, following the Zen of Python.
If you are starting a Python3 project from scratch, and you need to write robust and clean code, this repository could help you.
What is and why clean code matters? Read here.
Requirements
Usage
Setup
Clone:
$ git clone git@github.com:iacopy/cleanpython.git $ mv cleanpython yourprojectname
Create virtualenv. I suggest to use fish with virtualfish. Otherwise, manually:
$ virtualenv -p python3 ~/.virtualenvs/yourprojectname $ source ~/.virtualenvs/yourprojectname/bin/activate
Install (assume to be on the repository root):
$ just setup # install requirements $ just install-hooks # install git hooks
Test setup:
$ just # list recipes $ just checkup # complete code quality assurance check
Minimal workflow
- write test first (TDD)
- write code until test pass
- add your files to git index (e.g.
git add -u) just commit <your commit message>
When you launch just commit, all your codebase is linted and tested before actually commit it.
In case of any fail, the commit is aborted.
For example:
- are there broken tests? Fail.
- are you trying to escape by avoiding to write tests? Fail.
- your function is too long? Fail.
- your class contains too much methods or attributes? Fail.
- your code is too complex? Fail.
- your code follows random style? Fail.
You don't want waste time committing broken code, isn't it?
Remember: prevention is better than cure.
Recipes
Make a complete code checkup (lint, test and coverage):
just checkup
The following are just recipes that are not called automatically
when you call just commit or just checkup.
Run tests without coverage.py overhead:
just test
Create and open your HTML test coverage:
just coverage
Create your HTML documentation:
just doc
Run benchmarks (you have to write down them before :) ):
just benchmarks
Remove build artifacts (i.e. all untracked files, pay attention!):
just clean
Just integrated tools
- Pytest
- useful to write data driven tests
- pytest-benchmark makes easy to compare different functions performances
- Hypothesis
- "property based testing"
- really useful to find unexpected edge cases to test
- Mypy
- tests typing annotations
- helps to find hidden bugs before they come up
- NB: still experimental
- Coverage.py
- tells you which lines and branches are executed
- a 100% coverage should be the minimal quality requirement
- Pylint
- the most complete python linter
- with several complexity metrics it's useful to keep your code clean, simple and readable
- helps you to start refactor before your code become too complex
- Flake8
- helps to write standard, clean and documented code
- wraps pep8, pyflakes, McCabe Complexity analysis
- supports plugins
- Sphinx
- produce html documentation
- can auto-extract documentation from your codebase
- just
- rules them all together in your workflow
just commit MESSAGEallows you to commit only clean and tested code
Zen of Python
The highlighted lines are the ones that, mostly, CleanPython
(explicitly or implicitly) tries to help to reach.
- Beautiful is better than ugly.
- Explicit is better than implicit.
- Simple is better than complex.
- Complex is better than complicated.
- Flat is better than nested.
- Sparse is better than dense.
- Readability counts.
- Special cases aren't special enough to break the rules.
- Although practicality beats purity.
- Errors should never pass silently.
- Unless explicitly silenced.
- In the face of ambiguity, refuse the temptation to guess.
- There should be one-- and preferably only one --obvious way to do it.
- Although that way may not be obvious at first unless you're Dutch.
- Now is better than never.
- Although never is often better than right now.
- If the implementation is hard to explain, it's a bad idea.
- If the implementation is easy to explain, it may be a good idea.
- Namespaces are one honking great idea -- let's do more of those!
Legend
- bold
- explicitly, strongly targeted by
CleanPython - italic
- implicitly or indirectly or weakly targeted by
CleanPython