同步操作将从 OpenHarmony-SIG/python 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
"""Find modules used by a script, using introspection."""import disimport importlib._bootstrap_externalimport importlib.machineryimport marshalimport osimport ioimport sysimport typesimport warningsLOAD_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_GLOBALEXTENDED_ARG = dis.EXTENDED_ARG# Old imp constants:_SEARCH_ERROR = 0_PY_SOURCE = 1_PY_COMPILED = 2_C_EXTENSION = 3_PKG_DIRECTORY = 5_C_BUILTIN = 6_PY_FROZEN = 7# Modulefinder does a good job at simulating Python's, but it can not# handle __path__ 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 = {}# A Public interfacedef AddPackagePath(packagename, path):packagePathMap.setdefault(packagename, []).append(path)replacePackageMap = {}# This ReplacePackage mechanism allows modulefinder to work around# situations in which a package injects itself under the name# of another package into sys.modules at runtime by calling# ReplacePackage("real_package_name", "faked_package_name")# before running ModuleFinder.def ReplacePackage(oldname, newname):replacePackageMap[oldname] = newnamedef _find_module(name, path=None):"""An importlib reimplementation of imp.find_module (for our purposes)."""# It's necessary to clear the caches for our Finder first, in case any# modules are being added/deleted/modified at runtime. In particular,# test_modulefinder.py changes file tree contents in a cache-breaking way:importlib.machinery.PathFinder.invalidate_caches()spec = importlib.machinery.PathFinder.find_spec(name, path)if spec is None:raise ImportError("No module named {name!r}".format(name=name), name=name)# Some special cases:if spec.loader is importlib.machinery.BuiltinImporter:return None, None, ("", "", _C_BUILTIN)if spec.loader is importlib.machinery.FrozenImporter:return None, None, ("", "", _PY_FROZEN)file_path = spec.originif spec.loader.is_package(name):return None, os.path.dirname(file_path), ("", "", _PKG_DIRECTORY)if isinstance(spec.loader, importlib.machinery.SourceFileLoader):kind = _PY_SOURCEelif isinstance(spec.loader, importlib.machinery.ExtensionFileLoader):kind = _C_EXTENSIONelif isinstance(spec.loader, importlib.machinery.SourcelessFileLoader):kind = _PY_COMPILEDelse: # Should never happen.return None, None, ("", "", _SEARCH_ERROR)file = io.open_code(file_path)suffix = os.path.splitext(file_path)[-1]return file, file_path, (suffix, "rb", kind)class Module:def __init__(self, name, file=None, path=None):self.__name__ = nameself.__file__ = fileself.__path__ = pathself.__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 = {}# The set of starimports this module did that could not be# resolved, ie. a starimport from a non-Python module.self.starimports = {}def __repr__(self):s = "Module(%r" % (self.__name__,)if self.__file__ is not None:s = s + ", %r" % (self.__file__,)if self.__path__ is not None:s = s + ", %r" % (self.__path__,)s = s + ")"return sclass ModuleFinder:def __init__(self, path=None, debug=0, excludes=None, replace_paths=None):if path is None:path = sys.pathself.path = pathself.modules = {}self.badmodules = {}self.debug = debugself.indent = 0self.excludes = excludes if excludes is not None else []self.replace_paths = replace_paths if replace_paths is not None else []self.processed_paths = [] # Used in debugging onlydef msg(self, level, str, *args):if level <= self.debug:for i in range(self.indent):print(" ", end=' ')print(str, end=' ')for arg in args:print(repr(arg), end=' ')print()def msgin(self, *args):level = args[0]if level <= self.debug:self.indent = self.indent + 1self.msg(*args)def msgout(self, *args):level = args[0]if level <= self.debug:self.indent = self.indent - 1self.msg(*args)def run_script(self, pathname):self.msg(2, "run_script", pathname)with io.open_code(pathname) as fp:stuff = ("", "rb", _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 io.open_code(pathname) as fp:stuff = (ext, "rb", _PY_SOURCE)self.load_module(name, fp, pathname, stuff)def import_hook(self, name, caller=None, fromlist=None, level=-1):self.msg(3, "import_hook", name, caller, fromlist, level)parent = self.determine_parent(caller, level=level)q, tail = self.find_head_package(parent, name)m = self.load_tail(q, tail)if not fromlist:return qif m.__path__:self.ensure_fromlist(m, fromlist)return Nonedef determine_parent(self, caller, level=-1):self.msgin(4, "determine_parent", caller, level)if not caller or level == 0:self.msgout(4, "determine_parent -> None")return Nonepname = caller.__name__if level >= 1: # relative importif caller.__path__:level -= 1if level == 0:parent = self.modules[pname]assert parent is callerself.msgout(4, "determine_parent ->", parent)return parentif pname.count(".") < level:raise ImportError("relative importpath too deep")pname = ".".join(pname.split(".")[:-level])parent = self.modules[pname]self.msgout(4, "determine_parent ->", parent)return parentif caller.__path__:parent = self.modules[pname]assert caller is parentself.msgout(4, "determine_parent ->", parent)return parentif '.' in pname:i = pname.rfind('.')pname = pname[:i]parent = self.modules[pname]assert parent.__name__ == pnameself.msgout(4, "determine_parent ->", parent)return parentself.msgout(4, "determine_parent -> None")return Nonedef find_head_package(self, parent, name):self.msgin(4, "find_head_package", parent, name)if '.' in name:i = name.find('.')head = name[:i]tail = name[i+1:]else:head = nametail = ""if parent:qname = "%s.%s" % (parent.__name__, head)else:qname = headq = self.import_module(head, qname, parent)if q:self.msgout(4, "find_head_package ->", (q, tail))return q, tailif parent:qname = headparent = Noneq = self.import_module(head, qname, parent)if q:self.msgout(4, "find_head_package ->", (q, tail))return q, tailself.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 = qwhile tail:i = tail.find('.')if i < 0: i = len(tail)head, tail = tail[:i], tail[i+1:]mname = "%s.%s" % (m.__name__, 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 mdef ensure_fromlist(self, m, fromlist, recursive=0):self.msg(4, "ensure_fromlist", m, fromlist, recursive)for sub in fromlist:if sub == "*":if not recursive:all = self.find_all_submodules(m)if all:self.ensure_fromlist(m, all, 1)elif not hasattr(m, sub):subname = "%s.%s" % (m.__name__, sub)submod = self.import_module(sub, subname, m)if not submod:raise ImportError("No module named " + subname)def find_all_submodules(self, m):if not m.__path__:returnmodules = {}# 'suffixes' used to be a list hardcoded to [".py", ".pyc"].# But we must also collect Python extension modules - although# we cannot separate normal dlls from Python extensions.suffixes = []suffixes += importlib.machinery.EXTENSION_SUFFIXES[:]suffixes += importlib.machinery.SOURCE_SUFFIXES[:]suffixes += importlib.machinery.BYTECODE_SUFFIXES[:]for dir in m.__path__:try:names = os.listdir(dir)except OSError:self.msg(2, "can't list directory", dir)continuefor name in names:mod = Nonefor suff in suffixes:n = len(suff)if name[-n:] == suff:mod = name[:-n]breakif mod and mod != "__init__":modules[mod] = modreturn modules.keys()def import_module(self, partname, fqname, parent):self.msgin(3, "import_module", partname, fqname, parent)try:m = self.modules[fqname]except KeyError:passelse:self.msgout(3, "import_module ->", m)return mif fqname in self.badmodules:self.msgout(3, "import_module -> None")return Noneif parent and parent.__path__ is None:self.msgout(3, "import_module -> None")return Nonetry:fp, pathname, stuff = self.find_module(partname,parent and parent.__path__, parent)except ImportError:self.msgout(3, "import_module ->", None)return Nonetry:m = self.load_module(fqname, fp, pathname, stuff)finally:if fp:fp.close()if parent:setattr(parent, partname, m)self.msgout(3, "import_module ->", m)return mdef load_module(self, fqname, fp, pathname, file_info):suffix, mode, type = file_infoself.msgin(2, "load_module", fqname, fp and "fp", pathname)if type == _PKG_DIRECTORY:m = self.load_package(fqname, pathname)self.msgout(2, "load_module ->", m)return mif type == _PY_SOURCE:co = compile(fp.read(), pathname, 'exec')elif type == _PY_COMPILED:try:data = fp.read()importlib._bootstrap_external._classify_pyc(data, fqname, {})except ImportError as exc:self.msgout(2, "raise ImportError: " + str(exc), pathname)raiseco = marshal.loads(memoryview(data)[16:])else:co = Nonem = self.add_module(fqname)m.__file__ = pathnameif co:if self.replace_paths:co = self.replace_paths_in_code(co)m.__code__ = coself.scan_code(co, m)self.msgout(2, "load_module ->", m)return mdef _add_badmodule(self, name, caller):if name not in self.badmodules:self.badmodules[name] = {}if caller:self.badmodules[name][caller.__name__] = 1else:self.badmodules[name]["-"] = 1def _safe_import_hook(self, name, caller, fromlist, level=-1):# wrapper for self.import_hook() that won't raise ImportErrorif name in self.badmodules:self._add_badmodule(name, caller)returntry:self.import_hook(name, caller, level=level)except ImportError as msg:self.msg(2, "ImportError:", str(msg))self._add_badmodule(name, caller)except SyntaxError as msg:self.msg(2, "SyntaxError:", str(msg))self._add_badmodule(name, caller)else:if fromlist:for sub in fromlist:fullname = name + "." + subif fullname in self.badmodules:self._add_badmodule(fullname, caller)continuetry:self.import_hook(name, caller, [sub], level=level)except ImportError as msg:self.msg(2, "ImportError:", str(msg))self._add_badmodule(fullname, caller)def scan_opcodes(self, co):# Scan the code, and yield 'interesting' opcode combinationscode = co.co_codenames = co.co_namesconsts = co.co_constsopargs = [(op, arg) for _, op, arg in dis._unpack_opargs(code)if op != EXTENDED_ARG]for i, (op, oparg) in enumerate(opargs):if op in STORE_OPS:yield "store", (names[oparg],)continueif (op == IMPORT_NAME and i >= 2and opargs[i-1][0] == opargs[i-2][0] == LOAD_CONST):level = consts[opargs[i-2][1]]fromlist = consts[opargs[i-1][1]]if level == 0: # absolute importyield "absolute_import", (fromlist, names[oparg])else: # relative importyield "relative_import", (level, fromlist, names[oparg])continuedef scan_code(self, co, m):code = co.co_codescanner = self.scan_opcodesfor what, args in scanner(co):if what == "store":name, = argsm.globalnames[name] = 1elif what == "absolute_import":fromlist, name = argshave_star = 0if fromlist is not None:if "*" in fromlist:have_star = 1fromlist = [f for f in fromlist if f != "*"]self._safe_import_hook(name, m, fromlist, level=0)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 = Noneif m.__path__:# 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.modules.get(m.__name__ + "." + name)if mm is None:mm = self.modules.get(name)if mm is not None:m.globalnames.update(mm.globalnames)m.starimports.update(mm.starimports)if mm.__code__ is None:m.starimports[name] = 1else:m.starimports[name] = 1elif what == "relative_import":level, fromlist, name = argsif name:self._safe_import_hook(name, m, fromlist, level=level)else:parent = self.determine_parent(m, level=level)self._safe_import_hook(parent.__name__, None, fromlist, level=0)else:# 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)def load_package(self, fqname, pathname):self.msgin(2, "load_package", fqname, pathname)newname = replacePackageMap.get(fqname)if newname:fqname = newnamem = self.add_module(fqname)m.__file__ = pathnamem.__path__ = [pathname]# As per comment at top of file, simulate runtime __path__ additions.m.__path__ = m.__path__ + packagePathMap.get(fqname, [])fp, buf, stuff = self.find_module("__init__", m.__path__)try:self.load_module(fqname, fp, buf, stuff)self.msgout(2, "load_package ->", m)return mfinally:if fp:fp.close()def add_module(self, fqname):if fqname in self.modules:return self.modules[fqname]self.modules[fqname] = m = Module(fqname)return mdef find_module(self, name, path, parent=None):if parent is not None:# assert path is not Nonefullname = parent.__name__+'.'+nameelse:fullname = nameif fullname in self.excludes:self.msgout(3, "find_module -> Excluded", fullname)raise ImportError(name)if path is None:if name in sys.builtin_module_names:return (None, None, ("", "", _C_BUILTIN))path = self.pathreturn _find_module(name, path)def report(self):"""Print a report to stdout, listing the found modules with theirpaths, as well as modules that are missing, or seem to be missing."""print()print(" %-25s %s" % ("Name", "File"))print(" %-25s %s" % ("----", "----"))# Print modules foundkeys = sorted(self.modules.keys())for key in keys:m = self.modules[key]if m.__path__:print("P", end=' ')else:print("m", end=' ')print("%-25s" % key, m.__file__ or "")# Print missing modulesmissing, maybe = self.any_missing_maybe()if missing:print()print("Missing modules:")for name in missing:mods = sorted(self.badmodules[name].keys())print("?", name, "imported from", ', '.join(mods))# Print modules that may be missing, but then again, maybe not...if maybe:print()print("Submodules that appear to be missing, but could also be", end=' ')print("global names in the parent package:")for name in maybe:mods = sorted(self.badmodules[name].keys())print("?", name, "imported from", ', '.join(mods))def any_missing(self):"""Return a list of modules that appear to be missing. Useany_missing_maybe() if you want to know which modules arecertain to be missing, and which *may* be missing."""missing, maybe = self.any_missing_maybe()return missing + maybedef any_missing_maybe(self):"""Return two lists, one with modules that are certainly missingand one with modules that *may* be missing. The latter names couldeither be submodules *or* just global names in the package.The reason it can't always be determined is that it's impossible totell which names are imported when "from module import *" is donewith an extension module, short of actually importing it."""missing = []maybe = []for name in self.badmodules:if name in self.excludes:continuei = name.rfind(".")if i < 0:missing.append(name)continuesubname = name[i+1:]pkgname = name[:i]pkg = self.modules.get(pkgname)if pkg is not None:if pkgname in self.badmodules[name]:# The package tried to import this module itself and# failed. It's definitely missing.missing.append(name)elif subname in pkg.globalnames:# It's a global in the package: definitely not missing.passelif pkg.starimports:# It could be missing, but the package did an "import *"# from a non-Python module, so we simply can't be sure.maybe.append(name)else:# It's not a global in the package, the package didn't# do funny star imports, it's very likely to be missing.# The symbol could be inserted into the package from the# outside, but since that's not good style we simply list# it missing.missing.append(name)else:missing.append(name)missing.sort()maybe.sort()return missing, maybedef replace_paths_in_code(self, co):new_filename = original_filename = os.path.normpath(co.co_filename)for f, r in self.replace_paths:if original_filename.startswith(f):new_filename = r + original_filename[len(f):]breakif self.debug and original_filename not in self.processed_paths:if new_filename != original_filename:self.msgout(2, "co_filename %r changed to %r" \% (original_filename,new_filename,))else:self.msgout(2, "co_filename %r remains unchanged" \% (original_filename,))self.processed_paths.append(original_filename)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 co.replace(co_consts=tuple(consts), co_filename=new_filename)def test():# Parse command lineimport getopttry:opts, args = getopt.getopt(sys.argv[1:], "dmp:qx:")except getopt.error as msg:print(msg)return# Process optionsdebug = 1domods = 0addpath = []exclude = []for o, a in opts:if o == '-d':debug = debug + 1if o == '-m':domods = 1if o == '-p':addpath = addpath + a.split(os.pathsep)if o == '-q':debug = 0if o == '-x':exclude.append(a)# Provide default argumentsif not args:script = "hello.py"else:script = args[0]# Set the path based on sys.path and the script directorypath = sys.path[:]path[0] = os.path.dirname(script)path = addpath + pathif debug > 1:print("path:")for item in path:print(" ", repr(item))# Create the module finder and turn its crankmf = ModuleFinder(path, debug, exclude)for arg in args[1:]:if arg == '-m':domods = 1continueif domods:if arg[-2:] == '.*':mf.import_hook(arg[:-2], None, ["*"])else:mf.import_hook(arg)else:mf.load_file(arg)mf.run_script(script)mf.report()return mf # for -i debuggingif __name__ == '__main__':try:mf = test()except KeyboardInterrupt:print("\n[interrupted]")
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。