comparison tests/coverage.py @ 5760:0145f9afb0e7

Removed tabs and trailing whitespace in python files
author Thomas Arendsen Hein <thomas@intevation.de>
date Sat, 29 Dec 2007 19:49:48 +0100
parents 8623debad845
children d0576d065993
comparison
equal deleted inserted replaced
5759:027264e720aa 5760:0145f9afb0e7
103 compiler.visitor.ASTVisitor.__init__(self) 103 compiler.visitor.ASTVisitor.__init__(self)
104 self.statements = statements 104 self.statements = statements
105 self.excluded = excluded 105 self.excluded = excluded
106 self.suite_spots = suite_spots 106 self.suite_spots = suite_spots
107 self.excluding_suite = 0 107 self.excluding_suite = 0
108 108
109 def doRecursive(self, node): 109 def doRecursive(self, node):
110 for n in node.getChildNodes(): 110 for n in node.getChildNodes():
111 self.dispatch(n) 111 self.dispatch(n)
112 112
113 visitStmt = visitModule = doRecursive 113 visitStmt = visitModule = doRecursive
114 114
115 def doCode(self, node): 115 def doCode(self, node):
116 if hasattr(node, 'decorators') and node.decorators: 116 if hasattr(node, 'decorators') and node.decorators:
117 self.dispatch(node.decorators) 117 self.dispatch(node.decorators)
118 self.recordAndDispatch(node.code) 118 self.recordAndDispatch(node.code)
119 else: 119 else:
120 self.doSuite(node, node.code) 120 self.doSuite(node, node.code)
121 121
122 visitFunction = visitClass = doCode 122 visitFunction = visitClass = doCode
123 123
124 def getFirstLine(self, node): 124 def getFirstLine(self, node):
125 # Find the first line in the tree node. 125 # Find the first line in the tree node.
126 lineno = node.lineno 126 lineno = node.lineno
136 # Find the first line in the tree node. 136 # Find the first line in the tree node.
137 lineno = node.lineno 137 lineno = node.lineno
138 for n in node.getChildNodes(): 138 for n in node.getChildNodes():
139 lineno = max(lineno, self.getLastLine(n)) 139 lineno = max(lineno, self.getLastLine(n))
140 return lineno 140 return lineno
141 141
142 def doStatement(self, node): 142 def doStatement(self, node):
143 self.recordLine(self.getFirstLine(node)) 143 self.recordLine(self.getFirstLine(node))
144 144
145 visitAssert = visitAssign = visitAssTuple = visitPrint = \ 145 visitAssert = visitAssign = visitAssTuple = visitPrint = \
146 visitPrintnl = visitRaise = visitSubscript = visitDecorators = \ 146 visitPrintnl = visitRaise = visitSubscript = visitDecorators = \
147 doStatement 147 doStatement
148 148
149 def visitPass(self, node): 149 def visitPass(self, node):
150 # Pass statements have weird interactions with docstrings. If this 150 # Pass statements have weird interactions with docstrings. If this
151 # pass statement is part of one of those pairs, claim that the statement 151 # pass statement is part of one of those pairs, claim that the statement
152 # is on the later of the two lines. 152 # is on the later of the two lines.
153 l = node.lineno 153 l = node.lineno
154 if l: 154 if l:
155 lines = self.suite_spots.get(l, [l,l]) 155 lines = self.suite_spots.get(l, [l,l])
156 self.statements[lines[1]] = 1 156 self.statements[lines[1]] = 1
157 157
158 def visitDiscard(self, node): 158 def visitDiscard(self, node):
159 # Discard nodes are statements that execute an expression, but then 159 # Discard nodes are statements that execute an expression, but then
160 # discard the results. This includes function calls, so we can't 160 # discard the results. This includes function calls, so we can't
161 # ignore them all. But if the expression is a constant, the statement 161 # ignore them all. But if the expression is a constant, the statement
162 # won't be "executed", so don't count it now. 162 # won't be "executed", so don't count it now.
163 if node.expr.__class__.__name__ != 'Const': 163 if node.expr.__class__.__name__ != 'Const':
164 self.doStatement(node) 164 self.doStatement(node)
165 165
169 # like "global a"). 169 # like "global a").
170 if node.__class__.__name__ != 'Stmt': 170 if node.__class__.__name__ != 'Stmt':
171 return self.recordLine(self.getFirstLine(node)) 171 return self.recordLine(self.getFirstLine(node))
172 else: 172 else:
173 return 0 173 return 0
174 174
175 def recordLine(self, lineno): 175 def recordLine(self, lineno):
176 # Returns a bool, whether the line is included or excluded. 176 # Returns a bool, whether the line is included or excluded.
177 if lineno: 177 if lineno:
178 # Multi-line tests introducing suites have to get charged to their 178 # Multi-line tests introducing suites have to get charged to their
179 # keyword. 179 # keyword.
193 # Otherwise, this is an executable line. 193 # Otherwise, this is an executable line.
194 else: 194 else:
195 self.statements[lineno] = 1 195 self.statements[lineno] = 1
196 return 1 196 return 1
197 return 0 197 return 0
198 198
199 default = recordNodeLine 199 default = recordNodeLine
200 200
201 def recordAndDispatch(self, node): 201 def recordAndDispatch(self, node):
202 self.recordNodeLine(node) 202 self.recordNodeLine(node)
203 self.dispatch(node) 203 self.dispatch(node)
204 204
205 def doSuite(self, intro, body, exclude=0): 205 def doSuite(self, intro, body, exclude=0):
206 exsuite = self.excluding_suite 206 exsuite = self.excluding_suite
207 if exclude or (intro and not self.recordNodeLine(intro)): 207 if exclude or (intro and not self.recordNodeLine(intro)):
208 self.excluding_suite = 1 208 self.excluding_suite = 1
209 self.recordAndDispatch(body) 209 self.recordAndDispatch(body)
210 self.excluding_suite = exsuite 210 self.excluding_suite = exsuite
211 211
212 def doPlainWordSuite(self, prevsuite, suite): 212 def doPlainWordSuite(self, prevsuite, suite):
213 # Finding the exclude lines for else's is tricky, because they aren't 213 # Finding the exclude lines for else's is tricky, because they aren't
214 # present in the compiler parse tree. Look at the previous suite, 214 # present in the compiler parse tree. Look at the previous suite,
215 # and find its last line. If any line between there and the else's 215 # and find its last line. If any line between there and the else's
216 # first line are excluded, then we exclude the else. 216 # first line are excluded, then we exclude the else.
220 if self.suite_spots.has_key(l): 220 if self.suite_spots.has_key(l):
221 self.doSuite(None, suite, exclude=self.excluded.has_key(l)) 221 self.doSuite(None, suite, exclude=self.excluded.has_key(l))
222 break 222 break
223 else: 223 else:
224 self.doSuite(None, suite) 224 self.doSuite(None, suite)
225 225
226 def doElse(self, prevsuite, node): 226 def doElse(self, prevsuite, node):
227 if node.else_: 227 if node.else_:
228 self.doPlainWordSuite(prevsuite, node.else_) 228 self.doPlainWordSuite(prevsuite, node.else_)
229 229
230 def visitFor(self, node): 230 def visitFor(self, node):
231 self.doSuite(node, node.body) 231 self.doSuite(node, node.body)
232 self.doElse(node.body, node) 232 self.doElse(node.body, node)
233 233
234 visitWhile = visitFor 234 visitWhile = visitFor
254 prev = node.body 254 prev = node.body
255 self.doPlainWordSuite(prev, h) 255 self.doPlainWordSuite(prev, h)
256 else: 256 else:
257 self.doSuite(a, h) 257 self.doSuite(a, h)
258 self.doElse(node.handlers[-1][2], node) 258 self.doElse(node.handlers[-1][2], node)
259 259
260 def visitTryFinally(self, node): 260 def visitTryFinally(self, node):
261 self.doSuite(node, node.body) 261 self.doSuite(node, node.body)
262 self.doPlainWordSuite(node.body, node.final) 262 self.doPlainWordSuite(node.body, node.final)
263 263
264 def visitWith(self, node): 264 def visitWith(self, node):
265 self.doSuite(node, node.body) 265 self.doSuite(node, node.body)
266 266
267 def visitGlobal(self, node): 267 def visitGlobal(self, node):
268 # "global" statements don't execute like others (they don't call the 268 # "global" statements don't execute like others (they don't call the
269 # trace function), so don't record their line numbers. 269 # trace function), so don't record their line numbers.
270 pass 270 pass
271 271
281 cache_env = "COVERAGE_FILE" 281 cache_env = "COVERAGE_FILE"
282 282
283 # A dictionary with an entry for (Python source file name, line number 283 # A dictionary with an entry for (Python source file name, line number
284 # in that file) if that line has been executed. 284 # in that file) if that line has been executed.
285 c = {} 285 c = {}
286 286
287 # A map from canonical Python source file name to a dictionary in 287 # A map from canonical Python source file name to a dictionary in
288 # which there's an entry for each line number that has been 288 # which there's an entry for each line number that has been
289 # executed. 289 # executed.
290 cexecuted = {} 290 cexecuted = {}
291 291
309 self.cstack = [] 309 self.cstack = []
310 self.xstack = [] 310 self.xstack = []
311 self.relative_dir = os.path.normcase(os.path.abspath(os.curdir)+os.sep) 311 self.relative_dir = os.path.normcase(os.path.abspath(os.curdir)+os.sep)
312 self.exclude('# *pragma[: ]*[nN][oO] *[cC][oO][vV][eE][rR]') 312 self.exclude('# *pragma[: ]*[nN][oO] *[cC][oO][vV][eE][rR]')
313 313
314 # t(f, x, y). This method is passed to sys.settrace as a trace function. 314 # t(f, x, y). This method is passed to sys.settrace as a trace function.
315 # See [van Rossum 2001-07-20b, 9.2] for an explanation of sys.settrace and 315 # See [van Rossum 2001-07-20b, 9.2] for an explanation of sys.settrace and
316 # the arguments and return value of the trace function. 316 # the arguments and return value of the trace function.
317 # See [van Rossum 2001-07-20a, 3.2] for a description of frame and code 317 # See [van Rossum 2001-07-20a, 3.2] for a description of frame and code
318 # objects. 318 # objects.
319 319
320 def t(self, f, w, unused): #pragma: no cover 320 def t(self, f, w, unused): #pragma: no cover
321 if w == 'line': 321 if w == 'line':
322 #print "Executing %s @ %d" % (f.f_code.co_filename, f.f_lineno) 322 #print "Executing %s @ %d" % (f.f_code.co_filename, f.f_lineno)
323 self.c[(f.f_code.co_filename, f.f_lineno)] = 1 323 self.c[(f.f_code.co_filename, f.f_lineno)] = 1
324 for c in self.cstack: 324 for c in self.cstack:
325 c[(f.f_code.co_filename, f.f_lineno)] = 1 325 c[(f.f_code.co_filename, f.f_lineno)] = 1
326 return self.t 326 return self.t
327 327
328 def help(self, error=None): #pragma: no cover 328 def help(self, error=None): #pragma: no cover
329 if error: 329 if error:
330 print error 330 print error
331 print 331 print
332 print __doc__ 332 print __doc__
374 "options at the same time." % (i, j)) 374 "options at the same time." % (i, j))
375 375
376 args_needed = (settings.get('execute') 376 args_needed = (settings.get('execute')
377 or settings.get('annotate') 377 or settings.get('annotate')
378 or settings.get('report')) 378 or settings.get('report'))
379 action = (settings.get('erase') 379 action = (settings.get('erase')
380 or settings.get('collect') 380 or settings.get('collect')
381 or args_needed) 381 or args_needed)
382 if not action: 382 if not action:
383 help_fn("You must specify at least one of -e, -x, -c, -r, or -a.") 383 help_fn("You must specify at least one of -e, -x, -c, -r, or -a.")
384 if not args_needed and args: 384 if not args_needed and args:
385 help_fn("Unexpected arguments: %s" % " ".join(args)) 385 help_fn("Unexpected arguments: %s" % " ".join(args))
386 386
387 self.parallel_mode = settings.get('parallel-mode') 387 self.parallel_mode = settings.get('parallel-mode')
388 self.get_ready() 388 self.get_ready()
389 389
390 if settings.get('erase'): 390 if settings.get('erase'):
391 self.erase() 391 self.erase()
399 execfile(sys.argv[0], __main__.__dict__) 399 execfile(sys.argv[0], __main__.__dict__)
400 if settings.get('collect'): 400 if settings.get('collect'):
401 self.collect() 401 self.collect()
402 if not args: 402 if not args:
403 args = self.cexecuted.keys() 403 args = self.cexecuted.keys()
404 404
405 ignore_errors = settings.get('ignore-errors') 405 ignore_errors = settings.get('ignore-errors')
406 show_missing = settings.get('show-missing') 406 show_missing = settings.get('show-missing')
407 directory = settings.get('directory=') 407 directory = settings.get('directory=')
408 408
409 omit = settings.get('omit=') 409 omit = settings.get('omit=')
419 419
420 def use_cache(self, usecache, cache_file=None): 420 def use_cache(self, usecache, cache_file=None):
421 self.usecache = usecache 421 self.usecache = usecache
422 if cache_file and not self.cache: 422 if cache_file and not self.cache:
423 self.cache_default = cache_file 423 self.cache_default = cache_file
424 424
425 def get_ready(self, parallel_mode=False): 425 def get_ready(self, parallel_mode=False):
426 if self.usecache and not self.cache: 426 if self.usecache and not self.cache:
427 self.cache = os.environ.get(self.cache_env, self.cache_default) 427 self.cache = os.environ.get(self.cache_env, self.cache_default)
428 if self.parallel_mode: 428 if self.parallel_mode:
429 self.cache += "." + gethostname() + "." + str(os.getpid()) 429 self.cache += "." + gethostname() + "." + str(os.getpid())
430 self.restore() 430 self.restore()
431 self.analysis_cache = {} 431 self.analysis_cache = {}
432 432
433 def start(self, parallel_mode=False): 433 def start(self, parallel_mode=False):
434 self.get_ready() 434 self.get_ready()
435 if self.nesting == 0: #pragma: no cover 435 if self.nesting == 0: #pragma: no cover
436 sys.settrace(self.t) 436 sys.settrace(self.t)
437 if hasattr(threading, 'settrace'): 437 if hasattr(threading, 'settrace'):
438 threading.settrace(self.t) 438 threading.settrace(self.t)
439 self.nesting += 1 439 self.nesting += 1
440 440
441 def stop(self): 441 def stop(self):
442 self.nesting -= 1 442 self.nesting -= 1
443 if self.nesting == 0: #pragma: no cover 443 if self.nesting == 0: #pragma: no cover
444 sys.settrace(None) 444 sys.settrace(None)
445 if hasattr(threading, 'settrace'): 445 if hasattr(threading, 'settrace'):
459 self.exclude_re += "(" + re + ")" 459 self.exclude_re += "(" + re + ")"
460 460
461 def begin_recursive(self): 461 def begin_recursive(self):
462 self.cstack.append(self.c) 462 self.cstack.append(self.c)
463 self.xstack.append(self.exclude_re) 463 self.xstack.append(self.exclude_re)
464 464
465 def end_recursive(self): 465 def end_recursive(self):
466 self.c = self.cstack.pop() 466 self.c = self.cstack.pop()
467 self.exclude_re = self.xstack.pop() 467 self.exclude_re = self.xstack.pop()
468 468
469 # save(). Save coverage data to the coverage cache. 469 # save(). Save coverage data to the coverage cache.
539 break 539 break
540 cf = os.path.normcase(os.path.abspath(f)) 540 cf = os.path.normcase(os.path.abspath(f))
541 self.canonical_filename_cache[filename] = cf 541 self.canonical_filename_cache[filename] = cf
542 return self.canonical_filename_cache[filename] 542 return self.canonical_filename_cache[filename]
543 543
544 # canonicalize_filenames(). Copy results from "c" to "cexecuted", 544 # canonicalize_filenames(). Copy results from "c" to "cexecuted",
545 # canonicalizing filenames on the way. Clear the "c" map. 545 # canonicalizing filenames on the way. Clear the "c" map.
546 546
547 def canonicalize_filenames(self): 547 def canonicalize_filenames(self):
548 for filename, lineno in self.c.keys(): 548 for filename, lineno in self.c.keys():
549 if filename == '<string>': 549 if filename == '<string>':
571 # Otherwise, return a tuple of (1) the canonical filename of the 571 # Otherwise, return a tuple of (1) the canonical filename of the
572 # source code for the module, (2) a list of lines of statements 572 # source code for the module, (2) a list of lines of statements
573 # in the source code, (3) a list of lines of excluded statements, 573 # in the source code, (3) a list of lines of excluded statements,
574 # and (4), a map of line numbers to multi-line line number ranges, for 574 # and (4), a map of line numbers to multi-line line number ranges, for
575 # statements that cross lines. 575 # statements that cross lines.
576 576
577 def analyze_morf(self, morf): 577 def analyze_morf(self, morf):
578 if self.analysis_cache.has_key(morf): 578 if self.analysis_cache.has_key(morf):
579 return self.analysis_cache[morf] 579 return self.analysis_cache[morf]
580 filename = self.morf_filename(morf) 580 filename = self.morf_filename(morf)
581 ext = os.path.splitext(filename)[1] 581 ext = os.path.splitext(filename)[1]
598 def first_line_of_tree(self, tree): 598 def first_line_of_tree(self, tree):
599 while True: 599 while True:
600 if len(tree) == 3 and type(tree[2]) == type(1): 600 if len(tree) == 3 and type(tree[2]) == type(1):
601 return tree[2] 601 return tree[2]
602 tree = tree[1] 602 tree = tree[1]
603 603
604 def last_line_of_tree(self, tree): 604 def last_line_of_tree(self, tree):
605 while True: 605 while True:
606 if len(tree) == 3 and type(tree[2]) == type(1): 606 if len(tree) == 3 and type(tree[2]) == type(1):
607 return tree[2] 607 return tree[2]
608 tree = tree[-1] 608 tree = tree[-1]
609 609
610 def find_docstring_pass_pair(self, tree, spots): 610 def find_docstring_pass_pair(self, tree, spots):
611 for i in range(1, len(tree)): 611 for i in range(1, len(tree)):
612 if self.is_string_constant(tree[i]) and self.is_pass_stmt(tree[i+1]): 612 if self.is_string_constant(tree[i]) and self.is_pass_stmt(tree[i+1]):
613 first_line = self.first_line_of_tree(tree[i]) 613 first_line = self.first_line_of_tree(tree[i])
614 last_line = self.last_line_of_tree(tree[i+1]) 614 last_line = self.last_line_of_tree(tree[i+1])
615 self.record_multiline(spots, first_line, last_line) 615 self.record_multiline(spots, first_line, last_line)
616 616
617 def is_string_constant(self, tree): 617 def is_string_constant(self, tree):
618 try: 618 try:
619 return tree[0] == symbol.stmt and tree[1][1][1][0] == symbol.expr_stmt 619 return tree[0] == symbol.stmt and tree[1][1][1][0] == symbol.expr_stmt
620 except: 620 except:
621 return False 621 return False
622 622
623 def is_pass_stmt(self, tree): 623 def is_pass_stmt(self, tree):
624 try: 624 try:
625 return tree[0] == symbol.stmt and tree[1][1][1][0] == symbol.pass_stmt 625 return tree[0] == symbol.stmt and tree[1][1][1][0] == symbol.pass_stmt
626 except: 626 except:
627 return False 627 return False
628 628
629 def record_multiline(self, spots, i, j): 629 def record_multiline(self, spots, i, j):
630 for l in range(i, j+1): 630 for l in range(i, j+1):
631 spots[l] = (i, j) 631 spots[l] = (i, j)
632 632
633 def get_suite_spots(self, tree, spots): 633 def get_suite_spots(self, tree, spots):
634 """ Analyze a parse tree to find suite introducers which span a number 634 """ Analyze a parse tree to find suite introducers which span a number
635 of lines. 635 of lines.
636 """ 636 """
637 for i in range(1, len(tree)): 637 for i in range(1, len(tree)):
669 669
670 # "pass" statements are tricky: different versions of Python 670 # "pass" statements are tricky: different versions of Python
671 # treat them differently, especially in the common case of a 671 # treat them differently, especially in the common case of a
672 # function with a doc string and a single pass statement. 672 # function with a doc string and a single pass statement.
673 self.find_docstring_pass_pair(tree[i], spots) 673 self.find_docstring_pass_pair(tree[i], spots)
674 674
675 elif tree[i][0] == symbol.simple_stmt: 675 elif tree[i][0] == symbol.simple_stmt:
676 first_line = self.first_line_of_tree(tree[i]) 676 first_line = self.first_line_of_tree(tree[i])
677 last_line = self.last_line_of_tree(tree[i]) 677 last_line = self.last_line_of_tree(tree[i])
678 if first_line != last_line: 678 if first_line != last_line:
679 self.record_multiline(spots, first_line, last_line) 679 self.record_multiline(spots, first_line, last_line)
694 # are multiline, and where suites begin and end. 694 # are multiline, and where suites begin and end.
695 import parser 695 import parser
696 tree = parser.suite(text+'\n\n').totuple(1) 696 tree = parser.suite(text+'\n\n').totuple(1)
697 self.get_suite_spots(tree, suite_spots) 697 self.get_suite_spots(tree, suite_spots)
698 #print "Suite spots:", suite_spots 698 #print "Suite spots:", suite_spots
699 699
700 # Use the compiler module to parse the text and find the executable 700 # Use the compiler module to parse the text and find the executable
701 # statements. We add newlines to be impervious to final partial lines. 701 # statements. We add newlines to be impervious to final partial lines.
702 statements = {} 702 statements = {}
703 ast = compiler.parse(text+'\n\n') 703 ast = compiler.parse(text+'\n\n')
704 visitor = StatementFindingAstVisitor(statements, excluded, suite_spots) 704 visitor = StatementFindingAstVisitor(statements, excluded, suite_spots)
804 if isinstance(morf, strclass): 804 if isinstance(morf, strclass):
805 globbed.extend(glob.glob(morf)) 805 globbed.extend(glob.glob(morf))
806 else: 806 else:
807 globbed.append(morf) 807 globbed.append(morf)
808 morfs = globbed 808 morfs = globbed
809 809
810 morfs = self.filter_by_prefix(morfs, omit_prefixes) 810 morfs = self.filter_by_prefix(morfs, omit_prefixes)
811 morfs.sort(self.morf_name_compare) 811 morfs.sort(self.morf_name_compare)
812 812
813 max_name = max([5,] + map(len, map(self.morf_name, morfs))) 813 max_name = max([5,] + map(len, map(self.morf_name, morfs)))
814 fmt_name = "%%- %ds " % max_name 814 fmt_name = "%%- %ds " % max_name
871 except KeyboardInterrupt: 871 except KeyboardInterrupt:
872 raise 872 raise
873 except: 873 except:
874 if not ignore_errors: 874 if not ignore_errors:
875 raise 875 raise
876 876
877 def annotate_file(self, filename, statements, excluded, missing, directory=None): 877 def annotate_file(self, filename, statements, excluded, missing, directory=None):
878 source = open(filename, 'r') 878 source = open(filename, 'r')
879 if directory: 879 if directory:
880 dest_file = os.path.join(directory, 880 dest_file = os.path.join(directory,
881 os.path.basename(filename) 881 os.path.basename(filename)
899 if i < len(statements) and statements[i] == lineno: 899 if i < len(statements) and statements[i] == lineno:
900 covered = j >= len(missing) or missing[j] > lineno 900 covered = j >= len(missing) or missing[j] > lineno
901 if self.blank_re.match(line): 901 if self.blank_re.match(line):
902 dest.write(' ') 902 dest.write(' ')
903 elif self.else_re.match(line): 903 elif self.else_re.match(line):
904 # Special logic for lines containing only 'else:'. 904 # Special logic for lines containing only 'else:'.
905 # See [GDR 2001-12-04b, 3.2]. 905 # See [GDR 2001-12-04b, 3.2].
906 if i >= len(statements) and j >= len(missing): 906 if i >= len(statements) and j >= len(missing):
907 dest.write('! ') 907 dest.write('! ')
908 elif i >= len(statements) or j >= len(missing): 908 elif i >= len(statements) or j >= len(missing):
909 dest.write('> ') 909 dest.write('> ')
923 923
924 # Singleton object. 924 # Singleton object.
925 the_coverage = coverage() 925 the_coverage = coverage()
926 926
927 # Module functions call methods in the singleton object. 927 # Module functions call methods in the singleton object.
928 def use_cache(*args, **kw): 928 def use_cache(*args, **kw):
929 return the_coverage.use_cache(*args, **kw) 929 return the_coverage.use_cache(*args, **kw)
930 930
931 def start(*args, **kw): 931 def start(*args, **kw):
932 return the_coverage.start(*args, **kw) 932 return the_coverage.start(*args, **kw)
933 933
934 def stop(*args, **kw): 934 def stop(*args, **kw):
935 return the_coverage.stop(*args, **kw) 935 return the_coverage.stop(*args, **kw)
936 936
937 def erase(*args, **kw): 937 def erase(*args, **kw):
938 return the_coverage.erase(*args, **kw) 938 return the_coverage.erase(*args, **kw)
939 939
940 def begin_recursive(*args, **kw): 940 def begin_recursive(*args, **kw):
941 return the_coverage.begin_recursive(*args, **kw) 941 return the_coverage.begin_recursive(*args, **kw)
942 942
943 def end_recursive(*args, **kw): 943 def end_recursive(*args, **kw):
944 return the_coverage.end_recursive(*args, **kw) 944 return the_coverage.end_recursive(*args, **kw)
945 945
946 def exclude(*args, **kw): 946 def exclude(*args, **kw):
947 return the_coverage.exclude(*args, **kw) 947 return the_coverage.exclude(*args, **kw)
948 948
949 def analysis(*args, **kw): 949 def analysis(*args, **kw):
950 return the_coverage.analysis(*args, **kw) 950 return the_coverage.analysis(*args, **kw)
951 951
952 def analysis2(*args, **kw): 952 def analysis2(*args, **kw):
953 return the_coverage.analysis2(*args, **kw) 953 return the_coverage.analysis2(*args, **kw)
954 954
955 def report(*args, **kw): 955 def report(*args, **kw):
956 return the_coverage.report(*args, **kw) 956 return the_coverage.report(*args, **kw)
957 957
958 def annotate(*args, **kw): 958 def annotate(*args, **kw):
959 return the_coverage.annotate(*args, **kw) 959 return the_coverage.annotate(*args, **kw)
960 960
961 def annotate_file(*args, **kw): 961 def annotate_file(*args, **kw):
962 return the_coverage.annotate_file(*args, **kw) 962 return the_coverage.annotate_file(*args, **kw)
963 963
964 # Save coverage data when Python exits. (The atexit module wasn't 964 # Save coverage data when Python exits. (The atexit module wasn't
965 # introduced until Python 2.0, so use sys.exitfunc when it's not 965 # introduced until Python 2.0, so use sys.exitfunc when it's not
966 # available.) 966 # available.)
1031 # 1031 #
1032 # 2004-12-31 NMB Allow for keyword arguments in the module global functions. 1032 # 2004-12-31 NMB Allow for keyword arguments in the module global functions.
1033 # Thanks, Allen. 1033 # Thanks, Allen.
1034 # 1034 #
1035 # 2005-12-02 NMB Call threading.settrace so that all threads are measured. 1035 # 2005-12-02 NMB Call threading.settrace so that all threads are measured.
1036 # Thanks Martin Fuzzey. Add a file argument to report so that reports can be 1036 # Thanks Martin Fuzzey. Add a file argument to report so that reports can be
1037 # captured to a different destination. 1037 # captured to a different destination.
1038 # 1038 #
1039 # 2005-12-03 NMB coverage.py can now measure itself. 1039 # 2005-12-03 NMB coverage.py can now measure itself.
1040 # 1040 #
1041 # 2005-12-04 NMB Adapted Greg Rogers' patch for using relative filenames, 1041 # 2005-12-04 NMB Adapted Greg Rogers' patch for using relative filenames,