

"""simple docstring"""




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     :    Dict    =		logging.get_logger(__name__)

# Dynamically import the Transformers module to grab the attribute classes of the processor form their names.
__A     :    Optional[Any]    =		direct_transformers_import(Path(__file__).parent)


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





class 			__UpperCamelCase (   _A						):
		SCREAMING_SNAKE_CASE								=    ["feature_extractor", "tokenizer"]
		# Names need to be attr_class for attr in attributes
		SCREAMING_SNAKE_CASE								=    None
		SCREAMING_SNAKE_CASE								=    None
		SCREAMING_SNAKE_CASE								=    None


		def __init__(self :		Optional[Any]     ,     *__SCREAMING_SNAKE_CASE :		Union[str, Any]     ,     **__SCREAMING_SNAKE_CASE :		List[str]):
							# 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(__SCREAMING_SNAKE_CASE     ,     self.attributes):
												if attribute_name in kwargs:
																	raise TypeError(F"""Got multiple values for argument {attribute_name}.""")
												else:
																	A			=					arg

							if len(__SCREAMING_SNAKE_CASE) != len(self.attributes):
												raise ValueError(
												    F"""This processor requires {len(self.attributes)} arguments: {", ".join(self.attributes)}. Got """
												    F"""{len(__SCREAMING_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(__SCREAMING_SNAKE_CASE     ,     __SCREAMING_SNAKE_CASE)
												if isinstance(__SCREAMING_SNAKE_CASE     ,     __SCREAMING_SNAKE_CASE):
																	A			=					tuple(getattr(__SCREAMING_SNAKE_CASE     ,     __SCREAMING_SNAKE_CASE) for n in class_name if n is not None)
												else:
																	A			=					getattr(__SCREAMING_SNAKE_CASE     ,     __SCREAMING_SNAKE_CASE)

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

												setattr(self     ,     __SCREAMING_SNAKE_CASE     ,     __SCREAMING_SNAKE_CASE)


		def __repr__(self :		int):
							A			=					[F"""- {name}: {repr(getattr(self     ,     __SCREAMING_SNAKE_CASE))}""" for name in self.attributes]
							A			=					"\n".join(__SCREAMING_SNAKE_CASE)
							return F"""{self.__class__.__name__}:\n{attributes_repr}"""


		def 					SCREAMING_SNAKE_CASE__   (self :		str     ,     __SCREAMING_SNAKE_CASE :		Optional[int]     ,     __SCREAMING_SNAKE_CASE :		bool = False     ,     **__SCREAMING_SNAKE_CASE :		Any):
							os.makedirs(__SCREAMING_SNAKE_CASE     ,     exist_ok=__SCREAMING_SNAKE_CASE)

							if push_to_hub:
												A			=					kwargs.pop("commit_message"     ,     __SCREAMING_SNAKE_CASE)
												A			=					kwargs.pop("repo_id"     ,     save_directory.split(os.path.sep)[-1])
												A			=					self._create_repo(__SCREAMING_SNAKE_CASE     ,     **__SCREAMING_SNAKE_CASE)
												A			=					self._get_files_timestamps(__SCREAMING_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     ,     __SCREAMING_SNAKE_CASE) for attribute_name in self.attributes]
												A			=					[(a.init_kwargs if isinstance(__SCREAMING_SNAKE_CASE     ,     __SCREAMING_SNAKE_CASE) else a) for a in attrs]
												custom_object_save(self     ,     __SCREAMING_SNAKE_CASE     ,     config=__SCREAMING_SNAKE_CASE)

							for attribute_name in self.attributes:
												A			=					getattr(self     ,     __SCREAMING_SNAKE_CASE)
												# Include the processor class in the attribute config so this processor can then be reloaded with the
												# `AutoProcessor` API.
												if hasattr(__SCREAMING_SNAKE_CASE     ,     "_set_processor_class"):
																	attribute._set_processor_class(self.__class__.__name__)
												attribute.save_pretrained(__SCREAMING_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     ,     __SCREAMING_SNAKE_CASE)
																	if isinstance(__SCREAMING_SNAKE_CASE     ,     __SCREAMING_SNAKE_CASE):
																						del attribute.init_kwargs["auto_map"]

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


		@classmethod
		def 					SCREAMING_SNAKE_CASE__   (cls :		Union[str, Any]     ,     __SCREAMING_SNAKE_CASE :		Union[str, os.PathLike]     ,     __SCREAMING_SNAKE_CASE :		Optional[Union[str, os.PathLike]] = None     ,     __SCREAMING_SNAKE_CASE :		bool = False     ,     __SCREAMING_SNAKE_CASE :		bool = False     ,     __SCREAMING_SNAKE_CASE :		Optional[Union[str, bool]] = None     ,     __SCREAMING_SNAKE_CASE :		str = "main"     ,     **__SCREAMING_SNAKE_CASE :		int     ,     ):
							A			=					cache_dir
							A			=					force_download
							A			=					local_files_only
							A			=					revision

							A			=					kwargs.pop("use_auth_token"     ,     __SCREAMING_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."     ,     __SCREAMING_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(__SCREAMING_SNAKE_CASE     ,     **__SCREAMING_SNAKE_CASE)
							return cls(*__SCREAMING_SNAKE_CASE)


		@classmethod
		def 					SCREAMING_SNAKE_CASE__   (cls :		List[str]     ,     __SCREAMING_SNAKE_CASE :		Tuple="AutoProcessor"):
							if not isinstance(__SCREAMING_SNAKE_CASE     ,     __SCREAMING_SNAKE_CASE):
												A			=					auto_class.__name__

							import transformers.models.auto as auto_module

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

							A			=					auto_class


		@classmethod
		def 					SCREAMING_SNAKE_CASE__   (cls :		Optional[Any]     ,     __SCREAMING_SNAKE_CASE :		Tuple     ,     **__SCREAMING_SNAKE_CASE :		List[str]):
							A			=					[]
							for attribute_name in cls.attributes:
												A			=					getattr(cls     ,     F"""{attribute_name}_class""")
												if isinstance(__SCREAMING_SNAKE_CASE     ,     __SCREAMING_SNAKE_CASE):
																	A			=					tuple(getattr(__SCREAMING_SNAKE_CASE     ,     __SCREAMING_SNAKE_CASE) if n is not None else None for n in class_name)
																	A			=					kwargs.get("use_fast"     ,     __SCREAMING_SNAKE_CASE)
																	if use_fast and classes[1] is not None:
																						A			=					classes[1]
																	else:
																						A			=					classes[0]
												else:
																	A			=					getattr(__SCREAMING_SNAKE_CASE     ,     __SCREAMING_SNAKE_CASE)

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


		@property
		def 					SCREAMING_SNAKE_CASE__   (self :		Union[str, Any]):
							A			=					getattr(self     ,     self.attributes[0])
							return getattr(__SCREAMING_SNAKE_CASE     ,     "model_input_names"     ,     __SCREAMING_SNAKE_CASE)

__A     :    Union[str, Any]    =		copy_func(ProcessorMixin.push_to_hub)
if ProcessorMixin.push_to_hub.__doc__ is not None:
	__A     :    List[str]    =		ProcessorMixin.push_to_hub.__doc__.format(
	    object='processor', object_class='AutoProcessor', object_files='processor files'
	)













class   SCREAMING_SNAKE_CASE :





							"""simple docstring"""

							def __init__(     self:      Any      )			-> None:
												# numbermap keys are the number and its values are lists of indexes sorted
												# in ascending order
												_A									=       {}
												# indexmap keys are an index and it's values are the number at that index
												_A									=       {}

							def 					__A       (     self:      Any						,   __A:      list | str | range						,   __A:      int      )			-> list[int]:
												if isinstance(__A						,   (range, str)      ):
																	_A									=       list(__A      )
												elif not isinstance(__A						,   __A      ):
																	raise TypeError(
																	    '''binary_search_delete() only accepts either a list, range or str'''      )

												_A									=       0
												_A									=       len(__A      ) - 1

												while low <= high:
																	_A									=       (low + high) // 2
																	if array[mid] == item:
																						array.pop(__A      )
																						return array
																	elif array[mid] < item:
																						_A									=       mid + 1
																	else:
																						_A									=       mid - 1
												raise ValueError(
												    '''Either the item is not in the array or the array was unsorted'''      )

							def 					__A       (     self:      int						,   __A:      list | str | range						,   __A:      int      )			-> list[int]:
												if isinstance(__A						,   (range, str)      ):
																	_A									=       list(__A      )
												elif not isinstance(__A						,   __A      ):
																	raise TypeError(
																	    '''binary_search_insert() only accepts either a list, range or str'''      )

												_A									=       0
												_A									=       len(__A      ) - 1

												while low <= high:
																	_A									=       (low + high) // 2
																	if array[mid] == index:
																						# If the item already exists in the array,
																						# insert it after the existing item
																						array.insert(mid + 1						,   __A      )
																						return array
																	elif array[mid] < index:
																						_A									=       mid + 1
																	else:
																						_A									=       mid - 1

        # If the item doesn't exist in the array, insert it at the appropriate position
												array.insert(__A						,   __A      )
												return array

							def 					__A       (     self:      Union[str, Any]						,   __A:      int						,   __A:      int      )			-> None:
												# Remove previous index
												if index in self.indexmap:
																	_A									=       self.indexmap[index]
																	if len(self.numbermap[n]      ) == 1:
																						del self.numbermap[n]
																	else:
																						_A									=       self.binary_search_delete(self.numbermap[n]						,   __A      )

        # Set new index
												_A									=       number

												# Number not seen before or empty so insert number value
												if number not in self.numbermap:
																	_A									=       [index]

												# Here we need to perform a binary search insertion in order to insert
												# The item in the correct place
												else:
																	_A									=       self.binary_search_insert(
																	    self.numbermap[number]						,   __A      )



							def 					__A       (     self:      List[Any]						,   __A:      int      )			-> int:
												return self.numbermap.get(__A						,   [-1]      )[0]


if __name__ == "__main__":
				import doctest

				doctest.testmod()



