Skip to content

Conversation

@timhoffm
Copy link
Member

@timhoffm timhoffm commented Dec 16, 2025

Current status
Until now, the parameter definition was dispersed: valid names and defaults are loaded from the canonical matplotlibrc data file. Docs are only available as comments in there. Validators are attached ad-hoc in rcsetup.py.

Proposed change
Define the parameters in code, including meta-information, like validators, docs in a single place. It will simplify the rcParams related code in matplotlib.__init__.py and matplotlib.rcsetup.py. It also enables us to generate sphinx documentation on the parameters.

Closes #23531.
Superseeds #26088. Ensuring consistency through tests is a better approach than trying to be able to exactly reproduce matplotlibrc.

Discarded alternative: Use another stuctured data file to store the information. Among available formats, I would only find YAML easy enough to human-read and -write this kind of structured information. But I don't want to introduce a YAML parser as a dependency.

Notes:

  • This is a PoC and nothing is set in stone. In particular no special care has been taken of
    • The exact structures how we want to define the parameters (is a dataclass good? Likely yes, but ymmv) and format them so that they are as readable as possible.
    • Description of the parameters. These are just extracted from matplotlibrc
    • More fancy stuff like grouping, additional info like human-readable accepted values may come later.
    • Representation in the docs. Generating and embedding a simple rst page will not be the final state. My plan is to make a proper sphinx extension so that :rc:some.param can directly line the parameters.
    • Location of the params documentation in the docs.
  • Transition plan:
    1. matplotlibrc and the validator lists are used for functionality. Tests ensure that the new definitions match the existing ones.
    2. After we have merged, a later PR will switch to using the content from the new definitions and remove matplotlibrc and the validator lists.

How to review:

Feedback welcome.

@github-actions github-actions bot added topic: rcparams Documentation: user guide files in galleries/users_explain or doc/users labels Dec 16, 2025
Until now, the parameter definition was dispersed:
valid names and defaults are loaded from the
canonical `matplotlibrc` data file. Docs are only
available as comments in there. Validators are
attached ad-hoc in `rcsetup.py`.

This makes for a more formal definition of parameters,
including meta-information, like validators, docs in
a single place. It will simplify the rcParams related
code in `matplotlib.__init__.py` and `matplotlib.rcsetup.py`.
It also enables us to generate sphinx documentation
on the parameters.
@story645
Copy link
Member

How can we improve on that?

This definitely looks better than what's currently there. I think subheadings based on the artist/object that the rcParam applies to - like #lines, which will also make the right hand side really nice for quick skims I think. I think the two ways to achieve that are probably either manually add a family or peel off the family with a .split?

@timhoffm
Copy link
Member Author

timhoffm commented Dec 17, 2025

Alternative: It would likely be feasible to define the rcParams via a TOML file, which we would carry around and read at startup like we do with matplotlibrc.

Compare:

Param("timezone", "UTC", validate_string,
    description="a pytz timezone string, e.g., US/Central or Europe/Paris"),
Param("pcolor.shading", "auto", ["auto", "flat", "nearest", "gouraud"]),
Param("figure.constrained_layout.hspace", 0.02, validate_float,
    description="Spacing between subplots, relative to the subplot sizes.  Much "
                "smaller than for tight_layout (figure.subplot.hspace, "
                "figure.subplot.wspace) as constrained_layout already takes "
                "surrounding texts (titles, labels, # ticklabels) into account."),

and:

[timezone]
default = "UTC"
validator = "validate_string"
description ="a pytz timezone string, e.g., US/Central or Europe/Paris"

[pcolor.shading]
default = "auto"
validator = '["auto", "flat", "nearest", "gouraud"]'

[figure.constrained_layout.hspace]
default = 0.02
validator = "validate_float"
description = """
Spacing between subplots, relative to the subplot sizes.  Much
smaller than for tight_layout (figure.subplot.hspace, "
figure.subplot.wspace) as constrained_layout already takes
surrounding texts (titles, labels, # ticklabels) into account.
"""

Which one is easier to maintain?

There'll be slight complications that we need to be able to express None as a default value and that we have to define validators as strings and map them to code objects at runtime, but nothing that cannot be done.

@story645
Copy link
Member

story645 commented Dec 17, 2025

Which one is easier to maintain?

The toml file looks way easier to read/find the right value. And I like that the leveling structure means we can do group level stuff trivially (if I'm reading the TOML docs correctly), eg:

[figure.constrained_layout]
description = "default settings for constrained layout, see <link to constrained layout docs>" 

@tacaswell tacaswell added this to the v3.12.0 milestone Dec 17, 2025
@jklymak
Copy link
Member

jklymak commented Dec 17, 2025

I think it has been suggested for years that the matplotlibrc be a Python file instead of some parsable text format?

@story645
Copy link
Member

story645 commented Dec 17, 2025

@jklymak Tim is proposing a replacement for how rcParams are specified in rcsetup.py. Roughly this replaces the _validators dictionary and the adds in the default values and description from the default rcParams file so that all the info about the param is in one place.
ETA: basically, we should be able to generate a default matplotlibrc file from the specs rather than the current scheme where defaults are defined in the matplotlibrc file.

Separately it might be nice for users to be able to specify params using a TOML structure, but generally they're only going to need to specify the values so the structure here is a bit overkill for that.

@jklymak
Copy link
Member

jklymak commented Dec 17, 2025

Sure I understand that - however, I don't see why we would add a new TOML format to the mix.

@WeatherGod
Copy link
Member

WeatherGod commented Dec 17, 2025 via email

@timhoffm
Copy link
Member Author

Chiming in here with a note about a tool I used once in a work project for schema validation: https://docs.python-cerberus.org/

Thanks for the hint. Though I think schema validation is not our primary concern for now. We have potentially two schemas:

  • the config_parameter_schema, but if we define (or parse) that into a dataclass, errors will show up. Also the input is on our side and rarely changes.
  • user-defind rcParams setttings. These are just key-value pairs, with a potentially complicated (in the sense of allowed values, not in the sense of structure) value type. A schema is not much help here either.

@story645
Copy link
Member

however, I don't see why we would add a new TOML format to the mix.

Because it's a ready made solution to the problem of defining specs for nested configurations, which is more or less what rcParams are. The alternative proposal of wrapping everything in Param objects (or the like) would likely grow to something that looks like TOML in object form if we want to make the groupings explicit, which I think we do because that's really useful for documentation purposes.

@timhoffm
Copy link
Member Author

timhoffm commented Dec 17, 2025

Sure I understand that - however, I don't see why we would add a new TOML format to the mix.

It's a variant how to systematically represent that information. We are completely free to decide which one we like better.

What I like about the TOML approach:

  • The parameter name stands out [param.name], it's visually separated from the other values

  • There's no extra syntactic clutter that we need in Python: no class name, no parentheses, no commas

  • Multiline strings look a bit nicer. This is mainly because your keys are not indented.

    [some.param]
    description="""
    A longer description that spans multiple
    lines.
    """

    In Python you do one of

    implicit concatenation of single lines (needs extra quotes on each line and ensure that there's a space at the end of each line.

        Param(
            description="A longer description that spans multiple "
                        "lines."
        )

    or (visually breaking the indentation)

        Param(
            description="""\
     A longer description that spans multiple
    lines.
    """
        )

    or (adding additional space into the string)

        Param(
            description="""\
                A longer description that spans multiple
                lines.
                """
        )

    Also, depending on the variant, effective line length gets much shorter, which means we need more wrapping.

What I don't like about the TOML approach:

  • Overhead for carrying a file around (but we right now do this with matplotlibrc) so not too bad.
  • No native value for None
  • We must define a pattern how we define validators (e.g. as string) and then parse them into the actual objects on load.

@story645
Copy link
Member

Overhead for carrying a file around (but we right now do this with matplotlibrc) so not too bad.

I think it'd be nice to pull the configuration out of rcsetup even if we don't go the TOML route.

@timhoffm
Copy link
Member Author

Overhead for carrying a file around (but we right now do this with matplotlibrc) so not too bad.

I think it'd be nice to pull the configuration out of rcsetup even if we don't go the TOML route.

I did not do this for a start, because one then needs to import all the validators, and that gets messy. But rearrangement is possible and will happen in some form.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Documentation: user guide files in galleries/users_explain or doc/users topic: rcparams

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Doc]: Documentation of rc parameters could be improved

5 participants