Ejemplo n.º 1
0
    def test(self, args, targets):
        """
        :type args: SanityConfig
        :type targets: SanityTargets
        :rtype: TestResult
        """
        if args.python_version in UNSUPPORTED_PYTHON_VERSIONS:
            display.warning('Skipping rstcheck on unsupported Python version %s.' % args.python_version)
            return SanitySkipped(self.name)

        ignore_file = os.path.join(ANSIBLE_ROOT, 'test/sanity/rstcheck/ignore-substitutions.txt')
        ignore_substitutions = sorted(set(read_lines_without_comments(ignore_file, remove_blank_lines=True)))

        settings = self.load_settings(args, None)

        paths = sorted(i.path for i in targets.include if os.path.splitext(i.path)[1] in ('.rst',))
        paths = settings.filter_skipped_paths(paths)

        if not paths:
            return SanitySkipped(self.name)

        cmd = [
            args.python_executable,
            '-m', 'rstcheck',
            '--report', 'warning',
            '--ignore-substitutions', ','.join(ignore_substitutions),
        ] + paths

        try:
            stdout, stderr = run_command(args, cmd, capture=True)
            status = 0
        except SubprocessError as ex:
            stdout = ex.stdout
            stderr = ex.stderr
            status = ex.status

        if stdout:
            raise SubprocessError(cmd=cmd, status=status, stderr=stderr, stdout=stdout)

        if args.explain:
            return SanitySuccess(self.name)

        pattern = r'^(?P<path>[^:]*):(?P<line>[0-9]+): \((?P<level>INFO|WARNING|ERROR|SEVERE)/[0-4]\) (?P<message>.*)$'

        results = parse_to_list_of_dict(pattern, stderr)

        results = [SanityMessage(
            message=r['message'],
            path=r['path'],
            line=int(r['line']),
            column=0,
            level=r['level'],
        ) for r in results]

        settings.process_errors(results, paths)

        if results:
            return SanityFailure(self.name, messages=results)

        return SanitySuccess(self.name)
Ejemplo n.º 2
0
    def test(self, args, targets, python_version):
        """
        :type args: SanityConfig
        :type targets: SanityTargets
        :type python_version: str
        :rtype: TestResult
        """
        settings = self.load_processor(args, python_version)

        paths = [target.path for target in targets.include]

        cmd = [
            find_python(python_version),
            os.path.join(SANITY_ROOT, 'compile', 'compile.py')
        ]

        data = '\n'.join(paths)

        display.info(data, verbosity=4)

        try:
            stdout, stderr = run_command(args, cmd, data=data, capture=True)
            status = 0
        except SubprocessError as ex:
            stdout = ex.stdout
            stderr = ex.stderr
            status = ex.status

        if stderr:
            raise SubprocessError(cmd=cmd,
                                  status=status,
                                  stderr=stderr,
                                  stdout=stdout)

        if args.explain:
            return SanitySuccess(self.name, python_version=python_version)

        pattern = r'^(?P<path>[^:]*):(?P<line>[0-9]+):(?P<column>[0-9]+): (?P<message>.*)$'

        results = parse_to_list_of_dict(pattern, stdout)

        results = [
            SanityMessage(
                message=r['message'],
                path=r['path'].replace('./', ''),
                line=int(r['line']),
                column=int(r['column']),
            ) for r in results
        ]

        results = settings.process_errors(results, paths)

        if results:
            return SanityFailure(self.name,
                                 messages=results,
                                 python_version=python_version)

        return SanitySuccess(self.name, python_version=python_version)
Ejemplo n.º 3
0
    def test(self, args, targets, python_version):
        """
        :type args: SanityConfig
        :type targets: SanityTargets
        :type python_version: str
        :rtype: TestResult
        """
        ignore_file = os.path.join(SANITY_ROOT, 'rstcheck', 'ignore-substitutions.txt')
        ignore_substitutions = sorted(set(read_lines_without_comments(ignore_file, remove_blank_lines=True)))

        settings = self.load_processor(args)

        paths = [target.path for target in targets.include]

        cmd = [
            find_python(python_version),
            '-m', 'rstcheck',
            '--report', 'warning',
            '--ignore-substitutions', ','.join(ignore_substitutions),
        ] + paths

        try:
            stdout, stderr = run_command(args, cmd, capture=True)
            status = 0
        except SubprocessError as ex:
            stdout = ex.stdout
            stderr = ex.stderr
            status = ex.status

        if stdout:
            raise SubprocessError(cmd=cmd, status=status, stderr=stderr, stdout=stdout)

        if args.explain:
            return SanitySuccess(self.name)

        pattern = r'^(?P<path>[^:]*):(?P<line>[0-9]+): \((?P<level>INFO|WARNING|ERROR|SEVERE)/[0-4]\) (?P<message>.*)$'

        results = parse_to_list_of_dict(pattern, stderr)

        results = [SanityMessage(
            message=r['message'],
            path=r['path'],
            line=int(r['line']),
            column=0,
            level=r['level'],
        ) for r in results]

        settings.process_errors(results, paths)

        if results:
            return SanityFailure(self.name, messages=results)

        return SanitySuccess(self.name)
Ejemplo n.º 4
0
    def test(self, args, targets, python_version):
        """
        :type args: SanityConfig
        :type targets: SanityTargets
        :type python_version: str
        :rtype: TestResult
        """

        #skip_file = 'test/sanity/import/skip.txt'
        skip_file = os.path.join(
            os.path.dirname(ansible_test.__file__),
            'lib/sanity/import/skip.txt'
        )

        skip_paths = read_lines_without_comments(skip_file, remove_blank_lines=True)
        skip_paths_set = set(skip_paths)

        paths = sorted(
            i.path
            for i in targets.include
            if os.path.splitext(i.path)[1] == '.py' and
            (i.path.startswith('lib/ansible/modules/') or i.path.startswith('lib/ansible/module_utils/')) and
            i.path not in skip_paths_set
        )

        if not paths:
            return SanitySkipped(self.name, python_version=python_version)

        env = ansible_environment(args, color=False)

        # create a clean virtual environment to minimize the available imports beyond the python standard library
        virtual_environment_path = os.path.abspath('test/runner/.tox/minimal-py%s' % python_version.replace('.', ''))
        virtual_environment_bin = os.path.join(virtual_environment_path, 'bin')

        remove_tree(virtual_environment_path)

        python = find_python(python_version)

        cmd = [python, '-m', 'virtualenv', virtual_environment_path, '--python', python, '--no-setuptools', '--no-wheel']

        if not args.coverage:
            cmd.append('--no-pip')

        run_command(args, cmd, capture=True)

        # add the importer to our virtual environment so it can be accessed through the coverage injector
        importer_path = os.path.join(virtual_environment_bin, 'importer.py')
        if not args.explain:
            os.symlink(os.path.abspath('test/sanity/import/importer.py'), importer_path)

        # create a minimal python library
        python_path = os.path.abspath('test/runner/.tox/import/lib')
        ansible_path = os.path.join(python_path, 'ansible')
        ansible_init = os.path.join(ansible_path, '__init__.py')
        ansible_link = os.path.join(ansible_path, 'module_utils')

        if not args.explain:
            make_dirs(ansible_path)

            with open(ansible_init, 'w'):
                pass

            if not os.path.exists(ansible_link):
                os.symlink('../../../../../../lib/ansible/module_utils', ansible_link)

        # activate the virtual environment
        env['PATH'] = '%s:%s' % (virtual_environment_bin, env['PATH'])
        env['PYTHONPATH'] = python_path

        # make sure coverage is available in the virtual environment if needed
        if args.coverage:
            run_command(args, generate_pip_install(['pip'], 'sanity.import', packages=['setuptools']), env=env)
            run_command(args, generate_pip_install(['pip'], 'sanity.import', packages=['coverage']), env=env)
            run_command(args, ['pip', 'uninstall', '--disable-pip-version-check', '-y', 'setuptools'], env=env)
            run_command(args, ['pip', 'uninstall', '--disable-pip-version-check', '-y', 'pip'], env=env)

        cmd = ['importer.py']

        data = '\n'.join(paths)

        display.info(data, verbosity=4)

        results = []

        virtualenv_python = os.path.join(virtual_environment_bin, 'python')

        try:
            stdout, stderr = intercept_command(args, cmd, self.name, env, capture=True, data=data, python_version=python_version, virtualenv=virtualenv_python)

            if stdout or stderr:
                raise SubprocessError(cmd, stdout=stdout, stderr=stderr)
        except SubprocessError as ex:
            if ex.status != 10 or ex.stderr or not ex.stdout:
                raise

            pattern = r'^(?P<path>[^:]*):(?P<line>[0-9]+):(?P<column>[0-9]+): (?P<message>.*)$'

            results = parse_to_list_of_dict(pattern, ex.stdout)

            results = [SanityMessage(
                message=r['message'],
                path=r['path'],
                line=int(r['line']),
                column=int(r['column']),
            ) for r in results]

            results = [result for result in results if result.path not in skip_paths_set]

        if results:
            return SanityFailure(self.name, messages=results, python_version=python_version)

        return SanitySuccess(self.name, python_version=python_version)
Ejemplo n.º 5
0
    def test(self, args, targets):
        """
        :type args: SanityConfig
        :type targets: SanityTargets
        :rtype: TestResult
        """
        skip_paths = read_lines_without_comments(PEP8_SKIP_PATH, optional=True)
        legacy_paths = read_lines_without_comments(PEP8_LEGACY_PATH,
                                                   optional=True)

        legacy_ignore_file = os.path.join(
            INSTALL_ROOT, 'test/sanity/pep8/legacy-ignore.txt')
        legacy_ignore = set(
            read_lines_without_comments(legacy_ignore_file,
                                        remove_blank_lines=True))

        current_ignore_file = os.path.join(
            INSTALL_ROOT, 'test/sanity/pep8/current-ignore.txt')
        current_ignore = sorted(
            read_lines_without_comments(current_ignore_file,
                                        remove_blank_lines=True))

        skip_paths_set = set(skip_paths)
        legacy_paths_set = set(legacy_paths)

        paths = sorted(
            i.path for i in targets.include
            if (os.path.splitext(i.path)[1] == '.py'
                or i.path.startswith('bin/')) and i.path not in skip_paths_set)

        cmd = [
            args.python_executable,
            '-m',
            'pycodestyle',
            '--max-line-length',
            '160',
            '--config',
            '/dev/null',
            '--ignore',
            ','.join(sorted(current_ignore)),
        ] + paths

        if paths:
            try:
                stdout, stderr = run_command(args, cmd, capture=True)
                status = 0
            except SubprocessError as ex:
                stdout = ex.stdout
                stderr = ex.stderr
                status = ex.status

            if stderr:
                raise SubprocessError(cmd=cmd,
                                      status=status,
                                      stderr=stderr,
                                      stdout=stdout)
        else:
            stdout = None

        if args.explain:
            return SanitySuccess(self.name)

        if stdout:
            pattern = '^(?P<path>[^:]*):(?P<line>[0-9]+):(?P<column>[0-9]+): (?P<code>[WE][0-9]{3}) (?P<message>.*)$'

            results = parse_to_list_of_dict(pattern, stdout)
        else:
            results = []

        results = [
            SanityMessage(
                message=r['message'],
                path=r['path'],
                line=int(r['line']),
                column=int(r['column']),
                level='warning' if r['code'].startswith('W') else 'error',
                code=r['code'],
            ) for r in results
        ]

        failed_result_paths = set([result.path for result in results])
        used_paths = set(paths)

        errors = []
        summary = {}

        line = 0

        for path in legacy_paths:
            line += 1

            if not path:
                continue

            if not os.path.exists(path):
                # Keep files out of the list which no longer exist in the repo.
                errors.append(
                    SanityMessage(
                        code='A101',
                        message='Remove "%s" since it does not exist' % path,
                        path=PEP8_LEGACY_PATH,
                        line=line,
                        column=1,
                        confidence=calculate_best_confidence(
                            ((PEP8_LEGACY_PATH, line), (path, 0)),
                            args.metadata) if args.metadata.changes else None,
                    ))

            if path in used_paths and path not in failed_result_paths:
                # Keep files out of the list which no longer require the relaxed rule set.
                errors.append(
                    SanityMessage(
                        code='A201',
                        message=
                        'Remove "%s" since it passes the current rule set' %
                        path,
                        path=PEP8_LEGACY_PATH,
                        line=line,
                        column=1,
                        confidence=calculate_best_confidence(
                            ((PEP8_LEGACY_PATH, line), (path, 0)),
                            args.metadata) if args.metadata.changes else None,
                    ))

        line = 0

        for path in skip_paths:
            line += 1

            if not path:
                continue

            if not os.path.exists(path):
                # Keep files out of the list which no longer exist in the repo.
                errors.append(
                    SanityMessage(
                        code='A101',
                        message='Remove "%s" since it does not exist' % path,
                        path=PEP8_SKIP_PATH,
                        line=line,
                        column=1,
                        confidence=calculate_best_confidence(
                            ((PEP8_SKIP_PATH, line), (path, 0)), args.metadata)
                        if args.metadata.changes else None,
                    ))

        for result in results:
            if result.path in legacy_paths_set and result.code in legacy_ignore:
                # Files on the legacy list are permitted to have errors on the legacy ignore list.
                # However, we want to report on their existence to track progress towards eliminating these exceptions.
                display.info('PEP 8: %s (legacy)' % result, verbosity=3)

                key = '%s %s' % (result.code,
                                 re.sub('[0-9]+', 'NNN', result.message))

                if key not in summary:
                    summary[key] = 0

                summary[key] += 1
            else:
                # Files not on the legacy list and errors not on the legacy ignore list are PEP 8 policy errors.
                errors.append(result)

        if summary:
            lines = []
            count = 0

            for key in sorted(summary):
                count += summary[key]
                lines.append('PEP 8: %5d %s' % (summary[key], key))

            display.info(
                'PEP 8: There were %d different legacy issues found (%d total):'
                % (len(summary), count),
                verbosity=1)
            display.info('PEP 8: Count Code Message', verbosity=1)

            for line in lines:
                display.info(line, verbosity=1)

        if errors:
            return SanityFailure(self.name, messages=errors)

        return SanitySuccess(self.name)
Ejemplo n.º 6
0
    def test(self, args, targets):
        """
        :type args: SanityConfig
        :type targets: SanityTargets
        :rtype: TestResult
        """
        if self.path.endswith('.py'):
            cmd = [args.python_executable, self.path]
        else:
            cmd = [self.path]

        env = ansible_environment(args, color=False)

        pattern = None
        data = None

        if self.config:
            output = self.config.get('output')
            extensions = self.config.get('extensions')
            prefixes = self.config.get('prefixes')
            files = self.config.get('files')
            always = self.config.get('always')
            text = self.config.get('text')
            ignore_changes = self.config.get('ignore_changes')

            if output == 'path-line-column-message':
                pattern = '^(?P<path>[^:]*):(?P<line>[0-9]+):(?P<column>[0-9]+): (?P<message>.*)$'
            elif output == 'path-message':
                pattern = '^(?P<path>[^:]*): (?P<message>.*)$'
            else:
                pattern = ApplicationError('Unsupported output type: %s' %
                                           output)

            if ignore_changes:
                paths = sorted(i.path for i in targets.targets)
                always = False
            else:
                paths = sorted(i.path for i in targets.include)

            if always:
                paths = []

            # short-term work-around for paths being str instead of unicode on python 2.x
            if sys.version_info[0] == 2:
                paths = [p.decode('utf-8') for p in paths]

            if text is not None:
                if text:
                    paths = [p for p in paths if not is_binary_file(p)]
                else:
                    paths = [p for p in paths if is_binary_file(p)]

            if extensions:
                paths = [
                    p for p in paths
                    if os.path.splitext(p)[1] in extensions or (
                        p.startswith('bin/') and '.py' in extensions)
                ]

            if prefixes:
                paths = [
                    p for p in paths if any(
                        p.startswith(pre) for pre in prefixes)
                ]

            if files:
                paths = [p for p in paths if os.path.basename(p) in files]

            if not paths and not always:
                return SanitySkipped(self.name)

            data = '\n'.join(paths)

            if data:
                display.info(data, verbosity=4)

        try:
            stdout, stderr = run_command(args,
                                         cmd,
                                         data=data,
                                         env=env,
                                         capture=True)
            status = 0
        except SubprocessError as ex:
            stdout = ex.stdout
            stderr = ex.stderr
            status = ex.status

        if stdout and not stderr:
            if pattern:
                matches = parse_to_list_of_dict(pattern, stdout)

                messages = [
                    SanityMessage(
                        message=m['message'],
                        path=m['path'],
                        line=int(m.get('line', 0)),
                        column=int(m.get('column', 0)),
                    ) for m in matches
                ]

                return SanityFailure(self.name, messages=messages)

        if stderr or status:
            summary = u'%s' % SubprocessError(
                cmd=cmd, status=status, stderr=stderr, stdout=stdout)
            return SanityFailure(self.name, summary=summary)

        return SanitySuccess(self.name)
Ejemplo n.º 7
0
    def test(self, args, targets):
        """
        :type args: SanityConfig
        :type targets: SanityTargets
        :rtype: TestResult
        """
        current_ignore_file = os.path.join(
            ANSIBLE_ROOT, 'test/sanity/pep8/current-ignore.txt')
        current_ignore = sorted(
            read_lines_without_comments(current_ignore_file,
                                        remove_blank_lines=True))

        settings = self.load_settings(args, 'A100')

        paths = sorted(i.path for i in targets.include
                       if os.path.splitext(i.path)[1] == '.py'
                       or i.path.startswith('bin/'))
        paths = settings.filter_skipped_paths(paths)

        cmd = [
            args.python_executable,
            '-m',
            'pycodestyle',
            '--max-line-length',
            '160',
            '--config',
            '/dev/null',
            '--ignore',
            ','.join(sorted(current_ignore)),
        ] + paths

        if paths:
            try:
                stdout, stderr = run_command(args, cmd, capture=True)
                status = 0
            except SubprocessError as ex:
                stdout = ex.stdout
                stderr = ex.stderr
                status = ex.status

            if stderr:
                raise SubprocessError(cmd=cmd,
                                      status=status,
                                      stderr=stderr,
                                      stdout=stdout)
        else:
            stdout = None

        if args.explain:
            return SanitySuccess(self.name)

        if stdout:
            pattern = '^(?P<path>[^:]*):(?P<line>[0-9]+):(?P<column>[0-9]+): (?P<code>[WE][0-9]{3}) (?P<message>.*)$'

            results = parse_to_list_of_dict(pattern, stdout)
        else:
            results = []

        results = [
            SanityMessage(
                message=r['message'],
                path=r['path'],
                line=int(r['line']),
                column=int(r['column']),
                level='warning' if r['code'].startswith('W') else 'error',
                code=r['code'],
            ) for r in results
        ]

        errors = settings.process_errors(results, paths)

        if errors:
            return SanityFailure(self.name, messages=errors)

        return SanitySuccess(self.name)
Ejemplo n.º 8
0
    def test(self, args, targets, python_version):
        """
        :type args: SanityConfig
        :type targets: SanityTargets
        :type python_version: str
        :rtype: TestResult
        """
        settings = self.load_processor(args, python_version)

        paths = [target.path for target in targets.include]

        env = ansible_environment(args, color=False)

        # create a clean virtual environment to minimize the available imports beyond the python standard library
        virtual_environment_path = os.path.abspath(
            'test/runner/.tox/minimal-py%s' % python_version.replace('.', ''))
        virtual_environment_bin = os.path.join(virtual_environment_path, 'bin')

        remove_tree(virtual_environment_path)

        python = find_python(python_version)

        cmd = [
            python, '-m', 'virtualenv', virtual_environment_path, '--python',
            python, '--no-setuptools', '--no-wheel'
        ]

        if not args.coverage:
            cmd.append('--no-pip')

        run_command(args, cmd, capture=True)

        # add the importer to our virtual environment so it can be accessed through the coverage injector
        importer_path = os.path.join(virtual_environment_bin, 'importer.py')
        if not args.explain:
            os.symlink(
                os.path.abspath(
                    os.path.join(ANSIBLE_ROOT,
                                 'test/sanity/import/importer.py')),
                importer_path)

        # create a minimal python library
        python_path = os.path.abspath('test/runner/.tox/import/lib')
        ansible_path = os.path.join(python_path, 'ansible')
        ansible_init = os.path.join(ansible_path, '__init__.py')
        ansible_link = os.path.join(ansible_path, 'module_utils')

        if not args.explain:
            remove_tree(ansible_path)

            make_dirs(ansible_path)

            with open(ansible_init, 'w'):
                pass

            os.symlink(os.path.join(ANSIBLE_ROOT, 'lib/ansible/module_utils'),
                       ansible_link)

            if data_context().content.collection:
                # inject just enough Ansible code for the collections loader to work on all supported Python versions
                # the __init__.py files are needed only for Python 2.x
                # the empty modules directory is required for the collection loader to generate the synthetic packages list

                make_dirs(os.path.join(ansible_path, 'utils'))
                with open(os.path.join(ansible_path, 'utils/__init__.py'),
                          'w'):
                    pass

                os.symlink(
                    os.path.join(ANSIBLE_ROOT,
                                 'lib/ansible/utils/collection_loader.py'),
                    os.path.join(ansible_path, 'utils/collection_loader.py'))
                os.symlink(
                    os.path.join(ANSIBLE_ROOT,
                                 'lib/ansible/utils/singleton.py'),
                    os.path.join(ansible_path, 'utils/singleton.py'))

                make_dirs(os.path.join(ansible_path, 'modules'))
                with open(os.path.join(ansible_path, 'modules/__init__.py'),
                          'w'):
                    pass

        # activate the virtual environment
        env['PATH'] = '%s:%s' % (virtual_environment_bin, env['PATH'])
        env['PYTHONPATH'] = python_path

        # make sure coverage is available in the virtual environment if needed
        if args.coverage:
            run_command(args,
                        generate_pip_install(['pip'],
                                             'sanity.import',
                                             packages=['setuptools']),
                        env=env)
            run_command(args,
                        generate_pip_install(['pip'],
                                             'sanity.import',
                                             packages=['coverage']),
                        env=env)
            run_command(args, [
                'pip', 'uninstall', '--disable-pip-version-check', '-y',
                'setuptools'
            ],
                        env=env)
            run_command(args, [
                'pip', 'uninstall', '--disable-pip-version-check', '-y', 'pip'
            ],
                        env=env)

        cmd = ['importer.py']

        data = '\n'.join(paths)

        display.info(data, verbosity=4)

        results = []

        virtualenv_python = os.path.join(virtual_environment_bin, 'python')

        try:
            with coverage_context(args):
                stdout, stderr = intercept_command(
                    args,
                    cmd,
                    self.name,
                    env,
                    capture=True,
                    data=data,
                    python_version=python_version,
                    virtualenv=virtualenv_python)

            if stdout or stderr:
                raise SubprocessError(cmd, stdout=stdout, stderr=stderr)
        except SubprocessError as ex:
            if ex.status != 10 or ex.stderr or not ex.stdout:
                raise

            pattern = r'^(?P<path>[^:]*):(?P<line>[0-9]+):(?P<column>[0-9]+): (?P<message>.*)$'

            results = parse_to_list_of_dict(pattern, ex.stdout)

            results = [
                SanityMessage(
                    message=r['message'],
                    path=r['path'],
                    line=int(r['line']),
                    column=int(r['column']),
                ) for r in results
            ]

        results = settings.process_errors(results, paths)

        if results:
            return SanityFailure(self.name,
                                 messages=results,
                                 python_version=python_version)

        return SanitySuccess(self.name, python_version=python_version)
Ejemplo n.º 9
0
    def test(self, args, targets, python_version):
        """
        :type args: SanityConfig
        :type targets: SanityTargets
        :type python_version: str
        :rtype: TestResult
        """
        skip_file = 'test/sanity/compile/python%s-skip.txt' % python_version

        if os.path.exists(skip_file):
            skip_paths = read_lines_without_comments(skip_file)
        else:
            skip_paths = []

        paths = sorted(
            i.path for i in targets.include
            if (os.path.splitext(i.path)[1] == '.py'
                or i.path.startswith('bin/')) and i.path not in skip_paths)

        if not paths:
            return SanitySkipped(self.name, python_version=python_version)

        cmd = [
            find_python(python_version),
            os.path.join(ANSIBLE_ROOT, 'test/sanity/compile/compile.py')
        ]

        data = '\n'.join(paths)

        display.info(data, verbosity=4)

        try:
            stdout, stderr = run_command(args, cmd, data=data, capture=True)
            status = 0
        except SubprocessError as ex:
            stdout = ex.stdout
            stderr = ex.stderr
            status = ex.status

        if stderr:
            raise SubprocessError(cmd=cmd,
                                  status=status,
                                  stderr=stderr,
                                  stdout=stdout)

        if args.explain:
            return SanitySuccess(self.name, python_version=python_version)

        pattern = r'^(?P<path>[^:]*):(?P<line>[0-9]+):(?P<column>[0-9]+): (?P<message>.*)$'

        results = parse_to_list_of_dict(pattern, stdout)

        results = [
            SanityMessage(
                message=r['message'],
                path=r['path'].replace('./', ''),
                line=int(r['line']),
                column=int(r['column']),
            ) for r in results
        ]

        line = 0

        for path in skip_paths:
            line += 1

            if not path:
                continue

            if not os.path.exists(path):
                # Keep files out of the list which no longer exist in the repo.
                results.append(
                    SanityMessage(
                        code='A101',
                        message='Remove "%s" since it does not exist' % path,
                        path=skip_file,
                        line=line,
                        column=1,
                        confidence=calculate_best_confidence(
                            ((skip_file, line), (path, 0)), args.metadata)
                        if args.metadata.changes else None,
                    ))

        if results:
            return SanityFailure(self.name,
                                 messages=results,
                                 python_version=python_version)

        return SanitySuccess(self.name, python_version=python_version)
Ejemplo n.º 10
0
    def test(self, args, targets, python_version):
        """
        :type args: SanityConfig
        :type targets: SanityTargets
        :type python_version: str
        :rtype: TestResult
        """
        cmd = [find_python(python_version), self.path]

        env = ansible_environment(args, color=False)

        pattern = None
        data = None

        settings = self.load_processor(args)

        paths = [target.path for target in targets.include]

        if self.config:
            if self.output == 'path-line-column-message':
                pattern = '^(?P<path>[^:]*):(?P<line>[0-9]+):(?P<column>[0-9]+): (?P<message>.*)$'
            elif self.output == 'path-message':
                pattern = '^(?P<path>[^:]*): (?P<message>.*)$'
            else:
                pattern = ApplicationError('Unsupported output type: %s' %
                                           self.output)

        if not self.no_targets:
            data = '\n'.join(paths)

            if data:
                display.info(data, verbosity=4)

        try:
            stdout, stderr = run_command(args,
                                         cmd,
                                         data=data,
                                         env=env,
                                         capture=True)
            status = 0
        except SubprocessError as ex:
            stdout = ex.stdout
            stderr = ex.stderr
            status = ex.status

        if stdout and not stderr:
            if pattern:
                matches = parse_to_list_of_dict(pattern, stdout)

                messages = [
                    SanityMessage(
                        message=m['message'],
                        path=m['path'],
                        line=int(m.get('line', 0)),
                        column=int(m.get('column', 0)),
                    ) for m in matches
                ]

                messages = settings.process_errors(messages, paths)

                if not messages:
                    return SanitySuccess(self.name)

                return SanityFailure(self.name, messages=messages)

        if stderr or status:
            summary = u'%s' % SubprocessError(
                cmd=cmd, status=status, stderr=stderr, stdout=stdout)
            return SanityFailure(self.name, summary=summary)

        messages = settings.process_errors([], paths)

        if messages:
            return SanityFailure(self.name, messages=messages)

        return SanitySuccess(self.name)