Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #8193: all dynamic imports in Django are now done correctly. I …

…know this because Brett Cannon borrowed the time machine and brought Python 2.7's '`importlib` back for inclusion in Django. Thanks for the patch-from-the-future, Brett!

git-svn-id: http://code.djangoproject.com/svn/django/trunk@10088 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit c485e236bd7e5ea40c64b2fe54d85dbb15b2fd39 1 parent ee2f04d
@jacobian jacobian authored
Showing with 128 additions and 71 deletions.
  1. +1 −0  AUTHORS
  2. +4 −2 django/conf/__init__.py
  3. +3 −2 django/contrib/admin/__init__.py
  4. +2 −1  django/contrib/admin/views/template.py
  5. +5 −4 django/contrib/admindocs/views.py
  6. +2 −1  django/contrib/auth/__init__.py
  7. +2 −1  django/contrib/comments/__init__.py
  8. +2 −1  django/contrib/sessions/middleware.py
  9. +4 −2 django/core/cache/__init__.py
  10. +2 −1  django/core/files/storage.py
  11. +2 −1  django/core/files/uploadhandler.py
  12. +2 −1  django/core/handlers/base.py
  13. +7 −9 django/core/management/__init__.py
  14. +2 −1  django/core/management/commands/flush.py
  15. +2 −1  django/core/management/commands/startapp.py
  16. +2 −1  django/core/management/commands/startproject.py
  17. +2 −1  django/core/management/commands/syncdb.py
  18. +2 −1  django/core/serializers/__init__.py
  19. +4 −2 django/core/servers/fastcgi.py
  20. +4 −3 django/core/urlresolvers.py
  21. +3 −2 django/db/__init__.py
  22. +9 −6 django/db/models/loading.py
  23. +2 −1  django/template/__init__.py
  24. +3 −2 django/template/context.py
  25. +2 −1  django/template/loader.py
  26. +2 −9 django/template/loaders/app_directories.py
  27. +2 −1  django/templatetags/__init__.py
  28. +4 −3 django/test/client.py
  29. +36 −0 django/utils/importlib.py
  30. +3 −7 django/utils/translation/trans_real.py
  31. +3 −1 django/views/debug.py
  32. +3 −2 django/views/i18n.py
View
1  AUTHORS
@@ -75,6 +75,7 @@ answer newbie questions, and generally made Django that much better:
Chris Cahoon <chris.cahoon@gmail.com>
Juan Manuel Caicedo <juan.manuel.caicedo@gmail.com>
Trevor Caira <trevor@caira.com>
+ Brett Cannon <brett@python.org>
Ricardo Javier Cárdenes Medina <ricardo.cardenes@gmail.com>
Jeremy Carbaugh <jcarbaugh@gmail.com>
carljm <carl@dirtcircle.com>
View
6 django/conf/__init__.py
@@ -12,6 +12,7 @@
from django.conf import global_settings
from django.utils.functional import LazyObject
+from django.utils import importlib
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
@@ -69,7 +70,7 @@ def __init__(self, settings_module):
self.SETTINGS_MODULE = settings_module
try:
- mod = __import__(self.SETTINGS_MODULE, {}, {}, [''])
+ mod = importlib.import_module(self.SETTINGS_MODULE)
except ImportError, e:
raise ImportError, "Could not import settings '%s' (Is it on sys.path? Does it have syntax errors?): %s" % (self.SETTINGS_MODULE, e)
@@ -89,7 +90,8 @@ def __init__(self, settings_module):
new_installed_apps = []
for app in self.INSTALLED_APPS:
if app.endswith('.*'):
- appdir = os.path.dirname(__import__(app[:-2], {}, {}, ['']).__file__)
+ app_mod = importlib.import_module(app[:-2])
+ appdir = os.path.dirname(app_mod.__file__)
app_subdirs = os.listdir(appdir)
app_subdirs.sort()
name_pattern = re.compile(r'[a-zA-Z]\w*')
View
5 django/contrib/admin/__init__.py
@@ -1,6 +1,7 @@
from django.contrib.admin.options import ModelAdmin, HORIZONTAL, VERTICAL
from django.contrib.admin.options import StackedInline, TabularInline
from django.contrib.admin.sites import AdminSite, site
+from django.utils.importlib import import_module
# A flag to tell us if autodiscover is running. autodiscover will set this to
# True while running, and False when it finishes.
@@ -36,7 +37,7 @@ def autodiscover():
# fails silently -- apps that do weird things with __path__ might
# need to roll their own admin registration.
try:
- app_path = __import__(app, {}, {}, [app.split('.')[-1]]).__path__
+ app_path = import_module(app).__path__
except AttributeError:
continue
@@ -51,6 +52,6 @@ def autodiscover():
# Step 3: import the app's admin file. If this has errors we want them
# to bubble up.
- __import__("%s.admin" % app)
+ import_module("%s.admin" % app)
# autodiscover was successful, reset loading flag.
LOADING = False
View
3  django/contrib/admin/views/template.py
@@ -4,6 +4,7 @@
from django.shortcuts import render_to_response
from django.contrib.sites.models import Site
from django.conf import settings
+from django.utils.importlib import import_module
from django.utils.translation import ugettext_lazy as _
@@ -15,7 +16,7 @@ def template_validator(request):
# get a dict of {site_id : settings_module} for the validator
settings_modules = {}
for mod in settings.ADMIN_FOR:
- settings_module = __import__(mod, {}, {}, [''])
+ settings_module = import_module(mod)
settings_modules[settings_module.SITE_ID] = settings_module
site_list = Site.objects.in_bulk(settings_modules.keys()).values()
if request.POST:
View
9 django/contrib/admindocs/views.py
@@ -9,6 +9,7 @@
from django.core import urlresolvers
from django.contrib.admindocs import utils
from django.contrib.sites.models import Site
+from django.utils.importlib import import_module
from django.utils.translation import ugettext as _
from django.utils.safestring import mark_safe
import inspect, os, re
@@ -114,13 +115,13 @@ def view_index(request):
return missing_docutils_page(request)
if settings.ADMIN_FOR:
- settings_modules = [__import__(m, {}, {}, ['']) for m in settings.ADMIN_FOR]
+ settings_modules = [import_module(m) for m in settings.ADMIN_FOR]
else:
settings_modules = [settings]
views = []
for settings_mod in settings_modules:
- urlconf = __import__(settings_mod.ROOT_URLCONF, {}, {}, [''])
+ urlconf = import_module(settings_mod.ROOT_URLCONF)
view_functions = extract_views_from_urlpatterns(urlconf.urlpatterns)
if Site._meta.installed:
site_obj = Site.objects.get(pk=settings_mod.SITE_ID)
@@ -146,7 +147,7 @@ def view_detail(request, view):
mod, func = urlresolvers.get_mod_func(view)
try:
- view_func = getattr(__import__(mod, {}, {}, ['']), func)
+ view_func = getattr(import_module(mod), func)
except (ImportError, AttributeError):
raise Http404
title, body, metadata = utils.parse_docstring(view_func.__doc__)
@@ -257,7 +258,7 @@ def model_detail(request, app_label, model_name):
def template_detail(request, template):
templates = []
for site_settings_module in settings.ADMIN_FOR:
- settings_mod = __import__(site_settings_module, {}, {}, [''])
+ settings_mod = import_module(site_settings_module)
if Site._meta.installed:
site_obj = Site.objects.get(pk=settings_mod.SITE_ID)
else:
View
3  django/contrib/auth/__init__.py
@@ -1,5 +1,6 @@
import datetime
from django.core.exceptions import ImproperlyConfigured
+from django.utils.importlib import import_module
SESSION_KEY = '_auth_user_id'
BACKEND_SESSION_KEY = '_auth_user_backend'
@@ -9,7 +10,7 @@ def load_backend(path):
i = path.rfind('.')
module, attr = path[:i], path[i+1:]
try:
- mod = __import__(module, {}, {}, [attr])
+ mod = import_module(module)
except ImportError, e:
raise ImproperlyConfigured, 'Error importing authentication backend %s: "%s"' % (module, e)
except ValueError, e:
View
3  django/contrib/comments/__init__.py
@@ -3,6 +3,7 @@
from django.core.exceptions import ImproperlyConfigured
from django.contrib.comments.models import Comment
from django.contrib.comments.forms import CommentForm
+from django.utils.importlib import import_module
DEFAULT_COMMENTS_APP = 'django.contrib.comments'
@@ -18,7 +19,7 @@ def get_comment_app():
# Try to import the package
try:
- package = __import__(comments_app, '', '', [''])
+ package = import_module(comments_app)
except ImportError:
raise ImproperlyConfigured("The COMMENTS_APP setting refers to "\
"a non-existing package.")
View
3  django/contrib/sessions/middleware.py
@@ -3,10 +3,11 @@
from django.conf import settings
from django.utils.cache import patch_vary_headers
from django.utils.http import cookie_date
+from django.utils.importlib import import_module
class SessionMiddleware(object):
def process_request(self, request):
- engine = __import__(settings.SESSION_ENGINE, {}, {}, [''])
+ engine = import_module(settings.SESSION_ENGINE)
session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME, None)
request.session = engine.SessionStore(session_key)
View
6 django/core/cache/__init__.py
@@ -19,6 +19,7 @@
from django.conf import settings
from django.core import signals
from django.core.cache.backends.base import InvalidCacheBackendError
+from django.utils import importlib
# Name for use in settings file --> name of module in "backends" directory.
# Any backend scheme that is not in this dictionary is treated as a Python
@@ -58,9 +59,10 @@ def parse_backend_uri(backend_uri):
def get_cache(backend_uri):
scheme, host, params = parse_backend_uri(backend_uri)
if scheme in BACKENDS:
- module = __import__('django.core.cache.backends.%s' % BACKENDS[scheme], {}, {}, [''])
+ name = 'django.core.cache.backends.%s' % BACKENDS[scheme]
else:
- module = __import__(scheme, {}, {}, [''])
+ name = scheme
+ module = importlib.import_module(name)
return getattr(module, 'CacheClass')(host, params)
cache = get_cache(settings.CACHE_BACKEND)
View
3  django/core/files/storage.py
@@ -8,6 +8,7 @@
from django.core.files.move import file_move_safe
from django.utils.encoding import force_unicode
from django.utils.functional import LazyObject
+from django.utils.importlib import import_module
from django.utils.text import get_valid_filename
from django.utils._os import safe_join
@@ -230,7 +231,7 @@ def get_storage_class(import_path=None):
raise ImproperlyConfigured("%s isn't a storage module." % import_path)
module, classname = import_path[:dot], import_path[dot+1:]
try:
- mod = __import__(module, {}, {}, [''])
+ mod = import_module(module)
except ImportError, e:
raise ImproperlyConfigured('Error importing storage module %s: "%s"' % (module, e))
try:
View
3  django/core/files/uploadhandler.py
@@ -10,6 +10,7 @@
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.core.files.uploadedfile import TemporaryUploadedFile, InMemoryUploadedFile
+from django.utils import importlib
__all__ = ['UploadFileException','StopUpload', 'SkipFile', 'FileUploadHandler',
'TemporaryFileUploadHandler', 'MemoryFileUploadHandler',
@@ -201,7 +202,7 @@ def load_handler(path, *args, **kwargs):
i = path.rfind('.')
module, attr = path[:i], path[i+1:]
try:
- mod = __import__(module, {}, {}, [attr])
+ mod = importlib.import_module(module)
except ImportError, e:
raise ImproperlyConfigured('Error importing upload handler module %s: "%s"' % (module, e))
except ValueError, e:
View
3  django/core/handlers/base.py
@@ -3,6 +3,7 @@
from django import http
from django.core import signals
from django.utils.encoding import force_unicode
+from django.utils.importlib import import_module
class BaseHandler(object):
# Changes that are always applied to a response (in this order).
@@ -36,7 +37,7 @@ def load_middleware(self):
raise exceptions.ImproperlyConfigured, '%s isn\'t a middleware module' % middleware_path
mw_module, mw_classname = middleware_path[:dot], middleware_path[dot+1:]
try:
- mod = __import__(mw_module, {}, {}, [''])
+ mod = import_module(mw_module)
except ImportError, e:
raise exceptions.ImproperlyConfigured, 'Error importing middleware %s: "%s"' % (mw_module, e)
try:
View
16 django/core/management/__init__.py
@@ -5,6 +5,7 @@
import django
from django.core.management.base import BaseCommand, CommandError, handle_default_options
+from django.utils.importlib import import_module
# For backwards compatibility: get_version() used to be in this module.
get_version = django.get_version
@@ -63,8 +64,8 @@ def load_command_class(app_name, name):
class instance. All errors raised by the import process
(ImportError, AttributeError) are allowed to propagate.
"""
- return getattr(__import__('%s.management.commands.%s' % (app_name, name),
- {}, {}, ['Command']), 'Command')()
+ module = import_module('%s.management.commands.%s' % (app_name, name))
+ return module.Command()
def get_commands():
"""
@@ -104,12 +105,9 @@ def get_commands():
# Find the project directory
try:
from django.conf import settings
- project_directory = setup_environ(
- __import__(
- settings.SETTINGS_MODULE, {}, {},
- (settings.SETTINGS_MODULE.split(".")[-1],)
- ), settings.SETTINGS_MODULE
- )
+ module = import_module(settings.SETTINGS_MODULE.split('.', 1)[0])
+ project_directory = setup_environ(module,
+ settings.SETTINGS_MODULE)
except (AttributeError, EnvironmentError, ImportError):
project_directory = None
@@ -328,7 +326,7 @@ def setup_environ(settings_mod, original_settings_path=None):
# Import the project module. We add the parent directory to PYTHONPATH to
# avoid some of the path errors new users can have.
sys.path.append(os.path.join(project_directory, os.pardir))
- project_module = __import__(project_name, {}, {}, [''])
+ project_module = import_module(project_name)
sys.path.pop()
return project_directory
View
3  django/core/management/commands/flush.py
@@ -1,5 +1,6 @@
from django.core.management.base import NoArgsCommand, CommandError
from django.core.management.color import no_style
+from django.utils.importlib import import_module
from optparse import make_option
class Command(NoArgsCommand):
@@ -23,7 +24,7 @@ def handle_noargs(self, **options):
# dispatcher events.
for app_name in settings.INSTALLED_APPS:
try:
- __import__(app_name + '.management', {}, {}, [''])
+ import_module('.management', app_name)
except ImportError:
pass
View
3  django/core/management/commands/startapp.py
@@ -1,6 +1,7 @@
import os
from django.core.management.base import copy_helper, CommandError, LabelCommand
+from django.utils.importlib import import_module
class Command(LabelCommand):
help = "Creates a Django app directory structure for the given app name in the current directory."
@@ -26,7 +27,7 @@ def handle_label(self, app_name, directory=None, **options):
# Check that the app_name cannot be imported.
try:
- __import__(app_name)
+ import_module(app_name)
except ImportError:
pass
else:
View
3  django/core/management/commands/startproject.py
@@ -1,4 +1,5 @@
from django.core.management.base import copy_helper, CommandError, LabelCommand
+from django.utils.importlib import import_module
import os
import re
from random import choice
@@ -20,7 +21,7 @@ def handle_label(self, project_name, **options):
# Check that the project_name cannot be imported.
try:
- __import__(project_name)
+ import_module(project_name)
except ImportError:
pass
else:
View
3  django/core/management/commands/syncdb.py
@@ -1,5 +1,6 @@
from django.core.management.base import NoArgsCommand
from django.core.management.color import no_style
+from django.utils.importlib import import_module
from optparse import make_option
import sys
@@ -30,7 +31,7 @@ def handle_noargs(self, **options):
# dispatcher events.
for app_name in settings.INSTALLED_APPS:
try:
- __import__(app_name + '.management', {}, {}, [''])
+ import_module('.management', app_name)
except ImportError, exc:
# This is slightly hackish. We want to ignore ImportErrors
# if the "management" module itself is missing -- but we don't
View
3  django/core/serializers/__init__.py
@@ -17,6 +17,7 @@
"""
from django.conf import settings
+from django.utils import importlib
# Built-in serializers
BUILTIN_SERIALIZERS = {
@@ -47,7 +48,7 @@ def register_serializer(format, serializer_module, serializers=None):
directly into the global register of serializers. Adding serializers
directly is not a thread-safe operation.
"""
- module = __import__(serializer_module, {}, {}, [''])
+ module = importlib.import_module(serializer_module)
if serializers is None:
_serializers[format] = module
else:
View
6 django/core/servers/fastcgi.py
@@ -12,6 +12,7 @@
pass to this server.
"""
+from django.utils import importlib
import sys, os
__version__ = "0.1"
@@ -113,7 +114,7 @@ def runfastcgi(argset=[], **kwargs):
'maxSpare': int(options["maxspare"]),
'minSpare': int(options["minspare"]),
'maxChildren': int(options["maxchildren"]),
- 'maxRequests': int(options["maxrequests"]),
+ 'maxRequests': int(options["maxrequests"]),
}
flup_module += '_fork'
elif options['method'] in ('thread', 'threaded'):
@@ -128,7 +129,8 @@ def runfastcgi(argset=[], **kwargs):
wsgi_opts['debug'] = False # Turn off flup tracebacks
try:
- WSGIServer = getattr(__import__('flup.' + flup_module, '', '', flup_module), 'WSGIServer')
+ module = importlib_import_module('.%s' % flup_module, 'flup')
+ WSGIServer = module.WSGIServer
except:
print "Can't import flup." + flup_module
return False
View
7 django/core/urlresolvers.py
@@ -14,6 +14,7 @@
from django.utils.datastructures import MultiValueDict
from django.utils.encoding import iri_to_uri, force_unicode, smart_str
from django.utils.functional import memoize
+from django.utils.importlib import import_module
from django.utils.regex_helper import normalize
from django.utils.thread_support import currentThread
@@ -54,7 +55,7 @@ def get_callable(lookup_view, can_fail=False):
lookup_view = lookup_view.encode('ascii')
mod_name, func_name = get_mod_func(lookup_view)
if func_name != '':
- lookup_view = getattr(__import__(mod_name, {}, {}, ['']), func_name)
+ lookup_view = getattr(import_module(mod_name), func_name)
if not callable(lookup_view):
raise AttributeError("'%s.%s' is not a callable." % (mod_name, func_name))
except (ImportError, AttributeError):
@@ -199,7 +200,7 @@ def _get_urlconf_module(self):
try:
return self._urlconf_module
except AttributeError:
- self._urlconf_module = __import__(self.urlconf_name, {}, {}, [''])
+ self._urlconf_module = import_module(self.urlconf_name)
return self._urlconf_module
urlconf_module = property(_get_urlconf_module)
@@ -217,7 +218,7 @@ def _resolve_special(self, view_type):
callback = getattr(self.urlconf_module, 'handler%s' % view_type)
mod_name, func_name = get_mod_func(callback)
try:
- return getattr(__import__(mod_name, {}, {}, ['']), func_name), {}
+ return getattr(import_module(mod_name), func_name), {}
except (ImportError, AttributeError), e:
raise ViewDoesNotExist, "Tried %s. Error was: %s" % (callback, str(e))
View
5 django/db/__init__.py
@@ -3,6 +3,7 @@
from django.core import signals
from django.core.exceptions import ImproperlyConfigured
from django.utils.functional import curry
+from django.utils.importlib import import_module
__all__ = ('backend', 'connection', 'DatabaseError', 'IntegrityError')
@@ -13,12 +14,12 @@ def load_backend(backend_name):
try:
# Most of the time, the database backend will be one of the official
# backends that ships with Django, so look there first.
- return __import__('django.db.backends.%s.base' % backend_name, {}, {}, [''])
+ return import_module('.base', 'django.db.backends.%s' % settings.DATABASE_ENGINE)
except ImportError, e:
# If the import failed, we might be looking for a database backend
# distributed external to Django. So we'll try that next.
try:
- return __import__('%s.base' % backend_name, {}, {}, [''])
+ return import_module('.base', backend_name)
except ImportError, e_user:
# The database backend wasn't found. Display a helpful error message
# listing all possible (built-in) database backends.
View
15 django/db/models/loading.py
@@ -3,6 +3,7 @@
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.utils.datastructures import SortedDict
+from django.utils.importlib import import_module
import sys
import os
@@ -69,9 +70,10 @@ def load_app(self, app_name, can_postpone=False):
"""
self.handled[app_name] = None
self.nesting_level += 1
- mod = __import__(app_name, {}, {}, ['models'])
- self.nesting_level -= 1
- if not hasattr(mod, 'models'):
+ try:
+ models = import_module('.models', app_name)
+ except ImportError:
+ self.nesting_level -= 1
if can_postpone:
# Either the app has no models, or the package is still being
# imported by Python and the model module isn't available yet.
@@ -79,9 +81,10 @@ def load_app(self, app_name, can_postpone=False):
# populate).
self.postponed.append(app_name)
return None
- if mod.models not in self.app_store:
- self.app_store[mod.models] = len(self.app_store)
- return mod.models
+ self.nesting_level -= 1
+ if models not in self.app_store:
+ self.app_store[models] = len(self.app_store)
+ return models
def app_cache_ready(self):
"""
View
3  django/template/__init__.py
@@ -52,6 +52,7 @@
from inspect import getargspec
from django.conf import settings
from django.template.context import Context, RequestContext, ContextPopException
+from django.utils.importlib import import_module
from django.utils.itercompat import is_iterable
from django.utils.functional import curry, Promise
from django.utils.text import smart_split
@@ -935,7 +936,7 @@ def get_library(module_name):
lib = libraries.get(module_name, None)
if not lib:
try:
- mod = __import__(module_name, {}, {}, [''])
+ mod = import_module(module_name)
except ImportError, e:
raise InvalidTemplateLibrary("Could not load template library from %s, %s" % (module_name, e))
try:
View
5 django/template/context.py
@@ -1,5 +1,6 @@
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
+from django.utils.importlib import import_module
_standard_context_processors = None
@@ -62,7 +63,7 @@ def get(self, key, otherwise=None):
def update(self, other_dict):
"Like dict.update(). Pushes an entire dictionary's keys and values onto the context."
- if not hasattr(other_dict, '__getitem__'):
+ if not hasattr(other_dict, '__getitem__'):
raise TypeError('other_dict must be a mapping (dictionary-like) object.')
self.dicts = [other_dict] + self.dicts
return other_dict
@@ -77,7 +78,7 @@ def get_standard_processors():
i = path.rfind('.')
module, attr = path[:i], path[i+1:]
try:
- mod = __import__(module, {}, {}, [attr])
+ mod = import_module(module)
except ImportError, e:
raise ImproperlyConfigured('Error importing request processor module %s: "%s"' % (module, e))
try:
View
3  django/template/loader.py
@@ -22,6 +22,7 @@
from django.core.exceptions import ImproperlyConfigured
from django.template import Origin, Template, Context, TemplateDoesNotExist, add_to_builtins
+from django.utils.importlib import import_module
from django.conf import settings
template_source_loaders = None
@@ -51,7 +52,7 @@ def find_template_source(name, dirs=None):
i = path.rfind('.')
module, attr = path[:i], path[i+1:]
try:
- mod = __import__(module, globals(), locals(), [attr])
+ mod = import_module(module)
except ImportError, e:
raise ImproperlyConfigured, 'Error importing template source loader %s: "%s"' % (module, e)
try:
View
11 django/template/loaders/app_directories.py
@@ -10,21 +10,14 @@
from django.core.exceptions import ImproperlyConfigured
from django.template import TemplateDoesNotExist
from django.utils._os import safe_join
+from django.utils.importlib import import_module
# At compile time, cache the directories to search.
fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
app_template_dirs = []
for app in settings.INSTALLED_APPS:
- i = app.rfind('.')
- if i == -1:
- m, a = app, None
- else:
- m, a = app[:i], app[i+1:]
try:
- if a is None:
- mod = __import__(m, {}, {}, [])
- else:
- mod = getattr(__import__(m, {}, {}, [a]), a)
+ mod = import_module(app)
except ImportError, e:
raise ImproperlyConfigured, 'ImportError %s: %s' % (app, e.args[0])
template_dir = os.path.join(os.path.dirname(mod.__file__), 'templates')
View
3  django/templatetags/__init__.py
@@ -1,7 +1,8 @@
from django.conf import settings
+from django.utils import importlib
for a in settings.INSTALLED_APPS:
try:
- __path__.extend(__import__(a + '.templatetags', {}, {}, ['']).__path__)
+ __path__.extend(importlib.import_module('.templatetags', a).__path__)
except ImportError:
pass
View
7 django/test/client.py
@@ -18,6 +18,7 @@
from django.utils.functional import curry
from django.utils.encoding import smart_str
from django.utils.http import urlencode
+from django.utils.importlib import import_module
from django.utils.itercompat import is_iterable
from django.db import transaction, close_connection
from django.test.utils import ContextList
@@ -176,7 +177,7 @@ def _session(self):
Obtains the current session variables.
"""
if 'django.contrib.sessions' in settings.INSTALLED_APPS:
- engine = __import__(settings.SESSION_ENGINE, {}, {}, [''])
+ engine = import_module(settings.SESSION_ENGINE)
cookie = self.cookies.get(settings.SESSION_COOKIE_NAME, None)
if cookie:
return engine.SessionStore(cookie.value)
@@ -399,7 +400,7 @@ def login(self, **credentials):
user = authenticate(**credentials)
if user and user.is_active \
and 'django.contrib.sessions' in settings.INSTALLED_APPS:
- engine = __import__(settings.SESSION_ENGINE, {}, {}, [''])
+ engine = import_module(settings.SESSION_ENGINE)
# Create a fake request to store login details.
request = HttpRequest()
@@ -434,7 +435,7 @@ def logout(self):
Causes the authenticated user to be logged out.
"""
- session = __import__(settings.SESSION_ENGINE, {}, {}, ['']).SessionStore()
+ session = import_module(settings.SESSION_ENGINE).SessionStore()
session.delete(session_key=self.cookies[settings.SESSION_COOKIE_NAME].value)
self.cookies = SimpleCookie()
View
36 django/utils/importlib.py
@@ -0,0 +1,36 @@
+# Taken from Python 2.7 with permission from/by the original author.
+import sys
+
+def _resolve_name(name, package, level):
+ """Return the absolute name of the module to be imported."""
+ if not hasattr(package, 'rindex'):
+ raise ValueError("'package' not set to a string")
+ dot = len(package)
+ for x in xrange(level, 1, -1):
+ try:
+ dot = package.rindex('.', 0, dot)
+ except ValueError:
+ raise ValueError("attempted relative import beyond top-level "
+ "package")
+ return "%s.%s" % (package[:dot], name)
+
+
+def import_module(name, package=None):
+ """Import a module.
+
+ The 'package' argument is required when performing a relative import. It
+ specifies the package to use as the anchor point from which to resolve the
+ relative import to an absolute import.
+
+ """
+ if name.startswith('.'):
+ if not package:
+ raise TypeError("relative imports require the 'package' argument")
+ level = 0
+ for character in name:
+ if character != '.':
+ break
+ level += 1
+ name = _resolve_name(name[level:], package, level)
+ __import__(name)
+ return sys.modules[name]
View
10 django/utils/translation/trans_real.py
@@ -7,6 +7,7 @@
import gettext as gettext_module
from cStringIO import StringIO
+from django.utils.importlib import import_module
from django.utils.safestring import mark_safe, SafeData
from django.utils.thread_support import currentThread
@@ -125,7 +126,7 @@ def translation(language):
if settings.SETTINGS_MODULE is not None:
parts = settings.SETTINGS_MODULE.split('.')
- project = __import__(parts[0], {}, {}, [])
+ project = import_module(parts[0])
projectpath = os.path.join(os.path.dirname(project.__file__), 'locale')
else:
projectpath = None
@@ -176,12 +177,7 @@ def _merge(path):
res = _merge(projectpath)
for appname in settings.INSTALLED_APPS:
- p = appname.rfind('.')
- if p >= 0:
- app = getattr(__import__(appname[:p], {}, {}, [appname[p+1:]]), appname[p+1:])
- else:
- app = __import__(appname, {}, {}, [])
-
+ app = import_module(appname)
apppath = os.path.join(os.path.dirname(app.__file__), 'locale')
if os.path.isdir(apppath):
View
4 django/views/debug.py
@@ -6,6 +6,7 @@
from django.conf import settings
from django.template import Template, Context, TemplateDoesNotExist
from django.utils.html import escape
+from django.utils.importlib import import_module
from django.http import HttpResponse, HttpResponseServerError, HttpResponseNotFound
from django.utils.encoding import smart_unicode, smart_str
@@ -67,7 +68,8 @@ def get_traceback_html(self):
self.loader_debug_info = []
for loader in template_source_loaders:
try:
- source_list_func = getattr(__import__(loader.__module__, {}, {}, ['get_template_sources']), 'get_template_sources')
+ module = import_module(loader.__module__)
+ source_list_func = module.get_template_sources
# NOTE: This assumes exc_value is the name of the template that
# the loader attempted to load.
template_list = [{'name': t, 'exists': os.path.exists(t)} \
View
5 django/views/i18n.py
@@ -1,7 +1,8 @@
from django import http
+from django.conf import settings
+from django.utils import importlib
from django.utils.translation import check_for_language, activate, to_locale, get_language
from django.utils.text import javascript_quote
-from django.conf import settings
import os
import gettext as gettext_module
@@ -128,7 +129,7 @@ def javascript_catalog(request, domain='djangojs', packages=None):
paths = []
# first load all english languages files for defaults
for package in packages:
- p = __import__(package, {}, {}, [''])
+ p = importlib.import_module(package)
path = os.path.join(os.path.dirname(p.__file__), 'locale')
paths.append(path)
try:
Please sign in to comment.
Something went wrong with that request. Please try again.