Skip to content

🐛 Settings are loaded eagerly instead of lazily #546

@sergei-maertens

Description

@sergei-maertens

Bug Description

The settings of django-health-check (from health_check.conf) are loaded at import time rather than dynamically accessing them when they're needed trough a callable or other defer mechanism.

This is mostly annoying for testing in projects/downstream libraries. Our package provides opt-in support and allows configuring the necessary settings in the test module with a construct like:

@pytest.fixture(autouse=True)
def _add_installed_apps(settings):
    settings.INSTALLED_APPS = [
        *settings.INSTALLED_APPS,
        *default_health_check_apps,
    ]
    settings.HEALTH_CHECK = {
        "SUBSETS": default_health_check_subsets,
    }

The updated HEALTH_CHECK setting is not picked up here because the view was already imported before this code runs, which had trigger the import of the conf module which evaluated the django settings at import time.

A common pattern we apply is:

from typing import Literal

from django.conf import settings

HEALTH_CHECK = {}

type SettingName = Literal["HEALTH_CHECK"]


def get_setting(name: SettingName):
    default = globals()[name]
    return getattr(settings, name, default)

would you be open to a patch in this direction?

Expected Behavior

django-health-check plays nice with the pytest-django settings fixture and the @override_settings decorator from django.test.

Version

3.20.8

Stack trace

When applying the pattern described above in a test, this results in a 404 because the subset "does not exist":

    def test_readyz_subset_endpoint(client: Client):
        response = client.get("/_healthz/readyz/")
    
        # there are pending migrations because of the added health check installed apps,
        # which results in HTTP 500 response (as intended).
>       assert response.status_code in (200, 500)
E       assert 404 in (200, 500)
E        +  where 404 = <HttpResponseNotFound status_code=404, "text/html; charset=utf-8">.status_code

tests/health_checks/test_endpoints.py:53: AssertionError

Steps to Reproduce

No response

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions