




import gc
import random
import tempfile
import unittest

import numpy as np
import torch
from PIL import Image
from transformers import CLIPTextConfig, CLIPTextModel, CLIPTokenizer

from diffusers import (
    AutoencoderKL,
    DDIMInverseScheduler,
    DDIMScheduler,
    DPMSolverMultistepInverseScheduler,
    DPMSolverMultistepScheduler,
    StableDiffusionDiffEditPipeline,
    UNetaDConditionModel,
)
from diffusers.utils import load_image, slow
from diffusers.utils.testing_utils import enable_full_determinism, floats_tensor, require_torch_gpu, torch_device

from ..pipeline_params import TEXT_GUIDED_IMAGE_INPAINTING_BATCH_PARAMS, TEXT_GUIDED_IMAGE_INPAINTING_PARAMS
from ..test_pipelines_common import PipelineLatentTesterMixin, PipelineTesterMixin


enable_full_determinism()




class       _A				(		__lowercase       ,     __lowercase       ,     unittest.TestCase     ):
		__a					    =       StableDiffusionDiffEditPipeline
		__a					    =       TEXT_GUIDED_IMAGE_INPAINTING_PARAMS - {"""height""", """width""", """image"""} | {"""image_latents"""}
		__a					    =       TEXT_GUIDED_IMAGE_INPAINTING_BATCH_PARAMS - {"""image"""} | {"""image_latents"""}
		__a					    =       frozenset(
		    []     )  # TO-DO: update image_params once pipeline is refactored with VaeImageProcessor.preprocess
		__a					    =       frozenset([]     )






		def 				UpperCAmelCase (    self			):
								torch.manual_seed(0			)
								_UpperCAmelCase      =			UNetaDConditionModel(
								    block_out_channels=(32, 64)						,		layers_per_block=2						,		sample_size=32						,		in_channels=4						,		out_channels=4						,		down_block_types=("""DownBlock2D""", """CrossAttnDownBlock2D""")						,		up_block_types=("""CrossAttnUpBlock2D""", """UpBlock2D""")						,		cross_attention_dim=32						,		attention_head_dim=(2, 4)						,		use_linear_projection=_SCREAMING_SNAKE_CASE						,		)
								_UpperCAmelCase      =			DDIMScheduler(
								    beta_start=0.0_0085						,		beta_end=0.012						,		beta_schedule="""scaled_linear"""						,		clip_sample=_SCREAMING_SNAKE_CASE						,		set_alpha_to_one=_SCREAMING_SNAKE_CASE						,		)
								_UpperCAmelCase      =			DDIMInverseScheduler(
								    beta_start=0.0_0085						,		beta_end=0.012						,		beta_schedule="""scaled_linear"""						,		clip_sample=_SCREAMING_SNAKE_CASE						,		set_alpha_to_zero=_SCREAMING_SNAKE_CASE						,		)
								torch.manual_seed(0			)
								_UpperCAmelCase      =			AutoencoderKL(
								    block_out_channels=[32, 64]						,		in_channels=3						,		out_channels=3						,		down_block_types=["""DownEncoderBlock2D""", """DownEncoderBlock2D"""]						,		up_block_types=["""UpDecoderBlock2D""", """UpDecoderBlock2D"""]						,		latent_channels=4						,		sample_size=128						,		)
								torch.manual_seed(0			)
								_UpperCAmelCase      =			CLIPTextConfig(
								    bos_token_id=0						,		eos_token_id=2						,		hidden_size=32						,		intermediate_size=37						,		layer_norm_eps=1e-05						,		num_attention_heads=4						,		num_hidden_layers=5						,		pad_token_id=1						,		vocab_size=1000						,		hidden_act="""gelu"""						,		projection_dim=512						,		)
								_UpperCAmelCase      =			CLIPTextModel(_SCREAMING_SNAKE_CASE			)
								_UpperCAmelCase      =			CLIPTokenizer.from_pretrained("""hf-internal-testing/tiny-random-clip"""			)

								_UpperCAmelCase      =			{
								    """unet""": unet,
								    """scheduler""": scheduler,
								    """inverse_scheduler""": inverse_scheduler,
								    """vae""": vae,
								    """text_encoder""": text_encoder,
								    """tokenizer""": tokenizer,
								    """safety_checker""": None,
								    """feature_extractor""": None,
								}

								return components






		def 				UpperCAmelCase (    self						,		_SCREAMING_SNAKE_CASE						,		_SCREAMING_SNAKE_CASE=0			):
								_UpperCAmelCase      =			floats_tensor((1, 16, 16)						,		rng=random.Random(_SCREAMING_SNAKE_CASE			)			).to(_SCREAMING_SNAKE_CASE			)
								_UpperCAmelCase      =			floats_tensor((1, 2, 4, 16, 16)						,		rng=random.Random(_SCREAMING_SNAKE_CASE			)			).to(_SCREAMING_SNAKE_CASE			)
								if str(_SCREAMING_SNAKE_CASE			).startswith("""mps"""			):
														_UpperCAmelCase      =			torch.manual_seed(_SCREAMING_SNAKE_CASE			)
								else:
														_UpperCAmelCase      =			torch.Generator(device=_SCREAMING_SNAKE_CASE			).manual_seed(_SCREAMING_SNAKE_CASE			)
								_UpperCAmelCase      =			{
								    """prompt""": """a dog and a newt""",
								    """mask_image""": mask,
								    """image_latents""": latents,
								    """generator""": generator,
								    """num_inference_steps""": 2,
								    """inpaint_strength""": 1.0,
								    """guidance_scale""": 6.0,
								    """output_type""": """numpy""",
								}

								return inputs






		def 				UpperCAmelCase (    self						,		_SCREAMING_SNAKE_CASE						,		_SCREAMING_SNAKE_CASE=0			):
								_UpperCAmelCase      =			floats_tensor((1, 3, 32, 32)						,		rng=random.Random(_SCREAMING_SNAKE_CASE			)			).to(_SCREAMING_SNAKE_CASE			)
								_UpperCAmelCase      =			image.cpu().permute(0						,		2						,		3						,		1			)[0]
								_UpperCAmelCase      =			Image.fromarray(np.uinta(_SCREAMING_SNAKE_CASE			)			).convert("""RGB"""			)
								if str(_SCREAMING_SNAKE_CASE			).startswith("""mps"""			):
														_UpperCAmelCase      =			torch.manual_seed(_SCREAMING_SNAKE_CASE			)
								else:
														_UpperCAmelCase      =			torch.Generator(device=_SCREAMING_SNAKE_CASE			).manual_seed(_SCREAMING_SNAKE_CASE			)
								_UpperCAmelCase      =			{
								    """image""": image,
								    """source_prompt""": """a cat and a frog""",
								    """target_prompt""": """a dog and a newt""",
								    """generator""": generator,
								    """num_inference_steps""": 2,
								    """num_maps_per_mask""": 2,
								    """mask_encode_strength""": 1.0,
								    """guidance_scale""": 6.0,
								    """output_type""": """numpy""",
								}

								return inputs






		def 				UpperCAmelCase (    self						,		_SCREAMING_SNAKE_CASE						,		_SCREAMING_SNAKE_CASE=0			):
								_UpperCAmelCase      =			floats_tensor((1, 3, 32, 32)						,		rng=random.Random(_SCREAMING_SNAKE_CASE			)			).to(_SCREAMING_SNAKE_CASE			)
								_UpperCAmelCase      =			image.cpu().permute(0						,		2						,		3						,		1			)[0]
								_UpperCAmelCase      =			Image.fromarray(np.uinta(_SCREAMING_SNAKE_CASE			)			).convert("""RGB"""			)
								if str(_SCREAMING_SNAKE_CASE			).startswith("""mps"""			):
														_UpperCAmelCase      =			torch.manual_seed(_SCREAMING_SNAKE_CASE			)
								else:
														_UpperCAmelCase      =			torch.Generator(device=_SCREAMING_SNAKE_CASE			).manual_seed(_SCREAMING_SNAKE_CASE			)
								_UpperCAmelCase      =			{
								    """image""": image,
								    """prompt""": """a cat and a frog""",
								    """generator""": generator,
								    """num_inference_steps""": 2,
								    """inpaint_strength""": 1.0,
								    """guidance_scale""": 6.0,
								    """decode_latents""": True,
								    """output_type""": """numpy""",
								}
								return inputs






		def 				UpperCAmelCase (    self			):
								if not hasattr(self.pipeline_class						,		"""_optional_components"""			):
														return

								_UpperCAmelCase      =			self.get_dummy_components()
								_UpperCAmelCase      =			self.pipeline_class(**_SCREAMING_SNAKE_CASE			)
								pipe.to(_SCREAMING_SNAKE_CASE			)
								pipe.set_progress_bar_config(disable=_SCREAMING_SNAKE_CASE			)

								# set all optional components to None and update pipeline config accordingly
								for optional_component in pipe._optional_components:
														setattr(_SCREAMING_SNAKE_CASE						,		_SCREAMING_SNAKE_CASE						,		_SCREAMING_SNAKE_CASE			)
								pipe.register_modules(**{optional_component: None for optional_component in pipe._optional_components}			)

								_UpperCAmelCase      =			self.get_dummy_inputs(_SCREAMING_SNAKE_CASE			)
								_UpperCAmelCase      =			pipe(**_SCREAMING_SNAKE_CASE			)[0]

								with tempfile.TemporaryDirectory() as tmpdir:
														pipe.save_pretrained(_SCREAMING_SNAKE_CASE			)
														_UpperCAmelCase      =			self.pipeline_class.from_pretrained(_SCREAMING_SNAKE_CASE			)
														pipe_loaded.to(_SCREAMING_SNAKE_CASE			)
														pipe_loaded.set_progress_bar_config(disable=_SCREAMING_SNAKE_CASE			)

								for optional_component in pipe._optional_components:
														self.assertTrue(
														    getattr(_SCREAMING_SNAKE_CASE						,		_SCREAMING_SNAKE_CASE			) is None						,		F"`{optional_component}` did not stay set to None after loading."						,		)

								_UpperCAmelCase      =			self.get_dummy_inputs(_SCREAMING_SNAKE_CASE			)
								_UpperCAmelCase      =			pipe_loaded(**_SCREAMING_SNAKE_CASE			)[0]

								_UpperCAmelCase      =			np.abs(output - output_loaded			).max()
								self.assertLess(_SCREAMING_SNAKE_CASE						,		1e-4			)






		def 				UpperCAmelCase (    self			):
								_UpperCAmelCase      =			"""cpu"""

								_UpperCAmelCase      =			self.get_dummy_components()
								_UpperCAmelCase      =			self.pipeline_class(**_SCREAMING_SNAKE_CASE			)
								pipe.to(_SCREAMING_SNAKE_CASE			)
								pipe.set_progress_bar_config(disable=_SCREAMING_SNAKE_CASE			)

								_UpperCAmelCase      =			self.get_dummy_mask_inputs(_SCREAMING_SNAKE_CASE			)
								_UpperCAmelCase      =			pipe.generate_mask(**_SCREAMING_SNAKE_CASE			)
								_UpperCAmelCase      =			mask[0, -3:, -3:]

								self.assertEqual(mask.shape						,		(1, 16, 16)			)
								_UpperCAmelCase      =			np.array([0] * 9			)
								_UpperCAmelCase      =			np.abs(mask_slice.flatten() - expected_slice			).max()
								self.assertLessEqual(_SCREAMING_SNAKE_CASE						,		1e-3			)
								self.assertEqual(mask[0, -3, -4]						,		0			)






		def 				UpperCAmelCase (    self			):
								_UpperCAmelCase      =			"""cpu"""

								_UpperCAmelCase      =			self.get_dummy_components()
								_UpperCAmelCase      =			self.pipeline_class(**_SCREAMING_SNAKE_CASE			)
								pipe.to(_SCREAMING_SNAKE_CASE			)
								pipe.set_progress_bar_config(disable=_SCREAMING_SNAKE_CASE			)

								_UpperCAmelCase      =			self.get_dummy_inversion_inputs(_SCREAMING_SNAKE_CASE			)
								_UpperCAmelCase      =			pipe.invert(**_SCREAMING_SNAKE_CASE			).images
								_UpperCAmelCase      =			image[0, -1, -3:, -3:]

								self.assertEqual(image.shape						,		(2, 32, 32, 3)			)
								_UpperCAmelCase      =			np.array(
								    [0.5150, 0.5134, 0.5043, 0.5376, 0.4694, 0.5_1050, 0.5015, 0.4407, 0.4799]						,		)
								_UpperCAmelCase      =			np.abs(image_slice.flatten() - expected_slice			).max()
								self.assertLessEqual(_SCREAMING_SNAKE_CASE						,		1e-3			)






		def 				UpperCAmelCase (    self			):
								super().test_inference_batch_single_identical(expected_max_diff=5e-3			)






		def 				UpperCAmelCase (    self			):
								_UpperCAmelCase      =			"""cpu"""

								_UpperCAmelCase      =			self.get_dummy_components()

								_UpperCAmelCase      =			{"""beta_start""": 0.0_0085, """beta_end""": 0.012, """beta_schedule""": """scaled_linear"""}
								_UpperCAmelCase      =			DPMSolverMultistepScheduler(**_SCREAMING_SNAKE_CASE			)
								_UpperCAmelCase      =			DPMSolverMultistepInverseScheduler(**_SCREAMING_SNAKE_CASE			)

								_UpperCAmelCase      =			self.pipeline_class(**_SCREAMING_SNAKE_CASE			)
								pipe.to(_SCREAMING_SNAKE_CASE			)
								pipe.set_progress_bar_config(disable=_SCREAMING_SNAKE_CASE			)

								_UpperCAmelCase      =			self.get_dummy_inversion_inputs(_SCREAMING_SNAKE_CASE			)
								_UpperCAmelCase      =			pipe.invert(**_SCREAMING_SNAKE_CASE			).images
								_UpperCAmelCase      =			image[0, -1, -3:, -3:]

								self.assertEqual(image.shape						,		(2, 32, 32, 3)			)
								_UpperCAmelCase      =			np.array(
								    [0.5150, 0.5134, 0.5043, 0.5376, 0.4694, 0.5_1050, 0.5015, 0.4407, 0.4799]						,		)
								_UpperCAmelCase      =			np.abs(image_slice.flatten() - expected_slice			).max()
								self.assertLessEqual(_SCREAMING_SNAKE_CASE						,		1e-3			)




@require_torch_gpu
@slow
class       _A				(		unittest.TestCase     ):






		def 				UpperCAmelCase (    self			):
								super().tearDown()
								gc.collect()
								torch.cuda.empty_cache()






		@classmethod
		def 				UpperCAmelCase (    cls			):
								_UpperCAmelCase      =			load_image(
								    """https://huggingface.co/datasets/hf-internal-testing/diffusers-images/resolve/main/diffedit/fruit.png"""			)

								_UpperCAmelCase      =			raw_image.convert("""RGB"""			).resize((768, 768)			)

								_UpperCAmelCase      =			raw_image






		def 				UpperCAmelCase (    self			):
								_UpperCAmelCase      =			torch.manual_seed(0			)

								_UpperCAmelCase      =			StableDiffusionDiffEditPipeline.from_pretrained(
								    """stabilityai/stable-diffusion-2-1"""						,		safety_checker=_SCREAMING_SNAKE_CASE						,		torch_dtype=torch.floataa			)
								_UpperCAmelCase      =			DDIMScheduler.from_config(pipe.scheduler.config			)
								_UpperCAmelCase      =			DDIMInverseScheduler.from_config(pipe.scheduler.config			)
								pipe.enable_model_cpu_offload()
								pipe.set_progress_bar_config(disable=_SCREAMING_SNAKE_CASE			)

								_UpperCAmelCase      =			"""a bowl of fruit"""
								_UpperCAmelCase      =			"""a bowl of pears"""

								_UpperCAmelCase      =			pipe.generate_mask(
								    image=self.raw_image						,		source_prompt=_SCREAMING_SNAKE_CASE						,		target_prompt=_SCREAMING_SNAKE_CASE						,		generator=_SCREAMING_SNAKE_CASE						,		)

								_UpperCAmelCase      =			pipe.invert(
								    prompt=_SCREAMING_SNAKE_CASE						,		image=self.raw_image						,		inpaint_strength=0.7						,		generator=_SCREAMING_SNAKE_CASE			).latents

								_UpperCAmelCase      =			pipe(
								    prompt=_SCREAMING_SNAKE_CASE						,		mask_image=_SCREAMING_SNAKE_CASE						,		image_latents=_SCREAMING_SNAKE_CASE						,		generator=_SCREAMING_SNAKE_CASE						,		negative_prompt=_SCREAMING_SNAKE_CASE						,		inpaint_strength=0.7						,		output_type="""numpy"""						,		).images[0]

								_UpperCAmelCase      =			(
								    np.array(
								        load_image(
								            """https://huggingface.co/datasets/hf-internal-testing/diffusers-images/resolve/main"""
								            """/diffedit/pears.png"""			).resize((768, 768)			)			)
								    / 255
								)
								assert np.abs((expected_image - image).max()			) < 5e-1






		def 				UpperCAmelCase (    self			):
								_UpperCAmelCase      =			torch.manual_seed(0			)

								_UpperCAmelCase      =			StableDiffusionDiffEditPipeline.from_pretrained(
								    """stabilityai/stable-diffusion-2-1"""						,		safety_checker=_SCREAMING_SNAKE_CASE						,		torch_dtype=torch.floataa			)
								_UpperCAmelCase      =			DPMSolverMultistepScheduler.from_config(pipe.scheduler.config			)
								_UpperCAmelCase      =			DPMSolverMultistepInverseScheduler.from_config(pipe.scheduler.config			)
								pipe.enable_model_cpu_offload()
								pipe.set_progress_bar_config(disable=_SCREAMING_SNAKE_CASE			)

								_UpperCAmelCase      =			"""a bowl of fruit"""
								_UpperCAmelCase      =			"""a bowl of pears"""

								_UpperCAmelCase      =			pipe.generate_mask(
								    image=self.raw_image						,		source_prompt=_SCREAMING_SNAKE_CASE						,		target_prompt=_SCREAMING_SNAKE_CASE						,		generator=_SCREAMING_SNAKE_CASE						,		)

								_UpperCAmelCase      =			pipe.invert(
								    prompt=_SCREAMING_SNAKE_CASE						,		image=self.raw_image						,		inpaint_strength=0.7						,		generator=_SCREAMING_SNAKE_CASE						,		num_inference_steps=25						,		).latents

								_UpperCAmelCase      =			pipe(
								    prompt=_SCREAMING_SNAKE_CASE						,		mask_image=_SCREAMING_SNAKE_CASE						,		image_latents=_SCREAMING_SNAKE_CASE						,		generator=_SCREAMING_SNAKE_CASE						,		negative_prompt=_SCREAMING_SNAKE_CASE						,		inpaint_strength=0.7						,		num_inference_steps=25						,		output_type="""numpy"""						,		).images[0]

								_UpperCAmelCase      =			(
								    np.array(
								        load_image(
								            """https://huggingface.co/datasets/hf-internal-testing/diffusers-images/resolve/main"""
								            """/diffedit/pears.png"""			).resize((768, 768)			)			)
								    / 255
								)
								assert np.abs((expected_image - image).max()			) < 5e-1





import itertools
import string
from collections.abc import Generator, Iterable




def        _SCREAMING_SNAKE_CASE      (		snake_case			,     snake_case       )						->				Generator[tuple[str, ...], None, None]:
						_UpperCAmelCase      =			iter(snake_case       )
						while True:
												_UpperCAmelCase      =			tuple(itertools.islice(snake_case			,     snake_case       )       )
												if not chunk:
																		return
												yield chunk




def        _SCREAMING_SNAKE_CASE      (		snake_case       )						->				str:
						_UpperCAmelCase      =			"""""".join([c.upper() for c in dirty if c in string.ascii_letters]       )
						_UpperCAmelCase      =			""""""

						if len(snake_case       ) < 2:
												return dirty

						for i in range(len(snake_case       ) - 1       ):
												clean += dirty[i]

												if dirty[i] == dirty[i + 1]:
																		clean += "X"

						clean += dirty[-1]

						if len(snake_case       ) & 1:
												clean += "X"

						return clean




def        _SCREAMING_SNAKE_CASE      (		snake_case       )						->				list[str]:
						# I and J are used interchangeably to allow
						# us to use a 5x5 table (25 letters)
						_UpperCAmelCase      =			"""ABCDEFGHIKLMNOPQRSTUVWXYZ"""
						# we're using a list instead of a '2d' array because it makes the math
						# for setting up the table and doing the actual encoding/decoding simpler
						_UpperCAmelCase      =			[]

						# copy key chars into the table if they are in `alphabet` ignoring duplicates
						for char in key.upper():
												if char not in table and char in alphabet:
																		table.append(snake_case       )

    # fill the rest of the table in with the remaining alphabet chars
						for char in alphabet:
												if char not in table:
																		table.append(snake_case       )

						return table




def        _SCREAMING_SNAKE_CASE      (		snake_case			,     snake_case       )						->				str:
						_UpperCAmelCase      =			generate_table(snake_case       )
						_UpperCAmelCase      =			prepare_input(snake_case       )
						_UpperCAmelCase      =			""""""

						# https://en.wikipedia.org/wiki/Playfair_cipher#Description
						for chara, chara in chunker(snake_case			,     2       ):
												_UpperCAmelCase    ,					_UpperCAmelCase      =			divmod(table.index(snake_case       )			,     5       )
												_UpperCAmelCase    ,					_UpperCAmelCase      =			divmod(table.index(snake_case       )			,     5       )

												if rowa == rowa:
																		ciphertext += table[rowa * 5 + (cola + 1) % 5]
																		ciphertext += table[rowa * 5 + (cola + 1) % 5]
												elif cola == cola:
																		ciphertext += table[((rowa + 1) % 5) * 5 + cola]
																		ciphertext += table[((rowa + 1) % 5) * 5 + cola]
												else:  # rectangle
																		ciphertext += table[rowa * 5 + cola]
																		ciphertext += table[rowa * 5 + cola]

						return ciphertext




def        _SCREAMING_SNAKE_CASE      (		snake_case			,     snake_case       )						->				str:
						_UpperCAmelCase      =			generate_table(snake_case       )
						_UpperCAmelCase      =			""""""

						# https://en.wikipedia.org/wiki/Playfair_cipher#Description
						for chara, chara in chunker(snake_case			,     2       ):
												_UpperCAmelCase    ,					_UpperCAmelCase      =			divmod(table.index(snake_case       )			,     5       )
												_UpperCAmelCase    ,					_UpperCAmelCase      =			divmod(table.index(snake_case       )			,     5       )

												if rowa == rowa:
																		plaintext += table[rowa * 5 + (cola - 1) % 5]
																		plaintext += table[rowa * 5 + (cola - 1) % 5]
												elif cola == cola:
																		plaintext += table[((rowa - 1) % 5) * 5 + cola]
																		plaintext += table[((rowa - 1) % 5) * 5 + cola]
												else:  # rectangle
																		plaintext += table[rowa * 5 + cola]
																		plaintext += table[rowa * 5 + cola]

						return plaintext