1# SPDX-License-Identifier: GPL-2.0-only 2# This file is part of Scapy 3# See https://scapy.net/ for more information 4# Copyright (C) Gabriel Potter <gabriel[]potter[]fr> 5 6""" 7Performs Static typing checks over Scapy's codebase 8""" 9 10# IMPORTANT NOTE 11# 12# Because we are rolling out mypy tests progressively, 13# we currently use --follow-imports=skip. This means that 14# mypy doesn't check consistency between the imports (different files). 15# 16# Once each file has been processed individually, we'll remove that to 17# check the inconsistencies across the files 18 19import io 20import os 21import sys 22 23from mypy.main import main as mypy_main 24 25# Check platform arg 26 27PLATFORM = None 28 29if len(sys.argv) >= 2: 30 if len(sys.argv) > 2: 31 print("Usage: mypy_check.py [platform]") 32 sys.exit(1) 33 PLATFORM = sys.argv[1] 34 35# Load files 36 37localdir = os.path.split(__file__)[0] 38 39with io.open(os.path.join(localdir, "mypy_enabled.txt")) as fd: 40 FILES = [l.strip() for l in fd.readlines() if l.strip() and l[0] != "#"] 41 42if not FILES: 43 print("No files specified. Arborting") 44 sys.exit(1) 45 46# Generate mypy arguments 47 48ARGS = [ 49 # strictness: same as --strict minus --disallow-subclassing-any 50 "--warn-unused-configs", 51 "--disallow-any-generics", 52 "--disallow-untyped-calls", 53 "--disallow-untyped-defs", 54 "--disallow-incomplete-defs", 55 "--check-untyped-defs", 56 "--disallow-untyped-decorators", 57 "--no-implicit-optional", 58 "--warn-redundant-casts", 59 "--warn-unused-ignores", 60 "--warn-return-any", 61 "--no-implicit-reexport", 62 "--strict-equality", 63 "--ignore-missing-imports", 64 # config 65 "--follow-imports=skip", # Remove eventually 66 "--config-file=" + os.path.abspath(os.path.join(localdir, "mypy.ini")), 67 "--show-traceback", 68] + (["--platform=" + PLATFORM] if PLATFORM else []) 69 70if PLATFORM.startswith("linux"): 71 ARGS.extend( 72 [ 73 "--always-true=LINUX", 74 "--always-false=OPENBSD", 75 "--always-false=FREEBSD", 76 "--always-false=NETBSD", 77 "--always-false=DARWIN", 78 "--always-false=WINDOWS", 79 "--always-false=BSD", 80 ] 81 ) 82 FILES = [x for x in FILES if not x.startswith("scapy/arch/windows")] 83elif PLATFORM.startswith("win32"): 84 ARGS.extend( 85 [ 86 "--always-false=LINUX", 87 "--always-false=OPENBSD", 88 "--always-false=FREEBSD", 89 "--always-false=NETBSD", 90 "--always-false=DARWIN", 91 "--always-true=WINDOWS", 92 "--always-false=WINDOWS_XP", 93 "--always-false=BSD", 94 ] 95 ) 96 FILES = [ 97 x 98 for x in FILES 99 if ( 100 x 101 not in { 102 # Disabled on Windows 103 "scapy/arch/unix.py", 104 "scapy/arch/solaris.py", 105 "scapy/contrib/cansocket_native.py", 106 "scapy/contrib/isotp/isotp_native_socket.py", 107 } 108 ) 109 and not x.startswith("scapy/arch/bpf") 110 and not x.startswith("scapy/arch/linux") 111 ] 112else: 113 raise ValueError("Unknown platform") 114 115# Run mypy over the files 116ARGS += [os.path.abspath(f) for f in FILES] 117 118mypy_main(args=ARGS) 119