From a828de0c0d27b1aba070749f165ab38851888122 Mon Sep 17 00:00:00 2001 From: Brian Kohan Date: Wed, 5 Jun 2024 00:03:51 -0700 Subject: [PATCH] finish docs, fix a few remaining issues --- README.md | 172 +++++++++++++++++- django_routines/__init__.py | 40 +++- .../management/commands/routine.py | 14 +- doc/.DS_Store | Bin 0 -> 6148 bytes doc/source/_static/style.css | 4 + doc/source/conf.py | 6 +- doc/source/index.rst | 107 ++++++++--- doc/source/installation.rst | 35 ++++ doc/source/refs.rst | 2 + examples/__init__.py | 34 ++++ examples/deploy.svg | 162 +++++++++++++++++ examples/package.svg | 133 ++++++++++++++ examples/readme.py | 33 ++++ examples/readme_dict.py | 34 ++++ tests/settings.py | 102 ++--------- tests/urls.py | 1 - 16 files changed, 747 insertions(+), 132 deletions(-) create mode 100644 doc/.DS_Store create mode 100644 doc/source/_static/style.css create mode 100644 doc/source/installation.rst create mode 100644 examples/__init__.py create mode 100644 examples/deploy.svg create mode 100644 examples/package.svg create mode 100644 examples/readme.py create mode 100644 examples/readme_dict.py delete mode 100644 tests/urls.py diff --git a/README.md b/README.md index 6720d34..b1dd2fe 100644 --- a/README.md +++ b/README.md @@ -10,4 +10,174 @@ [![Documentation Status](https://readthedocs.org/projects/django-routines/badge/?version=latest)](http://django-routines.readthedocs.io/?badge=latest/) [![Code Cov](https://codecov.io/gh/bckohan/django-routines/branch/main/graph/badge.svg?token=0IZOKN2DYL)](https://codecov.io/gh/bckohan/django-routines) [![Test Status](https://github.com/bckohan/django-routines/workflows/test/badge.svg)](https://github.com/bckohan/django-routines/actions/workflows/test.yml) -[![Lint Status](https://github.com/bckohan/django-routines/workflows/lint/badge.svg)](https://github.com/bckohan/django-routines/actions/workflows/lint.yml) \ No newline at end of file +[![Lint Status](https://github.com/bckohan/django-routines/workflows/lint/badge.svg)](https://github.com/bckohan/django-routines/actions/workflows/lint.yml) + + +Configure batches of Django management commands in your settings files and run them all at once. +For example, batch together your common database maintenance tasks, deployment routines or any +other set of commands you need to run together. This helps single source general site maintenance +into your settings files keeping your code base [DRY](). + +## Example + +Let's define two named routines, "package" and "deploy". The package routine will be a collection +of commands that we typically run to generate package artifacts (like migrations and transpiled +javascript). The deploy routine will be a collection of commands we typically run when deploying +the site for the first time on a new server or when we deploy version updates on the server. + +**Routines commands are run in the order they are registered, or by priority.** + +```python +from django_routines import RoutineCommand, command, routine + +# register routines and their help text +routine( + name="package", + help_text=( + "Generate pre-package artifacts like migrations and transpiled " + "javascript." + ) +) +# you may register commands on a routine after defining a routine (or before!) +command("package", "makemigrations") +command("package", "renderstatic") + +routine( + "deploy", + "Deploy the site application into production.", + + # you may also specify commands inline using the RoutineCommand dataclass + RoutineCommand( + ("routine", "package"), switches=["prepare"] + ), # routine commands can be other routines! + RoutineCommand("migrate"), + RoutineCommand("collectstatic"), + RoutineCommand(("shellcompletion", "install"), switches=["initial"]), + RoutineCommand(("loaddata", "./fixtures/demo.json"), switches=["demo"]), + + # define switches that toggle commands on and off + prepare="Generate artifacts like migrations and transpiled javascript.", + initial="Things to do on the very first deployment on a new server.", + demo="Load the demo data.", +) +``` + +The routine command will read our settings file and generate two subcommands, one called deploy and one called package: + +![package](https://raw.githubusercontent.com/bckohan/django-routines/main/examples/package.svg) + +Now we can run all of our package routines with one command: + +```bash + ?> ./manage.py routine package + makemigrations + ... + renderstatic + ... +``` + +The deploy command has several switches that we can enable to run additional commands. + +![deploy](https://raw.githubusercontent.com/bckohan/django-routines/main/examples/deploy.svg) + +For example to deploy our demo on a new server we would run: + +```bash + ?> ./manage.py routine deploy --initial --demo + migrate + ... + collectstatic + ... + shellcompletion install + ... + loaddata ./fixtures/demo.json + ... +``` + +## Settings + +The [RoutineCommand](https://django-routines.readthedocs.io/en/latest/reference.html#django_routines.RoutineCommand) dataclass, [routine](https://django-routines.readthedocs.io/en/latest/reference.html#django_routines.routine) and [command](https://django-routines.readthedocs.io/en/latest/reference.html#django_routines.command) helper functions in the example above make it easier for us to work with the native configuration format which is a dictionary structure defined in the ``DJANGO_ROUTINES`` setting attribute. For example the above configuration is equivalent to: + +```python +DJANGO_ROUTINES = { + "deploy": { + "commands": [ + {"command": ("routine", "package"), "switches": ["prepare"]}, + {"command": "migrate"}, + {"command": "collectstatic"}, + { + "command": ("shellcompletion", "install"), + "switches": ["initial"], + }, + { + "command": ("loaddata", "./fixtures/demo.json"), + "switches": ["demo"], + }, + ], + "help_text": "Deploy the site application into production.", + "name": "deploy", + "switch_helps": { + "demo": "Load the demo data.", + "initial": "Things to do on the very first deployment on a new server.", + "prepare": "Generate artifacts like migrations and transpiled javascript.", + }, + }, + "package": { + "commands": [ + {"command": "makemigrations"}, + {"command": "renderstatic"}, + ], + "help_text": "Generate pre-package artifacts like migrations and transpiled javascript.", + "name": "package", + }, +} +``` + + +## Priorities + +If you are composing settings from multiple apps or source files using a utility like [django-split-settings](https://pypi.org/project/django-split-settings/) you may not be able to define all routines at once. You can use priorities to make sure commands defined in a de-coupled way run in the correct order. + +```python + command("deploy", "makemigrations", priority=1) + command("deploy", "migrate", priority=2) +``` + +## Options + +When specifying arguments you may add them to the command tuple OR specify them as named options in the style that will be passed to [call_command](https://docs.djangoproject.com/en/stable/ref/django-admin/#django.core.management.call_command): + +```python + # these two are equivalent + command("package", ("makemigrations", "--no-header")) + command("package", "makemigrations", no_header=True) +``` + + +## Installation + + +1. Clone django-routines from [GitHub](https://github.com/bckohan/django-routines) or install a release off [PyPI](https://pypi.python.org/pypi/django-routines) : + + ```bash + pip install django-routines + ``` + + [rich](https://rich.readthedocs.io/) is a powerful library for rich text and beautiful formatting in the terminal. It is not required, but highly recommended for the best experience: + + ```bash + pip install "django-routines[rich]" + ``` + + +2. Add ``django_routines`` to your ``INSTALLED_APPS`` setting: + + ```python + INSTALLED_APPS = [ + ... + 'django_routines', + 'django_typer', # optional! + ] + ``` + + *You only need to install django_typer as an app if you want to use the shellcompletion command to* [enable tab-completion](https://django-typer.readthedocs.io/en/latest/shell_completion.html) *or if you would like django-typer to install* [rich traceback rendering](https://django-typer.readthedocs.io/en/latest/howto.html#configure-rich-stack-traces) *for you - which it does by default if rich is also installed.* diff --git a/django_routines/__init__.py b/django_routines/__init__.py index 3f73d7b..e524c6e 100644 --- a/django_routines/__init__.py +++ b/django_routines/__init__.py @@ -52,7 +52,7 @@ class RoutineCommand: Dataclass to hold the routine command information. """ - command: t.Tuple[str, ...] + command: t.Union[str, t.Tuple[str, ...]] """ The command and its arguments to run the routine, all strings or coercible to strings that the command will parse correctly. @@ -75,6 +75,18 @@ class RoutineCommand: t.Any options to pass to the command via call_command. """ + @property + def command_name(self) -> str: + return self.command if isinstance(self.command, str) else self.command[0] + + @property + def command_args(self) -> t.Tuple[str, ...]: + return tuple() if isinstance(self.command, str) else self.command[1:] + + @property + def command_str(self) -> str: + return self.command if isinstance(self.command, str) else " ".join(self.command) + @classmethod def from_dict( cls, obj: t.Union["RoutineCommand", t.Dict[str, t.Any]] @@ -161,7 +173,12 @@ def from_dict(cls, obj: t.Union["Routine", t.Dict[str, t.Any]]) -> "Routine": ) -def routine(name: str, help_text: str = "", *commands: RoutineCommand, **switch_helps): +def routine( + name: str, + help_text: t.Union[str, Promise] = "", + *commands: RoutineCommand, + **switch_helps, +): """ Register a routine to the t.List of routines in settings to be run. @@ -172,7 +189,24 @@ def routine(name: str, help_text: str = "", *commands: RoutineCommand, **switch_ settings = sys._getframe(1).f_globals # noqa: WPS437 if not settings.get(ROUTINE_SETTING, {}): settings[ROUTINE_SETTING] = {} - routine = Routine(name, help_text, switch_helps=switch_helps) + + existing: t.List[RoutineCommand] = [] + try: + routine = get_routine(name) + help_text = ( + help_text + # don't trigger translation - we're in settings! + if isinstance(help_text, Promise) or help_text + else routine.help_text + ) + switch_helps = {**routine.switch_helps, **switch_helps} + existing = routine.commands + except KeyError: + pass + routine = Routine( + name, help_text=help_text, commands=existing, switch_helps=switch_helps + ) + for command in commands: routine.add(command) settings[ROUTINE_SETTING][name] = asdict(routine) diff --git a/django_routines/management/commands/routine.py b/django_routines/management/commands/routine.py index 0f9ef23..1f2a5b9 100644 --- a/django_routines/management/commands/routine.py +++ b/django_routines/management/commands/routine.py @@ -88,10 +88,10 @@ def _run_routine(self): assert self.routine for command in self.plan: if self.verbosity > 0: - self.secho(" ".join(command.command), fg="cyan") + self.secho(command.command_str, fg="cyan") try: cmd = get_command( - command.command[0], + command.command_name, BaseCommand, stdout=t.cast(t.IO[str], self.stdout._out), stderr=t.cast(t.IO[str], self.stderr._out), @@ -105,19 +105,19 @@ def _run_routine(self): "verbosity" in arg for arg in getattr(cmd, "suppressed_base_arguments", []) ) - and not any("--verbosity" in arg for arg in command.command[1:]) + and not any("--verbosity" in arg for arg in command.command_args) ): # only pass verbosity if it was passed to routines, not suppressed # by the command class and not passed by the configured command options = {"verbosity": self.verbosity, **options} - call_command(cmd, *command.command[1:], **options) + call_command(cmd, *command.command_args, **options) except KeyError: - raise CommandError(f"Command not found: {command.command[0]}") + raise CommandError(f"Command not found: {command.command_name}") def _list(self) -> None: for command in self.plan: priority = str(command.priority) - cmd_str = " ".join(command.command) + cmd_str = command.command_str switches_str = " | " if command.switches else "" opt_str = " ".join([f"{k}={v}" for k, v in command.options.items()]) if self.force_color or not self.no_color: @@ -162,7 +162,7 @@ def _list(self) -> None: command_strings = [] for command in routine.commands: priority = f"{'[green]' if use_rich else ''}{command.priority}{'[/green]' if use_rich else ''}" - cmd_str = f"{'[cyan]' if use_rich else ''}{' '.join(command.command)}{'[/cyan]' if use_rich else ''}" + cmd_str = f"{'[cyan]' if use_rich else ''}{command.command_str}{'[/cyan]' if use_rich else ''}" if command.options: if use_rich: opt_str = " ".join( diff --git a/doc/.DS_Store b/doc/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..272505e0ae18401d382e5f90916fb8b663a6241f GIT binary patch literal 6148 zcmeHKOH0E*5Z>*>rW7Fug&r5Y7Od7MUP7#Yz=$4HYC?(zW41J@Ig~=q`iJ}_{vKy` zH_&46C}L+|_nV!^ZsvpRgE7Y4S-8iT%^0(wA#zkI1kIJMnh8eaYK}0-(@7A^pkkW8 zX~J)BvVhH4#A3Gm{U5<3j?%2(|KzoLqq)(tT2{xp_nu_#WqvkGU4MFuqbn)npw#`~ zIvVFAd+S^#nI9$NsY-~#F@)URL`f)fSI&|!Rk@yaSZ%94vb*#7;eNj-1}Ddho|vDa zelR#%EZWxg&hFXe=sA8#Kpo;7gM~(% T1??&wkS+p>5bB75Utr)1y1+`! literal 0 HcmV?d00001 diff --git a/doc/source/_static/style.css b/doc/source/_static/style.css new file mode 100644 index 0000000..c49d190 --- /dev/null +++ b/doc/source/_static/style.css @@ -0,0 +1,4 @@ +.big { + font-size: 24px; /* Or any size you prefer */ + font-weight: bold; /* If you want it bold */ +} diff --git a/doc/source/conf.py b/doc/source/conf.py index 4691f12..63e4257 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -8,7 +8,7 @@ import django_routines -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tests.settings") +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "examples.readme") django.setup() sys.path.append(str(Path(__file__).parent.parent / "tests")) @@ -70,7 +70,9 @@ # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". - +html_static_path = [ + '_static', +] html_css_files = [ "style.css", ] diff --git a/doc/source/index.rst b/doc/source/index.rst index 05721fc..1aa3d43 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -5,59 +5,112 @@ Django Routines =============== -Build up batches of Django management commands in your settings files and run them all at once. +Configure batches of Django management commands in your settings files and run them all at once. For example, batch together your common database maintenance tasks, deployment routines or any other set of commands you need to run together. This helps single source general site maintenance into your settings files keeping your code base DRY_. -:big:`Installation` +:big:`Example` -1. Clone django-routines from GitHub_ or install a release off PyPI_ : +Let's define two named routines, "package" and "deploy". The package routine will be a collection +of commands that we typically run to generate package artifacts (like migrations and transpiled +javascript). The deploy routine will be a collection of commands we typically run when deploying +the site for the first time on a new server or when we deploy version updates on the server. - .. code:: bash +.. note:: - pip install django-routines + Routines commands are run in the order they are registered, or by priority_. - rich_ is a powerful library for rich text and beautiful formatting in the terminal. - It is not required, but highly recommended for the best experience: +.. literalinclude:: ../../examples/readme.py + :caption: settings.py + :linenos: + :lines: 2-33 - .. code:: bash +The routine command will read our settings file and generate two subcommands, one called deploy +and one called package: - pip install "django-routines[rich]" +.. typer:: django_routines.management.commands.routine.Command:typer_app:package + :prog: ./manage.py routine + :theme: dark + :convert-png: latex +Now we can run all of our package routines with one command: -2. Add ``django_routines`` to your ``INSTALLED_APPS`` setting: +.. code-block:: console - .. code:: python + ?> ./manage.py routine package + makemigrations + ... + renderstatic + ... - INSTALLED_APPS = [ - ... - 'django_routines', - ] +The deploy command has several switches that we can enable to run additional commands. -3. Optionally add ``django_typer`` to your ``INSTALLED_APPS`` setting: +.. typer:: django_routines.management.commands.routine.Command:typer_app:deploy + :prog: ./manage.py routine + :theme: dark + :convert-png: latex - .. code:: python +For example to deploy our demo on a new server we would run: - INSTALLED_APPS = [ - ... - 'django_typer', - ] +.. code-block:: console - *You only need to install django_typer as an app if you want to use the shellcompletion command - to enable tab-completion or if you would like django-typer to install* - `rich traceback rendering `_ - *for you - which it does by default if rich is also installed.* + ?> ./manage.py routine deploy --initial --demo + migrate + ... + collectstatic + ... + shellcompletion install + ... + loaddata ./fixtures/demo.json + ... -:big:`Basic Example` +:big:`Settings` -.. todo:: Add a basic example +The :class:`~django_routines.RoutineCommand` dataclass, :func:`django_routines.routine` and +:func:`django_routines.command` helper functions in the example above make it easier for us to +work with the native configuration format which is a dictionary structure defined in the +``DJANGO_ROUTINES`` setting attribute. For example the above configuration is equivalent to: +.. literalinclude:: ../../examples/readme_dict.py + :caption: settings.py + :linenos: + :lines: 2-33 + + +.. _priority: + +:big:`Priorities` + +If you are composing settings from multiple apps or source files using a utility like +django-split-settings_ you may not be able to define all routines at once. You can use +priorities to make sure commands defined in a de-coupled way run in the correct order. + +.. code-block:: python + + command("deploy", "makemigrations", priority=1) + command("deploy", "migrate", priority=2) + +:big:`Options` + +When specifying arguments you may add them to the command tuple OR specify them as named +options in the style that will be passed to call_command_: + +.. code-block:: python + + # these two are equivalent + command("package", ("makemigrations", "--no-header")) + command("package", "makemigrations", no_header=True) + +.. note:: + + Lazy translations work as help_text for routines and switches. .. toctree:: :maxdepth: 2 :caption: Contents: + installation reference changelog diff --git a/doc/source/installation.rst b/doc/source/installation.rst new file mode 100644 index 0000000..f86f90b --- /dev/null +++ b/doc/source/installation.rst @@ -0,0 +1,35 @@ +.. include:: ./refs.rst + +============ +Installation +============ + +1. Clone django-routines from GitHub_ or install a release off PyPI_ : + + .. code:: bash + + pip install django-routines + + rich_ is a powerful library for rich text and beautiful formatting in the terminal. + It is not required, but highly recommended for the best experience: + + .. code:: bash + + pip install "django-routines[rich]" + + +2. Add ``django_routines`` to your ``INSTALLED_APPS`` setting: + + .. code:: python + + INSTALLED_APPS = [ + ... + 'django_routines', + 'django_typer', # optional! + ] + + *You only need to install django_typer as an app if you want to use the shellcompletion command + to* `enable tab-completion `_ + *or if you would like django-typer to install* + `rich traceback rendering `_ + *for you - which it does by default if rich is also installed.* diff --git a/doc/source/refs.rst b/doc/source/refs.rst index 25323d2..74baf21 100644 --- a/doc/source/refs.rst +++ b/doc/source/refs.rst @@ -6,3 +6,5 @@ .. _django-routines: https://pypi.python.org/pypi/django-routines .. _DRY: https://en.wikipedia.org/wiki/Don%27t_repeat_yourself .. _TyperCommand: https://django-typer.readthedocs.io/en/latest/reference.html#django_typer.TyperCommand +.. _django-split-settings: https://pypi.org/project/django-split-settings/ +.. _call_command: https://docs.djangoproject.com/en/stable/ref/django-admin/#django.core.management.call_command diff --git a/examples/__init__.py b/examples/__init__.py new file mode 100644 index 0000000..2524bd9 --- /dev/null +++ b/examples/__init__.py @@ -0,0 +1,34 @@ +import os +from pathlib import Path + +# Set default terminal width for help outputs - necessary for +# testing help output in CI environments. +os.environ["TERMINAL_WIDTH"] = "80" + +BASE_DIR = Path(__file__).resolve().parent.parent + + +INSTALLED_APPS = [ + "tests.django_routines_tests", + "django_routines", + "django_typer", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", +] + +DATABASES = {"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}} + +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", +] + +STATIC_URL = "static/" diff --git a/examples/deploy.svg b/examples/deploy.svg new file mode 100644 index 0000000..22fd303 --- /dev/null +++ b/examples/deploy.svg @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ./manage.py routine + + + + + + + + + + +Usage: ./manage.py routine [OPTIONS] COMMAND [ARGS]... + + +Deploy the site application into production. + + +[0routine package | prepare +[0migrate +[0collectstatic +[0shellcompletion install | initial +[0loaddata ./fixtures/demo.json | demo + +╭─ Options ─────────────────────────────────────────────────────╮ +--allInclude all switched commands. +--demoLoad the demo data. +--initialThings to do on the very first deployment  +on a new server.                           +--prepareGenerate artifacts like migrations and     +transpiled javascript.                     +--helpShow this message and exit. +╰───────────────────────────────────────────────────────────────╯ +╭─ Commands ────────────────────────────────────────────────────╮ +list List the commands that will be run.                    +╰───────────────────────────────────────────────────────────────╯ + + + + diff --git a/examples/package.svg b/examples/package.svg new file mode 100644 index 0000000..a6b4224 --- /dev/null +++ b/examples/package.svg @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ./manage.py routine + + + + + + + + + + +Usage: ./manage.py routine [OPTIONS] COMMAND [ARGS]... + + +Generate pre-package artifacts like migrations and transpiled  +javascript. + + +[0makemigrations +[0renderstatic + +╭─ Options ─────────────────────────────────────────────────────╮ +--allInclude all switched commands. +--helpShow this message and exit. +╰───────────────────────────────────────────────────────────────╯ +╭─ Commands ────────────────────────────────────────────────────╮ +list List the commands that will be run.                    +╰───────────────────────────────────────────────────────────────╯ + + + + diff --git a/examples/readme.py b/examples/readme.py new file mode 100644 index 0000000..69e6a26 --- /dev/null +++ b/examples/readme.py @@ -0,0 +1,33 @@ +from . import * # noqa: F403 +from django_routines import RoutineCommand, command, routine + +# register routines and their help text +routine( + name="package", + help_text=( + "Generate pre-package artifacts like migrations and transpiled " + "javascript." + ) +) +# you may register commands on a routine after defining a routine (or before!) +command("package", "makemigrations") +command("package", "renderstatic") + +routine( + "deploy", + "Deploy the site application into production.", + + # you may also specify commands inline using the RoutineCommand dataclass + RoutineCommand( + ("routine", "package"), switches=["prepare"] + ), # routine commands can be other routines! + RoutineCommand("migrate"), + RoutineCommand("collectstatic"), + RoutineCommand(("shellcompletion", "install"), switches=["initial"]), + RoutineCommand(("loaddata", "./fixtures/demo.json"), switches=["demo"]), + + # define switches that toggle commands on and off + prepare="Generate artifacts like migrations and transpiled javascript.", + initial="Things to do on the very first deployment on a new server.", + demo="Load the demo data.", +) diff --git a/examples/readme_dict.py b/examples/readme_dict.py new file mode 100644 index 0000000..106eb3c --- /dev/null +++ b/examples/readme_dict.py @@ -0,0 +1,34 @@ +from . import * # noqa: F403 + +DJANGO_ROUTINES = { + "deploy": { + "commands": [ + {"command": ("routine", "package"), "switches": ["prepare"]}, + {"command": "migrate"}, + {"command": "collectstatic"}, + { + "command": ("shellcompletion", "install"), + "switches": ["initial"], + }, + { + "command": ("loaddata", "./fixtures/demo.json"), + "switches": ["demo"], + }, + ], + "help_text": "Deploy the site application into production.", + "name": "deploy", + "switch_helps": { + "demo": "Load the demo data.", + "initial": "Things to do on the very first deployment on a new server.", + "prepare": "Generate artifacts like migrations and transpiled javascript.", + }, + }, + "package": { + "commands": [ + {"command": "makemigrations"}, + {"command": "renderstatic"}, + ], + "help_text": "Generate pre-package artifacts like migrations and transpiled javascript.", + "name": "package", + }, +} diff --git a/tests/settings.py b/tests/settings.py index 94b2c35..618f017 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -10,7 +10,6 @@ ) from django.utils.translation import gettext_lazy as _ -_ = str # Set default terminal width for help outputs - necessary for # testing help output in CI environments. @@ -19,26 +18,12 @@ # 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", @@ -46,36 +31,6 @@ "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": { @@ -85,55 +40,20 @@ } } - -# 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", - }, +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", ] - -# 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" - DJANGO_ROUTINES = None +STATIC_URL = "static/" + routine( "deploy", _("Deploy the site application into production."), @@ -151,6 +71,7 @@ assert get_routine("deploy").name == "deploy" +command("test", "track", "2", priority=0, switches=("initial", "demo")) routine( "test", _("Test Routine 1"), @@ -160,7 +81,6 @@ RoutineCommand(("track", "1"), priority=4), ) -command("test", "track", "2", priority=0, switches=("initial", "demo")) command("test", "track", "3", priority=3, demo=2) command("test", "track", "4", priority=3, demo=6) command("test", "track", "5", priority=6, switches=["demo"]) diff --git a/tests/urls.py b/tests/urls.py deleted file mode 100644 index 637600f..0000000 --- a/tests/urls.py +++ /dev/null @@ -1 +0,0 @@ -urlpatterns = []