




'''simple docstring'''


import json
import os
from functools import lru_cache
from typing import List, Optional, Tuple

import regex as re

from ...tokenization_utils import AddedToken, PreTrainedTokenizer
from ...utils import logging


UpperCamelCase			     =					logging.get_logger(__name__)

UpperCamelCase			     =					{
    '''vocab_file''': '''vocab.json''',
    '''merges_file''': '''merges.txt''',
}

UpperCamelCase			     =					{
    '''vocab_file''': {
        '''roberta-base''': '''https://huggingface.co/roberta-base/resolve/main/vocab.json''',
        '''roberta-large''': '''https://huggingface.co/roberta-large/resolve/main/vocab.json''',
        '''roberta-large-mnli''': '''https://huggingface.co/roberta-large-mnli/resolve/main/vocab.json''',
        '''distilroberta-base''': '''https://huggingface.co/distilroberta-base/resolve/main/vocab.json''',
        '''roberta-base-openai-detector''': '''https://huggingface.co/roberta-base-openai-detector/resolve/main/vocab.json''',
        '''roberta-large-openai-detector''': (
            '''https://huggingface.co/roberta-large-openai-detector/resolve/main/vocab.json'''
        ),
    },
    '''merges_file''': {
        '''roberta-base''': '''https://huggingface.co/roberta-base/resolve/main/merges.txt''',
        '''roberta-large''': '''https://huggingface.co/roberta-large/resolve/main/merges.txt''',
        '''roberta-large-mnli''': '''https://huggingface.co/roberta-large-mnli/resolve/main/merges.txt''',
        '''distilroberta-base''': '''https://huggingface.co/distilroberta-base/resolve/main/merges.txt''',
        '''roberta-base-openai-detector''': '''https://huggingface.co/roberta-base-openai-detector/resolve/main/merges.txt''',
        '''roberta-large-openai-detector''': (
            '''https://huggingface.co/roberta-large-openai-detector/resolve/main/merges.txt'''
        ),
    },
}

UpperCamelCase			     =					{
    '''roberta-base''': 512,
    '''roberta-large''': 512,
    '''roberta-large-mnli''': 512,
    '''distilroberta-base''': 512,
    '''roberta-base-openai-detector''': 512,
    '''roberta-large-openai-detector''': 512,
}
@lru_cache()
def 					SCREAMING_SNAKE_CASE(   )			-> List[Any]:
     A:		Dict          =		(
         list(range(ord('''!'''	)		,				ord('''~'''	) + 1	)	) + list(range(ord('''¡'''	)		,				ord('''¬'''	) + 1	)	) + list(range(ord('''®'''	)		,				ord('''ÿ'''	) + 1	)	)
     )
     A:		Optional[int]          =		bs[:]
     A:		Union[str, Any]          =		0
     for b in range(2**8	):
          if b not in bs:
               bs.append(__lowercase	)
               cs.append(2**8 + n	)
               n += 1
     A:		List[Any]          =		[chr(__lowercase	) for n in cs]
     return dict(zip(__lowercase		,				__lowercase	)	)
def 					SCREAMING_SNAKE_CASE(   __lowercase	)			-> Tuple:
     A:		Any          =		set()
     A:		Optional[Any]          =		word[0]
     for char in word[1:]:
          pairs.add((prev_char, char)	)
          A:		List[Any]          =		char
     return pairs






class 						lowerCAmelCase_	(       UpperCAmelCase_							):







  '''simple docstring'''

  UpperCamelCase_			:      int										=				VOCAB_FILES_NAMES
  UpperCamelCase_			:      Union[str, Any]										=				PRETRAINED_VOCAB_FILES_MAP
  UpperCamelCase_			:      List[Any]										=				PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES
  UpperCamelCase_			:      str										=				["""input_ids""", """attention_mask"""]



  def __init__( self				:							Dict					,  SCREAMING_SNAKE_CASE_				:							Union[str, Any]					,  SCREAMING_SNAKE_CASE_				:							Dict					,  SCREAMING_SNAKE_CASE_				:							Optional[int]="replace"					,  SCREAMING_SNAKE_CASE_				:							str="<s>"					,  SCREAMING_SNAKE_CASE_				:							List[str]="</s>"					,  SCREAMING_SNAKE_CASE_				:							Any="</s>"					,  SCREAMING_SNAKE_CASE_				:							Tuple="<s>"					,  SCREAMING_SNAKE_CASE_				:							Any="<unk>"					,  SCREAMING_SNAKE_CASE_				:							str="<pad>"					,  SCREAMING_SNAKE_CASE_				:							Optional[Any]="<mask>"					,  SCREAMING_SNAKE_CASE_				:							str=False					,  **SCREAMING_SNAKE_CASE_				:							Optional[Any]					,  )			->		str:







       '''simple docstring'''



       A:		List[Any]          =		AddedToken(SCREAMING_SNAKE_CASE_					,  lstrip=SCREAMING_SNAKE_CASE_					,  rstrip=SCREAMING_SNAKE_CASE_	) if isinstance(SCREAMING_SNAKE_CASE_					,  SCREAMING_SNAKE_CASE_	) else bos_token
       A:		str          =		AddedToken(SCREAMING_SNAKE_CASE_					,  lstrip=SCREAMING_SNAKE_CASE_					,  rstrip=SCREAMING_SNAKE_CASE_	) if isinstance(SCREAMING_SNAKE_CASE_					,  SCREAMING_SNAKE_CASE_	) else eos_token
       A:		List[str]          =		AddedToken(SCREAMING_SNAKE_CASE_					,  lstrip=SCREAMING_SNAKE_CASE_					,  rstrip=SCREAMING_SNAKE_CASE_	) if isinstance(SCREAMING_SNAKE_CASE_					,  SCREAMING_SNAKE_CASE_	) else sep_token
       A:		List[Any]          =		AddedToken(SCREAMING_SNAKE_CASE_					,  lstrip=SCREAMING_SNAKE_CASE_					,  rstrip=SCREAMING_SNAKE_CASE_	) if isinstance(SCREAMING_SNAKE_CASE_					,  SCREAMING_SNAKE_CASE_	) else cls_token
       A:		List[Any]          =		AddedToken(SCREAMING_SNAKE_CASE_					,  lstrip=SCREAMING_SNAKE_CASE_					,  rstrip=SCREAMING_SNAKE_CASE_	) if isinstance(SCREAMING_SNAKE_CASE_					,  SCREAMING_SNAKE_CASE_	) else unk_token
       A:		Union[str, Any]          =		AddedToken(SCREAMING_SNAKE_CASE_					,  lstrip=SCREAMING_SNAKE_CASE_					,  rstrip=SCREAMING_SNAKE_CASE_	) if isinstance(SCREAMING_SNAKE_CASE_					,  SCREAMING_SNAKE_CASE_	) else pad_token

       # Mask token behave like a normal word, i.e. include the space before it
       A:		int          =		AddedToken(SCREAMING_SNAKE_CASE_					,  lstrip=SCREAMING_SNAKE_CASE_					,  rstrip=SCREAMING_SNAKE_CASE_	) if isinstance(SCREAMING_SNAKE_CASE_					,  SCREAMING_SNAKE_CASE_	) else mask_token

       super().__init__(
           errors=SCREAMING_SNAKE_CASE_					,  bos_token=SCREAMING_SNAKE_CASE_					,  eos_token=SCREAMING_SNAKE_CASE_					,  unk_token=SCREAMING_SNAKE_CASE_					,  sep_token=SCREAMING_SNAKE_CASE_					,  cls_token=SCREAMING_SNAKE_CASE_					,  pad_token=SCREAMING_SNAKE_CASE_					,  mask_token=SCREAMING_SNAKE_CASE_					,  add_prefix_space=SCREAMING_SNAKE_CASE_					,  **SCREAMING_SNAKE_CASE_					,  )

       with open(SCREAMING_SNAKE_CASE_					,  encoding='''utf-8'''	) as vocab_handle:
            A:		Any          =		json.load(SCREAMING_SNAKE_CASE_	)
       A:		Optional[Any]          =		{v: k for k, v in self.encoder.items()}
       A:		Union[str, Any]          =		errors  # how to handle errors in decoding
       A:		Optional[Any]          =		bytes_to_unicode()
       A:		Optional[int]          =		{v: k for k, v in self.byte_encoder.items()}
       with open(SCREAMING_SNAKE_CASE_					,  encoding='''utf-8'''	) as merges_handle:
            A:		List[Any]          =		merges_handle.read().split('''\n'''	)[1:-1]
       A:		Optional[Any]          =		[tuple(merge.split()	) for merge in bpe_merges]
       A:		List[str]          =		dict(zip(SCREAMING_SNAKE_CASE_					,  range(len(SCREAMING_SNAKE_CASE_	)	)	)	)
       A:		Dict          =		{}
       A:		Optional[Any]          =		add_prefix_space

       # Should have added re.IGNORECASE so BPE merges can happen for capitalized versions of contractions
       A:		Union[str, Any]          =		re.compile(R'''\'s|\'t|\'re|\'ve|\'m|\'ll|\'d| ?\p{L}+| ?\p{N}+| ?[^\s\p{L}\p{N}]+|\s+(?!\S)|\s+'''	)



  @property
  def 					_snake_case     ( self				:							List[str]	)			->		Optional[Any]:







       '''simple docstring'''



       return len(self.encoder	)



  def 					_snake_case     ( self				:							Tuple	)			->		List[str]:







       '''simple docstring'''



       return dict(self.encoder					,  **self.added_tokens_encoder	)



  def 					_snake_case     ( self				:							Optional[int]					,  SCREAMING_SNAKE_CASE_				:							Tuple	)			->		List[Any]:







       '''simple docstring'''



       if token in self.cache:
            return self.cache[token]
       A:		Optional[Any]          =		tuple(SCREAMING_SNAKE_CASE_	)
       A:		List[str]          =		get_pairs(SCREAMING_SNAKE_CASE_	)

       if not pairs:
            return token

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

                 if word[i] == first and i < len(SCREAMING_SNAKE_CASE_	) - 1 and word[i + 1] == second:
                      new_word.append(first + second	)
                      i += 2
                 else:
                      new_word.append(word[i]	)
                      i += 1
            A:		List[str]          =		tuple(SCREAMING_SNAKE_CASE_	)
            A:		int          =		new_word
            if len(SCREAMING_SNAKE_CASE_	) == 1:
                 break
            else:
                 A:		Any          =		get_pairs(SCREAMING_SNAKE_CASE_	)
       A:		Union[str, Any]          =		''' '''.join(SCREAMING_SNAKE_CASE_	)
       A:		Optional[int]          =		word
       return word



  def 					_snake_case     ( self				:							int					,  SCREAMING_SNAKE_CASE_				:							Optional[int]	)			->		List[Any]:







       '''simple docstring'''



       A:		List[str]          =		[]
       for token in re.findall(self.pat					,  SCREAMING_SNAKE_CASE_	):
            A:		Any          =		''''''.join(
                self.byte_encoder[b] for b in token.encode('''utf-8'''	)	)  # Maps all our bytes to unicode strings, avoiding control tokens of the BPE (spaces in our case)
            bpe_tokens.extend(bpe_token for bpe_token in self.bpe(SCREAMING_SNAKE_CASE_	).split(''' '''	)	)
       return bpe_tokens



  def 					_snake_case     ( self				:							Union[str, Any]					,  SCREAMING_SNAKE_CASE_				:							Any	)			->		str:







       '''simple docstring'''



       return self.encoder.get(SCREAMING_SNAKE_CASE_					,  self.encoder.get(self.unk_token	)	)



  def 					_snake_case     ( self				:							Tuple					,  SCREAMING_SNAKE_CASE_				:							Dict	)			->		Tuple:







       '''simple docstring'''



       return self.decoder.get(SCREAMING_SNAKE_CASE_	)



  def 					_snake_case     ( self				:							Any					,  SCREAMING_SNAKE_CASE_				:							Any	)			->		Optional[Any]:







       '''simple docstring'''



       A:		Tuple          =		''''''.join(SCREAMING_SNAKE_CASE_	)
       A:		Dict          =		bytearray([self.byte_decoder[c] for c in text]	).decode('''utf-8'''					,  errors=self.errors	)
       return text



  def 					_snake_case     ( self				:							Tuple					,  SCREAMING_SNAKE_CASE_				:							str					,  SCREAMING_SNAKE_CASE_				:							Optional[str] = None	)			->		Tuple[str]:







       '''simple docstring'''



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

       with open(SCREAMING_SNAKE_CASE_					,  '''w'''					,  encoding='''utf-8'''	) as f:
            f.write(json.dumps(self.encoder					,  indent=2					,  sort_keys=SCREAMING_SNAKE_CASE_					,  ensure_ascii=SCREAMING_SNAKE_CASE_	) + '''\n'''	)

       A:		List[Any]          =		0
       with open(SCREAMING_SNAKE_CASE_					,  '''w'''					,  encoding='''utf-8'''	) as writer:
            writer.write('''#version: 0.2\n'''	)
            for bpe_tokens, token_index in sorted(self.bpe_ranks.items()					,  key=lambda SCREAMING_SNAKE_CASE_	: kv[1]	):
                 if index != token_index:
                      logger.warning(
                          f"""Saving vocabulary to {merge_file}: BPE merge indices are not consecutive."""
                          ''' Please check that the tokenizer is not corrupted!'''	)
                      A:		Union[str, Any]          =		token_index
                 writer.write(''' '''.join(SCREAMING_SNAKE_CASE_	) + '''\n'''	)
                 index += 1

       return vocab_file, merge_file



  def 					_snake_case     ( self				:							Dict					,  SCREAMING_SNAKE_CASE_				:							List[int]					,  SCREAMING_SNAKE_CASE_				:							Optional[List[int]] = None	)			->		List[int]:







       '''simple docstring'''



       if token_ids_a is None:
            return [self.cls_token_id] + token_ids_a + [self.sep_token_id]
       A:		Union[str, Any]          =		[self.cls_token_id]
       A:		str          =		[self.sep_token_id]
       return cls + token_ids_a + sep + sep + token_ids_a + sep



  def 					_snake_case     ( self				:							Tuple					,  SCREAMING_SNAKE_CASE_				:							List[int]					,  SCREAMING_SNAKE_CASE_				:							Optional[List[int]] = None					,  SCREAMING_SNAKE_CASE_				:							bool = False	)			->		List[int]:







       '''simple docstring'''



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

       if token_ids_a is None:
            return [1] + ([0] * len(SCREAMING_SNAKE_CASE_	)) + [1]
       return [1] + ([0] * len(SCREAMING_SNAKE_CASE_	)) + [1, 1] + ([0] * len(SCREAMING_SNAKE_CASE_	)) + [1]



  def 					_snake_case     ( self				:							Union[str, Any]					,  SCREAMING_SNAKE_CASE_				:							List[int]					,  SCREAMING_SNAKE_CASE_				:							Optional[List[int]] = None	)			->		List[int]:







       '''simple docstring'''



       A:		Tuple          =		[self.sep_token_id]
       A:		Dict          =		[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]




  def 					_snake_case     ( self				:							Optional[int]					,  SCREAMING_SNAKE_CASE_				:							List[Any]					,  SCREAMING_SNAKE_CASE_				:							List[Any]=False					,  **SCREAMING_SNAKE_CASE_				:							Tuple	)			->		str:







       '''simple docstring'''



       A:		Optional[Any]          =		kwargs.pop('''add_prefix_space'''					,  self.add_prefix_space	)
       if (is_split_into_words or add_prefix_space) and (len(SCREAMING_SNAKE_CASE_	) > 0 and not text[0].isspace()):
            A:		Any          =		''' ''' + text
       return (text, kwargs)












'''simple docstring'''


from __future__ import annotations

from collections.abc import Callable
from typing import Generic, TypeVar

UpperCamelCase			     =					TypeVar('''T''')
UpperCamelCase			     =					TypeVar('''U''')






class 						lowerCAmelCase_	(       Generic[T, U]							):







  '''simple docstring'''

  def __init__( self				:							Tuple					,  SCREAMING_SNAKE_CASE_				:							T | None					,  SCREAMING_SNAKE_CASE_				:							U | None	)			->		Any:







       '''simple docstring'''



       A:		Union[str, Any]          =		key
       A:		Union[str, Any]          =		val
       A:		int          =		0
       A:		DoubleLinkedListNode[T, U] | None          =		None
       A:		DoubleLinkedListNode[T, U] | None          =		None




  def __repr__( self				:							Any	)			->		str:







       '''simple docstring'''



       return "Node: key: {}, val: {}, freq: {}, has next: {}, has prev: {}".format(
           self.key					,  self.val					,  self.freq					,  self.next is not None					,  self.prev is not None	)






class 						lowerCAmelCase_	(       Generic[T, U]							):







  '''simple docstring'''

  def __init__( self				:							int	)			->		None:







       '''simple docstring'''



       A:		DoubleLinkedListNode[T, U]          =		DoubleLinkedListNode(SCREAMING_SNAKE_CASE_					,  SCREAMING_SNAKE_CASE_	)
       A:		DoubleLinkedListNode[T, U]          =		DoubleLinkedListNode(SCREAMING_SNAKE_CASE_					,  SCREAMING_SNAKE_CASE_	)
       A     ,    A:		Any          =		self.rear, self.head



  def __repr__( self				:							Optional[int]	)			->		str:







       '''simple docstring'''



       A:		int          =		['''DoubleLinkedList''']
       A:		Dict          =		self.head
       while node.next is not None:
            rep.append(str(SCREAMING_SNAKE_CASE_	)	)
            A:		int          =		node.next
       rep.append(str(self.rear	)	)
       return ",\n    ".join(SCREAMING_SNAKE_CASE_	)



  def 					_snake_case     ( self				:							Any					,  SCREAMING_SNAKE_CASE_				:							DoubleLinkedListNode[T, U]	)			->		None:







       '''simple docstring'''



       A:		Union[str, Any]          =		self.rear.prev

       # All nodes other than self.head are guaranteed to have non-None previous
       assert previous is not None

       A:		Optional[int]          =		node
       A:		int          =		previous
       A:		Dict          =		node
       A:		int          =		self.rear
       node.freq += 1
       self._position_node(SCREAMING_SNAKE_CASE_	)



  def 					_snake_case     ( self				:							int					,  SCREAMING_SNAKE_CASE_				:							DoubleLinkedListNode[T, U]	)			->		None:







       '''simple docstring'''



       while node.prev is not None and node.prev.freq > node.freq:
            # swap node with previous node
            A:		Any          =		node.prev

            A:		Optional[Any]          =		previous_node.prev
            A:		int          =		node.prev
            A:		int          =		previous_node
            A:		Optional[int]          =		node




  def 					_snake_case     ( self				:							Dict					,  SCREAMING_SNAKE_CASE_				:							DoubleLinkedListNode[T, U]	)			->		DoubleLinkedListNode[T, U] | None:







       '''simple docstring'''



       if node.prev is None or node.next is None:
            return None

       A:		List[Any]          =		node.next
       A:		Dict          =		node.prev
       A:		str          =		None
       A:		Union[str, Any]          =		None
       return node






class 						lowerCAmelCase_	(       Generic[T, U]							):







  '''simple docstring'''

  UpperCamelCase_			:      dict[Callable[[T], U], LFUCache[T, U]]										=				{}



  def __init__( self				:							List[str]					,  SCREAMING_SNAKE_CASE_				:							int	)			->		int:







       '''simple docstring'''



       A:		DoubleLinkedList[T, U]          =		DoubleLinkedList()
       A:		Any          =		capacity
       A:		List[Any]          =		0
       A:		Dict          =		0
       A:		Dict          =		0
       A:		dict[T, DoubleLinkedListNode[T, U]]          =		{}



  def __repr__( self				:							Optional[int]	)			->		str:







       '''simple docstring'''



       return (
           f"""CacheInfo(hits={self.hits}, misses={self.miss}, """
           f"""capacity={self.capacity}, current_size={self.num_keys})"""
       )



  def __contains__( self				:							str					,  SCREAMING_SNAKE_CASE_				:							T	)			->		bool:







       '''simple docstring'''



       return key in self.cache



  def 					_snake_case     ( self				:							Dict					,  SCREAMING_SNAKE_CASE_				:							T	)			->		U | None:







       '''simple docstring'''



       if key in self.cache:
            self.hits += 1
            A:		DoubleLinkedListNode[T, U]          =		self.cache[key]
            A:		List[str]          =		self.list.remove(self.cache[key]	)
            assert node == value_node

            # node is guaranteed not None because it is in self.cache
            assert node is not None
            self.list.add(SCREAMING_SNAKE_CASE_	)
            return node.val
       self.miss += 1
       return None



  def 					_snake_case     ( self				:							List[str]					,  SCREAMING_SNAKE_CASE_				:							T					,  SCREAMING_SNAKE_CASE_				:							U	)			->		None:







       '''simple docstring'''



       if key not in self.cache:
            if self.num_keys >= self.capacity:
                 # delete first node when over capacity
                 A:		List[Any]          =		self.list.head.next

                 # guaranteed to have a non-None first node when num_keys > 0
                 # explain to type checker via assertions
                 assert first_node is not None
                 assert first_node.key is not None
                 assert self.list.remove(SCREAMING_SNAKE_CASE_	) is not None
                 # first_node guaranteed to be in list

                 del self.cache[first_node.key]
                 self.num_keys -= 1
            A:		Tuple          =		DoubleLinkedListNode(SCREAMING_SNAKE_CASE_					,  SCREAMING_SNAKE_CASE_	)
            self.list.add(self.cache[key]	)
            self.num_keys += 1

       else:
            A:		Optional[Any]          =		self.list.remove(self.cache[key]	)
            assert node is not None  # node guaranteed to be in list
            A:		List[str]          =		value
            self.list.add(SCREAMING_SNAKE_CASE_	)




  @classmethod
  def 					_snake_case     ( cls				:							type[LFUCache[T, U]]					,  SCREAMING_SNAKE_CASE_				:							int = 1_28	)			->		Callable[[Callable[[T], U]], Callable[..., U]]:







       '''simple docstring'''



       def cache_decorator_inner(SCREAMING_SNAKE_CASE_				:							Callable[[T], U]	) -> Callable[..., U]:
            def cache_decorator_wrapper(*SCREAMING_SNAKE_CASE_				:							T	) -> U:
                 if func not in cls.decorator_function_to_instance_map:
                      A:		Tuple          =		LFUCache(SCREAMING_SNAKE_CASE_	)

                 A:		List[Any]          =		cls.decorator_function_to_instance_map[func].get(args[0]	)
                 if result is None:
                      A:		List[str]          =		func(*SCREAMING_SNAKE_CASE_	)
                      cls.decorator_function_to_instance_map[func].put(args[0]					,  SCREAMING_SNAKE_CASE_	)
                 return result

            def cache_info() -> LFUCache[T, U]:
                 return cls.decorator_function_to_instance_map[func]

            setattr(SCREAMING_SNAKE_CASE_					,  '''cache_info'''					,  SCREAMING_SNAKE_CASE_	)  # noqa: B010

            return cache_decorator_wrapper

       return cache_decorator_inner


if __name__ == "__main__":
     import doctest

     doctest.testmod()






