mirror of
				https://github.com/pytorch/pytorch.git
				synced 2025-10-31 04:04:57 +08:00 
			
		
		
		
	Automatic fixes that replaces certain list comprehensions with generator ones where appropriate so that they are immediately consumed. This is preview functionality in ruff for rule C419 and it was automatically applied. Co-authored-by: Nikita Shulga <2453524+malfet@users.noreply.github.com> Pull Request resolved: https://github.com/pytorch/pytorch/pull/123960 Approved by: https://github.com/malfet
		
			
				
	
	
		
			167 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			167 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import argparse
 | |
| import re
 | |
| 
 | |
| from common import download_reports, get_testcases, key, open_test_results, skipped_test
 | |
| 
 | |
| from passrate import compute_pass_rate
 | |
| 
 | |
| 
 | |
| """
 | |
| python failures_histogram.py commit_sha
 | |
| 
 | |
| Analyzes skip reasons for Dynamo tests and prints a histogram with repro
 | |
| commands. You'll need to provide the commit_sha for a commit on the main branch,
 | |
| from which we will pull CI test results.
 | |
| 
 | |
| This script requires the `gh` cli. You'll need to install it and then
 | |
| authenticate with it via `gh auth login` before using this script.
 | |
| https://docs.github.com/en/github-cli/github-cli/quickstart
 | |
| """
 | |
| 
 | |
| 
 | |
| def skip_reason(testcase):
 | |
|     for child in testcase.iter():
 | |
|         if child.tag != "skipped":
 | |
|             continue
 | |
|         return child.attrib["message"]
 | |
|     raise AssertionError("no message?")
 | |
| 
 | |
| 
 | |
| def skip_reason_normalized(testcase):
 | |
|     for child in testcase.iter():
 | |
|         if child.tag != "skipped":
 | |
|             continue
 | |
|         result = child.attrib["message"].split("\n")[0]
 | |
|         result = result.split(">")[0]
 | |
|         result = re.sub(r"0x\w+", "0xDEADBEEF", result)
 | |
|         result = re.sub(r"MagicMock id='\d+'", "MagicMock id='0000000000'", result)
 | |
|         result = re.sub(r"issues/\d+", "issues/XXX", result)
 | |
|         result = re.sub(r"torch.Size\(\[.*\]\)", "torch.Size([...])", result)
 | |
|         result = re.sub(
 | |
|             r"Could not get qualified name for class '.*'",
 | |
|             "Could not get qualified name for class",
 | |
|             result,
 | |
|         )
 | |
|         return result
 | |
|     raise AssertionError("no message?")
 | |
| 
 | |
| 
 | |
| def get_failures(testcases):
 | |
|     skipped = [t for t in testcases if skipped_test(t)]
 | |
|     skipped_dict = {}
 | |
|     for s in skipped:
 | |
|         reason = skip_reason_normalized(s)
 | |
|         if reason not in skipped_dict:
 | |
|             skipped_dict[reason] = []
 | |
|         skipped_dict[reason].append(s)
 | |
|     result = []
 | |
|     for s, v in skipped_dict.items():
 | |
|         result.append((len(v), s, v))
 | |
|     result.sort(reverse=True)
 | |
|     return result
 | |
| 
 | |
| 
 | |
| def repro(testcase):
 | |
|     return f"PYTORCH_TEST_WITH_DYNAMO=1 pytest {testcase.attrib['file']} -v -k {testcase.attrib['name']}"
 | |
| 
 | |
| 
 | |
| def all_tests(testcase):
 | |
|     return f"{testcase.attrib['file']}::{testcase.attrib['classname']}.{testcase.attrib['name']}"
 | |
| 
 | |
| 
 | |
| # e.g. "17c5f69852/eager", "17c5f69852/dynamo"
 | |
| def failures_histogram(eager_dir, dynamo_dir, verbose=False, format_issues=False):
 | |
|     fail_keys = compute_pass_rate(eager_dir, dynamo_dir)
 | |
|     xmls = open_test_results(dynamo_dir)
 | |
| 
 | |
|     testcases = get_testcases(xmls)
 | |
|     testcases = [t for t in testcases if key(t) in fail_keys]
 | |
|     dct = get_failures(testcases)
 | |
| 
 | |
|     result = []
 | |
|     for count, reason, testcases in dct:
 | |
|         if verbose:
 | |
|             row = (
 | |
|                 count,
 | |
|                 reason,
 | |
|                 repro(testcases[0]),
 | |
|                 [all_tests(t) for t in testcases],
 | |
|             )
 | |
|         else:
 | |
|             row = (count, reason, repro(testcases[0]))
 | |
|         result.append(row)
 | |
| 
 | |
|     header = (
 | |
|         "(num_failed_tests, error_msg, sample_test, all_tests)"
 | |
|         if verbose
 | |
|         else "(num_failed_tests, error_msg, sample_test)"
 | |
|     )
 | |
|     print(header)
 | |
|     sum_counts = sum(r[0] for r in result)
 | |
|     for row in result:
 | |
|         if format_issues:
 | |
|             print(as_issue(*row))
 | |
|         else:
 | |
|             print(row)
 | |
|     print("[counts]", sum_counts)
 | |
| 
 | |
| 
 | |
| def as_issue(count, msg, repro, tests):
 | |
|     tests = "\n".join(tests)
 | |
|     result = f"""
 | |
| {'-' * 50}
 | |
| {count} Dynamo test are failing with \"{msg}\".
 | |
| 
 | |
| ## Repro
 | |
| 
 | |
| `{repro}`
 | |
| 
 | |
| You will need to remove the skip or expectedFailure before running the repro command.
 | |
| This may be just removing a sentinel file from in
 | |
| [dynamo_expected_failures](https://github.com/pytorch/pytorch/blob/main/test/dynamo_expected_failures)
 | |
| or [dynamo_skips](https://github.com/pytorch/pytorch/blob/main/test/dynamo_skips).
 | |
| 
 | |
| 
 | |
| ## Failing tests
 | |
| 
 | |
| Here's a comprehensive list of tests that fail (as of this issue) with the above message:
 | |
| <details>
 | |
| <summary>Click me</summary>
 | |
| ```
 | |
| {tests}
 | |
| ```
 | |
| </details>
 | |
| """
 | |
|     return result
 | |
| 
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     parser = argparse.ArgumentParser(
 | |
|         prog="failures_histogram",
 | |
|         description="See statistics about skipped Dynamo tests",
 | |
|     )
 | |
|     parser.add_argument(
 | |
|         "commit",
 | |
|         help=(
 | |
|             "The commit sha for the latest commit on a PR from which we will "
 | |
|             "pull CI test results, e.g. 7e5f597aeeba30c390c05f7d316829b3798064a5"
 | |
|         ),
 | |
|     )
 | |
|     parser.add_argument(
 | |
|         "-v", "--verbose", help="Prints all failing test names", action="store_true"
 | |
|     )
 | |
|     parser.add_argument(
 | |
|         "--format-issues",
 | |
|         help="Prints histogram in a way that they can be copy-pasted as a github issues",
 | |
|         action="store_true",
 | |
|     )
 | |
|     args = parser.parse_args()
 | |
| 
 | |
|     # args.format_issues implies verbose=True
 | |
|     verbose = args.verbose
 | |
|     if args.format_issues:
 | |
|         verbose = True
 | |
| 
 | |
|     dynamo311, eager311 = download_reports(args.commit, ("dynamo311", "eager311"))
 | |
|     failures_histogram(eager311, dynamo311, verbose, args.format_issues)
 |