1"""Sanity test for proper python syntax.""" 2from __future__ import (absolute_import, division, print_function) 3__metaclass__ = type 4 5import os 6 7from .. import types as t 8 9from ..sanity import ( 10 SanityMultipleVersion, 11 SanityMessage, 12 SanityFailure, 13 SanitySuccess, 14 SanityTargets, 15 SANITY_ROOT, 16) 17 18from ..target import ( 19 TestTarget, 20) 21 22from ..util import ( 23 SubprocessError, 24 display, 25 find_python, 26 parse_to_list_of_dict, 27 is_subdir, 28) 29 30from ..util_common import ( 31 run_command, 32) 33 34from ..config import ( 35 SanityConfig, 36) 37 38 39class CompileTest(SanityMultipleVersion): 40 """Sanity test for proper python syntax.""" 41 def filter_targets(self, targets): # type: (t.List[TestTarget]) -> t.List[TestTarget] 42 """Return the given list of test targets, filtered to include only those relevant for the test.""" 43 return [target for target in targets if os.path.splitext(target.path)[1] == '.py' or is_subdir(target.path, 'bin')] 44 45 def test(self, args, targets, python_version): 46 """ 47 :type args: SanityConfig 48 :type targets: SanityTargets 49 :type python_version: str 50 :rtype: TestResult 51 """ 52 settings = self.load_processor(args, python_version) 53 54 paths = [target.path for target in targets.include] 55 56 cmd = [find_python(python_version), os.path.join(SANITY_ROOT, 'compile', 'compile.py')] 57 58 data = '\n'.join(paths) 59 60 display.info(data, verbosity=4) 61 62 try: 63 stdout, stderr = run_command(args, cmd, data=data, capture=True) 64 status = 0 65 except SubprocessError as ex: 66 stdout = ex.stdout 67 stderr = ex.stderr 68 status = ex.status 69 70 if stderr: 71 raise SubprocessError(cmd=cmd, status=status, stderr=stderr, stdout=stdout) 72 73 if args.explain: 74 return SanitySuccess(self.name, python_version=python_version) 75 76 pattern = r'^(?P<path>[^:]*):(?P<line>[0-9]+):(?P<column>[0-9]+): (?P<message>.*)$' 77 78 results = parse_to_list_of_dict(pattern, stdout) 79 80 results = [SanityMessage( 81 message=r['message'], 82 path=r['path'].replace('./', ''), 83 line=int(r['line']), 84 column=int(r['column']), 85 ) for r in results] 86 87 results = settings.process_errors(results, paths) 88 89 if results: 90 return SanityFailure(self.name, messages=results, python_version=python_version) 91 92 return SanitySuccess(self.name, python_version=python_version) 93