From eb76378585eee6d8f797b8e423b59591a8f15eed Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Wed, 4 Dec 2019 00:57:44 +0100 Subject: [PATCH] Deprecate support for dash-offset = None. e.g. `plot([1, 2], ls=(None, (4, 4)))` which was previously a synonym for `plot([1, 2], ls=(0, (4, 4)))` which means "dash-pattern of 4pt-long dashes separated by 4pt spaces, with an offset of 0pt at start". Passing None instead of 0 was already not (likely, never) supported for pdf, ps, or svg (an exception is raised at savefig() time for ps/svg, an invalid pdf is generated). There isn't much of a point in supporting None (this also makes e.g. mplcairo more complex because of static typing in C++ extensions), so just deprecate it. --- doc/api/next_api_changes/deprecations.rst | 9 ++++++++ .../legend_demo.py | 2 +- lib/matplotlib/backend_bases.py | 2 +- lib/matplotlib/collections.py | 6 ++--- lib/matplotlib/lines.py | 22 ++++++++++--------- lib/matplotlib/rcsetup.py | 8 ++++++- lib/matplotlib/tests/test_collections.py | 6 ++--- lib/matplotlib/tests/test_rcparams.py | 7 +++--- src/py_converters.cpp | 8 +++++++ 9 files changed, 47 insertions(+), 23 deletions(-) diff --git a/doc/api/next_api_changes/deprecations.rst b/doc/api/next_api_changes/deprecations.rst index 63ad76a5762a..987024602da6 100644 --- a/doc/api/next_api_changes/deprecations.rst +++ b/doc/api/next_api_changes/deprecations.rst @@ -264,3 +264,12 @@ method consistent across all artists; thus, additional parameters to ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This method is deprecated. `.DraggableBase.on_motion` now handles both the blitting and the non-blitting cases. + +Passing the dash offset as None +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Fine control of dash patterns can be achieved by passing an ``(offset, +(on-length, off-length, on-length, off-length, ...))`` pair as the linestyle +property of `.Line2D` and `.LineCollection`. Previously, certain APIs would +accept ``offset = None`` as a synonym for ``offset = 0``, but this was never +universally implemented, e.g. for vector output. Support for ``offset = None`` +is deprecated, set the offset to 0 instead. diff --git a/examples/text_labels_and_annotations/legend_demo.py b/examples/text_labels_and_annotations/legend_demo.py index 20fd9325993b..f90297b87c8d 100644 --- a/examples/text_labels_and_annotations/legend_demo.py +++ b/examples/text_labels_and_annotations/legend_demo.py @@ -153,7 +153,7 @@ def create_artists(self, legend, orig_handle, lw = orig_handle.get_linewidths()[i] except IndexError: lw = orig_handle.get_linewidths()[0] - if dashes[0] is not None: + if dashes[1] is not None: legline.set_dashes(dashes[1]) legline.set_color(color) legline.set_transform(trans) diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index d77d2aaeaf36..b17da96dbee9 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -711,7 +711,7 @@ def __init__(self): self._capstyle = 'butt' self._cliprect = None self._clippath = None - self._dashes = None, None + self._dashes = 0, None self._joinstyle = 'round' self._linestyle = 'solid' self._linewidth = 1 diff --git a/lib/matplotlib/collections.py b/lib/matplotlib/collections.py index 94b1ce1ed91b..ea86b3f5a85f 100644 --- a/lib/matplotlib/collections.py +++ b/lib/matplotlib/collections.py @@ -115,9 +115,9 @@ def __init__(self, cm.ScalarMappable.__init__(self, norm, cmap) # list of un-scaled dash patterns # this is needed scaling the dash pattern by linewidth - self._us_linestyles = [(None, None)] + self._us_linestyles = [(0, None)] # list of dash patterns - self._linestyles = [(None, None)] + self._linestyles = [(0, None)] # list of unbroadcast/scaled linewidths self._us_lw = [0] self._linewidths = [0] @@ -333,7 +333,7 @@ def draw(self, renderer): if (len(paths) == 1 and len(trans) <= 1 and len(facecolors) == 1 and len(edgecolors) == 1 and len(self._linewidths) == 1 and - self._linestyles == [(None, None)] and + all(ls[1] is None for ls in self._linestyles) and len(self._antialiaseds) == 1 and len(self._urls) == 1 and self.get_hatch() is None): if len(trans): diff --git a/lib/matplotlib/lines.py b/lib/matplotlib/lines.py index fd6f103a2c0d..3b2b71807313 100644 --- a/lib/matplotlib/lines.py +++ b/lib/matplotlib/lines.py @@ -38,7 +38,8 @@ def _get_dash_pattern(style): style = ls_mapper.get(style, style) # un-dashed styles if style in ['solid', 'None']: - offset, dashes = None, None + offset = 0 + dashes = None # dashed styles elif style in ['dashed', 'dashdot', 'dotted']: offset = 0 @@ -46,11 +47,17 @@ def _get_dash_pattern(style): # elif isinstance(style, tuple): offset, dashes = style + if offset is None: + cbook.warn_deprecated( + "3.3", message="Passing the dash offset as None is deprecated " + "since %(since)s and support for it will be removed " + "%(removal)s; pass it as zero instead.") + offset = 0 else: raise ValueError('Unrecognized linestyle: %s' % str(style)) # normalize offset to be positive and shorter than the dash cycle - if dashes is not None and offset is not None: + if dashes is not None: dsum = sum(dashes) if dsum: offset %= dsum @@ -61,14 +68,9 @@ def _get_dash_pattern(style): def _scale_dashes(offset, dashes, lw): if not rcParams['lines.scale_dashes']: return offset, dashes - - scaled_offset = scaled_dashes = None - if offset is not None: - scaled_offset = offset * lw - if dashes is not None: - scaled_dashes = [x * lw if x is not None else None - for x in dashes] - + scaled_offset = offset * lw + scaled_dashes = ([x * lw if x is not None else None for x in dashes] + if dashes is not None else None) return scaled_offset, scaled_dashes diff --git a/lib/matplotlib/rcsetup.py b/lib/matplotlib/rcsetup.py index 9eefcccdcbc7..d9b3b01571d3 100644 --- a/lib/matplotlib/rcsetup.py +++ b/lib/matplotlib/rcsetup.py @@ -579,12 +579,18 @@ def _is_iterable_not_string_like(x): and _is_iterable_not_string_like(ls[1]) and len(ls[1]) % 2 == 0 and all(isinstance(elem, Number) for elem in ls[1])): + if ls[0] is None: + cbook.warn_deprecated( + "3.3", message="Passing the dash offset as None is deprecated " + "since %(since)s and support for it will be removed " + "%(removal)s; pass it as zero instead.") + ls = (0, ls[1]) return ls # For backcompat: (on, off, on, off, ...); the offset is implicitly None. if (_is_iterable_not_string_like(ls) and len(ls) % 2 == 0 and all(isinstance(elem, Number) for elem in ls)): - return (None, ls) + return (0, ls) raise ValueError(f"linestyle {ls!r} is not a valid on-off ink sequence.") diff --git a/lib/matplotlib/tests/test_collections.py b/lib/matplotlib/tests/test_collections.py index 75cdbf0ce7c5..59aabf0fae98 100644 --- a/lib/matplotlib/tests/test_collections.py +++ b/lib/matplotlib/tests/test_collections.py @@ -77,7 +77,7 @@ def test__EventCollection__get_props(): # check that the default lineoffset matches the input lineoffset assert props['lineoffset'] == coll.get_lineoffset() # check that the default linestyle matches the input linestyle - assert coll.get_linestyle() == [(None, None)] + assert coll.get_linestyle() == [(0, None)] # check that the default color matches the input color for color in [coll.get_color(), *coll.get_colors()]: np.testing.assert_array_equal(color, props['color']) @@ -501,11 +501,11 @@ def test_lslw_bcast(): col.set_linestyles(['-', '-']) col.set_linewidths([1, 2, 3]) - assert col.get_linestyles() == [(None, None)] * 6 + assert col.get_linestyles() == [(0, None)] * 6 assert col.get_linewidths() == [1, 2, 3] * 2 col.set_linestyles(['-', '-', '-']) - assert col.get_linestyles() == [(None, None)] * 3 + assert col.get_linestyles() == [(0, None)] * 3 assert (col.get_linewidths() == [1, 2, 3]).all() diff --git a/lib/matplotlib/tests/test_rcparams.py b/lib/matplotlib/tests/test_rcparams.py index d68e2a94f693..35a17ffc9c41 100644 --- a/lib/matplotlib/tests/test_rcparams.py +++ b/lib/matplotlib/tests/test_rcparams.py @@ -370,10 +370,9 @@ def generate_validator_testcases(valid): ('', ''), (' ', ' '), ('None', 'none'), ('none', 'none'), ('DoTtEd', 'dotted'), # case-insensitive - ('1, 3', (None, (1, 3))), - ([1.23, 456], (None, [1.23, 456.0])), - ([1, 2, 3, 4], (None, [1.0, 2.0, 3.0, 4.0])), - ((None, [1, 2]), (None, [1, 2])), + ('1, 3', (0, (1, 3))), + ([1.23, 456], (0, [1.23, 456.0])), + ([1, 2, 3, 4], (0, [1.0, 2.0, 3.0, 4.0])), ((0, [1, 2]), (0, [1, 2])), ((-1, [1, 2]), (-1, [1, 2])), ), diff --git a/src/py_converters.cpp b/src/py_converters.cpp index 03fdb5845bef..b5e88dd0b2b5 100644 --- a/src/py_converters.cpp +++ b/src/py_converters.cpp @@ -237,6 +237,14 @@ int convert_dashes(PyObject *dashobj, void *dashesp) if (PyErr_Occurred()) { return 0; } + } else { + if (PyErr_WarnEx(PyExc_FutureWarning, + "Passing the dash offset as None is deprecated since " + "Matplotlib 3.3 and will be removed in Matplotlib 3.5; " + "pass it as zero instead.", + 1)) { + return 0; + } } if (dashes_seq == Py_None) { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy