#!/usr/bin/python
# Copyright 2014 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import argparse
import sys
import textwrap

is_python3 = bool(sys.version_info.major == 3)


ALL_PRAGMAS = ['no cover', 'no win32', 'python2', 'python3', 'untested',
               'win32']
DEFAULT_PRAGMAS = ALL_PRAGMAS[:]

if is_python3:
    DEFAULT_PRAGMAS.remove('python3')
else:
    DEFAULT_PRAGMAS.remove('python2')

if sys.platform == 'win32':
    DEFAULT_PRAGMAS.remove('win32')
else:
    DEFAULT_PRAGMAS.remove('no win32')


def add_arguments(parser):
    parser.add_argument('--no-pragmas', action='store_true', default=False,
                        help='Show all uncovered lines (no pragmas).')
    parser.add_argument('--path', action='append', default=[],
                        help='Prepend given directories to sys.path.')
    parser.add_argument('--pragma', action='append', default=[],
                        help=('The coverage pragmas to honor '
                              '(defaults to %s).' % DEFAULT_PRAGMAS))
    parser.add_argument('--show', action='append', default=[],
                        help='Show code protected by the specified pragmas '
                             '(uses all pragmas *except* for the ones '
                             'specified).')
    parser.add_argument('--show-missing', action='store_true',
                        default=False, help='Show missing lines.')
    parser.add_argument('--source', action='append', default=[],
                        help='Limit coverage data to the given directories.')

    parser.formatter_class = argparse.RawTextHelpFormatter
    parser.epilog = textwrap.dedent("""
    Valid pragma values are:
        'no cover': The default coverage pragma, this now means we
                    truly cannot cover it.
        'no win32': Code that only executes when not on Windows.
        'python2':  Code that only executes under Python2.
        'python3':  Code that only executees under Python3.
        'untested': Code that does not yet have tests.
        'win32':    Code that only executes on Windows.

    In typ, we aim for 'no cover' to only apply to code that executes only
    when coverage is not available (and hence can never be counted). Most
    code, if annotated at all, should be 'untested', and we should strive
    for 'untested' to not be used, either.
    """)


def argv_from_args(args):
    argv = []
    if args.no_pragmas:
        argv.append('--no-pragmas')
    for arg in args.path:
        argv.extend(['--path', arg])
    for arg in args.show:
        argv.extend(['--show', arg])
    if args.show_missing:
        argv.append('--show-missing')
    for arg in args.source:
        argv.extend(['--source', arg])
    for arg in args.pragma:
        argv.extend(['--pragma', arg])
    return argv


def main(argv=None):
    parser = argparse.ArgumentParser()
    add_arguments(parser)
    args, remaining_args = parser.parse_known_args(argv)

    for path in args.path:
        if path not in sys.path:
            sys.path.append(path)

    try:
        import coverage
        from coverage.execfile import run_python_module, run_python_file
    except ImportError:
        print("Error: coverage is not available.")
        sys.exit(1)

    cov = coverage.coverage(source=args.source)
    cov.erase()
    cov.clear_exclude()

    if args.no_pragmas:
        args.pragma = []

    args.pragma = args.pragma or DEFAULT_PRAGMAS

    if args.show:
        args.show_missing = True
    for pragma in args.show:
        if pragma in args.pragma:
            args.pragma.remove(pragma)

    for pragma in args.pragma:
        cov.exclude('pragma: %s' % pragma)

    ret = 0
    cov.start()
    try:
        if remaining_args[0] == '-m':
            run_python_module(remaining_args[1], remaining_args[1:])
        else:
            run_python_file(remaining_args[0], remaining_args)
    except SystemExit as e:
        ret = e.code
    cov.stop()
    cov.save()
    cov.report(show_missing=args.show_missing)
    return ret


if __name__ == '__main__':
    sys.exit(main())
