

"""simple docstring"""




from __future__ import annotations

import inspect
import unittest
from math import floor

import numpy as np

from transformers import CvtConfig
from transformers.testing_utils import require_tf, require_vision, slow
from transformers.utils import cached_property, is_tf_available, is_vision_available

from ...test_configuration_common import ConfigTester
from ...test_modeling_tf_common import TFModelTesterMixin, floats_tensor, ids_tensor
from ...test_pipeline_mixin import PipelineTesterMixin


if is_tf_available():
      import tensorflow as tf

      from transformers import TFCvtForImageClassification, TFCvtModel
      from transformers.models.cvt.modeling_tf_cvt import TF_CVT_PRETRAINED_MODEL_ARCHIVE_LIST


if is_vision_available():
      from PIL import Image

      from transformers import AutoImageProcessor







class   __lowercase      (     __lowerCamelCase       ):

  def  __lowercase							(	self		:      Optional[int]     ):






   '''simple docstring'''
   UpperCAmelCase__       :	Union[str, Any]        =       self.config_class(**self.inputs_dict     )
   self.parent.assertTrue(hasattr(A       ,"""embed_dim"""     )     )
   self.parent.assertTrue(hasattr(A       ,"""num_heads"""     )     )







class   __lowercase      :

  def __init__(	self		:      Optional[int]       ,A		:      Tuple       ,A		:      Any=13       ,A		:      str=64       ,A		:      List[str]=3       ,A		:      int=[16, 48, 96]       ,A		:      Optional[Any]=[1, 3, 6]       ,A		:      Any=[1, 2, 10]       ,A		:      List[str]=[7, 3, 3]       ,A		:      str=[4, 2, 2]       ,A		:      str=[2, 1, 1]       ,A		:      Union[str, Any]=[2, 2, 2]       ,A		:      List[str]=[False, False, True]       ,A		:      Dict=[0.0, 0.0, 0.0]       ,A		:      Tuple=0.0_2       ,A		:      List[Any]=1e-12       ,A		:      Dict=True       ,A		:      Optional[Any]=True       ,A		:      Optional[int]=2       ,):






   '''simple docstring'''
   UpperCAmelCase__       :	List[str]        =       parent
   UpperCAmelCase__       :	List[str]        =       batch_size
   UpperCAmelCase__       :	int        =       image_size
   UpperCAmelCase__       :	List[str]        =       patch_sizes
   UpperCAmelCase__       :	int        =       patch_stride
   UpperCAmelCase__       :	Tuple        =       patch_padding
   UpperCAmelCase__       :	Tuple        =       is_training
   UpperCAmelCase__       :	Dict        =       use_labels
   UpperCAmelCase__       :	Dict        =       num_labels
   UpperCAmelCase__       :	Tuple        =       num_channels
   UpperCAmelCase__       :	Any        =       embed_dim
   UpperCAmelCase__       :	Tuple        =       num_heads
   UpperCAmelCase__       :	Union[str, Any]        =       stride_kv
   UpperCAmelCase__       :	List[str]        =       depth
   UpperCAmelCase__       :	Optional[Any]        =       cls_token
   UpperCAmelCase__       :	List[Any]        =       attention_drop_rate
   UpperCAmelCase__       :	Any        =       initializer_range
   UpperCAmelCase__       :	Optional[int]        =       layer_norm_eps

  def  __lowercase							(	self		:      Optional[Any]     ):






   '''simple docstring'''
   UpperCAmelCase__       :	int        =       floats_tensor([self.batch_size, self.num_channels, self.image_size, self.image_size]     )

   UpperCAmelCase__       :	Any        =       None
   if self.use_labels:
    # create a random int32 tensor of given shape
    UpperCAmelCase__       :	Union[str, Any]        =       ids_tensor([self.batch_size]       ,self.num_labels     )

   UpperCAmelCase__       :	Dict        =       self.get_config()
   return config, pixel_values, labels

  def  __lowercase							(	self		:      Optional[int]     ):






   '''simple docstring'''
   return CvtConfig(
       image_size=self.image_size       ,num_labels=self.num_labels       ,num_channels=self.num_channels       ,embed_dim=self.embed_dim       ,num_heads=self.num_heads       ,patch_sizes=self.patch_sizes       ,patch_padding=self.patch_padding       ,patch_stride=self.patch_stride       ,stride_kv=self.stride_kv       ,depth=self.depth       ,cls_token=self.cls_token       ,attention_drop_rate=self.attention_drop_rate       ,initializer_range=self.initializer_range       ,)

  def  __lowercase							(	self		:      List[str]       ,A		:      Any       ,A		:      List[Any]       ,A		:      Tuple     ):






   '''simple docstring'''
   UpperCAmelCase__       :	Dict        =       TFCvtModel(config=A     )
   UpperCAmelCase__       :	Dict        =       model(A       ,training=A     )
   UpperCAmelCase__       :	List[str]        =       (self.image_size, self.image_size)
   UpperCAmelCase__ ,   UpperCAmelCase__       :	Tuple        =       image_size[0], image_size[1]
   for i in range(len(self.depth     )     ):
    UpperCAmelCase__       :	Optional[Any]        =       floor(((height + 2 * self.patch_padding[i] - self.patch_sizes[i]) / self.patch_stride[i]) + 1     )
    UpperCAmelCase__       :	List[Any]        =       floor(((width + 2 * self.patch_padding[i] - self.patch_sizes[i]) / self.patch_stride[i]) + 1     )
   self.parent.assertEqual(result.last_hidden_state.shape       ,(self.batch_size, self.embed_dim[-1], height, width)     )

  def  __lowercase							(	self		:      int       ,A		:      List[Any]       ,A		:      int       ,A		:      Union[str, Any]     ):






   '''simple docstring'''
   UpperCAmelCase__       :	Union[str, Any]        =       self.num_labels
   UpperCAmelCase__       :	List[Any]        =       TFCvtForImageClassification(A     )
   UpperCAmelCase__       :	Union[str, Any]        =       model(A       ,labels=A       ,training=A     )
   self.parent.assertEqual(result.logits.shape       ,(self.batch_size, self.num_labels)     )




  def  __lowercase							(	self		:      Optional[Any]     ):






   '''simple docstring'''
   UpperCAmelCase__       :	Union[str, Any]        =       self.prepare_config_and_inputs()
   UpperCAmelCase__ ,   UpperCAmelCase__ ,   UpperCAmelCase__       :	List[str]        =       config_and_inputs
   UpperCAmelCase__       :	List[str]        =       {"""pixel_values""": pixel_values}
   return config, inputs_dict







@require_tf
class   __lowercase      (     __lowerCamelCase						,      __lowerCamelCase						,      unittest.TestCase       ):
  snake_case_												=							(TFCvtModel, TFCvtForImageClassification) if is_tf_available() else ()
  snake_case_												=							(
      {"""feature-extraction""": TFCvtModel, """image-classification""": TFCvtForImageClassification}
      if is_tf_available()
      else {}
  )
  snake_case_												=							False
  snake_case_												=							False
  snake_case_												=							False
  snake_case_												=							False
  snake_case_												=							False

  def  __lowercase							(	self		:      str     ):






   '''simple docstring'''
   UpperCAmelCase__       :	Tuple        =       TFCvtModelTester(self     )
   UpperCAmelCase__       :	Union[str, Any]        =       TFCvtConfigTester(self       ,config_class=A       ,has_text_modality=A       ,hidden_size=37     )

  def  __lowercase							(	self		:      List[str]     ):






   '''simple docstring'''
   self.config_tester.create_and_test_config_common_properties()
   self.config_tester.create_and_test_config_to_json_string()
   self.config_tester.create_and_test_config_to_json_file()
   self.config_tester.create_and_test_config_from_and_save_pretrained()
   self.config_tester.create_and_test_config_with_num_labels()
   self.config_tester.check_config_can_be_init_without_params()
   self.config_tester.check_config_arguments_init()

  @unittest.skip(reason="""Cvt does not output attentions"""     )
  def  __lowercase							(	self		:      List[str]     ):






   '''simple docstring'''
   pass

  @unittest.skip(reason="""Cvt does not use inputs_embeds"""     )
  def  __lowercase							(	self		:      Dict     ):






   '''simple docstring'''
   pass

  @unittest.skip(reason="""Cvt does not support input and output embeddings"""     )
  def  __lowercase							(	self		:      int     ):






   '''simple docstring'''
   pass

  @unittest.skipIf(
      not is_tf_available() or len(tf.config.list_physical_devices("""GPU"""     )     ) == 0       ,reason="""TF does not support backprop for grouped convolutions on CPU."""       ,)
  def  __lowercase							(	self		:      str     ):






   '''simple docstring'''
   super().test_dataset_conversion()

  @unittest.skipIf(
      not is_tf_available() or len(tf.config.list_physical_devices("""GPU"""     )     ) == 0       ,reason="""TF does not support backprop for grouped convolutions on CPU."""       ,)
  @slow
  def  __lowercase							(	self		:      str     ):






   '''simple docstring'''
   super().test_keras_fit()

  @unittest.skip(reason="""Get `Failed to determine best cudnn convolution algo.` error after using TF 2.12+cuda 11.8"""     )
  def  __lowercase							(	self		:      str     ):






   '''simple docstring'''
   UpperCAmelCase__       :	Tuple        =       tf.keras.mixed_precision.Policy("""mixed_float16"""     )
   tf.keras.mixed_precision.set_global_policy(A     )
   super().test_keras_fit()
   tf.keras.mixed_precision.set_global_policy("""float32"""     )

  def  __lowercase							(	self		:      str     ):






   '''simple docstring'''
   UpperCAmelCase__ ,   UpperCAmelCase__       :	List[Any]        =       self.model_tester.prepare_config_and_inputs_for_common()

   for model_class in self.all_model_classes:
    UpperCAmelCase__       :	int        =       model_class(A     )
    UpperCAmelCase__       :	List[Any]        =       inspect.signature(model.call     )
    # signature.parameters is an OrderedDict => so arg_names order is deterministic
    UpperCAmelCase__       :	Optional[int]        =       [*signature.parameters.keys()]

    UpperCAmelCase__       :	Dict        =       ["""pixel_values"""]
    self.assertListEqual(arg_names[:1]       ,A     )

  def  __lowercase							(	self		:      Tuple     ):






   '''simple docstring'''
   def check_hidden_states_output(A		:      List[Any]       ,A		:      Tuple       ,A		:      int     ):
    UpperCAmelCase__       :	Any        =       model_class(A     )

    UpperCAmelCase__       :	Any        =       model(**self._prepare_for_class(A       ,A     )     )
    UpperCAmelCase__       :	List[str]        =       outputs.hidden_states

    UpperCAmelCase__       :	int        =       len(self.model_tester.depth     )
    self.assertEqual(len(A     )       ,A     )

    # verify the first hidden states (first block)
    self.assertListEqual(
        list(hidden_states[0].shape[-3:]     )       ,[
            self.model_tester.embed_dim[0],
            self.model_tester.image_size // 4,
            self.model_tester.image_size // 4,
        ]       ,)

   UpperCAmelCase__ ,   UpperCAmelCase__       :	str        =       self.model_tester.prepare_config_and_inputs_for_common()

   for model_class in self.all_model_classes:
    UpperCAmelCase__       :	Union[str, Any]        =       True
    check_hidden_states_output(A       ,A       ,A     )

    # check that output_hidden_states also work using config
    del inputs_dict["output_hidden_states"]
    UpperCAmelCase__       :	List[str]        =       True

    check_hidden_states_output(A       ,A       ,A     )

  def  __lowercase							(	self		:      List[Any]     ):






   '''simple docstring'''
   UpperCAmelCase__       :	Optional[int]        =       self.model_tester.prepare_config_and_inputs()
   self.model_tester.create_and_check_model(*A     )

  def  __lowercase							(	self		:      str     ):






   '''simple docstring'''
   UpperCAmelCase__       :	Optional[int]        =       self.model_tester.prepare_config_and_inputs()
   self.model_tester.create_and_check_for_image_classification(*A     )




  @slow
  def  __lowercase							(	self		:      Tuple     ):






   '''simple docstring'''
   for model_name in TF_CVT_PRETRAINED_MODEL_ARCHIVE_LIST[:1]:
    UpperCAmelCase__       :	List[Any]        =       TFCvtModel.from_pretrained(A     )
    self.assertIsNotNone(A     )







def 	lowerCAmelCase    (       ):
 '''simple docstring'''





 UpperCAmelCase__       :	Optional[Any]        =       Image.open("""./tests/fixtures/tests_samples/COCO/000000039769.png"""   )
 return image







@require_tf
@require_vision
class   __lowercase      (     unittest.TestCase       ):

  @cached_property
  def  __lowercase							(	self		:      str     ):






   '''simple docstring'''
   return AutoImageProcessor.from_pretrained(TF_CVT_PRETRAINED_MODEL_ARCHIVE_LIST[0]     )




  @slow
  def  __lowercase							(	self		:      str     ):






   '''simple docstring'''
   UpperCAmelCase__       :	Optional[Any]        =       TFCvtForImageClassification.from_pretrained(TF_CVT_PRETRAINED_MODEL_ARCHIVE_LIST[0]     )

   UpperCAmelCase__       :	Tuple        =       self.default_image_processor
   UpperCAmelCase__       :	Optional[Any]        =       prepare_img()
   UpperCAmelCase__       :	Optional[int]        =       image_processor(images=A       ,return_tensors="""tf"""     )

   # forward pass
   UpperCAmelCase__       :	Union[str, Any]        =       model(**A     )

   # verify the logits
   UpperCAmelCase__       :	List[str]        =       tf.TensorShape((1, 1_000)     )
   self.assertEqual(outputs.logits.shape       ,A     )

   UpperCAmelCase__       :	Any        =       tf.constant([0.9_2_8_5, 0.9_0_1_5, -0.3_1_5_0]     )
   self.assertTrue(np.allclose(outputs.logits[0, :3].numpy()       ,A       ,atol=1e-4     )     )







"""simple docstring"""



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

import requests


def 			_UpperCamelCase						(    _A       ,   _A=None   )     ->	Optional[int]:





    """simple docstring"""

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

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

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

        for i in range(_A   ):
            _UpperCAmelCase        = 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 			_UpperCamelCase						(    _A       ,   _A=None   )     ->	str:





    """simple docstring"""

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

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

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

        for i in range(_A   ):
            _UpperCAmelCase        = 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 			_UpperCamelCase						(    _A       ,   _A       ,   _A       ,   _A   )     ->	List[Any]:





    """simple docstring"""

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

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


def 			_UpperCamelCase						(    _A       ,   _A=None   )     ->	Union[str, Any]:





    """simple docstring"""

    _UpperCAmelCase        = []
    _UpperCAmelCase        = []
    _UpperCAmelCase        = 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:
                            _UpperCAmelCase        = line.decode("""UTF-8"""   ).strip()
                            if filename == "failures_line.txt":
                                try:
                                    # `error_line` is the place where `error` occurs
                                    _UpperCAmelCase        = line[: line.index(""": """   )]
                                    _UpperCAmelCase        = 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
                                _UpperCAmelCase        = line[len("""FAILED """   ) :]
                                failed_tests.append(_A   )
                            elif filename == "job_name.txt":
                                _UpperCAmelCase        = 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."""   )

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

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

    return result


def 			_UpperCamelCase						(    _A       ,   _A=None   )     ->	List[str]:





    """simple docstring"""

    _UpperCAmelCase        = []

    _UpperCAmelCase        = [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 			_UpperCamelCase						(    _A       ,   _A=None   )     ->	Union[str, Any]:





    """simple docstring"""

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

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


def 			_UpperCamelCase						(    _A   )     ->	int:





    """simple docstring"""

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

    return test


def 			_UpperCamelCase						(    _A       ,   _A=None   )     ->	str:





    """simple docstring"""

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

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

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


def 			_UpperCamelCase						(    _A   )     ->	Optional[int]:





    """simple docstring"""

    _UpperCAmelCase        = """| no. | error | status |"""
    _UpperCAmelCase        = """|-:|:-|:-|"""
    _UpperCAmelCase        = [header, sep]
    for error in reduced_by_error:
        _UpperCAmelCase        = reduced_by_error[error]["""count"""]
        _UpperCAmelCase        = F"""| {count} | {error[:1_0_0]} |  |"""
        lines.append(_A   )

    return "\n".join(_A   )


def 			_UpperCamelCase						(    _A   )     ->	int:





    """simple docstring"""

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

    return "\n".join(_A   )


if __name__ == "__main__":
 a       :						Optional[Any]       		=		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.''')
 a       :						Any       		=		parser.parse_args()

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

 a       :						Optional[int]       		=		get_job_links(args.workflow_run_id, token=args.token)
 a       :						Optional[int]       		=		{}
 # 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:
    a       :						Union[str, Any]       		=		k.find(''' / ''')
    a       :						Optional[int]       		=		k[index + len(''' / ''') :]
   a       :						Optional[int]       		=		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)

 a       :						Union[str, 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)

 a       :						Any       		=		get_all_errors(args.output_dir, job_links=job_links)

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

 # print the top 30 most common test errors
 a       :						List[str]       		=		counter.most_common(3_0)
 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)

 a       :						List[Any]       		=		reduce_by_error(errors)
 a       :						List[str]       		=		reduce_by_model(errors)

 a       :						Dict       		=		make_github_table(reduced_by_error)
 a       :						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)