OLD | NEW |
1 """Command-line support for Coverage.""" | 1 """Command-line support for Coverage.""" |
2 | 2 |
3 import optparse, sys, traceback | 3 import optparse, os, sys, time, traceback |
4 | 4 |
5 from coverage.backward import sorted # pylint: disable=W0622 | 5 from coverage.backward import sorted # pylint: disable=W0622 |
6 from coverage.execfile import run_python_file, run_python_module | 6 from coverage.execfile import run_python_file, run_python_module |
7 from coverage.misc import CoverageException, ExceptionDuringRun, NoSource | 7 from coverage.misc import CoverageException, ExceptionDuringRun, NoSource |
| 8 from coverage.debug import info_formatter |
8 | 9 |
9 | 10 |
10 class Opts(object): | 11 class Opts(object): |
11 """A namespace class for individual options we'll build parsers from.""" | 12 """A namespace class for individual options we'll build parsers from.""" |
12 | 13 |
13 append = optparse.make_option( | 14 append = optparse.make_option( |
14 '-a', '--append', action='store_false', dest="erase_first", | 15 '-a', '--append', action='store_false', dest="erase_first", |
15 help="Append coverage data to .coverage, otherwise it is started " | 16 help="Append coverage data to .coverage, otherwise it is started " |
16 "clean with each run." | 17 "clean with each run." |
17 ) | 18 ) |
18 branch = optparse.make_option( | 19 branch = optparse.make_option( |
19 '', '--branch', action='store_true', | 20 '', '--branch', action='store_true', |
20 help="Measure branch coverage in addition to statement coverage." | 21 help="Measure branch coverage in addition to statement coverage." |
21 ) | 22 ) |
| 23 debug = optparse.make_option( |
| 24 '', '--debug', action='store', metavar="OPTS", |
| 25 help="Debug options, separated by commas" |
| 26 ) |
22 directory = optparse.make_option( | 27 directory = optparse.make_option( |
23 '-d', '--directory', action='store', metavar="DIR", | 28 '-d', '--directory', action='store', metavar="DIR", |
24 help="Write the output files to DIR." | 29 help="Write the output files to DIR." |
25 ) | 30 ) |
26 fail_under = optparse.make_option( | 31 fail_under = optparse.make_option( |
27 '', '--fail-under', action='store', metavar="MIN", type="int", | 32 '', '--fail-under', action='store', metavar="MIN", type="int", |
28 help="Exit with a status of 2 if the total coverage is less than MIN." | 33 help="Exit with a status of 2 if the total coverage is less than MIN." |
29 ) | 34 ) |
30 help = optparse.make_option( | 35 help = optparse.make_option( |
31 '-h', '--help', action='store_true', | 36 '-h', '--help', action='store_true', |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 | 115 |
111 """ | 116 """ |
112 | 117 |
113 def __init__(self, *args, **kwargs): | 118 def __init__(self, *args, **kwargs): |
114 super(CoverageOptionParser, self).__init__( | 119 super(CoverageOptionParser, self).__init__( |
115 add_help_option=False, *args, **kwargs | 120 add_help_option=False, *args, **kwargs |
116 ) | 121 ) |
117 self.set_defaults( | 122 self.set_defaults( |
118 actions=[], | 123 actions=[], |
119 branch=None, | 124 branch=None, |
| 125 debug=None, |
120 directory=None, | 126 directory=None, |
121 fail_under=None, | 127 fail_under=None, |
122 help=None, | 128 help=None, |
123 ignore_errors=None, | 129 ignore_errors=None, |
124 include=None, | 130 include=None, |
125 omit=None, | 131 omit=None, |
126 parallel_mode=None, | 132 parallel_mode=None, |
127 module=None, | 133 module=None, |
128 pylib=None, | 134 pylib=None, |
129 rcfile=True, | 135 rcfile=True, |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 Opts.show_missing, | 309 Opts.show_missing, |
304 ] + GLOBAL_ARGS, | 310 ] + GLOBAL_ARGS, |
305 usage = "[options] [modules]", | 311 usage = "[options] [modules]", |
306 description = "Report coverage statistics on modules." | 312 description = "Report coverage statistics on modules." |
307 ), | 313 ), |
308 | 314 |
309 'run': CmdOptionParser("execute", | 315 'run': CmdOptionParser("execute", |
310 [ | 316 [ |
311 Opts.append, | 317 Opts.append, |
312 Opts.branch, | 318 Opts.branch, |
| 319 Opts.debug, |
313 Opts.pylib, | 320 Opts.pylib, |
314 Opts.parallel_mode, | 321 Opts.parallel_mode, |
315 Opts.module, | 322 Opts.module, |
316 Opts.timid, | 323 Opts.timid, |
317 Opts.source, | 324 Opts.source, |
318 Opts.omit, | 325 Opts.omit, |
319 Opts.include, | 326 Opts.include, |
320 ] + GLOBAL_ARGS, | 327 ] + GLOBAL_ARGS, |
321 defaults = {'erase_first': True}, | 328 defaults = {'erase_first': True}, |
322 cmd = "run", | 329 cmd = "run", |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 return OK | 404 return OK |
398 | 405 |
399 # Check for conflicts and problems in the options. | 406 # Check for conflicts and problems in the options. |
400 if not self.args_ok(options, args): | 407 if not self.args_ok(options, args): |
401 return ERR | 408 return ERR |
402 | 409 |
403 # Listify the list options. | 410 # Listify the list options. |
404 source = unshell_list(options.source) | 411 source = unshell_list(options.source) |
405 omit = unshell_list(options.omit) | 412 omit = unshell_list(options.omit) |
406 include = unshell_list(options.include) | 413 include = unshell_list(options.include) |
| 414 debug = unshell_list(options.debug) |
407 | 415 |
408 # Do something. | 416 # Do something. |
409 self.coverage = self.covpkg.coverage( | 417 self.coverage = self.covpkg.coverage( |
410 data_suffix = options.parallel_mode, | 418 data_suffix = options.parallel_mode, |
411 cover_pylib = options.pylib, | 419 cover_pylib = options.pylib, |
412 timid = options.timid, | 420 timid = options.timid, |
413 branch = options.branch, | 421 branch = options.branch, |
414 config_file = options.rcfile, | 422 config_file = options.rcfile, |
415 source = source, | 423 source = source, |
416 omit = omit, | 424 omit = omit, |
417 include = include, | 425 include = include, |
| 426 debug = debug, |
418 ) | 427 ) |
419 | 428 |
420 if 'debug' in options.actions: | 429 if 'debug' in options.actions: |
421 return self.do_debug(args) | 430 return self.do_debug(args) |
422 | 431 |
423 if 'erase' in options.actions or options.erase_first: | 432 if 'erase' in options.actions or options.erase_first: |
424 self.coverage.erase() | 433 self.coverage.erase() |
425 else: | 434 else: |
426 self.coverage.load() | 435 self.coverage.load() |
427 | 436 |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
542 | 551 |
543 if 'execute' in options.actions and not args: | 552 if 'execute' in options.actions and not args: |
544 self.help_fn("Nothing to do.") | 553 self.help_fn("Nothing to do.") |
545 return False | 554 return False |
546 | 555 |
547 return True | 556 return True |
548 | 557 |
549 def do_execute(self, options, args): | 558 def do_execute(self, options, args): |
550 """Implementation of 'coverage run'.""" | 559 """Implementation of 'coverage run'.""" |
551 | 560 |
| 561 # Set the first path element properly. |
| 562 old_path0 = sys.path[0] |
| 563 |
552 # Run the script. | 564 # Run the script. |
553 self.coverage.start() | 565 self.coverage.start() |
554 code_ran = True | 566 code_ran = True |
555 try: | 567 try: |
556 try: | 568 try: |
557 if options.module: | 569 if options.module: |
| 570 sys.path[0] = '' |
558 self.run_python_module(args[0], args) | 571 self.run_python_module(args[0], args) |
559 else: | 572 else: |
560 self.run_python_file(args[0], args) | 573 filename = args[0] |
| 574 sys.path[0] = os.path.abspath(os.path.dirname(filename)) |
| 575 self.run_python_file(filename, args) |
561 except NoSource: | 576 except NoSource: |
562 code_ran = False | 577 code_ran = False |
563 raise | 578 raise |
564 finally: | 579 finally: |
565 self.coverage.stop() | 580 self.coverage.stop() |
566 if code_ran: | 581 if code_ran: |
567 self.coverage.save() | 582 self.coverage.save() |
568 | 583 |
| 584 # Restore the old path |
| 585 sys.path[0] = old_path0 |
| 586 |
569 def do_debug(self, args): | 587 def do_debug(self, args): |
570 """Implementation of 'coverage debug'.""" | 588 """Implementation of 'coverage debug'.""" |
571 | 589 |
572 if not args: | 590 if not args: |
573 self.help_fn("What information would you like: data, sys?") | 591 self.help_fn("What information would you like: data, sys?") |
574 return ERR | 592 return ERR |
575 for info in args: | 593 for info in args: |
576 if info == 'sys': | 594 if info == 'sys': |
577 print("-- sys ----------------------------------------") | 595 print("-- sys ----------------------------------------") |
578 for label, info in self.coverage.sysinfo(): | 596 for line in info_formatter(self.coverage.sysinfo()): |
579 if info == []: | 597 print(" %s" % line) |
580 info = "-none-" | |
581 if isinstance(info, list): | |
582 prefix = "%15s:" % label | |
583 for e in info: | |
584 print("%16s %s" % (prefix, e)) | |
585 prefix = "" | |
586 else: | |
587 print("%15s: %s" % (label, info)) | |
588 elif info == 'data': | 598 elif info == 'data': |
589 print("-- data ---------------------------------------") | 599 print("-- data ---------------------------------------") |
590 self.coverage.load() | 600 self.coverage.load() |
591 print("path: %s" % self.coverage.data.filename) | 601 print("path: %s" % self.coverage.data.filename) |
592 print("has_arcs: %r" % self.coverage.data.has_arcs()) | 602 print("has_arcs: %r" % self.coverage.data.has_arcs()) |
593 summary = self.coverage.data.summary(fullpath=True) | 603 summary = self.coverage.data.summary(fullpath=True) |
594 if summary: | 604 if summary: |
595 filenames = sorted(summary.keys()) | 605 filenames = sorted(summary.keys()) |
596 print("\n%d files:" % len(filenames)) | 606 print("\n%d files:" % len(filenames)) |
597 for f in filenames: | 607 for f in filenames: |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
700 | 710 |
701 def main(argv=None): | 711 def main(argv=None): |
702 """The main entry point to Coverage. | 712 """The main entry point to Coverage. |
703 | 713 |
704 This is installed as the script entry point. | 714 This is installed as the script entry point. |
705 | 715 |
706 """ | 716 """ |
707 if argv is None: | 717 if argv is None: |
708 argv = sys.argv[1:] | 718 argv = sys.argv[1:] |
709 try: | 719 try: |
| 720 start = time.clock() |
710 status = CoverageScript().command_line(argv) | 721 status = CoverageScript().command_line(argv) |
| 722 end = time.clock() |
| 723 if 0: |
| 724 print("time: %.3fs" % (end - start)) |
711 except ExceptionDuringRun: | 725 except ExceptionDuringRun: |
712 # An exception was caught while running the product code. The | 726 # An exception was caught while running the product code. The |
713 # sys.exc_info() return tuple is packed into an ExceptionDuringRun | 727 # sys.exc_info() return tuple is packed into an ExceptionDuringRun |
714 # exception. | 728 # exception. |
715 _, err, _ = sys.exc_info() | 729 _, err, _ = sys.exc_info() |
716 traceback.print_exception(*err.args) | 730 traceback.print_exception(*err.args) |
717 status = ERR | 731 status = ERR |
718 except CoverageException: | 732 except CoverageException: |
719 # A controlled error inside coverage.py: print the message to the user. | 733 # A controlled error inside coverage.py: print the message to the user. |
720 _, err, _ = sys.exc_info() | 734 _, err, _ = sys.exc_info() |
721 print(err) | 735 print(err) |
722 status = ERR | 736 status = ERR |
723 except SystemExit: | 737 except SystemExit: |
724 # The user called `sys.exit()`. Exit with their argument, if any. | 738 # The user called `sys.exit()`. Exit with their argument, if any. |
725 _, err, _ = sys.exc_info() | 739 _, err, _ = sys.exc_info() |
726 if err.args: | 740 if err.args: |
727 status = err.args[0] | 741 status = err.args[0] |
728 else: | 742 else: |
729 status = None | 743 status = None |
730 return status | 744 return status |
OLD | NEW |