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     :			Union[str, Any]					    =						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     :			Union[str, Any]					    =						{
    '''AutoTokenizer''': '''PreTrainedTokenizerBase''',
    '''AutoFeatureExtractor''': '''FeatureExtractionMixin''',
    '''AutoImageProcessor''': '''ImageProcessingMixin''',
}

class 				_lowercase						(    lowercase__ ):






    '''simple docstring'''
    SCREAMING_SNAKE_CASE:							str        =						["""feature_extractor""", """tokenizer"""]
    # Names need to be attr_class for attr in attributes
    SCREAMING_SNAKE_CASE:							int        =						None
    SCREAMING_SNAKE_CASE:							List[str]        =						None
    SCREAMING_SNAKE_CASE:							List[Any]        =						None




    def __init__(						self					,	*lowerCamelCase__					,	**lowerCamelCase__   ):
        # 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(_A					,	self.attributes   ):
            if attribute_name in kwargs:
                raise TypeError(F'''Got multiple values for argument {attribute_name}.'''   )
            else:
                lowerCAmelCase_:       Any         =  arg

        if len(_A   ) != len(self.attributes   ):
            raise ValueError(
                F'''This processor requires {len(self.attributes   )} arguments: {", ".join(self.attributes   )}. Got '''
                F'''{len(_A   )} 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():
            lowerCAmelCase_:       List[Any]         =  getattr(self					,	F'''{attribute_name}_class'''   )
            # Nothing is ever going to be an instance of "AutoXxx", in that case we check the base class.
            lowerCAmelCase_:       int         =  AUTO_TO_BASE_CLASS_MAPPING.get(_A					,	_A   )
            if isinstance(_A					,	_A   ):
                lowerCAmelCase_:       List[Any]         =  tuple(getattr(_A					,	_A   ) for n in class_name if n is not None   )
            else:
                lowerCAmelCase_:       Optional[int]         =  getattr(_A					,	_A   )

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

            setattr(self					,	_A					,	_A   )




    def __repr__(						self   ):
        lowerCAmelCase_:       int         =  [F'''- {name}: {repr(getattr(self					,	_A   )   )}''' for name in self.attributes]
        lowerCAmelCase_:       Union[str, Any]         =  '\n'.join(_A   )
        return F'''{self.__class__.__name__}:\n{attributes_repr}'''




    def     _a						(						self					,	lowerCamelCase__					,	lowerCamelCase__ = False					,	**lowerCamelCase__   ):
        os.makedirs(_A					,	exist_ok=_A   )

        if push_to_hub:
            lowerCAmelCase_:       Dict         =  kwargs.pop("commit_message"					,	_A   )
            lowerCAmelCase_:       Optional[Any]         =  kwargs.pop("repo_id"					,	save_directory.split(os.path.sep   )[-1]   )
            lowerCAmelCase_:       List[str]         =  self._create_repo(_A					,	**_A   )
            lowerCAmelCase_:       Optional[Any]         =  self._get_files_timestamps(_A   )
        # 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:
            lowerCAmelCase_:       Optional[Any]         =  [getattr(self					,	_A   ) for attribute_name in self.attributes]
            lowerCAmelCase_:       Dict         =  [(a.init_kwargs if isinstance(_A					,	_A   ) else a) for a in attrs]
            custom_object_save(self					,	_A					,	config=_A   )

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

        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:
                lowerCAmelCase_:       Optional[int]         =  getattr(self					,	_A   )
                if isinstance(_A					,	_A   ):
                    del attribute.init_kwargs["auto_map"]

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




    @classmethod
    def     _a						(						cls					,	lowerCamelCase__					,	lowerCamelCase__ = None					,	lowerCamelCase__ = False					,	lowerCamelCase__ = False					,	lowerCamelCase__ = None					,	lowerCamelCase__ = "main"					,	**lowerCamelCase__					,	):
        lowerCAmelCase_:       str         =  cache_dir
        lowerCAmelCase_:       Any         =  force_download
        lowerCAmelCase_:       List[str]         =  local_files_only
        lowerCAmelCase_:       Optional[int]         =  revision

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

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

        lowerCAmelCase_:       Dict         =  cls._get_arguments_from_pretrained(_A					,	**_A   )
        return cls(*_A   )




    @classmethod
    def     _a						(						cls					,	lowerCamelCase__="AutoProcessor"   ):
        if not isinstance(_A					,	_A   ):
            lowerCAmelCase_:       Dict         =  auto_class.__name__

        import transformers.models.auto as auto_module

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

        lowerCAmelCase_:       Tuple         =  auto_class




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

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




    @property
    def     _a						(						self   ):
        lowerCAmelCase_:       Optional[Any]         =  getattr(self					,	self.attributes[0]   )
        return getattr(_A					,	"model_input_names"					,	_A   )





a     :			str					    =						copy_func(ProcessorMixin.push_to_hub)
if ProcessorMixin.push_to_hub.__doc__ is not None:
 a     :			str					    =						ProcessorMixin.push_to_hub.__doc__.format(
     object="""processor""", object_class="""AutoProcessor""", object_files="""processor files"""
 )
def 		snake_case__  (		lowercase = 998001				):

   # fetches the next number
   for number in range(n - 1       ,							9999       ,							-1				):
      lowerCAmelCase_:       str         =  str(lowercase				)

      # checks whether 'str_number' is a palindrome.
      if str_number == str_number[::-1]:
         lowerCAmelCase_:       List[str]         =  999

         # if 'number' is a product of two 3-digit numbers
         # then number is the answer otherwise fetch next number.
         while divisor != 99:
            if (number % divisor == 0) and (len(str(number // divisor				)				) == 3.0):
               return number
            divisor -= 1
   raise ValueError("That number is larger than our acceptable range."				)


if __name__ == "__main__":
 print(f'''{solution() = }''')