diff --git a/AUTHORS b/AUTHORS index 2272df0f..224b0120 100644 --- a/AUTHORS +++ b/AUTHORS @@ -13,4 +13,5 @@ Rafal Stozek Donald Stufft Nicolas Delaby Daniel Hahler +Michael Howitz Hasan Ramezani diff --git a/docs/changelog.rst b/docs/changelog.rst index 5b04c3ba..35e1e09a 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,16 @@ Changelog ========= +unreleased +---------- + +Bugfixes +^^^^^^^^ + +* Fix fixture ``.live_server_helper.LiveServer`` when using an in-memory SQLite + database on Django >= 3. + + v4.4.0 (2021-06-06) ------------------- diff --git a/pytest_django/django_compat.py b/pytest_django/django_compat.py index 615e4701..3a02f42f 100644 --- a/pytest_django/django_compat.py +++ b/pytest_django/django_compat.py @@ -1,6 +1,11 @@ # Note that all functions here assume django is available. So ensure # this is the case before you call them. +import pkg_resources + + +IS_DJANGO_2 = pkg_resources.get_distribution("Django").version < '3' + def is_django_unittest(request_or_item) -> bool: """Returns True if the request_or_item is a Django test case, otherwise False""" diff --git a/pytest_django/live_server_helper.py b/pytest_django/live_server_helper.py index 943198d7..7d2920a6 100644 --- a/pytest_django/live_server_helper.py +++ b/pytest_django/live_server_helper.py @@ -1,5 +1,7 @@ from typing import Any, Dict +from .django_compat import IS_DJANGO_2 + class LiveServer: """The liveserver fixture @@ -24,7 +26,10 @@ def __init__(self, addr: str) -> None: and conn.settings_dict["NAME"] == ":memory:" ): # Explicitly enable thread-shareability for this connection - conn.allow_thread_sharing = True + if IS_DJANGO_2: + conn.allow_thread_sharing = True + else: + conn.inc_thread_sharing() connections_override[conn.alias] = conn liveserver_kwargs["connections_override"] = connections_override @@ -60,6 +65,37 @@ def __init__(self, addr: str) -> None: def stop(self) -> None: """Stop the server""" + from django.db import connections + + liveserver_kwargs = {} # type: Dict[str, Any] + + connections_override = {} + for conn in connections.all(): + # If using in-memory sqlite databases, pass the connections to + # the server thread. + if ( + conn.settings_dict["ENGINE"] == "django.db.backends.sqlite3" + and conn.settings_dict["NAME"] == ":memory:" + ): + # Explicitly enable thread-shareability for this connection + if IS_DJANGO_2: + conn.allow_thread_sharing = False + else: + conn.dec_thread_sharing() + connections_override[conn.alias] = conn + + liveserver_kwargs["connections_override"] = connections_override + from django.conf import settings + + if "django.contrib.staticfiles" in settings.INSTALLED_APPS: + from django.contrib.staticfiles.handlers import StaticFilesHandler + + liveserver_kwargs["static_handler"] = StaticFilesHandler + else: + from django.test.testcases import _StaticFilesHandler + + liveserver_kwargs["static_handler"] = _StaticFilesHandler + self.thread.terminate() self.thread.join() diff --git a/setup.cfg b/setup.cfg index bc670a46..9ff49da6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -95,3 +95,5 @@ ignore_missing_imports = True ignore_missing_imports = True [mypy-psycopg2cffi.*] ignore_missing_imports = True +[mypy-pkg_resources.*] +ignore_missing_imports = True