diff --git a/config/__init__.py b/config/__init__.py index 69052b7a..17d10dd7 100644 --- a/config/__init__.py +++ b/config/__init__.py @@ -1 +1,24 @@ -"""Holds the setings and entrypoints.""" +"""Define the configuration scheme using environ-config.""" + +import logging + +import environ + +logger = logging.getLogger(__name__) + + +@environ.config(prefix="SCRAM") +class AppConfig: + """Top level configuration (i.e. SCRAM_).""" + + debugger = environ.var( + default="", help='Will launch the appropriate debugger if set to either "pycharm-pydevd" or "debugpy".' + ) + + @debugger.validator + def _warn_on_unknown_debugger(self, var, debugger): + if debugger and debugger not in {"pycharm-pydevd", "debugpy"}: + logger.warning("Unknown debugger value: %s", debugger) + + +cfg = environ.to_config(AppConfig) diff --git a/config/asgi.py b/config/asgi.py index 5e11d1fa..24095fe5 100644 --- a/config/asgi.py +++ b/config/asgi.py @@ -18,13 +18,14 @@ # TODO: from channels.security.websocket import AllowedHostsOriginValidator from django.core.asgi import get_asgi_application +from config import cfg + logger = logging.getLogger(__name__) # Here we setup a debugger if this is desired. This obviously should not be run in production. -debug = os.environ.get("DEBUG") -if debug: - logger.info("Django is set to use a debugger. Provided debug mode: %s", debug) - if debug == "pycharm-pydevd": +if cfg.debugger: + logger.info("Django is set to use a debugger. Provided debug mode: %s", cfg.debugger) + if cfg.debugger == "pycharm-pydevd": logger.info("Entering debug mode for pycharm, make sure the debug server is running in PyCharm!") import pydevd_pycharm @@ -32,7 +33,7 @@ pydevd_pycharm.settrace("host.docker.internal", port=56783, stdoutToServer=True, stderrToServer=True) logger.info("Debugger started.") - elif debug == "debugpy": + elif cfg.debugger == "debugpy": logger.info("Entering debug mode for debugpy (VSCode)") import debugpy @@ -41,7 +42,7 @@ logger.info("Debugger listening on port 56780.") else: - logger.warning("Invalid debug mode given: %s. Debugger not started", debug) + logger.warning("Invalid debug mode given: %s. Debugger not started", cfg.debugger) # This allows easy placement of apps within the interior # scram directory. diff --git a/docs/document_env_vars.py b/docs/document_env_vars.py new file mode 100644 index 00000000..71ec1e4c --- /dev/null +++ b/docs/document_env_vars.py @@ -0,0 +1,28 @@ +"""Converts environ-config's documentation to Markdown and writes it to the docs folder.""" + +import sys +from pathlib import Path + +sys.path.append(".") + +from config import cfg + + +def formatter(options): + """Formats the help text to Markdown. + + Returns: + str: A simple Markdown table with the env vars + """ + result = "| Name | Description | Required | Default |\n" + result += "|-|-|-|-|\n" + for o in options: + result += f"|{o['var_name']}|{o['help_str']}|{o['required']}|{o['default']!r}|\n" + + return result + + +def on_pre_build(config): + """Handler from mkdocs hook.""" + with Path("docs/environment_variables.md").open("w", encoding="utf-8") as f: + f.write(cfg.generate_help(formatter=formatter)) diff --git a/docs/reference/index.md b/docs/reference/index.md index fc771185..517dbe31 100644 --- a/docs/reference/index.md +++ b/docs/reference/index.md @@ -2,6 +2,6 @@ The SCRAM ecosystem consists of two parts: -A Django app, [route_manager](/reference/django) +A Django app, [route_manager](django.md) -A translator service, [translator](/reference/translator) +A translator service, [translator](translator.md) diff --git a/mkdocs.yml b/mkdocs.yml index 704db80c..ee762ea5 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -14,3 +14,6 @@ plugins: show_submodules: true - search - section-index + +hooks: + - docs/document_env_vars.py diff --git a/pyproject.toml b/pyproject.toml index 5c332104..549bd79c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,7 @@ data_file = "coverage.coverage" [tool.coverage.report] exclude_also = [ + "if cfg.debugger:", "if debug:", "if self.debug:", "if settings.DEBUG", diff --git a/requirements/base.txt b/requirements/base.txt index b43b582a..a4b43109 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -1,6 +1,7 @@ argon2-cffi==21.3.0 # https://github.com/hynek/argon2_cffi django-celery-beat # https://github.com/celery/django-celery-beat django-netfields # https://pypi.org/project/django-netfields/ +environ-config # https://pypi.org/project/environ-config/ flower==1.0.0 # https://github.com/mher/flower python-slugify==6.1.2 # https://github.com/un33k/python-slugify uvicorn[standard]==0.17.6 # https://github.com/encode/uvicorn diff --git a/requirements/local.txt b/requirements/local.txt index 2712cf7e..37b27421 100644 --- a/requirements/local.txt +++ b/requirements/local.txt @@ -41,9 +41,3 @@ django-debug-toolbar==3.4.0 # https://github.com/jazzband/django-debug-toolbar django-extensions==3.1.5 # https://github.com/django-extensions/django-extensions django-coverage-plugin==3.1.0 # https://github.com/nedbat/django_coverage_plugin pytest-django==4.5.2 # https://github.com/pytest-dev/pytest-django - -# Debugging -# ------------------------------------------------------------------------------ -debugpy -# Pycharm might force you to be on the same version IDE as library, use caution. -pydevd-pycharm diff --git a/translator/translator.py b/translator/translator.py index d2c34018..1591bf05 100644 --- a/translator/translator.py +++ b/translator/translator.py @@ -11,6 +11,8 @@ import websockets from gobgp import GoBGP +from config import cfg + logger = logging.getLogger(__name__) KNOWN_MESSAGES = { @@ -21,8 +23,7 @@ } # Here we setup a debugger if this is desired. This obviously should not be run in production. -debug_mode = os.environ.get("DEBUG") -if debug_mode: +if cfg.debugger: def install_deps(): """Install necessary dependencies for debuggers. @@ -41,10 +42,10 @@ def install_deps(): logger.info("Done installing dependencies for debuggers") - logger.info("Translator is set to use a debugger. Provided debug mode: %s", debug_mode) + logger.info("Translator is set to use a debugger. Provided debug mode: %s", cfg.debugger) # We have to setup the debugger appropriately for various IDEs. It'd be nice if they all used the same thing but # sadly, we live in a fallen world. - if debug_mode == "pycharm-pydevd": + if cfg.debugger == "pycharm-pydevd": logger.info("Entering debug mode for pycharm, make sure the debug server is running in PyCharm!") install_deps() @@ -54,7 +55,7 @@ def install_deps(): pydevd_pycharm.settrace("host.docker.internal", port=56782, stdoutToServer=True, stderrToServer=True) logger.info("Debugger started.") - elif debug_mode == "debugpy": + elif cfg.debugger == "debugpy": logger.info("Entering debug mode for debugpy (VSCode)") install_deps() @@ -65,7 +66,7 @@ def install_deps(): logger.info("Debugger listening on port 56781.") else: - logger.warning("Invalid debug mode given: %s. Debugger not started", debug_mode) + logger.warning("Invalid debug mode given: %s. Debugger not started", cfg.debugger) # Must match the URL in asgi.py, and needs a trailing slash hostname = os.environ.get("SCRAM_HOSTNAME", "scram_hostname_not_set")