Skip to content

Commit 3d6fd84

Browse files
committed
Create named sentinels for each use case
This makes the code easier to read and the documentation look better. Signed-off-by: Sahas Subramanian <[email protected]>
1 parent ec430ce commit 3d6fd84

File tree

1 file changed

+22
-15
lines changed

1 file changed

+22
-15
lines changed

src/frequenz/channels/_latest_value_cache.py

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,22 @@
5151
HashableT = typing.TypeVar("HashableT", bound=typing.Hashable)
5252

5353

54-
class _Sentinel:
54+
class Sentinel:
5555
"""A sentinel to denote that no value has been received yet."""
5656

57+
def __init__(self, desc: str) -> None:
58+
"""Initialize the sentinel."""
59+
self._desc = desc
60+
pass
61+
5762
def __str__(self) -> str:
5863
"""Return a string representation of this sentinel."""
59-
return "<no value received yet>"
64+
return f"<Sentinel: {self._desc}>"
6065

6166

62-
_SENTINEL = _Sentinel()
67+
NO_KEY = Sentinel("no key provided")
68+
NO_KEY_FUNCTION = Sentinel("no key function provided")
69+
NO_VALUE_RECEIVED = Sentinel("no value received yet")
6370

6471

6572
class LatestValueCache(typing.Generic[T_co, HashableT]):
@@ -71,11 +78,11 @@ class LatestValueCache(typing.Generic[T_co, HashableT]):
7178

7279
@typing.overload
7380
def __init__(
74-
self: LatestValueCache[T_co, _Sentinel],
81+
self: LatestValueCache[T_co, Sentinel],
7582
receiver: Receiver[T_co],
7683
*,
7784
unique_id: str | None = None,
78-
key: _Sentinel = _SENTINEL,
85+
key: Sentinel = NO_KEY_FUNCTION,
7986
) -> None:
8087
"""Create a new cache that does not use keys.
8188
@@ -111,7 +118,7 @@ def __init__(
111118
receiver: Receiver[T_co],
112119
*,
113120
unique_id: str | None = None,
114-
key: typing.Callable[[T_co], typing.Any] | _Sentinel = _SENTINEL,
121+
key: typing.Callable[[T_co], typing.Any] | Sentinel = NO_KEY_FUNCTION,
115122
) -> None:
116123
"""Create a new cache.
117124
@@ -126,9 +133,9 @@ def __init__(
126133
received overall.
127134
"""
128135
self._receiver = receiver
129-
self._key: typing.Callable[[T_co], HashableT] | _Sentinel = key
136+
self._key: typing.Callable[[T_co], HashableT] | Sentinel = key
130137
self._unique_id: str = hex(id(self)) if unique_id is None else unique_id
131-
self._latest_value: T_co | _Sentinel = _SENTINEL
138+
self._latest_value: T_co | Sentinel = NO_VALUE_RECEIVED
132139
self._latest_value_by_key: dict[HashableT, T_co] = {}
133140
self._task = asyncio.create_task(
134141
self._run(), name=f"LatestValueCache«{self._unique_id}»"
@@ -139,7 +146,7 @@ def unique_id(self) -> str:
139146
"""The unique identifier of this instance."""
140147
return self._unique_id
141148

142-
def get(self, key: HashableT | _Sentinel = _SENTINEL) -> T_co:
149+
def get(self, key: HashableT | Sentinel = NO_KEY) -> T_co:
143150
"""Return the latest value that has been received.
144151
145152
This raises a `ValueError` if no value has been received yet. Use `has_value` to
@@ -156,16 +163,16 @@ def get(self, key: HashableT | _Sentinel = _SENTINEL) -> T_co:
156163
Raises:
157164
ValueError: If no value has been received yet.
158165
"""
159-
if not isinstance(key, _Sentinel):
166+
if not isinstance(key, Sentinel):
160167
if key not in self._latest_value_by_key:
161168
raise ValueError(f"No value received for key: {key!r}")
162169
return self._latest_value_by_key[key]
163170

164-
if isinstance(self._latest_value, _Sentinel):
171+
if isinstance(self._latest_value, Sentinel):
165172
raise ValueError("No value has been received yet.")
166173
return self._latest_value
167174

168-
def has_value(self, key: HashableT | _Sentinel = _SENTINEL) -> bool:
175+
def has_value(self, key: HashableT | Sentinel = NO_KEY) -> bool:
169176
"""Check whether a value has been received yet.
170177
171178
If `key` is provided, it checks whether a value has been received for that key.
@@ -176,14 +183,14 @@ def has_value(self, key: HashableT | _Sentinel = _SENTINEL) -> bool:
176183
Returns:
177184
`True` if a value has been received, `False` otherwise.
178185
"""
179-
if not isinstance(key, _Sentinel):
186+
if not isinstance(key, Sentinel):
180187
return key in self._latest_value_by_key
181-
return not isinstance(self._latest_value, _Sentinel)
188+
return not isinstance(self._latest_value, Sentinel)
182189

183190
async def _run(self) -> None:
184191
async for value in self._receiver:
185192
self._latest_value = value
186-
if not isinstance(self._key, _Sentinel):
193+
if not isinstance(self._key, Sentinel):
187194
key = self._key(value)
188195
self._latest_value_by_key[key] = value
189196

0 commit comments

Comments
 (0)