Fixed #21674 -- Deprecated the import_by_path() function in favor of import_string().
Thanks Aymeric Augustin for the suggestion and review.
This commit is contained in:
parent
fcc21837dc
commit
5d263dee30
1
AUTHORS
1
AUTHORS
|
@ -484,6 +484,7 @@ answer newbie questions, and generally made Django that much better:
|
||||||
John Paulett <john@paulett.org>
|
John Paulett <john@paulett.org>
|
||||||
pavithran s <pavithran.s@gmail.com>
|
pavithran s <pavithran.s@gmail.com>
|
||||||
Barry Pederson <bp@barryp.org>
|
Barry Pederson <bp@barryp.org>
|
||||||
|
Berker Peksag <berker.peksag@gmail.com>
|
||||||
Andreas Pelme <andreas@pelme.se>
|
Andreas Pelme <andreas@pelme.se>
|
||||||
permonik@mesias.brnonet.cz
|
permonik@mesias.brnonet.cz
|
||||||
peter@mymart.com
|
peter@mymart.com
|
||||||
|
|
|
@ -2,7 +2,7 @@ import os
|
||||||
from unittest import SkipTest
|
from unittest import SkipTest
|
||||||
|
|
||||||
from django.contrib.staticfiles.testing import StaticLiveServerCase
|
from django.contrib.staticfiles.testing import StaticLiveServerCase
|
||||||
from django.utils.module_loading import import_by_path
|
from django.utils.module_loading import import_string
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ class AdminSeleniumWebDriverTestCase(StaticLiveServerCase):
|
||||||
if not os.environ.get('DJANGO_SELENIUM_TESTS', False):
|
if not os.environ.get('DJANGO_SELENIUM_TESTS', False):
|
||||||
raise SkipTest('Selenium tests not requested')
|
raise SkipTest('Selenium tests not requested')
|
||||||
try:
|
try:
|
||||||
cls.selenium = import_by_path(cls.webdriver_class)()
|
cls.selenium = import_string(cls.webdriver_class)()
|
||||||
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)))
|
||||||
|
|
|
@ -4,7 +4,7 @@ import re
|
||||||
from django.apps import apps as django_apps
|
from django.apps import apps as django_apps
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
|
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
|
||||||
from django.utils.module_loading import import_by_path
|
from django.utils.module_loading import import_string
|
||||||
from django.middleware.csrf import rotate_token
|
from django.middleware.csrf import rotate_token
|
||||||
|
|
||||||
from .signals import user_logged_in, user_logged_out, user_login_failed
|
from .signals import user_logged_in, user_logged_out, user_login_failed
|
||||||
|
@ -15,7 +15,7 @@ REDIRECT_FIELD_NAME = 'next'
|
||||||
|
|
||||||
|
|
||||||
def load_backend(path):
|
def load_backend(path):
|
||||||
return import_by_path(path)()
|
return import_string(path)()
|
||||||
|
|
||||||
|
|
||||||
def get_backends():
|
def get_backends():
|
||||||
|
|
|
@ -13,7 +13,7 @@ from django.utils.encoding import force_bytes, force_str, force_text
|
||||||
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.module_loading import import_string
|
||||||
from django.utils.translation import ugettext_noop as _
|
from django.utils.translation import ugettext_noop as _
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,7 +92,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:
|
||||||
hasher = import_by_path(backend)()
|
hasher = import_string(backend)()
|
||||||
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)
|
||||||
|
|
|
@ -58,7 +58,7 @@ class RemoteUserMiddleware(object):
|
||||||
auth.BACKEND_SESSION_KEY, ''))
|
auth.BACKEND_SESSION_KEY, ''))
|
||||||
if isinstance(stored_backend, RemoteUserBackend):
|
if isinstance(stored_backend, RemoteUserBackend):
|
||||||
auth.logout(request)
|
auth.logout(request)
|
||||||
except ImproperlyConfigured:
|
except ImportError:
|
||||||
# backend failed to load
|
# backend failed to load
|
||||||
auth.logout(request)
|
auth.logout(request)
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.utils.module_loading import import_string
|
||||||
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 (
|
||||||
|
@ -12,7 +11,7 @@ __all__ = [
|
||||||
|
|
||||||
def get_storage(path, *args, **kwargs):
|
def get_storage(path, *args, **kwargs):
|
||||||
try:
|
try:
|
||||||
storage_class = import_by_path(path)
|
storage_class = import_string(path)
|
||||||
except ImproperlyConfigured as e:
|
except ImportError as e:
|
||||||
raise MissingStorage('Error loading storage: %s' % e)
|
raise MissingStorage('Error loading storage: %s' % e)
|
||||||
return storage_class(*args, **kwargs)
|
return storage_class(*args, **kwargs)
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils.module_loading import import_by_path
|
from django.utils.module_loading import import_string
|
||||||
|
|
||||||
|
|
||||||
def default_storage(request):
|
def default_storage(request):
|
||||||
"""
|
"""
|
||||||
Callable with the same interface as the storage classes.
|
Callable with the same interface as the storage classes.
|
||||||
|
|
||||||
This isn't just default_storage = import_by_path(settings.MESSAGE_STORAGE)
|
This isn't just default_storage = import_string(settings.MESSAGE_STORAGE)
|
||||||
to avoid accessing the settings at the module level.
|
to avoid accessing the settings at the module level.
|
||||||
"""
|
"""
|
||||||
return import_by_path(settings.MESSAGE_STORAGE)(request)
|
return import_string(settings.MESSAGE_STORAGE)(request)
|
||||||
|
|
|
@ -12,7 +12,7 @@ from django.utils.crypto import get_random_string
|
||||||
from django.utils.crypto import salted_hmac
|
from django.utils.crypto import salted_hmac
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.encoding import force_bytes, force_text
|
from django.utils.encoding import force_bytes, force_text
|
||||||
from django.utils.module_loading import import_by_path
|
from django.utils.module_loading import import_string
|
||||||
|
|
||||||
from django.contrib.sessions.exceptions import SuspiciousSession
|
from django.contrib.sessions.exceptions import SuspiciousSession
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ class SessionBase(object):
|
||||||
self._session_key = session_key
|
self._session_key = session_key
|
||||||
self.accessed = False
|
self.accessed = False
|
||||||
self.modified = False
|
self.modified = False
|
||||||
self.serializer = import_by_path(settings.SESSION_SERIALIZER)
|
self.serializer = import_string(settings.SESSION_SERIALIZER)
|
||||||
|
|
||||||
def __contains__(self, key):
|
def __contains__(self, key):
|
||||||
return key in self._session
|
return key in self._session
|
||||||
|
|
|
@ -6,7 +6,7 @@ from django.conf import settings
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
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.functional import empty, LazyObject
|
from django.utils.functional import empty, LazyObject
|
||||||
from django.utils.module_loading import import_by_path
|
from django.utils.module_loading import import_string
|
||||||
from django.utils._os import safe_join
|
from django.utils._os import safe_join
|
||||||
from django.utils import six, lru_cache
|
from django.utils import six, lru_cache
|
||||||
|
|
||||||
|
@ -257,7 +257,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.
|
||||||
"""
|
"""
|
||||||
Finder = import_by_path(import_path)
|
Finder = import_string(import_path)
|
||||||
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))
|
||||||
|
|
|
@ -20,7 +20,7 @@ from django.core import signals
|
||||||
from django.core.cache.backends.base import (
|
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.module_loading import import_by_path
|
from django.utils.module_loading import import_string
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
@ -69,8 +69,8 @@ def _create_cache(backend, **kwargs):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
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
|
||||||
import_by_path(backend)
|
import_string(backend)
|
||||||
except ImproperlyConfigured as e:
|
except ImportError as e:
|
||||||
raise InvalidCacheBackendError("Could not find backend '%s': %s" % (
|
raise InvalidCacheBackendError("Could not find backend '%s': %s" % (
|
||||||
backend, e))
|
backend, e))
|
||||||
location = kwargs.pop('LOCATION', '')
|
location = kwargs.pop('LOCATION', '')
|
||||||
|
@ -80,8 +80,8 @@ def _create_cache(backend, **kwargs):
|
||||||
params.update(kwargs)
|
params.update(kwargs)
|
||||||
backend = params.pop('BACKEND')
|
backend = params.pop('BACKEND')
|
||||||
location = params.pop('LOCATION', '')
|
location = params.pop('LOCATION', '')
|
||||||
backend_cls = import_by_path(backend)
|
backend_cls = import_string(backend)
|
||||||
except (AttributeError, ImportError, ImproperlyConfigured) as e:
|
except ImportError as e:
|
||||||
raise InvalidCacheBackendError(
|
raise InvalidCacheBackendError(
|
||||||
"Could not find backend '%s': %s" % (backend, e))
|
"Could not find backend '%s': %s" % (backend, e))
|
||||||
return backend_cls(location, params)
|
return backend_cls(location, params)
|
||||||
|
|
|
@ -5,7 +5,7 @@ import time
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
from django.core.exceptions import ImproperlyConfigured, DjangoRuntimeWarning
|
from django.core.exceptions import ImproperlyConfigured, DjangoRuntimeWarning
|
||||||
from django.utils.module_loading import import_by_path
|
from django.utils.module_loading import import_string
|
||||||
|
|
||||||
|
|
||||||
class InvalidCacheBackendError(ImproperlyConfigured):
|
class InvalidCacheBackendError(ImproperlyConfigured):
|
||||||
|
@ -45,7 +45,7 @@ def get_key_func(key_func):
|
||||||
if callable(key_func):
|
if callable(key_func):
|
||||||
return key_func
|
return key_func
|
||||||
else:
|
else:
|
||||||
return import_by_path(key_func)
|
return import_string(key_func)
|
||||||
return default_key_func
|
return default_key_func
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ 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.module_loading import import_by_path
|
from django.utils.module_loading import import_string
|
||||||
from django.utils.six.moves.urllib.parse import urljoin
|
from django.utils.six.moves.urllib.parse import urljoin
|
||||||
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
|
||||||
|
@ -301,7 +301,7 @@ class FileSystemStorage(Storage):
|
||||||
|
|
||||||
|
|
||||||
def get_storage_class(import_path=None):
|
def get_storage_class(import_path=None):
|
||||||
return import_by_path(import_path or settings.DEFAULT_FILE_STORAGE)
|
return import_string(import_path or settings.DEFAULT_FILE_STORAGE)
|
||||||
|
|
||||||
|
|
||||||
class DefaultStorage(LazyObject):
|
class DefaultStorage(LazyObject):
|
||||||
|
|
|
@ -9,7 +9,7 @@ from io import BytesIO
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.files.uploadedfile import TemporaryUploadedFile, InMemoryUploadedFile
|
from django.core.files.uploadedfile import TemporaryUploadedFile, InMemoryUploadedFile
|
||||||
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
|
from django.utils.module_loading import import_string
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'UploadFileException', 'StopUpload', 'SkipFile', 'FileUploadHandler',
|
'UploadFileException', 'StopUpload', 'SkipFile', 'FileUploadHandler',
|
||||||
|
@ -214,4 +214,4 @@ def load_handler(path, *args, **kwargs):
|
||||||
<TemporaryFileUploadHandler object at 0x...>
|
<TemporaryFileUploadHandler object at 0x...>
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return import_by_path(path)(*args, **kwargs)
|
return import_string(path)(*args, **kwargs)
|
||||||
|
|
|
@ -11,7 +11,7 @@ from django.core import signals
|
||||||
from django.core.exceptions import MiddlewareNotUsed, PermissionDenied, SuspiciousOperation
|
from django.core.exceptions import MiddlewareNotUsed, PermissionDenied, SuspiciousOperation
|
||||||
from django.db import connections, transaction
|
from django.db import connections, transaction
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.module_loading import import_by_path
|
from django.utils.module_loading import import_string
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
from django.views import debug
|
from django.views import debug
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ class BaseHandler(object):
|
||||||
|
|
||||||
request_middleware = []
|
request_middleware = []
|
||||||
for middleware_path in settings.MIDDLEWARE_CLASSES:
|
for middleware_path in settings.MIDDLEWARE_CLASSES:
|
||||||
mw_class = import_by_path(middleware_path)
|
mw_class = import_string(middleware_path)
|
||||||
try:
|
try:
|
||||||
mw_instance = mw_class()
|
mw_instance = mw_class()
|
||||||
except MiddlewareNotUsed:
|
except MiddlewareNotUsed:
|
||||||
|
|
|
@ -4,7 +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.utils.module_loading import import_by_path
|
from django.utils.module_loading import import_string
|
||||||
|
|
||||||
# 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
|
||||||
|
@ -34,7 +34,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.
|
||||||
"""
|
"""
|
||||||
klass = import_by_path(backend or settings.EMAIL_BACKEND)
|
klass = import_string(backend or settings.EMAIL_BACKEND)
|
||||||
return klass(fail_silently=fail_silently, **kwds)
|
return klass(fail_silently=fail_silently, **kwds)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,11 @@ import traceback
|
||||||
from wsgiref import simple_server
|
from wsgiref import simple_server
|
||||||
from wsgiref.util import FileWrapper # NOQA: for backwards compatibility
|
from wsgiref.util import FileWrapper # NOQA: for backwards compatibility
|
||||||
|
|
||||||
|
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.module_loading import import_by_path
|
from django.utils import six
|
||||||
|
from django.utils.module_loading import import_string
|
||||||
from django.utils.six.moves import socketserver
|
from django.utils.six.moves import socketserver
|
||||||
|
|
||||||
__all__ = ('WSGIServer', 'WSGIRequestHandler', 'MAX_SOCKET_CHUNK_SIZE')
|
__all__ = ('WSGIServer', 'WSGIRequestHandler', 'MAX_SOCKET_CHUNK_SIZE')
|
||||||
|
@ -50,10 +52,18 @@ def get_internal_wsgi_application():
|
||||||
if app_path is None:
|
if app_path is None:
|
||||||
return get_wsgi_application()
|
return get_wsgi_application()
|
||||||
|
|
||||||
return import_by_path(
|
try:
|
||||||
app_path,
|
return import_string(app_path)
|
||||||
error_prefix="WSGI application '%s' could not be loaded; " % app_path
|
except ImportError as e:
|
||||||
)
|
msg = (
|
||||||
|
"WSGI application '%(app_path)s' could not be loaded; "
|
||||||
|
"Error importing module: '%(exception)s'" % ({
|
||||||
|
'app_path': app_path,
|
||||||
|
'exception': e,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
six.reraise(ImproperlyConfigured, ImproperlyConfigured(msg),
|
||||||
|
sys.exc_info()[2])
|
||||||
|
|
||||||
|
|
||||||
class ServerHandler(simple_server.ServerHandler, object):
|
class ServerHandler(simple_server.ServerHandler, object):
|
||||||
|
|
|
@ -44,7 +44,7 @@ from django.conf import settings
|
||||||
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.module_loading import import_by_path
|
from django.utils.module_loading import import_string
|
||||||
|
|
||||||
|
|
||||||
class BadSignature(Exception):
|
class BadSignature(Exception):
|
||||||
|
@ -75,7 +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'):
|
||||||
Signer = import_by_path(settings.SIGNING_BACKEND)
|
Signer = import_string(settings.SIGNING_BACKEND)
|
||||||
return Signer('django.http.cookies' + settings.SECRET_KEY, salt=salt)
|
return Signer('django.http.cookies' + settings.SECRET_KEY, salt=salt)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ from django.apps.registry import Apps
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models.options import DEFAULT_NAMES, normalize_unique_together
|
from django.db.models.options import DEFAULT_NAMES, normalize_unique_together
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
from django.utils.module_loading import import_by_path
|
from django.utils.module_loading import import_string
|
||||||
|
|
||||||
|
|
||||||
class InvalidBasesError(ValueError):
|
class InvalidBasesError(ValueError):
|
||||||
|
@ -115,7 +115,7 @@ class ModelState(object):
|
||||||
fields = []
|
fields = []
|
||||||
for field in model._meta.local_fields:
|
for field in model._meta.local_fields:
|
||||||
name, path, args, kwargs = field.deconstruct()
|
name, path, args, kwargs = field.deconstruct()
|
||||||
field_class = import_by_path(path)
|
field_class = import_string(path)
|
||||||
try:
|
try:
|
||||||
fields.append((name, field_class(*args, **kwargs)))
|
fields.append((name, field_class(*args, **kwargs)))
|
||||||
except TypeError as e:
|
except TypeError as e:
|
||||||
|
@ -127,7 +127,7 @@ class ModelState(object):
|
||||||
))
|
))
|
||||||
for field in model._meta.local_many_to_many:
|
for field in model._meta.local_many_to_many:
|
||||||
name, path, args, kwargs = field.deconstruct()
|
name, path, args, kwargs = field.deconstruct()
|
||||||
field_class = import_by_path(path)
|
field_class = import_string(path)
|
||||||
try:
|
try:
|
||||||
fields.append((name, field_class(*args, **kwargs)))
|
fields.append((name, field_class(*args, **kwargs)))
|
||||||
except TypeError as e:
|
except TypeError as e:
|
||||||
|
@ -175,7 +175,7 @@ class ModelState(object):
|
||||||
fields = []
|
fields = []
|
||||||
for name, field in self.fields:
|
for name, field in self.fields:
|
||||||
_, path, args, kwargs = field.deconstruct()
|
_, path, args, kwargs = field.deconstruct()
|
||||||
field_class = import_by_path(path)
|
field_class = import_string(path)
|
||||||
fields.append((name, field_class(*args, **kwargs)))
|
fields.append((name, field_class(*args, **kwargs)))
|
||||||
# Now make a copy
|
# Now make a copy
|
||||||
return self.__class__(
|
return self.__class__(
|
||||||
|
|
|
@ -7,7 +7,7 @@ import warnings
|
||||||
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.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.module_loading import import_by_path
|
from django.utils.module_loading import import_string
|
||||||
from django.utils._os import upath
|
from django.utils._os import upath
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
|
|
||||||
|
@ -221,7 +221,7 @@ class ConnectionRouter(object):
|
||||||
routers = []
|
routers = []
|
||||||
for r in self._routers:
|
for r in self._routers:
|
||||||
if isinstance(r, six.string_types):
|
if isinstance(r, six.string_types):
|
||||||
router = import_by_path(r)()
|
router = import_string(r)()
|
||||||
else:
|
else:
|
||||||
router = r
|
router = r
|
||||||
routers.append(router)
|
routers.append(router)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from django.utils.module_loading import import_by_path
|
from django.utils.module_loading import import_string
|
||||||
|
|
||||||
# Cache of actual callables.
|
# Cache of actual callables.
|
||||||
_standard_context_processors = None
|
_standard_context_processors = None
|
||||||
|
@ -162,7 +162,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:
|
||||||
func = import_by_path(path)
|
func = import_string(path)
|
||||||
processors.append(func)
|
processors.append(func)
|
||||||
_standard_context_processors = tuple(processors)
|
_standard_context_processors = tuple(processors)
|
||||||
return _standard_context_processors
|
return _standard_context_processors
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.template.base import Origin, Template, Context, TemplateDoesNotExist
|
from django.template.base import Origin, Template, Context, TemplateDoesNotExist
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils.module_loading import import_by_path
|
from django.utils.module_loading import import_string
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
|
|
||||||
template_source_loaders = None
|
template_source_loaders = None
|
||||||
|
@ -95,7 +95,7 @@ def find_template_loader(loader):
|
||||||
else:
|
else:
|
||||||
args = []
|
args = []
|
||||||
if isinstance(loader, six.string_types):
|
if isinstance(loader, six.string_types):
|
||||||
TemplateLoader = import_by_path(loader)
|
TemplateLoader = import_string(loader)
|
||||||
|
|
||||||
if hasattr(TemplateLoader, 'load_template_source'):
|
if hasattr(TemplateLoader, 'load_template_source'):
|
||||||
func = TemplateLoader(*args)
|
func = TemplateLoader(*args)
|
||||||
|
|
|
@ -5,7 +5,7 @@ import warnings
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core import mail
|
from django.core import mail
|
||||||
from django.core.mail import get_connection
|
from django.core.mail import get_connection
|
||||||
from django.utils.module_loading import import_by_path
|
from django.utils.module_loading import import_string
|
||||||
from django.views.debug import ExceptionReporter, get_exception_reporter_filter
|
from django.views.debug import ExceptionReporter, get_exception_reporter_filter
|
||||||
|
|
||||||
# Imports kept for backwards-compatibility in Django 1.7.
|
# Imports kept for backwards-compatibility in Django 1.7.
|
||||||
|
@ -73,7 +73,7 @@ def configure_logging(logging_config, logging_settings):
|
||||||
|
|
||||||
if logging_config:
|
if logging_config:
|
||||||
# First find the logging configuration function ...
|
# First find the logging configuration function ...
|
||||||
logging_config_func = import_by_path(logging_config)
|
logging_config_func = import_string(logging_config)
|
||||||
|
|
||||||
logging_config_func(DEFAULT_LOGGING)
|
logging_config_func(DEFAULT_LOGGING)
|
||||||
|
|
||||||
|
|
|
@ -5,33 +5,48 @@ import imp
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import warnings
|
||||||
|
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
|
|
||||||
|
|
||||||
|
def import_string(dotted_path):
|
||||||
|
"""
|
||||||
|
Import a dotted module path and return the attribute/class designated by the
|
||||||
|
last name in the path. Raise ImportError if the import failed.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
module_path, class_name = dotted_path.rsplit('.', 1)
|
||||||
|
except ValueError:
|
||||||
|
msg = "%s doesn't look like a module path" % dotted_path
|
||||||
|
six.reraise(ImportError, ImportError(msg), sys.exc_info()[2])
|
||||||
|
|
||||||
|
module = import_module(module_path)
|
||||||
|
|
||||||
|
try:
|
||||||
|
return getattr(module, class_name)
|
||||||
|
except AttributeError:
|
||||||
|
msg = 'Module "%s" does not define a "%s" attribute/class' % (
|
||||||
|
dotted_path, class_name)
|
||||||
|
six.reraise(ImportError, ImportError(msg), sys.exc_info()[2])
|
||||||
|
|
||||||
|
|
||||||
def import_by_path(dotted_path, error_prefix=''):
|
def import_by_path(dotted_path, error_prefix=''):
|
||||||
"""
|
"""
|
||||||
Import a dotted module path and return the attribute/class designated by the
|
Import a dotted module path and return the attribute/class designated by the
|
||||||
last name in the path. Raise ImproperlyConfigured if something goes wrong.
|
last name in the path. Raise ImproperlyConfigured if something goes wrong.
|
||||||
"""
|
"""
|
||||||
|
warnings.warn(
|
||||||
|
'import_by_path() has been deprecated. Use import_string() instead.',
|
||||||
|
PendingDeprecationWarning, stacklevel=2)
|
||||||
try:
|
try:
|
||||||
module_path, class_name = dotted_path.rsplit('.', 1)
|
attr = import_string(dotted_path)
|
||||||
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:
|
except ImportError as e:
|
||||||
msg = '%sError importing module %s: "%s"' % (
|
msg = '%sError importing module %s: "%s"' % (
|
||||||
error_prefix, module_path, e)
|
error_prefix, dotted_path, e)
|
||||||
six.reraise(ImproperlyConfigured, ImproperlyConfigured(msg),
|
six.reraise(ImproperlyConfigured, ImproperlyConfigured(msg),
|
||||||
sys.exc_info()[2])
|
sys.exc_info()[2])
|
||||||
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
|
return attr
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ from django.template.defaultfilters import force_escape, pprint
|
||||||
from django.utils.datastructures import MultiValueDict
|
from django.utils.datastructures import MultiValueDict
|
||||||
from django.utils.html import escape
|
from django.utils.html import escape
|
||||||
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.module_loading import import_string
|
||||||
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')
|
||||||
|
@ -85,7 +85,7 @@ 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.
|
||||||
default_exception_reporter_filter = import_by_path(
|
default_exception_reporter_filter = import_string(
|
||||||
settings.DEFAULT_EXCEPTION_REPORTER_FILTER)()
|
settings.DEFAULT_EXCEPTION_REPORTER_FILTER)()
|
||||||
if request:
|
if request:
|
||||||
return getattr(request, 'exception_reporter_filter', default_exception_reporter_filter)
|
return getattr(request, 'exception_reporter_filter', default_exception_reporter_filter)
|
||||||
|
|
|
@ -116,6 +116,9 @@ details on these changes.
|
||||||
* ``django.db.backends.DatabaseValidation.validate_field`` will be removed in
|
* ``django.db.backends.DatabaseValidation.validate_field`` will be removed in
|
||||||
favor of the ``check_field`` method.
|
favor of the ``check_field`` method.
|
||||||
|
|
||||||
|
* ``django.utils.module_loading.import_by_path`` will be removed in favor of
|
||||||
|
``django.utils.module_loading.import_string``.
|
||||||
|
|
||||||
.. _deprecation-removed-in-1.8:
|
.. _deprecation-removed-in-1.8:
|
||||||
|
|
||||||
1.8
|
1.8
|
||||||
|
|
|
@ -709,22 +709,31 @@ escaping HTML.
|
||||||
|
|
||||||
Functions for working with Python modules.
|
Functions for working with Python modules.
|
||||||
|
|
||||||
.. function:: import_by_path(dotted_path, error_prefix='')
|
.. function:: import_string(dotted_path)
|
||||||
|
|
||||||
.. versionadded:: 1.6
|
.. versionadded:: 1.7
|
||||||
|
|
||||||
Imports a dotted module path and returns the attribute/class designated by
|
Imports a dotted module path and returns the attribute/class designated by
|
||||||
the last name in the path. Raises
|
the last name in the path. Raises ``ImportError`` if the import failed. For
|
||||||
:exc:`~django.core.exceptions.ImproperlyConfigured` if something goes
|
example::
|
||||||
wrong. For example::
|
|
||||||
|
|
||||||
from django.utils.module_loading import import_by_path
|
from django.utils.module_loading import import_string
|
||||||
ImproperlyConfigured = import_by_path('django.core.exceptions.ImproperlyConfigured')
|
ImproperlyConfigured = import_string('django.core.exceptions.ImproperlyConfigured')
|
||||||
|
|
||||||
is equivalent to::
|
is equivalent to::
|
||||||
|
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
|
||||||
|
.. function:: import_by_path(dotted_path, error_prefix='')
|
||||||
|
|
||||||
|
.. versionadded:: 1.6
|
||||||
|
.. deprecated:: 1.7
|
||||||
|
Use :meth:`~django.utils.module_loading.import_string` instead.
|
||||||
|
|
||||||
|
Imports a dotted module path and returns the attribute/class designated by
|
||||||
|
the last name in the path. Raises :exc:`~django.core.exceptions.ImproperlyConfigured`
|
||||||
|
if something goes wrong.
|
||||||
|
|
||||||
``django.utils.safestring``
|
``django.utils.safestring``
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
|
|
|
@ -1042,6 +1042,17 @@ Features deprecated in 1.7
|
||||||
respectively :mod:`logging.config` and :mod:`importlib` provided for Python
|
respectively :mod:`logging.config` and :mod:`importlib` provided for Python
|
||||||
versions prior to 2.7. They have been deprecated.
|
versions prior to 2.7. They have been deprecated.
|
||||||
|
|
||||||
|
``django.utils.module_loading.import_by_path``
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The current :meth:`~django.utils.module_loading.import_by_path` function
|
||||||
|
catches ``AttributeError``, ``ImportError`` and ``ValueError`` exceptions,
|
||||||
|
and re-raises :exc:`~django.core.exceptions.ImproperlyConfigured`. Such
|
||||||
|
exception masking makes it needlessly hard to diagnose circular import
|
||||||
|
problems, because it makes it look like the problem comes from inside Django.
|
||||||
|
It has been deprecated in favor of
|
||||||
|
:meth:`~django.utils.module_loading.import_string`.
|
||||||
|
|
||||||
``django.utils.tzinfo``
|
``django.utils.tzinfo``
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ except ImportError:
|
||||||
import dummy_threading as threading
|
import dummy_threading as threading
|
||||||
|
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.core.exceptions import SuspiciousOperation, ImproperlyConfigured
|
from django.core.exceptions import SuspiciousOperation
|
||||||
from django.core.files.base import File, ContentFile
|
from django.core.files.base import File, ContentFile
|
||||||
from django.core.files.storage import FileSystemStorage, get_storage_class
|
from django.core.files.storage import FileSystemStorage, get_storage_class
|
||||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||||
|
@ -43,29 +43,23 @@ class GetStorageClassTests(SimpleTestCase):
|
||||||
"""
|
"""
|
||||||
get_storage_class raises an error if the requested import don't exist.
|
get_storage_class raises an error if the requested import don't exist.
|
||||||
"""
|
"""
|
||||||
with six.assertRaisesRegex(self, ImproperlyConfigured,
|
with six.assertRaisesRegex(self, ImportError, "No module named '?storage'?"):
|
||||||
"Error importing module storage: \"No module named '?storage'?\""):
|
|
||||||
get_storage_class('storage.NonExistingStorage')
|
get_storage_class('storage.NonExistingStorage')
|
||||||
|
|
||||||
def test_get_nonexisting_storage_class(self):
|
def test_get_nonexisting_storage_class(self):
|
||||||
"""
|
"""
|
||||||
get_storage_class raises an error if the requested class don't exist.
|
get_storage_class raises an error if the requested class don't exist.
|
||||||
"""
|
"""
|
||||||
self.assertRaisesMessage(
|
self.assertRaises(ImportError, get_storage_class,
|
||||||
ImproperlyConfigured,
|
'django.core.files.storage.NonExistingStorage')
|
||||||
'Module "django.core.files.storage" does not define a '
|
|
||||||
'"NonExistingStorage" attribute/class',
|
|
||||||
get_storage_class,
|
|
||||||
'django.core.files.storage.NonExistingStorage')
|
|
||||||
|
|
||||||
def test_get_nonexisting_storage_module(self):
|
def test_get_nonexisting_storage_module(self):
|
||||||
"""
|
"""
|
||||||
get_storage_class raises an error if the requested module don't exist.
|
get_storage_class raises an error if the requested module don't exist.
|
||||||
"""
|
"""
|
||||||
# Error message may or may not be the fully qualified path.
|
# Error message may or may not be the fully qualified path.
|
||||||
with six.assertRaisesRegex(self, ImproperlyConfigured,
|
with six.assertRaisesRegex(self, ImportError,
|
||||||
"Error importing module django.core.files.non_existing_storage: "
|
"No module named '?(django.core.files.)?non_existing_storage'?"):
|
||||||
"\"No module named '?(django.core.files.)?non_existing_storage'?\""):
|
|
||||||
get_storage_class(
|
get_storage_class(
|
||||||
'django.core.files.non_existing_storage.NonExistingStorage')
|
'django.core.files.non_existing_storage.NonExistingStorage')
|
||||||
|
|
||||||
|
|
|
@ -788,11 +788,11 @@ class TestMiscFinder(TestCase):
|
||||||
finders.FileSystemFinder)
|
finders.FileSystemFinder)
|
||||||
|
|
||||||
def test_get_finder_bad_classname(self):
|
def test_get_finder_bad_classname(self):
|
||||||
self.assertRaises(ImproperlyConfigured, finders.get_finder,
|
self.assertRaises(ImportError, finders.get_finder,
|
||||||
'django.contrib.staticfiles.finders.FooBarFinder')
|
'django.contrib.staticfiles.finders.FooBarFinder')
|
||||||
|
|
||||||
def test_get_finder_bad_module(self):
|
def test_get_finder_bad_module(self):
|
||||||
self.assertRaises(ImproperlyConfigured,
|
self.assertRaises(ImportError,
|
||||||
finders.get_finder, 'foo.bar.FooBarFinder')
|
finders.get_finder, 'foo.bar.FooBarFinder')
|
||||||
|
|
||||||
def test_cache(self):
|
def test_cache(self):
|
||||||
|
|
|
@ -3,13 +3,15 @@ from importlib import import_module
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
|
import warnings
|
||||||
from zipimport import zipimporter
|
from zipimport import zipimporter
|
||||||
|
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.test import SimpleTestCase, modify_settings
|
from django.test import SimpleTestCase, modify_settings
|
||||||
from django.test.utils import extend_sys_path
|
from django.test.utils import IgnorePendingDeprecationWarningsMixin, extend_sys_path
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
from django.utils.module_loading import autodiscover_modules, import_by_path, module_has_submodule
|
from django.utils.module_loading import (autodiscover_modules, import_by_path, import_string,
|
||||||
|
module_has_submodule)
|
||||||
from django.utils._os import upath
|
from django.utils._os import upath
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,15 +109,13 @@ class EggLoader(unittest.TestCase):
|
||||||
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):
|
class ModuleImportTestCase(IgnorePendingDeprecationWarningsMixin, unittest.TestCase):
|
||||||
def test_import_by_path(self):
|
def test_import_by_path(self):
|
||||||
cls = import_by_path(
|
cls = import_by_path('django.utils.module_loading.import_by_path')
|
||||||
'django.utils.module_loading.import_by_path')
|
|
||||||
self.assertEqual(cls, import_by_path)
|
self.assertEqual(cls, import_by_path)
|
||||||
|
|
||||||
# Test exceptions raised
|
# Test exceptions raised
|
||||||
for path in ('no_dots_in_path', 'unexistent.path',
|
for path in ('no_dots_in_path', 'unexistent.path', 'utils_tests.unexistent'):
|
||||||
'utils_tests.unexistent'):
|
|
||||||
self.assertRaises(ImproperlyConfigured, import_by_path, path)
|
self.assertRaises(ImproperlyConfigured, import_by_path, path)
|
||||||
|
|
||||||
with self.assertRaises(ImproperlyConfigured) as cm:
|
with self.assertRaises(ImproperlyConfigured) as cm:
|
||||||
|
@ -132,6 +132,24 @@ class ModuleImportTestCase(unittest.TestCase):
|
||||||
self.assertIsNotNone(traceback.tb_next.tb_next,
|
self.assertIsNotNone(traceback.tb_next.tb_next,
|
||||||
'Should have more than the calling frame in the traceback.')
|
'Should have more than the calling frame in the traceback.')
|
||||||
|
|
||||||
|
def test_import_by_path_pending_deprecation_warning(self):
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
warnings.simplefilter('always', category=PendingDeprecationWarning)
|
||||||
|
cls = import_by_path('django.utils.module_loading.import_by_path')
|
||||||
|
self.assertEqual(cls, import_by_path)
|
||||||
|
self.assertEqual(len(w), 1)
|
||||||
|
self.assertTrue(issubclass(w[-1].category, PendingDeprecationWarning))
|
||||||
|
self.assertIn('deprecated', str(w[-1].message))
|
||||||
|
|
||||||
|
def test_import_string(self):
|
||||||
|
cls = import_string('django.utils.module_loading.import_string')
|
||||||
|
self.assertEqual(cls, import_string)
|
||||||
|
|
||||||
|
# Test exceptions raised
|
||||||
|
self.assertRaises(ImportError, import_string, 'no_dots_in_path')
|
||||||
|
self.assertRaises(ImportError, import_string, 'utils_tests.unexistent')
|
||||||
|
self.assertRaises(ImportError, import_string, 'unexistent.path')
|
||||||
|
|
||||||
|
|
||||||
@modify_settings(INSTALLED_APPS={'append': 'utils_tests.test_module'})
|
@modify_settings(INSTALLED_APPS={'append': 'utils_tests.test_module'})
|
||||||
class AutodiscoverModulesTestCase(SimpleTestCase):
|
class AutodiscoverModulesTestCase(SimpleTestCase):
|
||||||
|
|
|
@ -101,6 +101,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 'wsgi.wsgi.noexist' could not be loaded; Module.*"):
|
r"^WSGI application 'wsgi.wsgi.noexist' could not be loaded; Error importing.*"):
|
||||||
|
|
||||||
get_internal_wsgi_application()
|
get_internal_wsgi_application()
|
||||||
|
|
Loading…
Reference in New Issue