pytorch/tools/render_junit.py
Huy Do 347b036350 Apply ufmt linter to all py files under tools (#81285)
With ufmt in place https://github.com/pytorch/pytorch/pull/81157, we can now use it to gradually format all files. I'm breaking this down into multiple smaller batches to avoid too many merge conflicts later on.

This batch (as copied from the current BLACK linter config):
* `tools/**/*.py`

Upcoming batchs:
* `torchgen/**/*.py`
* `torch/package/**/*.py`
* `torch/onnx/**/*.py`
* `torch/_refs/**/*.py`
* `torch/_prims/**/*.py`
* `torch/_meta_registrations.py`
* `torch/_decomp/**/*.py`
* `test/onnx/**/*.py`

Once they are all formatted, BLACK linter will be removed.

Pull Request resolved: https://github.com/pytorch/pytorch/pull/81285
Approved by: https://github.com/suo
2022-07-13 07:59:22 +00:00

105 lines
3.2 KiB
Python

#!/usr/bin/env python3
import argparse
import os
from typing import Any, List, Union
try:
from junitparser import ( # type: ignore[import]
Error,
Failure,
JUnitXml,
TestCase,
TestSuite,
)
except ImportError:
raise ImportError(
"junitparser not found, please install with 'pip install junitparser'"
)
try:
import rich
except ImportError:
print("rich not found, for color output use 'pip install rich'")
def parse_junit_reports(path_to_reports: str) -> List[TestCase]: # type: ignore[no-any-unimported]
def parse_file(path: str) -> List[TestCase]: # type: ignore[no-any-unimported]
try:
return convert_junit_to_testcases(JUnitXml.fromfile(path))
except Exception as err:
rich.print(
f":Warning: [yellow]Warning[/yellow]: Failed to read {path}: {err}"
)
return []
if not os.path.exists(path_to_reports):
raise FileNotFoundError(f"Path '{path_to_reports}', not found")
# Return early if the path provided is just a file
if os.path.isfile(path_to_reports):
return parse_file(path_to_reports)
ret_xml = []
if os.path.isdir(path_to_reports):
for root, _, files in os.walk(path_to_reports):
for fname in [f for f in files if f.endswith("xml")]:
ret_xml += parse_file(os.path.join(root, fname))
return ret_xml
def convert_junit_to_testcases(xml: Union[JUnitXml, TestSuite]) -> List[TestCase]: # type: ignore[no-any-unimported]
testcases = []
for item in xml:
if isinstance(item, TestSuite):
testcases.extend(convert_junit_to_testcases(item))
else:
testcases.append(item)
return testcases
def render_tests(testcases: List[TestCase]) -> None: # type: ignore[no-any-unimported]
num_passed = 0
num_skipped = 0
num_failed = 0
for testcase in testcases:
if not testcase.result:
num_passed += 1
continue
for result in testcase.result:
if isinstance(result, Error):
icon = ":rotating_light: [white on red]ERROR[/white on red]:"
num_failed += 1
elif isinstance(result, Failure):
icon = ":x: [white on red]Failure[/white on red]:"
num_failed += 1
else:
num_skipped += 1
continue
rich.print(
f"{icon} [bold red]{testcase.classname}.{testcase.name}[/bold red]"
)
print(f"{result.text}")
rich.print(f":white_check_mark: {num_passed} [green]Passed[green]")
rich.print(f":dash: {num_skipped} [grey]Skipped[grey]")
rich.print(f":rotating_light: {num_failed} [grey]Failed[grey]")
def parse_args() -> Any:
parser = argparse.ArgumentParser(
description="Render xunit output for failed tests",
)
parser.add_argument(
"report_path",
help="Base xunit reports (single file or directory) to compare to",
)
return parser.parse_args()
def main() -> None:
options = parse_args()
testcases = parse_junit_reports(options.report_path)
render_tests(testcases)
if __name__ == "__main__":
main()