Skip to content

Commit ab249b4

Browse files
committed
MAINT: deprecate validCap, validJoin
1 parent eeef6e5 commit ab249b4

File tree

8 files changed

+90
-35
lines changed

8 files changed

+90
-35
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 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/__init__.py

+35-1
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,44 @@
1919
deprecated, warn_deprecated,
2020
_rename_parameter, _delete_parameter, _make_keyword_only,
2121
_deprecate_method_override, _deprecate_privatize_attribute,
22-
_suppress_matplotlib_deprecation_warning,
22+
suppress_matplotlib_deprecation_warning,
2323
MatplotlibDeprecationWarning)
2424

2525

26+
class classproperty:
27+
"""
28+
Like `property`, but also triggers on access via the class, and it is the
29+
*class* that's passed as argument.
30+
31+
Examples
32+
--------
33+
::
34+
35+
class C:
36+
@_classproperty
37+
def foo(cls):
38+
return cls.__name__
39+
40+
assert C.foo == "C"
41+
"""
42+
43+
def __init__(self, fget, fset=None, fdel=None, doc=None):
44+
self._fget = fget
45+
if fset is not None or fdel is not None:
46+
raise ValueError('_classproperty only implements fget.')
47+
self.fset = fset
48+
self.fdel = fdel
49+
# docs are ignored for now
50+
self._doc = doc
51+
52+
def __get__(self, instance, owner):
53+
return self._fget(owner)
54+
55+
@property
56+
def fget(self):
57+
return self._fget
58+
59+
2660
def check_in_list(_values, *, _print_supported_values=True, **kwargs):
2761
"""
2862
For each *key, value* pair in *kwargs*, check that *value* is in *_values*.

lib/matplotlib/_api/deprecation.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ def the_function_to_deprecate():
186186

187187
def deprecate(obj, message=message, name=name, alternative=alternative,
188188
pending=pending, obj_type=obj_type, addendum=addendum):
189+
from matplotlib._api import classproperty
189190

190191
if isinstance(obj, type):
191192
if obj_type is None:
@@ -202,15 +203,16 @@ def finalize(wrapper, new_doc):
202203
obj.__init__ = functools.wraps(obj.__init__)(wrapper)
203204
return obj
204205

205-
elif isinstance(obj, property):
206+
elif isinstance(obj, (property, classproperty)):
206207
obj_type = "attribute"
207208
func = None
208209
name = name or obj.fget.__name__
209210
old_doc = obj.__doc__
210211

211-
class _deprecated_property(property):
212+
class _deprecated_property(type(obj)):
212213
def __get__(self, instance, owner):
213-
if instance is not None:
214+
if instance is not None or owner is not None \
215+
and isinstance(self, classproperty):
214216
emit_warning()
215217
return super().__get__(instance, owner)
216218

@@ -518,7 +520,7 @@ def empty_with_docstring(): """doc"""
518520

519521

520522
@contextlib.contextmanager
521-
def _suppress_matplotlib_deprecation_warning():
523+
def suppress_matplotlib_deprecation_warning():
522524
with warnings.catch_warnings():
523525
warnings.simplefilter("ignore", MatplotlibDeprecationWarning)
524526
yield

lib/matplotlib/cbook/__init__.py

+3-25
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,13 @@
2929

3030
import matplotlib
3131
from matplotlib import _c_internal_utils
32-
from matplotlib._api import warn_external as _warn_external
32+
from matplotlib._api import (
33+
warn_external as _warn_external, classproperty as _classproperty)
3334
from matplotlib._api.deprecation import (
3435
deprecated, warn_deprecated,
3536
_rename_parameter, _delete_parameter, _make_keyword_only,
3637
_deprecate_method_override, _deprecate_privatize_attribute,
38+
suppress_matplotlib_deprecation_warning as
3739
_suppress_matplotlib_deprecation_warning,
3840
MatplotlibDeprecationWarning, mplDeprecation)
3941

@@ -2262,30 +2264,6 @@ def type_name(tp):
22622264
type_name(type(v))))
22632265

22642266

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-
22892267
def _backend_module_name(name):
22902268
"""
22912269
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

+12-2
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,18 @@ class Patch(artist.Artist):
3333
are *None*, they default to their rc params setting.
3434
"""
3535
zorder = 1
36-
validCap = mlines.Line2D.validCap
37-
validJoin = mlines.Line2D.validJoin
36+
37+
@_api.deprecated("3.4")
38+
@_api.classproperty
39+
def validCap(cls):
40+
with _api.suppress_matplotlib_deprecation_warning():
41+
return mlines.Line2D.validCap
42+
43+
@_api.deprecated("3.4")
44+
@_api.classproperty
45+
def validJoin(cls):
46+
with _api.suppress_matplotlib_deprecation_warning():
47+
return mlines.Line2D.validJoin
3848

3949
# Whether to draw an edge by default. Set on a
4050
# subclass-by-subclass basis.

lib/matplotlib/tests/test_api.py

+14
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import pytest
55

66
from matplotlib import _api
7+
from matplotlib._api.deprecation import deprecated
78

89

910
@pytest.mark.parametrize('target,test_shape',
@@ -19,3 +20,16 @@ def test_check_shape(target, test_shape):
1920
data = np.zeros(test_shape)
2021
with pytest.raises(ValueError, match=error_pattern):
2122
_api.check_shape(target, aardvark=data)
23+
24+
25+
def test_classproperty_deprecation():
26+
class A:
27+
@_api.deprecated("0.0.0")
28+
@_api.classproperty
29+
def f(cls):
30+
pass
31+
with pytest.warns(_api.MatplotlibDeprecationWarning):
32+
A.f
33+
with pytest.warns(_api.MatplotlibDeprecationWarning):
34+
a = A()
35+
a.f

0 commit comments

Comments
 (0)