


import argparse

import torch

from diffusers import UNetaDConditionModel






def 			__lowerCAmelCase       (SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE=None   ,   SCREAMING_SNAKE_CASE=None   ,   SCREAMING_SNAKE_CASE=None   )->    Dict:




      """simple docstring"""

      assert isinstance(SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ), "Paths should be a list of dicts containing 'old' and 'new' keys."

      # Splits the attention layers into three variables.
      if attention_paths_to_split is not None:
            for path, path_map in attention_paths_to_split.items():
                  snake_case_			= old_checkpoint[path]
                  snake_case_			= old_tensor.shape[0] // 3

                  snake_case_			= (-1, channels) if len(old_tensor.shape   ) == 3 else (-1)

                  snake_case_			= old_tensor.shape[0] // config['''num_head_channels'''] // 3

                  snake_case_			= old_tensor.reshape((num_heads, 3 * channels // num_heads) + old_tensor.shape[1:]   )
                  snake_case_			,       snake_case_			,       snake_case_			= old_tensor.split(channels // num_heads   ,   dim=1   )

                  snake_case_			= query.reshape(SCREAMING_SNAKE_CASE   )
                  snake_case_			= key.reshape(SCREAMING_SNAKE_CASE   )
                  snake_case_			= value.reshape(SCREAMING_SNAKE_CASE   )

      for path in paths:
            snake_case_			= path['''new''']

            # These have already been assigned
            if attention_paths_to_split is not None and new_path in attention_paths_to_split:
                  continue

            if additional_replacements is not None:
                  for replacement in additional_replacements:
                        snake_case_			= new_path.replace(replacement['''old''']   ,   replacement['''new''']   )

        # proj_attn.weight has to be converted from conv 1D to linear
            snake_case_			= old_checkpoint[path['''old''']]
            snake_case_			= ['''proj_attn.weight''']
            snake_case_			= ['''proj_out.weight''', '''proj_in.weight''']
            if any(k in new_path for k in names   ):
                  snake_case_			= weight[:, :, 0]
            elif any(k in new_path for k in names_a   ) and len(weight.shape   ) > 2 and ".attentions." not in new_path:
                  snake_case_			= weight[:, :, 0]
            else:
                  snake_case_			= weight






def 			__lowerCAmelCase       (SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE=0   )->    Dict:




      """simple docstring"""

      snake_case_			= []
      for old_item in old_list:
            snake_case_			= old_item

            #         new_item = new_item.replace('norm.weight', 'group_norm.weight')
            #         new_item = new_item.replace('norm.bias', 'group_norm.bias')

            #         new_item = new_item.replace('proj_out.weight', 'proj_attn.weight')
            #         new_item = new_item.replace('proj_out.bias', 'proj_attn.bias')

            #         new_item = shave_segments(new_item, n_shave_prefix_segments=n_shave_prefix_segments)

            mapping.append({'''old''': old_item, '''new''': new_item}   )

      return mapping






def 			__lowerCAmelCase       (SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE=1   )->    int:




      """simple docstring"""

      if n_shave_prefix_segments >= 0:
            return ".".join(path.split('''.'''   )[n_shave_prefix_segments:]   )
      else:
            return ".".join(path.split('''.'''   )[:n_shave_prefix_segments]   )






def 			__lowerCAmelCase       (SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE=0   )->    str:




      """simple docstring"""

      snake_case_			= []
      for old_item in old_list:
            mapping.append({'''old''': old_item, '''new''': old_item}   )

      return mapping






def 			__lowerCAmelCase       (SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE=0   )->    Tuple:




      """simple docstring"""

      snake_case_			= []
      for old_item in old_list:
            snake_case_			= old_item.replace('''in_layers.0'''   ,   '''norm1'''   )
            snake_case_			= new_item.replace('''in_layers.2'''   ,   '''conv1'''   )

            snake_case_			= new_item.replace('''out_layers.0'''   ,   '''norm2'''   )
            snake_case_			= new_item.replace('''out_layers.3'''   ,   '''conv2'''   )

            snake_case_			= new_item.replace('''emb_layers.1'''   ,   '''time_emb_proj'''   )
            snake_case_			= new_item.replace('''skip_connection'''   ,   '''conv_shortcut'''   )

            snake_case_			= shave_segments(SCREAMING_SNAKE_CASE   ,   n_shave_prefix_segments=SCREAMING_SNAKE_CASE   )

            if "temopral_conv" not in old_item:
                  mapping.append({'''old''': old_item, '''new''': new_item}   )

      return mapping






def 			__lowerCAmelCase       (SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE=None   ,   SCREAMING_SNAKE_CASE=False   )->    List[str]:




      """simple docstring"""

      snake_case_			= {}
      snake_case_			= list(checkpoint.keys()   )

      snake_case_			= '''model.diffusion_model.'''

      # at least a 100 parameters have to start with `model_ema` in order for the checkpoint to be EMA
      if sum(k.startswith('''model_ema'''   ) for k in keys   ) > 100 and extract_ema:
            print(f'''Checkpoint {path} has both EMA and non-EMA weights.'''   )
            print(
                '''In this conversion only the EMA weights are extracted. If you want to instead extract the non-EMA'''
                ''' weights (useful to continue fine-tuning), please make sure to remove the `--extract_ema` flag.'''   )
            for key in keys:
                  if key.startswith('''model.diffusion_model'''   ):
                        snake_case_			= '''model_ema.''' + ''''''.join(key.split('''.'''   )[1:]   )
                        snake_case_			= checkpoint.pop(SCREAMING_SNAKE_CASE   )
      else:
            if sum(k.startswith('''model_ema'''   ) for k in keys   ) > 100:
                  print(
                      '''In this conversion only the non-EMA weights are extracted. If you want to instead extract the EMA'''
                      ''' weights (usually better for inference), please make sure to add the `--extract_ema` flag.'''   )

            for key in keys:
                  snake_case_			= checkpoint.pop(SCREAMING_SNAKE_CASE   )

      snake_case_			= {}

      snake_case_			= unet_state_dict['''time_embed.0.weight''']
      snake_case_			= unet_state_dict['''time_embed.0.bias''']
      snake_case_			= unet_state_dict['''time_embed.2.weight''']
      snake_case_			= unet_state_dict['''time_embed.2.bias''']

      if config["class_embed_type"] is None:
            # No parameters to port
            ...
      elif config["class_embed_type"] == "timestep" or config["class_embed_type"] == "projection":
            snake_case_			= unet_state_dict['''label_emb.0.0.weight''']
            snake_case_			= unet_state_dict['''label_emb.0.0.bias''']
            snake_case_			= unet_state_dict['''label_emb.0.2.weight''']
            snake_case_			= unet_state_dict['''label_emb.0.2.bias''']
      else:
            raise NotImplementedError(f'''Not implemented `class_embed_type`: {config["class_embed_type"]}'''   )

      snake_case_			= unet_state_dict['''input_blocks.0.0.weight''']
      snake_case_			= unet_state_dict['''input_blocks.0.0.bias''']

      snake_case_			= [v for v in unet_state_dict if v.startswith('''input_blocks.0.1'''   )]
      snake_case_			= renew_attention_paths(SCREAMING_SNAKE_CASE   )
      snake_case_			= {'''old''': '''input_blocks.0.1''', '''new''': '''transformer_in'''}
      assign_to_checkpoint(SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   additional_replacements=[meta_path]   ,   config=SCREAMING_SNAKE_CASE   )

      snake_case_			= unet_state_dict['''out.0.weight''']
      snake_case_			= unet_state_dict['''out.0.bias''']
      snake_case_			= unet_state_dict['''out.2.weight''']
      snake_case_			= unet_state_dict['''out.2.bias''']

      # Retrieves the keys for the input blocks only
      snake_case_			= len({'''.'''.join(layer.split('''.'''   )[:2]   ) for layer in unet_state_dict if '''input_blocks''' in layer}   )
      snake_case_			= {
          layer_id: [key for key in unet_state_dict if f'''input_blocks.{layer_id}''' in key]
          for layer_id in range(SCREAMING_SNAKE_CASE   )
      }

      # Retrieves the keys for the middle blocks only
      snake_case_			= len({'''.'''.join(layer.split('''.'''   )[:2]   ) for layer in unet_state_dict if '''middle_block''' in layer}   )
      snake_case_			= {
          layer_id: [key for key in unet_state_dict if f'''middle_block.{layer_id}''' in key]
          for layer_id in range(SCREAMING_SNAKE_CASE   )
      }

      # Retrieves the keys for the output blocks only
      snake_case_			= len({'''.'''.join(layer.split('''.'''   )[:2]   ) for layer in unet_state_dict if '''output_blocks''' in layer}   )
      snake_case_			= {
          layer_id: [key for key in unet_state_dict if f'''output_blocks.{layer_id}''' in key]
          for layer_id in range(SCREAMING_SNAKE_CASE   )
      }

      for i in range(1   ,   SCREAMING_SNAKE_CASE   ):
            snake_case_			= (i - 1) // (config['''layers_per_block'''] + 1)
            snake_case_			= (i - 1) % (config['''layers_per_block'''] + 1)

            snake_case_			= [
                key for key in input_blocks[i] if f'''input_blocks.{i}.0''' in key and f'''input_blocks.{i}.0.op''' not in key
            ]
            snake_case_			= [key for key in input_blocks[i] if f'''input_blocks.{i}.1''' in key]
            snake_case_			= [key for key in input_blocks[i] if f'''input_blocks.{i}.2''' in key]

            if f'''input_blocks.{i}.op.weight''' in unet_state_dict:
                  snake_case_			= unet_state_dict.pop(
                      f'''input_blocks.{i}.op.weight'''   )
                  snake_case_			= unet_state_dict.pop(
                      f'''input_blocks.{i}.op.bias'''   )

            snake_case_			= renew_resnet_paths(SCREAMING_SNAKE_CASE   )
            snake_case_			= {'''old''': f'''input_blocks.{i}.0''', '''new''': f'''down_blocks.{block_id}.resnets.{layer_in_block_id}'''}
            assign_to_checkpoint(
                SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   additional_replacements=[meta_path]   ,   config=SCREAMING_SNAKE_CASE   )

            snake_case_			= [key for key in resnets if '''temopral_conv''' in key]
            snake_case_			= renew_temp_conv_paths(SCREAMING_SNAKE_CASE   )
            snake_case_			= {
                '''old''': f'''input_blocks.{i}.0.temopral_conv''',
                '''new''': f'''down_blocks.{block_id}.temp_convs.{layer_in_block_id}''',
            }
            assign_to_checkpoint(
                SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   additional_replacements=[meta_path]   ,   config=SCREAMING_SNAKE_CASE   )

            if len(SCREAMING_SNAKE_CASE   ):
                  snake_case_			= renew_attention_paths(SCREAMING_SNAKE_CASE   )
                  snake_case_			= {'''old''': f'''input_blocks.{i}.1''', '''new''': f'''down_blocks.{block_id}.attentions.{layer_in_block_id}'''}
                  assign_to_checkpoint(
                      SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   additional_replacements=[meta_path]   ,   config=SCREAMING_SNAKE_CASE   )

            if len(SCREAMING_SNAKE_CASE   ):
                  snake_case_			= renew_attention_paths(SCREAMING_SNAKE_CASE   )
                  snake_case_			= {
                      '''old''': f'''input_blocks.{i}.2''',
                      '''new''': f'''down_blocks.{block_id}.temp_attentions.{layer_in_block_id}''',
                  }
                  assign_to_checkpoint(
                      SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   additional_replacements=[meta_path]   ,   config=SCREAMING_SNAKE_CASE   )

      snake_case_			= middle_blocks[0]
      snake_case_			= [key for key in resnet_a if '''temopral_conv''' in key]
      snake_case_			= middle_blocks[1]
      snake_case_			= middle_blocks[2]
      snake_case_			= middle_blocks[3]
      snake_case_			= [key for key in resnet_a if '''temopral_conv''' in key]

      snake_case_			= renew_resnet_paths(SCREAMING_SNAKE_CASE   )
      snake_case_			= {'''old''': '''middle_block.0''', '''new''': '''mid_block.resnets.0'''}
      assign_to_checkpoint(
          SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   config=SCREAMING_SNAKE_CASE   ,   additional_replacements=[meta_path]   )

      snake_case_			= renew_temp_conv_paths(SCREAMING_SNAKE_CASE   )
      snake_case_			= {'''old''': '''middle_block.0.temopral_conv''', '''new''': '''mid_block.temp_convs.0'''}
      assign_to_checkpoint(
          SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   config=SCREAMING_SNAKE_CASE   ,   additional_replacements=[meta_path]   )

      snake_case_			= renew_resnet_paths(SCREAMING_SNAKE_CASE   )
      snake_case_			= {'''old''': '''middle_block.3''', '''new''': '''mid_block.resnets.1'''}
      assign_to_checkpoint(
          SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   config=SCREAMING_SNAKE_CASE   ,   additional_replacements=[meta_path]   )

      snake_case_			= renew_temp_conv_paths(SCREAMING_SNAKE_CASE   )
      snake_case_			= {'''old''': '''middle_block.3.temopral_conv''', '''new''': '''mid_block.temp_convs.1'''}
      assign_to_checkpoint(
          SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   config=SCREAMING_SNAKE_CASE   ,   additional_replacements=[meta_path]   )

      snake_case_			= renew_attention_paths(SCREAMING_SNAKE_CASE   )
      snake_case_			= {'''old''': '''middle_block.1''', '''new''': '''mid_block.attentions.0'''}
      assign_to_checkpoint(
          SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   additional_replacements=[meta_path]   ,   config=SCREAMING_SNAKE_CASE   )

      snake_case_			= renew_attention_paths(SCREAMING_SNAKE_CASE   )
      snake_case_			= {'''old''': '''middle_block.2''', '''new''': '''mid_block.temp_attentions.0'''}
      assign_to_checkpoint(
          SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   additional_replacements=[meta_path]   ,   config=SCREAMING_SNAKE_CASE   )

      for i in range(SCREAMING_SNAKE_CASE   ):
            snake_case_			= i // (config['''layers_per_block'''] + 1)
            snake_case_			= i % (config['''layers_per_block'''] + 1)
            snake_case_			= [shave_segments(SCREAMING_SNAKE_CASE   ,   2   ) for name in output_blocks[i]]
            snake_case_			= {}

            for layer in output_block_layers:
                  snake_case_			,       snake_case_			= layer.split('''.'''   )[0], shave_segments(SCREAMING_SNAKE_CASE   ,   1   )
                  if layer_id in output_block_list:
                        output_block_list[layer_id].append(SCREAMING_SNAKE_CASE   )
                  else:
                        snake_case_			= [layer_name]

            if len(SCREAMING_SNAKE_CASE   ) > 1:
                  snake_case_			= [key for key in output_blocks[i] if f'''output_blocks.{i}.0''' in key]
                  snake_case_			= [key for key in output_blocks[i] if f'''output_blocks.{i}.1''' in key]
                  snake_case_			= [key for key in output_blocks[i] if f'''output_blocks.{i}.2''' in key]

                  snake_case_			= renew_resnet_paths(SCREAMING_SNAKE_CASE   )
                  snake_case_			= renew_resnet_paths(SCREAMING_SNAKE_CASE   )

                  snake_case_			= {'''old''': f'''output_blocks.{i}.0''', '''new''': f'''up_blocks.{block_id}.resnets.{layer_in_block_id}'''}
                  assign_to_checkpoint(
                      SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   additional_replacements=[meta_path]   ,   config=SCREAMING_SNAKE_CASE   )

                  snake_case_			= [key for key in resnets if '''temopral_conv''' in key]
                  snake_case_			= renew_temp_conv_paths(SCREAMING_SNAKE_CASE   )
                  snake_case_			= {
                      '''old''': f'''output_blocks.{i}.0.temopral_conv''',
                      '''new''': f'''up_blocks.{block_id}.temp_convs.{layer_in_block_id}''',
                  }
                  assign_to_checkpoint(
                      SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   additional_replacements=[meta_path]   ,   config=SCREAMING_SNAKE_CASE   )

                  snake_case_			= {k: sorted(SCREAMING_SNAKE_CASE   ) for k, v in output_block_list.items()}
                  if ["conv.bias", "conv.weight"] in output_block_list.values():
                        snake_case_			= list(output_block_list.values()   ).index(['''conv.bias''', '''conv.weight''']   )
                        snake_case_			= unet_state_dict[
                            f'''output_blocks.{i}.{index}.conv.weight'''
                        ]
                        snake_case_			= unet_state_dict[
                            f'''output_blocks.{i}.{index}.conv.bias'''
                        ]

                        # Clear attentions as they have been attributed above.
                        if len(SCREAMING_SNAKE_CASE   ) == 2:
                              snake_case_			= []

                  if len(SCREAMING_SNAKE_CASE   ):
                        snake_case_			= renew_attention_paths(SCREAMING_SNAKE_CASE   )
                        snake_case_			= {
                            '''old''': f'''output_blocks.{i}.1''',
                            '''new''': f'''up_blocks.{block_id}.attentions.{layer_in_block_id}''',
                        }
                        assign_to_checkpoint(
                            SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   additional_replacements=[meta_path]   ,   config=SCREAMING_SNAKE_CASE   )

                  if len(SCREAMING_SNAKE_CASE   ):
                        snake_case_			= renew_attention_paths(SCREAMING_SNAKE_CASE   )
                        snake_case_			= {
                            '''old''': f'''output_blocks.{i}.2''',
                            '''new''': f'''up_blocks.{block_id}.temp_attentions.{layer_in_block_id}''',
                        }
                        assign_to_checkpoint(
                            SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   SCREAMING_SNAKE_CASE   ,   additional_replacements=[meta_path]   ,   config=SCREAMING_SNAKE_CASE   )
            else:
                  snake_case_			= renew_resnet_paths(SCREAMING_SNAKE_CASE   ,   n_shave_prefix_segments=1   )
                  for path in resnet_0_paths:
                        snake_case_			= '''.'''.join(['''output_blocks''', str(SCREAMING_SNAKE_CASE   ), path['''old''']]   )
                        snake_case_			= '''.'''.join(['''up_blocks''', str(SCREAMING_SNAKE_CASE   ), '''resnets''', str(SCREAMING_SNAKE_CASE   ), path['''new''']]   )
                        snake_case_			= unet_state_dict[old_path]

                  snake_case_			= [l for l in output_block_layers if '''temopral_conv''' in l]
                  for path in temopral_conv_paths:
                        snake_case_			= path.split('''temopral_conv.'''   )[-1]
                        snake_case_			= '''.'''.join(['''output_blocks''', str(SCREAMING_SNAKE_CASE   ), str(SCREAMING_SNAKE_CASE   ), '''temopral_conv''', pruned_path]   )
                        snake_case_			= '''.'''.join(['''up_blocks''', str(SCREAMING_SNAKE_CASE   ), '''temp_convs''', str(SCREAMING_SNAKE_CASE   ), pruned_path]   )
                        snake_case_			= unet_state_dict[old_path]

      return new_checkpoint


if __name__ == "__main__":
   UpperCAmelCase     =       argparse.ArgumentParser()

   parser.add_argument(
       """--checkpoint_path""", default=None, type=str, required=True, help="""Path to the checkpoint to convert."""
   )
   parser.add_argument("""--dump_path""", default=None, type=str, required=True, help="""Path to the output model.""")
   UpperCAmelCase     =       parser.parse_args()

   UpperCAmelCase     =       torch.load(args.checkpoint_path, map_location="""cpu""")
   UpperCAmelCase     =       UNetaDConditionModel()

   UpperCAmelCase     =       convert_ldm_unet_checkpoint(unet_checkpoint, unet.config)

   UpperCAmelCase     =       set(unet.state_dict().keys()) - set(converted_ckpt.keys())
   UpperCAmelCase     =       set(converted_ckpt.keys()) - set(unet.state_dict().keys())

   assert len(diff_a) == len(diff_a) == 0, "Converted weights don't match"

   # load state_dict
   unet.load_state_dict(converted_ckpt)

   unet.save_pretrained(args.dump_path)

   # -- finish converting the unet --



from collections import OrderedDict
from dataclasses import fields
from typing import Any, Tuple

import numpy as np

from .import_utils import is_torch_available






def 			__lowerCAmelCase       (SCREAMING_SNAKE_CASE   )->    Union[str, Any]:




      """simple docstring"""

      if is_torch_available():
            import torch

            if isinstance(SCREAMING_SNAKE_CASE   ,   torch.Tensor   ):
                  return True

      return isinstance(SCREAMING_SNAKE_CASE   ,   np.ndarray   )







class lowerCAmelCase_		(					lowerCamelCase__			):

 '''simple docstring'''

 def 		UpperCamelCase__	(      self   ):
       snake_case_			= fields(self   )

       # Safety and consistency checks
       if not len(_UpperCAmelCase   ):
             raise ValueError(F'''{self.__class__.__name__} has no fields.'''   )

       snake_case_			= getattr(self						, class_fields[0].name   )
       snake_case_			= all(getattr(self						, field.name   ) is None for field in class_fields[1:]   )

       if other_fields_are_none and isinstance(_UpperCAmelCase						, _UpperCAmelCase   ):
             for key, value in first_field.items():
                   snake_case_			= value
       else:
             for field in class_fields:
                   snake_case_			= getattr(self						, field.name   )
                   if v is not None:
                         snake_case_			= v



 def __delitem__(      self						, *_UpperCAmelCase						, **_UpperCAmelCase   ):
       raise Exception(F'''You cannot use ``__delitem__`` on a {self.__class__.__name__} instance.'''   )



 def 		UpperCamelCase__	(      self						, *_UpperCAmelCase						, **_UpperCAmelCase   ):
       raise Exception(F'''You cannot use ``setdefault`` on a {self.__class__.__name__} instance.'''   )



 def 		UpperCamelCase__	(      self						, *_UpperCAmelCase						, **_UpperCAmelCase   ):
       raise Exception(F'''You cannot use ``pop`` on a {self.__class__.__name__} instance.'''   )



 def 		UpperCamelCase__	(      self						, *_UpperCAmelCase						, **_UpperCAmelCase   ):
       raise Exception(F'''You cannot use ``update`` on a {self.__class__.__name__} instance.'''   )



 def __getitem__(      self						, _UpperCAmelCase   ):
       if isinstance(_UpperCAmelCase						, _UpperCAmelCase   ):
             snake_case_			= dict(self.items()   )
             return inner_dict[k]
       else:
             return self.to_tuple()[k]



 def __setattr__(      self						, _UpperCAmelCase						, _UpperCAmelCase   ):
       if name in self.keys() and value is not None:
             # Don't call self.__setitem__ to avoid recursion errors
             super().__setitem__(_UpperCAmelCase						, _UpperCAmelCase   )
       super().__setattr__(_UpperCAmelCase						, _UpperCAmelCase   )



 def __setitem__(      self						, _UpperCAmelCase						, _UpperCAmelCase   ):
       # Will raise a KeyException if needed
       super().__setitem__(_UpperCAmelCase						, _UpperCAmelCase   )
       # Don't call self.__setattr__ to avoid recursion errors
       super().__setattr__(_UpperCAmelCase						, _UpperCAmelCase   )





 def 		UpperCamelCase__	(      self   ):
       return tuple(self[k] for k in self.keys()   )