




import gc
import random
import unittest

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

import diffusers
from diffusers import (
    AutoencoderKL,
    EulerDiscreteScheduler,
    StableDiffusionLatentUpscalePipeline,
    StableDiffusionPipeline,
    UNetaDConditionModel,
)
from diffusers.schedulers import KarrasDiffusionSchedulers
from diffusers.utils import floats_tensor, load_image, load_numpy, slow, torch_device
from diffusers.utils.testing_utils import enable_full_determinism, require_torch_gpu

from ..pipeline_params import TEXT_GUIDED_IMAGE_VARIATION_BATCH_PARAMS, TEXT_GUIDED_IMAGE_VARIATION_PARAMS
from ..test_pipelines_common import PipelineKarrasSchedulerTesterMixin, PipelineLatentTesterMixin, PipelineTesterMixin


enable_full_determinism()


def 		lowerCamelCase__       (						_A				):







	'''simple docstring'''





	snake_case_						       =	[tensor.shape for tensor in tensor_list]
	return all(shape == shapes[0] for shape in shapes[1:]				)
class 						UpperCAmelCase  (							UpperCAmelCase__			,  UpperCAmelCase__			,  UpperCAmelCase__			,  unittest.TestCase     ):







						'''simple docstring'''





						lowerCAmelCase_							=  StableDiffusionLatentUpscalePipeline
						lowerCAmelCase_							=  TEXT_GUIDED_IMAGE_VARIATION_PARAMS - {
						    '''height''',
						    '''width''',
						    '''cross_attention_kwargs''',
						    '''negative_prompt_embeds''',
						    '''prompt_embeds''',
						}
						lowerCAmelCase_							=  PipelineTesterMixin.required_optional_params - {'''num_images_per_prompt'''}
						lowerCAmelCase_							=  TEXT_GUIDED_IMAGE_VARIATION_BATCH_PARAMS
						lowerCAmelCase_							=  frozenset(
						    []     )  # TO-DO: update image_params once pipeline is refactored with VaeImageProcessor.preprocess
						lowerCAmelCase_							=  frozenset([]     )

						lowerCAmelCase_							=  True






						@property
						def 			snake_case__		(		self				:	Tuple		):






							"""simple docstring"""






							snake_case_						       =	1
							snake_case_						       =	4
							snake_case_						       =	(16, 16)

							snake_case_						       =	floats_tensor((batch_size, num_channels) + sizes			,      rng=random.Random(0		)		).to(__lowercase		)
							return image






						def 			snake_case__		(		self				:	Optional[Any]		):






							"""simple docstring"""






							torch.manual_seed(0		)
							snake_case_						       =	UNetaDConditionModel(
							    act_fn="gelu"			,      attention_head_dim=8			,      norm_num_groups=__lowercase			,      block_out_channels=[32, 32, 64, 64]			,      time_cond_proj_dim=1_60			,      conv_in_kernel=1			,      conv_out_kernel=1			,      cross_attention_dim=32			,      down_block_types=(
							        "KDownBlock2D",
							        "KCrossAttnDownBlock2D",
							        "KCrossAttnDownBlock2D",
							        "KCrossAttnDownBlock2D",
							    )			,      in_channels=8			,      mid_block_type=__lowercase			,      only_cross_attention=__lowercase			,      out_channels=5			,      resnet_time_scale_shift="scale_shift"			,      time_embedding_type="fourier"			,      timestep_post_act="gelu"			,      up_block_types=("KCrossAttnUpBlock2D", "KCrossAttnUpBlock2D", "KCrossAttnUpBlock2D", "KUpBlock2D")			,      )
							snake_case_						       =	AutoencoderKL(
							    block_out_channels=[32, 32, 64, 64]			,      in_channels=3			,      out_channels=3			,      down_block_types=[
							        "DownEncoderBlock2D",
							        "DownEncoderBlock2D",
							        "DownEncoderBlock2D",
							        "DownEncoderBlock2D",
							    ]			,      up_block_types=["UpDecoderBlock2D", "UpDecoderBlock2D", "UpDecoderBlock2D", "UpDecoderBlock2D"]			,      latent_channels=4			,      )
							snake_case_						       =	EulerDiscreteScheduler(prediction_type="sample"		)
							snake_case_						       =	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=10_00			,      hidden_act="quick_gelu"			,      projection_dim=5_12			,      )
							snake_case_						       =	CLIPTextModel(__lowercase		)
							snake_case_						       =	CLIPTokenizer.from_pretrained("hf-internal-testing/tiny-random-clip"		)

							snake_case_						       =	{
							    "unet": model.eval(),
							    "vae": vae.eval(),
							    "scheduler": scheduler,
							    "text_encoder": text_encoder,
							    "tokenizer": tokenizer,
							}

							return components






						def 			snake_case__		(		self				:	int			,      __lowercase				:	List[str]			,      __lowercase				:	Tuple=0		):






							"""simple docstring"""






							if str(__lowercase		).startswith("mps"		):
								snake_case_						       =	torch.manual_seed(__lowercase		)
							else:
								snake_case_						       =	torch.Generator(device=__lowercase		).manual_seed(__lowercase		)
							snake_case_						       =	{
							    "prompt": "A painting of a squirrel eating a burger",
							    "image": self.dummy_image.cpu(),
							    "generator": generator,
							    "num_inference_steps": 2,
							    "output_type": "numpy",
							}
							return inputs






						def 			snake_case__		(		self				:	List[str]		):






							"""simple docstring"""






							snake_case_						       =	"cpu"

							snake_case_						       =	self.get_dummy_components()
							snake_case_						       =	self.pipeline_class(**__lowercase		)
							pipe.to(__lowercase		)
							pipe.set_progress_bar_config(disable=__lowercase		)

							snake_case_						       =	self.get_dummy_inputs(__lowercase		)
							snake_case_						       =	pipe(**__lowercase		).images
							snake_case_						       =	image[0, -3:, -3:, -1]

							self.assertEqual(image.shape			,      (1, 2_56, 2_56, 3)		)
							snake_case_						       =	np.array(
							    [0.4722_2412, 0.4192_1633, 0.4471_7434, 0.4687_4192, 0.4258_8258, 0.4615_0726, 0.467_7534, 0.4558_3832, 0.4857_9055]		)
							snake_case_						       =	np.abs(image_slice.flatten() - expected_slice		).max()
							self.assertLessEqual(__lowercase			,      1E-3		)






						def 			snake_case__		(		self				:	List[Any]		):






							"""simple docstring"""






							super().test_attention_slicing_forward_pass(expected_max_diff=7E-3		)






						def 			snake_case__		(		self				:	List[str]		):






							"""simple docstring"""






							super().test_cpu_offload_forward_pass(expected_max_diff=3E-3		)






						def 			snake_case__		(		self				:	str		):






							"""simple docstring"""






							super().test_dict_tuple_outputs_equivalent(expected_max_difference=3E-3		)






						def 			snake_case__		(		self				:	Union[str, Any]		):






							"""simple docstring"""






							super().test_inference_batch_single_identical(expected_max_diff=7E-3		)






						def 			snake_case__		(		self				:	Dict		):






							"""simple docstring"""






							super().test_pt_np_pil_outputs_equivalent(expected_max_diff=3E-3		)






						def 			snake_case__		(		self				:	Optional[Any]		):






							"""simple docstring"""






							super().test_save_load_local(expected_max_difference=3E-3		)






						def 			snake_case__		(		self				:	List[Any]		):






							"""simple docstring"""






							super().test_save_load_optional_components(expected_max_difference=3E-3		)






						def 			snake_case__		(		self				:	str		):






							"""simple docstring"""






							snake_case_						       =	[
							    "DDIMScheduler",
							    "DDPMScheduler",
							    "PNDMScheduler",
							    "HeunDiscreteScheduler",
							    "EulerAncestralDiscreteScheduler",
							    "KDPM2DiscreteScheduler",
							    "KDPM2AncestralDiscreteScheduler",
							    "DPMSolverSDEScheduler",
							]
							snake_case_						       =	self.get_dummy_components()
							snake_case_						       =	self.pipeline_class(**__lowercase		)

							# make sure that PNDM does not need warm-up
							pipe.scheduler.register_to_config(skip_prk_steps=__lowercase		)

							pipe.to(__lowercase		)
							pipe.set_progress_bar_config(disable=__lowercase		)
							snake_case_						       =	self.get_dummy_inputs(__lowercase		)
							snake_case_						       =	2

							snake_case_						       =	[]
							for scheduler_enum in KarrasDiffusionSchedulers:
								if scheduler_enum.name in skip_schedulers:
									# no sigma schedulers are not supported
									# no schedulers
									continue

								snake_case_						       =	getattr(__lowercase			,      scheduler_enum.name		)
								snake_case_						       =	scheduler_cls.from_config(pipe.scheduler.config		)
								snake_case_						       =	pipe(**__lowercase		)[0]
								outputs.append(__lowercase		)

							assert check_same_shape(__lowercase		)







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







						'''simple docstring'''





						def 			snake_case__		(		self				:	Optional[int]		):






							"""simple docstring"""






							super().tearDown()
							gc.collect()
							torch.cuda.empty_cache()






						def 			snake_case__		(		self				:	Optional[int]		):






							"""simple docstring"""






							snake_case_						       =	torch.manual_seed(33		)

							snake_case_						       =	StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v1-4"			,      torch_dtype=torch.floataa		)
							pipe.to("cuda"		)

							snake_case_						       =	StableDiffusionLatentUpscalePipeline.from_pretrained(
							    "stabilityai/sd-x2-latent-upscaler"			,      torch_dtype=torch.floataa		)
							upscaler.to("cuda"		)

							snake_case_						       =	"a photo of an astronaut high resolution, unreal engine, ultra realistic"

							snake_case_						       =	pipe(__lowercase			,      generator=__lowercase			,      output_type="latent"		).images

							snake_case_						       =	upscaler(
							    prompt=__lowercase			,      image=__lowercase			,      num_inference_steps=20			,      guidance_scale=0			,      generator=__lowercase			,      output_type="np"			,      ).images[0]

							snake_case_						       =	load_numpy(
							    "https://huggingface.co/datasets/hf-internal-testing/diffusers-images/resolve/main/latent-upscaler/astronaut_1024.npy"		)
							assert np.abs((expected_image - image).mean()		) < 5E-2






						def 			snake_case__		(		self				:	List[str]		):






							"""simple docstring"""






							snake_case_						       =	torch.manual_seed(33		)

							snake_case_						       =	StableDiffusionLatentUpscalePipeline.from_pretrained(
							    "stabilityai/sd-x2-latent-upscaler"			,      torch_dtype=torch.floataa		)
							upscaler.to("cuda"		)

							snake_case_						       =	"the temple of fire by Ross Tran and Gerardo Dottori, oil on canvas"

							snake_case_						       =	load_image(
							    "https://huggingface.co/datasets/hf-internal-testing/diffusers-images/resolve/main/latent-upscaler/fire_temple_512.png"		)

							snake_case_						       =	upscaler(
							    prompt=__lowercase			,      image=__lowercase			,      num_inference_steps=20			,      guidance_scale=0			,      generator=__lowercase			,      output_type="np"			,      ).images[0]

							snake_case_						       =	load_numpy(
							    "https://huggingface.co/datasets/hf-internal-testing/diffusers-images/resolve/main/latent-upscaler/fire_temple_1024.npy"		)
							assert np.abs((expected_image - image).max()		) < 5E-2






from binascii import hexlify
from hashlib import shaaaa
from os import urandom

# RFC 3526 - More Modular Exponential (MODP) Diffie-Hellman groups for
# Internet Key Exchange (IKE) https://tools.ietf.org/html/rfc3526

lowercase__							:	Dict											=		{
    # 1536-bit
    5: {
        "prime": int(
            "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
            + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
            + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
            + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
            + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
            + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
            + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
            + "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF",
            base=16,
        ),
        "generator": 2,
    },
    # 2048-bit
    14: {
        "prime": int(
            "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
            + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
            + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
            + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
            + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
            + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
            + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
            + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
            + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
            + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
            + "15728E5A8AACAA68FFFFFFFFFFFFFFFF",
            base=16,
        ),
        "generator": 2,
    },
    # 3072-bit
    15: {
        "prime": int(
            "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
            + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
            + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
            + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
            + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
            + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
            + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
            + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
            + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
            + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
            + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
            + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
            + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
            + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
            + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
            + "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF",
            base=16,
        ),
        "generator": 2,
    },
    # 4096-bit
    16: {
        "prime": int(
            "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
            + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
            + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
            + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
            + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
            + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
            + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
            + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
            + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
            + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
            + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
            + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
            + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
            + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
            + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
            + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
            + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
            + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
            + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
            + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
            + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199"
            + "FFFFFFFFFFFFFFFF",
            base=16,
        ),
        "generator": 2,
    },
    # 6144-bit
    17: {
        "prime": int(
            "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
            + "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
            + "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
            + "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
            + "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8"
            + "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D"
            + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C"
            + "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718"
            + "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D"
            + "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D"
            + "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226"
            + "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
            + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC"
            + "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26"
            + "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB"
            + "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2"
            + "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127"
            + "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
            + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406"
            + "AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918"
            + "DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B33205151"
            + "2BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03"
            + "F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97F"
            + "BEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
            + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58B"
            + "B7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632"
            + "387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E"
            + "6DCC4024FFFFFFFFFFFFFFFF",
            base=16,
        ),
        "generator": 2,
    },
    # 8192-bit
    18: {
        "prime": int(
            "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
            + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
            + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
            + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
            + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
            + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
            + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
            + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
            + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
            + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
            + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
            + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
            + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
            + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
            + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
            + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
            + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
            + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
            + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
            + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
            + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
            + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD"
            + "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831"
            + "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B"
            + "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF"
            + "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6"
            + "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3"
            + "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
            + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328"
            + "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C"
            + "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE"
            + "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4"
            + "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300"
            + "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568"
            + "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9"
            + "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B"
            + "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A"
            + "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36"
            + "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1"
            + "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92"
            + "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47"
            + "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71"
            + "60C980DD98EDD3DFFFFFFFFFFFFFFFFF",
            base=16,
        ),
        "generator": 2,
    },
}
class 						UpperCAmelCase  :







						'''simple docstring'''





						def __init__(		self				:	Tuple			,      __lowercase				:	int = 14		):






							"""simple docstring"""






							if group not in primes:
								raise ValueError("Unsupported Group"		)
							snake_case_						       =	primes[group]["prime"]
							snake_case_						       =	primes[group]["generator"]

							snake_case_						       =	int(hexlify(urandom(32		)		)			,      base=16		)






						def 			snake_case__		(		self				:	Tuple		):






							"""simple docstring"""






							return hex(self.__private_key		)[2:]






						def 			snake_case__		(		self				:	Optional[int]		):






							"""simple docstring"""






							snake_case_						       =	pow(self.generator			,      self.__private_key			,      self.prime		)
							return hex(__lowercase		)[2:]






						def 			snake_case__		(		self				:	int			,      __lowercase				:	int		):






							"""simple docstring"""






							return (
							    2 <= key <= self.prime - 2
							    and pow(__lowercase			,      (self.prime - 1) // 2			,      self.prime		) == 1
							)






						def 			snake_case__		(		self				:	Union[str, Any]			,      __lowercase				:	str		):






							"""simple docstring"""






							snake_case_						       =	int(__lowercase			,      base=16		)
							if not self.is_valid_public_key(__lowercase		):
								raise ValueError("Invalid public key"		)
							snake_case_						       =	pow(__lowercase			,      self.__private_key			,      self.prime		)
							return shaaaa(str(__lowercase		).encode()		).hexdigest()






						@staticmethod
						def 			snake_case__		(		__lowercase				:	int			,      __lowercase				:	int		):






							"""simple docstring"""






							return (
							    2 <= remote_public_key_str <= prime - 2
							    and pow(__lowercase			,      (prime - 1) // 2			,      __lowercase		) == 1
							)






						@staticmethod
						def 			snake_case__		(		__lowercase				:	str			,      __lowercase				:	str			,      __lowercase				:	int = 14		):






							"""simple docstring"""






							snake_case_						       =	int(__lowercase			,      base=16		)
							snake_case_						       =	int(__lowercase			,      base=16		)
							snake_case_						       =	primes[group]["prime"]
							if not DiffieHellman.is_valid_public_key_static(__lowercase			,      __lowercase		):
								raise ValueError("Invalid public key"		)
							snake_case_						       =	pow(__lowercase			,      __lowercase			,      __lowercase		)
							return shaaaa(str(__lowercase		).encode()		).hexdigest()


if __name__ == "__main__":
		import doctest

		doctest.testmod()
