2
import concurrent.futures
10
from typing import Any, BinaryIO, List, NamedTuple, Optional
13
IS_WINDOWS: bool = os.name == "nt"
16
def eprint(*args: Any, **kwargs: Any) -> None:
17
print(*args, file=sys.stderr, flush=True, **kwargs)
20
class LintSeverity(str, Enum):
27
class LintMessage(NamedTuple):
32
severity: LintSeverity
34
original: Optional[str]
35
replacement: Optional[str]
36
description: Optional[str]
39
def as_posix(name: str) -> str:
40
return name.replace("\\", "/") if IS_WINDOWS else name
48
) -> "subprocess.CompletedProcess[bytes]":
49
logging.debug("$ %s", " ".join(args))
50
start_time = time.monotonic()
52
return subprocess.run(
56
shell=IS_WINDOWS, # So batch scripts are found.
61
end_time = time.monotonic()
62
logging.debug("took %dms", (end_time - start_time) * 1000)
71
) -> "subprocess.CompletedProcess[bytes]":
72
remaining_retries = retries
75
return _run_command(args, stdin=stdin, timeout=timeout)
76
except subprocess.TimeoutExpired as err:
77
if remaining_retries == 0:
79
remaining_retries -= 1
81
"(%s/%s) Retrying because command failed with: %r",
82
retries - remaining_retries,
93
) -> List[LintMessage]:
95
with open(filename, "rb") as f:
97
with open(filename, "rb") as f:
99
[sys.executable, "-mblack", "--stdin-filename", filename, "-"],
104
except subprocess.TimeoutExpired:
111
severity=LintSeverity.ERROR,
116
"black timed out while trying to process a file. "
117
"Please report an issue in pytorch/pytorch with the "
118
"label 'module: lint'"
122
except (OSError, subprocess.CalledProcessError) as err:
129
severity=LintSeverity.ADVICE,
130
name="command-failed",
134
f"Failed due to {err.__class__.__name__}:\n{err}"
135
if not isinstance(err, subprocess.CalledProcessError)
137
"COMMAND (exit code {returncode})\n"
139
"STDERR\n{stderr}\n\n"
142
returncode=err.returncode,
143
command=" ".join(as_posix(x) for x in err.cmd),
144
stderr=err.stderr.decode("utf-8").strip() or "(empty)",
145
stdout=err.stdout.decode("utf-8").strip() or "(empty)",
151
replacement = proc.stdout
152
if original == replacement:
161
severity=LintSeverity.WARNING,
163
original=original.decode("utf-8"),
164
replacement=replacement.decode("utf-8"),
165
description="Run `lintrunner -a` to apply this patch.",
171
parser = argparse.ArgumentParser(
172
description="Format files with black.",
173
fromfile_prefix_chars="@",
179
help="times to retry timed out black",
185
help="seconds to wait for black",
190
help="verbose logging",
195
help="paths to lint",
197
args = parser.parse_args()
200
format="<%(threadName)s:%(levelname)s> %(message)s",
204
if len(args.filenames) < 1000
209
with concurrent.futures.ThreadPoolExecutor(
210
max_workers=os.cpu_count(),
211
thread_name_prefix="Thread",
214
executor.submit(check_file, x, args.retries, args.timeout): x
215
for x in args.filenames
217
for future in concurrent.futures.as_completed(futures):
219
for lint_message in future.result():
220
print(json.dumps(lint_message._asdict()), flush=True)
222
logging.critical('Failed at "%s".', futures[future])
226
if __name__ == "__main__":