mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	Writing `subprocess.Popen[str]` requires python 3.9+. kunit.py has an assertion that the python version is 3.7+, so we should try to stay backwards compatible. This conflicts a bit with commit1da2e6220e("kunit: tool: fix pre-existing `mypy --strict` errors and update run_checks.py"), since mypy complains like so > kunit_kernel.py:95: error: Missing type parameters for generic type "Popen" [type-arg] Note: `mypy --strict --python-version 3.7` does not work. We could annotate each file with comments like `# mypy: disable-error-code="type-arg" but then we might still get nudged to break back-compat in other files. This patch adds a `mypy.ini` file since it seems like the only way to disable specific error codes for all our files. Note: run_checks.py doesn't need to specify `--config_file mypy.ini`, but I think being explicit is better, particularly since most kernel devs won't be familiar with how mypy works. Fixes:695e260308("kunit: tool: add subscripts for type annotations where appropriate") Reported-by: SeongJae Park <sj@kernel.org> Link: https://lore.kernel.org/linux-kselftest/20230501171520.138753-1-sj@kernel.org Signed-off-by: Daniel Latypov <dlatypov@google.com> Tested-by: SeongJae Park <sj@kernel.org> Reviewed-by: David Gow <davidgow@google.com> Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
		
			
				
	
	
		
			81 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			81 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
#!/usr/bin/env python3
 | 
						|
# SPDX-License-Identifier: GPL-2.0
 | 
						|
#
 | 
						|
# This file runs some basic checks to verify kunit works.
 | 
						|
# It is only of interest if you're making changes to KUnit itself.
 | 
						|
#
 | 
						|
# Copyright (C) 2021, Google LLC.
 | 
						|
# Author: Daniel Latypov <dlatypov@google.com.com>
 | 
						|
 | 
						|
from concurrent import futures
 | 
						|
import datetime
 | 
						|
import os
 | 
						|
import shutil
 | 
						|
import subprocess
 | 
						|
import sys
 | 
						|
import textwrap
 | 
						|
from typing import Dict, List, Sequence
 | 
						|
 | 
						|
ABS_TOOL_PATH = os.path.abspath(os.path.dirname(__file__))
 | 
						|
TIMEOUT = datetime.timedelta(minutes=5).total_seconds()
 | 
						|
 | 
						|
commands: Dict[str, Sequence[str]] = {
 | 
						|
	'kunit_tool_test.py': ['./kunit_tool_test.py'],
 | 
						|
	'kunit smoke test': ['./kunit.py', 'run', '--kunitconfig=lib/kunit', '--build_dir=kunit_run_checks'],
 | 
						|
	'pytype': ['/bin/sh', '-c', 'pytype *.py'],
 | 
						|
	'mypy': ['mypy', '--config-file', 'mypy.ini', '--exclude', '_test.py$', '--exclude', 'qemu_configs/', '.'],
 | 
						|
}
 | 
						|
 | 
						|
# The user might not have mypy or pytype installed, skip them if so.
 | 
						|
# Note: you can install both via `$ pip install mypy pytype`
 | 
						|
necessary_deps : Dict[str, str] = {
 | 
						|
	'pytype': 'pytype',
 | 
						|
	'mypy': 'mypy',
 | 
						|
}
 | 
						|
 | 
						|
def main(argv: Sequence[str]) -> None:
 | 
						|
	if argv:
 | 
						|
		raise RuntimeError('This script takes no arguments')
 | 
						|
 | 
						|
	future_to_name: Dict[futures.Future[None], str] = {}
 | 
						|
	executor = futures.ThreadPoolExecutor(max_workers=len(commands))
 | 
						|
	for name, argv in commands.items():
 | 
						|
		if name in necessary_deps and shutil.which(necessary_deps[name]) is None:
 | 
						|
			print(f'{name}: SKIPPED, {necessary_deps[name]} not in $PATH')
 | 
						|
			continue
 | 
						|
		f = executor.submit(run_cmd, argv)
 | 
						|
		future_to_name[f] = name
 | 
						|
 | 
						|
	has_failures = False
 | 
						|
	print(f'Waiting on {len(future_to_name)} checks ({", ".join(future_to_name.values())})...')
 | 
						|
	for f in  futures.as_completed(future_to_name.keys()):
 | 
						|
		name = future_to_name[f]
 | 
						|
		ex = f.exception()
 | 
						|
		if not ex:
 | 
						|
			print(f'{name}: PASSED')
 | 
						|
			continue
 | 
						|
 | 
						|
		has_failures = True
 | 
						|
		if isinstance(ex, subprocess.TimeoutExpired):
 | 
						|
			print(f'{name}: TIMED OUT')
 | 
						|
		elif isinstance(ex, subprocess.CalledProcessError):
 | 
						|
			print(f'{name}: FAILED')
 | 
						|
		else:
 | 
						|
			print(f'{name}: unexpected exception: {ex}')
 | 
						|
			continue
 | 
						|
 | 
						|
		output = ex.output
 | 
						|
		if output:
 | 
						|
			print(textwrap.indent(output.decode(), '> '))
 | 
						|
	executor.shutdown()
 | 
						|
 | 
						|
	if has_failures:
 | 
						|
		sys.exit(1)
 | 
						|
 | 
						|
 | 
						|
def run_cmd(argv: Sequence[str]) -> None:
 | 
						|
	subprocess.check_output(argv, stderr=subprocess.STDOUT, cwd=ABS_TOOL_PATH, timeout=TIMEOUT)
 | 
						|
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
	main(sys.argv[1:])
 |