Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a57ea3d

Browse files
authored
Merge pull request #16328 from anntzer/setkworder
Make Artist.set() apply properties in the order in which they are given.
2 parents 069fea5 + 71d725f commit a57ea3d

File tree

3 files changed

+47
-45
lines changed

3 files changed

+47
-45
lines changed

doc/api/api_changes_3.3/deprecations.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,3 +545,12 @@ The ``cbid`` and ``locator`` attribute are deprecated. Use
545545
~~~~~~~~~~~~~~~~~~~~~~
546546
This function is deprecated in prevision of the future release of PyQt6. The
547547
Qt version can be checked using ``QtCore.QT_VERSION_STR``.
548+
549+
Reordering of parameters by `.Artist.set`
550+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
551+
In a future version, ``Artist.set`` will apply artist properties in the order
552+
in which they are given. This only affects the interaction between the
553+
*color*, *edgecolor*, *facecolor*, and, for `.Collection`\s, *alpha*
554+
properties: the *color* property now needs to be passed first in order not to
555+
override the other properties. This is consistent with e.g. `.Artist.update`,
556+
which did not reorder the properties passed to it.

lib/matplotlib/artist.py

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,6 @@ class Artist:
6565
"""
6666

6767
zorder = 0
68-
# order of precedence when bulk setting/updating properties
69-
# via update. The keys should be property names and the values
70-
# integers
71-
_prop_order = dict(color=-1)
7268

7369
def __init__(self):
7470
self._stale = True
@@ -1088,10 +1084,31 @@ def properties(self):
10881084
def set(self, **kwargs):
10891085
"""A property batch setter. Pass *kwargs* to set properties."""
10901086
kwargs = cbook.normalize_kwargs(kwargs, self)
1091-
props = OrderedDict(
1092-
sorted(kwargs.items(), reverse=True,
1093-
key=lambda x: (self._prop_order.get(x[0], 0), x[0])))
1094-
return self.update(props)
1087+
move_color_to_start = False
1088+
if "color" in kwargs:
1089+
keys = [*kwargs]
1090+
i_color = keys.index("color")
1091+
props = ["edgecolor", "facecolor"]
1092+
if any(tp.__module__ == "matplotlib.collections"
1093+
and tp.__name__ == "Collection"
1094+
for tp in type(self).__mro__):
1095+
props.append("alpha")
1096+
for other in props:
1097+
if other not in keys:
1098+
continue
1099+
i_other = keys.index(other)
1100+
if i_other < i_color:
1101+
move_color_to_start = True
1102+
cbook.warn_deprecated(
1103+
"3.3", message=f"You have passed the {other!r} kwarg "
1104+
"before the 'color' kwarg. Artist.set() currently "
1105+
"reorders the properties to apply 'color' first, but "
1106+
"this is deprecated since %(since)s and will be "
1107+
"removed %(removal)s; please pass 'color' first "
1108+
"instead.")
1109+
if move_color_to_start:
1110+
kwargs = {"color": kwargs.pop("color"), **kwargs}
1111+
return self.update(kwargs)
10951112

10961113
def findobj(self, match=None, include_self=True):
10971114
"""

lib/matplotlib/cbook/__init__.py

Lines changed: 13 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1671,43 +1671,19 @@ def normalize_kwargs(kw, alias_mapping=None, required=(), forbidden=(),
16711671
or isinstance(alias_mapping, Artist)):
16721672
alias_mapping = getattr(alias_mapping, "_alias_map", {})
16731673

1674-
# make a local so we can pop
1675-
kw = dict(kw)
1676-
# output dictionary
1677-
ret = dict()
1678-
1679-
# hit all alias mappings
1680-
for canonical, alias_list in alias_mapping.items():
1681-
1682-
# the alias lists are ordered from lowest to highest priority
1683-
# so we know to use the last value in this list
1684-
tmp = []
1685-
seen = []
1686-
for a in alias_list:
1687-
try:
1688-
tmp.append(kw.pop(a))
1689-
seen.append(a)
1690-
except KeyError:
1691-
pass
1692-
# if canonical is not in the alias_list assume highest priority
1693-
if canonical not in alias_list:
1694-
try:
1695-
tmp.append(kw.pop(canonical))
1696-
seen.append(canonical)
1697-
except KeyError:
1698-
pass
1699-
# if we found anything in this set of aliases put it in the return
1700-
# dict
1701-
if tmp:
1702-
ret[canonical] = tmp[-1]
1703-
if len(tmp) > 1:
1704-
raise TypeError("Got the following keyword arguments which "
1705-
"are aliases of one another: {}"
1706-
.format(", ".join(map(repr, seen))))
1707-
1708-
# at this point we know that all keys which are aliased are removed, update
1709-
# the return dictionary from the cleaned local copy of the input
1710-
ret.update(kw)
1674+
to_canonical = {alias: canonical
1675+
for canonical, alias_list in alias_mapping.items()
1676+
for alias in alias_list}
1677+
canonical_to_seen = {}
1678+
ret = {} # output dictionary
1679+
1680+
for k, v in kw.items():
1681+
canonical = to_canonical.get(k, k)
1682+
if canonical in canonical_to_seen:
1683+
raise TypeError(f"Got both {canonical_to_seen[canonical]!r} and "
1684+
f"{k!r}, which are aliases of one another")
1685+
canonical_to_seen[canonical] = k
1686+
ret[canonical] = v
17111687

17121688
fail_keys = [k for k in required if k not in ret]
17131689
if fail_keys:

0 commit comments

Comments
 (0)