|
1 | 1 | #!/usr/bin/env python3 |
2 | 2 | from __future__ import annotations |
3 | 3 |
|
| 4 | +import argparse |
4 | 5 | import json |
5 | 6 | import os |
6 | 7 | import re |
@@ -44,16 +45,28 @@ def _get_strict_params(stub_path: str) -> list[str]: |
44 | 45 |
|
45 | 46 |
|
46 | 47 | def main() -> None: |
47 | | - try: |
48 | | - path = sys.argv[1] |
49 | | - except IndexError: |
50 | | - print("Missing path argument in format <folder>/<stub>", file=sys.stderr) |
51 | | - sys.exit(1) |
52 | | - assert os.path.exists(path), rf"Path {path} does not exist." |
| 48 | + parser = argparse.ArgumentParser() |
| 49 | + parser.add_argument( |
| 50 | + "--run-stubtest", |
| 51 | + action="store_true", |
| 52 | + help=( |
| 53 | + "Run stubtest for the selected package(s). Running stubtest may download and execute arbitrary code from PyPI: " |
| 54 | + "only use this option if you trust the package you are testing." |
| 55 | + ), |
| 56 | + ) |
| 57 | + parser.add_argument("path", help="Path of the stub to test in format <folder>/<stub>, from the root of the project.") |
| 58 | + args = parser.parse_args() |
| 59 | + path: str = args.path |
| 60 | + run_stubtest: bool = args.run_stubtest |
| 61 | + |
53 | 62 | path_tokens = Path(path).parts |
54 | | - assert len(path_tokens) == 2, "Path argument should be in format <folder>/<stub>." |
| 63 | + if len(path_tokens) != 2: |
| 64 | + parser.error("'path' argument should be in format <folder>/<stub>.") |
55 | 65 | folder, stub = path_tokens |
56 | | - assert folder in {"stdlib", "stubs"}, "Only the 'stdlib' and 'stubs' folders are supported." |
| 66 | + if folder not in {"stdlib", "stubs"}: |
| 67 | + parser.error("Only the 'stdlib' and 'stubs' folders are supported.") |
| 68 | + if not os.path.exists(path): |
| 69 | + parser.error(rf"'path' {path} does not exist.") |
57 | 70 | stubtest_result: subprocess.CompletedProcess[bytes] | None = None |
58 | 71 | pytype_result: subprocess.CompletedProcess[bytes] | None = None |
59 | 72 |
|
@@ -99,19 +112,18 @@ def main() -> None: |
99 | 112 | print("\nRunning stubtest...") |
100 | 113 | stubtest_result = subprocess.run([sys.executable, "tests/stubtest_stdlib.py", stub]) |
101 | 114 | else: |
102 | | - run_stubtest_query = ( |
103 | | - f"\nRun stubtest for {stub!r} (Y/N)?\n\n" |
104 | | - "NOTE: Running third-party stubtest involves downloading and executing arbitrary code from PyPI.\n" |
105 | | - f"Only run stubtest if you trust the {stub!r} package.\n" |
106 | | - ) |
107 | | - run_stubtest_answer = input(colored(run_stubtest_query, "yellow")).lower() |
108 | | - while run_stubtest_answer not in {"yes", "no", "y", "n"}: |
109 | | - run_stubtest_answer = input(colored("Invalid response; please try again.\n", "red")).lower() |
110 | | - if run_stubtest_answer in {"yes", "y"}: |
111 | | - print("\nRunning stubtest.") |
| 115 | + if run_stubtest: |
| 116 | + print("\nRunning stubtest...") |
112 | 117 | stubtest_result = subprocess.run([sys.executable, "tests/stubtest_third_party.py", stub]) |
113 | 118 | else: |
114 | | - print(colored(f"\nSkipping stubtest for {stub!r}...", "yellow")) |
| 119 | + print( |
| 120 | + colored( |
| 121 | + f"\nSkipping stubtest for {stub!r}..." |
| 122 | + + "\nNOTE: Running third-party stubtest involves downloading and executing arbitrary code from PyPI." |
| 123 | + + f"\nOnly run stubtest if you trust the {stub!r} package.", |
| 124 | + "yellow", |
| 125 | + ) |
| 126 | + ) |
115 | 127 | else: |
116 | 128 | print(colored("\nSkipping stubtest since mypy failed.", "yellow")) |
117 | 129 |
|
|
0 commit comments