=== modified file 'Lib/pkgutil.py' --- Lib/pkgutil.py 2013-04-14 21:45:56 +0000 +++ Lib/pkgutil.py 2013-04-18 23:46:36 +0000 @@ -66,6 +66,59 @@ wrapper.register = register return wrapper +def walk_path(path=None, *, pkg=None, onerror=None): + """Walk a package hierarchy, starting with the given path + + Iterator producing (package, subpackages, submodules) triples. The first + entry is the package currently being walked, or None for the top level path. + The subpackages and submodules entries are dictionaries mapping from fully + qualified module names to the appropriate module loaders. + + Entries may be removed from the subpackages dictionary to avoid loading + those packages and recursing into them. + + If both pkg and path are None, walks sys.path + + If path is not None, walks the specified path. + + If pkg is not None, walks pkg.__path__ + + Providing both path and pkg results in ValueError + """ + if path is not None and pkg is not None: + raise ValueError("Cannot specify both path and pkg") + + if pkg is not None: + path = pkg.__path__ + if path is None: + path = sys.path + + subpkgs = {} + submods = {} + prefix = "" if pkg is None else pkg.__name__ + "." + + for importer, name, ispkg in iter_modules(path, prefix): + if ispkg: + subpkgs[name] = importer + else: + submods[name] = importer + + yield pkg, subpkgs, submods + + for name in subpkgs: + try: + __import__(name) + except ImportError: + if onerror is not None: + onerror(name) + except Exception: + if onerror is not None: + onerror(name) + else: + raise + else: + pkg = sys.modules[name] + yield from walk_path(pkg=pkg) def walk_packages(path=None, prefix='', onerror=None): """Yields (module_loader, name, ispkg) for all modules recursively