




import argparse
import json
from pathlib import Path

import requests
import torch
from huggingface_hub import hf_hub_download
from PIL import Image

from transformers import DetrConfig, DetrForObjectDetection, DetrForSegmentation, DetrImageProcessor, ResNetConfig
from transformers.utils import logging


logging.set_verbosity_info()
lowerCAmelCase_					    = logging.get_logger(__name__)



def      __lowerCAmelCase			(					UpperCamelCase      )     ->	List[str]:
  # initialize config
  if "resnet-50" in model_name:
    lowerCAmelCase__				:  Optional[Any]		       =     ResNetConfig.from_pretrained('''microsoft/resnet-50'''      )
  elif "resnet-101" in model_name:
    lowerCAmelCase__				:  List[Any]		       =     ResNetConfig.from_pretrained('''microsoft/resnet-101'''      )
  else:
    raise ValueError('''Model name should include either resnet50 or resnet101'''      )

  lowerCAmelCase__				:  List[Any]		       =     DetrConfig(use_timm_backbone=UpperCamelCase	,      backbone_config=UpperCamelCase      )

  # set label attributes
  lowerCAmelCase__				:  Optional[int]		       =     '''panoptic''' in model_name
  if is_panoptic:
    lowerCAmelCase__				:  Optional[Any]		       =     250
  else:
    lowerCAmelCase__				:  Any		       =     91
    lowerCAmelCase__				:  Any		       =     '''huggingface/label-files'''
    lowerCAmelCase__				:  str		       =     '''coco-detection-id2label.json'''
    lowerCAmelCase__				:  str		       =     json.load(open(hf_hub_download(UpperCamelCase	,      UpperCamelCase	,      repo_type='''dataset'''      )	,      '''r'''      )      )
    lowerCAmelCase__				:  str		       =     {int(UpperCamelCase      ): v for k, v in idalabel.items()}
    lowerCAmelCase__				:  str		       =     idalabel
    lowerCAmelCase__				:  List[Any]		       =     {v: k for k, v in idalabel.items()}

  return config, is_panoptic



def      __lowerCAmelCase			(					UpperCamelCase      )     ->	List[Any]:
  # here we list all keys to be renamed (original name on the left, our name on the right)
  lowerCAmelCase__				:  Any		       =     []

  # stem
  # fmt: off
  rename_keys.append(('''backbone.0.body.conv1.weight''', '''backbone.conv_encoder.model.embedder.embedder.convolution.weight''')      )
  rename_keys.append(('''backbone.0.body.bn1.weight''', '''backbone.conv_encoder.model.embedder.embedder.normalization.weight''')      )
  rename_keys.append(('''backbone.0.body.bn1.bias''', '''backbone.conv_encoder.model.embedder.embedder.normalization.bias''')      )
  rename_keys.append(('''backbone.0.body.bn1.running_mean''', '''backbone.conv_encoder.model.embedder.embedder.normalization.running_mean''')      )
  rename_keys.append(('''backbone.0.body.bn1.running_var''', '''backbone.conv_encoder.model.embedder.embedder.normalization.running_var''')      )
  # stages
  for stage_idx in range(len(config.backbone_config.depths      )      ):
    for layer_idx in range(config.backbone_config.depths[stage_idx]      ):
      # shortcut
      if layer_idx == 0:
        rename_keys.append(
            (
                F"""backbone.0.body.layer{stage_idx + 1}.{layer_idx}.downsample.0.weight""",
                F"""backbone.conv_encoder.model.encoder.stages.{stage_idx}.layers.{layer_idx}.shortcut.convolution.weight""",
            )      )
        rename_keys.append(
            (
                F"""backbone.0.body.layer{stage_idx + 1}.{layer_idx}.downsample.1.weight""",
                F"""backbone.conv_encoder.model.encoder.stages.{stage_idx}.layers.{layer_idx}.shortcut.normalization.weight""",
            )      )
        rename_keys.append(
            (
                F"""backbone.0.body.layer{stage_idx + 1}.{layer_idx}.downsample.1.bias""",
                F"""backbone.conv_encoder.model.encoder.stages.{stage_idx}.layers.{layer_idx}.shortcut.normalization.bias""",
            )      )
        rename_keys.append(
            (
                F"""backbone.0.body.layer{stage_idx + 1}.{layer_idx}.downsample.1.running_mean""",
                F"""backbone.conv_encoder.model.encoder.stages.{stage_idx}.layers.{layer_idx}.shortcut.normalization.running_mean""",
            )      )
        rename_keys.append(
            (
                F"""backbone.0.body.layer{stage_idx + 1}.{layer_idx}.downsample.1.running_var""",
                F"""backbone.conv_encoder.model.encoder.stages.{stage_idx}.layers.{layer_idx}.shortcut.normalization.running_var""",
            )      )
      # 3 convs
      for i in range(3      ):
        rename_keys.append(
            (
                F"""backbone.0.body.layer{stage_idx + 1}.{layer_idx}.conv{i+1}.weight""",
                F"""backbone.conv_encoder.model.encoder.stages.{stage_idx}.layers.{layer_idx}.layer.{i}.convolution.weight""",
            )      )
        rename_keys.append(
            (
                F"""backbone.0.body.layer{stage_idx + 1}.{layer_idx}.bn{i+1}.weight""",
                F"""backbone.conv_encoder.model.encoder.stages.{stage_idx}.layers.{layer_idx}.layer.{i}.normalization.weight""",
            )      )
        rename_keys.append(
            (
                F"""backbone.0.body.layer{stage_idx + 1}.{layer_idx}.bn{i+1}.bias""",
                F"""backbone.conv_encoder.model.encoder.stages.{stage_idx}.layers.{layer_idx}.layer.{i}.normalization.bias""",
            )      )
        rename_keys.append(
            (
                F"""backbone.0.body.layer{stage_idx + 1}.{layer_idx}.bn{i+1}.running_mean""",
                F"""backbone.conv_encoder.model.encoder.stages.{stage_idx}.layers.{layer_idx}.layer.{i}.normalization.running_mean""",
            )      )
        rename_keys.append(
            (
                F"""backbone.0.body.layer{stage_idx + 1}.{layer_idx}.bn{i+1}.running_var""",
                F"""backbone.conv_encoder.model.encoder.stages.{stage_idx}.layers.{layer_idx}.layer.{i}.normalization.running_var""",
            )      )
    # fmt: on

  for i in range(config.encoder_layers      ):
    # encoder layers: output projection, 2 feedforward neural networks and 2 layernorms
    rename_keys.append(
        (
            F"""transformer.encoder.layers.{i}.self_attn.out_proj.weight""",
            F"""encoder.layers.{i}.self_attn.out_proj.weight""",
        )      )
    rename_keys.append(
        (F"""transformer.encoder.layers.{i}.self_attn.out_proj.bias""", F"""encoder.layers.{i}.self_attn.out_proj.bias""")      )
    rename_keys.append((F"""transformer.encoder.layers.{i}.linear1.weight""", F"""encoder.layers.{i}.fc1.weight""")      )
    rename_keys.append((F"""transformer.encoder.layers.{i}.linear1.bias""", F"""encoder.layers.{i}.fc1.bias""")      )
    rename_keys.append((F"""transformer.encoder.layers.{i}.linear2.weight""", F"""encoder.layers.{i}.fc2.weight""")      )
    rename_keys.append((F"""transformer.encoder.layers.{i}.linear2.bias""", F"""encoder.layers.{i}.fc2.bias""")      )
    rename_keys.append(
        (F"""transformer.encoder.layers.{i}.norm1.weight""", F"""encoder.layers.{i}.self_attn_layer_norm.weight""")      )
    rename_keys.append(
        (F"""transformer.encoder.layers.{i}.norm1.bias""", F"""encoder.layers.{i}.self_attn_layer_norm.bias""")      )
    rename_keys.append(
        (F"""transformer.encoder.layers.{i}.norm2.weight""", F"""encoder.layers.{i}.final_layer_norm.weight""")      )
    rename_keys.append((F"""transformer.encoder.layers.{i}.norm2.bias""", F"""encoder.layers.{i}.final_layer_norm.bias""")      )
    # decoder layers: 2 times output projection, 2 feedforward neural networks and 3 layernorms
    rename_keys.append(
        (
            F"""transformer.decoder.layers.{i}.self_attn.out_proj.weight""",
            F"""decoder.layers.{i}.self_attn.out_proj.weight""",
        )      )
    rename_keys.append(
        (F"""transformer.decoder.layers.{i}.self_attn.out_proj.bias""", F"""decoder.layers.{i}.self_attn.out_proj.bias""")      )
    rename_keys.append(
        (
            F"""transformer.decoder.layers.{i}.multihead_attn.out_proj.weight""",
            F"""decoder.layers.{i}.encoder_attn.out_proj.weight""",
        )      )
    rename_keys.append(
        (
            F"""transformer.decoder.layers.{i}.multihead_attn.out_proj.bias""",
            F"""decoder.layers.{i}.encoder_attn.out_proj.bias""",
        )      )
    rename_keys.append((F"""transformer.decoder.layers.{i}.linear1.weight""", F"""decoder.layers.{i}.fc1.weight""")      )
    rename_keys.append((F"""transformer.decoder.layers.{i}.linear1.bias""", F"""decoder.layers.{i}.fc1.bias""")      )
    rename_keys.append((F"""transformer.decoder.layers.{i}.linear2.weight""", F"""decoder.layers.{i}.fc2.weight""")      )
    rename_keys.append((F"""transformer.decoder.layers.{i}.linear2.bias""", F"""decoder.layers.{i}.fc2.bias""")      )
    rename_keys.append(
        (F"""transformer.decoder.layers.{i}.norm1.weight""", F"""decoder.layers.{i}.self_attn_layer_norm.weight""")      )
    rename_keys.append(
        (F"""transformer.decoder.layers.{i}.norm1.bias""", F"""decoder.layers.{i}.self_attn_layer_norm.bias""")      )
    rename_keys.append(
        (F"""transformer.decoder.layers.{i}.norm2.weight""", F"""decoder.layers.{i}.encoder_attn_layer_norm.weight""")      )
    rename_keys.append(
        (F"""transformer.decoder.layers.{i}.norm2.bias""", F"""decoder.layers.{i}.encoder_attn_layer_norm.bias""")      )
    rename_keys.append(
        (F"""transformer.decoder.layers.{i}.norm3.weight""", F"""decoder.layers.{i}.final_layer_norm.weight""")      )
    rename_keys.append((F"""transformer.decoder.layers.{i}.norm3.bias""", F"""decoder.layers.{i}.final_layer_norm.bias""")      )

  # convolutional projection + query embeddings + layernorm of decoder + class and bounding box heads
  rename_keys.extend(
      [
          ('''input_proj.weight''', '''input_projection.weight'''),
          ('''input_proj.bias''', '''input_projection.bias'''),
          ('''query_embed.weight''', '''query_position_embeddings.weight'''),
          ('''transformer.decoder.norm.weight''', '''decoder.layernorm.weight'''),
          ('''transformer.decoder.norm.bias''', '''decoder.layernorm.bias'''),
          ('''class_embed.weight''', '''class_labels_classifier.weight'''),
          ('''class_embed.bias''', '''class_labels_classifier.bias'''),
          ('''bbox_embed.layers.0.weight''', '''bbox_predictor.layers.0.weight'''),
          ('''bbox_embed.layers.0.bias''', '''bbox_predictor.layers.0.bias'''),
          ('''bbox_embed.layers.1.weight''', '''bbox_predictor.layers.1.weight'''),
          ('''bbox_embed.layers.1.bias''', '''bbox_predictor.layers.1.bias'''),
          ('''bbox_embed.layers.2.weight''', '''bbox_predictor.layers.2.weight'''),
          ('''bbox_embed.layers.2.bias''', '''bbox_predictor.layers.2.bias'''),
      ]      )

  return rename_keys



def      __lowerCAmelCase			(					UpperCamelCase	,      UpperCamelCase	,      UpperCamelCase      )     ->	List[Any]:
  lowerCAmelCase__				:  List[Any]		       =     state_dict.pop(UpperCamelCase      )
  lowerCAmelCase__				:  str		       =     val



def      __lowerCAmelCase			(					UpperCamelCase	,      UpperCamelCase=False      )     ->	Optional[Any]:
  lowerCAmelCase__				:  Optional[int]		       =     ''''''
  if is_panoptic:
    lowerCAmelCase__				:  Optional[Any]		       =     '''detr.'''

  # first: transformer encoder
  for i in range(6      ):
    # read in weights + bias of input projection layer (in PyTorch's MultiHeadAttention, this is a single matrix + bias)
    lowerCAmelCase__				:  str		       =     state_dict.pop(F"""{prefix}transformer.encoder.layers.{i}.self_attn.in_proj_weight"""      )
    lowerCAmelCase__				:  Tuple		       =     state_dict.pop(F"""{prefix}transformer.encoder.layers.{i}.self_attn.in_proj_bias"""      )
    # next, add query, keys and values (in that order) to the state dict
    lowerCAmelCase__				:  Any		       =     in_proj_weight[:256, :]
    lowerCAmelCase__				:  Optional[int]		       =     in_proj_bias[:256]
    lowerCAmelCase__				:  Dict		       =     in_proj_weight[256:512, :]
    lowerCAmelCase__				:  Optional[int]		       =     in_proj_bias[256:512]
    lowerCAmelCase__				:  Dict		       =     in_proj_weight[-256:, :]
    lowerCAmelCase__				:  List[str]		       =     in_proj_bias[-256:]
  # next: transformer decoder (which is a bit more complex because it also includes cross-attention)
  for i in range(6      ):
    # read in weights + bias of input projection layer of self-attention
    lowerCAmelCase__				:  str		       =     state_dict.pop(F"""{prefix}transformer.decoder.layers.{i}.self_attn.in_proj_weight"""      )
    lowerCAmelCase__				:  Tuple		       =     state_dict.pop(F"""{prefix}transformer.decoder.layers.{i}.self_attn.in_proj_bias"""      )
    # next, add query, keys and values (in that order) to the state dict
    lowerCAmelCase__				:  int		       =     in_proj_weight[:256, :]
    lowerCAmelCase__				:  Tuple		       =     in_proj_bias[:256]
    lowerCAmelCase__				:  Tuple		       =     in_proj_weight[256:512, :]
    lowerCAmelCase__				:  Union[str, Any]		       =     in_proj_bias[256:512]
    lowerCAmelCase__				:  Dict		       =     in_proj_weight[-256:, :]
    lowerCAmelCase__				:  Dict		       =     in_proj_bias[-256:]
    # read in weights + bias of input projection layer of cross-attention
    lowerCAmelCase__				:  Any		       =     state_dict.pop(
        F"""{prefix}transformer.decoder.layers.{i}.multihead_attn.in_proj_weight"""      )
    lowerCAmelCase__				:  List[str]		       =     state_dict.pop(F"""{prefix}transformer.decoder.layers.{i}.multihead_attn.in_proj_bias"""      )
    # next, add query, keys and values (in that order) of cross-attention to the state dict
    lowerCAmelCase__				:  List[Any]		       =     in_proj_weight_cross_attn[:256, :]
    lowerCAmelCase__				:  Tuple		       =     in_proj_bias_cross_attn[:256]
    lowerCAmelCase__				:  Optional[int]		       =     in_proj_weight_cross_attn[256:512, :]
    lowerCAmelCase__				:  List[Any]		       =     in_proj_bias_cross_attn[256:512]
    lowerCAmelCase__				:  Optional[int]		       =     in_proj_weight_cross_attn[-256:, :]
    lowerCAmelCase__				:  List[str]		       =     in_proj_bias_cross_attn[-256:]



def      __lowerCAmelCase			(					)     ->	List[Any]:
  lowerCAmelCase__				:  Optional[Any]		       =     '''http://images.cocodataset.org/val2017/000000039769.jpg'''
  lowerCAmelCase__				:  Tuple		       =     Image.open(requests.get(UpperCamelCase	,      stream=UpperCamelCase      ).raw      )

  return im



@torch.no_grad()
def      __lowerCAmelCase			(					UpperCamelCase	,      UpperCamelCase=None	,      UpperCamelCase=False      )     ->	str:
  lowerCAmelCase__       ,			lowerCAmelCase__				:  int		       =     get_detr_config(UpperCamelCase      )

  # load original model from torch hub
  lowerCAmelCase__				:  Union[str, Any]		       =     {
      '''detr-resnet-50''': '''detr_resnet50''',
      '''detr-resnet-101''': '''detr_resnet101''',
  }
  logger.info(F"""Converting model {model_name}..."""      )
  lowerCAmelCase__				:  Optional[Any]		       =     torch.hub.load('''facebookresearch/detr'''	,      model_name_to_original_name[model_name]	,      pretrained=UpperCamelCase      ).eval()
  lowerCAmelCase__				:  str		       =     detr.state_dict()
  # rename keys
  for src, dest in create_rename_keys(UpperCamelCase      ):
    if is_panoptic:
      lowerCAmelCase__				:  str		       =     '''detr.''' + src
    rename_key(UpperCamelCase	,      UpperCamelCase	,      UpperCamelCase      )
  # query, key and value matrices need special treatment
  read_in_q_k_v(UpperCamelCase	,      is_panoptic=UpperCamelCase      )
  # important: we need to prepend a prefix to each of the base model keys as the head models use different attributes for them
  lowerCAmelCase__				:  List[str]		       =     '''detr.model.''' if is_panoptic else '''model.'''
  for key in state_dict.copy().keys():
    if is_panoptic:
      if (
          key.startswith('''detr'''      )
          and not key.startswith('''class_labels_classifier'''      )
          and not key.startswith('''bbox_predictor'''      )
      ):
        lowerCAmelCase__				:  int		       =     state_dict.pop(UpperCamelCase      )
        lowerCAmelCase__				:  str		       =     val
      elif "class_labels_classifier" in key or "bbox_predictor" in key:
        lowerCAmelCase__				:  Optional[Any]		       =     state_dict.pop(UpperCamelCase      )
        lowerCAmelCase__				:  List[str]		       =     val
      elif key.startswith('''bbox_attention'''      ) or key.startswith('''mask_head'''      ):
        continue
      else:
        lowerCAmelCase__				:  str		       =     state_dict.pop(UpperCamelCase      )
        lowerCAmelCase__				:  List[str]		       =     val
    else:
      if not key.startswith('''class_labels_classifier'''      ) and not key.startswith('''bbox_predictor'''      ):
        lowerCAmelCase__				:  Tuple		       =     state_dict.pop(UpperCamelCase      )
        lowerCAmelCase__				:  Union[str, Any]		       =     val

    # finally, create HuggingFace model and load state dict
  lowerCAmelCase__				:  Tuple		       =     DetrForSegmentation(UpperCamelCase      ) if is_panoptic else DetrForObjectDetection(UpperCamelCase      )
  model.load_state_dict(UpperCamelCase      )
  model.eval()

  # verify our conversion on an image
  lowerCAmelCase__				:  str		       =     '''coco_panoptic''' if is_panoptic else '''coco_detection'''
  lowerCAmelCase__				:  Optional[Any]		       =     DetrImageProcessor(format=UpperCamelCase      )

  lowerCAmelCase__				:  Any		       =     processor(images=prepare_img()	,      return_tensors='''pt'''      )
  lowerCAmelCase__				:  str		       =     encoding['''pixel_values''']

  lowerCAmelCase__				:  str		       =     detr(UpperCamelCase      )
  lowerCAmelCase__				:  Optional[int]		       =     model(UpperCamelCase      )

  assert torch.allclose(outputs.logits	,      original_outputs['''pred_logits''']	,      atol=1E-3      )
  assert torch.allclose(outputs.pred_boxes	,      original_outputs['''pred_boxes''']	,      atol=1E-3      )
  if is_panoptic:
    assert torch.allclose(outputs.pred_masks	,      original_outputs['''pred_masks''']	,      atol=1E-4      )
  print('''Looks ok!'''      )

  if pytorch_dump_folder_path is not None:
    # Save model and image processor
    logger.info(F"""Saving PyTorch model and image processor to {pytorch_dump_folder_path}..."""      )
    Path(UpperCamelCase      ).mkdir(exist_ok=UpperCamelCase      )
    model.save_pretrained(UpperCamelCase      )
    processor.save_pretrained(UpperCamelCase      )

  if push_to_hub:
    # Upload model and image processor to the hub
    logger.info('''Uploading PyTorch model and image processor to the hub...'''      )
    model.push_to_hub(F"""nielsr/{model_name}"""      )
    processor.push_to_hub(F"""nielsr/{model_name}"""      )


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

     parser.add_argument(
         """--model_name""",
         default="""detr-resnet-50""",
         type=str,
         choices=["""detr-resnet-50""", """detr-resnet-101"""],
         help="""Name of the DETR model you'd like to convert.""",
     )
     parser.add_argument(
         """--pytorch_dump_folder_path""", default=None, type=str, help="""Path to the folder to output PyTorch model."""
     )
     parser.add_argument("""--push_to_hub""", action="""store_true""", help="""Whether to push the model to the hub or not.""")
     lowerCAmelCase_					    = parser.parse_args()
     convert_detr_checkpoint(args.model_name, args.pytorch_dump_folder_path, args.push_to_hub)







from typing import TYPE_CHECKING

from ...utils import (
    OptionalDependencyNotAvailable,
    _LazyModule,
    is_tf_available,
    is_tokenizers_available,
    is_torch_available,
)


lowerCAmelCase_					    = {
    """configuration_longformer""": [
        """LONGFORMER_PRETRAINED_CONFIG_ARCHIVE_MAP""",
        """LongformerConfig""",
        """LongformerOnnxConfig""",
    ],
    """tokenization_longformer""": ["""LongformerTokenizer"""],
}

try:
     if not is_tokenizers_available():
          raise OptionalDependencyNotAvailable()
except OptionalDependencyNotAvailable:
     pass
else:
     lowerCAmelCase_					    = ["""LongformerTokenizerFast"""]

try:
     if not is_torch_available():
          raise OptionalDependencyNotAvailable()
except OptionalDependencyNotAvailable:
     pass
else:
     lowerCAmelCase_					    = [
         """LONGFORMER_PRETRAINED_MODEL_ARCHIVE_LIST""",
         """LongformerForMaskedLM""",
         """LongformerForMultipleChoice""",
         """LongformerForQuestionAnswering""",
         """LongformerForSequenceClassification""",
         """LongformerForTokenClassification""",
         """LongformerModel""",
         """LongformerPreTrainedModel""",
         """LongformerSelfAttention""",
     ]

try:
     if not is_tf_available():
          raise OptionalDependencyNotAvailable()
except OptionalDependencyNotAvailable:
     pass
else:
     lowerCAmelCase_					    = [
         """TF_LONGFORMER_PRETRAINED_MODEL_ARCHIVE_LIST""",
         """TFLongformerForMaskedLM""",
         """TFLongformerForMultipleChoice""",
         """TFLongformerForQuestionAnswering""",
         """TFLongformerForSequenceClassification""",
         """TFLongformerForTokenClassification""",
         """TFLongformerModel""",
         """TFLongformerPreTrainedModel""",
         """TFLongformerSelfAttention""",
     ]


if TYPE_CHECKING:
     from .configuration_longformer import (
         LONGFORMER_PRETRAINED_CONFIG_ARCHIVE_MAP,
         LongformerConfig,
         LongformerOnnxConfig,
     )
     from .tokenization_longformer import LongformerTokenizer

     try:
          if not is_tokenizers_available():
               raise OptionalDependencyNotAvailable()
     except OptionalDependencyNotAvailable:
          pass
     else:
          from .tokenization_longformer_fast import LongformerTokenizerFast

     try:
          if not is_torch_available():
               raise OptionalDependencyNotAvailable()
     except OptionalDependencyNotAvailable:
          pass
     else:
          from .modeling_longformer import (
              LONGFORMER_PRETRAINED_MODEL_ARCHIVE_LIST,
              LongformerForMaskedLM,
              LongformerForMultipleChoice,
              LongformerForQuestionAnswering,
              LongformerForSequenceClassification,
              LongformerForTokenClassification,
              LongformerModel,
              LongformerPreTrainedModel,
              LongformerSelfAttention,
          )

     try:
          if not is_tf_available():
               raise OptionalDependencyNotAvailable()
     except OptionalDependencyNotAvailable:
          pass
     else:
          from .modeling_tf_longformer import (
              TF_LONGFORMER_PRETRAINED_MODEL_ARCHIVE_LIST,
              TFLongformerForMaskedLM,
              TFLongformerForMultipleChoice,
              TFLongformerForQuestionAnswering,
              TFLongformerForSequenceClassification,
              TFLongformerForTokenClassification,
              TFLongformerModel,
              TFLongformerPreTrainedModel,
              TFLongformerSelfAttention,
          )

else:
     import sys

     lowerCAmelCase_					    = _LazyModule(__name__, globals()["""__file__"""], _import_structure, module_spec=__spec__)

