Path: blob/main/py-polars/tests/unit/utils/test_cache.py
8416 views
from typing import Any12import pytest34from polars._utils.cache import LRUCache567def test_init() -> None:8cache = LRUCache[str, float](maxsize=0)9assert cache.maxsize == 010assert len(cache) == 01112with pytest.raises(ValueError, match="`maxsize` cannot be negative; found -100"):13LRUCache(maxsize=-100)141516def test_init_maxsize_zero() -> None:17# weird, but not actually invalid18cache = LRUCache[str, list[int]](maxsize=0)19cache["key"] = [1, 2, 3]20assert len(cache) == 0212223def test_setitem_getitem_delitem() -> None:24cache = LRUCache[int, str](maxsize=3)25cache[0] = "pear"26cache[1] = "apple"27cache[2] = "banana"28cache[3] = "cherry"2930assert list(cache.keys()) == [1, 2, 3]31assert list(cache.values()) == ["apple", "banana", "cherry"]32assert list(cache.items()) == [(1, "apple"), (2, "banana"), (3, "cherry")]33assert len(cache) == 334assert cache.maxsize == 33536del cache[2]37assert len(cache) == 238assert cache.maxsize == 339assert repr(cache) == "LRUCache({1: 'apple', 3: 'cherry'}, maxsize=3, currsize=2)"404142def test_cache_access_updates_order() -> None:43cache1 = LRUCache[int, str](maxsize=3)44cache1[30] = "thirty"45cache1[20] = "twenty"46cache1[10] = "ten"47assert list(cache1.keys()) == [30, 20, 10]4849cache1.get(20)50cache1.get(30)51assert list(cache1.keys()) == [10, 20, 30]5253cache2 = LRUCache[str, tuple[int, int]](maxsize=2)54cache2["first"] = (1, 2)55cache2["second"] = (3, 4)56assert list(cache2.keys()) == ["first", "second"]5758_ = cache2["first"]59assert list(cache2.keys()) == ["second", "first"]606162def test_contains() -> None:63cache = LRUCache[str, float](maxsize=3)64cache["pi"] = 3.1415965cache["e"] = 2.718286667assert "pi" in cache68assert "e" in cache69assert "phi" not in cache707172def test_getitem_keyerror() -> None:73cache = LRUCache[int, str](maxsize=3)74with pytest.raises(KeyError, match="999 not found in cache"):75cache[999]767778def test_get_with_default() -> None:79cache = LRUCache[str, list[str]](maxsize=3)80cache["fruits"] = ["apple", "banana"]8182assert cache.get("fruits") == ["apple", "banana"]83assert cache.get("vegetables") is None84assert cache.get("vegetables", ["carrot", "turnip"]) == ["carrot", "turnip"]858687def test_iter_and_update() -> None:88cache = LRUCache[int, str](maxsize=4)89cache.update({100: "hundred", 200: "two hundred", 300: "three hundred"})90assert list(cache) == [100, 200, 300]919293def test_maxsize_eviction() -> None:94cache = LRUCache[str, dict[str, Any]](maxsize=2)95cache["user1"] = {"name": "Alice", "age": 30}96cache["user2"] = {"name": "Bob", "age": 25}97cache["user3"] = {"name": "Charlie", "age": 35}9899assert len(cache) == 2100assert "user1" not in cache101assert "user2" in cache102assert "user3" in cache103104105def test_maxsize_increase() -> None:106cache = LRUCache[str, int].fromkeys(4, keys=[f"k{n}" for n in range(6)], value=0)107assert len(cache) == 4108assert cache.maxsize == 4109assert list(cache.keys()) == ["k2", "k3", "k4", "k5"]110111cache.maxsize = 6112cache.update(k6=1, k7=2, k8=3)113assert len(cache) == 6114assert cache.maxsize == 6115assert list(cache.keys()) == ["k3", "k4", "k5", "k6", "k7", "k8"]116117118def test_maxsize_decrease() -> None:119cache = LRUCache[int, list[int]](maxsize=4)120cache[1] = [1, 2]121cache[2] = [3, 4]122cache[3] = [5, 6]123cache[4] = [7, 8]124125cache.maxsize = 2126assert len(cache) == 2127assert cache.maxsize == 2128assert list(cache.items()) == [(3, [5, 6]), (4, [7, 8])]129130cache.maxsize = 0131assert len(cache) == 0132assert cache.maxsize == 0133assert list(cache.values()) == []134135136def test_pop() -> None:137cache = LRUCache[int, str](maxsize=4)138cache[42] = "answer"139cache[99] = "bottles"140141value = cache.pop(42)142assert value == "answer"143assert 42 not in cache144assert len(cache) == 1145146with pytest.raises(KeyError, match="404"):147cache.pop(404)148149150def test_popitem_setdefault() -> None:151cache = LRUCache[str, set[int]](maxsize=3)152cache["set1"] = {1, 2, 3}153cache["set2"] = {4, 5, 6}154cache["set3"] = {7, 8, 9}155156key, value = cache.popitem()157assert key == "set1"158assert value == {1, 2, 3}159assert len(cache) == 2160161res = cache.setdefault("set2", {10, 11, 12})162assert res == {4, 5, 6}163assert list(cache) == ["set3", "set2"]164165res = cache.setdefault("set4", {10, 11, 12})166assert res == {10, 11, 12}167assert list(cache) == ["set3", "set2", "set4"]168169170def test_popitem_empty_cache() -> None:171cache = LRUCache[str, bytes](maxsize=3)172with pytest.raises(KeyError):173cache.popitem()174175176def test_update_existing_key() -> None:177cache = LRUCache[int, float](maxsize=3)178cache.update([(1, 1.5), (2, 2.5)])179assert list(cache.keys()) == [1, 2]180181cache[1] = 10.5182assert list(cache.keys()) == [2, 1]183assert cache[1] == 10.5184185186def test_update_existing_keys() -> None:187cache = LRUCache[str, float](maxsize=3)188cache["pi"] = 3.14189cache["e"] = 2.71190191cache.update({"phi": 1.618, "pi": 3.14159})192assert tuple(cache.items()) == (("e", 2.71), ("phi", 1.618), ("pi", 3.14159))193194195def test_update_check_eviction() -> None:196cache = LRUCache[int, str](maxsize=2)197cache[1] = "first"198cache[2] = "second"199200cache.update({3: "third", 4: "fourth"})201202assert 1 not in cache203assert 2 not in cache204assert cache[3] == "third"205assert cache[4] == "fourth"206assert len(cache) == 2207208209def test_update_preserves_order() -> None:210cache = LRUCache[str, int](maxsize=3)211cache["a"] = 1212cache["b"] = 2213214cache.update({"c": 3})215assert list(cache.keys()) == ["a", "b", "c"]216217cache.update({"a": 10, "x": 4})218assert list(cache.items()) == [("c", 3), ("a", 10), ("x", 4)]219220221