diff --git a/Lib/modulefinder.py b/Lib/modulefinder.py --- a/Lib/modulefinder.py +++ b/Lib/modulefinder.py @@ -1,6 +1,5 @@ """Find modules used by a script, using introspection.""" -from __future__ import generators import dis import imp import marshal @@ -9,8 +8,6 @@ import sys import types import struct -READ_MODE = "rU" - # XXX Clean up once str8's cstor matches bytes. LOAD_CONST = bytes([dis.opname.index('LOAD_CONST')]) IMPORT_NAME = bytes([dis.opname.index('IMPORT_NAME')]) @@ -29,8 +26,7 @@ packagePathMap = {} # A Public interface def AddPackagePath(packagename, path): - paths = packagePathMap.get(packagename, []) - paths.append(path) + paths = packagePathMap.setdefault(packagename, []).append(path) packagePathMap[packagename] = paths replacePackageMap = {} @@ -71,13 +67,15 @@ class Module: class ModuleFinder: - def __init__(self, path=None, debug=0, excludes=[], replace_paths=[]): + def __init__(self, path=None, debug=0, excludes=[], replace_paths=[], + recurse=True): if path is None: path = sys.path self.path = path self.modules = {} self.badmodules = {} self.debug = debug + self.recurse = recurse self.indent = 0 self.excludes = excludes self.replace_paths = replace_paths @@ -106,14 +104,14 @@ class ModuleFinder: def run_script(self, pathname): self.msg(2, "run_script", pathname) - with open(pathname, READ_MODE) as fp: + with open(pathname) as fp: stuff = ("", "r", imp.PY_SOURCE) self.load_module('__main__', fp, pathname, stuff) def load_file(self, pathname): dir, name = os.path.split(pathname) name, ext = os.path.splitext(name) - with open(pathname, READ_MODE) as fp: + with open(pathname) as fp: stuff = (ext, "r", imp.PY_SOURCE) self.load_module(name, fp, pathname, stuff) @@ -435,9 +433,10 @@ class ModuleFinder: # We don't expect anything else from the generator. raise RuntimeError(what) - for c in co.co_consts: - if isinstance(c, type(co)): - self.scan_code(c, m) + if self.recurse: + for c in co.co_consts: + if isinstance(c, type(co)): + self.scan_code(c, m) def load_package(self, fqname, pathname): self.msgin(2, "load_package", fqname, pathname) @@ -662,4 +661,4 @@ if __name__ == '__main__': try: mf = test() except KeyboardInterrupt: - print("\n[interrupt]") + print("\n[interrupted]") diff --git a/Lib/test/test_modulefinder.py b/Lib/test/test_modulefinder.py --- a/Lib/test/test_modulefinder.py +++ b/Lib/test/test_modulefinder.py @@ -1,7 +1,7 @@ -import __future__ import os +import errno +import shutil import unittest -import distutils.dir_util import tempfile from test import support @@ -9,7 +9,7 @@ from test import support import modulefinder TEST_DIR = tempfile.mkdtemp() -TEST_PATH = [TEST_DIR, os.path.dirname(__future__.__file__)] +TEST_PATH = [TEST_DIR, os.path.dirname(tempfile.__file__)] # Each test description is a list of 5 items: # @@ -196,10 +196,29 @@ a/module.py from . import bar """] +non_recursive_import_test_1 = [ + "a", + ["a", "b"], + [], + [], + """\ +a.py + import b +b.py + import c +c.py + import sys +"""] + + + def open_file(path): - ##print "#", os.path.abspath(path) dirname = os.path.dirname(path) - distutils.dir_util.mkpath(dirname) + try: + os.makedirs(dirname) + except OSError as e: + if e.errno != errno.EEXIST: + raise return open(path, "w") def create_package(source): @@ -217,11 +236,11 @@ def create_package(source): ofi.close() class ModuleFinderTest(unittest.TestCase): - def _do_test(self, info, report=False): + def _do_test(self, info, report=False, **kwargs): import_this, modules, missing, maybe_missing, source = info create_package(source) try: - mf = modulefinder.ModuleFinder(path=TEST_PATH) + mf = modulefinder.ModuleFinder(path=TEST_PATH, **kwargs) mf.import_hook(import_this) if report: mf.report() @@ -234,19 +253,17 @@ class ModuleFinderTest(unittest.TestCase ## import traceback; traceback.print_exc() ## sys.path = opath ## return - modules = set(modules) - found = set(mf.modules.keys()) - more = list(found - modules) - less = list(modules - found) + modules = sorted(set(modules)) + found = sorted(mf.modules.keys()) # check if we found what we expected, not more, not less - self.assertEqual((more, less), ([], [])) + self.assertEqual(found, modules) # check for missing and maybe missing modules bad, maybe = mf.any_missing_maybe() self.assertEqual(bad, missing) self.assertEqual(maybe, maybe_missing) finally: - distutils.dir_util.remove_tree(TEST_DIR) + shutil.rmtree(TEST_DIR) def test_package(self): self._do_test(package_test) @@ -254,25 +271,26 @@ class ModuleFinderTest(unittest.TestCase def test_maybe(self): self._do_test(maybe_test) - if getattr(__future__, "absolute_import", None): + def test_maybe_new(self): + self._do_test(maybe_test_new) - def test_maybe_new(self): - self._do_test(maybe_test_new) + def test_absolute_imports(self): + self._do_test(absolute_import_test) - def test_absolute_imports(self): - self._do_test(absolute_import_test) + def test_relative_imports(self): + self._do_test(relative_import_test) - def test_relative_imports(self): - self._do_test(relative_import_test) + def test_relative_imports_2(self): + self._do_test(relative_import_test_2) - def test_relative_imports_2(self): - self._do_test(relative_import_test_2) + def test_relative_imports_3(self): + self._do_test(relative_import_test_3) - def test_relative_imports_3(self): - self._do_test(relative_import_test_3) + def test_non_recursive_1(self): + self._do_test(non_recursive_import_test_1, recurse=False) #, debug=10) + def test_main(): - distutils.log.set_threshold(distutils.log.WARN) support.run_unittest(ModuleFinderTest) if __name__ == "__main__":