diff --git a/compose.yml b/compose.yml index 0b092d2e..3b9367cc 100644 --- a/compose.yml +++ b/compose.yml @@ -28,7 +28,7 @@ x-django-env: &django-env - AZURE_TENANT_ID= - AZURE_CLIENT_KEY= - FLOWER_URL=http://flower:5555 - - STATIC_FILE_STORAGE=hope_country_report.apps.power_query.storage.DataSetStorage + - STATIC_FILE_STORAGE=django.core.files.storage.FileSystemStorage services: backend: diff --git a/pdm.lock b/pdm.lock index e4e4db4f..210bfee2 100644 --- a/pdm.lock +++ b/pdm.lock @@ -5,7 +5,7 @@ groups = ["default", "dev"] strategy = ["cross_platform"] lock_version = "4.5.0" -content_hash = "sha256:a259fdd901eced58b4b8eb2dcbb54eb415f2b84063f684ed4e5a5a8068ffa949" +content_hash = "sha256:6592691b0063680f9beae5b30149155b1db2fefdc9b0d8db3547eea95b5e1250" [[metadata.targets]] requires_python = ">=3.12" @@ -569,17 +569,17 @@ files = [ [[package]] name = "django" -version = "5.1.2" +version = "5.0.2" requires_python = ">=3.10" summary = "A high-level Python web framework that encourages rapid development and clean, pragmatic design." dependencies = [ - "asgiref<4,>=3.8.1", + "asgiref<4,>=3.7.0", "sqlparse>=0.3.1", "tzdata; sys_platform == \"win32\"", ] files = [ - {file = "Django-5.1.2-py3-none-any.whl", hash = "sha256:f11aa87ad8d5617171e3f77e1d5d16f004b79a2cf5d2e1d2b97a6a1f8e9ba5ed"}, - {file = "Django-5.1.2.tar.gz", hash = "sha256:bd7376f90c99f96b643722eee676498706c9fd7dc759f55ebfaf2c08ebcdf4f0"}, + {file = "Django-5.0.2-py3-none-any.whl", hash = "sha256:56ab63a105e8bb06ee67381d7b65fe6774f057e41a8bab06c8020c8882d8ecd4"}, + {file = "Django-5.0.2.tar.gz", hash = "sha256:b5bb1d11b2518a5f91372a282f24662f58f66749666b0a286ab057029f728080"}, ] [[package]] @@ -1222,14 +1222,14 @@ files = [ [[package]] name = "django-webtest" -version = "1.9.12" +version = "1.9.11" summary = "Instant integration of Ian Bicking's WebTest (http://docs.pylonsproject.org/projects/webtest/) with Django's testing framework." dependencies = [ "webtest>=1.3.3", ] files = [ - {file = "django_webtest-1.9.12-py3-none-any.whl", hash = "sha256:de5c988c20eef7abbb3d0508494d9e576af08087d0fb6109b1d54f15ef4d78fa"}, - {file = "django_webtest-1.9.12.tar.gz", hash = "sha256:5012c30665e7a6e585a1544eda75045d07d5b3f5ccccd4d0fe144c4555884095"}, + {file = "django-webtest-1.9.11.tar.gz", hash = "sha256:9597d26ced599bc5d4d9366bb451469fc9707b4779f79543cdf401ae6c5aeb35"}, + {file = "django_webtest-1.9.11-py3-none-any.whl", hash = "sha256:e29baf8337e7fe7db41ce63ca6661f7b5c77fe56f506f48b305e09313f5475b4"}, ] [[package]] diff --git a/pyproject.toml b/pyproject.toml index 136edf32..c9c2e552 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,9 +10,9 @@ license = {text = "Private"} requires-python = ">=3.12" dependencies = [ - "django", "azure-devops", "celery", + "django", "django-admin-cursor-paginator", "django-admin-extra-buttons", "django-adminactions", @@ -86,7 +86,8 @@ dependencies = [ "pathvalidate", "django-stubs-ext", "uwsgi", - "django-smart-env>=0.1.0", + "django-smart-env", + "django-webtest" ] [tool.pdm.dev-dependencies] diff --git a/src/hope_country_report/apps/core/management/commands/env.py b/src/hope_country_report/apps/core/management/commands/env.py index 7d7598a6..36c6d3a4 100644 --- a/src/hope_country_report/apps/core/management/commands/env.py +++ b/src/hope_country_report/apps/core/management/commands/env.py @@ -1,14 +1,6 @@ -from typing import TYPE_CHECKING - +from typing import Any, Dict from django.core.management import BaseCommand, CommandError, CommandParser - -if TYPE_CHECKING: - from typing import Any - -DEVELOP = { - "DEBUG": True, - "SECRET_KEY": "only-development-secret-key", -} +from hope_country_report.config import env class Command(BaseCommand): @@ -25,43 +17,50 @@ def add_arguments(self, parser: "CommandParser") -> None: help="Only dumps keys, without values", ) parser.add_argument( - "--develop", action="store_true", help="Get values from teh code not from the current environment" + "--develop", action="store_true", help="Get values from the code, not from the current environment" ) parser.add_argument( - "--changed", action="store_true", help="Get values from teh code not from the current environment" + "--changed", action="store_true", help="Display only variables that have changed from defaults" ) - parser.add_argument( "--pattern", action="store", dest="pattern", default="{key}={value} # {help}", - help="Check env for variable availability", + help="Pattern for printing variables", ) parser.add_argument( - "--check", action="store_true", dest="check", default=False, help="Check env for variable availability" + "--check", action="store_true", dest="check", default=False, help="Check for missing required variables" ) parser.add_argument( - "--ignore-errors", action="store_true", dest="ignore_errors", default=False, help="Do not fail" + "--ignore-errors", action="store_true", dest="ignore_errors", default=False, help="Ignore missing variables" ) - def handle(self, *args: "Any", **options: "Any") -> None: - from hope_country_report.config import CONFIG, env, EXPLICIT_SET - + def handle(self, *args: "Any", **options: "Dict[str, Any]") -> None: check_failure = False pattern = options["pattern"] - for k, __ in sorted(CONFIG.items()): - help: str = env.get_help(k) - default = env.get_default(k) - if options["check"]: - if default in EXPLICIT_SET and k not in env.ENVIRON: - self.stderr.write(self.style.ERROR(f"- Missing env variable: {k}")) + if options["check"]: + self.stdout.write(self.style.SUCCESS("Checking for missing required environment variables...")) + missing_vars = env.check_explicit() + if missing_vars: + for var in missing_vars: + self.stderr.write(self.style.ERROR(f"- Missing env variable: {var}")) check_failure = True + if check_failure and not options["ignore_errors"]: + raise CommandError("One or more required environment variables are missing!") + return + + for key, config in sorted(env.config.items()): + help_text = config.get("help", "") + default_value = config.get("default") + # develop_value = config.get("develop") + # explicit = config.get("explicit", False) + if options["develop"]: + value = env.get_develop_value(key) else: - value: Any = env.get_value(k) - if not options["changed"] or (value != default): - self.stdout.write(pattern.format(key=k, value=value, help=help, default=default)) + value = env.get_value(key) - if check_failure and not options["ignore_errors"]: - raise CommandError("Env check command failure!") + if options["changed"] and value == default_value: + continue + self.stdout.write(pattern.format(key=key, value=value, help=help_text, default=default_value)) diff --git a/src/hope_country_report/apps/power_query/storage.py b/src/hope_country_report/apps/power_query/storage.py index 882981a7..e280665d 100644 --- a/src/hope_country_report/apps/power_query/storage.py +++ b/src/hope_country_report/apps/power_query/storage.py @@ -1,17 +1,8 @@ import os -from django.core.files.storage import FileSystemStorage - from storages.backends.azure_storage import AzureStorage -class DataSetStorage(FileSystemStorage): - def get_available_name(self, name: str, max_length: int | None = None) -> str: - if self.exists(name): - self.delete(name) - return name - - class ReadOnlyStorageMixin: def delete(self, name): raise RuntimeError("This storage cannot delete files") diff --git a/src/hope_country_report/config/__init__.py b/src/hope_country_report/config/__init__.py index c51e5d17..61b20ece 100644 --- a/src/hope_country_report/config/__init__.py +++ b/src/hope_country_report/config/__init__.py @@ -1,5 +1,4 @@ from enum import Enum - from smart_env import SmartEnv DJANGO_HELP_BASE = "https://docs.djangoproject.com/en/5.0/ref/settings" @@ -119,7 +118,7 @@ class Group(Enum): ), "STATIC_FILE_STORAGE": ( str, - "hope_country_report.apps.power_query.storage.StaticStorage", + "django.core.files.storage.FileSystemStorage", setting("storages"), ), "STATIC_ROOT": (str, "/tmp/static/", setting("static-root")), diff --git a/src/hope_country_report/config/settings.py b/src/hope_country_report/config/settings.py index b88ca732..cb0f8365 100644 --- a/src/hope_country_report/config/settings.py +++ b/src/hope_country_report/config/settings.py @@ -33,18 +33,10 @@ MIGRATION_MODULES = {"hope": None} STORAGES = { - "default": { - "BACKEND": env("DEFAULT_FILE_STORAGE"), - }, - "staticfiles": { - "BACKEND": env("STATIC_FILE_STORAGE"), - }, - "media": { - "BACKEND": env("MEDIA_FILE_STORAGE"), - }, - "hope": { - "BACKEND": env("HOPE_FILE_STORAGE"), - }, + "default": env.storage("DEFAULT_FILE_STORAGE"), + "staticfiles": env.storage("STATIC_FILE_STORAGE"), + "media": env.storage("MEDIA_FILE_STORAGE"), + "hope": env.storage("HOPE_FILE_STORAGE"), } INSTALLED_APPS = [ "hope_country_report.web", diff --git a/tests/conftest.py b/tests/conftest.py index b8761480..bb314bee 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -80,8 +80,8 @@ def pytest_configure(config): ADMINS="", ALLOWED_HOSTS="*", AUTHENTICATION_BACKENDS="", - DEFAULT_FILE_STORAGE="hope_country_report.apps.power_query.storage.DataSetStorage", - STATIC_FILE_STORAGE="hope_country_report.apps.power_query.storage.DataSetStorage", + DEFAULT_FILE_STORAGE="django.core.files.storage.FileSystemStorage", + STATIC_FILE_STORAGE="django.core.files.storage.FileSystemStorage", DJANGO_SETTINGS_MODULE="hope_country_report.config.settings", CATCH_ALL_EMAIL="", CELERY_TASK_ALWAYS_EAGER="1",