



'''simple docstring'''

from __future__ import annotations

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

UpperCAmelCase     		=   TypeVar('T')
UpperCAmelCase     		=   TypeVar('U')

class __snake_case(				Generic[T, U] ):


						'''simple docstring'''



						def __init__( self     ,	A_     ,	A_				)     ->     Dict:
							lowerCAmelCase   =     key
							lowerCAmelCase   =     val
							lowerCAmelCase   =     None
							lowerCAmelCase   =     None




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







class __snake_case(				Generic[T, U] ):


						'''simple docstring'''



						def __init__( self				)     ->     None:
							lowerCAmelCase   =     DoubleLinkedListNode(A_     ,	A_				)
							lowerCAmelCase   =     DoubleLinkedListNode(A_     ,	A_				)
							lowerCAmelCase,       lowerCAmelCase   =     self.rear, self.head


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


						def     __snake_case   ( self     ,	A_				)     ->     None:
							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     __snake_case   ( self     ,	A_				)     ->     DoubleLinkedListNode[T, U] | None:

							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 __snake_case(				Generic[T, U] ):


						'''simple docstring'''



						UpperCAmelCase							:   dict[Callable[[T], U], LRUCache[T, U]]									=		{}


						def __init__( self     ,	A_				)     ->     str:
							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     ,	A_				)     ->     bool:
							return key in self.cache


						def     __snake_case   ( self     ,	A_				)     ->     U | None:
							# 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(A_				)
								return node.val
							self.miss += 1
							return None


						def     __snake_case   ( self     ,	A_     ,	A_				)     ->     None:

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




						@classmethod
						def     __snake_case   ( cls     ,	A_ = 128				)     ->     Callable[[Callable[[T], U]], Callable[..., U]]:

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

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

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

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

								return cache_decorator_wrapper

							return cache_decorator_inner


if __name__ == "__main__":
				import doctest

				doctest.testmod()




'''simple docstring'''

import pytest

import datasets


# Import fixture modules as plugins
UpperCAmelCase     		=   ['tests.fixtures.files', 'tests.fixtures.hub', 'tests.fixtures.fsspec']






def 		_snake_case		( _SCREAMING_SNAKE_CASE					:						str							,		_SCREAMING_SNAKE_CASE					:						int							)      ->						Optional[int]:







	"""simple docstring"""
	# Mark tests as "unit" by default if not marked as "integration" (or already marked as "unit")
	for item in items:
		if any(marker in item.keywords for marker in ["""integration""", """unit"""]							):
			continue
		item.add_marker(pytest.mark.unit							)






def 		_snake_case		( _SCREAMING_SNAKE_CASE					:						List[str]							)      ->						Any:







	"""simple docstring"""
	config.addinivalue_line("""markers"""							,		"""torchaudio_latest: mark test to run with torchaudio>=0.12"""							)






@pytest.fixture(autouse=_SCREAMING_SNAKE_CASE							)
def 		_snake_case		( _SCREAMING_SNAKE_CASE					:						Dict							,		_SCREAMING_SNAKE_CASE					:						Dict							)      ->						str:







	"""simple docstring"""
	# test_hf_cache_home = tmp_path_factory.mktemp("cache")  # TODO: why a cache dir per test function does not work?
	lowerCAmelCase   =     tmp_path_factory.getbasetemp() / """cache"""
	lowerCAmelCase   =     test_hf_cache_home / """datasets"""
	lowerCAmelCase   =     test_hf_cache_home / """metrics"""
	lowerCAmelCase   =     test_hf_cache_home / """modules"""
	monkeypatch.setattr("""datasets.config.HF_DATASETS_CACHE"""							,		str(_SCREAMING_SNAKE_CASE							)							)
	monkeypatch.setattr("""datasets.config.HF_METRICS_CACHE"""							,		str(_SCREAMING_SNAKE_CASE							)							)
	monkeypatch.setattr("""datasets.config.HF_MODULES_CACHE"""							,		str(_SCREAMING_SNAKE_CASE							)							)
	lowerCAmelCase   =     test_hf_datasets_cache / """downloads"""
	monkeypatch.setattr("""datasets.config.DOWNLOADED_DATASETS_PATH"""							,		str(_SCREAMING_SNAKE_CASE							)							)
	lowerCAmelCase   =     test_hf_datasets_cache / """downloads""" / """extracted"""
	monkeypatch.setattr("""datasets.config.EXTRACTED_DATASETS_PATH"""							,		str(_SCREAMING_SNAKE_CASE							)							)






@pytest.fixture(autouse=_SCREAMING_SNAKE_CASE							,		scope="""session"""							)
def 		_snake_case		( )      ->						Optional[Any]:







	"""simple docstring"""
	datasets.disable_progress_bar()






@pytest.fixture(autouse=_SCREAMING_SNAKE_CASE							)
def 		_snake_case		( _SCREAMING_SNAKE_CASE					:						Any							)      ->						Optional[int]:







	"""simple docstring"""
	# don't take tests into account when counting downloads
	monkeypatch.setattr("""datasets.config.HF_UPDATE_DOWNLOAD_COUNTS"""							,		_SCREAMING_SNAKE_CASE							)






@pytest.fixture
def 		_snake_case		( _SCREAMING_SNAKE_CASE					:						List[str]							)      ->						str:







	"""simple docstring"""
	# Required to suppress RemovedIn20Warning when feature(s) are not compatible with SQLAlchemy 2.0
	# To be removed once SQLAlchemy 2.0 supported
	monkeypatch.setattr("""sqlalchemy.util.deprecations.SILENCE_UBER_WARNING"""							,		_SCREAMING_SNAKE_CASE							)