Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit 5a0b652

Browse files
authored
Eliminate a few Anys in LruCache type hints (#11453)
1 parent 432a174 commit 5a0b652

File tree

4 files changed

+32
-19
lines changed

4 files changed

+32
-19
lines changed

changelog.d/11453.misc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Improve type hints for `LruCache`.

synapse/util/caches/deferred_cache.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
Iterable,
2323
MutableMapping,
2424
Optional,
25+
Sized,
2526
TypeVar,
2627
Union,
2728
cast,
@@ -104,7 +105,13 @@ def metrics_cb() -> None:
104105
max_size=max_entries,
105106
cache_name=name,
106107
cache_type=cache_type,
107-
size_callback=(lambda d: len(d) or 1) if iterable else None,
108+
size_callback=(
109+
(lambda d: len(cast(Sized, d)) or 1)
110+
# Argument 1 to "len" has incompatible type "VT"; expected "Sized"
111+
# We trust that `VT` is `Sized` when `iterable` is `True`
112+
if iterable
113+
else None
114+
),
108115
metrics_collection_callback=metrics_cb,
109116
apply_cache_factor_from_config=apply_cache_factor_from_config,
110117
prune_unread_entries=prune_unread_entries,

synapse/util/caches/lrucache.py

+21-16
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@
1515
import logging
1616
import threading
1717
import weakref
18+
from enum import Enum
1819
from functools import wraps
1920
from typing import (
2021
TYPE_CHECKING,
2122
Any,
2223
Callable,
2324
Collection,
25+
Dict,
2426
Generic,
25-
Iterable,
2627
List,
2728
Optional,
2829
Type,
@@ -190,7 +191,7 @@ def __init__(
190191
root: "ListNode[_Node]",
191192
key: KT,
192193
value: VT,
193-
cache: "weakref.ReferenceType[LruCache]",
194+
cache: "weakref.ReferenceType[LruCache[KT, VT]]",
194195
clock: Clock,
195196
callbacks: Collection[Callable[[], None]] = (),
196197
prune_unread_entries: bool = True,
@@ -290,6 +291,12 @@ def move_to_front(self, clock: Clock, cache_list_root: ListNode) -> None:
290291
self._global_list_node.update_last_access(clock)
291292

292293

294+
class _Sentinel(Enum):
295+
# defining a sentinel in this way allows mypy to correctly handle the
296+
# type of a dictionary lookup.
297+
sentinel = object()
298+
299+
293300
class LruCache(Generic[KT, VT]):
294301
"""
295302
Least-recently-used cache, supporting prometheus metrics and invalidation callbacks.
@@ -302,7 +309,7 @@ def __init__(
302309
max_size: int,
303310
cache_name: Optional[str] = None,
304311
cache_type: Type[Union[dict, TreeCache]] = dict,
305-
size_callback: Optional[Callable] = None,
312+
size_callback: Optional[Callable[[VT], int]] = None,
306313
metrics_collection_callback: Optional[Callable[[], None]] = None,
307314
apply_cache_factor_from_config: bool = True,
308315
clock: Optional[Clock] = None,
@@ -339,7 +346,7 @@ def __init__(
339346
else:
340347
real_clock = clock
341348

342-
cache = cache_type()
349+
cache: Union[Dict[KT, _Node[KT, VT]], TreeCache] = cache_type()
343350
self.cache = cache # Used for introspection.
344351
self.apply_cache_factor_from_config = apply_cache_factor_from_config
345352

@@ -374,7 +381,7 @@ def __init__(
374381
# creating more each time we create a `_Node`.
375382
weak_ref_to_self = weakref.ref(self)
376383

377-
list_root = ListNode[_Node].create_root_node()
384+
list_root = ListNode[_Node[KT, VT]].create_root_node()
378385

379386
lock = threading.Lock()
380387

@@ -422,7 +429,7 @@ def cache_len() -> int:
422429
def add_node(
423430
key: KT, value: VT, callbacks: Collection[Callable[[], None]] = ()
424431
) -> None:
425-
node = _Node(
432+
node: _Node[KT, VT] = _Node(
426433
list_root,
427434
key,
428435
value,
@@ -439,10 +446,10 @@ def add_node(
439446
if caches.TRACK_MEMORY_USAGE and metrics:
440447
metrics.inc_memory_usage(node.memory)
441448

442-
def move_node_to_front(node: _Node) -> None:
449+
def move_node_to_front(node: _Node[KT, VT]) -> None:
443450
node.move_to_front(real_clock, list_root)
444451

445-
def delete_node(node: _Node) -> int:
452+
def delete_node(node: _Node[KT, VT]) -> int:
446453
node.drop_from_lists()
447454

448455
deleted_len = 1
@@ -496,7 +503,7 @@ def cache_get(
496503

497504
@synchronized
498505
def cache_set(
499-
key: KT, value: VT, callbacks: Iterable[Callable[[], None]] = ()
506+
key: KT, value: VT, callbacks: Collection[Callable[[], None]] = ()
500507
) -> None:
501508
node = cache.get(key, None)
502509
if node is not None:
@@ -590,8 +597,6 @@ def cache_clear() -> None:
590597
def cache_contains(key: KT) -> bool:
591598
return key in cache
592599

593-
self.sentinel = object()
594-
595600
# make sure that we clear out any excess entries after we get resized.
596601
self._on_resize = evict
597602

@@ -608,18 +613,18 @@ def cache_contains(key: KT) -> bool:
608613
self.clear = cache_clear
609614

610615
def __getitem__(self, key: KT) -> VT:
611-
result = self.get(key, self.sentinel)
612-
if result is self.sentinel:
616+
result = self.get(key, _Sentinel.sentinel)
617+
if result is _Sentinel.sentinel:
613618
raise KeyError()
614619
else:
615-
return cast(VT, result)
620+
return result
616621

617622
def __setitem__(self, key: KT, value: VT) -> None:
618623
self.set(key, value)
619624

620625
def __delitem__(self, key: KT, value: VT) -> None:
621-
result = self.pop(key, self.sentinel)
622-
if result is self.sentinel:
626+
result = self.pop(key, _Sentinel.sentinel)
627+
if result is _Sentinel.sentinel:
623628
raise KeyError()
624629

625630
def __len__(self) -> int:

synapse/util/linked_list.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ def remove_from_list(self) -> None:
8484
# immediately rather than at the next GC.
8585
self.cache_entry = None
8686

87-
def move_after(self, node: "ListNode") -> None:
87+
def move_after(self, node: "ListNode[P]") -> None:
8888
"""Move this node from its current location in the list to after the
8989
given node.
9090
"""
@@ -122,7 +122,7 @@ def _refs_remove_node_from_list(self) -> None:
122122
self.prev_node = None
123123
self.next_node = None
124124

125-
def _refs_insert_after(self, node: "ListNode") -> None:
125+
def _refs_insert_after(self, node: "ListNode[P]") -> None:
126126
"""Internal method to insert the node after the given node."""
127127

128128
# This method should only be called when we're not already in the list.

0 commit comments

Comments
 (0)