diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..4e1f6fe --- /dev/null +++ b/.env.example @@ -0,0 +1,6 @@ +OV_DB_ENGINE=django.db.backends.postgresql +OV_DB_HOST=0.0.0.0 +OV_DB_PORT=5432 +OV_DB_NAME=postgres +OV_DB_USER=postgres +OV_DB_PASSWORD="" diff --git a/.gitignore b/.gitignore index c83a018..c0b3cc6 100644 --- a/.gitignore +++ b/.gitignore @@ -15,11 +15,15 @@ __pycache__ *.pyc .DS_Store -/venv/ -# Database -db/ +# Virtual environment +.venv -# Environment files +# Environment variable files .env -.db +!.env.example + +# VS Code +.vscode/ +!.vscode/settings.json +!.vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..503471f --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,64 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "inputs": [ + { + "id": "numWorkers", + "type": "promptString", + "default": "4", + "description": "Number of Gunicorn workers to run" + } + ], + "configurations": [ + { + "name": "OV Wagtail - Django dev server", + "type": "python", + "request": "launch", + "program": "${workspaceFolder}/manage.py", + "args": [ + "runserver", + "0.0.0.0:8000" + ], + "django": true, + "justMyCode": false + }, + { + "name": "OV Wagtail - Gunicorn", + "type": "python", + "request": "launch", + "program": "gunicorn", + "args": [ + "-w ${input:numWorkers}", + "-b 0.0.0.0:4000", + "ov-wag.wsgi:applications", + ], + "django": true, + "justMyCode": false + }, + { + "name": "Run Migrations", + "type": "python", + "request": "launch", + "program": "${workspaceFolder}/manage.py", + "args": [ + "migrate", + "--noinput" + ], + "django": true, + "justMyCode": false + }, + { + "name": "Run Tests", + "type": "python", + "request": "launch", + "program": "${workspaceFolder}/manage.py", + "args": [ + "test", + ], + "django": true, + "justMyCode": false + }, + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..ded7d63 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "python.testing.pytestArgs": [ + "-v", + ], + "python.testing.pytestEnabled": true, + "python.testing.unittestEnabled": false +} \ No newline at end of file diff --git a/dev.yml b/dev.yml index 0adc672..c43eb32 100644 --- a/dev.yml +++ b/dev.yml @@ -12,4 +12,4 @@ services: - .env db: env_file: - - .db + - .env diff --git a/docker-compose.yml b/docker-compose.yml index b58fcdc..82caf00 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,6 +19,12 @@ services: db: image: postgres:16-alpine restart: always + ports: + - 5432:5432 + environment: + - POSTGRES_DB=${OV_DB_NAME} + - POSTGRES_USER=${OV_DB_USER} + - POSTGRES_PASSWORD=${OV_DB_PASSWORD} volumes: - db:/var/lib/postgresql/data diff --git a/manage.py b/manage.py index f68b0bf..d3f5ab3 100755 --- a/manage.py +++ b/manage.py @@ -2,6 +2,11 @@ import os import sys +from dotenv import load_dotenv + +# take environment variables from .env. +load_dotenv() + if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ov_wag.settings.dev") diff --git a/ov_wag/settings/base.py b/ov_wag/settings/base.py index 9df4b2f..091f86e 100644 --- a/ov_wag/settings/base.py +++ b/ov_wag/settings/base.py @@ -13,6 +13,11 @@ # Build paths inside the project like this: os.path.join(BASE_DIR, ...) import os +from dotenv import load_dotenv + +# take environment variables from .env. +load_dotenv() + PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BASE_DIR = os.path.dirname(PROJECT_DIR) diff --git a/ov_wag/settings/dev.py b/ov_wag/settings/dev.py index adfe816..50e839f 100644 --- a/ov_wag/settings/dev.py +++ b/ov_wag/settings/dev.py @@ -1,4 +1,4 @@ -from .base import * +from ov_wag.settings.base import * # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True @@ -12,8 +12,6 @@ EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' - - try: from .local import * except ImportError: diff --git a/ov_wag/settings/production.py b/ov_wag/settings/production.py index 37f527b..2f430a8 100644 --- a/ov_wag/settings/production.py +++ b/ov_wag/settings/production.py @@ -1,5 +1,4 @@ -from .base import * -from os import environ +from ov_wag.settings.base import * DEBUG = False diff --git a/ov_wag/tests/test_api.py b/ov_wag/tests/test_api.py index db9cad7..b43d321 100644 --- a/ov_wag/tests/test_api.py +++ b/ov_wag/tests/test_api.py @@ -1,7 +1,8 @@ +import wagtail_factories from rest_framework import status from rest_framework.test import APITestCase from wagtail.core.models import Site -import wagtail_factories + from exhibits.models import ExhibitPageApiSchema from exhibits.tests.factories import ExhibitPageFactory @@ -41,7 +42,9 @@ def test_exhibit_api_schema_single(self): Compare response against ExhibitSchema """ exhibit_page = ExhibitPageFactory.create(parent=self.__home_page()) - response = self.client.get(f'/api/v2/exhibits/{exhibit_page.id}/', format='json') + response = self.client.get( + f'/api/v2/exhibits/{exhibit_page.id}/', format='json' + ) json = response.json() self.assertValidSchema(json) @@ -51,8 +54,8 @@ def test_exhibit_api_schema_multiple(self): Compare response against ExhibitSchema """ - exhibit_page = ExhibitPageFactory.create(parent=self.__home_page()) - response = self.client.get(f'/api/v2/exhibits/', format='json') + ExhibitPageFactory.create(parent=self.__home_page()) + response = self.client.get('/api/v2/exhibits/', format='json') json = response.json() for item in json['items']: self.assertValidSchema(item) diff --git a/ov_wag/tests/test_env.py b/ov_wag/tests/test_env.py index 35fc512..70606ac 100644 --- a/ov_wag/tests/test_env.py +++ b/ov_wag/tests/test_env.py @@ -1,27 +1,15 @@ +from os import path from unittest import TestCase -from os import environ, system, path -from pprint import pp class EnvTests(TestCase): - def test_env(self): - """ - Show the current environment - - debug: print environ - """ - self.assertIn('PYTHON_VERSION', dict(environ)) - - # Uncomment to show full environ in logs - # pp(dict(environ)) - def test_media_dir(self): """ Test if MEDIA_ROOT directory exists debug: ls -la MEDIA_ROOT """ - from ..settings.base import MEDIA_ROOT + from ov_wag.settings.base import MEDIA_ROOT self.assertTrue(path.isdir(MEDIA_ROOT)) diff --git a/pdm.lock b/pdm.lock index 1effd9b..1a6c509 100644 --- a/pdm.lock +++ b/pdm.lock @@ -5,7 +5,7 @@ groups = ["default"] strategy = ["cross_platform"] lock_version = "4.4" -content_hash = "sha256:ef9f7b76ccd3aa29e374113c094524d6e203f8c9fef0d8bdd434f17a82edc1fa" +content_hash = "sha256:a41c32388d7cca1bfe41e180054f2bad9ee24b500ba22ab75c21b7d38f66a7ff" [[package]] name = "anyascii" @@ -230,6 +230,19 @@ files = [ {file = "Faker-19.12.0.tar.gz", hash = "sha256:91438f6b1713274ec3f24970ba303617be86ce5caf6f6a0776f1d04777b6ff5f"}, ] +[[package]] +name = "gunicorn" +version = "21.2.0" +requires_python = ">=3.5" +summary = "WSGI HTTP Server for UNIX" +dependencies = [ + "packaging", +] +files = [ + {file = "gunicorn-21.2.0-py3-none-any.whl", hash = "sha256:3213aa5e8c24949e792bcacfc176fef362e7aac80b76c56f6b5122bf350722f0"}, + {file = "gunicorn-21.2.0.tar.gz", hash = "sha256:88ec8bff1d634f98e61b9f65bc4bf3cd918a90806c6f5c48bc5603849ec81033"}, +] + [[package]] name = "html5lib" version = "1.1" @@ -280,6 +293,16 @@ files = [ {file = "openpyxl-3.1.2.tar.gz", hash = "sha256:a6f5977418eff3b2d5500d54d9db50c8277a368436f4e4f8ddb1be3422870184"}, ] +[[package]] +name = "packaging" +version = "23.2" +requires_python = ">=3.7" +summary = "Core utilities for Python packages" +files = [ + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, +] + [[package]] name = "pillow" version = "9.5.0" @@ -359,6 +382,16 @@ files = [ {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, ] +[[package]] +name = "python-dotenv" +version = "1.0.0" +requires_python = ">=3.8" +summary = "Read key-value pairs from a .env file and set them as environment variables" +files = [ + {file = "python-dotenv-1.0.0.tar.gz", hash = "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba"}, + {file = "python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a"}, +] + [[package]] name = "pytz" version = "2023.3.post1" diff --git a/pyproject.toml b/pyproject.toml index cf9a154..4d4fdbd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,9 +2,23 @@ [project] # PEP 621 project metadata # See https://www.python.org/dev/peps/pep-0621/ -dependencies = ["Django<4.2,>=4.1.1", "wagtail<4.1,>=4.0.4", "wagtail-factories<3.2,>=3.1.0", "pydantic<2.0,>=1.10.2", "psycopg2<2.10,>=2.9.3"] +dependencies = [ + "Django<4.2,>=4.1.1", + "wagtail<4.1,>=4.0.4", + "wagtail-factories<3.2,>=3.1.0", + "pydantic<2.0,>=1.10.2", + "psycopg2<2.10,>=2.9.3", + "python-dotenv>=1.0.0,< 2.0", + "gunicorn>=21.2.0", +] requires-python = ">=3.11" [build-system] requires = ["pdm-backend"] build-backend = "pdm.backend" + + +[tool.pdm.dev-dependencies] +dev = [ + "pre-commit~=3.5", +] \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index a430b9c..70fcf10 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,4 @@ wagtail >= 4.0.4, < 4.1 wagtail_factories >= 3.1.0, < 3.2 pydantic >= 1.10.2, < 2.0 psycopg2 >= 2.9.3, < 2.10 +python-dotenv >= 1.0.0, < 2.0