From a7c73f559f2e04bd2cb80100fb4acd90f7436de8 Mon Sep 17 00:00:00 2001 From: bronsen Date: Wed, 20 Nov 2024 23:39:22 +0100 Subject: [PATCH 01/10] [pre-commit] add hook to verify the compiled requirements are up-to-date --- .pre-commit-config.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..4dd1b78 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,4 @@ +- repo: https://github.com/peterdemin/pip-compile-multi + rev: v2.6.2 + hooks: + - id: pip-compile-multi-verify From b5663d1bc85497d766ae912df2afc68b08915a23 Mon Sep 17 00:00:00 2001 From: bronsen Date: Wed, 20 Nov 2024 23:39:54 +0100 Subject: [PATCH 02/10] [foo] Add a module so we can test and create a coverage report --- src/foo.py | 2 ++ tests/test_something.py | 8 ++++++++ 2 files changed, 10 insertions(+) create mode 100644 src/foo.py create mode 100644 tests/test_something.py diff --git a/src/foo.py b/src/foo.py new file mode 100644 index 0000000..7dbdb99 --- /dev/null +++ b/src/foo.py @@ -0,0 +1,2 @@ +def dummy(): + return (1, 1, 1) diff --git a/tests/test_something.py b/tests/test_something.py new file mode 100644 index 0000000..c448d64 --- /dev/null +++ b/tests/test_something.py @@ -0,0 +1,8 @@ +def test_always_true(): + assert True + + +def test_something_in_src(): + from foo import dummy + + assert dummy() == (1, 1, 1) From 28f7db8b72069379cf521dd19146d495835fd37d Mon Sep 17 00:00:00 2001 From: bronsen Date: Thu, 21 Nov 2024 12:03:42 +0100 Subject: [PATCH 03/10] [requirements] Rely on django-configurations to manage Django settings --- requirements/base.in | 1 + requirements/base.txt | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/requirements/base.in b/requirements/base.in index 54d157a..797b722 100644 --- a/requirements/base.in +++ b/requirements/base.in @@ -1,2 +1,3 @@ +django-configurations django>=5.1,<5.2 pip-lock diff --git a/requirements/base.txt b/requirements/base.txt index 66a8864..3ea6a65 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -1,4 +1,4 @@ -# SHA1:e1677d1f2cf78dc26b96c6f8b02f0a0192f1d402 +# SHA1:78e037786a8e05baa81b92ef0373bd8fc1069bd9 # # This file is autogenerated by pip-compile-multi # To update, run: @@ -8,6 +8,10 @@ asgiref==3.8.1 # via django django==5.1.3 + # via + # -r requirements/base.in + # django-configurations +django-configurations==2.5.1 # via -r requirements/base.in pip-lock==2.12.0 # via -r requirements/base.in From 3603d26f1e926679c290ef29375d69fcf13d61d3 Mon Sep 17 00:00:00 2001 From: bronsen Date: Thu, 21 Nov 2024 12:04:40 +0100 Subject: [PATCH 04/10] [project] start with minimal project mainly, so we have a `manage.py` script --- src/dx/__init__.py | 0 src/dx/settings.py | 47 ++++++++++++++++++++++++++++++++++++++++++++++ src/dx/urls.py | 1 + src/manage.py | 18 ++++++++++++++++++ 4 files changed, 66 insertions(+) create mode 100644 src/dx/__init__.py create mode 100644 src/dx/settings.py create mode 100644 src/dx/urls.py create mode 100755 src/manage.py diff --git a/src/dx/__init__.py b/src/dx/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/dx/settings.py b/src/dx/settings.py new file mode 100644 index 0000000..add55c3 --- /dev/null +++ b/src/dx/settings.py @@ -0,0 +1,47 @@ +from pathlib import Path +from configurations import Configuration + +BASE_DIR = Path(__file__).resolve().parent.parent + + +class Base(Configuration): + DEBUG = False + DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" + + INSTALLED_APPS = [ + "dx", + ] + + ROOT_URLCONF = "dx.urls" + + SECRET_KEY = "django-insecure-cbgvn=orgh$&6l-w91pp2=(b#hjwe1z&ijwiafgt(py1lq5i85" + + TEMPLATES = [ + { + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [BASE_DIR / "templates"], + "APP_DIRS": True, + }, + ] + + USE_TZ = True + + +class Dev(Base): + # Dangerous: disable host header validation + ALLOWED_HOSTS = ["*"] + + DATABASES = { + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": "db.sqlite3", + }, + } + + DEBUG = True + + INSTALLED_APPS = Base.INSTALLED_APPS + ["django_extensions"] + + +class Local(Dev): + pass diff --git a/src/dx/urls.py b/src/dx/urls.py new file mode 100644 index 0000000..637600f --- /dev/null +++ b/src/dx/urls.py @@ -0,0 +1 @@ +urlpatterns = [] diff --git a/src/manage.py b/src/manage.py new file mode 100755 index 0000000..22d839f --- /dev/null +++ b/src/manage.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" + +import os +import sys + + +def main(): + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dx.settings") + os.environ.setdefault("DJANGO_CONFIGURATION", "Base") + + from configurations.management import execute_from_command_line + + execute_from_command_line(sys.argv) + + +if __name__ == "__main__": + main() From f4ed431a9490000630acb198deb477f2d70f6597 Mon Sep 17 00:00:00 2001 From: bronsen Date: Thu, 21 Nov 2024 12:16:17 +0100 Subject: [PATCH 05/10] [meta] Use .envrc to set up env variables and activate the virtualenv --- .envrc | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .envrc diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..4cc934b --- /dev/null +++ b/.envrc @@ -0,0 +1,4 @@ +export VIRTUAL_ENV=.venv +layout python3 +export DJANGO_SETTINGS_MODULE=dx.settings +export DJANGO_CONFIGURATION=Local From cd0b9d9c96b30634279f44afe0b0735ebee0513b Mon Sep 17 00:00:00 2001 From: bronsen Date: Thu, 21 Nov 2024 12:16:59 +0100 Subject: [PATCH 06/10] [pytest] Tell it where tests are Also tell coverage how to behave --- pyproject.toml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index e87510d..c17d348 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,3 +13,16 @@ build-backend = "hatchling.build" [tool.pytest.ini_options] pythonpath = ["src"] +testpaths = ["tests"] + +[tool.coverage.run] +branch = true +data_file = "coverage/.coverage" +source = ["src"] +omit = ["*/migrations/*"] + +[tool.coverage.html] +directory = "coverage/htmlcov" + +[tool.coverage.report] +skip_empty = true From 71c492c648fe1a46675e24e1cdcdb47413156e88 Mon Sep 17 00:00:00 2001 From: bronsen Date: Thu, 21 Nov 2024 12:19:06 +0100 Subject: [PATCH 07/10] [meta] Activate Python Development mode --- .envrc | 1 + 1 file changed, 1 insertion(+) diff --git a/.envrc b/.envrc index 4cc934b..1b51213 100644 --- a/.envrc +++ b/.envrc @@ -1,3 +1,4 @@ +export PYTHONDEVMODE=1 export VIRTUAL_ENV=.venv layout python3 export DJANGO_SETTINGS_MODULE=dx.settings From d635b7ba05ef9fe4d55849eda4eb540b6d031e4d Mon Sep 17 00:00:00 2001 From: bronsen Date: Thu, 21 Nov 2024 12:19:37 +0100 Subject: [PATCH 08/10] [tooling] Create simple justfile Let's see how well it works out for us --- justfile | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 justfile diff --git a/justfile b/justfile new file mode 100644 index 0000000..785960b --- /dev/null +++ b/justfile @@ -0,0 +1,18 @@ + +test: + # pytest options can be found in pyproject.toml + # look for [tool.pytest.ini_options] + @python -m pytest + +test-coverage: + # here we allow extra arguments to be passed to pytest + @python -m pytest --cov=src --cov-config=pyproject.toml + +lint: + @ruff check . + +lint-fix: + @ruff check --fix . + +compile-dependencies: + @pip-compile-multi From ca09a2916e77da4b12f4769cdaa6cdf39a4338ff Mon Sep 17 00:00:00 2001 From: bronsen Date: Thu, 21 Nov 2024 12:29:19 +0100 Subject: [PATCH 09/10] [settings] remove some empty lines --- src/dx/settings.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/dx/settings.py b/src/dx/settings.py index add55c3..2ff9590 100644 --- a/src/dx/settings.py +++ b/src/dx/settings.py @@ -7,15 +7,11 @@ BASE_DIR = Path(__file__).resolve().parent.parent class Base(Configuration): DEBUG = False DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" - INSTALLED_APPS = [ "dx", ] - ROOT_URLCONF = "dx.urls" - SECRET_KEY = "django-insecure-cbgvn=orgh$&6l-w91pp2=(b#hjwe1z&ijwiafgt(py1lq5i85" - TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", @@ -23,23 +19,19 @@ class Base(Configuration): "APP_DIRS": True, }, ] - USE_TZ = True class Dev(Base): # Dangerous: disable host header validation ALLOWED_HOSTS = ["*"] - DATABASES = { "default": { "ENGINE": "django.db.backends.sqlite3", "NAME": "db.sqlite3", }, } - DEBUG = True - INSTALLED_APPS = Base.INSTALLED_APPS + ["django_extensions"] From 77512fc73cc890c78864efc7246f10e9e4d2bab7 Mon Sep 17 00:00:00 2001 From: bronsen Date: Thu, 21 Nov 2024 12:29:53 +0100 Subject: [PATCH 10/10] [tooling] Expose commands that are used; add aliases and default recipe --- justfile | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/justfile b/justfile index 785960b..3fe2aed 100644 --- a/justfile +++ b/justfile @@ -1,18 +1,24 @@ +default: test + +alias tc := test-coverage +alias l := lint +alias lf := lint-fix +alias c := compile-dependencies test: # pytest options can be found in pyproject.toml # look for [tool.pytest.ini_options] - @python -m pytest + python -m pytest test-coverage: # here we allow extra arguments to be passed to pytest - @python -m pytest --cov=src --cov-config=pyproject.toml + python -m pytest --cov=src --cov-config=pyproject.toml lint: - @ruff check . + ruff check . lint-fix: - @ruff check --fix . + ruff check --fix . compile-dependencies: - @pip-compile-multi + pip-compile-multi