Skip to content

Commit 5ed2c4a

Browse files
authored
Merge pull request #17 from geoadmin/feat-pb-911-type-checking
PB-911 Introduce type checker
2 parents 64fd6b2 + 0e94efe commit 5ed2c4a

File tree

8 files changed

+206
-22
lines changed

8 files changed

+206
-22
lines changed

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ PYTHON := $(PIPENV_RUN) python3
3535
YAPF := $(PIPENV_RUN) yapf
3636
ISORT := $(PIPENV_RUN) isort
3737
PYLINT := $(PIPENV_RUN) pylint
38+
MYPY := $(PIPENV_RUN) mypy
3839

3940
# Find all python files that are not inside a hidden directory (directory starting with .)
4041
PYTHON_FILES := $(shell find $(APP_SRC_DIR) -type f -name "*.py" -print)
@@ -131,6 +132,9 @@ lint: ## Run the linter on the code base
131132
@echo "Run pylint..."
132133
LOGGING_CFG=0 $(PYLINT) $(PYTHON_FILES)
133134

135+
.PHONY: type-check
136+
type-check: ## Run the type-checker mypy
137+
$(MYPY) app/
134138

135139
.PHONY: start-local-db
136140
start-local-db: ## Run the local db as docker container

Pipfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ factory-boy = "*"
2626
dill = "*"
2727
pytest = "*"
2828
pytest-django = "*"
29+
mypy = "*"
30+
types-gevent = "*"
31+
django-stubs = "~=5.0.4"
2932

3033
[requires]
3134
python_version = "3.12"

Pipfile.lock

Lines changed: 120 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
- [Debug from vs code](#debug-from-vs-code)
1919
- [Attach debugger to the tests](#attach-debugger-to-the-tests)
2020
- [Run tests from within vs code](#run-tests-from-within-vs-code)
21+
- [Type Checking](#type-checking)
22+
- [Mypy](#mypy)
23+
- [Library types](#library-types)
2124

2225
## Summary of the project
2326

@@ -108,3 +111,25 @@ settings locally to your workspace:
108111

109112
They can either be in `.vscode/settings.json` or in your workspace settings. Now the tests can be
110113
run and debugged with the testing tab of vscode (beaker icon).
114+
115+
## Type Checking
116+
117+
### Mypy
118+
119+
Type checking can be done by either calling `mypy` or the make target:
120+
121+
```sh
122+
make type-check
123+
```
124+
125+
This will check all files in the repository.
126+
127+
### Library types
128+
129+
For type-checking, the external library [mypy](https://mypy.readthedocs.io) is being used. See the [type hints cheat sheet](https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html) for help on getting the types right.
130+
131+
Some 3rd party libraries need to have explicit type stubs installed for the type checker
132+
to work. Some of them can be found in [typeshed](https://github.com/python/typeshed). Sometimes dedicated
133+
packages exist, as is the case with [django-stubs](https://pypi.org/project/django-stubs/).
134+
135+
If there aren't any type hints available, they can also be auto-generated with [stubgen](https://mypy.readthedocs.io/en/stable/stubgen.html)

app/config/settings_base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/
2424

2525
# SECURITY WARNING: keep the secret key used in production secret!
26-
SECRET_KEY = env('SECRET_KEY', default=None)
26+
SECRET_KEY = env.str('SECRET_KEY', default=None)
2727

2828
# SECURITY WARNING: don't run with debug turned on in production!
2929
DEBUG = False
@@ -81,7 +81,7 @@
8181
'USER': env.str('DB_USER', 'service_control'),
8282
'PASSWORD': env.str('DB_PW', 'service_control'),
8383
'HOST': env.str('DB_HOST', 'service_control'),
84-
'PORT': env.str('DB_PORT', 5432),
84+
'PORT': env.str('DB_PORT', "5432"),
8585
'TEST': {
8686
'NAME': env.str('DB_NAME_TEST', 'test_service_control'),
8787
}

app/stubs/environ/__init__.pyi

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# basic implementation of the types of django-environ
2+
# since this package is neither critical nor widely used and rather of simple
3+
# nature, API wise, it intentionally contains the minimum needed to satisfy
4+
# the type checker
5+
import builtins
6+
from typing import Dict, List
7+
from _typeshed import Incomplete # pylint: disable=import-error
8+
9+
10+
class Env:
11+
12+
def __init__(self) -> None:
13+
...
14+
15+
def __call__(
16+
self, var: builtins.str, cast=..., default=..., parse_default: builtins.bool = False
17+
):
18+
...
19+
20+
def str(self, var: builtins.str, default=..., multiline: builtins.bool = ...) -> builtins.str:
21+
...
22+
23+
def bool(self, var: builtins.str, default=...) -> builtins.bool:
24+
...
25+
26+
def int(self, var: builtins.str, default=...) -> builtins.str:
27+
...
28+
29+
def list(self,
30+
var,
31+
cast: Incomplete | None = None,
32+
default=...) -> List[builtins.str | builtins.int]:
33+
...
34+
35+
def dict(self, var, cast=..., default=...) -> Dict[builtins.str, builtins.str | builtins.int]:
36+
...

app/stubs/gunicorn/app/base.pyi

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Basic implementation of the type for gunicorn used in wsgi.py
2+
# Since this is the only place used and very likely not subject to change,
3+
# this stubbing is intentionally very minimal to just satisfy the type checking
4+
class BaseApplication:
5+
6+
def run(self):
7+
...

mypy.ini

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[mypy]
2+
# this is important for mypy to find the imports
3+
mypy_path = ./app,./app/stubs
4+
plugins =
5+
mypy_django_plugin.main
6+
explicit_package_bases = True
7+
8+
[mypy.plugins.django-stubs]
9+
django_settings_module = "config.settings_dev"

0 commit comments

Comments
 (0)