Updated coverage.py to version 4.1.0.

Sun, 24 Jul 2016 12:01:01 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sun, 24 Jul 2016 12:01:01 +0200
changeset 5051
3586ebd9fac8
parent 5047
04e5dfbd3f3d
child 5053
dac4920b55ad

Updated coverage.py to version 4.1.0.

DataViews/PyCoverageDialog.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/__init__.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/annotate.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/backunittest.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/backward.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/bytecode.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/cmdline.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/collector.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/config.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/control.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/data.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/debug.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/doc/AUTHORS.txt file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/doc/CHANGES.rst file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/doc/CHANGES.txt file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/doc/README.rst file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/env.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/execfile.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/files.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/html.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/misc.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/monkey.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/parser.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/phystokens.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/pickle2json.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/plugin.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/plugin_support.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/python.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/pytracer.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/report.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/results.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/summary.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/templite.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/test_helpers.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/version.py file | annotate | diff | comparison | revisions
DebugClients/Python/coverage/xmlreport.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/__init__.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/annotate.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/backward.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/bytecode.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/cmdline.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/collector.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/config.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/control.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/data.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/debug.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/doc/AUTHORS.txt file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/doc/CHANGES.rst file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/doc/CHANGES.txt file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/doc/README.rst file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/execfile.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/files.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/html.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/misc.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/monkey.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/parser.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/phystokens.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/plugin.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/plugin_support.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/python.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/pytracer.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/report.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/results.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/summary.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/templite.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/test_helpers.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/version.py file | annotate | diff | comparison | revisions
DebugClients/Python3/coverage/xmlreport.py file | annotate | diff | comparison | revisions
Documentation/Help/source.qch file | annotate | diff | comparison | revisions
Documentation/Source/eric6.QScintilla.Editor.html file | annotate | diff | comparison | revisions
QScintilla/Editor.py file | annotate | diff | comparison | revisions
changelog file | annotate | diff | comparison | revisions
--- a/DataViews/PyCoverageDialog.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DataViews/PyCoverageDialog.py	Sun Jul 24 12:01:01 2016 +0200
@@ -22,7 +22,7 @@
 from .Ui_PyCoverageDialog import Ui_PyCoverageDialog
 
 import Utilities
-from coverage import coverage
+from coverage import Coverage
 from coverage.misc import CoverageException
 
 
@@ -168,7 +168,7 @@
             self.path = os.path.dirname(cfn)
         files.sort()
         
-        cover = coverage(data_file=self.cfn)
+        cover = Coverage(data_file=self.cfn)
         cover.load()
         
         # set the exclude pattern
@@ -315,7 +315,7 @@
         itm = self.resultList.currentItem()
         fn = itm.text(0)
         
-        cover = coverage(data_file=self.cfn)
+        cover = Coverage(data_file=self.cfn)
         cover.exclude(self.excludeList[0])
         cover.load()
         cover.annotate([fn], None, True)
@@ -337,7 +337,7 @@
             itm = self.resultList.topLevelItem(index)
             files.append(itm.text(0))
         
-        cover = coverage(data_file=self.cfn)
+        cover = Coverage(data_file=self.cfn)
         cover.exclude(self.excludeList[0])
         cover.load()
         
@@ -365,7 +365,7 @@
         This method erases the collected coverage data that is
         stored in the .coverage file.
         """
-        cover = coverage(data_file=self.cfn)
+        cover = Coverage(data_file=self.cfn)
         cover.load()
         cover.erase()
         
--- a/DebugClients/Python/coverage/__init__.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/__init__.py	Sun Jul 24 12:01:01 2016 +0200
@@ -14,6 +14,7 @@
 from coverage.data import CoverageData
 from coverage.misc import CoverageException
 from coverage.plugin import CoveragePlugin, FileTracer, FileReporter
+from coverage.pytracer import PyTracer
 
 # Backward compatibility.
 coverage = Coverage
--- a/DebugClients/Python/coverage/annotate.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/annotate.py	Sun Jul 24 12:01:01 2016 +0200
@@ -8,8 +8,12 @@
 import re
 
 from coverage.files import flat_rootname
+from coverage.misc import isolate_module
 from coverage.report import Reporter
 
+os = isolate_module(os)
+
+
 class AnnotateReporter(Reporter):
     """Generate annotated source files showing line coverage.
 
--- a/DebugClients/Python/coverage/backunittest.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/backunittest.py	Sun Jul 24 12:01:01 2016 +0200
@@ -40,3 +40,6 @@
     if not unittest_has('assertRegex'):
         def assertRegex(self, *args, **kwargs):
             return self.assertRegexpMatches(*args, **kwargs)
+
+#
+# eflag: FileType = Python2
--- a/DebugClients/Python/coverage/backward.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/backward.py	Sun Jul 24 12:01:01 2016 +0200
@@ -49,6 +49,15 @@
 except NameError:
     range = range
 
+# shlex.quote is new, but there's an undocumented implementation in "pipes",
+# who knew!?
+try:
+    from shlex import quote as shlex_quote
+except ImportError:
+    # Useful function, available under a different (undocumented) name
+    # in Python versions earlier than 3.3.
+    from pipes import quote as shlex_quote
+
 # A function to iterate listlessly over a dict's items.
 try:
     {}.iteritems
@@ -84,10 +93,6 @@
         """Produce a byte string with the ints from `byte_values`."""
         return bytes(byte_values)
 
-    def byte_to_int(byte_value):
-        """Turn an element of a bytes object into an int."""
-        return byte_value
-
     def bytes_to_ints(bytes_value):
         """Turn a bytes object into a sequence of ints."""
         # In Python 3, iterating bytes gives ints.
@@ -102,10 +107,6 @@
         """Produce a byte string with the ints from `byte_values`."""
         return "".join(chr(b) for b in byte_values)
 
-    def byte_to_int(byte_value):
-        """Turn an element of a bytes object into an int."""
-        return ord(byte_value)
-
     def bytes_to_ints(bytes_value):
         """Turn a bytes object into a sequence of ints."""
         for byte in bytes_value:
@@ -142,11 +143,12 @@
     PYC_MAGIC_NUMBER = imp.get_magic()
 
 
-def import_local_file(modname):
+def import_local_file(modname, modfile=None):
     """Import a local file as a module.
 
     Opens a file in the current directory named `modname`.py, imports it
-    as `modname`, and returns the module object.
+    as `modname`, and returns the module object.  `modfile` is the file to
+    import if it isn't in the current directory.
 
     """
     try:
@@ -154,7 +156,8 @@
     except ImportError:
         SourceFileLoader = None
 
-    modfile = modname + '.py'
+    if modfile is None:
+        modfile = modname + '.py'
     if SourceFileLoader:
         mod = SourceFileLoader(modname, modfile).load_module()
     else:
--- a/DebugClients/Python/coverage/bytecode.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/bytecode.py	Sun Jul 24 12:01:01 2016 +0200
@@ -3,73 +3,8 @@
 
 """Bytecode manipulation for coverage.py"""
 
-import opcode
 import types
 
-from coverage.backward import byte_to_int
-
-
-class ByteCode(object):
-    """A single bytecode."""
-    def __init__(self):
-        # The offset of this bytecode in the code object.
-        self.offset = -1
-
-        # The opcode, defined in the `opcode` module.
-        self.op = -1
-
-        # The argument, a small integer, whose meaning depends on the opcode.
-        self.arg = -1
-
-        # The offset in the code object of the next bytecode.
-        self.next_offset = -1
-
-        # The offset to jump to.
-        self.jump_to = -1
-
-
-class ByteCodes(object):
-    """Iterator over byte codes in `code`.
-
-    This handles the logic of EXTENDED_ARG byte codes internally.  Those byte
-    codes are not returned by this iterator.
-
-    Returns `ByteCode` objects.
-
-    """
-    def __init__(self, code):
-        self.code = code
-
-    def __getitem__(self, i):
-        return byte_to_int(self.code[i])
-
-    def __iter__(self):
-        offset = 0
-        ext_arg = 0
-        while offset < len(self.code):
-            bc = ByteCode()
-            bc.op = self[offset]
-            bc.offset = offset
-
-            next_offset = offset+1
-            if bc.op >= opcode.HAVE_ARGUMENT:
-                bc.arg = ext_arg + self[offset+1] + 256*self[offset+2]
-                next_offset += 2
-
-                label = -1
-                if bc.op in opcode.hasjrel:
-                    label = next_offset + bc.arg
-                elif bc.op in opcode.hasjabs:
-                    label = bc.arg
-                bc.jump_to = label
-
-            bc.next_offset = offset = next_offset
-            if bc.op == opcode.EXTENDED_ARG:
-                ext_arg = bc.arg * 256*256
-            else:
-                ext_arg = 0
-                yield bc
-
 
 class CodeObjects(object):
     """Iterate over all the code objects in `code`."""
--- a/DebugClients/Python/coverage/cmdline.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/cmdline.py	Sun Jul 24 12:01:01 2016 +0200
@@ -7,9 +7,11 @@
 import optparse
 import os.path
 import sys
+import textwrap
 import traceback
 
 from coverage import env
+from coverage.collector import CTracer
 from coverage.execfile import run_python_file, run_python_module
 from coverage.misc import CoverageException, ExceptionDuringRun, NoSource
 from coverage.debug import info_formatter, info_header
@@ -20,105 +22,117 @@
 
     append = optparse.make_option(
         '-a', '--append', action='store_true',
-        help="Append coverage data to .coverage, otherwise it is started "
-                "clean with each run."
-        )
+        help="Append coverage data to .coverage, otherwise it is started clean with each run.",
+    )
     branch = optparse.make_option(
         '', '--branch', action='store_true',
-        help="Measure branch coverage in addition to statement coverage."
-        )
+        help="Measure branch coverage in addition to statement coverage.",
+    )
     CONCURRENCY_CHOICES = [
         "thread", "gevent", "greenlet", "eventlet", "multiprocessing",
     ]
     concurrency = optparse.make_option(
         '', '--concurrency', action='store', metavar="LIB",
         choices=CONCURRENCY_CHOICES,
-        help="Properly measure code using a concurrency library. "
-            "Valid values are: %s." % ", ".join(CONCURRENCY_CHOICES)
-        )
+        help=(
+            "Properly measure code using a concurrency library. "
+            "Valid values are: %s."
+        ) % ", ".join(CONCURRENCY_CHOICES),
+    )
     debug = optparse.make_option(
         '', '--debug', action='store', metavar="OPTS",
-        help="Debug options, separated by commas"
-        )
+        help="Debug options, separated by commas",
+    )
     directory = optparse.make_option(
         '-d', '--directory', action='store', metavar="DIR",
-        help="Write the output files to DIR."
-        )
+        help="Write the output files to DIR.",
+    )
     fail_under = optparse.make_option(
         '', '--fail-under', action='store', metavar="MIN", type="int",
-        help="Exit with a status of 2 if the total coverage is less than MIN."
-        )
+        help="Exit with a status of 2 if the total coverage is less than MIN.",
+    )
     help = optparse.make_option(
         '-h', '--help', action='store_true',
-        help="Get help on this command."
-        )
+        help="Get help on this command.",
+    )
     ignore_errors = optparse.make_option(
         '-i', '--ignore-errors', action='store_true',
-        help="Ignore errors while reading source files."
-        )
+        help="Ignore errors while reading source files.",
+    )
     include = optparse.make_option(
         '', '--include', action='store',
         metavar="PAT1,PAT2,...",
-        help="Include only files whose paths match one of these patterns. "
-                "Accepts shell-style wildcards, which must be quoted."
-        )
+        help=(
+            "Include only files whose paths match one of these patterns. "
+            "Accepts shell-style wildcards, which must be quoted."
+        ),
+    )
     pylib = optparse.make_option(
         '-L', '--pylib', action='store_true',
-        help="Measure coverage even inside the Python installed library, "
-                "which isn't done by default."
-        )
+        help=(
+            "Measure coverage even inside the Python installed library, "
+            "which isn't done by default."
+        ),
+    )
     show_missing = optparse.make_option(
         '-m', '--show-missing', action='store_true',
-        help="Show line numbers of statements in each module that weren't "
-                "executed."
-        )
+        help="Show line numbers of statements in each module that weren't executed.",
+    )
     skip_covered = optparse.make_option(
         '--skip-covered', action='store_true',
-        help="Skip files with 100% coverage."
-        )
+        help="Skip files with 100% coverage.",
+    )
     omit = optparse.make_option(
         '', '--omit', action='store',
         metavar="PAT1,PAT2,...",
-        help="Omit files whose paths match one of these patterns. "
-                "Accepts shell-style wildcards, which must be quoted."
-        )
+        help=(
+            "Omit files whose paths match one of these patterns. "
+            "Accepts shell-style wildcards, which must be quoted."
+        ),
+    )
     output_xml = optparse.make_option(
         '-o', '', action='store', dest="outfile",
         metavar="OUTFILE",
-        help="Write the XML report to this file. Defaults to 'coverage.xml'"
-        )
+        help="Write the XML report to this file. Defaults to 'coverage.xml'",
+    )
     parallel_mode = optparse.make_option(
         '-p', '--parallel-mode', action='store_true',
-        help="Append the machine name, process id and random number to the "
-                ".coverage data file name to simplify collecting data from "
-                "many processes."
-        )
+        help=(
+            "Append the machine name, process id and random number to the "
+            ".coverage data file name to simplify collecting data from "
+            "many processes."
+        ),
+    )
     module = optparse.make_option(
         '-m', '--module', action='store_true',
-        help="<pyfile> is an importable Python module, not a script path, "
-                "to be run as 'python -m' would run it."
-        )
+        help=(
+            "<pyfile> is an importable Python module, not a script path, "
+            "to be run as 'python -m' would run it."
+        ),
+    )
     rcfile = optparse.make_option(
         '', '--rcfile', action='store',
-        help="Specify configuration file.  Defaults to '.coveragerc'"
-        )
+        help="Specify configuration file.  Defaults to '.coveragerc'",
+    )
     source = optparse.make_option(
         '', '--source', action='store', metavar="SRC1,SRC2,...",
-        help="A list of packages or directories of code to be measured."
-        )
+        help="A list of packages or directories of code to be measured.",
+    )
     timid = optparse.make_option(
         '', '--timid', action='store_true',
-        help="Use a simpler but slower trace method.  Try this if you get "
-                "seemingly impossible results!"
-        )
+        help=(
+            "Use a simpler but slower trace method.  Try this if you get "
+            "seemingly impossible results!"
+        ),
+    )
     title = optparse.make_option(
         '', '--title', action='store', metavar="TITLE",
-        help="A text string to use as the title on the HTML."
-        )
+        help="A text string to use as the title on the HTML.",
+    )
     version = optparse.make_option(
         '', '--version', action='store_true',
-        help="Display version information and exit."
-        )
+        help="Display version information and exit.",
+    )
 
 
 class CoverageOptionParser(optparse.OptionParser, object):
@@ -202,9 +216,7 @@
 class CmdOptionParser(CoverageOptionParser):
     """Parse one of the new-style commands for coverage.py."""
 
-    def __init__(self, action, options=None, defaults=None, usage=None,
-                description=None
-                ):
+    def __init__(self, action, options=None, defaults=None, usage=None, description=None):
         """Create an OptionParser for a coverage.py command.
 
         `action` is the slug to put into `options.action`.
@@ -217,7 +229,6 @@
         if usage:
             usage = "%prog " + usage
         super(CmdOptionParser, self).__init__(
-            prog="coverage %s" % action,
             usage=usage,
             description=description,
         )
@@ -231,6 +242,14 @@
         # results, and they will compare equal to objects.
         return (other == "<CmdOptionParser:%s>" % self.cmd)
 
+    def get_prog_name(self):
+        """Override of an undocumented function in optparse.OptionParser."""
+        program_name = super(CmdOptionParser, self).get_prog_name()
+
+        # Include the sub-command for this parser as part of the command.
+        return "%(command)s %(subcommand)s" % {'command': program_name, 'subcommand': self.cmd}
+
+
 GLOBAL_ARGS = [
     Opts.debug,
     Opts.help,
@@ -238,48 +257,60 @@
     ]
 
 CMDS = {
-    'annotate': CmdOptionParser("annotate",
+    'annotate': CmdOptionParser(
+        "annotate",
         [
             Opts.directory,
             Opts.ignore_errors,
             Opts.include,
             Opts.omit,
             ] + GLOBAL_ARGS,
-        usage = "[options] [modules]",
-        description = "Make annotated copies of the given files, marking "
-            "statements that are executed with > and statements that are "
-            "missed with !."
+        usage="[options] [modules]",
+        description=(
+            "Make annotated copies of the given files, marking statements that are executed "
+            "with > and statements that are missed with !."
         ),
+    ),
 
-    'combine': CmdOptionParser("combine", GLOBAL_ARGS,
-        usage = "<path1> <path2> ... <pathN>",
-        description = "Combine data from multiple coverage files collected "
+    'combine': CmdOptionParser(
+        "combine",
+        GLOBAL_ARGS,
+        usage="<path1> <path2> ... <pathN>",
+        description=(
+            "Combine data from multiple coverage files collected "
             "with 'run -p'.  The combined results are written to a single "
             "file representing the union of the data. The positional "
             "arguments are data files or directories containing data files. "
             "If no paths are provided, data files in the default data file's "
             "directory are combined."
         ),
+    ),
 
-    'debug': CmdOptionParser("debug", GLOBAL_ARGS,
-        usage = "<topic>",
-        description = "Display information on the internals of coverage.py, "
+    'debug': CmdOptionParser(
+        "debug", GLOBAL_ARGS,
+        usage="<topic>",
+        description=(
+            "Display information on the internals of coverage.py, "
             "for diagnosing problems. "
             "Topics are 'data' to show a summary of the collected data, "
             "or 'sys' to show installation information."
         ),
+    ),
 
-    'erase': CmdOptionParser("erase", GLOBAL_ARGS,
-        usage = " ",
-        description = "Erase previously collected coverage data."
-        ),
+    'erase': CmdOptionParser(
+        "erase", GLOBAL_ARGS,
+        usage=" ",
+        description="Erase previously collected coverage data.",
+    ),
 
-    'help': CmdOptionParser("help", GLOBAL_ARGS,
-        usage = "[command]",
-        description = "Describe how to use coverage.py"
-        ),
+    'help': CmdOptionParser(
+        "help", GLOBAL_ARGS,
+        usage="[command]",
+        description="Describe how to use coverage.py",
+    ),
 
-    'html': CmdOptionParser("html",
+    'html': CmdOptionParser(
+        "html",
         [
             Opts.directory,
             Opts.fail_under,
@@ -288,13 +319,16 @@
             Opts.omit,
             Opts.title,
             ] + GLOBAL_ARGS,
-        usage = "[options] [modules]",
-        description = "Create an HTML report of the coverage of the files.  "
+        usage="[options] [modules]",
+        description=(
+            "Create an HTML report of the coverage of the files.  "
             "Each file gets its own page, with the source decorated to show "
             "executed, excluded, and missed lines."
         ),
+    ),
 
-    'report': CmdOptionParser("report",
+    'report': CmdOptionParser(
+        "report",
         [
             Opts.fail_under,
             Opts.ignore_errors,
@@ -303,11 +337,12 @@
             Opts.show_missing,
             Opts.skip_covered,
             ] + GLOBAL_ARGS,
-        usage = "[options] [modules]",
-        description = "Report coverage statistics on modules."
-        ),
+        usage="[options] [modules]",
+        description="Report coverage statistics on modules."
+    ),
 
-    'run': CmdOptionParser("run",
+    'run': CmdOptionParser(
+        "run",
         [
             Opts.append,
             Opts.branch,
@@ -320,11 +355,12 @@
             Opts.source,
             Opts.timid,
             ] + GLOBAL_ARGS,
-        usage = "[options] <pyfile> [program options]",
-        description = "Run a Python program, measuring code execution."
-        ),
+        usage="[options] <pyfile> [program options]",
+        description="Run a Python program, measuring code execution."
+    ),
 
-    'xml': CmdOptionParser("xml",
+    'xml': CmdOptionParser(
+        "xml",
         [
             Opts.fail_under,
             Opts.ignore_errors,
@@ -332,10 +368,10 @@
             Opts.omit,
             Opts.output_xml,
             ] + GLOBAL_ARGS,
-        usage = "[options] [modules]",
-        description = "Generate an XML report of coverage results."
-        ),
-    }
+        usage="[options] [modules]",
+        description="Generate an XML report of coverage results."
+    ),
+}
 
 
 OK, ERR, FAIL_UNDER = 0, 1, 2
@@ -362,6 +398,17 @@
 
         self.coverage = None
 
+        self.program_name = os.path.basename(sys.argv[0])
+        if env.WINDOWS:
+            # entry_points={'console_scripts':...} on Windows makes files
+            # called coverage.exe, coverage3.exe, and coverage-3.5.exe. These
+            # invoke coverage-script.py, coverage3-script.py, and
+            # coverage-3.5-script.py.  argv[0] is the .py file, but we want to
+            # get back to the original form.
+            auto_suffix = "-script.py"
+            if self.program_name.endswith(auto_suffix):
+                self.program_name = self.program_name[:-len(auto_suffix)]
+
     def command_line(self, argv):
         """The bulk of the command line interface to coverage.py.
 
@@ -412,16 +459,16 @@
 
         # Do something.
         self.coverage = self.covpkg.coverage(
-            data_suffix = options.parallel_mode,
-            cover_pylib = options.pylib,
-            timid = options.timid,
-            branch = options.branch,
-            config_file = options.rcfile,
-            source = source,
-            omit = omit,
-            include = include,
-            debug = debug,
-            concurrency = options.concurrency,
+            data_suffix=options.parallel_mode,
+            cover_pylib=options.pylib,
+            timid=options.timid,
+            branch=options.branch,
+            config_file=options.rcfile,
+            source=source,
+            omit=omit,
+            include=include,
+            debug=debug,
+            concurrency=options.concurrency,
             )
 
         if options.action == "debug":
@@ -443,10 +490,10 @@
 
         # Remaining actions are reporting, with some common options.
         report_args = dict(
-            morfs = unglob_args(args),
-            ignore_errors = options.ignore_errors,
-            omit = omit,
-            include = include,
+            morfs=unglob_args(args),
+            ignore_errors=options.ignore_errors,
+            omit=omit,
+            include=include,
             )
 
         self.coverage.load()
@@ -495,13 +542,19 @@
         assert error or topic or parser
         if error:
             print(error)
-            print("Use 'coverage help' for help.")
+            print("Use '%s help' for help." % (self.program_name,))
         elif parser:
             print(parser.format_help().strip())
         else:
-            help_msg = HELP_TOPICS.get(topic, '').strip()
+            help_params = dict(self.covpkg.__dict__)
+            help_params['program_name'] = self.program_name
+            if CTracer is not None:
+                help_params['extension_modifier'] = 'with C extension'
+            else:
+                help_params['extension_modifier'] = 'without C extension'
+            help_msg = textwrap.dedent(HELP_TOPICS.get(topic, '')).strip()
             if help_msg:
-                print(help_msg % self.covpkg.__dict__)
+                print(help_msg.format(**help_params))
             else:
                 print("Don't know topic %r" % topic)
 
@@ -650,35 +703,34 @@
 
 
 HELP_TOPICS = {
-# -------------------------
-'help': """\
-Coverage.py, version %(__version__)s
-Measure, collect, and report on code coverage in Python programs.
+    'help': """\
+        Coverage.py, version {__version__} {extension_modifier}
+        Measure, collect, and report on code coverage in Python programs.
 
-usage: coverage <command> [options] [args]
+        usage: {program_name} <command> [options] [args]
 
-Commands:
-    annotate    Annotate source files with execution information.
-    combine     Combine a number of data files.
-    erase       Erase previously collected coverage data.
-    help        Get help on using coverage.py.
-    html        Create an HTML report.
-    report      Report coverage stats on modules.
-    run         Run a Python program and measure code execution.
-    xml         Create an XML report of coverage results.
+        Commands:
+            annotate    Annotate source files with execution information.
+            combine     Combine a number of data files.
+            erase       Erase previously collected coverage data.
+            help        Get help on using coverage.py.
+            html        Create an HTML report.
+            report      Report coverage stats on modules.
+            run         Run a Python program and measure code execution.
+            xml         Create an XML report of coverage results.
 
-Use "coverage help <command>" for detailed help on any command.
-For full documentation, see %(__url__)s
-""",
-# -------------------------
-'minimum_help': """\
-Code coverage for Python.  Use 'coverage help' for help.
-""",
-# -------------------------
-'version': """\
-Coverage.py, version %(__version__)s.
-Documentation at %(__url__)s
-""",
+        Use "{program_name} help <command>" for detailed help on any command.
+        For full documentation, see {__url__}
+    """,
+
+    'minimum_help': """\
+        Code coverage for Python.  Use '{program_name} help' for help.
+    """,
+
+    'version': """\
+        Coverage.py, version {__version__} {extension_modifier}
+        Documentation at {__url__}
+    """,
 }
 
 
--- a/DebugClients/Python/coverage/collector.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/collector.py	Sun Jul 24 12:01:01 2016 +0200
@@ -3,14 +3,18 @@
 
 """Raw data collector for coverage.py."""
 
-import os, sys
+import os
+import sys
 
 from coverage import env
 from coverage.backward import iitems
 from coverage.files import abs_file
-from coverage.misc import CoverageException
+from coverage.misc import CoverageException, isolate_module
 from coverage.pytracer import PyTracer
 
+os = isolate_module(os)
+
+
 try:
     # Use the C extension code when we can, for speed.
     from coverage.tracer import CTracer, CFileDisposition   # pylint: disable=no-name-in-module
@@ -33,6 +37,13 @@
     pass
 
 
+def should_start_context(frame):
+    """Who-Tests-What hack: Determine whether this frame begins a new who-context."""
+    fn_name = frame.f_code.co_name
+    if fn_name.startswith("test"):
+        return fn_name
+
+
 class Collector(object):
     """Collects trace data.
 
@@ -112,6 +123,10 @@
                 "Couldn't trace with concurrency=%s, the module isn't installed." % concurrency
             )
 
+        # Who-Tests-What is just a hack at the moment, so turn it on with an
+        # environment variable.
+        self.wtw = int(os.getenv('COVERAGE_WTW', 0))
+
         self.reset()
 
         if timid:
@@ -143,6 +158,10 @@
         # pairs as keys (if branch coverage).
         self.data = {}
 
+        # A dict mapping contexts to data dictionaries.
+        self.contexts = {}
+        self.contexts[None] = self.data
+
         # A dictionary mapping file names to file tracer plugin names that will
         # handle them.
         self.file_tracers = {}
@@ -202,6 +221,11 @@
             tracer.threading = self.threading
         if hasattr(tracer, 'check_include'):
             tracer.check_include = self.check_include
+        if self.wtw:
+            if hasattr(tracer, 'should_start_context'):
+                tracer.should_start_context = should_start_context
+            if hasattr(tracer, 'switch_context'):
+                tracer.switch_context = self.switch_context
 
         fn = tracer.start()
         self.tracers.append(tracer)
@@ -290,7 +314,7 @@
             if stats:
                 print("\nCoverage.py tracer stats:")
                 for k in sorted(stats.keys()):
-                    print("%16s: %s" % (k, stats[k]))
+                    print("%20s: %s" % (k, stats[k]))
         if self.threading:
             self.threading.settrace(None)
 
@@ -303,6 +327,14 @@
         else:
             self._start_tracer()
 
+    def switch_context(self, new_context):
+        """Who-Tests-What hack: switch to a new who-context."""
+        # Make a new data dict, or find the existing one, and switch all the
+        # tracers to use it.
+        data = self.contexts.setdefault(new_context, {})
+        for tracer in self.tracers:
+            tracer.data = data
+
     def save_data(self, covdata):
         """Save the collected data to a `CoverageData`.
 
@@ -319,6 +351,13 @@
             covdata.add_lines(abs_file_dict(self.data))
         covdata.add_file_tracers(abs_file_dict(self.file_tracers))
 
+        if self.wtw:
+            # Just a hack, so just hack it.
+            import pprint
+            out_file = "coverage_wtw_{:06}.py".format(os.getpid())
+            with open(out_file, "w") as wtw_out:
+                pprint.pprint(self.contexts, wtw_out)
+
         self.reset()
 
 #
--- a/DebugClients/Python/coverage/config.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/config.py	Sun Jul 24 12:01:01 2016 +0200
@@ -9,7 +9,9 @@
 import sys
 
 from coverage.backward import configparser, iitems, string_class
-from coverage.misc import CoverageException
+from coverage.misc import CoverageException, isolate_module
+
+os = isolate_module(os)
 
 
 class HandyConfigParser(configparser.RawConfigParser):
--- a/DebugClients/Python/coverage/control.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/control.py	Sun Jul 24 12:01:01 2016 +0200
@@ -7,6 +7,7 @@
 import inspect
 import os
 import platform
+import re
 import sys
 import traceback
 
@@ -22,7 +23,7 @@
 from coverage.files import ModuleMatcher, abs_file
 from coverage.html import HtmlReporter
 from coverage.misc import CoverageException, bool_or_none, join_regex
-from coverage.misc import file_be_gone
+from coverage.misc import file_be_gone, isolate_module
 from coverage.monkey import patch_multiprocessing
 from coverage.plugin import FileReporter
 from coverage.plugin_support import Plugins
@@ -31,6 +32,7 @@
 from coverage.summary import SummaryReporter
 from coverage.xmlreport import XmlReporter
 
+os = isolate_module(os)
 
 # Pypy has some unusual stuff in the "stdlib".  Consider those locations
 # when deciding where the stdlib is.
@@ -108,8 +110,8 @@
 
         `concurrency` is a string indicating the concurrency library being used
         in the measured code.  Without this, coverage.py will get incorrect
-        results.  Valid strings are "greenlet", "eventlet", "gevent", or
-        "thread" (the default).
+        results.  Valid strings are "greenlet", "eventlet", "gevent",
+        "multiprocessing", or "thread" (the default).
 
         .. versionadded:: 4.0
             The `concurrency` parameter.
@@ -279,7 +281,7 @@
         # data file will be written into the directory where the process
         # started rather than wherever the process eventually chdir'd to.
         self.data = CoverageData(debug=self.debug)
-        self.data_files = CoverageDataFiles(basename=self.config.data_file)
+        self.data_files = CoverageDataFiles(basename=self.config.data_file, warn=self._warn)
 
         # The directories for files considered "installed with the interpreter".
         self.pylib_dirs = set()
@@ -289,7 +291,7 @@
             # environments (virtualenv, for example), these modules may be
             # spread across a few locations. Look at all the candidate modules
             # we've imported, and take all the different ones.
-            for m in (atexit, inspect, os, platform, _structseq, traceback):
+            for m in (atexit, inspect, os, platform, re, _structseq, traceback):
                 if m is not None and hasattr(m, "__file__"):
                     self.pylib_dirs.add(self._canonical_dir(m))
             if _structseq and not hasattr(_structseq, '__file__'):
@@ -475,6 +477,11 @@
             # can't do anything with the data later anyway.
             return nope(disp, "not a real file name")
 
+        # pyexpat does a dumb thing, calling the trace function explicitly from
+        # C code with a C file name.
+        if re.search(r"[/\\]Modules[/\\]pyexpat.c", filename):
+            return nope(disp, "pyexpat lies about itself")
+
         # Jython reports the .class file to the tracer, use the source file.
         if filename.endswith("$py.class"):
             filename = filename[:-9] + ".py"
@@ -798,7 +805,7 @@
         """
         self._init()
         if not self._measured:
-            return
+            return self.data
 
         self.collector.save_data(self.data)
 
@@ -832,15 +839,6 @@
 
                 self.data.touch_file(py_file)
 
-        # Add run information.
-        self.data.add_run_info(
-            brief_sys=" ".join([
-                platform.python_implementation(),
-                platform.python_version(),
-                platform.system(),
-            ])
-        )
-
         if self.config.note:
             self.data.add_run_info(note=self.config.note)
 
@@ -943,9 +941,9 @@
         return file_reporters
 
     def report(
-        self, morfs=None, show_missing=True, ignore_errors=None,
+        self, morfs=None, show_missing=None, ignore_errors=None,
         file=None,                  # pylint: disable=redefined-builtin
-        omit=None, include=None, skip_covered=False,
+        omit=None, include=None, skip_covered=None,
     ):
         """Write a summary report to `file`.
 
@@ -1049,7 +1047,10 @@
                 output_dir = os.path.dirname(self.config.xml_output)
                 if output_dir and not os.path.isdir(output_dir):
                     os.makedirs(output_dir)
-                outfile = open(self.config.xml_output, "w")
+                open_kwargs = {}
+                if env.PY3:
+                    open_kwargs['encoding'] = 'utf8'
+                outfile = open(self.config.xml_output, "w", **open_kwargs)
                 file_to_close = outfile
         try:
             reporter = XmlReporter(self, self.config)
@@ -1165,11 +1166,14 @@
 
         import coverage; coverage.process_startup()
 
+    Returns the :class:`Coverage` instance that was started, or None if it was
+    not started by this call.
+
     """
     cps = os.environ.get("COVERAGE_PROCESS_START")
     if not cps:
         # No request for coverage, nothing to do.
-        return
+        return None
 
     # This function can be called more than once in a process. This happens
     # because some virtualenv configurations make the same directory visible
@@ -1184,7 +1188,7 @@
     if hasattr(process_startup, "done"):
         # We've annotated this function before, so we must have already
         # started coverage.py in this process.  Nothing to do.
-        return
+        return None
 
     process_startup.done = True
     cov = Coverage(config_file=cps, auto_data=True)
@@ -1192,5 +1196,7 @@
     cov._warn_no_data = False
     cov._warn_unimported_source = False
 
+    return cov
+
 #
 # eflag: FileType = Python2
--- a/DebugClients/Python/coverage/data.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/data.py	Sun Jul 24 12:01:01 2016 +0200
@@ -4,6 +4,7 @@
 """Coverage data for coverage.py."""
 
 import glob
+import itertools
 import json
 import optparse
 import os
@@ -11,13 +12,14 @@
 import random
 import re
 import socket
-import sys
 
 from coverage import env
 from coverage.backward import iitems, string_class
 from coverage.debug import _TEST_NAME_FILE
 from coverage.files import PathAliases
-from coverage.misc import CoverageException, file_be_gone
+from coverage.misc import CoverageException, file_be_gone, isolate_module
+
+os = isolate_module(os)
 
 
 class CoverageData(object):
@@ -177,11 +179,12 @@
 
         """
         if self._arcs is not None:
-            if filename in self._arcs:
-                return [s for s, __ in self._arcs[filename] if s > 0]
+            arcs = self._arcs.get(filename)
+            if arcs is not None:
+                all_lines = itertools.chain.from_iterable(arcs)
+                return list(set(l for l in all_lines if l > 0))
         elif self._lines is not None:
-            if filename in self._lines:
-                return self._lines[filename]
+            return self._lines.get(filename)
         return None
 
     def arcs(self, filename):
@@ -270,15 +273,10 @@
         self._lines = self._arcs = None
 
         if 'lines' in data:
-            self._lines = dict(
-                (fname.encode(sys.getfilesystemencoding()), linenos)
-                for fname, linenos in iitems(data['lines'])
-            )
-
+            self._lines = data['lines']
         if 'arcs' in data:
             self._arcs = dict(
-                (fname.encode(sys.getfilesystemencoding()),
-                    [tuple(pair) for pair in arcs])
+                (fname, [tuple(pair) for pair in arcs])
                 for fname, arcs in iitems(data['arcs'])
             )
         self._file_tracers = data.get('file_tracers', {})
@@ -290,8 +288,15 @@
         """Read the coverage data from `filename` into this object."""
         if self._debug and self._debug.should('dataio'):
             self._debug.write("Reading data from %r" % (filename,))
-        with self._open_for_reading(filename) as f:
-            self.read_fileobj(f)
+        try:
+            with self._open_for_reading(filename) as f:
+                self.read_fileobj(f)
+        except Exception as exc:
+            raise CoverageException(
+                "Couldn't read data from '%s': %s: %s" % (
+                    filename, exc.__class__.__name__, exc,
+                )
+            )
 
     _GO_AWAY = "!coverage.py: This is a private format, don't read it directly!"
 
@@ -433,17 +438,10 @@
         file_data = {}
 
         if self._has_arcs():
-            file_data['arcs'] = dict(
-                (fname.decode(sys.getfilesystemencoding()),
-                    [tuple(pair) for pair in self._arcs])
-                for fname, arcs in iitems(data['arcs'])
-            )
+            file_data['arcs'] = self._arcs
 
         if self._has_lines():
-            file_data['lines'] = dict(
-                (fname.decode(sys.getfilesystemencoding()), linenos)
-                for fname, linenos in iitems(self._lines)
-            )
+            file_data['lines'] = self._lines
 
         if self._file_tracers:
             file_data['file_tracers'] = self._file_tracers
@@ -580,7 +578,7 @@
     def add_to_hash(self, filename, hasher):
         """Contribute `filename`'s data to the `hasher`.
 
-        `hasher` is a :class:`coverage.misc.Hasher` instance to be updated with
+        `hasher` is a `coverage.misc.Hasher` instance to be updated with
         the file's data.  It should only get the results data, not the run
         data.
 
@@ -607,12 +605,15 @@
 class CoverageDataFiles(object):
     """Manage the use of coverage data files."""
 
-    def __init__(self, basename=None):
+    def __init__(self, basename=None, warn=None):
         """Create a CoverageDataFiles to manage data files.
 
+        `warn` is the warning function to use.
+
         `basename` is the name of the file to use for storing data.
 
         """
+        self.warn = warn
         # Construct the file name that will be used for data storage.
         self.filename = os.path.abspath(basename or ".coverage")
 
@@ -681,7 +682,9 @@
         If `data_paths` is not provided, then the directory portion of
         `self.filename` is used as the directory to search for data files.
 
-        Every data file found and combined is then deleted from disk.
+        Every data file found and combined is then deleted from disk. If a file
+        cannot be read, a warning will be issued, and the file will not be
+        deleted.
 
         """
         # Because of the os.path.abspath in the constructor, data_dir will
@@ -702,9 +705,16 @@
 
         for f in files_to_combine:
             new_data = CoverageData()
-            new_data.read_file(f)
-            data.update(new_data, aliases=aliases)
-            file_be_gone(f)
+            try:
+                new_data.read_file(f)
+            except CoverageException as exc:
+                if self.warn:
+                    # The CoverageException has the file name in it, so just
+                    # use the message as the warning.
+                    self.warn(str(exc))
+            else:
+                data.update(new_data, aliases=aliases)
+                file_be_gone(f)
 
 
 def canonicalize_json_data(data):
@@ -754,6 +764,7 @@
 
 
 if __name__ == '__main__':
+    import sys
     debug_main(sys.argv[1:])
 
 #
--- a/DebugClients/Python/coverage/debug.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/debug.py	Sun Jul 24 12:01:01 2016 +0200
@@ -7,6 +7,10 @@
 import os
 import sys
 
+from coverage.misc import isolate_module
+
+os = isolate_module(os)
+
 
 # When debugging, it can be helpful to force some options, especially when
 # debugging the configuration mechanisms you usually use to control debugging!
@@ -38,7 +42,7 @@
             msg = "pid %5d: %s" % (os.getpid(), msg)
         self.output.write(msg+"\n")
         if self.should('callers'):
-            dump_stack_frames(self.output)
+            dump_stack_frames(out=self.output)
         self.output.flush()
 
     def write_formatted_info(self, header, info):
@@ -76,7 +80,7 @@
             yield "%*s: %s" % (label_len, label, data)
 
 
-def short_stack():                                          # pragma: debugging
+def short_stack(limit=None):                                # pragma: debugging
     """Return a string summarizing the call stack.
 
     The string is multi-line, with one line per stack frame. Each line shows
@@ -88,15 +92,17 @@
         import_local_file : /Users/ned/coverage/trunk/coverage/backward.py @159
         ...
 
+    `limit` is the number of frames to include, defaulting to all of them.
+
     """
-    stack = inspect.stack()[:0:-1]
+    stack = inspect.stack()[limit:0:-1]
     return "\n".join("%30s : %s @%d" % (t[3], t[1], t[2]) for t in stack)
 
 
-def dump_stack_frames(out=None):                            # pragma: debugging
+def dump_stack_frames(limit=None, out=None):                # pragma: debugging
     """Print a summary of the stack to stdout, or some place else."""
     out = out or sys.stdout
-    out.write(short_stack())
+    out.write(short_stack(limit=limit))
     out.write("\n")
 
 #
--- a/DebugClients/Python/coverage/doc/AUTHORS.txt	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/doc/AUTHORS.txt	Sun Jul 24 12:01:01 2016 +0200
@@ -7,6 +7,7 @@
 Alex Gaynor
 Alexander Todorov
 Anthony Sottile
+Arcadiy Ivanov
 Ben Finney
 Bill Hart
 Brandon Rhodes
@@ -26,6 +27,7 @@
 David Stanek
 Detlev Offenbach
 Devin Jeanpierre
+Dmitry Shishov
 Dmitry Trofimov
 Eduardo Schettino
 Edward Loper
@@ -34,6 +36,7 @@
 George Song
 Greg Rogers
 Guillaume Chazarain
+Ilia Meerovich
 Imri Goldberg
 Ionel Cristian Mărieș
 JT Olds
@@ -49,11 +52,13 @@
 Mark van der Wal
 Martin Fuzzey
 Matthew Desmarais
+Max Linke
 Mickie Betz
 Noel O'Boyle
 Pablo Carballo
 Patrick Mezard
 Peter Portante
+Rodrigue Cloutier
 Roger Hu
 Ross Lawley
 Sandra Martocchia
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DebugClients/Python/coverage/doc/CHANGES.rst	Sun Jul 24 12:01:01 2016 +0200
@@ -0,0 +1,1654 @@
+.. Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
+.. For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
+
+==============================
+Change history for Coverage.py
+==============================
+
+
+Version 4.1 --- 2016-05-21
+--------------------------
+
+- The internal attribute `Reporter.file_reporters` was removed in 4.1b3.  It
+  should have come has no surprise that there were third-party tools out there
+  using that attribute.  It has been restored, but with a deprecation warning.
+
+
+Version 4.1b3 --- 2016-05-10
+----------------------------
+
+- When running your program, execution can jump from an ``except X:`` line to
+  some other line when an exception other than ``X`` happens.  This jump is no
+  longer considered a branch when measuring branch coverage.
+
+- When measuring branch coverage, ``yield`` statements that were never resumed
+  were incorrectly marked as missing, as reported in `issue 440`_.  This is now
+  fixed.
+
+- During branch coverage of single-line callables like lambdas and generator
+  expressions, coverage.py can now distinguish between them never being called,
+  or being called but not completed.  Fixes `issue 90`_, `issue 460`_ and
+  `issue 475`_.
+
+- The HTML report now has a map of the file along the rightmost edge of the
+  page, giving an overview of where the missed lines are.  Thanks, Dmitry
+  Shishov.
+
+- The HTML report now uses different monospaced fonts, favoring Consolas over
+  Courier.  Along the way, `issue 472`_ about not properly handling one-space
+  indents was fixed.  The index page also has slightly different styling, to
+  try to make the clickable detail pages more apparent.
+
+- Missing branches reported with ``coverage report -m`` will now say ``->exit``
+  for missed branches to the exit of a function, rather than a negative number.
+  Fixes `issue 469`_.
+
+- ``coverage --help`` and ``coverage --version`` now mention which tracer is
+  installed, to help diagnose problems. The docs mention which features need
+  the C extension. (`issue 479`_)
+
+- Officially support PyPy 5.1, which required no changes, just updates to the
+  docs.
+
+- The `Coverage.report` function had two parameters with non-None defaults,
+  which have been changed.  `show_missing` used to default to True, but now
+  defaults to None.  If you had been calling `Coverage.report` without
+  specifying `show_missing`, you'll need to explicitly set it to True to keep
+  the same behavior.  `skip_covered` used to default to False. It is now None,
+  which doesn't change the behavior.  This fixes `issue 485`_.
+
+- It's never been possible to pass a namespace module to one of the analysis
+  functions, but now at least we raise a more specific error message, rather
+  than getting confused. (`issue 456`_)
+
+- The `coverage.process_startup` function now returns the `Coverage` instance
+  it creates, as suggested in `issue 481`_.
+
+- Make a small tweak to how we compare threads, to avoid buggy custom
+  comparison code in thread classes. (`issue 245`_)
+
+.. _issue 90: https://bitbucket.org/ned/coveragepy/issues/90/lambda-expression-confuses-branch
+.. _issue 245: https://bitbucket.org/ned/coveragepy/issues/245/change-solution-for-issue-164
+.. _issue 440: https://bitbucket.org/ned/coveragepy/issues/440/yielded-twisted-failure-marked-as-missed
+.. _issue 456: https://bitbucket.org/ned/coveragepy/issues/456/coverage-breaks-with-implicit-namespaces
+.. _issue 460: https://bitbucket.org/ned/coveragepy/issues/460/confusing-html-report-for-certain-partial
+.. _issue 469: https://bitbucket.org/ned/coveragepy/issues/469/strange-1-line-number-in-branch-coverage
+.. _issue 472: https://bitbucket.org/ned/coveragepy/issues/472/html-report-indents-incorrectly-for-one
+.. _issue 475: https://bitbucket.org/ned/coveragepy/issues/475/generator-expression-is-marked-as-not
+.. _issue 479: https://bitbucket.org/ned/coveragepy/issues/479/clarify-the-need-for-the-c-extension
+.. _issue 481: https://bitbucket.org/ned/coveragepy/issues/481/asyncioprocesspoolexecutor-tracing-not
+.. _issue 485: https://bitbucket.org/ned/coveragepy/issues/485/coveragereport-ignores-show_missing-and
+
+
+Version 4.1b2 --- 2016-01-23
+----------------------------
+
+- Problems with the new branch measurement in 4.1 beta 1 were fixed:
+
+  - Class docstrings were considered executable.  Now they no longer are.
+
+  - ``yield from`` and ``await`` were considered returns from functions, since
+    they could tranfer control to the caller.  This produced unhelpful "missing
+    branch" reports in a number of circumstances.  Now they no longer are
+    considered returns.
+
+  - In unusual situations, a missing branch to a negative number was reported.
+    This has been fixed, closing `issue 466`_.
+
+- The XML report now produces correct package names for modules found in
+  directories specified with ``source=``.  Fixes `issue 465`_.
+
+- ``coverage report`` won't produce trailing whitespace.
+
+.. _issue 465: https://bitbucket.org/ned/coveragepy/issues/465/coveragexml-produces-package-names-with-an
+.. _issue 466: https://bitbucket.org/ned/coveragepy/issues/466/impossible-missed-branch-to-a-negative
+
+
+Version 4.1b1 --- 2016-01-10
+----------------------------
+
+- Branch analysis has been rewritten: it used to be based on bytecode, but now
+  uses AST analysis.  This has changed a number of things:
+
+  - More code paths are now considered runnable, especially in
+    ``try``/``except`` structures.  This may mean that coverage.py will
+    identify more code paths as uncovered.  This could either raise or lower
+    your overall coverage number.
+
+  - Python 3.5's ``async`` and ``await`` keywords are properly supported,
+    fixing `issue 434`_.
+
+  - Some long-standing branch coverage bugs were fixed:
+
+    - `issue 129`_: functions with only a docstring for a body would
+      incorrectly report a missing branch on the ``def`` line.
+
+    - `issue 212`_: code in an ``except`` block could be incorrectly marked as
+      a missing branch.
+
+    - `issue 146`_: context managers (``with`` statements) in a loop or ``try``
+      block could confuse the branch measurement, reporting incorrect partial
+      branches.
+
+    - `issue 422`_: in Python 3.5, an actual partial branch could be marked as
+      complete.
+
+- Pragmas to disable coverage measurement can now be used on decorator lines,
+  and they will apply to the entire function or class being decorated.  This
+  implements the feature requested in `issue 131`_.
+
+- Multiprocessing support is now available on Windows.  Thanks, Rodrigue
+  Cloutier.
+
+- Files with two encoding declarations are properly supported, fixing
+  `issue 453`_. Thanks, Max Linke.
+
+- Non-ascii characters in regexes in the configuration file worked in 3.7, but
+  stopped working in 4.0.  Now they work again, closing `issue 455`_.
+
+- Form-feed characters would prevent accurate determination of the beginning of
+  statements in the rest of the file.  This is now fixed, closing `issue 461`_.
+
+.. _issue 129: https://bitbucket.org/ned/coveragepy/issues/129/misleading-branch-coverage-of-empty
+.. _issue 131: https://bitbucket.org/ned/coveragepy/issues/131/pragma-on-a-decorator-line-should-affect
+.. _issue 146: https://bitbucket.org/ned/coveragepy/issues/146/context-managers-confuse-branch-coverage
+.. _issue 212: https://bitbucket.org/ned/coveragepy/issues/212/coverage-erroneously-reports-partial
+.. _issue 422: https://bitbucket.org/ned/coveragepy/issues/422/python35-partial-branch-marked-as-fully
+.. _issue 434: https://bitbucket.org/ned/coveragepy/issues/434/indexerror-in-python-35
+.. _issue 453: https://bitbucket.org/ned/coveragepy/issues/453/source-code-encoding-can-only-be-specified
+.. _issue 455: https://bitbucket.org/ned/coveragepy/issues/455/unusual-exclusions-stopped-working-in
+.. _issue 461: https://bitbucket.org/ned/coveragepy/issues/461/multiline-asserts-need-too-many-pragma
+
+
+Version 4.0.3 --- 2015-11-24
+----------------------------
+
+- Fixed a mysterious problem that manifested in different ways: sometimes
+  hanging the process (`issue 420`_), sometimes making database connections
+  fail (`issue 445`_).
+
+- The XML report now has correct ``<source>`` elements when using a
+  ``--source=`` option somewhere besides the current directory.  This fixes
+  `issue 439`_. Thanks, Arcady Ivanov.
+
+- Fixed an unusual edge case of detecting source encodings, described in
+  `issue 443`_.
+
+- Help messages that mention the command to use now properly use the actual
+  command name, which might be different than "coverage".  Thanks to Ben
+  Finney, this closes `issue 438`_.
+
+.. _issue 420: https://bitbucket.org/ned/coveragepy/issues/420/coverage-40-hangs-indefinitely-on-python27
+.. _issue 438: https://bitbucket.org/ned/coveragepy/issues/438/parameterise-coverage-command-name
+.. _issue 439: https://bitbucket.org/ned/coveragepy/issues/439/incorrect-cobertura-file-sources-generated
+.. _issue 443: https://bitbucket.org/ned/coveragepy/issues/443/coverage-gets-confused-when-encoding
+.. _issue 445: https://bitbucket.org/ned/coveragepy/issues/445/django-app-cannot-connect-to-cassandra
+
+
+Version 4.0.2 --- 2015-11-04
+----------------------------
+
+- More work on supporting unusually encoded source. Fixed `issue 431`_.
+
+- Files or directories with non-ASCII characters are now handled properly,
+  fixing `issue 432`_.
+
+- Setting a trace function with sys.settrace was broken by a change in 4.0.1,
+  as reported in `issue 436`_.  This is now fixed.
+
+- Officially support PyPy 4.0, which required no changes, just updates to the
+  docs.
+
+.. _issue 431: https://bitbucket.org/ned/coveragepy/issues/431/couldnt-parse-python-file-with-cp1252
+.. _issue 432: https://bitbucket.org/ned/coveragepy/issues/432/path-with-unicode-characters-various
+.. _issue 436: https://bitbucket.org/ned/coveragepy/issues/436/disabled-coverage-ctracer-may-rise-from
+
+
+Version 4.0.1 --- 2015-10-13
+----------------------------
+
+- When combining data files, unreadable files will now generate a warning
+  instead of failing the command.  This is more in line with the older
+  coverage.py v3.7.1 behavior, which silently ignored unreadable files.
+  Prompted by `issue 418`_.
+
+- The --skip-covered option would skip reporting on 100% covered files, but
+  also skipped them when calculating total coverage.  This was wrong, it should
+  only remove lines from the report, not change the final answer.  This is now
+  fixed, closing `issue 423`_.
+
+- In 4.0, the data file recorded a summary of the system on which it was run.
+  Combined data files would keep all of those summaries.  This could lead to
+  enormous data files consisting of mostly repetitive useless information. That
+  summary is now gone, fixing `issue 415`_.  If you want summary information,
+  get in touch, and we'll figure out a better way to do it.
+
+- Test suites that mocked os.path.exists would experience strange failures, due
+  to coverage.py using their mock inadvertently.  This is now fixed, closing
+  `issue 416`_.
+
+- Importing a ``__init__`` module explicitly would lead to an error:
+  ``AttributeError: 'module' object has no attribute '__path__'``, as reported
+  in `issue 410`_.  This is now fixed.
+
+- Code that uses ``sys.settrace(sys.gettrace())`` used to incur a more than 2x
+  speed penalty.  Now there's no penalty at all. Fixes `issue 397`_.
+
+- Pyexpat C code will no longer be recorded as a source file, fixing
+  `issue 419`_.
+
+- The source kit now contains all of the files needed to have a complete source
+  tree, re-fixing `issue 137`_ and closing `issue 281`_.
+
+.. _issue 281: https://bitbucket.org/ned/coveragepy/issues/281/supply-scripts-for-testing-in-the
+.. _issue 397: https://bitbucket.org/ned/coveragepy/issues/397/stopping-and-resuming-coverage-with
+.. _issue 410: https://bitbucket.org/ned/coveragepy/issues/410/attributeerror-module-object-has-no
+.. _issue 415: https://bitbucket.org/ned/coveragepy/issues/415/repeated-coveragedataupdates-cause
+.. _issue 416: https://bitbucket.org/ned/coveragepy/issues/416/mocking-ospathexists-causes-failures
+.. _issue 418: https://bitbucket.org/ned/coveragepy/issues/418/json-parse-error
+.. _issue 419: https://bitbucket.org/ned/coveragepy/issues/419/nosource-no-source-for-code-path-to-c
+.. _issue 423: https://bitbucket.org/ned/coveragepy/issues/423/skip_covered-changes-reported-total
+
+
+Version 4.0 --- 2015-09-20
+--------------------------
+
+No changes from 4.0b3
+
+
+Version 4.0b3 --- 2015-09-07
+----------------------------
+
+- Reporting on an unmeasured file would fail with a traceback.  This is now
+  fixed, closing `issue 403`_.
+
+- The Jenkins ShiningPanda plugin looks for an obsolete file name to find the
+  HTML reports to publish, so it was failing under coverage.py 4.0.  Now we
+  create that file if we are running under Jenkins, to keep things working
+  smoothly. `issue 404`_.
+
+- Kits used to include tests and docs, but didn't install them anywhere, or
+  provide all of the supporting tools to make them useful.  Kits no longer
+  include tests and docs.  If you were using them from the older packages, get
+  in touch and help me understand how.
+
+.. _issue 403: https://bitbucket.org/ned/coveragepy/issues/403/hasherupdate-fails-with-typeerror-nonetype
+.. _issue 404: https://bitbucket.org/ned/coveragepy/issues/404/shiningpanda-jenkins-plugin-cant-find-html
+
+
+
+Version 4.0b2 --- 2015-08-22
+----------------------------
+
+- 4.0b1 broke ``--append`` creating new data files.  This is now fixed, closing
+  `issue 392`_.
+
+- ``py.test --cov`` can write empty data, then touch files due to ``--source``,
+  which made coverage.py mistakenly force the data file to record lines instead
+  of arcs.  This would lead to a "Can't combine line data with arc data" error
+  message.  This is now fixed, and changed some method names in the
+  CoverageData interface.  Fixes `issue 399`_.
+
+- `CoverageData.read_fileobj` and `CoverageData.write_fileobj` replace the
+  `.read` and `.write` methods, and are now properly inverses of each other.
+
+- When using ``report --skip-covered``, a message will now be included in the
+  report output indicating how many files were skipped, and if all files are
+  skipped, coverage.py won't accidentally scold you for having no data to
+  report.  Thanks, Krystian Kichewko.
+
+- A new conversion utility has been added:  ``python -m coverage.pickle2json``
+  will convert v3.x pickle data files to v4.x JSON data files.  Thanks,
+  Alexander Todorov.  Closes `issue 395`_.
+
+- A new version identifier is available, `coverage.version_info`, a plain tuple
+  of values similar to `sys.version_info`_.
+
+.. _issue 392: https://bitbucket.org/ned/coveragepy/issues/392/run-append-doesnt-create-coverage-file
+.. _issue 395: https://bitbucket.org/ned/coveragepy/issues/395/rfe-read-pickled-files-as-well-for
+.. _issue 399: https://bitbucket.org/ned/coveragepy/issues/399/coverageexception-cant-combine-line-data
+.. _sys.version_info: https://docs.python.org/3/library/sys.html#sys.version_info
+
+
+Version 4.0b1 --- 2015-08-02
+----------------------------
+
+- Coverage.py is now licensed under the Apache 2.0 license.  See NOTICE.txt for
+  details.  Closes `issue 313`_.
+
+- The data storage has been completely revamped.  The data file is now
+  JSON-based instead of a pickle, closing `issue 236`_.  The `CoverageData`
+  class is now a public supported documented API to the data file.
+
+- A new configuration option, ``[run] note``, lets you set a note that will be
+  stored in the `runs` section of the data file.  You can use this to annotate
+  the data file with any information you like.
+
+- Unrecognized configuration options will now print an error message and stop
+  coverage.py.  This should help prevent configuration mistakes from passing
+  silently.  Finishes `issue 386`_.
+
+- In parallel mode, ``coverage erase`` will now delete all of the data files,
+  fixing `issue 262`_.
+
+- Coverage.py now accepts a directory name for ``coverage run`` and will run a
+  ``__main__.py`` found there, just like Python will.  Fixes `issue 252`_.
+  Thanks, Dmitry Trofimov.
+
+- The XML report now includes a ``missing-branches`` attribute.  Thanks, Steve
+  Peak.  This is not a part of the Cobertura DTD, so the XML report no longer
+  references the DTD.
+
+- Missing branches in the HTML report now have a bit more information in the
+  right-hand annotations.  Hopefully this will make their meaning clearer.
+
+- All the reporting functions now behave the same if no data had been
+  collected, exiting with a status code of 1.  Fixed ``fail_under`` to be
+  applied even when the report is empty.  Thanks, Ionel Cristian Mărieș.
+
+- Plugins are now initialized differently.  Instead of looking for a class
+  called ``Plugin``, coverage.py looks for a function called ``coverage_init``.
+
+- A file-tracing plugin can now ask to have built-in Python reporting by
+  returning `"python"` from its `file_reporter()` method.
+
+- Code that was executed with `exec` would be mis-attributed to the file that
+  called it.  This is now fixed, closing `issue 380`_.
+
+- The ability to use item access on `Coverage.config` (introduced in 4.0a2) has
+  been changed to a more explicit `Coverage.get_option` and
+  `Coverage.set_option` API.
+
+- The ``Coverage.use_cache`` method is no longer supported.
+
+- The private method ``Coverage._harvest_data`` is now called
+  ``Coverage.get_data``, and returns the ``CoverageData`` containing the
+  collected data.
+
+- The project is consistently referred to as "coverage.py" throughout the code
+  and the documentation, closing `issue 275`_.
+
+- Combining data files with an explicit configuration file was broken in 4.0a6,
+  but now works again, closing `issue 385`_.
+
+- ``coverage combine`` now accepts files as well as directories.
+
+- The speed is back to 3.7.1 levels, after having slowed down due to plugin
+  support, finishing up `issue 387`_.
+
+.. _issue 236: https://bitbucket.org/ned/coveragepy/issues/236/pickles-are-bad-and-you-should-feel-bad
+.. _issue 252: https://bitbucket.org/ned/coveragepy/issues/252/coverage-wont-run-a-program-with
+.. _issue 262: https://bitbucket.org/ned/coveragepy/issues/262/when-parallel-true-erase-should-erase-all
+.. _issue 275: https://bitbucket.org/ned/coveragepy/issues/275/refer-consistently-to-project-as-coverage
+.. _issue 313: https://bitbucket.org/ned/coveragepy/issues/313/add-license-file-containing-2-3-or-4
+.. _issue 380: https://bitbucket.org/ned/coveragepy/issues/380/code-executed-by-exec-excluded-from
+.. _issue 385: https://bitbucket.org/ned/coveragepy/issues/385/coverage-combine-doesnt-work-with-rcfile
+.. _issue 386: https://bitbucket.org/ned/coveragepy/issues/386/error-on-unrecognised-configuration
+.. _issue 387: https://bitbucket.org/ned/coveragepy/issues/387/performance-degradation-from-371-to-40
+
+.. 40 issues closed in 4.0 below here
+
+
+Version 4.0a6 --- 2015-06-21
+----------------------------
+
+- Python 3.5b2 and PyPy 2.6.0 are supported.
+
+- The original module-level function interface to coverage.py is no longer
+  supported.  You must now create a ``coverage.Coverage`` object, and use
+  methods on it.
+
+- The ``coverage combine`` command now accepts any number of directories as
+  arguments, and will combine all the data files from those directories.  This
+  means you don't have to copy the files to one directory before combining.
+  Thanks, Christine Lytwynec.  Finishes `issue 354`_.
+
+- Branch coverage couldn't properly handle certain extremely long files. This
+  is now fixed (`issue 359`_).
+
+- Branch coverage didn't understand yield statements properly.  Mickie Betz
+  persisted in pursuing this despite Ned's pessimism.  Fixes `issue 308`_ and
+  `issue 324`_.
+
+- The COVERAGE_DEBUG environment variable can be used to set the ``[run] debug``
+  configuration option to control what internal operations are logged.
+
+- HTML reports were truncated at formfeed characters.  This is now fixed
+  (`issue 360`_).  It's always fun when the problem is due to a `bug in the
+  Python standard library <http://bugs.python.org/issue19035>`_.
+
+- Files with incorrect encoding declaration comments are no longer ignored by
+  the reporting commands, fixing `issue 351`_.
+
+- HTML reports now include a timestamp in the footer, closing `issue 299`_.
+  Thanks, Conrad Ho.
+
+- HTML reports now begrudgingly use double-quotes rather than single quotes,
+  because there are "software engineers" out there writing tools that read HTML
+  and somehow have no idea that single quotes exist.  Capitulates to the absurd
+  `issue 361`_.  Thanks, Jon Chappell.
+
+- The ``coverage annotate`` command now handles non-ASCII characters properly,
+  closing `issue 363`_.  Thanks, Leonardo Pistone.
+
+- Drive letters on Windows were not normalized correctly, now they are. Thanks,
+  Ionel Cristian Mărieș.
+
+- Plugin support had some bugs fixed, closing `issue 374`_ and `issue 375`_.
+  Thanks, Stefan Behnel.
+
+.. _issue 299: https://bitbucket.org/ned/coveragepy/issue/299/inserted-created-on-yyyy-mm-dd-hh-mm-in
+.. _issue 308: https://bitbucket.org/ned/coveragepy/issue/308/yield-lambda-branch-coverage
+.. _issue 324: https://bitbucket.org/ned/coveragepy/issue/324/yield-in-loop-confuses-branch-coverage
+.. _issue 351: https://bitbucket.org/ned/coveragepy/issue/351/files-with-incorrect-encoding-are-ignored
+.. _issue 354: https://bitbucket.org/ned/coveragepy/issue/354/coverage-combine-should-take-a-list-of
+.. _issue 359: https://bitbucket.org/ned/coveragepy/issue/359/xml-report-chunk-error
+.. _issue 360: https://bitbucket.org/ned/coveragepy/issue/360/html-reports-get-confused-by-l-in-the-code
+.. _issue 361: https://bitbucket.org/ned/coveragepy/issue/361/use-double-quotes-in-html-output-to
+.. _issue 363: https://bitbucket.org/ned/coveragepy/issue/363/annotate-command-hits-unicode-happy-fun
+.. _issue 374: https://bitbucket.org/ned/coveragepy/issue/374/c-tracer-lookups-fail-in
+.. _issue 375: https://bitbucket.org/ned/coveragepy/issue/375/ctracer_handle_return-reads-byte-code
+
+
+Version 4.0a5 --- 2015-02-16
+----------------------------
+
+- Plugin support is now implemented in the C tracer instead of the Python
+  tracer. This greatly improves the speed of tracing projects using plugins.
+
+- Coverage.py now always adds the current directory to sys.path, so that
+  plugins can import files in the current directory (`issue 358`_).
+
+- If the `config_file` argument to the Coverage constructor is specified as
+  ".coveragerc", it is treated as if it were True.  This means setup.cfg is
+  also examined, and a missing file is not considered an error (`issue 357`_).
+
+- Wildly experimental: support for measuring processes started by the
+  multiprocessing module.  To use, set ``--concurrency=multiprocessing``,
+  either on the command line or in the .coveragerc file (`issue 117`_). Thanks,
+  Eduardo Schettino.  Currently, this does not work on Windows.
+
+- A new warning is possible, if a desired file isn't measured because it was
+  imported before coverage.py was started (`issue 353`_).
+
+- The `coverage.process_startup` function now will start coverage measurement
+  only once, no matter how many times it is called.  This fixes problems due
+  to unusual virtualenv configurations (`issue 340`_).
+
+- Added 3.5.0a1 to the list of supported CPython versions.
+
+.. _issue 117: https://bitbucket.org/ned/coveragepy/issue/117/enable-coverage-measurement-of-code-run-by
+.. _issue 340: https://bitbucket.org/ned/coveragepy/issue/340/keyerror-subpy
+.. _issue 353: https://bitbucket.org/ned/coveragepy/issue/353/40a3-introduces-an-unexpected-third-case
+.. _issue 357: https://bitbucket.org/ned/coveragepy/issue/357/behavior-changed-when-coveragerc-is
+.. _issue 358: https://bitbucket.org/ned/coveragepy/issue/358/all-coverage-commands-should-adjust
+
+
+Version 4.0a4 --- 2015-01-25
+----------------------------
+
+- Plugins can now provide sys_info for debugging output.
+
+- Started plugins documentation.
+
+- Prepared to move the docs to readthedocs.org.
+
+
+Version 4.0a3 --- 2015-01-20
+----------------------------
+
+- Reports now use file names with extensions.  Previously, a report would
+  describe a/b/c.py as "a/b/c".  Now it is shown as "a/b/c.py".  This allows
+  for better support of non-Python files, and also fixed `issue 69`_.
+
+- The XML report now reports each directory as a package again.  This was a bad
+  regression, I apologize.  This was reported in `issue 235`_, which is now
+  fixed.
+
+- A new configuration option for the XML report: ``[xml] package_depth``
+  controls which directories are identified as packages in the report.
+  Directories deeper than this depth are not reported as packages.
+  The default is that all directories are reported as packages.
+  Thanks, Lex Berezhny.
+
+- When looking for the source for a frame, check if the file exists. On
+  Windows, .pyw files are no longer recorded as .py files. Along the way, this
+  fixed `issue 290`_.
+
+- Empty files are now reported as 100% covered in the XML report, not 0%
+  covered (`issue 345`_).
+
+- Regexes in the configuration file are now compiled as soon as they are read,
+  to provide error messages earlier (`issue 349`_).
+
+.. _issue 69: https://bitbucket.org/ned/coveragepy/issue/69/coverage-html-overwrite-files-that-doesnt
+.. _issue 235: https://bitbucket.org/ned/coveragepy/issue/235/package-name-is-missing-in-xml-report
+.. _issue 290: https://bitbucket.org/ned/coveragepy/issue/290/running-programmatically-with-pyw-files
+.. _issue 345: https://bitbucket.org/ned/coveragepy/issue/345/xml-reports-line-rate-0-for-empty-files
+.. _issue 349: https://bitbucket.org/ned/coveragepy/issue/349/bad-regex-in-config-should-get-an-earlier
+
+
+Version 4.0a2 --- 2015-01-14
+----------------------------
+
+- Officially support PyPy 2.4, and PyPy3 2.4.  Drop support for
+  CPython 3.2 and older versions of PyPy.  The code won't work on CPython 3.2.
+  It will probably still work on older versions of PyPy, but I'm not testing
+  against them.
+
+- Plugins!
+
+- The original command line switches (`-x` to run a program, etc) are no
+  longer supported.
+
+- A new option: `coverage report --skip-covered` will reduce the number of
+  files reported by skipping files with 100% coverage.  Thanks, Krystian
+  Kichewko.  This means that empty `__init__.py` files will be skipped, since
+  they are 100% covered, closing `issue 315`_.
+
+- You can now specify the ``--fail-under`` option in the ``.coveragerc`` file
+  as the ``[report] fail_under`` option.  This closes `issue 314`_.
+
+- The ``COVERAGE_OPTIONS`` environment variable is no longer supported.  It was
+  a hack for ``--timid`` before configuration files were available.
+
+- The HTML report now has filtering.  Type text into the Filter box on the
+  index page, and only modules with that text in the name will be shown.
+  Thanks, Danny Allen.
+
+- The textual report and the HTML report used to report partial branches
+  differently for no good reason.  Now the text report's "missing branches"
+  column is a "partial branches" column so that both reports show the same
+  numbers.  This closes `issue 342`_.
+
+- If you specify a ``--rcfile`` that cannot be read, you will get an error
+  message.  Fixes `issue 343`_.
+
+- The ``--debug`` switch can now be used on any command.
+
+- You can now programmatically adjust the configuration of coverage.py by
+  setting items on `Coverage.config` after construction.
+
+- A module run with ``-m`` can be used as the argument to ``--source``, fixing
+  `issue 328`_.  Thanks, Buck Evan.
+
+- The regex for matching exclusion pragmas has been fixed to allow more kinds
+  of whitespace, fixing `issue 334`_.
+
+- Made some PyPy-specific tweaks to improve speed under PyPy.  Thanks, Alex
+  Gaynor.
+
+- In some cases, with a source file missing a final newline, coverage.py would
+  count statements incorrectly.  This is now fixed, closing `issue 293`_.
+
+- The status.dat file that HTML reports use to avoid re-creating files that
+  haven't changed is now a JSON file instead of a pickle file.  This obviates
+  `issue 287`_ and `issue 237`_.
+
+.. _issue 237: https://bitbucket.org/ned/coveragepy/issue/237/htmlcov-with-corrupt-statusdat
+.. _issue 287: https://bitbucket.org/ned/coveragepy/issue/287/htmlpy-doesnt-specify-pickle-protocol
+.. _issue 293: https://bitbucket.org/ned/coveragepy/issue/293/number-of-statement-detection-wrong-if-no
+.. _issue 314: https://bitbucket.org/ned/coveragepy/issue/314/fail_under-param-not-working-in-coveragerc
+.. _issue 315: https://bitbucket.org/ned/coveragepy/issue/315/option-to-omit-empty-files-eg-__init__py
+.. _issue 328: https://bitbucket.org/ned/coveragepy/issue/328/misbehavior-in-run-source
+.. _issue 334: https://bitbucket.org/ned/coveragepy/issue/334/pragma-not-recognized-if-tab-character
+.. _issue 342: https://bitbucket.org/ned/coveragepy/issue/342/console-and-html-coverage-reports-differ
+.. _issue 343: https://bitbucket.org/ned/coveragepy/issue/343/an-explicitly-named-non-existent-config
+
+
+Version 4.0a1 --- 2014-09-27
+----------------------------
+
+- Python versions supported are now CPython 2.6, 2.7, 3.2, 3.3, and 3.4, and
+  PyPy 2.2.
+
+- Gevent, eventlet, and greenlet are now supported, closing `issue 149`_.
+  The ``concurrency`` setting specifies the concurrency library in use.  Huge
+  thanks to Peter Portante for initial implementation, and to Joe Jevnik for
+  the final insight that completed the work.
+
+- Options are now also read from a setup.cfg file, if any.  Sections are
+  prefixed with "coverage:", so the ``[run]`` options will be read from the
+  ``[coverage:run]`` section of setup.cfg.  Finishes `issue 304`_.
+
+- The ``report -m`` command can now show missing branches when reporting on
+  branch coverage.  Thanks, Steve Leonard. Closes `issue 230`_.
+
+- The XML report now contains a <source> element, fixing `issue 94`_.  Thanks
+  Stan Hu.
+
+- The class defined in the coverage module is now called ``Coverage`` instead
+  of ``coverage``, though the old name still works, for backward compatibility.
+
+- The ``fail-under`` value is now rounded the same as reported results,
+  preventing paradoxical results, fixing `issue 284`_.
+
+- The XML report will now create the output directory if need be, fixing
+  `issue 285`_.  Thanks, Chris Rose.
+
+- HTML reports no longer raise UnicodeDecodeError if a Python file has
+  undecodable characters, fixing `issue 303`_ and `issue 331`_.
+
+- The annotate command will now annotate all files, not just ones relative to
+  the current directory, fixing `issue 57`_.
+
+- The coverage module no longer causes deprecation warnings on Python 3.4 by
+  importing the imp module, fixing `issue 305`_.
+
+- Encoding declarations in source files are only considered if they are truly
+  comments.  Thanks, Anthony Sottile.
+
+.. _issue 57: https://bitbucket.org/ned/coveragepy/issue/57/annotate-command-fails-to-annotate-many
+.. _issue 94: https://bitbucket.org/ned/coveragepy/issue/94/coverage-xml-doesnt-produce-sources
+.. _issue 149: https://bitbucket.org/ned/coveragepy/issue/149/coverage-gevent-looks-broken
+.. _issue 230: https://bitbucket.org/ned/coveragepy/issue/230/show-line-no-for-missing-branches-in
+.. _issue 284: https://bitbucket.org/ned/coveragepy/issue/284/fail-under-should-show-more-precision
+.. _issue 285: https://bitbucket.org/ned/coveragepy/issue/285/xml-report-fails-if-output-file-directory
+.. _issue 303: https://bitbucket.org/ned/coveragepy/issue/303/unicodedecodeerror
+.. _issue 304: https://bitbucket.org/ned/coveragepy/issue/304/attempt-to-get-configuration-from-setupcfg
+.. _issue 305: https://bitbucket.org/ned/coveragepy/issue/305/pendingdeprecationwarning-the-imp-module
+.. _issue 331: https://bitbucket.org/ned/coveragepy/issue/331/failure-of-encoding-detection-on-python2
+
+
+Version 3.7.1 --- 2013-12-13
+----------------------------
+
+- Improved the speed of HTML report generation by about 20%.
+
+- Fixed the mechanism for finding OS-installed static files for the HTML report
+  so that it will actually find OS-installed static files.
+
+
+Version 3.7 --- 2013-10-06
+--------------------------
+
+- Added the ``--debug`` switch to ``coverage run``.  It accepts a list of
+  options indicating the type of internal activity to log to stderr.
+
+- Improved the branch coverage facility, fixing `issue 92`_ and `issue 175`_.
+
+- Running code with ``coverage run -m`` now behaves more like Python does,
+  setting sys.path properly, which fixes `issue 207`_ and `issue 242`_.
+
+- Coverage.py can now run .pyc files directly, closing `issue 264`_.
+
+- Coverage.py properly supports .pyw files, fixing `issue 261`_.
+
+- Omitting files within a tree specified with the ``source`` option would
+  cause them to be incorrectly marked as unexecuted, as described in
+  `issue 218`_.  This is now fixed.
+
+- When specifying paths to alias together during data combining, you can now
+  specify relative paths, fixing `issue 267`_.
+
+- Most file paths can now be specified with username expansion (``~/src``, or
+  ``~build/src``, for example), and with environment variable expansion
+  (``build/$BUILDNUM/src``).
+
+- Trying to create an XML report with no files to report on, would cause a
+  ZeroDivideError, but no longer does, fixing `issue 250`_.
+
+- When running a threaded program under the Python tracer, coverage.py no
+  longer issues a spurious warning about the trace function changing: "Trace
+  function changed, measurement is likely wrong: None."  This fixes `issue
+  164`_.
+
+- Static files necessary for HTML reports are found in system-installed places,
+  to ease OS-level packaging of coverage.py.  Closes `issue 259`_.
+
+- Source files with encoding declarations, but a blank first line, were not
+  decoded properly.  Now they are.  Thanks, Roger Hu.
+
+- The source kit now includes the ``__main__.py`` file in the root coverage
+  directory, fixing `issue 255`_.
+
+.. _issue 92: https://bitbucket.org/ned/coveragepy/issue/92/finally-clauses-arent-treated-properly-in
+.. _issue 164: https://bitbucket.org/ned/coveragepy/issue/164/trace-function-changed-warning-when-using
+.. _issue 175: https://bitbucket.org/ned/coveragepy/issue/175/branch-coverage-gets-confused-in-certain
+.. _issue 207: https://bitbucket.org/ned/coveragepy/issue/207/run-m-cannot-find-module-or-package-in
+.. _issue 242: https://bitbucket.org/ned/coveragepy/issue/242/running-a-two-level-package-doesnt-work
+.. _issue 218: https://bitbucket.org/ned/coveragepy/issue/218/run-command-does-not-respect-the-omit-flag
+.. _issue 250: https://bitbucket.org/ned/coveragepy/issue/250/uncaught-zerodivisionerror-when-generating
+.. _issue 255: https://bitbucket.org/ned/coveragepy/issue/255/directory-level-__main__py-not-included-in
+.. _issue 259: https://bitbucket.org/ned/coveragepy/issue/259/allow-use-of-system-installed-third-party
+.. _issue 261: https://bitbucket.org/ned/coveragepy/issue/261/pyw-files-arent-reported-properly
+.. _issue 264: https://bitbucket.org/ned/coveragepy/issue/264/coverage-wont-run-pyc-files
+.. _issue 267: https://bitbucket.org/ned/coveragepy/issue/267/relative-path-aliases-dont-work
+
+
+Version 3.6 --- 2013-01-05
+--------------------------
+
+- Added a page to the docs about troublesome situations, closing `issue 226`_,
+  and added some info to the TODO file, closing `issue 227`_.
+
+.. _issue 226: https://bitbucket.org/ned/coveragepy/issue/226/make-readme-section-to-describe-when
+.. _issue 227: https://bitbucket.org/ned/coveragepy/issue/227/update-todo
+
+
+Version 3.6b3 --- 2012-12-29
+----------------------------
+
+- Beta 2 broke the nose plugin. It's fixed again, closing `issue 224`_.
+
+.. _issue 224: https://bitbucket.org/ned/coveragepy/issue/224/36b2-breaks-nosexcover
+
+
+Version 3.6b2 --- 2012-12-23
+----------------------------
+
+- Coverage.py runs on Python 2.3 and 2.4 again. It was broken in 3.6b1.
+
+- The C extension is optionally compiled using a different more widely-used
+  technique, taking another stab at fixing `issue 80`_ once and for all.
+
+- Combining data files would create entries for phantom files if used with
+  ``source`` and path aliases.  It no longer does.
+
+- ``debug sys`` now shows the configuration file path that was read.
+
+- If an oddly-behaved package claims that code came from an empty-string
+  file name, coverage.py no longer associates it with the directory name,
+  fixing `issue 221`_.
+
+.. _issue 221: https://bitbucket.org/ned/coveragepy/issue/221/coveragepy-incompatible-with-pyratemp
+
+
+Version 3.6b1 --- 2012-11-28
+----------------------------
+
+- Wildcards in ``include=`` and ``omit=`` arguments were not handled properly
+  in reporting functions, though they were when running.  Now they are handled
+  uniformly, closing `issue 143`_ and `issue 163`_.  **NOTE**: it is possible
+  that your configurations may now be incorrect.  If you use ``include`` or
+  ``omit`` during reporting, whether on the command line, through the API, or
+  in a configuration file, please check carefully that you were not relying on
+  the old broken behavior.
+
+- The **report**, **html**, and **xml** commands now accept a ``--fail-under``
+  switch that indicates in the exit status whether the coverage percentage was
+  less than a particular value.  Closes `issue 139`_.
+
+- The reporting functions coverage.report(), coverage.html_report(), and
+  coverage.xml_report() now all return a float, the total percentage covered
+  measurement.
+
+- The HTML report's title can now be set in the configuration file, with the
+  ``--title`` switch on the command line, or via the API.
+
+- Configuration files now support substitution of environment variables, using
+  syntax like ``${WORD}``.  Closes `issue 97`_.
+
+- Embarrassingly, the ``[xml] output=`` setting in the .coveragerc file simply
+  didn't work.  Now it does.
+
+- The XML report now consistently uses file names for the file name attribute,
+  rather than sometimes using module names.  Fixes `issue 67`_.
+  Thanks, Marcus Cobden.
+
+- Coverage percentage metrics are now computed slightly differently under
+  branch coverage.  This means that completely unexecuted files will now
+  correctly have 0% coverage, fixing `issue 156`_.  This also means that your
+  total coverage numbers will generally now be lower if you are measuring
+  branch coverage.
+
+- When installing, now in addition to creating a "coverage" command, two new
+  aliases are also installed.  A "coverage2" or "coverage3" command will be
+  created, depending on whether you are installing in Python 2.x or 3.x.
+  A "coverage-X.Y" command will also be created corresponding to your specific
+  version of Python.  Closes `issue 111`_.
+
+- The coverage.py installer no longer tries to bootstrap setuptools or
+  Distribute.  You must have one of them installed first, as `issue 202`_
+  recommended.
+
+- The coverage.py kit now includes docs (closing `issue 137`_) and tests.
+
+- On Windows, files are now reported in their correct case, fixing `issue 89`_
+  and `issue 203`_.
+
+- If a file is missing during reporting, the path shown in the error message
+  is now correct, rather than an incorrect path in the current directory.
+  Fixes `issue 60`_.
+
+- Running an HTML report in Python 3 in the same directory as an old Python 2
+  HTML report would fail with a UnicodeDecodeError. This issue (`issue 193`_)
+  is now fixed.
+
+- Fixed yet another error trying to parse non-Python files as Python, this
+  time an IndentationError, closing `issue 82`_ for the fourth time...
+
+- If `coverage xml` fails because there is no data to report, it used to
+  create a zero-length XML file.  Now it doesn't, fixing `issue 210`_.
+
+- Jython files now work with the ``--source`` option, fixing `issue 100`_.
+
+- Running coverage.py under a debugger is unlikely to work, but it shouldn't
+  fail with "TypeError: 'NoneType' object is not iterable".  Fixes `issue
+  201`_.
+
+- On some Linux distributions, when installed with the OS package manager,
+  coverage.py would report its own code as part of the results.  Now it won't,
+  fixing `issue 214`_, though this will take some time to be repackaged by the
+  operating systems.
+
+- Docstrings for the legacy singleton methods are more helpful.  Thanks Marius
+  Gedminas.  Closes `issue 205`_.
+
+- The pydoc tool can now show documentation for the class `coverage.coverage`.
+  Closes `issue 206`_.
+
+- Added a page to the docs about contributing to coverage.py, closing
+  `issue 171`_.
+
+- When coverage.py ended unsuccessfully, it may have reported odd errors like
+  ``'NoneType' object has no attribute 'isabs'``.  It no longer does,
+  so kiss `issue 153`_ goodbye.
+
+.. _issue 60: https://bitbucket.org/ned/coveragepy/issue/60/incorrect-path-to-orphaned-pyc-files
+.. _issue 67: https://bitbucket.org/ned/coveragepy/issue/67/xml-report-filenames-may-be-generated
+.. _issue 89: https://bitbucket.org/ned/coveragepy/issue/89/on-windows-all-packages-are-reported-in
+.. _issue 97: https://bitbucket.org/ned/coveragepy/issue/97/allow-environment-variables-to-be
+.. _issue 100: https://bitbucket.org/ned/coveragepy/issue/100/source-directive-doesnt-work-for-packages
+.. _issue 111: https://bitbucket.org/ned/coveragepy/issue/111/when-installing-coverage-with-pip-not
+.. _issue 137: https://bitbucket.org/ned/coveragepy/issue/137/provide-docs-with-source-distribution
+.. _issue 139: https://bitbucket.org/ned/coveragepy/issue/139/easy-check-for-a-certain-coverage-in-tests
+.. _issue 143: https://bitbucket.org/ned/coveragepy/issue/143/omit-doesnt-seem-to-work-in-coverage
+.. _issue 153: https://bitbucket.org/ned/coveragepy/issue/153/non-existent-filename-triggers
+.. _issue 156: https://bitbucket.org/ned/coveragepy/issue/156/a-completely-unexecuted-file-shows-14
+.. _issue 163: https://bitbucket.org/ned/coveragepy/issue/163/problem-with-include-and-omit-filename
+.. _issue 171: https://bitbucket.org/ned/coveragepy/issue/171/how-to-contribute-and-run-tests
+.. _issue 193: https://bitbucket.org/ned/coveragepy/issue/193/unicodedecodeerror-on-htmlpy
+.. _issue 201: https://bitbucket.org/ned/coveragepy/issue/201/coverage-using-django-14-with-pydb-on
+.. _issue 202: https://bitbucket.org/ned/coveragepy/issue/202/get-rid-of-ez_setuppy-and
+.. _issue 203: https://bitbucket.org/ned/coveragepy/issue/203/duplicate-filenames-reported-when-filename
+.. _issue 205: https://bitbucket.org/ned/coveragepy/issue/205/make-pydoc-coverage-more-friendly
+.. _issue 206: https://bitbucket.org/ned/coveragepy/issue/206/pydoc-coveragecoverage-fails-with-an-error
+.. _issue 210: https://bitbucket.org/ned/coveragepy/issue/210/if-theres-no-coverage-data-coverage-xml
+.. _issue 214: https://bitbucket.org/ned/coveragepy/issue/214/coveragepy-measures-itself-on-precise
+
+
+Version 3.5.3 --- 2012-09-29
+----------------------------
+
+- Line numbers in the HTML report line up better with the source lines, fixing
+  `issue 197`_, thanks Marius Gedminas.
+
+- When specifying a directory as the source= option, the directory itself no
+  longer needs to have a ``__init__.py`` file, though its sub-directories do,
+  to be considered as source files.
+
+- Files encoded as UTF-8 with a BOM are now properly handled, fixing
+  `issue 179`_.  Thanks, Pablo Carballo.
+
+- Fixed more cases of non-Python files being reported as Python source, and
+  then not being able to parse them as Python.  Closes `issue 82`_ (again).
+  Thanks, Julian Berman.
+
+- Fixed memory leaks under Python 3, thanks, Brett Cannon. Closes `issue 147`_.
+
+- Optimized .pyo files may not have been handled correctly, `issue 195`_.
+  Thanks, Marius Gedminas.
+
+- Certain unusually named file paths could have been mangled during reporting,
+  `issue 194`_.  Thanks, Marius Gedminas.
+
+- Try to do a better job of the impossible task of detecting when we can't
+  build the C extension, fixing `issue 183`_.
+
+- Testing is now done with `tox`_, thanks, Marc Abramowitz.
+
+.. _issue 147: https://bitbucket.org/ned/coveragepy/issue/147/massive-memory-usage-by-ctracer
+.. _issue 179: https://bitbucket.org/ned/coveragepy/issue/179/htmlreporter-fails-when-source-file-is
+.. _issue 183: https://bitbucket.org/ned/coveragepy/issue/183/install-fails-for-python-23
+.. _issue 194: https://bitbucket.org/ned/coveragepy/issue/194/filelocatorrelative_filename-could-mangle
+.. _issue 195: https://bitbucket.org/ned/coveragepy/issue/195/pyo-file-handling-in-codeunit
+.. _issue 197: https://bitbucket.org/ned/coveragepy/issue/197/line-numbers-in-html-report-do-not-align
+.. _tox: http://tox.readthedocs.org/
+
+
+Version 3.5.2 --- 2012-05-04
+----------------------------
+
+No changes since 3.5.2.b1
+
+
+Version 3.5.2b1 --- 2012-04-29
+------------------------------
+
+- The HTML report has slightly tweaked controls: the buttons at the top of
+  the page are color-coded to the source lines they affect.
+
+- Custom CSS can be applied to the HTML report by specifying a CSS file as
+  the ``extra_css`` configuration value in the ``[html]`` section.
+
+- Source files with custom encodings declared in a comment at the top are now
+  properly handled during reporting on Python 2.  Python 3 always handled them
+  properly.  This fixes `issue 157`_.
+
+- Backup files left behind by editors are no longer collected by the source=
+  option, fixing `issue 168`_.
+
+- If a file doesn't parse properly as Python, we don't report it as an error
+  if the file name seems like maybe it wasn't meant to be Python.  This is a
+  pragmatic fix for `issue 82`_.
+
+- The ``-m`` switch on ``coverage report``, which includes missing line numbers
+  in the summary report, can now be specified as ``show_missing`` in the
+  config file.  Closes `issue 173`_.
+
+- When running a module with ``coverage run -m <modulename>``, certain details
+  of the execution environment weren't the same as for
+  ``python -m <modulename>``.  This had the unfortunate side-effect of making
+  ``coverage run -m unittest discover`` not work if you had tests in a
+  directory named "test".  This fixes `issue 155`_ and `issue 142`_.
+
+- Now the exit status of your product code is properly used as the process
+  status when running ``python -m coverage run ...``.  Thanks, JT Olds.
+
+- When installing into pypy, we no longer attempt (and fail) to compile
+  the C tracer function, closing `issue 166`_.
+
+.. _issue 142: https://bitbucket.org/ned/coveragepy/issue/142/executing-python-file-syspath-is-replaced
+.. _issue 155: https://bitbucket.org/ned/coveragepy/issue/155/cant-use-coverage-run-m-unittest-discover
+.. _issue 157: https://bitbucket.org/ned/coveragepy/issue/157/chokes-on-source-files-with-non-utf-8
+.. _issue 166: https://bitbucket.org/ned/coveragepy/issue/166/dont-try-to-compile-c-extension-on-pypy
+.. _issue 168: https://bitbucket.org/ned/coveragepy/issue/168/dont-be-alarmed-by-emacs-droppings
+.. _issue 173: https://bitbucket.org/ned/coveragepy/issue/173/theres-no-way-to-specify-show-missing-in
+
+
+Version 3.5.1 --- 2011-09-23
+----------------------------
+
+- The ``[paths]`` feature unfortunately didn't work in real world situations
+  where you wanted to, you know, report on the combined data.  Now all paths
+  stored in the combined file are canonicalized properly.
+
+
+Version 3.5.1b1 --- 2011-08-28
+------------------------------
+
+- When combining data files from parallel runs, you can now instruct
+  coverage.py about which directories are equivalent on different machines.  A
+  ``[paths]`` section in the configuration file lists paths that are to be
+  considered equivalent.  Finishes `issue 17`_.
+
+- for-else constructs are understood better, and don't cause erroneous partial
+  branch warnings.  Fixes `issue 122`_.
+
+- Branch coverage for ``with`` statements is improved, fixing `issue 128`_.
+
+- The number of partial branches reported on the HTML summary page was
+  different than the number reported on the individual file pages.  This is
+  now fixed.
+
+- An explicit include directive to measure files in the Python installation
+  wouldn't work because of the standard library exclusion.  Now the include
+  directive takes precedence, and the files will be measured.  Fixes
+  `issue 138`_.
+
+- The HTML report now handles Unicode characters in Python source files
+  properly.  This fixes `issue 124`_ and `issue 144`_. Thanks, Devin
+  Jeanpierre.
+
+- In order to help the core developers measure the test coverage of the
+  standard library, Brandon Rhodes devised an aggressive hack to trick Python
+  into running some coverage.py code before anything else in the process.
+  See the coverage/fullcoverage directory if you are interested.
+
+.. _issue 17: http://bitbucket.org/ned/coveragepy/issue/17/support-combining-coverage-data-from
+.. _issue 122: http://bitbucket.org/ned/coveragepy/issue/122/for-else-always-reports-missing-branch
+.. _issue 124: http://bitbucket.org/ned/coveragepy/issue/124/no-arbitrary-unicode-in-html-reports-in
+.. _issue 128: http://bitbucket.org/ned/coveragepy/issue/128/branch-coverage-of-with-statement-in-27
+.. _issue 138: http://bitbucket.org/ned/coveragepy/issue/138/include-should-take-precedence-over-is
+.. _issue 144: http://bitbucket.org/ned/coveragepy/issue/144/failure-generating-html-output-for
+
+
+Version 3.5 --- 2011-06-29
+--------------------------
+
+- The HTML report hotkeys now behave slightly differently when the current
+  chunk isn't visible at all:  a chunk on the screen will be selected,
+  instead of the old behavior of jumping to the literal next chunk.
+  The hotkeys now work in Google Chrome.  Thanks, Guido van Rossum.
+
+
+Version 3.5b1 --- 2011-06-05
+----------------------------
+
+- The HTML report now has hotkeys.  Try ``n``, ``s``, ``m``, ``x``, ``b``,
+  ``p``, and ``c`` on the overview page to change the column sorting.
+  On a file page, ``r``, ``m``, ``x``, and ``p`` toggle the run, missing,
+  excluded, and partial line markings.  You can navigate the highlighted
+  sections of code by using the ``j`` and ``k`` keys for next and previous.
+  The ``1`` (one) key jumps to the first highlighted section in the file,
+  and ``0`` (zero) scrolls to the top of the file.
+
+- The ``--omit`` and ``--include`` switches now interpret their values more
+  usefully.  If the value starts with a wildcard character, it is used as-is.
+  If it does not, it is interpreted relative to the current directory.
+  Closes `issue 121`_.
+
+- Partial branch warnings can now be pragma'd away.  The configuration option
+  ``partial_branches`` is a list of regular expressions.  Lines matching any of
+  those expressions will never be marked as a partial branch.  In addition,
+  there's a built-in list of regular expressions marking statements which should
+  never be marked as partial.  This list includes ``while True:``, ``while 1:``,
+  ``if 1:``, and ``if 0:``.
+
+- The ``coverage()`` constructor accepts single strings for the ``omit=`` and
+  ``include=`` arguments, adapting to a common error in programmatic use.
+
+- Modules can now be run directly using ``coverage run -m modulename``, to
+  mirror Python's ``-m`` flag.  Closes `issue 95`_, thanks, Brandon Rhodes.
+
+- ``coverage run`` didn't emulate Python accurately in one small detail: the
+  current directory inserted into ``sys.path`` was relative rather than
+  absolute. This is now fixed.
+
+- HTML reporting is now incremental: a record is kept of the data that
+  produced the HTML reports, and only files whose data has changed will
+  be generated.  This should make most HTML reporting faster.
+
+- Pathological code execution could disable the trace function behind our
+  backs, leading to incorrect code measurement.  Now if this happens,
+  coverage.py will issue a warning, at least alerting you to the problem.
+  Closes `issue 93`_.  Thanks to Marius Gedminas for the idea.
+
+- The C-based trace function now behaves properly when saved and restored
+  with ``sys.gettrace()`` and ``sys.settrace()``.  This fixes `issue 125`_
+  and `issue 123`_.  Thanks, Devin Jeanpierre.
+
+- Source files are now opened with Python 3.2's ``tokenize.open()`` where
+  possible, to get the best handling of Python source files with encodings.
+  Closes `issue 107`_, thanks, Brett Cannon.
+
+- Syntax errors in supposed Python files can now be ignored during reporting
+  with the ``-i`` switch just like other source errors.  Closes `issue 115`_.
+
+- Installation from source now succeeds on machines without a C compiler,
+  closing `issue 80`_.
+
+- Coverage.py can now be run directly from a working tree by specifying
+  the directory name to python:  ``python coverage_py_working_dir run ...``.
+  Thanks, Brett Cannon.
+
+- A little bit of Jython support: `coverage run` can now measure Jython
+  execution by adapting when $py.class files are traced. Thanks, Adi Roiban.
+  Jython still doesn't provide the Python libraries needed to make
+  coverage reporting work, unfortunately.
+
+- Internally, files are now closed explicitly, fixing `issue 104`_.  Thanks,
+  Brett Cannon.
+
+.. _issue 80: https://bitbucket.org/ned/coveragepy/issue/80/is-there-a-duck-typing-way-to-know-we-cant
+.. _issue 93: http://bitbucket.org/ned/coveragepy/issue/93/copying-a-mock-object-breaks-coverage
+.. _issue 95: https://bitbucket.org/ned/coveragepy/issue/95/run-subcommand-should-take-a-module-name
+.. _issue 104: https://bitbucket.org/ned/coveragepy/issue/104/explicitly-close-files
+.. _issue 107: https://bitbucket.org/ned/coveragepy/issue/107/codeparser-not-opening-source-files-with
+.. _issue 115: https://bitbucket.org/ned/coveragepy/issue/115/fail-gracefully-when-reporting-on-file
+.. _issue 121: https://bitbucket.org/ned/coveragepy/issue/121/filename-patterns-are-applied-stupidly
+.. _issue 123: https://bitbucket.org/ned/coveragepy/issue/123/pyeval_settrace-used-in-way-that-breaks
+.. _issue 125: https://bitbucket.org/ned/coveragepy/issue/125/coverage-removes-decoratortoolss-tracing
+
+
+Version 3.4 --- 2010-09-19
+--------------------------
+
+- The XML report is now sorted by package name, fixing `issue 88`_.
+
+- Programs that exited with ``sys.exit()`` with no argument weren't handled
+  properly, producing a coverage.py stack trace.  That is now fixed.
+
+.. _issue 88: http://bitbucket.org/ned/coveragepy/issue/88/xml-report-lists-packages-in-random-order
+
+
+Version 3.4b2 --- 2010-09-06
+----------------------------
+
+- Completely unexecuted files can now be included in coverage results, reported
+  as 0% covered.  This only happens if the --source option is specified, since
+  coverage.py needs guidance about where to look for source files.
+
+- The XML report output now properly includes a percentage for branch coverage,
+  fixing `issue 65`_ and `issue 81`_.
+
+- Coverage percentages are now displayed uniformly across reporting methods.
+  Previously, different reports could round percentages differently.  Also,
+  percentages are only reported as 0% or 100% if they are truly 0 or 100, and
+  are rounded otherwise.  Fixes `issue 41`_ and `issue 70`_.
+
+- The precision of reported coverage percentages can be set with the
+  ``[report] precision`` config file setting.  Completes `issue 16`_.
+
+- Threads derived from ``threading.Thread`` with an overridden `run` method
+  would report no coverage for the `run` method.  This is now fixed, closing
+  `issue 85`_.
+
+.. _issue 16: http://bitbucket.org/ned/coveragepy/issue/16/allow-configuration-of-accuracy-of-percentage-totals
+.. _issue 41: http://bitbucket.org/ned/coveragepy/issue/41/report-says-100-when-it-isnt-quite-there
+.. _issue 65: http://bitbucket.org/ned/coveragepy/issue/65/branch-option-not-reported-in-cobertura
+.. _issue 70: http://bitbucket.org/ned/coveragepy/issue/70/text-report-and-html-report-disagree-on-coverage
+.. _issue 81: http://bitbucket.org/ned/coveragepy/issue/81/xml-report-does-not-have-condition-coverage-attribute-for-lines-with-a
+.. _issue 85: http://bitbucket.org/ned/coveragepy/issue/85/threadrun-isnt-measured
+
+
+Version 3.4b1 --- 2010-08-21
+----------------------------
+
+- BACKWARD INCOMPATIBILITY: the ``--omit`` and ``--include`` switches now take
+  file patterns rather than file prefixes, closing `issue 34`_ and `issue 36`_.
+
+- BACKWARD INCOMPATIBILITY: the `omit_prefixes` argument is gone throughout
+  coverage.py, replaced with `omit`, a list of file name patterns suitable for
+  `fnmatch`.  A parallel argument `include` controls what files are included.
+
+- The run command now has a ``--source`` switch, a list of directories or
+  module names.  If provided, coverage.py will only measure execution in those
+  source files.
+
+- Various warnings are printed to stderr for problems encountered during data
+  measurement: if a ``--source`` module has no Python source to measure, or is
+  never encountered at all, or if no data is collected.
+
+- The reporting commands (report, annotate, html, and xml) now have an
+  ``--include`` switch to restrict reporting to modules matching those file
+  patterns, similar to the existing ``--omit`` switch. Thanks, Zooko.
+
+- The run command now supports ``--include`` and ``--omit`` to control what
+  modules it measures. This can speed execution and reduce the amount of data
+  during reporting. Thanks Zooko.
+
+- Since coverage.py 3.1, using the Python trace function has been slower than
+  it needs to be.  A cache of tracing decisions was broken, but has now been
+  fixed.
+
+- Python 2.7 and 3.2 have introduced new opcodes that are now supported.
+
+- Python files with no statements, for example, empty ``__init__.py`` files,
+  are now reported as having zero statements instead of one.  Fixes `issue 1`_.
+
+- Reports now have a column of missed line counts rather than executed line
+  counts, since developers should focus on reducing the missed lines to zero,
+  rather than increasing the executed lines to varying targets.  Once
+  suggested, this seemed blindingly obvious.
+
+- Line numbers in HTML source pages are clickable, linking directly to that
+  line, which is highlighted on arrival.  Added a link back to the index page
+  at the bottom of each HTML page.
+
+- Programs that call ``os.fork`` will properly collect data from both the child
+  and parent processes.  Use ``coverage run -p`` to get two data files that can
+  be combined with ``coverage combine``.  Fixes `issue 56`_.
+
+- Coverage.py is now runnable as a module: ``python -m coverage``.  Thanks,
+  Brett Cannon.
+
+- When measuring code running in a virtualenv, most of the system library was
+  being measured when it shouldn't have been.  This is now fixed.
+
+- Doctest text files are no longer recorded in the coverage data, since they
+  can't be reported anyway.  Fixes `issue 52`_ and `issue 61`_.
+
+- Jinja HTML templates compile into Python code using the HTML file name,
+  which confused coverage.py.  Now these files are no longer traced, fixing
+  `issue 82`_.
+
+- Source files can have more than one dot in them (foo.test.py), and will be
+  treated properly while reporting.  Fixes `issue 46`_.
+
+- Source files with DOS line endings are now properly tokenized for syntax
+  coloring on non-DOS machines.  Fixes `issue 53`_.
+
+- Unusual code structure that confused exits from methods with exits from
+  classes is now properly analyzed.  See `issue 62`_.
+
+- Asking for an HTML report with no files now shows a nice error message rather
+  than a cryptic failure ('int' object is unsubscriptable). Fixes `issue 59`_.
+
+.. _issue 1:  http://bitbucket.org/ned/coveragepy/issue/1/empty-__init__py-files-are-reported-as-1-executable
+.. _issue 34: http://bitbucket.org/ned/coveragepy/issue/34/enhanced-omit-globbing-handling
+.. _issue 36: http://bitbucket.org/ned/coveragepy/issue/36/provide-regex-style-omit
+.. _issue 46: http://bitbucket.org/ned/coveragepy/issue/46
+.. _issue 53: http://bitbucket.org/ned/coveragepy/issue/53
+.. _issue 52: http://bitbucket.org/ned/coveragepy/issue/52/doctesttestfile-confuses-source-detection
+.. _issue 56: http://bitbucket.org/ned/coveragepy/issue/56
+.. _issue 61: http://bitbucket.org/ned/coveragepy/issue/61/annotate-i-doesnt-work
+.. _issue 62: http://bitbucket.org/ned/coveragepy/issue/62
+.. _issue 59: http://bitbucket.org/ned/coveragepy/issue/59/html-report-fails-with-int-object-is
+.. _issue 82: http://bitbucket.org/ned/coveragepy/issue/82/tokenerror-when-generating-html-report
+
+
+Version 3.3.1 --- 2010-03-06
+----------------------------
+
+- Using `parallel=True` in .coveragerc file prevented reporting, but now does
+  not, fixing `issue 49`_.
+
+- When running your code with "coverage run", if you call `sys.exit()`,
+  coverage.py will exit with that status code, fixing `issue 50`_.
+
+.. _issue 49: http://bitbucket.org/ned/coveragepy/issue/49
+.. _issue 50: http://bitbucket.org/ned/coveragepy/issue/50
+
+
+Version 3.3 --- 2010-02-24
+--------------------------
+
+- Settings are now read from a .coveragerc file.  A specific file can be
+  specified on the command line with --rcfile=FILE.  The name of the file can
+  be programmatically set with the `config_file` argument to the coverage()
+  constructor, or reading a config file can be disabled with
+  `config_file=False`.
+
+- Fixed a problem with nested loops having their branch possibilities
+  mischaracterized: `issue 39`_.
+
+- Added coverage.process_start to enable coverage measurement when Python
+  starts.
+
+- Parallel data file names now have a random number appended to them in
+  addition to the machine name and process id.
+
+- Parallel data files combined with "coverage combine" are deleted after
+  they're combined, to clean up unneeded files.  Fixes `issue 40`_.
+
+- Exceptions thrown from product code run with "coverage run" are now displayed
+  without internal coverage.py frames, so the output is the same as when the
+  code is run without coverage.py.
+
+- The `data_suffix` argument to the coverage constructor is now appended with
+  an added dot rather than simply appended, so that .coveragerc files will not
+  be confused for data files.
+
+- Python source files that don't end with a newline can now be executed, fixing
+  `issue 47`_.
+
+- Added an AUTHORS.txt file.
+
+.. _issue 39: http://bitbucket.org/ned/coveragepy/issue/39
+.. _issue 40: http://bitbucket.org/ned/coveragepy/issue/40
+.. _issue 47: http://bitbucket.org/ned/coveragepy/issue/47
+
+
+Version 3.2 --- 2009-12-05
+--------------------------
+
+- Added a ``--version`` option on the command line.
+
+
+Version 3.2b4 --- 2009-12-01
+----------------------------
+
+- Branch coverage improvements:
+
+  - The XML report now includes branch information.
+
+- Click-to-sort HTML report columns are now persisted in a cookie.  Viewing
+  a report will sort it first the way you last had a coverage report sorted.
+  Thanks, `Chris Adams`_.
+
+- On Python 3.x, setuptools has been replaced by `Distribute`_.
+
+.. _Distribute: http://packages.python.org/distribute/
+
+
+Version 3.2b3 --- 2009-11-23
+----------------------------
+
+- Fixed a memory leak in the C tracer that was introduced in 3.2b1.
+
+- Branch coverage improvements:
+
+  - Branches to excluded code are ignored.
+
+- The table of contents in the HTML report is now sortable: click the headers
+  on any column.  Thanks, `Chris Adams`_.
+
+.. _Chris Adams: http://improbable.org/chris/
+
+
+Version 3.2b2 --- 2009-11-19
+----------------------------
+
+- Branch coverage improvements:
+
+  - Classes are no longer incorrectly marked as branches: `issue 32`_.
+
+  - "except" clauses with types are no longer incorrectly marked as branches:
+    `issue 35`_.
+
+- Fixed some problems syntax coloring sources with line continuations and
+  source with tabs: `issue 30`_ and `issue 31`_.
+
+- The --omit option now works much better than before, fixing `issue 14`_ and
+  `issue 33`_.  Thanks, Danek Duvall.
+
+.. _issue 14: http://bitbucket.org/ned/coveragepy/issue/14
+.. _issue 30: http://bitbucket.org/ned/coveragepy/issue/30
+.. _issue 31: http://bitbucket.org/ned/coveragepy/issue/31
+.. _issue 32: http://bitbucket.org/ned/coveragepy/issue/32
+.. _issue 33: http://bitbucket.org/ned/coveragepy/issue/33
+.. _issue 35: http://bitbucket.org/ned/coveragepy/issue/35
+
+
+Version 3.2b1 --- 2009-11-10
+----------------------------
+
+- Branch coverage!
+
+- XML reporting has file paths that let Cobertura find the source code.
+
+- The tracer code has changed, it's a few percent faster.
+
+- Some exceptions reported by the command line interface have been cleaned up
+  so that tracebacks inside coverage.py aren't shown.  Fixes `issue 23`_.
+
+.. _issue 23: http://bitbucket.org/ned/coveragepy/issue/23
+
+
+Version 3.1 --- 2009-10-04
+--------------------------
+
+- Source code can now be read from eggs.  Thanks, Ross Lawley.  Fixes
+  `issue 25`_.
+
+.. _issue 25: http://bitbucket.org/ned/coveragepy/issue/25
+
+
+Version 3.1b1 --- 2009-09-27
+----------------------------
+
+- Python 3.1 is now supported.
+
+- Coverage.py has a new command line syntax with sub-commands.  This expands
+  the possibilities for adding features and options in the future.  The old
+  syntax is still supported.  Try "coverage help" to see the new commands.
+  Thanks to Ben Finney for early help.
+
+- Added an experimental "coverage xml" command for producing coverage reports
+  in a Cobertura-compatible XML format.  Thanks, Bill Hart.
+
+- Added the --timid option to enable a simpler slower trace function that works
+  for DecoratorTools projects, including TurboGears.  Fixed `issue 12`_ and
+  `issue 13`_.
+
+- HTML reports show modules from other directories.  Fixed `issue 11`_.
+
+- HTML reports now display syntax-colored Python source.
+
+- Programs that change directory will still write .coverage files in the
+  directory where execution started.  Fixed `issue 24`_.
+
+- Added a "coverage debug" command for getting diagnostic information about the
+  coverage.py installation.
+
+.. _issue 11: http://bitbucket.org/ned/coveragepy/issue/11
+.. _issue 12: http://bitbucket.org/ned/coveragepy/issue/12
+.. _issue 13: http://bitbucket.org/ned/coveragepy/issue/13
+.. _issue 24: http://bitbucket.org/ned/coveragepy/issue/24
+
+
+Version 3.0.1 --- 2009-07-07
+----------------------------
+
+- Removed the recursion limit in the tracer function.  Previously, code that
+  ran more than 500 frames deep would crash. Fixed `issue 9`_.
+
+- Fixed a bizarre problem involving pyexpat, whereby lines following XML parser
+  invocations could be overlooked.  Fixed `issue 10`_.
+
+- On Python 2.3, coverage.py could mis-measure code with exceptions being
+  raised.  This is now fixed.
+
+- The coverage.py code itself will now not be measured by coverage.py, and no
+  coverage.py modules will be mentioned in the nose --with-cover plug-in.
+  Fixed `issue 8`_.
+
+- When running source files, coverage.py now opens them in universal newline
+  mode just like Python does.  This lets it run Windows files on Mac, for
+  example.
+
+.. _issue 9: http://bitbucket.org/ned/coveragepy/issue/9
+.. _issue 10: http://bitbucket.org/ned/coveragepy/issue/10
+.. _issue 8: http://bitbucket.org/ned/coveragepy/issue/8
+
+
+Version 3.0 --- 2009-06-13
+--------------------------
+
+- Fixed the way the Python library was ignored.  Too much code was being
+  excluded the old way.
+
+- Tabs are now properly converted in HTML reports.  Previously indentation was
+  lost.  Fixed `issue 6`_.
+
+- Nested modules now get a proper flat_rootname.  Thanks, Christian Heimes.
+
+.. _issue 6: http://bitbucket.org/ned/coveragepy/issue/6
+
+
+Version 3.0b3 --- 2009-05-16
+----------------------------
+
+- Added parameters to coverage.__init__ for options that had been set on the
+  coverage object itself.
+
+- Added clear_exclude() and get_exclude_list() methods for programmatic
+  manipulation of the exclude regexes.
+
+- Added coverage.load() to read previously-saved data from the data file.
+
+- Improved the finding of code files.  For example, .pyc files that have been
+  installed after compiling are now located correctly.  Thanks, Detlev
+  Offenbach.
+
+- When using the object API (that is, constructing a coverage() object), data
+  is no longer saved automatically on process exit.  You can re-enable it with
+  the auto_data=True parameter on the coverage() constructor. The module-level
+  interface still uses automatic saving.
+
+
+Version 3.0b --- 2009-04-30
+---------------------------
+
+HTML reporting, and continued refactoring.
+
+- HTML reports and annotation of source files: use the new -b (browser) switch.
+  Thanks to George Song for code, inspiration and guidance.
+
+- Code in the Python standard library is not measured by default.  If you need
+  to measure standard library code, use the -L command-line switch during
+  execution, or the cover_pylib=True argument to the coverage() constructor.
+
+- Source annotation into a directory (-a -d) behaves differently.  The
+  annotated files are named with their hierarchy flattened so that same-named
+  files from different directories no longer collide.  Also, only files in the
+  current tree are included.
+
+- coverage.annotate_file is no longer available.
+
+- Programs executed with -x now behave more as they should, for example,
+  __file__ has the correct value.
+
+- .coverage data files have a new pickle-based format designed for better
+  extensibility.
+
+- Removed the undocumented cache_file argument to coverage.usecache().
+
+
+Version 3.0b1 --- 2009-03-07
+----------------------------
+
+Major overhaul.
+
+- Coverage.py is now a package rather than a module.  Functionality has been
+  split into classes.
+
+- The trace function is implemented in C for speed.  Coverage.py runs are now
+  much faster.  Thanks to David Christian for productive micro-sprints and
+  other encouragement.
+
+- Executable lines are identified by reading the line number tables in the
+  compiled code, removing a great deal of complicated analysis code.
+
+- Precisely which lines are considered executable has changed in some cases.
+  Therefore, your coverage stats may also change slightly.
+
+- The singleton coverage object is only created if the module-level functions
+  are used.  This maintains the old interface while allowing better
+  programmatic use of Coverage.py.
+
+- The minimum supported Python version is 2.3.
+
+
+Version 2.85 --- 2008-09-14
+---------------------------
+
+- Add support for finding source files in eggs. Don't check for
+  morf's being instances of ModuleType, instead use duck typing so that
+  pseudo-modules can participate. Thanks, Imri Goldberg.
+
+- Use os.realpath as part of the fixing of file names so that symlinks won't
+  confuse things. Thanks, Patrick Mezard.
+
+
+Version 2.80 --- 2008-05-25
+---------------------------
+
+- Open files in rU mode to avoid line ending craziness. Thanks, Edward Loper.
+
+
+Version 2.78 --- 2007-09-30
+---------------------------
+
+- Don't try to predict whether a file is Python source based on the extension.
+  Extension-less files are often Pythons scripts. Instead, simply parse the file
+  and catch the syntax errors. Hat tip to Ben Finney.
+
+
+Version 2.77 --- 2007-07-29
+---------------------------
+
+- Better packaging.
+
+
+Version 2.76 --- 2007-07-23
+---------------------------
+
+- Now Python 2.5 is *really* fully supported: the body of the new with
+  statement is counted as executable.
+
+
+Version 2.75 --- 2007-07-22
+---------------------------
+
+- Python 2.5 now fully supported. The method of dealing with multi-line
+  statements is now less sensitive to the exact line that Python reports during
+  execution. Pass statements are handled specially so that their disappearance
+  during execution won't throw off the measurement.
+
+
+Version 2.7 --- 2007-07-21
+--------------------------
+
+- "#pragma: nocover" is excluded by default.
+
+- Properly ignore docstrings and other constant expressions that appear in the
+  middle of a function, a problem reported by Tim Leslie.
+
+- coverage.erase() shouldn't clobber the exclude regex. Change how parallel
+  mode is invoked, and fix erase() so that it erases the cache when called
+  programmatically.
+
+- In reports, ignore code executed from strings, since we can't do anything
+  useful with it anyway.
+
+- Better file handling on Linux, thanks Guillaume Chazarain.
+
+- Better shell support on Windows, thanks Noel O'Boyle.
+
+- Python 2.2 support maintained, thanks Catherine Proulx.
+
+- Minor changes to avoid lint warnings.
+
+
+Version 2.6 --- 2006-08-23
+--------------------------
+
+- Applied Joseph Tate's patch for function decorators.
+
+- Applied Sigve Tjora and Mark van der Wal's fixes for argument handling.
+
+- Applied Geoff Bache's parallel mode patch.
+
+- Refactorings to improve testability. Fixes to command-line logic for parallel
+  mode and collect.
+
+
+Version 2.5 --- 2005-12-04
+--------------------------
+
+- Call threading.settrace so that all threads are measured. Thanks Martin
+  Fuzzey.
+
+- Add a file argument to report so that reports can be captured to a different
+  destination.
+
+- Coverage.py can now measure itself.
+
+- Adapted Greg Rogers' patch for using relative file names, and sorting and
+  omitting files to report on.
+
+
+Version 2.2 --- 2004-12-31
+--------------------------
+
+- Allow for keyword arguments in the module global functions. Thanks, Allen.
+
+
+Version 2.1 --- 2004-12-14
+--------------------------
+
+- Return 'analysis' to its original behavior and add 'analysis2'. Add a global
+  for 'annotate', and factor it, adding 'annotate_file'.
+
+
+Version 2.0 --- 2004-12-12
+--------------------------
+
+Significant code changes.
+
+- Finding executable statements has been rewritten so that docstrings and
+  other quirks of Python execution aren't mistakenly identified as missing
+  lines.
+
+- Lines can be excluded from consideration, even entire suites of lines.
+
+- The file system cache of covered lines can be disabled programmatically.
+
+- Modernized the code.
+
+
+Earlier History
+---------------
+
+2001-12-04 GDR Created.
+
+2001-12-06 GDR Added command-line interface and source code annotation.
+
+2001-12-09 GDR Moved design and interface to separate documents.
+
+2001-12-10 GDR Open cache file as binary on Windows. Allow simultaneous -e and
+-x, or -a and -r.
+
+2001-12-12 GDR Added command-line help. Cache analysis so that it only needs to
+be done once when you specify -a and -r.
+
+2001-12-13 GDR Improved speed while recording. Portable between Python 1.5.2
+and 2.1.1.
+
+2002-01-03 GDR Module-level functions work correctly.
+
+2002-01-07 GDR Update sys.path when running a file with the -x option, so that
+it matches the value the program would get if it were run on its own.
--- a/DebugClients/Python/coverage/doc/CHANGES.txt	Sat Jul 23 13:33:54 2016 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1411 +0,0 @@
-.. Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
-.. For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
-
-==============================
-Change history for Coverage.py
-==============================
-
-
-Version 4.0 --- 20 September 2015
----------------------------------
-
-No changes from 4.0b3
-
-
-Version 4.0b3 --- 7 September 2015
-----------------------------------
-
-- Reporting on an unmeasured file would fail with a traceback.  This is now
-  fixed, closing `issue 403`_.
-
-- The Jenkins ShiningPanda plugin looks for an obsolete file name to find the
-  HTML reports to publish, so it was failing under coverage.py 4.0.  Now we
-  create that file if we are running under Jenkins, to keep things working
-  smoothly. `issue 404`_.
-
-- Kits used to include tests and docs, but didn't install them anywhere, or
-  provide all of the supporting tools to make them useful.  Kits no longer
-  include tests and docs.  If you were using them from the older packages, get
-  in touch and help me understand how.
-
-.. _issue 403: https://bitbucket.org/ned/coveragepy/issues/403/hasherupdate-fails-with-typeerror-nonetype
-.. _issue 404: https://bitbucket.org/ned/coveragepy/issues/404/shiningpanda-jenkins-plugin-cant-find-html
-
-
-
-Version 4.0b2 --- 22 August 2015
---------------------------------
-
-- 4.0b1 broke --append creating new data files.  This is now fixed, closing
-  `issue 392`_.
-
-- ``py.test --cov`` can write empty data, then touch files due to ``--source``,
-  which made coverage.py mistakenly force the data file to record lines instead
-  of arcs.  This would lead to a "Can't combine line data with arc data" error
-  message.  This is now fixed, and changed some method names in the
-  CoverageData interface.  Fixes `issue 399`_.
-
-- `CoverageData.read_fileobj` and `CoverageData.write_fileobj` replace the
-  `.read` and `.write` methods, and are now properly inverses of each other.
-
-- When using ``report --skip-covered``, a message will now be included in the
-  report output indicating how many files were skipped, and if all files are
-  skipped, coverage.py won't accidentally scold you for having no data to
-  report.  Thanks, Krystian Kichewko.
-
-- A new conversion utility has been added:  ``python -m coverage.pickle2json``
-  will convert v3.x pickle data files to v4.x JSON data files.  Thanks,
-  Alexander Todorov.  Closes `issue 395`_.
-
-- A new version identifier is available, `coverage.version_info`, a plain tuple
-  of values similar to `sys.version_info`_.
-
-.. _issue 392: https://bitbucket.org/ned/coveragepy/issues/392/run-append-doesnt-create-coverage-file
-.. _issue 395: https://bitbucket.org/ned/coveragepy/issues/395/rfe-read-pickled-files-as-well-for
-.. _issue 399: https://bitbucket.org/ned/coveragepy/issues/399/coverageexception-cant-combine-line-data
-.. _sys.version_info: https://docs.python.org/3/library/sys.html#sys.version_info
-
-
-Version 4.0b1 --- 2 August 2015
--------------------------------
-
-- Coverage.py is now licensed under the Apache 2.0 license.  See NOTICE.txt for
-  details.  Closes `issue 313`_.
-
-- The data storage has been completely revamped.  The data file is now
-  JSON-based instead of a pickle, closing `issue 236`_.  The `CoverageData`
-  class is now a public supported documented API to the data file.
-
-- A new configuration option, ``[run] note``, lets you set a note that will be
-  stored in the `runs` section of the data file.  You can use this to annotate
-  the data file with any information you like.
-
-- Unrecognized configuration options will now print an error message and stop
-  coverage.py.  This should help prevent configuration mistakes from passing
-  silently.  Finishes `issue 386`_.
-
-- In parallel mode, ``coverage erase`` will now delete all of the data files,
-  fixing `issue 262`_.
-
-- Coverage.py now accepts a directory name for ``coverage run`` and will run a
-  ``__main__.py`` found there, just like Python will.  Fixes `issue 252`_.
-  Thanks, Dmitry Trofimov.
-
-- The XML report now includes a ``missing-branches`` attribute.  Thanks, Steve
-  Peak.  This is not a part of the Cobertura DTD, so the XML report no longer
-  references the DTD.
-
-- Missing branches in the HTML report now have a bit more information in the
-  right-hand annotations.  Hopefully this will make their meaning clearer.
-
-- All the reporting functions now behave the same if no data had been
-  collected, exiting with a status code of 1.  Fixed ``fail_under`` to be
-  applied even when the report is empty.  Thanks, Ionel Cristian Mărieș.
-
-- Plugins are now initialized differently.  Instead of looking for a class
-  called ``Plugin``, coverage.py looks for a function called ``coverage_init``.
-
-- A file-tracing plugin can now ask to have built-in Python reporting by
-  returning `"python"` from its `file_reporter()` method.
-
-- Code that was executed with `exec` would be mis-attributed to the file that
-  called it.  This is now fixed, closing `issue 380`_.
-
-- The ability to use item access on `Coverage.config` (introduced in 4.0a2) has
-  been changed to a more explicit `Coverage.get_option` and
-  `Coverage.set_option` API.
-
-- The ``Coverage.use_cache`` method is no longer supported.
-
-- The private method ``Coverage._harvest_data`` is now called
-  ``Coverage.get_data``, and returns the ``CoverageData`` containing the
-  collected data.
-
-- The project is consistently referred to as "coverage.py" throughout the code
-  and the documentation, closing `issue 275`_.
-
-- Combining data files with an explicit configuration file was broken in 4.0a6,
-  but now works again, closing `issue 385`_.
-
-- ``coverage combine`` now accepts files as well as directories.
-
-- The speed is back to 3.7.1 levels, after having slowed down due to plugin
-  support, finishing up `issue 387`_.
-
-.. _issue 236: https://bitbucket.org/ned/coveragepy/issues/236/pickles-are-bad-and-you-should-feel-bad
-.. _issue 252: https://bitbucket.org/ned/coveragepy/issues/252/coverage-wont-run-a-program-with
-.. _issue 262: https://bitbucket.org/ned/coveragepy/issues/262/when-parallel-true-erase-should-erase-all
-.. _issue 275: https://bitbucket.org/ned/coveragepy/issues/275/refer-consistently-to-project-as-coverage
-.. _issue 313: https://bitbucket.org/ned/coveragepy/issues/313/add-license-file-containing-2-3-or-4
-.. _issue 380: https://bitbucket.org/ned/coveragepy/issues/380/code-executed-by-exec-excluded-from
-.. _issue 385: https://bitbucket.org/ned/coveragepy/issues/385/coverage-combine-doesnt-work-with-rcfile
-.. _issue 386: https://bitbucket.org/ned/coveragepy/issues/386/error-on-unrecognised-configuration
-.. _issue 387: https://bitbucket.org/ned/coveragepy/issues/387/performance-degradation-from-371-to-40
-
-.. 40 issues closed in 4.0 below here
-
-
-Version 4.0a6 --- 21 June 2015
-------------------------------
-
-- Python 3.5b2 and PyPy 2.6.0 are supported.
-
-- The original module-level function interface to coverage.py is no longer
-  supported.  You must now create a ``coverage.Coverage`` object, and use
-  methods on it.
-
-- The ``coverage combine`` command now accepts any number of directories as
-  arguments, and will combine all the data files from those directories.  This
-  means you don't have to copy the files to one directory before combining.
-  Thanks, Christine Lytwynec.  Finishes `issue 354`_.
-
-- Branch coverage couldn't properly handle certain extremely long files. This
-  is now fixed (`issue 359`_).
-
-- Branch coverage didn't understand yield statements properly.  Mickie Betz
-  persisted in pursuing this despite Ned's pessimism.  Fixes `issue 308`_ and
-  `issue 324`_.
-
-- The COVERAGE_DEBUG environment variable can be used to set the ``[run] debug``
-  configuration option to control what internal operations are logged.
-
-- HTML reports were truncated at formfeed characters.  This is now fixed
-  (`issue 360`_).  It's always fun when the problem is due to a `bug in the
-  Python standard library <http://bugs.python.org/issue19035>`_.
-
-- Files with incorrect encoding declaration comments are no longer ignored by
-  the reporting commands, fixing `issue 351`_.
-
-- HTML reports now include a timestamp in the footer, closing `issue 299`_.
-  Thanks, Conrad Ho.
-
-- HTML reports now begrudgingly use double-quotes rather than single quotes,
-  because there are "software engineers" out there writing tools that read HTML
-  and somehow have no idea that single quotes exist.  Capitulates to the absurd
-  `issue 361`_.  Thanks, Jon Chappell.
-
-- The ``coverage annotate`` command now handles non-ASCII characters properly,
-  closing `issue 363`_.  Thanks, Leonardo Pistone.
-
-- Drive letters on Windows were not normalized correctly, now they are. Thanks,
-  Ionel Cristian Mărieș.
-
-- Plugin support had some bugs fixed, closing `issue 374`_ and `issue 375`_.
-  Thanks, Stefan Behnel.
-
-.. _issue 299: https://bitbucket.org/ned/coveragepy/issue/299/inserted-created-on-yyyy-mm-dd-hh-mm-in
-.. _issue 308: https://bitbucket.org/ned/coveragepy/issue/308/yield-lambda-branch-coverage
-.. _issue 324: https://bitbucket.org/ned/coveragepy/issue/324/yield-in-loop-confuses-branch-coverage
-.. _issue 351: https://bitbucket.org/ned/coveragepy/issue/351/files-with-incorrect-encoding-are-ignored
-.. _issue 354: https://bitbucket.org/ned/coveragepy/issue/354/coverage-combine-should-take-a-list-of
-.. _issue 359: https://bitbucket.org/ned/coveragepy/issue/359/xml-report-chunk-error
-.. _issue 360: https://bitbucket.org/ned/coveragepy/issue/360/html-reports-get-confused-by-l-in-the-code
-.. _issue 361: https://bitbucket.org/ned/coveragepy/issue/361/use-double-quotes-in-html-output-to
-.. _issue 363: https://bitbucket.org/ned/coveragepy/issue/363/annotate-command-hits-unicode-happy-fun
-.. _issue 374: https://bitbucket.org/ned/coveragepy/issue/374/c-tracer-lookups-fail-in
-.. _issue 375: https://bitbucket.org/ned/coveragepy/issue/375/ctracer_handle_return-reads-byte-code
-
-
-Version 4.0a5 --- 16 February 2015
-----------------------------------
-
-- Plugin support is now implemented in the C tracer instead of the Python
-  tracer. This greatly improves the speed of tracing projects using plugins.
-
-- Coverage.py now always adds the current directory to sys.path, so that
-  plugins can import files in the current directory (`issue 358`_).
-
-- If the `config_file` argument to the Coverage constructor is specified as
-  ".coveragerc", it is treated as if it were True.  This means setup.cfg is
-  also examined, and a missing file is not considered an error (`issue 357`_).
-
-- Wildly experimental: support for measuring processes started by the
-  multiprocessing module.  To use, set ``--concurrency=multiprocessing``,
-  either on the command line or in the .coveragerc file (`issue 117`_). Thanks,
-  Eduardo Schettino.  Currently, this does not work on Windows.
-
-- A new warning is possible, if a desired file isn't measured because it was
-  imported before coverage.py was started (`issue 353`_).
-
-- The `coverage.process_startup` function now will start coverage measurement
-  only once, no matter how many times it is called.  This fixes problems due
-  to unusual virtualenv configurations (`issue 340`_).
-
-- Added 3.5.0a1 to the list of supported CPython versions.
-
-.. _issue 117: https://bitbucket.org/ned/coveragepy/issue/117/enable-coverage-measurement-of-code-run-by
-.. _issue 340: https://bitbucket.org/ned/coveragepy/issue/340/keyerror-subpy
-.. _issue 353: https://bitbucket.org/ned/coveragepy/issue/353/40a3-introduces-an-unexpected-third-case
-.. _issue 357: https://bitbucket.org/ned/coveragepy/issue/357/behavior-changed-when-coveragerc-is
-.. _issue 358: https://bitbucket.org/ned/coveragepy/issue/358/all-coverage-commands-should-adjust
-
-
-Version 4.0a4 --- 25 January 2015
----------------------------------
-
-- Plugins can now provide sys_info for debugging output.
-
-- Started plugins documentation.
-
-- Prepared to move the docs to readthedocs.org.
-
-
-Version 4.0a3 --- 20 January 2015
----------------------------------
-
-- Reports now use file names with extensions.  Previously, a report would
-  describe a/b/c.py as "a/b/c".  Now it is shown as "a/b/c.py".  This allows
-  for better support of non-Python files, and also fixed `issue 69`_.
-
-- The XML report now reports each directory as a package again.  This was a bad
-  regression, I apologize.  This was reported in `issue 235`_, which is now
-  fixed.
-
-- A new configuration option for the XML report: ``[xml] package_depth``
-  controls which directories are identified as packages in the report.
-  Directories deeper than this depth are not reported as packages.
-  The default is that all directories are reported as packages.
-  Thanks, Lex Berezhny.
-
-- When looking for the source for a frame, check if the file exists. On
-  Windows, .pyw files are no longer recorded as .py files. Along the way, this
-  fixed `issue 290`_.
-
-- Empty files are now reported as 100% covered in the XML report, not 0%
-  covered (`issue 345`_).
-
-- Regexes in the configuration file are now compiled as soon as they are read,
-  to provide error messages earlier (`issue 349`_).
-
-.. _issue 69: https://bitbucket.org/ned/coveragepy/issue/69/coverage-html-overwrite-files-that-doesnt
-.. _issue 235: https://bitbucket.org/ned/coveragepy/issue/235/package-name-is-missing-in-xml-report
-.. _issue 290: https://bitbucket.org/ned/coveragepy/issue/290/running-programmatically-with-pyw-files
-.. _issue 345: https://bitbucket.org/ned/coveragepy/issue/345/xml-reports-line-rate-0-for-empty-files
-.. _issue 349: https://bitbucket.org/ned/coveragepy/issue/349/bad-regex-in-config-should-get-an-earlier
-
-
-Version 4.0a2 --- 14 January 2015
----------------------------------
-
-- Officially support PyPy 2.4, and PyPy3 2.4.  Drop support for
-  CPython 3.2 and older versions of PyPy.  The code won't work on CPython 3.2.
-  It will probably still work on older versions of PyPy, but I'm not testing
-  against them.
-
-- Plugins!
-
-- The original command line switches (`-x` to run a program, etc) are no
-  longer supported.
-
-- A new option: `coverage report --skip-covered` will reduce the number of
-  files reported by skipping files with 100% coverage.  Thanks, Krystian
-  Kichewko.  This means that empty `__init__.py` files will be skipped, since
-  they are 100% covered, closing `issue 315`_.
-
-- You can now specify the ``--fail-under`` option in the ``.coveragerc`` file
-  as the ``[report] fail_under`` option.  This closes `issue 314`_.
-
-- The ``COVERAGE_OPTIONS`` environment variable is no longer supported.  It was
-  a hack for ``--timid`` before configuration files were available.
-
-- The HTML report now has filtering.  Type text into the Filter box on the
-  index page, and only modules with that text in the name will be shown.
-  Thanks, Danny Allen.
-
-- The textual report and the HTML report used to report partial branches
-  differently for no good reason.  Now the text report's "missing branches"
-  column is a "partial branches" column so that both reports show the same
-  numbers.  This closes `issue 342`_.
-
-- If you specify a ``--rcfile`` that cannot be read, you will get an error
-  message.  Fixes `issue 343`_.
-
-- The ``--debug`` switch can now be used on any command.
-
-- You can now programmatically adjust the configuration of coverage.py by
-  setting items on `Coverage.config` after construction.
-
-- A module run with ``-m`` can be used as the argument to ``--source``, fixing
-  `issue 328`_.  Thanks, Buck Evan.
-
-- The regex for matching exclusion pragmas has been fixed to allow more kinds
-  of whitespace, fixing `issue 334`_.
-
-- Made some PyPy-specific tweaks to improve speed under PyPy.  Thanks, Alex
-  Gaynor.
-
-- In some cases, with a source file missing a final newline, coverage.py would
-  count statements incorrectly.  This is now fixed, closing `issue 293`_.
-
-- The status.dat file that HTML reports use to avoid re-creating files that
-  haven't changed is now a JSON file instead of a pickle file.  This obviates
-  `issue 287`_ and `issue 237`_.
-
-.. _issue 237: https://bitbucket.org/ned/coveragepy/issue/237/htmlcov-with-corrupt-statusdat
-.. _issue 287: https://bitbucket.org/ned/coveragepy/issue/287/htmlpy-doesnt-specify-pickle-protocol
-.. _issue 293: https://bitbucket.org/ned/coveragepy/issue/293/number-of-statement-detection-wrong-if-no
-.. _issue 314: https://bitbucket.org/ned/coveragepy/issue/314/fail_under-param-not-working-in-coveragerc
-.. _issue 315: https://bitbucket.org/ned/coveragepy/issue/315/option-to-omit-empty-files-eg-__init__py
-.. _issue 328: https://bitbucket.org/ned/coveragepy/issue/328/misbehavior-in-run-source
-.. _issue 334: https://bitbucket.org/ned/coveragepy/issue/334/pragma-not-recognized-if-tab-character
-.. _issue 342: https://bitbucket.org/ned/coveragepy/issue/342/console-and-html-coverage-reports-differ
-.. _issue 343: https://bitbucket.org/ned/coveragepy/issue/343/an-explicitly-named-non-existent-config
-
-
-Version 4.0a1 --- 27 September 2014
------------------------------------
-
-- Python versions supported are now CPython 2.6, 2.7, 3.2, 3.3, and 3.4, and
-  PyPy 2.2.
-
-- Gevent, eventlet, and greenlet are now supported, closing `issue 149`_.
-  The ``concurrency`` setting specifies the concurrency library in use.  Huge
-  thanks to Peter Portante for initial implementation, and to Joe Jevnik for
-  the final insight that completed the work.
-
-- Options are now also read from a setup.cfg file, if any.  Sections are
-  prefixed with "coverage:", so the ``[run]`` options will be read from the
-  ``[coverage:run]`` section of setup.cfg.  Finishes `issue 304`_.
-
-- The ``report -m`` command can now show missing branches when reporting on
-  branch coverage.  Thanks, Steve Leonard. Closes `issue 230`_.
-
-- The XML report now contains a <source> element, fixing `issue 94`_.  Thanks
-  Stan Hu.
-
-- The class defined in the coverage module is now called ``Coverage`` instead
-  of ``coverage``, though the old name still works, for backward compatibility.
-
-- The ``fail-under`` value is now rounded the same as reported results,
-  preventing paradoxical results, fixing `issue 284`_.
-
-- The XML report will now create the output directory if need be, fixing
-  `issue 285`_.  Thanks, Chris Rose.
-
-- HTML reports no longer raise UnicodeDecodeError if a Python file has
-  undecodable characters, fixing `issue 303`_ and `issue 331`_.
-
-- The annotate command will now annotate all files, not just ones relative to
-  the current directory, fixing `issue 57`_.
-
-- The coverage module no longer causes deprecation warnings on Python 3.4 by
-  importing the imp module, fixing `issue 305`_.
-
-- Encoding declarations in source files are only considered if they are truly
-  comments.  Thanks, Anthony Sottile.
-
-.. _issue 57: https://bitbucket.org/ned/coveragepy/issue/57/annotate-command-fails-to-annotate-many
-.. _issue 94: https://bitbucket.org/ned/coveragepy/issue/94/coverage-xml-doesnt-produce-sources
-.. _issue 149: https://bitbucket.org/ned/coveragepy/issue/149/coverage-gevent-looks-broken
-.. _issue 230: https://bitbucket.org/ned/coveragepy/issue/230/show-line-no-for-missing-branches-in
-.. _issue 284: https://bitbucket.org/ned/coveragepy/issue/284/fail-under-should-show-more-precision
-.. _issue 285: https://bitbucket.org/ned/coveragepy/issue/285/xml-report-fails-if-output-file-directory
-.. _issue 303: https://bitbucket.org/ned/coveragepy/issue/303/unicodedecodeerror
-.. _issue 304: https://bitbucket.org/ned/coveragepy/issue/304/attempt-to-get-configuration-from-setupcfg
-.. _issue 305: https://bitbucket.org/ned/coveragepy/issue/305/pendingdeprecationwarning-the-imp-module
-.. _issue 331: https://bitbucket.org/ned/coveragepy/issue/331/failure-of-encoding-detection-on-python2
-
-
-Version 3.7.1 --- 13 December 2013
-----------------------------------
-
-- Improved the speed of HTML report generation by about 20%.
-
-- Fixed the mechanism for finding OS-installed static files for the HTML report
-  so that it will actually find OS-installed static files.
-
-
-Version 3.7 --- 6 October 2013
-------------------------------
-
-- Added the ``--debug`` switch to ``coverage run``.  It accepts a list of
-  options indicating the type of internal activity to log to stderr.
-
-- Improved the branch coverage facility, fixing `issue 92`_ and `issue 175`_.
-
-- Running code with ``coverage run -m`` now behaves more like Python does,
-  setting sys.path properly, which fixes `issue 207`_ and `issue 242`_.
-
-- Coverage.py can now run .pyc files directly, closing `issue 264`_.
-
-- Coverage.py properly supports .pyw files, fixing `issue 261`_.
-
-- Omitting files within a tree specified with the ``source`` option would
-  cause them to be incorrectly marked as unexecuted, as described in
-  `issue 218`_.  This is now fixed.
-
-- When specifying paths to alias together during data combining, you can now
-  specify relative paths, fixing `issue 267`_.
-
-- Most file paths can now be specified with username expansion (``~/src``, or
-  ``~build/src``, for example), and with environment variable expansion
-  (``build/$BUILDNUM/src``).
-
-- Trying to create an XML report with no files to report on, would cause a
-  ZeroDivideError, but no longer does, fixing `issue 250`_.
-
-- When running a threaded program under the Python tracer, coverage.py no
-  longer issues a spurious warning about the trace function changing: "Trace
-  function changed, measurement is likely wrong: None."  This fixes `issue
-  164`_.
-
-- Static files necessary for HTML reports are found in system-installed places,
-  to ease OS-level packaging of coverage.py.  Closes `issue 259`_.
-
-- Source files with encoding declarations, but a blank first line, were not
-  decoded properly.  Now they are.  Thanks, Roger Hu.
-
-- The source kit now includes the ``__main__.py`` file in the root coverage
-  directory, fixing `issue 255`_.
-
-.. _issue 92: https://bitbucket.org/ned/coveragepy/issue/92/finally-clauses-arent-treated-properly-in
-.. _issue 164: https://bitbucket.org/ned/coveragepy/issue/164/trace-function-changed-warning-when-using
-.. _issue 175: https://bitbucket.org/ned/coveragepy/issue/175/branch-coverage-gets-confused-in-certain
-.. _issue 207: https://bitbucket.org/ned/coveragepy/issue/207/run-m-cannot-find-module-or-package-in
-.. _issue 242: https://bitbucket.org/ned/coveragepy/issue/242/running-a-two-level-package-doesnt-work
-.. _issue 218: https://bitbucket.org/ned/coveragepy/issue/218/run-command-does-not-respect-the-omit-flag
-.. _issue 250: https://bitbucket.org/ned/coveragepy/issue/250/uncaught-zerodivisionerror-when-generating
-.. _issue 255: https://bitbucket.org/ned/coveragepy/issue/255/directory-level-__main__py-not-included-in
-.. _issue 259: https://bitbucket.org/ned/coveragepy/issue/259/allow-use-of-system-installed-third-party
-.. _issue 261: https://bitbucket.org/ned/coveragepy/issue/261/pyw-files-arent-reported-properly
-.. _issue 264: https://bitbucket.org/ned/coveragepy/issue/264/coverage-wont-run-pyc-files
-.. _issue 267: https://bitbucket.org/ned/coveragepy/issue/267/relative-path-aliases-dont-work
-
-
-Version 3.6 --- 5 January 2013
-------------------------------
-
-- Added a page to the docs about troublesome situations, closing `issue 226`_,
-  and added some info to the TODO file, closing `issue 227`_.
-
-.. _issue 226: https://bitbucket.org/ned/coveragepy/issue/226/make-readme-section-to-describe-when
-.. _issue 227: https://bitbucket.org/ned/coveragepy/issue/227/update-todo
-
-
-Version 3.6b3 --- 29 December 2012
-----------------------------------
-
-- Beta 2 broke the nose plugin. It's fixed again, closing `issue 224`_.
-
-.. _issue 224: https://bitbucket.org/ned/coveragepy/issue/224/36b2-breaks-nosexcover
-
-
-Version 3.6b2 --- 23 December 2012
-----------------------------------
-
-- Coverage.py runs on Python 2.3 and 2.4 again. It was broken in 3.6b1.
-
-- The C extension is optionally compiled using a different more widely-used
-  technique, taking another stab at fixing `issue 80`_ once and for all.
-
-- Combining data files would create entries for phantom files if used with
-  ``source`` and path aliases.  It no longer does.
-
-- ``debug sys`` now shows the configuration file path that was read.
-
-- If an oddly-behaved package claims that code came from an empty-string
-  file name, coverage.py no longer associates it with the directory name,
-  fixing `issue 221`_.
-
-.. _issue 80: https://bitbucket.org/ned/coveragepy/issue/80/is-there-a-duck-typing-way-to-know-we-cant
-.. _issue 221: https://bitbucket.org/ned/coveragepy/issue/221/coveragepy-incompatible-with-pyratemp
-
-
-Version 3.6b1 --- 28 November 2012
-----------------------------------
-
-- Wildcards in ``include=`` and ``omit=`` arguments were not handled properly
-  in reporting functions, though they were when running.  Now they are handled
-  uniformly, closing `issue 143`_ and `issue 163`_.  **NOTE**: it is possible
-  that your configurations may now be incorrect.  If you use ``include`` or
-  ``omit`` during reporting, whether on the command line, through the API, or
-  in a configuration file, please check carefully that you were not relying on
-  the old broken behavior.
-
-- The **report**, **html**, and **xml** commands now accept a ``--fail-under``
-  switch that indicates in the exit status whether the coverage percentage was
-  less than a particular value.  Closes `issue 139`_.
-
-- The reporting functions coverage.report(), coverage.html_report(), and
-  coverage.xml_report() now all return a float, the total percentage covered
-  measurement.
-
-- The HTML report's title can now be set in the configuration file, with the
-  ``--title`` switch on the command line, or via the API.
-
-- Configuration files now support substitution of environment variables, using
-  syntax like ``${WORD}``.  Closes `issue 97`_.
-
-- Embarrassingly, the ``[xml] output=`` setting in the .coveragerc file simply
-  didn't work.  Now it does.
-
-- The XML report now consistently uses file names for the file name attribute,
-  rather than sometimes using module names.  Fixes `issue 67`_.
-  Thanks, Marcus Cobden.
-
-- Coverage percentage metrics are now computed slightly differently under
-  branch coverage.  This means that completely unexecuted files will now
-  correctly have 0% coverage, fixing `issue 156`_.  This also means that your
-  total coverage numbers will generally now be lower if you are measuring
-  branch coverage.
-
-- When installing, now in addition to creating a "coverage" command, two new
-  aliases are also installed.  A "coverage2" or "coverage3" command will be
-  created, depending on whether you are installing in Python 2.x or 3.x.
-  A "coverage-X.Y" command will also be created corresponding to your specific
-  version of Python.  Closes `issue 111`_.
-
-- The coverage.py installer no longer tries to bootstrap setuptools or
-  Distribute.  You must have one of them installed first, as `issue 202`_
-  recommended.
-
-- The coverage.py kit now includes docs (closing `issue 137`_) and tests.
-
-- On Windows, files are now reported in their correct case, fixing `issue 89`_
-  and `issue 203`_.
-
-- If a file is missing during reporting, the path shown in the error message
-  is now correct, rather than an incorrect path in the current directory.
-  Fixes `issue 60`_.
-
-- Running an HTML report in Python 3 in the same directory as an old Python 2
-  HTML report would fail with a UnicodeDecodeError. This issue (`issue 193`_)
-  is now fixed.
-
-- Fixed yet another error trying to parse non-Python files as Python, this
-  time an IndentationError, closing `issue 82`_ for the fourth time...
-
-- If `coverage xml` fails because there is no data to report, it used to
-  create a zero-length XML file.  Now it doesn't, fixing `issue 210`_.
-
-- Jython files now work with the ``--source`` option, fixing `issue 100`_.
-
-- Running coverage.py under a debugger is unlikely to work, but it shouldn't
-  fail with "TypeError: 'NoneType' object is not iterable".  Fixes `issue
-  201`_.
-
-- On some Linux distributions, when installed with the OS package manager,
-  coverage.py would report its own code as part of the results.  Now it won't,
-  fixing `issue 214`_, though this will take some time to be repackaged by the
-  operating systems.
-
-- Docstrings for the legacy singleton methods are more helpful.  Thanks Marius
-  Gedminas.  Closes `issue 205`_.
-
-- The pydoc tool can now show documentation for the class `coverage.coverage`.
-  Closes `issue 206`_.
-
-- Added a page to the docs about contributing to coverage.py, closing
-  `issue 171`_.
-
-- When coverage.py ended unsuccessfully, it may have reported odd errors like
-  ``'NoneType' object has no attribute 'isabs'``.  It no longer does,
-  so kiss `issue 153`_ goodbye.
-
-.. _issue 60: https://bitbucket.org/ned/coveragepy/issue/60/incorrect-path-to-orphaned-pyc-files
-.. _issue 67: https://bitbucket.org/ned/coveragepy/issue/67/xml-report-filenames-may-be-generated
-.. _issue 89: https://bitbucket.org/ned/coveragepy/issue/89/on-windows-all-packages-are-reported-in
-.. _issue 97: https://bitbucket.org/ned/coveragepy/issue/97/allow-environment-variables-to-be
-.. _issue 100: https://bitbucket.org/ned/coveragepy/issue/100/source-directive-doesnt-work-for-packages
-.. _issue 111: https://bitbucket.org/ned/coveragepy/issue/111/when-installing-coverage-with-pip-not
-.. _issue 137: https://bitbucket.org/ned/coveragepy/issue/137/provide-docs-with-source-distribution
-.. _issue 139: https://bitbucket.org/ned/coveragepy/issue/139/easy-check-for-a-certain-coverage-in-tests
-.. _issue 143: https://bitbucket.org/ned/coveragepy/issue/143/omit-doesnt-seem-to-work-in-coverage
-.. _issue 153: https://bitbucket.org/ned/coveragepy/issue/153/non-existent-filename-triggers
-.. _issue 156: https://bitbucket.org/ned/coveragepy/issue/156/a-completely-unexecuted-file-shows-14
-.. _issue 163: https://bitbucket.org/ned/coveragepy/issue/163/problem-with-include-and-omit-filename
-.. _issue 171: https://bitbucket.org/ned/coveragepy/issue/171/how-to-contribute-and-run-tests
-.. _issue 193: https://bitbucket.org/ned/coveragepy/issue/193/unicodedecodeerror-on-htmlpy
-.. _issue 201: https://bitbucket.org/ned/coveragepy/issue/201/coverage-using-django-14-with-pydb-on
-.. _issue 202: https://bitbucket.org/ned/coveragepy/issue/202/get-rid-of-ez_setuppy-and
-.. _issue 203: https://bitbucket.org/ned/coveragepy/issue/203/duplicate-filenames-reported-when-filename
-.. _issue 205: https://bitbucket.org/ned/coveragepy/issue/205/make-pydoc-coverage-more-friendly
-.. _issue 206: https://bitbucket.org/ned/coveragepy/issue/206/pydoc-coveragecoverage-fails-with-an-error
-.. _issue 210: https://bitbucket.org/ned/coveragepy/issue/210/if-theres-no-coverage-data-coverage-xml
-.. _issue 214: https://bitbucket.org/ned/coveragepy/issue/214/coveragepy-measures-itself-on-precise
-
-
-Version 3.5.3 --- 29 September 2012
------------------------------------
-
-- Line numbers in the HTML report line up better with the source lines, fixing
-  `issue 197`_, thanks Marius Gedminas.
-
-- When specifying a directory as the source= option, the directory itself no
-  longer needs to have a ``__init__.py`` file, though its sub-directories do,
-  to be considered as source files.
-
-- Files encoded as UTF-8 with a BOM are now properly handled, fixing
-  `issue 179`_.  Thanks, Pablo Carballo.
-
-- Fixed more cases of non-Python files being reported as Python source, and
-  then not being able to parse them as Python.  Closes `issue 82`_ (again).
-  Thanks, Julian Berman.
-
-- Fixed memory leaks under Python 3, thanks, Brett Cannon. Closes `issue 147`_.
-
-- Optimized .pyo files may not have been handled correctly, `issue 195`_.
-  Thanks, Marius Gedminas.
-
-- Certain unusually named file paths could have been mangled during reporting,
-  `issue 194`_.  Thanks, Marius Gedminas.
-
-- Try to do a better job of the impossible task of detecting when we can't
-  build the C extension, fixing `issue 183`_.
-
-- Testing is now done with `tox`_, thanks, Marc Abramowitz.
-
-.. _issue 147: https://bitbucket.org/ned/coveragepy/issue/147/massive-memory-usage-by-ctracer
-.. _issue 179: https://bitbucket.org/ned/coveragepy/issue/179/htmlreporter-fails-when-source-file-is
-.. _issue 183: https://bitbucket.org/ned/coveragepy/issue/183/install-fails-for-python-23
-.. _issue 194: https://bitbucket.org/ned/coveragepy/issue/194/filelocatorrelative_filename-could-mangle
-.. _issue 195: https://bitbucket.org/ned/coveragepy/issue/195/pyo-file-handling-in-codeunit
-.. _issue 197: https://bitbucket.org/ned/coveragepy/issue/197/line-numbers-in-html-report-do-not-align
-.. _tox: http://tox.readthedocs.org/
-
-
-Version 3.5.2 --- 4 May 2012
-----------------------------
-
-No changes since 3.5.2.b1
-
-
-Version 3.5.2b1 --- 29 April 2012
----------------------------------
-
-- The HTML report has slightly tweaked controls: the buttons at the top of
-  the page are color-coded to the source lines they affect.
-
-- Custom CSS can be applied to the HTML report by specifying a CSS file as
-  the ``extra_css`` configuration value in the ``[html]`` section.
-
-- Source files with custom encodings declared in a comment at the top are now
-  properly handled during reporting on Python 2.  Python 3 always handled them
-  properly.  This fixes `issue 157`_.
-
-- Backup files left behind by editors are no longer collected by the source=
-  option, fixing `issue 168`_.
-
-- If a file doesn't parse properly as Python, we don't report it as an error
-  if the file name seems like maybe it wasn't meant to be Python.  This is a
-  pragmatic fix for `issue 82`_.
-
-- The ``-m`` switch on ``coverage report``, which includes missing line numbers
-  in the summary report, can now be specified as ``show_missing`` in the
-  config file.  Closes `issue 173`_.
-
-- When running a module with ``coverage run -m <modulename>``, certain details
-  of the execution environment weren't the same as for
-  ``python -m <modulename>``.  This had the unfortunate side-effect of making
-  ``coverage run -m unittest discover`` not work if you had tests in a
-  directory named "test".  This fixes `issue 155`_ and `issue 142`_.
-
-- Now the exit status of your product code is properly used as the process
-  status when running ``python -m coverage run ...``.  Thanks, JT Olds.
-
-- When installing into pypy, we no longer attempt (and fail) to compile
-  the C tracer function, closing `issue 166`_.
-
-.. _issue 142: https://bitbucket.org/ned/coveragepy/issue/142/executing-python-file-syspath-is-replaced
-.. _issue 155: https://bitbucket.org/ned/coveragepy/issue/155/cant-use-coverage-run-m-unittest-discover
-.. _issue 157: https://bitbucket.org/ned/coveragepy/issue/157/chokes-on-source-files-with-non-utf-8
-.. _issue 166: https://bitbucket.org/ned/coveragepy/issue/166/dont-try-to-compile-c-extension-on-pypy
-.. _issue 168: https://bitbucket.org/ned/coveragepy/issue/168/dont-be-alarmed-by-emacs-droppings
-.. _issue 173: https://bitbucket.org/ned/coveragepy/issue/173/theres-no-way-to-specify-show-missing-in
-
-
-Version 3.5.1 --- 23 September 2011
------------------------------------
-
-- The ``[paths]`` feature unfortunately didn't work in real world situations
-  where you wanted to, you know, report on the combined data.  Now all paths
-  stored in the combined file are canonicalized properly.
-
-
-Version 3.5.1b1 --- 28 August 2011
-----------------------------------
-
-- When combining data files from parallel runs, you can now instruct
-  coverage.py about which directories are equivalent on different machines.  A
-  ``[paths]`` section in the configuration file lists paths that are to be
-  considered equivalent.  Finishes `issue 17`_.
-
-- for-else constructs are understood better, and don't cause erroneous partial
-  branch warnings.  Fixes `issue 122`_.
-
-- Branch coverage for ``with`` statements is improved, fixing `issue 128`_.
-
-- The number of partial branches reported on the HTML summary page was
-  different than the number reported on the individual file pages.  This is
-  now fixed.
-
-- An explicit include directive to measure files in the Python installation
-  wouldn't work because of the standard library exclusion.  Now the include
-  directive takes precedence, and the files will be measured.  Fixes
-  `issue 138`_.
-
-- The HTML report now handles Unicode characters in Python source files
-  properly.  This fixes `issue 124`_ and `issue 144`_. Thanks, Devin
-  Jeanpierre.
-
-- In order to help the core developers measure the test coverage of the
-  standard library, Brandon Rhodes devised an aggressive hack to trick Python
-  into running some coverage.py code before anything else in the process.
-  See the coverage/fullcoverage directory if you are interested.
-
-.. _issue 17: http://bitbucket.org/ned/coveragepy/issue/17/support-combining-coverage-data-from
-.. _issue 122: http://bitbucket.org/ned/coveragepy/issue/122/for-else-always-reports-missing-branch
-.. _issue 124: http://bitbucket.org/ned/coveragepy/issue/124/no-arbitrary-unicode-in-html-reports-in
-.. _issue 128: http://bitbucket.org/ned/coveragepy/issue/128/branch-coverage-of-with-statement-in-27
-.. _issue 138: http://bitbucket.org/ned/coveragepy/issue/138/include-should-take-precedence-over-is
-.. _issue 144: http://bitbucket.org/ned/coveragepy/issue/144/failure-generating-html-output-for
-
-
-Version 3.5 --- 29 June 2011
-----------------------------
-
-- The HTML report hotkeys now behave slightly differently when the current
-  chunk isn't visible at all:  a chunk on the screen will be selected,
-  instead of the old behavior of jumping to the literal next chunk.
-  The hotkeys now work in Google Chrome.  Thanks, Guido van Rossum.
-
-
-Version 3.5b1 --- 5 June 2011
------------------------------
-
-- The HTML report now has hotkeys.  Try ``n``, ``s``, ``m``, ``x``, ``b``,
-  ``p``, and ``c`` on the overview page to change the column sorting.
-  On a file page, ``r``, ``m``, ``x``, and ``p`` toggle the run, missing,
-  excluded, and partial line markings.  You can navigate the highlighted
-  sections of code by using the ``j`` and ``k`` keys for next and previous.
-  The ``1`` (one) key jumps to the first highlighted section in the file,
-  and ``0`` (zero) scrolls to the top of the file.
-
-- The ``--omit`` and ``--include`` switches now interpret their values more
-  usefully.  If the value starts with a wildcard character, it is used as-is.
-  If it does not, it is interpreted relative to the current directory.
-  Closes `issue 121`_.
-
-- Partial branch warnings can now be pragma'd away.  The configuration option
-  ``partial_branches`` is a list of regular expressions.  Lines matching any of
-  those expressions will never be marked as a partial branch.  In addition,
-  there's a built-in list of regular expressions marking statements which should
-  never be marked as partial.  This list includes ``while True:``, ``while 1:``,
-  ``if 1:``, and ``if 0:``.
-
-- The ``coverage()`` constructor accepts single strings for the ``omit=`` and
-  ``include=`` arguments, adapting to a common error in programmatic use.
-
-- Modules can now be run directly using ``coverage run -m modulename``, to
-  mirror Python's ``-m`` flag.  Closes `issue 95`_, thanks, Brandon Rhodes.
-
-- ``coverage run`` didn't emulate Python accurately in one small detail: the
-  current directory inserted into ``sys.path`` was relative rather than
-  absolute. This is now fixed.
-
-- HTML reporting is now incremental: a record is kept of the data that
-  produced the HTML reports, and only files whose data has changed will
-  be generated.  This should make most HTML reporting faster.
-
-- Pathological code execution could disable the trace function behind our
-  backs, leading to incorrect code measurement.  Now if this happens,
-  coverage.py will issue a warning, at least alerting you to the problem.
-  Closes `issue 93`_.  Thanks to Marius Gedminas for the idea.
-
-- The C-based trace function now behaves properly when saved and restored
-  with ``sys.gettrace()`` and ``sys.settrace()``.  This fixes `issue 125`_
-  and `issue 123`_.  Thanks, Devin Jeanpierre.
-
-- Source files are now opened with Python 3.2's ``tokenize.open()`` where
-  possible, to get the best handling of Python source files with encodings.
-  Closes `issue 107`_, thanks, Brett Cannon.
-
-- Syntax errors in supposed Python files can now be ignored during reporting
-  with the ``-i`` switch just like other source errors.  Closes `issue 115`_.
-
-- Installation from source now succeeds on machines without a C compiler,
-  closing `issue 80`_.
-
-- Coverage.py can now be run directly from a working tree by specifying
-  the directory name to python:  ``python coverage_py_working_dir run ...``.
-  Thanks, Brett Cannon.
-
-- A little bit of Jython support: `coverage run` can now measure Jython
-  execution by adapting when $py.class files are traced. Thanks, Adi Roiban.
-  Jython still doesn't provide the Python libraries needed to make
-  coverage reporting work, unfortunately.
-
-- Internally, files are now closed explicitly, fixing `issue 104`_.  Thanks,
-  Brett Cannon.
-
-.. _issue 80: https://bitbucket.org/ned/coveragepy/issue/80/is-there-a-duck-typing-way-to-know-we-cant
-.. _issue 93: http://bitbucket.org/ned/coveragepy/issue/93/copying-a-mock-object-breaks-coverage
-.. _issue 95: https://bitbucket.org/ned/coveragepy/issue/95/run-subcommand-should-take-a-module-name
-.. _issue 104: https://bitbucket.org/ned/coveragepy/issue/104/explicitly-close-files
-.. _issue 107: https://bitbucket.org/ned/coveragepy/issue/107/codeparser-not-opening-source-files-with
-.. _issue 115: https://bitbucket.org/ned/coveragepy/issue/115/fail-gracefully-when-reporting-on-file
-.. _issue 121: https://bitbucket.org/ned/coveragepy/issue/121/filename-patterns-are-applied-stupidly
-.. _issue 123: https://bitbucket.org/ned/coveragepy/issue/123/pyeval_settrace-used-in-way-that-breaks
-.. _issue 125: https://bitbucket.org/ned/coveragepy/issue/125/coverage-removes-decoratortoolss-tracing
-
-
-Version 3.4 --- 19 September 2010
----------------------------------
-
-- The XML report is now sorted by package name, fixing `issue 88`_.
-
-- Programs that exited with ``sys.exit()`` with no argument weren't handled
-  properly, producing a coverage.py stack trace.  That is now fixed.
-
-.. _issue 88: http://bitbucket.org/ned/coveragepy/issue/88/xml-report-lists-packages-in-random-order
-
-
-Version 3.4b2 --- 6 September 2010
-----------------------------------
-
-- Completely unexecuted files can now be included in coverage results, reported
-  as 0% covered.  This only happens if the --source option is specified, since
-  coverage.py needs guidance about where to look for source files.
-
-- The XML report output now properly includes a percentage for branch coverage,
-  fixing `issue 65`_ and `issue 81`_.
-
-- Coverage percentages are now displayed uniformly across reporting methods.
-  Previously, different reports could round percentages differently.  Also,
-  percentages are only reported as 0% or 100% if they are truly 0 or 100, and
-  are rounded otherwise.  Fixes `issue 41`_ and `issue 70`_.
-
-- The precision of reported coverage percentages can be set with the
-  ``[report] precision`` config file setting.  Completes `issue 16`_.
-
-- Threads derived from ``threading.Thread`` with an overridden `run` method
-  would report no coverage for the `run` method.  This is now fixed, closing
-  `issue 85`_.
-
-.. _issue 16: http://bitbucket.org/ned/coveragepy/issue/16/allow-configuration-of-accuracy-of-percentage-totals
-.. _issue 41: http://bitbucket.org/ned/coveragepy/issue/41/report-says-100-when-it-isnt-quite-there
-.. _issue 65: http://bitbucket.org/ned/coveragepy/issue/65/branch-option-not-reported-in-cobertura
-.. _issue 70: http://bitbucket.org/ned/coveragepy/issue/70/text-report-and-html-report-disagree-on-coverage
-.. _issue 81: http://bitbucket.org/ned/coveragepy/issue/81/xml-report-does-not-have-condition-coverage-attribute-for-lines-with-a
-.. _issue 85: http://bitbucket.org/ned/coveragepy/issue/85/threadrun-isnt-measured
-
-
-Version 3.4b1 --- 21 August 2010
---------------------------------
-
-- BACKWARD INCOMPATIBILITY: the ``--omit`` and ``--include`` switches now take
-  file patterns rather than file prefixes, closing `issue 34`_ and `issue 36`_.
-
-- BACKWARD INCOMPATIBILITY: the `omit_prefixes` argument is gone throughout
-  coverage.py, replaced with `omit`, a list of file name patterns suitable for
-  `fnmatch`.  A parallel argument `include` controls what files are included.
-
-- The run command now has a ``--source`` switch, a list of directories or
-  module names.  If provided, coverage.py will only measure execution in those
-  source files.
-
-- Various warnings are printed to stderr for problems encountered during data
-  measurement: if a ``--source`` module has no Python source to measure, or is
-  never encountered at all, or if no data is collected.
-
-- The reporting commands (report, annotate, html, and xml) now have an
-  ``--include`` switch to restrict reporting to modules matching those file
-  patterns, similar to the existing ``--omit`` switch. Thanks, Zooko.
-
-- The run command now supports ``--include`` and ``--omit`` to control what
-  modules it measures. This can speed execution and reduce the amount of data
-  during reporting. Thanks Zooko.
-
-- Since coverage.py 3.1, using the Python trace function has been slower than
-  it needs to be.  A cache of tracing decisions was broken, but has now been
-  fixed.
-
-- Python 2.7 and 3.2 have introduced new opcodes that are now supported.
-
-- Python files with no statements, for example, empty ``__init__.py`` files,
-  are now reported as having zero statements instead of one.  Fixes `issue 1`_.
-
-- Reports now have a column of missed line counts rather than executed line
-  counts, since developers should focus on reducing the missed lines to zero,
-  rather than increasing the executed lines to varying targets.  Once
-  suggested, this seemed blindingly obvious.
-
-- Line numbers in HTML source pages are clickable, linking directly to that
-  line, which is highlighted on arrival.  Added a link back to the index page
-  at the bottom of each HTML page.
-
-- Programs that call ``os.fork`` will properly collect data from both the child
-  and parent processes.  Use ``coverage run -p`` to get two data files that can
-  be combined with ``coverage combine``.  Fixes `issue 56`_.
-
-- Coverage.py is now runnable as a module: ``python -m coverage``.  Thanks,
-  Brett Cannon.
-
-- When measuring code running in a virtualenv, most of the system library was
-  being measured when it shouldn't have been.  This is now fixed.
-
-- Doctest text files are no longer recorded in the coverage data, since they
-  can't be reported anyway.  Fixes `issue 52`_ and `issue 61`_.
-
-- Jinja HTML templates compile into Python code using the HTML file name,
-  which confused coverage.py.  Now these files are no longer traced, fixing
-  `issue 82`_.
-
-- Source files can have more than one dot in them (foo.test.py), and will be
-  treated properly while reporting.  Fixes `issue 46`_.
-
-- Source files with DOS line endings are now properly tokenized for syntax
-  coloring on non-DOS machines.  Fixes `issue 53`_.
-
-- Unusual code structure that confused exits from methods with exits from
-  classes is now properly analyzed.  See `issue 62`_.
-
-- Asking for an HTML report with no files now shows a nice error message rather
-  than a cryptic failure ('int' object is unsubscriptable). Fixes `issue 59`_.
-
-.. _issue 1:  http://bitbucket.org/ned/coveragepy/issue/1/empty-__init__py-files-are-reported-as-1-executable
-.. _issue 34: http://bitbucket.org/ned/coveragepy/issue/34/enhanced-omit-globbing-handling
-.. _issue 36: http://bitbucket.org/ned/coveragepy/issue/36/provide-regex-style-omit
-.. _issue 46: http://bitbucket.org/ned/coveragepy/issue/46
-.. _issue 53: http://bitbucket.org/ned/coveragepy/issue/53
-.. _issue 52: http://bitbucket.org/ned/coveragepy/issue/52/doctesttestfile-confuses-source-detection
-.. _issue 56: http://bitbucket.org/ned/coveragepy/issue/56
-.. _issue 61: http://bitbucket.org/ned/coveragepy/issue/61/annotate-i-doesnt-work
-.. _issue 62: http://bitbucket.org/ned/coveragepy/issue/62
-.. _issue 59: http://bitbucket.org/ned/coveragepy/issue/59/html-report-fails-with-int-object-is
-.. _issue 82: http://bitbucket.org/ned/coveragepy/issue/82/tokenerror-when-generating-html-report
-
-
-Version 3.3.1 --- 6 March 2010
-------------------------------
-
-- Using `parallel=True` in .coveragerc file prevented reporting, but now does
-  not, fixing `issue 49`_.
-
-- When running your code with "coverage run", if you call `sys.exit()`,
-  coverage.py will exit with that status code, fixing `issue 50`_.
-
-.. _issue 49: http://bitbucket.org/ned/coveragepy/issue/49
-.. _issue 50: http://bitbucket.org/ned/coveragepy/issue/50
-
-
-Version 3.3 --- 24 February 2010
---------------------------------
-
-- Settings are now read from a .coveragerc file.  A specific file can be
-  specified on the command line with --rcfile=FILE.  The name of the file can
-  be programmatically set with the `config_file` argument to the coverage()
-  constructor, or reading a config file can be disabled with
-  `config_file=False`.
-
-- Fixed a problem with nested loops having their branch possibilities
-  mischaracterized: `issue 39`_.
-
-- Added coverage.process_start to enable coverage measurement when Python
-  starts.
-
-- Parallel data file names now have a random number appended to them in
-  addition to the machine name and process id.
-
-- Parallel data files combined with "coverage combine" are deleted after
-  they're combined, to clean up unneeded files.  Fixes `issue 40`_.
-
-- Exceptions thrown from product code run with "coverage run" are now displayed
-  without internal coverage.py frames, so the output is the same as when the
-  code is run without coverage.py.
-
-- The `data_suffix` argument to the coverage constructor is now appended with
-  an added dot rather than simply appended, so that .coveragerc files will not
-  be confused for data files.
-
-- Python source files that don't end with a newline can now be executed, fixing
-  `issue 47`_.
-
-- Added an AUTHORS.txt file.
-
-.. _issue 39: http://bitbucket.org/ned/coveragepy/issue/39
-.. _issue 40: http://bitbucket.org/ned/coveragepy/issue/40
-.. _issue 47: http://bitbucket.org/ned/coveragepy/issue/47
-
-
-Version 3.2 --- 5 December 2009
--------------------------------
-
-- Added a ``--version`` option on the command line.
-
-
-Version 3.2b4 --- 1 December 2009
----------------------------------
-
-- Branch coverage improvements:
-
-  - The XML report now includes branch information.
-
-- Click-to-sort HTML report columns are now persisted in a cookie.  Viewing
-  a report will sort it first the way you last had a coverage report sorted.
-  Thanks, `Chris Adams`_.
-
-- On Python 3.x, setuptools has been replaced by `Distribute`_.
-
-.. _Distribute: http://packages.python.org/distribute/
-
-
-Version 3.2b3 --- 23 November 2009
-----------------------------------
-
-- Fixed a memory leak in the C tracer that was introduced in 3.2b1.
-
-- Branch coverage improvements:
-
-  - Branches to excluded code are ignored.
-
-- The table of contents in the HTML report is now sortable: click the headers
-  on any column.  Thanks, `Chris Adams`_.
-
-.. _Chris Adams: http://improbable.org/chris/
-
-
-Version 3.2b2 --- 19 November 2009
-----------------------------------
-
-- Branch coverage improvements:
-
-  - Classes are no longer incorrectly marked as branches: `issue 32`_.
-
-  - "except" clauses with types are no longer incorrectly marked as branches:
-    `issue 35`_.
-
-- Fixed some problems syntax coloring sources with line continuations and
-  source with tabs: `issue 30`_ and `issue 31`_.
-
-- The --omit option now works much better than before, fixing `issue 14`_ and
-  `issue 33`_.  Thanks, Danek Duvall.
-
-.. _issue 14: http://bitbucket.org/ned/coveragepy/issue/14
-.. _issue 30: http://bitbucket.org/ned/coveragepy/issue/30
-.. _issue 31: http://bitbucket.org/ned/coveragepy/issue/31
-.. _issue 32: http://bitbucket.org/ned/coveragepy/issue/32
-.. _issue 33: http://bitbucket.org/ned/coveragepy/issue/33
-.. _issue 35: http://bitbucket.org/ned/coveragepy/issue/35
-
-
-Version 3.2b1 --- 10 November 2009
-----------------------------------
-
-- Branch coverage!
-
-- XML reporting has file paths that let Cobertura find the source code.
-
-- The tracer code has changed, it's a few percent faster.
-
-- Some exceptions reported by the command line interface have been cleaned up
-  so that tracebacks inside coverage.py aren't shown.  Fixes `issue 23`_.
-
-.. _issue 23: http://bitbucket.org/ned/coveragepy/issue/23
-
-
-Version 3.1 --- 4 October 2009
-------------------------------
-
-- Source code can now be read from eggs.  Thanks, Ross Lawley.  Fixes
-  `issue 25`_.
-
-.. _issue 25: http://bitbucket.org/ned/coveragepy/issue/25
-
-
-Version 3.1b1 --- 27 September 2009
------------------------------------
-
-- Python 3.1 is now supported.
-
-- Coverage.py has a new command line syntax with sub-commands.  This expands
-  the possibilities for adding features and options in the future.  The old
-  syntax is still supported.  Try "coverage help" to see the new commands.
-  Thanks to Ben Finney for early help.
-
-- Added an experimental "coverage xml" command for producing coverage reports
-  in a Cobertura-compatible XML format.  Thanks, Bill Hart.
-
-- Added the --timid option to enable a simpler slower trace function that works
-  for DecoratorTools projects, including TurboGears.  Fixed `issue 12`_ and
-  `issue 13`_.
-
-- HTML reports show modules from other directories.  Fixed `issue 11`_.
-
-- HTML reports now display syntax-colored Python source.
-
-- Programs that change directory will still write .coverage files in the
-  directory where execution started.  Fixed `issue 24`_.
-
-- Added a "coverage debug" command for getting diagnostic information about the
-  coverage.py installation.
-
-.. _issue 11: http://bitbucket.org/ned/coveragepy/issue/11
-.. _issue 12: http://bitbucket.org/ned/coveragepy/issue/12
-.. _issue 13: http://bitbucket.org/ned/coveragepy/issue/13
-.. _issue 24: http://bitbucket.org/ned/coveragepy/issue/24
-
-
-Version 3.0.1 --- 7 July 2009
------------------------------
-
-- Removed the recursion limit in the tracer function.  Previously, code that
-  ran more than 500 frames deep would crash. Fixed `issue 9`_.
-
-- Fixed a bizarre problem involving pyexpat, whereby lines following XML parser
-  invocations could be overlooked.  Fixed `issue 10`_.
-
-- On Python 2.3, coverage.py could mis-measure code with exceptions being
-  raised.  This is now fixed.
-
-- The coverage.py code itself will now not be measured by coverage.py, and no
-  coverage.py modules will be mentioned in the nose --with-cover plug-in.
-  Fixed `issue 8`_.
-
-- When running source files, coverage.py now opens them in universal newline
-  mode just like Python does.  This lets it run Windows files on Mac, for
-  example.
-
-.. _issue 9: http://bitbucket.org/ned/coveragepy/issue/9
-.. _issue 10: http://bitbucket.org/ned/coveragepy/issue/10
-.. _issue 8: http://bitbucket.org/ned/coveragepy/issue/8
-
-
-Version 3.0 --- 13 June 2009
-----------------------------
-
-- Fixed the way the Python library was ignored.  Too much code was being
-  excluded the old way.
-
-- Tabs are now properly converted in HTML reports.  Previously indentation was
-  lost.  Fixed `issue 6`_.
-
-- Nested modules now get a proper flat_rootname.  Thanks, Christian Heimes.
-
-.. _issue 6: http://bitbucket.org/ned/coveragepy/issue/6
-
-
-Version 3.0b3 --- 16 May 2009
------------------------------
-
-- Added parameters to coverage.__init__ for options that had been set on the
-  coverage object itself.
-
-- Added clear_exclude() and get_exclude_list() methods for programmatic
-  manipulation of the exclude regexes.
-
-- Added coverage.load() to read previously-saved data from the data file.
-
-- Improved the finding of code files.  For example, .pyc files that have been
-  installed after compiling are now located correctly.  Thanks, Detlev
-  Offenbach.
-
-- When using the object API (that is, constructing a coverage() object), data
-  is no longer saved automatically on process exit.  You can re-enable it with
-  the auto_data=True parameter on the coverage() constructor. The module-level
-  interface still uses automatic saving.
-
-
-Version 3.0b --- 30 April 2009
-------------------------------
-
-HTML reporting, and continued refactoring.
-
-- HTML reports and annotation of source files: use the new -b (browser) switch.
-  Thanks to George Song for code, inspiration and guidance.
-
-- Code in the Python standard library is not measured by default.  If you need
-  to measure standard library code, use the -L command-line switch during
-  execution, or the cover_pylib=True argument to the coverage() constructor.
-
-- Source annotation into a directory (-a -d) behaves differently.  The
-  annotated files are named with their hierarchy flattened so that same-named
-  files from different directories no longer collide.  Also, only files in the
-  current tree are included.
-
-- coverage.annotate_file is no longer available.
-
-- Programs executed with -x now behave more as they should, for example,
-  __file__ has the correct value.
-
-- .coverage data files have a new pickle-based format designed for better
-  extensibility.
-
-- Removed the undocumented cache_file argument to coverage.usecache().
-
-
-Version 3.0b1 --- 7 March 2009
-------------------------------
-
-Major overhaul.
-
-- Coverage.py is now a package rather than a module.  Functionality has been
-  split into classes.
-
-- The trace function is implemented in C for speed.  Coverage.py runs are now
-  much faster.  Thanks to David Christian for productive micro-sprints and
-  other encouragement.
-
-- Executable lines are identified by reading the line number tables in the
-  compiled code, removing a great deal of complicated analysis code.
-
-- Precisely which lines are considered executable has changed in some cases.
-  Therefore, your coverage stats may also change slightly.
-
-- The singleton coverage object is only created if the module-level functions
-  are used.  This maintains the old interface while allowing better
-  programmatic use of Coverage.py.
-
-- The minimum supported Python version is 2.3.
-
-
-Version 2.85 --- 14 September 2008
-----------------------------------
-
-- Add support for finding source files in eggs. Don't check for
-  morf's being instances of ModuleType, instead use duck typing so that
-  pseudo-modules can participate. Thanks, Imri Goldberg.
-
-- Use os.realpath as part of the fixing of file names so that symlinks won't
-  confuse things. Thanks, Patrick Mezard.
-
-
-Version 2.80 --- 25 May 2008
-----------------------------
-
-- Open files in rU mode to avoid line ending craziness. Thanks, Edward Loper.
-
-
-Version 2.78 --- 30 September 2007
-----------------------------------
-
-- Don't try to predict whether a file is Python source based on the extension.
-  Extension-less files are often Pythons scripts. Instead, simply parse the file
-  and catch the syntax errors. Hat tip to Ben Finney.
-
-
-Version 2.77 --- 29 July 2007
------------------------------
-
-- Better packaging.
-
-
-Version 2.76 --- 23 July 2007
------------------------------
-
-- Now Python 2.5 is *really* fully supported: the body of the new with
-  statement is counted as executable.
-
-
-Version 2.75 --- 22 July 2007
------------------------------
-
-- Python 2.5 now fully supported. The method of dealing with multi-line
-  statements is now less sensitive to the exact line that Python reports during
-  execution. Pass statements are handled specially so that their disappearance
-  during execution won't throw off the measurement.
-
-
-Version 2.7 --- 21 July 2007
-----------------------------
-
-- "#pragma: nocover" is excluded by default.
-
-- Properly ignore docstrings and other constant expressions that appear in the
-  middle of a function, a problem reported by Tim Leslie.
-
-- coverage.erase() shouldn't clobber the exclude regex. Change how parallel
-  mode is invoked, and fix erase() so that it erases the cache when called
-  programmatically.
-
-- In reports, ignore code executed from strings, since we can't do anything
-  useful with it anyway.
-
-- Better file handling on Linux, thanks Guillaume Chazarain.
-
-- Better shell support on Windows, thanks Noel O'Boyle.
-
-- Python 2.2 support maintained, thanks Catherine Proulx.
-
-- Minor changes to avoid lint warnings.
-
-
-Version 2.6 --- 23 August 2006
-------------------------------
-
-- Applied Joseph Tate's patch for function decorators.
-
-- Applied Sigve Tjora and Mark van der Wal's fixes for argument handling.
-
-- Applied Geoff Bache's parallel mode patch.
-
-- Refactorings to improve testability. Fixes to command-line logic for parallel
-  mode and collect.
-
-
-Version 2.5 --- 4 December 2005
--------------------------------
-
-- Call threading.settrace so that all threads are measured. Thanks Martin
-  Fuzzey.
-
-- Add a file argument to report so that reports can be captured to a different
-  destination.
-
-- Coverage.py can now measure itself.
-
-- Adapted Greg Rogers' patch for using relative file names, and sorting and
-  omitting files to report on.
-
-
-Version 2.2 --- 31 December 2004
---------------------------------
-
-- Allow for keyword arguments in the module global functions. Thanks, Allen.
-
-
-Version 2.1 --- 14 December 2004
---------------------------------
-
-- Return 'analysis' to its original behavior and add 'analysis2'. Add a global
-  for 'annotate', and factor it, adding 'annotate_file'.
-
-
-Version 2.0 --- 12 December 2004
---------------------------------
-
-Significant code changes.
-
-- Finding executable statements has been rewritten so that docstrings and
-  other quirks of Python execution aren't mistakenly identified as missing
-  lines.
-
-- Lines can be excluded from consideration, even entire suites of lines.
-
-- The file system cache of covered lines can be disabled programmatically.
-
-- Modernized the code.
-
-
-Earlier History
----------------
-
-2001-12-04 GDR Created.
-
-2001-12-06 GDR Added command-line interface and source code annotation.
-
-2001-12-09 GDR Moved design and interface to separate documents.
-
-2001-12-10 GDR Open cache file as binary on Windows. Allow simultaneous -e and
--x, or -a and -r.
-
-2001-12-12 GDR Added command-line help. Cache analysis so that it only needs to
-be done once when you specify -a and -r.
-
-2001-12-13 GDR Improved speed while recording. Portable between Python 1.5.2
-and 2.1.1.
-
-2002-01-03 GDR Module-level functions work correctly.
-
-2002-01-07 GDR Update sys.path when running a file with the -x option, so that
-it matches the value the program would get if it were run on its own.
--- a/DebugClients/Python/coverage/doc/README.rst	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/doc/README.rst	Sun Jul 24 12:01:01 2016 +0200
@@ -15,20 +15,23 @@
 the code analysis tools and tracing hooks provided in the Python standard
 library to determine which lines are executable, and which have been executed.
 
-Coverage.py runs on CPython 2.6, 2.7, 3.3, 3.4 or 3.5, PyPy 2.6, and PyPy3 2.4.
+Coverage.py runs on CPython 2.6, 2.7, and 3.3 through 3.6; PyPy 4.0 and 5.1;
+and PyPy3 2.4.
 
-Documentation is on `Read the Docs <http://coverage.readthedocs.org>`_.
+Documentation is on `Read the Docs <http://coverage.readthedocs.io>`_.
 Code repository and issue tracker are on `Bitbucket <http://bitbucket.org/ned/coveragepy>`_,
 with a mirrored repository on `GitHub <https://github.com/nedbat/coveragepy>`_.
 
-**New in 4.0:** ``--concurrency``, plugins for non-Python files, setup.cfg
+**New in 4.1:** much-improved branch coverage.
+
+New in 4.0: ``--concurrency``, plugins for non-Python files, setup.cfg
 support, --skip-covered, HTML filtering, and more than 50 issues closed.
 
 
-Quick Start
------------
+Getting Started
+---------------
 
-See the `quick start <http://coverage.readthedocs.org/#quick-start>`_
+See the `quick start <http://coverage.readthedocs.io/#quick-start>`_
 section of the docs.
 
 
@@ -46,7 +49,7 @@
     :target: https://ci.appveyor.com/project/nedbat/coveragepy
     :alt: Windows build status
 .. |docs| image:: https://readthedocs.org/projects/coverage/badge/?version=latest&style=flat
-    :target: http://coverage.readthedocs.org
+    :target: http://coverage.readthedocs.io
     :alt: Documentation
 .. |reqs| image:: https://requires.io/github/nedbat/coveragepy/requirements.svg?branch=master
     :target: https://requires.io/github/nedbat/coveragepy/requirements/?branch=master
@@ -57,9 +60,9 @@
 .. |format| image:: https://img.shields.io/pypi/format/coverage.svg
     :target: https://pypi.python.org/pypi/coverage
     :alt: Kit format
-.. |downloads| image:: https://img.shields.io/pypi/dd/coverage.svg
+.. |downloads| image:: https://img.shields.io/pypi/dw/coverage.svg
     :target: https://pypi.python.org/pypi/coverage
-    :alt: Daily PyPI downloads
+    :alt: Weekly PyPI downloads
 .. |versions| image:: https://img.shields.io/pypi/pyversions/coverage.svg
     :target: https://pypi.python.org/pypi/coverage
     :alt: Python versions supported
--- a/DebugClients/Python/coverage/env.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/env.py	Sun Jul 24 12:01:01 2016 +0200
@@ -30,3 +30,6 @@
 # Even when running tests, you can use COVERAGE_TESTING=0 to disable the
 # test-specific behavior like contracts.
 TESTING = os.getenv('COVERAGE_TESTING', '') == 'True'
+
+#
+# eflag: FileType = Python2
--- a/DebugClients/Python/coverage/execfile.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/execfile.py	Sun Jul 24 12:01:01 2016 +0200
@@ -10,10 +10,12 @@
 
 from coverage.backward import BUILTINS
 from coverage.backward import PYC_MAGIC_NUMBER, imp, importlib_util_find_spec
-from coverage.misc import ExceptionDuringRun, NoCode, NoSource
+from coverage.misc import ExceptionDuringRun, NoCode, NoSource, isolate_module
 from coverage.phystokens import compile_unicode
 from coverage.python import get_python_source
 
+os = isolate_module(os)
+
 
 class DummyLoader(object):
     """A shim for the pep302 __loader__, emulating pkgutil.ImpLoader.
@@ -39,7 +41,7 @@
             raise NoSource("No module named %r" % (modulename,))
         pathname = spec.origin
         packagename = spec.name
-        if pathname.endswith("__init__.py"):
+        if pathname.endswith("__init__.py") and not modulename.endswith("__init__"):
             mod_main = modulename + ".__main__"
             spec = importlib_util_find_spec(mod_main)
             if not spec:
--- a/DebugClients/Python/coverage/files.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/files.py	Sun Jul 24 12:01:01 2016 +0200
@@ -13,11 +13,10 @@
 
 from coverage import env
 from coverage.backward import unicode_class
-from coverage.misc import CoverageException, join_regex
+from coverage.misc import contract, CoverageException, join_regex, isolate_module
 
 
-RELATIVE_DIR = None
-CANONICAL_FILENAME_CACHE = {}
+os = isolate_module(os)
 
 
 def set_relative_directory():
@@ -31,10 +30,13 @@
     # avoid duplicating work.
     CANONICAL_FILENAME_CACHE = {}
 
+
 def relative_directory():
     """Return the directory that `relative_filename` is relative to."""
     return RELATIVE_DIR
 
+
+@contract(returns='unicode')
 def relative_filename(filename):
     """Return the relative form of `filename`.
 
@@ -45,8 +47,10 @@
     fnorm = os.path.normcase(filename)
     if fnorm.startswith(RELATIVE_DIR):
         filename = filename[len(RELATIVE_DIR):]
-    return filename
+    return unicode_filename(filename)
 
+
+@contract(returns='unicode')
 def canonical_filename(filename):
     """Return a canonical file name for `filename`.
 
@@ -58,7 +62,7 @@
             for path in [os.curdir] + sys.path:
                 if path is None:
                     continue
-                f = path + os.sep + filename
+                f = os.path.join(path, filename)
                 if os.path.exists(f):
                     filename = f
                     break
@@ -114,7 +118,7 @@
                 if os.path.normcase(f) == normtail:
                     tail = f
                     break
-            actpath = head.strip(os.sep) + os.sep + tail
+            actpath = os.path.join(head, tail)
         _ACTUAL_PATH_CACHE[path] = actpath
         return actpath
 
@@ -124,14 +128,36 @@
         return filename
 
 
+if env.PY2:
+    @contract(returns='unicode')
+    def unicode_filename(filename):
+        """Return a Unicode version of `filename`."""
+        if isinstance(filename, str):
+            encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
+            filename = filename.decode(encoding, "replace")
+        return filename
+else:
+    @contract(filename='unicode', returns='unicode')
+    def unicode_filename(filename):
+        """Return a Unicode version of `filename`."""
+        return filename
+
+
+@contract(returns='unicode')
 def abs_file(filename):
     """Return the absolute normalized form of `filename`."""
     path = os.path.expandvars(os.path.expanduser(filename))
     path = os.path.abspath(os.path.realpath(path))
     path = actual_path(path)
+    path = unicode_filename(path)
     return path
 
 
+RELATIVE_DIR = None
+CANONICAL_FILENAME_CACHE = None
+set_relative_directory()
+
+
 def isabs_anywhere(filename):
     """Is `filename` an absolute path on any OS?"""
     return ntpath.isabs(filename) or posixpath.isabs(filename)
@@ -349,7 +375,7 @@
             # files: Must end with .py or .pyw, and must not have certain funny
             # characters that probably mean they are editor junk.
             if re.match(r"^[^.#~!$@%^&*()+=,]+\.pyw?$", filename):
-                yield dirpath + os.sep + filename
+                yield os.path.join(dirpath, filename)
 
 #
 # eflag: FileType = Python2
--- a/DebugClients/Python/coverage/html.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/html.py	Sun Jul 24 12:01:01 2016 +0200
@@ -6,18 +6,19 @@
 import datetime
 import json
 import os
-import re
 import shutil
 
 import coverage
 from coverage import env
 from coverage.backward import iitems
 from coverage.files import flat_rootname
-from coverage.misc import CoverageException, Hasher
+from coverage.misc import CoverageException, Hasher, isolate_module
 from coverage.report import Reporter
 from coverage.results import Numbers
 from coverage.templite import Templite
 
+os = isolate_module(os)
+
 
 # Static files are looked for in a list of places.
 STATIC_PATH = [
@@ -57,12 +58,18 @@
     )
 
 
-def data(fname):
+def read_data(fname):
     """Return the contents of a data file of ours."""
     with open(data_filename(fname)) as data_file:
         return data_file.read()
 
 
+def write_html(fname, html):
+    """Write `html` to `fname`, properly encoded."""
+    with open(fname, "wb") as fout:
+        fout.write(html.encode('ascii', 'xmlcharrefreplace'))
+
+
 class HtmlReporter(Reporter):
     """HTML reporting."""
 
@@ -93,9 +100,7 @@
             '__url__': coverage.__url__,
             '__version__': coverage.__version__,
         }
-        self.source_tmpl = Templite(
-            data("pyfile.html"), self.template_globals
-        )
+        self.source_tmpl = Templite(read_data("pyfile.html"), self.template_globals)
 
         self.coverage = cov
 
@@ -157,11 +162,6 @@
                 os.path.join(self.directory, self.extra_css)
             )
 
-    def write_html(self, fname, html):
-        """Write `html` to `fname`, properly encoded."""
-        with open(fname, "wb") as fout:
-            fout.write(html.encode('ascii', 'xmlcharrefreplace'))
-
     def file_hash(self, source, fr):
         """Compute a hash that changes if the file needs to be re-reported."""
         m = Hasher()
@@ -189,6 +189,7 @@
 
         if self.has_arcs:
             missing_branch_arcs = analysis.missing_branch_arcs()
+            arcs_executed = analysis.arcs_executed()
 
         # These classes determine which lines are highlighted by default.
         c_run = "run hide_run"
@@ -202,7 +203,7 @@
             # Figure out how to mark this line.
             line_class = []
             annotate_html = ""
-            annotate_title = ""
+            annotate_long = ""
             if lineno in analysis.statements:
                 line_class.append("stm")
             if lineno in analysis.excluded:
@@ -216,23 +217,22 @@
                 for b in missing_branch_arcs[lineno]:
                     if b < 0:
                         shorts.append("exit")
-                        longs.append("the function exit")
                     else:
                         shorts.append(b)
-                        longs.append("line %d" % b)
+                    longs.append(fr.missing_arc_description(lineno, b, arcs_executed))
                 # 202F is NARROW NO-BREAK SPACE.
                 # 219B is RIGHTWARDS ARROW WITH STROKE.
                 short_fmt = "%s&#x202F;&#x219B;&#x202F;%s"
                 annotate_html = ",&nbsp;&nbsp; ".join(short_fmt % (lineno, d) for d in shorts)
-                annotate_html += " [?]"
 
-                annotate_title = "Line %d was executed, but never jumped to " % lineno
                 if len(longs) == 1:
-                    annotate_title += longs[0]
-                elif len(longs) == 2:
-                    annotate_title += longs[0] + " or " + longs[1]
+                    annotate_long = longs[0]
                 else:
-                    annotate_title += ", ".join(longs[:-1]) + ", or " + longs[-1]
+                    annotate_long = "%d missed branches: %s" % (
+                        len(longs),
+                        ", ".join("%d) %s" % (num, ann_long)
+                            for num, ann_long in enumerate(longs, start=1)),
+                    )
             elif lineno in analysis.statements:
                 line_class.append(c_run)
 
@@ -252,21 +252,26 @@
                 'number': lineno,
                 'class': ' '.join(line_class) or "pln",
                 'annotate': annotate_html,
-                'annotate_title': annotate_title,
+                'annotate_long': annotate_long,
             })
 
         # Write the HTML page for this file.
-        template_values = {
-            'c_exc': c_exc, 'c_mis': c_mis, 'c_par': c_par, 'c_run': c_run,
-            'has_arcs': self.has_arcs, 'extra_css': self.extra_css,
-            'fr': fr, 'nums': nums, 'lines': lines,
+        html = self.source_tmpl.render({
+            'c_exc': c_exc,
+            'c_mis': c_mis,
+            'c_par': c_par,
+            'c_run': c_run,
+            'has_arcs': self.has_arcs,
+            'extra_css': self.extra_css,
+            'fr': fr,
+            'nums': nums,
+            'lines': lines,
             'time_stamp': self.time_stamp,
-        }
-        html = spaceless(self.source_tmpl.render(template_values))
+        })
 
         html_filename = rootname + ".html"
         html_path = os.path.join(self.directory, html_filename)
-        self.write_html(html_path, html)
+        write_html(html_path, html)
 
         # Save this file's information for the index file.
         index_info = {
@@ -279,7 +284,7 @@
 
     def index_file(self):
         """Write the index.html file for this report."""
-        index_tmpl = Templite(data("index.html"), self.template_globals)
+        index_tmpl = Templite(read_data("index.html"), self.template_globals)
 
         self.totals = sum(f['nums'] for f in self.files)
 
@@ -291,7 +296,7 @@
             'time_stamp': self.time_stamp,
         })
 
-        self.write_html(os.path.join(self.directory, "index.html"), html)
+        write_html(os.path.join(self.directory, "index.html"), html)
 
         # Write the latest hashes for next time.
         self.status.write(self.directory)
@@ -416,29 +421,13 @@
 # Helpers for templates and generating HTML
 
 def escape(t):
-    """HTML-escape the text in `t`."""
-    return (
-        t
-        # Convert HTML special chars into HTML entities.
-        .replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
-        .replace("'", "&#39;").replace('"', "&quot;")
-        # Convert runs of spaces: "......" -> "&nbsp;.&nbsp;.&nbsp;."
-        .replace("  ", "&nbsp; ")
-        # To deal with odd-length runs, convert the final pair of spaces
-        # so that "....." -> "&nbsp;.&nbsp;&nbsp;."
-        .replace("  ", "&nbsp; ")
-    )
+    """HTML-escape the text in `t`.
 
-
-def spaceless(html):
-    """Squeeze out some annoying extra space from an HTML string.
-
-    Nicely-formatted templates mean lots of extra space in the result.
-    Get rid of some.
+    This is only suitable for HTML text, not attributes.
 
     """
-    html = re.sub(r">\s+<p ", ">\n<p ", html)
-    return html
+    # Convert HTML special chars into HTML entities.
+    return t.replace("&", "&amp;").replace("<", "&lt;")
 
 
 def pair(ratio):
--- a/DebugClients/Python/coverage/misc.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/misc.py	Sun Jul 24 12:01:01 2016 +0200
@@ -6,27 +6,57 @@
 import errno
 import hashlib
 import inspect
+import locale
 import os
+import sys
+import types
 
 from coverage import env
 from coverage.backward import string_class, to_bytes, unicode_class
 
+ISOLATED_MODULES = {}
+
+
+def isolate_module(mod):
+    """Copy a module so that we are isolated from aggressive mocking.
+
+    If a test suite mocks os.path.exists (for example), and then we need to use
+    it during the test, everything will get tangled up if we use their mock.
+    Making a copy of the module when we import it will isolate coverage.py from
+    those complications.
+    """
+    if mod not in ISOLATED_MODULES:
+        new_mod = types.ModuleType(mod.__name__)
+        ISOLATED_MODULES[mod] = new_mod
+        for name in dir(mod):
+            value = getattr(mod, name)
+            if isinstance(value, types.ModuleType):
+                value = isolate_module(value)
+            setattr(new_mod, name, value)
+    return ISOLATED_MODULES[mod]
+
+os = isolate_module(os)
+
 
 # Use PyContracts for assertion testing on parameters and returns, but only if
 # we are running our own test suite.
 if env.TESTING:
     from contracts import contract              # pylint: disable=unused-import
-    from contracts import new_contract
+    from contracts import new_contract as raw_new_contract
 
-    try:
-        # Define contract words that PyContract doesn't have.
-        new_contract('bytes', lambda v: isinstance(v, bytes))
-        if env.PY3:
-            new_contract('unicode', lambda v: isinstance(v, unicode_class))
-    except ValueError:
-        # During meta-coverage, this module is imported twice, and PyContracts
-        # doesn't like redefining contracts. It's OK.
-        pass
+    def new_contract(*args, **kwargs):
+        """A proxy for contracts.new_contract that doesn't mind happening twice."""
+        try:
+            return raw_new_contract(*args, **kwargs)
+        except ValueError:
+            # During meta-coverage, this module is imported twice, and
+            # PyContracts doesn't like redefining contracts. It's OK.
+            pass
+
+    # Define contract words that PyContract doesn't have.
+    new_contract('bytes', lambda v: isinstance(v, bytes))
+    if env.PY3:
+        new_contract('unicode', lambda v: isinstance(v, unicode_class))
 else:                                           # pragma: not covered
     # We aren't using real PyContracts, so just define a no-op decorator as a
     # stunt double.
@@ -34,6 +64,10 @@
         """Dummy no-op implementation of `contract`."""
         return lambda func: func
 
+    def new_contract(*args_unused, **kwargs_unused):
+        """Dummy no-op implementation of `new_contract`."""
+        pass
+
 
 def nice_pair(pair):
     """Make a nice string representation of a pair of numbers.
@@ -125,6 +159,18 @@
             raise
 
 
+def output_encoding(outfile=None):
+    """Determine the encoding to use for output written to `outfile` or stdout."""
+    if outfile is None:
+        outfile = sys.stdout
+    encoding = (
+        getattr(outfile, "encoding", None) or
+        getattr(sys.__stdout__, "encoding", None) or
+        locale.getpreferredencoding()
+    )
+    return encoding
+
+
 class Hasher(object):
     """Hashes Python data into md5."""
     def __init__(self):
--- a/DebugClients/Python/coverage/monkey.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/monkey.py	Sun Jul 24 12:01:01 2016 +0200
@@ -11,6 +11,36 @@
 # monkey-patched.
 PATCHED_MARKER = "_coverage$patched"
 
+if sys.version_info >= (3, 4):
+    klass = multiprocessing.process.BaseProcess
+else:
+    klass = multiprocessing.Process
+
+original_bootstrap = klass._bootstrap
+
+
+class ProcessWithCoverage(klass):
+    """A replacement for multiprocess.Process that starts coverage."""
+    def _bootstrap(self):
+        """Wrapper around _bootstrap to start coverage."""
+        from coverage import Coverage
+        cov = Coverage(data_suffix=True)
+        cov.start()
+        try:
+            return original_bootstrap(self)
+        finally:
+            cov.stop()
+            cov.save()
+
+
+class Stowaway(object):
+    """An object to pickle, so when it is unpickled, it can apply the monkey-patch."""
+    def __getstate__(self):
+        return {}
+
+    def __setstate__(self, state_unused):
+        patch_multiprocessing()
+
 
 def patch_multiprocessing():
     """Monkey-patch the multiprocessing module.
@@ -23,28 +53,31 @@
         return
 
     if sys.version_info >= (3, 4):
-        klass = multiprocessing.process.BaseProcess
-    else:
-        klass = multiprocessing.Process
-
-    original_bootstrap = klass._bootstrap
-
-    class ProcessWithCoverage(klass):
-        """A replacement for multiprocess.Process that starts coverage."""
-        def _bootstrap(self):
-            """Wrapper around _bootstrap to start coverage."""
-            from coverage import Coverage
-            cov = Coverage(data_suffix=True)
-            cov.start()
-            try:
-                return original_bootstrap(self)
-            finally:
-                cov.stop()
-                cov.save()
-
-    if sys.version_info >= (3, 4):
         klass._bootstrap = ProcessWithCoverage._bootstrap
     else:
         multiprocessing.Process = ProcessWithCoverage
 
+    # When spawning processes rather than forking them, we have no state in the
+    # new process.  We sneak in there with a Stowaway: we stuff one of our own
+    # objects into the data that gets pickled and sent to the sub-process. When
+    # the Stowaway is unpickled, it's __setstate__ method is called, which
+    # re-applies the monkey-patch.
+    # Windows only spawns, so this is needed to keep Windows working.
+    try:
+        from multiprocessing import spawn           # pylint: disable=no-name-in-module
+        original_get_preparation_data = spawn.get_preparation_data
+    except (ImportError, AttributeError):
+        pass
+    else:
+        def get_preparation_data_with_stowaway(name):
+            """Get the original preparation data, and also insert our stowaway."""
+            d = original_get_preparation_data(name)
+            d['stowaway'] = Stowaway()
+            return d
+
+        spawn.get_preparation_data = get_preparation_data_with_stowaway
+
     setattr(multiprocessing, PATCHED_MARKER, True)
+
+#
+# eflag: FileType = Python2
--- a/DebugClients/Python/coverage/parser.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/parser.py	Sun Jul 24 12:01:01 2016 +0200
@@ -3,23 +3,30 @@
 
 """Code parsing for coverage.py."""
 
+import ast
 import collections
-import dis
+import os
 import re
 import token
 import tokenize
 
+from coverage import env
 from coverage.backward import range    # pylint: disable=redefined-builtin
-from coverage.backward import bytes_to_ints
-from coverage.bytecode import ByteCodes, CodeObjects
-from coverage.misc import contract, nice_pair, expensive, join_regex
+from coverage.backward import bytes_to_ints, string_class
+from coverage.bytecode import CodeObjects
+from coverage.debug import short_stack
+from coverage.misc import contract, new_contract, nice_pair, join_regex
 from coverage.misc import CoverageException, NoSource, NotPython
-from coverage.phystokens import compile_unicode, generate_tokens
+from coverage.phystokens import compile_unicode, generate_tokens, neuter_encoding_declaration
 
 
 class PythonParser(object):
-    """Parse code to find executable lines, excluded lines, etc."""
+    """Parse code to find executable lines, excluded lines, etc.
 
+    This information is all based on static analysis: no code execution is
+    involved.
+
+    """
     @contract(text='unicode|None')
     def __init__(self, text=None, filename=None, exclude=None):
         """
@@ -42,29 +49,45 @@
 
         self.exclude = exclude
 
-        self.show_tokens = False
-
         # The text lines of the parsed code.
         self.lines = self.text.split('\n')
 
-        # The line numbers of excluded lines of code.
+        # The normalized line numbers of the statements in the code. Exclusions
+        # are taken into account, and statements are adjusted to their first
+        # lines.
+        self.statements = set()
+
+        # The normalized line numbers of the excluded lines in the code,
+        # adjusted to their first lines.
         self.excluded = set()
 
+        # The raw_* attributes are only used in this class, and in
+        # lab/parser.py to show how this class is working.
+
+        # The line numbers that start statements, as reported by the line
+        # number table in the bytecode.
+        self.raw_statements = set()
+
+        # The raw line numbers of excluded lines of code, as marked by pragmas.
+        self.raw_excluded = set()
+
+        # The line numbers of class and function definitions.
+        self.raw_classdefs = set()
+
         # The line numbers of docstring lines.
-        self.docstrings = set()
+        self.raw_docstrings = set()
 
-        # The line numbers of class definitions.
-        self.classdefs = set()
+        # Internal detail, used by lab/parser.py.
+        self.show_tokens = False
 
-        # A dict mapping line numbers to (lo,hi) for multi-line statements.
-        self.multiline = {}
+        # A dict mapping line numbers to lexical statement starts for
+        # multi-line statements.
+        self._multiline = {}
 
-        # The line numbers that start statements.
-        self.statement_starts = set()
-
-        # Lazily-created ByteParser and arc data.
+        # Lazily-created ByteParser, arc data, and missing arc descriptions.
         self._byte_parser = None
         self._all_arcs = None
+        self._missing_arc_fragments = None
 
     @property
     def byte_parser(self):
@@ -81,7 +104,10 @@
         part of it.
 
         """
-        regex_c = re.compile(join_regex(regexes))
+        combined = join_regex(regexes)
+        if env.PY2:
+            combined = combined.decode("utf8")
+        regex_c = re.compile(combined)
         matches = set()
         for i, ltext in enumerate(self.lines, start=1):
             if regex_c.search(ltext):
@@ -91,21 +117,23 @@
     def _raw_parse(self):
         """Parse the source to find the interesting facts about its lines.
 
-        A handful of member fields are updated.
+        A handful of attributes are updated.
 
         """
         # Find lines which match an exclusion pattern.
         if self.exclude:
-            self.excluded = self.lines_matching(self.exclude)
+            self.raw_excluded = self.lines_matching(self.exclude)
 
         # Tokenize, to find excluded suites, to find docstrings, and to find
         # multi-line statements.
         indent = 0
         exclude_indent = 0
         excluding = False
+        excluding_decorators = False
         prev_toktype = token.INDENT
         first_line = None
         empty = True
+        first_on_line = True
 
         tokgen = generate_tokens(self.text)
         for toktype, ttext, (slineno, _), (elineno, _), ltext in tokgen:
@@ -118,32 +146,44 @@
                 indent += 1
             elif toktype == token.DEDENT:
                 indent -= 1
-            elif toktype == token.NAME and ttext == 'class':
-                # Class definitions look like branches in the byte code, so
-                # we need to exclude them.  The simplest way is to note the
-                # lines with the 'class' keyword.
-                self.classdefs.add(slineno)
-            elif toktype == token.OP and ttext == ':':
-                if not excluding and elineno in self.excluded:
-                    # Start excluding a suite.  We trigger off of the colon
-                    # token so that the #pragma comment will be recognized on
-                    # the same line as the colon.
-                    exclude_indent = indent
-                    excluding = True
+            elif toktype == token.NAME:
+                if ttext == 'class':
+                    # Class definitions look like branches in the bytecode, so
+                    # we need to exclude them.  The simplest way is to note the
+                    # lines with the 'class' keyword.
+                    self.raw_classdefs.add(slineno)
+            elif toktype == token.OP:
+                if ttext == ':':
+                    should_exclude = (elineno in self.raw_excluded) or excluding_decorators
+                    if not excluding and should_exclude:
+                        # Start excluding a suite.  We trigger off of the colon
+                        # token so that the #pragma comment will be recognized on
+                        # the same line as the colon.
+                        self.raw_excluded.add(elineno)
+                        exclude_indent = indent
+                        excluding = True
+                        excluding_decorators = False
+                elif ttext == '@' and first_on_line:
+                    # A decorator.
+                    if elineno in self.raw_excluded:
+                        excluding_decorators = True
+                    if excluding_decorators:
+                        self.raw_excluded.add(elineno)
             elif toktype == token.STRING and prev_toktype == token.INDENT:
                 # Strings that are first on an indented line are docstrings.
                 # (a trick from trace.py in the stdlib.) This works for
                 # 99.9999% of cases.  For the rest (!) see:
                 # http://stackoverflow.com/questions/1769332/x/1769794#1769794
-                self.docstrings.update(range(slineno, elineno+1))
+                self.raw_docstrings.update(range(slineno, elineno+1))
             elif toktype == token.NEWLINE:
                 if first_line is not None and elineno != first_line:
                     # We're at the end of a line, and we've ended on a
                     # different line than the first line of the statement,
                     # so record a multi-line range.
                     for l in range(first_line, elineno+1):
-                        self.multiline[l] = first_line
+                        self._multiline[l] = first_line
                 first_line = None
+                first_on_line = True
 
             if ttext.strip() and toktype != tokenize.COMMENT:
                 # A non-whitespace token.
@@ -156,21 +196,18 @@
                     if excluding and indent <= exclude_indent:
                         excluding = False
                     if excluding:
-                        self.excluded.add(elineno)
+                        self.raw_excluded.add(elineno)
+                    first_on_line = False
 
             prev_toktype = toktype
 
         # Find the starts of the executable statements.
         if not empty:
-            self.statement_starts.update(self.byte_parser._find_statements())
+            self.raw_statements.update(self.byte_parser._find_statements())
 
     def first_line(self, line):
         """Return the first line number of the statement including `line`."""
-        first_line = self.multiline.get(line)
-        if first_line:
-            return first_line
-        else:
-            return line
+        return self._multiline.get(line, line)
 
     def first_lines(self, lines):
         """Map the line numbers in `lines` to the correct first line of the
@@ -187,20 +224,13 @@
 
     def translate_arcs(self, arcs):
         """Implement `FileReporter.translate_arcs`."""
-        return [
-            (self.first_line(a), self.first_line(b))
-            for (a, b) in arcs
-        ]
+        return [(self.first_line(a), self.first_line(b)) for (a, b) in arcs]
 
-    @expensive
     def parse_source(self):
         """Parse source text to find executable lines, excluded lines, etc.
 
-        Return values are 1) a set of executable line numbers, and 2) a set of
-        excluded line numbers.
-
-        Reported line numbers are normalized to the first line of multi-line
-        statements.
+        Sets the .excluded and .statements attributes, normalized to the first
+        line of multi-line statements.
 
         """
         try:
@@ -211,20 +241,16 @@
             else:
                 lineno = err.args[1][0]     # TokenError
             raise NotPython(
-                "Couldn't parse '%s' as Python source: '%s' at line %d" % (
+                u"Couldn't parse '%s' as Python source: '%s' at line %d" % (
                     self.filename, err.args[0], lineno
                 )
             )
 
-        excluded_lines = self.first_lines(self.excluded)
-        ignore = set()
-        ignore.update(excluded_lines)
-        ignore.update(self.docstrings)
-        starts = self.statement_starts - ignore
-        lines = self.first_lines(starts)
-        lines -= ignore
+        self.excluded = self.first_lines(self.raw_excluded)
 
-        return lines, excluded_lines
+        ignore = self.excluded | self.raw_docstrings
+        starts = self.raw_statements - ignore
+        self.statements = self.first_lines(starts) - ignore
 
     def arcs(self):
         """Get information about the arcs available in the code.
@@ -234,99 +260,98 @@
 
         """
         if self._all_arcs is None:
-            self._all_arcs = set()
-            for l1, l2 in self.byte_parser._all_arcs():
-                fl1 = self.first_line(l1)
-                fl2 = self.first_line(l2)
-                if fl1 != fl2:
-                    self._all_arcs.add((fl1, fl2))
+            self._analyze_ast()
         return self._all_arcs
 
+    def _analyze_ast(self):
+        """Run the AstArcAnalyzer and save its results.
+
+        `_all_arcs` is the set of arcs in the code.
+
+        """
+        aaa = AstArcAnalyzer(self.text, self.raw_statements, self._multiline)
+        aaa.analyze()
+
+        self._all_arcs = set()
+        for l1, l2 in aaa.arcs:
+            fl1 = self.first_line(l1)
+            fl2 = self.first_line(l2)
+            if fl1 != fl2:
+                self._all_arcs.add((fl1, fl2))
+
+        self._missing_arc_fragments = aaa.missing_arc_fragments
+
     def exit_counts(self):
         """Get a count of exits from that each line.
 
         Excluded lines are excluded.
 
         """
-        excluded_lines = self.first_lines(self.excluded)
         exit_counts = collections.defaultdict(int)
         for l1, l2 in self.arcs():
             if l1 < 0:
                 # Don't ever report -1 as a line number
                 continue
-            if l1 in excluded_lines:
+            if l1 in self.excluded:
                 # Don't report excluded lines as line numbers.
                 continue
-            if l2 in excluded_lines:
+            if l2 in self.excluded:
                 # Arcs to excluded lines shouldn't count.
                 continue
             exit_counts[l1] += 1
 
         # Class definitions have one extra exit, so remove one for each:
-        for l in self.classdefs:
+        for l in self.raw_classdefs:
             # Ensure key is there: class definitions can include excluded lines.
             if l in exit_counts:
                 exit_counts[l] -= 1
 
         return exit_counts
 
-
-## Opcodes that guide the ByteParser.
+    def missing_arc_description(self, start, end, executed_arcs=None):
+        """Provide an English sentence describing a missing arc."""
+        if self._missing_arc_fragments is None:
+            self._analyze_ast()
 
-def _opcode(name):
-    """Return the opcode by name from the dis module."""
-    return dis.opmap[name]
-
+        actual_start = start
 
-def _opcode_set(*names):
-    """Return a set of opcodes by the names in `names`."""
-    s = set()
-    for name in names:
-        try:
-            s.add(_opcode(name))
-        except KeyError:
-            pass
-    return s
+        if (
+            executed_arcs and
+            end < 0 and end == -start and
+            (end, start) not in executed_arcs and
+            (end, start) in self._missing_arc_fragments
+        ):
+            # It's a one-line callable, and we never even started it,
+            # and we have a message about not starting it.
+            start, end = end, start
 
-# Opcodes that leave the code object.
-OPS_CODE_END = _opcode_set('RETURN_VALUE')
-
-# Opcodes that unconditionally end the code chunk.
-OPS_CHUNK_END = _opcode_set(
-    'JUMP_ABSOLUTE', 'JUMP_FORWARD', 'RETURN_VALUE', 'RAISE_VARARGS',
-    'BREAK_LOOP', 'CONTINUE_LOOP',
-)
+        fragment_pairs = self._missing_arc_fragments.get((start, end), [(None, None)])
 
-# Opcodes that unconditionally begin a new code chunk.  By starting new chunks
-# with unconditional jump instructions, we neatly deal with jumps to jumps
-# properly.
-OPS_CHUNK_BEGIN = _opcode_set('JUMP_ABSOLUTE', 'JUMP_FORWARD')
-
-# Opcodes that push a block on the block stack.
-OPS_PUSH_BLOCK = _opcode_set(
-    'SETUP_LOOP', 'SETUP_EXCEPT', 'SETUP_FINALLY', 'SETUP_WITH'
-)
-
-# Block types for exception handling.
-OPS_EXCEPT_BLOCKS = _opcode_set('SETUP_EXCEPT', 'SETUP_FINALLY')
+        msgs = []
+        for fragment_pair in fragment_pairs:
+            smsg, emsg = fragment_pair
 
-# Opcodes that pop a block from the block stack.
-OPS_POP_BLOCK = _opcode_set('POP_BLOCK')
-
-# Opcodes that have a jump destination, but aren't really a jump.
-OPS_NO_JUMP = OPS_PUSH_BLOCK
+            if emsg is None:
+                if end < 0:
+                    # Hmm, maybe we have a one-line callable, let's check.
+                    if (-end, end) in self._missing_arc_fragments:
+                        return self.missing_arc_description(-end, end)
+                    emsg = "didn't jump to the function exit"
+                else:
+                    emsg = "didn't jump to line {lineno}"
+            emsg = emsg.format(lineno=end)
 
-# Individual opcodes we need below.
-OP_BREAK_LOOP = _opcode('BREAK_LOOP')
-OP_END_FINALLY = _opcode('END_FINALLY')
-OP_COMPARE_OP = _opcode('COMPARE_OP')
-COMPARE_EXCEPTION = 10  # just have to get this constant from the code.
-OP_LOAD_CONST = _opcode('LOAD_CONST')
-OP_RETURN_VALUE = _opcode('RETURN_VALUE')
+            msg = "line {start} {emsg}".format(start=actual_start, emsg=emsg)
+            if smsg is not None:
+                msg += ", because {smsg}".format(smsg=smsg.format(lineno=actual_start))
+
+            msgs.append(msg)
+
+        return " or ".join(msgs)
 
 
 class ByteParser(object):
-    """Parse byte codes to understand the structure of code."""
+    """Parse bytecode to understand the structure of code."""
 
     @contract(text='unicode')
     def __init__(self, text, code=None, filename=None):
@@ -338,14 +363,14 @@
                 self.code = compile_unicode(text, filename, "exec")
             except SyntaxError as synerr:
                 raise NotPython(
-                    "Couldn't parse '%s' as Python source: '%s' at line %d" % (
+                    u"Couldn't parse '%s' as Python source: '%s' at line %d" % (
                         filename, synerr.msg, synerr.lineno
                     )
                 )
 
         # Alternative Python implementations don't always provide all the
         # attributes on code objects that we need to do the analysis.
-        for attr in ['co_lnotab', 'co_firstlineno', 'co_consts', 'co_code']:
+        for attr in ['co_lnotab', 'co_firstlineno', 'co_consts']:
             if not hasattr(self.code, attr):
                 raise CoverageException(
                     "This implementation of Python doesn't support code analysis.\n"
@@ -400,275 +425,610 @@
             for _, l in bp._bytes_lines():
                 yield l
 
-    def _block_stack_repr(self, block_stack):               # pragma: debugging
-        """Get a string version of `block_stack`, for debugging."""
-        blocks = ", ".join(
-            "(%s, %r)" % (dis.opname[b[0]], b[1]) for b in block_stack
-        )
-        return "[" + blocks + "]"
+
+#
+# AST analysis
+#
+
+class LoopBlock(object):
+    """A block on the block stack representing a `for` or `while` loop."""
+    def __init__(self, start):
+        self.start = start
+        self.break_exits = set()
+
+
+class FunctionBlock(object):
+    """A block on the block stack representing a function definition."""
+    def __init__(self, start, name):
+        self.start = start
+        self.name = name
+
+
+class TryBlock(object):
+    """A block on the block stack representing a `try` block."""
+    def __init__(self, handler_start=None, final_start=None):
+        self.handler_start = handler_start
+        self.final_start = final_start
+        self.break_from = set()
+        self.continue_from = set()
+        self.return_from = set()
+        self.raise_from = set()
+
+
+class ArcStart(collections.namedtuple("Arc", "lineno, cause")):
+    """The information needed to start an arc.
+
+    `lineno` is the line number the arc starts from.  `cause` is a fragment
+    used as the startmsg for AstArcAnalyzer.missing_arc_fragments.
+
+    """
+    def __new__(cls, lineno, cause=None):
+        return super(ArcStart, cls).__new__(cls, lineno, cause)
+
+
+# Define contract words that PyContract doesn't have.
+# ArcStarts is for a list or set of ArcStart's.
+new_contract('ArcStarts', lambda seq: all(isinstance(x, ArcStart) for x in seq))
+
+
+class AstArcAnalyzer(object):
+    """Analyze source text with an AST to find executable code paths."""
+
+    @contract(text='unicode', statements=set)
+    def __init__(self, text, statements, multiline):
+        self.root_node = ast.parse(neuter_encoding_declaration(text))
+        # TODO: I think this is happening in too many places.
+        self.statements = set(multiline.get(l, l) for l in statements)
+        self.multiline = multiline
+
+        if int(os.environ.get("COVERAGE_ASTDUMP", 0)):      # pragma: debugging
+            # Dump the AST so that failing tests have helpful output.
+            print("Statements: {}".format(self.statements))
+            print("Multiline map: {}".format(self.multiline))
+            ast_dump(self.root_node)
+
+        self.arcs = set()
+
+        # A map from arc pairs to a pair of sentence fragments: (startmsg, endmsg).
+        # For an arc from line 17, they should be usable like:
+        #    "Line 17 {endmsg}, because {startmsg}"
+        self.missing_arc_fragments = collections.defaultdict(list)
+        self.block_stack = []
+
+        self.debug = bool(int(os.environ.get("COVERAGE_TRACK_ARCS", 0)))
+
+    def analyze(self):
+        """Examine the AST tree from `root_node` to determine possible arcs.
+
+        This sets the `arcs` attribute to be a set of (from, to) line number
+        pairs.
+
+        """
+        for node in ast.walk(self.root_node):
+            node_name = node.__class__.__name__
+            code_object_handler = getattr(self, "_code_object__" + node_name, None)
+            if code_object_handler is not None:
+                code_object_handler(node)
 
-    def _split_into_chunks(self):
-        """Split the code object into a list of `Chunk` objects.
+    def add_arc(self, start, end, smsg=None, emsg=None):
+        """Add an arc, including message fragments to use if it is missing."""
+        if self.debug:
+            print("\nAdding arc: ({}, {}): {!r}, {!r}".format(start, end, smsg, emsg))
+            print(short_stack(limit=6))
+        self.arcs.add((start, end))
+
+        if smsg is not None or emsg is not None:
+            self.missing_arc_fragments[(start, end)].append((smsg, emsg))
+
+    def nearest_blocks(self):
+        """Yield the blocks in nearest-to-farthest order."""
+        return reversed(self.block_stack)
+
+    @contract(returns=int)
+    def line_for_node(self, node):
+        """What is the right line number to use for this node?
+
+        This dispatches to _line__Node functions where needed.
+
+        """
+        node_name = node.__class__.__name__
+        handler = getattr(self, "_line__" + node_name, None)
+        if handler is not None:
+            return handler(node)
+        else:
+            return node.lineno
+
+    def _line__Assign(self, node):
+        return self.line_for_node(node.value)
+
+    def _line__Dict(self, node):
+        # Python 3.5 changed how dict literals are made.
+        if env.PYVERSION >= (3, 5) and node.keys:
+            if node.keys[0] is not None:
+                return node.keys[0].lineno
+            else:
+                # Unpacked dict literals `{**{'a':1}}` have None as the key,
+                # use the value in that case.
+                return node.values[0].lineno
+        else:
+            return node.lineno
 
-        Each chunk is only entered at its first instruction, though there can
-        be many exits from a chunk.
+    def _line__List(self, node):
+        if node.elts:
+            return self.line_for_node(node.elts[0])
+        else:
+            return node.lineno
+
+    def _line__Module(self, node):
+        if node.body:
+            return self.line_for_node(node.body[0])
+        else:
+            # Modules have no line number, they always start at 1.
+            return 1
+
+    OK_TO_DEFAULT = set([
+        "Assign", "Assert", "AugAssign", "Delete", "Exec", "Expr", "Global",
+        "Import", "ImportFrom", "Nonlocal", "Pass", "Print",
+    ])
+
+    @contract(returns='ArcStarts')
+    def add_arcs(self, node):
+        """Add the arcs for `node`.
 
-        Returns a list of `Chunk` objects.
+        Return a set of ArcStarts, exits from this node to the next.
+
+        """
+        node_name = node.__class__.__name__
+        handler = getattr(self, "_handle__" + node_name, None)
+        if handler is not None:
+            return handler(node)
+
+        if 0:
+            node_name = node.__class__.__name__
+            if node_name not in self.OK_TO_DEFAULT:
+                print("*** Unhandled: {0}".format(node))
+        return set([ArcStart(self.line_for_node(node), cause=None)])
+
+    @contract(returns='ArcStarts')
+    def add_body_arcs(self, body, from_start=None, prev_starts=None):
+        """Add arcs for the body of a compound statement.
+
+        `body` is the body node.  `from_start` is a single `ArcStart` that can
+        be the previous line in flow before this body.  `prev_starts` is a set
+        of ArcStarts that can be the previous line.  Only one of them should be
+        given.
+
+        Returns a set of ArcStarts, the exits from this body.
 
         """
-        # The list of chunks so far, and the one we're working on.
-        chunks = []
-        chunk = None
-
-        # A dict mapping byte offsets of line starts to the line numbers.
-        bytes_lines_map = dict(self._bytes_lines())
+        if prev_starts is None:
+            prev_starts = set([from_start])
+        for body_node in body:
+            lineno = self.line_for_node(body_node)
+            first_line = self.multiline.get(lineno, lineno)
+            if first_line not in self.statements:
+                continue
+            for prev_start in prev_starts:
+                self.add_arc(prev_start.lineno, lineno, prev_start.cause)
+            prev_starts = self.add_arcs(body_node)
+        return prev_starts
 
-        # The block stack: loops and try blocks get pushed here for the
-        # implicit jumps that can occur.
-        # Each entry is a tuple: (block type, destination)
-        block_stack = []
+    def is_constant_expr(self, node):
+        """Is this a compile-time constant?"""
+        node_name = node.__class__.__name__
+        if node_name in ["NameConstant", "Num"]:
+            return True
+        elif node_name == "Name":
+            if env.PY3 and node.id in ["True", "False", "None"]:
+                return True
+        return False
 
-        # Some op codes are followed by branches that should be ignored.  This
-        # is a count of how many ignores are left.
-        ignore_branch = 0
+    # tests to write:
+    # TODO: while EXPR:
+    # TODO: while False:
+    # TODO: listcomps hidden deep in other expressions
+    # TODO: listcomps hidden in lists: x = [[i for i in range(10)]]
+    # TODO: nested function definitions
 
-        # We have to handle the last two bytecodes specially.
-        ult = penult = None
+    @contract(exits='ArcStarts')
+    def process_break_exits(self, exits):
+        """Add arcs due to jumps from `exits` being breaks."""
+        for block in self.nearest_blocks():
+            if isinstance(block, LoopBlock):
+                block.break_exits.update(exits)
+                break
+            elif isinstance(block, TryBlock) and block.final_start is not None:
+                block.break_from.update(exits)
+                break
 
-        # Get a set of all of the jump-to points.
-        jump_to = set()
-        bytecodes = list(ByteCodes(self.code.co_code))
-        for bc in bytecodes:
-            if bc.jump_to >= 0:
-                jump_to.add(bc.jump_to)
-
-        chunk_lineno = 0
+    @contract(exits='ArcStarts')
+    def process_continue_exits(self, exits):
+        """Add arcs due to jumps from `exits` being continues."""
+        for block in self.nearest_blocks():
+            if isinstance(block, LoopBlock):
+                for xit in exits:
+                    self.add_arc(xit.lineno, block.start, xit.cause)
+                break
+            elif isinstance(block, TryBlock) and block.final_start is not None:
+                block.continue_from.update(exits)
+                break
 
-        # Walk the byte codes building chunks.
-        for bc in bytecodes:
-            # Maybe have to start a new chunk.
-            start_new_chunk = False
-            first_chunk = False
-            if bc.offset in bytes_lines_map:
-                # Start a new chunk for each source line number.
-                start_new_chunk = True
-                chunk_lineno = bytes_lines_map[bc.offset]
-                first_chunk = True
-            elif bc.offset in jump_to:
-                # To make chunks have a single entrance, we have to make a new
-                # chunk when we get to a place some bytecode jumps to.
-                start_new_chunk = True
-            elif bc.op in OPS_CHUNK_BEGIN:
-                # Jumps deserve their own unnumbered chunk.  This fixes
-                # problems with jumps to jumps getting confused.
-                start_new_chunk = True
+    @contract(exits='ArcStarts')
+    def process_raise_exits(self, exits):
+        """Add arcs due to jumps from `exits` being raises."""
+        for block in self.nearest_blocks():
+            if isinstance(block, TryBlock):
+                if block.handler_start is not None:
+                    for xit in exits:
+                        self.add_arc(xit.lineno, block.handler_start, xit.cause)
+                    break
+                elif block.final_start is not None:
+                    block.raise_from.update(exits)
+                    break
+            elif isinstance(block, FunctionBlock):
+                for xit in exits:
+                    self.add_arc(
+                        xit.lineno, -block.start, xit.cause,
+                        "didn't except from function '{0}'".format(block.name),
+                    )
+                break
+
+    @contract(exits='ArcStarts')
+    def process_return_exits(self, exits):
+        """Add arcs due to jumps from `exits` being returns."""
+        for block in self.nearest_blocks():
+            if isinstance(block, TryBlock) and block.final_start is not None:
+                block.return_from.update(exits)
+                break
+            elif isinstance(block, FunctionBlock):
+                for xit in exits:
+                    self.add_arc(
+                        xit.lineno, -block.start, xit.cause,
+                        "didn't return from function '{0}'".format(block.name),
+                    )
+                break
+
+    ## Handlers
 
-            if not chunk or start_new_chunk:
-                if chunk:
-                    chunk.exits.add(bc.offset)
-                chunk = Chunk(bc.offset, chunk_lineno, first_chunk)
-                if not chunks:
-                    # The very first chunk of a code object is always an
-                    # entrance.
-                    chunk.entrance = True
-                chunks.append(chunk)
+    @contract(returns='ArcStarts')
+    def _handle__Break(self, node):
+        here = self.line_for_node(node)
+        break_start = ArcStart(here, cause="the break on line {lineno} wasn't executed")
+        self.process_break_exits([break_start])
+        return set()
 
-            # Look at the opcode.
-            if bc.jump_to >= 0 and bc.op not in OPS_NO_JUMP:
-                if ignore_branch:
-                    # Someone earlier wanted us to ignore this branch.
-                    ignore_branch -= 1
-                else:
-                    # The opcode has a jump, it's an exit for this chunk.
-                    chunk.exits.add(bc.jump_to)
+    @contract(returns='ArcStarts')
+    def _handle_decorated(self, node):
+        """Add arcs for things that can be decorated (classes and functions)."""
+        last = self.line_for_node(node)
+        if node.decorator_list:
+            for dec_node in node.decorator_list:
+                dec_start = self.line_for_node(dec_node)
+                if dec_start != last:
+                    self.add_arc(last, dec_start)
+                    last = dec_start
+            # The definition line may have been missed, but we should have it
+            # in `self.statements`.  For some constructs, `line_for_node` is
+            # not what we'd think of as the first line in the statement, so map
+            # it to the first one.
+            body_start = self.line_for_node(node.body[0])
+            body_start = self.multiline.get(body_start, body_start)
+            for lineno in range(last+1, body_start):
+                if lineno in self.statements:
+                    self.add_arc(last, lineno)
+                    last = lineno
+        # The body is handled in collect_arcs.
+        return set([ArcStart(last, cause=None)])
+
+    _handle__ClassDef = _handle_decorated
+
+    @contract(returns='ArcStarts')
+    def _handle__Continue(self, node):
+        here = self.line_for_node(node)
+        continue_start = ArcStart(here, cause="the continue on line {lineno} wasn't executed")
+        self.process_continue_exits([continue_start])
+        return set()
 
-            if bc.op in OPS_CODE_END:
-                # The opcode can exit the code object.
-                chunk.exits.add(-self.code.co_firstlineno)
-            if bc.op in OPS_PUSH_BLOCK:
-                # The opcode adds a block to the block_stack.
-                block_stack.append((bc.op, bc.jump_to))
-            if bc.op in OPS_POP_BLOCK:
-                # The opcode pops a block from the block stack.
-                block_stack.pop()
-            if bc.op in OPS_CHUNK_END:
-                # This opcode forces the end of the chunk.
-                if bc.op == OP_BREAK_LOOP:
-                    # A break is implicit: jump where the top of the
-                    # block_stack points.
-                    chunk.exits.add(block_stack[-1][1])
-                chunk = None
-            if bc.op == OP_END_FINALLY:
-                # For the finally clause we need to find the closest exception
-                # block, and use its jump target as an exit.
-                for block in reversed(block_stack):
-                    if block[0] in OPS_EXCEPT_BLOCKS:
-                        chunk.exits.add(block[1])
-                        break
-            if bc.op == OP_COMPARE_OP and bc.arg == COMPARE_EXCEPTION:
-                # This is an except clause.  We want to overlook the next
-                # branch, so that except's don't count as branches.
-                ignore_branch += 1
+    @contract(returns='ArcStarts')
+    def _handle__For(self, node):
+        start = self.line_for_node(node.iter)
+        self.block_stack.append(LoopBlock(start=start))
+        from_start = ArcStart(start, cause="the loop on line {lineno} never started")
+        exits = self.add_body_arcs(node.body, from_start=from_start)
+        # Any exit from the body will go back to the top of the loop.
+        for xit in exits:
+            self.add_arc(xit.lineno, start, xit.cause)
+        my_block = self.block_stack.pop()
+        exits = my_block.break_exits
+        from_start = ArcStart(start, cause="the loop on line {lineno} didn't complete")
+        if node.orelse:
+            else_exits = self.add_body_arcs(node.orelse, from_start=from_start)
+            exits |= else_exits
+        else:
+            # no else clause: exit from the for line.
+            exits.add(from_start)
+        return exits
+
+    _handle__AsyncFor = _handle__For
+
+    _handle__FunctionDef = _handle_decorated
+    _handle__AsyncFunctionDef = _handle_decorated
 
-            penult = ult
-            ult = bc
+    @contract(returns='ArcStarts')
+    def _handle__If(self, node):
+        start = self.line_for_node(node.test)
+        from_start = ArcStart(start, cause="the condition on line {lineno} was never true")
+        exits = self.add_body_arcs(node.body, from_start=from_start)
+        from_start = ArcStart(start, cause="the condition on line {lineno} was never false")
+        exits |= self.add_body_arcs(node.orelse, from_start=from_start)
+        return exits
+
+    @contract(returns='ArcStarts')
+    def _handle__Raise(self, node):
+        here = self.line_for_node(node)
+        raise_start = ArcStart(here, cause="the raise on line {lineno} wasn't executed")
+        self.process_raise_exits([raise_start])
+        # `raise` statement jumps away, no exits from here.
+        return set()
+
+    @contract(returns='ArcStarts')
+    def _handle__Return(self, node):
+        here = self.line_for_node(node)
+        return_start = ArcStart(here, cause="the return on line {lineno} wasn't executed")
+        self.process_return_exits([return_start])
+        # `return` statement jumps away, no exits from here.
+        return set()
 
-        if chunks:
-            # The last two bytecodes could be a dummy "return None" that
-            # shouldn't be counted as real code. Every Python code object seems
-            # to end with a return, and a "return None" is inserted if there
-            # isn't an explicit return in the source.
-            if ult and penult:
-                if penult.op == OP_LOAD_CONST and ult.op == OP_RETURN_VALUE:
-                    if self.code.co_consts[penult.arg] is None:
-                        # This is "return None", but is it dummy?  A real line
-                        # would be a last chunk all by itself.
-                        if chunks[-1].byte != penult.offset:
-                            ex = -self.code.co_firstlineno
-                            # Split the last chunk
-                            last_chunk = chunks[-1]
-                            last_chunk.exits.remove(ex)
-                            last_chunk.exits.add(penult.offset)
-                            chunk = Chunk(
-                                penult.offset, last_chunk.line, False
-                            )
-                            chunk.exits.add(ex)
-                            chunks.append(chunk)
+    @contract(returns='ArcStarts')
+    def _handle__Try(self, node):
+        if node.handlers:
+            handler_start = self.line_for_node(node.handlers[0])
+        else:
+            handler_start = None
+
+        if node.finalbody:
+            final_start = self.line_for_node(node.finalbody[0])
+        else:
+            final_start = None
+
+        try_block = TryBlock(handler_start=handler_start, final_start=final_start)
+        self.block_stack.append(try_block)
+
+        start = self.line_for_node(node)
+        exits = self.add_body_arcs(node.body, from_start=ArcStart(start, cause=None))
 
-            # Give all the chunks a length.
-            chunks[-1].length = bc.next_offset - chunks[-1].byte
-            for i in range(len(chunks)-1):
-                chunks[i].length = chunks[i+1].byte - chunks[i].byte
+        # We're done with the `try` body, so this block no longer handles
+        # exceptions. We keep the block so the `finally` clause can pick up
+        # flows from the handlers and `else` clause.
+        if node.finalbody:
+            try_block.handler_start = None
+            if node.handlers:
+                # If there are `except` clauses, then raises in the try body
+                # will already jump to them.  Start this set over for raises in
+                # `except` and `else`.
+                try_block.raise_from = set([])
+        else:
+            self.block_stack.pop()
+
+        handler_exits = set()
+
+        if node.handlers:
+            last_handler_start = None
+            for handler_node in node.handlers:
+                handler_start = self.line_for_node(handler_node)
+                if last_handler_start is not None:
+                    self.add_arc(last_handler_start, handler_start)
+                last_handler_start = handler_start
+                from_cause = "the exception caught by line {lineno} didn't happen"
+                from_start = ArcStart(handler_start, cause=from_cause)
+                handler_exits |= self.add_body_arcs(handler_node.body, from_start=from_start)
 
-        #self.validate_chunks(chunks)
-        return chunks
+        if node.orelse:
+            exits = self.add_body_arcs(node.orelse, prev_starts=exits)
+
+        exits |= handler_exits
 
-    def validate_chunks(self, chunks):                      # pragma: debugging
-        """Validate the rule that chunks have a single entrance."""
-        # starts is the entrances to the chunks
-        starts = set(ch.byte for ch in chunks)
-        for ch in chunks:
-            assert all((ex in starts or ex < 0) for ex in ch.exits)
-
-    def _arcs(self):
-        """Find the executable arcs in the code.
+        if node.finalbody:
+            self.block_stack.pop()
+            final_from = (                  # You can get to the `finally` clause from:
+                exits |                         # the exits of the body or `else` clause,
+                try_block.break_from |          # or a `break`,
+                try_block.continue_from |       # or a `continue`,
+                try_block.raise_from |          # or a `raise`,
+                try_block.return_from           # or a `return`.
+            )
 
-        Yields pairs: (from,to).  From and to are integer line numbers.  If
-        from is < 0, then the arc is an entrance into the code object.  If to
-        is < 0, the arc is an exit from the code object.
+            exits = self.add_body_arcs(node.finalbody, prev_starts=final_from)
+            if try_block.break_from:
+                break_exits = self._combine_finally_starts(try_block.break_from, exits)
+                self.process_break_exits(break_exits)
+            if try_block.continue_from:
+                continue_exits = self._combine_finally_starts(try_block.continue_from, exits)
+                self.process_continue_exits(continue_exits)
+            if try_block.raise_from:
+                raise_exits = self._combine_finally_starts(try_block.raise_from, exits)
+                self.process_raise_exits(raise_exits)
+            if try_block.return_from:
+                return_exits = self._combine_finally_starts(try_block.return_from, exits)
+                self.process_return_exits(return_exits)
 
-        """
-        chunks = self._split_into_chunks()
+        return exits
 
-        # A map from byte offsets to the chunk starting at that offset.
-        byte_chunks = dict((c.byte, c) for c in chunks)
+    def _combine_finally_starts(self, starts, exits):
+        """Helper for building the cause of `finally` branches."""
+        causes = []
+        for lineno, cause in sorted(starts):
+            if cause is not None:
+                causes.append(cause.format(lineno=lineno))
+        cause = " or ".join(causes)
+        exits = set(ArcStart(ex.lineno, cause) for ex in exits)
+        return exits
 
-        # Traverse from the first chunk in each line, and yield arcs where
-        # the trace function will be invoked.
-        for chunk in chunks:
-            if chunk.entrance:
-                yield (-1, chunk.line)
+    @contract(returns='ArcStarts')
+    def _handle__TryExcept(self, node):
+        # Python 2.7 uses separate TryExcept and TryFinally nodes. If we get
+        # TryExcept, it means there was no finally, so fake it, and treat as
+        # a general Try node.
+        node.finalbody = []
+        return self._handle__Try(node)
 
-            if not chunk.first:
-                continue
+    @contract(returns='ArcStarts')
+    def _handle__TryFinally(self, node):
+        # Python 2.7 uses separate TryExcept and TryFinally nodes. If we get
+        # TryFinally, see if there's a TryExcept nested inside. If so, merge
+        # them. Otherwise, fake fields to complete a Try node.
+        node.handlers = []
+        node.orelse = []
 
-            chunks_considered = set()
-            chunks_to_consider = [chunk]
-            while chunks_to_consider:
-                # Get the chunk we're considering, and make sure we don't
-                # consider it again.
-                this_chunk = chunks_to_consider.pop()
-                chunks_considered.add(this_chunk)
+        first = node.body[0]
+        if first.__class__.__name__ == "TryExcept" and node.lineno == first.lineno:
+            assert len(node.body) == 1
+            node.body = first.body
+            node.handlers = first.handlers
+            node.orelse = first.orelse
+
+        return self._handle__Try(node)
 
-                # For each exit, add the line number if the trace function
-                # would be triggered, or add the chunk to those being
-                # considered if not.
-                for ex in this_chunk.exits:
-                    if ex < 0:
-                        yield (chunk.line, ex)
-                    else:
-                        next_chunk = byte_chunks[ex]
-                        if next_chunk in chunks_considered:
-                            continue
+    @contract(returns='ArcStarts')
+    def _handle__While(self, node):
+        constant_test = self.is_constant_expr(node.test)
+        start = to_top = self.line_for_node(node.test)
+        if constant_test:
+            to_top = self.line_for_node(node.body[0])
+        self.block_stack.append(LoopBlock(start=start))
+        from_start = ArcStart(start, cause="the condition on line {lineno} was never true")
+        exits = self.add_body_arcs(node.body, from_start=from_start)
+        for xit in exits:
+            self.add_arc(xit.lineno, to_top, xit.cause)
+        exits = set()
+        my_block = self.block_stack.pop()
+        exits.update(my_block.break_exits)
+        from_start = ArcStart(start, cause="the condition on line {lineno} was never false")
+        if node.orelse:
+            else_exits = self.add_body_arcs(node.orelse, from_start=from_start)
+            exits |= else_exits
+        else:
+            # No `else` clause: you can exit from the start.
+            if not constant_test:
+                exits.add(from_start)
+        return exits
+
+    @contract(returns='ArcStarts')
+    def _handle__With(self, node):
+        start = self.line_for_node(node)
+        exits = self.add_body_arcs(node.body, from_start=ArcStart(start))
+        return exits
 
-                        # The trace function is invoked if visiting the first
-                        # bytecode in a line, or if the transition is a
-                        # backward jump.
-                        backward_jump = next_chunk.byte < this_chunk.byte
-                        if next_chunk.first or backward_jump:
-                            if next_chunk.line != chunk.line:
-                                yield (chunk.line, next_chunk.line)
-                        else:
-                            chunks_to_consider.append(next_chunk)
+    _handle__AsyncWith = _handle__With
 
-    def _all_chunks(self):
-        """Returns a list of `Chunk` objects for this code and its children.
+    def _code_object__Module(self, node):
+        start = self.line_for_node(node)
+        if node.body:
+            exits = self.add_body_arcs(node.body, from_start=ArcStart(-start))
+            for xit in exits:
+                self.add_arc(xit.lineno, -start, xit.cause, "didn't exit the module")
+        else:
+            # Empty module.
+            self.add_arc(-start, start)
+            self.add_arc(start, -start)
 
-        See `_split_into_chunks` for details.
+    def _code_object__FunctionDef(self, node):
+        start = self.line_for_node(node)
+        self.block_stack.append(FunctionBlock(start=start, name=node.name))
+        exits = self.add_body_arcs(node.body, from_start=ArcStart(-start))
+        self.process_return_exits(exits)
+        self.block_stack.pop()
+
+    _code_object__AsyncFunctionDef = _code_object__FunctionDef
 
-        """
-        chunks = []
-        for bp in self.child_parsers():
-            chunks.extend(bp._split_into_chunks())
-
-        return chunks
+    def _code_object__ClassDef(self, node):
+        start = self.line_for_node(node)
+        self.add_arc(-start, start)
+        exits = self.add_body_arcs(node.body, from_start=ArcStart(start))
+        for xit in exits:
+            self.add_arc(
+                xit.lineno, -start, xit.cause,
+                "didn't exit the body of class '{0}'".format(node.name),
+            )
 
-    def _all_arcs(self):
-        """Get the set of all arcs in this code object and its children.
-
-        See `_arcs` for details.
+    def _make_oneline_code_method(noun):     # pylint: disable=no-self-argument
+        """A function to make methods for online callable _code_object__ methods."""
+        def _code_object__oneline_callable(self, node):
+            start = self.line_for_node(node)
+            self.add_arc(-start, start, None, "didn't run the {0} on line {1}".format(noun, start))
+            self.add_arc(
+                start, -start, None,
+                "didn't finish the {0} on line {1}".format(noun, start),
+            )
+        return _code_object__oneline_callable
 
-        """
-        arcs = set()
-        for bp in self.child_parsers():
-            arcs.update(bp._arcs())
-
-        return arcs
+    _code_object__Lambda = _make_oneline_code_method("lambda")
+    _code_object__GeneratorExp = _make_oneline_code_method("generator expression")
+    _code_object__DictComp = _make_oneline_code_method("dictionary comprehension")
+    _code_object__SetComp = _make_oneline_code_method("set comprehension")
+    if env.PY3:
+        _code_object__ListComp = _make_oneline_code_method("list comprehension")
 
 
-class Chunk(object):
-    """A sequence of byte codes with a single entrance.
-
-    To analyze byte code, we have to divide it into chunks, sequences of byte
-    codes such that each chunk has only one entrance, the first instruction in
-    the block.
-
-    This is almost the CS concept of `basic block`_, except that we're willing
-    to have many exits from a chunk, and "basic block" is a more cumbersome
-    term.
+SKIP_DUMP_FIELDS = ["ctx"]
 
-    .. _basic block: http://en.wikipedia.org/wiki/Basic_block
-
-    `byte` is the offset to the bytecode starting this chunk.
-
-    `line` is the source line number containing this chunk.
+def _is_simple_value(value):
+    """Is `value` simple enough to be displayed on a single line?"""
+    return (
+        value in [None, [], (), {}, set()] or
+        isinstance(value, (string_class, int, float))
+    )
 
-    `first` is true if this is the first chunk in the source line.
+# TODO: a test of ast_dump?
+def ast_dump(node, depth=0):
+    """Dump the AST for `node`.
 
-    An exit < 0 means the chunk can leave the code (return).  The exit is
-    the negative of the starting line number of the code block.
-
-    The `entrance` attribute is a boolean indicating whether the code object
-    can be entered at this chunk.
+    This recursively walks the AST, printing a readable version.
 
     """
-    def __init__(self, byte, line, first):
-        self.byte = byte
-        self.line = line
-        self.first = first
-        self.length = 0
-        self.entrance = False
-        self.exits = set()
+    indent = " " * depth
+    if not isinstance(node, ast.AST):
+        print("{0}<{1} {2!r}>".format(indent, node.__class__.__name__, node))
+        return
+
+    lineno = getattr(node, "lineno", None)
+    if lineno is not None:
+        linemark = " @ {0}".format(node.lineno)
+    else:
+        linemark = ""
+    head = "{0}<{1}{2}".format(indent, node.__class__.__name__, linemark)
 
-    def __repr__(self):
-        return "<%d+%d @%d%s%s %r>" % (
-            self.byte,
-            self.length,
-            self.line,
-            "!" if self.first else "",
-            "v" if self.entrance else "",
-            list(self.exits),
-        )
+    named_fields = [
+        (name, value)
+        for name, value in ast.iter_fields(node)
+        if name not in SKIP_DUMP_FIELDS
+    ]
+    if not named_fields:
+        print("{0}>".format(head))
+    elif len(named_fields) == 1 and _is_simple_value(named_fields[0][1]):
+        field_name, value = named_fields[0]
+        print("{0} {1}: {2!r}>".format(head, field_name, value))
+    else:
+        print(head)
+        if 0:
+            print("{0}# mro: {1}".format(
+                indent, ", ".join(c.__name__ for c in node.__class__.__mro__[1:]),
+            ))
+        next_indent = indent + "    "
+        for field_name, value in named_fields:
+            prefix = "{0}{1}:".format(next_indent, field_name)
+            if _is_simple_value(value):
+                print("{0} {1!r}".format(prefix, value))
+            elif isinstance(value, list):
+                print("{0} [".format(prefix))
+                for n in value:
+                    ast_dump(n, depth + 8)
+                print("{0}]".format(next_indent))
+            else:
+                print(prefix)
+                ast_dump(value, depth + 8)
+
+        print("{0}>".format(indent))
 
 #
 # eflag: FileType = Python2
--- a/DebugClients/Python/coverage/phystokens.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/phystokens.py	Sun Jul 24 12:01:01 2016 +0200
@@ -6,6 +6,7 @@
 import codecs
 import keyword
 import re
+import sys
 import token
 import tokenize
 
@@ -91,8 +92,7 @@
     line = []
     col = 0
 
-    # The \f is because of http://bugs.python.org/issue19035
-    source = source.expandtabs(8).replace('\r\n', '\n').replace('\f', ' ')
+    source = source.expandtabs(8).replace('\r\n', '\n')
     tokgen = generate_tokens(source)
 
     for ttype, ttext, (_, scol), (_, ecol), _ in phys_tokens(tokgen):
@@ -152,7 +152,7 @@
 generate_tokens = CachedTokenizer().generate_tokens
 
 
-COOKIE_RE = re.compile(r"^\s*#.*coding[:=]\s*([-\w.]+)", flags=re.MULTILINE)
+COOKIE_RE = re.compile(r"^[ \t]*#.*coding[:=][ \t]*([-\w.]+)", flags=re.MULTILINE)
 
 @contract(source='bytes')
 def _source_encoding_py2(source):
@@ -274,32 +274,23 @@
 
     Python 2's compile() builtin has a stupid restriction: if the source string
     is Unicode, then it may not have a encoding declaration in it.  Why not?
-    Who knows!
+    Who knows!  It also decodes to utf8, and then tries to interpret those utf8
+    bytes according to the encoding declaration.  Why? Who knows!
 
-    This function catches that exception, neuters the coding declaration, and
-    compiles it anyway.
+    This function neuters the coding declaration, and compiles it.
 
     """
-    try:
-        code = compile(source, filename, mode)
-    except SyntaxError as synerr:
-        if "coding declaration in unicode string" not in synerr.args[0].lower():
-            raise
-        source = neuter_encoding_declaration(source)
-        code = compile(source, filename, mode)
-
+    source = neuter_encoding_declaration(source)
+    if env.PY2 and isinstance(filename, unicode):
+        filename = filename.encode(sys.getfilesystemencoding(), "replace")
+    code = compile(source, filename, mode)
     return code
 
 
 @contract(source='unicode', returns='unicode')
 def neuter_encoding_declaration(source):
-    """Return `source`, with any encoding declaration neutered.
-
-    This function will only ever be called on `source` that has an encoding
-    declaration, so some edge cases can be ignored.
-
-    """
-    source = COOKIE_RE.sub("# (deleted declaration)", source)
+    """Return `source`, with any encoding declaration neutered."""
+    source = COOKIE_RE.sub("# (deleted declaration)", source, count=2)
     return source
 
 #
--- a/DebugClients/Python/coverage/pickle2json.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/pickle2json.py	Sun Jul 24 12:01:01 2016 +0200
@@ -45,3 +45,6 @@
     (options, args) = parser.parse_args()
 
     pickle2json(options.input_file, options.output_file)
+
+#
+# eflag: FileType = Python2
--- a/DebugClients/Python/coverage/plugin.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/plugin.py	Sun Jul 24 12:01:01 2016 +0200
@@ -324,11 +324,26 @@
         executable line number to a count of how many exits it has.
 
         To be honest, this feels wrong, and should be refactored.  Let me know
-        if you attempt to implement this...
+        if you attempt to implement this method in your plugin...
 
         """
         return {}
 
+    def missing_arc_description(self, start, end, executed_arcs=None):     # pylint: disable=unused-argument
+        """Provide an English sentence describing a missing arc.
+
+        The `start` and `end` arguments are the line numbers of the missing
+        arc. Negative numbers indicate entering or exiting code objects.
+
+        The `executed_arcs` argument is a set of line number pairs, the arcs
+        that were executed in this file.
+
+        By default, this simply returns the string "Line {start} didn't jump
+        to {end}".
+
+        """
+        return "Line {start} didn't jump to line {end}".format(start=start, end=end)
+
     def source_token_lines(self):
         """Generate a series of tokenized lines, one for each line in `source`.
 
@@ -379,3 +394,6 @@
 
     def __ge__(self, other):
         return self.filename >= other.filename
+
+#
+# eflag: FileType = Python2
--- a/DebugClients/Python/coverage/plugin_support.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/plugin_support.py	Sun Jul 24 12:01:01 2016 +0200
@@ -3,12 +3,15 @@
 
 """Support for plugins."""
 
+import os
 import os.path
 import sys
 
-from coverage.misc import CoverageException
+from coverage.misc import CoverageException, isolate_module
 from coverage.plugin import CoveragePlugin, FileTracer, FileReporter
 
+os = isolate_module(os)
+
 
 class Plugins(object):
     """The currently loaded collection of coverage.py plugins."""
@@ -242,3 +245,6 @@
         ret = list(self.reporter.source_token_lines())
         self.debug.write("source_token_lines() --> %d tokens" % (len(ret),))
         return ret
+
+#
+# eflag: FileType = Python2
--- a/DebugClients/Python/coverage/python.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/python.py	Sun Jul 24 12:01:01 2016 +0200
@@ -4,14 +4,19 @@
 """Python source expertise for coverage.py"""
 
 import os.path
+import types
 import zipimport
 
 from coverage import env, files
-from coverage.misc import contract, expensive, NoSource, join_regex
+from coverage.misc import (
+    contract, CoverageException, expensive, NoSource, join_regex, isolate_module,
+)
 from coverage.parser import PythonParser
 from coverage.phystokens import source_token_lines, source_encoding
 from coverage.plugin import FileReporter
 
+os = isolate_module(os)
+
 
 @contract(returns='bytes')
 def read_python_source(filename):
@@ -48,6 +53,8 @@
         # Couldn't find source.
         raise NoSource("No source for code: '%s'." % filename)
 
+    # Replace \f because of http://bugs.python.org/issue19035
+    source = source.replace(b'\f', b' ')
     source = source.decode(source_encoding(source), "replace")
 
     # Python code should always end with a line with a newline.
@@ -90,9 +97,15 @@
 
         if hasattr(morf, '__file__'):
             filename = morf.__file__
+        elif isinstance(morf, types.ModuleType):
+            # A module should have had .__file__, otherwise we can't use it.
+            # This could be a PEP-420 namespace package.
+            raise CoverageException("Module {0} has no file".format(morf))
         else:
             filename = morf
 
+        filename = files.unicode_filename(filename)
+
         # .pyc files should always refer to a .py instead.
         if filename.endswith(('.pyc', '.pyo')):
             filename = filename[:-1]
@@ -104,6 +117,7 @@
         if hasattr(morf, '__name__'):
             name = morf.__name__
             name = name.replace(".", os.sep) + ".py"
+            name = files.unicode_filename(name)
         else:
             name = files.relative_filename(filename)
         self.relname = name
@@ -113,6 +127,7 @@
         self._statements = None
         self._excluded = None
 
+    @contract(returns='unicode')
     def relative_filename(self):
         return self.relname
 
@@ -124,21 +139,16 @@
                 filename=self.filename,
                 exclude=self.coverage._exclude_regex('exclude'),
             )
+            self._parser.parse_source()
         return self._parser
 
-    @expensive
     def lines(self):
         """Return the line numbers of statements in the file."""
-        if self._statements is None:
-            self._statements, self._excluded = self.parser.parse_source()
-        return self._statements
+        return self.parser.statements
 
-    @expensive
     def excluded_lines(self):
         """Return the line numbers of statements in the file."""
-        if self._excluded is None:
-            self._statements, self._excluded = self.parser.parse_source()
-        return self._excluded
+        return self.parser.excluded
 
     def translate_lines(self, lines):
         return self.parser.translate_lines(lines)
@@ -162,6 +172,9 @@
     def exit_counts(self):
         return self.parser.exit_counts()
 
+    def missing_arc_description(self, start, end, executed_arcs=None):
+        return self.parser.missing_arc_description(start, end, executed_arcs)
+
     @contract(returns='unicode')
     def source(self):
         if self._source is None:
@@ -190,3 +203,6 @@
 
     def source_token_lines(self):
         return source_token_lines(self.source())
+
+#
+# eflag: FileType = Python2
--- a/DebugClients/Python/coverage/pytracer.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/pytracer.py	Sun Jul 24 12:01:01 2016 +0200
@@ -92,9 +92,12 @@
                 self.cur_file_dict = self.data[tracename]
             # The call event is really a "start frame" event, and happens for
             # function calls and re-entering generators.  The f_lasti field is
-            # -1 for calls, and a real offset for generators.  Use -1 as the
+            # -1 for calls, and a real offset for generators.  Use <0 as the
             # line number for calls, and the real line number for generators.
-            self.last_line = -1 if (frame.f_lasti < 0) else frame.f_lineno
+            if frame.f_lasti < 0:
+                self.last_line = -frame.f_code.co_firstlineno
+            else:
+                self.last_line = frame.f_lineno
         elif event == 'line':
             # Record an executed line.
             if self.cur_file_dict is not None:
@@ -134,7 +137,7 @@
     def stop(self):
         """Stop this Tracer."""
         self.stopped = True
-        if self.threading and self.thread != self.threading.currentThread():
+        if self.threading and self.thread.ident != self.threading.currentThread().ident:
             # Called on a different thread than started us: we can't unhook
             # ourselves, but we've set the flag that we should stop, so we
             # won't do any more tracing.
@@ -150,3 +153,6 @@
     def get_stats(self):
         """Return a dictionary of statistics, or None."""
         return None
+
+#
+# eflag: FileType = Python2
--- a/DebugClients/Python/coverage/report.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/report.py	Sun Jul 24 12:01:01 2016 +0200
@@ -4,9 +4,12 @@
 """Reporter foundation for coverage.py."""
 
 import os
+import warnings
 
 from coverage.files import prep_patterns, FnmatchMatcher
-from coverage.misc import CoverageException, NoSource, NotPython
+from coverage.misc import CoverageException, NoSource, NotPython, isolate_module
+
+os = isolate_module(os)
 
 
 class Reporter(object):
@@ -22,40 +25,45 @@
         self.coverage = coverage
         self.config = config
 
-        # The FileReporters to report on.  Set by find_file_reporters.
-        self.file_reporters = []
-
         # The directory into which to place the report, used by some derived
         # classes.
         self.directory = None
 
+        # Our method find_file_reporters used to set an attribute that other
+        # code could read.  That's been refactored away, but some third parties
+        # were using that attribute.  We'll continue to support it in a noisy
+        # way for now.
+        self._file_reporters = []
+
+    @property
+    def file_reporters(self):
+        """Keep .file_reporters working for private-grabbing tools."""
+        warnings.warn(
+            "Report.file_reporters will no longer be available in Coverage.py 4.2",
+            DeprecationWarning,
+        )
+        return self._file_reporters
+
     def find_file_reporters(self, morfs):
         """Find the FileReporters we'll report on.
 
         `morfs` is a list of modules or file names.
 
+        Returns a list of FileReporters.
+
         """
-        self.file_reporters = self.coverage._get_file_reporters(morfs)
+        reporters = self.coverage._get_file_reporters(morfs)
 
         if self.config.include:
-            patterns = prep_patterns(self.config.include)
-            matcher = FnmatchMatcher(patterns)
-            filtered = []
-            for fr in self.file_reporters:
-                if matcher.match(fr.filename):
-                    filtered.append(fr)
-            self.file_reporters = filtered
+            matcher = FnmatchMatcher(prep_patterns(self.config.include))
+            reporters = [fr for fr in reporters if matcher.match(fr.filename)]
 
         if self.config.omit:
-            patterns = prep_patterns(self.config.omit)
-            matcher = FnmatchMatcher(patterns)
-            filtered = []
-            for fr in self.file_reporters:
-                if not matcher.match(fr.filename):
-                    filtered.append(fr)
-            self.file_reporters = filtered
+            matcher = FnmatchMatcher(prep_patterns(self.config.omit))
+            reporters = [fr for fr in reporters if not matcher.match(fr.filename)]
 
-        self.file_reporters.sort()
+        self._file_reporters = sorted(reporters)
+        return self._file_reporters
 
     def report_files(self, report_fn, morfs, directory=None):
         """Run a reporting function on a number of morfs.
@@ -69,16 +77,16 @@
         `analysis` is the `Analysis` for the morf.
 
         """
-        self.find_file_reporters(morfs)
+        file_reporters = self.find_file_reporters(morfs)
 
-        if not self.file_reporters:
+        if not file_reporters:
             raise CoverageException("No data to report.")
 
         self.directory = directory
         if self.directory and not os.path.exists(self.directory):
             os.makedirs(self.directory)
 
-        for fr in self.file_reporters:
+        for fr in file_reporters:
             try:
                 report_fn(fr, self.coverage._analyze(fr))
             except NoSource:
--- a/DebugClients/Python/coverage/results.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/results.py	Sun Jul 24 12:01:01 2016 +0200
@@ -30,9 +30,7 @@
             self.no_branch = self.file_reporter.no_branch_lines()
             n_branches = self.total_branches()
             mba = self.missing_branch_arcs()
-            n_partial_branches = sum(
-                len(v) for k,v in iitems(mba) if k not in self.missing
-                )
+            n_partial_branches = sum(len(v) for k,v in iitems(mba) if k not in self.missing)
             n_missing_branches = sum(len(v) for k,v in iitems(mba))
         else:
             self._arc_possibilities = []
@@ -48,7 +46,7 @@
             n_branches=n_branches,
             n_partial_branches=n_partial_branches,
             n_missing_branches=n_missing_branches,
-            )
+        )
 
     def missing_formatted(self):
         """The missing line numbers, formatted nicely.
@@ -84,7 +82,7 @@
         return sorted(missing)
 
     def arcs_missing_formatted(self):
-        """ The missing branch arcs, formatted nicely.
+        """The missing branch arcs, formatted nicely.
 
         Returns a string like "1->2, 1->3, 16->20". Omits any mention of
         branches from missing lines, so if line 17 is missing, then 17->18
@@ -98,7 +96,7 @@
         for line, exits in line_exits:
             for ex in sorted(exits):
                 if line not in missing:
-                    pairs.append('%d->%d' % (line, ex))
+                    pairs.append("%d->%s" % (line, (ex if ex > 0 else "exit")))
         return ', '.join(pairs)
 
     def arcs_unpredicted(self):
--- a/DebugClients/Python/coverage/summary.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/summary.py	Sun Jul 24 12:01:01 2016 +0200
@@ -5,9 +5,10 @@
 
 import sys
 
+from coverage import env
 from coverage.report import Reporter
 from coverage.results import Numbers
-from coverage.misc import NotPython, CoverageException
+from coverage.misc import NotPython, CoverageException, output_encoding
 
 
 class SummaryReporter(Reporter):
@@ -20,46 +21,53 @@
     def report(self, morfs, outfile=None):
         """Writes a report summarizing coverage statistics per module.
 
-        `outfile` is a file object to write the summary to.
+        `outfile` is a file object to write the summary to. It must be opened
+        for native strings (bytes on Python 2, Unicode on Python 3).
 
         """
-        self.find_file_reporters(morfs)
+        file_reporters = self.find_file_reporters(morfs)
 
         # Prepare the formatting strings
-        max_name = max([len(fr.relative_filename()) for fr in self.file_reporters] + [5])
-        fmt_name = "%%- %ds  " % max_name
-        fmt_err = "%s   %s: %s\n"
-        fmt_skip_covered = "\n%s file%s skipped due to complete coverage.\n"
+        max_name = max([len(fr.relative_filename()) for fr in file_reporters] + [5])
+        fmt_name = u"%%- %ds  " % max_name
+        fmt_err = u"%s   %s: %s"
+        fmt_skip_covered = u"\n%s file%s skipped due to complete coverage."
 
-        header = (fmt_name % "Name") + " Stmts   Miss"
-        fmt_coverage = fmt_name + "%6d %6d"
+        header = (fmt_name % "Name") + u" Stmts   Miss"
+        fmt_coverage = fmt_name + u"%6d %6d"
         if self.branches:
-            header += " Branch BrPart"
-            fmt_coverage += " %6d %6d"
+            header += u" Branch BrPart"
+            fmt_coverage += u" %6d %6d"
         width100 = Numbers.pc_str_width()
-        header += "%*s" % (width100+4, "Cover")
-        fmt_coverage += "%%%ds%%%%" % (width100+3,)
+        header += u"%*s" % (width100+4, "Cover")
+        fmt_coverage += u"%%%ds%%%%" % (width100+3,)
         if self.config.show_missing:
-            header += "   Missing"
-            fmt_coverage += "   %s"
-        rule = "-" * len(header) + "\n"
-        header += "\n"
-        fmt_coverage += "\n"
+            header += u"   Missing"
+            fmt_coverage += u"   %s"
+        rule = u"-" * len(header)
 
-        if not outfile:
+        if outfile is None:
             outfile = sys.stdout
 
+        def writeout(line):
+            """Write a line to the output, adding a newline."""
+            if env.PY2:
+                line = line.encode(output_encoding())
+            outfile.write(line.rstrip())
+            outfile.write("\n")
+
         # Write the header
-        outfile.write(header)
-        outfile.write(rule)
+        writeout(header)
+        writeout(rule)
 
         total = Numbers()
         skipped_count = 0
 
-        for fr in self.file_reporters:
+        for fr in file_reporters:
             try:
                 analysis = self.coverage._analyze(fr)
                 nums = analysis.numbers
+                total += nums
 
                 if self.config.skip_covered:
                     # Don't report on 100% files.
@@ -82,8 +90,7 @@
                                 missing_fmtd += ", "
                             missing_fmtd += branches_fmtd
                     args += (missing_fmtd,)
-                outfile.write(fmt_coverage % args)
-                total += nums
+                writeout(fmt_coverage % args)
             except Exception:
                 report_it = not self.config.ignore_errors
                 if report_it:
@@ -93,23 +100,23 @@
                     if typ is NotPython and not fr.should_be_python():
                         report_it = False
                 if report_it:
-                    outfile.write(fmt_err % (fr.relative_filename(), typ.__name__, msg))
+                    writeout(fmt_err % (fr.relative_filename(), typ.__name__, msg))
 
         if total.n_files > 1:
-            outfile.write(rule)
+            writeout(rule)
             args = ("TOTAL", total.n_statements, total.n_missing)
             if self.branches:
                 args += (total.n_branches, total.n_partial_branches)
             args += (total.pc_covered_str,)
             if self.config.show_missing:
                 args += ("",)
-            outfile.write(fmt_coverage % args)
+            writeout(fmt_coverage % args)
 
         if not total.n_files and not skipped_count:
             raise CoverageException("No data to report.")
 
         if self.config.skip_covered and skipped_count:
-            outfile.write(fmt_skip_covered % (skipped_count, 's' if skipped_count > 1 else ''))
+            writeout(fmt_skip_covered % (skipped_count, 's' if skipped_count > 1 else ''))
 
         return total.n_statements and total.pc_covered
 
--- a/DebugClients/Python/coverage/templite.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/templite.py	Sun Jul 24 12:01:01 2016 +0200
@@ -90,6 +90,9 @@
 
         {# This will be ignored #}
 
+    Any of these constructs can have a hypen at the end (`-}}`, `-%}`, `-#}`),
+    which will collapse the whitespace following the tag.
+
     Construct a Templite with the template text, then use `render` against a
     dictionary context to create a finished string::
 
@@ -151,53 +154,64 @@
         # Split the text to form a list of tokens.
         tokens = re.split(r"(?s)({{.*?}}|{%.*?%}|{#.*?#})", text)
 
+        squash = False
+
         for token in tokens:
-            if token.startswith('{#'):
-                # Comment: ignore it and move on.
-                continue
-            elif token.startswith('{{'):
-                # An expression to evaluate.
-                expr = self._expr_code(token[2:-2].strip())
-                buffered.append("to_str(%s)" % expr)
-            elif token.startswith('{%'):
-                # Action tag: split into words and parse further.
-                flush_output()
-                words = token[2:-2].strip().split()
-                if words[0] == 'if':
-                    # An if statement: evaluate the expression to determine if.
-                    if len(words) != 2:
-                        self._syntax_error("Don't understand if", token)
-                    ops_stack.append('if')
-                    code.add_line("if %s:" % self._expr_code(words[1]))
-                    code.indent()
-                elif words[0] == 'for':
-                    # A loop: iterate over expression result.
-                    if len(words) != 4 or words[2] != 'in':
-                        self._syntax_error("Don't understand for", token)
-                    ops_stack.append('for')
-                    self._variable(words[1], self.loop_vars)
-                    code.add_line(
-                        "for c_%s in %s:" % (
-                            words[1],
-                            self._expr_code(words[3])
+            if token.startswith('{'):
+                start, end = 2, -2
+                squash = (token[-3] == '-')
+                if squash:
+                    end = -3
+
+                if token.startswith('{#'):
+                    # Comment: ignore it and move on.
+                    continue
+                elif token.startswith('{{'):
+                    # An expression to evaluate.
+                    expr = self._expr_code(token[start:end].strip())
+                    buffered.append("to_str(%s)" % expr)
+                elif token.startswith('{%'):
+                    # Action tag: split into words and parse further.
+                    flush_output()
+
+                    words = token[start:end].strip().split()
+                    if words[0] == 'if':
+                        # An if statement: evaluate the expression to determine if.
+                        if len(words) != 2:
+                            self._syntax_error("Don't understand if", token)
+                        ops_stack.append('if')
+                        code.add_line("if %s:" % self._expr_code(words[1]))
+                        code.indent()
+                    elif words[0] == 'for':
+                        # A loop: iterate over expression result.
+                        if len(words) != 4 or words[2] != 'in':
+                            self._syntax_error("Don't understand for", token)
+                        ops_stack.append('for')
+                        self._variable(words[1], self.loop_vars)
+                        code.add_line(
+                            "for c_%s in %s:" % (
+                                words[1],
+                                self._expr_code(words[3])
+                            )
                         )
-                    )
-                    code.indent()
-                elif words[0].startswith('end'):
-                    # Endsomething.  Pop the ops stack.
-                    if len(words) != 1:
-                        self._syntax_error("Don't understand end", token)
-                    end_what = words[0][3:]
-                    if not ops_stack:
-                        self._syntax_error("Too many ends", token)
-                    start_what = ops_stack.pop()
-                    if start_what != end_what:
-                        self._syntax_error("Mismatched end tag", end_what)
-                    code.dedent()
-                else:
-                    self._syntax_error("Don't understand tag", words[0])
+                        code.indent()
+                    elif words[0].startswith('end'):
+                        # Endsomething.  Pop the ops stack.
+                        if len(words) != 1:
+                            self._syntax_error("Don't understand end", token)
+                        end_what = words[0][3:]
+                        if not ops_stack:
+                            self._syntax_error("Too many ends", token)
+                        start_what = ops_stack.pop()
+                        if start_what != end_what:
+                            self._syntax_error("Mismatched end tag", end_what)
+                        code.dedent()
+                    else:
+                        self._syntax_error("Don't understand tag", words[0])
             else:
                 # Literal content.  If it isn't empty, output it.
+                if squash:
+                    token = token.lstrip()
                 if token:
                     buffered.append(repr(token))
 
--- a/DebugClients/Python/coverage/test_helpers.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/test_helpers.py	Sun Jul 24 12:01:01 2016 +0200
@@ -162,20 +162,20 @@
         # nose keeps stdout from littering the screen, so we can safely Tee it,
         # but it doesn't capture stderr, so we don't want to Tee stderr to the
         # real stderr, since it will interfere with our nice field of dots.
-        self.old_stdout = sys.stdout
+        old_stdout = sys.stdout
         self.captured_stdout = StringIO()
         sys.stdout = Tee(sys.stdout, self.captured_stdout)
 
-        self.old_stderr = sys.stderr
+        old_stderr = sys.stderr
         self.captured_stderr = StringIO()
         sys.stderr = self.captured_stderr
 
-        self.addCleanup(self.cleanup_std_streams)
+        self.addCleanup(self.cleanup_std_streams, old_stdout, old_stderr)
 
-    def cleanup_std_streams(self):
+    def cleanup_std_streams(self, old_stdout, old_stderr):
         """Restore stdout and stderr."""
-        sys.stdout = self.old_stdout
-        sys.stderr = self.old_stderr
+        sys.stdout = old_stdout
+        sys.stderr = old_stderr
 
     def stdout(self):
         """Return the data written to stdout during the test."""
@@ -186,6 +186,59 @@
         return self.captured_stderr.getvalue()
 
 
+class DelayedAssertionMixin(TestCase):
+    """A test case mixin that provides a `delayed_assertions` context manager.
+
+    Use it like this::
+
+        with self.delayed_assertions():
+            self.assertEqual(x, y)
+            self.assertEqual(z, w)
+
+    All of the assertions will run.  The failures will be displayed at the end
+    of the with-statement.
+
+    NOTE: this only works with some assertions.  These are known to work:
+
+        - `assertEqual(str, str)`
+
+        - `assertMultilineEqual(str, str)`
+
+    """
+    def __init__(self, *args, **kwargs):
+        super(DelayedAssertionMixin, self).__init__(*args, **kwargs)
+        # This mixin only works with assert methods that call `self.fail`.  In
+        # Python 2.7, `assertEqual` didn't, but we can do what Python 3 does,
+        # and use `assertMultiLineEqual` for comparing strings.
+        self.addTypeEqualityFunc(str, 'assertMultiLineEqual')
+        self._delayed_assertions = None
+
+    @contextlib.contextmanager
+    def delayed_assertions(self):
+        """The context manager: assert that we didn't collect any assertions."""
+        self._delayed_assertions = []
+        old_fail = self.fail
+        self.fail = self._delayed_fail
+        try:
+            yield
+        finally:
+            self.fail = old_fail
+        if self._delayed_assertions:
+            if len(self._delayed_assertions) == 1:
+                self.fail(self._delayed_assertions[0])
+            else:
+                self.fail(
+                    "{0} failed assertions:\n{1}".format(
+                        len(self._delayed_assertions),
+                        "\n".join(self._delayed_assertions),
+                    )
+                )
+
+    def _delayed_fail(self, msg=None):
+        """The stand-in for TestCase.fail during delayed_assertions."""
+        self._delayed_assertions.append(msg)
+
+
 class TempDirMixin(SysPathAwareMixin, ModuleAwareMixin, TestCase):
     """A test case mixin that creates a temp directory and files in it.
 
@@ -335,3 +388,6 @@
 
 # When the process ends, find out about bad classes.
 atexit.register(TempDirMixin.report_on_class_behavior)
+
+#
+# eflag: FileType = Python2
--- a/DebugClients/Python/coverage/version.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/version.py	Sun Jul 24 12:01:01 2016 +0200
@@ -5,7 +5,7 @@
 # This file is exec'ed in setup.py, don't import anything!
 
 # Same semantics as sys.version_info.
-version_info = (4, 0, 0, 'final', 0)
+version_info = (4, 1, 0, 'final', 0)
 
 
 def _make_version(major, minor, micro, releaselevel, serial):
@@ -22,7 +22,7 @@
 
 def _make_url(major, minor, micro, releaselevel, serial):
     """Make the URL people should start at for this version of coverage.py."""
-    url = "https://coverage.readthedocs.org"
+    url = "https://coverage.readthedocs.io"
     if releaselevel != 'final':
         # For pre-releases, use a version-specific URL.
         url += "/en/coverage-" + _make_version(major, minor, micro, releaselevel, serial)
--- a/DebugClients/Python/coverage/xmlreport.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python/coverage/xmlreport.py	Sun Jul 24 12:01:01 2016 +0200
@@ -4,13 +4,20 @@
 """XML reporting for coverage.py"""
 
 import os
+import os.path
 import sys
 import time
 import xml.dom.minidom
 
+from coverage import env
 from coverage import __url__, __version__, files
+from coverage.backward import iitems
+from coverage.misc import isolate_module
 from coverage.report import Reporter
 
+os = isolate_module(os)
+
+
 DTD_URL = (
     'https://raw.githubusercontent.com/cobertura/web/'
     'f0366e5e2cf18f111cbd61fc34ef720a6584ba02'
@@ -33,6 +40,10 @@
         super(XmlReporter, self).__init__(coverage, config)
 
         self.source_paths = set()
+        if config.source:
+            for src in config.source:
+                if os.path.exists(src):
+                    self.source_paths.add(files.canonical_filename(src))
         self.packages = {}
         self.xml_out = None
         self.has_arcs = coverage.data.has_arcs()
@@ -81,15 +92,14 @@
         xcoverage.appendChild(xpackages)
 
         # Populate the XML DOM with the package info.
-        for pkg_name in sorted(self.packages.keys()):
-            pkg_data = self.packages[pkg_name]
+        for pkg_name, pkg_data in sorted(iitems(self.packages)):
             class_elts, lhits, lnum, bhits, bnum = pkg_data
             xpackage = self.xml_out.createElement("package")
             xpackages.appendChild(xpackage)
             xclasses = self.xml_out.createElement("classes")
             xpackage.appendChild(xclasses)
-            for class_name in sorted(class_elts.keys()):
-                xclasses.appendChild(class_elts[class_name])
+            for _, class_elt in sorted(iitems(class_elts)):
+                xclasses.appendChild(class_elt)
             xpackage.setAttribute("name", pkg_name.replace(os.sep, '.'))
             xpackage.setAttribute("line-rate", rate(lhits, lnum))
             if self.has_arcs:
@@ -112,7 +122,10 @@
         xcoverage.setAttribute("branch-rate", branch_rate)
 
         # Use the DOM to write the output file.
-        outfile.write(self.xml_out.toprettyxml())
+        out = self.xml_out.toprettyxml()
+        if env.PY2:
+            out = out.encode("utf8")
+        outfile.write(out)
 
         # Return the total percentage.
         denom = lnum_tot + bnum_tot
@@ -127,15 +140,20 @@
 
         # Create the 'lines' and 'package' XML elements, which
         # are populated later.  Note that a package == a directory.
-        filename = fr.relative_filename()
-        filename = filename.replace("\\", "/")
-        dirname = os.path.dirname(filename) or "."
-        parts = dirname.split("/")
-        dirname = "/".join(parts[:self.config.xml_package_depth])
+        filename = fr.filename.replace("\\", "/")
+        for source_path in self.source_paths:
+            if filename.startswith(source_path.replace("\\", "/") + "/"):
+                rel_name = filename[len(source_path)+1:]
+                break
+        else:
+            rel_name = fr.relative_filename()
+
+        dirname = os.path.dirname(rel_name) or "."
+        dirname = "/".join(dirname.split("/")[:self.config.xml_package_depth])
         package_name = dirname.replace("/", ".")
-        className = fr.relative_filename()
 
-        self.source_paths.add(files.relative_directory().rstrip('/'))
+        if rel_name != fr.filename:
+            self.source_paths.add(fr.filename[:-len(rel_name)].rstrip(r"\/"))
         package = self.packages.setdefault(package_name, [{}, 0, 0, 0, 0])
 
         xclass = self.xml_out.createElement("class")
@@ -145,8 +163,8 @@
         xlines = self.xml_out.createElement("lines")
         xclass.appendChild(xlines)
 
-        xclass.setAttribute("name", os.path.relpath(filename, dirname))
-        xclass.setAttribute("filename", filename)
+        xclass.setAttribute("name", os.path.relpath(rel_name, dirname))
+        xclass.setAttribute("filename", fr.relative_filename().replace("\\", "/"))
         xclass.setAttribute("complexity", "0")
 
         branch_stats = analysis.branch_stats()
@@ -193,7 +211,7 @@
             branch_rate = "0"
         xclass.setAttribute("branch-rate", branch_rate)
 
-        package[0][className] = xclass
+        package[0][rel_name] = xclass
         package[1] += class_hits
         package[2] += class_lines
         package[3] += class_br_hits
--- a/DebugClients/Python3/coverage/__init__.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python3/coverage/__init__.py	Sun Jul 24 12:01:01 2016 +0200
@@ -14,6 +14,7 @@
 from coverage.data import CoverageData
 from coverage.misc import CoverageException
 from coverage.plugin import CoveragePlugin, FileTracer, FileReporter
+from coverage.pytracer import PyTracer
 
 # Backward compatibility.
 coverage = Coverage
--- a/DebugClients/Python3/coverage/annotate.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python3/coverage/annotate.py	Sun Jul 24 12:01:01 2016 +0200
@@ -8,8 +8,12 @@
 import re
 
 from coverage.files import flat_rootname
+from coverage.misc import isolate_module
 from coverage.report import Reporter
 
+os = isolate_module(os)
+
+
 class AnnotateReporter(Reporter):
     """Generate annotated source files showing line coverage.
 
--- a/DebugClients/Python3/coverage/backward.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python3/coverage/backward.py	Sun Jul 24 12:01:01 2016 +0200
@@ -49,6 +49,15 @@
 except NameError:
     range = range
 
+# shlex.quote is new, but there's an undocumented implementation in "pipes",
+# who knew!?
+try:
+    from shlex import quote as shlex_quote
+except ImportError:
+    # Useful function, available under a different (undocumented) name
+    # in Python versions earlier than 3.3.
+    from pipes import quote as shlex_quote
+
 # A function to iterate listlessly over a dict's items.
 try:
     {}.iteritems
@@ -84,10 +93,6 @@
         """Produce a byte string with the ints from `byte_values`."""
         return bytes(byte_values)
 
-    def byte_to_int(byte_value):
-        """Turn an element of a bytes object into an int."""
-        return byte_value
-
     def bytes_to_ints(bytes_value):
         """Turn a bytes object into a sequence of ints."""
         # In Python 3, iterating bytes gives ints.
@@ -102,10 +107,6 @@
         """Produce a byte string with the ints from `byte_values`."""
         return "".join(chr(b) for b in byte_values)
 
-    def byte_to_int(byte_value):
-        """Turn an element of a bytes object into an int."""
-        return ord(byte_value)
-
     def bytes_to_ints(bytes_value):
         """Turn a bytes object into a sequence of ints."""
         for byte in bytes_value:
@@ -142,11 +143,12 @@
     PYC_MAGIC_NUMBER = imp.get_magic()
 
 
-def import_local_file(modname):
+def import_local_file(modname, modfile=None):
     """Import a local file as a module.
 
     Opens a file in the current directory named `modname`.py, imports it
-    as `modname`, and returns the module object.
+    as `modname`, and returns the module object.  `modfile` is the file to
+    import if it isn't in the current directory.
 
     """
     try:
@@ -154,7 +156,8 @@
     except ImportError:
         SourceFileLoader = None
 
-    modfile = modname + '.py'
+    if modfile is None:
+        modfile = modname + '.py'
     if SourceFileLoader:
         mod = SourceFileLoader(modname, modfile).load_module()
     else:
--- a/DebugClients/Python3/coverage/bytecode.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python3/coverage/bytecode.py	Sun Jul 24 12:01:01 2016 +0200
@@ -3,73 +3,8 @@
 
 """Bytecode manipulation for coverage.py"""
 
-import opcode
 import types
 
-from coverage.backward import byte_to_int
-
-
-class ByteCode(object):
-    """A single bytecode."""
-    def __init__(self):
-        # The offset of this bytecode in the code object.
-        self.offset = -1
-
-        # The opcode, defined in the `opcode` module.
-        self.op = -1
-
-        # The argument, a small integer, whose meaning depends on the opcode.
-        self.arg = -1
-
-        # The offset in the code object of the next bytecode.
-        self.next_offset = -1
-
-        # The offset to jump to.
-        self.jump_to = -1
-
-
-class ByteCodes(object):
-    """Iterator over byte codes in `code`.
-
-    This handles the logic of EXTENDED_ARG byte codes internally.  Those byte
-    codes are not returned by this iterator.
-
-    Returns `ByteCode` objects.
-
-    """
-    def __init__(self, code):
-        self.code = code
-
-    def __getitem__(self, i):
-        return byte_to_int(self.code[i])
-
-    def __iter__(self):
-        offset = 0
-        ext_arg = 0
-        while offset < len(self.code):
-            bc = ByteCode()
-            bc.op = self[offset]
-            bc.offset = offset
-
-            next_offset = offset+1
-            if bc.op >= opcode.HAVE_ARGUMENT:
-                bc.arg = ext_arg + self[offset+1] + 256*self[offset+2]
-                next_offset += 2
-
-                label = -1
-                if bc.op in opcode.hasjrel:
-                    label = next_offset + bc.arg
-                elif bc.op in opcode.hasjabs:
-                    label = bc.arg
-                bc.jump_to = label
-
-            bc.next_offset = offset = next_offset
-            if bc.op == opcode.EXTENDED_ARG:
-                ext_arg = bc.arg * 256*256
-            else:
-                ext_arg = 0
-                yield bc
-
 
 class CodeObjects(object):
     """Iterate over all the code objects in `code`."""
--- a/DebugClients/Python3/coverage/cmdline.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python3/coverage/cmdline.py	Sun Jul 24 12:01:01 2016 +0200
@@ -7,9 +7,11 @@
 import optparse
 import os.path
 import sys
+import textwrap
 import traceback
 
 from coverage import env
+from coverage.collector import CTracer
 from coverage.execfile import run_python_file, run_python_module
 from coverage.misc import CoverageException, ExceptionDuringRun, NoSource
 from coverage.debug import info_formatter, info_header
@@ -20,105 +22,117 @@
 
     append = optparse.make_option(
         '-a', '--append', action='store_true',
-        help="Append coverage data to .coverage, otherwise it is started "
-                "clean with each run."
-        )
+        help="Append coverage data to .coverage, otherwise it is started clean with each run.",
+    )
     branch = optparse.make_option(
         '', '--branch', action='store_true',
-        help="Measure branch coverage in addition to statement coverage."
-        )
+        help="Measure branch coverage in addition to statement coverage.",
+    )
     CONCURRENCY_CHOICES = [
         "thread", "gevent", "greenlet", "eventlet", "multiprocessing",
     ]
     concurrency = optparse.make_option(
         '', '--concurrency', action='store', metavar="LIB",
         choices=CONCURRENCY_CHOICES,
-        help="Properly measure code using a concurrency library. "
-            "Valid values are: %s." % ", ".join(CONCURRENCY_CHOICES)
-        )
+        help=(
+            "Properly measure code using a concurrency library. "
+            "Valid values are: %s."
+        ) % ", ".join(CONCURRENCY_CHOICES),
+    )
     debug = optparse.make_option(
         '', '--debug', action='store', metavar="OPTS",
-        help="Debug options, separated by commas"
-        )
+        help="Debug options, separated by commas",
+    )
     directory = optparse.make_option(
         '-d', '--directory', action='store', metavar="DIR",
-        help="Write the output files to DIR."
-        )
+        help="Write the output files to DIR.",
+    )
     fail_under = optparse.make_option(
         '', '--fail-under', action='store', metavar="MIN", type="int",
-        help="Exit with a status of 2 if the total coverage is less than MIN."
-        )
+        help="Exit with a status of 2 if the total coverage is less than MIN.",
+    )
     help = optparse.make_option(
         '-h', '--help', action='store_true',
-        help="Get help on this command."
-        )
+        help="Get help on this command.",
+    )
     ignore_errors = optparse.make_option(
         '-i', '--ignore-errors', action='store_true',
-        help="Ignore errors while reading source files."
-        )
+        help="Ignore errors while reading source files.",
+    )
     include = optparse.make_option(
         '', '--include', action='store',
         metavar="PAT1,PAT2,...",
-        help="Include only files whose paths match one of these patterns. "
-                "Accepts shell-style wildcards, which must be quoted."
-        )
+        help=(
+            "Include only files whose paths match one of these patterns. "
+            "Accepts shell-style wildcards, which must be quoted."
+        ),
+    )
     pylib = optparse.make_option(
         '-L', '--pylib', action='store_true',
-        help="Measure coverage even inside the Python installed library, "
-                "which isn't done by default."
-        )
+        help=(
+            "Measure coverage even inside the Python installed library, "
+            "which isn't done by default."
+        ),
+    )
     show_missing = optparse.make_option(
         '-m', '--show-missing', action='store_true',
-        help="Show line numbers of statements in each module that weren't "
-                "executed."
-        )
+        help="Show line numbers of statements in each module that weren't executed.",
+    )
     skip_covered = optparse.make_option(
         '--skip-covered', action='store_true',
-        help="Skip files with 100% coverage."
-        )
+        help="Skip files with 100% coverage.",
+    )
     omit = optparse.make_option(
         '', '--omit', action='store',
         metavar="PAT1,PAT2,...",
-        help="Omit files whose paths match one of these patterns. "
-                "Accepts shell-style wildcards, which must be quoted."
-        )
+        help=(
+            "Omit files whose paths match one of these patterns. "
+            "Accepts shell-style wildcards, which must be quoted."
+        ),
+    )
     output_xml = optparse.make_option(
         '-o', '', action='store', dest="outfile",
         metavar="OUTFILE",
-        help="Write the XML report to this file. Defaults to 'coverage.xml'"
-        )
+        help="Write the XML report to this file. Defaults to 'coverage.xml'",
+    )
     parallel_mode = optparse.make_option(
         '-p', '--parallel-mode', action='store_true',
-        help="Append the machine name, process id and random number to the "
-                ".coverage data file name to simplify collecting data from "
-                "many processes."
-        )
+        help=(
+            "Append the machine name, process id and random number to the "
+            ".coverage data file name to simplify collecting data from "
+            "many processes."
+        ),
+    )
     module = optparse.make_option(
         '-m', '--module', action='store_true',
-        help="<pyfile> is an importable Python module, not a script path, "
-                "to be run as 'python -m' would run it."
-        )
+        help=(
+            "<pyfile> is an importable Python module, not a script path, "
+            "to be run as 'python -m' would run it."
+        ),
+    )
     rcfile = optparse.make_option(
         '', '--rcfile', action='store',
-        help="Specify configuration file.  Defaults to '.coveragerc'"
-        )
+        help="Specify configuration file.  Defaults to '.coveragerc'",
+    )
     source = optparse.make_option(
         '', '--source', action='store', metavar="SRC1,SRC2,...",
-        help="A list of packages or directories of code to be measured."
-        )
+        help="A list of packages or directories of code to be measured.",
+    )
     timid = optparse.make_option(
         '', '--timid', action='store_true',
-        help="Use a simpler but slower trace method.  Try this if you get "
-                "seemingly impossible results!"
-        )
+        help=(
+            "Use a simpler but slower trace method.  Try this if you get "
+            "seemingly impossible results!"
+        ),
+    )
     title = optparse.make_option(
         '', '--title', action='store', metavar="TITLE",
-        help="A text string to use as the title on the HTML."
-        )
+        help="A text string to use as the title on the HTML.",
+    )
     version = optparse.make_option(
         '', '--version', action='store_true',
-        help="Display version information and exit."
-        )
+        help="Display version information and exit.",
+    )
 
 
 class CoverageOptionParser(optparse.OptionParser, object):
@@ -202,9 +216,7 @@
 class CmdOptionParser(CoverageOptionParser):
     """Parse one of the new-style commands for coverage.py."""
 
-    def __init__(self, action, options=None, defaults=None, usage=None,
-                description=None
-                ):
+    def __init__(self, action, options=None, defaults=None, usage=None, description=None):
         """Create an OptionParser for a coverage.py command.
 
         `action` is the slug to put into `options.action`.
@@ -217,7 +229,6 @@
         if usage:
             usage = "%prog " + usage
         super(CmdOptionParser, self).__init__(
-            prog="coverage %s" % action,
             usage=usage,
             description=description,
         )
@@ -231,6 +242,14 @@
         # results, and they will compare equal to objects.
         return (other == "<CmdOptionParser:%s>" % self.cmd)
 
+    def get_prog_name(self):
+        """Override of an undocumented function in optparse.OptionParser."""
+        program_name = super(CmdOptionParser, self).get_prog_name()
+
+        # Include the sub-command for this parser as part of the command.
+        return "%(command)s %(subcommand)s" % {'command': program_name, 'subcommand': self.cmd}
+
+
 GLOBAL_ARGS = [
     Opts.debug,
     Opts.help,
@@ -238,48 +257,60 @@
     ]
 
 CMDS = {
-    'annotate': CmdOptionParser("annotate",
+    'annotate': CmdOptionParser(
+        "annotate",
         [
             Opts.directory,
             Opts.ignore_errors,
             Opts.include,
             Opts.omit,
             ] + GLOBAL_ARGS,
-        usage = "[options] [modules]",
-        description = "Make annotated copies of the given files, marking "
-            "statements that are executed with > and statements that are "
-            "missed with !."
+        usage="[options] [modules]",
+        description=(
+            "Make annotated copies of the given files, marking statements that are executed "
+            "with > and statements that are missed with !."
         ),
+    ),
 
-    'combine': CmdOptionParser("combine", GLOBAL_ARGS,
-        usage = "<path1> <path2> ... <pathN>",
-        description = "Combine data from multiple coverage files collected "
+    'combine': CmdOptionParser(
+        "combine",
+        GLOBAL_ARGS,
+        usage="<path1> <path2> ... <pathN>",
+        description=(
+            "Combine data from multiple coverage files collected "
             "with 'run -p'.  The combined results are written to a single "
             "file representing the union of the data. The positional "
             "arguments are data files or directories containing data files. "
             "If no paths are provided, data files in the default data file's "
             "directory are combined."
         ),
+    ),
 
-    'debug': CmdOptionParser("debug", GLOBAL_ARGS,
-        usage = "<topic>",
-        description = "Display information on the internals of coverage.py, "
+    'debug': CmdOptionParser(
+        "debug", GLOBAL_ARGS,
+        usage="<topic>",
+        description=(
+            "Display information on the internals of coverage.py, "
             "for diagnosing problems. "
             "Topics are 'data' to show a summary of the collected data, "
             "or 'sys' to show installation information."
         ),
+    ),
 
-    'erase': CmdOptionParser("erase", GLOBAL_ARGS,
-        usage = " ",
-        description = "Erase previously collected coverage data."
-        ),
+    'erase': CmdOptionParser(
+        "erase", GLOBAL_ARGS,
+        usage=" ",
+        description="Erase previously collected coverage data.",
+    ),
 
-    'help': CmdOptionParser("help", GLOBAL_ARGS,
-        usage = "[command]",
-        description = "Describe how to use coverage.py"
-        ),
+    'help': CmdOptionParser(
+        "help", GLOBAL_ARGS,
+        usage="[command]",
+        description="Describe how to use coverage.py",
+    ),
 
-    'html': CmdOptionParser("html",
+    'html': CmdOptionParser(
+        "html",
         [
             Opts.directory,
             Opts.fail_under,
@@ -288,13 +319,16 @@
             Opts.omit,
             Opts.title,
             ] + GLOBAL_ARGS,
-        usage = "[options] [modules]",
-        description = "Create an HTML report of the coverage of the files.  "
+        usage="[options] [modules]",
+        description=(
+            "Create an HTML report of the coverage of the files.  "
             "Each file gets its own page, with the source decorated to show "
             "executed, excluded, and missed lines."
         ),
+    ),
 
-    'report': CmdOptionParser("report",
+    'report': CmdOptionParser(
+        "report",
         [
             Opts.fail_under,
             Opts.ignore_errors,
@@ -303,11 +337,12 @@
             Opts.show_missing,
             Opts.skip_covered,
             ] + GLOBAL_ARGS,
-        usage = "[options] [modules]",
-        description = "Report coverage statistics on modules."
-        ),
+        usage="[options] [modules]",
+        description="Report coverage statistics on modules."
+    ),
 
-    'run': CmdOptionParser("run",
+    'run': CmdOptionParser(
+        "run",
         [
             Opts.append,
             Opts.branch,
@@ -320,11 +355,12 @@
             Opts.source,
             Opts.timid,
             ] + GLOBAL_ARGS,
-        usage = "[options] <pyfile> [program options]",
-        description = "Run a Python program, measuring code execution."
-        ),
+        usage="[options] <pyfile> [program options]",
+        description="Run a Python program, measuring code execution."
+    ),
 
-    'xml': CmdOptionParser("xml",
+    'xml': CmdOptionParser(
+        "xml",
         [
             Opts.fail_under,
             Opts.ignore_errors,
@@ -332,10 +368,10 @@
             Opts.omit,
             Opts.output_xml,
             ] + GLOBAL_ARGS,
-        usage = "[options] [modules]",
-        description = "Generate an XML report of coverage results."
-        ),
-    }
+        usage="[options] [modules]",
+        description="Generate an XML report of coverage results."
+    ),
+}
 
 
 OK, ERR, FAIL_UNDER = 0, 1, 2
@@ -362,6 +398,17 @@
 
         self.coverage = None
 
+        self.program_name = os.path.basename(sys.argv[0])
+        if env.WINDOWS:
+            # entry_points={'console_scripts':...} on Windows makes files
+            # called coverage.exe, coverage3.exe, and coverage-3.5.exe. These
+            # invoke coverage-script.py, coverage3-script.py, and
+            # coverage-3.5-script.py.  argv[0] is the .py file, but we want to
+            # get back to the original form.
+            auto_suffix = "-script.py"
+            if self.program_name.endswith(auto_suffix):
+                self.program_name = self.program_name[:-len(auto_suffix)]
+
     def command_line(self, argv):
         """The bulk of the command line interface to coverage.py.
 
@@ -412,16 +459,16 @@
 
         # Do something.
         self.coverage = self.covpkg.coverage(
-            data_suffix = options.parallel_mode,
-            cover_pylib = options.pylib,
-            timid = options.timid,
-            branch = options.branch,
-            config_file = options.rcfile,
-            source = source,
-            omit = omit,
-            include = include,
-            debug = debug,
-            concurrency = options.concurrency,
+            data_suffix=options.parallel_mode,
+            cover_pylib=options.pylib,
+            timid=options.timid,
+            branch=options.branch,
+            config_file=options.rcfile,
+            source=source,
+            omit=omit,
+            include=include,
+            debug=debug,
+            concurrency=options.concurrency,
             )
 
         if options.action == "debug":
@@ -443,10 +490,10 @@
 
         # Remaining actions are reporting, with some common options.
         report_args = dict(
-            morfs = unglob_args(args),
-            ignore_errors = options.ignore_errors,
-            omit = omit,
-            include = include,
+            morfs=unglob_args(args),
+            ignore_errors=options.ignore_errors,
+            omit=omit,
+            include=include,
             )
 
         self.coverage.load()
@@ -495,13 +542,19 @@
         assert error or topic or parser
         if error:
             print(error)
-            print("Use 'coverage help' for help.")
+            print("Use '%s help' for help." % (self.program_name,))
         elif parser:
             print(parser.format_help().strip())
         else:
-            help_msg = HELP_TOPICS.get(topic, '').strip()
+            help_params = dict(self.covpkg.__dict__)
+            help_params['program_name'] = self.program_name
+            if CTracer is not None:
+                help_params['extension_modifier'] = 'with C extension'
+            else:
+                help_params['extension_modifier'] = 'without C extension'
+            help_msg = textwrap.dedent(HELP_TOPICS.get(topic, '')).strip()
             if help_msg:
-                print(help_msg % self.covpkg.__dict__)
+                print(help_msg.format(**help_params))
             else:
                 print("Don't know topic %r" % topic)
 
@@ -650,35 +703,34 @@
 
 
 HELP_TOPICS = {
-# -------------------------
-'help': """\
-Coverage.py, version %(__version__)s
-Measure, collect, and report on code coverage in Python programs.
+    'help': """\
+        Coverage.py, version {__version__} {extension_modifier}
+        Measure, collect, and report on code coverage in Python programs.
 
-usage: coverage <command> [options] [args]
+        usage: {program_name} <command> [options] [args]
 
-Commands:
-    annotate    Annotate source files with execution information.
-    combine     Combine a number of data files.
-    erase       Erase previously collected coverage data.
-    help        Get help on using coverage.py.
-    html        Create an HTML report.
-    report      Report coverage stats on modules.
-    run         Run a Python program and measure code execution.
-    xml         Create an XML report of coverage results.
+        Commands:
+            annotate    Annotate source files with execution information.
+            combine     Combine a number of data files.
+            erase       Erase previously collected coverage data.
+            help        Get help on using coverage.py.
+            html        Create an HTML report.
+            report      Report coverage stats on modules.
+            run         Run a Python program and measure code execution.
+            xml         Create an XML report of coverage results.
 
-Use "coverage help <command>" for detailed help on any command.
-For full documentation, see %(__url__)s
-""",
-# -------------------------
-'minimum_help': """\
-Code coverage for Python.  Use 'coverage help' for help.
-""",
-# -------------------------
-'version': """\
-Coverage.py, version %(__version__)s.
-Documentation at %(__url__)s
-""",
+        Use "{program_name} help <command>" for detailed help on any command.
+        For full documentation, see {__url__}
+    """,
+
+    'minimum_help': """\
+        Code coverage for Python.  Use '{program_name} help' for help.
+    """,
+
+    'version': """\
+        Coverage.py, version {__version__} {extension_modifier}
+        Documentation at {__url__}
+    """,
 }
 
 
--- a/DebugClients/Python3/coverage/collector.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python3/coverage/collector.py	Sun Jul 24 12:01:01 2016 +0200
@@ -3,14 +3,18 @@
 
 """Raw data collector for coverage.py."""
 
-import os, sys
+import os
+import sys
 
 from coverage import env
 from coverage.backward import iitems
 from coverage.files import abs_file
-from coverage.misc import CoverageException
+from coverage.misc import CoverageException, isolate_module
 from coverage.pytracer import PyTracer
 
+os = isolate_module(os)
+
+
 try:
     # Use the C extension code when we can, for speed.
     from coverage.tracer import CTracer, CFileDisposition   # pylint: disable=no-name-in-module
@@ -33,6 +37,13 @@
     pass
 
 
+def should_start_context(frame):
+    """Who-Tests-What hack: Determine whether this frame begins a new who-context."""
+    fn_name = frame.f_code.co_name
+    if fn_name.startswith("test"):
+        return fn_name
+
+
 class Collector(object):
     """Collects trace data.
 
@@ -112,6 +123,10 @@
                 "Couldn't trace with concurrency=%s, the module isn't installed." % concurrency
             )
 
+        # Who-Tests-What is just a hack at the moment, so turn it on with an
+        # environment variable.
+        self.wtw = int(os.getenv('COVERAGE_WTW', 0))
+
         self.reset()
 
         if timid:
@@ -143,6 +158,10 @@
         # pairs as keys (if branch coverage).
         self.data = {}
 
+        # A dict mapping contexts to data dictionaries.
+        self.contexts = {}
+        self.contexts[None] = self.data
+
         # A dictionary mapping file names to file tracer plugin names that will
         # handle them.
         self.file_tracers = {}
@@ -202,6 +221,11 @@
             tracer.threading = self.threading
         if hasattr(tracer, 'check_include'):
             tracer.check_include = self.check_include
+        if self.wtw:
+            if hasattr(tracer, 'should_start_context'):
+                tracer.should_start_context = should_start_context
+            if hasattr(tracer, 'switch_context'):
+                tracer.switch_context = self.switch_context
 
         fn = tracer.start()
         self.tracers.append(tracer)
@@ -290,7 +314,7 @@
             if stats:
                 print("\nCoverage.py tracer stats:")
                 for k in sorted(stats.keys()):
-                    print("%16s: %s" % (k, stats[k]))
+                    print("%20s: %s" % (k, stats[k]))
         if self.threading:
             self.threading.settrace(None)
 
@@ -303,6 +327,14 @@
         else:
             self._start_tracer()
 
+    def switch_context(self, new_context):
+        """Who-Tests-What hack: switch to a new who-context."""
+        # Make a new data dict, or find the existing one, and switch all the
+        # tracers to use it.
+        data = self.contexts.setdefault(new_context, {})
+        for tracer in self.tracers:
+            tracer.data = data
+
     def save_data(self, covdata):
         """Save the collected data to a `CoverageData`.
 
@@ -319,4 +351,11 @@
             covdata.add_lines(abs_file_dict(self.data))
         covdata.add_file_tracers(abs_file_dict(self.file_tracers))
 
+        if self.wtw:
+            # Just a hack, so just hack it.
+            import pprint
+            out_file = "coverage_wtw_{:06}.py".format(os.getpid())
+            with open(out_file, "w") as wtw_out:
+                pprint.pprint(self.contexts, wtw_out)
+
         self.reset()
--- a/DebugClients/Python3/coverage/config.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python3/coverage/config.py	Sun Jul 24 12:01:01 2016 +0200
@@ -9,7 +9,9 @@
 import sys
 
 from coverage.backward import configparser, iitems, string_class
-from coverage.misc import CoverageException
+from coverage.misc import CoverageException, isolate_module
+
+os = isolate_module(os)
 
 
 class HandyConfigParser(configparser.RawConfigParser):
--- a/DebugClients/Python3/coverage/control.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python3/coverage/control.py	Sun Jul 24 12:01:01 2016 +0200
@@ -7,6 +7,7 @@
 import inspect
 import os
 import platform
+import re
 import sys
 import traceback
 
@@ -22,7 +23,7 @@
 from coverage.files import ModuleMatcher, abs_file
 from coverage.html import HtmlReporter
 from coverage.misc import CoverageException, bool_or_none, join_regex
-from coverage.misc import file_be_gone
+from coverage.misc import file_be_gone, isolate_module
 from coverage.monkey import patch_multiprocessing
 from coverage.plugin import FileReporter
 from coverage.plugin_support import Plugins
@@ -31,6 +32,7 @@
 from coverage.summary import SummaryReporter
 from coverage.xmlreport import XmlReporter
 
+os = isolate_module(os)
 
 # Pypy has some unusual stuff in the "stdlib".  Consider those locations
 # when deciding where the stdlib is.
@@ -108,8 +110,8 @@
 
         `concurrency` is a string indicating the concurrency library being used
         in the measured code.  Without this, coverage.py will get incorrect
-        results.  Valid strings are "greenlet", "eventlet", "gevent", or
-        "thread" (the default).
+        results.  Valid strings are "greenlet", "eventlet", "gevent",
+        "multiprocessing", or "thread" (the default).
 
         .. versionadded:: 4.0
             The `concurrency` parameter.
@@ -279,7 +281,7 @@
         # data file will be written into the directory where the process
         # started rather than wherever the process eventually chdir'd to.
         self.data = CoverageData(debug=self.debug)
-        self.data_files = CoverageDataFiles(basename=self.config.data_file)
+        self.data_files = CoverageDataFiles(basename=self.config.data_file, warn=self._warn)
 
         # The directories for files considered "installed with the interpreter".
         self.pylib_dirs = set()
@@ -289,7 +291,7 @@
             # environments (virtualenv, for example), these modules may be
             # spread across a few locations. Look at all the candidate modules
             # we've imported, and take all the different ones.
-            for m in (atexit, inspect, os, platform, _structseq, traceback):
+            for m in (atexit, inspect, os, platform, re, _structseq, traceback):
                 if m is not None and hasattr(m, "__file__"):
                     self.pylib_dirs.add(self._canonical_dir(m))
             if _structseq and not hasattr(_structseq, '__file__'):
@@ -475,6 +477,11 @@
             # can't do anything with the data later anyway.
             return nope(disp, "not a real file name")
 
+        # pyexpat does a dumb thing, calling the trace function explicitly from
+        # C code with a C file name.
+        if re.search(r"[/\\]Modules[/\\]pyexpat.c", filename):
+            return nope(disp, "pyexpat lies about itself")
+
         # Jython reports the .class file to the tracer, use the source file.
         if filename.endswith("$py.class"):
             filename = filename[:-9] + ".py"
@@ -798,7 +805,7 @@
         """
         self._init()
         if not self._measured:
-            return
+            return self.data
 
         self.collector.save_data(self.data)
 
@@ -832,15 +839,6 @@
 
                 self.data.touch_file(py_file)
 
-        # Add run information.
-        self.data.add_run_info(
-            brief_sys=" ".join([
-                platform.python_implementation(),
-                platform.python_version(),
-                platform.system(),
-            ])
-        )
-
         if self.config.note:
             self.data.add_run_info(note=self.config.note)
 
@@ -943,9 +941,9 @@
         return file_reporters
 
     def report(
-        self, morfs=None, show_missing=True, ignore_errors=None,
+        self, morfs=None, show_missing=None, ignore_errors=None,
         file=None,                  # pylint: disable=redefined-builtin
-        omit=None, include=None, skip_covered=False,
+        omit=None, include=None, skip_covered=None,
     ):
         """Write a summary report to `file`.
 
@@ -1049,7 +1047,10 @@
                 output_dir = os.path.dirname(self.config.xml_output)
                 if output_dir and not os.path.isdir(output_dir):
                     os.makedirs(output_dir)
-                outfile = open(self.config.xml_output, "w")
+                open_kwargs = {}
+                if env.PY3:
+                    open_kwargs['encoding'] = 'utf8'
+                outfile = open(self.config.xml_output, "w", **open_kwargs)
                 file_to_close = outfile
         try:
             reporter = XmlReporter(self, self.config)
@@ -1165,11 +1166,14 @@
 
         import coverage; coverage.process_startup()
 
+    Returns the :class:`Coverage` instance that was started, or None if it was
+    not started by this call.
+
     """
     cps = os.environ.get("COVERAGE_PROCESS_START")
     if not cps:
         # No request for coverage, nothing to do.
-        return
+        return None
 
     # This function can be called more than once in a process. This happens
     # because some virtualenv configurations make the same directory visible
@@ -1184,10 +1188,12 @@
     if hasattr(process_startup, "done"):
         # We've annotated this function before, so we must have already
         # started coverage.py in this process.  Nothing to do.
-        return
+        return None
 
     process_startup.done = True
     cov = Coverage(config_file=cps, auto_data=True)
     cov.start()
     cov._warn_no_data = False
     cov._warn_unimported_source = False
+
+    return cov
--- a/DebugClients/Python3/coverage/data.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python3/coverage/data.py	Sun Jul 24 12:01:01 2016 +0200
@@ -4,6 +4,7 @@
 """Coverage data for coverage.py."""
 
 import glob
+import itertools
 import json
 import optparse
 import os
@@ -16,7 +17,9 @@
 from coverage.backward import iitems, string_class
 from coverage.debug import _TEST_NAME_FILE
 from coverage.files import PathAliases
-from coverage.misc import CoverageException, file_be_gone
+from coverage.misc import CoverageException, file_be_gone, isolate_module
+
+os = isolate_module(os)
 
 
 class CoverageData(object):
@@ -176,11 +179,12 @@
 
         """
         if self._arcs is not None:
-            if filename in self._arcs:
-                return [s for s, __ in self._arcs[filename] if s > 0]
+            arcs = self._arcs.get(filename)
+            if arcs is not None:
+                all_lines = itertools.chain.from_iterable(arcs)
+                return list(set(l for l in all_lines if l > 0))
         elif self._lines is not None:
-            if filename in self._lines:
-                return self._lines[filename]
+            return self._lines.get(filename)
         return None
 
     def arcs(self, filename):
@@ -574,7 +578,7 @@
     def add_to_hash(self, filename, hasher):
         """Contribute `filename`'s data to the `hasher`.
 
-        `hasher` is a :class:`coverage.misc.Hasher` instance to be updated with
+        `hasher` is a `coverage.misc.Hasher` instance to be updated with
         the file's data.  It should only get the results data, not the run
         data.
 
@@ -601,12 +605,15 @@
 class CoverageDataFiles(object):
     """Manage the use of coverage data files."""
 
-    def __init__(self, basename=None):
+    def __init__(self, basename=None, warn=None):
         """Create a CoverageDataFiles to manage data files.
 
+        `warn` is the warning function to use.
+
         `basename` is the name of the file to use for storing data.
 
         """
+        self.warn = warn
         # Construct the file name that will be used for data storage.
         self.filename = os.path.abspath(basename or ".coverage")
 
@@ -675,7 +682,9 @@
         If `data_paths` is not provided, then the directory portion of
         `self.filename` is used as the directory to search for data files.
 
-        Every data file found and combined is then deleted from disk.
+        Every data file found and combined is then deleted from disk. If a file
+        cannot be read, a warning will be issued, and the file will not be
+        deleted.
 
         """
         # Because of the os.path.abspath in the constructor, data_dir will
@@ -696,9 +705,16 @@
 
         for f in files_to_combine:
             new_data = CoverageData()
-            new_data.read_file(f)
-            data.update(new_data, aliases=aliases)
-            file_be_gone(f)
+            try:
+                new_data.read_file(f)
+            except CoverageException as exc:
+                if self.warn:
+                    # The CoverageException has the file name in it, so just
+                    # use the message as the warning.
+                    self.warn(str(exc))
+            else:
+                data.update(new_data, aliases=aliases)
+                file_be_gone(f)
 
 
 def canonicalize_json_data(data):
--- a/DebugClients/Python3/coverage/debug.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python3/coverage/debug.py	Sun Jul 24 12:01:01 2016 +0200
@@ -7,6 +7,10 @@
 import os
 import sys
 
+from coverage.misc import isolate_module
+
+os = isolate_module(os)
+
 
 # When debugging, it can be helpful to force some options, especially when
 # debugging the configuration mechanisms you usually use to control debugging!
@@ -38,7 +42,7 @@
             msg = "pid %5d: %s" % (os.getpid(), msg)
         self.output.write(msg+"\n")
         if self.should('callers'):
-            dump_stack_frames(self.output)
+            dump_stack_frames(out=self.output)
         self.output.flush()
 
     def write_formatted_info(self, header, info):
@@ -76,7 +80,7 @@
             yield "%*s: %s" % (label_len, label, data)
 
 
-def short_stack():                                          # pragma: debugging
+def short_stack(limit=None):                                # pragma: debugging
     """Return a string summarizing the call stack.
 
     The string is multi-line, with one line per stack frame. Each line shows
@@ -88,13 +92,15 @@
         import_local_file : /Users/ned/coverage/trunk/coverage/backward.py @159
         ...
 
+    `limit` is the number of frames to include, defaulting to all of them.
+
     """
-    stack = inspect.stack()[:0:-1]
+    stack = inspect.stack()[limit:0:-1]
     return "\n".join("%30s : %s @%d" % (t[3], t[1], t[2]) for t in stack)
 
 
-def dump_stack_frames(out=None):                            # pragma: debugging
+def dump_stack_frames(limit=None, out=None):                # pragma: debugging
     """Print a summary of the stack to stdout, or some place else."""
     out = out or sys.stdout
-    out.write(short_stack())
+    out.write(short_stack(limit=limit))
     out.write("\n")
--- a/DebugClients/Python3/coverage/doc/AUTHORS.txt	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python3/coverage/doc/AUTHORS.txt	Sun Jul 24 12:01:01 2016 +0200
@@ -7,6 +7,7 @@
 Alex Gaynor
 Alexander Todorov
 Anthony Sottile
+Arcadiy Ivanov
 Ben Finney
 Bill Hart
 Brandon Rhodes
@@ -26,6 +27,7 @@
 David Stanek
 Detlev Offenbach
 Devin Jeanpierre
+Dmitry Shishov
 Dmitry Trofimov
 Eduardo Schettino
 Edward Loper
@@ -34,6 +36,7 @@
 George Song
 Greg Rogers
 Guillaume Chazarain
+Ilia Meerovich
 Imri Goldberg
 Ionel Cristian Mărieș
 JT Olds
@@ -49,11 +52,13 @@
 Mark van der Wal
 Martin Fuzzey
 Matthew Desmarais
+Max Linke
 Mickie Betz
 Noel O'Boyle
 Pablo Carballo
 Patrick Mezard
 Peter Portante
+Rodrigue Cloutier
 Roger Hu
 Ross Lawley
 Sandra Martocchia
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DebugClients/Python3/coverage/doc/CHANGES.rst	Sun Jul 24 12:01:01 2016 +0200
@@ -0,0 +1,1654 @@
+.. Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
+.. For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
+
+==============================
+Change history for Coverage.py
+==============================
+
+
+Version 4.1 --- 2016-05-21
+--------------------------
+
+- The internal attribute `Reporter.file_reporters` was removed in 4.1b3.  It
+  should have come has no surprise that there were third-party tools out there
+  using that attribute.  It has been restored, but with a deprecation warning.
+
+
+Version 4.1b3 --- 2016-05-10
+----------------------------
+
+- When running your program, execution can jump from an ``except X:`` line to
+  some other line when an exception other than ``X`` happens.  This jump is no
+  longer considered a branch when measuring branch coverage.
+
+- When measuring branch coverage, ``yield`` statements that were never resumed
+  were incorrectly marked as missing, as reported in `issue 440`_.  This is now
+  fixed.
+
+- During branch coverage of single-line callables like lambdas and generator
+  expressions, coverage.py can now distinguish between them never being called,
+  or being called but not completed.  Fixes `issue 90`_, `issue 460`_ and
+  `issue 475`_.
+
+- The HTML report now has a map of the file along the rightmost edge of the
+  page, giving an overview of where the missed lines are.  Thanks, Dmitry
+  Shishov.
+
+- The HTML report now uses different monospaced fonts, favoring Consolas over
+  Courier.  Along the way, `issue 472`_ about not properly handling one-space
+  indents was fixed.  The index page also has slightly different styling, to
+  try to make the clickable detail pages more apparent.
+
+- Missing branches reported with ``coverage report -m`` will now say ``->exit``
+  for missed branches to the exit of a function, rather than a negative number.
+  Fixes `issue 469`_.
+
+- ``coverage --help`` and ``coverage --version`` now mention which tracer is
+  installed, to help diagnose problems. The docs mention which features need
+  the C extension. (`issue 479`_)
+
+- Officially support PyPy 5.1, which required no changes, just updates to the
+  docs.
+
+- The `Coverage.report` function had two parameters with non-None defaults,
+  which have been changed.  `show_missing` used to default to True, but now
+  defaults to None.  If you had been calling `Coverage.report` without
+  specifying `show_missing`, you'll need to explicitly set it to True to keep
+  the same behavior.  `skip_covered` used to default to False. It is now None,
+  which doesn't change the behavior.  This fixes `issue 485`_.
+
+- It's never been possible to pass a namespace module to one of the analysis
+  functions, but now at least we raise a more specific error message, rather
+  than getting confused. (`issue 456`_)
+
+- The `coverage.process_startup` function now returns the `Coverage` instance
+  it creates, as suggested in `issue 481`_.
+
+- Make a small tweak to how we compare threads, to avoid buggy custom
+  comparison code in thread classes. (`issue 245`_)
+
+.. _issue 90: https://bitbucket.org/ned/coveragepy/issues/90/lambda-expression-confuses-branch
+.. _issue 245: https://bitbucket.org/ned/coveragepy/issues/245/change-solution-for-issue-164
+.. _issue 440: https://bitbucket.org/ned/coveragepy/issues/440/yielded-twisted-failure-marked-as-missed
+.. _issue 456: https://bitbucket.org/ned/coveragepy/issues/456/coverage-breaks-with-implicit-namespaces
+.. _issue 460: https://bitbucket.org/ned/coveragepy/issues/460/confusing-html-report-for-certain-partial
+.. _issue 469: https://bitbucket.org/ned/coveragepy/issues/469/strange-1-line-number-in-branch-coverage
+.. _issue 472: https://bitbucket.org/ned/coveragepy/issues/472/html-report-indents-incorrectly-for-one
+.. _issue 475: https://bitbucket.org/ned/coveragepy/issues/475/generator-expression-is-marked-as-not
+.. _issue 479: https://bitbucket.org/ned/coveragepy/issues/479/clarify-the-need-for-the-c-extension
+.. _issue 481: https://bitbucket.org/ned/coveragepy/issues/481/asyncioprocesspoolexecutor-tracing-not
+.. _issue 485: https://bitbucket.org/ned/coveragepy/issues/485/coveragereport-ignores-show_missing-and
+
+
+Version 4.1b2 --- 2016-01-23
+----------------------------
+
+- Problems with the new branch measurement in 4.1 beta 1 were fixed:
+
+  - Class docstrings were considered executable.  Now they no longer are.
+
+  - ``yield from`` and ``await`` were considered returns from functions, since
+    they could tranfer control to the caller.  This produced unhelpful "missing
+    branch" reports in a number of circumstances.  Now they no longer are
+    considered returns.
+
+  - In unusual situations, a missing branch to a negative number was reported.
+    This has been fixed, closing `issue 466`_.
+
+- The XML report now produces correct package names for modules found in
+  directories specified with ``source=``.  Fixes `issue 465`_.
+
+- ``coverage report`` won't produce trailing whitespace.
+
+.. _issue 465: https://bitbucket.org/ned/coveragepy/issues/465/coveragexml-produces-package-names-with-an
+.. _issue 466: https://bitbucket.org/ned/coveragepy/issues/466/impossible-missed-branch-to-a-negative
+
+
+Version 4.1b1 --- 2016-01-10
+----------------------------
+
+- Branch analysis has been rewritten: it used to be based on bytecode, but now
+  uses AST analysis.  This has changed a number of things:
+
+  - More code paths are now considered runnable, especially in
+    ``try``/``except`` structures.  This may mean that coverage.py will
+    identify more code paths as uncovered.  This could either raise or lower
+    your overall coverage number.
+
+  - Python 3.5's ``async`` and ``await`` keywords are properly supported,
+    fixing `issue 434`_.
+
+  - Some long-standing branch coverage bugs were fixed:
+
+    - `issue 129`_: functions with only a docstring for a body would
+      incorrectly report a missing branch on the ``def`` line.
+
+    - `issue 212`_: code in an ``except`` block could be incorrectly marked as
+      a missing branch.
+
+    - `issue 146`_: context managers (``with`` statements) in a loop or ``try``
+      block could confuse the branch measurement, reporting incorrect partial
+      branches.
+
+    - `issue 422`_: in Python 3.5, an actual partial branch could be marked as
+      complete.
+
+- Pragmas to disable coverage measurement can now be used on decorator lines,
+  and they will apply to the entire function or class being decorated.  This
+  implements the feature requested in `issue 131`_.
+
+- Multiprocessing support is now available on Windows.  Thanks, Rodrigue
+  Cloutier.
+
+- Files with two encoding declarations are properly supported, fixing
+  `issue 453`_. Thanks, Max Linke.
+
+- Non-ascii characters in regexes in the configuration file worked in 3.7, but
+  stopped working in 4.0.  Now they work again, closing `issue 455`_.
+
+- Form-feed characters would prevent accurate determination of the beginning of
+  statements in the rest of the file.  This is now fixed, closing `issue 461`_.
+
+.. _issue 129: https://bitbucket.org/ned/coveragepy/issues/129/misleading-branch-coverage-of-empty
+.. _issue 131: https://bitbucket.org/ned/coveragepy/issues/131/pragma-on-a-decorator-line-should-affect
+.. _issue 146: https://bitbucket.org/ned/coveragepy/issues/146/context-managers-confuse-branch-coverage
+.. _issue 212: https://bitbucket.org/ned/coveragepy/issues/212/coverage-erroneously-reports-partial
+.. _issue 422: https://bitbucket.org/ned/coveragepy/issues/422/python35-partial-branch-marked-as-fully
+.. _issue 434: https://bitbucket.org/ned/coveragepy/issues/434/indexerror-in-python-35
+.. _issue 453: https://bitbucket.org/ned/coveragepy/issues/453/source-code-encoding-can-only-be-specified
+.. _issue 455: https://bitbucket.org/ned/coveragepy/issues/455/unusual-exclusions-stopped-working-in
+.. _issue 461: https://bitbucket.org/ned/coveragepy/issues/461/multiline-asserts-need-too-many-pragma
+
+
+Version 4.0.3 --- 2015-11-24
+----------------------------
+
+- Fixed a mysterious problem that manifested in different ways: sometimes
+  hanging the process (`issue 420`_), sometimes making database connections
+  fail (`issue 445`_).
+
+- The XML report now has correct ``<source>`` elements when using a
+  ``--source=`` option somewhere besides the current directory.  This fixes
+  `issue 439`_. Thanks, Arcady Ivanov.
+
+- Fixed an unusual edge case of detecting source encodings, described in
+  `issue 443`_.
+
+- Help messages that mention the command to use now properly use the actual
+  command name, which might be different than "coverage".  Thanks to Ben
+  Finney, this closes `issue 438`_.
+
+.. _issue 420: https://bitbucket.org/ned/coveragepy/issues/420/coverage-40-hangs-indefinitely-on-python27
+.. _issue 438: https://bitbucket.org/ned/coveragepy/issues/438/parameterise-coverage-command-name
+.. _issue 439: https://bitbucket.org/ned/coveragepy/issues/439/incorrect-cobertura-file-sources-generated
+.. _issue 443: https://bitbucket.org/ned/coveragepy/issues/443/coverage-gets-confused-when-encoding
+.. _issue 445: https://bitbucket.org/ned/coveragepy/issues/445/django-app-cannot-connect-to-cassandra
+
+
+Version 4.0.2 --- 2015-11-04
+----------------------------
+
+- More work on supporting unusually encoded source. Fixed `issue 431`_.
+
+- Files or directories with non-ASCII characters are now handled properly,
+  fixing `issue 432`_.
+
+- Setting a trace function with sys.settrace was broken by a change in 4.0.1,
+  as reported in `issue 436`_.  This is now fixed.
+
+- Officially support PyPy 4.0, which required no changes, just updates to the
+  docs.
+
+.. _issue 431: https://bitbucket.org/ned/coveragepy/issues/431/couldnt-parse-python-file-with-cp1252
+.. _issue 432: https://bitbucket.org/ned/coveragepy/issues/432/path-with-unicode-characters-various
+.. _issue 436: https://bitbucket.org/ned/coveragepy/issues/436/disabled-coverage-ctracer-may-rise-from
+
+
+Version 4.0.1 --- 2015-10-13
+----------------------------
+
+- When combining data files, unreadable files will now generate a warning
+  instead of failing the command.  This is more in line with the older
+  coverage.py v3.7.1 behavior, which silently ignored unreadable files.
+  Prompted by `issue 418`_.
+
+- The --skip-covered option would skip reporting on 100% covered files, but
+  also skipped them when calculating total coverage.  This was wrong, it should
+  only remove lines from the report, not change the final answer.  This is now
+  fixed, closing `issue 423`_.
+
+- In 4.0, the data file recorded a summary of the system on which it was run.
+  Combined data files would keep all of those summaries.  This could lead to
+  enormous data files consisting of mostly repetitive useless information. That
+  summary is now gone, fixing `issue 415`_.  If you want summary information,
+  get in touch, and we'll figure out a better way to do it.
+
+- Test suites that mocked os.path.exists would experience strange failures, due
+  to coverage.py using their mock inadvertently.  This is now fixed, closing
+  `issue 416`_.
+
+- Importing a ``__init__`` module explicitly would lead to an error:
+  ``AttributeError: 'module' object has no attribute '__path__'``, as reported
+  in `issue 410`_.  This is now fixed.
+
+- Code that uses ``sys.settrace(sys.gettrace())`` used to incur a more than 2x
+  speed penalty.  Now there's no penalty at all. Fixes `issue 397`_.
+
+- Pyexpat C code will no longer be recorded as a source file, fixing
+  `issue 419`_.
+
+- The source kit now contains all of the files needed to have a complete source
+  tree, re-fixing `issue 137`_ and closing `issue 281`_.
+
+.. _issue 281: https://bitbucket.org/ned/coveragepy/issues/281/supply-scripts-for-testing-in-the
+.. _issue 397: https://bitbucket.org/ned/coveragepy/issues/397/stopping-and-resuming-coverage-with
+.. _issue 410: https://bitbucket.org/ned/coveragepy/issues/410/attributeerror-module-object-has-no
+.. _issue 415: https://bitbucket.org/ned/coveragepy/issues/415/repeated-coveragedataupdates-cause
+.. _issue 416: https://bitbucket.org/ned/coveragepy/issues/416/mocking-ospathexists-causes-failures
+.. _issue 418: https://bitbucket.org/ned/coveragepy/issues/418/json-parse-error
+.. _issue 419: https://bitbucket.org/ned/coveragepy/issues/419/nosource-no-source-for-code-path-to-c
+.. _issue 423: https://bitbucket.org/ned/coveragepy/issues/423/skip_covered-changes-reported-total
+
+
+Version 4.0 --- 2015-09-20
+--------------------------
+
+No changes from 4.0b3
+
+
+Version 4.0b3 --- 2015-09-07
+----------------------------
+
+- Reporting on an unmeasured file would fail with a traceback.  This is now
+  fixed, closing `issue 403`_.
+
+- The Jenkins ShiningPanda plugin looks for an obsolete file name to find the
+  HTML reports to publish, so it was failing under coverage.py 4.0.  Now we
+  create that file if we are running under Jenkins, to keep things working
+  smoothly. `issue 404`_.
+
+- Kits used to include tests and docs, but didn't install them anywhere, or
+  provide all of the supporting tools to make them useful.  Kits no longer
+  include tests and docs.  If you were using them from the older packages, get
+  in touch and help me understand how.
+
+.. _issue 403: https://bitbucket.org/ned/coveragepy/issues/403/hasherupdate-fails-with-typeerror-nonetype
+.. _issue 404: https://bitbucket.org/ned/coveragepy/issues/404/shiningpanda-jenkins-plugin-cant-find-html
+
+
+
+Version 4.0b2 --- 2015-08-22
+----------------------------
+
+- 4.0b1 broke ``--append`` creating new data files.  This is now fixed, closing
+  `issue 392`_.
+
+- ``py.test --cov`` can write empty data, then touch files due to ``--source``,
+  which made coverage.py mistakenly force the data file to record lines instead
+  of arcs.  This would lead to a "Can't combine line data with arc data" error
+  message.  This is now fixed, and changed some method names in the
+  CoverageData interface.  Fixes `issue 399`_.
+
+- `CoverageData.read_fileobj` and `CoverageData.write_fileobj` replace the
+  `.read` and `.write` methods, and are now properly inverses of each other.
+
+- When using ``report --skip-covered``, a message will now be included in the
+  report output indicating how many files were skipped, and if all files are
+  skipped, coverage.py won't accidentally scold you for having no data to
+  report.  Thanks, Krystian Kichewko.
+
+- A new conversion utility has been added:  ``python -m coverage.pickle2json``
+  will convert v3.x pickle data files to v4.x JSON data files.  Thanks,
+  Alexander Todorov.  Closes `issue 395`_.
+
+- A new version identifier is available, `coverage.version_info`, a plain tuple
+  of values similar to `sys.version_info`_.
+
+.. _issue 392: https://bitbucket.org/ned/coveragepy/issues/392/run-append-doesnt-create-coverage-file
+.. _issue 395: https://bitbucket.org/ned/coveragepy/issues/395/rfe-read-pickled-files-as-well-for
+.. _issue 399: https://bitbucket.org/ned/coveragepy/issues/399/coverageexception-cant-combine-line-data
+.. _sys.version_info: https://docs.python.org/3/library/sys.html#sys.version_info
+
+
+Version 4.0b1 --- 2015-08-02
+----------------------------
+
+- Coverage.py is now licensed under the Apache 2.0 license.  See NOTICE.txt for
+  details.  Closes `issue 313`_.
+
+- The data storage has been completely revamped.  The data file is now
+  JSON-based instead of a pickle, closing `issue 236`_.  The `CoverageData`
+  class is now a public supported documented API to the data file.
+
+- A new configuration option, ``[run] note``, lets you set a note that will be
+  stored in the `runs` section of the data file.  You can use this to annotate
+  the data file with any information you like.
+
+- Unrecognized configuration options will now print an error message and stop
+  coverage.py.  This should help prevent configuration mistakes from passing
+  silently.  Finishes `issue 386`_.
+
+- In parallel mode, ``coverage erase`` will now delete all of the data files,
+  fixing `issue 262`_.
+
+- Coverage.py now accepts a directory name for ``coverage run`` and will run a
+  ``__main__.py`` found there, just like Python will.  Fixes `issue 252`_.
+  Thanks, Dmitry Trofimov.
+
+- The XML report now includes a ``missing-branches`` attribute.  Thanks, Steve
+  Peak.  This is not a part of the Cobertura DTD, so the XML report no longer
+  references the DTD.
+
+- Missing branches in the HTML report now have a bit more information in the
+  right-hand annotations.  Hopefully this will make their meaning clearer.
+
+- All the reporting functions now behave the same if no data had been
+  collected, exiting with a status code of 1.  Fixed ``fail_under`` to be
+  applied even when the report is empty.  Thanks, Ionel Cristian Mărieș.
+
+- Plugins are now initialized differently.  Instead of looking for a class
+  called ``Plugin``, coverage.py looks for a function called ``coverage_init``.
+
+- A file-tracing plugin can now ask to have built-in Python reporting by
+  returning `"python"` from its `file_reporter()` method.
+
+- Code that was executed with `exec` would be mis-attributed to the file that
+  called it.  This is now fixed, closing `issue 380`_.
+
+- The ability to use item access on `Coverage.config` (introduced in 4.0a2) has
+  been changed to a more explicit `Coverage.get_option` and
+  `Coverage.set_option` API.
+
+- The ``Coverage.use_cache`` method is no longer supported.
+
+- The private method ``Coverage._harvest_data`` is now called
+  ``Coverage.get_data``, and returns the ``CoverageData`` containing the
+  collected data.
+
+- The project is consistently referred to as "coverage.py" throughout the code
+  and the documentation, closing `issue 275`_.
+
+- Combining data files with an explicit configuration file was broken in 4.0a6,
+  but now works again, closing `issue 385`_.
+
+- ``coverage combine`` now accepts files as well as directories.
+
+- The speed is back to 3.7.1 levels, after having slowed down due to plugin
+  support, finishing up `issue 387`_.
+
+.. _issue 236: https://bitbucket.org/ned/coveragepy/issues/236/pickles-are-bad-and-you-should-feel-bad
+.. _issue 252: https://bitbucket.org/ned/coveragepy/issues/252/coverage-wont-run-a-program-with
+.. _issue 262: https://bitbucket.org/ned/coveragepy/issues/262/when-parallel-true-erase-should-erase-all
+.. _issue 275: https://bitbucket.org/ned/coveragepy/issues/275/refer-consistently-to-project-as-coverage
+.. _issue 313: https://bitbucket.org/ned/coveragepy/issues/313/add-license-file-containing-2-3-or-4
+.. _issue 380: https://bitbucket.org/ned/coveragepy/issues/380/code-executed-by-exec-excluded-from
+.. _issue 385: https://bitbucket.org/ned/coveragepy/issues/385/coverage-combine-doesnt-work-with-rcfile
+.. _issue 386: https://bitbucket.org/ned/coveragepy/issues/386/error-on-unrecognised-configuration
+.. _issue 387: https://bitbucket.org/ned/coveragepy/issues/387/performance-degradation-from-371-to-40
+
+.. 40 issues closed in 4.0 below here
+
+
+Version 4.0a6 --- 2015-06-21
+----------------------------
+
+- Python 3.5b2 and PyPy 2.6.0 are supported.
+
+- The original module-level function interface to coverage.py is no longer
+  supported.  You must now create a ``coverage.Coverage`` object, and use
+  methods on it.
+
+- The ``coverage combine`` command now accepts any number of directories as
+  arguments, and will combine all the data files from those directories.  This
+  means you don't have to copy the files to one directory before combining.
+  Thanks, Christine Lytwynec.  Finishes `issue 354`_.
+
+- Branch coverage couldn't properly handle certain extremely long files. This
+  is now fixed (`issue 359`_).
+
+- Branch coverage didn't understand yield statements properly.  Mickie Betz
+  persisted in pursuing this despite Ned's pessimism.  Fixes `issue 308`_ and
+  `issue 324`_.
+
+- The COVERAGE_DEBUG environment variable can be used to set the ``[run] debug``
+  configuration option to control what internal operations are logged.
+
+- HTML reports were truncated at formfeed characters.  This is now fixed
+  (`issue 360`_).  It's always fun when the problem is due to a `bug in the
+  Python standard library <http://bugs.python.org/issue19035>`_.
+
+- Files with incorrect encoding declaration comments are no longer ignored by
+  the reporting commands, fixing `issue 351`_.
+
+- HTML reports now include a timestamp in the footer, closing `issue 299`_.
+  Thanks, Conrad Ho.
+
+- HTML reports now begrudgingly use double-quotes rather than single quotes,
+  because there are "software engineers" out there writing tools that read HTML
+  and somehow have no idea that single quotes exist.  Capitulates to the absurd
+  `issue 361`_.  Thanks, Jon Chappell.
+
+- The ``coverage annotate`` command now handles non-ASCII characters properly,
+  closing `issue 363`_.  Thanks, Leonardo Pistone.
+
+- Drive letters on Windows were not normalized correctly, now they are. Thanks,
+  Ionel Cristian Mărieș.
+
+- Plugin support had some bugs fixed, closing `issue 374`_ and `issue 375`_.
+  Thanks, Stefan Behnel.
+
+.. _issue 299: https://bitbucket.org/ned/coveragepy/issue/299/inserted-created-on-yyyy-mm-dd-hh-mm-in
+.. _issue 308: https://bitbucket.org/ned/coveragepy/issue/308/yield-lambda-branch-coverage
+.. _issue 324: https://bitbucket.org/ned/coveragepy/issue/324/yield-in-loop-confuses-branch-coverage
+.. _issue 351: https://bitbucket.org/ned/coveragepy/issue/351/files-with-incorrect-encoding-are-ignored
+.. _issue 354: https://bitbucket.org/ned/coveragepy/issue/354/coverage-combine-should-take-a-list-of
+.. _issue 359: https://bitbucket.org/ned/coveragepy/issue/359/xml-report-chunk-error
+.. _issue 360: https://bitbucket.org/ned/coveragepy/issue/360/html-reports-get-confused-by-l-in-the-code
+.. _issue 361: https://bitbucket.org/ned/coveragepy/issue/361/use-double-quotes-in-html-output-to
+.. _issue 363: https://bitbucket.org/ned/coveragepy/issue/363/annotate-command-hits-unicode-happy-fun
+.. _issue 374: https://bitbucket.org/ned/coveragepy/issue/374/c-tracer-lookups-fail-in
+.. _issue 375: https://bitbucket.org/ned/coveragepy/issue/375/ctracer_handle_return-reads-byte-code
+
+
+Version 4.0a5 --- 2015-02-16
+----------------------------
+
+- Plugin support is now implemented in the C tracer instead of the Python
+  tracer. This greatly improves the speed of tracing projects using plugins.
+
+- Coverage.py now always adds the current directory to sys.path, so that
+  plugins can import files in the current directory (`issue 358`_).
+
+- If the `config_file` argument to the Coverage constructor is specified as
+  ".coveragerc", it is treated as if it were True.  This means setup.cfg is
+  also examined, and a missing file is not considered an error (`issue 357`_).
+
+- Wildly experimental: support for measuring processes started by the
+  multiprocessing module.  To use, set ``--concurrency=multiprocessing``,
+  either on the command line or in the .coveragerc file (`issue 117`_). Thanks,
+  Eduardo Schettino.  Currently, this does not work on Windows.
+
+- A new warning is possible, if a desired file isn't measured because it was
+  imported before coverage.py was started (`issue 353`_).
+
+- The `coverage.process_startup` function now will start coverage measurement
+  only once, no matter how many times it is called.  This fixes problems due
+  to unusual virtualenv configurations (`issue 340`_).
+
+- Added 3.5.0a1 to the list of supported CPython versions.
+
+.. _issue 117: https://bitbucket.org/ned/coveragepy/issue/117/enable-coverage-measurement-of-code-run-by
+.. _issue 340: https://bitbucket.org/ned/coveragepy/issue/340/keyerror-subpy
+.. _issue 353: https://bitbucket.org/ned/coveragepy/issue/353/40a3-introduces-an-unexpected-third-case
+.. _issue 357: https://bitbucket.org/ned/coveragepy/issue/357/behavior-changed-when-coveragerc-is
+.. _issue 358: https://bitbucket.org/ned/coveragepy/issue/358/all-coverage-commands-should-adjust
+
+
+Version 4.0a4 --- 2015-01-25
+----------------------------
+
+- Plugins can now provide sys_info for debugging output.
+
+- Started plugins documentation.
+
+- Prepared to move the docs to readthedocs.org.
+
+
+Version 4.0a3 --- 2015-01-20
+----------------------------
+
+- Reports now use file names with extensions.  Previously, a report would
+  describe a/b/c.py as "a/b/c".  Now it is shown as "a/b/c.py".  This allows
+  for better support of non-Python files, and also fixed `issue 69`_.
+
+- The XML report now reports each directory as a package again.  This was a bad
+  regression, I apologize.  This was reported in `issue 235`_, which is now
+  fixed.
+
+- A new configuration option for the XML report: ``[xml] package_depth``
+  controls which directories are identified as packages in the report.
+  Directories deeper than this depth are not reported as packages.
+  The default is that all directories are reported as packages.
+  Thanks, Lex Berezhny.
+
+- When looking for the source for a frame, check if the file exists. On
+  Windows, .pyw files are no longer recorded as .py files. Along the way, this
+  fixed `issue 290`_.
+
+- Empty files are now reported as 100% covered in the XML report, not 0%
+  covered (`issue 345`_).
+
+- Regexes in the configuration file are now compiled as soon as they are read,
+  to provide error messages earlier (`issue 349`_).
+
+.. _issue 69: https://bitbucket.org/ned/coveragepy/issue/69/coverage-html-overwrite-files-that-doesnt
+.. _issue 235: https://bitbucket.org/ned/coveragepy/issue/235/package-name-is-missing-in-xml-report
+.. _issue 290: https://bitbucket.org/ned/coveragepy/issue/290/running-programmatically-with-pyw-files
+.. _issue 345: https://bitbucket.org/ned/coveragepy/issue/345/xml-reports-line-rate-0-for-empty-files
+.. _issue 349: https://bitbucket.org/ned/coveragepy/issue/349/bad-regex-in-config-should-get-an-earlier
+
+
+Version 4.0a2 --- 2015-01-14
+----------------------------
+
+- Officially support PyPy 2.4, and PyPy3 2.4.  Drop support for
+  CPython 3.2 and older versions of PyPy.  The code won't work on CPython 3.2.
+  It will probably still work on older versions of PyPy, but I'm not testing
+  against them.
+
+- Plugins!
+
+- The original command line switches (`-x` to run a program, etc) are no
+  longer supported.
+
+- A new option: `coverage report --skip-covered` will reduce the number of
+  files reported by skipping files with 100% coverage.  Thanks, Krystian
+  Kichewko.  This means that empty `__init__.py` files will be skipped, since
+  they are 100% covered, closing `issue 315`_.
+
+- You can now specify the ``--fail-under`` option in the ``.coveragerc`` file
+  as the ``[report] fail_under`` option.  This closes `issue 314`_.
+
+- The ``COVERAGE_OPTIONS`` environment variable is no longer supported.  It was
+  a hack for ``--timid`` before configuration files were available.
+
+- The HTML report now has filtering.  Type text into the Filter box on the
+  index page, and only modules with that text in the name will be shown.
+  Thanks, Danny Allen.
+
+- The textual report and the HTML report used to report partial branches
+  differently for no good reason.  Now the text report's "missing branches"
+  column is a "partial branches" column so that both reports show the same
+  numbers.  This closes `issue 342`_.
+
+- If you specify a ``--rcfile`` that cannot be read, you will get an error
+  message.  Fixes `issue 343`_.
+
+- The ``--debug`` switch can now be used on any command.
+
+- You can now programmatically adjust the configuration of coverage.py by
+  setting items on `Coverage.config` after construction.
+
+- A module run with ``-m`` can be used as the argument to ``--source``, fixing
+  `issue 328`_.  Thanks, Buck Evan.
+
+- The regex for matching exclusion pragmas has been fixed to allow more kinds
+  of whitespace, fixing `issue 334`_.
+
+- Made some PyPy-specific tweaks to improve speed under PyPy.  Thanks, Alex
+  Gaynor.
+
+- In some cases, with a source file missing a final newline, coverage.py would
+  count statements incorrectly.  This is now fixed, closing `issue 293`_.
+
+- The status.dat file that HTML reports use to avoid re-creating files that
+  haven't changed is now a JSON file instead of a pickle file.  This obviates
+  `issue 287`_ and `issue 237`_.
+
+.. _issue 237: https://bitbucket.org/ned/coveragepy/issue/237/htmlcov-with-corrupt-statusdat
+.. _issue 287: https://bitbucket.org/ned/coveragepy/issue/287/htmlpy-doesnt-specify-pickle-protocol
+.. _issue 293: https://bitbucket.org/ned/coveragepy/issue/293/number-of-statement-detection-wrong-if-no
+.. _issue 314: https://bitbucket.org/ned/coveragepy/issue/314/fail_under-param-not-working-in-coveragerc
+.. _issue 315: https://bitbucket.org/ned/coveragepy/issue/315/option-to-omit-empty-files-eg-__init__py
+.. _issue 328: https://bitbucket.org/ned/coveragepy/issue/328/misbehavior-in-run-source
+.. _issue 334: https://bitbucket.org/ned/coveragepy/issue/334/pragma-not-recognized-if-tab-character
+.. _issue 342: https://bitbucket.org/ned/coveragepy/issue/342/console-and-html-coverage-reports-differ
+.. _issue 343: https://bitbucket.org/ned/coveragepy/issue/343/an-explicitly-named-non-existent-config
+
+
+Version 4.0a1 --- 2014-09-27
+----------------------------
+
+- Python versions supported are now CPython 2.6, 2.7, 3.2, 3.3, and 3.4, and
+  PyPy 2.2.
+
+- Gevent, eventlet, and greenlet are now supported, closing `issue 149`_.
+  The ``concurrency`` setting specifies the concurrency library in use.  Huge
+  thanks to Peter Portante for initial implementation, and to Joe Jevnik for
+  the final insight that completed the work.
+
+- Options are now also read from a setup.cfg file, if any.  Sections are
+  prefixed with "coverage:", so the ``[run]`` options will be read from the
+  ``[coverage:run]`` section of setup.cfg.  Finishes `issue 304`_.
+
+- The ``report -m`` command can now show missing branches when reporting on
+  branch coverage.  Thanks, Steve Leonard. Closes `issue 230`_.
+
+- The XML report now contains a <source> element, fixing `issue 94`_.  Thanks
+  Stan Hu.
+
+- The class defined in the coverage module is now called ``Coverage`` instead
+  of ``coverage``, though the old name still works, for backward compatibility.
+
+- The ``fail-under`` value is now rounded the same as reported results,
+  preventing paradoxical results, fixing `issue 284`_.
+
+- The XML report will now create the output directory if need be, fixing
+  `issue 285`_.  Thanks, Chris Rose.
+
+- HTML reports no longer raise UnicodeDecodeError if a Python file has
+  undecodable characters, fixing `issue 303`_ and `issue 331`_.
+
+- The annotate command will now annotate all files, not just ones relative to
+  the current directory, fixing `issue 57`_.
+
+- The coverage module no longer causes deprecation warnings on Python 3.4 by
+  importing the imp module, fixing `issue 305`_.
+
+- Encoding declarations in source files are only considered if they are truly
+  comments.  Thanks, Anthony Sottile.
+
+.. _issue 57: https://bitbucket.org/ned/coveragepy/issue/57/annotate-command-fails-to-annotate-many
+.. _issue 94: https://bitbucket.org/ned/coveragepy/issue/94/coverage-xml-doesnt-produce-sources
+.. _issue 149: https://bitbucket.org/ned/coveragepy/issue/149/coverage-gevent-looks-broken
+.. _issue 230: https://bitbucket.org/ned/coveragepy/issue/230/show-line-no-for-missing-branches-in
+.. _issue 284: https://bitbucket.org/ned/coveragepy/issue/284/fail-under-should-show-more-precision
+.. _issue 285: https://bitbucket.org/ned/coveragepy/issue/285/xml-report-fails-if-output-file-directory
+.. _issue 303: https://bitbucket.org/ned/coveragepy/issue/303/unicodedecodeerror
+.. _issue 304: https://bitbucket.org/ned/coveragepy/issue/304/attempt-to-get-configuration-from-setupcfg
+.. _issue 305: https://bitbucket.org/ned/coveragepy/issue/305/pendingdeprecationwarning-the-imp-module
+.. _issue 331: https://bitbucket.org/ned/coveragepy/issue/331/failure-of-encoding-detection-on-python2
+
+
+Version 3.7.1 --- 2013-12-13
+----------------------------
+
+- Improved the speed of HTML report generation by about 20%.
+
+- Fixed the mechanism for finding OS-installed static files for the HTML report
+  so that it will actually find OS-installed static files.
+
+
+Version 3.7 --- 2013-10-06
+--------------------------
+
+- Added the ``--debug`` switch to ``coverage run``.  It accepts a list of
+  options indicating the type of internal activity to log to stderr.
+
+- Improved the branch coverage facility, fixing `issue 92`_ and `issue 175`_.
+
+- Running code with ``coverage run -m`` now behaves more like Python does,
+  setting sys.path properly, which fixes `issue 207`_ and `issue 242`_.
+
+- Coverage.py can now run .pyc files directly, closing `issue 264`_.
+
+- Coverage.py properly supports .pyw files, fixing `issue 261`_.
+
+- Omitting files within a tree specified with the ``source`` option would
+  cause them to be incorrectly marked as unexecuted, as described in
+  `issue 218`_.  This is now fixed.
+
+- When specifying paths to alias together during data combining, you can now
+  specify relative paths, fixing `issue 267`_.
+
+- Most file paths can now be specified with username expansion (``~/src``, or
+  ``~build/src``, for example), and with environment variable expansion
+  (``build/$BUILDNUM/src``).
+
+- Trying to create an XML report with no files to report on, would cause a
+  ZeroDivideError, but no longer does, fixing `issue 250`_.
+
+- When running a threaded program under the Python tracer, coverage.py no
+  longer issues a spurious warning about the trace function changing: "Trace
+  function changed, measurement is likely wrong: None."  This fixes `issue
+  164`_.
+
+- Static files necessary for HTML reports are found in system-installed places,
+  to ease OS-level packaging of coverage.py.  Closes `issue 259`_.
+
+- Source files with encoding declarations, but a blank first line, were not
+  decoded properly.  Now they are.  Thanks, Roger Hu.
+
+- The source kit now includes the ``__main__.py`` file in the root coverage
+  directory, fixing `issue 255`_.
+
+.. _issue 92: https://bitbucket.org/ned/coveragepy/issue/92/finally-clauses-arent-treated-properly-in
+.. _issue 164: https://bitbucket.org/ned/coveragepy/issue/164/trace-function-changed-warning-when-using
+.. _issue 175: https://bitbucket.org/ned/coveragepy/issue/175/branch-coverage-gets-confused-in-certain
+.. _issue 207: https://bitbucket.org/ned/coveragepy/issue/207/run-m-cannot-find-module-or-package-in
+.. _issue 242: https://bitbucket.org/ned/coveragepy/issue/242/running-a-two-level-package-doesnt-work
+.. _issue 218: https://bitbucket.org/ned/coveragepy/issue/218/run-command-does-not-respect-the-omit-flag
+.. _issue 250: https://bitbucket.org/ned/coveragepy/issue/250/uncaught-zerodivisionerror-when-generating
+.. _issue 255: https://bitbucket.org/ned/coveragepy/issue/255/directory-level-__main__py-not-included-in
+.. _issue 259: https://bitbucket.org/ned/coveragepy/issue/259/allow-use-of-system-installed-third-party
+.. _issue 261: https://bitbucket.org/ned/coveragepy/issue/261/pyw-files-arent-reported-properly
+.. _issue 264: https://bitbucket.org/ned/coveragepy/issue/264/coverage-wont-run-pyc-files
+.. _issue 267: https://bitbucket.org/ned/coveragepy/issue/267/relative-path-aliases-dont-work
+
+
+Version 3.6 --- 2013-01-05
+--------------------------
+
+- Added a page to the docs about troublesome situations, closing `issue 226`_,
+  and added some info to the TODO file, closing `issue 227`_.
+
+.. _issue 226: https://bitbucket.org/ned/coveragepy/issue/226/make-readme-section-to-describe-when
+.. _issue 227: https://bitbucket.org/ned/coveragepy/issue/227/update-todo
+
+
+Version 3.6b3 --- 2012-12-29
+----------------------------
+
+- Beta 2 broke the nose plugin. It's fixed again, closing `issue 224`_.
+
+.. _issue 224: https://bitbucket.org/ned/coveragepy/issue/224/36b2-breaks-nosexcover
+
+
+Version 3.6b2 --- 2012-12-23
+----------------------------
+
+- Coverage.py runs on Python 2.3 and 2.4 again. It was broken in 3.6b1.
+
+- The C extension is optionally compiled using a different more widely-used
+  technique, taking another stab at fixing `issue 80`_ once and for all.
+
+- Combining data files would create entries for phantom files if used with
+  ``source`` and path aliases.  It no longer does.
+
+- ``debug sys`` now shows the configuration file path that was read.
+
+- If an oddly-behaved package claims that code came from an empty-string
+  file name, coverage.py no longer associates it with the directory name,
+  fixing `issue 221`_.
+
+.. _issue 221: https://bitbucket.org/ned/coveragepy/issue/221/coveragepy-incompatible-with-pyratemp
+
+
+Version 3.6b1 --- 2012-11-28
+----------------------------
+
+- Wildcards in ``include=`` and ``omit=`` arguments were not handled properly
+  in reporting functions, though they were when running.  Now they are handled
+  uniformly, closing `issue 143`_ and `issue 163`_.  **NOTE**: it is possible
+  that your configurations may now be incorrect.  If you use ``include`` or
+  ``omit`` during reporting, whether on the command line, through the API, or
+  in a configuration file, please check carefully that you were not relying on
+  the old broken behavior.
+
+- The **report**, **html**, and **xml** commands now accept a ``--fail-under``
+  switch that indicates in the exit status whether the coverage percentage was
+  less than a particular value.  Closes `issue 139`_.
+
+- The reporting functions coverage.report(), coverage.html_report(), and
+  coverage.xml_report() now all return a float, the total percentage covered
+  measurement.
+
+- The HTML report's title can now be set in the configuration file, with the
+  ``--title`` switch on the command line, or via the API.
+
+- Configuration files now support substitution of environment variables, using
+  syntax like ``${WORD}``.  Closes `issue 97`_.
+
+- Embarrassingly, the ``[xml] output=`` setting in the .coveragerc file simply
+  didn't work.  Now it does.
+
+- The XML report now consistently uses file names for the file name attribute,
+  rather than sometimes using module names.  Fixes `issue 67`_.
+  Thanks, Marcus Cobden.
+
+- Coverage percentage metrics are now computed slightly differently under
+  branch coverage.  This means that completely unexecuted files will now
+  correctly have 0% coverage, fixing `issue 156`_.  This also means that your
+  total coverage numbers will generally now be lower if you are measuring
+  branch coverage.
+
+- When installing, now in addition to creating a "coverage" command, two new
+  aliases are also installed.  A "coverage2" or "coverage3" command will be
+  created, depending on whether you are installing in Python 2.x or 3.x.
+  A "coverage-X.Y" command will also be created corresponding to your specific
+  version of Python.  Closes `issue 111`_.
+
+- The coverage.py installer no longer tries to bootstrap setuptools or
+  Distribute.  You must have one of them installed first, as `issue 202`_
+  recommended.
+
+- The coverage.py kit now includes docs (closing `issue 137`_) and tests.
+
+- On Windows, files are now reported in their correct case, fixing `issue 89`_
+  and `issue 203`_.
+
+- If a file is missing during reporting, the path shown in the error message
+  is now correct, rather than an incorrect path in the current directory.
+  Fixes `issue 60`_.
+
+- Running an HTML report in Python 3 in the same directory as an old Python 2
+  HTML report would fail with a UnicodeDecodeError. This issue (`issue 193`_)
+  is now fixed.
+
+- Fixed yet another error trying to parse non-Python files as Python, this
+  time an IndentationError, closing `issue 82`_ for the fourth time...
+
+- If `coverage xml` fails because there is no data to report, it used to
+  create a zero-length XML file.  Now it doesn't, fixing `issue 210`_.
+
+- Jython files now work with the ``--source`` option, fixing `issue 100`_.
+
+- Running coverage.py under a debugger is unlikely to work, but it shouldn't
+  fail with "TypeError: 'NoneType' object is not iterable".  Fixes `issue
+  201`_.
+
+- On some Linux distributions, when installed with the OS package manager,
+  coverage.py would report its own code as part of the results.  Now it won't,
+  fixing `issue 214`_, though this will take some time to be repackaged by the
+  operating systems.
+
+- Docstrings for the legacy singleton methods are more helpful.  Thanks Marius
+  Gedminas.  Closes `issue 205`_.
+
+- The pydoc tool can now show documentation for the class `coverage.coverage`.
+  Closes `issue 206`_.
+
+- Added a page to the docs about contributing to coverage.py, closing
+  `issue 171`_.
+
+- When coverage.py ended unsuccessfully, it may have reported odd errors like
+  ``'NoneType' object has no attribute 'isabs'``.  It no longer does,
+  so kiss `issue 153`_ goodbye.
+
+.. _issue 60: https://bitbucket.org/ned/coveragepy/issue/60/incorrect-path-to-orphaned-pyc-files
+.. _issue 67: https://bitbucket.org/ned/coveragepy/issue/67/xml-report-filenames-may-be-generated
+.. _issue 89: https://bitbucket.org/ned/coveragepy/issue/89/on-windows-all-packages-are-reported-in
+.. _issue 97: https://bitbucket.org/ned/coveragepy/issue/97/allow-environment-variables-to-be
+.. _issue 100: https://bitbucket.org/ned/coveragepy/issue/100/source-directive-doesnt-work-for-packages
+.. _issue 111: https://bitbucket.org/ned/coveragepy/issue/111/when-installing-coverage-with-pip-not
+.. _issue 137: https://bitbucket.org/ned/coveragepy/issue/137/provide-docs-with-source-distribution
+.. _issue 139: https://bitbucket.org/ned/coveragepy/issue/139/easy-check-for-a-certain-coverage-in-tests
+.. _issue 143: https://bitbucket.org/ned/coveragepy/issue/143/omit-doesnt-seem-to-work-in-coverage
+.. _issue 153: https://bitbucket.org/ned/coveragepy/issue/153/non-existent-filename-triggers
+.. _issue 156: https://bitbucket.org/ned/coveragepy/issue/156/a-completely-unexecuted-file-shows-14
+.. _issue 163: https://bitbucket.org/ned/coveragepy/issue/163/problem-with-include-and-omit-filename
+.. _issue 171: https://bitbucket.org/ned/coveragepy/issue/171/how-to-contribute-and-run-tests
+.. _issue 193: https://bitbucket.org/ned/coveragepy/issue/193/unicodedecodeerror-on-htmlpy
+.. _issue 201: https://bitbucket.org/ned/coveragepy/issue/201/coverage-using-django-14-with-pydb-on
+.. _issue 202: https://bitbucket.org/ned/coveragepy/issue/202/get-rid-of-ez_setuppy-and
+.. _issue 203: https://bitbucket.org/ned/coveragepy/issue/203/duplicate-filenames-reported-when-filename
+.. _issue 205: https://bitbucket.org/ned/coveragepy/issue/205/make-pydoc-coverage-more-friendly
+.. _issue 206: https://bitbucket.org/ned/coveragepy/issue/206/pydoc-coveragecoverage-fails-with-an-error
+.. _issue 210: https://bitbucket.org/ned/coveragepy/issue/210/if-theres-no-coverage-data-coverage-xml
+.. _issue 214: https://bitbucket.org/ned/coveragepy/issue/214/coveragepy-measures-itself-on-precise
+
+
+Version 3.5.3 --- 2012-09-29
+----------------------------
+
+- Line numbers in the HTML report line up better with the source lines, fixing
+  `issue 197`_, thanks Marius Gedminas.
+
+- When specifying a directory as the source= option, the directory itself no
+  longer needs to have a ``__init__.py`` file, though its sub-directories do,
+  to be considered as source files.
+
+- Files encoded as UTF-8 with a BOM are now properly handled, fixing
+  `issue 179`_.  Thanks, Pablo Carballo.
+
+- Fixed more cases of non-Python files being reported as Python source, and
+  then not being able to parse them as Python.  Closes `issue 82`_ (again).
+  Thanks, Julian Berman.
+
+- Fixed memory leaks under Python 3, thanks, Brett Cannon. Closes `issue 147`_.
+
+- Optimized .pyo files may not have been handled correctly, `issue 195`_.
+  Thanks, Marius Gedminas.
+
+- Certain unusually named file paths could have been mangled during reporting,
+  `issue 194`_.  Thanks, Marius Gedminas.
+
+- Try to do a better job of the impossible task of detecting when we can't
+  build the C extension, fixing `issue 183`_.
+
+- Testing is now done with `tox`_, thanks, Marc Abramowitz.
+
+.. _issue 147: https://bitbucket.org/ned/coveragepy/issue/147/massive-memory-usage-by-ctracer
+.. _issue 179: https://bitbucket.org/ned/coveragepy/issue/179/htmlreporter-fails-when-source-file-is
+.. _issue 183: https://bitbucket.org/ned/coveragepy/issue/183/install-fails-for-python-23
+.. _issue 194: https://bitbucket.org/ned/coveragepy/issue/194/filelocatorrelative_filename-could-mangle
+.. _issue 195: https://bitbucket.org/ned/coveragepy/issue/195/pyo-file-handling-in-codeunit
+.. _issue 197: https://bitbucket.org/ned/coveragepy/issue/197/line-numbers-in-html-report-do-not-align
+.. _tox: http://tox.readthedocs.org/
+
+
+Version 3.5.2 --- 2012-05-04
+----------------------------
+
+No changes since 3.5.2.b1
+
+
+Version 3.5.2b1 --- 2012-04-29
+------------------------------
+
+- The HTML report has slightly tweaked controls: the buttons at the top of
+  the page are color-coded to the source lines they affect.
+
+- Custom CSS can be applied to the HTML report by specifying a CSS file as
+  the ``extra_css`` configuration value in the ``[html]`` section.
+
+- Source files with custom encodings declared in a comment at the top are now
+  properly handled during reporting on Python 2.  Python 3 always handled them
+  properly.  This fixes `issue 157`_.
+
+- Backup files left behind by editors are no longer collected by the source=
+  option, fixing `issue 168`_.
+
+- If a file doesn't parse properly as Python, we don't report it as an error
+  if the file name seems like maybe it wasn't meant to be Python.  This is a
+  pragmatic fix for `issue 82`_.
+
+- The ``-m`` switch on ``coverage report``, which includes missing line numbers
+  in the summary report, can now be specified as ``show_missing`` in the
+  config file.  Closes `issue 173`_.
+
+- When running a module with ``coverage run -m <modulename>``, certain details
+  of the execution environment weren't the same as for
+  ``python -m <modulename>``.  This had the unfortunate side-effect of making
+  ``coverage run -m unittest discover`` not work if you had tests in a
+  directory named "test".  This fixes `issue 155`_ and `issue 142`_.
+
+- Now the exit status of your product code is properly used as the process
+  status when running ``python -m coverage run ...``.  Thanks, JT Olds.
+
+- When installing into pypy, we no longer attempt (and fail) to compile
+  the C tracer function, closing `issue 166`_.
+
+.. _issue 142: https://bitbucket.org/ned/coveragepy/issue/142/executing-python-file-syspath-is-replaced
+.. _issue 155: https://bitbucket.org/ned/coveragepy/issue/155/cant-use-coverage-run-m-unittest-discover
+.. _issue 157: https://bitbucket.org/ned/coveragepy/issue/157/chokes-on-source-files-with-non-utf-8
+.. _issue 166: https://bitbucket.org/ned/coveragepy/issue/166/dont-try-to-compile-c-extension-on-pypy
+.. _issue 168: https://bitbucket.org/ned/coveragepy/issue/168/dont-be-alarmed-by-emacs-droppings
+.. _issue 173: https://bitbucket.org/ned/coveragepy/issue/173/theres-no-way-to-specify-show-missing-in
+
+
+Version 3.5.1 --- 2011-09-23
+----------------------------
+
+- The ``[paths]`` feature unfortunately didn't work in real world situations
+  where you wanted to, you know, report on the combined data.  Now all paths
+  stored in the combined file are canonicalized properly.
+
+
+Version 3.5.1b1 --- 2011-08-28
+------------------------------
+
+- When combining data files from parallel runs, you can now instruct
+  coverage.py about which directories are equivalent on different machines.  A
+  ``[paths]`` section in the configuration file lists paths that are to be
+  considered equivalent.  Finishes `issue 17`_.
+
+- for-else constructs are understood better, and don't cause erroneous partial
+  branch warnings.  Fixes `issue 122`_.
+
+- Branch coverage for ``with`` statements is improved, fixing `issue 128`_.
+
+- The number of partial branches reported on the HTML summary page was
+  different than the number reported on the individual file pages.  This is
+  now fixed.
+
+- An explicit include directive to measure files in the Python installation
+  wouldn't work because of the standard library exclusion.  Now the include
+  directive takes precedence, and the files will be measured.  Fixes
+  `issue 138`_.
+
+- The HTML report now handles Unicode characters in Python source files
+  properly.  This fixes `issue 124`_ and `issue 144`_. Thanks, Devin
+  Jeanpierre.
+
+- In order to help the core developers measure the test coverage of the
+  standard library, Brandon Rhodes devised an aggressive hack to trick Python
+  into running some coverage.py code before anything else in the process.
+  See the coverage/fullcoverage directory if you are interested.
+
+.. _issue 17: http://bitbucket.org/ned/coveragepy/issue/17/support-combining-coverage-data-from
+.. _issue 122: http://bitbucket.org/ned/coveragepy/issue/122/for-else-always-reports-missing-branch
+.. _issue 124: http://bitbucket.org/ned/coveragepy/issue/124/no-arbitrary-unicode-in-html-reports-in
+.. _issue 128: http://bitbucket.org/ned/coveragepy/issue/128/branch-coverage-of-with-statement-in-27
+.. _issue 138: http://bitbucket.org/ned/coveragepy/issue/138/include-should-take-precedence-over-is
+.. _issue 144: http://bitbucket.org/ned/coveragepy/issue/144/failure-generating-html-output-for
+
+
+Version 3.5 --- 2011-06-29
+--------------------------
+
+- The HTML report hotkeys now behave slightly differently when the current
+  chunk isn't visible at all:  a chunk on the screen will be selected,
+  instead of the old behavior of jumping to the literal next chunk.
+  The hotkeys now work in Google Chrome.  Thanks, Guido van Rossum.
+
+
+Version 3.5b1 --- 2011-06-05
+----------------------------
+
+- The HTML report now has hotkeys.  Try ``n``, ``s``, ``m``, ``x``, ``b``,