• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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