pytest-testcontainers-django 0.2.2__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pytest_testcontainers_django-0.2.2 → pytest_testcontainers_django-0.2.3}/CHANGELOG.md +18 -0
- {pytest_testcontainers_django-0.2.2 → pytest_testcontainers_django-0.2.3}/PKG-INFO +1 -1
- {pytest_testcontainers_django-0.2.2 → pytest_testcontainers_django-0.2.3}/pyproject.toml +1 -1
- {pytest_testcontainers_django-0.2.2 → pytest_testcontainers_django-0.2.3}/src/pytest_testcontainers_django/plugin.py +35 -20
- {pytest_testcontainers_django-0.2.2 → pytest_testcontainers_django-0.2.3}/tests/test_plugin.py +35 -0
- {pytest_testcontainers_django-0.2.2 → pytest_testcontainers_django-0.2.3}/.gitignore +0 -0
- {pytest_testcontainers_django-0.2.2 → pytest_testcontainers_django-0.2.3}/LICENSE +0 -0
- {pytest_testcontainers_django-0.2.2 → pytest_testcontainers_django-0.2.3}/README.md +0 -0
- {pytest_testcontainers_django-0.2.2 → pytest_testcontainers_django-0.2.3}/src/pytest_testcontainers_django/__init__.py +0 -0
- {pytest_testcontainers_django-0.2.2 → pytest_testcontainers_django-0.2.3}/src/pytest_testcontainers_django/_types.py +0 -0
- {pytest_testcontainers_django-0.2.2 → pytest_testcontainers_django-0.2.3}/src/pytest_testcontainers_django/config.py +0 -0
- {pytest_testcontainers_django-0.2.2 → pytest_testcontainers_django-0.2.3}/src/pytest_testcontainers_django/containers.py +0 -0
- {pytest_testcontainers_django-0.2.2 → pytest_testcontainers_django-0.2.3}/src/pytest_testcontainers_django/errors.py +0 -0
- {pytest_testcontainers_django-0.2.2 → pytest_testcontainers_django-0.2.3}/src/pytest_testcontainers_django/injection.py +0 -0
- {pytest_testcontainers_django-0.2.2 → pytest_testcontainers_django-0.2.3}/tests/__init__.py +0 -0
- {pytest_testcontainers_django-0.2.2 → pytest_testcontainers_django-0.2.3}/tests/conftest.py +0 -0
- {pytest_testcontainers_django-0.2.2 → pytest_testcontainers_django-0.2.3}/tests/test_config.py +0 -0
- {pytest_testcontainers_django-0.2.2 → pytest_testcontainers_django-0.2.3}/tests/test_injection.py +0 -0
|
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.3] - 2026-06-01
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- The rootdir-conftest preload no longer dumps a spurious traceback
|
|
15
|
+
(`preloading rootdir conftest.py raised; continuing`) when the conftest
|
|
16
|
+
transitively touches the Django app registry before `django.setup()` has
|
|
17
|
+
run — e.g. `model_bakery` >= 1.20 calling `apps.is_installed()` at import.
|
|
18
|
+
0.2.1 added a quiet-deferral shortcut, but it only recognised
|
|
19
|
+
`ImproperlyConfigured` (raised when `DJANGO_SETTINGS_MODULE` is unset).
|
|
20
|
+
When the settings module *is* configured early but the app registry has
|
|
21
|
+
not been populated yet, Django raises the sibling exception
|
|
22
|
+
`AppRegistryNotReady` ("Apps aren't loaded yet.") instead — which is *not*
|
|
23
|
+
a subclass of `ImproperlyConfigured`, so the shortcut missed it and the
|
|
24
|
+
benign deferral was logged as an error. The predicate (renamed
|
|
25
|
+
`_is_django_not_configured` → `_is_django_not_ready`) now matches both
|
|
26
|
+
exceptions by class name.
|
|
27
|
+
|
|
10
28
|
## [0.2.2] - 2026-05-14
|
|
11
29
|
|
|
12
30
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pytest-testcontainers-django
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Bridge between pytest-testcontainers and pytest-django: starts the DB container before Django imports settings.
|
|
5
5
|
Project-URL: Homepage, https://github.com/iplweb/pytest-testcontainers-django
|
|
6
6
|
Project-URL: Repository, https://github.com/iplweb/pytest-testcontainers-django
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pytest-testcontainers-django"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.3"
|
|
8
8
|
description = "Bridge between pytest-testcontainers and pytest-django: starts the DB container before Django imports settings."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -94,18 +94,32 @@ def _resolve_baseline_path(config: DjangoContainerConfig) -> DjangoContainerConf
|
|
|
94
94
|
return replace(config, postgres=new_pg)
|
|
95
95
|
|
|
96
96
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
97
|
+
# Django's two "not ready yet" signals, both of which a rootdir-conftest
|
|
98
|
+
# preload can legitimately trigger before pytest-django has run
|
|
99
|
+
# ``django.setup()``. Matched by class name (not isinstance) so the plugin
|
|
100
|
+
# never imports Django itself — preload runs before Django is configured and
|
|
101
|
+
# the plugin must work where Django is loaded lazily. ``apps.is_installed()``
|
|
102
|
+
# (called at import by ``model_bakery`` >= 1.20) raises ``ImproperlyConfigured``
|
|
103
|
+
# when ``DJANGO_SETTINGS_MODULE`` is unset, but ``AppRegistryNotReady`` when
|
|
104
|
+
# settings *are* configured yet the app registry has not been populated — the
|
|
105
|
+
# latter is a sibling class, NOT a subclass, so it must be listed explicitly.
|
|
106
|
+
_DJANGO_NOT_READY_EXC_NAMES = frozenset({"ImproperlyConfigured", "AppRegistryNotReady"})
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _is_django_not_ready(exc: BaseException) -> bool:
|
|
110
|
+
"""Walk ``__cause__`` / ``__context__`` for a Django "not ready yet" signal.
|
|
111
|
+
|
|
112
|
+
Returns ``True`` if any exception in the chain is one of
|
|
113
|
+
:data:`_DJANGO_NOT_READY_EXC_NAMES` (matched by type name) — meaning the
|
|
114
|
+
preload import failed only because Django settings/apps were not ready,
|
|
115
|
+
which is benign: pytest's normal trylast loader re-imports the conftest
|
|
116
|
+
later, after ``django.setup()``, where it succeeds.
|
|
103
117
|
"""
|
|
104
118
|
seen: set[int] = set()
|
|
105
119
|
cur: BaseException | None = exc
|
|
106
120
|
while cur is not None and id(cur) not in seen:
|
|
107
121
|
seen.add(id(cur))
|
|
108
|
-
if type(cur).__name__
|
|
122
|
+
if type(cur).__name__ in _DJANGO_NOT_READY_EXC_NAMES:
|
|
109
123
|
return True
|
|
110
124
|
cur = cur.__cause__ or cur.__context__
|
|
111
125
|
return False
|
|
@@ -191,22 +205,23 @@ def _preload_rootdir_conftest(early_config: pytest.Config) -> None:
|
|
|
191
205
|
consider_namespace_packages=consider_namespace_packages,
|
|
192
206
|
)
|
|
193
207
|
except Exception as exc:
|
|
194
|
-
if
|
|
208
|
+
if _is_django_not_ready(exc):
|
|
195
209
|
# Expected at preload time: the conftest transitively imports code
|
|
196
|
-
# that touches Django settings (e.g. model_bakery>=1.20 calls
|
|
210
|
+
# that touches Django settings/apps (e.g. model_bakery>=1.20 calls
|
|
197
211
|
# apps.is_installed() at module import). Our hook runs before
|
|
198
|
-
# pytest-django has
|
|
199
|
-
#
|
|
200
|
-
#
|
|
201
|
-
#
|
|
202
|
-
#
|
|
203
|
-
#
|
|
204
|
-
#
|
|
205
|
-
#
|
|
212
|
+
# pytest-django has run django.setup(), so the import fails here
|
|
213
|
+
# with either ImproperlyConfigured (settings module unset) or
|
|
214
|
+
# AppRegistryNotReady (settings configured, app registry not yet
|
|
215
|
+
# populated). Pytest's own trylast loader will re-import the
|
|
216
|
+
# conftest later (after Django is set up *and* after our env
|
|
217
|
+
# injection has populated DB host/port), where it will succeed.
|
|
218
|
+
# Caveat: any register() calls *before* the failing import won't
|
|
219
|
+
# run early — users hitting this should configure via
|
|
220
|
+
# pyproject.toml's [tool.pytest-testcontainers-django] instead,
|
|
221
|
+
# or move the offending import.
|
|
206
222
|
logger.debug(
|
|
207
|
-
"preloading rootdir conftest.py deferred: Django
|
|
208
|
-
"
|
|
209
|
-
"loader)"
|
|
223
|
+
"preloading rootdir conftest.py deferred: Django not ready "
|
|
224
|
+
"yet (will be re-imported by pytest's normal loader)"
|
|
210
225
|
)
|
|
211
226
|
return
|
|
212
227
|
# Real conftest error — pytest's trylast loader would re-raise it
|
{pytest_testcontainers_django-0.2.2 → pytest_testcontainers_django-0.2.3}/tests/test_plugin.py
RENAMED
|
@@ -459,6 +459,41 @@ if not getattr(sys, "_ttd_preload_seen", False):
|
|
|
459
459
|
assert "preloading rootdir conftest.py raised" not in combined, combined
|
|
460
460
|
|
|
461
461
|
|
|
462
|
+
def test_django_not_ready_predicate_matches_both_deferral_exceptions() -> None:
|
|
463
|
+
"""``_is_django_not_ready`` must recognise BOTH Django "not ready yet"
|
|
464
|
+
signals raised at preload time, matched by class name (the plugin must
|
|
465
|
+
not import Django itself):
|
|
466
|
+
|
|
467
|
+
* ``ImproperlyConfigured`` — ``DJANGO_SETTINGS_MODULE`` not set; raised
|
|
468
|
+
when ``apps.is_installed()`` reaches ``settings.INSTALLED_APPS``.
|
|
469
|
+
* ``AppRegistryNotReady`` — settings *are* configured but
|
|
470
|
+
``django.setup()`` / ``apps.populate()`` has not run yet. This is the
|
|
471
|
+
common real-world case (``model_bakery`` >= 1.20 calls
|
|
472
|
+
``apps.is_installed()`` at import once the settings module is pinned
|
|
473
|
+
early) and is NOT a subclass of ``ImproperlyConfigured``, so a check
|
|
474
|
+
for the latter alone misses it.
|
|
475
|
+
|
|
476
|
+
Unrelated exceptions (a plain ``ValueError`` etc.) must NOT match, and
|
|
477
|
+
the predicate must follow the ``__cause__`` / ``__context__`` chain.
|
|
478
|
+
"""
|
|
479
|
+
from pytest_testcontainers_django.plugin import _is_django_not_ready
|
|
480
|
+
|
|
481
|
+
class ImproperlyConfigured(Exception):
|
|
482
|
+
pass
|
|
483
|
+
|
|
484
|
+
class AppRegistryNotReady(Exception):
|
|
485
|
+
pass
|
|
486
|
+
|
|
487
|
+
assert _is_django_not_ready(ImproperlyConfigured("settings not configured"))
|
|
488
|
+
assert _is_django_not_ready(AppRegistryNotReady("Apps aren't loaded yet."))
|
|
489
|
+
assert not _is_django_not_ready(ValueError("unrelated"))
|
|
490
|
+
|
|
491
|
+
# Chained: the deferral signal hides behind an unrelated wrapper.
|
|
492
|
+
chained = RuntimeError("import failed")
|
|
493
|
+
chained.__cause__ = AppRegistryNotReady("Apps aren't loaded yet.")
|
|
494
|
+
assert _is_django_not_ready(chained)
|
|
495
|
+
|
|
496
|
+
|
|
462
497
|
def test_preload_still_logs_traceback_for_unrelated_conftest_errors(
|
|
463
498
|
pytester: pytest.Pytester,
|
|
464
499
|
) -> None:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytest_testcontainers_django-0.2.2 → pytest_testcontainers_django-0.2.3}/tests/test_config.py
RENAMED
|
File without changes
|
{pytest_testcontainers_django-0.2.2 → pytest_testcontainers_django-0.2.3}/tests/test_injection.py
RENAMED
|
File without changes
|