• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/python
2# Copyright 2014 Google Inc. All rights reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#    http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16from __future__ import print_function
17
18import argparse
19import sys
20import textwrap
21
22is_python3 = bool(sys.version_info.major == 3)
23
24
25ALL_PRAGMAS = ['no cover', 'no win32', 'python2', 'python3', 'untested',
26               'win32']
27DEFAULT_PRAGMAS = ALL_PRAGMAS[:]
28
29if is_python3:
30    DEFAULT_PRAGMAS.remove('python3')
31else:
32    DEFAULT_PRAGMAS.remove('python2')
33
34if sys.platform == 'win32':
35    DEFAULT_PRAGMAS.remove('win32')
36else:
37    DEFAULT_PRAGMAS.remove('no win32')
38
39
40def add_arguments(parser):
41    parser.add_argument('--no-pragmas', action='store_true', default=False,
42                        help='Show all uncovered lines (no pragmas).')
43    parser.add_argument('--path', action='append', default=[],
44                        help='Prepend given directories to sys.path.')
45    parser.add_argument('--pragma', action='append', default=[],
46                        help=('The coverage pragmas to honor '
47                              '(defaults to %s).' % DEFAULT_PRAGMAS))
48    parser.add_argument('--show', action='append', default=[],
49                        help='Show code protected by the specified pragmas '
50                             '(uses all pragmas *except* for the ones '
51                             'specified).')
52    parser.add_argument('--show-missing', action='store_true',
53                        default=False, help='Show missing lines.')
54    parser.add_argument('--source', action='append', default=[],
55                        help='Limit coverage data to the given directories.')
56
57    parser.formatter_class = argparse.RawTextHelpFormatter
58    parser.epilog = textwrap.dedent("""
59    Valid pragma values are:
60        'no cover': The default coverage pragma, this now means we
61                    truly cannot cover it.
62        'no win32': Code that only executes when not on Windows.
63        'python2':  Code that only executes under Python2.
64        'python3':  Code that only executees under Python3.
65        'untested': Code that does not yet have tests.
66        'win32':    Code that only executes on Windows.
67
68    In typ, we aim for 'no cover' to only apply to code that executes only
69    when coverage is not available (and hence can never be counted). Most
70    code, if annotated at all, should be 'untested', and we should strive
71    for 'untested' to not be used, either.
72    """)
73
74
75def argv_from_args(args):
76    argv = []
77    if args.no_pragmas:
78        argv.append('--no-pragmas')
79    for arg in args.path:
80        argv.extend(['--path', arg])
81    for arg in args.show:
82        argv.extend(['--show', arg])
83    if args.show_missing:
84        argv.append('--show-missing')
85    for arg in args.source:
86        argv.extend(['--source', arg])
87    for arg in args.pragma:
88        argv.extend(['--pragma', arg])
89    return argv
90
91
92def main(argv=None):
93    parser = argparse.ArgumentParser()
94    add_arguments(parser)
95    args, remaining_args = parser.parse_known_args(argv)
96
97    for path in args.path:
98        if path not in sys.path:
99            sys.path.append(path)
100
101    try:
102        import coverage
103        from coverage.execfile import run_python_module, run_python_file
104    except ImportError:
105        print("Error: coverage is not available.")
106        sys.exit(1)
107
108    cov = coverage.coverage(source=args.source)
109    cov.erase()
110    cov.clear_exclude()
111
112    if args.no_pragmas:
113        args.pragma = []
114
115    args.pragma = args.pragma or DEFAULT_PRAGMAS
116
117    if args.show:
118        args.show_missing = True
119    for pragma in args.show:
120        if pragma in args.pragma:
121            args.pragma.remove(pragma)
122
123    for pragma in args.pragma:
124        cov.exclude('pragma: %s' % pragma)
125
126    ret = 0
127    cov.start()
128    try:
129        if remaining_args[0] == '-m':
130            run_python_module(remaining_args[1], remaining_args[1:])
131        else:
132            run_python_file(remaining_args[0], remaining_args)
133    except SystemExit as e:
134        ret = e.code
135    cov.stop()
136    cov.save()
137    cov.report(show_missing=args.show_missing)
138    return ret
139
140
141if __name__ == '__main__':
142    sys.exit(main())
143