





'''simple docstring'''







import collections

from .utils import ExplicitEnum, is_torch_available, logging


if is_torch_available():
    import torch


A						    =							logging.get_logger(__name__)



class 							__SCREAMING_SNAKE_CASE			:
      '''simple docstring'''



      def __init__(							self    : Optional[Any]   ,UpperCamelCase    : Union[str, Any]   ,UpperCamelCase    : List[str]=21   ,UpperCamelCase    : Optional[int]=[]   ,UpperCamelCase    : Any=None  )		->  Optional[Any]:
           _lowercase							:      str  						=							model
           _lowercase							:      Dict  						=							trace_batch_nums
           _lowercase							:      List[Any]  						=							abort_after_batch_num

           # keep a LIFO buffer of frames to dump as soon as inf/nan is encountered to give context to the problem emergence
           _lowercase							:      Union[str, Any]  						=							collections.deque([]   ,UpperCamelCase  )
           _lowercase							:      Optional[int]  						=							[]
           _lowercase							:      Dict  						=							0
           _lowercase							:      int  						=							0
           _lowercase							:      Any  						=							False
           _lowercase							:      Optional[int]  						=							'                 '

           self.analyse_model()

           self.register_forward_hook()

      def   _lowerCamelCase		(							self    : Dict   ,UpperCamelCase    : Optional[int]=None  )		->  Union[str, Any]:
           if frame is not None:
                self.expand_frame(UpperCamelCase  )
           self.frames.append('\n'.join(self.frame  )  )
           _lowercase							:      str  						=							[]  # start a new frame

      def   _lowerCamelCase		(							self    : Any   ,UpperCamelCase    : Any  )		->  str:
           self.frame.append(UpperCamelCase  )

      def   _lowerCamelCase		(							self    : Optional[int]  )		->  Optional[int]:
           print('\n'.join(self.frames  )  )
           _lowercase							:      Dict  						=							[]

      def   _lowerCamelCase		(							self    : Dict  )		->  List[str]:
           _lowercase							:      str  						=							[]

      def   _lowerCamelCase		(							self    : List[Any]  )		->  List[Any]:
           print(F'''\nDetected inf/nan during batch_number={self.batch_number}'''  )
           print(F'''Last {len(self.frames  )} forward frames:'''  )
           print(F'''{'abs min':8} {'abs max':8} metadata'''  )
           print('\n'.join(self.frames  )  )
           print('\n\n'  )
           _lowercase							:      int  						=							[]

      def   _lowerCamelCase		(							self    : List[str]  )		->  Tuple:
           # extract the fully qualified module names, to be able to report at run time. e.g.:
           # encoder.block.2.layer.0.SelfAttention.o
           #
           # for shared weights only the first shared module name will be registered
           _lowercase							:      Tuple  						=							{m: name for name, m in self.model.named_modules()}
           # self.longest_module_name = max(len(v) for v in self.module_names.values())

      def   _lowerCamelCase		(							self    : str   ,UpperCamelCase    : Any   ,UpperCamelCase    : Optional[int]  )		->  List[Any]:
           if torch.is_tensor(UpperCamelCase  ):
                self.expand_frame(get_abs_min_max(UpperCamelCase   ,UpperCamelCase  )  )
                if detect_overflow(UpperCamelCase   ,UpperCamelCase  ):
                     _lowercase							:      Tuple  						=							True
           elif var is None:
                self.expand_frame(F'''{'None':>17} {ctx}'''  )
           else:
                self.expand_frame(F'''{'not a tensor':>17} {ctx}'''  )

      def   _lowerCamelCase		(							self    : Tuple  )		->  Optional[int]:
           self.expand_frame(F'''\n\n{self.prefix} *** Starting batch number={self.batch_number} ***'''  )
           self.expand_frame(F'''{'abs min':8} {'abs max':8} metadata'''  )

      def   _lowerCamelCase		(							self    : Tuple  )		->  int:
           self.expand_frame(F'''{self.prefix} *** Finished batch number={self.batch_number-1} ***\n\n'''  )

      def   _lowerCamelCase		(							self    : Tuple   ,UpperCamelCase    : Tuple   ,UpperCamelCase    : Any   ,UpperCamelCase    : Dict  )		->  Union[str, Any]:
           self.expand_frame(F'''{self.prefix} {self.module_names[module]} {module.__class__.__name__}'''  )

           # params
           for name, p in module.named_parameters(recurse=UpperCamelCase  ):
                self.analyse_variable(UpperCamelCase   ,UpperCamelCase  )

           # inputs
           if isinstance(UpperCamelCase   ,UpperCamelCase  ):
                for i, x in enumerate(UpperCamelCase  ):
                     self.analyse_variable(UpperCamelCase   ,F'''input[{i}]'''  )
           else:
                self.analyse_variable(UpperCamelCase   ,'input'  )

           # outputs
           if isinstance(UpperCamelCase   ,UpperCamelCase  ):
                for i, x in enumerate(UpperCamelCase  ):
                     # possibly a tuple of tuples
                     if isinstance(UpperCamelCase   ,UpperCamelCase  ):
                          for j, y in enumerate(UpperCamelCase  ):
                               self.analyse_variable(UpperCamelCase   ,F'''output[{i}][{j}]'''  )
                     else:
                          self.analyse_variable(UpperCamelCase   ,F'''output[{i}]'''  )
           else:
                self.analyse_variable(UpperCamelCase   ,'output'  )

           self.save_frame()

      def   _lowerCamelCase		(							self    : Dict  )		->  List[Any]:
           self.model.apply(self._register_forward_hook  )

      def   _lowerCamelCase		(							self    : Union[str, Any]   ,UpperCamelCase    : List[str]  )		->  str:
           module.register_forward_hook(self.forward_hook  )



      def   _lowerCamelCase		(							self    : Any   ,UpperCamelCase    : int   ,UpperCamelCase    : Dict   ,UpperCamelCase    : Any  )		->  Tuple:
           # - input is a tuple of packed inputs (could be non-Tensors)
           # - output could be a Tensor or a tuple of Tensors and non-Tensors

           _lowercase							:      int  						=							False

           _lowercase							:      Tuple  						=							True if self.batch_number in self.trace_batch_nums else False
           if trace_mode:
                self.reset_saved_frames()

           if self.total_calls == 0:
                self.batch_start_frame()
           self.total_calls += 1

           # count batch numbers - the very first forward hook of the batch will be called when the
           # batch completes - i.e. it gets called very last - we know this batch has finished
           if module == self.model:
                self.batch_number += 1
                _lowercase							:      Any  						=							True

           self.create_frame(UpperCamelCase   ,UpperCamelCase   ,UpperCamelCase  )

           # if last_frame_of_batch:
           #     self.batch_end_frame()

           if trace_mode:
                self.trace_frames()

           if last_frame_of_batch:
                self.batch_start_frame()

           if self.detected_overflow and not trace_mode:
                self.dump_saved_frames()

                # now we can abort, as it's pointless to continue running
                raise ValueError(
                    'DebugUnderflowOverflow: inf/nan detected, aborting as there is no point running further. '
                    'Please scroll up above this traceback to see the activation values prior to this event.'  )

           # abort after certain batch if requested to do so
           if self.abort_after_batch_num is not None and self.batch_number > self.abort_after_batch_num:
                raise ValueError(
                    F'''DebugUnderflowOverflow: aborting after {self.batch_number} batches due to'''
                    F''' `abort_after_batch_num={self.abort_after_batch_num}` arg'''  )

def 		SCREAMING_SNAKE_CASE      (					lowerCAmelCase__     :	str       ,  lowerCAmelCase__     :	int)			->						str:

     '''simple docstring'''




     _lowercase							:      str  						=							var.abs()
     return F'''{abs_var.min():8.2e} {abs_var.max():8.2e} {ctx}'''

def 		SCREAMING_SNAKE_CASE      (					lowerCAmelCase__     :	List[str]       ,  lowerCAmelCase__     :	str)			->						str:

     '''simple docstring'''




     _lowercase							:      Optional[Any]  						=							False
     if torch.isnan(lowerCAmelCase__).any().item():
          _lowercase							:      List[str]  						=							True
          print(F'''{ctx} has nans''')
     if torch.isinf(lowerCAmelCase__).any().item():
          _lowercase							:      str  						=							True
          print(F'''{ctx} has infs''')

     # if needed to monitor large elements can enable the following
     if 0:  # and detected:
          _lowercase							:      Union[str, Any]  						=							var[torch.ge(var.abs()       ,  1_00)]
          if naaa.numel() > 0:
               print(F'''{ctx}:  n100={naaa.numel()}''')
          _lowercase							:      Tuple  						=							var[torch.ge(var.abs()       ,  10_00)]
          if naaaa.numel() > 0:
               print(F'''{ctx}: n1000={naaaa.numel()}''')
          _lowercase							:      List[str]  						=							var[torch.ge(var.abs()       ,  1_00_00)]
          if naaaaa.numel() > 0:
               print(F'''{ctx}: n10000={naaaaa.numel()}''')

     if 0:
          print(F'''min={var.min():9.2e} max={var.max():9.2e}''')

     if 0:
          print(F'''min={var.min():9.2e} max={var.max():9.2e} var={var.var():9.2e} mean={var.mean():9.2e} ({ctx})''')

     return detected



class 							__SCREAMING_SNAKE_CASE			(       lowerCAmelCase__      ):
      '''simple docstring'''



      lowerCAmelCase__       :      Any 		=		"underflow_overflow"
      lowerCAmelCase__       :      Any 		=		"tpu_metrics_debug"






'''simple docstring'''







A						    =							{
    '''A''': ('''ABCDEFGHIJKLM''', '''NOPQRSTUVWXYZ'''),
    '''B''': ('''ABCDEFGHIJKLM''', '''NOPQRSTUVWXYZ'''),
    '''C''': ('''ABCDEFGHIJKLM''', '''ZNOPQRSTUVWXY'''),
    '''D''': ('''ABCDEFGHIJKLM''', '''ZNOPQRSTUVWXY'''),
    '''E''': ('''ABCDEFGHIJKLM''', '''YZNOPQRSTUVWX'''),
    '''F''': ('''ABCDEFGHIJKLM''', '''YZNOPQRSTUVWX'''),
    '''G''': ('''ABCDEFGHIJKLM''', '''XYZNOPQRSTUVW'''),
    '''H''': ('''ABCDEFGHIJKLM''', '''XYZNOPQRSTUVW'''),
    '''I''': ('''ABCDEFGHIJKLM''', '''WXYZNOPQRSTUV'''),
    '''J''': ('''ABCDEFGHIJKLM''', '''WXYZNOPQRSTUV'''),
    '''K''': ('''ABCDEFGHIJKLM''', '''VWXYZNOPQRSTU'''),
    '''L''': ('''ABCDEFGHIJKLM''', '''VWXYZNOPQRSTU'''),
    '''M''': ('''ABCDEFGHIJKLM''', '''UVWXYZNOPQRST'''),
    '''N''': ('''ABCDEFGHIJKLM''', '''UVWXYZNOPQRST'''),
    '''O''': ('''ABCDEFGHIJKLM''', '''TUVWXYZNOPQRS'''),
    '''P''': ('''ABCDEFGHIJKLM''', '''TUVWXYZNOPQRS'''),
    '''Q''': ('''ABCDEFGHIJKLM''', '''STUVWXYZNOPQR'''),
    '''R''': ('''ABCDEFGHIJKLM''', '''STUVWXYZNOPQR'''),
    '''S''': ('''ABCDEFGHIJKLM''', '''RSTUVWXYZNOPQ'''),
    '''T''': ('''ABCDEFGHIJKLM''', '''RSTUVWXYZNOPQ'''),
    '''U''': ('''ABCDEFGHIJKLM''', '''QRSTUVWXYZNOP'''),
    '''V''': ('''ABCDEFGHIJKLM''', '''QRSTUVWXYZNOP'''),
    '''W''': ('''ABCDEFGHIJKLM''', '''PQRSTUVWXYZNO'''),
    '''X''': ('''ABCDEFGHIJKLM''', '''PQRSTUVWXYZNO'''),
    '''Y''': ('''ABCDEFGHIJKLM''', '''OPQRSTUVWXYZN'''),
    '''Z''': ('''ABCDEFGHIJKLM''', '''OPQRSTUVWXYZN'''),
}

def 		SCREAMING_SNAKE_CASE      (					lowerCAmelCase__     :	str)			->						list[tuple[str, str]]:

     '''simple docstring'''




     return [alphabet[char] for char in key.upper()]

def 		SCREAMING_SNAKE_CASE      (					lowerCAmelCase__     :	str       ,  lowerCAmelCase__     :	str)			->						str:

     '''simple docstring'''




     _lowercase							:      Optional[int]  						=							''
     _lowercase							:      List[str]  						=							0
     _lowercase							:      Optional[Any]  						=							generate_table(lowerCAmelCase__)
     for char in words.upper():
          cipher += get_opponent(table[count]       ,  lowerCAmelCase__)
          _lowercase							:      Dict  						=							(count + 1) % len(lowerCAmelCase__)
     return cipher

def 		SCREAMING_SNAKE_CASE      (					lowerCAmelCase__     :	str       ,  lowerCAmelCase__     :	str)			->						str:

     '''simple docstring'''




     return encrypt(lowerCAmelCase__       ,  lowerCAmelCase__)

def 		SCREAMING_SNAKE_CASE      (					lowerCAmelCase__     :	tuple[str, str]       ,  lowerCAmelCase__     :	str)			->						tuple[int, int]:

     '''simple docstring'''




     _lowercase							:      Optional[Any]  						=							0 if char in table[0] else 1
     _lowercase							:      Tuple  						=							table[row].index(lowerCAmelCase__)
     return row, col

def 		SCREAMING_SNAKE_CASE      (					lowerCAmelCase__     :	tuple[str, str]       ,  lowerCAmelCase__     :	str)			->						str:

     '''simple docstring'''




     _lowercase						, _lowercase							:      str  						=							get_position(lowerCAmelCase__       ,  char.upper())
     if row == 1:
          return table[0][col]
     else:
          return table[1][col] if row == 0 else char


if __name__ == "__main__":
    import doctest

    doctest.testmod()  # Fist ensure that all our tests are passing...
    A						    =							input('''Enter key: ''').strip()
    A						    =							input('''Enter text to encrypt: ''').strip()
    A						    =							encrypt(key, text)

    print(F"""Encrypted: {cipher_text}""")
    print(F"""Decrypted with key: {decrypt(key, cipher_text)}""")