Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
841d5f75
Commit
841d5f75
authored
Jul 07, 2003
by
Jeremy Hylton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
This file was moved to Lib/.
parent
89ec06ff
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
0 additions
and
729 deletions
+0
-729
Tools/scripts/trace.py
Tools/scripts/trace.py
+0
-729
No files found.
Tools/scripts/trace.py
deleted
100644 → 0
View file @
89ec06ff
#!/usr/bin/env python
# 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
Sample use, programmatically
# create a Trace object, telling it what to ignore, and whether to
# do tracing or line-counting or both.
trace = trace.Trace(ignoredirs=[sys.prefix, sys.exec_prefix,], trace=0,
count=1)
# run the new command using the given trace
trace.run(coverage.globaltrace, 'main()')
# make a report, telling it where you want output
r = trace.results()
r.write_results(show_missing=1)
"""
import
sys
,
os
,
tempfile
,
types
,
copy
,
operator
,
inspect
,
exceptions
,
marshal
try
:
import
cPickle
pickle
=
cPickle
except
ImportError
:
import
pickle
# DEBUG_MODE=1 # make this true to get printouts which help you understand what's going on
def
usage
(
outfile
):
outfile
.
write
(
"""Usage: %s [OPTIONS] <file> [ARGS]
Meta-options:
--help Display this help then exit.
--version Output version information then exit.
Otherwise, exactly one of the following three options must be given:
-t, --trace Print each line to sys.stdout before it is executed.
-c, --count Count the number of times each line is executed
and write the counts to <module>.cover for each
module executed, in the module's directory.
See also `--coverdir', `--file', `--no-report' below.
-r, --report Generate a report from a counts file; do 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'.
Modifiers:
-f, --file=<file> File to accumulate counts over several runs.
-R, --no-report Do not generate the coverage report files.
Useful if you want to accumulate over several runs.
-C, --coverdir=<dir> Directory where the report files. The coverage
report for <package>.<module> is written to file
<dir>/<package>/<module>.cover.
-m, --missing Annotate executable lines that were not executed
with '>>>>>> '.
-s, --summary Write a brief summary on stdout for each file.
(Can only be used with --count or --report.)
Filters, may be repeated multiple times:
--ignore-module=<mod> Ignore the given module and its submodules
(if it is a package).
--ignore-dir=<dir> Ignore files in the given directory (multiple
directories can be joined by os.pathsep).
"""
%
sys
.
argv
[
0
])
class
Ignore
:
def
__init__
(
self
,
modules
=
None
,
dirs
=
None
):
self
.
_mods
=
modules
or
[]
self
.
_dirs
=
dirs
or
[]
self
.
_dirs
=
map
(
os
.
path
.
normpath
,
self
.
_dirs
)
self
.
_ignore
=
{
'<string>'
:
1
}
def
names
(
self
,
filename
,
modulename
):
if
self
.
_ignore
.
has_key
(
modulename
):
return
self
.
_ignore
[
modulename
]
# haven't seen this one before, so see if the module name is
# on the ignore list. Need to take some care since ignoring
# "cmp" musn't mean ignoring "cmpcache" but ignoring
# "Spam" must also mean ignoring "Spam.Eggs".
for
mod
in
self
.
_mods
:
if
mod
==
modulename
:
# Identical names, so ignore
self
.
_ignore
[
modulename
]
=
1
return
1
# check if the module is a proper submodule of something on
# the ignore list
n
=
len
(
mod
)
# (will not overflow since if the first n characters are the
# same and the name has not already occured, then the size
# of "name" is greater than that of "mod")
if
mod
==
modulename
[:
n
]
and
modulename
[
n
]
==
'.'
:
self
.
_ignore
[
modulename
]
=
1
return
1
# Now check that __file__ 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
class
CoverageResults
:
def
__init__
(
self
,
counts
=
None
,
calledfuncs
=
None
,
infile
=
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
.
infile
=
infile
self
.
outfile
=
outfile
if
self
.
infile
:
# try and merge existing counts file
try
:
thingie
=
pickle
.
load
(
open
(
self
.
infile
,
'r'
))
if
type
(
thingie
)
is
types
.
DictType
:
# backwards compatibility for old trace.py after
# Zooko touched it but before calledfuncs --Zooko
# 2001-10-24
self
.
update
(
self
.
__class__
(
thingie
))
elif
type
(
thingie
)
is
types
.
TupleType
and
len
(
thingie
)
==
2
:
counts
,
calledfuncs
=
thingie
self
.
update
(
self
.
__class__
(
counts
,
calledfuncs
))
except
(
IOError
,
EOFError
):
pass
except
pickle
.
UnpicklingError
:
# backwards compatibility for old trace.py before
# Zooko touched it --Zooko 2001-10-24
self
.
update
(
self
.
__class__
(
marshal
.
load
(
open
(
self
.
infile
))))
def
update
(
self
,
other
):
"""Merge in the data from another CoverageResults"""
counts
=
self
.
counts
calledfuncs
=
self
.
calledfuncs
other_counts
=
other
.
counts
other_calledfuncs
=
other
.
calledfuncs
for
key
in
other_counts
.
keys
():
if
key
!=
'calledfuncs'
:
# backwards compatibility for abortive attempt to
# stuff calledfuncs into self.counts, by Zooko
# --Zooko 2001-10-24
counts
[
key
]
=
counts
.
get
(
key
,
0
)
+
other_counts
[
key
]
for
key
in
other_calledfuncs
.
keys
():
calledfuncs
[
key
]
=
1
def
write_results
(
self
,
show_missing
=
1
,
summary
=
0
,
coverdir
=
None
):
"""
@param coverdir
"""
for
filename
,
modulename
,
funcname
in
self
.
calledfuncs
.
keys
():
print
(
"filename: %s, modulename: %s, funcname: %s"
%
(
filename
,
modulename
,
funcname
))
import
re
# turn the counts data ("(filename, lineno) = count") into something
# accessible on a per-file basis
per_file
=
{}
for
thingie
in
self
.
counts
.
keys
():
if
thingie
!=
"calledfuncs"
:
# backwards compatibility for abortive attempt to
# stuff calledfuncs into self.counts, by Zooko --Zooko
# 2001-10-24
filename
,
lineno
=
thingie
lines_hit
=
per_file
[
filename
]
=
per_file
.
get
(
filename
,
{})
lines_hit
[
lineno
]
=
self
.
counts
[(
filename
,
lineno
)]
# there are many places where this is insufficient, like a blank
# line embedded in a multiline string.
blank
=
re
.
compile
(
r'^\
s*(#.*)?$
')
# accumulate summary info, if needed
sums = {}
# generate file paths for the coverage files we are going to write...
fnlist = []
tfdir = tempfile.gettempdir()
for key in per_file.keys():
filename = key
# skip some "files" we don'
t
care
about
...
if
filename
==
"<string>"
:
continue
# are these caused by code compiled using exec or something?
if
filename
.
startswith
(
tfdir
):
continue
modulename
=
inspect
.
getmodulename
(
filename
)
if
filename
.
endswith
(
".pyc"
)
or
filename
.
endswith
(
".pyo"
):
filename
=
filename
[:
-
1
]
if
coverdir
:
thiscoverdir
=
coverdir
else
:
thiscoverdir
=
os
.
path
.
dirname
(
os
.
path
.
abspath
(
filename
))
# the code from here to "<<<" is the contents of the `fileutil.make_dirs()' function in the Mojo Nation project. --Zooko 2001-10-14
# http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/mojonation/evil/common/fileutil.py?rev=HEAD&content-type=text/vnd.viewcvs-markup
tx
=
None
try
:
os
.
makedirs
(
thiscoverdir
)
except
OSError
,
x
:
tx
=
x
if
not
os
.
path
.
isdir
(
thiscoverdir
):
if
tx
:
raise
tx
raise
exceptions
.
IOError
,
"unknown error prevented creation of directory: %s"
%
thiscoverdir
# careful not to construct an IOError with a 2-tuple, as that has a special meaning...
# <<<
# build list file name by appending a ".cover" to the module name
# and sticking it into the specified directory
if
"."
in
modulename
:
# A module in a package
finalname
=
modulename
.
split
(
"."
)[
-
1
]
listfilename
=
os
.
path
.
join
(
thiscoverdir
,
finalname
+
".cover"
)
else
:
listfilename
=
os
.
path
.
join
(
thiscoverdir
,
modulename
+
".cover"
)
# Get the original lines from the .py file
try
:
lines
=
open
(
filename
,
'r'
).
readlines
()
except
IOError
,
err
:
sys
.
stderr
.
write
(
"trace: Could not open %s for reading because: %s - skipping
\
n
"
%
(
`filename`
,
err
))
continue
try
:
outfile
=
open
(
listfilename
,
'w'
)
except
IOError
,
err
:
sys
.
stderr
.
write
(
'%s: Could not open %s for writing because: %s"
\
"- skipping
\
n
'
%
(
"trace"
,
`listfilename`
,
err
))
continue
# If desired, get a list of the line numbers which represent
# executable content (returned as a dict for better lookup speed)
if
show_missing
:
executable_linenos
=
find_executable_linenos
(
filename
)
else
:
executable_linenos
=
{}
n_lines
=
0
n_hits
=
0
lines_hit
=
per_file
[
key
]
for
i
in
range
(
len
(
lines
)):
line
=
lines
[
i
]
# do the blank/comment match to try to mark more lines
# (help the reader find stuff that hasn't been covered)
if
lines_hit
.
has_key
(
i
+
1
):
# count precedes the lines that we captured
outfile
.
write
(
'%5d: '
%
lines_hit
[
i
+
1
])
n_hits
=
n_hits
+
1
n_lines
=
n_lines
+
1
elif
blank
.
match
(
line
):
# blank lines and comments are preceded by dots
outfile
.
write
(
' . '
)
else
:
# lines preceded by no marks weren't hit
# Highlight them if so indicated, unless the line contains
# '#pragma: NO COVER' (it is possible to embed this into
# the text as a non-comment; no easy fix)
if
executable_linenos
.
has_key
(
i
+
1
)
and
\
lines
[
i
].
find
(
' '
.
join
([
'#pragma'
,
'NO COVER'
]))
==
-
1
:
outfile
.
write
(
'>>>>>> '
)
else
:
outfile
.
write
(
' '
*
7
)
n_lines
=
n_lines
+
1
outfile
.
write
(
lines
[
i
].
expandtabs
(
8
))
outfile
.
close
()
if
summary
and
n_lines
:
percent
=
int
(
100
*
n_hits
/
n_lines
)
sums
[
modulename
]
=
n_lines
,
percent
,
modulename
,
filename
if
summary
and
sums
:
mods
=
sums
.
keys
()
mods
.
sort
()
print
"lines cov% module (path)"
for
m
in
mods
:
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
),
open
(
self
.
outfile
,
'w'
),
1
)
except
IOError
,
err
:
sys
.
stderr
.
write
(
"cannot save counts files because %s"
%
err
)
def
_find_LINENO_from_code
(
code
):
"""return the numbers of the lines containing the source code that
was compiled into code"""
linenos
=
{}
line_increments
=
[
ord
(
c
)
for
c
in
code
.
co_lnotab
[
1
::
2
]]
table_length
=
len
(
line_increments
)
lineno
=
code
.
co_firstlineno
for
li
in
line_increments
:
linenos
[
lineno
]
=
1
lineno
+=
li
linenos
[
lineno
]
=
1
return
linenos
def
_find_LINENO
(
code
):
"""return all of the lineno information from a code object"""
import
types
# get all of the lineno information from the code of this scope level
linenos
=
_find_LINENO_from_code
(
code
)
# and check the constants for references to other code objects
for
c
in
code
.
co_consts
:
if
type
(
c
)
==
types
.
CodeType
:
# find another code object, so recurse into it
linenos
.
update
(
_find_LINENO
(
c
))
return
linenos
def
find_executable_linenos
(
filename
):
"""return a dict of the line numbers from executable statements in a file
"""
import
parser
assert
filename
.
endswith
(
'.py'
)
prog
=
open
(
filename
).
read
()
ast
=
parser
.
suite
(
prog
)
code
=
parser
.
compileast
(
ast
,
filename
)
return
_find_LINENO
(
code
)
### XXX because os.path.commonprefix seems broken by my way of thinking...
def
commonprefix
(
dirs
):
"Given a list of pathnames, returns the longest common leading component"
if
not
dirs
:
return
''
n
=
copy
.
copy
(
dirs
)
for
i
in
range
(
len
(
n
)):
n
[
i
]
=
n
[
i
].
split
(
os
.
sep
)
prefix
=
n
[
0
]
for
item
in
n
:
for
i
in
range
(
len
(
prefix
)):
if
prefix
[:
i
+
1
]
<>
item
[:
i
+
1
]:
prefix
=
prefix
[:
i
]
if
i
==
0
:
return
''
break
return
os
.
sep
.
join
(
prefix
)
class
Trace
:
def
__init__
(
self
,
count
=
1
,
trace
=
1
,
countfuncs
=
0
,
ignoremods
=
(),
ignoredirs
=
(),
infile
=
None
,
outfile
=
None
):
"""
@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
"""
self
.
infile
=
infile
self
.
outfile
=
outfile
self
.
ignore
=
Ignore
(
ignoremods
,
ignoredirs
)
self
.
counts
=
{}
# keys are (filename, linenumber)
self
.
blabbed
=
{}
# for debugging
self
.
pathtobasename
=
{}
# for memoizing os.path.basename
self
.
donothing
=
0
self
.
trace
=
trace
self
.
_calledfuncs
=
{}
if
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__
if
not
self
.
donothing
:
sys
.
settrace
(
self
.
globaltrace
)
try
:
exec
cmd
in
dict
,
dict
finally
:
if
not
self
.
donothing
:
sys
.
settrace
(
None
)
def
runctx
(
self
,
cmd
,
globals
=
None
,
locals
=
None
):
if
globals
is
None
:
globals
=
{}
if
locals
is
None
:
locals
=
{}
if
not
self
.
donothing
:
sys
.
settrace
(
self
.
globaltrace
)
try
:
exec
cmd
in
globals
,
locals
finally
:
if
not
self
.
donothing
:
sys
.
settrace
(
None
)
def
runfunc
(
self
,
func
,
*
args
,
**
kw
):
result
=
None
if
not
self
.
donothing
:
sys
.
settrace
(
self
.
globaltrace
)
try
:
result
=
apply
(
func
,
args
,
kw
)
finally
:
if
not
self
.
donothing
:
sys
.
settrace
(
None
)
return
result
def
globaltrace_countfuncs
(
self
,
frame
,
why
,
arg
):
"""
Handles `call' events (why == 'call') and adds the (filename, modulename, funcname,) to the self._calledfuncs dict.
"""
if
why
==
'call'
:
filename
,
lineno
,
funcname
,
context
,
lineindex
=
\
inspect
.
getframeinfo
(
frame
,
0
)
if
filename
:
modulename
=
inspect
.
getmodulename
(
filename
)
else
:
modulename
=
None
self
.
_calledfuncs
[(
filename
,
modulename
,
funcname
,)]
=
1
def
globaltrace_lt
(
self
,
frame
,
why
,
arg
):
"""
Handles `call' events (why == 'call') and if the code block being entered is to be ignored then it returns `None', else it returns `self.localtrace'.
"""
if
why
==
'call'
:
filename
,
lineno
,
funcname
,
context
,
lineindex
=
\
inspect
.
getframeinfo
(
frame
,
0
)
if
filename
:
modulename
=
inspect
.
getmodulename
(
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
,
funcname
))
return
self
.
localtrace
else
:
# XXX why no filename?
return
None
def
localtrace_trace_and_count
(
self
,
frame
,
why
,
arg
):
if
why
==
'line'
:
# record the file name and line number of every trace
# XXX I wish inspect offered me an optimized
# `getfilename(frame)' to use in place of the presumably
# heavier `getframeinfo()'. --Zooko 2001-10-14
filename
,
lineno
,
funcname
,
context
,
lineindex
=
\
inspect
.
getframeinfo
(
frame
,
1
)
key
=
filename
,
lineno
self
.
counts
[
key
]
=
self
.
counts
.
get
(
key
,
0
)
+
1
# XXX not convinced that this memoizing is a performance
# win -- I don't know enough about Python guts to tell.
# --Zooko 2001-10-14
bname
=
self
.
pathtobasename
.
get
(
filename
)
if
bname
is
None
:
# Using setdefault faster than two separate lines?
# --Zooko 2001-10-14
bname
=
self
.
pathtobasename
.
setdefault
(
filename
,
os
.
path
.
basename
(
filename
))
try
:
print
"%s(%d): %s"
%
(
bname
,
lineno
,
context
[
lineindex
]),
except
IndexError
:
# Uh.. sometimes getframeinfo gives me a context of
# length 1 and a lineindex of -2. Oh well.
pass
return
self
.
localtrace
def
localtrace_trace
(
self
,
frame
,
why
,
arg
):
if
why
==
'line'
:
# XXX shouldn't do the count increment when arg is
# exception? But be careful to return self.localtrace
# when arg is exception! ? --Zooko 2001-10-14
# record the file name and line number of every trace XXX
# I wish inspect offered me an optimized
# `getfilename(frame)' to use in place of the presumably
# heavier `getframeinfo()'. --Zooko 2001-10-14
filename
,
lineno
,
funcname
,
context
,
lineindex
=
\
inspect
.
getframeinfo
(
frame
)
# XXX not convinced that this memoizing is a performance
# win -- I don't know enough about Python guts to tell.
# --Zooko 2001-10-14
bname
=
self
.
pathtobasename
.
get
(
filename
)
if
bname
is
None
:
# Using setdefault faster than two separate lines?
# --Zooko 2001-10-14
bname
=
self
.
pathtobasename
.
setdefault
(
filename
,
os
.
path
.
basename
(
filename
))
if
context
is
not
None
:
try
:
print
"%s(%d): %s"
%
(
bname
,
lineno
,
context
[
lineindex
]),
except
IndexError
:
# Uh.. sometimes getframeinfo gives me a context of length 1 and a lineindex of -2. Oh well.
pass
else
:
print
"%s(???): ???"
%
bname
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
)
def
_err_exit
(
msg
):
sys
.
stderr
.
write
(
"%s: %s
\
n
"
%
(
sys
.
argv
[
0
],
msg
))
sys
.
exit
(
1
)
def
main
(
argv
=
None
):
import
getopt
if
argv
is
None
:
argv
=
sys
.
argv
try
:
opts
,
prog_argv
=
getopt
.
getopt
(
argv
[
1
:],
"tcrRf:d:msC:l"
,
[
"help"
,
"version"
,
"trace"
,
"count"
,
"report"
,
"no-report"
,
"summary"
,
"file="
,
"missing"
,
"ignore-module="
,
"ignore-dir="
,
"coverdir="
,
"listfuncs"
,])
except
getopt
.
error
,
msg
:
sys
.
stderr
.
write
(
"%s: %s
\
n
"
%
(
sys
.
argv
[
0
],
msg
))
sys
.
stderr
.
write
(
"Try `%s --help' for more information
\
n
"
%
sys
.
argv
[
0
])
sys
.
exit
(
1
)
trace
=
0
count
=
0
report
=
0
no_report
=
0
counts_file
=
None
missing
=
0
ignore_modules
=
[]
ignore_dirs
=
[]
coverdir
=
None
summary
=
0
listfuncs
=
False
for
opt
,
val
in
opts
:
if
opt
==
"--help"
:
usage
(
sys
.
stdout
)
sys
.
exit
(
0
)
if
opt
==
"--version"
:
sys
.
stdout
.
write
(
"trace 2.0
\
n
"
)
sys
.
exit
(
0
)
if
opt
==
"-l"
or
opt
==
"--listfuncs"
:
listfuncs
=
True
continue
if
opt
==
"-t"
or
opt
==
"--trace"
:
trace
=
1
continue
if
opt
==
"-c"
or
opt
==
"--count"
:
count
=
1
continue
if
opt
==
"-r"
or
opt
==
"--report"
:
report
=
1
continue
if
opt
==
"-R"
or
opt
==
"--no-report"
:
no_report
=
1
continue
if
opt
==
"-f"
or
opt
==
"--file"
:
counts_file
=
val
continue
if
opt
==
"-m"
or
opt
==
"--missing"
:
missing
=
1
continue
if
opt
==
"-C"
or
opt
==
"--coverdir"
:
coverdir
=
val
continue
if
opt
==
"-s"
or
opt
==
"--summary"
:
summary
=
1
continue
if
opt
==
"--ignore-module"
:
ignore_modules
.
append
(
val
)
continue
if
opt
==
"--ignore-dir"
:
for
s
in
val
.
split
(
os
.
pathsep
):
s
=
os
.
path
.
expandvars
(
s
)
# should I also call expanduser? (after all, could use $HOME)
s
=
s
.
replace
(
"$prefix"
,
os
.
path
.
join
(
sys
.
prefix
,
"lib"
,
"python"
+
sys
.
version
[:
3
]))
s
=
s
.
replace
(
"$exec_prefix"
,
os
.
path
.
join
(
sys
.
exec_prefix
,
"lib"
,
"python"
+
sys
.
version
[:
3
]))
s
=
os
.
path
.
normpath
(
s
)
ignore_dirs
.
append
(
s
)
continue
assert
0
,
"Should never get here"
if
listfuncs
and
(
count
or
trace
):
_err_exit
(
"cannot specify both --listfuncs and (--trace or --count)"
)
if
not
count
and
not
trace
and
not
report
and
not
listfuncs
:
_err_exit
(
"must specify one of --trace, --count, --report or --listfuncs"
)
if
report
and
no_report
:
_err_exit
(
"cannot specify both --report and --no-report"
)
if
report
and
not
counts_file
:
_err_exit
(
"--report requires a --file"
)
if
no_report
and
len
(
prog_argv
)
==
0
:
_err_exit
(
"missing name of file to run"
)
# everything is ready
if
report
:
results
=
CoverageResults
(
infile
=
counts_file
,
outfile
=
counts_file
)
results
.
write_results
(
missing
,
summary
=
summary
,
coverdir
=
coverdir
)
else
:
sys
.
argv
=
prog_argv
progname
=
prog_argv
[
0
]
sys
.
path
[
0
]
=
os
.
path
.
split
(
progname
)[
0
]
t
=
Trace
(
count
,
trace
,
countfuncs
=
listfuncs
,
ignoremods
=
ignore_modules
,
ignoredirs
=
ignore_dirs
,
infile
=
counts_file
,
outfile
=
counts_file
)
try
:
t
.
run
(
'execfile('
+
`progname`
+
')'
)
except
IOError
,
err
:
_err_exit
(
"Cannot run file %s because: %s"
%
(
`sys.argv[0]`
,
err
))
except
SystemExit
:
pass
results
=
t
.
results
()
if
not
no_report
:
results
.
write_results
(
missing
,
summary
=
summary
,
coverdir
=
coverdir
)
if
__name__
==
'__main__'
:
main
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment