
"""simple docstring"""




import argparse
import json
from pathlib import Path

import requests
import timm
import torch
from huggingface_hub import hf_hub_download
from PIL import Image
from timm.data import resolve_data_config
from timm.data.transforms_factory import create_transform

from transformers import (
    BitConfig,
    ViTHybridConfig,
    ViTHybridForImageClassification,
    ViTHybridImageProcessor,
    ViTHybridModel,
)
from transformers.image_utils import PILImageResampling
from transformers.utils import logging


logging.set_verbosity_info()
A__   :					int							=   logging.get_logger(__name__)




def  _lowerCAmelCase		(		_UpperCamelCase ,				_UpperCamelCase=False						):






  """simple docstring"""



  _lowercase:			int       =     []

  # fmt: off
  # stem:
  rename_keys.append(('''cls_token''', '''vit.embeddings.cls_token''')						)
  rename_keys.append(('''pos_embed''', '''vit.embeddings.position_embeddings''')						)

  rename_keys.append(('''patch_embed.proj.weight''', '''vit.embeddings.patch_embeddings.projection.weight''')						)
  rename_keys.append(('''patch_embed.proj.bias''', '''vit.embeddings.patch_embeddings.projection.bias''')						)

  # backbone
  rename_keys.append(('''patch_embed.backbone.stem.conv.weight''', '''vit.embeddings.patch_embeddings.backbone.bit.embedder.convolution.weight''')						)
  rename_keys.append(('''patch_embed.backbone.stem.norm.weight''', '''vit.embeddings.patch_embeddings.backbone.bit.embedder.norm.weight''')						)
  rename_keys.append(('''patch_embed.backbone.stem.norm.bias''', '''vit.embeddings.patch_embeddings.backbone.bit.embedder.norm.bias''')						)

  for stage_idx in range(len(config.backbone_config.depths						)						):
    for layer_idx in range(config.backbone_config.depths[stage_idx]						):
      rename_keys.append((f'''patch_embed.backbone.stages.{stage_idx}.blocks.{layer_idx}.conv1.weight''', f'''vit.embeddings.patch_embeddings.backbone.bit.encoder.stages.{stage_idx}.layers.{layer_idx}.conv1.weight''')						)
      rename_keys.append((f'''patch_embed.backbone.stages.{stage_idx}.blocks.{layer_idx}.norm1.weight''', f'''vit.embeddings.patch_embeddings.backbone.bit.encoder.stages.{stage_idx}.layers.{layer_idx}.norm1.weight''')						)
      rename_keys.append((f'''patch_embed.backbone.stages.{stage_idx}.blocks.{layer_idx}.norm1.bias''', f'''vit.embeddings.patch_embeddings.backbone.bit.encoder.stages.{stage_idx}.layers.{layer_idx}.norm1.bias''')						)
      rename_keys.append((f'''patch_embed.backbone.stages.{stage_idx}.blocks.{layer_idx}.conv2.weight''', f'''vit.embeddings.patch_embeddings.backbone.bit.encoder.stages.{stage_idx}.layers.{layer_idx}.conv2.weight''')						)
      rename_keys.append((f'''patch_embed.backbone.stages.{stage_idx}.blocks.{layer_idx}.norm2.weight''', f'''vit.embeddings.patch_embeddings.backbone.bit.encoder.stages.{stage_idx}.layers.{layer_idx}.norm2.weight''')						)
      rename_keys.append((f'''patch_embed.backbone.stages.{stage_idx}.blocks.{layer_idx}.norm2.bias''', f'''vit.embeddings.patch_embeddings.backbone.bit.encoder.stages.{stage_idx}.layers.{layer_idx}.norm2.bias''')						)
      rename_keys.append((f'''patch_embed.backbone.stages.{stage_idx}.blocks.{layer_idx}.conv3.weight''', f'''vit.embeddings.patch_embeddings.backbone.bit.encoder.stages.{stage_idx}.layers.{layer_idx}.conv3.weight''')						)
      rename_keys.append((f'''patch_embed.backbone.stages.{stage_idx}.blocks.{layer_idx}.norm3.weight''', f'''vit.embeddings.patch_embeddings.backbone.bit.encoder.stages.{stage_idx}.layers.{layer_idx}.norm3.weight''')						)
      rename_keys.append((f'''patch_embed.backbone.stages.{stage_idx}.blocks.{layer_idx}.norm3.bias''', f'''vit.embeddings.patch_embeddings.backbone.bit.encoder.stages.{stage_idx}.layers.{layer_idx}.norm3.bias''')						)

    rename_keys.append((f'''patch_embed.backbone.stages.{stage_idx}.blocks.0.downsample.conv.weight''', f'''vit.embeddings.patch_embeddings.backbone.bit.encoder.stages.{stage_idx}.layers.0.downsample.conv.weight''')						)
    rename_keys.append((f'''patch_embed.backbone.stages.{stage_idx}.blocks.0.downsample.norm.weight''', f'''vit.embeddings.patch_embeddings.backbone.bit.encoder.stages.{stage_idx}.layers.0.downsample.norm.weight''')						)
    rename_keys.append((f'''patch_embed.backbone.stages.{stage_idx}.blocks.0.downsample.norm.bias''', f'''vit.embeddings.patch_embeddings.backbone.bit.encoder.stages.{stage_idx}.layers.0.downsample.norm.bias''')						)

  # transformer encoder
  for i in range(config.num_hidden_layers						):
    # encoder layers: output projection, 2 feedforward neural networks and 2 layernorms
    rename_keys.append((f'''blocks.{i}.norm1.weight''', f'''vit.encoder.layer.{i}.layernorm_before.weight''')						)
    rename_keys.append((f'''blocks.{i}.norm1.bias''', f'''vit.encoder.layer.{i}.layernorm_before.bias''')						)
    rename_keys.append((f'''blocks.{i}.attn.proj.weight''', f'''vit.encoder.layer.{i}.attention.output.dense.weight''')						)
    rename_keys.append((f'''blocks.{i}.attn.proj.bias''', f'''vit.encoder.layer.{i}.attention.output.dense.bias''')						)
    rename_keys.append((f'''blocks.{i}.norm2.weight''', f'''vit.encoder.layer.{i}.layernorm_after.weight''')						)
    rename_keys.append((f'''blocks.{i}.norm2.bias''', f'''vit.encoder.layer.{i}.layernorm_after.bias''')						)
    rename_keys.append((f'''blocks.{i}.mlp.fc1.weight''', f'''vit.encoder.layer.{i}.intermediate.dense.weight''')						)
    rename_keys.append((f'''blocks.{i}.mlp.fc1.bias''', f'''vit.encoder.layer.{i}.intermediate.dense.bias''')						)
    rename_keys.append((f'''blocks.{i}.mlp.fc2.weight''', f'''vit.encoder.layer.{i}.output.dense.weight''')						)
    rename_keys.append((f'''blocks.{i}.mlp.fc2.bias''', f'''vit.encoder.layer.{i}.output.dense.bias''')						)

  if base_model:
    # layernorm + pooler
    rename_keys.extend(
        [
            ('''norm.weight''', '''layernorm.weight'''),
            ('''norm.bias''', '''layernorm.bias'''),
            ('''pre_logits.fc.weight''', '''pooler.dense.weight'''),
            ('''pre_logits.fc.bias''', '''pooler.dense.bias'''),
        ]						)

    # if just the base model, we should remove "vit" from all keys that start with "vit"
    _lowercase:			Optional[int]       =     [(pair[0], pair[1][4:]) if pair[1].startswith('''vit'''						) else pair for pair in rename_keys]
  else:
    # layernorm + classification head
    rename_keys.extend(
        [
            ('''norm.weight''', '''vit.layernorm.weight'''),
            ('''norm.bias''', '''vit.layernorm.bias'''),
            ('''head.weight''', '''classifier.weight'''),
            ('''head.bias''', '''classifier.bias'''),
        ]						)
  # fmt: on

  return rename_keys




def  _lowerCAmelCase		(		_UpperCamelCase ,				_UpperCamelCase ,				_UpperCamelCase=False						):






  """simple docstring"""



  for i in range(config.num_hidden_layers						):
    if base_model:
      _lowercase:			List[Any]       =     ''''''
    else:
      _lowercase:			str       =     '''vit.'''
    # read in weights + bias of input projection layer (in timm, this is a single matrix + bias)
    _lowercase:			Tuple       =     state_dict.pop(f'''blocks.{i}.attn.qkv.weight'''						)
    _lowercase:			Tuple       =     state_dict.pop(f'''blocks.{i}.attn.qkv.bias'''						)
    # next, add query, keys and values (in that order) to the state dict
    _lowercase:			int       =     in_proj_weight[
        : config.hidden_size, :
    ]
    _lowercase:			Optional[int]       =     in_proj_bias[: config.hidden_size]
    _lowercase:			Optional[Any]       =     in_proj_weight[
        config.hidden_size : config.hidden_size * 2, :
    ]
    _lowercase:			Optional[int]       =     in_proj_bias[
        config.hidden_size : config.hidden_size * 2
    ]
    _lowercase:			str       =     in_proj_weight[
        -config.hidden_size :, :
    ]
    _lowercase:			int       =     in_proj_bias[-config.hidden_size :]




def  _lowerCAmelCase		(		_UpperCamelCase						):






  """simple docstring"""



  _lowercase:			int       =     ['''head.weight''', '''head.bias''']
  for k in ignore_keys:
    state_dict.pop(_UpperCamelCase ,				_UpperCamelCase						)




def  _lowerCAmelCase		(		_UpperCamelCase ,				_UpperCamelCase ,				_UpperCamelCase						):






  """simple docstring"""



  _lowercase:			Tuple       =     dct.pop(_UpperCamelCase						)
  _lowercase:			Any       =     val




def  _lowerCAmelCase		(		):






  """simple docstring"""



  _lowercase:			Any       =     '''http://images.cocodataset.org/val2017/000000039769.jpg'''
  _lowercase:			Optional[Any]       =     Image.open(requests.get(_UpperCamelCase ,				stream=_UpperCamelCase						).raw						)
  return im




@torch.no_grad()
def  _lowerCAmelCase		(		_UpperCamelCase ,				_UpperCamelCase ,				_UpperCamelCase=False						):






  """simple docstring"""



  _lowercase:			Tuple       =     BitConfig(
      global_padding='''same''' ,				layer_type='''bottleneck''' ,				depths=(3, 4, 9) ,				out_features=['''stage3'''] ,				embedding_dynamic_padding=_UpperCamelCase ,				)
  _lowercase:			Any       =     ViTHybridConfig(backbone_config=_UpperCamelCase ,				image_size=384 ,				num_labels=1_000						)
  _lowercase:			Tuple       =     False

  # load original model from timm
  _lowercase:			Optional[Any]       =     timm.create_model(_UpperCamelCase ,				pretrained=_UpperCamelCase						)
  timm_model.eval()

  # load state_dict of original model, remove and rename some keys
  _lowercase:			int       =     timm_model.state_dict()
  if base_model:
    remove_classification_head_(_UpperCamelCase						)
  _lowercase:			Any       =     create_rename_keys(_UpperCamelCase ,				_UpperCamelCase						)
  for src, dest in rename_keys:
    rename_key(_UpperCamelCase ,				_UpperCamelCase ,				_UpperCamelCase						)
  read_in_q_k_v(_UpperCamelCase ,				_UpperCamelCase ,				_UpperCamelCase						)

  _lowercase:			Tuple       =     '''huggingface/label-files'''
  _lowercase:			List[Any]       =     '''imagenet-1k-id2label.json'''
  _lowercase:			str       =     json.load(open(hf_hub_download(_UpperCamelCase ,				_UpperCamelCase ,				repo_type='''dataset'''						) ,				'''r'''						)						)
  _lowercase:			List[Any]       =     {int(_UpperCamelCase						): v for k, v in idalabel.items()}
  _lowercase:			Optional[int]       =     idalabel
  _lowercase:			Optional[int]       =     {v: k for k, v in idalabel.items()}

  # load HuggingFace model
  if vit_name[-5:] == "in21k":
    _lowercase:			Union[str, Any]       =     ViTHybridModel(_UpperCamelCase						).eval()
  else:
    _lowercase:			Optional[int]       =     ViTHybridForImageClassification(_UpperCamelCase						).eval()
  model.load_state_dict(_UpperCamelCase						)

  # create image processor
  _lowercase:			Any       =     create_transform(**resolve_data_config({} ,				model=_UpperCamelCase						)						)
  _lowercase:			List[Any]       =     transform.transforms

  _lowercase:			int       =     {
      '''bilinear''': PILImageResampling.BILINEAR,
      '''bicubic''': PILImageResampling.BICUBIC,
      '''nearest''': PILImageResampling.NEAREST,
  }

  _lowercase:			Any       =     ViTHybridImageProcessor(
      do_resize=_UpperCamelCase ,				size={'''shortest_edge''': timm_transforms[0].size} ,				resample=pillow_resamplings[timm_transforms[0].interpolation.value] ,				do_center_crop=_UpperCamelCase ,				crop_size={'''height''': timm_transforms[1].size[0], '''width''': timm_transforms[1].size[1]} ,				do_normalize=_UpperCamelCase ,				image_mean=timm_transforms[-1].mean.tolist() ,				image_std=timm_transforms[-1].std.tolist() ,				)

  _lowercase:			Optional[int]       =     prepare_img()
  _lowercase:			Optional[int]       =     transform(_UpperCamelCase						).unsqueeze(0						)
  _lowercase:			Dict       =     processor(_UpperCamelCase ,				return_tensors='''pt'''						).pixel_values

  # verify pixel values
  assert torch.allclose(_UpperCamelCase ,				_UpperCamelCase						)

  # verify logits
  with torch.no_grad():
    _lowercase:			Any       =     model(_UpperCamelCase						)
    _lowercase:			Union[str, Any]       =     outputs.logits

  print('''Predicted class:''' ,				logits.argmax(-1						).item()						)
  if base_model:
    _lowercase:			List[Any]       =     timm_model.forward_features(_UpperCamelCase						)
    assert timm_pooled_output.shape == outputs.pooler_output.shape
    assert torch.allclose(_UpperCamelCase ,				outputs.pooler_output ,				atol=1e-3						)
  else:
    _lowercase:			List[Any]       =     timm_model(_UpperCamelCase						)
    assert timm_logits.shape == outputs.logits.shape
    assert torch.allclose(_UpperCamelCase ,				outputs.logits ,				atol=1e-3						)
  print('''Looks ok!'''						)

  if pytorch_dump_folder_path is not None:
    Path(_UpperCamelCase						).mkdir(exist_ok=_UpperCamelCase						)
    print(f'''Saving model {vit_name} to {pytorch_dump_folder_path}'''						)
    model.save_pretrained(_UpperCamelCase						)
    print(f'''Saving processor to {pytorch_dump_folder_path}'''						)
    processor.save_pretrained(_UpperCamelCase						)

  if push_to_hub:
    print(f'''Pushing model and processor to the hub {vit_name}'''						)
    model.push_to_hub(f'''ybelkada/{vit_name}'''						)
    processor.push_to_hub(f'''ybelkada/{vit_name}'''						)


if __name__ == "__main__":
  A__   :					Optional[int]							=   argparse.ArgumentParser()
  # Required parameters
  parser.add_argument(
      '--vit_name',
      default='vit_base_r50_s16_384',
      type=str,
      help='Name of the hybrid ViT timm model you\'d like to convert.',
  )
  parser.add_argument(
      '--pytorch_dump_folder_path', default=None, type=str, help='Path to the output PyTorch model directory.'
  )
  parser.add_argument(
      '--push_to_hub', action='store_true', help='Whether to upload the model to the HuggingFace hub.'
  )

  A__   :					str							=   parser.parse_args()
  convert_vit_checkpoint(args.vit_name, args.pytorch_dump_folder_path, args.push_to_hub)


"""simple docstring"""




import os
import re
from shutil import copyfile
from typing import List, Optional, Tuple

from ...tokenization_utils import PreTrainedTokenizer
from ...utils import logging


A__   :					str							=   logging.get_logger(__name__)

A__   :					Tuple							=   {
    'vocab_file': 'vocab.txt',
    'merges_file': 'bpe.codes',
}

A__   :					List[Any]							=   {
    'vocab_file': {
        'vinai/phobert-base': 'https://huggingface.co/vinai/phobert-base/resolve/main/vocab.txt',
        'vinai/phobert-large': 'https://huggingface.co/vinai/phobert-large/resolve/main/vocab.txt',
    },
    'merges_file': {
        'vinai/phobert-base': 'https://huggingface.co/vinai/phobert-base/resolve/main/bpe.codes',
        'vinai/phobert-large': 'https://huggingface.co/vinai/phobert-large/resolve/main/bpe.codes',
    },
}

A__   :					Any							=   {
    'vinai/phobert-base': 2_5_6,
    'vinai/phobert-large': 2_5_6,
}




def  _lowerCAmelCase		(		_UpperCamelCase						):






  """simple docstring"""



  _lowercase:			Optional[int]       =     set()
  _lowercase:			Union[str, Any]       =     word[0]
  for char in word[1:]:
    pairs.add((prev_char, char)						)
    _lowercase:			Tuple       =     char

  _lowercase:			Optional[Any]       =     set(_UpperCamelCase						)
  return pairs







class 			__magic_name__       (       SCREAMING_SNAKE_CASE__ ):
       UpperCamelCase_   =		VOCAB_FILES_NAMES
       UpperCamelCase_   =		PRETRAINED_VOCAB_FILES_MAP
       UpperCamelCase_   =		PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES
       def __init__(     self ,				A_ ,				A_ ,				A_="<s>" ,				A_="</s>" ,				A_="</s>" ,				A_="<s>" ,				A_="<unk>" ,				A_="<pad>" ,				A_="<mask>" ,				**A_ ,				)     ->	Dict:





         """simple docstring"""




         super().__init__(
             bos_token=A_ ,				eos_token=A_ ,				unk_token=A_ ,				sep_token=A_ ,				cls_token=A_ ,				pad_token=A_ ,				mask_token=A_ ,				**A_ ,				)

         _lowercase:			List[Any]       =     vocab_file
         _lowercase:			Union[str, Any]       =     merges_file

         _lowercase:			int       =     {}
         _lowercase:			Optional[int]       =     0
         _lowercase:			Optional[Any]       =     1
         _lowercase:			List[str]       =     2
         _lowercase:			List[Any]       =     3

         self.add_from_file(A_       )

         _lowercase:			Tuple       =     {v: k for k, v in self.encoder.items()}

         with open(A_ ,				encoding='''utf-8'''       ) as merges_handle:
           _lowercase:			int       =     merges_handle.read().split('''\n'''       )[:-1]
         _lowercase:			Optional[int]       =     [tuple(merge.split()[:-1]       ) for merge in merges]
         _lowercase:			List[str]       =     dict(zip(A_ ,				range(len(A_       )       )       )       )
         _lowercase:			Union[str, Any]       =     {}
       def 							lowercase_							(     self ,				A_ ,				A_ = None       )     ->	List[int]:





         """simple docstring"""




         if token_ids_a is None:
           return [self.cls_token_id] + token_ids_a + [self.sep_token_id]
         _lowercase:			Optional[Any]       =     [self.cls_token_id]
         _lowercase:			Tuple       =     [self.sep_token_id]
         return cls + token_ids_a + sep + sep + token_ids_a + sep
       def 							lowercase_							(     self ,				A_ ,				A_ = None ,				A_ = False       )     ->	List[int]:





         """simple docstring"""




         if already_has_special_tokens:
           return super().get_special_tokens_mask(
               token_ids_a=A_ ,				token_ids_a=A_ ,				already_has_special_tokens=A_       )

         if token_ids_a is None:
           return [1] + ([0] * len(A_       )) + [1]
         return [1] + ([0] * len(A_       )) + [1, 1] + ([0] * len(A_       )) + [1]
       def 							lowercase_							(     self ,				A_ ,				A_ = None       )     ->	List[int]:





         """simple docstring"""




         _lowercase:			Tuple       =     [self.sep_token_id]
         _lowercase:			List[Any]       =     [self.cls_token_id]

         if token_ids_a is None:
           return len(cls + token_ids_a + sep       ) * [0]
         return len(cls + token_ids_a + sep + sep + token_ids_a + sep       ) * [0]
       @property
       def 							lowercase_							(     self       )     ->	int:





         """simple docstring"""




         return len(self.encoder       )
       def 							lowercase_							(     self       )     ->	int:





         """simple docstring"""




         return dict(self.encoder ,				**self.added_tokens_encoder       )
       def 							lowercase_							(     self ,				A_       )     ->	Optional[Any]:





         """simple docstring"""




         if token in self.cache:
           return self.cache[token]
         _lowercase:			List[Any]       =     tuple(A_       )
         _lowercase:			Tuple       =     tuple(list(word[:-1]       ) + [word[-1] + '''</w>''']       )
         _lowercase:			List[Any]       =     get_pairs(A_       )

         if not pairs:
           return token

         while True:
           _lowercase:			List[str]       =     min(A_ ,				key=lambda A_       : self.bpe_ranks.get(A_ ,				float('''inf'''       )       )       )
           if bigram not in self.bpe_ranks:
             break
           _lowercase ,				_lowercase:			Optional[int]       =     bigram
           _lowercase:			Tuple       =     []
           _lowercase:			List[str]       =     0
           while i < len(A_       ):
             try:
               _lowercase:			Tuple       =     word.index(A_ ,				A_       )
             except ValueError:
               new_word.extend(word[i:]       )
               break
             else:
               new_word.extend(word[i:j]       )
               _lowercase:			List[Any]       =     j

             if word[i] == first and i < len(A_       ) - 1 and word[i + 1] == second:
               new_word.append(first + second       )
               i += 2
             else:
               new_word.append(word[i]       )
               i += 1
           _lowercase:			Union[str, Any]       =     tuple(A_       )
           _lowercase:			int       =     new_word
           if len(A_       ) == 1:
             break
           else:
             _lowercase:			List[Any]       =     get_pairs(A_       )
         _lowercase:			Tuple       =     '''@@ '''.join(A_       )
         _lowercase:			Dict       =     word[:-4]
         _lowercase:			Tuple       =     word
         return word
       def 							lowercase_							(     self ,				A_       )     ->	List[Any]:





         """simple docstring"""




         _lowercase:			Dict       =     []

         _lowercase:			str       =     re.findall(R'''\S+\n?''' ,				A_       )

         for token in words:
           split_tokens.extend(list(self.bpe(A_       ).split(''' '''       )       )       )
         return split_tokens
       def 							lowercase_							(     self ,				A_       )     ->	List[str]:





         """simple docstring"""




         return self.encoder.get(A_ ,				self.encoder.get(self.unk_token       )       )
       def 							lowercase_							(     self ,				A_       )     ->	Tuple:





         """simple docstring"""




         return self.decoder.get(A_ ,				self.unk_token       )
       def 							lowercase_							(     self ,				A_       )     ->	Union[str, Any]:





         """simple docstring"""




         _lowercase:			Union[str, Any]       =     ''' '''.join(A_       ).replace('''@@ ''' ,				''''''       ).strip()
         return out_string
       def 							lowercase_							(     self ,				A_ ,				A_ = None       )     ->	Tuple[str]:





         """simple docstring"""




         if not os.path.isdir(A_       ):
           logger.error(f'''Vocabulary path ({save_directory}) should be a directory'''       )
           return
         _lowercase:			List[Any]       =     os.path.join(
             A_ ,				(filename_prefix + '''-''' if filename_prefix else '''''') + VOCAB_FILES_NAMES['''vocab_file''']       )
         _lowercase:			str       =     os.path.join(
             A_ ,				(filename_prefix + '''-''' if filename_prefix else '''''') + VOCAB_FILES_NAMES['''merges_file''']       )

         if os.path.abspath(self.vocab_file       ) != os.path.abspath(A_       ):
           copyfile(self.vocab_file ,				A_       )

         if os.path.abspath(self.merges_file       ) != os.path.abspath(A_       ):
           copyfile(self.merges_file ,				A_       )

         return out_vocab_file, out_merge_file



       def 							lowercase_							(     self ,				A_       )     ->	str:





         """simple docstring"""




         if isinstance(A_ ,				A_       ):
           try:
             with open(A_ ,				'''r''' ,				encoding='''utf-8'''       ) as fd:
               self.add_from_file(A_       )
           except FileNotFoundError as fnfe:
             raise fnfe
           except UnicodeError:
             raise Exception(f'''Incorrect encoding detected in {f}, please rebuild the dataset'''       )
           return

         _lowercase:			Dict       =     f.readlines()
         for lineTmp in lines:
           _lowercase:			List[Any]       =     lineTmp.strip()
           _lowercase:			Optional[Any]       =     line.rfind(''' '''       )
           if idx == -1:
             raise ValueError('''Incorrect dictionary format, expected \'<token> <cnt>\''''       )
           _lowercase:			List[str]       =     line[:idx]
           _lowercase:			List[str]       =     len(self.encoder       )
