From 0f7a38f893c50a3cbd492854aeafdfb140ac4ba9 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Tue, 5 Nov 2019 23:13:34 +0100 Subject: [PATCH] Deprecate Locator.refresh and associated helpers. `Locator.refresh()` was called at certain places to let locators update their internal state, typically based on the axis limits. Instead, they can just always consult the axis limits when called, if needed. (This should be more robust -- otherwise, a call to a locator basically always needs to be preceded to a call to `refresh()` to ensure getting up-to-date results.) The deprecation is made slightly complex by the fact that we need to check whether the user is using a third-party locator which overrides `refresh()`, and warn in that case. The associated helper methods `NavigationToolbar2.draw()` and `ToolViewsPositions.refresh_locators()` (which called `refresh()` and then `canvas.draw_idle()` are deprecated, and should be replaced by calls to `draw_idle()` on the corresponding canvas once the deprecation period ends. --- doc/api/api_changes_3.3/deprecations.rst | 11 +++++++++++ lib/matplotlib/backend_bases.py | 15 +++++++++++---- lib/matplotlib/backend_tools.py | 12 +++++++++--- lib/matplotlib/projections/polar.py | 1 + lib/matplotlib/ticker.py | 14 +++++++++++++- 5 files changed, 45 insertions(+), 8 deletions(-) diff --git a/doc/api/api_changes_3.3/deprecations.rst b/doc/api/api_changes_3.3/deprecations.rst index 91e800e079fe..54fb8fe63ee4 100644 --- a/doc/api/api_changes_3.3/deprecations.rst +++ b/doc/api/api_changes_3.3/deprecations.rst @@ -439,3 +439,14 @@ names will be passed as is, allowing one to pass names such as *patchA* or ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ These attributes are deprecated in favor of ``ContourSet.axes`` and ``Quiver.axes``, for consistency with other artists. + +``Locator.refresh()`` and associated methods +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +``Locator.refresh()`` is deprecated. This method was called at certain places +to let locators update their internal state, typically based on the axis +limits. Locators should now always consult the axis limits when called, if +needed. + +The associated helper methods ``NavigationToolbar2.draw()`` and +``ToolViewsPositions.refresh_locators()`` are deprecated, and should be +replaced by calls to ``draw_idle()`` on the corresponding canvas. diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index 93842a40165b..66faf728b20f 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -41,6 +41,7 @@ import numpy as np +import matplotlib as mpl from matplotlib import ( backend_tools as tools, cbook, colors, textpath, tight_bbox, transforms, widgets, get_backend, is_interactive, rcParams) @@ -2983,7 +2984,7 @@ def release_pan(self, event): self._button_pressed = None self.push_current() self.release(event) - self.draw() + self._draw() def drag_pan(self, event): """Callback for dragging in pan/zoom mode.""" @@ -3026,7 +3027,7 @@ def release_zoom(self, event): (abs(y - start_y) < 5 and event.key != "x")): self._xypress = None self.release(event) - self.draw() + self._draw() return # Detect whether this axes is twinned with an earlier axes in the @@ -3040,14 +3041,20 @@ def release_zoom(self, event): (start_x, start_y, x, y), self._zoom_info["direction"], event.key, twinx, twiny) - self.draw() + self._draw() self._zoom_info = None self.push_current() self.release(event) + @cbook.deprecated("3.3", alternative="toolbar.canvas.draw_idle()") def draw(self): """Redraw the canvases, update the locators.""" + self._draw() + + # Can be removed once Locator.refresh() is removed, and replaced by an + # inline call to self.canvas.draw_idle(). + def _draw(self): for a in self.canvas.figure.get_axes(): xaxis = getattr(a, 'xaxis', None) yaxis = getattr(a, 'yaxis', None) @@ -3060,7 +3067,7 @@ def draw(self): locators.append(yaxis.get_minor_locator()) for loc in locators: - loc.refresh() + mpl.ticker._if_refresh_overridden_call_and_emit_deprec(loc) self.canvas.draw_idle() def _update_view(self): diff --git a/lib/matplotlib/backend_tools.py b/lib/matplotlib/backend_tools.py index 302b63a861d0..a27e364a4eb2 100644 --- a/lib/matplotlib/backend_tools.py +++ b/lib/matplotlib/backend_tools.py @@ -636,8 +636,14 @@ def update_home_views(self, figure=None): if a not in self.home_views[figure]: self.home_views[figure][a] = a._get_view() + @cbook.deprecated("3.3", alternative="self.figure.canvas.draw_idle()") def refresh_locators(self): """Redraw the canvases, update the locators.""" + self._refresh_locators() + + # Can be removed once Locator.refresh() is removed, and replaced by an + # inline call to self.figure.canvas.draw_idle(). + def _refresh_locators(self): for a in self.figure.get_axes(): xaxis = getattr(a, 'xaxis', None) yaxis = getattr(a, 'yaxis', None) @@ -654,7 +660,7 @@ def refresh_locators(self): locators.append(zaxis.get_minor_locator()) for loc in locators: - loc.refresh() + mpl.ticker._if_refresh_overridden_call_and_emit_deprec(loc) self.figure.canvas.draw_idle() def home(self): @@ -808,7 +814,7 @@ def _cancel_action(self): for zoom_id in self._ids_zoom: self.figure.canvas.mpl_disconnect(zoom_id) self.toolmanager.trigger_tool('rubberband', self) - self.toolmanager.get_tool(_views_positions).refresh_locators() + self.toolmanager.get_tool(_views_positions)._refresh_locators() self._xypress = None self._button_pressed = None self._ids_zoom = [] @@ -935,7 +941,7 @@ def _cancel_action(self): self._xypress = [] self.figure.canvas.mpl_disconnect(self._id_drag) self.toolmanager.messagelock.release(self) - self.toolmanager.get_tool(_views_positions).refresh_locators() + self.toolmanager.get_tool(_views_positions)._refresh_locators() def _press(self, event): if event.button == 1: diff --git a/lib/matplotlib/projections/polar.py b/lib/matplotlib/projections/polar.py index 6433d1ff1e4a..a039cd94b1e9 100644 --- a/lib/matplotlib/projections/polar.py +++ b/lib/matplotlib/projections/polar.py @@ -443,6 +443,7 @@ def pan(self, numsteps): def zoom(self, direction): return self.base.zoom(direction) + @cbook.deprecated("3.3") def refresh(self): # docstring inherited return self.base.refresh() diff --git a/lib/matplotlib/ticker.py b/lib/matplotlib/ticker.py index c2508f21f7d4..44ad98d375c5 100644 --- a/lib/matplotlib/ticker.py +++ b/lib/matplotlib/ticker.py @@ -1564,6 +1564,18 @@ def symbol(self, symbol): self._symbol = symbol +def _if_refresh_overridden_call_and_emit_deprec(locator): + if not locator.refresh.__func__.__module__.startswith("matplotlib."): + cbook.warn_external( + "3.3", message="Automatic calls to Locator.refresh by the draw " + "machinery are deprecated since %(since)s and will be removed in " + "%(removal)s. You are using a third-party locator that overrides " + "the refresh() method; this locator should instead perform any " + "required processing in __call__().") + with cbook._suppress_matplotlib_deprecation_warning(): + locator.refresh() + + class Locator(TickHelper): """ Determine the tick locations; @@ -1686,9 +1698,9 @@ def zoom(self, direction): step = 0.1 * interval * direction self.axis.set_view_interval(vmin + step, vmax - step, ignore=True) + @cbook.deprecated("3.3") def refresh(self): """Refresh internal information based on current limits.""" - pass class IndexLocator(Locator):