From 4ca7c4e34de273f0deab727d57132c9d18241b0b Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Tue, 4 May 2010 06:14:47 +0000 Subject: 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 --- django/utils/module_loading.py | 76 ++++++++++++++++++++++++++++++------------ 1 file changed, 55 insertions(+), 21 deletions(-) (limited to 'django/utils/module_loading.py') 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 - - -- cgit v1.3