Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

<!-- Here goes the main new features and examples or instructions on how to use them -->

- Remove `__setitem__` method from `OrderedRingBuffer` to enforce usage of the dedicated `update` method only.

## Bug Fixes

<!-- Here goes notable bug fixes that are worth a special mention or explanation -->
57 changes: 1 addition & 56 deletions src/frequenz/sdk/timeseries/_ringbuffer/buffer.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@
"""Ringbuffer implementation with focus on time & memory efficiency."""


from collections.abc import Iterable
from copy import deepcopy
from dataclasses import dataclass
from datetime import datetime, timedelta, timezone
from typing import Generic, SupportsFloat, SupportsIndex, TypeVar, overload
from typing import Generic, SupportsIndex, TypeVar, overload

import numpy as np
import numpy.typing as npt
Expand Down Expand Up @@ -498,60 +497,6 @@ def wrap(self, index: int) -> int:
"""
return index % self.maxlen

@overload
def __setitem__(self, index_or_slice: slice, value: Iterable[float]) -> None:
"""Set values at the request slice positions.

No wrapping of the index will be done.
Create a feature request if you require this function.

Args:
index_or_slice: Slice specification of the requested data.
value: Sequence of value to set at the given range.
"""

@overload
def __setitem__(self, index_or_slice: SupportsIndex, value: float) -> None:
"""Set value at requested index.

No wrapping of the index will be done.
Create a feature request if you require this function.

Args:
index_or_slice: Index of the data.
value: Value to set at the given position.
"""

def __setitem__(
self, index_or_slice: SupportsIndex | slice, value: float | Iterable[float]
) -> None:
"""Set item or slice at requested position.

No wrapping of the index will be done.
Create a feature request if you require this function.

Args:
index_or_slice: Index or slice specification of the requested data.
value: Value to set at the given position.
"""
# There seem to be 2 different mypy bugs at play here.
# First we need to check that the combination of input arguments are
# correct to make the type checker happy (I guess it could be inferred
# from the @overloads, but it's not currently working without this
# hack).
# Then we need to ignore a no-untyped-call error, for some reason it
# can't get the type for self._buffer.__setitem__()
if isinstance(index_or_slice, SupportsIndex) and isinstance(
value, SupportsFloat
):
self._buffer.__setitem__(index_or_slice, value) # type: ignore[no-untyped-call]
elif isinstance(index_or_slice, slice) and isinstance(value, Iterable):
self._buffer.__setitem__(index_or_slice, value) # type: ignore[no-untyped-call]
else:
assert (
False
), f"Incompatible input arguments: {type(index_or_slice)=} {type(value)=}"

@overload
def __getitem__(self, index_or_slice: SupportsIndex) -> float:
"""Get item at requested position.
Expand Down
2 changes: 1 addition & 1 deletion tests/timeseries/test_ringbuffer_serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def load_dump_test(dumped: rb.OrderedRingBuffer[Any], path: str) -> None:
# Fill with data so we have something to compare
# Avoiding .update() because it takes very long for 40k entries
for i in range(size):
dumped[i] = i
dumped._buffer[i] = i # pylint: disable=protected-access

# But use update a bit so the timestamp and gaps are initialized
for i in range(0, size, 100):
Expand Down