From 8f199eb40cb9c52a3632aef8292b4ece000b17cf Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Thu, 15 Mar 2018 12:48:39 +0100 Subject: [PATCH] _setup: do not call django.setup() if settings are configured already Without this, using `configurations.setup()` after Django has been setup already re-triggers the logging configuration, which then causes e.g. pytest's caplog to not work anymore. --- .gitignore | 2 +- configurations/__init__.py | 6 ++++-- tests/setup_test.py | 17 +++++++++++++++++ tests/test_main.py | 13 +++++++++++++ tox.ini | 3 ++- 5 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 tests/setup_test.py diff --git a/.gitignore b/.gitignore index cec3188..494e06b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -.coverage.* +.coverage coverage.xml sitecustomize.py docs/_build diff --git a/configurations/__init__.py b/configurations/__init__.py index a4fea8a..069756e 100644 --- a/configurations/__init__.py +++ b/configurations/__init__.py @@ -11,8 +11,10 @@ def _setup(): importer.install() - import django - django.setup() + from django.apps import apps + if not apps.ready: + import django + django.setup() def load_ipython_extension(ipython): diff --git a/tests/setup_test.py b/tests/setup_test.py new file mode 100644 index 0000000..cb156e6 --- /dev/null +++ b/tests/setup_test.py @@ -0,0 +1,17 @@ +"""Used by tests to ensure logging is kept when calling setup() twice.""" + +try: + from unittest import mock +except ImportError: + from mock import mock + +import configurations + +print('setup_1') +configurations.setup() + +with mock.patch('django.setup', side_effect=Exception('setup called twice')): + print('setup_2') + configurations.setup() + +print('setup_done') diff --git a/tests/test_main.py b/tests/test_main.py index 1c9669f..ac3e09b 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -105,3 +105,16 @@ class MainTests(TestCase): proc = subprocess.Popen(['django-cadmin', 'runserver', '--help'], stdout=subprocess.PIPE) self.assertIn('--configuration', proc.communicate()[0].decode('utf-8')) + + def test_django_setup_only_called_once(self): + proc = subprocess.Popen( + [sys.executable, os.path.join(os.path.dirname(__file__), + 'setup_test.py')], + stdout=subprocess.PIPE) + res = proc.communicate() + stdout = res[0].decode('utf-8') + + self.assertIn('setup_1', stdout) + self.assertIn('setup_2', stdout) + self.assertIn('setup_done', stdout) + self.assertEqual(proc.returncode, 0) diff --git a/tox.ini b/tox.ini index 7171957..ae43d6e 100644 --- a/tox.ini +++ b/tox.ini @@ -25,11 +25,12 @@ deps = dj20: django>=2.0a1,<2.1 dj21: django>=2.1a1,<2.2 djmaster: https://github.com/django/django/archive/master.tar.gz#egg=django + py27,pypy: mock commands = python --version coverage run {envbindir}/django-cadmin test -v2 {posargs:tests} - coverage combine + coverage combine . tests/docs coverage report -m --skip-covered [testenv:readme-py27]