


from __future__ import annotations

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

lowerCamelCase			:					int         =	TypeVar('''T''')
lowerCamelCase			:					Dict         =	TypeVar('''U''')



class 							_UpperCamelCase			(Generic[T, U]			):


      def __init__(	self					,						__UpperCamelCase					,						__UpperCamelCase	)->	List[Any]:
           __lowerCAmelCase								=					key
           __lowerCAmelCase								=					val
           __lowerCAmelCase								=					None
           __lowerCAmelCase								=					None


      def __repr__(	self	)->	Tuple:
           return (
               F"""Node: key: {self.key}, val: {self.val}, """
               F"""has next: {bool(self.next	)}, has prev: {bool(self.prev	)}"""
           )



class 							_UpperCamelCase			(Generic[T, U]			):


      def __init__(	self	)->	Tuple:
           __lowerCAmelCase								=					DoubleLinkedListNode(_lowerCamelCase					,						_lowerCamelCase	)
           __lowerCAmelCase								=					DoubleLinkedListNode(_lowerCamelCase					,						_lowerCamelCase	)
           __lowerCAmelCase			, __lowerCAmelCase								=					self.rear, self.head


      def __repr__(	self	)->	Any:
           __lowerCAmelCase								=					["DoubleLinkedList"]
           __lowerCAmelCase								=					self.head
           while node.next is not None:
                rep.append(str(_lowerCamelCase	)	)
                __lowerCAmelCase								=					node.next
           rep.append(str(self.rear	)	)
           return ",\n    ".join(_lowerCamelCase	)


      def  __UpperCAmelCase		(	self					,						__UpperCamelCase	)->	Optional[int]:
           __lowerCAmelCase								=					self.rear.prev

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

           __lowerCAmelCase								=					node
           __lowerCAmelCase								=					previous
           __lowerCAmelCase								=					node
           __lowerCAmelCase								=					self.rear


      def  __UpperCAmelCase		(	self					,						__UpperCamelCase	)->	int:

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

           __lowerCAmelCase								=					node.next
           __lowerCAmelCase								=					node.prev
           __lowerCAmelCase								=					None
           __lowerCAmelCase								=					None
           return node



class 							_UpperCamelCase			(Generic[T, U]			):
      snake_case_  =							{}


      def __init__(	self					,						__UpperCamelCase	)->	Dict:
           __lowerCAmelCase								=					DoubleLinkedList()
           __lowerCAmelCase								=					capacity
           __lowerCAmelCase								=					0
           __lowerCAmelCase								=					0
           __lowerCAmelCase								=					0
           __lowerCAmelCase								=					{}


      def __repr__(	self	)->	str:
           return (
               F"""CacheInfo(hits={self.hits}, misses={self.miss}, """
               F"""capacity={self.capacity}, current size={self.num_keys})"""
           )


      def __contains__(	self					,						__UpperCamelCase	)->	List[Any]:
           return key in self.cache


      def  __UpperCAmelCase		(	self					,						__UpperCamelCase	)->	str:
           # Note: pythonic interface would throw KeyError rather than return None

           if key in self.cache:
                self.hits += 1
                __lowerCAmelCase								=					self.cache[key]
                __lowerCAmelCase								=					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(_lowerCamelCase	)
                return node.val
           self.miss += 1
           return None


      def  __UpperCAmelCase		(	self					,						__UpperCamelCase					,						__UpperCamelCase	)->	Tuple:

           if key not in self.cache:
                if self.num_keys >= self.capacity:
                     # delete first node (oldest) when over capacity
                     __lowerCAmelCase								=					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(_lowerCamelCase	) is not None
                     )  # node guaranteed to be in list assert node.key is not None

                     del self.cache[first_node.key]
                     self.num_keys -= 1
                __lowerCAmelCase								=					DoubleLinkedListNode(_lowerCamelCase					,						_lowerCamelCase	)
                self.list.add(self.cache[key]	)
                self.num_keys += 1

           else:
                # bump node to the end of the list, update value
                __lowerCAmelCase								=					self.list.remove(self.cache[key]	)
                assert node is not None  # node guaranteed to be in list
                __lowerCAmelCase								=					value
                self.list.add(_lowerCamelCase	)


      @classmethod
      def  __UpperCAmelCase		(	cls					,						__UpperCamelCase = 1_2_8	)->	List[Any]:

           def cache_decorator_inner(__UpperCamelCase	) -> Callable[..., U]:
                def cache_decorator_wrapper(*__UpperCamelCase	) -> U:
                     if func not in cls.decorator_function_to_instance_map:
                          __lowerCAmelCase								=					LRUCache(_lowerCamelCase	)

                     __lowerCAmelCase								=					cls.decorator_function_to_instance_map[func].get(args[0]	)
                     if result is None:
                          __lowerCAmelCase								=					func(*_lowerCamelCase	)
                          cls.decorator_function_to_instance_map[func].put(args[0]					,						_lowerCamelCase	)
                     return result

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

                setattr(_lowerCamelCase					,						"cache_info"					,						_lowerCamelCase	)  # noqa: B010

                return cache_decorator_wrapper

           return cache_decorator_inner


if __name__ == "__main__":
 import doctest

 doctest.testmod()














lowerCamelCase			:					str         =	'''
# Transformers 설치 방법
! pip install transformers datasets
# 마지막 릴리스 대신 소스에서 설치하려면, 위 명령을 주석으로 바꾸고 아래 명령을 해제하세요.
# ! pip install git+https://github.com/huggingface/transformers.git
'''

lowerCamelCase			:					Tuple         =	[{'''type''': '''code''', '''content''': INSTALL_CONTENT}]
lowerCamelCase			:					Dict         =	{
    '''{processor_class}''': '''FakeProcessorClass''',
    '''{model_class}''': '''FakeModelClass''',
    '''{object_class}''': '''FakeObjectClass''',
}






