thirdparty/coverage/coverage.py
author Lennard de Rijk <ljvderijk@gmail.com>
Fri, 03 Jul 2009 15:00:00 +0200
changeset 2506 c98bf890156e
parent 780 042aafcd7dce
permissions -rw-r--r--
Removed getSurveyResponseFromPost from Surveys helper. We will use the power of Django Forms instead of getting our own properties. This fits better into the rest of Melange which also uses this approach.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
780
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
     1
#!/usr/bin/python
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
     2
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
     3
#             Perforce Defect Tracking Integration Project
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
     4
#              <http://www.ravenbrook.com/project/p4dti/>
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
     5
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
     6
#                   COVERAGE.PY -- COVERAGE TESTING
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
     7
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
     8
#             Gareth Rees, Ravenbrook Limited, 2001-12-04
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
     9
#                     Ned Batchelder, 2004-12-12
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    10
#         http://nedbatchelder.com/code/modules/coverage.html
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    11
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    12
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    13
# 1. INTRODUCTION
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    14
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    15
# This module provides coverage testing for Python code.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    16
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    17
# The intended readership is all Python developers.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    18
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    19
# This document is not confidential.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    20
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    21
# See [GDR 2001-12-04a] for the command-line interface, programmatic
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    22
# interface and limitations.  See [GDR 2001-12-04b] for requirements and
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    23
# design.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    24
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    25
r"""Usage:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    26
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    27
coverage.py -x [-p] MODULE.py [ARG1 ARG2 ...]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    28
    Execute module, passing the given command-line arguments, collecting
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    29
    coverage data. With the -p option, write to a temporary file containing
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    30
    the machine name and process ID.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    31
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    32
coverage.py -e
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    33
    Erase collected coverage data.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    34
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    35
coverage.py -c
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    36
    Collect data from multiple coverage files (as created by -p option above)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    37
    and store it into a single file representing the union of the coverage.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    38
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    39
coverage.py -r [-m] [-o dir1,dir2,...] FILE1 FILE2 ...
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    40
    Report on the statement coverage for the given files.  With the -m
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    41
    option, show line numbers of the statements that weren't executed.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    42
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    43
coverage.py -a [-d dir] [-o dir1,dir2,...] FILE1 FILE2 ...
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    44
    Make annotated copies of the given files, marking statements that
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    45
    are executed with > and statements that are missed with !.  With
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    46
    the -d option, make the copies in that directory.  Without the -d
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    47
    option, make each copy in the same directory as the original.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    48
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    49
-o dir,dir2,...
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    50
  Omit reporting or annotating files when their filename path starts with
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    51
  a directory listed in the omit list.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    52
  e.g. python coverage.py -i -r -o c:\python23,lib\enthought\traits
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    53
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    54
Coverage data is saved in the file .coverage by default.  Set the
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    55
COVERAGE_FILE environment variable to save it somewhere else."""
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    56
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    57
__version__ = "2.85.20080914"    # see detailed history at the end of this file.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    58
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    59
import compiler
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    60
import compiler.visitor
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    61
import glob
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    62
import os
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    63
import re
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    64
import string
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    65
import symbol
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    66
import sys
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    67
import threading
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    68
import token
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    69
import types
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    70
import zipimport
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    71
from socket import gethostname
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    72
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    73
# Python version compatibility
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    74
try:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    75
    strclass = basestring   # new to 2.3
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    76
except:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    77
    strclass = str
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    78
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    79
# 2. IMPLEMENTATION
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    80
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    81
# This uses the "singleton" pattern.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    82
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    83
# The word "morf" means a module object (from which the source file can
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    84
# be deduced by suitable manipulation of the __file__ attribute) or a
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    85
# filename.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    86
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    87
# When we generate a coverage report we have to canonicalize every
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    88
# filename in the coverage dictionary just in case it refers to the
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    89
# module we are reporting on.  It seems a shame to throw away this
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    90
# information so the data in the coverage dictionary is transferred to
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    91
# the 'cexecuted' dictionary under the canonical filenames.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    92
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    93
# The coverage dictionary is called "c" and the trace function "t".  The
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    94
# reason for these short names is that Python looks up variables by name
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    95
# at runtime and so execution time depends on the length of variables!
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    96
# In the bottleneck of this application it's appropriate to abbreviate
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    97
# names to increase speed.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    98
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
    99
class StatementFindingAstVisitor(compiler.visitor.ASTVisitor):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   100
    """ A visitor for a parsed Abstract Syntax Tree which finds executable
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   101
        statements.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   102
    """
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   103
    def __init__(self, statements, excluded, suite_spots):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   104
        compiler.visitor.ASTVisitor.__init__(self)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   105
        self.statements = statements
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   106
        self.excluded = excluded
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   107
        self.suite_spots = suite_spots
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   108
        self.excluding_suite = 0
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   109
        
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   110
    def doRecursive(self, node):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   111
        for n in node.getChildNodes():
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   112
            self.dispatch(n)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   113
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   114
    visitStmt = visitModule = doRecursive
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   115
    
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   116
    def doCode(self, node):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   117
        if hasattr(node, 'decorators') and node.decorators:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   118
            self.dispatch(node.decorators)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   119
            self.recordAndDispatch(node.code)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   120
        else:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   121
            self.doSuite(node, node.code)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   122
            
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   123
    visitFunction = visitClass = doCode
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   124
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   125
    def getFirstLine(self, node):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   126
        # Find the first line in the tree node.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   127
        lineno = node.lineno
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   128
        for n in node.getChildNodes():
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   129
            f = self.getFirstLine(n)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   130
            if lineno and f:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   131
                lineno = min(lineno, f)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   132
            else:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   133
                lineno = lineno or f
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   134
        return lineno
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   135
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   136
    def getLastLine(self, node):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   137
        # Find the first line in the tree node.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   138
        lineno = node.lineno
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   139
        for n in node.getChildNodes():
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   140
            lineno = max(lineno, self.getLastLine(n))
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   141
        return lineno
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   142
    
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   143
    def doStatement(self, node):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   144
        self.recordLine(self.getFirstLine(node))
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   145
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   146
    visitAssert = visitAssign = visitAssTuple = visitPrint = \
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   147
        visitPrintnl = visitRaise = visitSubscript = visitDecorators = \
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   148
        doStatement
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   149
    
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   150
    def visitPass(self, node):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   151
        # Pass statements have weird interactions with docstrings.  If this
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   152
        # pass statement is part of one of those pairs, claim that the statement
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   153
        # is on the later of the two lines.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   154
        l = node.lineno
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   155
        if l:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   156
            lines = self.suite_spots.get(l, [l,l])
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   157
            self.statements[lines[1]] = 1
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   158
        
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   159
    def visitDiscard(self, node):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   160
        # Discard nodes are statements that execute an expression, but then
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   161
        # discard the results.  This includes function calls, so we can't 
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   162
        # ignore them all.  But if the expression is a constant, the statement
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   163
        # won't be "executed", so don't count it now.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   164
        if node.expr.__class__.__name__ != 'Const':
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   165
            self.doStatement(node)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   166
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   167
    def recordNodeLine(self, node):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   168
        # Stmt nodes often have None, but shouldn't claim the first line of
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   169
        # their children (because the first child might be an ignorable line
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   170
        # like "global a").
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   171
        if node.__class__.__name__ != 'Stmt':
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   172
            return self.recordLine(self.getFirstLine(node))
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   173
        else:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   174
            return 0
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   175
    
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   176
    def recordLine(self, lineno):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   177
        # Returns a bool, whether the line is included or excluded.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   178
        if lineno:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   179
            # Multi-line tests introducing suites have to get charged to their
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   180
            # keyword.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   181
            if lineno in self.suite_spots:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   182
                lineno = self.suite_spots[lineno][0]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   183
            # If we're inside an excluded suite, record that this line was
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   184
            # excluded.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   185
            if self.excluding_suite:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   186
                self.excluded[lineno] = 1
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   187
                return 0
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   188
            # If this line is excluded, or suite_spots maps this line to
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   189
            # another line that is exlcuded, then we're excluded.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   190
            elif self.excluded.has_key(lineno) or \
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   191
                 self.suite_spots.has_key(lineno) and \
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   192
                 self.excluded.has_key(self.suite_spots[lineno][1]):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   193
                return 0
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   194
            # Otherwise, this is an executable line.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   195
            else:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   196
                self.statements[lineno] = 1
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   197
                return 1
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   198
        return 0
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   199
    
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   200
    default = recordNodeLine
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   201
    
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   202
    def recordAndDispatch(self, node):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   203
        self.recordNodeLine(node)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   204
        self.dispatch(node)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   205
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   206
    def doSuite(self, intro, body, exclude=0):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   207
        exsuite = self.excluding_suite
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   208
        if exclude or (intro and not self.recordNodeLine(intro)):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   209
            self.excluding_suite = 1
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   210
        self.recordAndDispatch(body)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   211
        self.excluding_suite = exsuite
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   212
        
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   213
    def doPlainWordSuite(self, prevsuite, suite):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   214
        # Finding the exclude lines for else's is tricky, because they aren't
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   215
        # present in the compiler parse tree.  Look at the previous suite,
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   216
        # and find its last line.  If any line between there and the else's
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   217
        # first line are excluded, then we exclude the else.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   218
        lastprev = self.getLastLine(prevsuite)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   219
        firstelse = self.getFirstLine(suite)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   220
        for l in range(lastprev+1, firstelse):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   221
            if self.suite_spots.has_key(l):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   222
                self.doSuite(None, suite, exclude=self.excluded.has_key(l))
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   223
                break
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   224
        else:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   225
            self.doSuite(None, suite)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   226
        
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   227
    def doElse(self, prevsuite, node):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   228
        if node.else_:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   229
            self.doPlainWordSuite(prevsuite, node.else_)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   230
    
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   231
    def visitFor(self, node):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   232
        self.doSuite(node, node.body)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   233
        self.doElse(node.body, node)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   234
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   235
    visitWhile = visitFor
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   236
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   237
    def visitIf(self, node):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   238
        # The first test has to be handled separately from the rest.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   239
        # The first test is credited to the line with the "if", but the others
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   240
        # are credited to the line with the test for the elif.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   241
        self.doSuite(node, node.tests[0][1])
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   242
        for t, n in node.tests[1:]:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   243
            self.doSuite(t, n)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   244
        self.doElse(node.tests[-1][1], node)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   245
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   246
    def visitTryExcept(self, node):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   247
        self.doSuite(node, node.body)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   248
        for i in range(len(node.handlers)):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   249
            a, b, h = node.handlers[i]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   250
            if not a:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   251
                # It's a plain "except:".  Find the previous suite.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   252
                if i > 0:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   253
                    prev = node.handlers[i-1][2]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   254
                else:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   255
                    prev = node.body
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   256
                self.doPlainWordSuite(prev, h)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   257
            else:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   258
                self.doSuite(a, h)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   259
        self.doElse(node.handlers[-1][2], node)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   260
    
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   261
    def visitTryFinally(self, node):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   262
        self.doSuite(node, node.body)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   263
        self.doPlainWordSuite(node.body, node.final)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   264
        
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   265
    def visitWith(self, node):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   266
        self.doSuite(node, node.body)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   267
        
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   268
    def visitGlobal(self, node):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   269
        # "global" statements don't execute like others (they don't call the
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   270
        # trace function), so don't record their line numbers.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   271
        pass
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   272
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   273
the_coverage = None
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   274
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   275
class CoverageException(Exception):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   276
    pass
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   277
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   278
class coverage:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   279
    # Name of the cache file (unless environment variable is set).
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   280
    cache_default = ".coverage"
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   281
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   282
    # Environment variable naming the cache file.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   283
    cache_env = "COVERAGE_FILE"
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   284
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   285
    # A dictionary with an entry for (Python source file name, line number
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   286
    # in that file) if that line has been executed.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   287
    c = {}
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   288
    
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   289
    # A map from canonical Python source file name to a dictionary in
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   290
    # which there's an entry for each line number that has been
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   291
    # executed.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   292
    cexecuted = {}
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   293
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   294
    # Cache of results of calling the analysis2() method, so that you can
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   295
    # specify both -r and -a without doing double work.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   296
    analysis_cache = {}
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   297
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   298
    # Cache of results of calling the canonical_filename() method, to
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   299
    # avoid duplicating work.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   300
    canonical_filename_cache = {}
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   301
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   302
    def __init__(self):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   303
        global the_coverage
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   304
        if the_coverage:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   305
            raise CoverageException("Only one coverage object allowed.")
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   306
        self.usecache = 1
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   307
        self.cache = None
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   308
        self.parallel_mode = False
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   309
        self.exclude_re = ''
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   310
        self.nesting = 0
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   311
        self.cstack = []
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   312
        self.xstack = []
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   313
        self.relative_dir = self.abs_file(os.curdir)+os.sep
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   314
        self.exclude('# *pragma[: ]*[nN][oO] *[cC][oO][vV][eE][rR]')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   315
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   316
    # t(f, x, y).  This method is passed to sys.settrace as a trace function.  
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   317
    # See [van Rossum 2001-07-20b, 9.2] for an explanation of sys.settrace and 
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   318
    # the arguments and return value of the trace function.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   319
    # See [van Rossum 2001-07-20a, 3.2] for a description of frame and code
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   320
    # objects.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   321
    
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   322
    def t(self, f, w, unused):                                 #pragma: no cover
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   323
        if w == 'line':
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   324
            self.c[(f.f_code.co_filename, f.f_lineno)] = 1
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   325
            #-for c in self.cstack:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   326
            #-    c[(f.f_code.co_filename, f.f_lineno)] = 1
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   327
        return self.t
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   328
    
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   329
    def help(self, error=None):     #pragma: no cover
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   330
        if error:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   331
            print error
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   332
            print
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   333
        print __doc__
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   334
        sys.exit(1)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   335
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   336
    def command_line(self, argv, help_fn=None):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   337
        import getopt
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   338
        help_fn = help_fn or self.help
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   339
        settings = {}
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   340
        optmap = {
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   341
            '-a': 'annotate',
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   342
            '-c': 'collect',
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   343
            '-d:': 'directory=',
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   344
            '-e': 'erase',
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   345
            '-h': 'help',
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   346
            '-i': 'ignore-errors',
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   347
            '-m': 'show-missing',
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   348
            '-p': 'parallel-mode',
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   349
            '-r': 'report',
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   350
            '-x': 'execute',
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   351
            '-o:': 'omit=',
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   352
            }
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   353
        short_opts = string.join(map(lambda o: o[1:], optmap.keys()), '')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   354
        long_opts = optmap.values()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   355
        options, args = getopt.getopt(argv, short_opts, long_opts)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   356
        for o, a in options:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   357
            if optmap.has_key(o):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   358
                settings[optmap[o]] = 1
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   359
            elif optmap.has_key(o + ':'):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   360
                settings[optmap[o + ':']] = a
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   361
            elif o[2:] in long_opts:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   362
                settings[o[2:]] = 1
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   363
            elif o[2:] + '=' in long_opts:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   364
                settings[o[2:]+'='] = a
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   365
            else:       #pragma: no cover
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   366
                pass    # Can't get here, because getopt won't return anything unknown.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   367
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   368
        if settings.get('help'):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   369
            help_fn()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   370
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   371
        for i in ['erase', 'execute']:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   372
            for j in ['annotate', 'report', 'collect']:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   373
                if settings.get(i) and settings.get(j):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   374
                    help_fn("You can't specify the '%s' and '%s' "
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   375
                              "options at the same time." % (i, j))
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   376
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   377
        args_needed = (settings.get('execute')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   378
                       or settings.get('annotate')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   379
                       or settings.get('report'))
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   380
        action = (settings.get('erase') 
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   381
                  or settings.get('collect')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   382
                  or args_needed)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   383
        if not action:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   384
            help_fn("You must specify at least one of -e, -x, -c, -r, or -a.")
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   385
        if not args_needed and args:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   386
            help_fn("Unexpected arguments: %s" % " ".join(args))
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   387
        
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   388
        self.parallel_mode = settings.get('parallel-mode')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   389
        self.get_ready()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   390
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   391
        if settings.get('erase'):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   392
            self.erase()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   393
        if settings.get('execute'):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   394
            if not args:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   395
                help_fn("Nothing to do.")
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   396
            sys.argv = args
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   397
            self.start()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   398
            import __main__
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   399
            sys.path[0] = os.path.dirname(sys.argv[0])
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   400
            execfile(sys.argv[0], __main__.__dict__)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   401
        if settings.get('collect'):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   402
            self.collect()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   403
        if not args:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   404
            args = self.cexecuted.keys()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   405
        
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   406
        ignore_errors = settings.get('ignore-errors')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   407
        show_missing = settings.get('show-missing')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   408
        directory = settings.get('directory=')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   409
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   410
        omit = settings.get('omit=')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   411
        if omit is not None:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   412
            omit = [self.abs_file(p) for p in omit.split(',')]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   413
        else:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   414
            omit = []
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   415
        
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   416
        if settings.get('report'):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   417
            self.report(args, show_missing, ignore_errors, omit_prefixes=omit)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   418
        if settings.get('annotate'):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   419
            self.annotate(args, directory, ignore_errors, omit_prefixes=omit)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   420
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   421
    def use_cache(self, usecache, cache_file=None):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   422
        self.usecache = usecache
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   423
        if cache_file and not self.cache:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   424
            self.cache_default = cache_file
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   425
        
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   426
    def get_ready(self, parallel_mode=False):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   427
        if self.usecache and not self.cache:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   428
            self.cache = os.environ.get(self.cache_env, self.cache_default)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   429
            if self.parallel_mode:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   430
                self.cache += "." + gethostname() + "." + str(os.getpid())
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   431
            self.restore()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   432
        self.analysis_cache = {}
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   433
        
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   434
    def start(self, parallel_mode=False):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   435
        self.get_ready()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   436
        if self.nesting == 0:                               #pragma: no cover
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   437
            sys.settrace(self.t)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   438
            if hasattr(threading, 'settrace'):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   439
                threading.settrace(self.t)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   440
        self.nesting += 1
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   441
        
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   442
    def stop(self):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   443
        self.nesting -= 1
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   444
        if self.nesting == 0:                               #pragma: no cover
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   445
            sys.settrace(None)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   446
            if hasattr(threading, 'settrace'):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   447
                threading.settrace(None)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   448
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   449
    def erase(self):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   450
        self.get_ready()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   451
        self.c = {}
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   452
        self.analysis_cache = {}
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   453
        self.cexecuted = {}
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   454
        if self.cache and os.path.exists(self.cache):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   455
            os.remove(self.cache)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   456
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   457
    def exclude(self, re):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   458
        if self.exclude_re:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   459
            self.exclude_re += "|"
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   460
        self.exclude_re += "(" + re + ")"
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   461
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   462
    def begin_recursive(self):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   463
        self.cstack.append(self.c)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   464
        self.xstack.append(self.exclude_re)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   465
        
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   466
    def end_recursive(self):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   467
        self.c = self.cstack.pop()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   468
        self.exclude_re = self.xstack.pop()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   469
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   470
    # save().  Save coverage data to the coverage cache.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   471
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   472
    def save(self):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   473
        if self.usecache and self.cache:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   474
            self.canonicalize_filenames()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   475
            cache = open(self.cache, 'wb')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   476
            import marshal
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   477
            marshal.dump(self.cexecuted, cache)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   478
            cache.close()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   479
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   480
    # restore().  Restore coverage data from the coverage cache (if it exists).
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   481
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   482
    def restore(self):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   483
        self.c = {}
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   484
        self.cexecuted = {}
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   485
        assert self.usecache
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   486
        if os.path.exists(self.cache):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   487
            self.cexecuted = self.restore_file(self.cache)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   488
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   489
    def restore_file(self, file_name):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   490
        try:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   491
            cache = open(file_name, 'rb')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   492
            import marshal
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   493
            cexecuted = marshal.load(cache)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   494
            cache.close()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   495
            if isinstance(cexecuted, types.DictType):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   496
                return cexecuted
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   497
            else:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   498
                return {}
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   499
        except:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   500
            return {}
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   501
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   502
    # collect(). Collect data in multiple files produced by parallel mode
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   503
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   504
    def collect(self):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   505
        cache_dir, local = os.path.split(self.cache)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   506
        for f in os.listdir(cache_dir or '.'):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   507
            if not f.startswith(local):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   508
                continue
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   509
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   510
            full_path = os.path.join(cache_dir, f)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   511
            cexecuted = self.restore_file(full_path)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   512
            self.merge_data(cexecuted)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   513
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   514
    def merge_data(self, new_data):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   515
        for file_name, file_data in new_data.items():
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   516
            if self.cexecuted.has_key(file_name):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   517
                self.merge_file_data(self.cexecuted[file_name], file_data)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   518
            else:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   519
                self.cexecuted[file_name] = file_data
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   520
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   521
    def merge_file_data(self, cache_data, new_data):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   522
        for line_number in new_data.keys():
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   523
            if not cache_data.has_key(line_number):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   524
                cache_data[line_number] = new_data[line_number]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   525
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   526
    def abs_file(self, filename):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   527
        """ Helper function to turn a filename into an absolute normalized
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   528
            filename.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   529
        """
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   530
        return os.path.normcase(os.path.abspath(os.path.realpath(filename)))
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   531
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   532
    def get_zip_data(self, filename):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   533
        """ Get data from `filename` if it is a zip file path, or return None
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   534
            if it is not.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   535
        """
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   536
        markers = ['.zip'+os.sep, '.egg'+os.sep]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   537
        for marker in markers:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   538
            if marker in filename:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   539
                parts = filename.split(marker)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   540
                try:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   541
                    zi = zipimport.zipimporter(parts[0]+marker[:-1])
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   542
                except zipimport.ZipImportError:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   543
                    continue
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   544
                try:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   545
                    data = zi.get_data(parts[1])
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   546
                except IOError:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   547
                    continue
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   548
                return data
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   549
        return None
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   550
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   551
    # canonical_filename(filename).  Return a canonical filename for the
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   552
    # file (that is, an absolute path with no redundant components and
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   553
    # normalized case).  See [GDR 2001-12-04b, 3.3].
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   554
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   555
    def canonical_filename(self, filename):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   556
        if not self.canonical_filename_cache.has_key(filename):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   557
            f = filename
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   558
            if os.path.isabs(f) and not os.path.exists(f):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   559
                if not self.get_zip_data(f):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   560
                    f = os.path.basename(f)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   561
            if not os.path.isabs(f):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   562
                for path in [os.curdir] + sys.path:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   563
                    g = os.path.join(path, f)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   564
                    if os.path.exists(g):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   565
                        f = g
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   566
                        break
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   567
            cf = self.abs_file(f)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   568
            self.canonical_filename_cache[filename] = cf
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   569
        return self.canonical_filename_cache[filename]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   570
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   571
    # canonicalize_filenames().  Copy results from "c" to "cexecuted", 
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   572
    # canonicalizing filenames on the way.  Clear the "c" map.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   573
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   574
    def canonicalize_filenames(self):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   575
        for filename, lineno in self.c.keys():
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   576
            if filename == '<string>':
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   577
                # Can't do anything useful with exec'd strings, so skip them.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   578
                continue
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   579
            f = self.canonical_filename(filename)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   580
            if not self.cexecuted.has_key(f):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   581
                self.cexecuted[f] = {}
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   582
            self.cexecuted[f][lineno] = 1
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   583
        self.c = {}
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   584
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   585
    # morf_filename(morf).  Return the filename for a module or file.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   586
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   587
    def morf_filename(self, morf):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   588
        if hasattr(morf, '__file__'):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   589
            f = morf.__file__
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   590
        else:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   591
            f = morf
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   592
        return self.canonical_filename(f)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   593
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   594
    # analyze_morf(morf).  Analyze the module or filename passed as
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   595
    # the argument.  If the source code can't be found, raise an error.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   596
    # Otherwise, return a tuple of (1) the canonical filename of the
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   597
    # source code for the module, (2) a list of lines of statements
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   598
    # in the source code, (3) a list of lines of excluded statements,
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   599
    # and (4), a map of line numbers to multi-line line number ranges, for
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   600
    # statements that cross lines.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   601
    
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   602
    def analyze_morf(self, morf):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   603
        if self.analysis_cache.has_key(morf):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   604
            return self.analysis_cache[morf]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   605
        filename = self.morf_filename(morf)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   606
        ext = os.path.splitext(filename)[1]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   607
        source, sourcef = None, None
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   608
        if ext == '.pyc':
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   609
            if not os.path.exists(filename[:-1]):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   610
                source = self.get_zip_data(filename[:-1])
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   611
                if not source:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   612
                    raise CoverageException(
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   613
                        "No source for compiled code '%s'." % filename
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   614
                        )
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   615
            filename = filename[:-1]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   616
        if not source:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   617
            sourcef = open(filename, 'rU')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   618
            source = sourcef.read()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   619
        try:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   620
            lines, excluded_lines, line_map = self.find_executable_statements(
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   621
                source, exclude=self.exclude_re
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   622
                )
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   623
        except SyntaxError, synerr:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   624
            raise CoverageException(
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   625
                "Couldn't parse '%s' as Python source: '%s' at line %d" %
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   626
                    (filename, synerr.msg, synerr.lineno)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   627
                )
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   628
        if sourcef:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   629
            sourcef.close()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   630
        result = filename, lines, excluded_lines, line_map
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   631
        self.analysis_cache[morf] = result
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   632
        return result
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   633
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   634
    def first_line_of_tree(self, tree):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   635
        while True:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   636
            if len(tree) == 3 and type(tree[2]) == type(1):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   637
                return tree[2]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   638
            tree = tree[1]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   639
    
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   640
    def last_line_of_tree(self, tree):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   641
        while True:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   642
            if len(tree) == 3 and type(tree[2]) == type(1):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   643
                return tree[2]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   644
            tree = tree[-1]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   645
    
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   646
    def find_docstring_pass_pair(self, tree, spots):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   647
        for i in range(1, len(tree)):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   648
            if self.is_string_constant(tree[i]) and self.is_pass_stmt(tree[i+1]):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   649
                first_line = self.first_line_of_tree(tree[i])
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   650
                last_line = self.last_line_of_tree(tree[i+1])
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   651
                self.record_multiline(spots, first_line, last_line)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   652
        
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   653
    def is_string_constant(self, tree):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   654
        try:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   655
            return tree[0] == symbol.stmt and tree[1][1][1][0] == symbol.expr_stmt
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   656
        except:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   657
            return False
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   658
        
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   659
    def is_pass_stmt(self, tree):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   660
        try:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   661
            return tree[0] == symbol.stmt and tree[1][1][1][0] == symbol.pass_stmt
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   662
        except:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   663
            return False
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   664
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   665
    def record_multiline(self, spots, i, j):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   666
        for l in range(i, j+1):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   667
            spots[l] = (i, j)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   668
            
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   669
    def get_suite_spots(self, tree, spots):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   670
        """ Analyze a parse tree to find suite introducers which span a number
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   671
            of lines.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   672
        """
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   673
        for i in range(1, len(tree)):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   674
            if type(tree[i]) == type(()):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   675
                if tree[i][0] == symbol.suite:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   676
                    # Found a suite, look back for the colon and keyword.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   677
                    lineno_colon = lineno_word = None
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   678
                    for j in range(i-1, 0, -1):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   679
                        if tree[j][0] == token.COLON:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   680
                            # Colons are never executed themselves: we want the
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   681
                            # line number of the last token before the colon.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   682
                            lineno_colon = self.last_line_of_tree(tree[j-1])
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   683
                        elif tree[j][0] == token.NAME:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   684
                            if tree[j][1] == 'elif':
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   685
                                # Find the line number of the first non-terminal
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   686
                                # after the keyword.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   687
                                t = tree[j+1]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   688
                                while t and token.ISNONTERMINAL(t[0]):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   689
                                    t = t[1]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   690
                                if t:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   691
                                    lineno_word = t[2]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   692
                            else:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   693
                                lineno_word = tree[j][2]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   694
                            break
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   695
                        elif tree[j][0] == symbol.except_clause:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   696
                            # "except" clauses look like:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   697
                            # ('except_clause', ('NAME', 'except', lineno), ...)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   698
                            if tree[j][1][0] == token.NAME:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   699
                                lineno_word = tree[j][1][2]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   700
                                break
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   701
                    if lineno_colon and lineno_word:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   702
                        # Found colon and keyword, mark all the lines
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   703
                        # between the two with the two line numbers.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   704
                        self.record_multiline(spots, lineno_word, lineno_colon)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   705
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   706
                    # "pass" statements are tricky: different versions of Python
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   707
                    # treat them differently, especially in the common case of a
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   708
                    # function with a doc string and a single pass statement.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   709
                    self.find_docstring_pass_pair(tree[i], spots)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   710
                    
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   711
                elif tree[i][0] == symbol.simple_stmt:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   712
                    first_line = self.first_line_of_tree(tree[i])
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   713
                    last_line = self.last_line_of_tree(tree[i])
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   714
                    if first_line != last_line:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   715
                        self.record_multiline(spots, first_line, last_line)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   716
                self.get_suite_spots(tree[i], spots)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   717
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   718
    def find_executable_statements(self, text, exclude=None):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   719
        # Find lines which match an exclusion pattern.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   720
        excluded = {}
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   721
        suite_spots = {}
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   722
        if exclude:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   723
            reExclude = re.compile(exclude)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   724
            lines = text.split('\n')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   725
            for i in range(len(lines)):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   726
                if reExclude.search(lines[i]):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   727
                    excluded[i+1] = 1
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   728
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   729
        # Parse the code and analyze the parse tree to find out which statements
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   730
        # are multiline, and where suites begin and end.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   731
        import parser
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   732
        tree = parser.suite(text+'\n\n').totuple(1)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   733
        self.get_suite_spots(tree, suite_spots)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   734
        #print "Suite spots:", suite_spots
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   735
        
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   736
        # Use the compiler module to parse the text and find the executable
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   737
        # statements.  We add newlines to be impervious to final partial lines.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   738
        statements = {}
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   739
        ast = compiler.parse(text+'\n\n')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   740
        visitor = StatementFindingAstVisitor(statements, excluded, suite_spots)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   741
        compiler.walk(ast, visitor, walker=visitor)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   742
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   743
        lines = statements.keys()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   744
        lines.sort()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   745
        excluded_lines = excluded.keys()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   746
        excluded_lines.sort()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   747
        return lines, excluded_lines, suite_spots
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   748
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   749
    # format_lines(statements, lines).  Format a list of line numbers
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   750
    # for printing by coalescing groups of lines as long as the lines
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   751
    # represent consecutive statements.  This will coalesce even if
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   752
    # there are gaps between statements, so if statements =
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   753
    # [1,2,3,4,5,10,11,12,13,14] and lines = [1,2,5,10,11,13,14] then
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   754
    # format_lines will return "1-2, 5-11, 13-14".
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   755
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   756
    def format_lines(self, statements, lines):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   757
        pairs = []
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   758
        i = 0
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   759
        j = 0
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   760
        start = None
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   761
        pairs = []
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   762
        while i < len(statements) and j < len(lines):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   763
            if statements[i] == lines[j]:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   764
                if start == None:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   765
                    start = lines[j]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   766
                end = lines[j]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   767
                j = j + 1
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   768
            elif start:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   769
                pairs.append((start, end))
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   770
                start = None
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   771
            i = i + 1
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   772
        if start:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   773
            pairs.append((start, end))
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   774
        def stringify(pair):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   775
            start, end = pair
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   776
            if start == end:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   777
                return "%d" % start
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   778
            else:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   779
                return "%d-%d" % (start, end)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   780
        ret = string.join(map(stringify, pairs), ", ")
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   781
        return ret
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   782
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   783
    # Backward compatibility with version 1.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   784
    def analysis(self, morf):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   785
        f, s, _, m, mf = self.analysis2(morf)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   786
        return f, s, m, mf
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   787
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   788
    def analysis2(self, morf):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   789
        filename, statements, excluded, line_map = self.analyze_morf(morf)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   790
        self.canonicalize_filenames()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   791
        if not self.cexecuted.has_key(filename):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   792
            self.cexecuted[filename] = {}
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   793
        missing = []
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   794
        for line in statements:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   795
            lines = line_map.get(line, [line, line])
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   796
            for l in range(lines[0], lines[1]+1):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   797
                if self.cexecuted[filename].has_key(l):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   798
                    break
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   799
            else:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   800
                missing.append(line)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   801
        return (filename, statements, excluded, missing,
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   802
                self.format_lines(statements, missing))
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   803
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   804
    def relative_filename(self, filename):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   805
        """ Convert filename to relative filename from self.relative_dir.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   806
        """
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   807
        return filename.replace(self.relative_dir, "")
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   808
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   809
    def morf_name(self, morf):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   810
        """ Return the name of morf as used in report.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   811
        """
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   812
        if hasattr(morf, '__name__'):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   813
            return morf.__name__
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   814
        else:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   815
            return self.relative_filename(os.path.splitext(morf)[0])
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   816
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   817
    def filter_by_prefix(self, morfs, omit_prefixes):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   818
        """ Return list of morfs where the morf name does not begin
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   819
            with any one of the omit_prefixes.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   820
        """
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   821
        filtered_morfs = []
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   822
        for morf in morfs:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   823
            for prefix in omit_prefixes:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   824
                if self.morf_name(morf).startswith(prefix):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   825
                    break
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   826
            else:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   827
                filtered_morfs.append(morf)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   828
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   829
        return filtered_morfs
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   830
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   831
    def morf_name_compare(self, x, y):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   832
        return cmp(self.morf_name(x), self.morf_name(y))
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   833
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   834
    def report(self, morfs, show_missing=1, ignore_errors=0, file=None, omit_prefixes=[]):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   835
        if not isinstance(morfs, types.ListType):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   836
            morfs = [morfs]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   837
        # On windows, the shell doesn't expand wildcards.  Do it here.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   838
        globbed = []
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   839
        for morf in morfs:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   840
            if isinstance(morf, strclass):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   841
                globbed.extend(glob.glob(morf))
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   842
            else:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   843
                globbed.append(morf)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   844
        morfs = globbed
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   845
        
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   846
        morfs = self.filter_by_prefix(morfs, omit_prefixes)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   847
        morfs.sort(self.morf_name_compare)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   848
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   849
        max_name = max([5,] + map(len, map(self.morf_name, morfs)))
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   850
        fmt_name = "%%- %ds  " % max_name
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   851
        fmt_err = fmt_name + "%s: %s"
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   852
        header = fmt_name % "Name" + " Stmts   Exec  Cover"
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   853
        fmt_coverage = fmt_name + "% 6d % 6d % 5d%%"
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   854
        if show_missing:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   855
            header = header + "   Missing"
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   856
            fmt_coverage = fmt_coverage + "   %s"
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   857
        if not file:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   858
            file = sys.stdout
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   859
        print >>file, header
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   860
        print >>file, "-" * len(header)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   861
        total_statements = 0
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   862
        total_executed = 0
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   863
        for morf in morfs:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   864
            name = self.morf_name(morf)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   865
            try:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   866
                _, statements, _, missing, readable  = self.analysis2(morf)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   867
                n = len(statements)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   868
                m = n - len(missing)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   869
                if n > 0:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   870
                    pc = 100.0 * m / n
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   871
                else:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   872
                    pc = 100.0
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   873
                args = (name, n, m, pc)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   874
                if show_missing:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   875
                    args = args + (readable,)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   876
                print >>file, fmt_coverage % args
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   877
                total_statements = total_statements + n
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   878
                total_executed = total_executed + m
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   879
            except KeyboardInterrupt:                       #pragma: no cover
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   880
                raise
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   881
            except:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   882
                if not ignore_errors:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   883
                    typ, msg = sys.exc_info()[:2]
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   884
                    print >>file, fmt_err % (name, typ, msg)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   885
        if len(morfs) > 1:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   886
            print >>file, "-" * len(header)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   887
            if total_statements > 0:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   888
                pc = 100.0 * total_executed / total_statements
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   889
            else:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   890
                pc = 100.0
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   891
            args = ("TOTAL", total_statements, total_executed, pc)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   892
            if show_missing:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   893
                args = args + ("",)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   894
            print >>file, fmt_coverage % args
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   895
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   896
    # annotate(morfs, ignore_errors).
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   897
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   898
    blank_re = re.compile(r"\s*(#|$)")
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   899
    else_re = re.compile(r"\s*else\s*:\s*(#|$)")
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   900
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   901
    def annotate(self, morfs, directory=None, ignore_errors=0, omit_prefixes=[]):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   902
        morfs = self.filter_by_prefix(morfs, omit_prefixes)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   903
        for morf in morfs:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   904
            try:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   905
                filename, statements, excluded, missing, _ = self.analysis2(morf)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   906
                self.annotate_file(filename, statements, excluded, missing, directory)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   907
            except KeyboardInterrupt:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   908
                raise
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   909
            except:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   910
                if not ignore_errors:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   911
                    raise
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   912
                
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   913
    def annotate_file(self, filename, statements, excluded, missing, directory=None):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   914
        source = open(filename, 'r')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   915
        if directory:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   916
            dest_file = os.path.join(directory,
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   917
                                     os.path.basename(filename)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   918
                                     + ',cover')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   919
        else:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   920
            dest_file = filename + ',cover'
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   921
        dest = open(dest_file, 'w')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   922
        lineno = 0
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   923
        i = 0
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   924
        j = 0
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   925
        covered = 1
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   926
        while 1:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   927
            line = source.readline()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   928
            if line == '':
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   929
                break
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   930
            lineno = lineno + 1
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   931
            while i < len(statements) and statements[i] < lineno:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   932
                i = i + 1
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   933
            while j < len(missing) and missing[j] < lineno:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   934
                j = j + 1
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   935
            if i < len(statements) and statements[i] == lineno:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   936
                covered = j >= len(missing) or missing[j] > lineno
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   937
            if self.blank_re.match(line):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   938
                dest.write('  ')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   939
            elif self.else_re.match(line):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   940
                # Special logic for lines containing only 'else:'.  
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   941
                # See [GDR 2001-12-04b, 3.2].
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   942
                if i >= len(statements) and j >= len(missing):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   943
                    dest.write('! ')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   944
                elif i >= len(statements) or j >= len(missing):
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   945
                    dest.write('> ')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   946
                elif statements[i] == missing[j]:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   947
                    dest.write('! ')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   948
                else:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   949
                    dest.write('> ')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   950
            elif lineno in excluded:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   951
                dest.write('- ')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   952
            elif covered:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   953
                dest.write('> ')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   954
            else:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   955
                dest.write('! ')
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   956
            dest.write(line)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   957
        source.close()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   958
        dest.close()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   959
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   960
# Singleton object.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   961
the_coverage = coverage()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   962
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   963
# Module functions call methods in the singleton object.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   964
def use_cache(*args, **kw): 
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   965
    return the_coverage.use_cache(*args, **kw)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   966
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   967
def start(*args, **kw): 
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   968
    return the_coverage.start(*args, **kw)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   969
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   970
def stop(*args, **kw): 
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   971
    return the_coverage.stop(*args, **kw)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   972
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   973
def erase(*args, **kw): 
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   974
    return the_coverage.erase(*args, **kw)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   975
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   976
def begin_recursive(*args, **kw): 
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   977
    return the_coverage.begin_recursive(*args, **kw)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   978
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   979
def end_recursive(*args, **kw): 
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   980
    return the_coverage.end_recursive(*args, **kw)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   981
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   982
def exclude(*args, **kw): 
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   983
    return the_coverage.exclude(*args, **kw)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   984
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   985
def analysis(*args, **kw): 
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   986
    return the_coverage.analysis(*args, **kw)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   987
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   988
def analysis2(*args, **kw): 
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   989
    return the_coverage.analysis2(*args, **kw)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   990
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   991
def report(*args, **kw): 
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   992
    return the_coverage.report(*args, **kw)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   993
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   994
def annotate(*args, **kw): 
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   995
    return the_coverage.annotate(*args, **kw)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   996
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   997
def annotate_file(*args, **kw): 
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   998
    return the_coverage.annotate_file(*args, **kw)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
   999
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1000
# Save coverage data when Python exits.  (The atexit module wasn't
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1001
# introduced until Python 2.0, so use sys.exitfunc when it's not
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1002
# available.)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1003
try:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1004
    import atexit
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1005
    atexit.register(the_coverage.save)
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1006
except ImportError:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1007
    sys.exitfunc = the_coverage.save
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1008
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1009
def main():
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1010
    the_coverage.command_line(sys.argv[1:])
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1011
    
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1012
# Command-line interface.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1013
if __name__ == '__main__':
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1014
    main()
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1015
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1016
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1017
# A. REFERENCES
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1018
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1019
# [GDR 2001-12-04a] "Statement coverage for Python"; Gareth Rees;
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1020
# Ravenbrook Limited; 2001-12-04;
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1021
# <http://www.nedbatchelder.com/code/modules/rees-coverage.html>.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1022
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1023
# [GDR 2001-12-04b] "Statement coverage for Python: design and
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1024
# analysis"; Gareth Rees; Ravenbrook Limited; 2001-12-04;
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1025
# <http://www.nedbatchelder.com/code/modules/rees-design.html>.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1026
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1027
# [van Rossum 2001-07-20a] "Python Reference Manual (releae 2.1.1)";
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1028
# Guide van Rossum; 2001-07-20;
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1029
# <http://www.python.org/doc/2.1.1/ref/ref.html>.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1030
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1031
# [van Rossum 2001-07-20b] "Python Library Reference"; Guido van Rossum;
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1032
# 2001-07-20; <http://www.python.org/doc/2.1.1/lib/lib.html>.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1033
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1034
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1035
# B. DOCUMENT HISTORY
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1036
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1037
# 2001-12-04 GDR Created.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1038
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1039
# 2001-12-06 GDR Added command-line interface and source code
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1040
# annotation.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1041
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1042
# 2001-12-09 GDR Moved design and interface to separate documents.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1043
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1044
# 2001-12-10 GDR Open cache file as binary on Windows.  Allow
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1045
# simultaneous -e and -x, or -a and -r.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1046
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1047
# 2001-12-12 GDR Added command-line help.  Cache analysis so that it
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1048
# only needs to be done once when you specify -a and -r.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1049
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1050
# 2001-12-13 GDR Improved speed while recording.  Portable between
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1051
# Python 1.5.2 and 2.1.1.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1052
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1053
# 2002-01-03 GDR Module-level functions work correctly.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1054
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1055
# 2002-01-07 GDR Update sys.path when running a file with the -x option,
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1056
# so that it matches the value the program would get if it were run on
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1057
# its own.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1058
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1059
# 2004-12-12 NMB Significant code changes.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1060
# - Finding executable statements has been rewritten so that docstrings and
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1061
#   other quirks of Python execution aren't mistakenly identified as missing
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1062
#   lines.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1063
# - Lines can be excluded from consideration, even entire suites of lines.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1064
# - The filesystem cache of covered lines can be disabled programmatically.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1065
# - Modernized the code.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1066
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1067
# 2004-12-14 NMB Minor tweaks.  Return 'analysis' to its original behavior
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1068
# and add 'analysis2'.  Add a global for 'annotate', and factor it, adding
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1069
# 'annotate_file'.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1070
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1071
# 2004-12-31 NMB Allow for keyword arguments in the module global functions.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1072
# Thanks, Allen.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1073
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1074
# 2005-12-02 NMB Call threading.settrace so that all threads are measured.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1075
# Thanks Martin Fuzzey. Add a file argument to report so that reports can be 
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1076
# captured to a different destination.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1077
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1078
# 2005-12-03 NMB coverage.py can now measure itself.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1079
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1080
# 2005-12-04 NMB Adapted Greg Rogers' patch for using relative filenames,
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1081
# and sorting and omitting files to report on.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1082
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1083
# 2006-07-23 NMB Applied Joseph Tate's patch for function decorators.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1084
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1085
# 2006-08-21 NMB Applied Sigve Tjora and Mark van der Wal's fixes for argument
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1086
# handling.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1087
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1088
# 2006-08-22 NMB Applied Geoff Bache's parallel mode patch.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1089
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1090
# 2006-08-23 NMB Refactorings to improve testability.  Fixes to command-line
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1091
# logic for parallel mode and collect.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1092
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1093
# 2006-08-25 NMB "#pragma: nocover" is excluded by default.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1094
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1095
# 2006-09-10 NMB Properly ignore docstrings and other constant expressions that
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1096
# appear in the middle of a function, a problem reported by Tim Leslie.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1097
# Minor changes to avoid lint warnings.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1098
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1099
# 2006-09-17 NMB coverage.erase() shouldn't clobber the exclude regex.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1100
# Change how parallel mode is invoked, and fix erase() so that it erases the
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1101
# cache when called programmatically.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1102
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1103
# 2007-07-21 NMB In reports, ignore code executed from strings, since we can't
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1104
# do anything useful with it anyway.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1105
# Better file handling on Linux, thanks Guillaume Chazarain.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1106
# Better shell support on Windows, thanks Noel O'Boyle.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1107
# Python 2.2 support maintained, thanks Catherine Proulx.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1108
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1109
# 2007-07-22 NMB Python 2.5 now fully supported. The method of dealing with
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1110
# multi-line statements is now less sensitive to the exact line that Python
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1111
# reports during execution. Pass statements are handled specially so that their
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1112
# disappearance during execution won't throw off the measurement.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1113
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1114
# 2007-07-23 NMB Now Python 2.5 is *really* fully supported: the body of the
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1115
# new with statement is counted as executable.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1116
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1117
# 2007-07-29 NMB Better packaging.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1118
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1119
# 2007-09-30 NMB Don't try to predict whether a file is Python source based on
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1120
# the extension. Extensionless files are often Pythons scripts. Instead, simply
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1121
# parse the file and catch the syntax errors.  Hat tip to Ben Finney.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1122
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1123
# 2008-05-25 NMB Open files in rU mode to avoid line ending craziness.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1124
# Thanks, Edward Loper.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1125
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1126
# 2008-09-14 NMB Add support for finding source files in eggs.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1127
# Don't check for morf's being instances of ModuleType, instead use duck typing
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1128
# so that pseudo-modules can participate. Thanks, Imri Goldberg.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1129
# Use os.realpath as part of the fixing of filenames so that symlinks won't
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1130
# confuse things.  Thanks, Patrick Mezard.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1131
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1132
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1133
# C. COPYRIGHT AND LICENCE
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1134
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1135
# Copyright 2001 Gareth Rees.  All rights reserved.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1136
# Copyright 2004-2008 Ned Batchelder.  All rights reserved.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1137
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1138
# Redistribution and use in source and binary forms, with or without
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1139
# modification, are permitted provided that the following conditions are
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1140
# met:
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1141
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1142
# 1. Redistributions of source code must retain the above copyright
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1143
#    notice, this list of conditions and the following disclaimer.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1144
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1145
# 2. Redistributions in binary form must reproduce the above copyright
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1146
#    notice, this list of conditions and the following disclaimer in the
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1147
#    documentation and/or other materials provided with the
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1148
#    distribution.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1149
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1150
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1151
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1152
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1153
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1154
# HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1155
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1156
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1157
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1158
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1159
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1160
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1161
# DAMAGE.
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1162
#
042aafcd7dce Add support for coverage to our testing system.
Augie Fackler <durin42@gmail.com>
parents:
diff changeset
  1163
# $Id: coverage.py 100 2008-10-12 12:08:22Z nedbat $