⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 modulegraph.py

📁 属性sosuo算法
💻 PY
📖 第 1 页 / 共 2 页
字号:
"""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"""import disimport impimport marshalimport osimport sysimport newfrom altgraph.Dot import Dotfrom altgraph.ObjectGraph import ObjectGraphfrom altgraph.GraphUtil import filter_stackfrom altgraph.compat import *READ_MODE = "U"  # universal line endingsLOAD_CONST = dis.opmap['LOAD_CONST']IMPORT_NAME = dis.opmap['IMPORT_NAME']STORE_NAME = dis.opmap['STORE_NAME']STORE_GLOBAL = dis.opmap['STORE_GLOBAL']STORE_OPS = [STORE_NAME, STORE_GLOBAL]# 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 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 interfacedef AddPackagePath(packagename, path):    paths = packagePathMap.get(packagename, [])    paths.append(path)    packagePathMap[packagename] = pathsreplacePackageMap = {}# 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] = newnameclass 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):    passclass 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):    passclass ExcludedModule(BadModule):    passclass MissingModule(BadModule):    passclass 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):    passclass SourceModule(BaseModule):    passclass CompiledModule(BaseModule):    passclass Package(BaseModule):    passclass FlatPackage(BaseModule):    passclass Extension(BaseModule):    passclass 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'):        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        """        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():

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -