<liclass="toctree-l1 has-children"><aclass="reference internal" href="development_setup.html">Setting up Matplotlib for development</a><details><summary><spanclass="toctree-toggle" role="presentation"><iclass="fa-solid fa-chevron-down"></i></span></summary><ul>
<liclass="toctree-l2"><aclass="reference internal" href="MEP/MEP12.html">MEP12: Improve Gallery and Examples</a></li>
<liclass="toctree-l2"><aclass="reference internal" href="MEP/MEP13.html">MEP13: Use properties for Artists</a></li>
<liclass="toctree-l2"><aclass="reference internal" href="MEP/MEP14.html">MEP14: Text handling</a></li>
<liclass="toctree-l2"><aclass="reference internal" href="MEP/MEP15.html">MEP15: Fix axis autoscaling when limits are specified for one axis only</a></li>
<pclass="admonition-title">This document is only relevant for Matplotlib release managers.</p>
<p>A guide for developers who are doing a Matplotlib release.</p>
</div>
<sectionid="versioning-scheme">
<h2>Versioning Scheme<aclass="headerlink" href="#versioning-scheme" title="Link to this heading">#</a></h2>
<p>Maplotlib follows the <aclass="reference external" href="https://jacobtomlinson.dev/effver/">Intended Effort Versioning (EffVer)</a>
versioning scheme: <em>macro.meso.micro</em>.</p>
<dl>
<dt><em>macro</em></dt><dd><p>A release that we expect a large effort from our users to upgrade to. The v1 to v2 transition
included a complete overhaul of the default styles and the v2 to v3 transition involved
dropping support for Python 2.</p>
<p>Future macro versions would include changes of a comparable scale that can not be done
incrementally in meso releases.</p>
</dd>
<dt><em>meso</em></dt><dd><p>A release that we expect some effort from our users to upgrade to. We target a
<em>Meso</em> release every 6 months. These release are primarily intended to release
new features to our users, however they also contain intentional feature deprecations and
removals per <aclass="reference internal" href="api_changes.html#deprecation-guidelines"><spanclass="std std-ref">our policy</span></a>.</p>
</dd>
<dt><em>micro</em></dt><dd><p>A release that we expect users to require little to no effort to upgrade to. Per
our <aclass="reference internal" href="pr_guide.html#backport-strategy"><spanclass="std std-ref">Backport strategy</span></a> we only backport bug fixes to the maintenance branch.
We expect minimal impact on users other than possibly breaking work arounds to a
fixed bug or <aclass="reference external" href="https://xkcd.com/1172/">bugs being used as features</a>.</p>
<p>These are released as-needed, but typically every 1-2 months between meso releases.</p>
</dd>
</dl>
</section>
<sectionid="making-the-release-branch">
<spanid="release-feature-freeze"></span><h2>Making the release branch<aclass="headerlink" href="#making-the-release-branch" title="Link to this heading">#</a></h2>
<divclass="admonition note">
<pclass="admonition-title">Note</p>
<p>This assumes that a read-only remote for the canonical repository is
<codeclass="docutils literal notranslate"><spanclass="pre">remote</span></code> and a read/write remote is <codeclass="docutils literal notranslate"><spanclass="pre">DANGER</span></code></p>
</div>
<p>When a new meso release (vX.Y.0) is approaching, a new release branch must be made.
When precisely this should happen is up to the release manager, but this point is where
most new features intended for the meso release are merged and you are entering a
feature freeze (i.e. newly implemented features will be going into vX.Y+1).
This does not necessarily mean that no further changes will be made prior to release,
just that those changes will be made using the backport system.</p>
<p>For an upcoming <codeclass="docutils literal notranslate"><spanclass="pre">v3.7.0</span></code> release, first create the branch:</p>
<p>Check all active milestones for consistency. Older milestones should also backport
to higher meso versions (e.g. <codeclass="docutils literal notranslate"><spanclass="pre">v3.6.3</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">v3.6-doc</span></code> should backport to both
<codeclass="docutils literal notranslate"><spanclass="pre">v3.6.x</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">v3.7.x</span></code> once the <codeclass="docutils literal notranslate"><spanclass="pre">v3.7.x</span></code> branch exists and while PR backports are
still targeting <codeclass="docutils literal notranslate"><spanclass="pre">v3.6.x</span></code>)</p>
<p>Create the milestone for the next-next meso release (i.e. <codeclass="docutils literal notranslate"><spanclass="pre">v3.9.0</span></code>, as <codeclass="docutils literal notranslate"><spanclass="pre">v3.8.0</span></code>
should already exist). While most active items should go in the next meso release,
this milestone can help with longer term planning, especially around deprecation
cycles.</p>
</section>
<sectionid="testing">
<spanid="release-testing"></span><h2>Testing<aclass="headerlink" href="#testing" title="Link to this heading">#</a></h2>
<p>We use <aclass="reference external" href="https://github.com/matplotlib/matplotlib/actions">GitHub Actions</a>
for continuous integration. When preparing for a release, the final tagged
commit should be tested locally before it is uploaded:</p>
<p>For ipympl, restart the kernel, add a cell for <codeclass="docutils literal notranslate"><spanclass="pre">%matplotlib</span><spanclass="pre">widget</span></code> and do
not run the cell with <codeclass="docutils literal notranslate"><spanclass="pre">matplotlib.use('nbagg')</span></code>. Tests which check
<codeclass="docutils literal notranslate"><spanclass="pre">connection_info</span></code>, use <codeclass="docutils literal notranslate"><spanclass="pre">reshow</span></code>, or test the OO interface are not expected
to work for <codeclass="docutils literal notranslate"><spanclass="pre">ipympl</span></code>.</p>
</section>
<sectionid="github-statistics">
<spanid="release-ghstats"></span><h2>GitHub statistics<aclass="headerlink" href="#github-statistics" title="Link to this heading">#</a></h2>
<p>We automatically extract GitHub issue, PRs, and authors from GitHub via the API. To
prepare this list:</p>
<olclass="arabic">
<li><p>Archive the existing GitHub statistics page.</p>
<olclass="loweralpha simple">
<li><p>Copy the current <codeclass="file docutils literal notranslate"><spanclass="pre">doc/users/github_stats.rst</span></code> to
<li><p>Review and commit changes. Some issue/PR titles may not be valid reST (the most
common issue is <codeclass="docutils literal notranslate"><spanclass="pre">*</span></code> which is interpreted as unclosed markup).</p></li>
</ol>
<divclass="admonition note">
<pclass="admonition-title">Note</p>
<p>Make sure you authenticate against the GitHub API. If you do not, you will get
blocked by GitHub for going over the API rate limits. You can authenticate in one of
two ways:</p>
<ulclass="simple">
<li><p>using the <codeclass="docutils literal notranslate"><spanclass="pre">keyring</span></code> package; <codeclass="docutils literal notranslate"><spanclass="pre">pip</span><spanclass="pre">install</span><spanclass="pre">keyring</span></code> and then when
running the stats script, you will be prompted for user name and password,
that will be stored in your system keyring, or,</p></li>
<li><p>using a personal access token; generate a new token <aclass="reference external" href="https://github.com/settings/tokens">on this GitHub page</a> with the <codeclass="docutils literal notranslate"><spanclass="pre">repo:public_repo</span></code>
scope and place the token in <codeclass="file docutils literal notranslate"><spanclass="pre">~/.ghoauth</span></code>.</p></li>
</ul>
</div>
</section>
<sectionid="update-and-validate-the-docs">
<spanid="release-chkdocs"></span><h2>Update and validate the docs<aclass="headerlink" href="#update-and-validate-the-docs" title="Link to this heading">#</a></h2>
<sectionid="merge-doc-branch">
<h3>Merge <codeclass="docutils literal notranslate"><spanclass="pre">*-doc</span></code> branch<aclass="headerlink" href="#merge-doc-branch" title="Link to this heading">#</a></h3>
<p>Merge the most recent 'doc' branch (e.g., <codeclass="docutils literal notranslate"><spanclass="pre">v3.7.0-doc</span></code>) into the branch you
are going to tag on and delete the doc branch on GitHub.</p>
<h3>Update supported versions in Security Policy<aclass="headerlink" href="#update-supported-versions-in-security-policy" title="Link to this heading">#</a></h3>
<p>When making macro or meso releases, update the supported versions in the Security
Policy in <codeclass="file docutils literal notranslate"><spanclass="pre">SECURITY.md</span></code>.</p>
<p>For meso version release update the table in <codeclass="file docutils literal notranslate"><spanclass="pre">SECURITY.md</span></code> to specify that the
two most recent meso releases in the current macro version series are supported.</p>
<p>For a macro version release update the table in <codeclass="file docutils literal notranslate"><spanclass="pre">SECURITY.md</span></code> to specify that the
last meso version in the previous macro version series is still supported. Dropping
support for the last version of a macro version series will be handled on an ad-hoc
basis.</p>
</section>
<sectionid="update-release-notes">
<h3>Update release notes<aclass="headerlink" href="#update-release-notes" title="Link to this heading">#</a></h3>
<sectionid="what-s-new">
<h4>What's new<aclass="headerlink" href="#what-s-new" title="Link to this heading">#</a></h4>
<p><em>Only needed for macro and meso releases. Bugfix releases should not have new
features.</em></p>
<p>Merge the contents of all the files in <codeclass="file docutils literal notranslate"><spanclass="pre">doc/users/next_whats_new/</span></code> into a single
file <codeclass="file docutils literal notranslate"><spanclass="pre">doc/users/prev_whats_new/whats_new_</span><em><spanclass="pre">X</span></em><spanclass="pre">.</span><em><spanclass="pre">Y</span></em><spanclass="pre">.0.rst</span></code> and delete the individual
files.</p>
</section>
<sectionid="api-changes">
<h4>API changes<aclass="headerlink" href="#api-changes" title="Link to this heading">#</a></h4>
<p><em>Primarily needed for macro and meso releases. We may sometimes have API
changes in micro releases.</em></p>
<p>Merge the contents of all the files in <codeclass="file docutils literal notranslate"><spanclass="pre">doc/api/next_api_changes/</span></code> into a single
file <codeclass="file docutils literal notranslate"><spanclass="pre">doc/api/prev_api_changes/api_changes_</span><em><spanclass="pre">X</span></em><spanclass="pre">.</span><em><spanclass="pre">Y</span></em><spanclass="pre">.</span><em><spanclass="pre">Z</span></em><spanclass="pre">.rst</span></code> and delete the
individual files.</p>
</section>
<sectionid="release-notes-toc">
<h4>Release notes TOC<aclass="headerlink" href="#release-notes-toc" title="Link to this heading">#</a></h4>
<li><p>If a micro release, <codeclass="samp docutils literal notranslate"><em><spanclass="pre">X</span></em><spanclass="pre">.</span><em><spanclass="pre">Y</span></em><spanclass="pre">.</span><em><spanclass="pre">Z</span></em></code>, no changes are needed.</p></li>
<li><p>If a macro release, <codeclass="samp docutils literal notranslate"><em><spanclass="pre">X</span></em><spanclass="pre">.</span><em><spanclass="pre">Y</span></em><spanclass="pre">.0</span></code>, change the name of <codeclass="samp docutils literal notranslate"><spanclass="pre">name:</span><em><spanclass="pre">X</span></em><spanclass="pre">.</span><em><spanclass="pre">Y+1</span></em>
<spanclass="pre">(dev)</span></code> and <codeclass="samp docutils literal notranslate"><spanclass="pre">name:</span><em><spanclass="pre">X</span></em><spanclass="pre">.</span><em><spanclass="pre">Y</span></em><spanclass="pre">(stable)</span></code> as well as adding a new version for the
<p>Address any issues which may arise. The internal links are checked on Circle CI, so this
should only flag failed external links.</p>
</section>
</section>
<sectionid="create-release-commit-and-tag">
<spanid="release-tag"></span><h2>Create release commit and tag<aclass="headerlink" href="#create-release-commit-and-tag" title="Link to this heading">#</a></h2>
<p>To create the tag, first create an empty commit with a very terse set of the release
<p>which will prompt you for your GPG key password and an annotation. For pre-releases it
is important to follow <spanclass="target" id="index-0"></span><aclass="pep reference external" href="https://peps.python.org/pep-0440/"><strong>PEP 440</strong></a> so that the build artifacts will sort correctly in
PyPI.</p>
<p>To prevent issues with any down-stream builders which download the tarball from GitHub
it is important to move all branches away from the commit with the tag <aclass="footnote-reference brackets" href="#id3" id="id2" role="doc-noteref"><spanclass="fn-bracket">[</span>1<spanclass="fn-bracket">]</span></a>:</p>
<p>The tarball that is provided by GitHub is produced using <aclass="reference external" href="https://git-scm.com/docs/git-archive">git archive</a>.
We use <aclass="reference external" href="https://github.com/pypa/setuptools_scm">setuptools_scm</a> which uses a format string in
<codeclass="file docutils literal notranslate"><spanclass="pre">lib/matplotlib/_version.py</span></code> to have <codeclass="docutils literal notranslate"><spanclass="pre">git</span></code> insert a
list of references to exported commit (see
<codeclass="file docutils literal notranslate"><spanclass="pre">.gitattributes</span></code> for the configuration). This string is
then used by <codeclass="docutils literal notranslate"><spanclass="pre">setuptools_scm</span></code> to produce the correct version,
based on the git tag, when users install from the tarball.
However, if there is a branch pointed at the tagged commit,
then the branch name will also be included in the tarball.
When the branch eventually moves, anyone who checked the hash
of the tarball before the branch moved will have an incorrect
<p>Update (or create) the <codeclass="docutils literal notranslate"><spanclass="pre">v3.7-doc</span></code> milestone.
The description should include the instruction for meeseeksmachine to backport changes
with the <codeclass="docutils literal notranslate"><spanclass="pre">v3.7-doc</span></code> milestone to both the <codeclass="docutils literal notranslate"><spanclass="pre">v3.7.x</span></code> branch and the <codeclass="docutils literal notranslate"><spanclass="pre">v3.7.0-doc</span></code> branch:</p>
<p>Check all active milestones for consistency. Older doc milestones should also backport to
higher meso versions (e.g. <codeclass="docutils literal notranslate"><spanclass="pre">v3.6-doc</span></code> should backport to both <codeclass="docutils literal notranslate"><spanclass="pre">v3.6.x</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">v3.7.x</span></code>
if the <codeclass="docutils literal notranslate"><spanclass="pre">v3.7.x</span></code> branch exists)</p>
</section>
<sectionid="release-management-doi">
<spanid="release-doi"></span><h2>Release management / DOI<aclass="headerlink" href="#release-management-doi" title="Link to this heading">#</a></h2>
<p>Via the <aclass="reference external" href="https://github.com/matplotlib/matplotlib/releases">GitHub UI</a>, turn the
newly pushed tag into a release. If this is a pre-release remember to mark it as such.</p>
<p>For final releases, also get the DOI from <aclass="reference external" href="https://zenodo.org/">Zenodo</a> (which will
automatically produce one once the tag is pushed). Add the DOI post-fix and version to
the dictionary in <codeclass="file docutils literal notranslate"><spanclass="pre">tools/cache_zenodo_svg.py</span></code> and run the script.</p>
<p>This will download the new SVG to <codeclass="file docutils literal notranslate"><spanclass="pre">doc/_static/zenodo_cache/</span><em><spanclass="pre">postfix</span></em><spanclass="pre">.svg</span></code> and
edit <codeclass="file docutils literal notranslate"><spanclass="pre">doc/project/citing.rst</span></code>. Commit the new SVG, the change to
<codeclass="file docutils literal notranslate"><spanclass="pre">tools/cache_zenodo_svg.py</span></code>, and the changes to <codeclass="file docutils literal notranslate"><spanclass="pre">doc/project/citing.rst</span></code>
<spanid="release-bld-bin"></span><h2>Building binaries<aclass="headerlink" href="#building-binaries" title="Link to this heading">#</a></h2>
<p>We distribute macOS, Windows, and many Linux wheels as well as a source tarball via
PyPI. Most builders should trigger automatically once the tag is pushed to GitHub:</p>
<ulclass="simple">
<li><p>Windows, macOS and manylinux wheels are built on GitHub Actions. Builds are triggered
by the GitHub Action defined in <codeclass="file docutils literal notranslate"><spanclass="pre">.github/workflows/cibuildwheel.yml</span></code>, and wheels
will be available as artifacts of the build.</p></li>
<li><p>The auto-tick bot should open a pull request into the <aclass="reference external" href="https://github.com/conda-forge/matplotlib-feedstock">conda-forge feedstock</a>. Review and merge (if you
have the power to).</p></li>
</ul>
<divclass="admonition warning">
<pclass="admonition-title">Warning</p>
<p>Because this is automated, it is extremely important to bump all branches away from
the tag as discussed in <aclass="reference internal" href="#release-tag"><spanclass="std std-ref">Create release commit and tag</span></a>.</p>
<spanid="release-upload-bin"></span><h2>Make distribution and upload to PyPI<aclass="headerlink" href="#make-distribution-and-upload-to-pypi" title="Link to this heading">#</a></h2>
<p>Once you have collected all of the wheels (expect this to take a few hours), generate
<p>and copy all of the wheels into <codeclass="file docutils literal notranslate"><spanclass="pre">dist</span></code> directory. First, check that the dist files
<p>Congratulations, you have now done the second scariest part!</p>
</section>
<sectionid="build-and-deploy-documentation">
<spanid="release-docs"></span><h2>Build and deploy documentation<aclass="headerlink" href="#build-and-deploy-documentation" title="Link to this heading">#</a></h2>
<p>To build the documentation you must have the tagged version installed, but
build the docs from the <codeclass="docutils literal notranslate"><spanclass="pre">ver-doc</span></code> branch. An easy way to arrange this is:</p>
<p>which will build both the HTML and PDF version of the documentation.</p>
<p>The built documentation exists in the <aclass="reference external" href="https://github.com/matplotlib/matplotlib.github.com/">matplotlib.github.com</a> repository.
Pushing changes to main automatically updates the website.</p>
<p>The documentation is organized in subdirectories by version. The latest stable release
is symlinked from the <codeclass="file docutils literal notranslate"><spanclass="pre">stable</span></code> directory. The documentation for current main is
built on Circle CI and pushed to the <aclass="reference external" href="https://github.com/matplotlib/devdocs/">devdocs</a> repository. These are available at
git<spanclass="w"></span>commit<spanclass="w"></span>-a<spanclass="w"></span>-m<spanclass="w"></span><spanclass="s1">'Updating docs for v3.7.0'</span>
<p>Congratulations you have now done the third scariest part!</p>
<p>If you have access, clear the CloudFlare caches.</p>
<p>It typically takes about 5-10 minutes for the website to process the push and update the
live web page (remember to clear your browser cache).</p>
</section>
<sectionid="merge-up-changes-to-main">
<spanid="release-merge-up"></span><h2>Merge up changes to main<aclass="headerlink" href="#merge-up-changes-to-main" title="Link to this heading">#</a></h2>
<p>After a release is done, the changes from the release branch should be merged into the
<codeclass="docutils literal notranslate"><spanclass="pre">main</span></code> branch. This is primarily done so that the released tag is on the main branch
so <codeclass="docutils literal notranslate"><spanclass="pre">git</span><spanclass="pre">describe</span></code> (and thus <codeclass="docutils literal notranslate"><spanclass="pre">setuptools-scm</span></code>) has the most current tag.
Secondarily, changes made during release (including removing individualized release
notes, fixing broken links, and updating the version switcher) are bubbled up to
<p>Git conflicts are very likely to arise, though aside from changes made directly to the
release branch (mostly as part of the release), they should be relatively-easily resolved
by using the version from <codeclass="docutils literal notranslate"><spanclass="pre">main</span></code>. This is not a universal rule, and care should be
<p>Due to branch protections for the <codeclass="docutils literal notranslate"><spanclass="pre">main</span></code> branch, this is merged via a standard pull
request, though the PR cleanliness status check is expected to fail. The PR should not
be squashed because the intent is to merge the branch histories.</p>
</section>
<sectionid="publicize-this-release">
<h2>Publicize this release<aclass="headerlink" href="#publicize-this-release" title="Link to this heading">#</a></h2>
<p>After the release is published to PyPI and conda, it should be announced