Skip to content

Commit

Permalink
Moved sys.path-extending decorator to django.test.utils and used thro…
Browse files Browse the repository at this point in the history
…ughout test suite.

Thanks Aymeric for the suggestion.
  • Loading branch information
carljm committed Jan 26, 2014
1 parent 8bc3780 commit ca95f8e
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 94 deletions.
12 changes: 12 additions & 0 deletions django/test/utils.py
Expand Up @@ -526,3 +526,15 @@ def tearDown(self):
requires_tz_support = skipUnless(TZ_SUPPORT,
"This test relies on the ability to run a program in an arbitrary "
"time zone, but your operating system isn't able to do that.")



@contextmanager
def extend_sys_path(*paths):
"""Context manager to temporarily add paths to sys.path."""
_orig_sys_path = sys.path[:]
sys.path.extend(paths)
try:
yield
finally:
sys.path = _orig_sys_path
44 changes: 21 additions & 23 deletions tests/app_loading/tests.py
@@ -1,67 +1,65 @@
from __future__ import unicode_literals

import os
import sys

from django.apps import apps
from django.test import TestCase
from django.test.utils import extend_sys_path
from django.utils._os import upath
from django.utils import six


class EggLoadingTest(TestCase):

def setUp(self):
self.old_path = sys.path[:]
self.egg_dir = '%s/eggs' % os.path.dirname(upath(__file__))

def tearDown(self):
apps.clear_cache()
sys.path = self.old_path

def test_egg1(self):
"""Models module can be loaded from an app in an egg"""
egg_name = '%s/modelapp.egg' % self.egg_dir
sys.path.append(egg_name)
with self.settings(INSTALLED_APPS=['app_with_models']):
models_module = apps.get_app_config('app_with_models').models_module
self.assertIsNotNone(models_module)
with extend_sys_path(egg_name):
with self.settings(INSTALLED_APPS=['app_with_models']):
models_module = apps.get_app_config('app_with_models').models_module
self.assertIsNotNone(models_module)
del apps.all_models['app_with_models']

def test_egg2(self):
"""Loading an app from an egg that has no models returns no models (and no error)"""
egg_name = '%s/nomodelapp.egg' % self.egg_dir
sys.path.append(egg_name)
with self.settings(INSTALLED_APPS=['app_no_models']):
models_module = apps.get_app_config('app_no_models').models_module
self.assertIsNone(models_module)
with extend_sys_path(egg_name):
with self.settings(INSTALLED_APPS=['app_no_models']):
models_module = apps.get_app_config('app_no_models').models_module
self.assertIsNone(models_module)
del apps.all_models['app_no_models']

def test_egg3(self):
"""Models module can be loaded from an app located under an egg's top-level package"""
egg_name = '%s/omelet.egg' % self.egg_dir
sys.path.append(egg_name)
with self.settings(INSTALLED_APPS=['omelet.app_with_models']):
models_module = apps.get_app_config('app_with_models').models_module
self.assertIsNotNone(models_module)
with extend_sys_path(egg_name):
with self.settings(INSTALLED_APPS=['omelet.app_with_models']):
models_module = apps.get_app_config('app_with_models').models_module
self.assertIsNotNone(models_module)
del apps.all_models['app_with_models']

def test_egg4(self):
"""Loading an app with no models from under the top-level egg package generates no error"""
egg_name = '%s/omelet.egg' % self.egg_dir
sys.path.append(egg_name)
with self.settings(INSTALLED_APPS=['omelet.app_no_models']):
models_module = apps.get_app_config('app_no_models').models_module
self.assertIsNone(models_module)
with extend_sys_path(egg_name):
with self.settings(INSTALLED_APPS=['omelet.app_no_models']):
models_module = apps.get_app_config('app_no_models').models_module
self.assertIsNone(models_module)
del apps.all_models['app_no_models']

def test_egg5(self):
"""Loading an app from an egg that has an import error in its models module raises that error"""
egg_name = '%s/brokenapp.egg' % self.egg_dir
sys.path.append(egg_name)
with six.assertRaisesRegex(self, ImportError, 'modelz'):
with self.settings(INSTALLED_APPS=['broken_app']):
pass
with extend_sys_path(egg_name):
with six.assertRaisesRegex(self, ImportError, 'modelz'):
with self.settings(INSTALLED_APPS=['broken_app']):
pass


class GetModelsTest(TestCase):
Expand Down
18 changes: 4 additions & 14 deletions tests/apps/tests.py
@@ -1,6 +1,5 @@
from __future__ import absolute_import, unicode_literals

from contextlib import contextmanager
import os
import sys
from unittest import skipUnless
Expand All @@ -10,6 +9,7 @@
from django.core.exceptions import ImproperlyConfigured
from django.db import models
from django.test import TestCase, override_settings
from django.test.utils import extend_sys_path
from django.utils._os import upath
from django.utils import six

Expand Down Expand Up @@ -189,21 +189,11 @@ class NamespacePackageAppTests(TestCase):
other_location = os.path.join(HERE, 'namespace_package_other_base')
app_path = os.path.join(base_location, 'nsapp')

@contextmanager
def add_to_path(self, *paths):
"""Context manager to temporarily add paths to sys.path."""
_orig_sys_path = sys.path[:]
sys.path.extend(paths)
try:
yield
finally:
sys.path = _orig_sys_path

def test_single_path(self):
"""
A Py3.3+ namespace package can be an app if it has only one path.
"""
with self.add_to_path(self.base_location):
with extend_sys_path(self.base_location):
with self.settings(INSTALLED_APPS=['nsapp']):
app_config = apps.get_app_config('nsapp')
self.assertEqual(app_config.path, upath(self.app_path))
Expand All @@ -218,7 +208,7 @@ def test_multiple_paths(self):
"""
# Temporarily add two directories to sys.path that both contain
# components of the "nsapp" package.
with self.add_to_path(self.base_location, self.other_location):
with extend_sys_path(self.base_location, self.other_location):
with self.assertRaises(ImproperlyConfigured):
with self.settings(INSTALLED_APPS=['nsapp']):
pass
Expand All @@ -229,7 +219,7 @@ def test_multiple_paths_explicit_path(self):
"""
# Temporarily add two directories to sys.path that both contain
# components of the "nsapp" package.
with self.add_to_path(self.base_location, self.other_location):
with extend_sys_path(self.base_location, self.other_location):
with self.settings(INSTALLED_APPS=['nsapp.apps.NSAppConfig']):
app_config = apps.get_app_config('nsapp')
self.assertEqual(app_config.path, upath(self.app_path))
23 changes: 8 additions & 15 deletions tests/proxy_model_inheritance/tests.py
@@ -1,11 +1,10 @@
from __future__ import absolute_import, unicode_literals

import os
import sys

from django.core.management import call_command
from django.test import TestCase, TransactionTestCase
from django.test.utils import override_system_checks
from django.test.utils import override_system_checks, extend_sys_path
from django.utils._os import upath

from .models import (ConcreteModel, ConcreteModelSubclass,
Expand All @@ -20,23 +19,17 @@ class ProxyModelInheritanceTests(TransactionTestCase):
"""
available_apps = []

def setUp(self):
self.old_sys_path = sys.path[:]
sys.path.append(os.path.dirname(os.path.abspath(upath(__file__))))

def tearDown(self):
sys.path = self.old_sys_path

# `auth` app is imported, but not installed in this test, so we need to
# exclude checks registered by this app.
@override_system_checks([])
def test_table_exists(self):
with self.modify_settings(INSTALLED_APPS={'append': ['app1', 'app2']}):
call_command('migrate', verbosity=0)
from app1.models import ProxyModel
from app2.models import NiceModel
self.assertEqual(NiceModel.objects.all().count(), 0)
self.assertEqual(ProxyModel.objects.all().count(), 0)
with extend_sys_path(os.path.dirname(os.path.abspath(upath(__file__)))):
with self.modify_settings(INSTALLED_APPS={'append': ['app1', 'app2']}):
call_command('migrate', verbosity=0)
from app1.models import ProxyModel
from app2.models import NiceModel
self.assertEqual(NiceModel.objects.all().count(), 0)
self.assertEqual(ProxyModel.objects.all().count(), 0)


class MultiTableInheritanceProxyTest(TestCase):
Expand Down
31 changes: 15 additions & 16 deletions tests/template_tests/tests.py
Expand Up @@ -22,7 +22,8 @@
from django.template.loaders import app_directories, filesystem, cached
from django.test import RequestFactory, TestCase
from django.test.utils import (setup_test_template_loader,
restore_template_loaders, override_settings, TransRealMixin)
restore_template_loaders, override_settings, TransRealMixin,
extend_sys_path)
from django.utils.encoding import python_2_unicode_compatible
from django.utils.formats import date_format
from django.utils._os import upath
Expand Down Expand Up @@ -1857,13 +1858,11 @@ def get_template_tests(self):
class TemplateTagLoading(TestCase):

def setUp(self):
self.old_path = sys.path[:]
self.egg_dir = '%s/eggs' % os.path.dirname(upath(__file__))
self.old_tag_modules = template_base.templatetags_modules
template_base.templatetags_modules = []

def tearDown(self):
sys.path = self.old_path
template_base.templatetags_modules = self.old_tag_modules

def test_load_error(self):
Expand All @@ -1878,23 +1877,23 @@ def test_load_error(self):
def test_load_error_egg(self):
ttext = "{% load broken_egg %}"
egg_name = '%s/tagsegg.egg' % self.egg_dir
sys.path.append(egg_name)
with self.assertRaises(template.TemplateSyntaxError):
with self.settings(INSTALLED_APPS=['tagsegg']):
template.Template(ttext)
try:
with self.settings(INSTALLED_APPS=['tagsegg']):
template.Template(ttext)
except template.TemplateSyntaxError as e:
self.assertTrue('ImportError' in e.args[0])
self.assertTrue('Xtemplate' in e.args[0])
with extend_sys_path(egg_name):
with self.assertRaises(template.TemplateSyntaxError):
with self.settings(INSTALLED_APPS=['tagsegg']):
template.Template(ttext)
try:
with self.settings(INSTALLED_APPS=['tagsegg']):
template.Template(ttext)
except template.TemplateSyntaxError as e:
self.assertTrue('ImportError' in e.args[0])
self.assertTrue('Xtemplate' in e.args[0])

def test_load_working_egg(self):
ttext = "{% load working_egg %}"
egg_name = '%s/tagsegg.egg' % self.egg_dir
sys.path.append(egg_name)
with self.settings(INSTALLED_APPS=['tagsegg']):
template.Template(ttext)
with extend_sys_path(egg_name):
with self.settings(INSTALLED_APPS=['tagsegg']):
template.Template(ttext)


class RequestContextTests(unittest.TestCase):
Expand Down
51 changes: 25 additions & 26 deletions tests/utils_tests/test_module_loading.py
Expand Up @@ -7,6 +7,7 @@

from django.core.exceptions import ImproperlyConfigured
from django.test import SimpleTestCase, modify_settings
from django.test.utils import extend_sys_path
from django.utils import six
from django.utils.module_loading import autodiscover_modules, import_by_path, module_has_submodule
from django.utils._os import upath
Expand Down Expand Up @@ -54,11 +55,9 @@ def test_loader(self):

class EggLoader(unittest.TestCase):
def setUp(self):
self.old_path = sys.path[:]
self.egg_dir = '%s/eggs' % os.path.dirname(upath(__file__))

def tearDown(self):
sys.path = self.old_path
sys.path_importer_cache.clear()

sys.modules.pop('egg_module.sub1.sub2.bad_module', None)
Expand All @@ -72,40 +71,40 @@ def tearDown(self):
def test_shallow_loader(self):
"Module existence can be tested inside eggs"
egg_name = '%s/test_egg.egg' % self.egg_dir
sys.path.append(egg_name)
egg_module = import_module('egg_module')
with extend_sys_path(egg_name):
egg_module = import_module('egg_module')

# An importable child
self.assertTrue(module_has_submodule(egg_module, 'good_module'))
mod = import_module('egg_module.good_module')
self.assertEqual(mod.content, 'Good Module')
# An importable child
self.assertTrue(module_has_submodule(egg_module, 'good_module'))
mod = import_module('egg_module.good_module')
self.assertEqual(mod.content, 'Good Module')

# A child that exists, but will generate an import error if loaded
self.assertTrue(module_has_submodule(egg_module, 'bad_module'))
self.assertRaises(ImportError, import_module, 'egg_module.bad_module')
# A child that exists, but will generate an import error if loaded
self.assertTrue(module_has_submodule(egg_module, 'bad_module'))
self.assertRaises(ImportError, import_module, 'egg_module.bad_module')

# A child that doesn't exist
self.assertFalse(module_has_submodule(egg_module, 'no_such_module'))
self.assertRaises(ImportError, import_module, 'egg_module.no_such_module')
# A child that doesn't exist
self.assertFalse(module_has_submodule(egg_module, 'no_such_module'))
self.assertRaises(ImportError, import_module, 'egg_module.no_such_module')

def test_deep_loader(self):
"Modules deep inside an egg can still be tested for existence"
egg_name = '%s/test_egg.egg' % self.egg_dir
sys.path.append(egg_name)
egg_module = import_module('egg_module.sub1.sub2')
with extend_sys_path(egg_name):
egg_module = import_module('egg_module.sub1.sub2')

# An importable child
self.assertTrue(module_has_submodule(egg_module, 'good_module'))
mod = import_module('egg_module.sub1.sub2.good_module')
self.assertEqual(mod.content, 'Deep Good Module')
# An importable child
self.assertTrue(module_has_submodule(egg_module, 'good_module'))
mod = import_module('egg_module.sub1.sub2.good_module')
self.assertEqual(mod.content, 'Deep Good Module')

# A child that exists, but will generate an import error if loaded
self.assertTrue(module_has_submodule(egg_module, 'bad_module'))
self.assertRaises(ImportError, import_module, 'egg_module.sub1.sub2.bad_module')
# A child that exists, but will generate an import error if loaded
self.assertTrue(module_has_submodule(egg_module, 'bad_module'))
self.assertRaises(ImportError, import_module, 'egg_module.sub1.sub2.bad_module')

# A child that doesn't exist
self.assertFalse(module_has_submodule(egg_module, 'no_such_module'))
self.assertRaises(ImportError, import_module, 'egg_module.sub1.sub2.no_such_module')
# A child that doesn't exist
self.assertFalse(module_has_submodule(egg_module, 'no_such_module'))
self.assertRaises(ImportError, import_module, 'egg_module.sub1.sub2.no_such_module')


class ModuleImportTestCase(unittest.TestCase):
Expand Down

0 comments on commit ca95f8e

Please sign in to comment.