Commits

Ronald Oussoren committed 44357b0

No longer needed here, the official repository is up-to-date

Comments (0)

Files changed (14)

modulegraph/ez_setup/README.txt

-This directory exists so that Subversion-based projects can share a single
-copy of the ``ez_setup`` bootstrap module for ``setuptools``, and have it
-automatically updated in their projects when ``setuptools`` is updated.
-
-For your convenience, you may use the following svn:externals definition::
-
-    ez_setup svn://svn.eby-sarna.com/svnroot/ez_setup
-
-You can set this by executing this command in your project directory::
-
-    svn propedit svn:externals .
-
-And then adding the line shown above to the file that comes up for editing.
-Then, whenever you update your project, ``ez_setup`` will be updated as well.
-

modulegraph/ez_setup/__init__.py

-#!python
-"""Bootstrap setuptools installation
-
-If you want to use setuptools in your package's setup.py, just include this
-file in the same directory with it, and add this to the top of your setup.py::
-
-    from ez_setup import use_setuptools
-    use_setuptools()
-
-If you want to require a specific version of setuptools, set a download
-mirror, or use an alternate download directory, you can do so by supplying
-the appropriate options to ``use_setuptools()``.
-
-This file can also be run as a script to install or upgrade setuptools.
-"""
-import sys
-DEFAULT_VERSION = "0.6c5"
-DEFAULT_URL     = "http://cheeseshop.python.org/packages/%s/s/setuptools/" % sys.version[:3]
-
-md5_data = {
-    'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca',
-    'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb',
-    'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b',
-    'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a',
-    'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618',
-    'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac',
-    'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5',
-    'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4',
-    'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c',
-    'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b',
-    'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27',
-    'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277',
-    'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa',
-    'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e',
-    'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e',
-    'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f',
-    'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2',
-    'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc',
-    'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167',
-    'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64',
-    'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d',
-}
-
-import sys, os
-
-def _validate_md5(egg_name, data):
-    if egg_name in md5_data:
-        from md5 import md5
-        digest = md5(data).hexdigest()
-        if digest != md5_data[egg_name]:
-            print >>sys.stderr, (
-                "md5 validation of %s failed!  (Possible download problem?)"
-                % egg_name
-            )
-            sys.exit(2)
-    return data
-
-
-def use_setuptools(
-    version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
-    download_delay=15
-):
-    """Automatically find/download setuptools and make it available on sys.path
-
-    `version` should be a valid setuptools version number that is available
-    as an egg for download under the `download_base` URL (which should end with
-    a '/').  `to_dir` is the directory where setuptools will be downloaded, if
-    it is not already available.  If `download_delay` is specified, it should
-    be the number of seconds that will be paused before initiating a download,
-    should one be required.  If an older version of setuptools is installed,
-    this routine will print a message to ``sys.stderr`` and raise SystemExit in
-    an attempt to abort the calling script.
-    """
-    try:
-        import setuptools
-        if setuptools.__version__ == '0.0.1':
-            print >>sys.stderr, (
-            "You have an obsolete version of setuptools installed.  Please\n"
-            "remove it from your system entirely before rerunning this script."
-            )
-            sys.exit(2)
-    except ImportError:
-        egg = download_setuptools(version, download_base, to_dir, download_delay)
-        sys.path.insert(0, egg)
-        import setuptools; setuptools.bootstrap_install_from = egg
-
-    import pkg_resources
-    try:
-        pkg_resources.require("setuptools>="+version)
-
-    except pkg_resources.VersionConflict, e:
-        # XXX could we install in a subprocess here?
-        print >>sys.stderr, (
-            "The required version of setuptools (>=%s) is not available, and\n"
-            "can't be installed while this script is running. Please install\n"
-            " a more recent version first.\n\n(Currently using %r)"
-        ) % (version, e.args[0])
-        sys.exit(2)
-
-def download_setuptools(
-    version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
-    delay = 15
-):
-    """Download setuptools from a specified location and return its filename
-
-    `version` should be a valid setuptools version number that is available
-    as an egg for download under the `download_base` URL (which should end
-    with a '/'). `to_dir` is the directory where the egg will be downloaded.
-    `delay` is the number of seconds to pause before an actual download attempt.
-    """
-    import urllib2, shutil
-    egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3])
-    url = download_base + egg_name
-    saveto = os.path.join(to_dir, egg_name)
-    src = dst = None
-    if not os.path.exists(saveto):  # Avoid repeated downloads
-        try:
-            from distutils import log
-            if delay:
-                log.warn("""
----------------------------------------------------------------------------
-This script requires setuptools version %s to run (even to display
-help).  I will attempt to download it for you (from
-%s), but
-you may need to enable firewall access for this script first.
-I will start the download in %d seconds.
-
-(Note: if this machine does not have network access, please obtain the file
-
-   %s
-
-and place it in this directory before rerunning this script.)
----------------------------------------------------------------------------""",
-                    version, download_base, delay, url
-                ); from time import sleep; sleep(delay)
-            log.warn("Downloading %s", url)
-            src = urllib2.urlopen(url)
-            # Read/write all in one block, so we don't create a corrupt file
-            # if the download is interrupted.
-            data = _validate_md5(egg_name, src.read())
-            dst = open(saveto,"wb"); dst.write(data)
-        finally:
-            if src: src.close()
-            if dst: dst.close()
-    return os.path.realpath(saveto)
-
-def main(argv, version=DEFAULT_VERSION):
-    """Install or upgrade setuptools and EasyInstall"""
-
-    try:
-        import setuptools
-    except ImportError:
-        egg = None
-        try:
-            egg = download_setuptools(version, delay=0)
-            sys.path.insert(0,egg)
-            from setuptools.command.easy_install import main
-            return main(list(argv)+[egg])   # we're done here
-        finally:
-            if egg and os.path.exists(egg):
-                os.unlink(egg)
-    else:
-        if setuptools.__version__ == '0.0.1':
-            # tell the user to uninstall obsolete version
-            use_setuptools(version)
-
-    req = "setuptools>="+version
-    import pkg_resources
-    try:
-        pkg_resources.require(req)
-    except pkg_resources.VersionConflict:
-        try:
-            from setuptools.command.easy_install import main
-        except ImportError:
-            from easy_install import main
-        main(list(argv)+[download_setuptools(delay=0)])
-        sys.exit(0) # try to force an exit
-    else:
-        if argv:
-            from setuptools.command.easy_install import main
-            main(argv)
-        else:
-            print "Setuptools version",version,"or greater has been installed."
-            print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)'
-
-
-
-def update_md5(filenames):
-    """Update our built-in md5 registry"""
-
-    import re
-    from md5 import md5
-
-    for name in filenames:
-        base = os.path.basename(name)
-        f = open(name,'rb')
-        md5_data[base] = md5(f.read()).hexdigest()
-        f.close()
-
-    data = ["    %r: %r,\n" % it for it in md5_data.items()]
-    data.sort()
-    repl = "".join(data)
-
-    import inspect
-    srcfile = inspect.getsourcefile(sys.modules[__name__])
-    f = open(srcfile, 'rb'); src = f.read(); f.close()
-
-    match = re.search("\nmd5_data = {\n([^}]+)}", src)
-    if not match:
-        print >>sys.stderr, "Internal error!"
-        sys.exit(2)
-
-    src = src[:match.start(1)] + repl + src[match.end(1):]
-    f = open(srcfile,'w')
-    f.write(src)
-    f.close()
-
-
-if __name__=='__main__':
-    if len(sys.argv)>2 and sys.argv[1]=='--md5update':
-        update_md5(sys.argv[2:])
-    else:
-        main(sys.argv[1:])
-
-
-
-
-

modulegraph/modulegraph.egg-info/PKG-INFO

-Metadata-Version: 1.0
-Name: modulegraph
-Version: 0.7.2.dev-r439
-Summary: Python module dependency analysis tool
-Home-page: http://undefined.org/python/#modulegraph
-Author: Bob Ippolito
-Author-email: bob@redivi.com
-License: MIT License
-Description: 
-        modulegraph determines a dependency graph between Python modules primarily
-        by bytecode analysis for import statements.
-        
-        modulegraph uses similar methods to modulefinder from the standard library,
-        but uses a more flexible internal representation, has more extensive
-        knowledge of special cases, and is extensible.
-        
-Platform: any
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: MIT License
-Classifier: Programming Language :: Python
-Classifier: Topic :: Software Development :: Libraries :: Python Modules
-Classifier: Topic :: Software Development :: Build Tools

modulegraph/modulegraph.egg-info/SOURCES.txt

-setup.cfg
-setup.py
-ez_setup/README.txt
-ez_setup/__init__.py
-modulegraph/__init__.py
-modulegraph/find_modules.py
-modulegraph/modulegraph.py
-modulegraph/util.py
-modulegraph.egg-info/PKG-INFO
-modulegraph.egg-info/SOURCES.txt
-modulegraph.egg-info/dependency_links.txt
-modulegraph.egg-info/requires.txt
-modulegraph.egg-info/top_level.txt
-modulegraph.egg-info/zip-safe

modulegraph/modulegraph.egg-info/dependency_links.txt

-

modulegraph/modulegraph.egg-info/requires.txt

-altgraph>=0.6.7

modulegraph/modulegraph.egg-info/top_level.txt

-modulegraph

modulegraph/modulegraph.egg-info/zip-safe

-

modulegraph/modulegraph/__init__.py

-__version__ = '0.7.1'

modulegraph/modulegraph/find_modules.py

-"""
-High-level module dependency finding interface
-
-See find_modules(...)
-
-Originally (loosely) based on code in py2exe's build_exe.py by Thomas Heller.
-"""
-
-import sys
-import os
-import imp
-import warnings
-try:
-    set
-except NameError:
-    from sets import Set as set
-
-#from modulegraph import modulegraph
-#from modulegraph.modulegraph import Alias
-#from modulegraph.util import imp_find_module
-import modulegraph
-from modulegraph import Alias
-from util import imp_find_module, imp_walk
-
-__all__ = [
-    'find_modules', 'parse_mf_results'
-]
-
-def get_implies():
-    result = {
-        # imports done from builtin modules in C code (untrackable by modulegraph)
-        "time":         ["_strptime"],
-        "datetime":     ["time"],
-        "MacOS":        ["macresource"],
-        "cPickle":      ["copy_reg", "cStringIO"],
-        "parser":       ["copy_reg"],
-        "codecs":       ["encodings"],
-        "cStringIO":    ["copy_reg"],
-        "_sre":         ["copy", "string", "sre"],
-        "zipimport":    ["zlib"],
-        # mactoolboxglue can do a bunch more of these
-        # that are far harder to predict, these should be tracked
-        # manually for now.
-
-        # this isn't C, but it uses __import__
-        "anydbm":       ["dbhash", "gdbm", "dbm", "dumbdbm", "whichdb"],
-        # package aliases
-        "wxPython.wx":  Alias('wx'),
-    }
-
-    if sys.version_info[:2] >= (2, 5):
-        result["_elementtree"] = ["pyexpat"]
-
-        import xml.etree
-        files = os.listdir(xml.etree.__path__[0])
-        for fn in files:
-            if fn.endswith('.py') and fn != "__init__.py":
-                result["_elementtree"].append("xml.etree.%s"%(fn[:-3],))
-
-    return result
-
-def parse_mf_results(mf):
-    #for name, imports in get_hidden_imports().items():
-    #    if name in mf.modules.keys():
-    #        for mod in imports:
-    #            mf.import_hook(mod)
-
-    # Retrieve modules from modulegraph
-    py_files = []
-    extensions = []
-
-    for item in mf.flatten():
-        # There may be __main__ modules (from mf.run_script), but
-        # we don't need it in the zipfile we build.
-        if item.identifier == "__main__":
-            continue
-        src = item.filename
-        if src:
-            suffix = os.path.splitext(src)[1]
-
-            if suffix in PY_SUFFIXES:
-                py_files.append(item)
-            elif suffix in C_SUFFIXES:
-                extensions.append(item)
-            else:
-                raise TypeError("Don't know how to handle '%s'" % repr(src))
-
-    # sort on the file names, the output is nicer to read
-    py_files.sort(lambda a,b:cmp(a.filename, b.filename))
-    extensions.sort(lambda a,b:cmp(a.filename, b.filename))
-    return py_files, extensions
-
-
-def plat_prepare(includes, packages, excludes):
-    # used by Python itself
-    includes.update(["warnings", "unicodedata", "weakref"])
-
-    if not sys.platform.startswith('irix'):
-        excludes.update([
-            'AL',
-            'sgi',
-        ])
-
-    if not sys.platform in ('mac', 'darwin'):
-        # XXX - this doesn't look nearly complete
-        excludes.update([
-            'Audio_mac',
-            'Carbon.File',
-            'Carbon.Folder',
-            'Carbon.Folders',
-            'EasyDialogs',
-            'MacOS',
-            'macfs',
-            'macostools',
-            'macpath',
-        ])
-
-    if not sys.platform == 'mac':
-        excludes.update([
-            'mkcwproject',
-        ])
-
-    if not sys.platform == 'win32':
-        # only win32
-        excludes.update([
-            'ntpath',
-            'nturl2path',
-            'win32api',
-            'win32con',
-            'win32event',
-            'win32evtlogutil',
-            'win32evtlog',
-            'win32file',
-            'win32gui',
-            'win32pipe',
-            'win32process',
-            'win32security',
-            'pywintypes',
-            'winsound',
-            'win32',
-            '_winreg',
-         ])
-
-    if not sys.platform == 'riscos':
-        excludes.update([
-             'riscosenviron',
-             'riscospath',
-             'rourl2path',
-          ])
-
-    if not sys.platform == 'dos' or sys.platform.startswith('ms-dos'):
-        excludes.update([
-            'dos',
-        ])
-
-    if not sys.platform == 'os2emx':
-        excludes.update([
-            'os2emxpath'
-        ])
-
-    excludes.update(set(['posix', 'nt', 'os2', 'mac', 'ce', 'riscos']) - set(sys.builtin_module_names))
-
-    try:
-        imp_find_module('poll')
-    except ImportError:
-        excludes.update([
-            'poll',
-        ])
-
-def find_needed_modules(mf=None, scripts=(), includes=(), packages=(), warn=warnings.warn):
-    if mf is None:
-        mf = modulegraph.ModuleGraph()
-    # feed Modulefinder with everything, and return it.
-
-    for path in scripts:
-        mf.run_script(path)
-
-    for mod in includes:
-        if mod[-2:] == '.*':
-            mf.import_hook(mod[:-2], None, ['*'])
-        else:
-            mf.import_hook(mod)
-
-    for f in packages:
-        # If modulegraph has seen a reference to the package, then
-        # we prefer to believe that (imp_find_module doesn't seem to locate
-        # sub-packages)
-        m = mf.findNode(f)
-        if m is not None:
-            path = m.packagepath[0]
-        else:
-            # Find path of package
-            # TODO: use imp_find_module_or_importer
-            try:
-                path = imp_find_module(f)[1]
-            except ImportError:
-                warn("No package named %s" % f)
-                continue
-
-        # walk the path to find subdirs containing __init__.py files
-        # scan the results (directory of __init__.py files)
-        # first trim the path (of the head package),
-        # then convert directory name in package name,
-        # finally push into modulegraph.
-        for (dirpath, dirnames, filenames) in os.walk(path):
-            if '__init__.py' in filenames and dirpath.startswith(path):
-                package = f + '.' + path[len(path)+1:].replace(os.sep, '.')
-                mf.import_hook(package, None, ["*"])
-
-    return mf
-
-#
-# resource constants
-#
-PY_SUFFIXES = ['.py', '.pyw', '.pyo', '.pyc']
-C_SUFFIXES = [
-    _triple[0] for _triple in imp.get_suffixes()
-    if _triple[2] == imp.C_EXTENSION
-]
-
-#
-# side-effects
-#
-
-def _replacePackages():
-    REPLACEPACKAGES = {
-        '_xmlplus':     'xml',
-    }
-    for k,v in REPLACEPACKAGES.iteritems():
-        modulegraph.ReplacePackage(k, v)
-
-_replacePackages()
-
-def find_modules(scripts=(), includes=(), packages=(), excludes=(), path=None, debug=0):
-    """
-    High-level interface, takes iterables for:
-        scripts, includes, packages, excludes
-
-    And returns a ModuleGraph instance, python_files, and extensions
-
-    python_files is a list of pure python dependencies as modulegraph.Module objects,
-    extensions is a list of platform-specific C extension dependencies as modulegraph.Module objects
-    """
-    scripts = set(scripts)
-    includes = set(includes)
-    packages = set(packages)
-    excludes = set(excludes)
-    plat_prepare(includes, packages, excludes)
-    mf = modulegraph.ModuleGraph(
-        path=path,
-        excludes=(excludes - includes),
-        implies=get_implies(),
-        debug=debug,
-    )
-    find_needed_modules(mf, scripts, includes, packages)
-    return mf
-
-def test():
-    if '-g' in sys.argv[1:]:
-        sys.argv.remove('-g')
-        dograph = True
-    else:
-        dograph = False
-    if '-x' in sys.argv[1:]:
-        sys.argv.remove('-x')
-        doxref = True
-    else:
-        doxref= False
-
-    scripts = sys.argv[1:] or [__file__]
-    mf = find_modules(scripts=scripts)
-    if doxref:
-        mf.create_xref()
-    elif dograph:
-        mf.graphreport()
-    else:
-        mf.report()
-
-if __name__ == '__main__':
-    test()

modulegraph/modulegraph/modulegraph.py

-"""
-Find modules used by a script, using bytecode analysis.
-
-Based on the stdlib modulefinder by Thomas Heller and Just van Rossum,
-but uses a graph data structure and 2.3 features
-"""
-
-from pkg_resources import require
-require("altgraph")
-
-import pkg_resources
-import StringIO
-import dis
-import imp
-import marshal
-import os
-import sys
-import new
-import struct
-import urllib
-import zipfile
-import zipimport
-
-from altgraph.Dot import Dot
-from altgraph.ObjectGraph import ObjectGraph
-from altgraph.GraphUtil import filter_stack
-from altgraph.compat import *
-
-import util
-
-READ_MODE = "U"  # universal line endings
-
-# Modulegraph does a good job at simulating Python's, but it can not
-# handle packagepath modifications packages make at runtime.  Therefore there
-# is a mechanism whereby you can register extra paths in this map for a
-# package, and it will be honored.
-
-# Note this is a mapping is lists of paths.
-packagePathMap = {}
-
-
-def namespace_package_path(fqname, pathname, syspath=None):
-    path = []
-
-    if syspath is None:
-        working_set = pkg_resources.working_set
-    else:
-        working_set = pkg_resources.WorkingSet(syspath)
-
-    for dist in working_set:
-        assert dist in working_set
-
-        if dist.has_metadata('namespace_packages.txt'):
-            namespaces = dist.get_metadata(
-                    'namespace_packages.txt').splitlines()
-            if fqname in namespaces:
-                path.append(os.path.join(dist.location, *fqname.split('.')))
-
-    if not path:
-        return [pathname]
-    
-    else:
-        return path
-
-def os_listdir(path):
-    """
-    os.listdir with support for zipfiles
-    """
-    try:
-        return os.listdir(path)
-    except os.error:
-        info = sys.exc_info()
-
-        rest = ''
-        while not os.path.exists(path):
-            path, r = os.path.split(path)
-            rest = os.path.join(r, rest)
-
-        if not os.path.isfile(path):
-            # Directory really doesn't exist
-            raise info[0], info[1], info[2]
-        
-        try:
-            zf = zipfile.ZipFile(path)
-        except zipfile.BadZipfile:
-            raise info[0], info[1], info[2]
-
-        if rest:
-            rest = rest + '/'
-        result = set()
-        for nm in zf.namelist():
-            if nm.startswith(rest):
-                result.add(nm[len(rest):].split('/')[0])
-        return list(result)
-
-
-def _code_to_file(co):
-    """ Convert code object to a .pyc pseudo-file """
-    return StringIO.StringIO(
-            imp.get_magic() + chr(0)*4 + marshal.dumps(co))
-
-def find_module(name, path=None):
-    """
-    A version of imp.find_module that works with zipped packages.
-    """
-    if path is None:
-        path = sys.path
-
-    for entry in path:
-        importer = pkg_resources.get_importer(entry)
-        loader = importer.find_module(name)
-        if loader is None: continue
-
-        if isinstance(importer, pkg_resources.ImpWrapper):
-            filename = loader.filename
-            if filename.endswith('.pyc') or filename.endswith('.pyo'):
-                fp = open(filename, 'rb')
-                description = ('.pyc', 'rb', imp.PY_COMPILED)
-                return (fp, filename, description)
-
-            elif filename.endswith('.py'):
-                fp = file(filename, READ_MODE)
-                description = ('.py', READ_MODE, imp.PY_SOURCE)
-                return (fp, filename, description)
-
-            else:
-                for _sfx, _mode, _type in imp.get_suffixes():
-                    if _type == imp.C_EXTENSION and filename.endswith(_sfx):
-                        description = (_sfx, 'rb', imp.C_EXTENSION)
-                        break
-                else:
-                    description = ('', '', imp.PKG_DIRECTORY)
-
-                return (None, filename, description)
-
-        elif hasattr(loader, 'get_code'):
-            co = loader.get_code(name)
-            fp = _code_to_file(co)
-
-        pathname = os.path.join(entry, *name.split('.'))
-
-        if isinstance(loader, zipimport.zipimporter):
-            # Check if this happens to be a wrapper module introduced by setuptools,
-            # if it is we return the actual extension.
-            zn = '/'.join(name.split('.'))
-            for _sfx, _mode, _type in imp.get_suffixes():
-                if _type == imp.C_EXTENSION:
-                    p = loader.prefix + zn + _sfx
-                    if p in loader._files:
-                        description = (_sfx, 'rb', imp.C_EXTENSION)
-                        return (None, pathname + _sfx, description)
-
-        if hasattr(loader, 'is_package') and loader.is_package(name):
-            return (None, pathname, ('', '', imp.PKG_DIRECTORY))
-
-        pathname = pathname + '.pyc'
-        description = ('.pyc', 'rb', imp.PY_COMPILED)
-        return (fp, pathname, description)
-
-    raise ImportError(name)
-
-def moduleInfoForPath(path, suffixes=imp.get_suffixes()):
-    for (ext, readmode, typ) in imp.get_suffixes():
-        if path.endswith(ext):
-            return os.path.basename(path)[:-len(ext)], readmode, typ
-    return None
-
-# A Public interface
-def AddPackagePath(packagename, path):
-    paths = packagePathMap.get(packagename, [])
-    paths.append(path)
-    packagePathMap[packagename] = paths
-
-replacePackageMap = {}
-
-# This ReplacePackage mechanism allows modulefinder to work around the
-# way the _xmlplus package injects itself under the name "xml" into
-# sys.modules at runtime by calling ReplacePackage("_xmlplus", "xml")
-# before running ModuleGraph.
-
-def ReplacePackage(oldname, newname):
-    replacePackageMap[oldname] = newname
-
-class Node(object):
-    def __init__(self, identifier):
-        self.graphident = identifier
-        self.identifier = identifier
-        self.namespace = {}
-        self.filename = None
-        self.packagepath = None
-        self.code = None
-        # The set of global names that are assigned to in the module.
-        # This includes those names imported through starimports of
-        # Python modules.
-        self.globalnames = set()
-        # The set of starimports this module did that could not be
-        # resolved, ie. a starimport from a non-Python module.
-        self.starimports = set()
-
-    def __contains__(self, name):
-        return name in self.namespace
-
-    def __getitem__(self, name):
-        return self.namespace[name]
-
-    def __setitem__(self, name, value):
-        self.namespace[name] = value
-
-    def get(self, *args):
-        return self.namespace.get(*args)
-
-    def __cmp__(self, other):
-        return cmp(self.graphident, other.graphident)
-
-    def __hash__(self):
-        return hash(self.graphident)
-
-    def infoTuple(self):
-        return (self.identifier,)
-
-    def __repr__(self):
-        return '%s%r' % (type(self).__name__, self.infoTuple())
-
-class Alias(str):
-    pass
-
-class AliasNode(Node):
-    def __init__(self, name, node):
-        super(AliasNode, self).__init__(name)
-        for k in 'identifier', 'packagepath', 'namespace', 'globalnames', 'startimports':
-            setattr(self, k, getattr(node, k, None))
-
-    def infoTuple(self):
-        return (self.graphident, self.identifier)
-
-class BadModule(Node):
-    pass
-
-class ExcludedModule(BadModule):
-    pass
-
-class MissingModule(BadModule):
-    pass
-
-class Script(Node):
-    def __init__(self, filename):
-        super(Script, self).__init__(filename)
-        self.filename = filename
-
-    def infoTuple(self):
-        return (self.filename,)
-
-class BaseModule(Node):
-    def __init__(self, name, filename=None, path=None):
-        super(BaseModule, self).__init__(name)
-        self.filename = filename
-        self.packagepath = path
-
-    def infoTuple(self):
-        return tuple(filter(None, (self.identifier, self.filename, self.packagepath)))
-
-class BuiltinModule(BaseModule):
-    pass
-
-class SourceModule(BaseModule):
-    pass
-
-class CompiledModule(BaseModule):
-    pass
-
-class Package(BaseModule):
-    pass
-
-class FlatPackage(BaseModule):
-    pass
-
-class Extension(BaseModule):
-    pass
-
-class ArchiveModule(BaseModule):
-    pass
-
-class ModuleGraph(ObjectGraph):
-    def __init__(self, path=None, excludes=(), replace_paths=(), implies=(), graph=None, debug=0):
-        super(ModuleGraph, self).__init__(graph=graph, debug=debug)
-        if path is None:
-            path = sys.path
-        self.path = path
-        self.lazynodes = {}
-        # excludes is stronger than implies
-        self.lazynodes.update(dict(implies))
-        for m in excludes:
-            self.lazynodes[m] = None
-        self.replace_paths = replace_paths
-
-    def implyNodeReference(self, node, other):
-        """
-        Imply that one node depends on another.
-        other may be a module name or another node.
-
-        For use by extension modules and tricky import code
-        """
-        if not isinstance(other, Node):
-            if not isinstance(other, tuple):
-                other = (other, node)
-            others = self.import_hook(*other)
-            for other in others:
-                self.createReference(node, other)
-        elif isinstance(other, AliasNode):
-            self.addNode(other)
-            other.connectTo(node)
-        else:
-            self.createReference(node, other)
-
-
-    def createReference(self, fromnode, tonode, edge_data='direct'):
-        """
-        Create a reference from fromnode to tonode
-        """
-        return super(ModuleGraph, self).createReference(fromnode, tonode, edge_data=edge_data)
-
-    def findNode(self, name):
-        """
-        Find a node by identifier.  If a node by that identifier exists,
-        it will be returned.
-
-        If a lazy node exists by that identifier with no dependencies (excluded),
-        it will be instantiated and returned.
-
-        If a lazy node exists by that identifier with dependencies, it and its
-        dependencies will be instantiated and scanned for additional dependencies.
-        """
-        data = super(ModuleGraph, self).findNode(name)
-        if data is not None:
-            return data
-        if name in self.lazynodes:
-            deps = self.lazynodes.pop(name)
-            if deps is None:
-                # excluded module
-                m = self.createNode(ExcludedModule, name)
-            elif isinstance(deps, Alias):
-                other = self._safe_import_hook(deps, None, None).pop()
-                m = self.createNode(AliasNode, name, other)
-                self.implyNodeReference(m, other)
-            else:
-                m = self._safe_import_hook(name, None, None).pop()
-                for dep in deps:
-                    self.implyNodeReference(m, dep)
-            return m
-        return None
-
-    def run_script(self, pathname, caller=None):
-        """
-        Create a node by path (not module name).  It is expected to be a Python
-        source file, and will be scanned for dependencies.
-        """
-        self.msg(2, "run_script", pathname)
-        pathname = os.path.realpath(pathname)
-        m = self.findNode(pathname)
-        if m is not None:
-            return m
-
-        co = compile(file(pathname, READ_MODE).read()+'\n', pathname, 'exec')
-        if self.replace_paths:
-            co = self.replace_paths_in_code(co)
-        m = self.createNode(Script, pathname)
-        m.code = co
-        self.createReference(caller, m)
-        self.scan_code(co, m)
-        return m
-
-    def import_hook(self, name, caller=None, fromlist=None):
-        """
-        Import a module
-
-        Return the set of modules that are imported
-        """
-        self.msg(3, "import_hook", name, caller, fromlist)
-        parent = self.determine_parent(caller)
-        q, tail = self.find_head_package(parent, name)
-        m = self.load_tail(q, tail)
-        modules = set([m])
-        if fromlist and m.packagepath:
-            modules.update(self.ensure_fromlist(m, fromlist))
-        for m in modules:
-            self.createReference(caller, m)
-        return modules
-
-    def determine_parent(self, caller):
-        """
-        Determine the package containing a node
-        """
-        self.msgin(4, "determine_parent", caller)
-        parent = None
-        if caller:
-            pname = caller.identifier
-            if caller.packagepath:
-                parent = self.findNode(pname)
-            elif '.' in pname:
-                pname = pname[:pname.rfind('.')]
-                parent = self.findNode(pname)
-        self.msgout(4, "determine_parent ->", parent)
-        return parent
-
-    def find_head_package(self, parent, name):
-        """
-        Given a calling parent package and an import name determine the containing
-        package for the name
-        """
-        self.msgin(4, "find_head_package", parent, name)
-        if '.' in name:
-            head, tail = name.split('.', 1)
-        else:
-            head, tail = name, ''
-        if parent:
-            qname = parent.identifier + '.' + head
-        else:
-            qname = head
-        q = self.import_module(head, qname, parent)
-        if q:
-            self.msgout(4, "find_head_package ->", (q, tail))
-            return q, tail
-        if parent:
-            qname = head
-            parent = None
-            q = self.import_module(head, qname, parent)
-            if q:
-                self.msgout(4, "find_head_package ->", (q, tail))
-                return q, tail
-        self.msgout(4, "raise ImportError: No module named", qname)
-        raise ImportError, "No module named " + qname
-
-    def load_tail(self, q, tail):
-        self.msgin(4, "load_tail", q, tail)
-        m = q
-        while tail:
-            i = tail.find('.')
-            if i < 0: i = len(tail)
-            head, tail = tail[:i], tail[i+1:]
-            mname = "%s.%s" % (m.identifier, head)
-            m = self.import_module(head, mname, m)
-            if not m:
-                self.msgout(4, "raise ImportError: No module named", mname)
-                raise ImportError, "No module named " + mname
-        self.msgout(4, "load_tail ->", m)
-        return m
-
-    def ensure_fromlist(self, m, fromlist):
-        fromlist = set(fromlist)
-        self.msg(4, "ensure_fromlist", m, fromlist)
-        if '*' in fromlist:
-            fromlist.update(self.find_all_submodules(m))
-            fromlist.remove('*')
-        for sub in fromlist:
-            submod = m.get(sub)
-            if submod is None:
-                fullname = m.identifier + '.' + sub
-                submod = self.import_module(sub, fullname, m)
-                if submod is None:
-                    raise ImportError, "No module named " + fullname
-            yield submod
-
-    def find_all_submodules(self, m):
-        if not m.packagepath:
-            return
-        # 'suffixes' used to be a list hardcoded to [".py", ".pyc", ".pyo"].
-        # But we must also collect Python extension modules - although
-        # we cannot separate normal dlls from Python extensions.
-        suffixes = [triple[0] for triple in imp.get_suffixes()]
-        for path in m.packagepath:
-            try:
-                names = os_listdir(path)
-            except os.error:
-                self.msg(2, "can't list directory", path)
-                continue
-            for (path, mode, typ) in ifilter(None, imap(moduleInfoForPath, names)):
-                if path != '__init__':
-                    yield path
-
-    def import_module(self, partname, fqname, parent):
-        self.msgin(3, "import_module", partname, fqname, parent)
-        m = self.findNode(fqname)
-        if m is not None:
-            self.msgout(3, "import_module ->", m)
-            if parent:
-                self.createReference(m, parent)
-            return m
-        if parent and parent.packagepath is None:
-            self.msgout(3, "import_module -> None")
-            return None
-        try:
-            fp, pathname, stuff = self.find_module(partname,
-                parent and parent.packagepath, parent)
-        except ImportError:
-            self.msgout(3, "import_module ->", None)
-            return None
-
-        m = self.load_module(fqname, fp, pathname, stuff)
-        if parent:
-            self.createReference(m, parent)
-            parent[partname] = m
-        self.msgout(3, "import_module ->", m)
-        return m
-
-    def load_module(self, fqname, fp, pathname, (suffix, mode, typ)):
-        self.msgin(2, "load_module", fqname, fp and "fp", pathname)
-        if typ == imp.PKG_DIRECTORY:
-            m = self.load_package(fqname, pathname)
-            self.msgout(2, "load_module ->", m)
-            return m
-        if typ == imp.PY_SOURCE:
-            co = compile(fp.read() + '\n', pathname, 'exec')
-            cls = SourceModule
-        elif typ == imp.PY_COMPILED:
-            if fp.read(4) != imp.get_magic():
-                self.msgout(2, "raise ImportError: Bad magic number", pathname)
-                raise ImportError, "Bad magic number in %s" % pathname
-            fp.read(4)
-            co = marshal.loads(fp.read())
-            cls = CompiledModule
-        elif typ == imp.C_BUILTIN:
-            cls = BuiltinModule
-            co = None
-        else:
-            cls = Extension
-            co = None
-        m = self.createNode(cls, fqname)
-        m.filename = pathname
-        if co:
-            if self.replace_paths:
-                co = self.replace_paths_in_code(co)
-            m.code = co
-            self.scan_code(co, m)
-        self.msgout(2, "load_module ->", m)
-        return m
-
-    def _safe_import_hook(self, name, caller, fromlist):
-        # wrapper for self.import_hook() that won't raise ImportError
-        try:
-            mods = self.import_hook(name, caller)
-        except ImportError, msg:
-            self.msg(2, "ImportError:", str(msg))
-            m = self.createNode(MissingModule, name)
-            self.createReference(caller, m)
-        else:
-            assert len(mods) == 1
-            m = list(mods)[0]
-
-        subs = set([m])
-        for sub in (fromlist or ()):
-            # If this name is in the module namespace already,
-            # then add the entry to the list of substitutions
-            if sub in m:
-                sm = m[sub]
-                if sm is not None:
-                    subs.add(sm)
-                continue
-
-            # See if we can load it
-            fullname = name + '.' + sub
-            sm = self.findNode(fullname)
-            if sm is None:
-                try:
-                    sm = self.import_hook(name, caller, [sub])
-                except ImportError, msg:
-                    self.msg(2, "ImportError:", str(msg))
-                    sm = self.createNode(MissingModule, fullname)
-                else:
-                    sm = self.findNode(fullname)
-
-            m[sub] = sm
-            if sm is not None:
-                self.createReference(sm, m)
-                subs.add(sm)
-        return subs
-
-    def scan_code(self, co, m,
-            HAVE_ARGUMENT=chr(dis.HAVE_ARGUMENT),
-            LOAD_CONST=chr(dis.opname.index('LOAD_CONST')),
-            IMPORT_NAME=chr(dis.opname.index('IMPORT_NAME')),
-            STORE_NAME=chr(dis.opname.index('STORE_NAME')),
-            STORE_GLOBAL=chr(dis.opname.index('STORE_GLOBAL')),
-            unpack=struct.unpack):
-        code = co.co_code
-        constants = co.co_consts
-        n = len(code)
-        i = 0
-        fromlist = None
-        while i < n:
-            c = code[i]
-            i += 1
-            if c >= HAVE_ARGUMENT:
-                i = i+2
-            if c == LOAD_CONST:
-                # An IMPORT_NAME is always preceded by a LOAD_CONST, it's
-                # a tuple of "from" names, or None for a regular import.
-                # The tuple may contain "*" for "from <mod> import *"
-                oparg = unpack('<H', code[i - 2:i])[0]
-                fromlist = co.co_consts[oparg]
-            elif c == IMPORT_NAME:
-                assert fromlist is None or type(fromlist) is tuple
-                oparg = unpack('<H', code[i - 2:i])[0]
-                name = co.co_names[oparg]
-                have_star = False
-                if fromlist is not None:
-                    fromlist = set(fromlist)
-                    if '*' in fromlist:
-                        fromlist.remove('*')
-                        have_star = True
-                self._safe_import_hook(name, m, fromlist)
-                if have_star:
-                    # We've encountered an "import *". If it is a Python module,
-                    # the code has already been parsed and we can suck out the
-                    # global names.
-                    mm = None
-                    if m.packagepath:
-                        # At this point we don't know whether 'name' is a
-                        # submodule of 'm' or a global module. Let's just try
-                        # the full name first.
-                        mm = self.findNode(m.identifier + '.' + name)
-                    if mm is None:
-                        mm = self.findNode(name)
-                    if mm is not None:
-                        m.globalnames.update(mm.globalnames)
-                        m.starimports.update(mm.starimports)
-                        if mm.code is None:
-                            m.starimports.add(name)
-                    else:
-                        m.starimports.add(name)
-            elif c == STORE_NAME or c == STORE_GLOBAL:
-                # keep track of all global names that are assigned to
-                oparg = unpack('<H', code[i - 2:i])[0]
-                name = co.co_names[oparg]
-                m.globalnames.add(name)
-        cotype = type(co)
-        for c in constants:
-            if isinstance(c, cotype):
-                self.scan_code(c, m)
-
-    def load_package(self, fqname, pathname):
-        """
-        Called only when an imp.PACKAGE_DIRECTORY is found
-        """
-        self.msgin(2, "load_package", fqname, pathname)
-        newname = replacePackageMap.get(fqname)
-        if newname:
-            fqname = newname
-        m = self.createNode(Package, fqname)
-        m.filename = pathname
-        m.packagepath = namespace_package_path(fqname, pathname)
-
-        # As per comment at top of file, simulate runtime packagepath additions.
-        m.packagepath = m.packagepath + packagePathMap.get(fqname, [])
-
-        
-
-        fp, buf, stuff = self.find_module("__init__", m.packagepath)
-        self.load_module(fqname, fp, buf, stuff)
-        self.msgout(2, "load_package ->", m)
-        return m
-
-    def find_module(self, name, path, parent=None):
-        if parent is not None:
-            # assert path is not None
-            fullname = parent.identifier + '.' + name
-        else:
-            fullname = name
-
-        node = self.findNode(fullname)
-        if node is not None:
-            self.msgout(3, "find_module -> already included?", node)
-            raise ImportError, name
-
-        if path is None:
-            if name in sys.builtin_module_names:
-                return (None, None, ("", "", imp.C_BUILTIN))
-
-            path = self.path
-
-        fp, buf, stuff = find_module(name, path)
-        if buf:
-            buf = os.path.realpath(buf)
-        return (fp, buf, stuff)
-
-    def create_xref(self, out=None):
-        if out is None:
-            out = sys.stdout
-        scripts = []
-        mods = []
-        for mod in self.flatten():
-            name = os.path.basename(mod.identifier)
-            if isinstance(mod, Script):
-                scripts.append((name, mod))
-            else:
-                mods.append((name, mod))
-        scripts.sort()
-        mods.sort()
-        scriptnames = [name for name, m in scripts]
-        scripts.extend(mods)
-        mods = scripts
-
-        title = "modulegraph cross reference for "  + ', '.join(scriptnames)
-        print >>out, """<html><head><title>%s</title></head>
-            <body><h1>%s</h1>""" % (title, title)
-
-        def sorted_namelist(mods):
-            lst = [os.path.basename(mod.identifier) for mod in mods if mod]
-            lst.sort()
-            return lst
-        for name, m in mods:
-            if isinstance(m, BuiltinModule):
-                print >>out, """<a name="%s" /><tt>%s</tt>
-                    <i>(builtin module)</i> <br />""" % (name, name)
-            elif isinstance(m, Extension):
-                print >>out, """<a name="%s" /><tt>%s</tt> <tt>%s</tt></a>
-                    <br />""" % (name, name, m.filename)
-            else:
-                url = urllib.pathname2url(m.filename or "")
-                print >>out, """<a name="%s" />
-                    <a target="code" href="%s" type="text/plain"><tt>%s</tt></a>
-                    <br />""" % (name, url, name)
-            oute, ince = map(sorted_namelist, self.get_edges(m))
-            if oute:
-                print >>out, 'imports:'
-                for n in oute:
-                    print >>out, """<a href="#%s">%s</a>""" % (n, n)
-                print >>out, '<br />'
-            if ince:
-                print >>out, 'imported by:'
-                for n in ince:
-                    print >>out, """<a href="#%s">%s</a>""" % (n, n)
-                print >>out, '<br />'
-            print >>out, '<br/>'
-        print >>out, '</body></html>'
-        
-
-    def itergraphreport(self, name='G', flatpackages=()):
-        nodes = map(self.graph.describe_node, self.graph.iterdfs(self))
-        describe_edge = self.graph.describe_edge
-        edges = deque()
-        packagenodes = set()
-        packageidents = {}
-        nodetoident = {}
-        inpackages = {}
-        mainedges = set()
-
-        # XXX - implement
-        flatpackages = dict(flatpackages)
-
-        def nodevisitor(node, data, outgoing, incoming):
-            if not isinstance(data, Node):
-                return {'label': str(node)}
-            #if isinstance(d, (ExcludedModule, MissingModule, BadModule)):
-            #    return None
-            s = '<f0> ' + type(data).__name__
-            for i,v in izip(count(1), data.infoTuple()[:1]):
-                s += '| <f%d> %s' % (i,v)
-            return {'label':s, 'shape':'record'}
-
-        def edgevisitor(edge, data, head, tail):
-            if data == 'orphan':
-                return {'style':'dashed'}
-            elif data == 'pkgref':
-                return {'style':'dotted'}
-            return {}
-
-        yield 'digraph %s {\n' % (name,)
-        attr = dict(rankdir='LR', concentrate='true')
-        cpatt  = '%s="%s"'
-        for item in attr.iteritems():
-            yield '\t%s;\n' % (cpatt % item,)
-
-        # find all packages (subgraphs)
-        for (node, data, outgoing, incoming) in nodes:
-            nodetoident[node] = getattr(data, 'identifier', None)
-            if isinstance(data, Package):
-                packageidents[data.identifier] = node
-                inpackages[node] = set([node])
-                packagenodes.add(node)
-
-
-        # create sets for subgraph, write out descriptions
-        for (node, data, outgoing, incoming) in nodes:
-            # update edges
-            for edge in imap(describe_edge, outgoing):
-                edges.append(edge)
-
-            # describe node
-            yield '\t"%s" [%s];\n' % (
-                node,
-                ','.join([
-                    (cpatt % item) for item in
-                    nodevisitor(node, data, outgoing, incoming).iteritems()
-                ]),
-            )
-
-            inside = inpackages.get(node)
-            if inside is None:
-                inside = inpackages[node] = set()
-            ident = nodetoident[node]
-            if ident is None:
-                continue
-            pkgnode = packageidents.get(ident[:ident.rfind('.')])
-            if pkgnode is not None:
-                inside.add(pkgnode)
-
-
-        graph = []
-        subgraphs = {}
-        for key in packagenodes:
-            subgraphs[key] = []
-
-        while edges:
-            edge, data, head, tail = edges.popleft()
-            if ((head, tail)) in mainedges:
-                continue
-            mainedges.add((head, tail))
-            tailpkgs = inpackages[tail]
-            common = inpackages[head] & tailpkgs
-            if not common and tailpkgs:
-                usepkgs = sorted(tailpkgs)
-                if len(usepkgs) != 1 or usepkgs[0] != tail:
-                    edges.append((edge, data, head, usepkgs[0]))
-                    edges.append((edge, 'pkgref', usepkgs[-1], tail))
-                    continue
-            if common:
-                common = common.pop()
-                if tail == common:
-                    edges.append((edge, data, tail, head))
-                elif head == common:
-                    subgraphs[common].append((edge, 'pkgref', head, tail))
-                else:
-                    edges.append((edge, data, common, head))
-                    edges.append((edge, data, common, tail))
-
-            else:
-                graph.append((edge, data, head, tail))
-
-        def do_graph(edges, tabs):
-            edgestr = tabs + '"%s" -> "%s" [%s];\n'
-            # describe edge
-            for (edge, data, head, tail) in edges:
-                attribs = edgevisitor(edge, data, head, tail)
-                yield edgestr % (
-                    head,
-                    tail,
-                    ','.join([(cpatt % item) for item in attribs.iteritems()]),
-                )
-
-        for g, edges in subgraphs.iteritems():
-            yield '\tsubgraph "cluster_%s" {\n' % (g,)
-            yield '\t\tlabel="%s";\n' % (nodetoident[g],)
-            for s in do_graph(edges, '\t\t'):
-                yield s
-            yield '\t}\n'
-
-        for s in do_graph(graph, '\t'):
-            yield s
-
-        yield '}\n'
-
-    def graphreport(self, fileobj=None, flatpackages=()):
-        if fileobj is None:
-            fileobj = sys.stdout
-        fileobj.writelines(self.itergraphreport(flatpackages=flatpackages))
-
-    def report(self):
-        """Print a report to stdout, listing the found modules with their
-        paths, as well as modules that are missing, or seem to be missing.
-        """
-        print
-        print "%-15s %-25s %s" % ("Class", "Name", "File")
-        print "%-15s %-25s %s" % ("----", "----", "----")
-        # Print modules found
-        sorted = [(os.path.basename(mod.identifier), mod) for mod in self.flatten()]
-        sorted.sort()
-        for (name, m) in sorted:
-            print "%-15s %-25s %s" % (type(m).__name__, name, m.filename or "")
-
-    def replace_paths_in_code(self, co):
-        new_filename = original_filename = os.path.normpath(co.co_filename)
-        for f, r in self.replace_paths:
-            f = os.path.join(f, '')
-            r = os.path.join(r, '')
-            if original_filename.startswith(f):
-                new_filename = r + original_filename[len(f):]
-                break
-
-        consts = list(co.co_consts)
-        for i in range(len(consts)):
-            if isinstance(consts[i], type(co)):
-                consts[i] = self.replace_paths_in_code(consts[i])
-
-        return new.code(co.co_argcount, co.co_nlocals, co.co_stacksize,
-                         co.co_flags, co.co_code, tuple(consts), co.co_names,
-                         co.co_varnames, new_filename, co.co_name,
-                         co.co_firstlineno, co.co_lnotab,
-                         co.co_freevars, co.co_cellvars)
-
-def main():
-    # Parse command line
-    import getopt
-    try:
-        opts, args = getopt.getopt(sys.argv[1:], "dgmp:qx:")
-    except getopt.error, msg:
-        print msg
-        return
-
-    # Process options
-    debug = 1
-    domods = 0
-    dodot = False
-    addpath = []
-    excludes = []
-    for o, a in opts:
-        if o == '-d':
-            debug = debug + 1
-        if o == '-m':
-            domods = 1
-        if o == '-p':
-            addpath = addpath + a.split(os.pathsep)
-        if o == '-q':
-            debug = 0
-        if o == '-x':
-            excludes.append(a)
-        if o == '-g':
-            dodot = True
-
-    # Provide default arguments
-    if not args:
-        script = __file__
-    else:
-        script = args[0]
-
-    # Set the path based on sys.path and the script directory
-    path = sys.path[:]
-    path[0] = os.path.dirname(script)
-    path = addpath + path
-    if debug > 1:
-        print "path:"
-        for item in path:
-            print "   ", repr(item)
-
-    # Create the module finder and turn its crank
-    mf = ModuleGraph(path, excludes=excludes, debug=debug)
-    for arg in args[1:]:
-        if arg == '-m':
-            domods = 1
-            continue
-        if domods:
-            if arg[-2:] == '.*':
-                mf.import_hook(arg[:-2], None, ["*"])
-            else:
-                mf.import_hook(arg)
-        else:
-            mf.run_script(arg)
-    mf.run_script(script)
-    if dodot:
-        mf.graphreport()
-    else:
-        mf.report()
-    return mf  # for -i debugging
-
-
-if __name__ == '__main__':
-    try:
-        mf = main()
-    except KeyboardInterrupt:
-        print "\n[interrupt]"

modulegraph/modulegraph/util.py

-import os
-import imp
-import sys
-
-def imp_find_module(name, path=None):
-    """
-    same as imp.find_module, but handles dotted names
-    """
-    names = name.split('.')
-    if path is not None:
-        path = [os.path.realpath(path)]
-    for name in names:
-        result = imp.find_module(name, path)
-        path = [result[1]]
-    return result
-
-def _check_importer_for_path(name, path_item):
-    try:
-        importer = sys.path_importer_cache[path_item]
-    except KeyError:
-        for path_hook in sys.path_hooks:
-            try:
-                importer = path_hook(path_item)
-                break
-            except ImportError:
-                pass
-        else:
-            importer = None
-        sys.path_importer_cache.setdefault(path_item, importer)
-
-    if importer is None:
-        try:
-            return imp.find_module(name, [path_item])
-        except ImportError:
-            return None
-    return importer.find_module(name)
-
-def imp_walk(name):
-    """
-    yields namepart, tuple_or_importer for each path item
-
-    raise ImportError if a name can not be found.
-    """
-    if name in sys.builtin_module_names:
-        yield name, (None, None, ("", "", imp.C_BUILTIN))
-        return
-    paths = sys.path
-    res = None
-    for namepart in name.split('.'):
-        for path_item in paths:
-            res = _check_importer_for_path(namepart, path_item)
-            if hasattr(res, 'find_module'):
-                break
-        else:
-            break
-        yield namepart, res
-        paths = [os.path.join(path_item, namepart)]
-    else:
-        return
-    raise ImportError('No module named %s' % (name,))
-
-
-def test_imp_find_module():
-    import encodings.aliases
-    fn = imp_find_module('encodings.aliases')[1]
-    assert encodings.aliases.__file__.startswith(fn)
-
-def test_imp_walk():
-    import encodings.aliases
-    imps = list(imp_walk('encodings.aliases'))
-    assert len(imps) == 2
-
-    assert imps[0][0] == 'encodings'
-    assert encodings.__file__.startswith(imps[0][1][1])
-
-    assert imps[1][0] == 'aliases'
-    assert encodings.aliases.__file__.startswith(imps[1][1][1])
-        
-
-if __name__ == '__main__':
-    test_imp_find_module()
-    test_imp_walk()

modulegraph/setup.cfg

-[egg_info]
-tag_build = .dev
-tag_svn_revision = true

modulegraph/setup.py

-#!/usr/bin/env python
-
-import ez_setup
-ez_setup.use_setuptools()
-
-from setuptools import setup, Extension
-
-VERSION = '0.7.2'
-DESCRIPTION = "Python module dependency analysis tool"
-LONG_DESCRIPTION = """
-modulegraph determines a dependency graph between Python modules primarily
-by bytecode analysis for import statements.
-
-modulegraph uses similar methods to modulefinder from the standard library,
-but uses a more flexible internal representation, has more extensive 
-knowledge of special cases, and is extensible.
-"""
-
-CLASSIFIERS = filter(None, map(str.strip,
-"""                 
-Intended Audience :: Developers
-License :: OSI Approved :: MIT License
-Programming Language :: Python
-Topic :: Software Development :: Libraries :: Python Modules
-Topic :: Software Development :: Build Tools
-""".splitlines()))
-
-setup(
-    name="modulegraph",
-    version=VERSION,
-    description=DESCRIPTION,
-    long_description=LONG_DESCRIPTION,
-    classifiers=CLASSIFIERS,
-    author="Bob Ippolito",
-    author_email="bob@redivi.com",
-    url="http://undefined.org/python/#modulegraph",
-    license="MIT License",
-    packages=['modulegraph'],
-    platforms=['any'],
-    install_requires=["altgraph>=0.6.7"],
-    zip_safe=True,
-)