Run mypy on the scripts directory in CI (#8133)

This commit is contained in:
Alex Waygood
2022-06-22 14:13:38 +01:00
committed by GitHub
parent 89f4dee452
commit a527bf27d5
3 changed files with 41 additions and 16 deletions

View File

@@ -139,9 +139,11 @@ def main() -> None:
# The importlib.metadata module is used for projects whose name is different
# from the runtime Python package name (example: PyYAML/yaml)
if sys.version_info >= (3, 8):
packages = [name for name in distribution(project).read_text("top_level.txt").split() if not name.startswith("_")]
if len(packages) == 1:
package = packages[0]
dist = distribution(project).read_text("top_level.txt")
if dist is not None:
packages = [name for name in dist.split() if not name.startswith("_")]
if len(packages) == 1:
package = packages[0]
print(f'Using detected package "{package}" for project "{project}"', file=sys.stderr)
print("Suggestion: Try again with --package argument if that's not what you wanted", file=sys.stderr)

View File

@@ -16,7 +16,7 @@ import urllib.parse
import zipfile
from dataclasses import dataclass
from pathlib import Path
from typing import Any
from typing import Any, TypeVar
import aiohttp
import packaging.specifiers
@@ -24,9 +24,11 @@ import packaging.version
import tomli
import tomlkit
ActionLevelSelf = TypeVar("ActionLevelSelf", bound="ActionLevel")
class ActionLevel(enum.IntEnum):
def __new__(cls, value: int, doc: str):
def __new__(cls: type[ActionLevelSelf], value: int, doc: str) -> ActionLevelSelf:
member = int.__new__(cls, value)
member._value_ = value
member.__doc__ = doc
@@ -191,7 +193,7 @@ TYPESHED_OWNER = "python"
@functools.lru_cache()
def get_origin_owner():
def get_origin_owner() -> str:
output = subprocess.check_output(["git", "remote", "get-url", "origin"], text=True)
match = re.search(r"(git@github.com:|https://github.com/)(?P<owner>[^/]+)/(?P<repo>[^/]+).git", output)
assert match is not None
@@ -199,7 +201,7 @@ def get_origin_owner():
return match.group("owner")
async def create_or_update_pull_request(*, title: str, body: str, branch_name: str, session: aiohttp.ClientSession):
async def create_or_update_pull_request(*, title: str, body: str, branch_name: str, session: aiohttp.ClientSession) -> None:
secret = os.environ["GITHUB_TOKEN"]
if secret.startswith("ghp"):
auth = f"token {secret}"

View File

@@ -174,7 +174,7 @@ def run_mypy(
with tempfile.NamedTemporaryFile("w+") as temp:
temp.write("[mypy]\n")
for dist_conf in configurations:
temp.write("[mypy-%s]\n" % dist_conf.module_name)
temp.write(f"[mypy-{dist_conf.module_name}]\n")
for k, v in dist_conf.values.items():
temp.write(f"{k} = {v}\n")
temp.flush()
@@ -230,19 +230,20 @@ def get_mypy_flags(
strict: bool = False,
test_suite_run: bool = False,
enforce_error_codes: bool = True,
ignore_missing_imports: bool = False,
) -> list[str]:
flags = [
"--python-version",
"%d.%d" % (major, minor),
f"{major}.{minor}",
"--show-traceback",
"--no-implicit-optional",
"--disallow-untyped-decorators",
"--disallow-any-generics",
"--warn-incomplete-stub",
"--show-error-codes",
"--no-error-summary",
"--strict-equality",
]
if strict:
flags.append("--strict")
else:
flags.extend(["--no-implicit-optional", "--disallow-untyped-decorators", "--disallow-any-generics", "--strict-equality"])
if temp_name is not None:
flags.extend(["--config-file", temp_name])
if custom_typeshed:
@@ -251,8 +252,6 @@ def get_mypy_flags(
flags.extend(["--custom-typeshed-dir", os.path.dirname(os.path.dirname(__file__))])
if args.platform:
flags.extend(["--platform", args.platform])
if strict:
flags.append("--strict")
if test_suite_run:
flags.append("--namespace-packages")
if sys.platform == "win32" or args.platform == "win32":
@@ -261,6 +260,8 @@ def get_mypy_flags(
flags.append("--no-site-packages")
if enforce_error_codes:
flags.extend(["--enable-error-code", "ignore-without-code"])
if ignore_missing_imports:
flags.append("--ignore-missing-imports")
return flags
@@ -404,6 +405,22 @@ def test_the_test_scripts(code: int, major: int, minor: int, args: argparse.Name
return TestResults(code, num_test_files_to_test)
def test_scripts_directory(code: int, major: int, minor: int, args: argparse.Namespace) -> TestResults:
files_to_test = list(Path("scripts").rglob("*.py"))
num_test_files_to_test = len(files_to_test)
flags = get_mypy_flags(args, major, minor, None, strict=True, ignore_missing_imports=True)
print(f"Testing the scripts directory ({num_test_files_to_test} files)...")
print("Running mypy " + " ".join(flags))
if args.dry_run:
this_code = 0
else:
this_code = run_mypy_as_subprocess("scripts", flags)
if not this_code:
print_success_msg()
code = max(code, this_code)
return TestResults(code, num_test_files_to_test)
def test_the_test_cases(code: int, major: int, minor: int, args: argparse.Namespace) -> TestResults:
test_case_files = list(map(str, Path("test_cases").rglob("*.py")))
num_test_case_files = len(test_case_files)
@@ -439,7 +456,7 @@ def test_typeshed(code: int, major: int, minor: int, args: argparse.Namespace) -
print()
if minor >= 9:
# Run mypy against our own test suite
# Run mypy against our own test suite and the scripts directory
#
# Skip this on earlier Python versions,
# as we're using new syntax and new functions in some test files
@@ -447,6 +464,10 @@ def test_typeshed(code: int, major: int, minor: int, args: argparse.Namespace) -
files_checked_this_version += test_script_files_checked
print()
code, script_files_checked = test_scripts_directory(code, major, minor, args)
files_checked_this_version += script_files_checked
print()
code, test_case_files_checked = test_the_test_cases(code, major, minor, args)
files_checked_this_version += test_case_files_checked
print()