From 69957e2fe09183fbcc8bc13018660a70d1497966 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Sun, 11 Jul 2021 13:41:07 +0200 Subject: [PATCH 1/5] Update mypy and isort --- requirements-tests-py3.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements-tests-py3.txt b/requirements-tests-py3.txt index 727e805cec99..ba62a18a56c6 100644 --- a/requirements-tests-py3.txt +++ b/requirements-tests-py3.txt @@ -1,8 +1,8 @@ -mypy==0.902 +mypy==0.910 typed-ast==1.4.3 black==21.6b0 flake8==3.9.2 flake8-bugbear==21.4.3 flake8-pyi==20.10.0 -isort==5.8.0 +isort==5.9.2 pytype==2021.06.17 From c4dbad2b8c39013ea35aed15fb1a0a9a0fcb69f8 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Sun, 11 Jul 2021 13:43:34 +0200 Subject: [PATCH 2/5] Extract run_mypy() --- tests/mypy_test.py | 96 ++++++++++++++++++++++++---------------------- 1 file changed, 51 insertions(+), 45 deletions(-) diff --git a/tests/mypy_test.py b/tests/mypy_test.py index 6f37b24ed947..057b58bd8276 100755 --- a/tests/mypy_test.py +++ b/tests/mypy_test.py @@ -179,18 +179,60 @@ def add_configuration(configurations, seen_dist_configs, distribution): seen_dist_configs.add(distribution) -def main(): - args = parser.parse_args() - - with open(os.path.join(os.path.dirname(__file__), "mypy_exclude_list.txt")) as f: - exclude_list = re.compile("(%s)$" % "|".join(re.findall(r"^\s*([^\s#]+)\s*(?:#.*)?$", f.read(), flags=re.M))) - +def run_mypy(args, configurations, major, minor, files): try: from mypy.main import main as mypy_main except ImportError: print("Cannot import mypy. Did you install it?") sys.exit(1) + with tempfile.NamedTemporaryFile("w+", delete=False) as temp: + temp.write("[mypy]\n") + + for dist_conf in configurations: + temp.write("[mypy-%s]\n" % dist_conf.module_name) + for k, v in dist_conf.values.items(): + temp.write("{} = {}\n".format(k, v)) + + config_file_name = temp.name + flags = [ + "--python-version", "%d.%d" % (major, minor), + "--config-file", config_file_name, + "--strict-optional", + "--no-site-packages", + "--show-traceback", + "--no-implicit-optional", + "--disallow-any-generics", + "--disallow-subclassing-any", + "--warn-incomplete-stub", + # Setting custom typeshed dir prevents mypy from falling back to its bundled + # typeshed in case of stub deletions + "--custom-typeshed-dir", os.path.dirname(os.path.dirname(__file__)), + ] + if args.warn_unused_ignores: + flags.append("--warn-unused-ignores") + if args.platform: + flags.extend(["--platform", args.platform]) + sys.argv = ["mypy"] + flags + files + if args.verbose: + print("running", " ".join(sys.argv)) + else: + print("running mypy", " ".join(flags), "# with", len(files), "files") + try: + if not args.dry_run: + mypy_main("", sys.stdout, sys.stderr) + except SystemExit as err: + return err.code + finally: + os.remove(config_file_name) + return 0 + +def main(): + args = parser.parse_args() + + with open(os.path.join(os.path.dirname(__file__), "mypy_exclude_list.txt")) as f: + exclude_list = re.compile("(%s)$" % "|".join(re.findall(r"^\s*([^\s#]+)\s*(?:#.*)?$", f.read(), flags=re.M))) + versions = [(3, 10), (3, 9), (3, 8), (3, 7), (3, 6), (2, 7)] if args.python_version: versions = [v for v in versions if any(("%d.%d" % v).startswith(av) for av in args.python_version)] @@ -242,46 +284,10 @@ def main(): add_configuration(configurations, seen_dist_configs, distribution) if files: - with tempfile.NamedTemporaryFile("w+", delete=False) as temp: - temp.write("[mypy]\n") - - for dist_conf in configurations: - temp.write("[mypy-%s]\n" % dist_conf.module_name) - for k, v in dist_conf.values.items(): - temp.write("{} = {}\n".format(k, v)) - - config_file_name = temp.name + this_code = run_mypy(args, configurations, major, minor, files) + code = max(code, this_code) runs += 1 - flags = [ - "--python-version", "%d.%d" % (major, minor), - "--config-file", config_file_name, - "--strict-optional", - "--no-site-packages", - "--show-traceback", - "--no-implicit-optional", - "--disallow-any-generics", - "--disallow-subclassing-any", - "--warn-incomplete-stub", - # Setting custom typeshed dir prevents mypy from falling back to its bundled - # typeshed in case of stub deletions - "--custom-typeshed-dir", os.path.dirname(os.path.dirname(__file__)), - ] - if args.warn_unused_ignores: - flags.append("--warn-unused-ignores") - if args.platform: - flags.extend(["--platform", args.platform]) - sys.argv = ["mypy"] + flags + files - if args.verbose: - print("running", " ".join(sys.argv)) - else: - print("running mypy", " ".join(flags), "# with", len(files), "files") - try: - if not args.dry_run: - mypy_main("", sys.stdout, sys.stderr) - except SystemExit as err: - code = max(code, err.code) - finally: - os.remove(config_file_name) + if code: print("--- exit status", code, "---") sys.exit(code) From 376e385a1b6765286dc27ee22e64f643e3b294fd Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Sun, 11 Jul 2021 13:46:53 +0200 Subject: [PATCH 3/5] Make config file removal more robust --- tests/mypy_test.py | 65 ++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/tests/mypy_test.py b/tests/mypy_test.py index 057b58bd8276..55e2446a88ab 100755 --- a/tests/mypy_test.py +++ b/tests/mypy_test.py @@ -186,46 +186,43 @@ def run_mypy(args, configurations, major, minor, files): print("Cannot import mypy. Did you install it?") sys.exit(1) - with tempfile.NamedTemporaryFile("w+", delete=False) as temp: + with tempfile.NamedTemporaryFile("w+") as temp: temp.write("[mypy]\n") - for dist_conf in configurations: temp.write("[mypy-%s]\n" % dist_conf.module_name) for k, v in dist_conf.values.items(): temp.write("{} = {}\n".format(k, v)) - - config_file_name = temp.name - flags = [ - "--python-version", "%d.%d" % (major, minor), - "--config-file", config_file_name, - "--strict-optional", - "--no-site-packages", - "--show-traceback", - "--no-implicit-optional", - "--disallow-any-generics", - "--disallow-subclassing-any", - "--warn-incomplete-stub", - # Setting custom typeshed dir prevents mypy from falling back to its bundled - # typeshed in case of stub deletions - "--custom-typeshed-dir", os.path.dirname(os.path.dirname(__file__)), - ] - if args.warn_unused_ignores: - flags.append("--warn-unused-ignores") - if args.platform: - flags.extend(["--platform", args.platform]) - sys.argv = ["mypy"] + flags + files - if args.verbose: - print("running", " ".join(sys.argv)) - else: - print("running mypy", " ".join(flags), "# with", len(files), "files") - try: + temp.flush() + + flags = [ + "--python-version", "%d.%d" % (major, minor), + "--config-file", temp.name, + "--strict-optional", + "--no-site-packages", + "--show-traceback", + "--no-implicit-optional", + "--disallow-any-generics", + "--disallow-subclassing-any", + "--warn-incomplete-stub", + # Setting custom typeshed dir prevents mypy from falling back to its bundled + # typeshed in case of stub deletions + "--custom-typeshed-dir", os.path.dirname(os.path.dirname(__file__)), + ] + if args.warn_unused_ignores: + flags.append("--warn-unused-ignores") + if args.platform: + flags.extend(["--platform", args.platform]) + sys.argv = ["mypy"] + flags + files + if args.verbose: + print("running", " ".join(sys.argv)) + else: + print("running mypy", " ".join(flags), "# with", len(files), "files") if not args.dry_run: - mypy_main("", sys.stdout, sys.stderr) - except SystemExit as err: - return err.code - finally: - os.remove(config_file_name) - return 0 + try: + mypy_main("", sys.stdout, sys.stderr) + except SystemExit as err: + return err.code + return 0 def main(): args = parser.parse_args() From 98e2c7e76a0fcf99ad79afe41209f602b0be76d3 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Sun, 11 Jul 2021 13:57:09 +0200 Subject: [PATCH 4/5] Run tests for stdlib and third-party separately --- tests/mypy_test.py | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/tests/mypy_test.py b/tests/mypy_test.py index 55e2446a88ab..3ea07179ccfb 100755 --- a/tests/mypy_test.py +++ b/tests/mypy_test.py @@ -179,7 +179,7 @@ def add_configuration(configurations, seen_dist_configs, distribution): seen_dist_configs.add(distribution) -def run_mypy(args, configurations, major, minor, files): +def run_mypy(args, configurations, major, minor, files, *, custom_typeshed=False): try: from mypy.main import main as mypy_main except ImportError: @@ -204,10 +204,14 @@ def run_mypy(args, configurations, major, minor, files): "--disallow-any-generics", "--disallow-subclassing-any", "--warn-incomplete-stub", + ] + if custom_typeshed: # Setting custom typeshed dir prevents mypy from falling back to its bundled # typeshed in case of stub deletions - "--custom-typeshed-dir", os.path.dirname(os.path.dirname(__file__)), - ] + flags.extend([ + "--custom-typeshed-dir", + os.path.dirname(os.path.dirname(__file__)), + ]) if args.warn_unused_ignores: flags.append("--warn-unused-ignores") if args.platform: @@ -240,12 +244,12 @@ def main(): code = 0 runs = 0 for major, minor in versions: - files = [] seen = {"__builtin__", "builtins", "typing"} # Always ignore these. configurations = [] seen_dist_configs = set() - # First add standard library files. + # Test standard library files. + files = [] if major == 2: root = os.path.join("stdlib", "@python2") for name in os.listdir(root): @@ -263,7 +267,13 @@ def main(): if supported_versions[mod][0] <= (major, minor) <= supported_versions[mod][1]: add_files(files, seen, root, name, args, exclude_list) - # Next add files for all third party distributions. + if files: + this_code = run_mypy(args, configurations, major, minor, files, custom_typeshed=True) + code = max(code, this_code) + runs += 1 + + # Test files of all third party distributions. + files = [] for distribution in os.listdir("stubs"): if not is_supported(distribution, major): continue @@ -281,7 +291,8 @@ def main(): add_configuration(configurations, seen_dist_configs, distribution) if files: - this_code = run_mypy(args, configurations, major, minor, files) + # TODO: remove custom_typeshed after mypy 0.920 is released + this_code = run_mypy(args, configurations, major, minor, files, custom_typeshed=True) code = max(code, this_code) runs += 1 From e606a4a1a25934010efe16fbf8348f0d975bab04 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Sun, 11 Jul 2021 14:00:54 +0200 Subject: [PATCH 5/5] Run mypy and isort --- tests/mypy_test.py | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/tests/mypy_test.py b/tests/mypy_test.py index 3ea07179ccfb..441c406ecc4d 100755 --- a/tests/mypy_test.py +++ b/tests/mypy_test.py @@ -16,15 +16,14 @@ import os import re import sys -import toml import tempfile from glob import glob from pathlib import Path from typing import Dict, NamedTuple -parser = argparse.ArgumentParser( - description="Test runner for typeshed. Patterns are unanchored regexps on the full path." -) +import toml + +parser = argparse.ArgumentParser(description="Test runner for typeshed. Patterns are unanchored regexps on the full path.") parser.add_argument("-v", "--verbose", action="count", default=0, help="More output") parser.add_argument("-n", "--dry-run", action="store_true", help="Don't actually run mypy") parser.add_argument("-x", "--exclude", type=str, nargs="*", help="Exclude pattern") @@ -123,10 +122,7 @@ def add_files(files, seen, root, name, args, exclude_list): if match(full, args, exclude_list): seen.add(mod) files.append(full) - elif ( - os.path.isfile(os.path.join(full, "__init__.pyi")) or - os.path.isfile(os.path.join(full, "__init__.py")) - ): + elif os.path.isfile(os.path.join(full, "__init__.pyi")) or os.path.isfile(os.path.join(full, "__init__.py")): for r, ds, fs in os.walk(full): ds.sort() fs.sort() @@ -143,6 +139,7 @@ class MypyDistConf(NamedTuple): module_name: str values: Dict + # The configuration section in the metadata file looks like the following, with multiple module sections possible # [mypy-tests] # [mypy-tests.yaml] @@ -195,8 +192,10 @@ def run_mypy(args, configurations, major, minor, files, *, custom_typeshed=False temp.flush() flags = [ - "--python-version", "%d.%d" % (major, minor), - "--config-file", temp.name, + "--python-version", + "%d.%d" % (major, minor), + "--config-file", + temp.name, "--strict-optional", "--no-site-packages", "--show-traceback", @@ -208,10 +207,7 @@ def run_mypy(args, configurations, major, minor, files, *, custom_typeshed=False if custom_typeshed: # Setting custom typeshed dir prevents mypy from falling back to its bundled # typeshed in case of stub deletions - flags.extend([ - "--custom-typeshed-dir", - os.path.dirname(os.path.dirname(__file__)), - ]) + flags.extend(["--custom-typeshed-dir", os.path.dirname(os.path.dirname(__file__))]) if args.warn_unused_ignores: flags.append("--warn-unused-ignores") if args.platform: @@ -228,6 +224,7 @@ def run_mypy(args, configurations, major, minor, files, *, custom_typeshed=False return err.code return 0 + def main(): args = parser.parse_args()