Skip to content

Better document Axes.set() #19884

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
timhoffm opened this issue Apr 6, 2021 · 5 comments
Closed

Better document Axes.set() #19884

timhoffm opened this issue Apr 6, 2021 · 5 comments
Milestone

Comments

@timhoffm
Copy link
Member

timhoffm commented Apr 6, 2021

Problem

The property batch setter is a nice way for a more compact configuration compared to various lines of ax.set_*() calls.

(Note: using kwargs is quite common with other plotting libraries, so this approach seems generally appealing).

Axes.set() is essentially undocumented:

Suggested Improvement

  • We should re-introduce Axes.set into the API docs.

  • That method needs a more approachable description than "A property batch setter. Pass kwargs to set properties."

  • Ideally, the signature should be explicit and not **kwargs, which would enable completion. There are two possible ways of doing this:

    1. Dynamically rewrite the signature.
    2. Hard-code the signature and add a test, that the parameters match the available properties.

    The first one has the advantage that this would trivially expand to all artists.
    The second one has the advantage that we can easily specify a meaningful order. Since we rarely change the available properties, hard-coding with a test would be good enough.

@anntzer
Copy link
Contributor

anntzer commented Apr 7, 2021

I like the idea (and really like Artist.set in general). FWIW dynamically rewriting the signature is quite easy, something like:

diff --git i/lib/matplotlib/artist.py w/lib/matplotlib/artist.py
index b6f13f898..5e17e3f18 100644
--- i/lib/matplotlib/artist.py
+++ w/lib/matplotlib/artist.py
@@ -1,6 +1,7 @@
 from collections import OrderedDict, namedtuple
 from functools import wraps
 import inspect
+from inspect import Signature, Parameter
 import logging
 from numbers import Number
 import re
@@ -87,6 +88,11 @@ def _stale_axes_callback(self, val):
 _XYPair = namedtuple("_XYPair", "x y")
 
 
+class _Unset:  # Not the same as "None" for many properties...
+    def __repr__(self):
+        return "<UNSET>"
+
+
 class Artist:
     """
     Abstract base class for objects that render into a FigureCanvas.
@@ -96,6 +102,24 @@ class Artist:
 
     zorder = 0
 
+    def __init_subclass__(cls):
+        # A wrapper function, so that we can set its signature just for this
+        # subclass.
+
+        def set(self, **kwargs):
+            Artist.set(**kwargs)
+
+        cls.set = set
+        set.__doc__ = Artist.set.__doc__
+        cls._update_set_signature()
+
+    @classmethod
+    def _update_set_signature(cls):
+        cls.set.__signature__ = Signature(
+            [Parameter("self", Parameter.POSITIONAL_OR_KEYWORD),
+             *[Parameter(prop, Parameter.KEYWORD_ONLY, default=_Unset())
+               for prop in ArtistInspector(cls).get_setters()]])
+
     def __init__(self):
         self._stale = True
         self.stale_callback = None
@@ -1565,6 +1589,9 @@ class ArtistInspector:
         return lines
 
 
+Artist._update_set_signature()
+
+
 def getp(obj, property=None):

and generating a longer docstring (e.g. with the summary line for each property) is likely doable as well.

For auto-ordering, I guess we could arrange so that inherited properties come last (we likely care more about Axes.set_xlim than Axes.set_rasterized) and/or list things in the order in which they appear in the source (there's co_firstlineno or inspect.getsourcelines for that), which should be reasonable... A separate _property_order_ magic attribute seems fine too, though (and we can easily add a check that it stays up to date).

@timhoffm
Copy link
Member Author

timhoffm commented Apr 7, 2021

Order ist necessary, because there are quite a few parameters.

Not sure if our code is well organized so that any automatic rule (Inheritance / code-order) gives satisfying results.
If we'd need to introduce _property_order_ we can equally well use the signature explicitly to specify the order.

@anntzer
Copy link
Contributor

anntzer commented Apr 7, 2021

At least we could consider reordering the set_foos to make their order semantically reasonable.

@timhoffm
Copy link
Member Author

timhoffm commented Apr 7, 2021

While I'm not too sensitive on that topic, that'd appears to be too much code churn. (but maybe we are lucky and only need to move one function??).

@timhoffm
Copy link
Member Author

Closed by #20569.

@QuLogic QuLogic added this to the v3.5.0 milestone Jul 29, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants