Skip to content

Commit 9de925e

Browse files
committed
Revert "simplify"
This reverts commit ab39326.
1 parent 292b3e5 commit 9de925e

File tree

4 files changed

+63
-62
lines changed

4 files changed

+63
-62
lines changed

lib/matplotlib/_style_helpers.py

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,41 @@
11
import collections.abc
22
import itertools
33

4+
import numpy as np
5+
46
import matplotlib.cbook as cbook
57
import matplotlib.colors as mcolors
68
import matplotlib.lines as mlines
79

810

9-
1011
def check_non_empty(key, value):
1112
"""Raise a TypeError if an empty sequence is passed"""
12-
if isinstance(value, collections.abc.Sized) and len(value) == 0:
13+
if (not cbook.is_scalar_or_string(value) and
14+
isinstance(value, collections.abc.Sized) and len(value) == 0):
1315
raise TypeError(f'{key} must not be an empty sequence')
1416

1517

16-
def iterate_styles(kw):
18+
def style_generator(kw):
1719
"""
1820
Helper for handling style sequences (e.g. facecolor=['r', 'b', 'k']) within plotting
19-
methods that repeatedly call other plotting methods (e.g. hist, stackplot).
20-
21-
Given a dictionary of keyword parameters, yield a series of copies of the
22-
dictionary. Style parameters expressed as sequences are replaced in the copy with
23-
the next element of the sequence.
24-
25-
Note 'color' is deliberately not handled since the calling methods have their own
26-
handling for that.
21+
methods that repeatedly call other plotting methods (e.g. hist, stackplot). Remove
22+
style keywords from the given dictionary. Return the reduced dictionary together
23+
with a generator which provides a series of dictionaries to be used in each call to
24+
the wrapped function.
2725
"""
2826
kw_iterators = {}
2927
remaining_kw = {}
3028
for key, value in kw.items():
31-
if cbook.is_scalar_or_string(value):
32-
# No iteration required
33-
remaining_kw[key] = value
34-
35-
elif key in ['facecolor', 'edgecolor']:
36-
check_non_empty(key, value)
37-
kw_iterators[key] = itertools.cycle(mcolors.to_rgba_array(value))
29+
if key in ['facecolor', 'edgecolor']:
30+
if value is None or cbook._str_lower_equal(value, 'none'):
31+
kw_iterators[key] = itertools.repeat(value)
32+
else:
33+
check_non_empty(key, value)
34+
kw_iterators[key] = itertools.cycle(mcolors.to_rgba_array(value))
3835

3936
elif key in ['hatch', 'linewidth']:
4037
check_non_empty(key, value)
41-
kw_iterators[key] = itertools.cycle(value)
38+
kw_iterators[key] = itertools.cycle(np.atleast_1d(value))
4239

4340
elif key == 'linestyle':
4441
check_non_empty(key, value)
@@ -47,6 +44,8 @@ def iterate_styles(kw):
4744
else:
4845
remaining_kw[key] = value
4946

47+
def style_gen():
48+
while True:
49+
yield {key: next(val) for key, val in kw_iterators.items()}
5050

51-
while True:
52-
yield {key: next(val) for key, val in kw_iterators.items()} | remaining_kw
51+
return remaining_kw, style_gen()

lib/matplotlib/axes/_axes.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3324,7 +3324,7 @@ def grouped_bar(self, heights, *, positions=None, group_spacing=1.5, bar_spacing
33243324
# TODO: do we want to be more restrictive and check lengths?
33253325
colors = itertools.cycle(colors)
33263326

3327-
kwargs_gen = _style_helpers.iterate_styles(kwargs)
3327+
kwargs, style_gen = _style_helpers.style_generator(kwargs)
33283328

33293329
bar_width = (group_distance /
33303330
(num_datasets + (num_datasets - 1) * bar_spacing + group_spacing))
@@ -3339,15 +3339,16 @@ def grouped_bar(self, heights, *, positions=None, group_spacing=1.5, bar_spacing
33393339
# place the bars, but only use numerical positions, categorical tick labels
33403340
# are handled separately below
33413341
bar_containers = []
3342-
for i, (hs, label, color) in enumerate(zip(heights, labels, colors)):
3342+
for i, (hs, label, color, styles) in enumerate(zip(heights, labels, colors,
3343+
style_gen)):
33433344
lefts = (group_centers - 0.5 * group_distance + margin_abs
33443345
+ i * (bar_width + bar_spacing_abs))
33453346
if orientation == "vertical":
33463347
bc = self.bar(lefts, hs, width=bar_width, align="edge",
3347-
label=label, color=color, **next(kwargs_gen))
3348+
label=label, color=color, **styles, **kwargs)
33483349
else:
33493350
bc = self.barh(lefts, hs, height=bar_width, align="edge",
3350-
label=label, color=color, **next(kwargs_gen))
3351+
label=label, color=color, **styles, **kwargs)
33513352
bar_containers.append(bc)
33523353

33533354
if tick_labels is not None:
@@ -7640,18 +7641,18 @@ def hist(self, x, bins=None, range=None, density=False, weights=None,
76407641
if histtype == "step":
76417642
kwargs.setdefault('edgecolor', colors)
76427643

7643-
kwargs_gen = _style_helpers.iterate_styles(kwargs)
7644+
kwargs, style_gen = _style_helpers.style_generator(kwargs)
76447645

76457646
for patch, lbl in itertools.zip_longest(patches, labels):
76467647
if not patch:
76477648
continue
7648-
kw = next(kwargs_gen)
76497649
p = patch[0]
7650-
p._internal_update(kw)
7650+
kwargs.update(next(style_gen))
7651+
p._internal_update(kwargs)
76517652
if lbl is not None:
76527653
p.set_label(lbl)
76537654
for p in patch[1:]:
7654-
p._internal_update(kw)
7655+
p._internal_update(kwargs)
76557656
p.set_label('_nolegend_')
76567657

76577658
if nx == 1:

lib/matplotlib/stackplot.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def stackplot(axes, x, *args,
9696
kwargs = cbook.normalize_kwargs(kwargs, collections.PolyCollection)
9797
kwargs.setdefault('facecolor', colors)
9898

99-
kwargs_gen = _style_helpers.iterate_styles(kwargs)
99+
kwargs, style_gen = _style_helpers.style_generator(kwargs)
100100

101101
# Assume data passed has not been 'stacked', so stack it here.
102102
# We'll need a float buffer for the upcoming calculations.
@@ -136,13 +136,13 @@ def stackplot(axes, x, *args,
136136
# Color between x = 0 and the first array.
137137
coll = axes.fill_between(x, first_line, stack[0, :],
138138
label=next(labels, None),
139-
**next(kwargs_gen))
139+
**next(style_gen), **kwargs)
140140
coll.sticky_edges.y[:] = [0]
141141
r = [coll]
142142

143143
# Color between array i-1 and array i
144144
for i in range(len(y) - 1):
145145
r.append(axes.fill_between(x, stack[i, :], stack[i + 1, :],
146146
label=next(labels, None),
147-
**next(kwargs_gen)))
147+
**next(style_gen), **kwargs))
148148
return r

lib/matplotlib/tests/test__style_helpers.py

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,75 +2,76 @@
22

33
import matplotlib.colors as mcolors
44
from matplotlib.lines import _get_dash_pattern
5-
from matplotlib._style_helpers import iterate_styles
5+
from matplotlib._style_helpers import style_generator
66

77

88
@pytest.mark.parametrize('key, value', [('facecolor', ["b", "g", "r"]),
99
('edgecolor', ["b", "g", "r"]),
1010
('hatch', ["/", "\\", "."]),
1111
('linestyle', ["-", "--", ":"]),
1212
('linewidth', [1, 1.5, 2])])
13-
def test_iterate_styles_list(key, value):
13+
def test_style_generator_list(key, value):
1414
kw = {'foo': 12, key: value}
15-
gen_kw = iterate_styles(kw)
15+
new_kw, gen = style_generator(kw)
16+
17+
assert new_kw == {'foo': 12}
1618

1719
for v in value * 2: # Result should repeat
18-
kw_dict = next(gen_kw)
19-
assert len(kw_dict) == 2
20-
assert kw_dict['foo'] == 12
20+
style_dict = next(gen)
21+
assert len(style_dict) == 1
2122
if key.endswith('color'):
22-
assert mcolors.same_color(v, kw_dict[key])
23+
assert mcolors.same_color(v, style_dict[key])
2324
elif key == 'linestyle':
24-
assert _get_dash_pattern(v) == kw_dict[key]
25+
assert _get_dash_pattern(v) == style_dict[key]
2526
else:
26-
assert v == kw_dict[key]
27+
assert v == style_dict[key]
2728

2829

2930
@pytest.mark.parametrize('key, value', [('facecolor', "b"),
3031
('edgecolor', "b"),
3132
('hatch', "/"),
3233
('linestyle', "-"),
3334
('linewidth', 1)])
34-
def test_iterate_styles_single(key, value):
35+
def test_style_generator_single(key, value):
3536
kw = {'foo': 12, key: value}
36-
gen_kw = iterate_styles(kw)
37+
new_kw, gen = style_generator(kw)
3738

39+
assert new_kw == {'foo': 12}
3840
for _ in range(2): # Result should repeat
39-
kw_dict = next(gen_kw)
40-
assert len(kw_dict) == 2
41-
assert kw_dict['foo'] == 12
41+
style_dict = next(gen)
4242
if key.endswith('color'):
43-
assert mcolors.same_color(value, kw_dict[key])
43+
assert mcolors.same_color(value, style_dict[key])
44+
elif key == 'linestyle':
45+
assert _get_dash_pattern(value) == style_dict[key]
4446
else:
45-
assert value == kw_dict[key]
47+
assert value == style_dict[key]
4648

4749

4850
@pytest.mark.parametrize('key', ['facecolor', 'hatch', 'linestyle'])
49-
def test_iterate_styles_empty(key):
51+
def test_style_generator_empty(key):
5052
kw = {key: []}
51-
gen_kw = iterate_styles(kw)
5253
with pytest.raises(TypeError, match=f'{key} must not be an empty sequence'):
53-
next(gen_kw)
54+
style_generator(kw)
5455

5556

56-
def test_iterate_styles_sequence_type_styles():
57+
def test_style_generator_sequence_type_styles():
5758
kw = {'facecolor': ('r', 0.5),
5859
'edgecolor': [0.5, 0.5, 0.5],
5960
'linestyle': (0, (1, 1))}
6061

61-
gen_kw = iterate_styles(kw)
62+
_, gen = style_generator(kw)
6263
for _ in range(2): # Result should repeat
63-
kw_dict = next(gen_kw)
64-
mcolors.same_color(kw['facecolor'], kw_dict['facecolor'])
65-
mcolors.same_color(kw['edgecolor'], kw_dict['edgecolor'])
66-
kw['linestyle'] == kw_dict['linestyle']
64+
style_dict = next(gen)
65+
mcolors.same_color(kw['facecolor'], style_dict['facecolor'])
66+
mcolors.same_color(kw['edgecolor'], style_dict['edgecolor'])
67+
kw['linestyle'] == style_dict['linestyle']
6768

6869

69-
def test_iterate_styles_none():
70+
def test_style_generator_none():
7071
kw = {'facecolor': 'none',
7172
'edgecolor': 'none'}
72-
gen_kw = iterate_styles(kw)
73+
_, gen = style_generator(kw)
7374
for _ in range(2): # Result should repeat
74-
kw_dict = next(gen_kw)
75-
assert kw_dict['facecolor'] == 'none'
76-
assert kw_dict['edgecolor'] == 'none'
75+
style_dict = next(gen)
76+
assert style_dict['facecolor'] == 'none'
77+
assert style_dict['edgecolor'] == 'none'

0 commit comments

Comments
 (0)