Skip to content

Commit

Permalink
more robust settings adjustments
Browse files Browse the repository at this point in the history
  • Loading branch information
bckohan committed Jun 5, 2024
1 parent 8178545 commit 030288d
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 11 deletions.
25 changes: 14 additions & 11 deletions django_routines/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from dataclasses import asdict, dataclass, field

from django.core.exceptions import ImproperlyConfigured
from django.utils.functional import Promise

VERSION = (1, 0, 0)

Expand Down Expand Up @@ -108,7 +109,7 @@ class Routine:
The name of the routine.
"""

help_text: str
help_text: t.Union[str, Promise]
"""
The help text to display for the routine.
"""
Expand All @@ -118,7 +119,7 @@ class Routine:
The commands to run in the routine.
"""

switch_helps: t.Dict[str, str] = field(default_factory=dict)
switch_helps: t.Dict[str, t.Union[str, Promise]] = field(default_factory=dict)

def __len__(self):
return len(self.commands)
Expand Down Expand Up @@ -169,7 +170,8 @@ def routine(name: str, help_text: str = "", *commands: RoutineCommand, **switch_
:param commands: The commands to run in the routine.
"""
settings = sys._getframe(1).f_globals # noqa: WPS437
settings.setdefault(ROUTINE_SETTING, {})
if not settings.get(ROUTINE_SETTING, {}):
settings[ROUTINE_SETTING] = {}
routine = Routine(name, help_text, switch_helps=switch_helps)
for command in commands:
routine.add(command)
Expand Down Expand Up @@ -201,19 +203,20 @@ def command(
:return: The new command.
"""
settings = sys._getframe(1).f_globals # noqa: WPS437
settings.setdefault(ROUTINE_SETTING, {})
routines = settings[ROUTINE_SETTING]
if not settings.get(ROUTINE_SETTING, {}):
settings[ROUTINE_SETTING] = {}
routine_dict = settings[ROUTINE_SETTING]
routine_obj = (
Routine.from_dict(routines[routine])
if routine in routines
Routine.from_dict(routine_dict[routine])
if routine in routine_dict
else Routine(routine, "", [])
)
new_cmd = routine_obj.add(
RoutineCommand(
t.cast(t.Tuple[str], command), priority, tuple(switches or []), options
)
)
settings[ROUTINE_SETTING][routine] = asdict(routine_obj)
routine_dict[routine] = asdict(routine_obj)
return new_cmd


Expand All @@ -235,7 +238,7 @@ def get_routine(name: str) -> Routine:

try:
if not settings.configured:
Routine.from_dict(sys._getframe(1).f_globals[ROUTINE_SETTING][name]) # noqa: WPS437
Routine.from_dict(sys._getframe(1).f_globals.get(ROUTINE_SETTING, {})[name]) # noqa: WPS437
return Routine.from_dict(getattr(settings, ROUTINE_SETTING, {})[name])
except TypeError as err:
raise ImproperlyConfigured(
Expand All @@ -252,10 +255,10 @@ def routines() -> t.Generator[Routine, None, None]:
from django.conf import settings

routines = (
sys._getframe(1).f_globals[ROUTINE_SETTING] # noqa: WPS437
sys._getframe(1).f_globals.get(ROUTINE_SETTING, {}) # noqa: WPS437
if not settings.configured
else getattr(settings, ROUTINE_SETTING, {})
)
) or {}
for name, routine in routines.items():
try:
yield Routine.from_dict(routine)
Expand Down
123 changes: 123 additions & 0 deletions tests/no_routines.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import os
from pathlib import Path
from django.utils.translation import gettext_lazy as _

# Set default terminal width for help outputs - necessary for
# testing help output in CI environments.
os.environ["TERMINAL_WIDTH"] = "80"

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "django-insecure-$druy$m$nio-bkagw_%=@(1w)q0=k^mk_5sfk3zi9#4v!%mh*u"

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
"tests.django_routines_tests",
"django_routines",
"django_typer",
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
]

MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]


TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]


# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases

DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
"TEST": {"NAME": BASE_DIR / "db.sqlite3"},
}
}


# Password validation
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
{
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
},
{
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
},
{
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
},
]


# Internationalization
# https://docs.djangoproject.com/en/3.2/topics/i18n/

LANGUAGE_CODE = "en-us"
# LANGUAGE_CODE = 'de'


TIME_ZONE = "UTC"

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/

STATIC_URL = "/static/"

# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"


SETTINGS_FILE = 1

ROOT_URLCONF = "tests.urls"
3 changes: 3 additions & 0 deletions tests/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
)
from django.utils.translation import gettext_lazy as _

_ = str

# Set default terminal width for help outputs - necessary for
# testing help output in CI environments.
os.environ["TERMINAL_WIDTH"] = "80"
Expand Down Expand Up @@ -130,6 +132,7 @@

ROOT_URLCONF = "tests.urls"

DJANGO_ROUTINES = None

routine(
"deploy",
Expand Down
12 changes: 12 additions & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django_typer import get_command
from django.test import TestCase, override_settings
from django.core.exceptions import ImproperlyConfigured
from django.core.management import CommandError, call_command
from django_routines import get_routine


Expand Down Expand Up @@ -69,3 +70,14 @@ def test_get_missing_routine(self):
def test_get_malformed_routine(self):
with self.assertRaises(ImproperlyConfigured):
get_routine("bad_command")

# why do these break everything??
# @override_settings(DJANGO_ROUTINES={})
# def test_no_routines(self):
# with self.assertRaises(CommandError):
# call_command("routine")

# @override_settings(DJANGO_ROUTINES=None)
# def test_routines_none(self):
# with self.assertRaises(CommandError):
# call_command("routine")

0 comments on commit 030288d

Please sign in to comment.