Skip to content

Commit aed162f

Browse files
committed
MAINT: deprecate validCap, validJoin
1 parent 82e2f94 commit aed162f

File tree

7 files changed

+92
-33
lines changed

7 files changed

+92
-33
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Line2D and Patch no longer duplicate ``validJoin`` and ``validCap``
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
Validation of joinstyle and capstyles is now centralized in ``rcsetup``.

doc/conf.py

+7
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
import shutil
1414
import subprocess
1515
import sys
16+
import warnings
1617

1718
import matplotlib
19+
from matplotlib._api.deprecation import MatplotlibDeprecationWarning
1820
import sphinx
1921

2022
from datetime import datetime
@@ -109,6 +111,11 @@ def _check_dependencies():
109111
autodoc_docstring_signature = True
110112
autodoc_default_options = {'members': None, 'undoc-members': None}
111113

114+
# make sure to ignore warnings that stem from simply inspecting deprecated
115+
# class-level attributes
116+
warnings.filterwarnings('ignore', category=MatplotlibDeprecationWarning,
117+
module='sphinx.util.inspect')
118+
112119
# missing-references names matches sphinx>=3 behavior, so we can't be nitpicky
113120
# for older sphinxes.
114121
nitpicky = sphinx.version_info >= (3,)

lib/matplotlib/_api/deprecation.py

+40-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,42 @@
1616
import warnings
1717

1818

19+
# has to be here (instead of cbook) to prevent circular import, since
20+
# deprecation.deprecated is *used* during cbook's import
21+
class _classproperty:
22+
"""
23+
Like `property`, but also triggers on access via the class, and it is the
24+
*class* that's passed as argument.
25+
26+
Examples
27+
--------
28+
::
29+
30+
class C:
31+
@_classproperty
32+
def foo(cls):
33+
return cls.__name__
34+
35+
assert C.foo == "C"
36+
"""
37+
38+
def __init__(self, fget, fset=None, fdel=None, doc=None):
39+
self._fget = fget
40+
if fset is not None or fdel is not None:
41+
raise ValueError('_classproperty only implements fget.')
42+
self.fset = fset
43+
self.fdel = fdel
44+
# docs are ignored for now
45+
self._doc = doc
46+
47+
def __get__(self, instance, owner):
48+
return self._fget(owner)
49+
50+
@property
51+
def fget(self):
52+
return self._fget
53+
54+
1955
class MatplotlibDeprecationWarning(UserWarning):
2056
"""
2157
A class for issuing deprecation warnings for Matplotlib users.
@@ -201,15 +237,16 @@ def finalize(wrapper, new_doc):
201237
obj.__init__ = functools.wraps(obj.__init__)(wrapper)
202238
return obj
203239

204-
elif isinstance(obj, property):
240+
elif isinstance(obj, (property, _classproperty)):
205241
obj_type = "attribute"
206242
func = None
207243
name = name or obj.fget.__name__
208244
old_doc = obj.__doc__
209245

210-
class _deprecated_property(property):
246+
class _deprecated_property(type(obj)):
211247
def __get__(self, instance, owner):
212-
if instance is not None:
248+
if instance is not None or owner is not None \
249+
and isinstance(self, _classproperty):
213250
emit_warning()
214251
return super().__get__(instance, owner)
215252

lib/matplotlib/cbook/__init__.py

+1-25
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
_rename_parameter, _delete_parameter, _make_keyword_only,
3636
_deprecate_method_override, _deprecate_privatize_attribute,
3737
_suppress_matplotlib_deprecation_warning,
38-
MatplotlibDeprecationWarning, mplDeprecation)
38+
MatplotlibDeprecationWarning, mplDeprecation, _classproperty)
3939

4040

4141
def _get_running_interactive_framework():
@@ -2262,30 +2262,6 @@ def type_name(tp):
22622262
type_name(type(v))))
22632263

22642264

2265-
class _classproperty:
2266-
"""
2267-
Like `property`, but also triggers on access via the class, and it is the
2268-
*class* that's passed as argument.
2269-
2270-
Examples
2271-
--------
2272-
::
2273-
2274-
class C:
2275-
@classproperty
2276-
def foo(cls):
2277-
return cls.__name__
2278-
2279-
assert C.foo == "C"
2280-
"""
2281-
2282-
def __init__(self, fget):
2283-
self._fget = fget
2284-
2285-
def __get__(self, instance, owner):
2286-
return self._fget(owner)
2287-
2288-
22892265
def _backend_module_name(name):
22902266
"""
22912267
Convert a backend name (either a standard backend -- "Agg", "TkAgg", ... --

lib/matplotlib/lines.py

+10-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
colors.
44
"""
55

6-
# TODO: expose cap and join style attrs
76
from numbers import Integral, Number, Real
87
import logging
98

@@ -251,8 +250,16 @@ class Line2D(Artist):
251250
fillStyles = MarkerStyle.fillstyles
252251

253252
zorder = 2
254-
validCap = ('butt', 'round', 'projecting')
255-
validJoin = ('miter', 'round', 'bevel')
253+
254+
@_api.deprecated("3.4")
255+
@_api._classproperty
256+
def validCap(cls):
257+
return ('butt', 'round', 'projecting')
258+
259+
@_api.deprecated("3.4")
260+
@_api._classproperty
261+
def validJoin(cls):
262+
return ('miter', 'round', 'bevel')
256263

257264
def __str__(self):
258265
if self._label != "":

lib/matplotlib/patches.py

+15-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from numbers import Number
66
import textwrap
77
from collections import namedtuple
8+
import warnings
89

910
import numpy as np
1011

@@ -33,8 +34,20 @@ class Patch(artist.Artist):
3334
are *None*, they default to their rc params setting.
3435
"""
3536
zorder = 1
36-
validCap = mlines.Line2D.validCap
37-
validJoin = mlines.Line2D.validJoin
37+
38+
@_api.deprecated("3.4")
39+
@_api._classproperty
40+
def validCap(cls):
41+
with warnings.catch_warnings():
42+
cbook._suppress_matplotlib_deprecation_warning()
43+
return mlines.Line2D.validCap
44+
45+
@_api.deprecated("3.4")
46+
@_api._classproperty
47+
def validJoin(cls):
48+
with warnings.catch_warnings():
49+
cbook._suppress_matplotlib_deprecation_warning()
50+
return mlines.Line2D.validJoin
3851

3952
# Whether to draw an edge by default. Set on a
4053
# subclass-by-subclass basis.

lib/matplotlib/tests/test_api.py

+16
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
import pytest
55

66
from matplotlib import _api
7+
from matplotlib.cbook import (
8+
_classproperty, MatplotlibDeprecationWarning)
9+
from matplotlib._api.deprecation import deprecated
710

811

912
@pytest.mark.parametrize('target,test_shape',
@@ -19,3 +22,16 @@ def test_check_shape(target, test_shape):
1922
data = np.zeros(test_shape)
2023
with pytest.raises(ValueError, match=error_pattern):
2124
_api.check_shape(target, aardvark=data)
25+
26+
27+
def test_classproperty_deprecation():
28+
class A:
29+
@deprecated("0.0.0")
30+
@_classproperty
31+
def f(cls):
32+
pass
33+
with pytest.warns(MatplotlibDeprecationWarning):
34+
A.f
35+
with pytest.warns(MatplotlibDeprecationWarning):
36+
a = A()
37+
a.f

0 commit comments

Comments
 (0)