diff --git a/.gitignore b/.gitignore index cec3188..283c869 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ -.coverage.* +.coverage coverage.xml -sitecustomize.py docs/_build *.egg-info *.egg 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/sitecustomize.py b/sitecustomize.py new file mode 100644 index 0000000..9b5135d --- /dev/null +++ b/sitecustomize.py @@ -0,0 +1,9 @@ +"""Setup coverage tracking for subprocesses. + +Any ImportError is silently ignored. +Requires COVERAGE_PROCESS_START in the environments, which gets set in +tox.ini. +""" +import coverage + +coverage.process_startup() 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]