Skip to content

Commit

Permalink
make settings file loading testable
Browse files Browse the repository at this point in the history
  • Loading branch information
mathiasertl committed Oct 1, 2023
1 parent d7ec18f commit c8a7fbb
Show file tree
Hide file tree
Showing 10 changed files with 72 additions and 21 deletions.
43 changes: 24 additions & 19 deletions ca/ca/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = Path(__file__).resolve().parent.parent # ca/
SETTINGS_YAML = BASE_DIR / "ca" / "settings.yaml"

DEBUG = False

Expand Down Expand Up @@ -209,30 +208,36 @@


# CONFIGURATION_DIRECTORY is set by the SystemD ConfigurationDirectory= directive.
_settings_files: List[Tuple[str, "os.PathLike[str]"]] = []
SETTINGS_DIRS = os.environ.get("DJANGO_CA_SETTINGS", os.environ.get("CONFIGURATION_DIRECTORY", ""))

for _path in [BASE_DIR / p for p in SETTINGS_DIRS.split(":")]:
if not _path.exists():
raise ImproperlyConfigured(f"{_path}: No such file or directory.")

if _path.is_dir():
# exclude files that don't end with '.yaml' and any directories
_settings_files += [
(_f, _path)
for _f in os.listdir(_path)
if _f.endswith(".yaml") and not os.path.isdir(os.path.join(_path, _f))
]
else:
_settings_files.append((_path.name, _path.parent))

_settings_files = sorted(_settings_files)
if SETTINGS_YAML.exists():
_settings_files.append((SETTINGS_YAML.name, SETTINGS_YAML.parent))
def _get_settings_files(base_dir: Path, dirs: str) -> List[Tuple[str, Path]]:
settings_files: List[Tuple[str, Path]] = []

for path in [base_dir / p for p in dirs.split(":")]:
if not path.exists():
raise ImproperlyConfigured(f"{path}: No such file or directory.")

if path.is_dir():
# exclude files that don't end with '.yaml' and any directories
settings_files += sorted(
[(_f.name, path) for _f in path.iterdir() if _f.suffix == ".yaml" and not _f.is_dir()]
)
else:
settings_files.append((path.name, path.parent))

settings_yaml = base_dir / "ca" / "settings.yaml"
if settings_yaml.exists():
settings_files.append((settings_yaml.name, settings_yaml.parent))

return settings_files


if not _skip_local_config and yaml is not False: # type: ignore[comparison-overlap]
_settings_files = _get_settings_files(BASE_DIR, SETTINGS_DIRS)

for _filename, _filename_path in _settings_files:
_full_path = os.path.join(_path, _filename)
_full_path = _filename_path / _filename
with open(_full_path, encoding="utf-8") as stream:
data = yaml.safe_load(stream)
if data is None:
Expand Down
3 changes: 2 additions & 1 deletion ca/django_ca/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ def pytest_configure(config: "PytestConfig") -> None:
# Add a header to log important software versions
print("Testing with:")
print("* Python: ", sys.version.replace("\n", ""))
installed_versions = {p.name: p.version for p in importlib.metadata.distributions()}
# pragma: only py<3.10 # p.name is available as a shortcut to p.metadata["Name"] in Python 3.10
installed_versions = {p.metadata["Name"]: p.version for p in importlib.metadata.distributions()}
for pkg in sorted(["Django", "acme", "cryptography", "celery", "idna", "josepy"]):
print(f"* {pkg}: {installed_versions[pkg]}")
print(f"* Selenium tests: {not skip_selenium}")
Expand Down
1 change: 1 addition & 0 deletions ca/django_ca/tests/fixtures/settings/base/ca/settings.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SETTINGS_YAML: True
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SETTINGS_DIR_ONE: True
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SETTINGS_DIR_TWO: True
1 change: 1 addition & 0 deletions ca/django_ca/tests/fixtures/settings/dirs/single-file.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SINGLE_FILE: True
41 changes: 41 additions & 0 deletions ca/django_ca/tests/test_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,61 @@
# You should have received a copy of the GNU General Public License along with django-ca. If not, see
# <http://www.gnu.org/licenses/>.

# pylint: disable=redefined-outer-name # does not work with fixtures

"""Test cases for the ``ca_settings`` module."""

import typing
from datetime import timedelta
from importlib import import_module
from pathlib import Path
from typing import List, Tuple
from unittest import mock

from cryptography import x509
from cryptography.hazmat.primitives import hashes
from cryptography.x509.oid import NameOID

from django.conf import settings
from django.test import TestCase

import pytest

from django_ca import ca_settings
from django_ca.tests.base.mixins import TestCaseMixin

GET_SETTINGS_FILES = typing.Callable[[Path, str], List[Tuple[str, Path]]] # pylint: disable=invalid-name


@pytest.fixture(scope="module")
def get_settings_files() -> GET_SETTINGS_FILES:
"""Fixture to import to the _get_settings_files() function."""
mod = import_module("ca.settings")
return typing.cast(GET_SETTINGS_FILES, getattr(mod, "_get_settings_files"))


def test_no_settings_files(tmp_path: Path, get_settings_files: GET_SETTINGS_FILES) -> None:
"""Test no settings.yaml exists and no DJANGO_CA_SETTINGS env variable set."""
assert get_settings_files(tmp_path, "") == []


def test_with_settings_files(get_settings_files: GET_SETTINGS_FILES) -> None:
"""Test a full list of settings files."""
base_dir = settings.FIXTURES_DIR / "settings" / "base"
single_file = settings.FIXTURES_DIR / "settings" / "dirs" / "single-file.yaml"
settings_dir = settings.FIXTURES_DIR / "settings" / "dirs" / "settings_dir"
settings_files = get_settings_files(base_dir, f"{single_file}:{settings_dir}")
assert settings_files == [
("single-file.yaml", single_file.parent),
("01-settings.yaml", settings_dir),
("02-settings.yaml", settings_dir),
("settings.yaml", base_dir / "ca"),
]

# Assert that all files actually exist
for name, path in settings_files:
assert (path / name).exists() is True


class SettingsTestCase(TestCase):
"""Test some standard settings."""
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ min-similarity-lines = 16
[tool.pytest.ini_options]
DJANGO_SETTINGS_MODULE = "ca.test_settings"
addopts = [
"--cov=ca/django_ca/",
"--cov",
"--cov-report=html:docs/build/coverage/",
"--cov-fail-under=100",
"--random-order",
Expand Down

0 comments on commit c8a7fbb

Please sign in to comment.