Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Bugfixes
^^^^^^^^

* Fixed type hints of assert methods to match actual signature (`PR #1271 <https://github.com/pytest-dev/pytest-django/pull/1271>`__)
* Fixed ``--help``/``--version`` failing with ``AppRegistryNotReady`` (surfaced as a ``could not load initial conftests`` warning) when a ``conftest.py`` imports Django models at the top level. Django is now set up before the initial conftests are loaded for these options (`#1152 <https://github.com/pytest-dev/pytest-django/issues/1152>`__).
* Handled Django 6.2's ``ImproperlyConfigured`` (in addition to ``ImportError``) when the configured ``DJANGO_SETTINGS_MODULE`` cannot be imported, so pytest-django still shows its guidance message.

v4.12.0 (2026-02-14)
Expand Down
32 changes: 22 additions & 10 deletions pytest_django/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,8 +312,11 @@ def pytest_load_initial_conftests(

options = parser.parse_known_args(args)

if options.version or options.help:
return
# With `--help`/`--version`, pytest still imports the initial conftests (it
# just doesn't run tests), so Django is set up for them below as well —
# otherwise a conftest with top-level model imports fails with
# AppRegistryNotReady (issue #1152).
is_help_or_version = bool(options.version or options.help)

django_find_project = _get_boolean_value(
early_config.getini("django_find_project"), "django_find_project"
Expand Down Expand Up @@ -363,16 +366,25 @@ def _get_option_with_source(

configurations.importer.install()

# Forcefully load Django settings, throws ImportError or
# ImproperlyConfigured if settings cannot be loaded.
from django.conf import settings as dj_settings

with _handle_import_error(_django_project_scan_outcome):
dj_settings.DATABASES # noqa: B018

early_config.stash[blocking_manager_key] = DjangoDbBlocker(_ispytest=True)

_setup_django(early_config)
try:
if ds:
# Forcefully load Django settings, throws ImportError or
# ImproperlyConfigured if settings cannot be loaded.
from django.conf import settings as dj_settings

with _handle_import_error(_django_project_scan_outcome):
dj_settings.DATABASES # noqa: B018

# Populates the app registry, which fails on a broken INSTALLED_APPS.
_setup_django(early_config)
except Exception:
Comment thread
alimony marked this conversation as resolved.
# `--help`/`--version` only print information and never run tests, so a
# broken Django configuration is tolerated here (issue #235); anything
# genuinely wrong still surfaces on a real test run.
if not is_help_or_version:
raise


@pytest.hookimpl(trylast=True)
Expand Down
39 changes: 39 additions & 0 deletions tests/test_initialization.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from textwrap import dedent

import pytest

from .helpers import DjangoPytester


Expand Down Expand Up @@ -60,3 +62,40 @@ def test_ds():
]
)
assert result.ret == 0


@pytest.mark.parametrize("option", ["--help", "--version"])
def test_django_setup_with_help_and_version(
django_pytester: DjangoPytester,
option: str,
) -> None:
"""Django must be set up before conftest files are imported, even for
``--help``/``--version``, so a top-level Django model import in a
``conftest.py`` does not fail with ``AppRegistryNotReady``.

Regression test for https://github.com/pytest-dev/pytest-django/issues/1152
"""
django_pytester.makeconftest(
"""
import sys

from tpkg.app.models import Item # noqa: F401

# Only reached if the model import above succeeds (i.e. Django is set
# up). With --version, pytest records but never prints the conftest
# load failure, so we assert on this positive marker instead.
print("conftest-imported-models", file=sys.stderr)
"""
)

# A single `--version`/`-V` is short-circuited before pytest loads any
# conftests (pytest #13574), so it wouldn't exercise this path; passing
# it twice forces full startup, which imports the initial conftests.
args = [option, option] if option == "--version" else [option]
result = django_pytester.runpytest_subprocess(*args)

output = result.stdout.str() + result.stderr.str()
assert result.ret == 0
assert "conftest-imported-models" in output
assert "AppRegistryNotReady" not in output
assert "could not load initial conftests" not in output