/opt/alt/python37/lib64/python3.7
NameSizeModeActions
asyncio/-0755rm
collections/-0755rm
concurrent/-0755rm
config-3.7m/-0755rm
ctypes/-0755rm
curses/-0755rm
dbm/-0755rm
distutils/-0755rm
email/-0755rm
encodings/-0755rm
ensurepip/-0755rm
html/-0755rm
http/-0755rm
idlelib/-0755rm
importlib/-0755rm
json/-0755rm
lib-dynload/-0755rm
lib2to3/-0755rm
logging/-0755rm
multiprocessing/-0755rm
pydoc_data/-0755rm
site-packages/-0755rm
sqlite3/-0755rm
test/-0755rm
unittest/-0755rm
urllib/-0755rm
venv/-0755rm
wsgiref/-0755rm
xml/-0755rm
xmlrpc/-0755rm
__pycache__/-0755rm
abc.py55800644editdlrm
aifc.py328140644editdlrm
antigravity.py4770644editdlrm
argparse.py953720644editdlrm
ast.py128420644editdlrm
asynchat.py113280644editdlrm
asyncore.py201180644editdlrm
base64.py203930755editdlrm
bdb.py317300644editdlrm
binhex.py139540644editdlrm
bisect.py25570644editdlrm
bz2.py124100644editdlrm
calendar.py248260644editdlrm
cgi.py350500755editdlrm
cgitb.py120180644editdlrm
chunk.py54350644editdlrm
cmd.py148600644editdlrm
code.py106220644editdlrm
codecs.py366150644editdlrm
codeop.py62750644editdlrm
colorsys.py40640644editdlrm
compileall.py137880644editdlrm
configparser.py542830644editdlrm
contextlib.py247630644editdlrm
contextvars.py1290644editdlrm
copy.py88560644editdlrm
copyreg.py70170644editdlrm
cProfile.py62530755editdlrm
crypt.py33460644editdlrm
csv.py161800644editdlrm
dataclasses.py495200644editdlrm
datetime.py865440644editdlrm
decimal.py3200644editdlrm
difflib.py843930644editdlrm
dis.py198880644editdlrm
doctest.py1045600644editdlrm
dummy_threading.py28150644editdlrm
enum.py350430644editdlrm
filecmp.py98300644editdlrm
fileinput.py146250644editdlrm
fnmatch.py40560644editdlrm
formatter.py151430644editdlrm
fractions.py237520644editdlrm
ftplib.py356180644editdlrm
functools.py329320644editdlrm
genericpath.py49120644editdlrm
getopt.py74890644editdlrm
getpass.py59940644editdlrm
gettext.py219670644editdlrm
glob.py56380644editdlrm
gzip.py206370644editdlrm
hashlib.py95340644editdlrm
heapq.py230170644editdlrm
hmac.py65170644editdlrm
imaplib.py532920644editdlrm
imghdr.py37950644editdlrm
imp.py105360644editdlrm
inspect.py1176350644editdlrm
io.py35170644editdlrm
ipaddress.py735780644editdlrm
keyword.py22560755editdlrm
linecache.py53300644editdlrm
locale.py781910644editdlrm
lzma.py129830644editdlrm
macpath.py61230644editdlrm
mailbox.py786540644editdlrm
mailcap.py90670644editdlrm
mimetypes.py214960644editdlrm
modulefinder.py230350644editdlrm
netrc.py55660644editdlrm
nntplib.py430870644editdlrm
ntpath.py223400644editdlrm
nturl2path.py25840644editdlrm
numbers.py102440644editdlrm
opcode.py58240644editdlrm
operator.py108630644editdlrm
optparse.py603710644editdlrm
os.py379010644editdlrm
pathlib.py503290644editdlrm
pdb.py625050755editdlrm
pickle.py579940644editdlrm
pickletools.py912200644editdlrm
pipes.py89160644editdlrm
pkgutil.py214610644editdlrm
platform.py469940755editdlrm
plistlib.py307090644editdlrm
poplib.py149640644editdlrm
posixpath.py157710644editdlrm
pprint.py208840644editdlrm
profile.py224940755editdlrm
pstats.py273150644editdlrm
pty.py47630644editdlrm
pyclbr.py151370644editdlrm
pydoc.py1058760644editdlrm
py_compile.py80010644editdlrm
queue.py113590644editdlrm
quopri.py72650755editdlrm
random.py275570644editdlrm
re.py153060644editdlrm
reprlib.py52670644editdlrm
rlcompleter.py70970644editdlrm
runpy.py119590644editdlrm
sched.py64420644editdlrm
secrets.py20380644editdlrm
selectors.py185610644editdlrm
shelve.py85270644editdlrm
shlex.py131000644editdlrm
shutil.py419500644editdlrm
signal.py21230644editdlrm
site.py215750644editdlrm
smtpd.py347220755editdlrm
smtplib.py444430755editdlrm
sndhdr.py70860644editdlrm
socket.py274690644editdlrm
socketserver.py269230644editdlrm
sre_compile.py268720644editdlrm
sre_constants.py71770644editdlrm
sre_parse.py391560644editdlrm
ssl.py454950644editdlrm
stat.py53910644editdlrm
statistics.py206510644editdlrm
string.py115640644editdlrm
stringprep.py129170644editdlrm
struct.py2570644editdlrm
subprocess.py726490644editdlrm
sunau.py183750644editdlrm
symbol.py21420755editdlrm
symtable.py72790644editdlrm
sysconfig.py244400644editdlrm
tabnanny.py114190755editdlrm
tarfile.py926750755editdlrm
telnetlib.py231350644editdlrm
tempfile.py267300644editdlrm
textwrap.py194070644editdlrm
this.py10030644editdlrm
threading.py492840644editdlrm
timeit.py134930755editdlrm
token.py37630644editdlrm
tokenize.py270310644editdlrm
trace.py289030755editdlrm
traceback.py234370644editdlrm
tracemalloc.py170760644editdlrm
tty.py8790644editdlrm
types.py98970644editdlrm
typing.py564380644editdlrm
uu.py72770644editdlrm
uuid.py295180644editdlrm
warnings.py200800644editdlrm
wave.py182300644editdlrm
weakref.py215080644editdlrm
webbrowser.py237150755editdlrm
xdrlib.py59130644editdlrm
zipapp.py75350644editdlrm
zipfile.py810940644editdlrm
_bootlocale.py18010644editdlrm
_collections_abc.py264240644editdlrm
_compat_pickle.py87490644editdlrm
_compression.py53400644editdlrm
_dummy_thread.py60270644editdlrm
_markupbase.py145980644editdlrm
_osx_support.py196000644editdlrm
_pydecimal.py2286900644editdlrm
_pyio.py916160644editdlrm
_py_abc.py61860644editdlrm
_sitebuiltins.py31150644editdlrm
_strptime.py255040644editdlrm
_sysconfigdata_dm_linux_x86_64-linux-gnu.py297860644editdlrm
_sysconfigdata_m_linux_x86_64-linux-gnu.py286510644editdlrm
_threading_local.py72140644editdlrm
_weakrefset.py56790644editdlrm
__future__.py51010644editdlrm
__phello__.foo.py640644editdlrm
Edit: /opt/alt/python37/lib64/python3.7/trace.py (28903B)
#! /opt/alt/python37/bin/python3.7 # portions copyright 2001, Autonomous Zones Industries, Inc., all rights... # err... reserved and offered to the public under the terms of the # Python 2.2 license. # Author: Zooko O'Whielacronx # http://zooko.com/ # mailto:zooko@zooko.com # # Copyright 2000, Mojam Media, Inc., all rights reserved. # Author: Skip Montanaro # # Copyright 1999, Bioreason, Inc., all rights reserved. # Author: Andrew Dalke # # Copyright 1995-1997, Automatrix, Inc., all rights reserved. # Author: Skip Montanaro # # Copyright 1991-1995, Stichting Mathematisch Centrum, all rights reserved. # # # Permission to use, copy, modify, and distribute this Python software and # its associated documentation for any purpose without fee is hereby # granted, provided that the above copyright notice appears in all copies, # and that both that copyright notice and this permission notice appear in # supporting documentation, and that the name of neither Automatrix, # Bioreason or Mojam Media be used in advertising or publicity pertaining to # distribution of the software without specific, written prior permission. # """program/module to trace Python program or function execution Sample use, command line: trace.py -c -f counts --ignore-dir '$prefix' spam.py eggs trace.py -t --ignore-dir '$prefix' spam.py eggs trace.py --trackcalls spam.py eggs Sample use, programmatically import sys # create a Trace object, telling it what to ignore, and whether to # do tracing or line-counting or both. tracer = trace.Trace(ignoredirs=[sys.base_prefix, sys.base_exec_prefix,], trace=0, count=1) # run the new command using the given tracer tracer.run('main()') # make a report, placing output in /tmp r = tracer.results() r.write_results(show_missing=True, coverdir="/tmp") """ __all__ = ['Trace', 'CoverageResults'] import linecache import os import re import sys import sysconfig import token import tokenize import inspect import gc import dis import pickle from time import monotonic as _time import threading PRAGMA_NOCOVER = "#pragma NO COVER" class _Ignore: def __init__(self, modules=None, dirs=None): self._mods = set() if not modules else set(modules) self._dirs = [] if not dirs else [os.path.normpath(d) for d in dirs] self._ignore = { '': 1 } def names(self, filename, modulename): if modulename in self._ignore: return self._ignore[modulename] # haven't seen this one before, so see if the module name is # on the ignore list. if modulename in self._mods: # Identical names, so ignore self._ignore[modulename] = 1 return 1 # check if the module is a proper submodule of something on # the ignore list for mod in self._mods: # Need to take some care since ignoring # "cmp" mustn't mean ignoring "cmpcache" but ignoring # "Spam" must also mean ignoring "Spam.Eggs". if modulename.startswith(mod + '.'): self._ignore[modulename] = 1 return 1 # Now check that filename isn't in one of the directories if filename is None: # must be a built-in, so we must ignore self._ignore[modulename] = 1 return 1 # Ignore a file when it contains one of the ignorable paths for d in self._dirs: # The '+ os.sep' is to ensure that d is a parent directory, # as compared to cases like: # d = "/usr/local" # filename = "/usr/local.py" # or # d = "/usr/local.py" # filename = "/usr/local.py" if filename.startswith(d + os.sep): self._ignore[modulename] = 1 return 1 # Tried the different ways, so we don't ignore this module self._ignore[modulename] = 0 return 0 def _modname(path): """Return a plausible module name for the patch.""" base = os.path.basename(path) filename, ext = os.path.splitext(base) return filename def _fullmodname(path): """Return a plausible module name for the path.""" # If the file 'path' is part of a package, then the filename isn't # enough to uniquely identify it. Try to do the right thing by # looking in sys.path for the longest matching prefix. We'll # assume that the rest is the package name. comparepath = os.path.normcase(path) longest = "" for dir in sys.path: dir = os.path.normcase(dir) if comparepath.startswith(dir) and comparepath[len(dir)] == os.sep: if len(dir) > len(longest): longest = dir if longest: base = path[len(longest) + 1:] else: base = path # the drive letter is never part of the module name drive, base = os.path.splitdrive(base) base = base.replace(os.sep, ".") if os.altsep: base = base.replace(os.altsep, ".") filename, ext = os.path.splitext(base) return filename.lstrip(".") class CoverageResults: def __init__(self, counts=None, calledfuncs=None, infile=None, callers=None, outfile=None): self.counts = counts if self.counts is None: self.counts = {} self.counter = self.counts.copy() # map (filename, lineno) to count self.calledfuncs = calledfuncs if self.calledfuncs is None: self.calledfuncs = {} self.calledfuncs = self.calledfuncs.copy() self.callers = callers if self.callers is None: self.callers = {} self.callers = self.callers.copy() self.infile = infile self.outfile = outfile if self.infile: # Try to merge existing counts file. try: with open(self.infile, 'rb') as f: counts, calledfuncs, callers = pickle.load(f) self.update(self.__class__(counts, calledfuncs, callers)) except (OSError, EOFError, ValueError) as err: print(("Skipping counts file %r: %s" % (self.infile, err)), file=sys.stderr) def is_ignored_filename(self, filename): """Return True if the filename does not refer to a file we want to have reported. """ return filename.startswith('<') and filename.endswith('>') def update(self, other): """Merge in the data from another CoverageResults""" counts = self.counts calledfuncs = self.calledfuncs callers = self.callers other_counts = other.counts other_calledfuncs = other.calledfuncs other_callers = other.callers for key in other_counts: counts[key] = counts.get(key, 0) + other_counts[key] for key in other_calledfuncs: calledfuncs[key] = 1 for key in other_callers: callers[key] = 1 def write_results(self, show_missing=True, summary=False, coverdir=None): """ Write the coverage results. :param show_missing: Show lines that had no hits. :param summary: Include coverage summary per module. :param coverdir: If None, the results of each module are placed in its directory, otherwise it is included in the directory specified. """ if self.calledfuncs: print() print("functions called:") calls = self.calledfuncs for filename, modulename, funcname in sorted(calls): print(("filename: %s, modulename: %s, funcname: %s" % (filename, modulename, funcname))) if self.callers: print() print("calling relationships:") lastfile = lastcfile = "" for ((pfile, pmod, pfunc), (cfile, cmod, cfunc)) \ in sorted(self.callers): if pfile != lastfile: print() print("***", pfile, "***") lastfile = pfile lastcfile = "" if cfile != pfile and lastcfile != cfile: print(" -->", cfile) lastcfile = cfile print(" %s.%s -> %s.%s" % (pmod, pfunc, cmod, cfunc)) # turn the counts data ("(filename, lineno) = count") into something # accessible on a per-file basis per_file = {} for filename, lineno in self.counts: lines_hit = per_file[filename] = per_file.get(filename, {}) lines_hit[lineno] = self.counts[(filename, lineno)] # accumulate summary info, if needed sums = {} for filename, count in per_file.items(): if self.is_ignored_filename(filename): continue if filename.endswith(".pyc"): filename = filename[:-1] if coverdir is None: dir = os.path.dirname(os.path.abspath(filename)) modulename = _modname(filename) else: dir = coverdir if not os.path.exists(dir): os.makedirs(dir) modulename = _fullmodname(filename) # If desired, get a list of the line numbers which represent # executable content (returned as a dict for better lookup speed) if show_missing: lnotab = _find_executable_linenos(filename) else: lnotab = {} source = linecache.getlines(filename) coverpath = os.path.join(dir, modulename + ".cover") with open(filename, 'rb') as fp: encoding, _ = tokenize.detect_encoding(fp.readline) n_hits, n_lines = self.write_results_file(coverpath, source, lnotab, count, encoding) if summary and n_lines: percent = int(100 * n_hits / n_lines) sums[modulename] = n_lines, percent, modulename, filename if summary and sums: print("lines cov% module (path)") for m in sorted(sums): n_lines, percent, modulename, filename = sums[m] print("%5d %3d%% %s (%s)" % sums[m]) if self.outfile: # try and store counts and module info into self.outfile try: pickle.dump((self.counts, self.calledfuncs, self.callers), open(self.outfile, 'wb'), 1) except OSError as err: print("Can't save counts files because %s" % err, file=sys.stderr) def write_results_file(self, path, lines, lnotab, lines_hit, encoding=None): """Return a coverage results file in path.""" # ``lnotab`` is a dict of executable lines, or a line number "table" try: outfile = open(path, "w", encoding=encoding) except OSError as err: print(("trace: Could not open %r for writing: %s " "- skipping" % (path, err)), file=sys.stderr) return 0, 0 n_lines = 0 n_hits = 0 with outfile: for lineno, line in enumerate(lines, 1): # do the blank/comment match to try to mark more lines # (help the reader find stuff that hasn't been covered) if lineno in lines_hit: outfile.write("%5d: " % lines_hit[lineno]) n_hits += 1 n_lines += 1 elif lineno in lnotab and not PRAGMA_NOCOVER in line: # Highlight never-executed lines, unless the line contains # #pragma: NO COVER outfile.write(">>>>>> ") n_lines += 1 else: outfile.write(" ") outfile.write(line.expandtabs(8)) return n_hits, n_lines def _find_lines_from_code(code, strs): """Return dict where keys are lines in the line number table.""" linenos = {} for _, lineno in dis.findlinestarts(code): if lineno not in strs: linenos[lineno] = 1 return linenos def _find_lines(code, strs): """Return lineno dict for all code objects reachable from code.""" # get all of the lineno information from the code of this scope level linenos = _find_lines_from_code(code, strs) # and check the constants for references to other code objects for c in code.co_consts: if inspect.iscode(c): # find another code object, so recurse into it linenos.update(_find_lines(c, strs)) return linenos def _find_strings(filename, encoding=None): """Return a dict of possible docstring positions. The dict maps line numbers to strings. There is an entry for line that contains only a string or a part of a triple-quoted string. """ d = {} # If the first token is a string, then it's the module docstring. # Add this special case so that the test in the loop passes. prev_ttype = token.INDENT with open(filename, encoding=encoding) as f: tok = tokenize.generate_tokens(f.readline) for ttype, tstr, start, end, line in tok: if ttype == token.STRING: if prev_ttype == token.INDENT: sline, scol = start eline, ecol = end for i in range(sline, eline + 1): d[i] = 1 prev_ttype = ttype return d def _find_executable_linenos(filename): """Return dict where keys are line numbers in the line number table.""" try: with tokenize.open(filename) as f: prog = f.read() encoding = f.encoding except OSError as err: print(("Not printing coverage data for %r: %s" % (filename, err)), file=sys.stderr) return {} code = compile(prog, filename, "exec") strs = _find_strings(filename, encoding) return _find_lines(code, strs) class Trace: def __init__(self, count=1, trace=1, countfuncs=0, countcallers=0, ignoremods=(), ignoredirs=(), infile=None, outfile=None, timing=False): """ @param count true iff it should count number of times each line is executed @param trace true iff it should print out each line that is being counted @param countfuncs true iff it should just output a list of (filename, modulename, funcname,) for functions that were called at least once; This overrides `count' and `trace' @param ignoremods a list of the names of modules to ignore @param ignoredirs a list of the names of directories to ignore all of the (recursive) contents of @param infile file from which to read stored counts to be added into the results @param outfile file in which to write the results @param timing true iff timing information be displayed """ self.infile = infile self.outfile = outfile self.ignore = _Ignore(ignoremods, ignoredirs) self.counts = {} # keys are (filename, linenumber) self.pathtobasename = {} # for memoizing os.path.basename self.donothing = 0 self.trace = trace self._calledfuncs = {} self._callers = {} self._caller_cache = {} self.start_time = None if timing: self.start_time = _time() if countcallers: self.globaltrace = self.globaltrace_trackcallers elif countfuncs: self.globaltrace = self.globaltrace_countfuncs elif trace and count: self.globaltrace = self.globaltrace_lt self.localtrace = self.localtrace_trace_and_count elif trace: self.globaltrace = self.globaltrace_lt self.localtrace = self.localtrace_trace elif count: self.globaltrace = self.globaltrace_lt self.localtrace = self.localtrace_count else: # Ahem -- do nothing? Okay. self.donothing = 1 def run(self, cmd): import __main__ dict = __main__.__dict__ self.runctx(cmd, dict, dict) def runctx(self, cmd, globals=None, locals=None): if globals is None: globals = {} if locals is None: locals = {} if not self.donothing: threading.settrace(self.globaltrace) sys.settrace(self.globaltrace) try: exec(cmd, globals, locals) finally: if not self.donothing: sys.settrace(None) threading.settrace(None) def runfunc(*args, **kw): if len(args) >= 2: self, func, *args = args elif not args: raise TypeError("descriptor 'runfunc' of 'Trace' object " "needs an argument") elif 'func' in kw: func = kw.pop('func') self, *args = args else: raise TypeError('runfunc expected at least 1 positional argument, ' 'got %d' % (len(args)-1)) result = None if not self.donothing: sys.settrace(self.globaltrace) try: result = func(*args, **kw) finally: if not self.donothing: sys.settrace(None) return result def file_module_function_of(self, frame): code = frame.f_code filename = code.co_filename if filename: modulename = _modname(filename) else: modulename = None funcname = code.co_name clsname = None if code in self._caller_cache: if self._caller_cache[code] is not None: clsname = self._caller_cache[code] else: self._caller_cache[code] = None ## use of gc.get_referrers() was suggested by Michael Hudson # all functions which refer to this code object funcs = [f for f in gc.get_referrers(code) if inspect.isfunction(f)] # require len(func) == 1 to avoid ambiguity caused by calls to # new.function(): "In the face of ambiguity, refuse the # temptation to guess." if len(funcs) == 1: dicts = [d for d in gc.get_referrers(funcs[0]) if isinstance(d, dict)] if len(dicts) == 1: classes = [c for c in gc.get_referrers(dicts[0]) if hasattr(c, "__bases__")] if len(classes) == 1: # ditto for new.classobj() clsname = classes[0].__name__ # cache the result - assumption is that new.* is # not called later to disturb this relationship # _caller_cache could be flushed if functions in # the new module get called. self._caller_cache[code] = clsname if clsname is not None: funcname = "%s.%s" % (clsname, funcname) return filename, modulename, funcname def globaltrace_trackcallers(self, frame, why, arg): """Handler for call events. Adds information about who called who to the self._callers dict. """ if why == 'call': # XXX Should do a better job of identifying methods this_func = self.file_module_function_of(frame) parent_func = self.file_module_function_of(frame.f_back) self._callers[(parent_func, this_func)] = 1 def globaltrace_countfuncs(self, frame, why, arg): """Handler for call events. Adds (filename, modulename, funcname) to the self._calledfuncs dict. """ if why == 'call': this_func = self.file_module_function_of(frame) self._calledfuncs[this_func] = 1 def globaltrace_lt(self, frame, why, arg): """Handler for call events. If the code block being entered is to be ignored, returns `None', else returns self.localtrace. """ if why == 'call': code = frame.f_code filename = frame.f_globals.get('__file__', None) if filename: # XXX _modname() doesn't work right for packages, so # the ignore support won't work right for packages modulename = _modname(filename) if modulename is not None: ignore_it = self.ignore.names(filename, modulename) if not ignore_it: if self.trace: print((" --- modulename: %s, funcname: %s" % (modulename, code.co_name))) return self.localtrace else: return None def localtrace_trace_and_count(self, frame, why, arg): if why == "line": # record the file name and line number of every trace filename = frame.f_code.co_filename lineno = frame.f_lineno key = filename, lineno self.counts[key] = self.counts.get(key, 0) + 1 if self.start_time: print('%.2f' % (_time() - self.start_time), end=' ') bname = os.path.basename(filename) print("%s(%d): %s" % (bname, lineno, linecache.getline(filename, lineno)), end='') return self.localtrace def localtrace_trace(self, frame, why, arg): if why == "line": # record the file name and line number of every trace filename = frame.f_code.co_filename lineno = frame.f_lineno if self.start_time: print('%.2f' % (_time() - self.start_time), end=' ') bname = os.path.basename(filename) print("%s(%d): %s" % (bname, lineno, linecache.getline(filename, lineno)), end='') return self.localtrace def localtrace_count(self, frame, why, arg): if why == "line": filename = frame.f_code.co_filename lineno = frame.f_lineno key = filename, lineno self.counts[key] = self.counts.get(key, 0) + 1 return self.localtrace def results(self): return CoverageResults(self.counts, infile=self.infile, outfile=self.outfile, calledfuncs=self._calledfuncs, callers=self._callers) def main(): import argparse parser = argparse.ArgumentParser() parser.add_argument('--version', action='version', version='trace 2.0') grp = parser.add_argument_group('Main options', 'One of these (or --report) must be given') grp.add_argument('-c', '--count', action='store_true', help='Count the number of times each line is executed and write ' 'the counts to .cover for each module executed, in ' 'the module\'s directory. See also --coverdir, --file, ' '--no-report below.') grp.add_argument('-t', '--trace', action='store_true', help='Print each line to sys.stdout before it is executed') grp.add_argument('-l', '--listfuncs', action='store_true', help='Keep track of which functions are executed at least once ' 'and write the results to sys.stdout after the program exits. ' 'Cannot be specified alongside --trace or --count.') grp.add_argument('-T', '--trackcalls', action='store_true', help='Keep track of caller/called pairs and write the results to ' 'sys.stdout after the program exits.') grp = parser.add_argument_group('Modifiers') _grp = grp.add_mutually_exclusive_group() _grp.add_argument('-r', '--report', action='store_true', help='Generate a report from a counts file; does not execute any ' 'code. --file must specify the results file to read, which ' 'must have been created in a previous run with --count ' '--file=FILE') _grp.add_argument('-R', '--no-report', action='store_true', help='Do not generate the coverage report files. ' 'Useful if you want to accumulate over several runs.') grp.add_argument('-f', '--file', help='File to accumulate counts over several runs') grp.add_argument('-C', '--coverdir', help='Directory where the report files go. The coverage report ' 'for . will be written to file ' '//.cover') grp.add_argument('-m', '--missing', action='store_true', help='Annotate executable lines that were not executed with ' '">>>>>> "') grp.add_argument('-s', '--summary', action='store_true', help='Write a brief summary for each file to sys.stdout. ' 'Can only be used with --count or --report') grp.add_argument('-g', '--timing', action='store_true', help='Prefix each line with the time since the program started. ' 'Only used while tracing') grp = parser.add_argument_group('Filters', 'Can be specified multiple times') grp.add_argument('--ignore-module', action='append', default=[], help='Ignore the given module(s) and its submodules ' '(if it is a package). Accepts comma separated list of ' 'module names.') grp.add_argument('--ignore-dir', action='append', default=[], help='Ignore files in the given directory ' '(multiple directories can be joined by os.pathsep).') parser.add_argument('filename', nargs='?', help='file to run as main program') parser.add_argument('arguments', nargs=argparse.REMAINDER, help='arguments to the program') opts = parser.parse_args() if opts.ignore_dir: _prefix = sysconfig.get_path("stdlib") _exec_prefix = sysconfig.get_path("platstdlib") def parse_ignore_dir(s): s = os.path.expanduser(os.path.expandvars(s)) s = s.replace('$prefix', _prefix).replace('$exec_prefix', _exec_prefix) return os.path.normpath(s) opts.ignore_module = [mod.strip() for i in opts.ignore_module for mod in i.split(',')] opts.ignore_dir = [parse_ignore_dir(s) for i in opts.ignore_dir for s in i.split(os.pathsep)] if opts.report: if not opts.file: parser.error('-r/--report requires -f/--file') results = CoverageResults(infile=opts.file, outfile=opts.file) return results.write_results(opts.missing, opts.summary, opts.coverdir) if not any([opts.trace, opts.count, opts.listfuncs, opts.trackcalls]): parser.error('must specify one of --trace, --count, --report, ' '--listfuncs, or --trackcalls') if opts.listfuncs and (opts.count or opts.trace): parser.error('cannot specify both --listfuncs and (--trace or --count)') if opts.summary and not opts.count: parser.error('--summary can only be used with --count or --report') if opts.filename is None: parser.error('filename is missing: required with the main options') sys.argv = [opts.filename, *opts.arguments] sys.path[0] = os.path.dirname(opts.filename) t = Trace(opts.count, opts.trace, countfuncs=opts.listfuncs, countcallers=opts.trackcalls, ignoremods=opts.ignore_module, ignoredirs=opts.ignore_dir, infile=opts.file, outfile=opts.file, timing=opts.timing) try: with open(opts.filename) as fp: code = compile(fp.read(), opts.filename, 'exec') # try to emulate __main__ namespace as much as possible globs = { '__file__': opts.filename, '__name__': '__main__', '__package__': None, '__cached__': None, } t.runctx(code, globs, globs) except OSError as err: sys.exit("Cannot run file %r because: %s" % (sys.argv[0], err)) except SystemExit: pass results = t.results() if not opts.no_report: results.write_results(opts.missing, opts.summary, opts.coverdir) if __name__=='__main__': main()