Fixed #17061 -- Factored out importing object from a dotted path

Thanks Carl Meyer for the report.
This commit is contained in:
Claude Paroz 2013-02-02 22:58:02 +01:00
parent 3f1c7b7053
commit 7c5b244826
26 changed files with 116 additions and 255 deletions

View File

@ -15,6 +15,7 @@ from django.conf import global_settings
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.utils.functional import LazyObject, empty from django.utils.functional import LazyObject, empty
from django.utils import importlib from django.utils import importlib
from django.utils.module_loading import import_by_path
from django.utils import six from django.utils import six
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE" ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
@ -68,9 +69,7 @@ class LazySettings(LazyObject):
if self.LOGGING_CONFIG: if self.LOGGING_CONFIG:
from django.utils.log import DEFAULT_LOGGING from django.utils.log import DEFAULT_LOGGING
# First find the logging configuration function ... # First find the logging configuration function ...
logging_config_path, logging_config_func_name = self.LOGGING_CONFIG.rsplit('.', 1) logging_config_func = import_by_path(self.LOGGING_CONFIG)
logging_config_module = importlib.import_module(logging_config_path)
logging_config_func = getattr(logging_config_module, logging_config_func_name)
logging_config_func(DEFAULT_LOGGING) logging_config_func(DEFAULT_LOGGING)

View File

@ -1,5 +1,5 @@
from django.test import LiveServerTestCase from django.test import LiveServerTestCase
from django.utils.importlib import import_module from django.utils.module_loading import import_by_path
from django.utils.unittest import SkipTest from django.utils.unittest import SkipTest
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
@ -9,11 +9,7 @@ class AdminSeleniumWebDriverTestCase(LiveServerTestCase):
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
try: try:
# Import and start the WebDriver class. cls.selenium = import_by_path(cls.webdriver_class)()
module, attr = cls.webdriver_class.rsplit('.', 1)
mod = import_module(module)
WebDriver = getattr(mod, attr)
cls.selenium = WebDriver()
except Exception as e: except Exception as e:
raise SkipTest('Selenium webdriver "%s" not installed or not ' raise SkipTest('Selenium webdriver "%s" not installed or not '
'operational: %s' % (cls.webdriver_class, str(e))) 'operational: %s' % (cls.webdriver_class, str(e)))

View File

@ -1,8 +1,8 @@
import re import re
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
from django.utils.importlib import import_module
from django.contrib.auth.signals import user_logged_in, user_logged_out, user_login_failed from django.contrib.auth.signals import user_logged_in, user_logged_out, user_login_failed
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
from django.utils.module_loading import import_by_path
SESSION_KEY = '_auth_user_id' SESSION_KEY = '_auth_user_id'
BACKEND_SESSION_KEY = '_auth_user_backend' BACKEND_SESSION_KEY = '_auth_user_backend'
@ -10,19 +10,7 @@ REDIRECT_FIELD_NAME = 'next'
def load_backend(path): def load_backend(path):
i = path.rfind('.') return import_by_path(path)()
module, attr = path[:i], path[i + 1:]
try:
mod = import_module(module)
except ImportError as e:
raise ImproperlyConfigured('Error importing authentication backend %s: "%s"' % (path, e))
except ValueError:
raise ImproperlyConfigured('Error importing authentication backends. Is AUTHENTICATION_BACKENDS a correctly defined list or tuple?')
try:
cls = getattr(mod, attr)
except AttributeError:
raise ImproperlyConfigured('Module "%s" does not define a "%s" authentication backend' % (module, attr))
return cls()
def get_backends(): def get_backends():

View File

@ -12,6 +12,7 @@ from django.utils.encoding import force_bytes, force_str
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.utils.crypto import ( from django.utils.crypto import (
pbkdf2, constant_time_compare, get_random_string) pbkdf2, constant_time_compare, get_random_string)
from django.utils.module_loading import import_by_path
from django.utils.translation import ugettext_noop as _ from django.utils.translation import ugettext_noop as _
@ -84,13 +85,7 @@ def load_hashers(password_hashers=None):
if not password_hashers: if not password_hashers:
password_hashers = settings.PASSWORD_HASHERS password_hashers = settings.PASSWORD_HASHERS
for backend in password_hashers: for backend in password_hashers:
try: hasher = import_by_path(backend)()
mod_path, cls_name = backend.rsplit('.', 1)
mod = importlib.import_module(mod_path)
hasher_cls = getattr(mod, cls_name)
except (AttributeError, ImportError, ValueError):
raise ImproperlyConfigured("hasher not found: %s" % backend)
hasher = hasher_cls()
if not getattr(hasher, 'algorithm'): if not getattr(hasher, 'algorithm'):
raise ImproperlyConfigured("hasher doesn't specify an " raise ImproperlyConfigured("hasher doesn't specify an "
"algorithm name: %s" % backend) "algorithm name: %s" % backend)

View File

@ -1,8 +1,6 @@
from django.test import TestCase from django.test import TestCase
from django.contrib.formtools.wizard.storage import (get_storage, from django.contrib.formtools.wizard.storage import get_storage, MissingStorage
MissingStorageModule,
MissingStorageClass)
from django.contrib.formtools.wizard.storage.base import BaseStorage from django.contrib.formtools.wizard.storage.base import BaseStorage
@ -12,11 +10,9 @@ class TestLoadStorage(TestCase):
type(get_storage('django.contrib.formtools.wizard.storage.base.BaseStorage', 'wizard1')), type(get_storage('django.contrib.formtools.wizard.storage.base.BaseStorage', 'wizard1')),
BaseStorage) BaseStorage)
def test_missing_module(self): def test_missing_storage(self):
self.assertRaises(MissingStorageModule, get_storage, self.assertRaises(MissingStorage, get_storage,
'django.contrib.formtools.wizard.storage.idontexist.IDontExistStorage', 'wizard1') 'django.contrib.formtools.wizard.storage.idontexist.IDontExistStorage', 'wizard1')
self.assertRaises(MissingStorage, get_storage,
def test_missing_class(self):
self.assertRaises(MissingStorageClass, get_storage,
'django.contrib.formtools.wizard.storage.base.IDontExistStorage', 'wizard1') 'django.contrib.formtools.wizard.storage.base.IDontExistStorage', 'wizard1')

View File

@ -1,22 +1,14 @@
from django.utils.importlib import import_module from django.core.exceptions import ImproperlyConfigured
from django.utils.module_loading import import_by_path
from django.contrib.formtools.wizard.storage.base import BaseStorage from django.contrib.formtools.wizard.storage.base import BaseStorage
from django.contrib.formtools.wizard.storage.exceptions import ( from django.contrib.formtools.wizard.storage.exceptions import (
MissingStorageModule, MissingStorageClass, NoFileStorageConfigured) MissingStorage, NoFileStorageConfigured)
def get_storage(path, *args, **kwargs): def get_storage(path, *args, **kwargs):
i = path.rfind('.')
module, attr = path[:i], path[i+1:]
try: try:
mod = import_module(module) storage_class = import_by_path(path)
except ImportError as e: except ImproperlyConfigured as e:
raise MissingStorageModule( raise MissingStorage('Error loading storage: %s' % e)
'Error loading storage %s: "%s"' % (module, e))
try:
storage_class = getattr(mod, attr)
except AttributeError:
raise MissingStorageClass(
'Module "%s" does not define a storage named "%s"' % (module, attr))
return storage_class(*args, **kwargs) return storage_class(*args, **kwargs)

View File

@ -1,9 +1,6 @@
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
class MissingStorageModule(ImproperlyConfigured): class MissingStorage(ImproperlyConfigured):
pass
class MissingStorageClass(ImproperlyConfigured):
pass pass
class NoFileStorageConfigured(ImproperlyConfigured): class NoFileStorageConfigured(ImproperlyConfigured):

View File

@ -1,28 +1,5 @@
from django.conf import settings from django.conf import settings
from django.core.exceptions import ImproperlyConfigured from django.utils.module_loading import import_by_path as get_storage
from django.utils.importlib import import_module
def get_storage(import_path):
"""
Imports the message storage class described by import_path, where
import_path is the full Python path to the class.
"""
try:
dot = import_path.rindex('.')
except ValueError:
raise ImproperlyConfigured("%s isn't a Python path." % import_path)
module, classname = import_path[:dot], import_path[dot + 1:]
try:
mod = import_module(module)
except ImportError as e:
raise ImproperlyConfigured('Error importing module %s: "%s"' %
(module, e))
try:
return getattr(mod, classname)
except AttributeError:
raise ImproperlyConfigured('Module "%s" does not define a "%s" '
'class.' % (module, classname))
# Callable with the same interface as the storage classes i.e. accepts a # Callable with the same interface as the storage classes i.e. accepts a

View File

@ -4,7 +4,7 @@ from django.core.exceptions import ImproperlyConfigured
from django.core.files.storage import default_storage, Storage, FileSystemStorage from django.core.files.storage import default_storage, Storage, FileSystemStorage
from django.utils.datastructures import SortedDict from django.utils.datastructures import SortedDict
from django.utils.functional import empty, memoize, LazyObject from django.utils.functional import empty, memoize, LazyObject
from django.utils.importlib import import_module from django.utils.module_loading import import_by_path
from django.utils._os import safe_join from django.utils._os import safe_join
from django.utils import six from django.utils import six
@ -258,17 +258,7 @@ def _get_finder(import_path):
Imports the staticfiles finder class described by import_path, where Imports the staticfiles finder class described by import_path, where
import_path is the full Python path to the class. import_path is the full Python path to the class.
""" """
module, attr = import_path.rsplit('.', 1) Finder = import_by_path(import_path)
try:
mod = import_module(module)
except ImportError as e:
raise ImproperlyConfigured('Error importing module %s: "%s"' %
(module, e))
try:
Finder = getattr(mod, attr)
except AttributeError:
raise ImproperlyConfigured('Module "%s" does not define a "%s" '
'class.' % (module, attr))
if not issubclass(Finder, BaseFinder): if not issubclass(Finder, BaseFinder):
raise ImproperlyConfigured('Finder "%s" is not a subclass of "%s"' % raise ImproperlyConfigured('Finder "%s" is not a subclass of "%s"' %
(Finder, BaseFinder)) (Finder, BaseFinder))

View File

@ -25,6 +25,8 @@ from django.core.cache.backends.base import (
InvalidCacheBackendError, CacheKeyWarning, BaseCache) InvalidCacheBackendError, CacheKeyWarning, BaseCache)
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.utils import importlib from django.utils import importlib
from django.utils.module_loading import import_by_path
__all__ = [ __all__ = [
'get_cache', 'cache', 'DEFAULT_CACHE_ALIAS' 'get_cache', 'cache', 'DEFAULT_CACHE_ALIAS'
@ -86,11 +88,10 @@ def parse_backend_conf(backend, **kwargs):
else: else:
try: try:
# Trying to import the given backend, in case it's a dotted path # Trying to import the given backend, in case it's a dotted path
mod_path, cls_name = backend.rsplit('.', 1) backend_cls = import_by_path(backend)
mod = importlib.import_module(mod_path) except ImproperlyConfigured as e:
backend_cls = getattr(mod, cls_name) raise InvalidCacheBackendError("Could not find backend '%s': %s" % (
except (AttributeError, ImportError, ValueError): backend, e))
raise InvalidCacheBackendError("Could not find backend '%s'" % backend)
location = kwargs.pop('LOCATION', '') location = kwargs.pop('LOCATION', '')
return backend, location, kwargs return backend, location, kwargs
@ -126,10 +127,8 @@ def get_cache(backend, **kwargs):
backend_cls = mod.CacheClass backend_cls = mod.CacheClass
else: else:
backend, location, params = parse_backend_conf(backend, **kwargs) backend, location, params = parse_backend_conf(backend, **kwargs)
mod_path, cls_name = backend.rsplit('.', 1) backend_cls = import_by_path(backend)
mod = importlib.import_module(mod_path) except (AttributeError, ImportError, ImproperlyConfigured) as e:
backend_cls = getattr(mod, cls_name)
except (AttributeError, ImportError) as e:
raise InvalidCacheBackendError( raise InvalidCacheBackendError(
"Could not find backend '%s': %s" % (backend, e)) "Could not find backend '%s': %s" % (backend, e))
cache = backend_cls(location, params) cache = backend_cls(location, params)

View File

@ -4,7 +4,7 @@ from __future__ import unicode_literals
import warnings import warnings
from django.core.exceptions import ImproperlyConfigured, DjangoRuntimeWarning from django.core.exceptions import ImproperlyConfigured, DjangoRuntimeWarning
from django.utils.importlib import import_module from django.utils.module_loading import import_by_path
class InvalidCacheBackendError(ImproperlyConfigured): class InvalidCacheBackendError(ImproperlyConfigured):
@ -40,9 +40,7 @@ def get_key_func(key_func):
if callable(key_func): if callable(key_func):
return key_func return key_func
else: else:
key_func_module_path, key_func_name = key_func.rsplit('.', 1) return import_by_path(key_func)
key_func_module = import_module(key_func_module_path)
return getattr(key_func_module, key_func_name)
return default_key_func return default_key_func

View File

@ -8,12 +8,12 @@ import itertools
from datetime import datetime from datetime import datetime
from django.conf import settings from django.conf import settings
from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation from django.core.exceptions import SuspiciousOperation
from django.core.files import locks, File from django.core.files import locks, File
from django.core.files.move import file_move_safe from django.core.files.move import file_move_safe
from django.utils.encoding import force_text, filepath_to_uri from django.utils.encoding import force_text, filepath_to_uri
from django.utils.functional import LazyObject from django.utils.functional import LazyObject
from django.utils.importlib import import_module from django.utils.module_loading import import_by_path
from django.utils.text import get_valid_filename from django.utils.text import get_valid_filename
from django.utils._os import safe_join, abspathu from django.utils._os import safe_join, abspathu
@ -277,21 +277,7 @@ class FileSystemStorage(Storage):
return datetime.fromtimestamp(os.path.getmtime(self.path(name))) return datetime.fromtimestamp(os.path.getmtime(self.path(name)))
def get_storage_class(import_path=None): def get_storage_class(import_path=None):
if import_path is None: return import_by_path(import_path or settings.DEFAULT_FILE_STORAGE)
import_path = settings.DEFAULT_FILE_STORAGE
try:
dot = import_path.rindex('.')
except ValueError:
raise ImproperlyConfigured("%s isn't a storage module." % import_path)
module, classname = import_path[:dot], import_path[dot+1:]
try:
mod = import_module(module)
except ImportError as e:
raise ImproperlyConfigured('Error importing storage module %s: "%s"' % (module, e))
try:
return getattr(mod, classname)
except AttributeError:
raise ImproperlyConfigured('Storage module "%s" does not define a "%s" class.' % (module, classname))
class DefaultStorage(LazyObject): class DefaultStorage(LazyObject):
def _setup(self): def _setup(self):

View File

@ -7,10 +7,9 @@ from __future__ import unicode_literals
from io import BytesIO from io import BytesIO
from django.conf import settings from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.core.files.uploadedfile import TemporaryUploadedFile, InMemoryUploadedFile from django.core.files.uploadedfile import TemporaryUploadedFile, InMemoryUploadedFile
from django.utils import importlib
from django.utils.encoding import python_2_unicode_compatible from django.utils.encoding import python_2_unicode_compatible
from django.utils.module_loading import import_by_path
__all__ = ['UploadFileException','StopUpload', 'SkipFile', 'FileUploadHandler', __all__ = ['UploadFileException','StopUpload', 'SkipFile', 'FileUploadHandler',
'TemporaryFileUploadHandler', 'MemoryFileUploadHandler', 'TemporaryFileUploadHandler', 'MemoryFileUploadHandler',
@ -201,17 +200,4 @@ def load_handler(path, *args, **kwargs):
<TemporaryFileUploadHandler object at 0x...> <TemporaryFileUploadHandler object at 0x...>
""" """
i = path.rfind('.') return import_by_path(path)(*args, **kwargs)
module, attr = path[:i], path[i+1:]
try:
mod = importlib.import_module(module)
except ImportError as e:
raise ImproperlyConfigured('Error importing upload handler module %s: "%s"' % (module, e))
except ValueError:
raise ImproperlyConfigured('Error importing upload handler module.'
'Is FILE_UPLOAD_HANDLERS a correctly defined list or tuple?')
try:
cls = getattr(mod, attr)
except AttributeError:
raise ImproperlyConfigured('Module "%s" does not define a "%s" upload handler backend' % (module, attr))
return cls(*args, **kwargs)

View File

@ -9,8 +9,9 @@ from django.conf import settings
from django.core import exceptions from django.core import exceptions
from django.core import urlresolvers from django.core import urlresolvers
from django.core import signals from django.core import signals
from django.core.exceptions import MiddlewareNotUsed, PermissionDenied
from django.utils.encoding import force_text from django.utils.encoding import force_text
from django.utils.importlib import import_module from django.utils.module_loading import import_by_path
from django.utils import six from django.utils import six
from django.views import debug from django.views import debug
@ -43,21 +44,10 @@ class BaseHandler(object):
request_middleware = [] request_middleware = []
for middleware_path in settings.MIDDLEWARE_CLASSES: for middleware_path in settings.MIDDLEWARE_CLASSES:
try: mw_class = import_by_path(middleware_path)
mw_module, mw_classname = middleware_path.rsplit('.', 1)
except ValueError:
raise exceptions.ImproperlyConfigured('%s isn\'t a middleware module' % middleware_path)
try:
mod = import_module(mw_module)
except ImportError as e:
raise exceptions.ImproperlyConfigured('Error importing middleware %s: "%s"' % (mw_module, e))
try:
mw_class = getattr(mod, mw_classname)
except AttributeError:
raise exceptions.ImproperlyConfigured('Middleware module "%s" does not define a "%s" class' % (mw_module, mw_classname))
try: try:
mw_instance = mw_class() mw_instance = mw_class()
except exceptions.MiddlewareNotUsed: except MiddlewareNotUsed:
continue continue
if hasattr(mw_instance, 'process_request'): if hasattr(mw_instance, 'process_request'):
@ -154,7 +144,7 @@ class BaseHandler(object):
except: except:
signals.got_request_exception.send(sender=self.__class__, request=request) signals.got_request_exception.send(sender=self.__class__, request=request)
response = self.handle_uncaught_exception(request, resolver, sys.exc_info()) response = self.handle_uncaught_exception(request, resolver, sys.exc_info())
except exceptions.PermissionDenied: except PermissionDenied:
logger.warning( logger.warning(
'Forbidden (Permission denied): %s', request.path, 'Forbidden (Permission denied): %s', request.path,
extra={ extra={

View File

@ -4,8 +4,7 @@ Tools for sending email.
from __future__ import unicode_literals from __future__ import unicode_literals
from django.conf import settings from django.conf import settings
from django.core.exceptions import ImproperlyConfigured from django.utils.module_loading import import_by_path
from django.utils.importlib import import_module
# Imported for backwards compatibility, and for the sake # Imported for backwards compatibility, and for the sake
# of a cleaner namespace. These symbols used to be in # of a cleaner namespace. These symbols used to be in
@ -27,18 +26,7 @@ def get_connection(backend=None, fail_silently=False, **kwds):
Both fail_silently and other keyword arguments are used in the Both fail_silently and other keyword arguments are used in the
constructor of the backend. constructor of the backend.
""" """
path = backend or settings.EMAIL_BACKEND klass = import_by_path(backend or settings.EMAIL_BACKEND)
try:
mod_name, klass_name = path.rsplit('.', 1)
mod = import_module(mod_name)
except ImportError as e:
raise ImproperlyConfigured(('Error importing email backend module %s: "%s"'
% (mod_name, e)))
try:
klass = getattr(mod, klass_name)
except AttributeError:
raise ImproperlyConfigured(('Module "%s" does not define a '
'"%s" class' % (mod_name, klass_name)))
return klass(fail_silently=fail_silently, **kwds) return klass(fail_silently=fail_silently, **kwds)

View File

@ -21,11 +21,9 @@ from django.utils.six.moves import socketserver
from wsgiref import simple_server from wsgiref import simple_server
from wsgiref.util import FileWrapper # for backwards compatibility from wsgiref.util import FileWrapper # for backwards compatibility
import django
from django.core.exceptions import ImproperlyConfigured
from django.core.management.color import color_style from django.core.management.color import color_style
from django.core.wsgi import get_wsgi_application from django.core.wsgi import get_wsgi_application
from django.utils.importlib import import_module from django.utils.module_loading import import_by_path
__all__ = ['WSGIServer', 'WSGIRequestHandler'] __all__ = ['WSGIServer', 'WSGIRequestHandler']
@ -49,22 +47,11 @@ def get_internal_wsgi_application():
app_path = getattr(settings, 'WSGI_APPLICATION') app_path = getattr(settings, 'WSGI_APPLICATION')
if app_path is None: if app_path is None:
return get_wsgi_application() return get_wsgi_application()
module_name, attr = app_path.rsplit('.', 1)
try:
mod = import_module(module_name)
except ImportError as e:
raise ImproperlyConfigured(
"WSGI application '%s' could not be loaded; "
"could not import module '%s': %s" % (app_path, module_name, e))
try:
app = getattr(mod, attr)
except AttributeError as e:
raise ImproperlyConfigured(
"WSGI application '%s' could not be loaded; "
"can't find '%s' in module '%s': %s"
% (app_path, attr, module_name, e))
return app return import_by_path(
app_path,
error_prefix="WSGI application '%s' could not be loaded; " % app_path
)
class WSGIServerException(Exception): class WSGIServerException(Exception):

View File

@ -41,11 +41,10 @@ import time
import zlib import zlib
from django.conf import settings from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.utils import baseconv from django.utils import baseconv
from django.utils.crypto import constant_time_compare, salted_hmac from django.utils.crypto import constant_time_compare, salted_hmac
from django.utils.encoding import force_bytes, force_str, force_text from django.utils.encoding import force_bytes, force_str, force_text
from django.utils.importlib import import_module from django.utils.module_loading import import_by_path
class BadSignature(Exception): class BadSignature(Exception):
@ -76,18 +75,7 @@ def base64_hmac(salt, value, key):
def get_cookie_signer(salt='django.core.signing.get_cookie_signer'): def get_cookie_signer(salt='django.core.signing.get_cookie_signer'):
modpath = settings.SIGNING_BACKEND Signer = import_by_path(settings.SIGNING_BACKEND)
module, attr = modpath.rsplit('.', 1)
try:
mod = import_module(module)
except ImportError as e:
raise ImproperlyConfigured(
'Error importing cookie signer %s: "%s"' % (modpath, e))
try:
Signer = getattr(mod, attr)
except AttributeError as e:
raise ImproperlyConfigured(
'Error importing cookie signer %s: "%s"' % (modpath, e))
return Signer('django.http.cookies' + settings.SECRET_KEY, salt=salt) return Signer('django.http.cookies' + settings.SECRET_KEY, salt=salt)

View File

@ -5,6 +5,7 @@ from threading import local
from django.conf import settings from django.conf import settings
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.utils.importlib import import_module from django.utils.importlib import import_module
from django.utils.module_loading import import_by_path
from django.utils._os import upath from django.utils._os import upath
from django.utils import six from django.utils import six
@ -110,17 +111,7 @@ class ConnectionRouter(object):
self.routers = [] self.routers = []
for r in routers: for r in routers:
if isinstance(r, six.string_types): if isinstance(r, six.string_types):
try: router = import_by_path(r)()
module_name, klass_name = r.rsplit('.', 1)
module = import_module(module_name)
except ImportError as e:
raise ImproperlyConfigured('Error importing database router %s: "%s"' % (klass_name, e))
try:
router_class = getattr(module, klass_name)
except AttributeError:
raise ImproperlyConfigured('Module "%s" does not define a database router name "%s"' % (module, klass_name))
else:
router = router_class()
else: else:
router = r router = r
self.routers.append(router) self.routers.append(router)

View File

@ -1,6 +1,5 @@
from copy import copy from copy import copy
from django.core.exceptions import ImproperlyConfigured from django.utils.module_loading import import_by_path
from django.utils.importlib import import_module
# Cache of actual callables. # Cache of actual callables.
_standard_context_processors = None _standard_context_processors = None
@ -146,16 +145,7 @@ def get_standard_processors():
collect.extend(_builtin_context_processors) collect.extend(_builtin_context_processors)
collect.extend(settings.TEMPLATE_CONTEXT_PROCESSORS) collect.extend(settings.TEMPLATE_CONTEXT_PROCESSORS)
for path in collect: for path in collect:
i = path.rfind('.') func = import_by_path(path)
module, attr = path[:i], path[i+1:]
try:
mod = import_module(module)
except ImportError as e:
raise ImproperlyConfigured('Error importing request processor module %s: "%s"' % (module, e))
try:
func = getattr(mod, attr)
except AttributeError:
raise ImproperlyConfigured('Module "%s" does not define a "%s" callable request processor' % (module, attr))
processors.append(func) processors.append(func)
_standard_context_processors = tuple(processors) _standard_context_processors = tuple(processors)
return _standard_context_processors return _standard_context_processors

View File

@ -27,8 +27,8 @@
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.template.base import Origin, Template, Context, TemplateDoesNotExist, add_to_builtins from django.template.base import Origin, Template, Context, TemplateDoesNotExist, add_to_builtins
from django.utils.importlib import import_module
from django.conf import settings from django.conf import settings
from django.utils.module_loading import import_by_path
from django.utils import six from django.utils import six
template_source_loaders = None template_source_loaders = None
@ -91,15 +91,7 @@ def find_template_loader(loader):
else: else:
args = [] args = []
if isinstance(loader, six.string_types): if isinstance(loader, six.string_types):
module, attr = loader.rsplit('.', 1) TemplateLoader = import_by_path(loader)
try:
mod = import_module(module)
except ImportError as e:
raise ImproperlyConfigured('Error importing template source loader %s: "%s"' % (loader, e))
try:
TemplateLoader = getattr(mod, attr)
except AttributeError as e:
raise ImproperlyConfigured('Error importing template source loader %s: "%s"' % (loader, e))
if hasattr(TemplateLoader, 'load_template_source'): if hasattr(TemplateLoader, 'load_template_source'):
func = TemplateLoader(*args) func = TemplateLoader(*args)

View File

@ -2,6 +2,32 @@ import imp
import os import os
import sys import sys
from django.core.exceptions import ImproperlyConfigured
from django.utils.importlib import import_module
def import_by_path(dotted_path, error_prefix=''):
"""
Import a dotted module path and return the attribute/class designated by the
last name in the path. Raise ImproperlyConfigured if something goes wrong.
"""
try:
module_path, class_name = dotted_path.rsplit('.', 1)
except ValueError:
raise ImproperlyConfigured("%s%s doesn't look like a module path" % (
error_prefix, dotted_path))
try:
module = import_module(module_path)
except ImportError as e:
raise ImproperlyConfigured('%sError importing module %s: "%s"' % (
error_prefix, module_path, e))
try:
attr = getattr(module, class_name)
except AttributeError:
raise ImproperlyConfigured('%sModule "%s" does not define a "%s" attribute/class' % (
error_prefix, module_path, class_name))
return attr
def module_has_submodule(package, module_name): def module_has_submodule(package, module_name):
"""See if 'module' is in 'package'.""" """See if 'module' is in 'package'."""

View File

@ -13,8 +13,8 @@ from django.http import (HttpResponse, HttpResponseServerError,
from django.template import Template, Context, TemplateDoesNotExist from django.template import Template, Context, TemplateDoesNotExist
from django.template.defaultfilters import force_escape, pprint from django.template.defaultfilters import force_escape, pprint
from django.utils.html import escape from django.utils.html import escape
from django.utils.importlib import import_module
from django.utils.encoding import force_bytes, smart_text from django.utils.encoding import force_bytes, smart_text
from django.utils.module_loading import import_by_path
from django.utils import six from django.utils import six
HIDDEN_SETTINGS = re.compile('API|TOKEN|KEY|SECRET|PASS|PROFANITIES_LIST|SIGNATURE') HIDDEN_SETTINGS = re.compile('API|TOKEN|KEY|SECRET|PASS|PROFANITIES_LIST|SIGNATURE')
@ -76,17 +76,8 @@ def get_exception_reporter_filter(request):
global default_exception_reporter_filter global default_exception_reporter_filter
if default_exception_reporter_filter is None: if default_exception_reporter_filter is None:
# Load the default filter for the first time and cache it. # Load the default filter for the first time and cache it.
modpath = settings.DEFAULT_EXCEPTION_REPORTER_FILTER default_exception_reporter_filter = import_by_path(
modname, classname = modpath.rsplit('.', 1) settings.DEFAULT_EXCEPTION_REPORTER_FILTER)()
try:
mod = import_module(modname)
except ImportError as e:
raise ImproperlyConfigured(
'Error importing default exception reporter filter %s: "%s"' % (modpath, e))
try:
default_exception_reporter_filter = getattr(mod, classname)()
except AttributeError:
raise ImproperlyConfigured('Default exception reporter filter module "%s" does not define a "%s" class' % (modname, classname))
if request: if request:
return getattr(request, 'exception_reporter_filter', default_exception_reporter_filter) return getattr(request, 'exception_reporter_filter', default_exception_reporter_filter)
else: else:

View File

@ -57,9 +57,9 @@ class GetStorageClassTests(SimpleTestCase):
""" """
self.assertRaisesMessage( self.assertRaisesMessage(
ImproperlyConfigured, ImproperlyConfigured,
"NonExistingStorage isn't a storage module.", "Error importing module storage: \"No module named storage\"",
get_storage_class, get_storage_class,
'NonExistingStorage') 'storage.NonExistingStorage')
def test_get_nonexisting_storage_class(self): def test_get_nonexisting_storage_class(self):
""" """
@ -67,8 +67,8 @@ class GetStorageClassTests(SimpleTestCase):
""" """
self.assertRaisesMessage( self.assertRaisesMessage(
ImproperlyConfigured, ImproperlyConfigured,
'Storage module "django.core.files.storage" does not define a '\ 'Module "django.core.files.storage" does not define a '
'"NonExistingStorage" class.', '"NonExistingStorage" attribute/class',
get_storage_class, get_storage_class,
'django.core.files.storage.NonExistingStorage') 'django.core.files.storage.NonExistingStorage')
@ -79,8 +79,8 @@ class GetStorageClassTests(SimpleTestCase):
# Error message may or may not be the fully qualified path. # Error message may or may not be the fully qualified path.
six.assertRaisesRegex(self, six.assertRaisesRegex(self,
ImproperlyConfigured, ImproperlyConfigured,
('Error importing storage module django.core.files.non_existing_' 'Error importing module django.core.files.non_existing_storage: '
'storage: "No module named .*non_existing_storage'), '"No module named non_existing_storage"',
get_storage_class, get_storage_class,
'django.core.files.non_existing_storage.NonExistingStorage' 'django.core.files.non_existing_storage.NonExistingStorage'
) )

View File

@ -3,9 +3,10 @@ import sys
import imp import imp
from zipimport import zipimporter from zipimport import zipimporter
from django.core.exceptions import ImproperlyConfigured
from django.utils import unittest from django.utils import unittest
from django.utils.importlib import import_module from django.utils.importlib import import_module
from django.utils.module_loading import module_has_submodule from django.utils.module_loading import import_by_path, module_has_submodule
from django.utils._os import upath from django.utils._os import upath
@ -103,6 +104,23 @@ class EggLoader(unittest.TestCase):
self.assertFalse(module_has_submodule(egg_module, 'no_such_module')) self.assertFalse(module_has_submodule(egg_module, 'no_such_module'))
self.assertRaises(ImportError, import_module, 'egg_module.sub1.sub2.no_such_module') self.assertRaises(ImportError, import_module, 'egg_module.sub1.sub2.no_such_module')
class ModuleImportTestCase(unittest.TestCase):
def test_import_by_path(self):
cls = import_by_path(
'django.utils.module_loading.import_by_path')
self.assertEqual(cls, import_by_path)
# Test exceptions raised
for path in ('no_dots_in_path', 'unexistent.path',
'tests.regressiontests.utils.unexistent'):
self.assertRaises(ImproperlyConfigured, import_by_path, path)
with self.assertRaises(ImproperlyConfigured) as cm:
import_by_path('unexistent.module.path', error_prefix="Foo")
self.assertTrue(str(cm.exception).startswith('Foo'))
class ProxyFinder(object): class ProxyFinder(object):
def __init__(self): def __init__(self):
self._cache = {} self._cache = {}

View File

@ -20,7 +20,8 @@ from .html import TestUtilsHtml
from .http import TestUtilsHttp, ETagProcessingTests, HttpDateProcessingTests from .http import TestUtilsHttp, ETagProcessingTests, HttpDateProcessingTests
from .ipv6 import TestUtilsIPv6 from .ipv6 import TestUtilsIPv6
from .jslex import JsToCForGettextTest, JsTokensTest from .jslex import JsToCForGettextTest, JsTokensTest
from .module_loading import CustomLoader, DefaultLoader, EggLoader from .module_loading import (CustomLoader, DefaultLoader, EggLoader,
ModuleImportTestCase)
from .numberformat import TestNumberFormat from .numberformat import TestNumberFormat
from .os_utils import SafeJoinTests from .os_utils import SafeJoinTests
from .regex_helper import NormalizeTests from .regex_helper import NormalizeTests

View File

@ -85,7 +85,7 @@ class GetInternalWSGIApplicationTest(unittest.TestCase):
def test_bad_module(self): def test_bad_module(self):
with six.assertRaisesRegex(self, with six.assertRaisesRegex(self,
ImproperlyConfigured, ImproperlyConfigured,
r"^WSGI application 'regressiontests.wsgi.noexist.app' could not be loaded; could not import module 'regressiontests.wsgi.noexist':"): r"^WSGI application 'regressiontests.wsgi.noexist.app' could not be loaded; Error importing.*"):
get_internal_wsgi_application() get_internal_wsgi_application()
@ -94,6 +94,6 @@ class GetInternalWSGIApplicationTest(unittest.TestCase):
def test_bad_name(self): def test_bad_name(self):
with six.assertRaisesRegex(self, with six.assertRaisesRegex(self,
ImproperlyConfigured, ImproperlyConfigured,
r"^WSGI application 'regressiontests.wsgi.wsgi.noexist' could not be loaded; can't find 'noexist' in module 'regressiontests.wsgi.wsgi':"): r"^WSGI application 'regressiontests.wsgi.wsgi.noexist' could not be loaded; Module.*"):
get_internal_wsgi_application() get_internal_wsgi_application()