-
-
Notifications
You must be signed in to change notification settings - Fork 403
change imports to from Y import X as X for compatibility with pyright --verifytypes
#2629
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
Changes from all commits
98ba041
d66b030
98d9db6
881f45b
133b222
bbb4c9b
e0f68fc
2f6cfc3
ffd1984
57f564d
2446507
14cf061
ee9bcb8
8b01b68
fe68911
f18755d
6a562d7
9f4058a
78ee000
0bb769c
2e34089
2c161b9
a78123a
7e12b88
4560301
0a65d5d
ddece80
21b3f75
968ec64
b018e76
811a4b8
54f79ab
bf1d995
d007808
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,159 @@ | ||
| #!/usr/bin/env python3 | ||
| # this file is not run as part of the tests, instead it's run standalone from check.sh | ||
| import subprocess | ||
| import json | ||
| from pathlib import Path | ||
| import sys | ||
| import argparse | ||
|
|
||
| # the result file is not marked in MANIFEST.in so it's not included in the package | ||
| RESULT_FILE = Path(__file__).parent / "verify_types.json" | ||
| failed = False | ||
|
|
||
|
|
||
| # TODO: consider checking manually without `--ignoreexternal`, and/or | ||
| # removing it from the below call later on. | ||
| def run_pyright(): | ||
| return subprocess.run( | ||
| ["pyright", "--verifytypes=trio", "--outputjson", "--ignoreexternal"], | ||
|
A5rocks marked this conversation as resolved.
|
||
| capture_output=True, | ||
| ) | ||
|
|
||
|
|
||
| def check_less_than(key, current_dict, last_dict, /, invert=False): | ||
| global failed | ||
| current = current_dict[key] | ||
| last = last_dict[key] | ||
| assert isinstance(current, (float, int)) | ||
| assert isinstance(last, (float, int)) | ||
| if current == last: | ||
| return | ||
| if (current > last) ^ invert: | ||
| failed = True | ||
| print("ERROR: ", end="") | ||
| if isinstance(current, float): | ||
| strcurrent = f"{current:.4}" | ||
| strlast = f"{last:.4}" | ||
| else: | ||
| strcurrent = str(current) | ||
| strlast = str(last) | ||
| print( | ||
| f"{key} has gone {'down' if current<last else 'up'} from {strlast} to {strcurrent}" | ||
| ) | ||
|
|
||
|
|
||
| def check_zero(key, current_dict): | ||
| global failed | ||
| if current_dict[key] != 0: | ||
| failed = True | ||
| print(f"ERROR: {key} is {current_dict[key]}") | ||
|
|
||
|
|
||
| def main(args: argparse.Namespace) -> int: | ||
| print("*" * 20, "\nChecking type completeness hasn't gone down...") | ||
|
|
||
| res = run_pyright() | ||
| current_result = json.loads(res.stdout) | ||
| py_typed_file: Path | None = None | ||
|
|
||
| # check if py.typed file was missing | ||
| if ( | ||
| current_result["generalDiagnostics"] | ||
| and current_result["generalDiagnostics"][0]["message"] | ||
| == "No py.typed file found" | ||
| ): | ||
| print("creating py.typed") | ||
| py_typed_file = ( | ||
| Path(current_result["typeCompleteness"]["packageRootDirectory"]) | ||
| / "py.typed" | ||
| ) | ||
| py_typed_file.write_text("") | ||
|
|
||
| res = run_pyright() | ||
| current_result = json.loads(res.stdout) | ||
|
|
||
| if res.stderr: | ||
| print(res.stderr) | ||
|
|
||
| last_result = json.loads(RESULT_FILE.read_text()) | ||
|
|
||
| for key in "errorCount", "warningCount", "informationCount": | ||
| check_zero(key, current_result["summary"]) | ||
|
|
||
| for key, invert in ( | ||
| ("missingFunctionDocStringCount", False), | ||
| ("missingClassDocStringCount", False), | ||
| ("missingDefaultParamCount", False), | ||
| ("completenessScore", True), | ||
| ): | ||
| check_less_than( | ||
| key, | ||
| current_result["typeCompleteness"], | ||
| last_result["typeCompleteness"], | ||
| invert=invert, | ||
| ) | ||
|
|
||
| for key, invert in ( | ||
| ("withUnknownType", False), | ||
| ("withAmbiguousType", False), | ||
| ("withKnownType", True), | ||
| ): | ||
| check_less_than( | ||
| key, | ||
| current_result["typeCompleteness"]["exportedSymbolCounts"], | ||
| last_result["typeCompleteness"]["exportedSymbolCounts"], | ||
| invert=invert, | ||
| ) | ||
|
|
||
| assert ( | ||
| res.returncode != 0 | ||
| ), "Fully type complete! Delete this script and instead directly run `pyright --verifytypes=trio` (consider `--ignoreexternal`) in CI and checking exit code." | ||
|
|
||
| if args.overwrite_file: | ||
| print("Overwriting file") | ||
|
|
||
| # don't care about differences in time taken | ||
| del current_result["time"] | ||
| del current_result["summary"]["timeInSec"] | ||
|
|
||
| # don't fail on version diff so pyright updates can be automerged | ||
| del current_result["version"] | ||
|
|
||
| for key in ( | ||
| # don't save path (because that varies between machines) | ||
| "moduleRootDirectory", | ||
| "packageRootDirectory", | ||
| "pyTypedPath", | ||
| ): | ||
| del current_result["typeCompleteness"][key] | ||
|
|
||
| # prune the symbols to only be the name of the symbols with | ||
| # errors, instead of saving a huge file. | ||
| new_symbols = [] | ||
| for symbol in current_result["typeCompleteness"]["symbols"]: | ||
| if symbol["diagnostics"]: | ||
| new_symbols.append(symbol["name"]) | ||
| continue | ||
|
|
||
| current_result["typeCompleteness"]["symbols"] = new_symbols | ||
|
|
||
| with open(RESULT_FILE, "w") as file: | ||
| json.dump(current_result, file, sort_keys=True, indent=2) | ||
| # add newline at end of file so it's easier to manually modify | ||
| file.write("\n") | ||
|
|
||
| if py_typed_file is not None: | ||
| print("deleting py.typed") | ||
| py_typed_file.unlink() | ||
|
|
||
| print("*" * 20) | ||
|
|
||
| return int(failed) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. haha, I guess it's my c++ programming leaking. But yeah I don't mind the int conversion |
||
|
|
||
|
|
||
| parser = argparse.ArgumentParser() | ||
| parser.add_argument("--overwrite-file", action="store_true", default=False) | ||
| args = parser.parse_args() | ||
|
|
||
| assert __name__ == "__main__", "This script should be run standalone" | ||
| sys.exit(main(args)) | ||
Uh oh!
There was an error while loading. Please reload this page.