[Python-Dev] tests for standard library modules
Vladimir Marangozov
Vladimir.Marangozov@inrialpes.fr
Fri, 4 Aug 2000 00:25:38 +0200 (CEST)
Jeremy Hylton wrote:
>
> Skip's trace.py code coverage tool is now available in Tools/script.
> You can use it to examine how much of a particular module is covered
> by existing tests.
Hmm. Glancing quickly at trace.py, I see that half of it is guessing
line numbers. The same SET_LINENO problem again. This is unfortunate.
But fortunately <wink>, here's another piece of code, modeled after
its C counterpart, that comes to Skip's rescue and that works with -O.
Example:
>>> import codeutil
>>> co = codeutil.PyCode_Line2Addr.func_code # some code object
>>> codeutil.PyCode_GetExecLines(co)
[20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36]
>>> codeutil.PyCode_Line2Addr(co, 29)
173
>>> codeutil.PyCode_Addr2Line(co, 173)
29
>>> codeutil.PyCode_Line2Addr(co, 10)
Traceback (innermost last):
File "<stdin>", line 1, in ?
File "codeutil.py", line 26, in PyCode_Line2Addr
raise IndexError, "line must be in range [%d,%d]" % (line, lastlineno)
IndexError: line must be in range [20,36]
etc...
--
Vladimir MARANGOZOV | Vladimir.Marangozov@inrialpes.fr
http://sirac.inrialpes.fr/~marangoz | tel:(+33-4)76615277 fax:76615252
------------------------------[ codeutil.py ]-------------------------
import types
def PyCode_Addr2Line(co, addrq):
assert type(co) == types.CodeType, \
"1st arg must be a code object, %s given" % type(co).__name__
if addrq < 0 or addrq > len(co.co_code):
raise IndexError, "address must be in range [0,%d]" % len(co.co_code)
addr = 0
line = co.co_firstlineno
lnotab = co.co_lnotab
for i in range(0, len(lnotab), 2):
addr_incr = ord(lnotab[i])
line_incr = ord(lnotab[i+1])
addr = addr + addr_incr
if (addr > addrq):
break
line = line + line_incr
return line
def PyCode_Line2Addr(co, lineq):
assert type(co) == types.CodeType, \
"1st arg must be a code object, %s given" % type(co).__name__
line = co.co_firstlineno
lastlineno = PyCode_Addr2Line(co, len(co.co_code))
if lineq < line or lineq > lastlineno:
raise IndexError, "line must be in range [%d,%d]" % (line, lastlineno)
addr = 0
lnotab = co.co_lnotab
for i in range(0, len(lnotab), 2):
if line >= lineq:
break
addr_incr = ord(lnotab[i])
line_incr = ord(lnotab[i+1])
addr = addr + addr_incr
line = line + line_incr
return addr
def PyCode_GetExecLines(co):
assert type(co) == types.CodeType, \
"arg must be a code object, %s given" % type(co).__name__
lastlineno = PyCode_Addr2Line(co, len(co.co_code))
lines = range(co.co_firstlineno, lastlineno + 1)
# remove void lines (w/o opcodes): comments, blank/escaped lines
i = len(lines) - 1
while i >= 0:
if lines[i] != PyCode_Addr2Line(co, PyCode_Line2Addr(co, lines[i])):
lines.pop(i)
i = i - 1
return lines