8000 Merge pull request #22229 from tacaswell/fix_mutation_safe_iter · matplotlib/matplotlib@e1910b8 · GitHub
[go: up one dir, main page]

Skip to content

Commit e1910b8

Browse files
authored
Merge pull request #22229 from tacaswell/fix_mutation_safe_iter
FIX: make safe to add / remove artists during ArtistList iteration
2 parents 738518a + fe511c5 commit e1910b8

File tree

3 files changed

+23
-1
lines changed

3 files changed

+23
-1
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
AritistList proxies copy contents on iteration
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
When iterating over the contents of the the dynamically generated proxy lists
5+
for the Artist-type accessors (see :ref:`Behavioural API Changes 3.5 - Axes
6+
children combined`), a copy of the contents is made. This ensure that artists
7+
can safely be added or removed from the Axes while iterating over their children.
8+
9+
This is a departure from the expected behavior of mutable iterable data types
10+
in Python -- iterating over list while mutating it has surprising consequences
11+
and dictionaries will error if they change size during iteration.
12+
Because all of the accessors are filtered views of the same underlying list, it
13+
is possible for seemingly unrelated changes, such as removing a Line, to affect
14+
the iteration over any of the other accessors. In this case, we have opted to
15+
make a copy of the relevant children before yielding them to the user.
16+
17+
This change is also consistent with our plan to make these accessors immutable
18+
in Matplotlib 3.7.

lib/matplotlib/axes/_base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1367,7 +1367,7 @@ def __len__(self):
13671367
for artist in self._axes._children)
13681368

13691369
def __iter__(self):
1370-
for artist in self._axes._children:
1370+
for artist in list(self._axes._children):
13711371
if self._type_check(artist):
13721372
yield artist
13731373

lib/matplotlib/tests/test_axes.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7508,6 +7508,10 @@ def test_artist_sublists():
75087508
assert ax.lines + [1, 2, 3] == [*lines, 1, 2, 3]
75097509
assert [1, 2, 3] + ax.lines == [1, 2, 3, *lines]
75107510

7511+
for ln in ax.lines:
7512+
ln.remove()
7513+
assert len(ax.lines) == 0
7514+
75117515

75127516
def test_empty_line_plots():
75137517
# Incompatible nr columns, plot "nothing"

0 commit comments

Comments
 (0)
0