


import os
import warnings
from pathlib import Path
from typing import Optional, Union

from .dynamic_module_utils import custom_object_save
from .tokenization_utils_base import PreTrainedTokenizerBase
from .utils import PushToHubMixin, copy_func, direct_transformers_import, logging


_A							     =       logging.get_logger(__name__)

# Dynamically import the Transformers module to grab the attribute classes of the processor form their names.
_A							     =       direct_transformers_import(Path(__file__).parent)


_A							     =       {
    'AutoTokenizer': 'PreTrainedTokenizerBase',
    'AutoFeatureExtractor': 'FeatureExtractionMixin',
    'AutoImageProcessor': 'ImageProcessingMixin',
}

class 			lowerCamelCase_					(    _lowercase    ):
							_lowerCamelCase				: List[str]       =					["""feature_extractor""", """tokenizer"""]
							# Names need to be attr_class for attr in attributes
							_lowerCamelCase				: Optional[Any]       =					None
							_lowerCamelCase				: Dict       =					None
							_lowerCamelCase				: List[Any]       =					None





							def __init__(							self			,       *_SCREAMING_SNAKE_CASE			,       **_SCREAMING_SNAKE_CASE    ):
								# Sanitize args and kwargs
								for key in kwargs:
									if key not in self.attributes:
										raise TypeError(f"""Unexpected keyword argument {key}."""    )
								for arg, attribute_name in zip(__snake_case			,       self.attributes    ):
									if attribute_name in kwargs:
										raise TypeError(f"""Got multiple values for argument {attribute_name}."""    )
									else:
										a_     			=   arg

								if len(__snake_case    ) != len(self.attributes    ):
									raise ValueError(
									    f"""This processor requires {len(self.attributes    )} arguments: {", ".join(self.attributes    )}. Got """
									    f"""{len(__snake_case    )} arguments instead."""    )

								# Check each arg is of the proper class (this will also catch a user initializing in the wrong order)
								for attribute_name, arg in kwargs.items():
									a_     			=   getattr(self			,       f"""{attribute_name}_class"""    )
									# Nothing is ever going to be an instance of "AutoXxx", in that case we check the base class.
									a_     			=   AUTO_TO_BASE_CLASS_MAPPING.get(__snake_case			,       __snake_case    )
									if isinstance(__snake_case			,       __snake_case    ):
										a_     			=   tuple(getattr(__snake_case			,       __snake_case    ) for n in class_name if n is not None    )
									else:
										a_     			=   getattr(__snake_case			,       __snake_case    )

									if not isinstance(__snake_case			,       __snake_case    ):
										raise ValueError(
										    f"""Received a {type(__snake_case    ).__name__} for argument {attribute_name}, but a {class_name} was expected."""    )

									setattr(self			,       __snake_case			,       __snake_case    )





							def __repr__(							self    ):
								a_     			=   [f"""- {name}: {repr(getattr(self			,       __snake_case    )    )}""" for name in self.attributes]
								a_     			=   '\n'.join(__snake_case    )
								return f"""{self.__class__.__name__}:\n{attributes_repr}"""





							def   __magic_name__      (							self			,       _SCREAMING_SNAKE_CASE			,       _SCREAMING_SNAKE_CASE = False			,       **_SCREAMING_SNAKE_CASE    ):
								os.makedirs(__snake_case			,       exist_ok=__snake_case    )

								if push_to_hub:
									a_     			=   kwargs.pop("""commit_message"""			,       __snake_case    )
									a_     			=   kwargs.pop("""repo_id"""			,       save_directory.split(os.path.sep    )[-1]    )
									a_     			=   self._create_repo(__snake_case			,       **__snake_case    )
									a_     			=   self._get_files_timestamps(__snake_case    )
								# If we have a custom config, we copy the file defining it in the folder and set the attributes so it can be
								# loaded from the Hub.
								if self._auto_class is not None:
									a_     			=   [getattr(self			,       __snake_case    ) for attribute_name in self.attributes]
									a_     			=   [(a.init_kwargs if isinstance(__snake_case			,       __snake_case    ) else a) for a in attrs]
									custom_object_save(self			,       __snake_case			,       config=__snake_case    )

								for attribute_name in self.attributes:
									a_     			=   getattr(self			,       __snake_case    )
									# Include the processor class in the attribute config so this processor can then be reloaded with the
									# `AutoProcessor` API.
									if hasattr(__snake_case			,       """_set_processor_class"""    ):
										attribute._set_processor_class(self.__class__.__name__    )
									attribute.save_pretrained(__snake_case    )

								if self._auto_class is not None:
									# We added an attribute to the init_kwargs of the tokenizers, which needs to be cleaned up.
									for attribute_name in self.attributes:
										a_     			=   getattr(self			,       __snake_case    )
										if isinstance(__snake_case			,       __snake_case    ):
											del attribute.init_kwargs["auto_map"]

								if push_to_hub:
									self._upload_modified_files(
									    __snake_case			,       __snake_case			,       __snake_case			,       commit_message=__snake_case			,       token=kwargs.get("""use_auth_token"""    )			,       )





							@classmethod
							def   __magic_name__      (							cls			,       _SCREAMING_SNAKE_CASE			,       _SCREAMING_SNAKE_CASE = None			,       _SCREAMING_SNAKE_CASE = False			,       _SCREAMING_SNAKE_CASE = False			,       _SCREAMING_SNAKE_CASE = None			,       _SCREAMING_SNAKE_CASE = "main"			,       **_SCREAMING_SNAKE_CASE			,       ):
								a_     			=   cache_dir
								a_     			=   force_download
								a_     			=   local_files_only
								a_     			=   revision

								a_     			=   kwargs.pop("""use_auth_token"""			,       __snake_case    )
								if use_auth_token is not None:
									warnings.warn(
									    """The `use_auth_token` argument is deprecated and will be removed in v5 of Transformers."""			,       __snake_case    )
									if token is not None:
										raise ValueError(
										    """`token` and `use_auth_token` are both specified. Please set only the argument `token`."""    )
									a_     			=   use_auth_token

								if token is not None:
									# change to `token` in a follow-up PR
									a_     			=   token

								a_     			=   cls._get_arguments_from_pretrained(__snake_case			,       **__snake_case    )
								return cls(*__snake_case    )





							@classmethod
							def   __magic_name__      (							cls			,       _SCREAMING_SNAKE_CASE="AutoProcessor"    ):
								if not isinstance(__snake_case			,       __snake_case    ):
									a_     			=   auto_class.__name__

								import transformers.models.auto as auto_module

								if not hasattr(__snake_case			,       __snake_case    ):
									raise ValueError(f"""{auto_class} is not a valid auto class."""    )

								a_     			=   auto_class





							@classmethod
							def   __magic_name__      (							cls			,       _SCREAMING_SNAKE_CASE			,       **_SCREAMING_SNAKE_CASE    ):
								a_     			=   []
								for attribute_name in cls.attributes:
									a_     			=   getattr(cls			,       f"""{attribute_name}_class"""    )
									if isinstance(__snake_case			,       __snake_case    ):
										a_     			=   tuple(getattr(__snake_case			,       __snake_case    ) if n is not None else None for n in class_name    )
										a_     			=   kwargs.get("""use_fast"""			,       __snake_case    )
										if use_fast and classes[1] is not None:
											a_     			=   classes[1]
										else:
											a_     			=   classes[0]
									else:
										a_     			=   getattr(__snake_case			,       __snake_case    )

									args.append(attribute_class.from_pretrained(__snake_case			,       **__snake_case    )    )
								return args





							@property
							def   __magic_name__      (							self    ):
								a_     			=   getattr(self			,       self.attributes[0]    )
								return getattr(__snake_case			,       """model_input_names"""			,       __snake_case    )







_A							     =       copy_func(ProcessorMixin.push_to_hub)
if ProcessorMixin.push_to_hub.__doc__ is not None:
			_A							     =       ProcessorMixin.push_to_hub.__doc__.format(
			    object='processor', object_class='AutoProcessor', object_files='processor files'
			)


import unittest

from cer import CER


lowerCAmelCase__             =		CER()







class 						lowercase     (					unittest.TestCase				):


		"""simple docstring"""




		def 		A__       (					self):
			_UpperCamelCase :		Any								=    ['White House']
			_UpperCamelCase :		Tuple								=    ['white house']
			# S = 2, D = 0, I = 0, N = 11, CER = 2 / 11
			_UpperCamelCase :		Tuple								=    cer.compute(predictions=__snake_case						,							references=__snake_case)
			self.assertTrue(abs(char_error_rate - 0.1_8_1_8_1_8_1_8_1_8) < 1e-6)


		def 		A__       (					self):
			_UpperCamelCase :		Union[str, Any]								=    ['were wolf']
			_UpperCamelCase :		List[Any]								=    ['werewolf']
			# S = 0, D = 0, I = 1, N = 9, CER = 1 / 9
			_UpperCamelCase :		Dict								=    cer.compute(predictions=__snake_case						,							references=__snake_case)
			self.assertTrue(abs(char_error_rate - 0.1_1_1_1_1_1_1) < 1e-6)

			_UpperCamelCase :		int								=    ['werewolf']
			_UpperCamelCase :		Optional[Any]								=    ['weae     wolf']
			# S = 1, D = 1, I = 0, N = 8, CER = 0.25
			_UpperCamelCase :		str								=    cer.compute(predictions=__snake_case						,							references=__snake_case)
			self.assertTrue(abs(char_error_rate - 0.2_5) < 1e-6)

			# consecutive whitespaces case 1
			_UpperCamelCase :		Tuple								=    ['were wolf']
			_UpperCamelCase :		Dict								=    ['were               wolf']
			# S = 0, D = 0, I = 0, N = 9, CER = 0
			_UpperCamelCase :		List[str]								=    cer.compute(predictions=__snake_case						,							references=__snake_case)
			self.assertTrue(abs(char_error_rate - 0.0) < 1e-6)

			# consecutive whitespaces case 2
			_UpperCamelCase :		Dict								=    ['were   wolf']
			_UpperCamelCase :		Dict								=    ['were               wolf']
			# S = 0, D = 0, I = 0, N = 9, CER = 0
			_UpperCamelCase :		Dict								=    cer.compute(predictions=__snake_case						,							references=__snake_case)
			self.assertTrue(abs(char_error_rate - 0.0) < 1e-6)


		def 		A__       (					self):
			_UpperCamelCase :		Tuple								=    ['werewolf']
			_UpperCamelCase :		Optional[Any]								=    ['weaewolf']
			# S = 1, D = 0, I = 0, N = 8, CER = 0.125
			_UpperCamelCase :		List[str]								=    cer.compute(predictions=__snake_case						,							references=__snake_case)
			self.assertTrue(abs(char_error_rate - 0.1_2_5) < 1e-6)


		def 		A__       (					self):
			_UpperCamelCase :		int								=    ['werewolf']
			_UpperCamelCase :		Any								=    ['wereawolf']
			# S = 0, D = 1, I = 0, N = 8, CER = 0.125
			_UpperCamelCase :		Optional[int]								=    cer.compute(predictions=__snake_case						,							references=__snake_case)
			self.assertTrue(abs(char_error_rate - 0.1_2_5) < 1e-6)


		def 		A__       (					self):
			_UpperCamelCase :		str								=    ['werewolf']
			_UpperCamelCase :		Optional[Any]								=    ['wereolf']
			# S = 0, D = 0, I = 1, N = 8, CER = 0.125
			_UpperCamelCase :		List[Any]								=    cer.compute(predictions=__snake_case						,							references=__snake_case)
			self.assertTrue(abs(char_error_rate - 0.1_2_5) < 1e-6)


		def 		A__       (					self):
			_UpperCamelCase :		Optional[Any]								=    ['werewolf']
			_UpperCamelCase :		Optional[Any]								=    cer.compute(predictions=__snake_case						,							references=__snake_case)
			self.assertEqual(__snake_case						,							0.0)


		def 		A__       (					self):
			_UpperCamelCase :		Union[str, Any]								=    ['werewolf', 'I am your father']
			_UpperCamelCase :		Dict								=    cer.compute(predictions=__snake_case						,							references=__snake_case)
			self.assertEqual(__snake_case						,							0.0)

			_UpperCamelCase :		List[Any]								=    ['werewolf', 'I am your father', 'doge']
			_UpperCamelCase :		Optional[int]								=    ['werxwolf', 'I       am your father', 'doge']
			# S = 1, D = 0, I = 0, N = 28, CER = 1 / 28
			_UpperCamelCase :		Any								=    cer.compute(predictions=__snake_case						,							references=__snake_case)
			self.assertTrue(abs(char_error_rate - 0.0_3_5_7_1_4_2_8) < 1e-6)


		def 		A__       (					self):
			_UpperCamelCase :		Tuple								=    ['My hovercraft', 'is full of eels']
			_UpperCamelCase :		List[Any]								=    ['My hovercraft is full', ' of eels']
			# S = 0, D = 0, I = 2, N = 28, CER = 2 / 28
			# whitespace at the front of " of eels" will be strip during preporcessing
			# so need to insert 2 whitespaces
			_UpperCamelCase :		Dict								=    cer.compute(predictions=__snake_case						,							references=__snake_case						,							concatenate_texts=__snake_case)
			self.assertTrue(abs(char_error_rate - 0.0_7_1_4_2_8) < 1e-6)


		def 		A__       (					self):
			_UpperCamelCase :		Union[str, Any]								=    ['我能吞下玻璃而不伤身体']
			_UpperCamelCase :		Optional[Any]								=    [' 能吞虾玻璃而 不霜身体啦']
			# S = 3, D = 2, I = 0, N = 11, CER = 5 / 11
			_UpperCamelCase :		Any								=    cer.compute(predictions=__snake_case						,							references=__snake_case)
			self.assertTrue(abs(char_error_rate - 0.4_5_4_5_4_5_4_5_4_5) < 1e-6)

			_UpperCamelCase :		Union[str, Any]								=    ['我能吞下玻璃', '而不伤身体']
			_UpperCamelCase :		List[str]								=    ['我    能 吞 下 玻 璃', '而不伤身体']
			# S = 0, D = 5, I = 0, N = 11, CER = 5 / 11
			_UpperCamelCase :		Union[str, Any]								=    cer.compute(predictions=__snake_case						,							references=__snake_case)
			self.assertTrue(abs(char_error_rate - 0.4_5_4_5_4_5_4_5_4_5_4_5) < 1e-6)

			_UpperCamelCase :		Optional[int]								=    ['我能吞下玻璃而不伤身体']
			_UpperCamelCase :		int								=    cer.compute(predictions=__snake_case						,							references=__snake_case)
			self.assertFalse(__snake_case						,							0.0)






		def 		A__       (					self):
			_UpperCamelCase :		Tuple								=    ['']
			_UpperCamelCase :		Dict								=    ['Hypothesis']
			with self.assertRaises(__snake_case):
				cer.compute(predictions=__snake_case						,							references=__snake_case)


if __name__ == "__main__":
							unittest.main()




