159aec869SMax Reitz#!/usr/bin/env python3 29dd003a9SVladimir Sementsov-Ogievskiy# group: meta 319b7868eSKevin Wolf# 419b7868eSKevin Wolf# Copyright (C) 2020 Red Hat, Inc. 519b7868eSKevin Wolf# 619b7868eSKevin Wolf# This program is free software; you can redistribute it and/or modify 719b7868eSKevin Wolf# it under the terms of the GNU General Public License as published by 819b7868eSKevin Wolf# the Free Software Foundation; either version 2 of the License, or 919b7868eSKevin Wolf# (at your option) any later version. 1019b7868eSKevin Wolf# 1119b7868eSKevin Wolf# This program is distributed in the hope that it will be useful, 1219b7868eSKevin Wolf# but WITHOUT ANY WARRANTY; without even the implied warranty of 1319b7868eSKevin Wolf# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1419b7868eSKevin Wolf# GNU General Public License for more details. 1519b7868eSKevin Wolf# 1619b7868eSKevin Wolf# You should have received a copy of the GNU General Public License 1719b7868eSKevin Wolf# along with this program. If not, see <http://www.gnu.org/licenses/>. 1819b7868eSKevin Wolf 1959aec869SMax Reitzimport os 2059aec869SMax Reitzimport re 2159aec869SMax Reitzimport shutil 2259aec869SMax Reitzimport subprocess 2359aec869SMax Reitzimport sys 24*2d804f55SJohn Snowfrom typing import List, Mapping, Optional 2519b7868eSKevin Wolf 2659aec869SMax Reitzimport iotests 2719b7868eSKevin Wolf 2819b7868eSKevin Wolf 2959aec869SMax Reitz# TODO: Empty this list! 3059aec869SMax ReitzSKIP_FILES = ( 3159aec869SMax Reitz '030', '040', '041', '044', '045', '055', '056', '057', '065', '093', 32636aa64dSMax Reitz '096', '118', '124', '132', '136', '139', '147', '148', '149', 3326db7b23SHanna Reitz '151', '152', '155', '163', '165', '194', '196', '202', 3459aec869SMax Reitz '203', '205', '206', '207', '208', '210', '211', '212', '213', '216', 35f08ef043SVladimir Sementsov-Ogievskiy '218', '219', '224', '228', '234', '235', '236', '237', '238', 3659aec869SMax Reitz '240', '242', '245', '246', '248', '255', '256', '257', '258', '260', 3759aec869SMax Reitz '262', '264', '266', '274', '277', '280', '281', '295', '296', '298', 3859c9466dSMax Reitz '299', '302', '303', '304', '307', 3959aec869SMax Reitz 'nbd-fault-injector.py', 'qcow2.py', 'qcow2_format.py', 'qed.py' 4059aec869SMax Reitz) 4119b7868eSKevin Wolf 4219b7868eSKevin Wolf 4359aec869SMax Reitzdef is_python_file(filename): 4459aec869SMax Reitz if not os.path.isfile(filename): 4559aec869SMax Reitz return False 4619b7868eSKevin Wolf 4759aec869SMax Reitz if filename.endswith('.py'): 4859aec869SMax Reitz return True 4959aec869SMax Reitz 5081dcb9caSHanna Reitz with open(filename, encoding='utf-8') as f: 5159aec869SMax Reitz try: 5259aec869SMax Reitz first_line = f.readline() 5359aec869SMax Reitz return re.match('^#!.*python', first_line) is not None 5459aec869SMax Reitz except UnicodeDecodeError: # Ignore binary files 5559aec869SMax Reitz return False 5659aec869SMax Reitz 5759aec869SMax Reitz 583c1d5012SJohn Snowdef get_test_files() -> List[str]: 59098d983eSHanna Reitz named_tests = [f'tests/{entry}' for entry in os.listdir('tests')] 60098d983eSHanna Reitz check_tests = set(os.listdir('.') + named_tests) - set(SKIP_FILES) 613c1d5012SJohn Snow return list(filter(is_python_file, check_tests)) 623c1d5012SJohn Snow 633c1d5012SJohn Snow 64*2d804f55SJohn Snowdef run_pylint( 65*2d804f55SJohn Snow files: List[str], 66*2d804f55SJohn Snow env: Optional[Mapping[str, str]] = None, 67*2d804f55SJohn Snow) -> None: 6859aec869SMax Reitz 69f1be6219SJohn Snow subprocess.run(('python3', '-m', 'pylint', *files), 7059aec869SMax Reitz env=env, check=False) 7159aec869SMax Reitz 7259aec869SMax Reitz 73*2d804f55SJohn Snowdef run_mypy( 74*2d804f55SJohn Snow files: List[str], 75*2d804f55SJohn Snow env: Optional[Mapping[str, str]] = None, 76*2d804f55SJohn Snow) -> None: 77f1be6219SJohn Snow p = subprocess.run(('python3', '-m', 'mypy', *files), 7859aec869SMax Reitz env=env, 7959aec869SMax Reitz check=False, 8059aec869SMax Reitz stdout=subprocess.PIPE, 8159aec869SMax Reitz stderr=subprocess.STDOUT, 8259aec869SMax Reitz universal_newlines=True) 8359aec869SMax Reitz 8459aec869SMax Reitz if p.returncode != 0: 8559aec869SMax Reitz print(p.stdout) 8659aec869SMax Reitz 8759aec869SMax Reitz 88447aebdaSJohn Snowdef main() -> None: 8959aec869SMax Reitz for linter in ('pylint-3', 'mypy'): 9059aec869SMax Reitz if shutil.which(linter) is None: 9159aec869SMax Reitz iotests.notrun(f'{linter} not found') 9259aec869SMax Reitz 93*2d804f55SJohn Snow files = get_test_files() 94*2d804f55SJohn Snow 95*2d804f55SJohn Snow iotests.logger.debug('Files to be checked:') 96*2d804f55SJohn Snow iotests.logger.debug(', '.join(sorted(files))) 97*2d804f55SJohn Snow 98*2d804f55SJohn Snow env = os.environ.copy() 99*2d804f55SJohn Snow env['MYPYPATH'] = env['PYTHONPATH'] 100*2d804f55SJohn Snow 101*2d804f55SJohn Snow print('=== pylint ===') 102*2d804f55SJohn Snow sys.stdout.flush() 103*2d804f55SJohn Snow run_pylint(files, env=env) 104*2d804f55SJohn Snow 105*2d804f55SJohn Snow print('=== mypy ===') 106*2d804f55SJohn Snow sys.stdout.flush() 107*2d804f55SJohn Snow run_mypy(files, env=env) 108447aebdaSJohn Snow 109447aebdaSJohn Snow 110447aebdaSJohn Snowiotests.script_main(main) 111