summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorRussell Keith-Magee <russell@keith-magee.com>2010-05-04 06:14:47 +0000
committerRussell Keith-Magee <russell@keith-magee.com>2010-05-04 06:14:47 +0000
commit4ca7c4e34de273f0deab727d57132c9d18241b0b (patch)
treea92caadaa2d99d610290f50b03585f0a3ec34504 /django
parent7fc25715d6af20e14827c85170fff20f82ded8ab (diff)
Fixed #13464 -- Reworked module_has_submodule to break the requirement for loader and finder to be the same class. Thanks to Alex Gaynor for the report and patch, and Brett Cannon for suggesting the approach.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@13082 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django')
-rw-r--r--django/utils/module_loading.py76
1 files changed, 55 insertions, 21 deletions
diff --git a/django/utils/module_loading.py b/django/utils/module_loading.py
index 9bcdd276fd..f251035387 100644
--- a/django/utils/module_loading.py
+++ b/django/utils/module_loading.py
@@ -1,26 +1,60 @@
-import os
import imp
+import os
+import sys
-def module_has_submodule(mod, submod_name):
- # If the module was loaded from an egg, __loader__ will be set and
- # its find_module must be used to search for submodules.
- loader = getattr(mod, '__loader__', None)
- if loader:
- mod_path = "%s.%s" % (mod.__name__.rsplit('.',1)[-1], submod_name)
- x = loader.find_module(mod_path)
- if x is None:
- # zipimport.zipimporter.find_module is documented to take
- # dotted paths but in fact through Python 2.7 is observed
- # to require os.sep in place of dots...so try using os.sep
- # if the dotted path version failed to find the requested
- # submodule.
- x = loader.find_module(mod_path.replace('.', os.sep))
- return x is not None
- try:
- imp.find_module(submod_name, mod.__path__)
+def module_has_submodule(package, module_name):
+ """See if 'module' is in 'package'."""
+ name = ".".join([package.__name__, module_name])
+ if name in sys.modules:
return True
- except ImportError:
+ for finder in sys.meta_path:
+ if finder.find_module(name):
+ return True
+ for entry in package.__path__: # No __path__, then not a package.
+ try:
+ # Try the cached finder.
+ finder = sys.path_importer_cache[entry]
+ if finder is None:
+ # Implicit import machinery should be used.
+ try:
+ file_, _, _ = imp.find_module(module_name, [entry])
+ if file_:
+ file_.close()
+ return True
+ except ImportError:
+ continue
+ # Else see if the finder knows of a loader.
+ elif finder.find_module(name):
+ return True
+ else:
+ continue
+ except KeyError:
+ # No cached finder, so try and make one.
+ for hook in sys.path_hooks:
+ try:
+ finder = hook(entry)
+ # XXX Could cache in sys.path_importer_cache
+ if finder.find_module(name):
+ return True
+ else:
+ # Once a finder is found, stop the search.
+ break
+ except ImportError:
+ # Continue the search for a finder.
+ continue
+ else:
+ # No finder found.
+ # Try the implicit import machinery if searching a directory.
+ if os.path.isdir(entry):
+ try:
+ file_, _, _ = imp.find_module(module_name, [entry])
+ if file_:
+ file_.close()
+ return True
+ except ImportError:
+ pass
+ # XXX Could insert None or NullImporter
+ else:
+ # Exhausted the search, so the module cannot be found.
return False
-
-