Mercurial > hg
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, |