-
Notifications
You must be signed in to change notification settings - Fork 103
/
Copy pathartist.py
86 lines (76 loc) · 2.27 KB
/
artist.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#!/usr/bin/env python3
"""
Add dot-notation properties for matplotlib setter and getter functions.
"""
import warnings
import matplotlib.artist as martist
from matplotlib import MatplotlibDeprecationWarning
__all__ = []
PROPS_IGNORE = (
# Axes props
'axes',
'figure',
'xaxis', # axes prop
'yaxis', # axes prop
'zaxis', # axes prop
'units', # axis prop
'gridlines',
# Method conflicts
'legend',
'tight_layout',
# Class-level conflicts
'contains',
'zorder',
'pickradius', # line property related to 'contains'
# Instance-level artist conflicts
'label',
'label_position',
# Instance-level axes conflicts
'cmap',
'norm',
'lines',
'images',
'title', # TODO: use internal title handling
)
def _iter_subclasses(cls):
"""
Iterate through all subclasses.
"""
yield cls
try:
for subclass in cls.__subclasses__():
yield from _iter_subclasses(subclass)
except TypeError:
pass
def _add_properties(cls):
"""
Generate property definitions for every artist getter.
"""
for attr in dir(cls):
try:
getter = getattr(cls, attr)
except MatplotlibDeprecationWarning:
continue
if not callable(getter) or attr[:4] != 'get_':
continue
prop = attr[4:]
if prop in PROPS_IGNORE:
continue
if hasattr(cls, prop):
value = getattr(cls, prop)
if not isinstance(value, property): # i.e. this is not child of a class
warnings._warn_proplot(f'Skipping property {prop!r}. Already exists as attribute.') # noqa: E501
continue
args = [getter] # property() function args
setter = getattr(cls, 'set_' + prop, None)
if callable(setter):
args.append(setter)
obj = property(*args, doc=getter.__doc__)
setattr(cls, prop, obj)
# Apply properties
# NOTE: While we can guard against class-level attribute conflicts we *cannot* guard
# against instance-level attribute conflicts. Therefore this may never work.
for cls in _iter_subclasses(martist.Artist):
with warnings.catch_warnings():
warnings.simplefilter('error', MatplotlibDeprecationWarning)
_add_properties(cls)