Howdy Lars,

Here is an updated patch bundle against your current 
'python-coverage/sid' branch. It includes all changes from my earlier 
message and adjusts the Build-Depends for the required 
'python-central' version.

-- 
 \      "I wish a robot would get elected president. That way, when he |
  `\    came to town, we could all take a shot at him and not feel too |
_o__)                                            bad."  -- Jack Handey |
Ben Finney <[EMAIL PROTECTED]>
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: [EMAIL PROTECTED]
# target_branch: http://liw.iki.fi/bzr/python-coverage/sid/
# testament_sha1: 5afc119e4bd58578ab4aa4ee48a8b9ff5a342956
# timestamp: 2008-05-11 17:01:26 +1000
# base_revision_id: [EMAIL PROTECTED]
# 
# Begin patch
=== modified file 'coverage.py'
--- coverage.py	2007-07-30 17:31:03 +0000
+++ coverage.py	2008-05-10 00:36:53 +0000
@@ -52,18 +52,27 @@
 Coverage data is saved in the file .coverage by default.  Set the
 COVERAGE_FILE environment variable to save it somewhere else."""
 
-__version__ = "2.6.20060823"    # see detailed history at the end of this file.
+__version__ = "2.78.20070930"    # see detailed history at the end of this file.
 
 import compiler
 import compiler.visitor
+import glob
 import os
 import re
 import string
+import symbol
 import sys
 import threading
+import token
 import types
 from socket import gethostname
 
+# Python version compatibility
+try:
+    strclass = basestring   # new to 2.3
+except:
+    strclass = str
+
 # 2. IMPLEMENTATION
 #
 # This uses the "singleton" pattern.
@@ -85,6 +94,9 @@
 # names to increase speed.
 
 class StatementFindingAstVisitor(compiler.visitor.ASTVisitor):
+    """ A visitor for a parsed Abstract Syntax Tree which finds executable
+        statements.
+    """
     def __init__(self, statements, excluded, suite_spots):
         compiler.visitor.ASTVisitor.__init__(self)
         self.statements = statements
@@ -93,7 +105,6 @@
         self.excluding_suite = 0
         
     def doRecursive(self, node):
-        self.recordNodeLine(node)
         for n in node.getChildNodes():
             self.dispatch(n)
 
@@ -129,12 +140,35 @@
     def doStatement(self, node):
         self.recordLine(self.getFirstLine(node))
 
-    visitAssert = visitAssign = visitAssTuple = visitDiscard = visitPrint = \
+    visitAssert = visitAssign = visitAssTuple = visitPrint = \
         visitPrintnl = visitRaise = visitSubscript = visitDecorators = \
         doStatement
     
+    def visitPass(self, node):
+        # Pass statements have weird interactions with docstrings.  If this
+        # pass statement is part of one of those pairs, claim that the statement
+        # is on the later of the two lines.
+        l = node.lineno
+        if l:
+            lines = self.suite_spots.get(l, [l,l])
+            self.statements[lines[1]] = 1
+        
+    def visitDiscard(self, node):
+        # Discard nodes are statements that execute an expression, but then
+        # discard the results.  This includes function calls, so we can't 
+        # ignore them all.  But if the expression is a constant, the statement
+        # won't be "executed", so don't count it now.
+        if node.expr.__class__.__name__ != 'Const':
+            self.doStatement(node)
+
     def recordNodeLine(self, node):
-        return self.recordLine(node.lineno)
+        # Stmt nodes often have None, but shouldn't claim the first line of
+        # their children (because the first child might be an ignorable line
+        # like "global a").
+        if node.__class__.__name__ != 'Stmt':
+            return self.recordLine(self.getFirstLine(node))
+        else:
+            return 0
     
     def recordLine(self, lineno):
         # Returns a bool, whether the line is included or excluded.
@@ -143,7 +177,7 @@
             # keyword.
             if lineno in self.suite_spots:
                 lineno = self.suite_spots[lineno][0]
-            # If we're inside an exluded suite, record that this line was
+            # If we're inside an excluded suite, record that this line was
             # excluded.
             if self.excluding_suite:
                 self.excluded[lineno] = 1
@@ -195,6 +229,8 @@
         self.doSuite(node, node.body)
         self.doElse(node.body, node)
 
+    visitWhile = visitFor
+
     def visitIf(self, node):
         # The first test has to be handled separately from the rest.
         # The first test is credited to the line with the "if", but the others
@@ -204,10 +240,6 @@
             self.doSuite(t, n)
         self.doElse(node.tests[-1][1], node)
 
-    def visitWhile(self, node):
-        self.doSuite(node, node.body)
-        self.doElse(node.body, node)
-
     def visitTryExcept(self, node):
         self.doSuite(node, node.body)
         for i in range(len(node.handlers)):
@@ -227,6 +259,9 @@
         self.doSuite(node, node.body)
         self.doPlainWordSuite(node.body, node.final)
         
+    def visitWith(self, node):
+        self.doSuite(node, node.body)
+        
     def visitGlobal(self, node):
         # "global" statements don't execute like others (they don't call the
         # trace function), so don't record their line numbers.
@@ -263,14 +298,16 @@
     def __init__(self):
         global the_coverage
         if the_coverage:
-            raise CoverageException, "Only one coverage object allowed."
+            raise CoverageException("Only one coverage object allowed.")
         self.usecache = 1
         self.cache = None
+        self.parallel_mode = False
         self.exclude_re = ''
         self.nesting = 0
         self.cstack = []
         self.xstack = []
-        self.relative_dir = os.path.normcase(os.path.abspath(os.curdir)+os.path.sep)
+        self.relative_dir = os.path.normcase(os.path.abspath(os.curdir)+os.sep)
+        self.exclude('# *pragma[: ]*[nN][oO] *[cC][oO][vV][eE][rR]')
 
     # t(f, x, y).  This method is passed to sys.settrace as a trace function.  
     # See [van Rossum 2001-07-20b, 9.2] for an explanation of sys.settrace and 
@@ -278,23 +315,24 @@
     # See [van Rossum 2001-07-20a, 3.2] for a description of frame and code
     # objects.
     
-    def t(self, f, w, a):                                   #pragma: no cover
+    def t(self, f, w, unused):                                 #pragma: no cover
         if w == 'line':
+            #print "Executing %s @ %d" % (f.f_code.co_filename, f.f_lineno)
             self.c[(f.f_code.co_filename, f.f_lineno)] = 1
             for c in self.cstack:
                 c[(f.f_code.co_filename, f.f_lineno)] = 1
         return self.t
     
-    def help(self, error=None):
+    def help(self, error=None):     #pragma: no cover
         if error:
             print error
             print
         print __doc__
         sys.exit(1)
 
-    def command_line(self, argv, help=None):
+    def command_line(self, argv, help_fn=None):
         import getopt
-        help = help or self.help
+        help_fn = help_fn or self.help
         settings = {}
         optmap = {
             '-a': 'annotate',
@@ -325,12 +363,12 @@
                 pass    # Can't get here, because getopt won't return anything unknown.
 
         if settings.get('help'):
-            help()
+            help_fn()
 
         for i in ['erase', 'execute']:
             for j in ['annotate', 'report', 'collect']:
                 if settings.get(i) and settings.get(j):
-                    help("You can't specify the '%s' and '%s' "
+                    help_fn("You can't specify the '%s' and '%s' "
                               "options at the same time." % (i, j))
 
         args_needed = (settings.get('execute')
@@ -340,18 +378,18 @@
                   or settings.get('collect')
                   or args_needed)
         if not action:
-            help("You must specify at least one of -e, -x, -c, -r, or -a.")
+            help_fn("You must specify at least one of -e, -x, -c, -r, or -a.")
         if not args_needed and args:
-            help("Unexpected arguments: %s" % " ".join(args))
+            help_fn("Unexpected arguments: %s" % " ".join(args))
         
-        self.get_ready(settings.get('parallel-mode'))
-        self.exclude('#pragma[: ]+[nN][oO] [cC][oO][vV][eE][rR]')
+        self.parallel_mode = settings.get('parallel-mode')
+        self.get_ready()
 
         if settings.get('erase'):
             self.erase()
         if settings.get('execute'):
             if not args:
-                help("Nothing to do.")
+                help_fn("Nothing to do.")
             sys.argv = args
             self.start()
             import __main__
@@ -385,13 +423,13 @@
     def get_ready(self, parallel_mode=False):
         if self.usecache and not self.cache:
             self.cache = os.environ.get(self.cache_env, self.cache_default)
-            if parallel_mode:
+            if self.parallel_mode:
                 self.cache += "." + gethostname() + "." + str(os.getpid())
             self.restore()
         self.analysis_cache = {}
         
     def start(self, parallel_mode=False):
-        self.get_ready(parallel_mode)
+        self.get_ready()
         if self.nesting == 0:                               #pragma: no cover
             sys.settrace(self.t)
             if hasattr(threading, 'settrace'):
@@ -406,12 +444,12 @@
                 threading.settrace(None)
 
     def erase(self):
+        self.get_ready()
         self.c = {}
         self.analysis_cache = {}
         self.cexecuted = {}
         if self.cache and os.path.exists(self.cache):
             os.remove(self.cache)
-        self.exclude_re = ""
 
     def exclude(self, re):
         if self.exclude_re:
@@ -462,11 +500,11 @@
 
     def collect(self):
         cache_dir, local = os.path.split(self.cache)
-        for file in os.listdir(cache_dir):
-            if not file.startswith(local):
+        for f in os.listdir(cache_dir or '.'):
+            if not f.startswith(local):
                 continue
 
-            full_path = os.path.join(cache_dir, file)
+            full_path = os.path.join(cache_dir, f)
             cexecuted = self.restore_file(full_path)
             self.merge_data(cexecuted)
 
@@ -506,6 +544,9 @@
 
     def canonicalize_filenames(self):
         for filename, lineno in self.c.keys():
+            if filename == '<string>':
+                # Can't do anything useful with exec'd strings, so skip them.
+                continue
             f = self.canonical_filename(filename)
             if not self.cexecuted.has_key(f):
                 self.cexecuted[f] = {}
@@ -517,41 +558,85 @@
     def morf_filename(self, morf):
         if isinstance(morf, types.ModuleType):
             if not hasattr(morf, '__file__'):
-                raise CoverageException, "Module has no __file__ attribute."
-            file = morf.__file__
+                raise CoverageException("Module has no __file__ attribute.")
+            f = morf.__file__
         else:
-            file = morf
-        return self.canonical_filename(file)
+            f = morf
+        return self.canonical_filename(f)
 
     # analyze_morf(morf).  Analyze the module or filename passed as
     # the argument.  If the source code can't be found, raise an error.
     # Otherwise, return a tuple of (1) the canonical filename of the
     # source code for the module, (2) a list of lines of statements
-    # in the source code, and (3) a list of lines of excluded statements.
-
+    # in the source code, (3) a list of lines of excluded statements,
+    # and (4), a map of line numbers to multi-line line number ranges, for
+    # statements that cross lines.
+    
     def analyze_morf(self, morf):
         if self.analysis_cache.has_key(morf):
             return self.analysis_cache[morf]
         filename = self.morf_filename(morf)
         ext = os.path.splitext(filename)[1]
         if ext == '.pyc':
-            if not os.path.exists(filename[0:-1]):
-                raise CoverageException, ("No source for compiled code '%s'."
-                                   % filename)
-            filename = filename[0:-1]
-        elif ext != '.py':
-            raise CoverageException, "File '%s' not Python source." % filename
+            if not os.path.exists(filename[:-1]):
+                raise CoverageException(
+                    "No source for compiled code '%s'." % filename
+                    )
+            filename = filename[:-1]
         source = open(filename, 'r')
-        lines, excluded_lines = self.find_executable_statements(
-            source.read(), exclude=self.exclude_re
-            )
+        try:
+            lines, excluded_lines, line_map = self.find_executable_statements(
+                source.read(), exclude=self.exclude_re
+                )
+        except SyntaxError, synerr:
+            raise CoverageException(
+                "Couldn't parse '%s' as Python source: '%s' at line %d" %
+                    (filename, synerr.msg, synerr.lineno)
+                )            
         source.close()
-        result = filename, lines, excluded_lines
+        result = filename, lines, excluded_lines, line_map
         self.analysis_cache[morf] = result
         return result
 
+    def first_line_of_tree(self, tree):
+        while True:
+            if len(tree) == 3 and type(tree[2]) == type(1):
+                return tree[2]
+            tree = tree[1]
+    
+    def last_line_of_tree(self, tree):
+        while True:
+            if len(tree) == 3 and type(tree[2]) == type(1):
+                return tree[2]
+            tree = tree[-1]
+    
+    def find_docstring_pass_pair(self, tree, spots):
+        for i in range(1, len(tree)):
+            if self.is_string_constant(tree[i]) and self.is_pass_stmt(tree[i+1]):
+                first_line = self.first_line_of_tree(tree[i])
+                last_line = self.last_line_of_tree(tree[i+1])
+                self.record_multiline(spots, first_line, last_line)
+        
+    def is_string_constant(self, tree):
+        try:
+            return tree[0] == symbol.stmt and tree[1][1][1][0] == symbol.expr_stmt
+        except:
+            return False
+        
+    def is_pass_stmt(self, tree):
+        try:
+            return tree[0] == symbol.stmt and tree[1][1][1][0] == symbol.pass_stmt
+        except:
+            return False
+
+    def record_multiline(self, spots, i, j):
+        for l in range(i, j+1):
+            spots[l] = (i, j)
+            
     def get_suite_spots(self, tree, spots):
-        import symbol, token
+        """ Analyze a parse tree to find suite introducers which span a number
+            of lines.
+        """
         for i in range(1, len(tree)):
             if type(tree[i]) == type(()):
                 if tree[i][0] == symbol.suite:
@@ -559,7 +644,9 @@
                     lineno_colon = lineno_word = None
                     for j in range(i-1, 0, -1):
                         if tree[j][0] == token.COLON:
-                            lineno_colon = tree[j][2]
+                            # Colons are never executed themselves: we want the
+                            # line number of the last token before the colon.
+                            lineno_colon = self.last_line_of_tree(tree[j-1])
                         elif tree[j][0] == token.NAME:
                             if tree[j][1] == 'elif':
                                 # Find the line number of the first non-terminal
@@ -581,8 +668,18 @@
                     if lineno_colon and lineno_word:
                         # Found colon and keyword, mark all the lines
                         # between the two with the two line numbers.
-                        for l in range(lineno_word, lineno_colon+1):
-                            spots[l] = (lineno_word, lineno_colon)
+                        self.record_multiline(spots, lineno_word, lineno_colon)
+
+                    # "pass" statements are tricky: different versions of Python
+                    # treat them differently, especially in the common case of a
+                    # function with a doc string and a single pass statement.
+                    self.find_docstring_pass_pair(tree[i], spots)
+                    
+                elif tree[i][0] == symbol.simple_stmt:
+                    first_line = self.first_line_of_tree(tree[i])
+                    last_line = self.last_line_of_tree(tree[i])
+                    if first_line != last_line:
+                        self.record_multiline(spots, first_line, last_line)
                 self.get_suite_spots(tree[i], spots)
 
     def find_executable_statements(self, text, exclude=None):
@@ -596,10 +693,13 @@
                 if reExclude.search(lines[i]):
                     excluded[i+1] = 1
 
+        # Parse the code and analyze the parse tree to find out which statements
+        # are multiline, and where suites begin and end.
         import parser
         tree = parser.suite(text+'\n\n').totuple(1)
         self.get_suite_spots(tree, suite_spots)
-            
+        #print "Suite spots:", suite_spots
+        
         # Use the compiler module to parse the text and find the executable
         # statements.  We add newlines to be impervious to final partial lines.
         statements = {}
@@ -611,7 +711,7 @@
         lines.sort()
         excluded_lines = excluded.keys()
         excluded_lines.sort()
-        return lines, excluded_lines
+        return lines, excluded_lines, suite_spots
 
     # format_lines(statements, lines).  Format a list of line numbers
     # for printing by coalescing groups of lines as long as the lines
@@ -644,7 +744,8 @@
                 return "%d" % start
             else:
                 return "%d-%d" % (start, end)
-        return string.join(map(stringify, pairs), ", ")
+        ret = string.join(map(stringify, pairs), ", ")
+        return ret
 
     # Backward compatibility with version 1.
     def analysis(self, morf):
@@ -652,13 +753,17 @@
         return f, s, m, mf
 
     def analysis2(self, morf):
-        filename, statements, excluded = self.analyze_morf(morf)
+        filename, statements, excluded, line_map = self.analyze_morf(morf)
         self.canonicalize_filenames()
         if not self.cexecuted.has_key(filename):
             self.cexecuted[filename] = {}
         missing = []
         for line in statements:
-            if not self.cexecuted[filename].has_key(line):
+            lines = line_map.get(line, [line, line])
+            for l in range(lines[0], lines[1]+1):
+                if self.cexecuted[filename].has_key(l):
+                    break
+            else:
                 missing.append(line)
         return (filename, statements, excluded, missing,
                 self.format_lines(statements, missing))
@@ -696,6 +801,15 @@
     def report(self, morfs, show_missing=1, ignore_errors=0, file=None, omit_prefixes=[]):
         if not isinstance(morfs, types.ListType):
             morfs = [morfs]
+        # On windows, the shell doesn't expand wildcards.  Do it here.
+        globbed = []
+        for morf in morfs:
+            if isinstance(morf, strclass):
+                globbed.extend(glob.glob(morf))
+            else:
+                globbed.append(morf)
+        morfs = globbed
+        
         morfs = self.filter_by_prefix(morfs, omit_prefixes)
         morfs.sort(self.morf_name_compare)
 
@@ -733,8 +847,8 @@
                 raise
             except:
                 if not ignore_errors:
-                    type, msg = sys.exc_info()[0:2]
-                    print >>file, fmt_err % (name, type, msg)
+                    typ, msg = sys.exc_info()[:2]
+                    print >>file, fmt_err % (name, typ, msg)
         if len(morfs) > 1:
             print >>file, "-" * len(header)
             if total_statements > 0:
@@ -814,18 +928,41 @@
 the_coverage = coverage()
 
 # Module functions call methods in the singleton object.
-def use_cache(*args, **kw): return the_coverage.use_cache(*args, **kw)
-def start(*args, **kw): return the_coverage.start(*args, **kw)
-def stop(*args, **kw): return the_coverage.stop(*args, **kw)
-def erase(*args, **kw): return the_coverage.erase(*args, **kw)
-def begin_recursive(*args, **kw): return the_coverage.begin_recursive(*args, **kw)
-def end_recursive(*args, **kw): return the_coverage.end_recursive(*args, **kw)
-def exclude(*args, **kw): return the_coverage.exclude(*args, **kw)
-def analysis(*args, **kw): return the_coverage.analysis(*args, **kw)
-def analysis2(*args, **kw): return the_coverage.analysis2(*args, **kw)
-def report(*args, **kw): return the_coverage.report(*args, **kw)
-def annotate(*args, **kw): return the_coverage.annotate(*args, **kw)
-def annotate_file(*args, **kw): return the_coverage.annotate_file(*args, **kw)
+def use_cache(*args, **kw): 
+    return the_coverage.use_cache(*args, **kw)
+
+def start(*args, **kw): 
+    return the_coverage.start(*args, **kw)
+
+def stop(*args, **kw): 
+    return the_coverage.stop(*args, **kw)
+
+def erase(*args, **kw): 
+    return the_coverage.erase(*args, **kw)
+
+def begin_recursive(*args, **kw): 
+    return the_coverage.begin_recursive(*args, **kw)
+
+def end_recursive(*args, **kw): 
+    return the_coverage.end_recursive(*args, **kw)
+
+def exclude(*args, **kw): 
+    return the_coverage.exclude(*args, **kw)
+
+def analysis(*args, **kw): 
+    return the_coverage.analysis(*args, **kw)
+
+def analysis2(*args, **kw): 
+    return the_coverage.analysis2(*args, **kw)
+
+def report(*args, **kw): 
+    return the_coverage.report(*args, **kw)
+
+def annotate(*args, **kw): 
+    return the_coverage.annotate(*args, **kw)
+
+def annotate_file(*args, **kw): 
+    return the_coverage.annotate_file(*args, **kw)
 
 # Save coverage data when Python exits.  (The atexit module wasn't
 # introduced until Python 2.0, so use sys.exitfunc when it's not
@@ -916,11 +1053,41 @@
 #
 # 2006-08-23 NMB Refactorings to improve testability.  Fixes to command-line
 # logic for parallel mode and collect.
+#
+# 2006-08-25 NMB "#pragma: nocover" is excluded by default.
+#
+# 2006-09-10 NMB Properly ignore docstrings and other constant expressions that
+# appear in the middle of a function, a problem reported by Tim Leslie.
+# Minor changes to avoid lint warnings.
+#
+# 2006-09-17 NMB 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.
+#
+# 2007-07-21 NMB 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.
+#
+# 2007-07-22 NMB 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.
+#
+# 2007-07-23 NMB Now Python 2.5 is *really* fully supported: the body of the
+# new with statement is counted as executable.
+#
+# 2007-07-29 NMB Better packaging.
+#
+# 2007-09-30 NMB Don't try to predict whether a file is Python source based on
+# the extension. Extensionless files are often Pythons scripts. Instead, simply
+# parse the file and catch the syntax errors.  Hat tip to Ben Finney.
 
 # C. COPYRIGHT AND LICENCE
 #
 # Copyright 2001 Gareth Rees.  All rights reserved.
-# Copyright 2004-2006 Ned Batchelder.  All rights reserved.
+# Copyright 2004-2007 Ned Batchelder.  All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are
@@ -947,4 +1114,4 @@
 # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 # DAMAGE.
 #
-# $Id: coverage.py 47 2006-08-24 01:08:48Z Ned $
+# $Id: coverage.py 79 2007-10-01 01:01:52Z nedbat $

=== modified file 'debian/README.source'
--- debian/README.source	2007-07-30 17:31:34 +0000
+++ debian/README.source	2008-05-10 00:36:53 +0000
@@ -3,7 +3,7 @@
 * http://liw.iki.fi/bzr/python-coverage/ is the bzr repository; all the
   branches mentioned in this document are in that repository, so to access
   them append their name to the url.
-  
+
 * There are three branches: upstream, sid, and tarballs. You need to check
   out all of them ("bzr branch $BRANCHURL").
 
@@ -11,7 +11,11 @@
   a single Python file (coverage.py), and that's what upstream publishes.
   For each new release, I add the new coverage.py to the upstream branch,
   and commit.
-  
+
+  (As of 2007-07-29, the upstream package uses distutils packaging and
+  is no longer published as "a single Python file". TODO: Work with
+  the distutils packaging being provided by upstream.)
+
 * I then generate an .orig.tar.gz tarball, from within the upstream branch:
 
     V=2.6

=== modified file 'debian/changelog'
--- debian/changelog	2007-08-19 19:54:32 +0000
+++ debian/changelog	2008-05-11 07:00:53 +0000
@@ -1,3 +1,16 @@
+python-coverage (2.78-0.1) UNRELEASED; urgency=low
+
+  * Non-maintainer upload.
+  * New upstream version (closes: #454982).
+  * debian/python-coverage.install:
+    + Install Python modules to /usr/share/pyshared as per new behaviour of
+      python-central.
+  * debian/control:
+    + Update to Standards-Version: 3.7.3 (no changes required).
+    + Build-Depends: python-central (>= 0.6).
+
+ -- Ben Finney <[EMAIL PROTECTED]>  Sat, 10 May 2008 10:53:09 +1000
+
 python-coverage (2.6-1) unstable; urgency=low
 
   * Initial version. Closes: #405230.

=== modified file 'debian/control'
--- debian/control	2007-12-16 10:23:00 +0000
+++ debian/control	2008-05-11 07:00:53 +0000
@@ -2,8 +2,8 @@
 Maintainer: Lars Wirzenius <[EMAIL PROTECTED]>
 Section: devel
 Priority: optional
-Standards-Version: 3.7.2
-Build-Depends-Indep: python-central (>= 0.5.6), python (>= 2.3)
+Standards-Version: 3.7.3
+Build-Depends-Indep: python-central (>= 0.6), python (>= 2.3)
 Build-Depends: cdbs (>= 0.4.43), debhelper (>= 5.0.38)
 XS-Python-Version: all
 
@@ -15,5 +15,4 @@
  This tool measures which parts (statements) of a Python program are
  executed while it is run. This is useful for testing: those parts of
  a program that are not executed by the tests have not been tested.
- .
 Homepage: http://www.nedbatchelder.com/code/modules/coverage.html

=== modified file 'debian/python-coverage.install'
--- debian/python-coverage.install	2007-07-30 17:18:05 +0000
+++ debian/python-coverage.install	2008-05-10 01:00:25 +0000
@@ -1,2 +1,2 @@
 debian/python-coverage.1 usr/share/man/man1
-coverage.py usr/share/pycentral/python-coverage/site-packages
+coverage.py usr/share/pyshared/python-coverage/site-packages

# Begin bundle
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
5IpwoSHn+VsU

Attachment: signature.asc
Description: Digital signature

Reply via email to