Skip to content

Commit 919109d

Browse files
committed
Update 2022
1 parent 588c0d0 commit 919109d

35 files changed

Lines changed: 290 additions & 98 deletions

‎.flake8‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[flake8]
2+
max-line-length = 120

‎.gitignore‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1-
venv
2-
*.egg-info
1+
.venv
2+
__pycache__
3+
.coverage
4+
htmlcov

‎.pre-commit-config.yaml‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
repos:
2+
- repo: https://github.com/pre-commit/pre-commit-hooks
3+
rev: v4.3.0
4+
hooks:
5+
- id: check-toml
6+
- id: check-symlinks
7+
- id: check-merge-conflict
8+
- id: check-case-conflict
9+
- id: check-shebang-scripts-are-executable
10+
- id: mixed-line-ending
11+
- id: trailing-whitespace
12+
- repo: https://github.com/psf/black
13+
rev: 22.10.0
14+
hooks:
15+
- id: black
16+
- repo: https://github.com/PyCQA/isort
17+
rev: 5.10.1
18+
hooks:
19+
- id: isort
20+
- repo: https://github.com/PyCQA/flake8
21+
rev: 5.0.4
22+
hooks:
23+
- id: flake8
24+
- repo: https://github.com/shellcheck-py/shellcheck-py
25+
rev: v0.8.0.4
26+
hooks:
27+
- id: shellcheck
28+
- repo: https://github.com/jackdewinter/pymarkdown
29+
rev: v0.9.8
30+
hooks:
31+
- id: pymarkdown
32+
- repo: https://github.com/cmake-lint/cmake-lint
33+
rev: 1.4.2
34+
hooks:
35+
- id: cmakelint

‎.shellcheckrc‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
disable=SC1091 # don't follow .venv/bin/activate

‎.vscode/extensions.json‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"recommendations": [
3-
"ms-python.python"
3+
"ms-python.python",
4+
"davidanson.vscode-markdownlint"
45
]
56
}

‎.vscode/settings.json‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
{
22
"python.linting.pylintEnabled": false,
33
"python.linting.flake8Enabled": true,
4-
"python.linting.flake8Args": ["--config", "${workspaceFolder}/python/.flake8"],
4+
"python.linting.flake8Args": ["--config", "${workspaceFolder}/.flake8"],
55
"python.linting.enabled": true,
66
"python.testing.pytestEnabled": true,
7-
"python.testing.nosetestsEnabled": false,
87
"python.testing.unittestEnabled": false,
9-
"python.pythonPath": "${workspaceFolder}/venv/bin/python3",
8+
"python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python3",
109
"python.envFile": "${workspaceFolder}/.env"
1110
}

‎Makefile‎

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,44 @@
1+
# the things that don't have output files or run every time
2+
.PHONY: help all install test dev coverage clean \
3+
pre-commit update-pre-commit
14

2-
.PHONY: all clean test dev \
3-
test-example_project
45

5-
all: venv/bin/activate test
6+
all: dev coverage ## builds everything
67

7-
test: venv/bin/activate test-example_project
8+
install: .venv/.installed ## installs the venv and the project packages
89

9-
test-example_project: venv/bin/activate venv/.test-dependencies
10-
build-scripts/test.sh
10+
dev: .venv/.installed-dev pre-commit ## prepare local repo and venv for dev
1111

12-
clean:
13-
./build-scripts/clean.sh
12+
test: .venv/.installed-dev ## run the project's tests
13+
build/test.sh
1414

15-
linter: ./venv/bin/activate
16-
./build-scripts/linter.sh
15+
coverage: .venv/.installed-dev build/coverage.sh ## build the html coverage report
16+
build/coverage.sh
1717

18-
venv/bin/activate: example_project/requirements.txt build-scripts/venv.sh
19-
build-scripts/venv.sh
18+
clean: ## delete caches and the venv
19+
build/clean.sh
2020

21-
venv/.test-dependencies: example_project/requirements-test.txt venv/bin/activate
22-
build-scripts/venv-test.sh
21+
pre-commit: .git/hooks/pre-commit ## install pre-commit into the git repo
2322

24-
venv/bin/activate: example_project/requirements.txt example_project/requirements-test.txt
25-
build-scripts/venv.sh
23+
update-pre-commit: build/update-pre-commit.sh ## autoupdate pre-commit
24+
build/update-pre-commit.sh
2625

26+
27+
28+
# Caching doesn't work if we depend on PHONY targets
29+
30+
.venv/.installed: */pyproject.toml .venv/bin/activate build/install.sh
31+
build/install.sh
32+
33+
.venv/.installed-dev: */pyproject.toml .venv/bin/activate build/install-dev.sh
34+
build/install-dev.sh
35+
36+
.venv/bin/activate:
37+
build/venv.sh
38+
39+
.git/hooks/pre-commit: build/install-pre-commit.sh
40+
build/install-pre-commit.sh
41+
42+
43+
help: ## Show this help
44+
@egrep -h '\s##\s' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'

‎README.md‎

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# Example Python Project
2+
3+
This is how I like to lay my Python projects out. You don't have to do it
4+
this way, but this way works for me. If you think it's bad or out of date
5+
feel free to create an issue or even a pull request.
6+
7+
## To run me
8+
9+
make dev
10+
11+
Then open the project dir in Visual Studio code, if you like to use an IDE.
12+
13+
## Project structure
14+
15+
### Makefile
16+
17+
I like to use a `Makefile` to install my dependencies, build env, run tests
18+
and create packages. I get tab completion and it doesn't matter what CI
19+
platform I use, I just run `make stuff` and let GNU Make deal with it.
20+
`Makefile`s are of course an ancient curse, but if you don't use them you'll
21+
have to live in interesting times, which is a far worse curse.
22+
23+
The trick is:
24+
25+
1. Have each step run one script that has a good name, so they're documented
26+
by that script and its name, and can be run without `make` - like from
27+
your editor or whatever. I keep mine in `./build-scripts/`.
28+
2. Have the dependencies for the step be the script itself plus one file
29+
that it creates and anything that it depends on. So when you switch branch
30+
and the script or its inputs have changed, it'll blow the cache and re-run
31+
that step and all the ones after it.
32+
3. If you don't know what the output file will be then just fake one. Like
33+
when installing `requirements-test.txt` I `touch ./venv/.test-dependencies`
34+
so it knows that step has been done and won't run it again.
35+
4. Remember to remove those files in `clean.sh`. Remove everything in there.
36+
5. Try to avoid use Make's advanced features. In a world where you can do
37+
anything, what you *don't* do is what defines you.
38+
39+
As a bonus, the file is self-documenting. Type `make help` to see what it can
40+
do.
41+
42+
### Linting and commit checks
43+
44+
I like `flake8` for linting because it's not as harsh as `pylint`, and is
45+
supported by my IDE of choice.
46+
47+
Part of the `make dev` setup installs `pre-commit`, which will make sure that
48+
commits are up to a certain standard. The provided config file runs code
49+
formatters, linters and a few other checks. Have a look at
50+
`.pre-commit-config.yaml` to see what's going on in there.
51+
52+
### IDE
53+
54+
I'm using VS Code because it works everywhere and supports all the things that
55+
I need. I commit my config to source control so anyone can open the project dir
56+
and start hacking with a working debugger and the tests auto-detected.
57+
58+
The config also provides recommendations for extensions.
59+
60+
### Package layout
61+
62+
Under the `example_project` dir there's a `pyproject.toml` that defines the
63+
project and its dependencies. Then there's `src` and `test` dirs that contain
64+
the code and tests.
65+
66+
The layout is as-per the pypi packaging guidelines. When referencing stuff in
67+
the code I tend to use the full `package.module` names because otherwise imports
68+
tend to break in weird ways in different environments.
69+
70+
### Testing
71+
72+
I use `pytest` and write tests in a functional style, and develop using TDD.
73+
If you get into the habit of actually running a new piece of code from a new
74+
unit test then you'll find yourself writing testable code. Tests are
75+
fundamentally just other pieces of code, so if a function is difficult to test
76+
then it's probably difficult to reuse too.
77+
78+
Run `make coverage` for a test coverage report. I like to keep my coverage at
79+
100%.
80+
81+
## Some opinionated stuff
82+
83+
### Megarepos
84+
85+
When working on microservices and with other teams I prefer a single mega repo
86+
than lots of different ones if I can help it. Otherwise the style of things
87+
will diverge, deps will change, things will get forgotten about and turn up
88+
when you go to add something then add days of work, they'll be too difficult to
89+
test. Keep everything together and you've got one source of the truth. Your
90+
stubs, test data, functional and integration tests, infrastructure code,
91+
architecture diagrams and specs - everything you need to actually understand
92+
the project in one place.
93+
94+
## Docs in Markdown
95+
96+
Did you know that you can add a `README.md` to any dir and it'll get rendered
97+
to HTML in most online viewers for git repos? Drop them in wherever you think
98+
a directory/subtree needs an explanation for existing.
99+
100+
I think it's worth keeping most of the project documentation in Markdown as a
101+
general rule, up to a point anyway. The project wiki is somewhere else, it goes
102+
out of sync, it's difficult to see what the docs were on a specific release
103+
tag. Docs in the codebase can be edited alongside new features and have a much
104+
richer history.

‎build-scripts/test.sh‎

Lines changed: 0 additions & 7 deletions
This file was deleted.

‎build-scripts/venv-test.sh‎

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)