Skip to content

Introduce ArtistList for FigureBase - #31746

Merged
QuLogic merged 1 commit into
matplotlib:mainfrom
rcomer:fig-artistlist
Jul 27, 2026
Merged

Introduce ArtistList for FigureBase#31746
QuLogic merged 1 commit into
matplotlib:mainfrom
rcomer:fig-artistlist

Conversation

@rcomer

@rcomer rcomer commented May 25, 2026

Copy link
Copy Markdown
Member

PR summary

At #31730 (comment) Tom said

We deprecated directly mutating the artist lists on Axes a while ago, but apparently forgot to do that on Figure as well!

This PR generalises the ArtistList so it can work for both figures and axes. The new _FigureArtistList subclasses it just to add the deprecated methods. I adapted the deprecated methods and their tests from #18216, where this was originally done for Axes. Note that fig.subfigures is still a plain list. I do not think subfigures belong in fig._children, but rather should have their own handling similar to fig.axes. That can be done separately.

AI Disclosure

I asked duck.ai how to get a class as a string, to use in the ArtistList repr self._parent.__class__.__name__.

PR checklist

@rcomer rcomer added API: changes Changes to the public API, typically requiring deprecation. status: waiting for other PR labels May 25, 2026
@github-actions github-actions Bot added topic: mplot3d GUI: Qt backend: cairo topic: axes topic: figures and subfigures CI: Run cibuildwheel Run wheel building tests on a PR CI: Run cygwin Run cygwin tests on a PR Documentation: examples files in galleries/examples Documentation: tutorials files in galleries/tutorials Documentation: devdocs files in doc/devel Documentation: user guide files in galleries/users_explain or doc/users labels May 25, 2026
@rcomer rcomer added this to the v3.12.0 milestone May 25, 2026
@rcomer

rcomer commented May 25, 2026

Copy link
Copy Markdown
Member Author

It seems I have discovered something that only works at py314 🧐

@rcomer

This comment was marked as outdated.

@rcomer

This comment was marked as outdated.

@rcomer

This comment was marked as outdated.

@rcomer
rcomer marked this pull request as ready for review May 30, 2026 15:49
Comment thread lib/matplotlib/figure.py
Comment on lines +121 to +122
A sublist of Figure children based on their type. This subclass exists only to
provide deprecation warnings. When the deprecations expire, use ArtistList

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be simpler to add

if isinstance(parent, FigureBase):
    _api.warn_deprecated(...)

or even

self.warn_deprecated_if_on_figure(...)

to the regular ArtistList methods?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ArtistList is already immutable. It doesn’t have these methods.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I see. There's a lot of unforeseen complexity in the migration of ArtistList from AxesBase to artist, which gives me a bit of a headeache overlooking the complete PR. In hindsight it would likely have been better to either split this in two PRs / commits: (1) move ArtistList (2) use ArtistList in Figure; or alternatively just duplicate the 70 lines of ArtistList in Figure, and when the Figure deprecations run out and both classes become identical merge them back together. But I'm somewhat reluctant to request that now.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah sorry. It did occur to me when I was moving it that splitting into separate commits for moving and modifying might help the review, but at the time I couldn't quite see how to split it. I will have a go at just moving it in a separate branch and if it works I'll make a prequel PR.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... and now the difference appears.

@rcomer
rcomer marked this pull request as draft May 31, 2026 09:51
@rcomer

rcomer commented May 31, 2026

Copy link
Copy Markdown
Member Author

Hid the discussion about doc-failure debugging as that is now fixed in #31794 and summarised at #31794 (comment).

Comment thread galleries/tutorials/artists.py Outdated
Comment on lines +318 to +320
# children. Adding images and text is usually achieved with the
# `~.Figure.figimage` and `~.Figure.text` methods. Other artists may be added
# with the `~.Figure.add_artist` method.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me, there is not enough distinction between the factory methods and add_artist. You are using "add" with different semantics: For the factory methods it's a high-level logical add ("add a text to the figure") whereas for add_artist it's a technical "add an Artists instance to the figure".

Suggested change
# children. Adding images and text is usually achieved with the
# `~.Figure.figimage` and `~.Figure.text` methods. Other artists may be added
# with the `~.Figure.add_artist` method.
# children. Artists are added to theses lists via `~.Figure.add_artist`.

Then put the example (which now does not contain transforms.

Then add

# As a convenience for images and text, the helper methods
# `~.Figure.figimage` and `~.Figure.text` conveniently create the
# respective Artists and internally call `~.Figure.add_artist`.

to set the stage for images and text.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tweaked your suggestion slightly as currently figimage and text are not calling add_artist but directly appending to _children. I did go back and forth on that:

  • Obviously using add_artist would mean less code duplication.
  • Using _children.append kept the change within those functions minimal.
  • If figimage used add_artist then it would need to explicitly set the IdentityTransform to prevent add_artist setting transSubfigure. This might arguably be a good thing to do (and would fix [Bug]: Figure.add_artist() fails to re-render an image previously added via Figure.figimage() after .remove() #31730) but it created an extra thing to think about and there was already more than enough in this PR!
  • Possibly some other consideration that I have since forgotten...

Comment thread lib/matplotlib/tests/test_cbook.py Outdated
Comment thread lib/matplotlib/_api/__init__.py
Comment thread lib/matplotlib/tests/test_figure.py
Comment thread lib/matplotlib/figure.py Outdated
Comment thread lib/matplotlib/figure.py
Comment on lines +240 to 244
return _FigureArtistList(self, 'texts', valid_types=Text)



def _get_draw_artists(self, renderer):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Too many blank lines.

Suggested change
return _FigureArtistList(self, 'texts', valid_types=Text)
def _get_draw_artists(self, renderer):
return _FigureArtistList(self, 'texts', valid_types=Text)
def _get_draw_artists(self, renderer):

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh. I wonder why ruff doesn't catch that.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even though we enable E rules, we also have explicit-preview-rules=true, so those blank line ones are not enabled yet. #32126

Comment thread lib/matplotlib/figure.pyi
Following matplotlib#18216 for Axes artists, combine all figure artists except
axes and subfigures into a single list and deprecate modifying the lists
directly.
@QuLogic
QuLogic merged commit 7ad06b1 into matplotlib:main Jul 27, 2026
41 checks passed
@QuLogic

QuLogic commented Jul 28, 2026

Copy link
Copy Markdown
Member

So I'm looking at type hint errors, and I noticed that this doesn't mark the Figure-level lists as modifiable since it uses the original ArtistList. We have a mix of whether we change type hints to match future behaviour or not, so I just wanted to flag this here in case we did want the type hints to match current behaviour.

@timhoffm

Copy link
Copy Markdown
Member

Let’s not jump extra hoops. This will become immutable in the future, so already flaggingbitbin typing is ok.

@rcomer
rcomer deleted the fig-artistlist branch July 28, 2026 11:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

API: changes Changes to the public API, typically requiring deprecation. Documentation: examples files in galleries/examples Documentation: tutorials files in galleries/tutorials Documentation: user guide files in galleries/users_explain or doc/users topic: figures and subfigures

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants