




import re
import time
from typing import Optional

import IPython.display as disp

from ..trainer_callback import TrainerCallback
from ..trainer_utils import IntervalStrategy, has_length


def 						lowerCamelCase__    (		_A							):







	'''simple docstring'''





	snake_case_		    =     int(_A							)
	snake_case_    ,      snake_case_    ,      snake_case_		    =     t // 3600, (t // 60) % 60, t % 60
	return f"{h}:{m:02d}:{s:02d}" if h != 0 else f"{m:02d}:{s:02d}"


def 						lowerCamelCase__    (		_A     ,	_A     ,	_A     ,	_A     ,	_A=300							):







	'''simple docstring'''





	return f"\n    <div>\n      {prefix}\n      <progress value='{value}' max='{total}' style='width:{width}px; height:20px; vertical-align: middle;'></progress>\n      {label}\n    </div>\n    "


def 						lowerCamelCase__    (		_A							):







	'''simple docstring'''





	snake_case_		    =     "<table border=\"1\" class=\"dataframe\">\n"
	html_code += """  <thead>\n <tr style="text-align: left;">\n"""
	for i in items[0]:
		html_code += f"      <th>{i}</th>\n"
	html_code += "    </tr>\n  </thead>\n  <tbody>\n"
	for line in items[1:]:
		html_code += "    <tr>\n"
		for elt in line:
			snake_case_		    =     f"{elt:.6f}" if isinstance(_A     ,	_A							) else str(_A							)
			html_code += f"      <td>{elt}</td>\n"
		html_code += "    </tr>\n"
	html_code += "  </tbody>\n</table><p>"
	return html_code
class 		UpperCAmelCase   :







						'''simple docstring'''





						lowerCAmelCase_     		=   5
						lowerCAmelCase_     		=   0.2






						def __init__(						self							:     str       ,	__lowercase							:     int       ,	__lowercase							:     Optional[str] = None       ,	__lowercase							:     bool = True       ,	__lowercase							:     Optional["NotebookTrainingTracker"] = None       ,	__lowercase							:     int = 3_00       ,	):






							"""simple docstring"""






							snake_case_		    =     total
							snake_case_		    =     "" if prefix is None else prefix
							snake_case_		    =     leave
							snake_case_		    =     parent
							snake_case_		    =     width
							snake_case_		    =     None
							snake_case_		    =     None
							snake_case_		    =     None






						def        snake_case__						(						self							:     str       ,	__lowercase							:     int       ,	__lowercase							:     bool = False       ,	__lowercase							:     str = None						):






							"""simple docstring"""






							snake_case_		    =     value
							if comment is not None:
								snake_case_		    =     comment
							if self.last_value is None:
								snake_case_		    =     snake_case_		    =     time.time()
								snake_case_		    =     snake_case_		    =     value
								snake_case_		    =     snake_case_		    =     None
								snake_case_		    =     self.warmup
								snake_case_		    =     1
								self.update_bar(__lowercase						)
							elif value <= self.last_value and not force_update:
								return
							elif force_update or self.first_calls > 0 or value >= min(self.last_value + self.wait_for       ,	self.total						):
								if self.first_calls > 0:
									self.first_calls -= 1
								snake_case_		    =     time.time()
								snake_case_		    =     current_time - self.start_time
								# We could have value = self.start_value if the update is called twixe with the same start value.
								if value > self.start_value:
									snake_case_		    =     self.elapsed_time / (value - self.start_value)
								else:
									snake_case_		    =     None
								if value >= self.total:
									snake_case_		    =     self.total
									snake_case_		    =     None
									if not self.leave:
										self.close()
								elif self.average_time_per_item is not None:
									snake_case_		    =     self.average_time_per_item * (self.total - value)
								self.update_bar(__lowercase						)
								snake_case_		    =     value
								snake_case_		    =     current_time
								if self.average_time_per_item is None:
									snake_case_		    =     1
								else:
									snake_case_		    =     max(int(self.update_every / self.average_time_per_item						)       ,	1						)






						def        snake_case__						(						self							:     int       ,	__lowercase							:     Union[str, Any]       ,	__lowercase							:     List[str]=None						):






							"""simple docstring"""






							snake_case_		    =     " " * (len(str(self.total						)						) - len(str(__lowercase						)						)) + str(__lowercase						)
							if self.elapsed_time is None:
								snake_case_		    =     f"[{spaced_value}/{self.total} : < :"
							elif self.predicted_remaining is None:
								snake_case_		    =     f"[{spaced_value}/{self.total} {format_time(self.elapsed_time						)}"
							else:
								snake_case_		    =     (
								    f"[{spaced_value}/{self.total} {format_time(self.elapsed_time						)} <"
								    f" {format_time(self.predicted_remaining						)}"
								)
								self.label += f", {1/self.average_time_per_item:.2f} it/s"
							self.label += "]" if self.comment is None or len(self.comment						) == 0 else f", {self.comment}]"
							self.display()






						def        snake_case__						(						self							:     Dict						):






							"""simple docstring"""






							snake_case_		    =     html_progress_bar(self.value       ,	self.total       ,	self.prefix       ,	self.label       ,	self.width						)
							if self.parent is not None:
								# If this is a child bar, the parent will take care of the display.
								self.parent.display()
								return
							if self.output is None:
								snake_case_		    =     disp.display(disp.HTML(self.html_code						)       ,	display_id=__lowercase						)
							else:
								self.output.update(disp.HTML(self.html_code						)						)






						def        snake_case__						(						self							:     Dict						):






							"""simple docstring"""






							if self.parent is None and self.output is not None:
								self.output.update(disp.HTML(""						)						)







class 		UpperCAmelCase   (				UpperCAmelCase__			):







						'''simple docstring'''





						def __init__(						self							:     str       ,	__lowercase							:     int       ,	__lowercase							:     Any=None						):






							"""simple docstring"""






							super().__init__(__lowercase						)
							snake_case_		    =     None if column_names is None else [column_names]
							snake_case_		    =     None






						def        snake_case__						(						self							:     List[Any]						):






							"""simple docstring"""






							snake_case_		    =     html_progress_bar(self.value       ,	self.total       ,	self.prefix       ,	self.label       ,	self.width						)
							if self.inner_table is not None:
								self.html_code += text_to_html_table(self.inner_table						)
							if self.child_bar is not None:
								self.html_code += self.child_bar.html_code
							if self.output is None:
								snake_case_		    =     disp.display(disp.HTML(self.html_code						)       ,	display_id=__lowercase						)
							else:
								self.output.update(disp.HTML(self.html_code						)						)






						def        snake_case__						(						self							:     Optional[Any]       ,	__lowercase							:     Optional[int]						):






							"""simple docstring"""






							if self.inner_table is None:
								snake_case_		    =     [list(values.keys()						), list(values.values()						)]
							else:
								snake_case_		    =     self.inner_table[0]
								if len(self.inner_table						) == 1:
									# We give a chance to update the column names at the first iteration
									for key in values.keys():
										if key not in columns:
											columns.append(__lowercase						)
									snake_case_		    =     columns
								self.inner_table.append([values[c] for c in columns]						)






						def        snake_case__						(						self							:     str       ,	__lowercase							:     Optional[int]       ,	__lowercase							:     int=None       ,	__lowercase							:     Any=3_00						):






							"""simple docstring"""






							snake_case_		    =     NotebookProgressBar(__lowercase       ,	prefix=__lowercase       ,	parent=self       ,	width=__lowercase						)
							return self.child_bar






						def        snake_case__						(						self							:     Any						):






							"""simple docstring"""






							snake_case_		    =     None
							self.display()







class 		UpperCAmelCase   (				UpperCAmelCase__			):







						'''simple docstring'''





						def __init__(						self							:     str						):






							"""simple docstring"""






							snake_case_		    =     None
							snake_case_		    =     None
							snake_case_		    =     False






						def        snake_case__						(						self							:     int       ,	__lowercase							:     List[Any]       ,	__lowercase							:     List[Any]       ,	__lowercase							:     Dict       ,	**__lowercase							:     Union[str, Any]						):






							"""simple docstring"""






							snake_case_		    =     "Epoch" if args.evaluation_strategy == IntervalStrategy.EPOCH else "Step"
							snake_case_		    =     0
							snake_case_		    =     0
							snake_case_		    =     [self.first_column] + ["Training Loss"]
							if args.evaluation_strategy != IntervalStrategy.NO:
								column_names.append("Validation Loss"						)
							snake_case_		    =     NotebookTrainingTracker(state.max_steps       ,	__lowercase						)






						def        snake_case__						(						self							:     int       ,	__lowercase							:     Tuple       ,	__lowercase							:     List[Any]       ,	__lowercase							:     Union[str, Any]       ,	**__lowercase							:     Optional[Any]						):






							"""simple docstring"""






							snake_case_		    =     int(state.epoch						) if int(state.epoch						) == state.epoch else f"{state.epoch:.2f}"
							self.training_tracker.update(
							    state.global_step + 1       ,	comment=f"Epoch {epoch}/{state.num_train_epochs}"       ,	force_update=self._force_next_update       ,	)
							snake_case_		    =     False






						def        snake_case__						(						self							:     Optional[Any]       ,	__lowercase							:     Union[str, Any]       ,	__lowercase							:     str       ,	__lowercase							:     Union[str, Any]       ,	__lowercase							:     Any=None       ,	**__lowercase							:     List[str]						):






							"""simple docstring"""






							if not has_length(__lowercase						):
								return
							if self.prediction_bar is None:
								if self.training_tracker is not None:
									snake_case_		    =     self.training_tracker.add_child(len(__lowercase						)						)
								else:
									snake_case_		    =     NotebookProgressBar(len(__lowercase						)						)
								self.prediction_bar.update(1						)
							else:
								self.prediction_bar.update(self.prediction_bar.value + 1						)






						def        snake_case__						(						self							:     Union[str, Any]       ,	__lowercase							:     Tuple       ,	__lowercase							:     Optional[int]       ,	__lowercase							:     List[Any]       ,	**__lowercase							:     Union[str, Any]						):






							"""simple docstring"""






							if self.prediction_bar is not None:
								self.prediction_bar.close()
							snake_case_		    =     None






						def        snake_case__						(						self							:     Union[str, Any]       ,	__lowercase							:     List[Any]       ,	__lowercase							:     Union[str, Any]       ,	__lowercase							:     Any       ,	__lowercase							:     List[Any]=None       ,	**__lowercase							:     Optional[int]						):






							"""simple docstring"""






							if args.evaluation_strategy == IntervalStrategy.NO and "loss" in logs:
								snake_case_		    =     {"Training Loss": logs["loss"]}
								# First column is necessarily Step sine we're not in epoch eval strategy
								snake_case_		    =     state.global_step
								self.training_tracker.write_line(__lowercase						)






						def        snake_case__						(						self							:     Tuple       ,	__lowercase							:     Dict       ,	__lowercase							:     Union[str, Any]       ,	__lowercase							:     int       ,	__lowercase							:     Tuple=None       ,	**__lowercase							:     str						):






							"""simple docstring"""






							if self.training_tracker is not None:
								snake_case_		    =     {"Training Loss": "No log", "Validation Loss": "No log"}
								for log in reversed(state.log_history						):
									if "loss" in log:
										snake_case_		    =     log["loss"]
										break

								if self.first_column == "Epoch":
									snake_case_		    =     int(state.epoch						)
								else:
									snake_case_		    =     state.global_step
								snake_case_		    =     "eval"
								for k in metrics:
									if k.endswith("_loss"						):
										snake_case_		    =     re.sub(r"\_loss$"       ,	""       ,	__lowercase						)
								snake_case_		    =     metrics.pop("total_flos"       ,	__lowercase						)
								snake_case_		    =     metrics.pop("epoch"       ,	__lowercase						)
								snake_case_		    =     metrics.pop(f"{metric_key_prefix}_runtime"       ,	__lowercase						)
								snake_case_		    =     metrics.pop(f"{metric_key_prefix}_samples_per_second"       ,	__lowercase						)
								snake_case_		    =     metrics.pop(f"{metric_key_prefix}_steps_per_second"       ,	__lowercase						)
								snake_case_		    =     metrics.pop(f"{metric_key_prefix}_jit_compilation_time"       ,	__lowercase						)
								for k, v in metrics.items():
									if k == f"{metric_key_prefix}_loss":
										snake_case_		    =     v
									else:
										snake_case_		    =     k.split("_"						)
										snake_case_		    =     " ".join([part.capitalize() for part in splits[1:]]						)
										snake_case_		    =     v
								self.training_tracker.write_line(__lowercase						)
								self.training_tracker.remove_child()
								snake_case_		    =     None
								# Evaluation takes a long time so we should force the next update.
								snake_case_		    =     True






						def        snake_case__						(						self							:     Dict       ,	__lowercase							:     Union[str, Any]       ,	__lowercase							:     Dict       ,	__lowercase							:     Any       ,	**__lowercase							:     List[Any]						):






							"""simple docstring"""






							self.training_tracker.update(
							    state.global_step       ,	comment=f"Epoch {int(state.epoch						)}/{state.num_train_epochs}"       ,	force_update=__lowercase						)
							snake_case_		    =     None






import argparse
import json
import math
import os
import time
import traceback
import zipfile
from collections import Counter

import requests


def 						lowerCamelCase__    (		_A     ,	_A=None							):







	'''simple docstring'''





	snake_case_		    =     None
	if token is not None:
		snake_case_		    =     {"Accept": "application/vnd.github+json", "Authorization": f"Bearer {token}"}

	snake_case_		    =     f"https://api.github.com/repos/huggingface/transformers/actions/runs/{workflow_run_id}/jobs?per_page=100"
	snake_case_		    =     requests.get(_A     ,	headers=_A							).json()
	snake_case_		    =     {}

	try:
		job_links.update({job["name"]: job["html_url"] for job in result["jobs"]}							)
		snake_case_		    =     math.ceil((result["total_count"] - 100) / 100							)

		for i in range(_A							):
			snake_case_		    =     requests.get(url + f"&page={i + 2}"     ,	headers=_A							).json()
			job_links.update({job["name"]: job["html_url"] for job in result["jobs"]}							)

		return job_links
	except Exception:
		print(f"Unknown error, could not fetch links:\n{traceback.format_exc()}"							)

	return {}


def 						lowerCamelCase__    (		_A     ,	_A=None							):







	'''simple docstring'''





	snake_case_		    =     None
	if token is not None:
		snake_case_		    =     {"Accept": "application/vnd.github+json", "Authorization": f"Bearer {token}"}

	snake_case_		    =     f"https://api.github.com/repos/huggingface/transformers/actions/runs/{worflow_run_id}/artifacts?per_page=100"
	snake_case_		    =     requests.get(_A     ,	headers=_A							).json()
	snake_case_		    =     {}

	try:
		artifacts.update({artifact["name"]: artifact["archive_download_url"] for artifact in result["artifacts"]}							)
		snake_case_		    =     math.ceil((result["total_count"] - 100) / 100							)

		for i in range(_A							):
			snake_case_		    =     requests.get(url + f"&page={i + 2}"     ,	headers=_A							).json()
			artifacts.update({artifact["name"]: artifact["archive_download_url"] for artifact in result["artifacts"]}							)

		return artifacts
	except Exception:
		print(f"Unknown error, could not fetch links:\n{traceback.format_exc()}"							)

	return {}


def 						lowerCamelCase__    (		_A     ,	_A     ,	_A     ,	_A							):







	'''simple docstring'''





	snake_case_		    =     None
	if token is not None:
		snake_case_		    =     {"Accept": "application/vnd.github+json", "Authorization": f"Bearer {token}"}

	snake_case_		    =     requests.get(_A     ,	headers=_A     ,	allow_redirects=_A							)
	snake_case_		    =     result.headers["Location"]
	snake_case_		    =     requests.get(_A     ,	allow_redirects=_A							)
	snake_case_		    =     os.path.join(_A     ,	f"{artifact_name}.zip"							)
	with open(_A     ,	"wb"							) as fp:
		fp.write(response.content							)


def 						lowerCamelCase__    (		_A     ,	_A=None							):







	'''simple docstring'''





	snake_case_		    =     []
	snake_case_		    =     []
	snake_case_		    =     None

	with zipfile.ZipFile(_A							) as z:
		for filename in z.namelist():
			if not os.path.isdir(_A							):
				# read the file
				if filename in ["failures_line.txt", "summary_short.txt", "job_name.txt"]:
					with z.open(_A							) as f:
						for line in f:
							snake_case_		    =     line.decode("UTF-8"							).strip()
							if filename == "failures_line.txt":
								try:
									# `error_line` is the place where `error` occurs
									snake_case_		    =     line[: line.index(": "							)]
									snake_case_		    =     line[line.index(": "							) + len(": "							) :]
									errors.append([error_line, error]							)
								except Exception:
									# skip un-related lines
									pass
							elif filename == "summary_short.txt" and line.startswith("FAILED "							):
								# `test` is the test method that failed
								snake_case_		    =     line[len("FAILED "							) :]
								failed_tests.append(_A							)
							elif filename == "job_name.txt":
								snake_case_		    =     line

	if len(_A							) != len(_A							):
		raise ValueError(
		    f"`errors` and `failed_tests` should have the same number of elements. Got {len(_A							)} for `errors` "
		    f"and {len(_A							)} for `failed_tests` instead. The test reports in {artifact_zip_path} have some"
		    " problem."							)

	snake_case_		    =     None
	if job_name and job_links:
		snake_case_		    =     job_links.get(_A     ,	_A							)

	# A list with elements of the form (line of error, error, failed test)
	snake_case_		    =     [x + [y] + [job_link] for x, y in zip(_A     ,	_A							)]

	return result


def 						lowerCamelCase__    (		_A     ,	_A=None							):







	'''simple docstring'''





	snake_case_		    =     []

	snake_case_		    =     [os.path.join(_A     ,	_A							) for p in os.listdir(_A							) if p.endswith(".zip"							)]
	for p in paths:
		errors.extend(get_errors_from_single_artifact(_A     ,	job_links=_A							)							)

	return errors


def 						lowerCamelCase__    (		_A     ,	_A=None							):







	'''simple docstring'''





	snake_case_		    =     Counter()
	counter.update([x[1] for x in logs]							)
	snake_case_		    =     counter.most_common()
	snake_case_		    =     {}
	for error, count in counts:
		if error_filter is None or error not in error_filter:
			snake_case_		    =     {"count": count, "failed_tests": [(x[2], x[0]) for x in logs if x[1] == error]}

	snake_case_		    =     dict(sorted(r.items()     ,	key=lambda _A							: item[1]["count"]     ,	reverse=_A							)							)
	return r


def 						lowerCamelCase__    (		_A							):







	'''simple docstring'''





	snake_case_		    =     test.split("::"							)[0]
	if test.startswith("tests/models/"							):
		snake_case_		    =     test.split("/"							)[2]
	else:
		snake_case_		    =     None

	return test


def 						lowerCamelCase__    (		_A     ,	_A=None							):







	'''simple docstring'''





	snake_case_		    =     [(x[0], x[1], get_model(x[2]							)) for x in logs]
	snake_case_		    =     [x for x in logs if x[2] is not None]
	snake_case_		    =     {x[2] for x in logs}

	snake_case_		    =     {}
	for test in tests:
		snake_case_		    =     Counter()
		# count by errors in `test`
		counter.update([x[1] for x in logs if x[2] == test]							)
		snake_case_		    =     counter.most_common()
		snake_case_		    =     {error: count for error, count in counts if (error_filter is None or error not in error_filter)}
		snake_case_		    =     sum(error_counts.values()							)
		if n_errors > 0:
			snake_case_		    =     {"count": n_errors, "errors": error_counts}

	snake_case_		    =     dict(sorted(r.items()     ,	key=lambda _A							: item[1]["count"]     ,	reverse=_A							)							)
	return r


def 						lowerCamelCase__    (		_A							):







	'''simple docstring'''





	snake_case_		    =     "| no. | error | status |"
	snake_case_		    =     "|-:|:-|:-|"
	snake_case_		    =     [header, sep]
	for error in reduced_by_error:
		snake_case_		    =     reduced_by_error[error]["count"]
		snake_case_		    =     f"| {count} | {error[:100]} |  |"
		lines.append(_A							)

	return "\n".join(_A							)


def 						lowerCamelCase__    (		_A							):







	'''simple docstring'''





	snake_case_		    =     "| model | no. of errors | major error | count |"
	snake_case_		    =     "|-:|-:|-:|-:|"
	snake_case_		    =     [header, sep]
	for model in reduced_by_model:
		snake_case_		    =     reduced_by_model[model]["count"]
		snake_case_    ,      snake_case_		    =     list(reduced_by_model[model]["errors"].items()							)[0]
		snake_case_		    =     f"| {model} | {count} | {error[:60]} | {_count} |"
		lines.append(_A							)

	return "\n".join(_A							)


if __name__ == "__main__":
		lowercase__				:     int 		=						argparse.ArgumentParser()
		# Required parameters
		parser.add_argument("--workflow_run_id", type=str, required=True, help="A GitHub Actions workflow run id.")
		parser.add_argument(
		    "--output_dir",
		    type=str,
		    required=True,
		    help="Where to store the downloaded artifacts and other result files.",
		)
		parser.add_argument("--token", default=None, type=str, help="A token that has actions:read permission.")
		lowercase__				:     int 		=						parser.parse_args()

		os.makedirs(args.output_dir, exist_ok=True)

		lowercase__				:     Optional[Any] 		=						get_job_links(args.workflow_run_id, token=args.token)
		lowercase__				:     List[Any] 		=						{}
		# To deal with `workflow_call` event, where a job name is the combination of the job names in the caller and callee.
		# For example, `PyTorch 1.11 / Model tests (models/albert, single-gpu)`.
		if _job_links:
				for k, v in _job_links.items():
						# This is how GitHub actions combine job names.
						if " / " in k:
								lowercase__				:     Tuple 		=						k.find(" / ")
								lowercase__				:     Union[str, Any] 		=						k[index + len(" / ") :]
						lowercase__				:     Union[str, Any] 		=						v
		with open(os.path.join(args.output_dir, "job_links.json"), "w", encoding="UTF-8") as fp:
				json.dump(job_links, fp, ensure_ascii=False, indent=4)

		lowercase__				:     Any 		=						get_artifacts_links(args.workflow_run_id, token=args.token)
		with open(os.path.join(args.output_dir, "artifacts.json"), "w", encoding="UTF-8") as fp:
				json.dump(artifacts, fp, ensure_ascii=False, indent=4)

		for idx, (name, url) in enumerate(artifacts.items()):
				download_artifact(name, url, args.output_dir, args.token)
				# Be gentle to GitHub
				time.sleep(1)

		lowercase__				:     List[Any] 		=						get_all_errors(args.output_dir, job_links=job_links)

		# `e[1]` is the error
		lowercase__				:     str 		=						Counter()
		counter.update([e[1] for e in errors])

		# print the top 30 most common test errors
		lowercase__				:     Union[str, Any] 		=						counter.most_common(30)
		for item in most_common:
				print(item)

		with open(os.path.join(args.output_dir, "errors.json"), "w", encoding="UTF-8") as fp:
				json.dump(errors, fp, ensure_ascii=False, indent=4)

		lowercase__				:     int 		=						reduce_by_error(errors)
		lowercase__				:     List[str] 		=						reduce_by_model(errors)

		lowercase__				:     Tuple 		=						make_github_table(reduced_by_error)
		lowercase__				:     Optional[int] 		=						make_github_table_per_model(reduced_by_model)

		with open(os.path.join(args.output_dir, "reduced_by_error.txt"), "w", encoding="UTF-8") as fp:
				fp.write(sa)
		with open(os.path.join(args.output_dir, "reduced_by_model.txt"), "w", encoding="UTF-8") as fp:
				fp.write(sa)
