
import inspect
import unittest

from transformers import SegformerConfig, is_torch_available, is_vision_available
from transformers.models.auto import get_values
from transformers.testing_utils import require_torch, slow, torch_device

from ...test_configuration_common import ConfigTester
from ...test_modeling_common import ModelTesterMixin, floats_tensor, ids_tensor
from ...test_pipeline_mixin import PipelineTesterMixin


if is_torch_available():
		import torch

		from transformers import (
		    MODEL_MAPPING,
		    SegformerForImageClassification,
		    SegformerForSemanticSegmentation,
		    SegformerModel,
		)
		from transformers.models.segformer.modeling_segformer import SEGFORMER_PRETRAINED_MODEL_ARCHIVE_LIST


if is_vision_available():
		from PIL import Image

		from transformers import SegformerImageProcessor




class 					lowerCamelCase__				(							__lowercase):




	'''simple docstring'''




	def   _lowerCamelCase							(   self						:List[str]		)						->					int:
								__UpperCamelCase      :  List[Any]       =   self.config_class(**self.inputs_dict		)
								self.parent.assertTrue(hasattr(a	,  "hidden_sizes"		)		)
								self.parent.assertTrue(hasattr(a	,  "num_attention_heads"		)		)
								self.parent.assertTrue(hasattr(a	,  "num_encoder_blocks"		)		)




class 					lowerCamelCase__				:




	'''simple docstring'''




	def __init__(   self						:List[Any]	,  a						:Dict	,  a						:List[str]=1_3	,  a						:Tuple=6_4	,  a						:List[str]=3	,  a						:Any=4	,  a						:Union[str, Any]=[2, 2, 2, 2]	,  a						:Dict=[8, 4, 2, 1]	,  a						:str=[1_6, 3_2, 6_4, 1_2_8]	,  a						:List[str]=[1, 4, 8, 1_6]	,  a						:Tuple=[1, 2, 4, 8]	,  a						:Union[str, Any]=True	,  a						:Union[str, Any]=True	,  a						:int="gelu"	,  a						:Tuple=0.1	,  a						:Optional[Any]=0.1	,  a						:Any=0.02	,  a						:Union[str, Any]=3	,  a						:List[str]=None	,  )						->					Union[str, Any]:
								__UpperCamelCase      :  Tuple       =   parent
								__UpperCamelCase      :  Union[str, Any]       =   batch_size
								__UpperCamelCase      :  List[Any]       =   image_size
								__UpperCamelCase      :  List[Any]       =   num_channels
								__UpperCamelCase      :  int       =   num_encoder_blocks
								__UpperCamelCase      :  List[Any]       =   sr_ratios
								__UpperCamelCase      :  int       =   depths
								__UpperCamelCase      :  Any       =   hidden_sizes
								__UpperCamelCase      :  Optional[Any]       =   downsampling_rates
								__UpperCamelCase      :  Optional[int]       =   num_attention_heads
								__UpperCamelCase      :  Union[str, Any]       =   is_training
								__UpperCamelCase      :  Optional[Any]       =   use_labels
								__UpperCamelCase      :  Dict       =   hidden_act
								__UpperCamelCase      :  Optional[int]       =   hidden_dropout_prob
								__UpperCamelCase      :  Optional[int]       =   attention_probs_dropout_prob
								__UpperCamelCase      :  Any       =   initializer_range
								__UpperCamelCase      :  Union[str, Any]       =   num_labels
								__UpperCamelCase      :  List[str]       =   scope







	def   _lowerCamelCase							(   self						:Any		)						->					Union[str, Any]:
								__UpperCamelCase      :  Tuple       =   floats_tensor([self.batch_size, self.num_channels, self.image_size, self.image_size]		)

								__UpperCamelCase      :  List[str]       =   None
								if self.use_labels:
															__UpperCamelCase      :  str       =   ids_tensor([self.batch_size, self.image_size, self.image_size]	,  self.num_labels		)

								__UpperCamelCase      :  str       =   self.get_config()
								return config, pixel_values, labels







	def   _lowerCamelCase							(   self						:List[Any]		)						->					List[Any]:
								return SegformerConfig(
								    image_size=self.image_size	,  num_channels=self.num_channels	,  num_encoder_blocks=self.num_encoder_blocks	,  depths=self.depths	,  hidden_sizes=self.hidden_sizes	,  num_attention_heads=self.num_attention_heads	,  hidden_act=self.hidden_act	,  hidden_dropout_prob=self.hidden_dropout_prob	,  attention_probs_dropout_prob=self.attention_probs_dropout_prob	,  initializer_range=self.initializer_range	,  )







	def   _lowerCamelCase							(   self						:Optional[int]	,  a						:str	,  a						:Optional[int]	,  a						:List[Any]		)						->					Tuple:
								__UpperCamelCase      :  str       =   SegformerModel(config=a		)
								model.to(a		)
								model.eval()
								__UpperCamelCase      :  int       =   model(a		)
								__UpperCamelCase      :  str       =   self.image_size // (self.downsampling_rates[-1] * 2)
								self.parent.assertEqual(
								    result.last_hidden_state.shape	,  (self.batch_size, self.hidden_sizes[-1], expected_height, expected_width)		)







	def   _lowerCamelCase							(   self						:str	,  a						:Any	,  a						:Dict	,  a						:Optional[Any]		)						->					str:
								__UpperCamelCase      :  List[str]       =   self.num_labels
								__UpperCamelCase      :  List[str]       =   SegformerForSemanticSegmentation(a		)
								model.to(a		)
								model.eval()
								__UpperCamelCase      :  Any       =   model(a		)
								self.parent.assertEqual(
								    result.logits.shape	,  (self.batch_size, self.num_labels, self.image_size // 4, self.image_size // 4)		)
								__UpperCamelCase      :  Any       =   model(a	,  labels=a		)
								self.parent.assertEqual(
								    result.logits.shape	,  (self.batch_size, self.num_labels, self.image_size // 4, self.image_size // 4)		)
								self.parent.assertGreater(result.loss	,  0.0		)







	def   _lowerCamelCase							(   self						:Any	,  a						:int	,  a						:List[str]	,  a						:Dict		)						->					int:
								__UpperCamelCase      :  int       =   1
								__UpperCamelCase      :  Dict       =   SegformerForSemanticSegmentation(config=a		)
								model.to(a		)
								model.eval()
								__UpperCamelCase      :  int       =   torch.randint(0	,  1	,  (self.batch_size, self.image_size, self.image_size)		).to(a		)
								__UpperCamelCase      :  Union[str, Any]       =   model(a	,  labels=a		)
								self.parent.assertGreater(result.loss	,  0.0		)







	def   _lowerCamelCase							(   self						:str		)						->					Any:
								__UpperCamelCase      :  Optional[int]       =   self.prepare_config_and_inputs()
								__UpperCamelCase  ,		__UpperCamelCase  ,		__UpperCamelCase      :  Union[str, Any]       =   config_and_inputs
								__UpperCamelCase      :  str       =   {"pixel_values": pixel_values}
								return config, inputs_dict




@require_torch
class 					lowerCamelCase__				(							__lowercase	,		__lowercase	,		unittest.TestCase):




	'''simple docstring'''




	_A								=	(
	    (
	        SegformerModel,
	        SegformerForSemanticSegmentation,
	        SegformerForImageClassification,
	    )
	    if is_torch_available()
	    else ()
	)
	_A								=	(
	    {
	        'feature-extraction': SegformerModel,
	        'image-classification': SegformerForImageClassification,
	        'image-segmentation': SegformerForSemanticSegmentation,
	    }
	    if is_torch_available()
	    else {}
	)

	_A								=	True
	_A								=	False
	_A								=	False
	_A								=	False







	def   _lowerCamelCase							(   self						:List[str]		)						->					Optional[Any]:
								__UpperCamelCase      :  Any       =   SegformerModelTester(self		)
								__UpperCamelCase      :  Tuple       =   SegformerConfigTester(self	,  config_class=a		)







	def   _lowerCamelCase							(   self						:List[Any]		)						->					List[str]:
								self.config_tester.run_common_tests()







	def   _lowerCamelCase							(   self						:Dict		)						->					List[Any]:
								__UpperCamelCase      :  str       =   self.model_tester.prepare_config_and_inputs()
								self.model_tester.create_and_check_model(*a		)







	def   _lowerCamelCase							(   self						:Optional[Any]		)						->					Union[str, Any]:
								__UpperCamelCase      :  List[Any]       =   self.model_tester.prepare_config_and_inputs()
								self.model_tester.create_and_check_for_binary_image_segmentation(*a		)







	def   _lowerCamelCase							(   self						:Dict		)						->					Dict:
								__UpperCamelCase      :  int       =   self.model_tester.prepare_config_and_inputs()
								self.model_tester.create_and_check_for_image_segmentation(*a		)







	@unittest.skip("SegFormer does not use inputs_embeds"		)
	def   _lowerCamelCase							(   self						:int		)						->					List[Any]:
								pass







	@unittest.skip("SegFormer does not have get_input_embeddings method and get_output_embeddings methods"		)
	def   _lowerCamelCase							(   self						:Any		)						->					str:
								pass







	def   _lowerCamelCase							(   self						:Tuple		)						->					List[str]:
								__UpperCamelCase  ,		__UpperCamelCase      :  int       =   self.model_tester.prepare_config_and_inputs_for_common()

								for model_class in self.all_model_classes:
															__UpperCamelCase      :  str       =   model_class(a		)
															__UpperCamelCase      :  Optional[int]       =   inspect.signature(model.forward		)
															# signature.parameters is an OrderedDict => so arg_names order is deterministic
															__UpperCamelCase      :  Optional[int]       =   [*signature.parameters.keys()]

															__UpperCamelCase      :  Union[str, Any]       =   ["pixel_values"]
															self.assertListEqual(arg_names[:1]	,  a		)







	def   _lowerCamelCase							(   self						:Tuple		)						->					Union[str, Any]:
								__UpperCamelCase  ,		__UpperCamelCase      :  Optional[Any]       =   self.model_tester.prepare_config_and_inputs_for_common()
								__UpperCamelCase      :  Dict       =   True

								for model_class in self.all_model_classes:
															__UpperCamelCase      :  Optional[int]       =   True
															__UpperCamelCase      :  str       =   False
															__UpperCamelCase      :  int       =   True
															__UpperCamelCase      :  Union[str, Any]       =   model_class(a		)
															model.to(a		)
															model.eval()
															with torch.no_grad():
																						__UpperCamelCase      :  Dict       =   model(**self._prepare_for_class(a	,  a		)		)
															__UpperCamelCase      :  Any       =   outputs.attentions

															__UpperCamelCase      :  int       =   sum(self.model_tester.depths		)
															self.assertEqual(len(a		)	,  a		)

															# check that output_attentions also work using config
															del inputs_dict["output_attentions"]
															__UpperCamelCase      :  Optional[Any]       =   True
															__UpperCamelCase      :  Optional[Any]       =   model_class(a		)
															model.to(a		)
															model.eval()
															with torch.no_grad():
																						__UpperCamelCase      :  List[Any]       =   model(**self._prepare_for_class(a	,  a		)		)
															__UpperCamelCase      :  int       =   outputs.attentions

															self.assertEqual(len(a		)	,  a		)

															# verify the first attentions (first block, first layer)
															__UpperCamelCase      :  List[str]       =   (self.model_tester.image_size // 4) ** 2
															__UpperCamelCase      :  str       =   (self.model_tester.image_size // (4 * self.model_tester.sr_ratios[0])) ** 2
															self.assertListEqual(
															    list(attentions[0].shape[-3:]		)	,  [self.model_tester.num_attention_heads[0], expected_seq_len, expected_reduced_seq_len]	,  )

															# verify the last attentions (last block, last layer)
															__UpperCamelCase      :  List[Any]       =   (self.model_tester.image_size // 3_2) ** 2
															__UpperCamelCase      :  Tuple       =   (self.model_tester.image_size // (3_2 * self.model_tester.sr_ratios[-1])) ** 2
															self.assertListEqual(
															    list(attentions[-1].shape[-3:]		)	,  [self.model_tester.num_attention_heads[-1], expected_seq_len, expected_reduced_seq_len]	,  )
															__UpperCamelCase      :  int       =   len(a		)

															# Check attention is always last and order is fine
															__UpperCamelCase      :  str       =   True
															__UpperCamelCase      :  List[Any]       =   True
															__UpperCamelCase      :  Dict       =   model_class(a		)
															model.to(a		)
															model.eval()
															with torch.no_grad():
																						__UpperCamelCase      :  Dict       =   model(**self._prepare_for_class(a	,  a		)		)

															self.assertEqual(out_len + 1	,  len(a		)		)

															__UpperCamelCase      :  Dict       =   outputs.attentions

															self.assertEqual(len(a		)	,  a		)
															# verify the first attentions (first block, first layer)
															__UpperCamelCase      :  Optional[Any]       =   (self.model_tester.image_size // 4) ** 2
															__UpperCamelCase      :  Any       =   (self.model_tester.image_size // (4 * self.model_tester.sr_ratios[0])) ** 2
															self.assertListEqual(
															    list(self_attentions[0].shape[-3:]		)	,  [self.model_tester.num_attention_heads[0], expected_seq_len, expected_reduced_seq_len]	,  )







	def   _lowerCamelCase							(   self						:List[Any]		)						->					Union[str, Any]:
								def check_hidden_states_output(a						:Optional[Any]	,  a						:List[Any]	,  a						:List[Any]		):
															__UpperCamelCase      :  Union[str, Any]       =   model_class(a		)
															model.to(a		)
															model.eval()

															with torch.no_grad():
																						__UpperCamelCase      :  Dict       =   model(**self._prepare_for_class(a	,  a		)		)

															__UpperCamelCase      :  Tuple       =   outputs.hidden_states

															__UpperCamelCase      :  Tuple       =   self.model_tester.num_encoder_blocks
															self.assertEqual(len(a		)	,  a		)

															# verify the first hidden states (first block)
															self.assertListEqual(
															    list(hidden_states[0].shape[-3:]		)	,  [
															        self.model_tester.hidden_sizes[0],
															        self.model_tester.image_size // 4,
															        self.model_tester.image_size // 4,
															    ]	,  )

								__UpperCamelCase  ,		__UpperCamelCase      :  str       =   self.model_tester.prepare_config_and_inputs_for_common()

								for model_class in self.all_model_classes:
															__UpperCamelCase      :  Optional[int]       =   True
															check_hidden_states_output(a	,  a	,  a		)

															# check that output_hidden_states also work using config
															del inputs_dict["output_hidden_states"]
															__UpperCamelCase      :  List[Any]       =   True

															check_hidden_states_output(a	,  a	,  a		)







	def   _lowerCamelCase							(   self						:List[Any]		)						->					Any:
								if not self.model_tester.is_training:
															return

								__UpperCamelCase  ,		__UpperCamelCase      :  Union[str, Any]       =   self.model_tester.prepare_config_and_inputs_for_common()
								__UpperCamelCase      :  Any       =   True

								for model_class in self.all_model_classes:
															if model_class in get_values(a		):
																						continue

															__UpperCamelCase      :  int       =   model_class(a		)
															model.to(a		)
															model.train()
															__UpperCamelCase      :  List[str]       =   self._prepare_for_class(a	,  a	,  return_labels=a		)
															__UpperCamelCase      :  Dict       =   model(**a		).loss
															loss.backward()







	@unittest.skip("Will be fixed soon by reducing the size of the model used for common tests."		)
	def   _lowerCamelCase							(   self						:Optional[int]		)						->					Tuple:
								pass







	@slow
	def   _lowerCamelCase							(   self						:Union[str, Any]		)						->					Tuple:
								for model_name in SEGFORMER_PRETRAINED_MODEL_ARCHIVE_LIST[:1]:
															__UpperCamelCase      :  Optional[int]       =   SegformerModel.from_pretrained(a		)
															self.assertIsNotNone(a		)




def       _SCREAMING_SNAKE_CASE   (						)   ->       Dict:






							'''simple docstring'''





							__UpperCamelCase      :  Union[str, Any]       =   Image.open("./tests/fixtures/tests_samples/COCO/000000039769.png")
							return image




@require_torch
class 					lowerCamelCase__				(							unittest.TestCase):




	'''simple docstring'''




	@slow
	def   _lowerCamelCase							(   self						:Tuple		)						->					List[str]:
								# only resize + normalize
								__UpperCamelCase      :  Optional[int]       =   SegformerImageProcessor(
								    image_scale=(5_1_2, 5_1_2)	,  keep_ratio=a	,  align=a	,  do_random_crop=a		)
								__UpperCamelCase      :  Dict       =   SegformerForSemanticSegmentation.from_pretrained("nvidia/segformer-b0-finetuned-ade-512-512"		).to(
								    a		)

								__UpperCamelCase      :  str       =   prepare_img()
								__UpperCamelCase      :  List[Any]       =   image_processor(images=a	,  return_tensors="pt"		)
								__UpperCamelCase      :  Union[str, Any]       =   encoded_inputs.pixel_values.to(a		)

								with torch.no_grad():
															__UpperCamelCase      :  Optional[int]       =   model(a		)

								__UpperCamelCase      :  Optional[Any]       =   torch.Size((1, model.config.num_labels, 1_2_8, 1_2_8)		)
								self.assertEqual(outputs.logits.shape	,  a		)

								__UpperCamelCase      :  Tuple       =   torch.tensor(
								    [
								        [[-4.6310, -5.5232, -6.2356], [-5.1921, -6.1444, -6.5996], [-5.4424, -6.2790, -6.7574]],
								        [[-12.1391, -13.3122, -13.9554], [-12.8732, -13.9352, -14.3563], [-12.9438, -13.8226, -14.2513]],
								        [[-12.5134, -13.4686, -14.4915], [-12.8669, -14.4343, -14.7758], [-13.2523, -14.5819, -15.0694]],
								    ]		).to(a		)
								self.assertTrue(torch.allclose(outputs.logits[0, :3, :3, :3]	,  a	,  atol=1E-4		)		)







	@slow
	def   _lowerCamelCase							(   self						:List[Any]		)						->					Tuple:
								# only resize + normalize
								__UpperCamelCase      :  str       =   SegformerImageProcessor(
								    image_scale=(5_1_2, 5_1_2)	,  keep_ratio=a	,  align=a	,  do_random_crop=a		)
								__UpperCamelCase      :  List[Any]       =   SegformerForSemanticSegmentation.from_pretrained(
								    "nvidia/segformer-b1-finetuned-cityscapes-1024-1024"		).to(a		)

								__UpperCamelCase      :  str       =   prepare_img()
								__UpperCamelCase      :  Any       =   image_processor(images=a	,  return_tensors="pt"		)
								__UpperCamelCase      :  List[Any]       =   encoded_inputs.pixel_values.to(a		)

								with torch.no_grad():
															__UpperCamelCase      :  List[str]       =   model(a		)

								__UpperCamelCase      :  Optional[int]       =   torch.Size((1, model.config.num_labels, 1_2_8, 1_2_8)		)
								self.assertEqual(outputs.logits.shape	,  a		)

								__UpperCamelCase      :  Dict       =   torch.tensor(
								    [
								        [[-13.5748, -13.9111, -12.6500], [-14.3500, -15.3683, -14.2328], [-14.7532, -16.0424, -15.6087]],
								        [[-17.1651, -15.8725, -12.9653], [-17.2580, -17.3718, -14.8223], [-16.6058, -16.8783, -16.7452]],
								        [[-3.6456, -3.0209, -1.4203], [-3.0797, -3.1959, -2.0000], [-1.8757, -1.9217, -1.6997]],
								    ]		).to(a		)
								self.assertTrue(torch.allclose(outputs.logits[0, :3, :3, :3]	,  a	,  atol=1E-1		)		)







	@slow
	def   _lowerCamelCase							(   self						:Dict		)						->					Tuple:
								# only resize + normalize
								__UpperCamelCase      :  Dict       =   SegformerImageProcessor(
								    image_scale=(5_1_2, 5_1_2)	,  keep_ratio=a	,  align=a	,  do_random_crop=a		)
								__UpperCamelCase      :  int       =   SegformerForSemanticSegmentation.from_pretrained("nvidia/segformer-b0-finetuned-ade-512-512"		).to(
								    a		)

								__UpperCamelCase      :  Optional[Any]       =   prepare_img()
								__UpperCamelCase      :  List[str]       =   image_processor(images=a	,  return_tensors="pt"		)
								__UpperCamelCase      :  Union[str, Any]       =   encoded_inputs.pixel_values.to(a		)

								with torch.no_grad():
															__UpperCamelCase      :  List[str]       =   model(a		)

								__UpperCamelCase      :  List[Any]       =   outputs.logits.detach().cpu()

								__UpperCamelCase      :  Tuple       =   image_processor.post_process_semantic_segmentation(outputs=a	,  target_sizes=[(5_0_0, 3_0_0)]		)
								__UpperCamelCase      :  Dict       =   torch.Size((5_0_0, 3_0_0)		)
								self.assertEqual(segmentation[0].shape	,  a		)

								__UpperCamelCase      :  str       =   image_processor.post_process_semantic_segmentation(outputs=a		)
								__UpperCamelCase      :  Union[str, Any]       =   torch.Size((1_2_8, 1_2_8)		)
								self.assertEqual(segmentation[0].shape	,  a		)

from __future__ import annotations

lowercase    :   Dict						=			tuple[int, int, int]
lowercase    :   List[str]						=			tuple[str, str, str]


# used alphabet --------------------------
# from string.ascii_uppercase
lowercase    :   int						=			'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

# -------------------------- default selection --------------------------
# rotors --------------------------
lowercase    :   Optional[int]						=			'EGZWVONAHDCLFQMSIPJBYUKXTR'
lowercase    :   Optional[Any]						=			'FOBHMDKEXQNRAULPGSJVTYICZW'
lowercase    :   str						=			'ZJXESIUQLHAVRMDOYGTNFWPBKC'
# reflector --------------------------
lowercase    :   Tuple						=			{
    'A': 'N',
    'N': 'A',
    'B': 'O',
    'O': 'B',
    'C': 'P',
    'P': 'C',
    'D': 'Q',
    'Q': 'D',
    'E': 'R',
    'R': 'E',
    'F': 'S',
    'S': 'F',
    'G': 'T',
    'T': 'G',
    'H': 'U',
    'U': 'H',
    'I': 'V',
    'V': 'I',
    'J': 'W',
    'W': 'J',
    'K': 'X',
    'X': 'K',
    'L': 'Y',
    'Y': 'L',
    'M': 'Z',
    'Z': 'M',
}

# -------------------------- extra rotors --------------------------
lowercase    :   Optional[int]						=			'RMDJXFUWGISLHVTCQNKYPBEZOA'
lowercase    :   List[Any]						=			'SGLCPQWZHKXAREONTFBVIYJUDM'
lowercase    :   Dict						=			'HVSICLTYKQUBXDWAJZOMFGPREN'
lowercase    :   List[Any]						=			'RZWQHFMVDBKICJLNTUXAGYPSOE'
lowercase    :   Optional[Any]						=			'LFKIJODBEGAMQPXVUHYSTCZRWN'
lowercase    :   Tuple						=			'KOAEGVDHXPQZMLFTYWJNBRCIUS'




def       _SCREAMING_SNAKE_CASE   (						_lowerCamelCase					:     RotorPositionT		,    _lowerCamelCase					:     RotorSelectionT		,    _lowerCamelCase					:     str)   ->       tuple[RotorPositionT, RotorSelectionT, dict[str, str]]:






							'''simple docstring'''





							if (unique_rotsel := len(set(_lowerCamelCase))) < 3:
														__UpperCamelCase      :  Tuple       =   F'Please use 3 unique rotors (not {unique_rotsel})'
														raise Exception(_lowerCamelCase)

							# Checks if rotor positions are valid
							__UpperCamelCase  ,		__UpperCamelCase  ,		__UpperCamelCase      :  str       =   rotpos
							if not 0 < rotorposa <= len(_lowerCamelCase):
														__UpperCamelCase      :  Union[str, Any]       =   F'First rotor position is not within range of 1..26 ({rotorposa}'
														raise ValueError(_lowerCamelCase)
							if not 0 < rotorposa <= len(_lowerCamelCase):
														__UpperCamelCase      :  int       =   F'Second rotor position is not within range of 1..26 ({rotorposa})'
														raise ValueError(_lowerCamelCase)
							if not 0 < rotorposa <= len(_lowerCamelCase):
														__UpperCamelCase      :  List[Any]       =   F'Third rotor position is not within range of 1..26 ({rotorposa})'
														raise ValueError(_lowerCamelCase)

							# Validates string and returns dict
							__UpperCamelCase      :  str       =   _plugboard(_lowerCamelCase)

							return rotpos, rotsel, pbdict




def       _SCREAMING_SNAKE_CASE   (						_lowerCamelCase					:     str)   ->       dict[str, str]:






							'''simple docstring'''





							if not isinstance(_lowerCamelCase		,    _lowerCamelCase):
														__UpperCamelCase      :  Union[str, Any]       =   F'Plugboard setting isn\'t type string ({type(_lowerCamelCase)})'
														raise TypeError(_lowerCamelCase)
							elif len(_lowerCamelCase) % 2 != 0:
														__UpperCamelCase      :  int       =   F'Odd number of symbols ({len(_lowerCamelCase)})'
														raise Exception(_lowerCamelCase)
							elif pbstring == "":
														return {}

							pbstring.replace(" "		,    "")

							# Checks if all characters are unique
							__UpperCamelCase      :  Optional[int]       =   set()
							for i in pbstring:
														if i not in abc:
																					__UpperCamelCase      :  Tuple       =   F'\'{i}\' not in list of symbols'
																					raise Exception(_lowerCamelCase)
														elif i in tmppbl:
																					__UpperCamelCase      :  Tuple       =   F'Duplicate symbol ({i})'
																					raise Exception(_lowerCamelCase)
														else:
																					tmppbl.add(_lowerCamelCase)
							del tmppbl

							# Created the dictionary
							__UpperCamelCase      :  Union[str, Any]       =   {}
							for j in range(0		,    len(_lowerCamelCase) - 1		,    2):
														__UpperCamelCase      :  Union[str, Any]       =   pbstring[j + 1]
														__UpperCamelCase      :  str       =   pbstring[j]

							return pb




def       _SCREAMING_SNAKE_CASE   (						_lowerCamelCase					:     str		,    _lowerCamelCase					:     RotorPositionT		,    _lowerCamelCase					:     RotorSelectionT = (rotora, rotora, rotora)		,    _lowerCamelCase					:     str = ""		,    )   ->       str:






							'''simple docstring'''





							__UpperCamelCase      :  List[Any]       =   text.upper()
							__UpperCamelCase  ,		__UpperCamelCase  ,		__UpperCamelCase      :  Optional[int]       =   _validator(
							    _lowerCamelCase		,    _lowerCamelCase		,    plugb.upper())

							__UpperCamelCase  ,		__UpperCamelCase  ,		__UpperCamelCase      :  Tuple       =   rotor_position
							__UpperCamelCase  ,		__UpperCamelCase  ,		__UpperCamelCase      :  List[Any]       =   rotor_selection
							rotorposa -= 1
							rotorposa -= 1
							rotorposa -= 1

							__UpperCamelCase      :  List[str]       =   []

							# encryption/decryption process --------------------------
							for symbol in text:
														if symbol in abc:
																					# 1st plugboard --------------------------
																					if symbol in plugboard:
																												__UpperCamelCase      :  Dict       =   plugboard[symbol]

																					# rotor ra --------------------------
																					__UpperCamelCase      :  Optional[int]       =   abc.index(_lowerCamelCase) + rotorposa
																					__UpperCamelCase      :  List[Any]       =   rotora[index % len(_lowerCamelCase)]

																					# rotor rb --------------------------
																					__UpperCamelCase      :  Dict       =   abc.index(_lowerCamelCase) + rotorposa
																					__UpperCamelCase      :  Any       =   rotora[index % len(_lowerCamelCase)]

																					# rotor rc --------------------------
																					__UpperCamelCase      :  str       =   abc.index(_lowerCamelCase) + rotorposa
																					__UpperCamelCase      :  Union[str, Any]       =   rotora[index % len(_lowerCamelCase)]

																					# reflector --------------------------
																					# this is the reason you don't need another machine to decipher

																					__UpperCamelCase      :  Union[str, Any]       =   reflector[symbol]

																					# 2nd rotors
																					__UpperCamelCase      :  Optional[int]       =   abc[rotora.index(_lowerCamelCase) - rotorposa]
																					__UpperCamelCase      :  Optional[Any]       =   abc[rotora.index(_lowerCamelCase) - rotorposa]
																					__UpperCamelCase      :  str       =   abc[rotora.index(_lowerCamelCase) - rotorposa]

																					# 2nd plugboard
																					if symbol in plugboard:
																												__UpperCamelCase      :  Optional[Any]       =   plugboard[symbol]

																					# moves/resets rotor positions
																					rotorposa += 1
																					if rotorposa >= len(_lowerCamelCase):
																												__UpperCamelCase      :  Any       =   0
																												rotorposa += 1
																					if rotorposa >= len(_lowerCamelCase):
																												__UpperCamelCase      :  Tuple       =   0
																												rotorposa += 1
																					if rotorposa >= len(_lowerCamelCase):
																												__UpperCamelCase      :  List[str]       =   0

        # else:
        #    pass
        #    Error could be also raised
        #    raise ValueError(
        #       'Invalid symbol('+repr(symbol)+')')
														result.append(_lowerCamelCase)

							return "".join(_lowerCamelCase)


if __name__ == "__main__":
		lowercase    :   Optional[Any]						=			'This is my Python script that emulates the Enigma machine from WWII.'
		lowercase    :   int						=			(1, 1, 1)
		lowercase    :   Optional[Any]						=			'pictures'
		lowercase    :   Optional[Any]						=			(rotora, rotora, rotora)
		lowercase    :   Optional[Any]						=			enigma(message, rotor_pos, rotor_sel, pb)

		print('Encrypted message:', en)
		print('Decrypted message:', enigma(en, rotor_pos, rotor_sel, pb))