Skip to content

Commit

Permalink
Fix PropertyValueColumnData._stream() to handle rollover >= len(L) (
Browse files Browse the repository at this point in the history
#13318)

* Fix PropertyValueColumnData._stream() to handle rollover >= len(data)

* Clean implementation
  • Loading branch information
xiaoyang-sde committed Aug 9, 2023
1 parent 99310e6 commit ef355aa
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/bokeh/core/property/wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ def _stream(self, doc: Document, source: ColumnarDataSource, new_data: dict[str,
else:
L = self[k]
L.extend(new_data[k])
if rollover is not None:
if rollover is not None and len(L) > rollover:
del L[:len(L) - rollover]

from ...document.events import ColumnsStreamedEvent
Expand Down
40 changes: 40 additions & 0 deletions tests/unit/bokeh/core/property/test_wrappers__property.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,24 @@ def test_PropertyValueColumnData__stream_list_with_rollover_equals_zero(mock_not
assert event.rollover == 0
assert event.data == {'foo': [40]}

@patch('bokeh.core.property.wrappers.PropertyValueContainer._notify_owners')
def test_PropertyValueColumnData__stream_list_with_rollover_greater_than_list_length(mock_notify: MagicMock) -> None:
from bokeh.document.events import ColumnsStreamedEvent

source = ColumnDataSource(data=dict(foo=[10, 20, 30]))
pvcd = bcpw.PropertyValueColumnData(source.data)

mock_notify.reset_mock()
pvcd._stream("doc", source, dict(foo=[40]), rollover=5, setter="setter")
assert mock_notify.call_count == 1
assert mock_notify.call_args[0] == ({'foo': [10, 20, 30, 40]},) # streaming to list, "old" is actually updated value
assert 'hint' in mock_notify.call_args[1]
event = mock_notify.call_args[1]['hint']
assert isinstance(event, ColumnsStreamedEvent)
assert event.setter == 'setter'
assert event.rollover == 5
assert event.data == {'foo': [40]}

@patch('bokeh.core.property.wrappers.PropertyValueContainer._notify_owners')
def test_PropertyValueColumnData__stream_array_to_array(mock_notify: MagicMock) -> None:
import numpy as np
Expand Down Expand Up @@ -335,6 +353,28 @@ def test_PropertyValueColumnData__stream_array_with_rollover_equals_zero(mock_no
assert event.rollover == 0
assert event.data == {'foo': [40]}

@patch('bokeh.core.property.wrappers.PropertyValueContainer._notify_owners')
def test_PropertyValueColumnData__stream_array_greater_than_array_length(mock_notify: MagicMock) -> None:
import numpy as np

from bokeh.document.events import ColumnsStreamedEvent

source = ColumnDataSource(data=dict(foo=np.array([10, 20, 30])))
pvcd = bcpw.PropertyValueColumnData(source.data)

mock_notify.reset_mock()
pvcd._stream("doc", source, dict(foo=[40]), rollover=5, setter="setter")
assert mock_notify.call_count == 1
assert len(mock_notify.call_args[0]) == 1
assert 'foo' in mock_notify.call_args[0][0]
assert (mock_notify.call_args[0][0]['foo'] == np.array([10, 20, 30])).all()
assert 'hint' in mock_notify.call_args[1]
event = mock_notify.call_args[1]['hint']
assert isinstance(event, ColumnsStreamedEvent)
assert event.setter == 'setter'
assert event.rollover == 5
assert event.data == {'foo': [40]}

@patch('bokeh.core.property.wrappers.PropertyValueContainer._notify_owners')
def test_PropertyValueColumnData__patch_with_simple_indices(mock_notify: MagicMock) -> None:
from bokeh.document.events import ColumnsPatchedEvent
Expand Down

0 comments on commit ef355aa

Please sign in to comment.