




"""simple docstring"""







from __future__ import annotations

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

a            =							TypeVar('T')
a            =							TypeVar('U')






class 					SCREAMING_SNAKE_CASE__    (    Generic[T, U]    ):


						def __init__(							self :	Dict  ,  lowerCAmelCase :	T | None  ,  lowerCAmelCase :	U | None    ):
										lowerCAmelCase              = key
										lowerCAmelCase              = val
										lowerCAmelCase              = None
										lowerCAmelCase              = None




						def __repr__(							self :	List[str]    ):
										return (
										    f'''Node: key: {self.key}, val: {self.val}, '''
										    f'''has next: {bool(self.next    )}, has prev: {bool(self.prev    )}'''
										)






class 					SCREAMING_SNAKE_CASE__    (    Generic[T, U]    ):


						def __init__(							self :	Tuple    ):
										lowerCAmelCase              = DoubleLinkedListNode(lowercase_  ,  lowercase_    )
										lowerCAmelCase              = DoubleLinkedListNode(lowercase_  ,  lowercase_    )
										lowerCAmelCase       ,  lowerCAmelCase              = self.rear, self.head


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


						def      __lowercase       (							self :	Optional[Any]  ,  lowerCAmelCase :	DoubleLinkedListNode[T, U]    ):
										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      __lowercase       (							self :	Optional[Any]  ,  lowerCAmelCase :	DoubleLinkedListNode[T, U]    ):

										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 					SCREAMING_SNAKE_CASE__    (    Generic[T, U]    ):
						_a			  =  {}


						def __init__(							self :	List[Any]  ,  lowerCAmelCase :	int    ):
										lowerCAmelCase              = DoubleLinkedList()
										lowerCAmelCase              = capacity
										lowerCAmelCase              = 0
										lowerCAmelCase              = 0
										lowerCAmelCase              = 0
										lowerCAmelCase              = {}


						def __repr__(							self :	Optional[Any]    ):
										return (
										    f'''CacheInfo(hits={self.hits}, misses={self.miss}, '''
										    f'''capacity={self.capacity}, current size={self.num_keys})'''
										)


						def __contains__(							self :	Union[str, Any]  ,  lowerCAmelCase :	T    ):
										return key in self.cache


						def      __lowercase       (							self :	int  ,  lowerCAmelCase :	T    ):
										# 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(lowercase_    )
														return node.val
										self.miss += 1
										return None


						def      __lowercase       (							self :	List[str]  ,  lowerCAmelCase :	T  ,  lowerCAmelCase :	U    ):

										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(lowercase_    ) 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(lowercase_  ,  lowercase_    )
														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(lowercase_    )




						@classmethod
						def      __lowercase       (							cls :	List[Any]  ,  lowerCAmelCase :	int = 128    ):

										def cache_decorator_inner(lowerCAmelCase :	Callable[[T], U]    ) -> Callable[..., U]:
														def cache_decorator_wrapper(*lowerCAmelCase :	T    ) -> U:
																		if func not in cls.decorator_function_to_instance_map:
																						lowerCAmelCase              = LRUCache(lowercase_    )

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

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

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

														return cache_decorator_wrapper

										return cache_decorator_inner


if __name__ == "__main__":
		import doctest

		doctest.testmod()












'''simple docstring'''

from ..utils import DummyObject, requires_backends






class    UpperCAmelCase	(       metaclass=UpperCamelCase__				):
 __lowercase   		=				["""note_seq"""]
 def __init__(				self      :Optional[Any]						,       *lowercase_      :List[Any]						,       **lowercase_      :List[str]							)->							int:
     requires_backends(self						,       ["note_seq"]							)
 @classmethod
 def      UpperCAmelCase_							(				cls      :str						,       *lowercase_      :Union[str, Any]						,       **lowercase_      :Any							)->							Optional[int]:
     requires_backends(cls						,       ["note_seq"]							)



 @classmethod
 def      UpperCAmelCase_							(				cls      :Dict						,       *lowercase_      :Tuple						,       **lowercase_      :List[Any]							)->							Optional[Any]:
     requires_backends(cls						,       ["note_seq"]							)



