diff --git a/CHANGELOG.md b/CHANGELOG.md index 562282f16f..989d416659 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,95 @@ -Version 1.11.0 +Version 1.10.8 ============== -Backward incompatible changes: +This a likely the last hotfix release in the 1.10.x series containing +fixes for compatibility with bokeh 1.0 and matplotlib 3.0. It also +contains a wide array of fixes contributed and reported by users: + +Special thanks for the contributions by Andrew Huang (@ahuang11), +Julia Signell (@jsignell), and Zachary Barry (@zbarry). + +Enhancements: + +- Add support for labels, choord, hextiles and area in `.to` interface + ([#2924](https://github.com/ioam/holoviews/pull/2923)) +- Allow defining default bokeh themes as strings on Renderer + ([#2972](https://github.com/ioam/holoviews/pull/2972)) +- Allow specifying fontsize for categorical axis ticks in bokeh + ([#3047](https://github.com/ioam/holoviews/pull/3047)) +- Allow hiding toolbar without disabling tools + ([#3074](https://github.com/ioam/holoviews/pull/3074)) +- Allow specifying explicit colormapping on non-categorical data + ([#3071](https://github.com/ioam/holoviews/pull/3071)) +- Support for displaying xarray without explicit coordinates + ([#2968](https://github.com/ioam/holoviews/pull/2968)) + +Fixes: + +- Ensured that objects are garbage collected when using + linked streams ([#2111](https://github.com/ioam/holoviews/issues/2111)) +- Allow dictionary data to reference values which are not dimensions + ([#2855](https://github.com/ioam/holoviews/pull/2855), + [#2859](https://github.com/ioam/holoviews/pull/2859)) +- Fixes for zero and non-finite ranges in datashader operation + ([#2860](https://github.com/ioam/holoviews/pull/2860), + [#2863](https://github.com/ioam/holoviews/pull/2863), + [#2869](https://github.com/ioam/holoviews/pull/2869)) +- Fixes for CDSStream and drawing tools on bokeh server + ([#2915](https://github.com/ioam/holoviews/pull/2915)) +- Fixed issues with nans, datetimes and streaming on Area and Spread + elements ([#2951](https://github.com/ioam/holoviews/pull/2951), + [c55b044](https://github.com/ioam/holoviews/commit/c55b044)) +- General fixes for datetime handling + ([#3005](https://github.com/ioam/holoviews/pull/3005), + [#3045](https://github.com/ioam/holoviews/pull/3045), + [#3075](https://github.com/ioam/holoviews/pull/3074)) +- Fixed handling of curvilinear and datetime coordinates on QuadMesh + ([#3017](https://github.com/ioam/holoviews/pull/3017), + [#3081](https://github.com/ioam/holoviews/pull/3081)) +- Fixed issue when inverting a shared axis in bokeh + ([#3083](https://github.com/ioam/holoviews/pull/3083)) +- Fixed formatting of values in HoloMap widgets + ([#2954](https://github.com/ioam/holoviews/pull/2954)) +- Fixed setting fontsize for z-axis label + ([#2967](https://github.com/ioam/holoviews/pull/2967)) + +Compatibility: + +- Suppress warnings about rcParams in matplotlib 3.0 + ([#3013](https://github.com/ioam/holoviews/pull/3013), + [#3058](https://github.com/ioam/holoviews/pull/3058), + [#3104](https://github.com/ioam/holoviews/pull/3104)) +- Fixed incompatibility with Python <=3.5 + ([#3073](https://github.com/ioam/holoviews/pull/3073)) +- Fixed incompatibility with bokeh >=1.0 + ([#3051](https://github.com/ioam/holoviews/pull/3051)) + +Documentation: + +- Completely overhauled the FAQ + ([#2928](https://github.com/ioam/holoviews/pull/2928), + [#2941](https://github.com/ioam/holoviews/pull/2941), + [#2959](https://github.com/ioam/holoviews/pull/2959), + [#3025](https://github.com/ioam/holoviews/pull/3025)) + +Version 1.10.7 +============== + +This a very minor hotfix release mostly containing fixes for datashader +aggregation of empty datasets: + +Fixes: + +- Fix datashader aggregation of empty and zero-range data + ([#2860](https://github.com/ioam/holoviews/pull/2860), + [#2863](https://github.com/ioam/holoviews/pull/2863)) +- Disable validation for additional, non-referenced keys in the + DictInterface ([#2860](https://github.com/ioam/holoviews/pull/2860)) +- Fixed frame lookup for non-overlapping dimensions + ([#2861](https://github.com/ioam/holoviews/pull/2861)) +- Fixed ticks on log Colorbar if low value <= 0 + ([#2865](https://github.com/ioam/holoviews/pull/2865)) -- The `.to` interface no longer sorts `Curve` data by default ([#3001](https://github.com/ioam/holoviews/pull/3001)) Version 1.10.6 ============== diff --git a/doc/index.rst b/doc/index.rst index e2aa805756..1b18df0380 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -15,7 +15,7 @@ The `User Guide `_ goes more deeply into key concepts from HoloViews The `API `_ is the definitive guide to each HoloViews object, but the same information is available more conveniently via the `hv.help()` command and tab completion in the Jupyter notebook. -If you have any `issues `_ or wish to `contribute code `_, you can visit our `GitHub site `_ or chat with the developers on `gitter `_. +If you have any `issues `_ or wish to `contribute code `_, you can visit our `GitHub site `_ or chat with the developers on `gitter `_. .. raw:: html :file: latest_news.html diff --git a/doc/releases.rst b/doc/releases.rst index 92893be58a..6b1388d2ab 100644 --- a/doc/releases.rst +++ b/doc/releases.rst @@ -14,6 +14,98 @@ Release notes ************* +Version 1.10.8 +============== + +This a likely the last hotfix release in the 1.10.x series containing +fixes for compatibility with bokeh 1.0 and matplotlib 3.0. It also +contains a wide array of fixes contributed and reported by users: + +Special thanks for the contributions by Andrew Huang (@ahuang11), +Julia Signell (@jsignell), and Zachary Barry (@zbarry). + +Enhancements: + +- Add support for labels, choord, hextiles and area in `.to` interface + (`#2924 =1.0 + (`#3051 `_, + `#2863 `_) +- Disable validation for additional, non-referenced keys in the + DictInterface (`#2860 `_) +- Fixed frame lookup for non-overlapping dimensions + (`#2861 `_) +- Fixed ticks on log Colorbar if low value <= 0 + (`#2865 `_) + + Version 1.10.6 ============== diff --git a/examples/gallery/demos/bokeh/boxplot_chart.ipynb b/examples/gallery/demos/bokeh/boxplot_chart.ipynb index d2cbfe4b50..c89dc74e7e 100644 --- a/examples/gallery/demos/bokeh/boxplot_chart.ipynb +++ b/examples/gallery/demos/bokeh/boxplot_chart.ipynb @@ -37,7 +37,7 @@ "from bokeh.sampledata.autompg import autompg as df\n", "\n", "title = \"MPG by Cylinders and Data Source, Colored by Cylinders\"\n", - "boxwhisker = hv.BoxWhisker(df, ['cyl', 'origin'], 'mpg', label=title).options(color_index=0)" + "boxwhisker = hv.BoxWhisker(df, ['cyl', 'origin'], 'mpg', label=title)" ] }, { diff --git a/examples/gallery/demos/matplotlib/boxplot_chart.ipynb b/examples/gallery/demos/matplotlib/boxplot_chart.ipynb index c66f14f5f8..cbdf222ffe 100644 --- a/examples/gallery/demos/matplotlib/boxplot_chart.ipynb +++ b/examples/gallery/demos/matplotlib/boxplot_chart.ipynb @@ -38,7 +38,7 @@ "from bokeh.sampledata.autompg import autompg as df\n", "\n", "title = \"MPG by Cylinders and Data Source, Colored by Cylinders\"\n", - "boxwhisker = hv.BoxWhisker(df, ['cyl', 'origin'], 'mpg', label=title).options(color_index=0)" + "boxwhisker = hv.BoxWhisker(df, ['cyl', 'origin'], 'mpg', label=title)" ] }, { diff --git a/holoviews/plotting/bokeh/element.py b/holoviews/plotting/bokeh/element.py index bbb1fd85a4..e72ae97bf1 100644 --- a/holoviews/plotting/bokeh/element.py +++ b/holoviews/plotting/bokeh/element.py @@ -889,7 +889,7 @@ def model_changed(self, model): update on the backend. """ callbacks = [cb for cbs in self.traverse(lambda x: x.callbacks) - for cb in cbs] + for cb in cbs] stream_metadata = [stream._metadata for cb in callbacks for stream in cb.streams if stream._metadata] return any(md['id'] == model.ref['id'] for models in stream_metadata diff --git a/holoviews/plotting/bokeh/plot.py b/holoviews/plotting/bokeh/plot.py index e0cc133d9d..ef33f8494e 100644 --- a/holoviews/plotting/bokeh/plot.py +++ b/holoviews/plotting/bokeh/plot.py @@ -107,7 +107,10 @@ def document(self, doc): self.root is self.handles.get('plot') and not isinstance(self, AdjointLayoutPlot)): doc.on_session_destroyed(self._session_destroy) if self._document: - self._document._session_destroyed_callbacks.pop(self._session_destroy, None) + if isinstance(self._document._session_destroyed_callbacks, set): + self._document._session_destroyed_callbacks.discard(self._session_destroy) + else: + self._document._session_destroyed_callbacks.pop(self._session_destroy, None) self._document = doc if self.subplots: @@ -160,7 +163,8 @@ def _construct_callbacks(self): streams = Stream.registry.get(source, []) registry = Stream._callbacks['bokeh'] cb_classes |= {(registry[type(stream)], stream) for stream in streams - if type(stream) in registry and stream.linked} + if type(stream) in registry and stream.linked + and stream.source is not None} cbs = [] sorted_cbs = sorted(cb_classes, key=lambda x: id(x[0])) for cb, group in groupby(sorted_cbs, lambda x: x[0]): diff --git a/holoviews/plotting/bokeh/util.py b/holoviews/plotting/bokeh/util.py index e07f42aaa4..d6cf865de3 100644 --- a/holoviews/plotting/bokeh/util.py +++ b/holoviews/plotting/bokeh/util.py @@ -46,6 +46,7 @@ # Conversion between matplotlib and bokeh markers markers = {'s': {'marker': 'square'}, 'd': {'marker': 'diamond'}, + '+': {'marker': 'cross'}, '^': {'marker': 'triangle', 'angle': 0}, '>': {'marker': 'triangle', 'angle': -np.pi/2}, 'v': {'marker': 'triangle', 'angle': np.pi}, diff --git a/holoviews/streams.py b/holoviews/streams.py index 1da3ec5e25..000c36e3b1 100644 --- a/holoviews/streams.py +++ b/holoviews/streams.py @@ -204,7 +204,7 @@ def __init__(self, rename={}, source=None, subscribers=[], linked=False, """ # Source is stored as a weakref to allow it to be garbage collected - self._source = weakref.ref(source) if source else None + self._source = None if source is None else weakref.ref(source) self._subscribers = [] for subscriber in subscribers: @@ -315,11 +315,15 @@ def source(self): @source.setter def source(self, source): - old_source = self._source() if self._source else None - if old_source: - source_list = self.registry[old_source] + if self.source: + source_list = self.registry[self.source] if self in source_list: source_list.remove(self) + + if source is None: + self._source = None + return + self._source = weakref.ref(source) if source in self.registry: self.registry[source].append(self) diff --git a/holoviews/tests/plotting/bokeh/testcallbacks.py b/holoviews/tests/plotting/bokeh/testcallbacks.py index 4cdfe748da..5df38489a1 100644 --- a/holoviews/tests/plotting/bokeh/testcallbacks.py +++ b/holoviews/tests/plotting/bokeh/testcallbacks.py @@ -96,10 +96,12 @@ def test_reset_callback(self): def record(resetting): resets.append(resetting) curve = Curve([]) - PlotReset(source=curve).add_subscriber(record) + stream = PlotReset(source=curve) + stream.add_subscriber(record) plot = bokeh_server_renderer.get_plot(curve) plot.callbacks[0].on_msg({'reset': True}) self.assertEqual(resets, [True]) + self.assertIs(stream.source, curve) class TestEditToolCallbacks(CallbackTestCase): diff --git a/holoviews/tests/teststreams.py b/holoviews/tests/teststreams.py index ca7012f8e8..619f4822df 100644 --- a/holoviews/tests/teststreams.py +++ b/holoviews/tests/teststreams.py @@ -481,6 +481,16 @@ class TestStreamSource(ComparisonTestCase): def tearDown(self): Stream.registry = defaultdict(list) + def test_source_empty_element(self): + points = Points([]) + stream = PointerX(source=points) + self.assertIs(stream.source, points) + + def test_source_empty_dmap(self): + points_dmap = DynamicMap(lambda x: Points([]), kdims=['X']) + stream = PointerX(source=points_dmap) + self.assertIs(stream.source, points_dmap) + def test_source_registry(self): points = Points([(0, 0)]) PointerX(source=points)