Pull request guidelines#
Pull requests (PRs) on GitHub are the mechanism for contributing to Matplotlib's code and documentation.
It is recommended to check that your contribution complies with the following rules before submitting a pull request:
If your pull request addresses an issue, please use the title to describe the issue (e.g. "Add ability to plot timedeltas") and mention the issue number in the pull request description to ensure that a link is created to the original issue (e.g. "Closes #8869" or "Fixes #8869"). This will ensure the original issue mentioned is automatically closed when your PR is merged. See the GitHub documentation for more details.
Formatting should follow the recommendations of PEP8, as enforced by flake8. Matplotlib modifies PEP8 to extend the maximum line length to 88 characters. You can check flake8 compliance from the command line with
python -m pip install flake8 flake8 /path/to/module.py
or your editor may provide integration with it. Note that Matplotlib intentionally does not use the black auto-formatter (1), in particular due to its inability to understand the semantics of mathematical expressions (2, 3).
All public methods should have informative docstrings with sample usage when appropriate. Use the docstring standards.
For high-level plotting functions, consider adding a simple example either in the
Examplesection of the docstring or the examples gallery.
Changes (both new features and bugfixes) should have good test coverage. See Testing for more details.
Import the following modules using the standard scipy conventions:
import numpy as np import numpy.ma as ma import matplotlib as mpl import matplotlib.pyplot as plt import matplotlib.cbook as cbook import matplotlib.patches as mpatches
In general, Matplotlib modules should not import
from matplotlib import rcParams, but rather access it as
mpl.rcParams. This is because some modules are imported very early, before the
rcParamssingleton is constructed.
If your change is a major new feature, add an entry to the
What's newsection by adding a new file in
doc/users/next_whats_new/README.rstfor more information).
If you change the API in a backward-incompatible way, please document it in
doc/api/next_api_changes/behavior, by adding a new file with the naming convention
99999-ABC.rstwhere the pull request number is followed by the contributor's initials. (see
doc/api/api_changes.rstfor more information)
If you add new public API or change public API, update or add the corresponding type hints. Most often this is found in the corresponding
.pyifile for the
.pyfile which was edited. Changes in
pyplot.pyare type hinted inline.
See below for additional points about Keyword argument processing, if applicable for your pull request.
The current state of the Matplotlib code base is not compliant with all of these guidelines, but we expect that enforcing these constraints on all new contributions will move the overall code base quality in the right direction.
Summary for pull request reviewers#
If you have commit rights, then you are trusted to use them. Please help review and merge PRs!
Be patient and kind with contributors.
Is the feature / bugfix reasonable?
Does the PR conform with the Coding guidelines?
Is the documentation (docstrings, examples, what's new, API changes) updated?
Is the change purely stylistic? Generally, such changes are discouraged when not part of other non-stylistic work because it obscures the git history of functional changes to the code. Reflowing a method or docstring as part of a larger refactor/rewrite is acceptable.
Every new feature should be documented. If it's a new module, don't forget to add a new rst file to the API docs.
Each high-level plotting function should have a small example in the
Examplessection of the docstring. This should be as simple as possible to demonstrate the method. More complex examples should go into a dedicated example file in the
examplesdirectory, which will be rendered to the examples gallery in the documentation.
Build the docs and make sure all formatting warnings are addressed.
See Write documentation for our documentation style guide.
New features and API changes#
When adding a major new feature or changing the API in a backward incompatible way, please document it by including a versioning directive in the docstring and adding an entry to the folder for either the what's new or API change notes.
for this addition
include this directive
create entry in this folder
The directives should be placed at the end of a description block. For example:
class Foo: """ This is the summary. Followed by a longer description block. Consisting of multiple lines and paragraphs. .. versionadded:: 3.5 Parameters ---------- a : int The first parameter. b: bool, default: False This was added later. .. versionadded:: 3.6 """ def set_b(b): """ Set b. .. versionadded:: 3.6 Parameters ---------- b: bool
For classes and functions, the directive should be placed before the Parameters section. For parameters, the directive should be placed at the end of the parameter description. The patch release version is omitted and the directive should not be added to entire modules.
If you have the rights to set labels, tag the PR with descriptive labels. See the list of labels.
If the PR makes changes to the wheel building Action, add the "Run cibuildwheel" label to enable testing wheels.
Set the milestone according to these guidelines:
New features and API changes are milestoned for the next minor release
Bugfixes, tests for released code, and docstring changes may be milestoned for the next patch release
Documentation changes (only .rst files and examples) may be milestoned
If multiple rules apply, choose the first matching from the above list. See Backport strategy for detailed guidance on what should or should not be backported.
The milestone marks the release a PR should go into. It states intent, but can be changed because of release planning or re-evaluation of the PR scope and maturity.
All Pull Requests should target the main branch. The milestone tag triggers an automatic backport for milestones which have a corresponding branch.
Documentation and examples may be merged by the first reviewer. Use the threshold "is this better than it was?" as the review criteria.
For code changes (anything in
lib) at least two core developers (those with commit rights) should review all pull requests. If you are the first to review a PR and approve of the changes use the GitHub 'approve review' tool to mark it as such. If you are a subsequent reviewer please approve the review and if you think no more review is needed, merge the PR.
Ensure that all API changes are documented in a file in one of the subdirectories of
doc/api/next_api_changes, and significant new features have an entry in
If a PR already has a positive review, a core developer (e.g. the first reviewer, but not necessarily) may champion that PR for merging. In order to do so, they should ping all core devs both on GitHub and on the dev mailing list, and label the PR with the "Merge with single review?" label. Other core devs can then either review the PR and merge or reject it, or simply request that it gets a second review before being merged. If no one asks for such a second review within a week, the PR can then be merged on the basis of that single review.
A core dev should only champion one PR at a time and we should try to keep the flow of championed PRs reasonable.
Do not self merge, except for 'small' patches to un-break the CI or when another reviewer explicitly allows it (ex, "Approve modulo CI passing, may self merge when green").
Whenever a pull request is created or updated, various automated test tools will run on all supported platforms and versions of Python.
Make sure the Linting, GitHub Actions, AppVeyor, CircleCI, and Azure pipelines are passing before merging (All checks are listed at the bottom of the GitHub page of your pull request). Here are some tips for finding the cause of the test failure:
If Linting fails, you have a code style issue, which will be listed as annotations on the pull request's diff.
If Mypy or Stubtest fails, you have inconsistency in type hints, which will be listed as annotations in the diff.
If a GitHub Actions or AppVeyor run fails, search the log for
FAILURES. The subsequent section will contain information on the failed tests.
If CircleCI fails, likely you have some reStructuredText style issue in the docs. Search the CircleCI log for
If Azure pipelines fail with an image comparison error, you can find the images as artifacts of the Azure job:
Click Details on the check on the GitHub PR page.
Click View more details on Azure Pipelines to go to Azure.
On the overview page artifacts are listed in the section Related.
Codecov and CodeQL are currently for information only. Their failure is not necessarily a blocker.
tox is not used in the automated testing. It is supported for testing locally.
If you know only a subset of CIs need to be run, this can be controlled on individual commits by including the following substrings in commit messages:
[ci doc]: restrict the CI to documentation checks. For when you only changed documentation (this skip is automatic if the changes are only under
[skip circle]: skip the documentation build check. For when you didn't change documentation.
Unit tests can be turned off for individual platforms with
[skip actions]: GitHub Actions
[skip appveyor](must be in the first line of the commit): AppVeyor
[skip azp]: Azure Pipelines
[skip ci]: skip all CIs. Use this only if you know your changes do not need to be tested at all, which is very rare.
Number of commits and squashing#
Squashing is case-by-case. The balance is between burden on the contributor, keeping a relatively clean history, and keeping a history usable for bisecting. The only time we are really strict about it is to eliminate binary files (ex multiple test image re-generations) and to remove upstream merges.
Do not let perfect be the enemy of the good, particularly for documentation or example PRs. If you find yourself making many small suggestions, either open a PR against the original branch, push changes to the contributor branch, or merge the PR and then open a new PR against upstream.
If you push to a contributor branch leave a comment explaining what you did, ex "I took the liberty of pushing a small clean-up PR to your branch, thanks for your work.". If you are going to make substantial changes to the code or intent of the PR please check with the contributor first.
Branches and backports#
The current active branches are
The current development version. Future minor releases (v3.N.0) will be branched from this.
Maintenance branch for Matplotlib 3.N. Future patch releases will be branched from this.
Documentation for the current release. On a patch release, this will be replaced by a properly named branch for the new release.
Branch selection for pull requests#
Generally, all pull requests should target the main branch.
Backports to the patch release branch (v3.N.x) are the changes that will be included in the next patch (aka bug-fix) release. The goal of the patch releases is to fix bugs without adding any new regressions or behavior changes. We will always attempt to backport:
critical bug fixes (segfault, failure to import, things that the user cannot work around)
fixes for regressions introduced in the last two minor releases
and may attempt to backport fixes for regressions introduced in older releases.
In the case where the backport is not clean, for example if the bug fix is built on top of other code changes we do not want to backport, balance the effort and risk of re-implementing the bug fix vs the severity of the bug. When in doubt, err on the side of not backporting.
When backporting a Pull Request fails or is declined, re-milestone the original PR to the next minor release and leave a comment explaining why.
The only changes backported to the documentation branch (v3.N.M-doc)
are changes to
galleries. Any changes to
src, including docstring-only changes, must not be backported to
We use MeeseeksDev bot to automatically backport merges to the correct
maintenance branch base on the milestone. To work properly the
milestone must be set before merging. If you have commit rights, the
bot can also be manually triggered after a merge by leaving a message
@meeseeksdev backport to BRANCH on the PR. If there are conflicts
MeeseeksDev will inform you that the backport needs to be done
The target branch is configured by putting
on-merge: backport to
TARGETBRANCH in the milestone description on it's own line.
If the bot is not working as expected, please report issues to MeeseeksDev.
When doing backports please copy the form used by MeeseeksDev,
Backport PR #XXXX: TITLE OF PR. If you need to manually resolve
conflicts make note of them and how you resolved them in the commit
We do a backport from main to v2.2.x assuming:
matplotlibis a read-only remote branch of the matplotlib/matplotlib repo
TARGET_SHA is the hash of the merge commit you would like to
backport. This can be read off of the GitHub PR page (in the UI with
the merge notification) or through the git CLI tools.
Assuming that you already have a local branch
v2.2.x (if not, then
git checkout -b v2.2.x), and that your remote pointing to
https://github.com/matplotlib/matplotlib is called
git fetch upstream git checkout v2.2.x # or include -b if you don't already have this. git reset --hard upstream/v2.2.x git cherry-pick -m 1 TARGET_SHA # resolve conflicts and commit if required
Files with conflicts can be listed by
and will have to be fixed by hand (search on
the conflict is resolved, you will have to re-add the file(s) to the branch
and then continue the cherry pick:
git add lib/matplotlib/conflicted_file.py git add lib/matplotlib/conflicted_file2.py git cherry-pick --continue
Use your discretion to push directly to upstream or to open a PR; be
sure to push or PR against the
v2.2.x upstream branch, not