From cdd8af380391f2e2dd843fcc6c05f64d5e0c44c7 Mon Sep 17 00:00:00 2001 From: Maik Hoepfel Date: Thu, 2 May 2013 14:10:51 +0100 Subject: [PATCH] get_classes now allows top-level apps. Fixes #614 --- oscar/core/loading.py | 7 +++++-- tests/__init__.py | 17 +++++++++++++++++ tests/unit/core/loading_tests.py | 11 +++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/oscar/core/loading.py b/oscar/core/loading.py index 5851aef16d9..00eb2ba7d65 100644 --- a/oscar/core/loading.py +++ b/oscar/core/loading.py @@ -44,8 +44,11 @@ class can't be found in the overriding module, then we attempt to import it # App must be local - check if module is in local app (it could be in # oscar's) app_label = module_label.split('.')[0] - base_package = app_module_path.rsplit('.' + app_label, 1)[0] - local_app = "%s.%s" % (base_package, module_label) + if '.' in app_module_path: + base_package = app_module_path.rsplit('.' + app_label, 1)[0] + local_app = "%s.%s" % (base_package, module_label) + else: + local_app = module_label try: imported_local_module = __import__(local_app, fromlist=classnames) except ImportError: diff --git a/tests/__init__.py b/tests/__init__.py index e69de29bb2d..4fc6e6c2e88 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -0,0 +1,17 @@ +import sys + + +class temporary_python_path(object): + """ + Acts as a context manager to temporarily append a list of paths to sys.path + """ + + def __init__(self, paths): + self.paths = paths + + def __enter__(self): + self.original_paths = sys.path[:] + sys.path = self.paths + self.original_paths + + def __exit__(self, exc_type, exc_value, traceback): + sys.path = self.original_paths diff --git a/tests/unit/core/loading_tests.py b/tests/unit/core/loading_tests.py index 5a0f40d5605..d162388ebb7 100644 --- a/tests/unit/core/loading_tests.py +++ b/tests/unit/core/loading_tests.py @@ -1,3 +1,4 @@ +from os.path import dirname from django.test import TestCase from django.core.exceptions import ValidationError from django.conf import settings @@ -9,6 +10,7 @@ get_classes, get_class, ClassNotFoundError from oscar.core.validators import ExtendedURLValidator from oscar.core.validators import URLDoesNotExistValidator +from tests import temporary_python_path class TestImportModule(TestCase): @@ -78,6 +80,15 @@ def test_loading_classes_defined_in_both_local_and_oscar_modules(self): self.assertEqual('tests._site.shipping.methods', Free.__module__) self.assertEqual('oscar.apps.shipping.methods', FixedPrice.__module__) + def test_loading_classes_with_root_app(self): + import tests._site.shipping + path = dirname(dirname(tests._site.shipping.__file__)) + with temporary_python_path([path]): + self.installed_apps[self.installed_apps.index('tests._site.shipping')] = 'shipping' + with override_settings(INSTALLED_APPS=self.installed_apps): + (Free,) = get_classes('shipping.methods', ('Free',)) + self.assertEqual('shipping.methods', Free.__module__) + class TestExtendedURLValidator(TestCase): """