




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


__lowerCAmelCase						:							Union[str, Any]			     =						logging.get_logger(__name__)

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


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




class        snake_case__				(_UpperCamelCase  ):
				"""simple docstring"""



				SCREAMING_SNAKE_CASE_			:				Union[str, Any]									=   ["""feature_extractor""", """tokenizer"""]
				# Names need to be attr_class for attr in attributes
				SCREAMING_SNAKE_CASE_			:				Dict									=   None
				SCREAMING_SNAKE_CASE_			:				List[Any]									=   None
				SCREAMING_SNAKE_CASE_			:				int									=   None





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

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

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

										setattr(self   , __lowerCamelCase   , __lowerCamelCase				)





				def __repr__( self							:	Tuple				)   ->	str:
							a       =     [f"""- {name}: {repr(getattr(self   , __lowerCamelCase				)				)}""" for name in self.attributes]
							a       =     "\n".join(__lowerCamelCase				)
							return f"""{self.__class__.__name__}:\n{attributes_repr}"""





				def 				__UpperCAmelCase				( self							:	Optional[int]   , __lowerCamelCase							:	Optional[int]   , __lowerCamelCase							:	bool = False   , **__lowerCamelCase							:	Optional[Any]				)   ->	List[str]:
							os.makedirs(__lowerCamelCase   , exist_ok=__lowerCamelCase				)

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

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

							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   , __lowerCamelCase				)
													if isinstance(__lowerCamelCase   , __lowerCamelCase				):
																del attribute.init_kwargs["auto_map"]

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





				@classmethod
				def 				__UpperCAmelCase				( cls							:	List[str]   , __lowerCamelCase							:	Union[str, os.PathLike]   , __lowerCamelCase							:	Optional[Union[str, os.PathLike]] = None   , __lowerCamelCase							:	bool = False   , __lowerCamelCase							:	bool = False   , __lowerCamelCase							:	Optional[Union[str, bool]] = None   , __lowerCamelCase							:	str = "main"   , **__lowerCamelCase							:	Optional[int]   , )   ->	List[Any]:
							a       =     cache_dir
							a       =     force_download
							a       =     local_files_only
							a       =     revision

							a       =     kwargs.pop("use_auth_token"   , __lowerCamelCase				)
							if use_auth_token is not None:
										warnings.warn(
										    "The `use_auth_token` argument is deprecated and will be removed in v5 of Transformers."   , __lowerCamelCase				)
										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(__lowerCamelCase   , **__lowerCamelCase				)
							return cls(*__lowerCamelCase				)





				@classmethod
				def 				__UpperCAmelCase				( cls							:	List[Any]   , __lowerCamelCase							:	Dict="AutoProcessor"				)   ->	Optional[int]:
							if not isinstance(__lowerCamelCase   , __lowerCamelCase				):
										a       =     auto_class.__name__

							import transformers.models.auto as auto_module

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

							a       =     auto_class





				@classmethod
				def 				__UpperCAmelCase				( cls							:	int   , __lowerCamelCase							:	Union[str, Any]   , **__lowerCamelCase							:	Any				)   ->	Optional[int]:
							a       =     []
							for attribute_name in cls.attributes:
										a       =     getattr(cls   , f"""{attribute_name}_class"""				)
										if isinstance(__lowerCamelCase   , __lowerCamelCase				):
													a       =     tuple(getattr(__lowerCamelCase   , __lowerCamelCase				) if n is not None else None for n in class_name				)
													a       =     kwargs.get("use_fast"   , __lowerCamelCase				)
													if use_fast and classes[1] is not None:
																a       =     classes[1]
													else:
																a       =     classes[0]
										else:
													a       =     getattr(__lowerCamelCase   , __lowerCamelCase				)

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





				@property
				def 				__UpperCAmelCase				( self							:	Union[str, Any]				)   ->	List[Any]:
							a       =     getattr(self   , self.attributes[0]				)
							return getattr(__lowerCamelCase   , "model_input_names"   , __lowerCamelCase				)

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












import tempfile
import unittest

import torch

from diffusers import UNetaDConditionModel
from diffusers.training_utils import EMAModel
from diffusers.utils.testing_utils import enable_full_determinism, skip_mps, torch_device


enable_full_determinism()




class        snake_case__				(unittest.TestCase  ):
				"""simple docstring"""



				SCREAMING_SNAKE_CASE_			:				Optional[int]									=   """hf-internal-testing/tiny-stable-diffusion-pipe"""
				SCREAMING_SNAKE_CASE_			:				str									=   1
				SCREAMING_SNAKE_CASE_			:				Dict									=   77
				SCREAMING_SNAKE_CASE_			:				List[str]									=   32
				SCREAMING_SNAKE_CASE_			:				List[str]									=   4
				SCREAMING_SNAKE_CASE_			:				Union[str, Any]									=   64
				SCREAMING_SNAKE_CASE_			:				int									=   torch.manual_seed(0  )





				def 				__UpperCAmelCase				( self							:	List[Any]   , __lowerCamelCase							:	List[Any]=0.9_999				)   ->	Tuple:
							a       =     UNetaDConditionModel.from_pretrained(self.model_id   , subfolder="unet"				)
							a       =     unet.to(__lowerCamelCase				)
							a       =     EMAModel(unet.parameters()   , decay=__lowerCamelCase   , model_cls=__lowerCamelCase   , model_config=unet.config				)
							return unet, ema_unet





				def 				__UpperCAmelCase				( self							:	Tuple				)   ->	Any:
							a       =     torch.randn(
							    self.batch_size   , self.num_in_channels   , self.latent_height   , self.latent_width   , generator=self.generator				).to(__lowerCamelCase				)
							a       =     torch.randint(0   , 10_00   , size=(self.batch_size,)   , generator=self.generator				).to(__lowerCamelCase				)
							a       =     torch.randn(
							    self.batch_size   , self.prompt_length   , self.text_encoder_hidden_dim   , generator=self.generator				).to(__lowerCamelCase				)
							return noisy_latents, timesteps, encoder_hidden_states





				def 				__UpperCAmelCase				( self							:	Optional[int]   , __lowerCamelCase							:	Any				)   ->	Optional[int]:
							a       =     {}
							for k, param in unet.state_dict().items():
										a       =     torch.randn_like(__lowerCamelCase				) + (param * torch.randn_like(__lowerCamelCase				))
										updated_state_dict.update({k: updated_param}				)
							unet.load_state_dict(__lowerCamelCase				)
							return unet





				def 				__UpperCAmelCase				( self							:	Optional[Any]				)   ->	Union[str, Any]:
							a       ,						a       =     self.get_models()
							# Take the first (hypothetical) EMA step.
							ema_unet.step(unet.parameters()				)
							assert ema_unet.optimization_step == 1

							# Take two more.
							for _ in range(2				):
										ema_unet.step(unet.parameters()				)
							assert ema_unet.optimization_step == 3





				def 				__UpperCAmelCase				( self							:	Optional[int]				)   ->	Optional[int]:
							a       ,						a       =     self.get_models()
							# Since the `unet` is not being updated (i.e., backprop'd)
							# there won't be any difference between the `params` of `unet`
							# and `ema_unet` even if we call `ema_unet.step(unet.parameters())`.
							ema_unet.step(unet.parameters()				)
							a       =     list(unet.parameters()				)
							for s_param, param in zip(ema_unet.shadow_params   , __lowerCamelCase				):
										assert torch.allclose(__lowerCamelCase   , __lowerCamelCase				)

							# The above holds true even if we call `ema.step()` multiple times since
							# `unet` params are still not being updated.
							for _ in range(4				):
										ema_unet.step(unet.parameters()				)
							for s_param, param in zip(ema_unet.shadow_params   , __lowerCamelCase				):
										assert torch.allclose(__lowerCamelCase   , __lowerCamelCase				)





				def 				__UpperCAmelCase				( self							:	Any				)   ->	Dict:
							a       ,						a       =     self.get_models()
							# Here we simulate the parameter updates for `unet`. Since there might
							# be some parameters which are initialized to zero we take extra care to
							# initialize their values to something non-zero before the multiplication.
							a       =     self.simulate_backprop(__lowerCamelCase				)

							# Take the EMA step.
							ema_unet.step(unet_pseudo_updated_step_one.parameters()				)

							# Now the EMA'd parameters won't be equal to the original model parameters.
							a       =     list(unet_pseudo_updated_step_one.parameters()				)
							for s_param, param in zip(ema_unet.shadow_params   , __lowerCamelCase				):
										assert ~torch.allclose(__lowerCamelCase   , __lowerCamelCase				)

							# Ensure this is the case when we take multiple EMA steps.
							for _ in range(4				):
										ema_unet.step(unet.parameters()				)
							for s_param, param in zip(ema_unet.shadow_params   , __lowerCamelCase				):
										assert ~torch.allclose(__lowerCamelCase   , __lowerCamelCase				)





				def 				__UpperCAmelCase				( self							:	Optional[Any]				)   ->	Any:
							# If we call EMA step after a backpropagation consecutively for two times,
							# the shadow params from those two steps should be different.
							a       ,						a       =     self.get_models()

							# First backprop + EMA
							a       =     self.simulate_backprop(__lowerCamelCase				)
							ema_unet.step(unet_step_one.parameters()				)
							a       =     ema_unet.shadow_params

							# Second backprop + EMA
							a       =     self.simulate_backprop(__lowerCamelCase				)
							ema_unet.step(unet_step_two.parameters()				)
							a       =     ema_unet.shadow_params

							for step_one, step_two in zip(__lowerCamelCase   , __lowerCamelCase				):
										assert ~torch.allclose(__lowerCamelCase   , __lowerCamelCase				)





				def 				__UpperCAmelCase				( self							:	Any				)   ->	List[Any]:
							# If there's no decay even if there are backprops, EMA steps
							# won't take any effect i.e., the shadow params would remain the
							# same.
							a       ,						a       =     self.get_models(decay=0.0				)
							a       =     self.simulate_backprop(__lowerCamelCase				)
							ema_unet.step(unet_step_one.parameters()				)
							a       =     ema_unet.shadow_params

							a       =     self.simulate_backprop(__lowerCamelCase				)
							ema_unet.step(unet_step_two.parameters()				)
							a       =     ema_unet.shadow_params

							for step_one, step_two in zip(__lowerCamelCase   , __lowerCamelCase				):
										assert torch.allclose(__lowerCamelCase   , __lowerCamelCase				)





				@skip_mps
				def 				__UpperCAmelCase				( self							:	List[str]				)   ->	Dict:
							a       ,						a       =     self.get_models()
							a       ,						a       ,						a       =     self.get_dummy_inputs()

							with tempfile.TemporaryDirectory() as tmpdir:
										ema_unet.save_pretrained(__lowerCamelCase				)
										a       =     UNetaDConditionModel.from_pretrained(__lowerCamelCase   , model_cls=__lowerCamelCase				)
										a       =     loaded_unet.to(unet.device				)

							# Since no EMA step has been performed the outputs should match.
							a       =     unet(__lowerCamelCase   , __lowerCamelCase   , __lowerCamelCase				).sample
							a       =     loaded_unet(__lowerCamelCase   , __lowerCamelCase   , __lowerCamelCase				).sample

							assert torch.allclose(__lowerCamelCase   , __lowerCamelCase   , atol=1e-4				)






