8000 Merge branch 'v2.0.x' · matplotlib/matplotlib@b7c7c5e · GitHub
[go: up one dir, main page]

Skip to content

Commit b7c7c5e

Browse files
committed
Merge branch 'v2.0.x'
2 parents 7a29ad1 + 16f4895 commit b7c7c5e

File tree

2 files changed

+67
-41
lines changed

2 files changed

+67
-41
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
`Artist.update` has return value
2+
````````````````````````````````
3+
4+
The methods `matplotlib.artist.Artist.set`,
5+
`matplotlib.Artist.update`, and the function `matplotlib.artist.setp`
6+
now use a common codepath to look up how to update the given artist
7+
properties (either using the setter methods or an attribute/property).
8+
9+
The behavior of `matplotlib.Artist.update` is slightly changed to
10+
return a list of the returned values from the setter methods to avoid
11+
changing the API of `matplotlib.Artist.set` and
12+
`matplotlib.artist.setp`.
13+
14+
The keys passed into `matplotlib.Artist.update` are now converted to
15+
lower case before being processed to match the behavior of
16+
`matplotlib.Artist.set` and `matplotlib.artist.setp`. This should not
17+
break any user code because there are no set methods with capitals in
18+
the names, however going forward this puts a constraint on naming
19+
properties.

lib/matplotlib/artist.py

Lines changed: 48 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
unicode_literals)
33

44
from matplotlib.externals import six
5+
from collections import OrderedDict
56

67
import re
78
import warnings
@@ -82,6 +83,10 @@ class Artist(object):
8283

8384
aname = 'Artist'
8485
zorder = 0
86+
# order of precedence when bulk setting/updating properties
87+
# via update. The keys should be property names and the values
88+
# integers
89+
_prop_order = dict(color=-1)
8590

8691
def __init__(self):
8792
self._stale = True
@@ -846,23 +851,43 @@ def update(self, props):
846851
Update the properties of this :class:`Artist` from the
847852
dictionary *prop*.
848853
"""
849-
store = self.eventson
850-
self.eventson = False
851-
changed = False
852-
853-
for k, v in six.iteritems(props):
854-
if k in ['axes']:
855-
setattr(self, k, v)
854+
def _update_property(self, k, v):
855+
"""sorting out how to update property (setter or setattr)
856+
857+
Parameters
858+
----------
859+
k : str
860+
The name of property to update
861+
v : obj
862+
The value to assign to the property
863+
Returns
864+
-------
865+
ret : obj or None
866+
If using a `set_*` method return it's return, else None.
867+
"""
868+
k = k.lower()
869+
# white list attributes we want to be able to update through
870+
# art.update, art.set, setp
871+
if k in {'axes'}:
872+
return setattr(self, k, v)
856873
else:
857874
func = getattr(self, 'set_' + k, None)
858875
if func is None or not six.callable(func):
859876
raise AttributeError('Unknown property %s' % k)
860-
func(v)
861-
changed = True
862-
self.eventson = store
863-
if changed:
877+
return func(v)
878+
879+
store = self.eventson
880+
self.eventson = False
881+
try:
882+
ret = [_update_property(self, k, v)
883+
for k, v in props.items()]
884+
finally:
885+
self.eventson = store
886+
887+
if len(ret):
864888
self.pchanged()
865889
self.stale = True
890+
return ret
866891

867892
def get_label(self):
868893
"""
@@ -1015,23 +1040,13 @@ def properties(self):
10151040
return ArtistInspector(self).properties()
10161041

10171042
def set(self, **kwargs):
1043+
"""A property batch setter. Pass *kwargs* to set properties.
10181044
"""
1019-
A property batch setter. Pass *kwargs* to set properties.
1020-
Will handle property name collisions (e.g., if both
1021-
'color' and 'facecolor' are specified, the property
1022-
with higher priority gets set last).
1045+
props = OrderedDict(
1046+
sorted(kwargs.items(), reverse=True,
1047+
key=lambda x: (self._prop_order.get(x[0], 0), x[0])))
10231048

1024-
"""
1025-
ret = []
1026-
for k, v in sorted(kwargs.items(), reverse=True):
1027-
k = k.lower()
1028-
funcName = "set_%s" % k
1029-
func = getattr(self, funcName, None)
1030-
if func is None:
1031-
raise TypeError('There is no %s property "%s"' %
1032-
(self.__class__.__name__, k))
1033-
ret.extend([func(v)])
1034-
return ret
1049+
return self.update(props)
10351050

10361051
def findobj(self, match=None, include_self=True):
10371052
"""
@@ -1541,26 +1556,18 @@ def setp(obj, *args, **kwargs):
15411556
if not cbook.iterable(obj):
15421557
objs = [obj]
15431558
else:
1544-
objs = cbook.flatten(obj)
1559+
objs = list(cbook.flatten(obj))
15451560

15461561
if len(args) % 2:
15471562
raise ValueError('The set args must be string, value pairs')
15481563

1549-
funcvals = []
1564+
# put args into ordereddict to maintain order
1565+
funcvals = OrderedDict()
15501566
for i in range(0, len(args) - 1, 2):
1551-
funcvals.append((args[i], args[i + 1]))
1552-
funcvals.extend(sorted(kwargs.items(), reverse=True))
1553-
1554-
ret = []
1555-
for o in objs:
1556-
for s, val in funcvals:
1557-
s = s.lower()
1558-
funcName = "set_%s" % s
1559-
func = getattr(o, funcName, None)
1560-
if func is None:
1561-
raise TypeError('There is no %s property "%s"' %
1562-
(o.__class__.__name__, s))
1563-
ret.extend([func(val)])
1567+
funcvals[args[i]] = args[i + 1]
1568+
1569+
ret = [o.update(funcvals) for o in objs]
1570+
ret.extend([o.set(**kwargs) for o in objs])
15641571
return [x for x in cbook.flatten(ret)]
15651572

15661573

0 commit comments

Comments
 (0)
0