-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Script to run all checks locally #8798
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
JelleZijlstra
merged 29 commits into
python:master
from
Avasam:run-all-checks-single-script
Oct 4, 2022
Merged
Changes from 26 commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
8c6c7ac
Script to run all checks locally
Avasam da2191e
missing return types
Avasam e3d293f
Apply suggestions from code review
Avasam 9a0757c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 850d7fa
summary
Avasam 9f92d0f
Merge branch 'run-all-checks-single-script' of https://github.com/Ava…
Avasam 60f3f86
skip pyright if no npx
Avasam 6b0544d
mypy type ignore
Avasam dc9d4eb
"Skipping" message
Avasam 0241da0
mypy false positive
Avasam 6ad47a3
rename
Avasam 994173a
explicit CompletedProcess type because mypy
Avasam 69c8bd8
Merge branch 'master' into run-all-checks-single-script
AlexWaygood 36aaf68
mention in readme
Avasam 80bc8c7
Apply suggestions from code review
Avasam 430f855
Merge branch 'run-all-checks-single-script' of https://github.com/Ava…
Avasam 169ad68
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 7aa69d3
annotations
Avasam 901a4ad
Merge branch 'run-all-checks-single-script' of https://github.com/Ava…
Avasam f02191e
obsolete comment
Avasam 31a3c10
PR comments
Avasam 22b6cc9
Merge branch 'master' of https://github.com/python/typeshed into run-…
Avasam 4ff0c8d
Merge branch 'master' of https://github.com/python/typeshed into run-…
Avasam 77a3c9b
Set python version and better output
Avasam e8e1c43
Typed main
Avasam 024e696
mention venv bug
Avasam 3ceb0d3
output update
Avasam f9f3154
revert debug change
Avasam fad18bf
Update tests/README.md
Avasam File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
#!/usr/bin/env python3 | ||
from __future__ import annotations | ||
|
||
import json | ||
import re | ||
import subprocess | ||
import sys | ||
from pathlib import Path | ||
|
||
try: | ||
from termcolor import colored | ||
except ImportError: | ||
|
||
def colored(text: str, color: str = "") -> str: # type: ignore[misc] | ||
return text | ||
|
||
|
||
_STRICTER_CONFIG_FILE = "pyrightconfig.stricter.json" | ||
_SUCCESS = colored("Success", "green") | ||
_SKIPPED = colored("Skipped", "yellow") | ||
_FAILED = colored("Failed", "red") | ||
# We're using the oldest supported version because it's the most likely to produce errors | ||
# due to unsupported syntax, feature, or bug in a tool. | ||
_PYTHON_VERSION = "3.7" | ||
|
||
|
||
def _parse_jsonc(json_text: str) -> str: | ||
# strip comments from the file | ||
lines = [line for line in json_text.split("\n") if not line.strip().startswith("//")] | ||
# strip trailing commas from the file | ||
valid_json = re.sub(r",(\s*?[\}\]])", r"\1", "\n".join(lines)) | ||
return valid_json | ||
|
||
|
||
def _get_strict_params(stub_path: str) -> list[str]: | ||
with open(_STRICTER_CONFIG_FILE) as file: | ||
data = json.loads(_parse_jsonc(file.read())) | ||
if stub_path in data["exclude"]: | ||
return [] | ||
return ["-p", _STRICTER_CONFIG_FILE] | ||
|
||
|
||
def main() -> None: | ||
try: | ||
path = sys.argv[1] | ||
AlexWaygood marked this conversation as resolved.
Show resolved
Hide resolved
|
||
except IndexError: | ||
print("Missing path argument in format <folder>/<stub>", file=sys.stderr) | ||
sys.exit(1) | ||
path_tokens = Path(path).parts | ||
assert len(path_tokens) == 2, "Path argument should be in format <folder>/<stub>" | ||
folder, stub = path_tokens | ||
assert folder in {"stdlib", "stubs"}, "Only the 'stdlib' and 'stubs' folders are supported" | ||
stubtest_result: subprocess.CompletedProcess[bytes] | None = None | ||
pytype_result: subprocess.CompletedProcess[bytes] | None = None | ||
|
||
# Run formatters first. Order matters. | ||
print("\nRunning pycln...") | ||
subprocess.run([sys.executable, "-m", "pycln", path, "--all"]) | ||
print("\nRunning isort...") | ||
subprocess.run([sys.executable, "-m", "isort", path]) | ||
print("\nRunning Black...") | ||
black_result = subprocess.run([sys.executable, "-m", "black", path]) | ||
if black_result.returncode == 123: | ||
print("Could not run tests due to an internal error with Black. See above for details.", file=sys.stderr) | ||
sys.exit(black_result.returncode) | ||
|
||
print("\nRunning Flake8...") | ||
flake8_result = subprocess.run([sys.executable, "-m", "flake8", path]) | ||
|
||
print("\nRunning check_consistent.py...") | ||
check_consistent_result = subprocess.run([sys.executable, "tests/check_consistent.py"]) | ||
print("\nRunning check_new_syntax.py...") | ||
check_new_syntax_result = subprocess.run([sys.executable, "tests/check_new_syntax.py"]) | ||
|
||
print(f"\nRunning Pyright on Python {_PYTHON_VERSION}...") | ||
pyright_result = subprocess.run( | ||
[sys.executable, "tests/pyright_test.py", path, "--pythonversion", _PYTHON_VERSION] + _get_strict_params(path), | ||
stderr=subprocess.PIPE, | ||
text=True, | ||
) | ||
if re.match(r"error (runn|find)ing npx", pyright_result.stderr): | ||
print("\nSkipping Pyright tests: npx is not installed or can't be run!") | ||
AlexWaygood marked this conversation as resolved.
Show resolved
Hide resolved
|
||
pyright_returncode = 0 | ||
pyright_skipped = True | ||
else: | ||
print(pyright_result.stderr) | ||
pyright_returncode = pyright_result.returncode | ||
pyright_skipped = False | ||
|
||
print(f"\nRunning mypy for Python {_PYTHON_VERSION}...") | ||
mypy_result = subprocess.run([sys.executable, "tests/mypy_test.py", path, "--python-version", _PYTHON_VERSION]) | ||
# If mypy failed, stubtest will fail without any helpful error | ||
if mypy_result.returncode == 0: | ||
print("\nRunning stubtest...") | ||
if folder == "stdlib": | ||
stubtest_result = subprocess.run([sys.executable, "tests/stubtest_stdlib.py", stub]) | ||
else: | ||
stubtest_result = subprocess.run([sys.executable, "tests/stubtest_third_party.py", stub]) | ||
else: | ||
print("\nSkipping stubtest since mypy failed.") | ||
AlexWaygood marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
if sys.platform == "win32": | ||
print("\nSkipping pytype on Windows. You can run the test with WSL.") | ||
AlexWaygood marked this conversation as resolved.
Show resolved
Hide resolved
|
||
else: | ||
print("\nRunning pytype...") | ||
pytype_result = subprocess.run([sys.executable, "tests/pytype_test.py", path]) | ||
|
||
print(f"\nRunning regression tests for Python {_PYTHON_VERSION}...") | ||
regr_test_result = subprocess.run( | ||
[sys.executable, "tests/regr_test.py", "stdlib" if folder == "stdlib" else stub, "--python-version", _PYTHON_VERSION], | ||
stderr=subprocess.PIPE, | ||
text=True, | ||
) | ||
# No test means they all ran successfully (0 out of 0). Not all 3rd-party stubs have regression tests. | ||
if "No test cases found" in regr_test_result.stderr: | ||
regr_test_returncode = 0 | ||
print(colored(f"\nNo test cases found for '{stub}'!"), "green") | ||
AlexWaygood marked this conversation as resolved.
Show resolved
Hide resolved
|
||
else: | ||
regr_test_returncode = regr_test_result.returncode | ||
print(regr_test_result.stderr) | ||
|
||
any_failure = any( | ||
[ | ||
flake8_result.returncode, | ||
check_consistent_result.returncode, | ||
check_new_syntax_result.returncode, | ||
pyright_returncode, | ||
mypy_result.returncode, | ||
getattr(stubtest_result, "returncode", 0), | ||
getattr(pytype_result, "returncode", 0), | ||
regr_test_returncode, | ||
] | ||
) | ||
|
||
if any_failure: | ||
print(colored("\n\n--- TEST SUMMARY: One or more tests failed. See above for details. ---\n", "red")) | ||
else: | ||
print(colored("\n\n--- TEST SUMMARY: All tests passed! ---\n", "green")) | ||
print("Flake8:", _SUCCESS if flake8_result.returncode == 0 else _FAILED) | ||
print("Check consistent:", _SUCCESS if check_consistent_result.returncode == 0 else _FAILED) | ||
print("Check new syntax:", _SUCCESS if check_new_syntax_result.returncode == 0 else _FAILED) | ||
if pyright_skipped: | ||
print("Pyright:", _SKIPPED) | ||
else: | ||
print("Pyright:", _SUCCESS if pyright_returncode == 0 else _FAILED) | ||
print("mypy:", _SUCCESS if mypy_result.returncode == 0 else _FAILED) | ||
if stubtest_result is None: | ||
print("stubtest:", _SKIPPED) | ||
else: | ||
print("stubtest:", _SUCCESS if stubtest_result.returncode == 0 else _FAILED) | ||
if pytype_result is None: | ||
print("pytype:", _SKIPPED) | ||
else: | ||
print("pytype:", _SUCCESS if pytype_result.returncode == 0 else _FAILED) | ||
print("Regression test:", _SUCCESS if regr_test_returncode == 0 else _FAILED) | ||
|
||
sys.exit(int(any_failure)) | ||
|
||
|
||
if __name__ == "__main__": | ||
try: | ||
main() | ||
except KeyboardInterrupt: | ||
print(colored("\nTests aborted due to KeyboardInterrupt!\n", "red")) | ||
sys.exit(1) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.