diff --git a/.appveyor.yml b/.appveyor.yml
index 6e71e94e58f5..a637fe545466 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -1,7 +1,7 @@
# With infos from
# http://tjelvarolsson.com/blog/how-to-continuously-test-your-python-code-on-windows-using-appveyor/
# https://packaging.python.org/en/latest/appveyor/
-# https://github.com/rmcgibbo/python-appveyor-conda-example
+---
# Backslashes in quotes need to be escaped: \ -> "\\"
branches:
@@ -17,28 +17,24 @@ skip_commits:
clone_depth: 50
-image: Visual Studio 2017
+image: Visual Studio 2019
environment:
global:
PYTHONFAULTHANDLER: 1
PYTHONIOENCODING: UTF-8
- PYTEST_ARGS: -raR --numprocesses=auto --timeout=300 --durations=25
+ PYTEST_ARGS: -rfEsXR --numprocesses=auto --timeout=300 --durations=25
--cov-report= --cov=lib --log-level=DEBUG
matrix:
- - PYTHON_VERSION: "3.9"
- CONDA_INSTALL_LOCN: "C:\\Miniconda3-x64"
- TEST_ALL: "no"
- - PYTHON_VERSION: "3.10"
- CONDA_INSTALL_LOCN: "C:\\Miniconda3-x64"
- TEST_ALL: "no"
+ - PYTHON_VERSION: "3.11"
+ TEST_ALL: "yes"
# We always use a 64-bit machine, but can build x86 distributions
# with the PYTHON_ARCH variable
platform:
- - x64
+ - x64
# all our python builds have to happen in tests_script...
build: false
@@ -48,41 +44,42 @@ cache:
- '%USERPROFILE%\.cache\matplotlib'
init:
- - echo %PYTHON_VERSION% %CONDA_INSTALL_LOCN%
+ - ps:
+ Invoke-Webrequest
+ -URI https://micro.mamba.pm/api/micromamba/win-64/latest
+ -OutFile C:\projects\micromamba.tar.bz2
+ - ps: C:\PROGRA~1\7-Zip\7z.exe x C:\projects\micromamba.tar.bz2 -aoa -oC:\projects\
+ - ps: C:\PROGRA~1\7-Zip\7z.exe x C:\projects\micromamba.tar -ttar -aoa -oC:\projects\
+ - 'set PATH=C:\projects\Library\bin;%PATH%'
+ - micromamba shell init --shell cmd.exe
+ - micromamba config set always_yes true
+ - micromamba config prepend channels conda-forge
+ - micromamba info
install:
- - set PATH=%CONDA_INSTALL_LOCN%;%CONDA_INSTALL_LOCN%\scripts;%PATH%;
- - conda config --set always_yes true
- - conda config --set show_channel_urls yes
- - conda config --prepend channels conda-forge
-
- # For building, use a new environment
- # Add python version to environment
- # `^ ` escapes spaces for indentation
- - echo ^ ^ - python=%PYTHON_VERSION% >> environment.yml
- - conda env create -f environment.yml
- - activate mpl-dev
- - conda install -c conda-forge pywin32
- - echo %PYTHON_VERSION% %TARGET_ARCH%
- # Show the installed packages + versions
- - conda list
+ - micromamba env create -f environment.yml python=%PYTHON_VERSION% pywin32
+ - micromamba activate mpl-dev
test_script:
# Now build the thing..
- set LINK=/LIBPATH:%cd%\lib
- - pip install -v --no-build-isolation --config-settings=setup-args="--vsenv" --editable .[dev]
+ - pip install -v --no-build-isolation --editable .[dev]
# this should show no freetype dll...
- set "DUMPBIN=%VS140COMNTOOLS%\..\..\VC\bin\dumpbin.exe"
- '"%DUMPBIN%" /DEPENDENTS lib\matplotlib\ft2font*.pyd | findstr freetype.*.dll && exit /b 1 || exit /b 0'
# this are optional dependencies so that we don't skip so many tests...
- - if x%TEST_ALL% == xyes conda install -q ffmpeg inkscape miktex
+ - if x%TEST_ALL% == xyes micromamba install -q ffmpeg inkscape
+ # miktex is available on conda, but seems to fail with permission errors.
# missing packages on conda-forge for imagemagick
# This install sometimes failed randomly :-(
- #- choco install imagemagick
+ # - choco install imagemagick
# Test import of tkagg backend
- - python -c "import matplotlib as m; m.use('tkagg'); import matplotlib.pyplot as plt; print(plt.get_backend())"
+ - python -c
+ "import matplotlib as m; m.use('tkagg');
+ import matplotlib.pyplot as plt;
+ print(plt.get_backend())"
# tests
- echo The following args are passed to pytest %PYTEST_ARGS%
- pytest %PYTEST_ARGS%
@@ -90,11 +87,11 @@ test_script:
artifacts:
- path: result_images\*
name: result_images
- type: zip
+ type: Zip
on_finish:
- - conda install codecov
- - codecov -e PYTHON_VERSION PLATFORM
+ - micromamba install codecov
+ - codecov -e PYTHON_VERSION PLATFORM -n "%PYTHON_VERSION% Windows"
on_failure:
# Generate a html for visual tests
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 2f79a6fbba5c..40ba933cf0d9 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -1,6 +1,6 @@
# Circle CI configuration file
# https://circleci.com/docs/
-
+---
version: 2.1
@@ -17,7 +17,8 @@ commands:
export git_log=$(git log --max-count=1 --pretty=format:"%B" | tr "\n" " ")
echo "Got commit message:"
echo "${git_log}"
- if [[ -v CIRCLE_PULL_REQUEST ]] && ([[ "$git_log" == *"[skip circle]"* ]] || [[ "$git_log" == *"[circle skip]"* ]]); then
+ if [[ -v CIRCLE_PULL_REQUEST ]] &&
+ [[ $git_log =~ (\[skip circle\]|\[circle skip\]|\[skip doc\]|\[doc skip\]) ]]; then
echo "Skip detected, exiting job ${CIRCLE_JOB} for PR ${CIRCLE_PULL_REQUEST}."
circleci-agent step halt;
fi
@@ -71,8 +72,12 @@ commands:
name: Install custom fonts
command: |
mkdir -p ~/.local/share/fonts
- wget -nc https://github.com/google/fonts/blob/master/ofl/felipa/Felipa-Regular.ttf?raw=true -O ~/.local/share/fonts/Felipa-Regular.ttf || true
- wget -nc https://github.com/ipython/xkcd-font/blob/master/xkcd-script/font/xkcd-script.ttf?raw=true -O ~/.local/share/fonts/xkcd-Script.ttf || true
+ wget -nc \
+ https://github.com/google/fonts/blob/master/ofl/felipa/Felipa-Regular.ttf?raw=true \
+ -O ~/.local/share/fonts/Felipa-Regular.ttf || true
+ wget -nc \
+ https://github.com/ipython/xkcd-font/blob/master/xkcd-script/font/xkcd-script.ttf?raw=true \
+ -O ~/.local/share/fonts/xkcd-Script.ttf || true
fc-cache -f -v
- save_cache:
key: fonts-4
@@ -98,7 +103,7 @@ commands:
- run:
name: Install Python dependencies
command: |
- python -m pip install --user meson-python pybind11
+ python -m pip install --user -r requirements/dev/build-requirements.txt
python -m pip install --user \
numpy<< parameters.numpy_version >> \
-r requirements/doc/doc-requirements.txt
@@ -199,15 +204,21 @@ commands:
- store_artifacts:
path: doc/build/sphinx-gallery-files.tar.gz
+ deploy-docs:
+ steps:
+ - run:
+ name: "Deploy new docs"
+ command: ./.circleci/deploy-docs.sh
+
##########################################
# Here is where the real jobs are defined.
#
jobs:
- docs-python39:
+ docs-python3:
docker:
- - image: cimg/python:3.9
+ - image: cimg/python:3.12
resource_class: large
steps:
- checkout
@@ -236,9 +247,7 @@ jobs:
fingerprints:
- "be:c3:c1:d8:fb:a1:0e:37:71:72:d7:a3:40:13:8f:14"
- - deploy:
- name: "Deploy new docs"
- command: ./.circleci/deploy-docs.sh
+ - deploy-docs
#########################################
# Defining workflows gets us parallelism.
@@ -250,4 +259,4 @@ workflows:
jobs:
# NOTE: If you rename this job, then you must update the `if` condition
# and `circleci-jobs` option in `.github/workflows/circleci.yml`.
- - docs-python39
+ - docs-python3
diff --git a/.flake8 b/.flake8
deleted file mode 100644
index 00cd213e0f79..000000000000
--- a/.flake8
+++ /dev/null
@@ -1,95 +0,0 @@
-[flake8]
-max-line-length = 88
-select =
- # flake8 default
- D, E, F, W,
-ignore =
- # flake8 default
- E121,E123,E126,E226,E24,E704,W503,W504,
- # Additional ignores:
- E127, E131,
- E266,
- E305, E306,
- E741,
- F841,
- # pydocstyle
- D100, D101, D102, D103, D104, D105, D106,
- D200, D202, D204, D205,
- D301,
- D400, D401, D403, D404
- # ignored by pydocstyle numpy docstring convention
- D107, D203, D212, D213, D402, D413, D415, D416, D417,
-
-exclude =
- .git
- build
- doc/gallery
- doc/tutorials
- # External files.
- tools/gh_api.py
- .tox
- .eggs
-
-per-file-ignores =
- lib/matplotlib/__init__.py: E402, F401
- lib/matplotlib/_animation_data.py: E501
- lib/matplotlib/_api/__init__.py: F401
- lib/matplotlib/_cm.py: E122, E202, E203, E302
- lib/matplotlib/_mathtext.py: E221, E251
- lib/matplotlib/_mathtext_data.py: E122, E203, E261
- lib/matplotlib/axes/__init__.py: F401, F403
- lib/matplotlib/backends/backend_template.py: F401
- lib/matplotlib/font_manager.py: E501
- lib/matplotlib/image.py: F401, F403
- lib/matplotlib/mathtext.py: E221
- lib/matplotlib/pylab.py: F401, F403
- lib/matplotlib/pyplot.py: F401, F811
- lib/matplotlib/tests/test_mathtext.py: E501
- lib/matplotlib/transforms.py: E201, E202, E203
- lib/matplotlib/tri/_triinterpolate.py: E201, E221
- lib/mpl_toolkits/axes_grid1/axes_size.py: E272
- lib/mpl_toolkits/axisartist/__init__.py: F401
- lib/mpl_toolkits/axisartist/angle_helper.py: E221
- lib/pylab.py: F401, F403
-
- doc/conf.py: E402
- galleries/users_explain/artists/paths.py: E402
- galleries/users_explain/artists/patheffects_guide.py: E402
- galleries/users_explain/artists/transforms_tutorial.py: E402, E501
- galleries/users_explain/colors/colormaps.py: E501
- galleries/users_explain/colors/colors.py: E402
- galleries/tutorials/artists.py: E402
- galleries/users_explain/axes/constrainedlayout_guide.py: E402
- galleries/users_explain/axes/legend_guide.py: E402
- galleries/users_explain/axes/tight_layout_guide.py: E402
- galleries/users_explain/animations/animations.py: E501
- galleries/tutorials/images.py: E501
- galleries/tutorials/pyplot.py: E402, E501
- galleries/users_explain/text/annotations.py: E402, E501
- galleries/users_explain/text/mathtext.py: E501
- galleries/users_explain/text/text_intro.py: E402
- galleries/users_explain/text/text_props.py: E501
-
- galleries/examples/animation/frame_grabbing_sgskip.py: E402
- galleries/examples/images_contours_and_fields/tricontour_demo.py: E201
- galleries/examples/images_contours_and_fields/tripcolor_demo.py: E201
- galleries/examples/images_contours_and_fields/triplot_demo.py: E201
- galleries/examples/lines_bars_and_markers/marker_reference.py: E402
- galleries/examples/misc/print_stdout_sgskip.py: E402
- galleries/examples/misc/table_demo.py: E201
- galleries/examples/style_sheets/bmh.py: E501
- galleries/examples/subplots_axes_and_figures/demo_constrained_layout.py: E402
- galleries/examples/text_labels_and_annotations/custom_legends.py: E402
- galleries/examples/ticks/date_concise_formatter.py: E402
- galleries/examples/ticks/date_formatters_locators.py: F401
- galleries/examples/user_interfaces/embedding_in_gtk3_panzoom_sgskip.py: E402
- galleries/examples/user_interfaces/embedding_in_gtk3_sgskip.py: E402
- galleries/examples/user_interfaces/embedding_in_gtk4_panzoom_sgskip.py: E402
- galleries/examples/user_interfaces/embedding_in_gtk4_sgskip.py: E402
- galleries/examples/user_interfaces/gtk3_spreadsheet_sgskip.py: E402
- galleries/examples/user_interfaces/gtk4_spreadsheet_sgskip.py: E402
- galleries/examples/user_interfaces/mpl_with_glade3_sgskip.py: E402
- galleries/examples/user_interfaces/pylab_with_gtk3_sgskip.py: E402
- galleries/examples/user_interfaces/pylab_with_gtk4_sgskip.py: E402
- galleries/examples/userdemo/pgf_preamble_sgskip.py: E402
-force-check = True
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index 613852425632..611431e707ab 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -12,3 +12,6 @@ c1a33a481b9c2df605bcb9bef9c19fe65c3dac21
# chore: pyupgrade --py39-plus
4d306402bb66d6d4c694d8e3e14b91054417070e
+
+# style: docstring parameter indentation
+68daa962de5634753205cba27f21d6edff7be7a2
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index c4198cdcdf14..cb27bbf19d46 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -1 +1 @@
-Please refer to the [developers guide](https://matplotlib.org/devel/index.html).
+Please refer to the [contributing guide](https://matplotlib.org/devel/index.html).
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index 5c9afed3c02b..a474d51d6f64 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,3 +1,4 @@
+---
# These are supported funding model platforms
github: [matplotlib, numfocus]
custom: https://numfocus.org/donate-to-matplotlib
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 985762649b67..a19b6d2346e3 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -1,3 +1,4 @@
+---
name: Bug Report
description: Report a bug or issue with Matplotlib.
title: "[Bug]: "
@@ -6,26 +7,26 @@ body:
id: summary
attributes:
label: Bug summary
- description: Describe the bug in 1-2 short sentences
- placeholder:
- value:
+ description: Describe the bug in 1-2 short sentences
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: Code for reproduction
- description: |
- If possible, please provide a minimum self-contained example.
+ description: >-
+ If possible, please provide a minimum self-contained example. If you
+ have used generative AI as an aid see
+ https://matplotlib.org/devdocs/devel/contribute.html#restrictions-on-generative-ai-usage
placeholder: Paste your code here. This field is automatically formatted as Python code.
- render: python
+ render: Python
validations:
required: true
- type: textarea
id: actual
attributes:
label: Actual outcome
- description: |
+ description: >-
Paste the output produced by the code provided above, e.g.
console output, images/videos produced by the code, any relevant screenshots/screencasts, etc.
validations:
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index 10c9d5c0d580..dc80f6d7c91d 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1,5 +1,7 @@
-# Ref: https://help.github.com/en/github/building-a-strong-community/configuring-issue-templates-for-your-repository#configuring-the-template-chooser
-blank_issues_enabled: true # default
+# Reference:
+# https://help.github.com/en/github/building-a-strong-community/configuring-issue-templates-for-your-repository#configuring-the-template-chooser
+---
+blank_issues_enabled: true # default
contact_links:
- name: Question/Support/Other
url: https://discourse.matplotlib.org
diff --git a/.github/ISSUE_TEMPLATE/documentation.yml b/.github/ISSUE_TEMPLATE/documentation.yml
index ea0eb385baaf..5f7a0d6c7176 100644
--- a/.github/ISSUE_TEMPLATE/documentation.yml
+++ b/.github/ISSUE_TEMPLATE/documentation.yml
@@ -1,3 +1,4 @@
+---
name: Documentation
description: Create a report to help us improve the documentation
title: "[Doc]: "
@@ -7,9 +8,9 @@ body:
id: link
attributes:
label: Documentation Link
- description: |
- Link to any documentation or examples that you are referencing.
- Suggested improvements should be based on the development version of the docs: https://matplotlib.org/devdocs/
+ description: >-
+ Link to any documentation or examples that you are referencing. Suggested improvements should be based
+ on [the development version of the docs](https://matplotlib.org/devdocs/)
placeholder: https://matplotlib.org/devdocs/...
- type: textarea
id: problem
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
index 5274c287569c..e174fb8994aa 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.yml
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -1,3 +1,4 @@
+---
name: Feature Request
description: Suggest something to add to Matplotlib!
title: "[ENH]: "
@@ -5,8 +6,9 @@ labels: [New feature]
body:
- type: markdown
attributes:
- value: |
- Please search the [issues](https://github.com/matplotlib/matplotlib/issues) for relevant feature requests before creating a new feature request.
+ value: >-
+ Please search the [issues](https://github.com/matplotlib/matplotlib/issues) for relevant feature
+ requests before creating a new feature request.
- type: textarea
id: problem
attributes:
diff --git a/.github/ISSUE_TEMPLATE/maintenance.yml b/.github/ISSUE_TEMPLATE/maintenance.yml
index 746ab55ef0e3..6ebb64c0c3e9 100644
--- a/.github/ISSUE_TEMPLATE/maintenance.yml
+++ b/.github/ISSUE_TEMPLATE/maintenance.yml
@@ -1,3 +1,4 @@
+---
name: Maintenance
description: Help improve performance, usability and/or consistency.
title: "[MNT]: "
@@ -7,7 +8,7 @@ body:
id: summary
attributes:
label: Summary
- description: Please provide 1-2 short sentences that succinctly describes what could be improved.
+ description: Please provide 1-2 short sentences that succinctly describes what could be improved.
validations:
required: true
- type: textarea
diff --git a/.github/ISSUE_TEMPLATE/tag_proposal.yml b/.github/ISSUE_TEMPLATE/tag_proposal.yml
index 6876226f6240..2bb856d26be6 100644
--- a/.github/ISSUE_TEMPLATE/tag_proposal.yml
+++ b/.github/ISSUE_TEMPLATE/tag_proposal.yml
@@ -1,12 +1,13 @@
+---
name: Tag Proposal
description: Suggest a new tag or subcategory for the gallery of examples
title: "[Tag]: "
-labels: [Tag proposal]
+labels: ["Documentation: tags"]
body:
- type: markdown
attributes:
- value: |
- Please search the [tag glossary]() for relevant tags before creating a new tag proposal.
+ value: >-
+ Please search the [tag glossary]() for relevant tags before creating a new tag proposal.
- type: textarea
id: need
attributes:
@@ -23,5 +24,5 @@ body:
id: solution
attributes:
label: Proposed solution
- description: >
+ description: >-
What should the tag be? All tags are in the format `subcategory: tag`
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index c79f22ffdf8a..bf483dbdd4f4 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -4,20 +4,30 @@ out the development guide https://matplotlib.org/devdocs/devel/index.html
-->
## PR summary
-
+
+
## PR checklist
- [ ] "closes #0000" is in the body of the PR description to [link the related issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue)
- [ ] new and changed code is [tested](https://matplotlib.org/devdocs/devel/testing.html)
- [ ] *Plotting related* features are demonstrated in an [example](https://matplotlib.org/devdocs/devel/document.html#write-examples-and-tutorials)
-- [ ] *New Features* and *API Changes* are noted with a [directive and release note](https://matplotlib.org/devdocs/devel/coding_guide.html#new-features-and-api-changes)
+- [ ] *New Features* and *API Changes* are noted with a [directive and release note](https://matplotlib.org/devdocs/devel/api_changes.html#announce-changes-deprecations-and-new-features)
- [ ] Documentation complies with [general](https://matplotlib.org/devdocs/devel/document.html#write-rest-pages) and [docstring](https://matplotlib.org/devdocs/devel/document.html#write-docstrings) guidelines
Our Code of Conduct is at
-https://matplotlib.org/stable/users/project/code_of_conduct.html
+https://matplotlib.org/stable/project/code_of_conduct.html
-It is rendered from `doc/users/project/code_of_conduct.rst`
+It is rendered from `doc/project/code_of_conduct.rst`
diff --git a/INSTALL.rst b/INSTALL.rst
index ac24c70ac518..3fb01c58d259 100644
--- a/INSTALL.rst
+++ b/INSTALL.rst
@@ -1 +1 @@
-See doc/users/installing/index.rst
+See doc/install/index.rst
diff --git a/LICENSE/LICENSE_LAST_RESORT_FONT b/LICENSE/LICENSE_LAST_RESORT_FONT
new file mode 100644
index 000000000000..5fe3297bc1e1
--- /dev/null
+++ b/LICENSE/LICENSE_LAST_RESORT_FONT
@@ -0,0 +1,97 @@
+Last Resort High-Efficiency Font License
+========================================
+
+This Font Software is licensed under the SIL Open Font License,
+Version 1.1.
+
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font
+creation efforts of academic and linguistic communities, and to
+provide a free and open framework in which fonts may be shared and
+improved in partnership with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply to
+any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software
+components as distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to,
+deleting, or substituting -- in part or in whole -- any of the
+components of the Original Version, by changing formats or by porting
+the Font Software to a new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed,
+modify, redistribute, and sell modified and unmodified copies of the
+Font Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components, in
+Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the
+corresponding Copyright Holder. This restriction only applies to the
+primary font name as presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created using
+the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
+
+SPDX-License-Identifier: OFL-1.1
diff --git a/README.md b/README.md
index 5e15c645c9a2..7b9c99597c0d 100644
--- a/README.md
+++ b/README.md
@@ -12,6 +12,7 @@
[](https://dev.azure.com/matplotlib/matplotlib/_build/latest?definitionId=1&branchName=main)
[](https://ci.appveyor.com/project/matplotlib/matplotlib)
[](https://app.codecov.io/gh/matplotlib/matplotlib)
+[](https://jacobtomlinson.dev/effver)

@@ -31,7 +32,7 @@ and various graphical user interface toolkits.
See the [install
documentation](https://matplotlib.org/stable/users/installing/index.html),
-which is generated from `/doc/users/installing/index.rst`
+which is generated from `/doc/install/index.rst`
## Contribute
@@ -42,7 +43,7 @@ You've worked out a way to fix it — even better!
You want to tell us about it — best of all!
Start at the [contributing
-guide](https://matplotlib.org/devdocs/devel/contributing.html)!
+guide](https://matplotlib.org/devdocs/devel/contribute.html)!
## Contact
diff --git a/SECURITY.md b/SECURITY.md
index 88d523bec637..4400a4501b51 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -8,13 +8,13 @@ versions.
| Version | Supported |
| ------- | ------------------ |
-| 3.8.x | :white_check_mark: |
-| 3.7.x | :white_check_mark: |
+| 3.10.x | :white_check_mark: |
+| 3.9.x | :white_check_mark: |
+| 3.8.x | :x: |
+| 3.7.x | :x: |
| 3.6.x | :x: |
| 3.5.x | :x: |
-| 3.4.x | :x: |
-| 3.3.x | :x: |
-| < 3.3 | :x: |
+| < 3.5 | :x: |
## Reporting a Vulnerability
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 8eb5cacfb55a..d68a9d36f0d3 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -1,8 +1,10 @@
# Python package
# Create and test a Python package on multiple Python versions.
-# Add steps that analyze code, save the dist with the build record, publish to a PyPI-compatible index, and more:
+# Add steps that analyze code, save the dist with the build record, publish to a PyPI-compatible index, and
+# more:
# https://docs.microsoft.com/en-us/azure/devops/pipelines/ecosystems/python?view=azure-devops
+---
trigger:
branches:
exclude:
@@ -18,154 +20,143 @@ pr:
stages:
-- stage: Check
- jobs:
- - job: Skip
- pool:
- vmImage: 'ubuntu-latest'
- variables:
- DECODE_PERCENTS: 'false'
- RET: 'true'
- steps:
- - bash: |
- git_log=`git log --max-count=1 --skip=1 --pretty=format:"%B" | tr "\n" " "`
- echo "##vso[task.setvariable variable=log]$git_log"
- - bash: echo "##vso[task.setvariable variable=RET]false"
- condition: or(contains(variables.log, '[skip azp]'), contains(variables.log, '[azp skip]'), contains(variables.log, '[skip ci]'), contains(variables.log, '[ci skip]'), contains(variables.log, '[ci doc]'))
- - bash: echo "##vso[task.setvariable variable=start_main;isOutput=true]$RET"
- name: result
-
-- stage: Main
- condition: and(succeeded(), eq(dependencies.Check.outputs['Skip.result.start_main'], 'true'))
- dependsOn: Check
- jobs:
- - job: Pytest
- strategy:
- matrix:
- Linux_py39:
- vmImage: 'ubuntu-20.04' # keep one job pinned to the oldest image
- python.version: '3.9'
- Linux_py310:
- vmImage: 'ubuntu-latest'
- python.version: '3.10'
- Linux_py311:
- vmImage: 'ubuntu-latest'
- python.version: '3.11'
- macOS_py39:
- vmImage: 'macOS-latest'
- python.version: '3.9'
- macOS_py310:
- vmImage: 'macOS-latest'
- python.version: '3.10'
- macOS_py311:
- vmImage: 'macOS-latest'
- python.version: '3.11'
- Windows_py39:
- vmImage: 'windows-2019' # keep one job pinned to the oldest image
- python.version: '3.9'
- Windows_py310:
- vmImage: 'windows-latest'
- python.version: '3.10'
- Windows_py311:
- vmImage: 'windows-latest'
- python.version: '3.11'
- maxParallel: 4
- pool:
- vmImage: '$(vmImage)'
- steps:
- - task: UsePythonVersion@0
- inputs:
- versionSpec: '$(python.version)'
- architecture: 'x64'
- displayName: 'Use Python $(python.version)'
- condition: and(succeeded(), ne(variables['python.version'], 'Pre'))
-
- - task: stevedower.python.InstallPython.InstallPython@1
- displayName: 'Use prerelease Python'
- inputs:
- prerelease: true
- condition: and(succeeded(), eq(variables['python.version'], 'Pre'))
-
- - bash: |
- set -e
- case "$(python -c 'import sys; print(sys.platform)')" in
- linux)
- echo 'Acquire::Retries "3";' | sudo tee /etc/apt/apt.conf.d/80-retries
- sudo apt update
- sudo apt install --no-install-recommends \
- cm-super \
- dvipng \
- ffmpeg \
- fonts-freefont-otf \
- fonts-noto-cjk \
- fonts-wqy-zenhei \
- gdb \
- gir1.2-gtk-3.0 \
- graphviz \
- inkscape \
- libcairo2 \
- libgirepository-1.0-1 \
- lmodern \
- ninja-build \
- poppler-utils \
- texlive-fonts-recommended \
- texlive-latex-base \
- texlive-latex-extra \
- texlive-latex-recommended \
- texlive-luatex \
- texlive-pictures \
- texlive-xetex
- ;;
- darwin)
- brew install --cask xquartz
- brew install ccache ffmpeg imagemagick mplayer ninja pkg-config
- brew tap homebrew/cask-fonts
- brew install font-noto-sans-cjk-sc
- ;;
- win32)
- choco install ninja
- ;;
- *)
- exit 1
- ;;
- esac
- displayName: 'Install dependencies'
-
- - bash: |
- python -m pip install --upgrade pip
- python -m pip install --upgrade meson-python pybind11
- python -m pip install -r requirements/testing/all.txt -r requirements/testing/extra.txt ||
- [[ "$PYTHON_VERSION" = 'Pre' ]]
- displayName: 'Install dependencies with pip'
-
- - bash: |
- python -m pip install \
- --no-build-isolation --config-settings=setup-args="--vsenv" \
- --verbose --editable .[dev] ||
- [[ "$PYTHON_VERSION" = 'Pre' ]]
- displayName: "Install self"
-
- - script: env
- displayName: 'print env'
-
- - script: pip list
- displayName: 'print pip'
-
- - bash: |
- PYTHONFAULTHANDLER=1 python -m pytest --junitxml=junit/test-results.xml -raR --maxfail=50 --timeout=300 --durations=25 --cov-report= --cov=lib -n 2 ||
- [[ "$PYTHON_VERSION" = 'Pre' ]]
- displayName: 'pytest'
-
- - bash: |
- bash <(curl -s https://codecov.io/bash) -f "!*.gcov" -X gcov
- displayName: 'Upload to codecov.io'
-
- - task: PublishTestResults@2
- inputs:
- testResultsFiles: '**/test-results.xml'
- testRunTitle: 'Python $(python.version)'
- condition: succeededOrFailed()
-
- - publish: $(System.DefaultWorkingDirectory)/result_images
- artifact: $(Agent.JobName)-result_images
- condition: and(failed(), ne(variables['python.version'], 'Pre'))
+ - stage: Check
+ jobs:
+ - job: Skip
+ pool:
+ vmImage: 'ubuntu-latest'
+ variables:
+ DECODE_PERCENTS: 'false'
+ RET: 'true'
+ steps:
+ - bash: |
+ git_log=`git log --max-count=1 --skip=1 --pretty=format:"%B" | tr "\n" " "`
+ echo "##vso[task.setvariable variable=log]$git_log"
+ - bash: echo "##vso[task.setvariable variable=RET]false"
+ condition: >-
+ or(contains(variables.log, '[skip azp]'),
+ contains(variables.log, '[azp skip]'),
+ contains(variables.log, '[skip ci]'),
+ contains(variables.log, '[ci skip]'),
+ contains(variables.log, '[ci doc]'))
+ - bash: echo "##vso[task.setvariable variable=start_main;isOutput=true]$RET"
+ name: result
+
+ - stage: Main
+ condition: and(succeeded(), eq(dependencies.Check.outputs['Skip.result.start_main'], 'true'))
+ dependsOn: Check
+ jobs:
+ - job: Pytest
+ strategy:
+ matrix:
+ Windows_py311:
+ vmImage: 'windows-2022' # Keep one job pinned to the oldest image
+ python.version: '3.11'
+ Windows_py312:
+ vmImage: 'windows-latest'
+ python.version: '3.12'
+ Windows_py313:
+ vmImage: 'windows-latest'
+ python.version: '3.13'
+ maxParallel: 4
+ pool:
+ vmImage: '$(vmImage)'
+ steps:
+ - task: UsePythonVersion@0
+ inputs:
+ versionSpec: '$(python.version)'
+ architecture: 'x64'
+ displayName: 'Use Python $(python.version)'
+
+ - bash: |
+ choco install ninja
+ displayName: 'Install dependencies'
+
+ - bash: |
+ python -m pip install --upgrade pip
+ python -m pip install --upgrade -r requirements/dev/build-requirements.txt
+ python -m pip install -r requirements/testing/all.txt -r requirements/testing/extra.txt
+ displayName: 'Install dependencies with pip'
+
+ - bash: |
+ CONFIG='--config-settings=setup-args=--vsenv'
+ CONFIG="$CONFIG --config-settings=setup-args=-Dcpp_link_args=-PROFILE"
+ CONFIG="$CONFIG --config-settings=setup-args=-Dbuildtype=debug"
+
+ python -m pip install \
+ --no-build-isolation $CONFIG \
+ --verbose --editable .[dev]
+ displayName: "Install self"
+
+ - script: env
+ displayName: 'print env'
+
+ - script: pip list
+ displayName: 'print pip'
+
+ - bash: |
+ set -e
+ SESSION_ID=$(python -c "import uuid; print(uuid.uuid4(), end='')")
+ echo "Coverage session ID: ${SESSION_ID}"
+ VS=$(ls -d /c/Program\ Files*/Microsoft\ Visual\ Studio/*/Enterprise)
+ echo "Visual Studio: ${VS}"
+ DIR="$VS/Common7/IDE/Extensions/Microsoft/CodeCoverage.Console"
+ # This is for MSVC 2022 (on windows-latest).
+ TOOL="$DIR/Microsoft.CodeCoverage.Console.exe"
+ for f in build/cp*/src/*.pyd; do
+ echo $f
+ echo "=============================="
+ "$TOOL" instrument $f --session-id $SESSION_ID \
+ --log-level Verbose --log-file instrument.log
+ cat instrument.log
+ rm instrument.log
+ done
+ echo "Starting $TOOL in server mode"
+ "$TOOL" collect \
+ --session-id $SESSION_ID --server-mode \
+ --output-format cobertura --output extensions.xml \
+ --log-level Verbose --log-file extensions.log &
+ VS_VER=2022
+
+ echo "##vso[task.setvariable variable=VS_COVERAGE_TOOL]$TOOL"
+
+ PYTHONFAULTHANDLER=1 pytest -rfEsXR -n 2 \
+ --maxfail=50 --timeout=300 --durations=25 \
+ --junitxml=junit/test-results.xml --cov-report=xml --cov=lib
+
+ if [[ $VS_VER == 2022 ]]; then
+ "$TOOL" shutdown $SESSION_ID
+ echo "Coverage collection log"
+ echo "======================="
+ cat extensions.log
+ else
+ "$TOOL" shutdown -session:$SESSION_ID
+ fi
+ displayName: 'pytest'
+
+ - bash: |
+ if [[ -f extensions.coverage ]]; then
+ # For MSVC 2019.
+ "$VS_COVERAGE_TOOL" analyze -output:extensions.xml \
+ -include_skipped_functions -include_skipped_modules \
+ extensions.coverage
+ rm extensions.coverage
+ fi
+ displayName: 'Filter C coverage'
+ condition: succeededOrFailed()
+ - bash: |
+ bash <(curl -s https://codecov.io/bash) \
+ -n "$PYTHON_VERSION $AGENT_OS" \
+ -f 'coverage.xml' -f 'extensions.xml'
+ displayName: 'Upload to codecov.io'
+ condition: succeededOrFailed()
+
+ - task: PublishTestResults@2
+ inputs:
+ testResultsFiles: '**/test-results.xml'
+ testRunTitle: 'Python $(python.version)'
+ condition: succeededOrFailed()
+
+ - publish: $(System.DefaultWorkingDirectory)/result_images
+ artifact: $(Agent.JobName)-result_images
+ condition: failed()
diff --git a/ci/codespell-ignore-words.txt b/ci/codespell-ignore-words.txt
index 1a29d054cdc3..0ebc5211b80c 100644
--- a/ci/codespell-ignore-words.txt
+++ b/ci/codespell-ignore-words.txt
@@ -1,24 +1,22 @@
aas
-ans
+ABD
axises
-ba
-cannotation
-ccompiler
coo
curvelinear
-dedented
-falsy
+filll
flate
fpt
hax
-hist
inh
inout
ment
nd
+oint
oly
-resizeable
te
thisy
+ure
whis
wit
+Copin
+socio-economic
diff --git a/ci/mypy-stubtest-allowlist.txt b/ci/mypy-stubtest-allowlist.txt
index 9f3efd283906..46ec06e0a9f1 100644
--- a/ci/mypy-stubtest-allowlist.txt
+++ b/ci/mypy-stubtest-allowlist.txt
@@ -1,54 +1,51 @@
# Non-typed (and private) modules/functions
-matplotlib.backends.*
-matplotlib.tests.*
-matplotlib.pylab.*
-matplotlib._.*
-matplotlib.rcsetup._listify_validator
-matplotlib.rcsetup._validate_linestyle
-matplotlib.ft2font.Glyph
-matplotlib.testing.jpl_units.*
-matplotlib.sphinxext.*
+matplotlib\.backends\..*
+matplotlib\.tests(\..*)?
+matplotlib\.pylab(\..*)?
+matplotlib\._.*
+matplotlib\.rcsetup\._listify_validator
+matplotlib\.rcsetup\._validate_linestyle
+matplotlib\.ft2font\.Glyph
+matplotlib\.testing\.jpl_units\..*
+matplotlib\.sphinxext(\..*)?
# set methods have heavy dynamic usage of **kwargs, with differences for subclasses
# which results in technically inconsistent signatures, but not actually a problem
-matplotlib.*\.set$
+matplotlib\..*\.set$
# Typed inline, inconsistencies largely due to imports
-matplotlib.pyplot.*
-matplotlib.typing.*
+matplotlib\.pyplot\..*
+matplotlib\.typing\..*
# Other decorator modifying signature
-# Runtime picks up *args **kwargs, but only decorated by a decorator that uses @wraps so?
-matplotlib.axis.Axis.draw
# Backcompat decorator which does not modify runtime reported signature
-matplotlib.offsetbox.*Offset[Bb]ox.get_offset
+matplotlib\.offsetbox\..*Offset[Bb]ox\.get_offset
# Inconsistent super/sub class parameter name (maybe rename for consistency)
-matplotlib.projections.polar.RadialLocator.nonsingular
-matplotlib.ticker.LogLocator.nonsingular
-matplotlib.ticker.LogitLocator.nonsingular
+matplotlib\.projections\.polar\.RadialLocator\.nonsingular
+matplotlib\.ticker\.LogLocator\.nonsingular
+matplotlib\.ticker\.LogitLocator\.nonsingular
# Stdlib/Enum considered inconsistent (no fault of ours, I don't think)
-matplotlib.backend_bases._Mode.__new__
-matplotlib.units.Number.__hash__
+matplotlib\.backend_bases\._Mode\.__new__
+matplotlib\.units\.Number\.__hash__
# 3.6 Pending deprecations
-matplotlib.figure.Figure.set_constrained_layout
-matplotlib.figure.Figure.set_constrained_layout_pads
-matplotlib.figure.Figure.set_tight_layout
-
-# 3.7 deprecations
-matplotlib.cm.register_cmap
-matplotlib.cm.unregister_cmap
-
-# positional-only argument name lacking leading underscores
-matplotlib.axes._base._AxesBase.axis
+matplotlib\.figure\.Figure\.set_constrained_layout
+matplotlib\.figure\.Figure\.set_constrained_layout_pads
+matplotlib\.figure\.Figure\.set_tight_layout
# Maybe should be abstractmethods, required for subclasses, stubs define once
-matplotlib.tri.*TriInterpolator.__call__
-matplotlib.tri.*TriInterpolator.gradient
+matplotlib\.tri\..*TriInterpolator\.__call__
+matplotlib\.tri\..*TriInterpolator\.gradient
# TypeVar used only in type hints
-matplotlib.backend_bases.FigureCanvasBase._T
-matplotlib.backend_managers.ToolManager._T
-matplotlib.spines.Spine._T
+matplotlib\.backend_bases\.FigureCanvasBase\._T
+matplotlib\.backend_managers\.ToolManager\._T
+matplotlib\.spines\.Spine\._T
+
+# Parameter inconsistency due to 3.10 deprecation
+matplotlib\.figure\.FigureBase\.get_figure
+
+# getitem method only exists for 3.10 deprecation backcompatability
+matplotlib\.inset\.InsetIndicator\.__getitem__
diff --git a/ci/schemas/README.md b/ci/schemas/README.md
new file mode 100644
index 000000000000..087fd31d2ab8
--- /dev/null
+++ b/ci/schemas/README.md
@@ -0,0 +1,5 @@
+YAML Schemas for linting and validation
+=======================================
+
+Since pre-commit CI doesn't have Internet access, we need to bundle these files
+in the repo. The schemas can be updated using `vendor_schemas.py`.
diff --git a/ci/schemas/appveyor.json b/ci/schemas/appveyor.json
new file mode 100644
index 000000000000..d19a10f23b75
--- /dev/null
+++ b/ci/schemas/appveyor.json
@@ -0,0 +1,781 @@
+{
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "allOf": [
+ {
+ "$ref": "#/definitions/job"
+ }
+ ],
+ "definitions": {
+ "possiblySecretString": {
+ "anyOf": [
+ {
+ "type": "string",
+ "description": "This value will be used directly (regular string)"
+ },
+ {
+ "type": "number",
+ "description": "This value will be treated as a string even though it is a number"
+ },
+ {
+ "title": "secret string",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "secure": {
+ "type": "string",
+ "description": "This should have been encrypted by the same user account to which the project belongs"
+ }
+ }
+ }
+ ]
+ },
+ "commitFilter": {
+ "title": "commit filter",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "message": {
+ "type": "string",
+ "format": "regex",
+ "description": "Regex for matching commit message"
+ },
+ "author": {
+ "description": "Commit author's username, name, email or regexp matching one of these.",
+ "anyOf": [
+ {
+ "type": "string",
+ "format": "regex"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ },
+ "files": {
+ "type": "array",
+ "description": "Only specific files (glob patterns)",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "command": {
+ "title": "command",
+ "oneOf": [
+ {
+ "type": "string",
+ "description": "Run a batch command"
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "ps": {
+ "type": "string",
+ "description": "Run a PowerShell command"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pwsh": {
+ "type": "string",
+ "description": "Run a PowerShell Core command"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "description": "Run a batch command",
+ "additionalProperties": false,
+ "properties": {
+ "cmd": {
+ "type": "string"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "description": "Run a Bash command",
+ "additionalProperties": false,
+ "properties": {
+ "sh": {
+ "type": "string"
+ }
+ }
+ }
+ ]
+ },
+ "envVarHash": {
+ "title": "environment variable hash",
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/definitions/possiblySecretString"
+ }
+ },
+ "platform": {
+ "enum": ["x86", "x64", "ARM", "ARM64", "Win32", "Any CPU"]
+ },
+ "configuration": {
+ "type": "string"
+ },
+ "imageName": {
+ "enum": [
+ "macOS",
+ "macOS-Mojave",
+ "macos-bigsur",
+ "macos-monterey",
+ "Previous macOS",
+ "Previous macOS-Mojave",
+ "Ubuntu",
+ "Ubuntu1604",
+ "Ubuntu1804",
+ "Ubuntu2004",
+ "Ubuntu2204",
+ "Previous Ubuntu",
+ "Previous Ubuntu1604",
+ "Previous Ubuntu1804",
+ "Previous Ubuntu2004",
+ "Visual Studio 2013",
+ "Visual Studio 2015",
+ "Visual Studio 2017",
+ "Visual Studio 2019",
+ "Visual Studio 2022",
+ "Visual Studio 2017 Preview",
+ "Visual Studio 2019 Preview",
+ "Previous Visual Studio 2013",
+ "Previous Visual Studio 2015",
+ "Previous Visual Studio 2017",
+ "Previous Visual Studio 2019",
+ "Previous Visual Studio 2022",
+ "zhaw18",
+ "WMF 5"
+ ]
+ },
+ "image": {
+ "description": "Build worker image (VM template) -DEV_VERSION",
+ "oneOf": [
+ {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/imageName"
+ }
+ },
+ {
+ "$ref": "#/definitions/imageName"
+ }
+ ]
+ },
+ "jobScalars": {
+ "title": "job scalars",
+ "type": "object",
+ "properties": {
+ "image": {
+ "$ref": "#/definitions/image"
+ },
+ "platform": {
+ "description": "Build platform, i.e. x86, x64, Any CPU. This setting is optional",
+ "oneOf": [
+ {
+ "$ref": "#/definitions/platform"
+ },
+ {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/platform"
+ }
+ }
+ ]
+ },
+ "configuration": {
+ "description": "Build Configuration, i.e. Debug, Release, etc.",
+ "oneOf": [
+ {
+ "$ref": "#/definitions/configuration"
+ },
+ {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/configuration"
+ }
+ }
+ ]
+ }
+ },
+ "allOf": [
+ {
+ "not": {
+ "required": ["skip_tags"]
+ }
+ },
+ {
+ "not": {
+ "required": ["skip_commits"]
+ }
+ },
+ {
+ "not": {
+ "required": ["skip_branch_with_pr"]
+ }
+ },
+ {
+ "not": {
+ "required": ["skip_non_tags"]
+ }
+ }
+ ]
+ },
+ "job": {
+ "title": "job",
+ "type": "object",
+ "properties": {
+ "version": {
+ "description": "Version format",
+ "type": "string"
+ },
+ "branches": {
+ "title": "branch options",
+ "type": "object",
+ "description": "Branches to build",
+ "additionalProperties": false,
+ "properties": {
+ "only": {
+ "description": "Whitelist",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "except": {
+ "type": "array",
+ "description": "Blacklist",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "skip_tags": {
+ "type": "boolean",
+ "description": "Do not build on tags (GitHub and BitBucket)"
+ },
+ "skip_non_tags": {
+ "type": "boolean",
+ "description": "Start builds on tags only (GitHub and BitBucket)"
+ },
+ "skip_commits": {
+ "$ref": "#/definitions/commitFilter",
+ "description": "Skipping commits with particular message or from specific user"
+ },
+ "only_commits": {
+ "$ref": "#/definitions/commitFilter",
+ "description": "Including commits with particular message or from specific user"
+ },
+ "skip_branch_with_pr": {
+ "type": "boolean",
+ "description": "Do not build feature branch with open Pull Requests"
+ },
+ "max_jobs": {
+ "description": "Maximum number of concurrent jobs for the project",
+ "type": "integer"
+ },
+ "notifications": {
+ "type": "array",
+ "items": {
+ "title": "notification",
+ "type": "object"
+ }
+ },
+ "image": {
+ "$ref": "#/definitions/image"
+ },
+ "init": {
+ "description": "Scripts that are called at very beginning, before repo cloning",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/command"
+ }
+ },
+ "clone_folder": {
+ "type": "string",
+ "description": "Clone directory"
+ },
+ "shallow_clone": {
+ "type": "boolean",
+ "description": "Fetch repository as zip archive",
+ "default": false
+ },
+ "clone_depth": {
+ "description": "Set git clone depth",
+ "type": "integer"
+ },
+ "hosts": {
+ "title": "host options",
+ "type": "object",
+ "description": "Setting up etc\\hosts file",
+ "additionalProperties": {
+ "type": "string",
+ "anyOf": [
+ {
+ "format": "ipv4"
+ },
+ {
+ "format": "ipv6"
+ }
+ ]
+ }
+ },
+ "environment": {
+ "description": "Environment variables",
+ "anyOf": [
+ {
+ "title": "environment options",
+ "type": "object",
+ "properties": {
+ "global": {
+ "$ref": "#/definitions/envVarHash",
+ "description": "variables defined here are no different than those defined at top level of 'environment' node"
+ },
+ "matrix": {
+ "type": "array",
+ "description": "an array of environment variables, each member of which is one dimension in the build matrix calculation",
+ "items": {
+ "$ref": "#/definitions/envVarHash"
+ }
+ }
+ }
+ },
+ {
+ "$ref": "#/definitions/envVarHash"
+ }
+ ]
+ },
+ "matrix": {
+ "title": "matrix options",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "fast_finish": {
+ "type": "boolean",
+ "description": "Set this flag to immediately finish build once one of the jobs fails"
+ },
+ "allow_failures": {
+ "type": "array",
+ "description": "This is how to allow failing jobs in the matrix",
+ "items": {
+ "$ref": "#/definitions/jobScalars"
+ }
+ },
+ "exclude": {
+ "type": "array",
+ "description": "Exclude configuration from the matrix. Works similarly to 'allow_failures' but build not even being started for excluded combination.",
+ "items": {
+ "$ref": "#/definitions/job"
+ }
+ }
+ }
+ },
+ "cache": {
+ "type": "array",
+ "description": "Build cache to preserve files/folders between builds",
+ "items": {
+ "type": "string"
+ }
+ },
+ "services": {
+ "type": "array",
+ "description": "Enable service required for build/tests",
+ "items": {
+ "enum": [
+ "docker",
+ "iis",
+ "mongodb",
+ "msmq",
+ "mssql",
+ "mssql2008r2sp2",
+ "mssql2008r2sp2rs",
+ "mssql2012sp1",
+ "mssql2012sp1rs",
+ "mssql2014",
+ "mssql2014rs",
+ "mssql2016",
+ "mssql2017",
+ "mysql",
+ "postgresql",
+ "postgresql93",
+ "postgresql94",
+ "postgresql95",
+ "postgresql96",
+ "postgresql10",
+ "postgresql11",
+ "postgresql12",
+ "postgresql13"
+ ]
+ }
+ },
+ "install": {
+ "description": "Scripts that run after cloning repository",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/command"
+ }
+ },
+ "assembly_info": {
+ "title": "assembly options",
+ "type": "object",
+ "description": "Enable patching of AssemblyInfo.* files",
+ "additionalProperties": false,
+ "properties": {
+ "patch": {
+ "type": "boolean"
+ },
+ "file": {
+ "type": "string"
+ },
+ "assembly_version": {
+ "type": "string"
+ },
+ "assembly_file_version": {
+ "type": "string"
+ },
+ "assembly_informational_version": {
+ "type": "string"
+ }
+ }
+ },
+ "nuget": {
+ "title": "NuGet options",
+ "type": "object",
+ "description": "Automatically register private account and/or project AppVeyor NuGet feeds",
+ "properties": {
+ "account_feed": {
+ "type": "boolean"
+ },
+ "project_feed": {
+ "type": "boolean"
+ },
+ "disable_publish_on_pr": {
+ "type": "boolean",
+ "description": "Disable publishing of .nupkg artifacts to account/project feeds for pull request builds"
+ }
+ }
+ },
+ "platform": {
+ "description": "Build platform, i.e. x86, x64, Any CPU. This setting is optional",
+ "oneOf": [
+ {
+ "$ref": "#/definitions/platform"
+ },
+ {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/platform"
+ }
+ }
+ ]
+ },
+ "configuration": {
+ "description": "Build Configuration, i.e. Debug, Release, etc.",
+ "oneOf": [
+ {
+ "$ref": "#/definitions/configuration"
+ },
+ {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/configuration"
+ }
+ }
+ ]
+ },
+ "build": {
+ "oneOf": [
+ {
+ "type": "boolean",
+ "enum": [false]
+ },
+ {
+ "title": "build options",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "parallel": {
+ "type": "boolean",
+ "description": "Enable MSBuild parallel builds"
+ },
+ "project": {
+ "type": "string",
+ "description": "Path to Visual Studio solution or project"
+ },
+ "publish_wap": {
+ "type": "boolean",
+ "description": "Package Web Application Projects (WAP) for Web Deploy"
+ },
+ "publish_wap_xcopy": {
+ "type": "boolean",
+ "description": "Package Web Application Projects (WAP) for XCopy deployment"
+ },
+ "publish_wap_beanstalk": {
+ "type": "boolean",
+ "description": "Package Web Applications for AWS Elastic Beanstalk deployment"
+ },
+ "publish_wap_octopus": {
+ "type": "boolean",
+ "description": "Package Web Applications for Octopus deployment"
+ },
+ "publish_azure_webjob": {
+ "type": "boolean",
+ "description": "Package Azure WebJobs for Zip Push deployment"
+ },
+ "publish_azure": {
+ "type": "boolean",
+ "description": "Package Azure Cloud Service projects and push to artifacts"
+ },
+ "publish_aspnet_core": {
+ "type": "boolean",
+ "description": "Package ASP.NET Core projects"
+ },
+ "publish_core_console": {
+ "type": "boolean",
+ "description": "Package .NET Core console projects"
+ },
+ "publish_nuget": {
+ "type": "boolean",
+ "description": "Package projects with .nuspec files and push to artifacts"
+ },
+ "publish_nuget_symbols": {
+ "type": "boolean",
+ "description": "Generate and publish NuGet symbol packages"
+ },
+ "include_nuget_references": {
+ "type": "boolean",
+ "description": "Add -IncludeReferencedProjects option while packaging NuGet artifacts"
+ },
+ "verbosity": {
+ "enum": ["quiet", "minimal", "normal", "detailed"],
+ "description": "MSBuild verbosity level"
+ }
+ }
+ }
+ ]
+ },
+ "before_build": {
+ "description": "Scripts to run before build",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/command"
+ }
+ },
+ "before_package": {
+ "description": "Scripts to run *after* solution is built and *before* automatic packaging occurs (web apps, NuGet packages, Azure Cloud Services)",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/command"
+ }
+ },
+ "after_build": {
+ "description": "Scripts to run after build",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/command"
+ }
+ },
+ "build_script": {
+ "description": "To run your custom scripts instead of automatic MSBuild",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/command"
+ }
+ },
+ "before_test": {
+ "description": "Scripts to run before tests",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/command"
+ }
+ },
+ "test": {
+ "oneOf": [
+ {
+ "type": "boolean",
+ "enum": [false],
+ "description": "To disable automatic tests"
+ },
+ {
+ "title": "test options",
+ "description": "To run tests again only selected assemblies and/or categories",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "assemblies": {
+ "title": "assembly options",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "categories": {
+ "oneOf": [
+ {
+ "title": "category options",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "except": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ {
+ "description": "To run tests from different categories as separate jobs in parallel",
+ "type": "array",
+ "items": {
+ "oneOf": [
+ {
+ "type": "string",
+ "description": "A category common for all jobs"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ }
+ ]
+ },
+ "test_script": {
+ "description": "To run your custom scripts instead of automatic tests",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/command"
+ }
+ },
+ "after_test": {
+ "type": "array",
+ "description": "Scripts to run after tests",
+ "items": {
+ "$ref": "#/definitions/command"
+ }
+ },
+ "artifacts": {
+ "type": "array",
+ "items": {
+ "title": "artifact options",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "type": {
+ "enum": [
+ "Auto",
+ "WebDeployPackage",
+ "NuGetPackage",
+ "AzureCloudService",
+ "AzureCloudServiceConfig",
+ "SsdtPackage",
+ "Zip",
+ "File"
+ ]
+ }
+ },
+ "required": ["path"]
+ }
+ },
+ "before_deploy": {
+ "type": "array",
+ "description": "Scripts to run before deployment",
+ "items": {
+ "$ref": "#/definitions/command"
+ }
+ },
+ "deploy": {
+ "oneOf": [
+ {
+ "enum": ["off"]
+ },
+ {
+ "type": "array",
+ "items": {
+ "title": "deployment options",
+ "type": "object"
+ }
+ }
+ ]
+ },
+ "deploy_script": {
+ "description": "To run your custom scripts instead of provider deployments",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/command"
+ }
+ },
+ "after_deploy": {
+ "type": "array",
+ "description": "Scripts to run after deployment",
+ "items": {
+ "$ref": "#/definitions/command"
+ }
+ },
+ "on_success": {
+ "type": "array",
+ "description": "On successful build",
+ "items": {
+ "$ref": "#/definitions/command"
+ }
+ },
+ "on_failure": {
+ "type": "array",
+ "description": "On build failure",
+ "items": {
+ "$ref": "#/definitions/command"
+ }
+ },
+ "on_finish": {
+ "type": "array",
+ "description": "After build failure or success",
+ "items": {
+ "$ref": "#/definitions/command"
+ }
+ }
+ }
+ }
+ },
+ "id": "https://json.schemastore.org/appveyor.json",
+ "title": "JSON schema for AppVeyor CI configuration files"
+}
diff --git a/ci/schemas/circleciconfig.json b/ci/schemas/circleciconfig.json
new file mode 100644
index 000000000000..076944098440
--- /dev/null
+++ b/ci/schemas/circleciconfig.json
@@ -0,0 +1,1411 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/circleciconfig.json",
+ "definitions": {
+ "logical": {
+ "description": "https://circleci.com/docs/configuration-reference#logic-statements \n\nA logical statement to be used in dynamic configuration",
+ "oneOf": [
+ {
+ "type": ["string", "boolean", "integer", "number"]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "minProperties": 1,
+ "maxProperties": 1,
+ "properties": {
+ "and": {
+ "description": "https://circleci.com/docs/configuration-reference#logic-statements \n\nLogical and: true when all statements in the list are true",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/logical"
+ }
+ },
+ "or": {
+ "description": "https://circleci.com/docs/configuration-reference#logic-statements \n\nLogical or: true when at least one statements in the list is true",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/logical"
+ }
+ },
+ "not": {
+ "$ref": "#/definitions/logical",
+ "description": "https://circleci.com/docs/configuration-reference#logic-statements \n\nLogical not: true when statement is false"
+ },
+ "equal": {
+ "description": "https://circleci.com/docs/configuration-reference#logic-statements \n\nTrue when all elements in the list are equal",
+ "type": "array"
+ },
+ "matches": {
+ "description": "https://circleci.com/docs/configuration-reference#logic-statements \n\nTrue when value matches the pattern",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "pattern": {
+ "type": "string"
+ },
+ "value": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ ]
+ },
+ "filter": {
+ "description": "A map defining rules for execution on specific branches",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "only": {
+ "description": "Either a single branch specifier, or a list of branch specifiers",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ },
+ "ignore": {
+ "description": "Either a single branch specifier, or a list of branch specifiers",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ }
+ }
+ },
+ "orbs": {
+ "description": "https://circleci.com/docs/configuration-reference#orbs-requires-version-21\n\nOrbs are reusable packages of CircleCI configuration that you may share across projects, enabling you to create encapsulated, parameterized commands, jobs, and executors that can be used across multiple projects.",
+ "type": "object",
+ "additionalProperties": {
+ "oneOf": [
+ {
+ "description": "https://circleci.com/docs/creating-orbs#semantic-versioning-in-orbs\n\nAn orb to depend on and its semver range, or volatile for the most recent release.",
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_-]+/[a-z][a-z0-9_-]+@(dev:[\\.a-z0-9_-]+|\\d+|\\d+\\.\\d+|\\d+\\.\\d+\\.\\d+|volatile)$"
+ },
+ {
+ "description": "https://circleci.com/docs/creating-orbs#creating-inline-orbs\n\nInline orbs can be handy during development of an orb or as a convenience for name-spacing jobs and commands in lengthy configurations, particularly if you later intend to share the orb with others.",
+ "type": "object",
+ "properties": {
+ "orbs": {
+ "$ref": "#/definitions/orbs"
+ },
+ "commands": {
+ "$ref": "#/definitions/commands"
+ },
+ "executors": {
+ "$ref": "#/definitions/executors"
+ },
+ "jobs": {
+ "$ref": "#/definitions/jobs"
+ }
+ }
+ }
+ ]
+ }
+ },
+ "commands": {
+ "description": "https://circleci.com/docs/configuration-reference#commands-requires-version-21\n\nA command definition defines a sequence of steps as a map to be executed in a job, enabling you to reuse a single command definition across multiple jobs.",
+ "type": "object",
+ "additionalProperties": {
+ "description": "https://circleci.com/docs/configuration-reference#commands-requires-version-21\n\nDefinition of a custom command.",
+ "type": "object",
+ "required": ["steps"],
+ "properties": {
+ "steps": {
+ "description": "A sequence of steps run inside the calling job of the command.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/step"
+ }
+ },
+ "parameters": {
+ "description": "https://circleci.com/docs/reusing-config#using-the-parameters-declaration\n\nA map of parameter keys.",
+ "type": "object",
+ "patternProperties": {
+ "^[a-z][a-z0-9_-]+$": {
+ "oneOf": [
+ {
+ "description": "https://circleci.com/docs/reusing-config#string\n\nA string parameter.",
+ "type": "object",
+ "required": ["type"],
+ "properties": {
+ "type": {
+ "enum": ["string"]
+ },
+ "description": {
+ "type": "string"
+ },
+ "default": {
+ "type": "string"
+ }
+ }
+ },
+ {
+ "description": "https://circleci.com/docs/reusing-config#boolean\n\nA boolean parameter.",
+ "type": "object",
+ "required": ["type"],
+ "properties": {
+ "type": {
+ "enum": ["boolean"]
+ },
+ "description": {
+ "type": "string"
+ },
+ "default": {
+ "type": "boolean"
+ }
+ }
+ },
+ {
+ "description": "https://circleci.com/docs/reusing-config#integer\n\nAn integer parameter.",
+ "type": "object",
+ "required": ["type"],
+ "properties": {
+ "type": {
+ "enum": ["integer"]
+ },
+ "description": {
+ "type": "string"
+ },
+ "default": {
+ "type": "integer"
+ }
+ }
+ },
+ {
+ "description": "https://circleci.com/docs/reusing-config#enum\n\nThe `enum` parameter may be a list of any values. Use the `enum` parameter type when you want to enforce that the value must be one from a specific set of string values.",
+ "type": "object",
+ "required": ["type", "enum"],
+ "properties": {
+ "type": {
+ "enum": ["enum"]
+ },
+ "enum": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "string"
+ }
+ },
+ "description": {
+ "type": "string"
+ },
+ "default": {
+ "type": "string"
+ }
+ }
+ },
+ {
+ "description": "https://circleci.com/docs/reusing-config#executor\n\nUse an `executor` parameter type to allow the invoker of a job to decide what executor it will run on.",
+ "type": "object",
+ "required": ["type"],
+ "properties": {
+ "type": {
+ "enum": ["executor"]
+ },
+ "description": {
+ "type": "string"
+ },
+ "default": {
+ "type": "string"
+ }
+ }
+ },
+ {
+ "description": "https://circleci.com/docs/reusing-config#steps\n\nSteps are used when you have a job or command that needs to mix predefined and user-defined steps. When passed in to a command or job invocation, the steps passed as parameters are always defined as a sequence, even if only one step is provided.",
+ "type": "object",
+ "required": ["type"],
+ "properties": {
+ "type": {
+ "enum": ["steps"]
+ },
+ "description": {
+ "type": "string"
+ },
+ "default": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/step"
+ }
+ }
+ }
+ },
+ {
+ "description": "https://circleci.com/docs/reusing-config#environment-variable-name\n\nThe environment variable name parameter is a string that must match a POSIX_NAME regexp (e.g. no spaces or special characters) and is a more meaningful parameter type that enables additional checks to be performed. ",
+ "type": "object",
+ "required": ["type"],
+ "properties": {
+ "type": {
+ "enum": ["env_var_name"]
+ },
+ "description": {
+ "type": "string"
+ },
+ "default": {
+ "type": "string",
+ "pattern": "^[a-zA-Z][a-zA-Z0-9_-]+$"
+ }
+ }
+ }
+ ]
+ }
+ }
+ },
+ "description": {
+ "description": "A string that describes the purpose of the command.",
+ "type": "string"
+ }
+ }
+ }
+ },
+ "dockerLayerCaching": {
+ "description": "Set to `true` to enable [Docker Layer Caching](https://circleci.com/docs/docker-layer-caching). Note: If you haven't already, you must open a support ticket to have a CircleCI Sales representative contact you about enabling this feature on your account for an additional fee.",
+ "type": "boolean",
+ "default": "true"
+ },
+ "dockerExecutor": {
+ "description": "Options for the [docker executor](https://circleci.com/docs/configuration-reference#docker)",
+ "required": ["docker"],
+ "properties": {
+ "docker": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["image"],
+ "properties": {
+ "image": {
+ "description": "The name of a custom docker image to use",
+ "type": "string"
+ },
+ "name": {
+ "description": "The name the container is reachable by. By default, container services are accessible through `localhost`",
+ "type": "string"
+ },
+ "entrypoint": {
+ "description": "The command used as executable when launching the container",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ },
+ "command": {
+ "description": "The command used as pid 1 (or args for entrypoint) when launching the container",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ },
+ "user": {
+ "description": "Which user to run the command as",
+ "type": "string"
+ },
+ "environment": {
+ "description": "A map of environment variable names and values",
+ "type": "object",
+ "additionalProperties": {
+ "type": ["string", "number", "boolean"]
+ }
+ },
+ "auth": {
+ "description": "Authentication for registries using standard `docker login` credentials",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "username": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ }
+ }
+ },
+ "aws_auth": {
+ "description": "Authentication for AWS EC2 Container Registry (ECR). You can use the access/secret keys or OIDC.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "aws_access_key_id": {
+ "type": "string"
+ },
+ "aws_secret_access_key": {
+ "type": "string"
+ },
+ "oidc_role_arn": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "resource_class": {
+ "description": "Amount of CPU and RAM allocated for each job. Note: A performance plan is required to access this feature.",
+ "type": "string",
+ "enum": [
+ "small",
+ "medium",
+ "medium+",
+ "large",
+ "xlarge",
+ "2xlarge",
+ "2xlarge+",
+ "arm.medium",
+ "arm.large",
+ "arm.xlarge",
+ "arm.2xlarge"
+ ]
+ }
+ }
+ },
+ "machineExecutor": {
+ "description": "Options for the [machine executor](https://circleci.com/docs/configuration-reference#machine)",
+ "type": "object",
+ "required": ["machine"],
+ "oneOf": [
+ {
+ "properties": {
+ "machine": {
+ "oneOf": [
+ { "const": "default" },
+ { "const": true },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["image"],
+ "properties": {
+ "image": {
+ "description": "The VM image to use. View [available images](https://circleci.com/docs/configuration-reference/#available-linux-machine-images-cloud). **Note:** This key is **not** supported on the installable CircleCI. For information about customizing machine executor images on CircleCI installed on your servers, see our [VM Service documentation](https://circleci.com/docs/vm-service).",
+ "type": "string",
+ "enum": [
+ "ubuntu-2004:2023.10.1",
+ "ubuntu-2004:2023.07.1",
+ "ubuntu-2004:2023.04.2",
+ "ubuntu-2004:2023.04.1",
+ "ubuntu-2004:2023.02.1",
+ "ubuntu-2004:2022.10.1",
+ "ubuntu-2004:2022.07.1",
+ "ubuntu-2004:2022.04.2",
+ "ubuntu-2004:2022.04.1",
+ "ubuntu-2004:202201-02",
+ "ubuntu-2004:202201-01",
+ "ubuntu-2004:202111-02",
+ "ubuntu-2004:202111-01",
+ "ubuntu-2004:202107-02",
+ "ubuntu-2004:202104-01",
+ "ubuntu-2004:202101-01",
+ "ubuntu-2004:202010-01",
+ "ubuntu-2004:current",
+ "ubuntu-2004:edge",
+ "ubuntu-2204:2023.10.1",
+ "ubuntu-2204:2023.07.2",
+ "ubuntu-2204:2023.04.2",
+ "ubuntu-2204:2023.04.1",
+ "ubuntu-2204:2023.02.1",
+ "ubuntu-2204:2022.10.2",
+ "ubuntu-2204:2022.10.1",
+ "ubuntu-2204:2022.07.2",
+ "ubuntu-2204:2022.07.1",
+ "ubuntu-2204:2022.04.2",
+ "ubuntu-2204:2022.04.1",
+ "ubuntu-2204:current",
+ "ubuntu-2204:edge",
+ "android:2023.11.1",
+ "android:2023.10.1",
+ "android:2023.09.1",
+ "android:2023.08.1",
+ "android:2023.07.1",
+ "android:2023.06.1",
+ "android:2023.05.1",
+ "android:2023.04.1",
+ "android:2023.03.1",
+ "android:2023.02.1",
+ "android:2022.12.1",
+ "android:2022.09.1",
+ "android:2022.08.1",
+ "android:2022.07.1",
+ "android:2022.06.2",
+ "android:2022.06.1",
+ "android:2022.04.1",
+ "android:2022.03.1",
+ "android:2022.01.1",
+ "android:2021.12.1",
+ "android:2021.10.1",
+ "android:202102-01"
+ ]
+ },
+ "docker_layer_caching": {
+ "$ref": "#/definitions/dockerLayerCaching"
+ }
+ }
+ }
+ ]
+ },
+ "resource_class": {
+ "description": "Amount of CPU and RAM allocated for each job. View [available resource classes](https://circleci.com/docs/configuration-reference/#linuxvm-execution-environment)",
+ "type": "string",
+ "enum": [
+ "medium",
+ "large",
+ "xlarge",
+ "2xlarge",
+ "2xlarge+",
+ "arm.medium",
+ "arm.large",
+ "arm.xlarge",
+ "arm.2xlarge"
+ ]
+ }
+ }
+ },
+ {
+ "properties": {
+ "machine": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["image"],
+ "properties": {
+ "image": {
+ "description": "The VM image to use. View [available images](https://circleci.com/docs/configuration-reference/#available-linux-gpu-images). **Note:** This key is **not** supported on the installable CircleCI. For information about customizing machine executor images on CircleCI installed on your servers, see our [VM Service documentation](https://circleci.com/docs/vm-service).",
+ "type": "string",
+ "enum": ["linux-cuda-11:default", "linux-cuda-12:default"]
+ },
+ "docker_layer_caching": {
+ "$ref": "#/definitions/dockerLayerCaching"
+ }
+ }
+ },
+ "resource_class": {
+ "description": "Amount of CPU and RAM allocated for each job. View [available resource classes](https://circleci.com/docs/configuration-reference/#gpu-execution-environment-linux)",
+ "type": "string",
+ "enum": ["gpu.nvidia.medium", "gpu.nvidia.large"]
+ }
+ }
+ },
+ {
+ "properties": {
+ "machine": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["image"],
+ "properties": {
+ "image": {
+ "description": "The VM image to use. View [available images](https://circleci.com/docs/configuration-reference/#available-windows-machine-images-cloud). **Note:** This key is **not** supported on the installable CircleCI. For information about customizing machine executor images on CircleCI installed on your servers, see our [VM Service documentation](https://circleci.com/docs/vm-service).",
+ "type": "string",
+ "enum": [
+ "windows-server-2022-gui:2023.10.1",
+ "windows-server-2022-gui:2023.09.1",
+ "windows-server-2022-gui:2023.08.1",
+ "windows-server-2022-gui:2023.07.1",
+ "windows-server-2022-gui:2023.06.1",
+ "windows-server-2022-gui:2023.05.1",
+ "windows-server-2022-gui:2023.04.1",
+ "windows-server-2022-gui:2023.03.1",
+ "windows-server-2022-gui:2022.08.1",
+ "windows-server-2022-gui:2022.07.1",
+ "windows-server-2022-gui:2022.06.1",
+ "windows-server-2022-gui:2022.04.1",
+ "windows-server-2022-gui:current",
+ "windows-server-2022-gui:edge",
+ "windows-server-2019:2023.10.1",
+ "windows-server-2019:2023.08.1",
+ "windows-server-2019:2023.04.1",
+ "windows-server-2019:2022.08.1",
+ "windows-server-2019:current",
+ "windows-server-2019:edge"
+ ]
+ },
+ "docker_layer_caching": {
+ "$ref": "#/definitions/dockerLayerCaching"
+ }
+ }
+ },
+ "resource_class": {
+ "description": "Amount of CPU and RAM allocated for each job. View [available resource classes](https://circleci.com/docs/configuration-reference/#windows-execution-environment)",
+ "type": "string",
+ "enum": [
+ "windows.medium",
+ "windows.large",
+ "windows.xlarge",
+ "windows.2xlarge"
+ ]
+ }
+ }
+ },
+ {
+ "properties": {
+ "machine": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["image"],
+ "properties": {
+ "image": {
+ "description": "The VM image to use. View [available images](https://circleci.com/docs/configuration-reference/#available-windows-gpu-image). **Note:** This key is **not** supported on the installable CircleCI. For information about customizing machine executor images on CircleCI installed on your servers, see our [VM Service documentation](https://circleci.com/docs/vm-service).",
+ "type": "string",
+ "enum": [
+ "windows-server-2019-cuda:current",
+ "windows-server-2019-cuda:edge"
+ ]
+ },
+ "docker_layer_caching": {
+ "$ref": "#/definitions/dockerLayerCaching"
+ }
+ }
+ },
+ "resource_class": {
+ "description": "Amount of CPU and RAM allocated for each job. View [available resource classes](https://circleci.com/docs/configuration-reference/#gpu-execution-environment-windows)",
+ "type": "string",
+ "enum": ["windows.gpu.nvidia.medium"]
+ }
+ }
+ }
+ ]
+ },
+ "macosExecutor": {
+ "description": "Options for the [macOS executor](https://circleci.com/docs/configuration-reference#macos)",
+ "type": "object",
+ "required": ["macos"],
+ "properties": {
+ "macos": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["xcode"],
+ "properties": {
+ "xcode": {
+ "description": "The version of Xcode that is installed on the virtual machine, see the [Supported Xcode Versions section of the Testing iOS](https://circleci.com/docs/testing-ios#supported-xcode-versions) document for the complete list.",
+ "type": "string",
+ "enum": [
+ "15.2.0",
+ "15.1.0",
+ "15.0.0",
+ "14.3.1",
+ "14.2.0",
+ "14.1.0",
+ "14.0.1",
+ "13.4.1",
+ "12.5.1"
+ ]
+ }
+ }
+ },
+ "resource_class": {
+ "description": "Amount of CPU and RAM allocated for each job. View [available resource classes](https://circleci.com/docs/configuration-reference/#macos-execution-environment)",
+ "type": "string",
+ "enum": [
+ "macos.x86.medium.gen2",
+ "macos.m1.medium.gen1",
+ "macos.m1.large.gen1"
+ ]
+ }
+ }
+ },
+ "executorChoice": {
+ "type": "object",
+ "oneOf": [
+ {
+ "$ref": "#/definitions/dockerExecutor"
+ },
+ {
+ "$ref": "#/definitions/machineExecutor"
+ },
+ {
+ "$ref": "#/definitions/macosExecutor"
+ }
+ ]
+ },
+ "executors": {
+ "description": "Executors define the environment in which the steps of a job will be run, allowing you to reuse a single executor definition across multiple jobs.",
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/definitions/executorChoice",
+ "type": "object",
+ "properties": {
+ "shell": {
+ "description": "Shell to use for execution command in all steps. Can be overridden by shell in each step (default: See [Default Shell Options](https://circleci.com/docs/configuration-reference#default-shell-options)",
+ "type": "string"
+ },
+ "working_directory": {
+ "description": "In which directory to run the steps.",
+ "type": "string"
+ },
+ "environment": {
+ "description": "A map of environment variable names and values.",
+ "type": "object",
+ "additionalProperties": {
+ "type": ["string", "number"]
+ }
+ }
+ }
+ }
+ },
+ "builtinSteps": {
+ "documentation": {
+ "run": {
+ "description": "https://circleci.com/docs/configuration-reference#run\n\nUsed for invoking all command-line programs, taking either a map of configuration values, or, when called in its short-form, a string that will be used as both the `command` and `name`. Run commands are executed using non-login shells by default, so you must explicitly source any dotfiles as part of the command."
+ },
+ "checkout": {
+ "description": "https://circleci.com/docs/configuration-reference#checkout\n\nSpecial step used to check out source code to the configured `path` (defaults to the `working_directory`). The reason this is a special step is because it is more of a helper function designed to make checking out code easy for you. If you require doing git over HTTPS you should not use this step as it configures git to checkout over ssh."
+ },
+ "setup_remote_docker": {
+ "description": "https://circleci.com/docs/configuration-reference#setup_remote_docker\n\nCreates a remote Docker environment configured to execute Docker commands."
+ },
+ "save_cache": {
+ "description": "https://circleci.com/docs/configuration-reference#save_cache\n\nGenerates and stores a cache of a file or directory of files such as dependencies or source code in our object storage. Later jobs can restore this cache using the `restore_cache` step."
+ },
+ "restore_cache": {
+ "description": "https://circleci.com/docs/configuration-reference#restore_cache\n\nRestores a previously saved cache based on a `key`. Cache needs to have been saved first for this key using the `save_cache` step."
+ },
+ "deploy": {
+ "description": "https://circleci.com/docs/configuration-reference#deploy\n\nSpecial step for deploying artifacts. `deploy` uses the same configuration map and semantics as run step. Jobs may have more than one deploy step. In general deploy step behaves just like run with two exceptions:\n* In a job with parallelism, the deploy step will only be executed by node #0 and only if all nodes succeed. Nodes other than #0 will skip this step.\n* In a job that runs with SSH, the deploy step will not execute"
+ },
+ "store_artifacts": {
+ "description": "https://circleci.com/docs/configuration-reference#store_artifacts\n\nStep to store artifacts (for example logs, binaries, etc) to be available in the web app or through the API."
+ },
+ "store_test_results": {
+ "description": "https://circleci.com/docs/configuration-reference#storetestresults\n\nSpecial step used to upload test results so they display in builds' Test Summary section and can be used for timing analysis. To also see test result as build artifacts, please use the `store_artifacts` step."
+ },
+ "persist_to_workspace": {
+ "description": "https://circleci.com/docs/configuration-reference#persist_to_workspace\n\nSpecial step used to persist a temporary file to be used by another job in the workflow"
+ },
+ "attach_workspace": {
+ "description": "https://circleci.com/docs/configuration-reference#attach_workspace\n\nSpecial step used to attach the workflow's workspace to the current container. The full contents of the workspace are downloaded and copied into the directory the workspace is being attached at."
+ },
+ "add_ssh_keys": {
+ "description": "https://circleci.com/docs/configuration-reference#add_ssh_keys\n\nSpecial step that adds SSH keys from a project's settings to a container. Also configures SSH to use these keys."
+ },
+ "when": {
+ "description": "https://circleci.com/docs/configuration-reference#the-when-step-requires-version-21 \n\nConditional step to run on custom conditions (determined at config-compile time) that are checked before a workflow runs"
+ },
+ "unless": {
+ "description": "https://circleci.com/docs/configuration-reference#the-when-step-requires-version-21 \n\nConditional step to run when custom conditions aren't met (determined at config-compile time) that are checked before a workflow runs"
+ }
+ },
+ "configuration": {
+ "run": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/builtinSteps/documentation/run"
+ }
+ ],
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["command"],
+ "properties": {
+ "command": {
+ "description": "Command to run via the shell",
+ "type": "string"
+ },
+ "name": {
+ "description": "Title of the step to be shown in the CircleCI UI (default: full `command`)",
+ "type": "string"
+ },
+ "shell": {
+ "description": "Shell to use for execution command",
+ "type": "string"
+ },
+ "environment": {
+ "description": "Additional environmental variables, locally scoped to command",
+ "type": "object",
+ "additionalProperties": {
+ "type": ["string", "number"]
+ }
+ },
+ "background": {
+ "description": "Whether or not this step should run in the background (default: false)",
+ "default": false,
+ "type": "boolean"
+ },
+ "working_directory": {
+ "description": "In which directory to run this step (default: `working_directory` of the job",
+ "type": "string"
+ },
+ "no_output_timeout": {
+ "description": "Elapsed time the command can run without output. The string is a decimal with unit suffix, such as \"20m\", \"1.25h\", \"5s\" (default: 10 minutes)",
+ "type": "string",
+ "pattern": "\\d+(\\.\\d+)?[mhs]",
+ "default": "10m"
+ },
+ "when": {
+ "description": "Specify when to enable or disable the step. Takes the following values: `always`, `on_success`, `on_fail` (default: `on_success`)",
+ "enum": ["always", "on_success", "on_fail"]
+ }
+ }
+ }
+ ]
+ },
+ "checkout": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/builtinSteps/documentation/checkout"
+ }
+ ],
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "description": "Title of the step to be shown in the CircleCI UI",
+ "type": "string"
+ },
+ "path": {
+ "description": "Checkout directory (default: job's `working_directory`)",
+ "type": "string"
+ }
+ }
+ },
+ "setup_remote_docker": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/builtinSteps/documentation/setup_remote_docker"
+ }
+ ],
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "description": "Title of the step to be shown in the CircleCI UI",
+ "type": "string"
+ },
+ "docker_layer_caching": {
+ "description": "When `docker_layer_caching` is set to `true`, CircleCI will try to reuse Docker Images (layers) built during a previous job or workflow (Paid feature)",
+ "type": "boolean",
+ "default": false
+ },
+ "version": {
+ "description": "If your build requires a specific docker image, you can set it as an image attribute",
+ "anyOf": [
+ {
+ "type": "string",
+ "enum": [
+ "20.10.24",
+ "20.10.23",
+ "20.10.18",
+ "20.10.17",
+ "20.10.14",
+ "20.10.12",
+ "20.10.11",
+ "20.10.7",
+ "20.10.6",
+ "20.10.2",
+ "19.03.13"
+ ]
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ }
+ },
+ "save_cache": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/builtinSteps/documentation/save_cache"
+ }
+ ],
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["paths", "key"],
+ "properties": {
+ "paths": {
+ "description": "List of directories which should be added to the cache",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "key": {
+ "description": "Unique identifier for this cache",
+ "type": "string"
+ },
+ "name": {
+ "type": "string",
+ "description": "Title of the step to be shown in the CircleCI UI (default: 'Saving Cache')"
+ },
+ "when": {
+ "description": "Specify when to enable or disable the step. Takes the following values: `always`, `on_success`, `on_fail` (default: `on_success`)",
+ "enum": ["always", "on_success", "on_fail"]
+ }
+ }
+ },
+ "restore_cache": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/builtinSteps/documentation/restore_cache"
+ }
+ ],
+ "oneOf": [
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["key"],
+ "properties": {
+ "key": {
+ "type": "string",
+ "description": "Single cache key to restore"
+ },
+ "name": {
+ "type": "string",
+ "description": "Title of the step to be shown in the CircleCI UI (default: 'Restoring Cache')"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["keys"],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Title of the step to be shown in the CircleCI UI (default: 'Restoring Cache')"
+ },
+ "keys": {
+ "description": "List of cache keys to lookup for a cache to restore. Only first existing key will be restored.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ ]
+ },
+ "deploy": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/builtinSteps/documentation/deploy"
+ },
+ {
+ "$ref": "#/definitions/builtinSteps/configuration/run"
+ }
+ ]
+ },
+ "store_artifacts": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/builtinSteps/documentation/store_artifacts"
+ }
+ ],
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["path"],
+ "properties": {
+ "name": {
+ "description": "Title of the step to be shown in the CircleCI UI",
+ "type": "string"
+ },
+ "path": {
+ "description": "Directory in the primary container to save as job artifacts",
+ "type": "string"
+ },
+ "destination": {
+ "description": "Prefix added to the artifact paths in the artifacts API (default: the directory of the file specified in `path`)",
+ "type": "string"
+ }
+ }
+ },
+ "store_test_results": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/builtinSteps/documentation/store_test_results"
+ }
+ ],
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["path"],
+ "properties": {
+ "name": {
+ "description": "Title of the step to be shown in the CircleCI UI",
+ "type": "string"
+ },
+ "path": {
+ "description": "Path (absolute, or relative to your `working_directory`) to directory containing subdirectories of JUnit XML or Cucumber JSON test metadata files",
+ "type": "string"
+ }
+ }
+ },
+ "persist_to_workspace": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/builtinSteps/documentation/persist_to_workspace"
+ }
+ ],
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["root", "paths"],
+ "properties": {
+ "name": {
+ "description": "Title of the step to be shown in the CircleCI UI",
+ "type": "string"
+ },
+ "root": {
+ "description": "Either an absolute path or a path relative to `working_directory`",
+ "type": "string"
+ },
+ "paths": {
+ "description": "Glob identifying file(s), or a non-glob path to a directory to add to the shared workspace. Interpreted as relative to the workspace root. Must not be the workspace root itself.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "attach_workspace": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/builtinSteps/documentation/attach_workspace"
+ }
+ ],
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["at"],
+ "properties": {
+ "name": {
+ "description": "Title of the step to be shown in the CircleCI UI",
+ "type": "string"
+ },
+ "at": {
+ "description": "Directory to attach the workspace to",
+ "type": "string"
+ }
+ }
+ },
+ "add_ssh_keys": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/builtinSteps/documentation/add_ssh_keys"
+ }
+ ],
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "description": "Title of the step to be shown in the CircleCI UI",
+ "type": "string"
+ },
+ "fingerprints": {
+ "description": "Directory to attach the workspace to",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "when": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/builtinSteps/documentation/when"
+ }
+ ],
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "condition": {
+ "$ref": "#/definitions/logical"
+ },
+ "steps": {
+ "description": "A list of steps to be performed",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/step"
+ }
+ }
+ },
+ "required": ["condition", "steps"]
+ },
+ "unless": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/builtinSteps/documentation/unless"
+ }
+ ],
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "condition": {
+ "$ref": "#/definitions/logical"
+ },
+ "steps": {
+ "description": "A list of steps to be performed",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/step"
+ }
+ }
+ },
+ "required": ["condition", "steps"]
+ }
+ }
+ },
+ "step": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/builtinSteps/documentation/checkout",
+ "enum": ["checkout"]
+ },
+ {
+ "$ref": "#/definitions/builtinSteps/documentation/setup_remote_docker",
+ "enum": ["setup_remote_docker"]
+ },
+ {
+ "$ref": "#/definitions/builtinSteps/documentation/add_ssh_keys",
+ "enum": ["add_ssh_keys"]
+ },
+ {
+ "description": "https://circleci.com/docs/reusing-config#invoking-reusable-commands\n\nA custom command defined via the top level commands key",
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_-]+$"
+ },
+ {
+ "description": "https://circleci.com/docs/using-orbs#commands\n\nA custom command defined via an orb.",
+ "type": "string",
+ "pattern": "^[a-z][a-z0-9_-]+/[a-z][a-z0-9_-]+$"
+ },
+ {
+ "type": "object",
+ "minProperties": 1,
+ "maxProperties": 1,
+ "properties": {
+ "run": {
+ "$ref": "#/definitions/builtinSteps/configuration/run"
+ },
+ "checkout": {
+ "$ref": "#/definitions/builtinSteps/configuration/checkout"
+ },
+ "setup_remote_docker": {
+ "$ref": "#/definitions/builtinSteps/configuration/setup_remote_docker"
+ },
+ "save_cache": {
+ "$ref": "#/definitions/builtinSteps/configuration/save_cache"
+ },
+ "restore_cache": {
+ "$ref": "#/definitions/builtinSteps/configuration/restore_cache"
+ },
+ "deploy": {
+ "$ref": "#/definitions/builtinSteps/configuration/deploy"
+ },
+ "store_artifacts": {
+ "$ref": "#/definitions/builtinSteps/configuration/store_artifacts"
+ },
+ "store_test_results": {
+ "$ref": "#/definitions/builtinSteps/configuration/store_test_results"
+ },
+ "persist_to_workspace": {
+ "$ref": "#/definitions/builtinSteps/configuration/persist_to_workspace"
+ },
+ "attach_workspace": {
+ "$ref": "#/definitions/builtinSteps/configuration/attach_workspace"
+ },
+ "add_ssh_keys": {
+ "$ref": "#/definitions/builtinSteps/configuration/add_ssh_keys"
+ },
+ "when": {
+ "$ref": "#/definitions/builtinSteps/configuration/when"
+ },
+ "unless": {
+ "$ref": "#/definitions/builtinSteps/configuration/unless"
+ }
+ },
+ "patternProperties": {
+ "^[a-z][a-z0-9_-]+$": {
+ "description": "https://circleci.com/docs/reusing-config#invoking-reusable-commands\n\nA custom command defined via the top level commands key"
+ },
+ "^[a-z][a-z0-9_-]+/[a-z][a-z0-9_-]+$": {
+ "description": "https://circleci.com/docs/using-orbs#commands\n\nA custom command defined via an orb."
+ }
+ }
+ }
+ ]
+ },
+ "jobRef": {
+ "description": "Run a job as part of this workflow",
+ "type": "object",
+ "additionalProperties": true,
+ "properties": {
+ "requires": {
+ "description": "Jobs are run in parallel by default, so you must explicitly require any dependencies by their job name.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "name": {
+ "description": "The name key can be used to ensure build numbers are not appended when invoking the same job multiple times (e.g., sayhello-1, sayhello-2). The name assigned needs to be unique, otherwise numbers will still be appended to the job name",
+ "type": "string"
+ },
+ "context": {
+ "description": "Either a single context name, or a list of contexts. The default name is `org-global`",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ],
+ "default": "org-global"
+ },
+ "type": {
+ "description": "A job may have a `type` of `approval` indicating it must be manually approved before downstream jobs may proceed.",
+ "enum": ["approval"]
+ },
+ "filters": {
+ "description": "A map defining rules for execution on specific branches",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "branches": {
+ "$ref": "#/definitions/filter"
+ },
+ "tags": {
+ "$ref": "#/definitions/filter"
+ }
+ }
+ },
+ "matrix": {
+ "description": "https://circleci.com/docs/configuration-reference#matrix-requires-version-21\n\nThe matrix stanza allows you to run a parameterized job multiple times with different arguments.",
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["parameters"],
+ "properties": {
+ "parameters": {
+ "description": "A map of parameter names to every value the job should be called with",
+ "type": "object",
+ "additionalProperties": {
+ "type": "array"
+ }
+ },
+ "exclude": {
+ "description": "A list of argument maps that should be excluded from the matrix",
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "alias": {
+ "description": "An alias for the matrix, usable from another job's requires stanza. Defaults to the name of the job being executed",
+ "type": "string"
+ }
+ }
+ }
+ }
+ },
+ "jobs": {
+ "description": "Jobs are collections of steps. All of the steps in the job are executed in a single unit, either within a fresh container or VM.",
+ "type": "object",
+ "additionalProperties": {
+ "type": "object",
+ "oneOf": [
+ {
+ "$ref": "#/definitions/executorChoice"
+ },
+ {
+ "type": "object",
+ "required": ["executor"],
+ "properties": {
+ "executor": {
+ "description": "The name of the executor to use (defined via the top level executors map).",
+ "type": "string"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "required": ["executor"],
+ "properties": {
+ "executor": {
+ "description": "Executor stanza to use for the job",
+ "type": "object",
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "description": "The name of the executor to use (defined via the top level executors map).",
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ ],
+ "required": ["steps"],
+ "properties": {
+ "shell": {
+ "description": "Shell to use for execution command in all steps. Can be overridden by shell in each step",
+ "type": "string"
+ },
+ "steps": {
+ "description": "A list of steps to be performed",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/step"
+ }
+ },
+ "working_directory": {
+ "description": "In which directory to run the steps. (default: `~/project`. `project` is a literal string, not the name of the project.) You can also refer the directory with `$CIRCLE_WORKING_DIRECTORY` environment variable.",
+ "type": "string",
+ "default": "~/project"
+ },
+ "parallelism": {
+ "description": "Number of parallel instances of this job to run (default: 1)",
+ "default": 1,
+ "oneOf": [
+ {
+ "type": "integer"
+ },
+ {
+ "type": "string",
+ "pattern": "^<<.+\\..+>>$"
+ }
+ ]
+ },
+ "environment": {
+ "description": "A map of environment variable names and variables (NOTE: these will override any environment variables you set in the CircleCI web interface).",
+ "type": "object",
+ "additionalProperties": {
+ "type": ["string", "number"]
+ }
+ },
+ "branches": {
+ "description": "A map defining rules for whitelisting/blacklisting execution of specific branches for a single job that is **not** in a workflow (default: all whitelisted). See Workflows for configuring branch execution for jobs in a workflow.",
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "properties": {
+ "version": {
+ "description": "The version field is intended to be used in order to issue warnings for deprecation or breaking changes.",
+ "default": 2.1,
+ "enum": [2, 2.1]
+ },
+ "orbs": {
+ "$ref": "#/definitions/orbs"
+ },
+ "commands": {
+ "$ref": "#/definitions/commands"
+ },
+ "executors": {
+ "$ref": "#/definitions/executors"
+ },
+ "jobs": {
+ "$ref": "#/definitions/jobs"
+ },
+ "workflows": {
+ "description": "Used for orchestrating all jobs. Each workflow consists of the workflow name as a key and a map as a value",
+ "type": "object",
+ "properties": {
+ "version": {
+ "description": "The Workflows `version` field is used to issue warnings for deprecation or breaking changes during v2 Beta. It is deprecated as of CircleCI v2.1",
+ "enum": [2]
+ }
+ },
+ "additionalProperties": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "triggers": {
+ "description": "Specifies which triggers will cause this workflow to be executed. Default behavior is to trigger the workflow when pushing to a branch.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "schedule": {
+ "description": "A workflow may have a schedule indicating it runs at a certain time, for example a nightly build that runs every day at 12am UTC:",
+ "type": "object",
+ "properties": {
+ "cron": {
+ "description": "See the [crontab man page](http://pubs.opengroup.org/onlinepubs/7908799/xcu/crontab.html)",
+ "type": "string"
+ },
+ "filters": {
+ "description": "A map defining rules for execution on specific branches",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "branches": {
+ "$ref": "#/definitions/filter"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "jobs": {
+ "type": "array",
+ "items": {
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/definitions/jobRef",
+ "type": "object"
+ }
+ }
+ ]
+ }
+ },
+ "when": {
+ "$ref": "#/definitions/logical",
+ "description": "Specify when to run the workflow."
+ },
+ "unless": {
+ "$ref": "#/definitions/logical",
+ "description": "Specify when *not* to run the workflow."
+ }
+ }
+ }
+ }
+ },
+ "required": ["version"],
+ "title": "JSON schema for CircleCI configuration files",
+ "type": "object"
+}
diff --git a/ci/schemas/codecov.json b/ci/schemas/codecov.json
new file mode 100644
index 000000000000..98decea44415
--- /dev/null
+++ b/ci/schemas/codecov.json
@@ -0,0 +1,620 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/codecov",
+ "definitions": {
+ "default": {
+ "$comment": "See https://docs.codecov.com/docs/commit-status#basic-configuration",
+ "properties": {
+ "target": {
+ "type": ["string", "number"],
+ "pattern": "^(([0-9]+\\.?[0-9]*|\\.[0-9]+)%?|auto)$",
+ "default": "auto"
+ },
+ "threshold": {
+ "type": "string",
+ "default": "0%",
+ "pattern": "^([0-9]+\\.?[0-9]*|\\.[0-9]+)%?$"
+ },
+ "base": {
+ "type": "string",
+ "default": "auto",
+ "deprecated": true
+ },
+ "flags": {
+ "type": "array",
+ "default": []
+ },
+ "paths": {
+ "type": ["array", "string"],
+ "default": []
+ },
+ "branches": {
+ "type": "array",
+ "default": []
+ },
+ "if_not_found": {
+ "type": "string",
+ "enum": ["failure", "success"],
+ "default": "success"
+ },
+ "informational": {
+ "type": "boolean",
+ "default": false
+ },
+ "only_pulls": {
+ "type": "boolean",
+ "default": false
+ },
+ "if_ci_failed": {
+ "type": "string",
+ "enum": ["error", "success"]
+ },
+ "flag_coverage_not_uploaded_behavior": {
+ "type": "string",
+ "enum": ["include", "exclude", "pass"]
+ }
+ }
+ },
+ "flag": {
+ "type": "object",
+ "properties": {
+ "joined": {
+ "type": "boolean"
+ },
+ "required": {
+ "type": "boolean"
+ },
+ "ignore": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "assume": {
+ "type": ["boolean", "array"],
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "layout": {
+ "anyOf": [
+ {},
+ {
+ "enum": [
+ "header",
+ "footer",
+ "diff",
+ "file",
+ "files",
+ "flag",
+ "flags",
+ "reach",
+ "sunburst",
+ "uncovered"
+ ]
+ }
+ ]
+ },
+ "notification": {
+ "type": "object",
+ "properties": {
+ "url": {
+ "type": "string"
+ },
+ "branches": {
+ "type": "string"
+ },
+ "threshold": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "flags": {
+ "type": "string"
+ },
+ "base": {
+ "enum": ["parent", "pr", "auto"]
+ },
+ "only_pulls": {
+ "type": "boolean"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ },
+ "description": "Schema for codecov.yml files.",
+ "properties": {
+ "codecov": {
+ "description": "See https://docs.codecov.io/docs/codecov-yaml for details",
+ "type": "object",
+ "properties": {
+ "url": {
+ "type": "string"
+ },
+ "slug": {
+ "type": "string"
+ },
+ "bot": {
+ "description": "Team bot. See https://docs.codecov.io/docs/team-bot for details",
+ "type": "string"
+ },
+ "branch": {
+ "type": "string"
+ },
+ "ci": {
+ "description": "Detecting CI services. See https://docs.codecov.io/docs/detecting-ci-services for details.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "assume_all_flags": {
+ "type": "boolean"
+ },
+ "strict_yaml_branch": {
+ "type": "string"
+ },
+ "max_report_age": {
+ "type": ["string", "integer", "boolean"]
+ },
+ "disable_default_path_fixes": {
+ "type": "boolean"
+ },
+ "require_ci_to_pass": {
+ "type": "boolean"
+ },
+ "allow_pseudo_compare": {
+ "type": "boolean"
+ },
+ "archive": {
+ "type": "object",
+ "properties": {
+ "uploads": {
+ "type": "boolean"
+ }
+ }
+ },
+ "notify": {
+ "type": "object",
+ "properties": {
+ "after_n_builds": {
+ "type": "integer"
+ },
+ "countdown": {
+ "type": "integer"
+ },
+ "delay": {
+ "type": "integer"
+ },
+ "wait_for_ci": {
+ "type": "boolean"
+ }
+ }
+ },
+ "ui": {
+ "type": "object",
+ "properties": {
+ "hide_density": {
+ "type": ["boolean", "array"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "hide_complexity": {
+ "type": ["boolean", "array"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "hide_contextual": {
+ "type": "boolean"
+ },
+ "hide_sunburst": {
+ "type": "boolean"
+ },
+ "hide_search": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
+ "coverage": {
+ "description": "Coverage configuration. See https://docs.codecov.io/docs/coverage-configuration for details.",
+ "type": "object",
+ "properties": {
+ "precision": {
+ "type": "integer",
+ "minimum": 0,
+ "maximum": 5
+ },
+ "round": {
+ "enum": ["down", "up", "nearest"]
+ },
+ "range": {
+ "type": "string"
+ },
+ "notify": {
+ "description": "Notifications. See https://docs.codecov.io/docs/notifications for details.",
+ "type": "object",
+ "properties": {
+ "irc": {
+ "type": "object",
+ "properties": {
+ "url": {
+ "type": "string"
+ },
+ "branches": {
+ "type": "string"
+ },
+ "threshold": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "flags": {
+ "type": "string"
+ },
+ "base": {
+ "enum": ["parent", "pr", "auto"]
+ },
+ "only_pulls": {
+ "type": "boolean"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "channel": {
+ "type": "string"
+ },
+ "password": {
+ "type": "string"
+ },
+ "nickserv_password": {
+ "type": "string"
+ },
+ "notice": {
+ "type": "boolean"
+ }
+ }
+ },
+ "slack": {
+ "description": "Slack. See https://docs.codecov.io/docs/notifications#section-slack for details.",
+ "type": "object",
+ "properties": {
+ "url": {
+ "type": "string"
+ },
+ "branches": {
+ "type": "string"
+ },
+ "threshold": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "flags": {
+ "type": "string"
+ },
+ "base": {
+ "enum": ["parent", "pr", "auto"]
+ },
+ "only_pulls": {
+ "type": "boolean"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "attachments": {
+ "$ref": "#/definitions/layout"
+ }
+ }
+ },
+ "gitter": {
+ "description": "Gitter. See https://docs.codecov.io/docs/notifications#section-gitter for details.",
+ "type": "object",
+ "properties": {
+ "url": {
+ "type": "string"
+ },
+ "branches": {
+ "type": "string"
+ },
+ "threshold": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "flags": {
+ "type": "string"
+ },
+ "base": {
+ "enum": ["parent", "pr", "auto"]
+ },
+ "only_pulls": {
+ "type": "boolean"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "hipchat": {
+ "description": "Hipchat. See https://docs.codecov.io/docs/notifications#section-hipchat for details.",
+ "type": "object",
+ "properties": {
+ "url": {
+ "type": "string"
+ },
+ "branches": {
+ "type": "string"
+ },
+ "threshold": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "flags": {
+ "type": "string"
+ },
+ "base": {
+ "enum": ["parent", "pr", "auto"]
+ },
+ "only_pulls": {
+ "type": "boolean"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "card": {
+ "type": "boolean"
+ },
+ "notify": {
+ "type": "boolean"
+ }
+ }
+ },
+ "webhook": {
+ "type": "object",
+ "properties": {
+ "url": {
+ "type": "string"
+ },
+ "branches": {
+ "type": "string"
+ },
+ "threshold": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "flags": {
+ "type": "string"
+ },
+ "base": {
+ "enum": ["parent", "pr", "auto"]
+ },
+ "only_pulls": {
+ "type": "boolean"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "email": {
+ "type": "object",
+ "properties": {
+ "url": {
+ "type": "string"
+ },
+ "branches": {
+ "type": "string"
+ },
+ "threshold": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ },
+ "flags": {
+ "type": "string"
+ },
+ "base": {
+ "enum": ["parent", "pr", "auto"]
+ },
+ "only_pulls": {
+ "type": "boolean"
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "layout": {
+ "$ref": "#/definitions/layout"
+ },
+ "+to": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "status": {
+ "description": "Commit status. See https://docs.codecov.io/docs/commit-status for details.",
+ "type": ["boolean", "object"],
+ "additionalProperties": false,
+ "properties": {
+ "default_rules": {
+ "type": "object"
+ },
+ "project": {
+ "properties": {
+ "default": {
+ "$ref": "#/definitions/default",
+ "type": ["object", "boolean"]
+ }
+ },
+ "additionalProperties": {
+ "$ref": "#/definitions/default",
+ "type": ["object", "boolean"]
+ }
+ },
+ "patch": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/default",
+ "type": "object"
+ },
+ {
+ "type": "string",
+ "enum": ["off"]
+ },
+ {
+ "type": "boolean"
+ }
+ ]
+ },
+ "changes": {
+ "$ref": "#/definitions/default",
+ "type": ["object", "boolean"]
+ }
+ }
+ }
+ }
+ },
+ "ignore": {
+ "description": "Ignoring paths. see https://docs.codecov.io/docs/ignoring-paths for details.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "fixes": {
+ "description": "Fixing paths. See https://docs.codecov.io/docs/fixing-paths for details.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "flags": {
+ "description": "Flags. See https://docs.codecov.io/docs/flags for details.",
+ "oneOf": [
+ {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/flag"
+ }
+ },
+ {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/definitions/flag"
+ }
+ }
+ ]
+ },
+ "comment": {
+ "description": "Pull request comments. See https://docs.codecov.io/docs/pull-request-comments for details.",
+ "oneOf": [
+ {
+ "type": "object",
+ "properties": {
+ "layout": {
+ "$ref": "#/definitions/layout"
+ },
+ "require_changes": {
+ "type": "boolean"
+ },
+ "require_base": {
+ "type": "boolean"
+ },
+ "require_head": {
+ "type": "boolean"
+ },
+ "branches": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "behavior": {
+ "enum": ["default", "once", "new", "spammy"]
+ },
+ "flags": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/flag"
+ }
+ },
+ "paths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ {
+ "const": false
+ }
+ ]
+ },
+ "github_checks": {
+ "description": "GitHub Checks. See https://docs.codecov.com/docs/github-checks for details.",
+ "anyOf": [
+ {
+ "type": "object",
+ "properties": {
+ "annotations": {
+ "type": "boolean"
+ }
+ }
+ },
+ { "type": "boolean" },
+ { "type": "string", "enum": ["off"] }
+ ]
+ }
+ },
+ "title": "JSON schema for Codecov configuration files",
+ "type": "object"
+}
diff --git a/ci/schemas/conda-environment.json b/ci/schemas/conda-environment.json
new file mode 100644
index 000000000000..458676942a44
--- /dev/null
+++ b/ci/schemas/conda-environment.json
@@ -0,0 +1,53 @@
+{
+ "title": "conda environment file",
+ "description": "Support for conda's enviroment.yml files (e.g. `conda env export > environment.yml`)",
+ "id": "https://raw.githubusercontent.com/Microsoft/vscode-python/main/schemas/conda-environment.json",
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "definitions": {
+ "channel": {
+ "type": "string"
+ },
+ "package": {
+ "type": "string"
+ },
+ "path": {
+ "type": "string"
+ }
+ },
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "channels": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/channel"
+ }
+ },
+ "dependencies": {
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/package"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "pip": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/package"
+ }
+ }
+ },
+ "required": ["pip"]
+ }
+ ]
+ }
+ },
+ "prefix": {
+ "$ref": "#/definitions/path"
+ }
+ }
+}
diff --git a/ci/schemas/github-funding.json b/ci/schemas/github-funding.json
new file mode 100644
index 000000000000..d146d692c483
--- /dev/null
+++ b/ci/schemas/github-funding.json
@@ -0,0 +1,113 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/github-funding.json",
+ "$comment": "https://docs.github.com/en/github/administering-a-repository/displaying-a-sponsor-button-in-your-repository",
+ "additionalProperties": false,
+ "definitions": {
+ "github_username": {
+ "type": "string",
+ "maxLength": 39,
+ "pattern": "^[a-zA-Z0-9](-?[a-zA-Z0-9])*$",
+ "examples": ["SampleUserName"]
+ },
+ "nullable_string": {
+ "type": ["string", "null"]
+ }
+ },
+ "description": "You can add a sponsor button in your repository to increase the visibility of funding options for your open source project.",
+ "properties": {
+ "community_bridge": {
+ "$ref": "#/definitions/nullable_string",
+ "title": "CommunityBridge",
+ "description": "Project name on CommunityBridge.",
+ "minLength": 1
+ },
+ "github": {
+ "title": "GitHub Sponsors",
+ "description": "Username or usernames on GitHub.",
+ "oneOf": [
+ {
+ "$ref": "#/definitions/github_username"
+ },
+ {
+ "type": "array",
+ "minItems": 1,
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/github_username"
+ }
+ }
+ ]
+ },
+ "issuehunt": {
+ "$ref": "#/definitions/nullable_string",
+ "title": "IssueHunt",
+ "description": "Username on IssueHunt.",
+ "minLength": 1
+ },
+ "ko_fi": {
+ "$ref": "#/definitions/nullable_string",
+ "title": "Ko-fi",
+ "description": "Username on Ko-fi.",
+ "minLength": 1
+ },
+ "liberapay": {
+ "$ref": "#/definitions/nullable_string",
+ "title": "Liberapay",
+ "description": "Username on Liberapay.",
+ "minLength": 1
+ },
+ "open_collective": {
+ "$ref": "#/definitions/nullable_string",
+ "title": "Open Collective",
+ "description": "Username on Open Collective.",
+ "minLength": 1
+ },
+ "otechie": {
+ "$ref": "#/definitions/nullable_string",
+ "title": "Otechie",
+ "description": "Username on Otechie.",
+ "minLength": 1
+ },
+ "patreon": {
+ "$ref": "#/definitions/nullable_string",
+ "title": "Patreon",
+ "description": "Username on Pateron.",
+ "minLength": 1,
+ "maxLength": 100
+ },
+ "tidelift": {
+ "$ref": "#/definitions/nullable_string",
+ "title": "Tidelift",
+ "description": "Platform and package on Tidelift.",
+ "pattern": "^(npm|pypi|rubygems|maven|packagist|nuget)/.+$"
+ },
+ "lfx_crowdfunding": {
+ "$ref": "#/definitions/nullable_string",
+ "title": "LFX Crowdfunding",
+ "description": "Project name on LFX Crowdfunding.",
+ "minLength": 1
+ },
+ "polar": {
+ "$ref": "#/definitions/github_username",
+ "title": "Polar",
+ "description": "Username on Polar.",
+ "minLength": 1
+ },
+ "custom": {
+ "title": "Custom URL",
+ "description": "Link or links where funding is accepted on external locations.",
+ "type": ["string", "array", "null"],
+ "format": "uri-reference",
+ "items": {
+ "title": "Link",
+ "description": "Link to an external location.",
+ "type": "string",
+ "format": "uri-reference"
+ },
+ "uniqueItems": true
+ }
+ },
+ "title": "GitHub Funding",
+ "type": "object"
+}
diff --git a/ci/schemas/github-issue-config.json b/ci/schemas/github-issue-config.json
new file mode 100644
index 000000000000..b46556bb04a5
--- /dev/null
+++ b/ci/schemas/github-issue-config.json
@@ -0,0 +1,45 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/github-issue-config.json",
+ "$comment": "https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#configuring-the-template-chooser",
+ "properties": {
+ "blank_issues_enabled": {
+ "description": "Specify whether allow blank issue creation\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#configuring-the-template-chooser",
+ "type": "boolean"
+ },
+ "contact_links": {
+ "title": "contact links",
+ "description": "Contact links\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#configuring-the-template-chooser",
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object",
+ "required": ["name", "url", "about"],
+ "properties": {
+ "name": {
+ "description": "A link title\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#configuring-the-template-chooser",
+ "type": "string",
+ "minLength": 1,
+ "examples": ["Sample name"]
+ },
+ "url": {
+ "description": "A link URL\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#configuring-the-template-chooser",
+ "type": "string",
+ "pattern": "^https?://",
+ "examples": ["https://sample/url"]
+ },
+ "about": {
+ "description": "A link description\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#configuring-the-template-chooser",
+ "type": "string",
+ "minLength": 1,
+ "examples": ["Sample description"]
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "additionalProperties": false,
+ "title": "GitHub issue template chooser config file schema",
+ "type": "object"
+}
diff --git a/ci/schemas/github-issue-forms.json b/ci/schemas/github-issue-forms.json
new file mode 100644
index 000000000000..c928818dfdd1
--- /dev/null
+++ b/ci/schemas/github-issue-forms.json
@@ -0,0 +1,1295 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/github-issue-forms.json",
+ "$comment": "https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms",
+ "additionalProperties": false,
+ "definitions": {
+ "type": {
+ "description": "A form item type\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#keys",
+ "type": "string",
+ "enum": ["checkboxes", "dropdown", "input", "markdown", "textarea"]
+ },
+ "id": {
+ "type": "string",
+ "pattern": "^[a-zA-Z0-9_-]+$",
+ "examples": ["SampleId"]
+ },
+ "validations": {
+ "title": "validation options",
+ "type": "object",
+ "properties": {
+ "required": {
+ "description": "Specify whether require a form item",
+ "type": "boolean",
+ "default": false
+ }
+ },
+ "additionalProperties": false
+ },
+ "assignee": {
+ "type": "string",
+ "maxLength": 39,
+ "pattern": "^[a-zA-Z0-9](-?[a-zA-Z0-9])*$",
+ "examples": ["SampleAssignee"]
+ },
+ "label": {
+ "type": "string",
+ "minLength": 1,
+ "examples": ["Sample label"]
+ },
+ "description": {
+ "type": "string",
+ "default": "",
+ "examples": ["Sample description"]
+ },
+ "placeholder": {
+ "type": "string",
+ "default": "",
+ "examples": ["Sample placeholder"]
+ },
+ "value": {
+ "type": "string",
+ "minLength": 1,
+ "examples": ["Sample value"]
+ },
+ "form_item": {
+ "title": "form item",
+ "description": "A form item\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#about-githubs-form-schema",
+ "type": "object",
+ "required": ["type"],
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/type"
+ }
+ },
+ "allOf": [
+ {
+ "if": {
+ "properties": {
+ "type": {
+ "const": "markdown"
+ }
+ }
+ },
+ "then": {
+ "$comment": "For `additionalProperties` to work `type` must also be present here.",
+ "title": "markdown",
+ "description": "Markdown\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#markdown",
+ "type": "object",
+ "required": ["type", "attributes"],
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/type"
+ },
+ "attributes": {
+ "title": "markdown attributes",
+ "description": "Markdown attributes\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes",
+ "type": "object",
+ "required": ["value"],
+ "properties": {
+ "value": {
+ "description": "A markdown code\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes",
+ "type": "string",
+ "minLength": 1,
+ "examples": ["Sample code"]
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "type": {
+ "const": "textarea"
+ }
+ }
+ },
+ "then": {
+ "$comment": "For `additionalProperties` to work `type` must also be present here.",
+ "title": "textarea",
+ "description": "Textarea\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#textarea",
+ "type": "object",
+ "required": ["type", "attributes"],
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/type"
+ },
+ "id": {
+ "$ref": "#/definitions/id",
+ "description": "A textarea id\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#keys"
+ },
+ "attributes": {
+ "title": "textarea attributes",
+ "description": "Textarea attributes\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-1",
+ "type": "object",
+ "required": ["label"],
+ "properties": {
+ "label": {
+ "$ref": "#/definitions/label",
+ "description": "A short textarea description\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-1"
+ },
+ "description": {
+ "$ref": "#/definitions/description",
+ "description": "A long textarea description\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-1"
+ },
+ "placeholder": {
+ "$ref": "#/definitions/placeholder",
+ "description": "A textarea placeholder\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-1"
+ },
+ "value": {
+ "$ref": "#/definitions/value",
+ "description": "A textarea value\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-1"
+ },
+ "render": {
+ "description": "A textarea syntax highlighting mode\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-1",
+ "type": "string",
+ "enum": [
+ "1C Enterprise",
+ "4D",
+ "ABAP CDS",
+ "ABAP",
+ "ABNF",
+ "AFDKO",
+ "AGS Script",
+ "AIDL",
+ "AL",
+ "AMPL",
+ "ANTLR",
+ "API Blueprint",
+ "APL",
+ "ASL",
+ "ASN.1",
+ "ASP.NET",
+ "ATS",
+ "ActionScript",
+ "Ada",
+ "Alloy",
+ "Alpine Abuild",
+ "Altium Designer",
+ "AngelScript",
+ "Ant Build System",
+ "ApacheConf",
+ "Apex",
+ "Apollo Guidance Computer",
+ "AppleScript",
+ "Arc",
+ "AsciiDoc",
+ "AspectJ",
+ "Assembly",
+ "Astro",
+ "Asymptote",
+ "Augeas",
+ "AutoHotkey",
+ "AutoIt",
+ "AutoIt3",
+ "AutoItScript",
+ "Avro IDL",
+ "Awk",
+ "BASIC",
+ "Ballerina",
+ "Batchfile",
+ "Beef",
+ "Befunge",
+ "BibTeX",
+ "Bicep",
+ "Bison",
+ "BitBake",
+ "Blade",
+ "BlitzBasic",
+ "BlitzMax",
+ "Boo",
+ "Boogie",
+ "Brainfuck",
+ "Brightscript",
+ "Browserslist",
+ "C",
+ "C#",
+ "C++",
+ "C-ObjDump",
+ "C2hs Haskell",
+ "CIL",
+ "CLIPS",
+ "CMake",
+ "COBOL",
+ "CODEOWNERS",
+ "COLLADA",
+ "CSON",
+ "CSS",
+ "CSV",
+ "CUE",
+ "CWeb",
+ "Cabal Config",
+ "Cabal",
+ "Cap'n Proto",
+ "Carto",
+ "CartoCSS",
+ "Ceylon",
+ "Chapel",
+ "Charity",
+ "ChucK",
+ "Cirru",
+ "Clarion",
+ "Classic ASP",
+ "Clean",
+ "Click",
+ "Clojure",
+ "Closure Templates",
+ "Cloud Firestore Security Rules",
+ "CoNLL",
+ "CoNLL-U",
+ "CoNLL-X",
+ "ColdFusion CFC",
+ "ColdFusion",
+ "Common Lisp",
+ "Common Workflow Language",
+ "Component Pascal",
+ "Containerfile",
+ "Cool",
+ "Coq",
+ "Cpp-ObjDump",
+ "Crystal",
+ "Csound Document",
+ "Csound Score",
+ "Csound",
+ "Cuda",
+ "Cue Sheet",
+ "Cycript",
+ "Cython",
+ "D-ObjDump",
+ "DIGITAL Command Language",
+ "DM",
+ "DTrace",
+ "Dafny",
+ "Darcs Patch",
+ "Dart",
+ "DataWeave",
+ "Dhall",
+ "Diff",
+ "Dlang",
+ "Dockerfile",
+ "Dogescript",
+ "Dylan",
+ "E",
+ "E-mail",
+ "EBNF",
+ "ECL",
+ "ECLiPSe",
+ "EJS",
+ "EQ",
+ "Eagle",
+ "Earthly",
+ "Easybuild",
+ "Ecere Projects",
+ "EditorConfig",
+ "Eiffel",
+ "Elixir",
+ "Elm",
+ "Emacs Lisp",
+ "EmberScript",
+ "Erlang",
+ "F#",
+ "F*",
+ "FIGfont",
+ "FIGlet Font",
+ "FLUX",
+ "Factor",
+ "Fancy",
+ "Fantom",
+ "Faust",
+ "Fennel",
+ "Filebench WML",
+ "Filterscript",
+ "Fluent",
+ "Formatted",
+ "Forth",
+ "Fortran Free Form",
+ "Fortran",
+ "FreeBasic",
+ "Frege",
+ "Futhark",
+ "G-code",
+ "GAML",
+ "GAMS",
+ "GAP",
+ "GCC Machine Description",
+ "GDB",
+ "GDScript",
+ "GEDCOM",
+ "GLSL",
+ "GN",
+ "Game Maker Language",
+ "Gemfile.lock",
+ "Genie",
+ "Genshi",
+ "Gentoo Eclass",
+ "Gerber Image",
+ "Gettext Catalog",
+ "Gherkin",
+ "Git Config",
+ "Glyph Bitmap Distribution Format",
+ "Glyph",
+ "Gnuplot",
+ "Go Checksums",
+ "Go Module",
+ "Go",
+ "Golo",
+ "Gosu",
+ "Grace",
+ "Gradle",
+ "Grammatical Framework",
+ "Graph Modeling Language",
+ "GraphQL",
+ "Graphviz (DOT)",
+ "Groovy Server Pages",
+ "Groovy",
+ "HAProxy",
+ "HCL",
+ "HTML",
+ "HTML+ECR",
+ "HTML+EEX",
+ "HTML+ERB",
+ "HTML+PHP",
+ "HTML+Razor",
+ "HTTP",
+ "HXML",
+ "Hack",
+ "Haml",
+ "Handlebars",
+ "Harbour",
+ "HashiCorp Configuration Language",
+ "Haskell",
+ "Haxe",
+ "HiveQL",
+ "HolyC",
+ "Hy",
+ "IDL",
+ "IGOR Pro",
+ "IPython Notebook",
+ "Idris",
+ "Ignore List",
+ "ImageJ Macro",
+ "Inform 7",
+ "Io",
+ "Ioke",
+ "Isabelle ROOT",
+ "Isabelle",
+ "J",
+ "JAR Manifest",
+ "JFlex",
+ "JSON with Comments",
+ "JSON",
+ "JSON5",
+ "JSONLD",
+ "JSONiq",
+ "Jasmin",
+ "Java Properties",
+ "Java Server Pages",
+ "Java",
+ "JavaScript",
+ "JavaScript+ERB",
+ "Jest Snapshot",
+ "Jinja",
+ "Jison Lex",
+ "Jison",
+ "Jolie",
+ "Jsonnet",
+ "Julia",
+ "Jupyter Notebook",
+ "Kaitai Struct",
+ "KakouneScript",
+ "KiCad Layout",
+ "KiCad Legacy Layout",
+ "KiCad Schematic",
+ "Kit",
+ "Kotlin",
+ "Kusto",
+ "LFE",
+ "LLVM",
+ "LOLCODE",
+ "LSL",
+ "LTspice Symbol",
+ "LabVIEW",
+ "Lark",
+ "Lasso",
+ "Lean",
+ "Less",
+ "Lex",
+ "LilyPond",
+ "Limbo",
+ "Linker Script",
+ "Linux Kernel Module",
+ "Liquid",
+ "Literate Agda",
+ "Literate CoffeeScript",
+ "Literate Haskell",
+ "LiveScript",
+ "Logos",
+ "Logtalk",
+ "LookML",
+ "LoomScript",
+ "Lua",
+ "M",
+ "M4",
+ "M4Sugar",
+ "MATLAB",
+ "MAXScript",
+ "MLIR",
+ "MQL4",
+ "MQL5",
+ "MTML",
+ "MUF",
+ "Macaulay2",
+ "Makefile",
+ "Mako",
+ "Markdown",
+ "Marko",
+ "Mathematica",
+ "Max",
+ "Mercury",
+ "Meson",
+ "Metal",
+ "Microsoft Developer Studio Project",
+ "Microsoft Visual Studio Solution",
+ "MiniD",
+ "Mirah",
+ "Modelica",
+ "Modula-2",
+ "Modula-3",
+ "Module Management System",
+ "Monkey",
+ "Moocode",
+ "MoonScript",
+ "Motoko",
+ "Motorola 68K Assembly",
+ "Muse",
+ "Myghty",
+ "NASL",
+ "NCL",
+ "NEON",
+ "NPM Config",
+ "NSIS",
+ "NWScript",
+ "Nearley",
+ "Nemerle",
+ "NeoSnippet",
+ "NetLinx",
+ "NetLinx+ERB",
+ "NetLogo",
+ "NewLisp",
+ "Nextflow",
+ "Nginx",
+ "Ninja",
+ "Nit",
+ "Nix",
+ "NumPy",
+ "Nunjucks",
+ "ObjDump",
+ "Object Data Instance Notation",
+ "ObjectScript",
+ "Objective-C",
+ "Objective-C++",
+ "Objective-J",
+ "Odin",
+ "Omgrofl",
+ "Opa",
+ "Opal",
+ "Open Policy Agent",
+ "OpenCL",
+ "OpenEdge ABL",
+ "OpenQASM",
+ "OpenRC runscript",
+ "OpenSCAD",
+ "OpenStep Property List",
+ "OpenType Feature File",
+ "Org",
+ "Ox",
+ "Oxygene",
+ "Oz",
+ "P4",
+ "PEG.js",
+ "PHP",
+ "PLpgSQL",
+ "POV-Ray SDL",
+ "Pan",
+ "Papyrus",
+ "Parrot Assembly",
+ "Parrot Internal Representation",
+ "Parrot",
+ "Pascal",
+ "Pawn",
+ "Pep8",
+ "Perl",
+ "Pickle",
+ "PicoLisp",
+ "PigLatin",
+ "Pike",
+ "PlantUML",
+ "Pod 6",
+ "Pod",
+ "PogoScript",
+ "Pony",
+ "PostCSS",
+ "PostScript",
+ "PowerShell",
+ "Prisma",
+ "Processing",
+ "Proguard",
+ "Prolog",
+ "Promela",
+ "Propeller Spin",
+ "Protocol Buffer",
+ "Protocol Buffers",
+ "Public Key",
+ "Pug",
+ "Puppet",
+ "Pure Data",
+ "PureBasic",
+ "PureScript",
+ "Python",
+ "Q#",
+ "QMake",
+ "Qt Script",
+ "Quake",
+ "R",
+ "RAML",
+ "RDoc",
+ "REALbasic",
+ "REXX",
+ "RMarkdown",
+ "RPC",
+ "RPM Spec",
+ "Racket",
+ "Ragel",
+ "Raw token data",
+ "ReScript",
+ "Readline Config",
+ "Reason",
+ "Rebol",
+ "Record Jar",
+ "Red",
+ "Redirect Rules",
+ "Regular Expression",
+ "RenderScript",
+ "Rich Text Format",
+ "Ring",
+ "Riot",
+ "RobotFramework",
+ "Roff",
+ "Rouge",
+ "Rscript",
+ "Ruby",
+ "Rust",
+ "SAS",
+ "SCSS",
+ "SELinux Kernel Policy Language",
+ "SELinux Policy",
+ "SMT",
+ "SPARQL",
+ "SQF",
+ "SQL",
+ "SQLPL",
+ "SRecode Template",
+ "SSH Config",
+ "STON",
+ "SVG",
+ "SWIG",
+ "Sage",
+ "SaltStack",
+ "Sass",
+ "Scala",
+ "Scaml",
+ "Scheme",
+ "Scilab",
+ "Self",
+ "ShaderLab",
+ "Shell",
+ "ShellCheck Config",
+ "Sieve",
+ "Singularity",
+ "Slash",
+ "Slice",
+ "Slim",
+ "SmPL",
+ "Smalltalk",
+ "SnipMate",
+ "Solidity",
+ "Soong",
+ "SourcePawn",
+ "Spline Font Database",
+ "Squirrel",
+ "Stan",
+ "Standard ML",
+ "Starlark",
+ "StringTemplate",
+ "Stylus",
+ "SubRip Text",
+ "SugarSS",
+ "SuperCollider",
+ "Svelte",
+ "Swift",
+ "SystemVerilog",
+ "TI Program",
+ "TLA",
+ "TOML",
+ "TSQL",
+ "TSV",
+ "TSX",
+ "TXL",
+ "Tcl",
+ "Tcsh",
+ "TeX",
+ "Tea",
+ "Terra",
+ "Texinfo",
+ "Text",
+ "TextMate Properties",
+ "Textile",
+ "Thrift",
+ "Turing",
+ "Turtle",
+ "Twig",
+ "Type Language",
+ "TypeScript",
+ "UltiSnip",
+ "UltiSnips",
+ "Unified Parallel C",
+ "Unity3D Asset",
+ "Unix Assembly",
+ "Uno",
+ "UnrealScript",
+ "Ur",
+ "Ur/Web",
+ "UrWeb",
+ "V",
+ "VBA",
+ "VCL",
+ "VHDL",
+ "Vala",
+ "Valve Data Format",
+ "Verilog",
+ "Vim Help File",
+ "Vim Script",
+ "Vim Snippet",
+ "Visual Basic .NET",
+ "Vue",
+ "Wavefront Material",
+ "Wavefront Object",
+ "Web Ontology Language",
+ "WebAssembly",
+ "WebVTT",
+ "Wget Config",
+ "Wikitext",
+ "Windows Registry Entries",
+ "Wollok",
+ "World of Warcraft Addon Data",
+ "X BitMap",
+ "X Font Directory Index",
+ "X PixMap",
+ "X10",
+ "XC",
+ "XCompose",
+ "XML Property List",
+ "XML",
+ "XPages",
+ "XProc",
+ "XQuery",
+ "XS",
+ "XSLT",
+ "Xojo",
+ "Xonsh",
+ "Xtend",
+ "YAML",
+ "YANG",
+ "YARA",
+ "YASnippet",
+ "Yacc",
+ "ZAP",
+ "ZIL",
+ "Zeek",
+ "ZenScript",
+ "Zephir",
+ "Zig",
+ "Zimpl",
+ "abl",
+ "abuild",
+ "acfm",
+ "aconf",
+ "actionscript 3",
+ "actionscript3",
+ "ada2005",
+ "ada95",
+ "adobe composite font metrics",
+ "adobe multiple font metrics",
+ "advpl",
+ "ags",
+ "ahk",
+ "altium",
+ "amfm",
+ "amusewiki",
+ "apache",
+ "apkbuild",
+ "arexx",
+ "as3",
+ "asm",
+ "asp",
+ "aspx",
+ "aspx-vb",
+ "ats2",
+ "au3",
+ "autoconf",
+ "b3d",
+ "bash session",
+ "bash",
+ "bat",
+ "batch",
+ "bazel",
+ "blitz3d",
+ "blitzplus",
+ "bmax",
+ "bplus",
+ "bro",
+ "bsdmake",
+ "byond",
+ "bzl",
+ "c++-objdump",
+ "c2hs",
+ "cURL Config",
+ "cake",
+ "cakescript",
+ "cfc",
+ "cfm",
+ "cfml",
+ "chpl",
+ "clipper",
+ "coccinelle",
+ "coffee",
+ "coffee-script",
+ "coldfusion html",
+ "console",
+ "cperl",
+ "cpp",
+ "csharp",
+ "csound-csd",
+ "csound-orc",
+ "csound-sco",
+ "cucumber",
+ "curlrc",
+ "cwl",
+ "dcl",
+ "delphi",
+ "desktop",
+ "dircolors",
+ "django",
+ "dosbatch",
+ "dosini",
+ "dpatch",
+ "dtrace-script",
+ "eC",
+ "ecr",
+ "editor-config",
+ "edn",
+ "eeschema schematic",
+ "eex",
+ "elisp",
+ "emacs muse",
+ "emacs",
+ "email",
+ "eml",
+ "erb",
+ "fb",
+ "fish",
+ "flex",
+ "foxpro",
+ "fsharp",
+ "fstar",
+ "ftl",
+ "fundamental",
+ "gf",
+ "git-ignore",
+ "gitattributes",
+ "gitconfig",
+ "gitignore",
+ "gitmodules",
+ "go mod",
+ "go sum",
+ "go.mod",
+ "go.sum",
+ "golang",
+ "groff",
+ "gsp",
+ "hbs",
+ "heex",
+ "help",
+ "html+django",
+ "html+jinja",
+ "html+ruby",
+ "htmlbars",
+ "htmldjango",
+ "hylang",
+ "i7",
+ "ignore",
+ "igor",
+ "igorpro",
+ "ijm",
+ "inc",
+ "inform7",
+ "inputrc",
+ "irc logs",
+ "irc",
+ "java server page",
+ "jq",
+ "jruby",
+ "js",
+ "jsonc",
+ "jsp",
+ "kak",
+ "kakscript",
+ "keyvalues",
+ "ksy",
+ "lassoscript",
+ "latex",
+ "leex",
+ "lhaskell",
+ "lhs",
+ "lisp",
+ "litcoffee",
+ "live-script",
+ "ls",
+ "m2",
+ "m68k",
+ "mIRC Script",
+ "macruby",
+ "mail",
+ "make",
+ "man page",
+ "man",
+ "man-page",
+ "manpage",
+ "markojs",
+ "max/msp",
+ "maxmsp",
+ "mbox",
+ "mcfunction",
+ "mdoc",
+ "mediawiki",
+ "mf",
+ "mma",
+ "mumps",
+ "mupad",
+ "nanorc",
+ "nasm",
+ "ne-on",
+ "nesC",
+ "nette object notation",
+ "nginx configuration file",
+ "nixos",
+ "njk",
+ "node",
+ "npmrc",
+ "nroff",
+ "nush",
+ "nvim",
+ "obj-c",
+ "obj-c++",
+ "obj-j",
+ "objc",
+ "objc++",
+ "objectivec",
+ "objectivec++",
+ "objectivej",
+ "objectpascal",
+ "objj",
+ "octave",
+ "odin-lang",
+ "odinlang",
+ "oncrpc",
+ "ooc",
+ "openedge",
+ "openrc",
+ "osascript",
+ "pandoc",
+ "pasm",
+ "pcbnew",
+ "perl-6",
+ "perl6",
+ "pir",
+ "plain text",
+ "posh",
+ "postscr",
+ "pot",
+ "pov-ray",
+ "povray",
+ "progress",
+ "protobuf",
+ "pwsh",
+ "pycon",
+ "pyrex",
+ "python3",
+ "q",
+ "ql",
+ "qsharp",
+ "ragel-rb",
+ "ragel-ruby",
+ "rake",
+ "raw",
+ "razor",
+ "rb",
+ "rbx",
+ "reStructuredText",
+ "readline",
+ "red/system",
+ "redirects",
+ "regex",
+ "regexp",
+ "renpy",
+ "rhtml",
+ "robots txt",
+ "robots",
+ "robots.txt",
+ "rpcgen",
+ "rs",
+ "rs-274x",
+ "rss",
+ "rst",
+ "rusthon",
+ "salt",
+ "saltstate",
+ "sed",
+ "sepolicy",
+ "sh",
+ "shell-script",
+ "shellcheckrc",
+ "sml",
+ "snippet",
+ "sourcemod",
+ "soy",
+ "specfile",
+ "splus",
+ "squeak",
+ "terraform",
+ "tl",
+ "tm-properties",
+ "troff",
+ "ts",
+ "udiff",
+ "vb .net",
+ "vb.net",
+ "vb6",
+ "vbnet",
+ "vdf",
+ "vim",
+ "vimhelp",
+ "viml",
+ "visual basic 6",
+ "visual basic for applications",
+ "visual basic",
+ "vlang",
+ "wasm",
+ "wast",
+ "wdl",
+ "wgetrc",
+ "wiki",
+ "winbatch",
+ "wisp",
+ "wl",
+ "wolfram lang",
+ "wolfram language",
+ "wolfram",
+ "wsdl",
+ "xBase",
+ "xbm",
+ "xdr",
+ "xhtml",
+ "xml+genshi",
+ "xml+kid",
+ "xpm",
+ "xsd",
+ "xsl",
+ "xten",
+ "yas",
+ "yml",
+ "zsh"
+ ]
+ }
+ },
+ "additionalProperties": false
+ },
+ "validations": {
+ "$ref": "#/definitions/validations",
+ "title": "textarea validations",
+ "description": "Textarea validations\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#validations"
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "type": {
+ "const": "input"
+ }
+ }
+ },
+ "then": {
+ "$comment": "For `additionalProperties` to work `type` must also be present here.",
+ "title": "input",
+ "description": "Input\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#input",
+ "type": "object",
+ "required": ["type", "attributes"],
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/type"
+ },
+ "id": {
+ "$ref": "#/definitions/id",
+ "description": "An input id\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#keys"
+ },
+ "attributes": {
+ "title": "input attributes",
+ "description": "Input attributes\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-2",
+ "type": "object",
+ "required": ["label"],
+ "properties": {
+ "label": {
+ "$ref": "#/definitions/label",
+ "description": "A short input description\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-2"
+ },
+ "description": {
+ "$ref": "#/definitions/description",
+ "description": "A long input description\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-2"
+ },
+ "placeholder": {
+ "$ref": "#/definitions/placeholder",
+ "description": "An input placeholder\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-2"
+ },
+ "value": {
+ "$ref": "#/definitions/value",
+ "description": "An input value\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-2"
+ }
+ },
+ "additionalProperties": false
+ },
+ "validations": {
+ "$ref": "#/definitions/validations",
+ "title": "input validations",
+ "description": "Input validations\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#validations-1"
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "type": {
+ "const": "dropdown"
+ }
+ }
+ },
+ "then": {
+ "$comment": "For `additionalProperties` to work `type` must also be present here.",
+ "title": "dropdown",
+ "description": "dropdown\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#dropdown",
+ "type": "object",
+ "required": ["type", "attributes"],
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/type"
+ },
+ "id": {
+ "$ref": "#/definitions/id",
+ "description": "A dropdown id\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#keys"
+ },
+ "attributes": {
+ "title": "dropdown attributes",
+ "description": "Dropdown attributes\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-3",
+ "type": "object",
+ "required": ["label", "options"],
+ "properties": {
+ "label": {
+ "$ref": "#/definitions/label",
+ "description": "A short dropdown description\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-3"
+ },
+ "description": {
+ "$ref": "#/definitions/description",
+ "description": "A long dropdown description\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-3"
+ },
+ "multiple": {
+ "description": "Specify whether allow a multiple choices\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-3",
+ "type": "boolean",
+ "default": false
+ },
+ "options": {
+ "description": "Dropdown choices\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-3",
+ "type": "array",
+ "minItems": 1,
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "minLength": 1,
+ "examples": ["Sample choice"]
+ }
+ },
+ "default": {
+ "description": "Index of the default option\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-3",
+ "type": "integer",
+ "examples": [0]
+ }
+ },
+ "additionalProperties": false
+ },
+ "validations": {
+ "$ref": "#/definitions/validations",
+ "title": "dropdown validations",
+ "description": "Dropdown validations\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#validations-2"
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "type": {
+ "const": "checkboxes"
+ }
+ }
+ },
+ "then": {
+ "$comment": "For `additionalProperties` to work `type` must also be present here.",
+ "title": "checkboxes",
+ "description": "Checkboxes\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#checkboxes",
+ "type": "object",
+ "required": ["type", "attributes"],
+ "properties": {
+ "type": {
+ "$ref": "#/definitions/type"
+ },
+ "id": {
+ "$ref": "#/definitions/id",
+ "description": "Checkbox list id\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#keys"
+ },
+ "attributes": {
+ "title": "checkbox list attributes",
+ "description": "Checkbox list attributes\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-4",
+ "type": "object",
+ "required": ["label", "options"],
+ "properties": {
+ "label": {
+ "$ref": "#/definitions/label",
+ "description": "A short checkbox list description\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-4"
+ },
+ "description": {
+ "$ref": "#/definitions/description",
+ "description": "A long checkbox list description\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-4"
+ },
+ "options": {
+ "description": "Checkbox list choices\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-4",
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "title": "checkbox list choice",
+ "description": "Checkbox list choice\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-4",
+ "type": "object",
+ "required": ["label"],
+ "properties": {
+ "label": {
+ "description": "A short checkbox list choice description\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-4",
+ "type": "string",
+ "minLength": 1,
+ "examples": ["Sample label"]
+ },
+ "required": {
+ "description": "Specify whether a choice is required\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema#attributes-4",
+ "type": "boolean",
+ "default": false
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ ]
+ }
+ },
+ "properties": {
+ "name": {
+ "description": "An issue template name\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#top-level-syntax",
+ "type": "string",
+ "minLength": 1,
+ "examples": ["Sample name"]
+ },
+ "description": {
+ "description": "An issue template description\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#top-level-syntax",
+ "type": "string",
+ "minLength": 1,
+ "examples": ["Sample description"]
+ },
+ "body": {
+ "description": "An issue template body\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#top-level-syntax",
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "$ref": "#/definitions/form_item"
+ }
+ },
+ "assignees": {
+ "description": "An issue template assignees\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#top-level-syntax",
+ "oneOf": [
+ {
+ "$ref": "#/definitions/assignee"
+ },
+ {
+ "type": "array",
+ "minItems": 1,
+ "uniqueItems": true,
+ "items": {
+ "$ref": "#/definitions/assignee"
+ }
+ }
+ ]
+ },
+ "labels": {
+ "description": "An issue template labels\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#top-level-syntax",
+ "type": "array",
+ "minItems": 1,
+ "uniqueItems": true,
+ "items": {
+ "type": "string",
+ "minLength": 1,
+ "examples": [
+ "Sample label",
+ "bug",
+ "documentation",
+ "duplicate",
+ "enhancement",
+ "good first issue",
+ "help wanted",
+ "invalid",
+ "question",
+ "wontfix"
+ ]
+ }
+ },
+ "title": {
+ "description": "An issue template title\nhttps://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms#top-level-syntax",
+ "type": "string",
+ "minLength": 1,
+ "examples": ["Sample title", "Bug: ", "Feature: "]
+ }
+ },
+ "required": ["name", "description", "body"],
+ "title": "GitHub issue forms config file schema",
+ "type": "object"
+}
diff --git a/ci/schemas/pull-request-labeler-5.json b/ci/schemas/pull-request-labeler-5.json
new file mode 100644
index 000000000000..22ad7955814f
--- /dev/null
+++ b/ci/schemas/pull-request-labeler-5.json
@@ -0,0 +1,95 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "https://json.schemastore.org/pull-request-labeler-5.json",
+ "$comment": "https://github.com/actions/labeler",
+ "$defs": {
+ "stringOrStringArray": {
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ },
+ "match": {
+ "title": "Match",
+ "type": "object",
+ "properties": {
+ "changed-files": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "any-glob-to-any-file": { "$ref": "#/$defs/stringOrStringArray" },
+ "any-glob-to-all-files": {
+ "$ref": "#/$defs/stringOrStringArray"
+ },
+ "all-globs-to-any-file": {
+ "$ref": "#/$defs/stringOrStringArray"
+ },
+ "all-globs-to-all-files": {
+ "$ref": "#/$defs/stringOrStringArray"
+ }
+ },
+ "oneOf": [
+ { "required": ["any-glob-to-any-file"] },
+ { "required": ["any-glob-to-all-files"] },
+ { "required": ["all-globs-to-any-file"] },
+ { "required": ["all-globs-to-all-files"] }
+ ],
+ "additionalProperties": false
+ }
+ },
+ "base-branch": { "$ref": "#/$defs/stringOrStringArray" },
+ "head-branch": { "$ref": "#/$defs/stringOrStringArray" }
+ },
+ "oneOf": [
+ { "required": ["changed-files"] },
+ { "required": ["base-branch"] },
+ { "required": ["head-branch"] }
+ ],
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": {
+ "title": "Label",
+ "type": "array",
+ "items": {
+ "anyOf": [
+ {
+ "type": "object",
+ "properties": {
+ "all": {
+ "title": "All",
+ "type": "array",
+ "items": { "$ref": "#/$defs/match" }
+ }
+ },
+ "additionalProperties": false,
+ "required": ["all"]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "any": {
+ "title": "Any",
+ "type": "array",
+ "items": { "$ref": "#/$defs/match" }
+ }
+ },
+ "additionalProperties": false,
+ "required": ["any"]
+ },
+ { "$ref": "#/$defs/match" }
+ ]
+ }
+ },
+ "description": "A GitHub Action for automatically labelling pull requests.",
+ "title": "Pull Request Labeler",
+ "type": "object"
+}
diff --git a/ci/schemas/vendor_schemas.py b/ci/schemas/vendor_schemas.py
new file mode 100644
index 000000000000..a40e262e69f7
--- /dev/null
+++ b/ci/schemas/vendor_schemas.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python3
+"""
+Download YAML Schemas for linting and validation.
+
+Since pre-commit CI doesn't have Internet access, we need to bundle these files
+in the repo.
+"""
+
+import os
+import pathlib
+import urllib.request
+
+
+HERE = pathlib.Path(__file__).parent
+SCHEMAS = [
+ 'https://json.schemastore.org/appveyor.json',
+ 'https://json.schemastore.org/circleciconfig.json',
+ 'https://json.schemastore.org/github-funding.json',
+ 'https://json.schemastore.org/github-issue-config.json',
+ 'https://json.schemastore.org/github-issue-forms.json',
+ 'https://json.schemastore.org/codecov.json',
+ 'https://json.schemastore.org/pull-request-labeler-5.json',
+ 'https://github.com/microsoft/vscode-python/raw/'
+ 'main/schemas/conda-environment.json',
+]
+
+
+def print_progress(block_count, block_size, total_size):
+ size = block_count * block_size
+ if total_size != -1:
+ size = min(size, total_size)
+ width = 50
+ percent = size / total_size * 100
+ filled = int(percent // (100 // width))
+ percent_str = '\N{Full Block}' * filled + '\N{Light Shade}' * (width - filled)
+ print(f'{percent_str} {size:6d} / {total_size:6d}', end='\r')
+
+
+# First clean up existing files.
+for json in HERE.glob('*.json'):
+ os.remove(json)
+
+for schema in SCHEMAS:
+ path = HERE / schema.rsplit('/', 1)[-1]
+ print(f'Downloading {schema} to {path}')
+ urllib.request.urlretrieve(schema, filename=path, reporthook=print_progress)
+ print()
+ # This seems weird, but it normalizes line endings to the current platform,
+ # so that Git doesn't complain about it.
+ path.write_text(path.read_text())
diff --git a/doc/Makefile b/doc/Makefile
index 7eda39d87624..baed196a3ee2 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -18,6 +18,7 @@ help:
clean:
@$(SPHINXBUILD) -M clean "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
rm -rf "$(SOURCEDIR)/build"
+ rm -rf "$(SOURCEDIR)/_tags"
rm -rf "$(SOURCEDIR)/api/_as_gen"
rm -rf "$(SOURCEDIR)/gallery"
rm -rf "$(SOURCEDIR)/plot_types"
diff --git a/doc/README.txt b/doc/README.txt
index 0caf5e013c9b..c34dbd769712 100644
--- a/doc/README.txt
+++ b/doc/README.txt
@@ -9,35 +9,58 @@ See :file:`doc/devel/documenting_mpl.rst` for instructions to build the docs.
Organization
------------
-This is the top level build directory for the Matplotlib
-documentation. All of the documentation is written using sphinx, a
-python documentation system built on top of ReST. This directory contains
+This is the top level directory for the Matplotlib
+documentation. All of the documentation is written using Sphinx, a
+python documentation system based on reStructuredText. This directory contains the
+following
-* users - the user documentation, e.g., installation, plotting tutorials,
-configuration tips, faq, explanations, etc.
+Files
+^^^^^
-* devel - documentation for Matplotlib developers
+* index.rst - the top level include document (and landing page) for the Matplotlib docs
-* api - placeholders to automatically generate the api documentation
+* conf.py - the sphinx configuration
-* tutorials, plot_types, and gallery - automatically
-generated by sphinx-gallery from ``../tutorials``, ``../plot_types``, and
-``../examples`` respectively (these are only present if docs have been
-built locally).
+* docutils.conf - htmnl output configuration
-* thirdpartypackages - redirect to
+* Makefile and make.bat - entry points for building the docs
-* mpl_toolkits - documentation of individual toolkits that ship with
- Matplotlib
+* matplotlibrc - rcParam configuration for docs
-* index.rst - the top level include document for Matplotlib docs
+* missing-references.json - list of known missing/broken references
-* conf.py - the sphinx configuration
-* Makefile and make.bat - entry points for building the docs
+Content folders
+^^^^^^^^^^^^^^^
+
+* api - templates for generating the api documentation
-* _static - used by the sphinx build system
+* devel - documentation for contributing to Matplotlib
-* _templates - used by the sphinx build system
+* project - about Matplotlib, e.g. mission, code of conduct, licenses, history, etc.
+
+* users - usage documentation, e.g., installation, tutorials, faq, explanations, etc.
+
+* thirdpartypackages - redirect to
+
+Build folders
+^^^^^^^^^^^^^
+
+* _static - supplementary files; e.g. images, CSS, etc.
+
+* _templates - Sphinx page templates
* sphinxext - Sphinx extensions for the Matplotlib docs
+
+Symlinks
+--------
+
+During the documentation build, sphinx-gallery creates symlinks from the source folders
+in `/galleries` to target_folders in '/doc'; therefore ensure that you are editing the
+real files rather than the symbolic links.
+
+Source files -> symlink:
+* galleries/tutorials -> doc/tutorials
+* galleries/plot_types -> doc/plot_types
+* galleries/examples -> doc/gallery
+* galleries/users_explain -> doc/users/explain
diff --git a/doc/_embedded_plots/axes_margins.py b/doc/_embedded_plots/axes_margins.py
new file mode 100644
index 000000000000..d026840c3c15
--- /dev/null
+++ b/doc/_embedded_plots/axes_margins.py
@@ -0,0 +1,42 @@
+import numpy as np
+import matplotlib.pyplot as plt
+
+fig, ax = plt.subplots(figsize=(6.5, 4))
+x = np.linspace(0, 1, 33)
+y = -np.sin(x * 2*np.pi)
+ax.plot(x, y, 'o')
+ax.margins(0.5, 0.2)
+ax.set_title("margins(x=0.5, y=0.2)")
+
+# fix the Axes limits so that the following helper drawings
+# cannot change them further.
+ax.set(xlim=ax.get_xlim(), ylim=ax.get_ylim())
+
+
+def arrow(p1, p2, **props):
+ ax.annotate("", p1, p2,
+ arrowprops=dict(arrowstyle="<->", shrinkA=0, shrinkB=0, **props))
+
+
+axmin, axmax = ax.get_xlim()
+aymin, aymax = ax.get_ylim()
+xmin, xmax = x.min(), x.max()
+ymin, ymax = y.min(), y.max()
+
+y0 = -0.8
+ax.axvspan(axmin, xmin, color=("orange", 0.1))
+ax.axvspan(xmax, axmax, color=("orange", 0.1))
+arrow((xmin, y0), (xmax, y0), color="sienna")
+arrow((xmax, y0), (axmax, y0), color="orange")
+ax.text((xmax + axmax)/2, y0+0.05, "x margin\n* x data range",
+ ha="center", va="bottom", color="orange")
+ax.text(0.55, y0+0.1, "x data range", va="bottom", color="sienna")
+
+x0 = 0.1
+ax.axhspan(aymin, ymin, color=("tab:green", 0.1))
+ax.axhspan(ymax, aymax, color=("tab:green", 0.1))
+arrow((x0, ymin), (x0, ymax), color="darkgreen")
+arrow((x0, ymax), (x0, aymax), color="tab:green")
+ax.text(x0, (ymax + aymax) / 2, " y margin * y data range",
+ va="center", color="tab:green")
+ax.text(x0, 0.5, " y data range", color="darkgreen")
diff --git a/doc/_embedded_plots/figure_subplots_adjust.py b/doc/_embedded_plots/figure_subplots_adjust.py
new file mode 100644
index 000000000000..6f99a3febcdc
--- /dev/null
+++ b/doc/_embedded_plots/figure_subplots_adjust.py
@@ -0,0 +1,34 @@
+import matplotlib.pyplot as plt
+
+
+fig, axs = plt.subplots(2, 2, figsize=(6.5, 4))
+fig.set_facecolor('lightblue')
+fig.subplots_adjust(0.1, 0.1, 0.9, 0.9, 0.4, 0.4)
+
+overlay = fig.add_axes([0, 0, 1, 1], zorder=100)
+overlay.axis("off")
+xycoords='figure fraction'
+arrowprops=dict(arrowstyle="<->", shrinkA=0, shrinkB=0)
+
+for ax in axs.flat:
+ ax.set(xticks=[], yticks=[])
+
+overlay.annotate("", (0, 0.75), (0.1, 0.75),
+ xycoords=xycoords, arrowprops=arrowprops) # left
+overlay.annotate("", (0.435, 0.25), (0.565, 0.25),
+ xycoords=xycoords, arrowprops=arrowprops) # wspace
+overlay.annotate("", (0, 0.8), (0.9, 0.8),
+ xycoords=xycoords, arrowprops=arrowprops) # right
+fig.text(0.05, 0.7, "left", ha="center")
+fig.text(0.5, 0.3, "wspace", ha="center")
+fig.text(0.05, 0.83, "right", ha="center")
+
+overlay.annotate("", (0.75, 0), (0.75, 0.1),
+ xycoords=xycoords, arrowprops=arrowprops) # bottom
+overlay.annotate("", (0.25, 0.435), (0.25, 0.565),
+ xycoords=xycoords, arrowprops=arrowprops) # hspace
+overlay.annotate("", (0.8, 0), (0.8, 0.9),
+ xycoords=xycoords, arrowprops=arrowprops) # top
+fig.text(0.65, 0.05, "bottom", va="center")
+fig.text(0.28, 0.5, "hspace", va="center")
+fig.text(0.82, 0.05, "top", va="center")
diff --git a/doc/_embedded_plots/hatch_classes.py b/doc/_embedded_plots/hatch_classes.py
new file mode 100644
index 000000000000..cb9cd7d4b356
--- /dev/null
+++ b/doc/_embedded_plots/hatch_classes.py
@@ -0,0 +1,28 @@
+import matplotlib.pyplot as plt
+from matplotlib.patches import Rectangle
+
+fig, ax = plt.subplots()
+
+pattern_to_class = {
+ '/': 'NorthEastHatch',
+ '\\': 'SouthEastHatch',
+ '|': 'VerticalHatch',
+ '-': 'HorizontalHatch',
+ '+': 'VerticalHatch + HorizontalHatch',
+ 'x': 'NorthEastHatch + SouthEastHatch',
+ 'o': 'SmallCircles',
+ 'O': 'LargeCircles',
+ '.': 'SmallFilledCircles',
+ '*': 'Stars',
+}
+
+for i, (hatch, classes) in enumerate(pattern_to_class.items()):
+ r = Rectangle((0.1, i+0.5), 0.8, 0.8, fill=False, hatch=hatch*2)
+ ax.add_patch(r)
+ h = ax.annotate(f"'{hatch}'", xy=(1.2, .5), xycoords=r,
+ family='monospace', va='center', ha='left')
+ ax.annotate(pattern_to_class[hatch], xy=(1.5, .5), xycoords=h,
+ family='monospace', va='center', ha='left', color='tab:blue')
+
+ax.set(xlim=(0, 5), ylim=(0, i+1.5), yinverted=True)
+ax.set_axis_off()
diff --git a/doc/_static/mpl.css b/doc/_static/mpl.css
index 6f17005a810b..25bad17c3938 100644
--- a/doc/_static/mpl.css
+++ b/doc/_static/mpl.css
@@ -14,29 +14,6 @@
margin: 0;
}
-/* Make announcement an error colour for unreleased documentation, and sticky. */
-#unreleased-message.bd-header-announcement {
- border-bottom: solid var(--pst-color-danger-highlight);
- color: var(--pst-color-danger-text);
- font-weight: var(--pst-admonition-font-weight-heading);
- position: sticky;
- top: 0;
- z-index: 1050;
-}
-
-#unreleased-message.bd-header-announcement:after {
- background-color: var(--pst-color-danger);
- opacity: 1;
-}
-
-#unreleased-message.bd-header-announcement a {
- color: var(--pst-color-danger-text);
-}
-
-#unreleased-message.bd-header-announcement + .bd-navbar {
- top: 3rem; /* Minimum height of announcement header. */
-}
-
/* multi column TOC */
.contents ul {
list-style-type: none;
@@ -85,9 +62,13 @@ html[data-theme="dark"] .sphx-glr-thumbcontainer {
background-color: rgb(63, 63, 63);
}
-/* workaround: the default padding decenters the image inside the frame */
-.sphx-glr-thumbcontainer .figure {
- padding: 0;
+/* Set a fixed height so that lazy loading does not change heights. Without a fixed
+ * height lazy loading of images interferes with anchor links: Clicking a link goes to
+ * a certain position, but then the loaded images add content and move the anchor to a
+ * different position.
+ */
+.sphx-glr-thumbcontainer img {
+ height: 112px;
}
/* hide download buttons in example headers
@@ -186,6 +167,14 @@ div.wide-table table th.stub {
display: inline;
}
+/* sdd is a custom class that strips out styling from dropdowns
+ * Example usage:
+ *
+ * .. dropdown::
+ * :class-container: sdd
+ *
+ */
+
.sdd.sd-dropdown {
box-shadow: none!important;
}
@@ -204,3 +193,30 @@ div.wide-table table th.stub {
.sdd.sd-dropdown .sd-card-header +.sd-card-body{
--pst-sd-dropdown-color: none;
}
+
+/* section-toc is a custom class that removes the page title from a toctree listing
+ * and shifts the resulting list left
+ * Example usage:
+ *
+ * .. rst-class:: section-toc
+ * .. toctree::
+ *
+ */
+ .section-toc.toctree-wrapper .toctree-l1>a{
+ display: none;
+}
+.section-toc.toctree-wrapper .toctree-l1>ul{
+ padding-left: 0;
+}
+
+.sidebar-cheatsheets {
+ margin-bottom: 3em;
+}
+
+.sidebar-cheatsheets > h3 {
+ margin-top: 0;
+}
+
+.sidebar-cheatsheets > img {
+ width: 100%;
+}
diff --git a/doc/_static/switcher.json b/doc/_static/switcher.json
index e5c3abbe5bce..62c8ed756824 100644
--- a/doc/_static/switcher.json
+++ b/doc/_static/switcher.json
@@ -1,18 +1,29 @@
[
{
- "name": "3.8 (stable)",
- "version": "stable",
- "url": "https://matplotlib.org/stable/"
+ "name": "3.10 (stable)",
+ "version": "3.10.3",
+ "url": "https://matplotlib.org/stable/",
+ "preferred": true
},
{
- "name": "3.9 (dev)",
+ "name": "3.11 (dev)",
"version": "dev",
"url": "https://matplotlib.org/devdocs/"
},
+ {
+ "name": "3.9",
+ "version": "3.9.3",
+ "url": "https://matplotlib.org/3.9.3/"
+ },
+ {
+ "name": "3.8",
+ "version": "3.8.4",
+ "url": "https://matplotlib.org/3.8.4/"
+ },
{
"name": "3.7",
- "version": "3.7.3",
- "url": "https://matplotlib.org/3.7.3/"
+ "version": "3.7.5",
+ "url": "https://matplotlib.org/3.7.5/"
},
{
"name": "3.6",
diff --git a/doc/_static/transforms.png b/doc/_static/transforms.png
deleted file mode 100644
index ab07fb575961..000000000000
Binary files a/doc/_static/transforms.png and /dev/null differ
diff --git a/doc/_static/zenodo_cache/10150955.svg b/doc/_static/zenodo_cache/10150955.svg
new file mode 100644
index 000000000000..132bc97ab61d
--- /dev/null
+++ b/doc/_static/zenodo_cache/10150955.svg
@@ -0,0 +1,35 @@
+
\ No newline at end of file
diff --git a/doc/_static/zenodo_cache/10661079.svg b/doc/_static/zenodo_cache/10661079.svg
new file mode 100644
index 000000000000..ac659bcc870f
--- /dev/null
+++ b/doc/_static/zenodo_cache/10661079.svg
@@ -0,0 +1,35 @@
+
\ No newline at end of file
diff --git a/doc/_static/zenodo_cache/10916799.svg b/doc/_static/zenodo_cache/10916799.svg
new file mode 100644
index 000000000000..ca9c0a454251
--- /dev/null
+++ b/doc/_static/zenodo_cache/10916799.svg
@@ -0,0 +1,35 @@
+
\ No newline at end of file
diff --git a/doc/_static/zenodo_cache/11201097.svg b/doc/_static/zenodo_cache/11201097.svg
new file mode 100644
index 000000000000..70f35a7a659f
--- /dev/null
+++ b/doc/_static/zenodo_cache/11201097.svg
@@ -0,0 +1,35 @@
+
\ No newline at end of file
diff --git a/doc/_static/zenodo_cache/12652732.svg b/doc/_static/zenodo_cache/12652732.svg
new file mode 100644
index 000000000000..cde5c5f37839
--- /dev/null
+++ b/doc/_static/zenodo_cache/12652732.svg
@@ -0,0 +1,35 @@
+
\ No newline at end of file
diff --git a/doc/_static/zenodo_cache/13308876.svg b/doc/_static/zenodo_cache/13308876.svg
new file mode 100644
index 000000000000..749bc3c19026
--- /dev/null
+++ b/doc/_static/zenodo_cache/13308876.svg
@@ -0,0 +1,35 @@
+
\ No newline at end of file
diff --git a/doc/_static/zenodo_cache/14249941.svg b/doc/_static/zenodo_cache/14249941.svg
new file mode 100644
index 000000000000..f9165f17fdf0
--- /dev/null
+++ b/doc/_static/zenodo_cache/14249941.svg
@@ -0,0 +1,35 @@
+
\ No newline at end of file
diff --git a/doc/_static/zenodo_cache/14436121.svg b/doc/_static/zenodo_cache/14436121.svg
new file mode 100644
index 000000000000..1e4a7cd5b7a4
--- /dev/null
+++ b/doc/_static/zenodo_cache/14436121.svg
@@ -0,0 +1,35 @@
+
\ No newline at end of file
diff --git a/doc/_static/zenodo_cache/14464227.svg b/doc/_static/zenodo_cache/14464227.svg
new file mode 100644
index 000000000000..7126d239d6a5
--- /dev/null
+++ b/doc/_static/zenodo_cache/14464227.svg
@@ -0,0 +1,35 @@
+
\ No newline at end of file
diff --git a/doc/_templates/autofunctions.rst b/doc/_templates/autofunctions.rst
deleted file mode 100644
index 291b8eee2ede..000000000000
--- a/doc/_templates/autofunctions.rst
+++ /dev/null
@@ -1,22 +0,0 @@
-
-{{ fullname | escape | underline }}
-
-
-.. automodule:: {{ fullname }}
- :no-members:
-
-{% block functions %}
-{% if functions %}
-
-Functions
----------
-
-.. autosummary::
- :template: autosummary.rst
- :toctree:
-
-{% for item in functions %}{% if item not in ['plotting', 'colormaps'] %}
- {{ item }}{% endif %}{% endfor %}
-
-{% endif %}
-{% endblock %}
diff --git a/doc/_templates/automodule.rst b/doc/_templates/automodule.rst
index fef899a38a5e..df3e8283f2f6 100644
--- a/doc/_templates/automodule.rst
+++ b/doc/_templates/automodule.rst
@@ -1,15 +1,5 @@
{{ fullname | escape | underline}}
-{% if fullname in ['mpl_toolkits.axes_grid1.colorbar'] %}
-
-.. To prevent problems with the autosummary for the colorbar doc treat this
- separately (sphinx-doc/sphinx/issues/4874)
-
-.. automodule:: {{ fullname }}
- :members:
-
-{% else %}
-
.. automodule:: {{ fullname }}
:no-members:
:no-inherited-members:
@@ -45,4 +35,3 @@ Functions
{% endif %}
{% endblock %}
-{% endif %}
diff --git a/doc/_templates/cheatsheet_sidebar.html b/doc/_templates/cheatsheet_sidebar.html
index 3f2b7c4f4db1..2ca6548ddd4d 100644
--- a/doc/_templates/cheatsheet_sidebar.html
+++ b/doc/_templates/cheatsheet_sidebar.html
@@ -1,6 +1,6 @@
-
Matplotlib cheatsheets
+
Cheatsheets
diff --git a/doc/api/.gitignore b/doc/api/.gitignore
new file mode 100644
index 000000000000..dbed88d89836
--- /dev/null
+++ b/doc/api/.gitignore
@@ -0,0 +1 @@
+scalarmappable.gen_rst
diff --git a/doc/api/_afm_api.rst b/doc/api/_afm_api.rst
new file mode 100644
index 000000000000..4e2ac4997272
--- /dev/null
+++ b/doc/api/_afm_api.rst
@@ -0,0 +1,8 @@
+*******************
+``matplotlib._afm``
+*******************
+
+.. automodule:: matplotlib._afm
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/doc/api/_docstring_api.rst b/doc/api/_docstring_api.rst
new file mode 100644
index 000000000000..040a3653a87b
--- /dev/null
+++ b/doc/api/_docstring_api.rst
@@ -0,0 +1,8 @@
+*************************
+``matplotlib._docstring``
+*************************
+
+.. automodule:: matplotlib._docstring
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/doc/api/_tight_bbox_api.rst b/doc/api/_tight_bbox_api.rst
new file mode 100644
index 000000000000..826e051fcf6d
--- /dev/null
+++ b/doc/api/_tight_bbox_api.rst
@@ -0,0 +1,8 @@
+**************************
+``matplotlib._tight_bbox``
+**************************
+
+.. automodule:: matplotlib._tight_bbox
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/doc/api/_tight_layout_api.rst b/doc/api/_tight_layout_api.rst
new file mode 100644
index 000000000000..ac4f66f280e1
--- /dev/null
+++ b/doc/api/_tight_layout_api.rst
@@ -0,0 +1,8 @@
+****************************
+``matplotlib._tight_layout``
+****************************
+
+.. automodule:: matplotlib._tight_layout
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/doc/api/_type1font.rst b/doc/api/_type1font.rst
new file mode 100644
index 000000000000..1a9ff2292887
--- /dev/null
+++ b/doc/api/_type1font.rst
@@ -0,0 +1,8 @@
+*************************
+``matplotlib._type1font``
+*************************
+
+.. automodule:: matplotlib._type1font
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/doc/api/afm_api.rst b/doc/api/afm_api.rst
deleted file mode 100644
index bcae04150909..000000000000
--- a/doc/api/afm_api.rst
+++ /dev/null
@@ -1,13 +0,0 @@
-******************
-``matplotlib.afm``
-******************
-
-.. attention::
- This module is considered internal.
-
- Its use is deprecated and it will be removed in a future version.
-
-.. automodule:: matplotlib._afm
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/doc/api/animation_api.rst b/doc/api/animation_api.rst
index df39b5942199..1233b482165d 100644
--- a/doc/api/animation_api.rst
+++ b/doc/api/animation_api.rst
@@ -18,6 +18,9 @@ Animation
The easiest way to make a live animation in Matplotlib is to use one of the
`Animation` classes.
+.. seealso::
+ - :ref:`animations`
+
.. inheritance-diagram:: matplotlib.animation.FuncAnimation matplotlib.animation.ArtistAnimation
:parts: 1
diff --git a/doc/api/axes_api.rst b/doc/api/axes_api.rst
index 8b01a120da5b..4bbcbe081194 100644
--- a/doc/api/axes_api.rst
+++ b/doc/api/axes_api.rst
@@ -28,6 +28,18 @@ The Axes class
Axes
+Attributes
+----------
+
+.. autosummary::
+ :toctree: _as_gen
+ :template: autosummary.rst
+ :nosignatures:
+
+ Axes.viewLim
+ Axes.dataLim
+ Axes.spines
+
Plotting
========
@@ -43,7 +55,6 @@ Basic
Axes.errorbar
Axes.scatter
- Axes.plot_date
Axes.step
Axes.loglog
@@ -251,6 +262,7 @@ Property cycle
Axes.set_prop_cycle
+.. _axes-api-axis:
Axis / limits
=============
@@ -258,11 +270,16 @@ Axis / limits
.. For families of methods of the form {get,set}_{x,y}foo, try to list them in
the order set_xfoo, get_xfoo, set_yfoo, get_yfoo
+Axis access
+-----------
+
.. autosummary::
:toctree: _as_gen
:template: autosummary.rst
:nosignatures:
+ Axes.xaxis
+ Axes.yaxis
Axes.get_xaxis
Axes.get_yaxis
@@ -274,8 +291,12 @@ Axis limits and direction
:template: autosummary.rst
:nosignatures:
+ Axes.set_xinverted
+ Axes.get_xinverted
Axes.invert_xaxis
Axes.xaxis_inverted
+ Axes.set_yinverted
+ Axes.get_yinverted
Axes.invert_yaxis
Axes.yaxis_inverted
@@ -517,6 +538,9 @@ Interactive
Axes.get_navigate_mode
Axes.set_navigate_mode
+ Axes.get_forward_navigation_events
+ Axes.set_forward_navigation_events
+
Axes.start_pan
Axes.drag_pan
Axes.end_pan
@@ -602,5 +626,6 @@ Other
Axes.get_transformed_clip_path_and_affine
Axes.has_data
Axes.set
+ Axes.remove
.. autoclass:: matplotlib.axes.Axes.ArtistList
diff --git a/doc/api/axis_api.rst b/doc/api/axis_api.rst
index a177f82a4a9a..85ba990ffece 100644
--- a/doc/api/axis_api.rst
+++ b/doc/api/axis_api.rst
@@ -73,10 +73,10 @@ Axis Label
:template: autosummary.rst
:nosignatures:
+ Axis.label
Axis.set_label_coords
Axis.set_label_position
Axis.set_label_text
- Axis.get_label
Axis.get_label_position
Axis.get_label_text
@@ -112,6 +112,9 @@ Ticks, tick labels and Offset text
Axis.axis_date
+ Axis.minorticks_off
+ Axis.minorticks_on
+
Data and view intervals
-----------------------
@@ -166,6 +169,8 @@ Units
Axis.convert_units
Axis.set_units
Axis.get_units
+ Axis.set_converter
+ Axis.get_converter
Axis.update_units
@@ -214,6 +219,7 @@ Other
Axis.axes
Axis.limit_range_for_scale
Axis.reset_ticks
+ Axis.set_clip_path
Axis.set_default_intervals
Discouraged
@@ -231,6 +237,8 @@ specify a matching series of labels. Calling ``set_ticks`` makes a
:template: autosummary.rst
:nosignatures:
+ Axis.get_label
+ Axis.set_label
Axis.set_ticks
Axis.set_ticklabels
@@ -260,8 +268,7 @@ specify a matching series of labels. Calling ``set_ticks`` makes a
Tick.get_tick_padding
Tick.get_tickdir
Tick.get_view_interval
- Tick.set_label1
- Tick.set_label2
+ Tick.set_clip_path
Tick.set_pad
Tick.set_url
Tick.update_position
diff --git a/doc/api/backend_registry_api.rst b/doc/api/backend_registry_api.rst
new file mode 100644
index 000000000000..ca184c67d0a2
--- /dev/null
+++ b/doc/api/backend_registry_api.rst
@@ -0,0 +1,8 @@
+********************************
+``matplotlib.backends.registry``
+********************************
+
+.. automodule:: matplotlib.backends.registry
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/doc/api/cm_api.rst b/doc/api/cm_api.rst
index 990d204c2a98..c9509389a2bb 100644
--- a/doc/api/cm_api.rst
+++ b/doc/api/cm_api.rst
@@ -6,3 +6,5 @@
:members:
:undoc-members:
:show-inheritance:
+
+.. include:: scalarmappable.gen_rst
diff --git a/doc/api/collections_api.rst b/doc/api/collections_api.rst
index 2a06c00a2ad1..f2d9cb5226b2 100644
--- a/doc/api/collections_api.rst
+++ b/doc/api/collections_api.rst
@@ -11,3 +11,13 @@
:undoc-members:
:show-inheritance:
:inherited-members:
+
+.. autoclass:: _CollectionWithSizes
+ :no-members:
+ :members: get_sizes, set_sizes
+ :class-doc-from: class
+
+.. autoclass:: _MeshData
+ :no-members:
+ :members: set_array
+ :class-doc-from: class
diff --git a/doc/api/colorizer_api.rst b/doc/api/colorizer_api.rst
new file mode 100644
index 000000000000..e72da5cfb030
--- /dev/null
+++ b/doc/api/colorizer_api.rst
@@ -0,0 +1,9 @@
+************************
+``matplotlib.colorizer``
+************************
+
+.. automodule:: matplotlib.colorizer
+ :members:
+ :undoc-members:
+ :show-inheritance:
+ :private-members: _ColorizerInterface, _ScalarMappable
diff --git a/doc/api/colors_api.rst b/doc/api/colors_api.rst
index 7ed2436d6661..6b02f723d74d 100644
--- a/doc/api/colors_api.rst
+++ b/doc/api/colors_api.rst
@@ -32,8 +32,8 @@ Color norms
SymLogNorm
TwoSlopeNorm
-Colormaps
----------
+Univariate Colormaps
+--------------------
.. autosummary::
:toctree: _as_gen/
@@ -43,6 +43,17 @@ Colormaps
LinearSegmentedColormap
ListedColormap
+Multivariate Colormaps
+----------------------
+
+.. autosummary::
+ :toctree: _as_gen/
+ :template: autosummary.rst
+
+ BivarColormap
+ SegmentedBivarColormap
+ BivarColormapFromImage
+
Other classes
-------------
diff --git a/doc/api/docstring_api.rst b/doc/api/docstring_api.rst
deleted file mode 100644
index 38a73a2e83d1..000000000000
--- a/doc/api/docstring_api.rst
+++ /dev/null
@@ -1,13 +0,0 @@
-************************
-``matplotlib.docstring``
-************************
-
-.. attention::
- This module is considered internal.
-
- Its use is deprecated and it will be removed in a future version.
-
-.. automodule:: matplotlib._docstring
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/doc/api/figure_api.rst b/doc/api/figure_api.rst
index 937020afd8fc..5dd3adbfec9f 100644
--- a/doc/api/figure_api.rst
+++ b/doc/api/figure_api.rst
@@ -71,6 +71,7 @@ Annotating
Figure.align_labels
Figure.align_xlabels
Figure.align_ylabels
+ Figure.align_titles
Figure.autofmt_xdate
@@ -90,7 +91,7 @@ Figure geometry
Figure.get_figwidth
Figure.dpi
Figure.set_dpi
- Figure.set_dpi
+ Figure.get_dpi
Subplot layout
--------------
@@ -264,6 +265,7 @@ Annotating
SubFigure.align_labels
SubFigure.align_xlabels
SubFigure.align_ylabels
+ SubFigure.align_titles
Adding and getting Artists
--------------------------
diff --git a/doc/api/font_manager_api.rst b/doc/api/font_manager_api.rst
index ba1d785ca939..1a1b06da1fa9 100644
--- a/doc/api/font_manager_api.rst
+++ b/doc/api/font_manager_api.rst
@@ -4,6 +4,7 @@
.. automodule:: matplotlib.font_manager
:members:
+ :exclude-members: FontEntry
:undoc-members:
:show-inheritance:
diff --git a/doc/api/index.rst b/doc/api/index.rst
index e55a0ed3c5b2..04c0e279a4fe 100644
--- a/doc/api/index.rst
+++ b/doc/api/index.rst
@@ -79,7 +79,6 @@ Alphabetical list of modules:
:maxdepth: 1
matplotlib_configuration_api.rst
- afm_api.rst
animation_api.rst
artist_api.rst
axes_api.rst
@@ -94,11 +93,11 @@ Alphabetical list of modules:
cm_api.rst
collections_api.rst
colorbar_api.rst
+ colorizer_api.rst
colors_api.rst
container_api.rst
contour_api.rst
dates_api.rst
- docstring_api.rst
dviread.rst
figure_api.rst
font_manager_api.rst
@@ -106,6 +105,7 @@ Alphabetical list of modules:
gridspec_api.rst
hatch_api.rst
image_api.rst
+ inset_api.rst
layout_engine_api.rst
legend_api.rst
legend_handler_api.rst
@@ -126,6 +126,7 @@ Alphabetical list of modules:
sphinxext_mathmpl_api.rst
sphinxext_plot_directive_api.rst
sphinxext_figmpl_directive_api.rst
+ sphinxext_roles.rst
spines_api.rst
style_api.rst
table_api.rst
@@ -133,16 +134,18 @@ Alphabetical list of modules:
text_api.rst
texmanager_api.rst
ticker_api.rst
- tight_bbox_api.rst
- tight_layout_api.rst
transformations.rst
tri_api.rst
- type1font.rst
typing_api.rst
units_api.rst
widgets_api.rst
+ _afm_api.rst
_api_api.rst
+ _docstring_api.rst
_enums_api.rst
+ _type1font.rst
+ _tight_bbox_api.rst
+ _tight_layout_api.rst
toolkits/mplot3d.rst
toolkits/axes_grid1.rst
toolkits/axisartist.rst
diff --git a/doc/api/index_backend_api.rst b/doc/api/index_backend_api.rst
index 6012f71c52a4..66009d86825d 100644
--- a/doc/api/index_backend_api.rst
+++ b/doc/api/index_backend_api.rst
@@ -17,6 +17,7 @@
backend_pdf_api.rst
backend_pgf_api.rst
backend_ps_api.rst
+ backend_registry_api.rst
backend_qt_api.rst
backend_svg_api.rst
backend_tk_api.rst
diff --git a/doc/api/inset_api.rst b/doc/api/inset_api.rst
new file mode 100644
index 000000000000..d8b89a106a7a
--- /dev/null
+++ b/doc/api/inset_api.rst
@@ -0,0 +1,8 @@
+********************
+``matplotlib.inset``
+********************
+
+.. automodule:: matplotlib.inset
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/doc/api/next_api_changes.rst b/doc/api/next_api_changes.rst
index d33c8014f735..9c0630697763 100644
--- a/doc/api/next_api_changes.rst
+++ b/doc/api/next_api_changes.rst
@@ -5,11 +5,40 @@ Next API changes
.. ifconfig:: releaselevel == 'dev'
+ This page lists API changes for the next release.
+
+ Behavior changes
+ ----------------
+
.. toctree::
:glob:
:maxdepth: 1
next_api_changes/behavior/*
+
+ Deprecations
+ ------------
+
+ .. toctree::
+ :glob:
+ :maxdepth: 1
+
next_api_changes/deprecations/*
- next_api_changes/development/*
+
+ Removals
+ --------
+
+ .. toctree::
+ :glob:
+ :maxdepth: 1
+
next_api_changes/removals/*
+
+ Development changes
+ -------------------
+
+ .. toctree::
+ :glob:
+ :maxdepth: 1
+
+ next_api_changes/development/*
diff --git a/doc/api/next_api_changes/README.rst b/doc/api/next_api_changes/README.rst
index 75e70b456eb9..1f40122aa318 100644
--- a/doc/api/next_api_changes/README.rst
+++ b/doc/api/next_api_changes/README.rst
@@ -1,10 +1,18 @@
:orphan:
+.. NOTE TO EDITORS OF THIS FILE
+ This file serves as the README directly available in the file system next to the
+ next_api_changes entries. The content between the ``api-change-guide-*`` markers is
+ additionally included in the documentation page ``doc/devel/api_changes.rst``. Please
+ check that the page builds correctly after changing this file.
+
Adding API change notes
=======================
-API change notes for future releases are collected in
-:file:`next_api_changes`. They are divided into four subdirectories:
+.. api-change-guide-start
+
+API change notes for future releases are collected in :file:`doc/api/next_api_changes/`.
+They are divided into four subdirectories:
- **Deprecations**: Announcements of future changes. Typically, these will
raise a deprecation warning and users of this API should change their code
@@ -31,8 +39,7 @@ A typical entry could look like this::
Please avoid using references in section titles, as it causes links to be
confusing in the table of contents. Instead, ensure that a reference is
-included in the descriptive text.
+included in the descriptive text. Use inline literals (double backticks)
+to denote code objects in the title.
-.. NOTE
- Lines 5-30 of this file are include in :ref:`api_whats_new`;
- therefore, please check the doc build after changing this file.
+.. api-change-guide-end
diff --git a/doc/api/next_api_changes/behavior/26634-TH.rst b/doc/api/next_api_changes/behavior/26634-TH.rst
deleted file mode 100644
index 4961722078d6..000000000000
--- a/doc/api/next_api_changes/behavior/26634-TH.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-``SubplotParams`` has been moved from ``matplotlib.figure`` to ``matplotlib.gridspec``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-It is still importable from ``matplotlib.figure``, so does not require any changes to
-existing code.
diff --git a/doc/api/next_api_changes/behavior/26696-SR.rst b/doc/api/next_api_changes/behavior/26696-SR.rst
deleted file mode 100644
index 231f412e426d..000000000000
--- a/doc/api/next_api_changes/behavior/26696-SR.rst
+++ /dev/null
@@ -1,6 +0,0 @@
-*loc* parameter of ``Cell`` doesn't accept ``None`` anymore
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The default value of the *loc* parameter has been changed from ``None`` to ``right``,
-which already was the default location. The behavior of `.Cell` didn't change when
-called without an explicit *loc* parameter.
diff --git a/doc/api/next_api_changes/behavior/26788-AL.rst b/doc/api/next_api_changes/behavior/26788-AL.rst
deleted file mode 100644
index 14573e870843..000000000000
--- a/doc/api/next_api_changes/behavior/26788-AL.rst
+++ /dev/null
@@ -1,6 +0,0 @@
-``axvspan`` and ``axhspan`` now return ``Rectangle``\s, not ``Polygons``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-This change allows using `~.Axes.axhspan` to draw an annulus on polar axes.
-
-This change also affects other elements built via `~.Axes.axvspan` and
-`~.Axes.axhspan`, such as ``Slider.poly``.
diff --git a/doc/api/next_api_changes/behavior/26902-RP.rst b/doc/api/next_api_changes/behavior/26902-RP.rst
deleted file mode 100644
index 3106de94fbd5..000000000000
--- a/doc/api/next_api_changes/behavior/26902-RP.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-``Line2D``
-~~~~~~~~~~
-
-When creating a Line2D or using `.Line2D.set_xdata` and `.Line2D.set_ydata`,
-passing x/y data as non sequence is now an error.
diff --git a/doc/api/next_api_changes/behavior/26917-AL.rst b/doc/api/next_api_changes/behavior/26917-AL.rst
deleted file mode 100644
index 7872caf3204d..000000000000
--- a/doc/api/next_api_changes/behavior/26917-AL.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-``ContourLabeler.add_label`` now respects *use_clabeltext*
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-... and sets `.Text.set_transform_rotates_text` accordingly.
diff --git a/doc/api/next_api_changes/behavior/27179-KS.rst b/doc/api/next_api_changes/behavior/27179-KS.rst
deleted file mode 100644
index 873cd622bbd4..000000000000
--- a/doc/api/next_api_changes/behavior/27179-KS.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-Default behavior of ``hexbin`` with *C* provided requires at least 1 point
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The behavior changed in 3.8.0 to be inclusive of *mincnt*. However that resulted in
-errors or warnings with some reduction functions, so now the default is to require at
-least 1 point to call the reduction function. This effectively restores the default
-behavior to match that of Matplotlib 3.7 and before.
diff --git a/doc/api/next_api_changes/behavior/27347-GL.rst b/doc/api/next_api_changes/behavior/27347-GL.rst
deleted file mode 100644
index 2cf8f65cd745..000000000000
--- a/doc/api/next_api_changes/behavior/27347-GL.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-ScalarMappables auto-scale their norm when an array is set
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Collections previously deferred auto-scaling of the norm until draw time.
-This has been changed to scale the norm whenever the first array is set
-to align with the docstring and reduce unexpected behavior when
-accessing the norm before drawing.
diff --git a/doc/api/next_api_changes/behavior/28437-CH.rst b/doc/api/next_api_changes/behavior/28437-CH.rst
new file mode 100644
index 000000000000..6121dfec8163
--- /dev/null
+++ b/doc/api/next_api_changes/behavior/28437-CH.rst
@@ -0,0 +1,8 @@
+*alpha* parameter handling on images
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When passing and array to ``imshow(..., alpha=...)``, the parameter was silently ignored
+if the image data was a RGB or RBGA image or if :rc:`interpolation_state`
+resolved to "rbga".
+
+This is now fixed, and the alpha array overwrites any previous transparency information.
diff --git a/doc/api/next_api_changes/behavior/29054-AL.rst b/doc/api/next_api_changes/behavior/29054-AL.rst
new file mode 100644
index 000000000000..3c65e9ae9b78
--- /dev/null
+++ b/doc/api/next_api_changes/behavior/29054-AL.rst
@@ -0,0 +1,11 @@
+Minor log tick labels are set depending on number of major log ticks, not on number of decades spanned
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Previously, by default, on a log-scaled axis, the minor ticks would be
+unlabeled if the axis limits spanned more than one decade. The meaning of the
+``minor_thresholds`` parameter to `.LogFormatter` has been altered so that the
+decision of whether to label the minor ticks is now based on the number of
+major ticks drawn within the axis limits.
+
+For example, for an axis spanning from 4 to 60 (with thus a single major log
+tick, at 10), minor ticks are now labeled, even though the axis spans more than
+one decade.
diff --git a/doc/api/next_api_changes/behavior/29256_IMT.rst b/doc/api/next_api_changes/behavior/29256_IMT.rst
new file mode 100644
index 000000000000..57ec8f68d85c
--- /dev/null
+++ b/doc/api/next_api_changes/behavior/29256_IMT.rst
@@ -0,0 +1,6 @@
+Setting titles of figures using webagg backend
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Previously when using the ``webagg`` backend the title of a figure was set using
+``figure.set_label``. Now it is set using ``figure.canvas.manager.set_window_title``
+which is more consistent with other backends.
diff --git a/doc/api/next_api_changes/behavior/29827-ES.rst b/doc/api/next_api_changes/behavior/29827-ES.rst
new file mode 100644
index 000000000000..d25dfa0c6574
--- /dev/null
+++ b/doc/api/next_api_changes/behavior/29827-ES.rst
@@ -0,0 +1,6 @@
+``matplotlib.testing.check_figures_equal`` defaults to PNG only
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In most cases, checking that figures are equal with `.check_figures_equal` does not
+depend on the file format. Consequently, the *extensions* parameter now defaults to
+``['png']`` instead of ``['png', 'pdf', 'svg']``, reducing default test requirements.
diff --git a/doc/api/next_api_changes/behavior/29832-REC.rst b/doc/api/next_api_changes/behavior/29832-REC.rst
new file mode 100644
index 000000000000..a23b043a823b
--- /dev/null
+++ b/doc/api/next_api_changes/behavior/29832-REC.rst
@@ -0,0 +1,11 @@
+Mixing positional and keyword arguments for ``legend`` handles and labels...
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+... is no longer valid. If passing *handles* and *labels* to ``legend``, they must
+now be passed either both positionally or both as keywords.
+
+Legend labels for ``plot``
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+Previously if a sequence was passed to the *label* parameter of `~.Axes.plot` when
+plotting a single dataset, the sequence was automatically cast to string for the legend
+label. Now, if the sequence length is not one an error is raised. To keep the old
+behavior, cast the sequence to string before passing.
diff --git a/doc/api/next_api_changes/deprecations/26894-AL.rst b/doc/api/next_api_changes/deprecations/26894-AL.rst
deleted file mode 100644
index b156fa843917..000000000000
--- a/doc/api/next_api_changes/deprecations/26894-AL.rst
+++ /dev/null
@@ -1,6 +0,0 @@
-*interval* parameter of ``TimerBase.start``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Setting the timer *interval* while starting it is deprecated. The interval can
-be specified instead in the timer constructor, or by setting the
-``timer.interval`` attribute.
diff --git a/doc/api/next_api_changes/deprecations/26917-AL.rst b/doc/api/next_api_changes/deprecations/26917-AL.rst
deleted file mode 100644
index d3cf16f5c511..000000000000
--- a/doc/api/next_api_changes/deprecations/26917-AL.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-``ContourLabeler.add_label_clabeltext``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-... is deprecated.
diff --git a/doc/api/next_api_changes/deprecations/27088-JK.rst b/doc/api/next_api_changes/deprecations/27088-JK.rst
deleted file mode 100644
index ea7fef5abf64..000000000000
--- a/doc/api/next_api_changes/deprecations/27088-JK.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-Deprecations removed in ``contour``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-``contour.allsegs``, ``contour.allkinds``, and ``contour.find_nearest_contour`` are no
-longer marked for deprecation.
diff --git a/doc/api/next_api_changes/deprecations/27175-AL.rst b/doc/api/next_api_changes/deprecations/27175-AL.rst
deleted file mode 100644
index 3fce05765a59..000000000000
--- a/doc/api/next_api_changes/deprecations/27175-AL.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-Mixing positional and keyword arguments for ``legend`` handles and labels
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-This previously only raised a warning, but is now formally deprecated. If
-passing *handles* and *labels*, they must be passed either both positionally or
-both as keyword.
diff --git a/doc/api/next_api_changes/deprecations/27551-AL.rst b/doc/api/next_api_changes/deprecations/27551-AL.rst
new file mode 100644
index 000000000000..4811f542bd5f
--- /dev/null
+++ b/doc/api/next_api_changes/deprecations/27551-AL.rst
@@ -0,0 +1,4 @@
+``GridFinder.transform_xy`` and ``GridFinder.inv_transform_xy``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+... are deprecated. Directly use the standard transform returned by
+`.GridFinder.get_transform` instead.
diff --git a/doc/api/next_api_changes/deprecations/27972-AL.rst b/doc/api/next_api_changes/deprecations/27972-AL.rst
new file mode 100644
index 000000000000..cf14b24345b5
--- /dev/null
+++ b/doc/api/next_api_changes/deprecations/27972-AL.rst
@@ -0,0 +1,8 @@
+``axes_grid.Grid.ngrids``
+~~~~~~~~~~~~~~~~~~~~~~~~~
+This attribute has been deprecated and renamed ``n_axes``, consistently with
+the new name of the `~.axes_grid.Grid` constructor parameter that allows
+setting the actual number of axes in the grid (the old parameter, ``ngrids``,
+did not actually work since Matplotlib 3.3).
+
+The same change has been made in ``axes_grid.ImageGrid``.
diff --git a/doc/api/next_api_changes/deprecations/27998-TS.rst b/doc/api/next_api_changes/deprecations/27998-TS.rst
new file mode 100644
index 000000000000..ab69b87f0989
--- /dev/null
+++ b/doc/api/next_api_changes/deprecations/27998-TS.rst
@@ -0,0 +1,7 @@
+``violinplot`` and ``violin`` *vert* parameter
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The parameter *vert: bool* has been deprecated on `~.Axes.violinplot` and
+`~.Axes.violin`.
+It will be replaced by *orientation: {"vertical", "horizontal"}* for API
+consistency.
diff --git a/doc/api/next_api_changes/deprecations/28074-TS.rst b/doc/api/next_api_changes/deprecations/28074-TS.rst
new file mode 100644
index 000000000000..6a8b5d4b21b8
--- /dev/null
+++ b/doc/api/next_api_changes/deprecations/28074-TS.rst
@@ -0,0 +1,9 @@
+``boxplot`` and ``bxp`` *vert* parameter, and ``rcParams["boxplot.vertical"]``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The parameter *vert: bool* has been deprecated on `~.Axes.boxplot` and
+`~.Axes.bxp`. It is replaced by *orientation: {"vertical", "horizontal"}*
+for API consistency.
+
+``rcParams["boxplot.vertical"]``, which controlled the orientation of ``boxplot``,
+is deprecated without replacement.
diff --git a/doc/api/next_api_changes/deprecations/29135-TH.rst b/doc/api/next_api_changes/deprecations/29135-TH.rst
new file mode 100644
index 000000000000..e2289a248076
--- /dev/null
+++ b/doc/api/next_api_changes/deprecations/29135-TH.rst
@@ -0,0 +1,5 @@
+Parameter ``ListedColormap(..., N=...)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Passing the parameter *N* to `.ListedColormap` is deprecated.
+Please preprocess the list colors yourself if needed.
diff --git a/doc/api/next_api_changes/deprecations/29529-TH.rst b/doc/api/next_api_changes/deprecations/29529-TH.rst
new file mode 100644
index 000000000000..e396e68c4aa1
--- /dev/null
+++ b/doc/api/next_api_changes/deprecations/29529-TH.rst
@@ -0,0 +1,7 @@
+Capitalization of None in matplotlibrc
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In :file:`matplotlibrc` config files every capitalization of None was
+accepted for denoting the Python constant `None`. This is deprecated. The
+only accepted capitalization is now None, i.e. starting with a capital letter
+and all other letters in lowercase.
diff --git a/doc/api/next_api_changes/deprecations/29817-AL.rst b/doc/api/next_api_changes/deprecations/29817-AL.rst
new file mode 100644
index 000000000000..f3b339ed7c10
--- /dev/null
+++ b/doc/api/next_api_changes/deprecations/29817-AL.rst
@@ -0,0 +1,7 @@
+``DviFont.widths``
+~~~~~~~~~~~~~~~~~~
+... is deprecated with no replacement.
+
+Direct access to ``Tfm``'s ``widths``, ``heights``, ``depths`` dicts
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+... is deprecated; access a glyph's metrics with `.Tfm.get_metrics` instead.
diff --git a/doc/api/next_api_changes/deprecations/29904-tac.rst b/doc/api/next_api_changes/deprecations/29904-tac.rst
new file mode 100644
index 000000000000..8e4f986ffa77
--- /dev/null
+++ b/doc/api/next_api_changes/deprecations/29904-tac.rst
@@ -0,0 +1,16 @@
+
+Increase to minimum supported versions of dependencies
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For Matplotlib 3.11, the :ref:`minimum supported versions ` are
+being bumped:
+
++------------+-----------------+----------------+
+| Dependency | min in mpl3.10 | min in mpl3.11 |
++============+=================+================+
+| Python | 3.10 | 3.11 |
+| NumPy | 1.23 | 1.25 |
++------------+-----------------+----------------+
+
+This is consistent with our :ref:`min_deps_policy` and `SPEC0
+`__
diff --git a/doc/api/next_api_changes/deprecations/30027-AL.rst b/doc/api/next_api_changes/deprecations/30027-AL.rst
new file mode 100644
index 000000000000..ed65d9391371
--- /dev/null
+++ b/doc/api/next_api_changes/deprecations/30027-AL.rst
@@ -0,0 +1,3 @@
+``PdfFile.fontNames``, ``PdfFile.dviFontInfo``, ``PdfFile.type1Descriptors``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+... are deprecated with no replacement.
diff --git a/doc/api/next_api_changes/deprecations/30044-AL.rst b/doc/api/next_api_changes/deprecations/30044-AL.rst
new file mode 100644
index 000000000000..e004d5f2730f
--- /dev/null
+++ b/doc/api/next_api_changes/deprecations/30044-AL.rst
@@ -0,0 +1,12 @@
+``FT2Image``
+~~~~~~~~~~~~
+... is deprecated. Use 2D uint8 ndarrays instead. In particular:
+
+- The ``FT2Image`` constructor took ``width, height`` as separate parameters
+ but the ndarray constructor takes ``(height, width)`` as single tuple
+ parameter.
+- `.FT2Font.draw_glyph_to_bitmap` now (also) takes 2D uint8 arrays as input.
+- ``FT2Image.draw_rect_filled`` should be replaced by directly setting pixel
+ values to black.
+- The ``image`` attribute of the object returned by ``MathTextParser("agg").parse``
+ is now a 2D uint8 array.
diff --git a/doc/api/next_api_changes/development/26849-KS.rst b/doc/api/next_api_changes/development/26849-KS.rst
deleted file mode 100644
index 1a1deda40fca..000000000000
--- a/doc/api/next_api_changes/development/26849-KS.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-Minimum version of setuptools bumped to 64
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-To comply with requirements of ``setuptools_scm``, the minimum version of ``setuptools``
-has been increased from 42 to 64.
diff --git a/doc/api/next_api_changes/development/27012-ES.rst b/doc/api/next_api_changes/development/27012-ES.rst
deleted file mode 100644
index 1bec3e7d91df..000000000000
--- a/doc/api/next_api_changes/development/27012-ES.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-Extensions require C++17
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-Matplotlib now requires a compiler that supports C++17 in order to build its extensions.
-According to `SciPy's analysis
-`_, this
-should be available on all supported platforms.
diff --git a/doc/api/next_api_changes/development/29745-DS.rst b/doc/api/next_api_changes/development/29745-DS.rst
new file mode 100644
index 000000000000..7d9b1c2b143b
--- /dev/null
+++ b/doc/api/next_api_changes/development/29745-DS.rst
@@ -0,0 +1,4 @@
+New minimum version of pyparsing
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The minimum required version of ``pyparsing`` has been updated from 2.3.1 to 3.0.0.
diff --git a/doc/api/next_api_changes/removals/26797-OG.rst b/doc/api/next_api_changes/removals/26797-OG.rst
deleted file mode 100644
index 680f69e01a96..000000000000
--- a/doc/api/next_api_changes/removals/26797-OG.rst
+++ /dev/null
@@ -1,17 +0,0 @@
-``draw_gouraud_triangle``
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-... is removed. Use `~.RendererBase.draw_gouraud_triangles` instead.
-
-A ``draw_gouraud_triangle`` call in a custom `~matplotlib.artist.Artist` can readily be
-replaced as::
-
- self.draw_gouraud_triangles(gc, points.reshape((1, 3, 2)),
- colors.reshape((1, 3, 4)), trans)
-
-A `~.RendererBase.draw_gouraud_triangles` method can be implemented from an
-existing ``draw_gouraud_triangle`` method as::
-
- transform = transform.frozen()
- for tri, col in zip(triangles_array, colors_array):
- self.draw_gouraud_triangle(gc, tri, col, transform)
diff --git a/doc/api/next_api_changes/removals/26798-OG.rst b/doc/api/next_api_changes/removals/26798-OG.rst
deleted file mode 100644
index 0d7d0a11faf2..000000000000
--- a/doc/api/next_api_changes/removals/26798-OG.rst
+++ /dev/null
@@ -1,9 +0,0 @@
-``unit_cube``, ``tunit_cube``, and ``tunit_edges``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-... of `.Axes3D` are removed without replacements.
-
-``axes3d.vvec``, ``axes3d.eye``, ``axes3d.sx``, and ``axes3d.sy``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-... are removed without replacement.
diff --git a/doc/api/next_api_changes/removals/26852-OG.rst b/doc/api/next_api_changes/removals/26852-OG.rst
deleted file mode 100644
index 08ad0105b70a..000000000000
--- a/doc/api/next_api_changes/removals/26852-OG.rst
+++ /dev/null
@@ -1,12 +0,0 @@
-``num2julian``, ``julian2num`` and ``JULIAN_OFFSET``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-... of the `.dates` module are removed without replacements. These were
-undocumented and not exported.
-
-Julian dates in Matplotlib were calculated from a Julian date epoch: ``jdate =
-(date - np.datetime64(EPOCH)) / np.timedelta64(1, 'D')``. Conversely, a Julian
-date was converted to datetime as ``date = np.timedelta64(int(jdate * 24 *
-3600), 's') + np.datetime64(EPOCH)``. Matplotlib was using
-``EPOCH='-4713-11-24T12:00'`` so that 2000-01-01 at 12:00 is 2_451_545.0 (see
-`).
diff --git a/doc/api/next_api_changes/removals/26853-OG.rst b/doc/api/next_api_changes/removals/26853-OG.rst
deleted file mode 100644
index dc5c37e38db5..000000000000
--- a/doc/api/next_api_changes/removals/26853-OG.rst
+++ /dev/null
@@ -1,26 +0,0 @@
-Most arguments to widgets have been made keyword-only
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Passing all but the very few first arguments positionally in the constructors
-of Widgets is now keyword-only. In general, all optional arguments are keyword-only.
-
-``RadioButtons.circles``
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-... is removed. (``RadioButtons`` now draws itself using `~.Axes.scatter`.)
-
-``CheckButtons.rectangles`` and ``CheckButtons.lines``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-``CheckButtons.rectangles`` and ``CheckButtons.lines`` are removed.
-(``CheckButtons`` now draws itself using `~.Axes.scatter`.)
-
-Remove unused parameter *x* to ``TextBox.begin_typing``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-This parameter was unused in the method, but was a required argument.
-
-``MultiCursor.needclear``
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-... is removed.
diff --git a/doc/api/next_api_changes/removals/26871-AG.rst b/doc/api/next_api_changes/removals/26871-AG.rst
deleted file mode 100644
index 9c24ac3215a1..000000000000
--- a/doc/api/next_api_changes/removals/26871-AG.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-``matplotlib.axis.Axis.set_ticklabels``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-... a param was renamed to labels from ticklabels.
diff --git a/doc/api/next_api_changes/removals/26872-AD.rst b/doc/api/next_api_changes/removals/26872-AD.rst
deleted file mode 100644
index 411359813e51..000000000000
--- a/doc/api/next_api_changes/removals/26872-AD.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-``Animation`` attributes
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-The attributes ``repeat`` of `.TimedAnimation` and subclasses and
-``save_count`` of `.FuncAnimation` are considered private and removed.
diff --git a/doc/api/next_api_changes/removals/26874-AG.rst b/doc/api/next_api_changes/removals/26874-AG.rst
deleted file mode 100644
index ad305cf9d96c..000000000000
--- a/doc/api/next_api_changes/removals/26874-AG.rst
+++ /dev/null
@@ -1,4 +0,0 @@
-``collections.PolyCollection.span_where`` and ``collections.BrokenBarHCollection``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-... removed as it was deprecated during 3.7. Use ``fill_between`` instead
diff --git a/doc/api/next_api_changes/removals/26885-AD.rst b/doc/api/next_api_changes/removals/26885-AD.rst
deleted file mode 100644
index c617f10d07ed..000000000000
--- a/doc/api/next_api_changes/removals/26885-AD.rst
+++ /dev/null
@@ -1,4 +0,0 @@
-``raw`` parameter
-~~~~~~~~~~~~~~~~~
-
-... of `.GridSpecBase.get_grid_positions` is removed without replacements.
diff --git a/doc/api/next_api_changes/removals/26889-GC.rst b/doc/api/next_api_changes/removals/26889-GC.rst
deleted file mode 100644
index 2cccc9fee113..000000000000
--- a/doc/api/next_api_changes/removals/26889-GC.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-Removing Deprecated API SimpleEvent
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-``matplotlib.patches.ConnectionStyle._Base.SimpleEvent``
diff --git a/doc/api/next_api_changes/removals/26900-jf.rst b/doc/api/next_api_changes/removals/26900-jf.rst
deleted file mode 100644
index 5f14c1543ad8..000000000000
--- a/doc/api/next_api_changes/removals/26900-jf.rst
+++ /dev/null
@@ -1,4 +0,0 @@
-``passthru_pt``
-~~~~~~~~~~~~~~~
-
-This attribute of ``AxisArtistHelper``\s has been removed.
diff --git a/doc/api/next_api_changes/removals/26907-DCH.rst b/doc/api/next_api_changes/removals/26907-DCH.rst
deleted file mode 100644
index 889743ba9cb0..000000000000
--- a/doc/api/next_api_changes/removals/26907-DCH.rst
+++ /dev/null
@@ -1,14 +0,0 @@
-``contour.ClabelText`` and ``ContourLabeler.set_label_props``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-... are removed.
-
-Use ``Text(..., transform_rotates_text=True)`` as a replacement for
-``contour.ClabelText(...)`` and ``text.set(text=text, color=color,
-fontproperties=labeler.labelFontProps, clip_box=labeler.axes.bbox)`` as a
-replacement for the ``ContourLabeler.set_label_props(label, text, color)``.
-
-``ContourLabeler`` attributes
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The ``labelFontProps``, ``labelFontSizeList``, and ``labelTextsList``
-attributes of `.ContourLabeler` have been removed. Use the ``labelTexts``
-attribute and the font properties of the corresponding text objects instead.
diff --git a/doc/api/next_api_changes/removals/26909-VV.rst b/doc/api/next_api_changes/removals/26909-VV.rst
deleted file mode 100644
index bdb815eed322..000000000000
--- a/doc/api/next_api_changes/removals/26909-VV.rst
+++ /dev/null
@@ -1,4 +0,0 @@
-``matplotlib.tri`` submodules are removed
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The ``matplotlib.tri.*`` submodules are removed. All functionality is
-available in ``matplotlib.tri`` directly and should be imported from there.
diff --git a/doc/api/next_api_changes/removals/26910-JP.rst b/doc/api/next_api_changes/removals/26910-JP.rst
deleted file mode 100644
index 0de12cd89ad5..000000000000
--- a/doc/api/next_api_changes/removals/26910-JP.rst
+++ /dev/null
@@ -1,13 +0,0 @@
-``offsetbox.bbox_artist``
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-... is removed. This was just a wrapper to call `.patches.bbox_artist` if a flag is set in the file, so use that directly if you need the behavior.
-
-``offsetBox.get_extent_offsets`` and ``offsetBox.get_extent``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-... are removed; these methods are also removed on all subclasses of `.OffsetBox`.
-
-... To get the offsetbox extents, instead of ``get_extent``, use `.OffsetBox.get_bbox`, which directly returns a `.Bbox` instance.
-
-... To also get the child offsets, instead of ``get_extent_offsets``, separately call `~.OffsetBox.get_offset` on each children after triggering a draw.
diff --git a/doc/api/next_api_changes/removals/26918-EW.rst b/doc/api/next_api_changes/removals/26918-EW.rst
deleted file mode 100644
index 454f35d5e200..000000000000
--- a/doc/api/next_api_changes/removals/26918-EW.rst
+++ /dev/null
@@ -1,3 +0,0 @@
-``Quiver.quiver_doc`` and ``Barbs.barbs_doc``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-... are removed. These are the doc-string and should not be accessible as a named class member.
diff --git a/doc/api/next_api_changes/removals/26962-IA.rst b/doc/api/next_api_changes/removals/26962-IA.rst
deleted file mode 100644
index ac1ab46944b6..000000000000
--- a/doc/api/next_api_changes/removals/26962-IA.rst
+++ /dev/null
@@ -1,19 +0,0 @@
-Deprecated Classes Removed
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The following deprecated classes from version 3.7 have been removed:
-
-- ``matplotlib.backends.backend_ps.PsBackendHelper``
-- ``matplotlib.backends.backend_webagg.ServerThread``
-
-These classes were previously marked as deprecated and have now been removed in accordance with the deprecation cycle.
-
-Deprecated C++ Methods Removed
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The following deprecated C++ methods from :file:`src/_backend_agg_wrapper.cpp`, deprecated since version 3.7, have also been removed:
-
-- ``PyBufferRegion_to_string``
-- ``PyBufferRegion_to_string_argb``
-
-These methods were previously marked as deprecated and have now been removed.
diff --git a/doc/api/next_api_changes/removals/27095-AL.rst b/doc/api/next_api_changes/removals/27095-AL.rst
deleted file mode 100644
index 7b8e5981ca79..000000000000
--- a/doc/api/next_api_changes/removals/27095-AL.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-Inconsistent *nth_coord* and *loc* passed to ``_FixedAxisArtistHelperBase``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The value of the *nth_coord* parameter of ``_FixedAxisArtistHelperBase`` and
-its subclasses is now inferred from the value of *loc*; passing inconsistent
-values (e.g., requesting a "top y axis" or a "left x axis") has no more effect.
diff --git a/doc/api/next_api_changes/removals/29697-REC.rst b/doc/api/next_api_changes/removals/29697-REC.rst
new file mode 100644
index 000000000000..0155578f0c21
--- /dev/null
+++ b/doc/api/next_api_changes/removals/29697-REC.rst
@@ -0,0 +1,10 @@
+``plot_date``
+~~~~~~~~~~~~~
+
+Use of ``plot_date`` has been discouraged since Matplotlib 3.5 and deprecated
+since 3.9. The ``plot_date`` function has now been removed.
+
+- ``datetime``-like data should directly be plotted using `~.Axes.plot`.
+- If you need to plot plain numeric data as :ref:`date-format` or need to set
+ a timezone, call ``ax.xaxis.axis_date`` / ``ax.yaxis.axis_date`` before
+ `~.Axes.plot`. See `.Axis.axis_date`.
diff --git a/doc/api/next_api_changes/removals/30005-DS.rst b/doc/api/next_api_changes/removals/30005-DS.rst
new file mode 100644
index 000000000000..a5ba482c848f
--- /dev/null
+++ b/doc/api/next_api_changes/removals/30005-DS.rst
@@ -0,0 +1,11 @@
+``matplotlib.cm.get_cmap``
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Colormaps are now available through the `.ColormapRegistry` accessible via
+`matplotlib.colormaps` or `matplotlib.pyplot.colormaps`.
+
+If you have the name of a colormap as a string, you can use a direct lookup,
+``matplotlib.colormaps[name]`` or ``matplotlib.pyplot.colormaps[name]`` . Alternatively, ``matplotlib.colormaps.get_cmap`` will
+maintain the existing behavior of additionally passing through `.Colormap` instances
+and converting ``None`` to the default colormap. `matplotlib.pyplot.get_cmap` will stay as a
+shortcut to ``matplotlib.colormaps.get_cmap``.
diff --git a/doc/api/next_api_changes/deprecations/27300-AL.rst b/doc/api/next_api_changes/removals/30014-DS.rst
similarity index 69%
rename from doc/api/next_api_changes/deprecations/27300-AL.rst
rename to doc/api/next_api_changes/removals/30014-DS.rst
index 87f4bb259537..d13737f17e40 100644
--- a/doc/api/next_api_changes/deprecations/27300-AL.rst
+++ b/doc/api/next_api_changes/removals/30014-DS.rst
@@ -1,3 +1,4 @@
``GridHelperCurveLinear.get_tick_iterator``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-... is deprecated with no replacement.
+
+... is removed with no replacement.
diff --git a/doc/api/next_api_changes/deprecations/27095-AL.rst b/doc/api/next_api_changes/removals/30015-DS.rst
similarity index 54%
rename from doc/api/next_api_changes/deprecations/27095-AL.rst
rename to doc/api/next_api_changes/removals/30015-DS.rst
index 2e5b2e1ea5e5..e5f17518a9f3 100644
--- a/doc/api/next_api_changes/deprecations/27095-AL.rst
+++ b/doc/api/next_api_changes/removals/30015-DS.rst
@@ -1,10 +1,9 @@
*nth_coord* parameter to axisartist helpers for fixed axis
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
Helper APIs in `.axisartist` for generating a "fixed" axis on rectilinear axes
-(`.FixedAxisArtistHelperRectilinear`) no longer take a *nth_coord* parameter,
-as that parameter is entirely inferred from the (required) *loc* parameter and
-having inconsistent *nth_coord* and *loc* is an error.
+(`.FixedAxisArtistHelperRectilinear`) no longer take a *nth_coord* parameter.
+That parameter is entirely inferred from the (required) *loc* parameter.
For curvilinear axes, the *nth_coord* parameter remains supported (it affects
-the *ticks*, not the axis position itself), but that parameter will become
-keyword-only, for consistency with the rectilinear case.
+the *ticks*, not the axis position itself), but it is now keyword-only.
diff --git a/doc/api/next_api_changes/deprecations/26960-AL.rst b/doc/api/next_api_changes/removals/xxxxxx-DS.rst
similarity index 51%
rename from doc/api/next_api_changes/deprecations/26960-AL.rst
rename to doc/api/next_api_changes/removals/xxxxxx-DS.rst
index cbde4cbba424..8ae7919afa31 100644
--- a/doc/api/next_api_changes/deprecations/26960-AL.rst
+++ b/doc/api/next_api_changes/removals/xxxxxx-DS.rst
@@ -1,3 +1,4 @@
``backend_ps.get_bbox_header``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-... is deprecated, as it is considered an internal helper.
+
+... is removed, as it is considered an internal helper.
diff --git a/doc/api/prev_api_changes/api_changes_0.99.rst b/doc/api/prev_api_changes/api_changes_0.99.rst
index 5d544eaec7f5..e03face0d075 100644
--- a/doc/api/prev_api_changes/api_changes_0.99.rst
+++ b/doc/api/prev_api_changes/api_changes_0.99.rst
@@ -7,7 +7,7 @@ Changes in 0.99
NumPy arrays.
* User-generated colormaps can now be added to the set recognized
- by :func:`matplotlib.cm.get_cmap`. Colormaps can be made the
+ by ``matplotlib.cm.get_cmap``. Colormaps can be made the
default and applied to the current image using
:func:`matplotlib.pyplot.set_cmap`.
diff --git a/doc/api/prev_api_changes/api_changes_1.3.x.rst b/doc/api/prev_api_changes/api_changes_1.3.x.rst
index 0aeb47815fcc..2601824ba7d1 100644
--- a/doc/api/prev_api_changes/api_changes_1.3.x.rst
+++ b/doc/api/prev_api_changes/api_changes_1.3.x.rst
@@ -7,7 +7,7 @@ API Changes in 1.3.x
Changes in 1.3.1
----------------
-It is rare that we make an API change in a bugfix release, however,
+It is rare that we make an API change in a micro release, however,
for 1.3.1 since 1.3.0 the following change was made:
- ``text.Text.cached`` (used to cache font objects) has been made into a
diff --git a/doc/api/prev_api_changes/api_changes_1.4.x.rst b/doc/api/prev_api_changes/api_changes_1.4.x.rst
index 30f077995e44..915aa28a9f26 100644
--- a/doc/api/prev_api_changes/api_changes_1.4.x.rst
+++ b/doc/api/prev_api_changes/api_changes_1.4.x.rst
@@ -139,7 +139,7 @@ Code changes
``matplotlib.testing.image_util.autocontrast``. These will be removed
completely in v1.5.0.
-* The ``fmt`` argument of :meth:`~matplotlib.axes.Axes.plot_date` has been
+* The ``fmt`` argument of ``Axes.plot_date`` has been
changed from ``bo`` to just ``o``, so color cycling can happen by default.
* Removed the class ``FigureManagerQTAgg`` and deprecated
diff --git a/doc/api/prev_api_changes/api_changes_2.2.0.rst b/doc/api/prev_api_changes/api_changes_2.2.0.rst
index 83369b66f8ab..404d0ca3ba38 100644
--- a/doc/api/prev_api_changes/api_changes_2.2.0.rst
+++ b/doc/api/prev_api_changes/api_changes_2.2.0.rst
@@ -61,7 +61,7 @@ the future, only broadcasting (1 column to *n* columns) will be performed.
rcparams
~~~~~~~~
-The :rc:`backend.qt4` and :rc:`backend.qt5` rcParams were deprecated
+The ``backend.qt4`` and ``backend.qt5`` rcParams were deprecated
in version 2.2. In order to force the use of a specific Qt binding,
either import that binding first, or set the ``QT_API`` environment
variable.
diff --git a/doc/api/prev_api_changes/api_changes_3.1.0.rst b/doc/api/prev_api_changes/api_changes_3.1.0.rst
index 18f25d459200..d5b2a1369cf1 100644
--- a/doc/api/prev_api_changes/api_changes_3.1.0.rst
+++ b/doc/api/prev_api_changes/api_changes_3.1.0.rst
@@ -308,7 +308,7 @@ FreeType or libpng are not in the compiler or linker's default path, set the
standard environment variables ``CFLAGS``/``LDFLAGS`` on Linux or OSX, or
``CL``/``LINK`` on Windows, to indicate the relevant paths.
-See details in :doc:`/users/installing/index`.
+See details in :doc:`/install/index`.
Setting artist properties twice or more in the same call
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -533,7 +533,7 @@ The following miscellaneous API elements have been removed
logger = logging.getLogger('matplotlib')
logger.setLevel(logging.INFO)
# configure log handling: Either include it into your ``logging`` hierarchy,
- # e.g. by configuring a root looger using ``logging.basicConfig()``,
+ # e.g. by configuring a root logger using ``logging.basicConfig()``,
# or add a standalone handler to the matplotlib logger:
logger.addHandler(logging.StreamHandler())
@@ -743,8 +743,8 @@ The following signature related behaviours are deprecated:
`.Axes.annotate()` instead.
- Passing (n, 1)-shaped error arrays to `.Axes.errorbar()`, which was not
documented and did not work for ``n = 2``. Pass a 1D array instead.
-- The *frameon* kwarg to `~.Figure.savefig` and the :rc:`savefig.frameon` rcParam.
- To emulate ``frameon = False``, set *facecolor* to fully
+- The *frameon* keyword argument to `~.Figure.savefig` and the ``savefig.frameon``
+ rcParam. To emulate ``frameon = False``, set *facecolor* to fully
transparent (``"none"``, or ``(0, 0, 0, 0)``).
- Passing a non-1D (typically, (n, 1)-shaped) input to `.Axes.pie`.
Pass a 1D array instead.
diff --git a/doc/api/prev_api_changes/api_changes_3.10.0.rst b/doc/api/prev_api_changes/api_changes_3.10.0.rst
new file mode 100644
index 000000000000..ac4e4e981b21
--- /dev/null
+++ b/doc/api/prev_api_changes/api_changes_3.10.0.rst
@@ -0,0 +1,14 @@
+API Changes for 3.10.0
+======================
+
+.. contents::
+ :local:
+ :depth: 1
+
+.. include:: /api/prev_api_changes/api_changes_3.10.0/behavior.rst
+
+.. include:: /api/prev_api_changes/api_changes_3.10.0/deprecations.rst
+
+.. include:: /api/prev_api_changes/api_changes_3.10.0/removals.rst
+
+.. include:: /api/prev_api_changes/api_changes_3.10.0/development.rst
diff --git a/doc/api/prev_api_changes/api_changes_3.10.0/behavior.rst b/doc/api/prev_api_changes/api_changes_3.10.0/behavior.rst
new file mode 100644
index 000000000000..ae50371fa7aa
--- /dev/null
+++ b/doc/api/prev_api_changes/api_changes_3.10.0/behavior.rst
@@ -0,0 +1,122 @@
+Behavior Changes
+----------------
+
+
+onselect argument to selector widgets made optional
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The *onselect* argument to `.EllipseSelector`, `.LassoSelector`, `.PolygonSelector`, and
+`.RectangleSelector` is no longer required.
+
+``NavigationToolbar2.save_figure`` now returns filepath of saved figure
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+``NavigationToolbar2.save_figure`` function may return the filename of the saved figure.
+
+If a backend implements this functionality it should return `None`
+in the case where no figure is actually saved (because the user closed the dialog without saving).
+
+If the backend does not or can not implement this functionality (currently the Gtk4 backends
+and webagg backends do not) this method will return ``NavigationToolbar2.UNKNOWN_SAVED_STATUS``.
+
+SVG output: improved reproducibility
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Some SVG-format plots `produced different output on each render `__, even with a static ``svg.hashsalt`` value configured.
+
+The problem was a non-deterministic ID-generation scheme for clip paths; the fix introduces a repeatable, monotonically increasing integer ID scheme as a replacement.
+
+Provided that plots add clip paths themselves in deterministic order, this enables repeatable (a.k.a. reproducible, deterministic) SVG output.
+
+ft2font classes are now final
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ft2font classes `.ft2font.FT2Font`, and `.ft2font.FT2Image` are now final
+and can no longer be subclassed.
+
+``InsetIndicator`` artist
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+`~.Axes.indicate_inset` and `~.Axes.indicate_inset_zoom` now return an instance
+of `~matplotlib.inset.InsetIndicator`. Use the
+`~matplotlib.inset.InsetIndicator.rectangle` and
+`~matplotlib.inset.InsetIndicator.connectors` properties of this artist to
+access the objects that were previously returned directly.
+
+``imshow`` *interpolation_stage* default changed to 'auto'
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The *interpolation_stage* parameter of `~.Axes.imshow` has a new default
+value 'auto'. For images that are up-sampled less than a factor of
+three or down-sampled, image interpolation will occur in 'rgba' space. For images
+that are up-sampled by a factor of 3 or more, then image interpolation occurs
+in 'data' space.
+
+The previous default was 'data', so down-sampled images may change subtly with
+the new default. However, the new default also avoids floating point artifacts
+at sharp boundaries in a colormap when down-sampling.
+
+The previous behavior can achieved by setting the *interpolation_stage* parameter
+or :rc:`image.interpolation_stage` to 'data'.
+
+imshow default *interpolation* changed to 'auto'
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The *interpolation* parameter of `~.Axes.imshow` has a new default
+value 'auto', changed from 'antialiased', for consistency with *interpolation_stage*
+and because the interpolation is only anti-aliasing during down-sampling. Passing
+'antialiased' still works, and behaves exactly the same as 'auto', but is discouraged.
+
+dark_background and fivethirtyeight styles no longer set ``savefig.facecolor`` and ``savefig.edgecolor``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When using these styles, :rc:`savefig.facecolor` and :rc:`savefig.edgecolor`
+now inherit the global default value of "auto", which means that the actual
+figure colors will be used. Previously, these rcParams were set to the same
+values as :rc:`figure.facecolor` and :rc:`figure.edgecolor`, i.e. a saved
+figure would always use the theme colors even if the user manually overrode
+them; this is no longer the case.
+
+This change should have no impact for users that do not manually set the figure
+face and edge colors.
+
+Add zorder option in QuiverKey
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+``zorder`` can be used as a keyword argument to `.QuiverKey`. Previously,
+that parameter did not have any effect because the zorder was hard coded.
+
+Subfigures
+~~~~~~~~~~
+
+`.Figure.subfigures` are now added in row-major order to be consistent with
+`.Figure.subplots`. The return value of `~.Figure.subfigures` is not changed,
+but the order of ``fig.subfigs`` is.
+
+(Sub)Figure.get_figure
+~~~~~~~~~~~~~~~~~~~~~~
+
+...in future will by default return the direct parent figure, which may be a SubFigure.
+This will make the default behavior consistent with the
+`~matplotlib.artist.Artist.get_figure` method of other artists. To control the
+behavior, use the newly introduced *root* parameter.
+
+
+``transforms.AffineDeltaTransform`` updates correctly on axis limit changes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Before this change, transform sub-graphs with ``AffineDeltaTransform`` did not update correctly.
+This PR ensures that changes to the child transform are passed through correctly.
+
+The offset string associated with ConciseDateFormatter will now invert when the axis is inverted
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Previously, when the axis was inverted, the offset string associated with ConciseDateFormatter would not change,
+so the offset string indicated the axis was oriented in the wrong direction. Now, when the axis is inverted, the offset
+string is oriented correctly.
+
+``suptitle`` in compressed layout
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Compressed layout now automatically positions the `~.Figure.suptitle` just
+above the top row of axes. To keep this title in its previous position,
+either pass ``in_layout=False`` or explicitly set ``y=0.98`` in the
+`~.Figure.suptitle` call.
diff --git a/doc/api/prev_api_changes/api_changes_3.10.0/deprecations.rst b/doc/api/prev_api_changes/api_changes_3.10.0/deprecations.rst
new file mode 100644
index 000000000000..383c19f3c811
--- /dev/null
+++ b/doc/api/prev_api_changes/api_changes_3.10.0/deprecations.rst
@@ -0,0 +1,169 @@
+Deprecations
+------------
+
+
+Positional parameters in plotting functions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Many plotting functions will restrict positional arguments to the first few parameters
+in the future. All further configuration parameters will have to be passed as keyword
+arguments. This is to enforce better code and and allow for future changes with reduced
+risk of breaking existing code.
+
+Changing ``Figure.number``
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Changing ``Figure.number`` is deprecated. This value is used by `.pyplot`
+to identify figures. It must stay in sync with the pyplot internal state
+and is not intended to be modified by the user.
+
+``PdfFile.hatchPatterns``
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+... is deprecated.
+
+(Sub)Figure.set_figure
+~~~~~~~~~~~~~~~~~~~~~~
+
+...is deprecated and in future will always raise an exception. The parent and
+root figures of a (Sub)Figure are set at instantiation and cannot be changed.
+
+``Poly3DCollection.get_vector``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+... is deprecated with no replacement.
+
+Deprecated ``register`` on ``matplotlib.patches._Styles`` and subclasses
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This class method is never used internally. Due to the internal check in the
+method it only accepts subclasses of a private baseclass embedded in the host
+class which makes it unlikely that it has been used externally.
+
+matplotlib.validate_backend
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+...is deprecated. Please use `matplotlib.rcsetup.validate_backend` instead.
+
+
+matplotlib.sanitize_sequence
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+...is deprecated. Please use `matplotlib.cbook.sanitize_sequence` instead.
+
+ft2font module-level constants replaced by enums
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The `.ft2font`-level constants have been converted to `enum` classes, and all API using
+them now take/return the new types.
+
+The following constants are now part of `.ft2font.Kerning` (without the ``KERNING_``
+prefix):
+
+- ``KERNING_DEFAULT``
+- ``KERNING_UNFITTED``
+- ``KERNING_UNSCALED``
+
+The following constants are now part of `.ft2font.LoadFlags` (without the ``LOAD_``
+prefix):
+
+- ``LOAD_DEFAULT``
+- ``LOAD_NO_SCALE``
+- ``LOAD_NO_HINTING``
+- ``LOAD_RENDER``
+- ``LOAD_NO_BITMAP``
+- ``LOAD_VERTICAL_LAYOUT``
+- ``LOAD_FORCE_AUTOHINT``
+- ``LOAD_CROP_BITMAP``
+- ``LOAD_PEDANTIC``
+- ``LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH``
+- ``LOAD_NO_RECURSE``
+- ``LOAD_IGNORE_TRANSFORM``
+- ``LOAD_MONOCHROME``
+- ``LOAD_LINEAR_DESIGN``
+- ``LOAD_NO_AUTOHINT``
+- ``LOAD_TARGET_NORMAL``
+- ``LOAD_TARGET_LIGHT``
+- ``LOAD_TARGET_MONO``
+- ``LOAD_TARGET_LCD``
+- ``LOAD_TARGET_LCD_V``
+
+The following constants are now part of `.ft2font.FaceFlags`:
+
+- ``EXTERNAL_STREAM``
+- ``FAST_GLYPHS``
+- ``FIXED_SIZES``
+- ``FIXED_WIDTH``
+- ``GLYPH_NAMES``
+- ``HORIZONTAL``
+- ``KERNING``
+- ``MULTIPLE_MASTERS``
+- ``SCALABLE``
+- ``SFNT``
+- ``VERTICAL``
+
+The following constants are now part of `.ft2font.StyleFlags`:
+
+- ``ITALIC``
+- ``BOLD``
+
+FontProperties initialization
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+`.FontProperties` initialization is limited to the two call patterns:
+
+- single positional parameter, interpreted as fontconfig pattern
+- only keyword parameters for setting individual properties
+
+All other previously supported call patterns are deprecated.
+
+``AxLine`` ``xy1`` and ``xy2`` setters
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+These setters now each take a single argument, ``xy1`` or ``xy2`` as a tuple.
+The old form, where ``x`` and ``y`` were passed as separate arguments, is
+deprecated.
+
+Calling ``pyplot.polar()`` with an existing non-polar Axes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This currently plots the data into the non-polar Axes, ignoring
+the "polar" intention. This usage scenario is deprecated and
+will raise an error in the future.
+
+Passing floating-point values to ``RendererAgg.draw_text_image``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Any floating-point values passed to the *x* and *y* parameters were truncated to integers
+silently. This behaviour is now deprecated, and only `int` values should be used.
+
+Passing floating-point values to ``FT2Image``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Any floating-point values passed to the `.FT2Image` constructor, or the *x0*, *y0*, *x1*,
+and *y1* parameters of `.FT2Image.draw_rect_filled` were truncated to integers silently.
+This behaviour is now deprecated, and only `int` values should be used.
+
+``boxplot`` and ``bxp`` *vert* parameter, and ``rcParams["boxplot.vertical"]``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The parameter *vert: bool* has been deprecated on `~.Axes.boxplot` and
+`~.Axes.bxp`. It is replaced by *orientation: {"vertical", "horizontal"}*
+for API consistency.
+
+``rcParams["boxplot.vertical"]``, which controlled the orientation of ``boxplot``,
+is deprecated without replacement.
+
+This deprecation is currently marked as pending and will be fully deprecated in Matplotlib 3.11.
+
+``violinplot`` and ``violin`` *vert* parameter
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The parameter *vert: bool* has been deprecated on `~.Axes.violinplot` and
+`~.Axes.violin`.
+It will be replaced by *orientation: {"vertical", "horizontal"}* for API
+consistency.
+
+This deprecation is currently marked as pending and will be fully deprecated in Matplotlib 3.11.
+
+``proj3d.proj_transform_clip``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+... is deprecated with no replacement.
diff --git a/doc/api/prev_api_changes/api_changes_3.10.0/development.rst b/doc/api/prev_api_changes/api_changes_3.10.0/development.rst
new file mode 100644
index 000000000000..329256b466b5
--- /dev/null
+++ b/doc/api/prev_api_changes/api_changes_3.10.0/development.rst
@@ -0,0 +1,25 @@
+Development changes
+-------------------
+
+Documentation-specific custom Sphinx roles are now semi-public
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For third-party packages that derive types from Matplotlib, our use of custom roles may
+prevent Sphinx from building their docs. These custom Sphinx roles are now public solely
+for the purposes of use within projects that derive from Matplotlib types. See
+:mod:`matplotlib.sphinxext.roles` for details.
+
+Increase to minimum supported versions of dependencies
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For Matplotlib 3.10, the :ref:`minimum supported versions ` are
+being bumped:
+
++------------+-----------------+----------------+
+| Dependency | min in mpl3.9 | min in mpl3.10 |
++============+=================+================+
+| Python | 3.9 | 3.10 |
++------------+-----------------+----------------+
+
+This is consistent with our :ref:`min_deps_policy` and `SPEC0
+`__
diff --git a/doc/api/prev_api_changes/api_changes_3.10.0/removals.rst b/doc/api/prev_api_changes/api_changes_3.10.0/removals.rst
new file mode 100644
index 000000000000..7ed06e7446ef
--- /dev/null
+++ b/doc/api/prev_api_changes/api_changes_3.10.0/removals.rst
@@ -0,0 +1,307 @@
+Removals
+--------
+
+
+ttconv removed
+~~~~~~~~~~~~~~
+
+The ``matplotlib._ttconv`` extension has been removed. Most of its
+functionaliy was already replaced by other code, and the only thing left
+was embedding TTF fonts in PostScript in Type 42 format. This is now
+done in the PS backend using the FontTools library.
+
+Remove hard reference to ``lastevent`` in ``LocationEvent``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+This was previously used to detect exiting from axes, however the hard
+reference would keep closed `.Figure` objects and their children alive longer
+than expected.
+
+``ft2font.FT2Image.draw_rect`` and ``ft2font.FT2Font.get_xys``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+... have been removed as they are unused.
+
+``Tick.set_label``, ``Tick.set_label1`` and ``Tick.set_label2``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+... are removed. Calling these methods from third-party code usually had no
+effect, as the labels are overwritten at draw time by the tick formatter.
+
+
+Functions in ``mpl_toolkits.mplot3d.proj3d``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The function ``transform`` is just an alias for ``proj_transform``,
+use the latter instead.
+
+The following functions were either unused (so no longer required in Matplotlib)
+or considered private.
+
+* ``ortho_transformation``
+* ``persp_transformation``
+* ``proj_points``
+* ``proj_trans_points``
+* ``rot_x``
+* ``rotation_about_vector``
+* ``view_transformation``
+
+
+Arguments other than ``renderer`` to ``get_tightbbox``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+... are keyword-only arguments. This is for consistency and that
+different classes have different additional arguments.
+
+
+Method parameters renamed to match base classes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The only parameter of ``transform_affine`` and ``transform_non_affine`` in ``Transform`` subclasses is renamed
+to *values*.
+
+The *points* parameter of ``transforms.IdentityTransform.transform`` is renamed to *values*.
+
+The *trans* parameter of ``table.Cell.set_transform`` is renamed to *t* consistently with
+`.Artist.set_transform`.
+
+The *clippath* parameters of ``axis.Axis.set_clip_path`` and ``axis.Tick.set_clip_path`` are
+renamed to *path* consistently with `.Artist.set_clip_path`.
+
+The *s* parameter of ``images.NonUniformImage.set_filternorm`` is renamed to *filternorm*
+consistently with ``_ImageBase.set_filternorm``.
+
+The *s* parameter of ``images.NonUniformImage.set_filterrad`` is renamed to *filterrad*
+consistently with ``_ImageBase.set_filterrad``.
+
+The only parameter of ``Annotation.contains`` and ``Legend.contains`` is renamed to *mouseevent*
+consistently with `.Artist.contains`.
+
+Method parameters renamed
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The *p* parameter of ``BboxBase.padded`` is renamed to *w_pad*, consistently with the other parameter, *h_pad*
+
+*numdecs* parameter and attribute of ``LogLocator``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+... are removed without replacement, because they had no effect.
+The ``PolyQuadMesh`` class requires full 2D arrays of values
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Previously, if a masked array was input, the list of polygons within the collection
+would shrink to the size of valid polygons and users were required to keep track of
+which polygons were drawn and call ``set_array()`` with the smaller "compressed"
+array size. Passing the "compressed" and flattened array values will no longer
+work and the full 2D array of values (including the mask) should be passed
+to `.PolyQuadMesh.set_array`.
+``ContourSet.collections``
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+... has been removed. `~.ContourSet` is now implemented as a single
+`~.Collection` of paths, each path corresponding to a contour level, possibly
+including multiple unconnected components.
+
+``ContourSet.antialiased``
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+... has been removed. Use `~.Collection.get_antialiased` or
+`~.Collection.set_antialiased` instead. Note that `~.Collection.get_antialiased`
+returns an array.
+
+``tcolors`` and ``tlinewidths`` attributes of ``ContourSet``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+... have been removed. Use `~.Collection.get_facecolor`, `~.Collection.get_edgecolor`
+or `~.Collection.get_linewidths` instead.
+
+
+``calc_label_rot_and_inline`` method of ``ContourLabeler``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+... has been removed without replacement.
+
+
+``add_label_clabeltext`` method of ``ContourLabeler``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+... has been removed. Use `~.ContourLabeler.add_label` instead.
+Passing extra positional arguments to ``Figure.add_axes``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Positional arguments passed to `.Figure.add_axes` other than a rect or an existing
+``Axes`` were previously ignored, and is now an error.
+
+
+Artists explicitly passed in will no longer be filtered by legend() based on their label
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Previously, artists explicitly passed to ``legend(handles=[...])`` are filtered out if
+their label starts with an underscore. This filter is no longer applied; explicitly
+filter out such artists (``[art for art in artists if not
+art.get_label().startswith('_')]``) if necessary.
+
+Note that if no handles are specified at all, then the default still filters out labels
+starting with an underscore.
+
+
+The parameter of ``Annotation.contains`` and ``Legend.contains`` is renamed to *mouseevent*
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+... consistently with `.Artist.contains`.
+
+
+Support for passing the "frac" key in ``annotate(..., arrowprops={"frac": ...})``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+... has been removed. This key has had no effect since Matplotlib 1.5.
+
+
+Passing non-int or sequence of non-int to ``Table.auto_set_column_width``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Column numbers are ints, and formerly passing any other type was effectively ignored.
+This has now become an error.
+
+
+Widgets
+~~~~~~~
+
+The *visible* attribute getter of ``*Selector`` widgets has been removed; use
+``get_visible`` instead.
+
+
+Auto-closing of figures when switching backend
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Allowable backend switches (i.e. those that do not swap a GUI event loop with another
+one) will not close existing figures. If necessary, call ``plt.close("all")`` before
+switching.
+
+
+``FigureCanvasBase.switch_backends``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+... has been removed with no replacement.
+
+
+Accessing ``event.guiEvent`` after event handlers return
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+... is no longer supported, and ``event.guiEvent`` will be set to None once the event
+handlers return. For some GUI toolkits, it is unsafe to use the event, though you may
+separately stash the object at your own risk.
+
+
+``PdfPages(keep_empty=True)``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A zero-page PDF is not valid, thus passing ``keep_empty=True`` to `.backend_pdf.PdfPages`
+and `.backend_pgf.PdfPages`, and the ``keep_empty`` attribute of these classes, is no
+longer allowed, and empty PDF files will not be created.
+
+Furthermore, `.backend_pdf.PdfPages` no longer immediately creates the target file upon
+instantiation, but only when the first figure is saved. To fully control file creation,
+directly pass an opened file object as argument (``with open(path, "wb") as file,
+PdfPages(file) as pdf: ...``).
+
+
+``backend_ps.psDefs``
+~~~~~~~~~~~~~~~~~~~~~
+
+The ``psDefs`` module-level variable in ``backend_ps`` has been removed with no
+replacement.
+
+
+Automatic papersize selection in PostScript
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Setting :rc:`ps.papersize` to ``'auto'`` or passing ``papersize='auto'`` to
+`.Figure.savefig` is no longer supported. Either pass an explicit paper type name, or
+omit this parameter to use the default from the rcParam.
+
+
+``RendererAgg.tostring_rgb`` and ``FigureCanvasAgg.tostring_rgb``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+... have been remove with no direct replacement. Consider using ``buffer_rgba`` instead,
+which should cover most use cases.
+
+
+``NavigationToolbar2QT.message`` has been removed
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+... with no replacement.
+
+
+``TexManager.texcache``
+~~~~~~~~~~~~~~~~~~~~~~~
+
+... is considered private and has been removed. The location of the cache directory is
+clarified in the doc-string.
+
+
+``cbook`` API changes
+~~~~~~~~~~~~~~~~~~~~~
+
+``cbook.Stack`` has been removed with no replacement.
+
+``Grouper.clean()`` has been removed with no replacement. The Grouper class now cleans
+itself up automatically.
+
+The *np_load* parameter of ``cbook.get_sample_data`` has been removed; `.get_sample_data`
+now auto-loads numpy arrays. Use ``get_sample_data(..., asfileobj=False)`` instead to get
+the filename of the data file, which can then be passed to `open`, if desired.
+
+
+Calling ``paths.get_path_collection_extents`` with empty *offsets*
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Calling `~.get_path_collection_extents` with an empty *offsets* parameter has an
+ambiguous interpretation and is no longer allowed.
+
+
+``bbox.anchored()`` with no explicit container
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Not passing a *container* argument to `.BboxBase.anchored` is no longer supported.
+
+
+``INVALID_NON_AFFINE``, ``INVALID_AFFINE``, ``INVALID`` attributes of ``TransformNode``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+These attributes have been removed.
+
+
+``axes_grid1`` API changes
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+``anchored_artists.AnchoredEllipse`` has been removed. Instead, directly construct an
+`.AnchoredOffsetbox`, an `.AuxTransformBox`, and an `~.patches.Ellipse`, as demonstrated
+in :doc:`/gallery/misc/anchored_artists`.
+
+The ``axes_divider.AxesLocator`` class has been removed. The ``new_locator`` method of
+divider instances now instead returns an opaque callable (which can still be passed to
+``ax.set_axes_locator``).
+
+``axes_divider.Divider.locate`` has been removed; use ``Divider.new_locator(...)(ax,
+renderer)`` instead.
+
+``axes_grid.CbarAxesBase.toggle_label`` has been removed. Instead, use standard methods
+for manipulating colorbar labels (`.Colorbar.set_label`) and tick labels
+(`.Axes.tick_params`).
+
+``inset_location.InsetPosition`` has been removed; use `~.Axes.inset_axes` instead.
+
+
+``axisartist`` API changes
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``axisartist.axes_grid`` and ``axisartist.axes_rgb`` modules, which provide wrappers
+combining the functionality of `.axes_grid1` and `.axisartist`, have been removed;
+directly use e.g. ``AxesGrid(..., axes_class=axislines.Axes)`` instead.
+
+Calling an axisartist Axes to mean `~matplotlib.pyplot.axis` has been removed; explicitly
+call the method instead.
+
+``floating_axes.GridHelperCurveLinear.get_data_boundary`` has been removed. Use
+``grid_finder.extreme_finder(*[None] * 5)`` to get the extremes of the grid.
diff --git a/doc/api/prev_api_changes/api_changes_3.10.1.rst b/doc/api/prev_api_changes/api_changes_3.10.1.rst
new file mode 100644
index 000000000000..26d43ddf8b17
--- /dev/null
+++ b/doc/api/prev_api_changes/api_changes_3.10.1.rst
@@ -0,0 +1,14 @@
+API Changes for 3.10.1
+======================
+
+Behaviour
+---------
+
+*alpha* parameter handling on images
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When passing and array to ``imshow(..., alpha=...)``, the parameter was silently ignored
+if the image data was a RGB or RBGA image or if :rc:`interpolation_state`
+resolved to "rbga".
+
+This is now fixed, and the alpha array overwrites any previous transparency information.
diff --git a/doc/api/prev_api_changes/api_changes_3.2.0/behavior.rst b/doc/api/prev_api_changes/api_changes_3.2.0/behavior.rst
index 407494bdb53f..6c1960c4dfaf 100644
--- a/doc/api/prev_api_changes/api_changes_3.2.0/behavior.rst
+++ b/doc/api/prev_api_changes/api_changes_3.2.0/behavior.rst
@@ -294,10 +294,11 @@ Exception changes
~~~~~~~~~~~~~~~~~
Various APIs that raised a `ValueError` for incorrectly typed inputs now raise
`TypeError` instead: `.backend_bases.GraphicsContextBase.set_clip_path`,
-``blocking_input.BlockingInput.__call__``, `.cm.register_cmap`, `.dviread.DviFont`,
-`.rcsetup.validate_hatch`, ``.rcsetup.validate_animation_writer_path``, `.spines.Spine`,
-many classes in the :mod:`matplotlib.transforms` module and :mod:`matplotlib.tri`
-package, and Axes methods that take a ``norm`` parameter.
+``blocking_input.BlockingInput.__call__``, ``matplotlib.cm.register_cmap``,
+`.dviread.DviFont`, `.rcsetup.validate_hatch`,
+``.rcsetup.validate_animation_writer_path``, `.spines.Spine`, many classes in
+the :mod:`matplotlib.transforms` module and :mod:`matplotlib.tri` package, and
+Axes methods that take a ``norm`` parameter.
If extra kwargs are passed to `.LogScale`, `TypeError` will now be
raised instead of `ValueError`.
diff --git a/doc/api/prev_api_changes/api_changes_3.2.0/removals.rst b/doc/api/prev_api_changes/api_changes_3.2.0/removals.rst
index 8e4c1e81f9ec..53d76d667509 100644
--- a/doc/api/prev_api_changes/api_changes_3.2.0/removals.rst
+++ b/doc/api/prev_api_changes/api_changes_3.2.0/removals.rst
@@ -61,7 +61,7 @@ The following API elements have been removed:
- passing ``(verts, 0)`` or ``(..., 3)`` when specifying a marker to specify a
path or a circle, respectively (instead, use ``verts`` or ``"o"``,
respectively)
-- :rc:`examples.directory`
+- the ``examples.directory`` rcParam
The following members of ``matplotlib.backends.backend_pdf.PdfFile`` were removed:
diff --git a/doc/api/prev_api_changes/api_changes_3.3.0/deprecations.rst b/doc/api/prev_api_changes/api_changes_3.3.0/deprecations.rst
index d9d79adcfbd5..76c43b12aaaa 100644
--- a/doc/api/prev_api_changes/api_changes_3.3.0/deprecations.rst
+++ b/doc/api/prev_api_changes/api_changes_3.3.0/deprecations.rst
@@ -55,7 +55,7 @@ Please pass capstyles ("miter", "round", "bevel") and joinstyles ("butt",
Passing raw data to ``register_cmap()``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Passing raw data via parameters *data* and *lut* to `.register_cmap()` is
+Passing raw data via parameters *data* and *lut* to ``matplotlib.cm.register_cmap()`` is
deprecated. Instead, explicitly create a `.LinearSegmentedColormap` and pass
it via the *cmap* parameter:
``register_cmap(cmap=LinearSegmentedColormap(name, data, lut))``.
@@ -83,8 +83,8 @@ Passing both singular and plural *colors*, *linewidths*, *linestyles* to `.Axes.
Passing e.g. both *linewidth* and *linewidths* will raise a TypeError in the
future.
-Setting :rc:`text.latex.preamble` or :rc:`pdf.preamble` to non-strings
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Setting ``text.latex.preamble`` or ``pdf.preamble`` rcParams to non-strings
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
These rcParams should be set to string values. Support for None (meaning the
empty string) and lists of strings (implicitly joined with newlines) is
deprecated.
@@ -311,7 +311,7 @@ JPEG options
~~~~~~~~~~~~
The *quality*, *optimize*, and *progressive* keyword arguments to
`~.Figure.savefig`, which were only used when saving to JPEG, are deprecated.
-:rc:`savefig.jpeg_quality` is likewise deprecated.
+The ``savefig.jpeg_quality`` rcParam is likewise deprecated.
Such options should now be directly passed to Pillow using
``savefig(..., pil_kwargs={"quality": ..., "optimize": ..., "progressive": ...})``.
diff --git a/doc/api/prev_api_changes/api_changes_3.4.0/behaviour.rst b/doc/api/prev_api_changes/api_changes_3.4.0/behaviour.rst
index df08097dba03..e35301c11986 100644
--- a/doc/api/prev_api_changes/api_changes_3.4.0/behaviour.rst
+++ b/doc/api/prev_api_changes/api_changes_3.4.0/behaviour.rst
@@ -203,7 +203,7 @@ time, not at draw time.
Raise or warn on registering a colormap twice
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When using `matplotlib.cm.register_cmap` to register a user provided or
+When using ``matplotlib.cm.register_cmap`` to register a user provided or
third-party colormap it will now raise a `ValueError` if trying to over-write
one of the built in colormaps and warn if trying to over write a user
registered colormap. This may raise for user-registered colormaps in the
diff --git a/doc/api/prev_api_changes/api_changes_3.5.0/deprecations.rst b/doc/api/prev_api_changes/api_changes_3.5.0/deprecations.rst
index 7bb9009fbe77..05f42035f1ac 100644
--- a/doc/api/prev_api_changes/api_changes_3.5.0/deprecations.rst
+++ b/doc/api/prev_api_changes/api_changes_3.5.0/deprecations.rst
@@ -47,7 +47,7 @@ type. See their documentation for the types they expect.
Discouraged: ``plot_date``
~~~~~~~~~~~~~~~~~~~~~~~~~~
-The use of `~.Axes.plot_date` is discouraged. This method exists for historic
+The use of ``plot_date`` is discouraged. This method exists for historic
reasons and may be deprecated in the future.
- ``datetime``-like data should directly be plotted using `~.Axes.plot`.
@@ -353,7 +353,7 @@ is thus deprecated as well.
To test an installed copy, be sure to specify both ``matplotlib`` and
``mpl_toolkits`` with ``--pyargs``::
- python -m pytest --pyargs matplotlib.tests mpl_toolkits.tests
+ pytest --pyargs matplotlib.tests mpl_toolkits.tests
See :ref:`testing` for more details.
diff --git a/doc/api/prev_api_changes/api_changes_3.5.0/development.rst b/doc/api/prev_api_changes/api_changes_3.5.0/development.rst
index 2db21237a699..b42e6eff3423 100644
--- a/doc/api/prev_api_changes/api_changes_3.5.0/development.rst
+++ b/doc/api/prev_api_changes/api_changes_3.5.0/development.rst
@@ -77,6 +77,6 @@ In order to avoid conflicting with the use of :file:`setup.cfg` by
``setup.cfg`` to ``mplsetup.cfg``. The :file:`setup.cfg.template` has been
correspondingly been renamed to :file:`mplsetup.cfg.template`.
-Note that the path to this configuration file can still be set via the
-:envvar:`MPLSETUPCFG` environment variable, which allows one to keep using the
-same file before and after this change.
+Note that the path to this configuration file can still be set via the ``MPLSETUPCFG``
+environment variable, which allows one to keep using the same file before and after this
+change.
diff --git a/doc/api/prev_api_changes/api_changes_3.5.0/removals.rst b/doc/api/prev_api_changes/api_changes_3.5.0/removals.rst
index 0dcf76cbbe7a..3acab92c3577 100644
--- a/doc/api/prev_api_changes/api_changes_3.5.0/removals.rst
+++ b/doc/api/prev_api_changes/api_changes_3.5.0/removals.rst
@@ -359,7 +359,6 @@ rcParams
- :rc:`axes.axisbelow` no longer accepts strings starting with "line"
(case-insensitive) as "line"; use "line" (case-sensitive) instead.
- - :rc:`text.latex.preamble` and :rc:`pdf.preamble` no longer accept
- non-string values.
+ - :rc:`text.latex.preamble` and ``pdf.preamble`` no longer accept non-string values.
- All ``*.linestyle`` rcParams no longer accept ``offset = None``; set the
offset to 0 instead.
diff --git a/doc/api/prev_api_changes/api_changes_3.6.0/behaviour.rst b/doc/api/prev_api_changes/api_changes_3.6.0/behaviour.rst
index a35584b04961..6ace010515fb 100644
--- a/doc/api/prev_api_changes/api_changes_3.6.0/behaviour.rst
+++ b/doc/api/prev_api_changes/api_changes_3.6.0/behaviour.rst
@@ -4,10 +4,10 @@ Behaviour changes
``plt.get_cmap`` and ``matplotlib.cm.get_cmap`` return a copy
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Formerly, `~.pyplot.get_cmap` and `.cm.get_cmap` returned a global version of a
-`.Colormap`. This was prone to errors as modification of the colormap would
-propagate from one location to another without warning. Now, a new copy of the
-colormap is returned.
+Formerly, `~.pyplot.get_cmap` and ``matplotlib.cm.get_cmap`` returned a global version
+of a `.Colormap`. This was prone to errors as modification of the colormap would
+propagate from one location to another without warning. Now, a new copy of the colormap
+is returned.
Large ``imshow`` images are now downsampled
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -241,7 +241,7 @@ Specified exception types in ``Grid``
In a few cases an `Exception` was thrown when an incorrect argument value was
set in the `mpl_toolkits.axes_grid1.axes_grid.Grid` (=
-`mpl_toolkits.axisartist.axes_grid.Grid`) constructor. These are replaced as
+``mpl_toolkits.axisartist.axes_grid.Grid``) constructor. These are replaced as
follows:
* Providing an incorrect value for *ngrids* now raises a `ValueError`
diff --git a/doc/api/prev_api_changes/api_changes_3.7.0/behaviour.rst b/doc/api/prev_api_changes/api_changes_3.7.0/behaviour.rst
index a4fd8b57e419..2409eb2a5dd0 100644
--- a/doc/api/prev_api_changes/api_changes_3.7.0/behaviour.rst
+++ b/doc/api/prev_api_changes/api_changes_3.7.0/behaviour.rst
@@ -20,10 +20,10 @@ also be based on ``mpl_toolkits.axisartist``. This behavior is consistent with
``plt.get_cmap`` and ``matplotlib.cm.get_cmap`` return a copy
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Formerly, `~.pyplot.get_cmap` and `.cm.get_cmap` returned a global version of a
-`.Colormap`. This was prone to errors as modification of the colormap would
-propagate from one location to another without warning. Now, a new copy of the
-colormap is returned.
+Formerly, `~.pyplot.get_cmap` and ``matplotlib.cm.get_cmap`` returned a global version
+of a `.Colormap`. This was prone to errors as modification of the colormap would
+propagate from one location to another without warning. Now, a new copy of the colormap
+is returned.
``TrapezoidMapTriFinder`` uses different random number generator
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -120,14 +120,13 @@ dtype and *levels* is not specified, *levels* now defaults to ``[0.5]`` for
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This can occur if the user explicitly passes a ``levels`` array with no values
+between ``z.min()`` and ``z.max()``; or if ``z`` has the same value everywhere.
``AxesImage.set_extent`` now raises ``TypeError`` for unknown keyword arguments
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It previously raised a `ValueError`.
-etween ``z.min()`` and ``z.max()``; or if ``z`` has the same value everywhere.
-
Change of ``legend(loc="best")`` behavior
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/doc/api/prev_api_changes/api_changes_3.7.0/deprecations.rst b/doc/api/prev_api_changes/api_changes_3.7.0/deprecations.rst
index dd6d9d8e0894..55a0a7133c65 100644
--- a/doc/api/prev_api_changes/api_changes_3.7.0/deprecations.rst
+++ b/doc/api/prev_api_changes/api_changes_3.7.0/deprecations.rst
@@ -90,7 +90,7 @@ Passing undefined *label_mode* to ``Grid``
... is deprecated. This includes `mpl_toolkits.axes_grid1.axes_grid.Grid`,
`mpl_toolkits.axes_grid1.axes_grid.AxesGrid`, and
`mpl_toolkits.axes_grid1.axes_grid.ImageGrid` as well as the corresponding
-classes imported from `mpl_toolkits.axisartist.axes_grid`.
+classes imported from ``mpl_toolkits.axisartist.axes_grid``.
Pass ``label_mode='keep'`` instead to get the previous behavior of not modifying labels.
diff --git a/doc/api/prev_api_changes/api_changes_3.7.0/removals.rst b/doc/api/prev_api_changes/api_changes_3.7.0/removals.rst
index 76ce9ff71819..03239be31057 100644
--- a/doc/api/prev_api_changes/api_changes_3.7.0/removals.rst
+++ b/doc/api/prev_api_changes/api_changes_3.7.0/removals.rst
@@ -185,7 +185,7 @@ is thus removed as well.
To test an installed copy, be sure to specify both ``matplotlib`` and
``mpl_toolkits`` with ``--pyargs``::
- python -m pytest --pyargs matplotlib.tests mpl_toolkits.tests
+ pytest --pyargs matplotlib.tests mpl_toolkits.tests
See :ref:`testing` for more details.
diff --git a/doc/api/prev_api_changes/api_changes_3.8.0/behaviour.rst b/doc/api/prev_api_changes/api_changes_3.8.0/behaviour.rst
index 3476a05394df..8a21d5b4941e 100644
--- a/doc/api/prev_api_changes/api_changes_3.8.0/behaviour.rst
+++ b/doc/api/prev_api_changes/api_changes_3.8.0/behaviour.rst
@@ -159,10 +159,10 @@ Passing ``None`` as ``rotation_mode`` to `.Text` (the default value) or passing
`.Text.set_rotation_mode` will make `.Text.get_rotation_mode` return ``"default"``
instead of ``None``. The behaviour otherwise is the same.
-PostScript paper type adds option to use figure size
+PostScript paper size adds option to use figure size
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The :rc:`ps.papertype` rcParam can now be set to ``'figure'``, which will use
+The :rc:`ps.papersize` rcParam can now be set to ``'figure'``, which will use
a paper size that corresponds exactly with the size of the figure that is being
saved.
@@ -171,3 +171,22 @@ saved.
Previously, *mincnt* was inclusive with no *C* provided but exclusive when *C* is provided.
It is now inclusive of *mincnt* in both cases.
+
+
+``matplotlib.mpl_toolkits`` is now an implicit namespace package
+----------------------------------------------------------------
+
+Following the deprecation of ``pkg_resources.declare_namespace`` in ``setuptools`` 67.3.0,
+``matplotlib.mpl_toolkits`` is now implemented as an implicit namespace, following
+`PEP 420 `_.
+
+As a consequence using ``pip`` to install a version of Matplotlib >= 3.8 on top
+of a version of Matplotlib < 3.8 (e.g. via ``pip install --local`` or
+``python -m venv --system-site-packages ...``) will fail because the old
+``matplotlib.mpl_toolkits`` files will be found whereas the newer files will be
+found for all other modules. This will result in errors due to the version
+mismatch.
+
+To avoid this issue you need to avoid having multiple versions of Matplotlib
+in different entries of ``sys.path``. Either uninstall Matplotlib
+at the system level or use a more isolated virtual environment.
diff --git a/doc/api/prev_api_changes/api_changes_3.8.0/deprecations.rst b/doc/api/prev_api_changes/api_changes_3.8.0/deprecations.rst
index b442a4af51dc..5398cec623b9 100644
--- a/doc/api/prev_api_changes/api_changes_3.8.0/deprecations.rst
+++ b/doc/api/prev_api_changes/api_changes_3.8.0/deprecations.rst
@@ -153,10 +153,10 @@ The *clippath* parameters of ``axis.Axis.set_clip_path`` and ``axis.Tick.set_cl
renamed to *path* consistently with `.Artist.set_clip_path`.
The *s* parameter of ``images.NonUniformImage.set_filternorm`` is renamed to *filternorm*
-consistently with ```_ImageBase.set_filternorm``.
+consistently with ``_ImageBase.set_filternorm``.
The *s* parameter of ``images.NonUniformImage.set_filterrad`` is renamed to *filterrad*
-consistently with ```_ImageBase.set_filterrad``.
+consistently with ``_ImageBase.set_filterrad``.
*numdecs* parameter and attribute of ``LogLocator``
diff --git a/doc/api/prev_api_changes/api_changes_3.9.0.rst b/doc/api/prev_api_changes/api_changes_3.9.0.rst
new file mode 100644
index 000000000000..8bd2628c90dc
--- /dev/null
+++ b/doc/api/prev_api_changes/api_changes_3.9.0.rst
@@ -0,0 +1,14 @@
+API Changes for 3.9.0
+=====================
+
+.. contents::
+ :local:
+ :depth: 1
+
+.. include:: /api/prev_api_changes/api_changes_3.9.0/behaviour.rst
+
+.. include:: /api/prev_api_changes/api_changes_3.9.0/deprecations.rst
+
+.. include:: /api/prev_api_changes/api_changes_3.9.0/removals.rst
+
+.. include:: /api/prev_api_changes/api_changes_3.9.0/development.rst
diff --git a/doc/api/prev_api_changes/api_changes_3.9.0/behaviour.rst b/doc/api/prev_api_changes/api_changes_3.9.0/behaviour.rst
new file mode 100644
index 000000000000..498dfb766922
--- /dev/null
+++ b/doc/api/prev_api_changes/api_changes_3.9.0/behaviour.rst
@@ -0,0 +1,120 @@
+Behaviour Changes
+-----------------
+
+plot() shorthand format interprets "Cn" (n>9) as a color-cycle color
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Previously, ``plot(..., "-C11")`` would be interpreted as requesting a plot using
+linestyle "-", color "C1" (color #1 of the color cycle), and marker "1" ("tri-down").
+It is now interpreted as requesting linestyle "-" and color "C11" (color #11 of the
+color cycle).
+
+It is recommended to pass ambiguous markers (such as "1") explicitly using the *marker*
+keyword argument. If the shorthand form is desired, such markers can also be
+unambiguously set by putting them *before* the color string.
+
+Legend labels for ``plot``
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Previously if a sequence was passed to the *label* parameter of `~.Axes.plot` when
+plotting a single dataset, the sequence was automatically cast to string for the legend
+label. Now, if the sequence has only one element, that element will be the legend label.
+To keep the old behavior, cast the sequence to string before passing.
+
+Boxplots now ignore masked data points
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+`~matplotlib.axes.Axes.boxplot` and `~matplotlib.cbook.boxplot_stats` now ignore any
+masked points in the input data.
+
+``axhspan`` and ``axvspan`` now return ``Rectangle``\s, not ``Polygon``\s
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This change allows using `~.Axes.axhspan` to draw an annulus on polar axes.
+
+This change also affects other elements built via `~.Axes.axhspan` and `~.Axes.axvspan`,
+such as ``Slider.poly``.
+
+Improved handling of pan/zoom events of overlapping Axes
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The forwarding of pan/zoom events is now determined by the visibility of the
+background-patch (e.g. ``ax.patch.get_visible()``) and by the ``zorder`` of the axes.
+
+- Axes with a visible patch capture the event and do not pass it on to axes below. Only
+ the Axes with the highest ``zorder`` that contains the event is triggered (if there
+ are multiple Axes with the same ``zorder``, the last added Axes counts)
+- Axes with an invisible patch are also invisible to events and they are passed on to
+ the axes below.
+
+To override the default behavior and explicitly set whether an Axes should forward
+navigation events, use `.Axes.set_forward_navigation_events`.
+
+``loc='best'`` for ``legend`` now considers ``Text`` and ``PolyCollections``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The location selection ``legend`` now considers the existence of ``Text`` and
+``PolyCollections`` in the ``badness`` calculation.
+
+Note: The ``best`` option can already be quite slow for plots with large amounts of
+data. For ``PolyCollections``, it only considers the ``Path`` of ``PolyCollections`` and
+not the enclosed area when checking for overlap to reduce additional latency. However,
+it can still be quite slow when there are large amounts of ``PolyCollections`` in the
+plot to check for.
+
+Exception when not passing a Bbox to BboxTransform*-classes
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The exception when not passing a Bbox to BboxTransform*-classes that expect one, e.g.,
+`~matplotlib.transforms.BboxTransform` has changed from ``ValueError`` to ``TypeError``.
+
+*loc* parameter of ``Cell`` no longer accepts ``None``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The default value of the *loc* parameter has been changed from ``None`` to ``right``,
+which already was the default location. The behavior of `.Cell` didn't change when
+called without an explicit *loc* parameter.
+
+``ContourLabeler.add_label`` now respects *use_clabeltext*
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+... and sets `.Text.set_transform_rotates_text` accordingly.
+
+``Line2D``
+^^^^^^^^^^
+
+When creating a Line2D or using `.Line2D.set_xdata` and `.Line2D.set_ydata`,
+passing x/y data as non sequence is now an error.
+
+``ScalarMappable``\s auto-scale their norm when an array is set
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Collections previously deferred auto-scaling of the norm until draw time. This has been
+changed to scale the norm whenever the first array is set to align with the docstring
+and reduce unexpected behavior when accessing the norm before drawing.
+
+``SubplotParams`` moved from ``matplotlib.figure`` to ``matplotlib.gridspec``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+It is still importable from ``matplotlib.figure``, so does not require any changes to
+existing code.
+
+``PowerNorm`` no longer clips values below vmin
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+When ``clip=False`` is set (the default) on `~matplotlib.colors.PowerNorm`, values below
+``vmin`` are now linearly normalised. Previously they were clipped to zero. This fixes
+issues with the display of colorbars associated with a power norm.
+
+Image path semantics of toolmanager-based tools
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Previously, MEP22 ("toolmanager-based") Tools would try to load their icon
+(``tool.image``) relative to the current working directory, or, as a fallback, from
+Matplotlib's own image directory. Because both approaches are problematic for
+third-party tools (the end-user may change the current working directory at any time,
+and third-parties cannot add new icons in Matplotlib's image directory), this behavior
+is deprecated; instead, ``tool.image`` is now interpreted relative to the directory
+containing the source file where the ``Tool.image`` class attribute is defined.
+(Defining ``tool.image`` as an absolute path also works and is compatible with both the
+old and the new semantics.)
diff --git a/doc/api/prev_api_changes/api_changes_3.9.0/deprecations.rst b/doc/api/prev_api_changes/api_changes_3.9.0/deprecations.rst
new file mode 100644
index 000000000000..2cf1df8c9579
--- /dev/null
+++ b/doc/api/prev_api_changes/api_changes_3.9.0/deprecations.rst
@@ -0,0 +1,93 @@
+Deprecations
+------------
+
+``plot_date``
+^^^^^^^^^^^^^
+
+Use of ``plot_date`` has been discouraged since Matplotlib 3.5 and the function is
+now formally deprecated.
+
+- ``datetime``-like data should directly be plotted using `~.Axes.plot`.
+- If you need to plot plain numeric data as :ref:`date-format` or need to set a
+ timezone, call ``ax.xaxis.axis_date`` / ``ax.yaxis.axis_date`` before `~.Axes.plot`.
+ See `.Axis.axis_date`.
+
+Legend labels for ``plot``
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Previously if a sequence was passed to the *label* parameter of `~.Axes.plot` when
+plotting a single dataset, the sequence was automatically cast to string for the legend
+label. This behavior is now deprecated and in future will error if the sequence length
+is not one (consistent with multi-dataset behavior, where the number of elements must
+match the number of datasets). To keep the old behavior, cast the sequence to string
+before passing.
+
+``boxplot`` tick labels
+^^^^^^^^^^^^^^^^^^^^^^^
+
+The parameter *labels* has been renamed to *tick_labels* for clarity and consistency
+with `~.Axes.bar`.
+
+Mixing positional and keyword arguments for ``legend`` handles and labels
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This previously only raised a warning, but is now formally deprecated. If passing
+*handles* and *labels*, they must be passed either both positionally or both as keyword.
+
+Applying theta transforms in ``PolarTransform``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Applying theta transforms in `~matplotlib.projections.polar.PolarTransform` and
+`~matplotlib.projections.polar.InvertedPolarTransform` is deprecated, and will be
+removed in a future version of Matplotlib. This is currently the default behaviour when
+these transforms are used externally, but only takes affect when:
+
+- An axis is associated with the transform.
+- The axis has a non-zero theta offset or has theta values increasing in a clockwise
+ direction.
+
+To silence this warning and adopt future behaviour, set
+``apply_theta_transforms=False``. If you need to retain the behaviour where theta values
+are transformed, chain the ``PolarTransform`` with a `~matplotlib.transforms.Affine2D`
+transform that performs the theta shift and/or sign shift.
+
+*interval* parameter of ``TimerBase.start``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Setting the timer *interval* while starting it is deprecated. The interval can be
+specified instead in the timer constructor, or by setting the ``timer.interval``
+attribute.
+
+*nth_coord* parameter to axisartist helpers for fixed axis
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Helper APIs in `.axisartist` for generating a "fixed" axis on rectilinear axes
+(`.FixedAxisArtistHelperRectilinear`) no longer take a *nth_coord* parameter, as that
+parameter is entirely inferred from the (required) *loc* parameter and having
+inconsistent *nth_coord* and *loc* is an error.
+
+For curvilinear axes, the *nth_coord* parameter remains supported (it affects the
+*ticks*, not the axis position itself), but that parameter will become keyword-only, for
+consistency with the rectilinear case.
+
+``rcsetup.interactive_bk``, ``rcsetup.non_interactive_bk`` and ``rcsetup.all_backends``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+... are deprecated and replaced by ``matplotlib.backends.backend_registry.list_builtin``
+with the following arguments
+
+- ``matplotlib.backends.BackendFilter.INTERACTIVE``
+- ``matplotlib.backends.BackendFilter.NON_INTERACTIVE``
+- ``None``
+
+respectively.
+
+Miscellaneous deprecations
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- ``backend_ps.get_bbox_header`` is considered an internal helper
+- ``BboxTransformToMaxOnly``; if you rely on this, please make a copy of the code
+- ``ContourLabeler.add_label_clabeltext``
+- ``TransformNode.is_bbox``; instead check the object using ``isinstance(...,
+ BboxBase)``
+- ``GridHelperCurveLinear.get_tick_iterator``
diff --git a/doc/api/next_api_changes/development/26621-ES.rst b/doc/api/prev_api_changes/api_changes_3.9.0/development.rst
similarity index 60%
rename from doc/api/next_api_changes/development/26621-ES.rst
rename to doc/api/prev_api_changes/api_changes_3.9.0/development.rst
index ff87f53b3573..c16e8e98ecc4 100644
--- a/doc/api/next_api_changes/development/26621-ES.rst
+++ b/doc/api/prev_api_changes/api_changes_3.9.0/development.rst
@@ -1,5 +1,8 @@
+Development changes
+-------------------
+
Build system ported to Meson
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The build system of Matplotlib has been ported from setuptools to `meson-python
`_ and `Meson `_.
@@ -26,7 +29,7 @@ Consequently, there have been a few changes for development and packaging purpos
may be replaced by passing the following arguments to ``pip``::
- --config-settings=setup-args="-DrcParams-backend=Agg" \
+ --config-settings=setup-args="-DrcParams-backend=Agg"
--config-settings=setup-args="-Dsystem-qhull=true"
Note that you must use ``pip`` >= 23.1 in order to pass more than one setting.
@@ -37,10 +40,45 @@ Consequently, there have been a few changes for development and packaging purpos
`_ if you wish to
change the priority of chosen compilers.
5. Installation of test data was previously controlled by :file:`mplsetup.cfg`, but has
- now been moved to Meson's install tags. To install test data, add the ``tests``
- tag to the requested install (be sure to include the existing tags as below)::
+ now been moved to Meson's install tags. To install test data, add the ``tests`` tag
+ to the requested install (be sure to include the existing tags as below)::
--config-settings=install-args="--tags=data,python-runtime,runtime,tests"
6. Checking typing stubs with ``stubtest`` does not work easily with editable install.
For the time being, we suggest using a normal (non-editable) install if you wish to
run ``stubtest``.
+
+Increase to minimum supported versions of dependencies
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+For Matplotlib 3.9, the :ref:`minimum supported versions ` are being
+bumped:
+
++------------+-----------------+---------------+
+| Dependency | min in mpl3.8 | min in mpl3.9 |
++============+=================+===============+
+| NumPy | 1.21.0 | 1.23.0 |
++------------+-----------------+---------------+
+| setuptools | 42 | 64 |
++------------+-----------------+---------------+
+
+This is consistent with our :ref:`min_deps_policy` and `SPEC 0
+`__.
+
+To comply with requirements of ``setuptools_scm``, the minimum version of ``setuptools``
+has been increased from 42 to 64.
+
+Extensions require C++17
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+Matplotlib now requires a compiler that supports C++17 in order to build its extensions.
+According to `SciPy's analysis
+`_, this
+should be available on all supported platforms.
+
+Windows on ARM64 support
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+Windows on ARM64 now bundles FreeType 2.6.1 instead of 2.11.1 when building from source.
+This may cause small changes to text rendering, but should become consistent with all
+other platforms.
diff --git a/doc/api/prev_api_changes/api_changes_3.9.0/removals.rst b/doc/api/prev_api_changes/api_changes_3.9.0/removals.rst
new file mode 100644
index 000000000000..791c04149981
--- /dev/null
+++ b/doc/api/prev_api_changes/api_changes_3.9.0/removals.rst
@@ -0,0 +1,159 @@
+Removals
+--------
+
+Top-level cmap registration and access functions in ``mpl.cm``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+As part of the `multi-step refactoring of colormap registration
+`_, the following functions have
+been removed:
+
+- ``matplotlib.cm.get_cmap``; use ``matplotlib.colormaps[name]`` instead if you have a
+ `str`.
+
+ Use `matplotlib.cm.ColormapRegistry.get_cmap` if you have a `str`, `None` or a
+ `matplotlib.colors.Colormap` object that you want to convert to a `.Colormap` object.
+- ``matplotlib.cm.register_cmap``; use `matplotlib.colormaps.register
+ <.ColormapRegistry.register>` instead.
+- ``matplotlib.cm.unregister_cmap``; use `matplotlib.colormaps.unregister
+ <.ColormapRegistry.unregister>` instead.
+- ``matplotlib.pyplot.register_cmap``; use `matplotlib.colormaps.register
+ <.ColormapRegistry.register>` instead.
+
+The `matplotlib.pyplot.get_cmap` function will stay available for backward
+compatibility.
+
+Contour labels
+^^^^^^^^^^^^^^
+
+``contour.ClabelText`` and ``ContourLabeler.set_label_props`` are removed. Use
+``Text(..., transform_rotates_text=True)`` as a replacement for
+``contour.ClabelText(...)`` and ``text.set(text=text, color=color,
+fontproperties=labeler.labelFontProps, clip_box=labeler.axes.bbox)`` as a replacement
+for the ``ContourLabeler.set_label_props(label, text, color)``.
+
+The ``labelFontProps``, ``labelFontSizeList``, and ``labelTextsList`` attributes of
+`.ContourLabeler` have been removed. Use the ``labelTexts`` attribute and the font
+properties of the corresponding text objects instead.
+
+``num2julian``, ``julian2num`` and ``JULIAN_OFFSET``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+... of the `.dates` module are removed without replacements. These were undocumented and
+not exported.
+
+Julian dates in Matplotlib were calculated from a Julian date epoch: ``jdate = (date -
+np.datetime64(EPOCH)) / np.timedelta64(1, 'D')``. Conversely, a Julian date was
+converted to datetime as ``date = np.timedelta64(int(jdate * 24 * 3600), 's') +
+np.datetime64(EPOCH)``. Matplotlib was using ``EPOCH='-4713-11-24T12:00'`` so that
+2000-01-01 at 12:00 is 2_451_545.0 (see https://en.wikipedia.org/wiki/Julian_day).
+
+``offsetbox`` methods
+^^^^^^^^^^^^^^^^^^^^^
+
+``offsetbox.bbox_artist`` is removed. This was just a wrapper to call
+`.patches.bbox_artist` if a flag is set in the file, so use that directly if you need
+the behavior.
+
+``OffsetBox.get_extent_offsets`` and ``OffsetBox.get_extent`` are removed; these methods
+are also removed on all subclasses of `.OffsetBox`. To get the offsetbox extents,
+instead of ``get_extent``, use `.OffsetBox.get_bbox`, which directly returns a `.Bbox`
+instance. To also get the child offsets, instead of ``get_extent_offsets``, separately
+call `~.OffsetBox.get_offset` on each children after triggering a draw.
+
+``parse_fontconfig_pattern`` raises on unknown constant names
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Previously, in a fontconfig pattern like ``DejaVu Sans:foo``, the unknown ``foo``
+constant name would be silently ignored. This now raises an error.
+
+``tri`` submodules
+^^^^^^^^^^^^^^^^^^
+
+The ``matplotlib.tri.*`` submodules are removed. All functionality is available in
+``matplotlib.tri`` directly and should be imported from there.
+
+Widget API
+^^^^^^^^^^
+
+- ``CheckButtons.rectangles`` and ``CheckButtons.lines`` are removed; `.CheckButtons`
+ now draws itself using `~.Axes.scatter`.
+- ``RadioButtons.circles`` is removed; `.RadioButtons` now draws itself using
+ `~.Axes.scatter`.
+- ``MultiCursor.needclear`` is removed with no replacement.
+- The unused parameter *x* to ``TextBox.begin_typing`` was a required argument, and is
+ now removed.
+
+Most arguments to widgets have been made keyword-only
+"""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+Passing all but the very few first arguments positionally in the constructors of Widgets
+is now keyword-only. In general, all optional arguments are keyword-only.
+
+``Axes3D`` API
+^^^^^^^^^^^^^^
+
+- ``Axes3D.unit_cube``, ``Axes3D.tunit_cube``, and ``Axes3D.tunit_edges`` are removed
+ without replacement.
+- ``axes3d.vvec``, ``axes3d.eye``, ``axes3d.sx``, and ``axes3d.sy`` are removed without
+ replacement.
+
+Inconsistent *nth_coord* and *loc* passed to ``_FixedAxisArtistHelperBase``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The value of the *nth_coord* parameter of ``_FixedAxisArtistHelperBase`` and its
+subclasses is now inferred from the value of *loc*; passing inconsistent values (e.g.,
+requesting a "top y axis" or a "left x axis") has no more effect.
+
+Passing undefined *label_mode* to ``Grid``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+... is no longer allowed. This includes `mpl_toolkits.axes_grid1.axes_grid.Grid`,
+`mpl_toolkits.axes_grid1.axes_grid.AxesGrid`, and
+`mpl_toolkits.axes_grid1.axes_grid.ImageGrid` as well as the corresponding classes
+imported from ``mpl_toolkits.axisartist.axes_grid``.
+
+Pass ``label_mode='keep'`` instead to get the previous behavior of not modifying labels.
+
+``draw_gouraud_triangle``
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+... is removed. Use `~.RendererBase.draw_gouraud_triangles` instead.
+
+A ``draw_gouraud_triangle`` call in a custom `~matplotlib.artist.Artist` can readily be
+replaced as::
+
+ self.draw_gouraud_triangles(gc, points.reshape((1, 3, 2)),
+ colors.reshape((1, 3, 4)), trans)
+
+A `~.RendererBase.draw_gouraud_triangles` method can be implemented from an
+existing ``draw_gouraud_triangle`` method as::
+
+ transform = transform.frozen()
+ for tri, col in zip(triangles_array, colors_array):
+ self.draw_gouraud_triangle(gc, tri, col, transform)
+
+Miscellaneous removals
+^^^^^^^^^^^^^^^^^^^^^^
+
+The following items have previously been replaced, and are now removed:
+
+- *ticklabels* parameter of ``matplotlib.axis.Axis.set_ticklabels`` has been renamed to
+ *labels*.
+- ``Barbs.barbs_doc`` and ``Quiver.quiver_doc`` are removed. These are the doc-strings
+ and should not be accessible as a named class member, but as normal doc-strings would.
+- ``collections.PolyCollection.span_where`` and ``collections.BrokenBarHCollection``;
+ use ``fill_between`` instead.
+- ``Legend.legendHandles`` was undocumented and has been renamed to ``legend_handles``.
+
+The following items have been removed without replacements:
+
+- The attributes ``repeat`` of `.TimedAnimation` and subclasses and ``save_count`` of
+ `.FuncAnimation` are considered private and removed.
+- ``matplotlib.backend.backend_agg.BufferRegion.to_string``
+- ``matplotlib.backend.backend_agg.BufferRegion.to_string_argb``
+- ``matplotlib.backends.backend_ps.PsBackendHelper``
+- ``matplotlib.backends.backend_webagg.ServerThread``
+- *raw* parameter of `.GridSpecBase.get_grid_positions`
+- ``matplotlib.patches.ConnectionStyle._Base.SimpleEvent``
+- ``passthru_pt`` attribute of ``mpl_toolkits.axisartist.AxisArtistHelper``
diff --git a/doc/api/prev_api_changes/api_changes_3.9.1.rst b/doc/api/prev_api_changes/api_changes_3.9.1.rst
new file mode 100644
index 000000000000..4a9a1fc6669c
--- /dev/null
+++ b/doc/api/prev_api_changes/api_changes_3.9.1.rst
@@ -0,0 +1,13 @@
+API Changes for 3.9.1
+=====================
+
+Development
+-----------
+
+Documentation-specific custom Sphinx roles are now semi-public
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For third-party packages that derive types from Matplotlib, our use of custom roles may
+prevent Sphinx from building their docs. These custom Sphinx roles are now public solely
+for the purposes of use within projects that derive from Matplotlib types. See
+:mod:`matplotlib.sphinxext.roles` for details.
diff --git a/doc/api/prev_api_changes/api_changes_3.9.2.rst b/doc/api/prev_api_changes/api_changes_3.9.2.rst
new file mode 100644
index 000000000000..4c2a69634502
--- /dev/null
+++ b/doc/api/prev_api_changes/api_changes_3.9.2.rst
@@ -0,0 +1,16 @@
+API Changes for 3.9.2
+=====================
+
+Development
+-----------
+
+Windows wheel runtime bundling made static
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In 3.7.0, the MSVC runtime DLL was bundled in wheels to enable importing Matplotlib on
+systems that do not have it installed. However, this could cause inconsistencies with
+other wheels that did the same, and trigger random crashes depending on import order. See
+`this issue `_ for further
+details.
+
+Since 3.9.2, wheels now bundle the MSVC runtime DLL statically to avoid such issues.
diff --git a/doc/api/pyplot_summary.rst b/doc/api/pyplot_summary.rst
index d0def34c4995..cdd57bfe6276 100644
--- a/doc/api/pyplot_summary.rst
+++ b/doc/api/pyplot_summary.rst
@@ -51,7 +51,6 @@ Basic
plot
errorbar
scatter
- plot_date
step
loglog
semilogx
diff --git a/doc/api/scale_api.rst b/doc/api/scale_api.rst
index 1eb890dcfb48..623fbdd0392f 100644
--- a/doc/api/scale_api.rst
+++ b/doc/api/scale_api.rst
@@ -6,3 +6,4 @@
:members:
:undoc-members:
:show-inheritance:
+ :member-order: bysource
diff --git a/doc/api/sphinxext_roles.rst b/doc/api/sphinxext_roles.rst
new file mode 100644
index 000000000000..99959ff05d14
--- /dev/null
+++ b/doc/api/sphinxext_roles.rst
@@ -0,0 +1,7 @@
+==============================
+``matplotlib.sphinxext.roles``
+==============================
+
+.. automodule:: matplotlib.sphinxext.roles
+ :no-undoc-members:
+ :private-members: _rcparam_role, _mpltype_role
diff --git a/doc/api/testing_api.rst b/doc/api/testing_api.rst
index 7731d4510b27..ae81d2f89ca7 100644
--- a/doc/api/testing_api.rst
+++ b/doc/api/testing_api.rst
@@ -37,3 +37,11 @@
:members:
:undoc-members:
:show-inheritance:
+
+
+Testing with optional dependencies
+==================================
+For more information on fixtures, see :external+pytest:ref:`pytest fixtures `.
+
+.. autofunction:: matplotlib.testing.conftest.pd
+.. autofunction:: matplotlib.testing.conftest.xr
diff --git a/doc/api/tight_bbox_api.rst b/doc/api/tight_bbox_api.rst
deleted file mode 100644
index 9e8dd2fa66f9..000000000000
--- a/doc/api/tight_bbox_api.rst
+++ /dev/null
@@ -1,13 +0,0 @@
-*************************
-``matplotlib.tight_bbox``
-*************************
-
-.. attention::
- This module is considered internal.
-
- Its use is deprecated and it will be removed in a future version.
-
-.. automodule:: matplotlib._tight_bbox
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/doc/api/tight_layout_api.rst b/doc/api/tight_layout_api.rst
deleted file mode 100644
index 35f92e3ddced..000000000000
--- a/doc/api/tight_layout_api.rst
+++ /dev/null
@@ -1,13 +0,0 @@
-***************************
-``matplotlib.tight_layout``
-***************************
-
-.. attention::
- This module is considered internal.
-
- Its use is deprecated and it will be removed in a future version.
-
-.. automodule:: matplotlib._tight_layout
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/doc/api/toolkits/axisartist.rst b/doc/api/toolkits/axisartist.rst
index 8cac4d68a266..2dec9cafa01d 100644
--- a/doc/api/toolkits/axisartist.rst
+++ b/doc/api/toolkits/axisartist.rst
@@ -4,7 +4,7 @@
===========================
The *axisartist* namespace provides a derived Axes implementation
-(:class:`mpl_toolkits.axisartist.Axes`), designed to support curvilinear
+(:class:`~mpl_toolkits.axisartist.axislines.Axes`), designed to support curvilinear
grids. The biggest difference is that the artists that are responsible for
drawing axis lines, ticks, ticklabels, and axis labels are separated out from
Matplotlib's Axis class.
@@ -34,8 +34,6 @@ You can find a tutorial describing usage of axisartist at the
axisartist.angle_helper
axisartist.axes_divider
- axisartist.axes_grid
- axisartist.axes_rgb
axisartist.axis_artist
axisartist.axisline_style
axisartist.axislines
diff --git a/doc/api/toolkits/mplot3d.rst b/doc/api/toolkits/mplot3d.rst
index f14918314b97..4810bb742bd2 100644
--- a/doc/api/toolkits/mplot3d.rst
+++ b/doc/api/toolkits/mplot3d.rst
@@ -63,7 +63,7 @@ the toolbar pan and zoom buttons are not used.
===================================
.. note::
- See :attr:`mpl_toolkits.mplot3d.axis3d._axinfo` for a dictionary containing
+ See :attr:`!mpl_toolkits.mplot3d.axis3d._axinfo` for a dictionary containing
constants that may be modified for controlling the look and feel
of mplot3d axes (e.g., label spacing, font colors and panel colors).
Historically, axis3d has suffered from having hard-coded constants
@@ -118,12 +118,6 @@ the toolbar pan and zoom buttons are not used.
:template: autosummary.rst
proj3d.inv_transform
- proj3d.persp_transformation
- proj3d.proj_points
- proj3d.proj_trans_points
proj3d.proj_transform
proj3d.proj_transform_clip
- proj3d.rot_x
- proj3d.transform
- proj3d.view_transformation
proj3d.world_transformation
diff --git a/doc/api/toolkits/mplot3d/axes3d.rst b/doc/api/toolkits/mplot3d/axes3d.rst
index 877e47b7e93a..612b3dd82a4b 100644
--- a/doc/api/toolkits/mplot3d/axes3d.rst
+++ b/doc/api/toolkits/mplot3d/axes3d.rst
@@ -30,6 +30,7 @@ Plotting
plot_surface
plot_wireframe
plot_trisurf
+ fill_between
clabel
contour
@@ -98,10 +99,16 @@ Axis limits and direction
get_zlim
set_zlim
get_w_lims
+ get_xinverted
+ set_xinverted
invert_xaxis
xaxis_inverted
+ get_yinverted
+ set_yinverted
invert_yaxis
yaxis_inverted
+ get_zinverted
+ set_zinverted
invert_zaxis
zaxis_inverted
get_xbound
diff --git a/doc/api/toolkits/mplot3d/view_angles.rst b/doc/api/toolkits/mplot3d/view_angles.rst
index 10d4fac39e8c..75b24ba9c7b0 100644
--- a/doc/api/toolkits/mplot3d/view_angles.rst
+++ b/doc/api/toolkits/mplot3d/view_angles.rst
@@ -12,8 +12,8 @@ The position of the viewport "camera" in a 3D plot is defined by three angles:
points towards the center of the plot box volume. The angle direction is a
common convention, and is shared with
`PyVista `_ and
-`MATLAB `_
-(though MATLAB lacks a roll angle). Note that a positive roll angle rotates the
+`MATLAB `_.
+Note that a positive roll angle rotates the
viewing plane clockwise, so the 3d axes will appear to rotate
counter-clockwise.
@@ -21,8 +21,8 @@ counter-clockwise.
:align: center
:scale: 50
-Rotating the plot using the mouse will control only the azimuth and elevation,
-but all three angles can be set programmatically::
+Rotating the plot using the mouse will control azimuth, elevation,
+as well as roll, and all three angles can be set programmatically::
import matplotlib.pyplot as plt
ax = plt.figure().add_subplot(projection='3d')
@@ -38,3 +38,168 @@ further documented in the `.mplot3d.axes3d.Axes3D.view_init` API.
.. plot:: gallery/mplot3d/view_planes_3d.py
:align: center
+
+
+.. _toolkit_mouse-rotation:
+
+Rotation with mouse
+===================
+
+3D plots can be reoriented by dragging the mouse.
+There are various ways to accomplish this; the style of mouse rotation
+can be specified by setting :rc:`axes3d.mouserotationstyle`, see
+:doc:`/users/explain/customizing`.
+
+Prior to v3.10, the 2D mouse position corresponded directly
+to azimuth and elevation; this is also how it is done
+in `MATLAB `_.
+To keep it this way, set ``mouserotationstyle: azel``.
+This approach works fine for spherical coordinate plots, where the *z* axis is special;
+however, it leads to a kind of 'gimbal lock' when looking down the *z* axis:
+the plot reacts differently to mouse movement, dependent on the particular
+orientation at hand. Also, 'roll' cannot be controlled.
+
+As an alternative, there are various mouse rotation styles where the mouse
+manipulates a virtual 'trackball'. In its simplest form (``mouserotationstyle: trackball``),
+the trackball rotates around an in-plane axis perpendicular to the mouse motion
+(it is as if there is a plate laying on the trackball; the plate itself is fixed
+in orientation, but you can drag the plate with the mouse, thus rotating the ball).
+This is more natural to work with than the ``azel`` style; however,
+the plot cannot be easily rotated around the viewing direction - one has to
+move the mouse in circles with a handedness opposite to the desired rotation,
+counterintuitively.
+
+A different variety of trackball rotates along the shortest arc on the virtual
+sphere (``mouserotationstyle: sphere``). Rotating around the viewing direction
+is straightforward with it: grab the ball near its edge instead of near the center.
+
+Ken Shoemake's ARCBALL [Shoemake1992]_ is also available (``mouserotationstyle: Shoemake``);
+it resembles the ``sphere`` style, but is free of hysteresis,
+i.e., returning mouse to the original position
+returns the figure to its original orientation; the rotation is independent
+of the details of the path the mouse took, which could be desirable.
+However, Shoemake's arcball rotates at twice the angular rate of the
+mouse movement (it is quite noticeable, especially when adjusting roll),
+and it lacks an obvious mechanical equivalent; arguably, the path-independent
+rotation is not natural (however convenient), it could take some getting used to.
+So it is a trade-off.
+
+Henriksen et al. [Henriksen2002]_ provide an overview. In summary:
+
+.. list-table::
+ :width: 100%
+ :widths: 30 20 20 20 20 35
+
+ * - Style
+ - traditional [1]_
+ - incl. roll [2]_
+ - uniform [3]_
+ - path independent [4]_
+ - mechanical counterpart [5]_
+ * - azel
+ - ✔️
+ - ❌
+ - ❌
+ - ✔️
+ - ✔️
+ * - trackball
+ - ❌
+ - ✓ [6]_
+ - ✔️
+ - ❌
+ - ✔️
+ * - sphere
+ - ❌
+ - ✔️
+ - ✔️
+ - ❌
+ - ✔️
+ * - arcball
+ - ❌
+ - ✔️
+ - ✔️
+ - ✔️
+ - ❌
+
+
+.. [1] The way it was prior to v3.10; this is also MATLAB's style
+.. [2] Mouse controls roll too (not only azimuth and elevation)
+.. [3] Figure reacts the same way to mouse movements, regardless of orientation (no difference between 'poles' and 'equator')
+.. [4] Returning mouse to original position returns figure to original orientation (rotation is independent of the details of the path the mouse took)
+.. [5] The style has a corresponding natural implementation as a mechanical device
+.. [6] While it is possible to control roll with the ``trackball`` style, this is not immediately obvious (it requires moving the mouse in large circles) and a bit counterintuitive (the resulting roll is in the opposite direction)
+
+You can try out one of the various mouse rotation styles using:
+
+.. code::
+
+ import matplotlib as mpl
+ mpl.rcParams['axes3d.mouserotationstyle'] = 'trackball' # 'azel', 'trackball', 'sphere', or 'arcball'
+
+ import numpy as np
+ import matplotlib.pyplot as plt
+ from matplotlib import cm
+
+ ax = plt.figure().add_subplot(projection='3d')
+
+ X = np.arange(-5, 5, 0.25)
+ Y = np.arange(-5, 5, 0.25)
+ X, Y = np.meshgrid(X, Y)
+ R = np.sqrt(X**2 + Y**2)
+ Z = np.sin(R)
+
+ surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm,
+ linewidth=0, antialiased=False)
+
+ plt.show()
+
+Alternatively, create a file ``matplotlibrc``, with contents::
+
+ axes3d.mouserotationstyle: trackball
+
+(or any of the other styles, instead of ``trackball``), and then run any of
+the :ref:`mplot3d-examples-index` examples.
+
+The size of the virtual trackball, sphere, or arcball can be adjusted
+by setting :rc:`axes3d.trackballsize`. This specifies how much
+mouse motion is needed to obtain a given rotation angle (when near the center),
+and it controls where the edge of the sphere or arcball is (how far from
+the center, hence how close to the plot edge).
+The size is specified in units of the Axes bounding box,
+i.e., to make the arcball span the whole bounding box, set it to 1.
+A size of about 2/3 appears to work reasonably well; this is the default.
+
+Both arcballs (``mouserotationstyle: sphere`` and
+``mouserotationstyle: arcball``) have a noticeable edge; the edge can be made
+less abrupt by specifying a border width, :rc:`axes3d.trackballborder`.
+This works somewhat like Gavin Bell's arcball, which was
+originally written for OpenGL [Bell1988]_, and is used in Blender and Meshlab.
+Bell's arcball extends the arcball's spherical control surface with a hyperbola;
+the two are smoothly joined. However, the hyperbola extends all the way beyond
+the edge of the plot. In the mplot3d sphere and arcball style, the border extends
+to a radius ``trackballsize/2 + trackballborder``.
+Beyond the border, the style works like the original: it controls roll only.
+A border width of about 0.2 appears to work well; this is the default.
+To obtain the original Shoemake's arcball with a sharp border,
+set the border width to 0.
+For an extended border similar to Bell's arcball, where the transition from
+the arcball to the border occurs at 45°, set the border width to
+:math:`\sqrt 2 \approx 1.414`.
+The border is a circular arc, wrapped around the arcball sphere cylindrically
+(like a doughnut), joined smoothly to the sphere, much like Bell's hyperbola.
+
+
+.. [Shoemake1992] Ken Shoemake, "ARCBALL: A user interface for specifying
+ three-dimensional rotation using a mouse", in Proceedings of Graphics
+ Interface '92, 1992, pp. 151-156, https://doi.org/10.20380/GI1992.18
+
+.. [Bell1988] Gavin Bell, in the examples included with the GLUT (OpenGL
+ Utility Toolkit) library,
+ https://github.com/markkilgard/glut/blob/master/progs/examples/trackball.h
+
+.. [Henriksen2002] Knud Henriksen, Jon Sporring, Kasper Hornbæk,
+ "Virtual Trackballs Revisited", in IEEE Transactions on Visualization
+ and Computer Graphics, Volume 10, Issue 2, March-April 2004, pp. 206-216,
+ https://doi.org/10.1109/TVCG.2004.1260772 `[full-text]`__;
+
+__ https://www.researchgate.net/publication/8329656_Virtual_Trackballs_Revisited#fullTextFileContent
diff --git a/doc/api/transforms.dot b/doc/api/transforms.dot
new file mode 100644
index 000000000000..c3ea975158bf
--- /dev/null
+++ b/doc/api/transforms.dot
@@ -0,0 +1,141 @@
+digraph {
+ splines="polyline";
+
+ node [
+ fontname="DejaVu Sans, Vera Sans, Liberation Sans, Arial, Helvetica, sans",
+ shape=box,
+ ];
+ edge [
+ arrowsize=0.5,
+ fontname="DejaVu Sans, Vera Sans, Liberation Sans, Arial, Helvetica, sans",
+ ];
+
+ // Axes properties.
+ Axes__bbox [
+ label=Axes.bbox>,
+ target="_top",
+ tooltip="TransformedBbox",
+ URL="transformations.html#matplotlib.transforms.TransformedBbox",
+ ];
+ Axes__transAxes [
+ label=Axes.transAxes>
+ target="_top",
+ tooltip="BboxTransformTo",
+ URL="transformations.html#matplotlib.transforms.BboxTransformTo",
+ ];
+ Axes__transData [
+ label=Axes.transData>
+ target="_top",
+ tooltip="CompositeGenericTransform",
+ URL="transformations.html#matplotlib.transforms.CompositeGenericTransform",
+ ];
+ Axes__transLimits [
+ label=Axes.transLimits>
+ target="_top",
+ tooltip="BboxTransformFrom",
+ URL="transformations.html#matplotlib.transforms.BboxTransformFrom",
+ ];
+ Axes__transScale [
+ label=Axes.transScale>
+ target="_top",
+ tooltip="TransformWrapper",
+ URL="transformations.html#matplotlib.transforms.TransformWrapper",
+ ];
+ Axes__position [
+ label=Axes.get_position()>
+ target="_top",
+ tooltip="Bbox",
+ URL="transformations.html#matplotlib.transforms.Bbox",
+ ];
+ Axes__viewLim [
+ label = Axes._viewLim>
+ target="_top",
+ tooltip="Bbox",
+ URL="transformations.html#matplotlib.transforms.Bbox",
+ ];
+
+ // Axis properties.
+ XAxis_transform [
+ label=Axes.xaxis.get_transform()>
+ target="_top",
+ tooltip="IdentityTransform",
+ URL="transformations.html#matplotlib.transforms.IdentityTransform",
+ ];
+ YAxis_transform [
+ label=Axes.yaxis.get_transform()>
+ target="_top",
+ tooltip="IdentityTransform",
+ URL="transformations.html#matplotlib.transforms.IdentityTransform",
+ ];
+
+ // Figure properties.
+ Figure__transFigure [
+ label=Figure.transFigure>
+ target="_top",
+ tooltip="BboxTransformTo",
+ URL="transformations.html#matplotlib.transforms.BboxTransformTo",
+ ];
+ Figure__bbox [
+ label=Figure.bbox>
+ target="_top",
+ tooltip="TransformedBbox",
+ URL="transformations.html#matplotlib.transforms.TransformedBbox",
+ ];
+ Figure__bbox_inches [
+ label=Figure.bbox_inches>
+ target="_top",
+ tooltip="Bbox",
+ URL="transformations.html#matplotlib.transforms.Bbox",
+ ];
+ Figure__dpi_scale_trans [
+ label=Figure.dpi_scale_trans>
+ target="_top",
+ tooltip="Affine2D",
+ URL="transformations.html#matplotlib.transforms.Affine2D",
+ ];
+
+ // Internal unnamed transform children.
+ Axes__transDataB [
+ label="CompositeGenericTransform",
+ target="_top",
+ tooltip="CompositeGenericTransform",
+ URL="transformations.html#matplotlib.transforms.CompositeGenericTransform",
+ ];
+ Axes__transLimitsBbox [
+ label="TransformedBbox",
+ target="_top",
+ tooltip="TransformedBbox",
+ URL="transformations.html#matplotlib.transforms.TransformedBbox",
+ ];
+ Axes__transScaleBlend [
+ label="BlendedAffine2D",
+ target="_top",
+ tooltip="BlendedAffine2D",
+ URL="transformations.html#matplotlib.transforms.BlendedAffine2D",
+ ];
+
+ // The actual Axes__transform tree follows:
+ Axes__transData -> Axes__transScale [label="a", labelangle=90];
+ Axes__transData -> Axes__transDataB [label="b"];
+ Axes__transDataB -> Axes__transLimits [label="a"];
+ Axes__transDataB -> Axes__transAxes [label="b"];
+
+ Axes__transScale -> Axes__transScaleBlend [label="child"];
+ Axes__transScaleBlend -> XAxis_transform [label="x_transform"];
+ Axes__transScaleBlend -> YAxis_transform [label="y_transform"];
+
+ Axes__transLimits -> Axes__transLimitsBbox [label="boxin"];
+ Axes__transLimitsBbox -> Axes__viewLim [label="bbox"];
+ Axes__transLimitsBbox -> Axes__transScale [label="transform"];
+
+ Axes__transAxes -> Axes__bbox [label="boxout"];
+ Axes__bbox -> Axes__position [label="bbox"];
+ Axes__bbox -> Figure__transFigure [label="transform"];
+
+ Figure__transFigure -> Figure__bbox [label="boxout"];
+ Figure__bbox -> Figure__bbox_inches [label="bbox"];
+ Figure__bbox -> Figure__dpi_scale_trans [label="transform"];
+}
diff --git a/doc/api/type1font.rst b/doc/api/type1font.rst
deleted file mode 100644
index 00ef38f4d447..000000000000
--- a/doc/api/type1font.rst
+++ /dev/null
@@ -1,13 +0,0 @@
-************************
-``matplotlib.type1font``
-************************
-
-.. attention::
- This module is considered internal.
-
- Its use is deprecated and it will be removed in a future version.
-
-.. automodule:: matplotlib._type1font
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/doc/api/typing_api.rst b/doc/api/typing_api.rst
index 10582f8111d0..4c0cad953487 100644
--- a/doc/api/typing_api.rst
+++ b/doc/api/typing_api.rst
@@ -2,18 +2,33 @@
``matplotlib.typing``
*********************
+.. automodule:: matplotlib.typing
+ :no-members:
+ :no-undoc-members:
+
+Color
+=====
+
+.. autodata:: matplotlib.typing.ColorType
.. autodata:: matplotlib.typing.RGBColorType
-.. autodata:: matplotlib.typing.RGBColourType
.. autodata:: matplotlib.typing.RGBAColorType
-.. autodata:: matplotlib.typing.RGBAColourType
-.. autodata:: matplotlib.typing.ColorType
.. autodata:: matplotlib.typing.ColourType
+.. autodata:: matplotlib.typing.RGBColourType
+.. autodata:: matplotlib.typing.RGBAColourType
+
+Styles
+======
+
.. autodata:: matplotlib.typing.LineStyleType
.. autodata:: matplotlib.typing.DrawStyleType
.. autodata:: matplotlib.typing.MarkEveryType
.. autodata:: matplotlib.typing.FillStyleType
.. autodata:: matplotlib.typing.CapStyleType
.. autodata:: matplotlib.typing.JoinStyleType
+
+Other types
+===========
+
+.. autodata:: matplotlib.typing.CoordsType
.. autodata:: matplotlib.typing.RcStyleType
.. autodata:: matplotlib.typing.HashableList
- :annotation: Nested list with Hashable values
diff --git a/doc/conf.py b/doc/conf.py
index 544bddf2e5a1..199249fdd437 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -15,6 +15,7 @@
import logging
import os
from pathlib import Path
+import re
import shutil
import subprocess
import sys
@@ -22,12 +23,12 @@
from urllib.parse import urlsplit, urlunsplit
import warnings
+from packaging.version import parse as parse_version
import sphinx
import yaml
import matplotlib
-
# debug that building expected version
print(f"Building Documentation for Matplotlib: {matplotlib.__version__}")
@@ -36,6 +37,14 @@
# are we running circle CI?
CIRCLECI = 'CIRCLECI' in os.environ
+# are we deploying this build to matplotlib.org/devdocs?
+# This is a copy of the logic in .circleci/deploy-docs.sh
+DEVDOCS = (
+ CIRCLECI and
+ (os.environ.get("CIRCLE_PROJECT_USERNAME") == "matplotlib") and
+ (os.environ.get("CIRCLE_BRANCH") == "main") and
+ (not os.environ.get("CIRCLE_PULL_REQUEST", "").startswith(
+ "https://github.com/matplotlib/matplotlib/pull")))
def _parse_skip_subdirs_file():
@@ -93,11 +102,20 @@ def _parse_skip_subdirs_file():
# usage in the gallery.
warnings.filterwarnings('error', append=True)
+# Warnings for missing glyphs occur during `savefig`, and would cause any such plot to
+# not be created. Because the exception occurs in savefig, there is no way for the plot
+# itself to ignore these warnings locally, so we must do so globally.
+warnings.filterwarnings('default', category=UserWarning,
+ message=r'Glyph \d+ \(.+\) missing from font\(s\)')
+warnings.filterwarnings('default', category=UserWarning,
+ message=r'Matplotlib currently does not support .+ natively\.')
+
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.autosummary',
+ 'sphinx.ext.graphviz',
'sphinx.ext.inheritance_diagram',
'sphinx.ext.intersphinx',
'sphinx.ext.ifconfig',
@@ -107,9 +125,9 @@ def _parse_skip_subdirs_file():
'sphinx_gallery.gen_gallery',
'matplotlib.sphinxext.mathmpl',
'matplotlib.sphinxext.plot_directive',
+ 'matplotlib.sphinxext.roles',
'matplotlib.sphinxext.figmpl_directive',
'sphinxcontrib.inkscapeconverter',
- 'sphinxext.custom_roles',
'sphinxext.github',
'sphinxext.math_symbol_table',
'sphinxext.missing_references',
@@ -122,7 +140,10 @@ def _parse_skip_subdirs_file():
]
exclude_patterns = [
- 'api/prev_api_changes/api_changes_*/*', '**/*inc.rst']
+ 'api/prev_api_changes/api_changes_*/*',
+ '**/*inc.rst',
+ 'users/explain/index.rst' # Page has no content, but required by sphinx gallery
+]
exclude_patterns += skip_subdirs
@@ -158,14 +179,34 @@ def _check_dependencies():
raise OSError(
"No binary named dot - graphviz must be installed to build the "
"documentation")
+ if shutil.which('latex') is None:
+ raise OSError(
+ "No binary named latex - a LaTeX distribution must be installed to build "
+ "the documentation")
_check_dependencies()
# Import only after checking for dependencies.
-# gallery_order.py from the sphinxext folder provides the classes that
-# allow custom ordering of sections and subsections of the gallery
-import sphinxext.gallery_order as gallery_order
+import sphinx_gallery
+
+if parse_version(sphinx_gallery.__version__) >= parse_version('0.16.0'):
+ gallery_order_sectionorder = 'sphinxext.gallery_order.sectionorder'
+ gallery_order_subsectionorder = 'sphinxext.gallery_order.subsectionorder'
+ clear_basic_units = 'sphinxext.util.clear_basic_units'
+ matplotlib_reduced_latex_scraper = 'sphinxext.util.matplotlib_reduced_latex_scraper'
+else:
+ # gallery_order.py from the sphinxext folder provides the classes that
+ # allow custom ordering of sections and subsections of the gallery
+ from sphinxext.gallery_order import (
+ sectionorder as gallery_order_sectionorder,
+ subsectionorder as gallery_order_subsectionorder)
+ from sphinxext.util import clear_basic_units, matplotlib_reduced_latex_scraper
+
+if parse_version(sphinx_gallery.__version__) >= parse_version('0.17.0'):
+ sg_matplotlib_animations = (True, 'mp4')
+else:
+ sg_matplotlib_animations = True
# The following import is only necessary to monkey patch the signature later on
from sphinx_gallery import gen_rst
@@ -174,8 +215,20 @@ def _check_dependencies():
warnings.filterwarnings('ignore', category=UserWarning,
message=r'(\n|.)*is non-interactive, and thus cannot be shown')
+
+# hack to catch sphinx-gallery 17.0 warnings
+def tutorials_download_error(record):
+ if re.match("download file not readable: .*tutorials_(python|jupyter).zip",
+ record.msg):
+ return False
+
+
+logger = logging.getLogger('sphinx')
+logger.addFilter(tutorials_download_error)
+
autosummary_generate = True
autodoc_typehints = "none"
+autodoc_mock_imports = ["pytest"]
# we should ignore warnings coming from importing deprecated modules for
# autodoc purposes, as this will disappear automatically when they are removed
@@ -186,6 +239,20 @@ def _check_dependencies():
autodoc_docstring_signature = True
autodoc_default_options = {'members': None, 'undoc-members': None}
+
+def autodoc_process_bases(app, name, obj, options, bases):
+ """
+ Hide pybind11 base object from inheritance tree.
+
+ Note, *bases* must be modified in place.
+ """
+ for cls in bases[:]:
+ if not isinstance(cls, type):
+ continue
+ if cls.__module__ == 'pybind11_builtins' and cls.__name__ == 'pybind11_object':
+ bases.remove(cls)
+
+
# make sure to ignore warnings that stem from simply inspecting deprecated
# class-level attributes
warnings.filterwarnings('ignore', category=DeprecationWarning,
@@ -196,6 +263,7 @@ def _check_dependencies():
missing_references_write_json = False
missing_references_warn_unused_ignores = False
+
intersphinx_mapping = {
'Pillow': ('https://pillow.readthedocs.io/en/stable/', None),
'cycler': ('https://matplotlib.org/cycler/', None),
@@ -208,26 +276,11 @@ def _check_dependencies():
'scipy': ('https://docs.scipy.org/doc/scipy/', None),
'tornado': ('https://www.tornadoweb.org/en/stable/', None),
'xarray': ('https://docs.xarray.dev/en/stable/', None),
- 'meson-python': ('https://meson-python.readthedocs.io/en/stable/', None)
+ 'meson-python': ('https://mesonbuild.com/meson-python/', None),
+ 'pip': ('https://pip.pypa.io/en/stable/', None),
}
-# Sphinx gallery configuration
-
-def matplotlib_reduced_latex_scraper(block, block_vars, gallery_conf,
- **kwargs):
- """
- Reduce srcset when creating a PDF.
-
- Because sphinx-gallery runs *very* early, we cannot modify this even in the
- earliest builder-inited signal. Thus we do it at scraping time.
- """
- from sphinx_gallery.scrapers import matplotlib_scraper
-
- if gallery_conf['builder_name'] == 'latex':
- gallery_conf['image_srcset'] = []
- return matplotlib_scraper(block, block_vars, gallery_conf, **kwargs)
-
gallery_dirs = [f'{ed}' for ed in
['gallery', 'tutorials', 'plot_types', 'users/explain']
if f'{ed}/*' not in skip_subdirs]
@@ -238,7 +291,7 @@ def matplotlib_reduced_latex_scraper(block, block_vars, gallery_conf,
example_dirs += [f'../galleries/{gd}']
sphinx_gallery_conf = {
- 'backreferences_dir': Path('api') / Path('_as_gen'),
+ 'backreferences_dir': Path('api', '_as_gen'),
# Compression is a significant effort that we skip for local and CI builds.
'compress_images': ('thumbnails', 'images') if is_release_build else (),
'doc_module': ('matplotlib', 'mpl_toolkits'),
@@ -248,23 +301,25 @@ def matplotlib_reduced_latex_scraper(block, block_vars, gallery_conf,
'image_scrapers': (matplotlib_reduced_latex_scraper, ),
'image_srcset': ["2x"],
'junit': '../test-results/sphinx-gallery/junit.xml' if CIRCLECI else '',
- 'matplotlib_animations': True,
+ 'matplotlib_animations': sg_matplotlib_animations,
'min_reported_time': 1,
'plot_gallery': 'True', # sphinx-gallery/913
- 'reference_url': {'matplotlib': None},
+ 'reference_url': {'matplotlib': None, 'mpl_toolkits': None},
+ 'prefer_full_module': {r'mpl_toolkits\.'},
'remove_config_comments': True,
- 'reset_modules': (
- 'matplotlib',
- # clear basic_units module to re-register with unit registry on import
- lambda gallery_conf, fname: sys.modules.pop('basic_units', None)
- ),
- 'subsection_order': gallery_order.sectionorder,
+ 'reset_modules': ('matplotlib', clear_basic_units),
+ 'subsection_order': gallery_order_sectionorder,
'thumbnail_size': (320, 224),
- 'within_subsection_order': gallery_order.subsectionorder,
+ 'within_subsection_order': gallery_order_subsectionorder,
'capture_repr': (),
'copyfile_regex': r'.*\.rst',
}
+if parse_version(sphinx_gallery.__version__) >= parse_version('0.17.0'):
+ sphinx_gallery_conf['parallel'] = True
+ # Any warnings from joblib turned into errors may cause a deadlock.
+ warnings.filterwarnings('default', category=UserWarning, module='joblib')
+
if 'plot_gallery=0' in sys.argv:
# Gallery images are not created. Suppress warnings triggered where other
# parts of the documentation link to these images.
@@ -317,7 +372,7 @@ def gallery_image_warning_filter(record):
:class: sphx-glr-download-link-note
:ref:`Go to the end `
- to download the full example code{2}
+ to download the full example code.{2}
.. rst-class:: sphx-glr-example-title
@@ -334,8 +389,8 @@ def gallery_image_warning_filter(record):
# This is the default encoding, but it doesn't hurt to be explicit
source_encoding = "utf-8"
-# The toplevel toctree document (renamed to root_doc in Sphinx 4.0)
-root_doc = master_doc = 'index'
+# The toplevel toctree document.
+root_doc = 'index'
# General substitutions.
try:
@@ -478,22 +533,28 @@ def js_tag_with_cache_busting(js):
"switcher": {
# Add a unique query to the switcher.json url. This will be ignored by
# the server, but will be used as part of the key for caching by browsers
- # so when we do a new minor release the switcher will update "promptly" on
+ # so when we do a new meso release the switcher will update "promptly" on
# the stable and devdocs.
- "json_url": f"https://matplotlib.org/devdocs/_static/switcher.json?{SHA}",
+ "json_url": (
+ "https://output.circle-artifacts.com/output/job/"
+ f"{os.environ['CIRCLE_WORKFLOW_JOB_ID']}/artifacts/"
+ f"{os.environ['CIRCLE_NODE_INDEX']}"
+ "/doc/build/html/_static/switcher.json" if CIRCLECI and not DEVDOCS else
+ f"https://matplotlib.org/devdocs/_static/switcher.json?{SHA}"
+ ),
"version_match": (
- # The start version to show. This must be in switcher.json.
- # We either go to 'stable' or to 'devdocs'
- 'stable' if matplotlib.__version_info__.releaselevel == 'final'
- else 'devdocs')
+ matplotlib.__version__
+ if matplotlib.__version_info__.releaselevel == 'final'
+ else 'dev')
},
"navbar_end": ["theme-switcher", "version-switcher", "mpl_icon_links"],
- "secondary_sidebar_items": "page-toc.html",
+ "navbar_persistent": ["search-button"],
"footer_start": ["copyright", "sphinx-version", "doc_version"],
# We override the announcement template from pydata-sphinx-theme, where
# this special value indicates the use of the unreleased banner. If we need
# an actual announcement, then just place the text here as usual.
"announcement": "unreleased" if not is_release_build else "",
+ "show_version_warning_banner": True,
}
include_analytics = is_release_build
if include_analytics:
@@ -528,13 +589,19 @@ def js_tag_with_cache_busting(js):
html_sidebars = {
"index": [
# 'sidebar_announcement.html',
- "sidebar_versions.html",
"cheatsheet_sidebar.html",
"donate_sidebar.html",
],
+ # no sidebar for release notes, because that page is only a collection of links
+ # to sub-pages. The sidebar would repeat all the titles of the sub-pages and
+ # thus basically repeat all the content of the page.
+ "users/release_notes": ["empty_sidebar.html"],
# '**': ['localtoc.html', 'pagesource.html']
}
+# Don't include link to doc source files
+html_show_sourcelink = False
+
# Copies only relevant code, not the '>>>' prompt
copybutton_prompt_text = r'>>> |\.\.\. '
copybutton_prompt_is_regexp = True
@@ -713,16 +780,14 @@ def js_tag_with_cache_busting(js):
numpydoc_show_class_members = False
# We want to prevent any size limit, as we'll add scroll bars with CSS.
-inheritance_graph_attrs = dict(dpi=100, size='1000.0', splines='polyline')
+inheritance_graph_attrs = dict(size='1000.0', splines='polyline')
# Also remove minimum node dimensions, and increase line size a bit.
inheritance_node_attrs = dict(height=0.02, margin=0.055, penwidth=1,
width=0.01)
inheritance_edge_attrs = dict(penwidth=1)
graphviz_dot = shutil.which('dot')
-# Still use PNG until SVG linking is fixed
-# https://github.com/sphinx-doc/sphinx/issues/3176
-# graphviz_output_format = 'svg'
+graphviz_output_format = 'svg'
# -----------------------------------------------------------------------------
# Source code links
@@ -732,7 +797,6 @@ def js_tag_with_cache_busting(js):
if link_github:
import inspect
- from packaging.version import parse
extensions.append('sphinx.ext.linkcode')
@@ -788,7 +852,7 @@ def linkcode_resolve(domain, info):
if not fn.startswith(('matplotlib/', 'mpl_toolkits/')):
return None
- version = parse(matplotlib.__version__)
+ version = parse_version(matplotlib.__version__)
tag = 'main' if version.is_devrelease else f'v{version.public}'
return ("https://github.com/matplotlib/matplotlib/blob"
f"/{tag}/lib/{fn}{linespec}")
@@ -796,6 +860,58 @@ def linkcode_resolve(domain, info):
extensions.append('sphinx.ext.viewcode')
+def generate_ScalarMappable_docs():
+
+ import matplotlib.colorizer
+ from numpydoc.docscrape_sphinx import get_doc_object
+ from pathlib import Path
+ import textwrap
+ from sphinx.util.inspect import stringify_signature
+ target_file = Path(__file__).parent / 'api' / 'scalarmappable.gen_rst'
+ with open(target_file, 'w') as fout:
+ fout.write("""
+.. class:: ScalarMappable(colorizer, **kwargs)
+ :canonical: matplotlib.colorizer._ScalarMappable
+
+""")
+ for meth in [
+ matplotlib.colorizer._ScalarMappable.autoscale,
+ matplotlib.colorizer._ScalarMappable.autoscale_None,
+ matplotlib.colorizer._ScalarMappable.changed,
+ """
+ .. attribute:: colorbar
+
+ The last colorbar associated with this ScalarMappable. May be None.
+""",
+ matplotlib.colorizer._ScalarMappable.get_alpha,
+ matplotlib.colorizer._ScalarMappable.get_array,
+ matplotlib.colorizer._ScalarMappable.get_clim,
+ matplotlib.colorizer._ScalarMappable.get_cmap,
+ """
+ .. property:: norm
+""",
+ matplotlib.colorizer._ScalarMappable.set_array,
+ matplotlib.colorizer._ScalarMappable.set_clim,
+ matplotlib.colorizer._ScalarMappable.set_cmap,
+ matplotlib.colorizer._ScalarMappable.set_norm,
+ matplotlib.colorizer._ScalarMappable.to_rgba,
+ ]:
+ if isinstance(meth, str):
+ fout.write(meth)
+ else:
+ name = meth.__name__
+ sig = stringify_signature(inspect.signature(meth))
+ docstring = textwrap.indent(
+ str(get_doc_object(meth)),
+ ' '
+ ).rstrip()
+ fout.write(f"""
+ .. method:: {name}{sig}
+{docstring}
+
+""")
+
+
# -----------------------------------------------------------------------------
# Sphinx setup
# -----------------------------------------------------------------------------
@@ -806,5 +922,7 @@ def setup(app):
bld_type = 'rel'
app.add_config_value('skip_sub_dirs', 0, '')
app.add_config_value('releaselevel', bld_type, 'env')
+ app.connect('autodoc-process-bases', autodoc_process_bases)
if sphinx.version_info[:2] < (7, 1):
app.connect('html-page-context', add_html_cache_busting, priority=1000)
+ generate_ScalarMappable_docs()
diff --git a/doc/devel/MEP/MEP13.rst b/doc/devel/MEP/MEP13.rst
index 58131a9a06fb..b8b80f281b6e 100644
--- a/doc/devel/MEP/MEP13.rst
+++ b/doc/devel/MEP/MEP13.rst
@@ -63,7 +63,7 @@ The following steps can be done simultaneously: 1, 2, and 3; 4 and 5;
Only the following steps must be done in the same release: 4, 5,
and 6. All other changes can be done in separate releases. 8 should
-be done several major releases after everything else.
+be done several macro releases after everything else.
Backward compatibility
======================
diff --git a/doc/devel/MEP/MEP23.rst b/doc/devel/MEP/MEP23.rst
index d6b342877959..ec56f362c867 100644
--- a/doc/devel/MEP/MEP23.rst
+++ b/doc/devel/MEP/MEP23.rst
@@ -38,8 +38,8 @@ desirable to be able to group these under the same window. See :ghpull:`2194`.
The proposed solution modifies `.FigureManagerBase` to contain and manage more
-than one ``Canvas``. The settings parameter :rc:`backend.multifigure` control
-when the **MultiFigure** behaviour is desired.
+than one ``Canvas``. The ``backend.multifigure`` rcParam controls when the
+**MultiFigure** behaviour is desired.
**Note**
diff --git a/doc/devel/README.txt b/doc/devel/README.txt
deleted file mode 100644
index d7636cd4c37c..000000000000
--- a/doc/devel/README.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-All documentation in the gitwash directory are automatically generated by running the gitwash_dumper.py
-script in the project's root directory using the following parameters:
-
-python gitwash_dumper.py doc/devel Matplotlib --repo-name=matplotlib --github-user=matplotlib \
- --project-url=https://matplotlib.org \
- --project-ml-url=https://mail.python.org/mailman/listinfo/matplotlib-devel
-
-The script is hosted at https://raw.githubusercontent.com/matthew-brett/gitwash/master/gitwash_dumper.py.
-For more information please visit https://github.com/matthew-brett/gitwash
diff --git a/doc/devel/api_changes.rst b/doc/devel/api_changes.rst
new file mode 100644
index 000000000000..19bc530abf6b
--- /dev/null
+++ b/doc/devel/api_changes.rst
@@ -0,0 +1,333 @@
+.. _api_changes:
+
+API guidelines
+==============
+
+API consistency and stability are of great value; Therefore, API changes
+(e.g. signature changes, behavior changes, removals) will only be conducted
+if the added benefit is worth the effort of adapting existing code.
+
+Because we are a visualization library, our primary output is the final
+visualization the user sees; therefore, the appearance of the figure is part of
+the API and any changes, either semantic or aesthetic, are backwards-incompatible
+API changes.
+
+
+Add new API
+-----------
+
+Every new function, parameter and attribute that is not explicitly marked as
+private (i.e., starts with an underscore) becomes part of Matplotlib's public
+API. As discussed above, changing the existing API is cumbersome. Therefore,
+take particular care when adding new API:
+
+- Mark helper functions and internal attributes as private by prefixing them
+ with an underscore.
+- Carefully think about good names for your functions and variables.
+- Try to adopt patterns and naming conventions from existing parts of the
+ Matplotlib API.
+- Consider making as many arguments keyword-only as possible. See also
+ `API Evolution the Right Way -- Add Parameters Compatibly`__.
+
+ __ https://emptysqua.re/blog/api-evolution-the-right-way/#adding-parameters
+
+
+Add or change colormaps, color sequences, and styles
+----------------------------------------------------
+Visual changes are considered an API break. Therefore, we generally do not modify
+existing colormaps, color sequences, or styles.
+
+We put a high bar on adding new colormaps and styles to prevent excessively growing
+them. While the decision is case-by-case, evaluation criteria include:
+
+- novelty: Does it support a new use case? e.g. slight variations of existing maps,
+ sequences and styles are likely not accepted.
+- usability and accessibility: Are colors of sequences sufficiently distinct? Has
+ colorblindness been considered?
+- evidence of wide spread usage: for example academic papers, industry blogs and
+ whitepapers, or inclusion in other visualization libraries or domain specific tools
+- open license: colormaps, sequences, and styles must have a BSD compatible license
+ (see :ref:`license-discussion`)
+
+.. _deprecation-guidelines:
+
+Deprecate API
+-------------
+
+When deciding to deprecate API we carefully consider the balance between the advantages
+(clearer interfaces, better usability, less maintenance) and the disadvantages (users
+have to learn new API and have to modify existing code).
+
+.. tip::
+
+ A rough estimate on the current usage of an API can be obtained by a GitHub code
+ search. A good search pattern is typically
+ ``[expression] language:Python NOT is:fork``. ``[expression]`` may be a simple
+ string, but often regular expressions are helpful to exclude incorrect matches.
+ You can start simple and look at the search results, if there are too many
+ incorrect matches, gradually refine your search criteria.
+
+ It can also be helpful to add ``NOT path:**/matplotlib/** NOT path:**/site-packages/**``
+ to exclude matches where the matplotlib codebase is checked into another repo,
+ either as direct sources or as part of an environment.
+
+ *Example*: Calls of the method ``Figure.draw()`` could be matched using
+ ``/\bfig(ure)?\.draw\(/``. This expression employs a number of patterns:
+
+ - Add the opening bracket ``(`` after the method name to only find method calls.
+ - Include a common object name if there are otherwise too many false positives.
+ There are many ``draw()`` functions out there, but the ones we are looking for
+ are likely called via ``fig.draw()`` or ``figure.draw()``.
+ - Use the word boundary marker ``\b`` to make sure your expression is not a
+ matching as part of a longer word.
+
+ `Link to the resulting GitHub search `_
+
+
+API changes in Matplotlib have to be performed following the deprecation process
+below, except in very rare circumstances as deemed necessary by the development
+team. Generally API deprecation happens in two stages:
+
+* **introduce:** warn users that the API *will* change
+* **expire:** API *is* changed as described in the introduction period
+
+This ensures that users are notified before the change will take effect and thus
+prevents unexpected breaking of code. Occasionally deprecations are marked as
+**pending**, which means that the deprecation will be introduced in a future release.
+
+Rules
+^^^^^
+- Deprecations are targeted at the next :ref:`meso release ` (e.g. 3.Y)
+- Deprecated API is generally removed (expired) two point-releases after introduction
+ of the deprecation. Longer deprecations can be imposed by core developers on
+ a case-by-case basis to give more time for the transition
+- The old API must remain fully functional during the deprecation period
+- If alternatives to the deprecated API exist, they should be available
+ during the deprecation period
+- If in doubt, decisions about API changes are finally made by the
+ `API consistency lead `_ developer.
+
+
+.. _intro-deprecation:
+
+Introduce deprecation
+^^^^^^^^^^^^^^^^^^^^^
+
+Deprecations are introduced to warn users that the API will change. The deprecation
+notice describes how the API will change. When alternatives to the deprecated API exist,
+they are also listed in the notice and decorators.
+
+#. Create a :ref:`deprecation notice `
+
+#. If possible, issue a `~matplotlib.MatplotlibDeprecationWarning` when the
+ deprecated API is used. There are a number of helper tools for this:
+
+ - Use ``_api.warn_deprecated()`` for general deprecation warnings
+ - Use the decorator ``@_api.deprecated`` to deprecate classes, functions,
+ methods, or properties
+ - Use ``@_api.deprecate_privatize_attribute`` to annotate deprecation of
+ attributes while keeping the internal private version.
+ - To warn on changes of the function signature, use the decorators
+ ``@_api.delete_parameter``, ``@_api.rename_parameter``, and
+ ``@_api.make_keyword_only``
+
+ All these helpers take a first parameter *since*, which should be set to
+ the next point release, e.g. "3.x".
+
+ You can use standard rst cross references in *alternative*.
+
+#. Make appropriate changes to the type hints in the associated ``.pyi`` file.
+ The general guideline is to match runtime reported behavior.
+
+ - Items marked with ``@_api.deprecated`` or ``@_api.deprecate_privatize_attribute``
+ are generally kept during the expiry period, and thus no changes are needed on
+ introduction.
+ - Items decorated with ``@_api.rename_parameter`` or ``@_api.make_keyword_only``
+ report the *new* (post deprecation) signature at runtime, and thus *should* be
+ updated on introduction.
+ - Items decorated with ``@_api.delete_parameter`` should include a default value hint
+ for the deleted parameter, even if it did not previously have one (e.g.
+ ``param: = ...``).
+
+.. _expire-deprecation:
+
+Expire deprecation
+^^^^^^^^^^^^^^^^^^
+The API changes described in the introduction notice are only implemented after the
+introduction period has expired.
+
+#. Create a :ref:`deprecation announcement `. For the content,
+ you can usually copy the deprecation notice and adapt it slightly.
+
+#. Change the code functionality and remove any related deprecation warnings.
+
+#. Make appropriate changes to the type hints in the associated ``.pyi`` file.
+
+ - Items marked with ``@_api.deprecated`` or ``@_api.deprecate_privatize_attribute``
+ are to be removed on expiry.
+ - Items decorated with ``@_api.rename_parameter`` or ``@_api.make_keyword_only``
+ will have been updated at introduction, and require no change now.
+ - Items decorated with ``@_api.delete_parameter`` will need to be updated to the
+ final signature, in the same way as the ``.py`` file signature is updated.
+ - Any entries in :file:`ci/mypy-stubtest-allowlist.txt` which indicate a deprecation
+ version should be double checked. In most cases this is not needed, though some
+ items were never type hinted in the first place and were added to this file
+ instead. For removed items that were not in the stub file, only deleting from the
+ allowlist is required.
+
+.. _pending-deprecation:
+
+Pending deprecation
+^^^^^^^^^^^^^^^^^^^
+
+A pending deprecation is an announcement that a deprecation will be introduced in the
+future. By default, pending deprecations do not raise a warning to the user; however,
+pending deprecations are rendered in the documentation and listed in the release notes.
+Pending notices are primarily intended to give downstream library and tool developers
+time to adapt their code so that it does not raise a deprecation
+warning. This is because their users cannot act on warnings triggered by how the tools
+and libraries use Matplotlib. It's also possible to run Python in dev mode to raise
+`PendingDeprecationWarning`.
+
+To mark a deprecation as pending, set the following parameters on the appropriate
+deprecation decorator:
+* the *pending* parameter is set to ``True``
+* the *removal* parameter is left blank
+
+When converting a pending deprecation to an introduced deprecation, update the
+decorator such that:
+* *pending* is set to ``False``
+* *since* is set to the next meso release (3.Y+1)
+* *removal* is set to at least 2 meso releases after (3.Y+3) introduction.
+
+Pending deprecations are documented in the :ref:`API change notes ` in
+the same manner as introduced and expired deprecations. The notice should include
+*pending deprecation* in the title.
+
+
+.. redirect-from:: /devel/coding_guide#new-features-and-api-changes
+
+.. _api_whats_new:
+
+Announce new and deprecated API
+-------------------------------
+
+When adding or changing the API in a backward in-compatible way, please add the
+appropriate :ref:`versioning directive ` and document it
+in the :ref:`release notes ` by adding an entry to the appropriate
+folder:
+
++-------------------+-----------------------------+----------------------------------------------+
+| | versioning directive | announcement folder |
++===================+=============================+==============================================+
+| new feature | ``.. versionadded:: 3.N`` | :file:`doc/users/next_whats_new/` |
++-------------------+-----------------------------+----------------------------------------------+
+| API change | ``.. versionchanged:: 3.N`` | :file:`doc/api/next_api_changes/[kind]` |
++-------------------+-----------------------------+----------------------------------------------+
+
+When deprecating API, please add a notice as described in the
+:ref:`deprecation guidelines ` and summarized here:
+
++--------------------------------------------------+----------------------------------------------+
+| stage | announcement folder |
++===========+======================================+==============================================+
+| :ref:`introduce deprecation ` | :file:`doc/api/next_api_changes/deprecation` |
++-----------+--------------------------------------+----------------------------------------------+
+| :ref:`expire deprecation ` | :file:`doc/api/next_api_changes/[kind]` |
++-----------+--------------------------------------+----------------------------------------------+
+
+Generally the introduction notices can be repurposed for the expiration notice as they
+are expected to be describing the same API changes and removals.
+
+.. _versioning-directives:
+
+Versioning directives
+^^^^^^^^^^^^^^^^^^^^^
+
+When making a backward incompatible change, please add a versioning directive in
+the docstring. 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 micro release version is omitted and
+the directive should not be added to entire modules.
+
+.. _release-notes:
+
+Release notes
+^^^^^^^^^^^^^
+
+For both change notes and what's new, please avoid using cross-references in section
+titles as it causes links to be confusing in the table of contents. Instead, ensure that
+a cross-reference is included in the descriptive text.
+
+.. _api-change-notes:
+
+API change notes
+""""""""""""""""
+
+.. include:: ../api/next_api_changes/README.rst
+ :start-after: api-change-guide-start
+ :end-before: api-change-guide-end
+
+.. _whats-new-notes:
+
+What's new notes
+""""""""""""""""
+
+.. include:: ../users/next_whats_new/README.rst
+ :start-after: whats-new-guide-start
+ :end-before: whats-new-guide-end
+
+Discourage API
+--------------
+
+We have API that we do not recommend anymore for new code, but that cannot be
+deprecated because its removal would be breaking backward-compatibility and too
+disruptive. In such a case we can formally discourage API. This can cover
+specific parameters, call patterns, whole methods etc.
+
+To do so, add a note to the docstring ::
+
+ .. admonition:: Discouraged
+
+ [description and suggested alternative]
+
+You find several examples for good descriptions if you search the codebase for
+``.. admonition:: Discouraged``.
+
+Additionally, if a whole function is discouraged, prefix the summary line with
+``[*Discouraged*]`` so that it renders in the API overview like this
+
+ [*Discouraged*] Return the XAxis instance.
diff --git a/doc/devel/coding_guide.rst b/doc/devel/coding_guide.rst
index 22873020f103..2b156cedca05 100644
--- a/doc/devel/coding_guide.rst
+++ b/doc/devel/coding_guide.rst
@@ -1,369 +1,320 @@
-.. _pr-guidelines:
+.. _coding_guidelines:
-***********************
-Pull request guidelines
-***********************
+*****************
+Coding guidelines
+*****************
-`Pull requests (PRs) on GitHub
-`__
-are the mechanism for contributing to Matplotlib's code and documentation.
+We appreciate these guidelines being followed because it improves the readability,
+consistency, and maintainability of the code base.
-We value contributions from people with all levels of experience. In particular,
-if this is your first PR not everything has to be perfect. We'll guide you
-through the PR process. Nevertheless, please try to follow our guidelines as well
-as you can to help make the PR process quick and smooth. If your pull request is
-incomplete or a work-in-progress, please mark it as a `draft pull requests `_
-on GitHub and specify what feedback from the developers would be helpful.
+.. admonition:: API guidelines
+ :class: seealso
-Please be patient with reviewers. We try our best to respond quickly, but we have
-limited bandwidth. If there is no feedback within a couple of days, please ping
-us by posting a comment to your PR or reaching out on a :ref:`communication channel `
+ If adding new features, changing behavior or function signatures, or removing
+ public interfaces, please consult the :ref:`api_changes`.
+.. _code-style:
-Summary for pull request authors
-================================
-
-We recommend that you check that your contribution complies with the following
-guidelines before submitting a pull request:
-
-.. rst-class:: checklist
-
-* Changes, both new features and bugfixes, should have good test coverage. See
- :ref:`testing` for more details.
-
-* Update the :ref:`documentation ` if necessary.
-
-* All public methods should have informative docstrings with sample usage when
- appropriate. Use the :ref:`docstring standards `.
-
-* For high-level plotting functions, consider adding a small example to the
- :ref:`examples gallery `.
-
-* If you add a major new feature or change the API in a backward-incompatible
- way, please document it as described in :ref:`new-changed-api`
-
-* Code should follow our conventions as documented in our :ref:`coding_guidelines`
-
-* When adding or changing public function signatures, add :ref:`type hints `
-
-* When adding keyword arguments, see our guide to :ref:`keyword-argument-processing`.
-
-When opening a pull request on Github, please ensure that:
-
-.. rst-class:: checklist
-
-* Changes were made on a :ref:`feature branch `.
-
-* :ref:`pre-commit ` checks for spelling, formatting, etc pass
-
-* The pull request targets the :ref:`main branch `
-
-* 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. For more
- details, see `linking an issue and pull request `__.
-
-* :ref:`pr-automated-tests` pass
-
-For guidance on creating and managing a pull request, please see our
-:ref:`contributing ` and :ref:`pull request workflow `
-guides.
-
+PEP8, as enforced by ruff
+=========================
-Summary for pull request reviewers
-==================================
+Formatting should follow the recommendations of PEP8_, as enforced by ruff_.
+Matplotlib modifies PEP8 to extend the maximum line length to 88
+characters. You can check PEP8 compliance from the command line with ::
-.. redirect-from:: /devel/maintainer_workflow
+ python -m pip install ruff
+ ruff check /path/to/module.py
-**Please help review and merge PRs!**
+or your editor may provide integration with it. To check all files,
+and fix any errors in-place (where possible) run ::
-If you have commit rights, then you are trusted to use them. Please be patient
-and `kind `__ with contributors.
+ ruff check --fix
-When reviewing, please ensure that the pull request satisfies the following
-requirements before merging it:
-Content topics:
+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__).
-.. rst-class:: checklist
+.. _PEP8: https://www.python.org/dev/peps/pep-0008/
+.. _ruff: https://docs.astral.sh/ruff/
+.. _black: https://black.readthedocs.io/
+.. __: https://github.com/matplotlib/matplotlib/issues/18796
+.. __: https://github.com/psf/black/issues/148
+.. __: https://github.com/psf/black/issues/1984
-* Is the feature / bugfix reasonable?
-* Does the PR conform with the :ref:`coding_guidelines`?
-* Is the :ref:`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.
+Package imports
+===============
-Organizational topics:
+Import the following modules using the standard scipy conventions::
-.. rst-class:: checklist
+ 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
-* Make sure all :ref:`automated tests ` pass.
-* The PR should :ref:`target the main branch `.
-* Tag with descriptive :ref:`labels `.
-* Set the :ref:`milestone `.
-* Keep an eye on the :ref:`number of commits `.
-* Approve if all of the above topics are handled.
-* :ref:`Merge ` if a sufficient number of approvals is reached.
+In general, Matplotlib modules should **not** import `.rcParams` using ``from
+matplotlib import rcParams``, but rather access it as ``mpl.rcParams``. This
+is because some modules are imported very early, before the `.rcParams`
+singleton is constructed.
-.. _pr-guidelines-details:
+Variable names
+==============
-Detailed guidelines
-===================
+When feasible, please use our internal variable naming convention for objects
+of a given class and objects of any child class:
-.. _pr-documentation:
++------------------------------------+---------------+------------------------------------------+
+| base class | variable | multiples |
++====================================+===============+==========================================+
+| `~matplotlib.figure.FigureBase` | ``fig`` | |
++------------------------------------+---------------+------------------------------------------+
+| `~matplotlib.axes.Axes` | ``ax`` | |
++------------------------------------+---------------+------------------------------------------+
+| `~matplotlib.transforms.Transform` | ``trans`` | ``trans__`` |
++ + + +
+| | | ``trans_`` when target is screen |
++------------------------------------+---------------+------------------------------------------+
-Documentation
--------------
+Generally, denote more than one instance of the same class by adding suffixes to
+the variable names. If a format isn't specified in the table, use numbers or
+letters as appropriate.
-* 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.
+.. _type-hints:
-* Each high-level plotting function should have a small example in
- the ``Examples`` section 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 :file:`examples` directory, which will be
- rendered to the examples gallery in the documentation.
+Type hints
+==========
-* Build the docs and make sure all formatting warnings are addressed.
+If you add new public API or change public API, update or add the
+corresponding `mypy `_ type hints.
+We generally use `stub files
+`_
+(``*.pyi``) to store the type information; for example ``colors.pyi`` contains
+the type information for ``colors.py``. A notable exception is ``pyplot.py``,
+which is type hinted inline.
-* See :ref:`documenting-matplotlib` for our documentation style guide.
+Type hints can be validated by the `stubtest
+`_ tool, which can be run
+locally using ``tox -e stubtest`` and is a part of the :ref:`automated-tests`
+suite. Type hints for existing functions are also checked by the mypy
+:ref:`pre-commit hook `.
-.. _pr-labels:
-Labels
-------
+New modules and files: installation
+===================================
-* 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.
+* If you have added new files or directories, or reorganized existing ones, make sure the
+ new files are included in the :file:`meson.build` in the corresponding directories.
+* New modules *may* be typed inline or using parallel stub file like existing modules.
-.. _pr-milestones:
+C/C++ extensions
+================
-Milestones
-----------
+* Extensions may be written in C or C++.
-Set the milestone according to these guidelines:
+* Code style should conform to PEP7 (understanding that PEP7 doesn't
+ address C++, but most of its admonitions still apply).
-* *New features and API changes* are milestoned for the next minor release
- ``v3.N.0``.
+* Python/C interface code should be kept separate from the core C/C++
+ code. The interface code should be named :file:`FOO_wrap.cpp` or
+ :file:`FOO_wrapper.cpp`.
-* *Bugfixes, tests for released code, and docstring changes* may be milestoned
- for the next patch release ``v3.N.M``.
-
-* *Documentation changes* (only .rst files and examples) may be milestoned
- ``v3.N-doc``.
-
-If multiple rules apply, choose the first matching from the above list. See
-:ref:`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 :ref:`automatic backport ` for milestones which have
-a corresponding branch.
-
-.. _pr-merging:
-
-Merging
--------
-
-* 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 ``src`` or ``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 :file:`doc/api/next_api_changes`, and significant new
- features have an entry in :file:`doc/user/whats_new`.
-
- - 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").
-
-.. _pr-automated-tests:
-
-Automated tests
----------------
-Before being merged, a PR should pass the :ref:`automated-tests`. If you are
-unsure why a test is failing, ask on the PR or in our :ref:`communication-channels`
-
-.. _pr-squashing:
-
-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.
+* Header file documentation (aka docstrings) should be in Numpydoc
+ format. We don't plan on using automated tools for these
+ docstrings, and the Numpydoc format is well understood in the
+ scientific Python community.
+
+* C/C++ code in the :file:`extern/` directory is vendored, and should be kept
+ close to upstream whenever possible. It can be modified to fix bugs or
+ implement new features only if the required changes cannot be made elsewhere
+ in the codebase. In particular, avoid making style fixes to it.
+
+.. _keyword-argument-processing:
+
+Keyword argument processing
+===========================
+
+Matplotlib makes extensive use of ``**kwargs`` for pass-through customizations
+from one function to another. A typical example is
+`~matplotlib.axes.Axes.text`. The definition of `matplotlib.pyplot.text` is a
+simple pass-through to `matplotlib.axes.Axes.text`::
+
+ # in pyplot.py
+ def text(x, y, s, fontdict=None, **kwargs):
+ return gca().text(x, y, s, fontdict=fontdict, **kwargs)
+
+`matplotlib.axes.Axes.text` (simplified for illustration) just
+passes all ``args`` and ``kwargs`` on to ``matplotlib.text.Text.__init__``::
+
+ # in axes/_axes.py
+ def text(self, x, y, s, fontdict=None, **kwargs):
+ t = Text(x=x, y=y, text=s, **kwargs)
+
+and ``matplotlib.text.Text.__init__`` (again, simplified)
+just passes them on to the `matplotlib.artist.Artist.update` method::
+
+ # in text.py
+ def __init__(self, x=0, y=0, text='', **kwargs):
+ super().__init__()
+ self.update(kwargs)
+
+``update`` does the work looking for methods named like
+``set_property`` if ``property`` is a keyword argument. i.e., no one
+looks at the keywords, they just get passed through the API to the
+artist constructor which looks for suitably named methods and calls
+them with the value.
+
+As a general rule, the use of ``**kwargs`` should be reserved for
+pass-through keyword arguments, as in the example above. If all the
+keyword args are to be used in the function, and not passed
+on, use the key/value keyword args in the function definition rather
+than the ``**kwargs`` idiom.
+
+In some cases, you may want to consume some keys in the local
+function, and let others pass through. Instead of popping arguments to
+use off ``**kwargs``, specify them as keyword-only arguments to the local
+function. This makes it obvious at a glance which arguments will be
+consumed in the function. For example, in
+:meth:`~matplotlib.axes.Axes.plot`, ``scalex`` and ``scaley`` are
+local arguments and the rest are passed on as
+:meth:`~matplotlib.lines.Line2D` keyword arguments::
+ # in axes/_axes.py
+ def plot(self, *args, scalex=True, scaley=True, **kwargs):
+ lines = []
+ for line in self._get_lines(*args, **kwargs):
+ self.add_line(line)
+ lines.append(line)
+
+.. _using_logging:
+
+Using logging for debug messages
+================================
-.. _branches_and_backports:
+Matplotlib uses the standard Python `logging` library to write verbose
+warnings, information, and debug messages. Please use it! In all those places
+you write `print` calls to do your debugging, try using `logging.debug`
+instead!
-Branches and backports
-======================
-Current branches
-----------------
-The current active branches are
+To include `logging` in your module, at the top of the module, you need to
+``import logging``. Then calls in your code like::
-*main*
- The current development version. Future minor releases (*v3.N.0*) will be
- branched from this.
+ _log = logging.getLogger(__name__) # right after the imports
-*v3.N.x*
- Maintenance branch for Matplotlib 3.N. Future patch releases will be
- branched from this.
+ # code
+ # more code
+ _log.info('Here is some information')
+ _log.debug('Here is some more detailed information')
-*v3.N.M-doc*
- Documentation for the current release. On a patch release, this will be
- replaced by a properly named branch for the new release.
+will log to a logger named ``matplotlib.yourmodulename``.
+If an end-user of Matplotlib sets up `logging` to display at levels more
+verbose than ``logging.WARNING`` in their code with the Matplotlib-provided
+helper::
-.. _pr-branch-selection:
+ plt.set_loglevel("debug")
-Branch selection for pull requests
-----------------------------------
+or manually with ::
-Generally, all pull requests should target the main branch.
+ import logging
+ logging.basicConfig(level=logging.DEBUG)
+ import matplotlib.pyplot as plt
-Other branches are fed through :ref:`automatic ` or
-:ref:`manual `. Directly
-targeting other branches is only rarely necessary for special maintenance
-work.
+Then they will receive messages like
-.. _backport-strategy:
+.. code-block:: none
-Backport strategy
------------------
+ DEBUG:matplotlib.backends:backend MacOSX version unknown
+ DEBUG:matplotlib.yourmodulename:Here is some information
+ DEBUG:matplotlib.yourmodulename:Here is some more detailed information
-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:
+Avoid using pre-computed strings (``f-strings``, ``str.format``,etc.) for logging because
+of security and performance issues, and because they interfere with style handlers. For
+example, use ``_log.error('hello %s', 'world')`` rather than ``_log.error('hello
+{}'.format('world'))`` or ``_log.error(f'hello {s}')``.
-- critical bug fixes (segfault, failure to import, things that the
- user cannot work around)
-- fixes for regressions introduced in the last two minor releases
+Which logging level to use?
+---------------------------
-and may attempt to backport fixes for regressions introduced in older releases.
+There are five levels at which you can emit messages.
-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.
+- `logging.critical` and `logging.error` are really only there for errors that
+ will end the use of the library but not kill the interpreter.
+- `logging.warning` and `._api.warn_external` are used to warn the user,
+ see below.
+- `logging.info` is for information that the user may want to know if the
+ program behaves oddly. They are not displayed by default. For instance, if
+ an object isn't drawn because its position is ``NaN``, that can usually
+ be ignored, but a mystified user could call
+ ``logging.basicConfig(level=logging.INFO)`` and get an error message that
+ says why.
+- `logging.debug` is the least likely to be displayed, and hence can be the
+ most verbose. "Expected" code paths (e.g., reporting normal intermediate
+ steps of layouting or rendering) should only log at this level.
-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.
+By default, `logging` displays all log messages at levels higher than
+``logging.WARNING`` to `sys.stderr`.
-The only changes backported to the documentation branch (*v3.N.M-doc*)
-are changes to :file:`doc` or :file:`galleries`. Any changes to :file:`lib`
-or :file:`src`, including docstring-only changes, must not be backported to
-this branch.
+The `logging tutorial`_ suggests that the difference between `logging.warning`
+and `._api.warn_external` (which uses `warnings.warn`) is that
+`._api.warn_external` should be used for things the user must change to stop
+the warning (typically in the source), whereas `logging.warning` can be more
+persistent. Moreover, note that `._api.warn_external` will by default only
+emit a given warning *once* for each line of user code, whereas
+`logging.warning` will display the message every time it is called.
+By default, `warnings.warn` displays the line of code that has the ``warn``
+call. This usually isn't more informative than the warning message itself.
+Therefore, Matplotlib uses `._api.warn_external` which uses `warnings.warn`,
+but goes up the stack and displays the first line of code outside of
+Matplotlib. For example, for the module::
-.. _automated-backports:
+ # in my_matplotlib_module.py
+ import warnings
-Automated backports
--------------------
+ def set_range(bottom, top):
+ if bottom == top:
+ warnings.warn('Attempting to set identical bottom==top')
-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
-manually.
+running the script::
-The target branch is configured by putting ``on-merge: backport to
-TARGETBRANCH`` in the milestone description on it's own line.
+ from matplotlib import my_matplotlib_module
+ my_matplotlib_module.set_range(0, 0) # set range
-If the bot is not working as expected, please report issues to
-`MeeseeksDev `__.
+will display
+.. code-block:: none
-.. _manual-backports:
+ UserWarning: Attempting to set identical bottom==top
+ warnings.warn('Attempting to set identical bottom==top')
-Manual backports
-----------------
+Modifying the module to use `._api.warn_external`::
-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
-message.
+ from matplotlib import _api
-We do a backport from main to v2.2.x assuming:
+ def set_range(bottom, top):
+ if bottom == top:
+ _api.warn_external('Attempting to set identical bottom==top')
-* ``matplotlib`` is a read-only remote branch of the matplotlib/matplotlib repo
+and running the same script will display
-The ``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.
+.. code-block:: none
-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 ``upstream``:
+ UserWarning: Attempting to set identical bottom==top
+ my_matplotlib_module.set_range(0, 0) # set range
-.. code-block:: bash
+.. _logging tutorial: https://docs.python.org/3/howto/logging.html#logging-basic-tutorial
- 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 ``git status``,
-and will have to be fixed by hand (search on ``>>>>>``). Once
-the conflict is resolved, you will have to re-add the file(s) to the branch
-and then continue the cherry pick:
+.. _licence-coding-guide:
-.. code-block:: bash
+.. include:: license.rst
+ :start-line: 2
- git add lib/matplotlib/conflicted_file.py
- git add lib/matplotlib/conflicted_file2.py
- git cherry-pick --continue
+.. toctree::
+ :hidden:
-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 ``main``!
+ license.rst
diff --git a/doc/devel/color_changes.rst b/doc/devel/color_changes.rst
deleted file mode 100644
index f7646ded7c14..000000000000
--- a/doc/devel/color_changes.rst
+++ /dev/null
@@ -1,136 +0,0 @@
-.. _color_changes:
-
-*********************
-Default color changes
-*********************
-
-As discussed at length `elsewhere `__ ,
-``jet`` is an
-empirically bad colormap and should not be the default colormap.
-Due to the position that changing the appearance of the plot breaks
-backward compatibility, this change has been put off for far longer
-than it should have been. In addition to changing the default color
-map we plan to take the chance to change the default color-cycle on
-plots and to adopt a different colormap for filled plots (``imshow``,
-``pcolor``, ``contourf``, etc) and for scatter like plots.
-
-
-Default heat map colormap
--------------------------
-
-The choice of a new colormap is fertile ground to bike-shedding ("No,
-it should be _this_ color") so we have a proposed set criteria (via
-Nathaniel Smith) to evaluate proposed colormaps.
-
-- it should be a sequential colormap, because diverging colormaps are
- really misleading unless you know where the "center" of the data is,
- and for a default colormap we generally won't.
-
-- it should be perceptually uniform, i.e., human subjective judgments
- of how far apart nearby colors are should correspond as linearly as
- possible to the difference between the numerical values they
- represent, at least locally.
-
-- it should have a perceptually uniform luminance ramp, i.e. if you
- convert to greyscale it should still be uniform. This is useful both
- in practical terms (greyscale printers are still a thing!) and
- because luminance is a very strong and natural cue to magnitude.
-
-- it should also have some kind of variation in hue, because hue
- variation is a really helpful additional cue to perception, having
- two cues is better than one, and there's no reason not to do it.
-
-- the hue variation should be chosen to produce reasonable results
- even for viewers with the more common types of
- colorblindness. (Which rules out things like red-to-green.)
-
-- For bonus points, it would be nice to choose a hue ramp that still
- works if you throw away the luminance variation, because then we
- could use the version with varying luminance for 2d plots, and the
- version with just hue variation for 3d plots. (In 3d plots you
- really want to reserve the luminance channel for lighting/shading,
- because your brain is *really* good at extracting 3d shape from
- luminance variation. If the 3d surface itself has massively varying
- luminance then this screws up the ability to see shape.)
-
-- Not infringe any existing IP
-
-Example script
-++++++++++++++
-
-Proposed colormaps
-++++++++++++++++++
-
-Default scatter colormap
-------------------------
-
-For heat-map like applications it can be desirable to cover as much of
-the luminance scale as possible, however when colormapping markers,
-having markers too close to white can be a problem. For that reason
-we propose using a different (but maybe related) colormap to the
-heat map for marker-based. The design parameters are the same as
-above, only with a more limited luminance variation.
-
-
-Example script
-++++++++++++++
-::
-
- import numpy as np
- import matplotlib.pyplot as plt
-
- np.random.seed(1234)
-
- fig, (ax1, ax2) = plt.subplots(1, 2)
-
- N = 50
- x = np.random.rand(N)
- y = np.random.rand(N)
- colors = np.random.rand(N)
- area = np.pi * (15 * np.random.rand(N))**2 # 0 to 15 point radiuses
-
- ax1.scatter(x, y, s=area, c=colors, alpha=0.5)
-
-
- X,Y = np.meshgrid(np.arange(0, 2*np.pi, .2),
- np.arange(0, 2*np.pi, .2))
- U = np.cos(X)
- V = np.sin(Y)
- Q = ax2.quiver(X, Y, U, V, units='width')
- qd = np.random.rand(np.prod(X.shape))
- Q.set_array(qd)
-
-Proposed colormaps
-++++++++++++++++++
-
-Color cycle / qualitative colormap
------------------------------------
-
-When plotting lines it is frequently desirable to plot multiple lines
-or artists which need to be distinguishable, but there is no inherent
-ordering.
-
-
-Example script
-++++++++++++++
-::
-
- import numpy as np
- import matplotlib.pyplot as plt
-
- fig, (ax1, ax2) = plt.subplots(1, 2)
-
- x = np.linspace(0, 1, 10)
-
- for j in range(10):
- ax1.plot(x, x * j)
-
-
- th = np.linspace(0, 2*np.pi, 1024)
- for j in np.linspace(0, np.pi, 10):
- ax2.plot(th, np.sin(th + j))
-
- ax2.set_xlim(0, 2*np.pi)
-
-Proposed color cycle
-++++++++++++++++++++
diff --git a/doc/devel/communication_guide.rst b/doc/devel/communication_guide.rst
index aed52be84e32..e44d9368da93 100644
--- a/doc/devel/communication_guide.rst
+++ b/doc/devel/communication_guide.rst
@@ -10,10 +10,10 @@ community venue managed by Matplotlib.
Our approach to community engagement is foremost guided by our :ref:`mission-statement`:
-* We demonstrate that we care about visualization as a practice
+* We demonstrate that we care about visualization as a practice.
* We deepen our practice and the community’s capacity to support users,
facilitate exploration, produce high quality visualizations, and be
- understandable and extensible
+ understandable and extensible.
* We showcase advanced use of the library without adding maintenance burden to
the documentation and recognize contributions that happen outside of the github
workflow.
@@ -21,7 +21,7 @@ Our approach to community engagement is foremost guided by our :ref:`mission-sta
who may no longer be active on GitHub, build relationships with potential
contributors, and connect with other projects and communities who use
Matplotlib.
-* In prioritizing understandability and extensiblity, we recognize that people
+* In prioritizing understandability and extensibility, we recognize that people
using Matplotlib, in whatever capacity, are part of our community. Doing so
empowers our community members to build community with each other, for example
by creating educational resources, building third party tools, and building
@@ -51,13 +51,14 @@ Social media
Active social media
^^^^^^^^^^^^^^^^^^^
-* https://twitter.com/matplotlib
+* https://bsky.app/profile/matplotlib.bsky.social
+* https://fosstodon.org/@matplotlib
+* https://x.com/matplotlib
* https://instagram.com/matplotart/
Official accounts
^^^^^^^^^^^^^^^^^
-* https://bsky.app/profile/matplotlib.bsky.social
-* https://fosstodon.org/@matplotlib
+
* https://www.tiktok.com/@matplotart
* https://www.youtube.com/matplotlib
@@ -89,7 +90,7 @@ media accounts:
* Everyone else should send an email to matplotlib-social-admin@numfocus.org:
- * Introduce yourself - github handle and participation in the community.
+ * Introduce yourself - GitHub handle and participation in the community.
* Describe the reason for wanting to moderate or contribute to social.
@@ -104,6 +105,8 @@ guidelines, ask on the :ref:`social-media-coordination` channels before posting.
General guidelines
------------------
+* Do not share information that violates Matplotlib's :ref:`code of conduct ` or does not align with Matplotlib's :ref:`mission-statement`.
+
* Focus on Matplotlib, 3rd party packages, and visualizations made with Matplotlib.
* These are also acceptable topics:
@@ -117,14 +120,15 @@ General guidelines
* Follow communication best practices:
- * Do not share non-expert visualizations when it could cause harm:
+ * Do not share non-expert visualizations when it could cause harm, e.g.:
- * e.g. https://twitter.com/matplotlib/status/1244178154618605568
+ * Could the information affect someone's decisions in a way that impacts their personal health or safety?
+ * Could the information be used as part of a politicised debate?
* Clearly state when the visualization data/conclusions cannot be verified.
* Do not rely on machine translations for sensitive visualization.
-* Verify sourcing of content (especially on instagram & blog):
+* Verify sourcing of content (especially on Instagram & blog):
* Instagram/blog: ensure mpl has right to repost/share content
* Make sure content is clearly cited:
@@ -144,7 +148,7 @@ Specifically:
* Visual media must conform to the guidelines of all sites it may be posted on:
- * https://help.twitter.com/en/rules-and-policies/twitter-rules
+ * https://help.x.com/en/rules-and-policies/x-rules
* https://help.instagram.com/477434105621119
* Emphasize the visualization techniques demonstrated by the visual media.
@@ -258,7 +262,7 @@ Changing the guidelines
As the person tasked with implementing these guidelines, the `community-manager`_
should be alerted to proposed changes. Similarly, specific platform guidelines
-(e.g. twitter, instagram) should be reviewed by the person responsible for that
+(e.g. X, Instagram) should be reviewed by the person responsible for that
platform, when different from the community manager. If there is no consensus,
decisions about guidelines revert to the community manager.
diff --git a/doc/devel/contribute.rst b/doc/devel/contribute.rst
index a7d81cbc06d9..558e19790d82 100644
--- a/doc/devel/contribute.rst
+++ b/doc/devel/contribute.rst
@@ -2,10 +2,9 @@
.. _contributing:
-==========
-Contribute
-==========
-
+******************
+Contributing guide
+******************
You've discovered a bug or something else you want to change
in Matplotlib — excellent!
@@ -13,853 +12,344 @@ You've worked out a way to fix it — even better!
You want to tell us about it — best of all!
-This project is a community effort, and everyone is welcome to contribute. Everyone
-within the community is expected to abide by our `code of conduct
-`_.
-
Below, you can find a number of ways to contribute, and how to connect with the
Matplotlib community.
-.. _start-contributing:
-
-Get started
-===========
-
-There is no pre-defined pathway for new contributors -- we recommend looking at
-existing issue and pull request discussions, and following the conversations
-during pull request reviews to get context. Or you can deep-dive into a subset
-of the code-base to understand what is going on.
-
-There are a few typical new contributor profiles:
-
-* **You are a Matplotlib user, and you see a bug, a potential improvement, or
- something that annoys you, and you can fix it.**
-
- You can search our issue tracker for an existing issue that describes your problem or
- open a new issue to inform us of the problem you observed and discuss the best approach
- to fix it. If your contributions would not be captured on GitHub (social media,
- communication, educational content), you can also reach out to us on gitter_,
- `Discourse `__ or attend any of our `community
- meetings `__.
-
-* **You are not a regular Matplotlib user but a domain expert: you know about
- visualization, 3D plotting, design, technical writing, statistics, or some
- other field where Matplotlib could be improved.**
-
- Awesome -- you have a focus on a specific application and domain and can
- start there. In this case, maintainers can help you figure out the best
- implementation; open an issue or pull request with a starting point, and we'll
- be happy to discuss technical approaches.
-
- If you prefer, you can use the `GitHub functionality for "draft" pull requests
- `__
- and request early feedback on whatever you are working on, but you should be
- aware that maintainers may not review your contribution unless it has the
- "Ready to review" state on GitHub.
-
-* **You are new to Matplotlib, both as a user and contributor, and want to start
- contributing but have yet to develop a particular interest.**
-
- Having some previous experience or relationship with the library can be very
- helpful when making open-source contributions. It helps you understand why
- things are the way they are and how they *should* be. Having first-hand
- experience and context is valuable both for what you can bring to the
- conversation (and given the breadth of Matplotlib's usage, there is a good
- chance it is a unique context in any given conversation) and make it easier to
- understand where other people are coming from.
-
- Understanding the entire codebase is a long-term project, and nobody expects
- you to do this right away. If you are determined to get started with
- Matplotlib and want to learn, going through the basic functionality,
- choosing something to focus on (3d, testing, documentation, animations, etc.)
- and gaining context on this area by reading the issues and pull requests
- touching these subjects is a reasonable approach.
-
-.. _get_connected:
-
-Get connected
-=============
-
-Do I really have something to contribute to Matplotlib?
--------------------------------------------------------
-
-100% yes. There are so many ways to contribute to our community.
-
-When in doubt, we recommend going together! Get connected with our community of
-active contributors, many of whom felt just like you when they started out and
-are happy to welcome you and support you as you get to know how we work, and
-where things are. Take a look at the next sections to learn more.
-
-Contributor incubator
----------------------
-
-The incubator is our non-public communication channel for new contributors. It
-is a private gitter_ (chat) room moderated by core Matplotlib developers where
-you can get guidance and support for your first few PRs. It's a place where you
-can ask questions about anything: how to use git, GitHub, how our PR review
-process works, technical questions about the code, what makes for good
-documentation or a blog post, how to get involved in community work, or get a
-"pre-review" on your PR.
-
-To join, please go to our public community_ channel, and ask to be added to
-``#incubator``. One of our core developers will see your message and will add you.
-
-New Contributors Meeting
-------------------------
-
-Once a month, we host a meeting to discuss topics that interest new
-contributors. Anyone can attend, present, or sit in and listen to the call.
-Among our attendees are fellow new contributors, as well as maintainers, and
-veteran contributors, who are keen to support onboarding of new folks and
-share their experience. You can find our community calendar link at the
-`Scientific Python website `_, and
-you can browse previous meeting notes on `GitHub
-`_.
-We recommend joining the meeting to clarify any doubts, or lingering
-questions you might have, and to get to know a few of the people behind the
-GitHub handles 😉. You can reach out to us on gitter_ for any clarifications or
-suggestions. We ❤ feedback!
-
-.. _new_contributors:
-
-Good first issues
------------------
-
-While any contributions are welcome, we have marked some issues as
-particularly suited for new contributors by the label `good first issue
-`_. These
-are well documented issues, that do not require a deep understanding of the
-internals of Matplotlib. The issues may additionally be tagged with a
-difficulty. ``Difficulty: Easy`` is suited for people with little Python
-experience. ``Difficulty: Medium`` and ``Difficulty: Hard`` require more
-programming experience. This could be for a variety of reasons, among them,
-though not necessarily all at the same time:
-
-- The issue is in areas of the code base which have more interdependencies,
- or legacy code.
-- It has less clearly defined tasks, which require some independent
- exploration, making suggestions, or follow-up discussions to clarify a good
- path to resolve the issue.
-- It involves Python features such as decorators and context managers, which
- have subtleties due to our implementation decisions.
-
-.. _managing_issues_prs:
-
-Work on an issue
-----------------
-
-In general, the Matplotlib project does not assign issues. Issues are
-"assigned" or "claimed" by opening a PR; there is no other assignment
-mechanism. If you have opened such a PR, please comment on the issue thread to
-avoid duplication of work. Please check if there is an existing PR for the
-issue you are addressing. If there is, try to work with the author by
-submitting reviews of their code or commenting on the PR rather than opening
-a new PR; duplicate PRs are subject to being closed. However, if the existing
-PR is an outline, unlikely to work, or stalled, and the original author is
-unresponsive, feel free to open a new PR referencing the old one.
-
-.. _submitting-a-bug-report:
-
-Submit a bug report
-===================
-
-If you find a bug in the code or documentation, do not hesitate to submit a
-ticket to the
-`Issue Tracker `_. You are
-also welcome to post feature requests or pull requests.
-
-If you are reporting a bug, please do your best to include the following:
-
-#. A short, top-level summary of the bug. In most cases, this should be 1-2
- sentences.
-
-#. A short, self-contained code snippet to reproduce the bug, ideally allowing
- a simple copy and paste to reproduce. Please do your best to reduce the code
- snippet to the minimum required.
-
-#. The actual outcome of the code snippet.
-
-#. The expected outcome of the code snippet.
-
-#. The Matplotlib version, Python version and platform that you are using. You
- can grab the version with the following commands::
-
- >>> import matplotlib
- >>> matplotlib.__version__
- '3.4.1'
- >>> import platform
- >>> platform.python_version()
- '3.9.2'
-
-We have preloaded the issue creation page with a Markdown form that you can
-use to organize this information.
-
-Thank you for your help in keeping bug reports complete, targeted and descriptive.
-
-.. _request-a-new-feature:
-
-Request a new feature
-=====================
-
-Please post feature requests to the
-`Issue Tracker `_.
-
-The Matplotlib developers will give feedback on the feature proposal. Since
-Matplotlib is an open source project with limited resources, we encourage
-users to then also
-:ref:`participate in the implementation `.
-
-.. _contributing-code:
-
-Contribute code
-===============
-
-.. _how-to-contribute:
-
-How to contribute
------------------
-
-The preferred way to contribute to Matplotlib is to fork the `main
-repository `__ on GitHub,
-then submit a "pull request" (PR). You can do this by cloning a copy of the
-Maplotlib repository to your own computer, or alternatively using
-`GitHub Codespaces `_, a cloud-based
-in-browser development environment that comes with the appropriated setup to
-contribute to Matplotlib.
-
-Workflow overview
-^^^^^^^^^^^^^^^^^
-
-A brief overview of the workflow is as follows.
-
-#. `Create an account `_ on GitHub if you do not
- already have one.
-
-#. Fork the `project repository `_ by
- clicking on the :octicon:`repo-forked` **Fork** button near the top of the page.
- This creates a copy of the code under your account on the GitHub server.
-
-#. Set up a development environment:
+Ways to contribute
+==================
+.. dropdown:: Do I really have something to contribute to Matplotlib?
+ :open:
+ :icon: person-fill
- .. tab-set::
+ 100% yes! There are so many ways to contribute to our community. Take a look
+ at the following sections to learn more.
- .. tab-item:: Local development
+ There are a few typical new contributor profiles:
- Clone this copy to your local disk::
+ * **You are a Matplotlib user, and you see a bug, a potential improvement, or
+ something that annoys you, and you can fix it.**
- git clone https://github.com//matplotlib.git
+ You can search our issue tracker for an existing issue that describes your problem or
+ open a new issue to inform us of the problem you observed and discuss the best approach
+ to fix it. If your contributions would not be captured on GitHub (social media,
+ communication, educational content), you can also reach out to us on gitter_,
+ `Discourse `__ or attend any of our `community
+ meetings `__.
- .. tab-item:: Using GitHub Codespaces
+ * **You are not a regular Matplotlib user but a domain expert: you know about
+ visualization, 3D plotting, design, technical writing, statistics, or some
+ other field where Matplotlib could be improved.**
- Check out the Matplotlib repository and activate your development environment:
+ Awesome — you have a focus on a specific application and domain and can
+ start there. In this case, maintainers can help you figure out the best
+ implementation; open an issue or pull request with a starting point, and we'll
+ be happy to discuss technical approaches.
- #. Open codespaces on your fork by clicking on the green "Code" button
- on the GitHub web interface and selecting the "Codespaces" tab.
+ If you prefer, you can use the `GitHub functionality for "draft" pull requests
+ `__
+ and request early feedback on whatever you are working on, but you should be
+ aware that maintainers may not review your contribution unless it has the
+ "Ready to review" state on GitHub.
- #. Next, click on "Open codespaces on ". You will be
- able to change branches later, so you can select the default
- ``main`` branch.
+ * **You are new to Matplotlib, both as a user and contributor, and want to start
+ contributing but have yet to develop a particular interest.**
- #. After the codespace is created, you will be taken to a new browser
- tab where you can use the terminal to activate a pre-defined conda
- environment called ``mpl-dev``::
+ Having some previous experience or relationship with the library can be very
+ helpful when making open-source contributions. It helps you understand why
+ things are the way they are and how they *should* be. Having first-hand
+ experience and context is valuable both for what you can bring to the
+ conversation (and given the breadth of Matplotlib's usage, there is a good
+ chance it is a unique context in any given conversation) and make it easier to
+ understand where other people are coming from.
- conda activate mpl-dev
+ Understanding the entire codebase is a long-term project, and nobody expects
+ you to do this right away. If you are determined to get started with
+ Matplotlib and want to learn, going through the basic functionality,
+ choosing something to focus on (3d, testing, documentation, animations, etc.)
+ and gaining context on this area by reading the issues and pull requests
+ touching these subjects is a reasonable approach.
+.. _contribute_code:
-#. Install the local version of Matplotlib with::
+Code
+----
+You want to implement a feature or fix a bug or help with maintenance - much
+appreciated! Our library source code is found in:
- python -m pip install --no-build-isolation --editable .[dev]
+* Python library code: :file:`lib/`
+* C-extension code: :file:`src/`
+* Tests: :file:`lib/matplotlib/tests/`
- See :ref:`installing_for_devs` for detailed instructions.
+Because many people use and work on Matplotlib, we have guidelines for keeping
+our code consistent and mitigating the impact of changes.
-#. Create a branch to hold your changes::
+* :ref:`coding_guidelines`
+* :ref:`api_changes`
+* :ref:`pr-guidelines`
- git checkout -b my-feature origin/main
+Code is contributed through pull requests, so we recommend that you start at
+:ref:`how-to-pull-request` If you get stuck, please reach out on the
+:ref:`contributor_incubator`
- and start making changes. Never work in the ``main`` branch!
+.. _contribute_documentation:
-#. Work on this task using Git to do the version control. Codespaces persist for
- some time (check the `documentation for details
- `_)
- and can be managed on https://github.com/codespaces. When you're done editing
- e.g., ``lib/matplotlib/collections.py``, do::
+Documentation
+-------------
- git add lib/matplotlib/collections.py
- git commit
-
- to record your changes in Git, then push them to your GitHub fork with::
-
- git push -u origin my-feature
-
-Open a pull request on Matplotlib
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Finally, go to the web page of *your fork* of the Matplotlib repo, and click
-**Compare & pull request** to send your changes to the maintainers for review.
-The base repository is ``matplotlib/matplotlib`` and the base branch is
-generally ``main``. For more guidance, see GitHub's `pull request tutorial
-`_.
-
-For more detailed instructions on how to set up Matplotlib for development and
-best practices for contribution, see :ref:`installing_for_devs`.
-
-GitHub Codespaces workflows
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-* If you need to open a GUI window with Matplotlib output on Codespaces, our
- configuration includes a `light-weight Fluxbox-based desktop
- `_.
- You can use it by connecting to this desktop via your web browser. To do this:
-
- #. Press ``F1`` or ``Ctrl/Cmd+Shift+P`` and select
- ``Ports: Focus on Ports View`` in the VSCode session to bring it into
- focus. Open the ports view in your tool, select the ``noVNC`` port, and
- click the Globe icon.
- #. In the browser that appears, click the Connect button and enter the desktop
- password (``vscode`` by default).
-
- Check the `GitHub instructions
- `_
- for more details on connecting to the desktop.
-
-* If you also built the documentation pages, you can view them using Codespaces.
- Use the "Extensions" icon in the activity bar to install the "Live Server"
- extension. Locate the ``doc/build/html`` folder in the Explorer, right click
- the file you want to open and select "Open with Live Server."
-
-.. _contributing_documentation:
-
-Contribute documentation
-========================
-
-You as an end-user of Matplotlib can make a valuable contribution because you
-more clearly see the potential for improvement than a core developer. For example, you can:
+You, as an end-user of Matplotlib can make a valuable contribution because you can
+more clearly see the potential for improvement than a core developer. For example,
+you can:
- Fix a typo
- Clarify a docstring
- Write or update an :ref:`example plot `
- Write or update a comprehensive :ref:`tutorial `
-The documentation source files live in the same GitHub repository as the code.
-Contributions are proposed and accepted through the pull request process.
-For details see :ref:`how-to-contribute`.
-
-If you have trouble getting started, you may instead open an `issue`_
-describing the intended improvement.
-
-.. _issue: https://github.com/matplotlib/matplotlib/issues
-
-.. seealso::
- * :ref:`documenting-matplotlib`
-
-.. _other_ways_to_contribute:
-
-Other ways to contribute
-========================
-
-It also helps us if you spread the word: reference the project from your blog
-and articles or link to it from your website! If Matplotlib contributes to a
-project that leads to a scientific publication, please follow the
-:doc:`/users/project/citing` guidelines.
-
-.. _coding_guidelines:
-
-Coding guidelines
-=================
-
-While the current state of the Matplotlib code base is not compliant with all
-of these guidelines, our goal in enforcing these constraints on new
-contributions is that it improves the readability and consistency of the code base
-going forward.
-
-PEP8, as enforced by flake8
----------------------------
-
-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__).
-
-.. _PEP8: https://www.python.org/dev/peps/pep-0008/
-.. _flake8: https://flake8.pycqa.org/
-.. _black: https://black.readthedocs.io/
-.. __: https://github.com/matplotlib/matplotlib/issues/18796
-.. __: https://github.com/psf/black/issues/148
-.. __: https://github.com/psf/black/issues/1984
-
-
-Package imports
----------------
-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 `.rcParams` using ``from
-matplotlib import rcParams``, but rather access it as ``mpl.rcParams``. This
-is because some modules are imported very early, before the `.rcParams`
-singleton is constructed.
-
-Variable names
---------------
-
-When feasible, please use our internal variable naming convention for objects
-of a given class and objects of any child class:
-
-+------------------------------------+---------------+------------------------------------------+
-| base class | variable | multiples |
-+====================================+===============+==========================================+
-| `~matplotlib.figure.FigureBase` | ``fig`` | |
-+------------------------------------+---------------+------------------------------------------+
-| `~matplotlib.axes.Axes` | ``ax`` | |
-+------------------------------------+---------------+------------------------------------------+
-| `~matplotlib.transforms.Transform` | ``trans`` | ``trans__`` |
-+ + + +
-| | | ``trans_`` when target is screen |
-+------------------------------------+---------------+------------------------------------------+
-
-Generally, denote more than one instance of the same class by adding suffixes to
-the variable names. If a format isn't specified in the table, use numbers or
-letters as appropriate.
-
-
-.. _type-hints:
-
-Type hints
-----------
-
-If you add new public API or change public API, update or add the
-corresponding `mypy `_ type hints.
-We generally use `stub files
-`_
-(``*.pyi``) to store the type information; for example ``colors.pyi`` contains
-the type information for ``colors.py``. A notable exception is ``pyplot.py``,
-which is type hinted inline.
-
-Type hints are checked by the mypy :ref:`pre-commit hook `
-and can often be verified using ``tools\stubtest.py`` and occasionally may
-require the use of ``tools\check_typehints.py``.
-
-
-.. _new-changed-api:
-
-API changes and new features
-----------------------------
-
-API consistency and stability are of great value; Therefore, API changes
-(e.g. signature changes, behavior changes, removals) will only be conducted
-if the added benefit is worth the effort of adapting existing code.
-
-Because we are a visualization library, our primary output is the final
-visualization the user sees; therefore, the appearance of the figure is part of
-the API and any changes, either semantic or :ref:`esthetic `,
-are backwards-incompatible API changes.
-
-.. _api_whats_new:
-
-Announce changes, deprecations, and new features
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-When adding or changing the API in a backward in-compatible way, please add the
-appropriate :ref:`versioning directive ` and document it
-for the release notes and add the entry to the appropriate folder:
-
-+-------------------+-----------------------------+----------------------------------------------+
-| addition | versioning directive | announcement folder |
-+===================+=============================+==============================================+
-| new feature | ``.. versionadded:: 3.N`` | :file:`doc/users/next_whats_new/` |
-+-------------------+-----------------------------+----------------------------------------------+
-| API change | ``.. versionchanged:: 3.N`` | :file:`doc/api/next_api_changes/[kind]` |
-+-------------------+-----------------------------+----------------------------------------------+
-
-API deprecations are first introduced and then expired. During the introduction
-period, users are warned that the API *will* change in the future.
-During the expiration period, code is changed as described in the notice posted
-during the introductory period.
-
-+-----------+--------------------------------------------------+----------------------------------------------+
-| stage | required changes | announcement folder |
-+===========+==================================================+==============================================+
-| introduce | :ref:`introduce deprecation ` | :file:`doc/api/next_api_changes/deprecation` |
-+-----------+--------------------------------------------------+----------------------------------------------+
-| expire | :ref:`expire deprecation ` | :file:`doc/api/next_api_changes/[kind]` |
-+-----------+--------------------------------------------------+----------------------------------------------+
-
-For both change notes and what's new, please avoid using references in section
-titles, as it causes links to be confusing in the table of contents. Instead,
-ensure that a reference is included in the descriptive text.
-
-API Change Notes
-""""""""""""""""
-.. include:: ../api/next_api_changes/README.rst
- :start-line: 5
- :end-line: 31
-
-What's new
-""""""""""
-.. include:: ../users/next_whats_new/README.rst
- :start-line: 5
- :end-line: 24
-
-
-Deprecation
-^^^^^^^^^^^
-API changes in Matplotlib have to be performed following the deprecation process
-below, except in very rare circumstances as deemed necessary by the development
-team. This ensures that users are notified before the change will take effect
-and thus prevents unexpected breaking of code.
-
-Rules
-"""""
-- Deprecations are targeted at the next point.release (e.g. 3.x)
-- Deprecated API is generally removed two point-releases after introduction
- of the deprecation. Longer deprecations can be imposed by core developers on
- a case-by-case basis to give more time for the transition
-- The old API must remain fully functional during the deprecation period
-- If alternatives to the deprecated API exist, they should be available
- during the deprecation period
-- If in doubt, decisions about API changes are finally made by the
- API consistency lead developer
+Our code is documented inline in the source code files in :file:`matplotlib/lib`.
+Our website structure mirrors our folder structure, meaning that a narrative
+document's URL roughly corresponds to its location in our folder structure:
-.. _intro-deprecation:
-
-Introduce deprecation
-"""""""""""""""""""""
-
-#. Create :ref:`deprecation notice `
-
-#. If possible, issue a `~matplotlib.MatplotlibDeprecationWarning` when the
- deprecated API is used. There are a number of helper tools for this:
-
- - Use ``_api.warn_deprecated()`` for general deprecation warnings
- - Use the decorator ``@_api.deprecated`` to deprecate classes, functions,
- methods, or properties
- - Use ``@_api.deprecate_privatize_attribute`` to annotate deprecation of
- attributes while keeping the internal private version.
- - To warn on changes of the function signature, use the decorators
- ``@_api.delete_parameter``, ``@_api.rename_parameter``, and
- ``@_api.make_keyword_only``
+.. grid:: 1 1 2 2
- All these helpers take a first parameter *since*, which should be set to
- the next point release, e.g. "3.x".
-
- You can use standard rst cross references in *alternative*.
-
-#. Make appropriate changes to the type hints in the associated ``.pyi`` file.
- The general guideline is to match runtime reported behavior.
-
- - Items marked with ``@_api.deprecated`` or ``@_api.deprecate_privatize_attribute``
- are generally kept during the expiry period, and thus no changes are needed on
- introduction.
- - Items decorated with ``@_api.rename_parameter`` or ``@_api.make_keyword_only``
- report the *new* (post deprecation) signature at runtime, and thus *should* be
- updated on introduction.
- - Items decorated with ``@_api.delete_parameter`` should include a default value hint
- for the deleted parameter, even if it did not previously have one (e.g.
- ``param: = ...``).
-
-.. _expire-deprecation:
-
-Expire deprecation
-""""""""""""""""""
-
-#. Create :ref:`deprecation announcement `. For the content,
- you can usually copy the deprecation notice and adapt it slightly.
-
-#. Change the code functionality and remove any related deprecation warnings.
-
-#. Make appropriate changes to the type hints in the associated ``.pyi`` file.
+ .. grid-item:: using the library
- - Items marked with ``@_api.deprecated`` or ``@_api.deprecate_privatize_attribute``
- are to be removed on expiry.
- - Items decorated with ``@_api.rename_parameter`` or ``@_api.make_keyword_only``
- will have been updated at introduction, and require no change now.
- - Items decorated with ``@_api.delete_parameter`` will need to be updated to the
- final signature, in the same way as the ``.py`` file signature is updated.
- - Any entries in :file:`ci/mypy-stubtest-allowlist.txt` which indicate a deprecation
- version should be double checked. In most cases this is not needed, though some
- items were never type hinted in the first place and were added to this file
- instead. For removed items that were not in the stub file, only deleting from the
- allowlist is required.
+ * :file:`galleries/plot_types/`
+ * :file:`users/getting_started/`
+ * :file:`galleries/user_explain/`
+ * :file:`galleries/tutorials/`
+ * :file:`galleries/examples/`
+ * :file:`doc/api/`
-Adding new API and features
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. grid-item:: information about the library
-Every new function, parameter and attribute that is not explicitly marked as
-private (i.e., starts with an underscore) becomes part of Matplotlib's public
-API. As discussed above, changing the existing API is cumbersome. Therefore,
-take particular care when adding new API:
+ * :file:`doc/install/`
+ * :file:`doc/project/`
+ * :file:`doc/devel/`
+ * :file:`doc/users/resources/index.rst`
+ * :file:`doc/users/faq.rst`
-- Mark helper functions and internal attributes as private by prefixing them
- with an underscore.
-- Carefully think about good names for your functions and variables.
-- Try to adopt patterns and naming conventions from existing parts of the
- Matplotlib API.
-- Consider making as many arguments keyword-only as possible. See also
- `API Evolution the Right Way -- Add Parameters Compatibly`__.
- __ https://emptysqua.re/blog/api-evolution-the-right-way/#adding-parameters
+Other documentation is generated from the following external sources:
+* matplotlib.org homepage: https://github.com/matplotlib/mpl-brochure-site
+* cheat sheets: https://github.com/matplotlib/cheatsheets
+* third party packages: https://github.com/matplotlib/mpl-third-party
-.. _versioning-directives:
+Instructions and guidelines for contributing documentation are found in:
-Versioning directives
-"""""""""""""""""""""
+* :doc:`document`
+* :doc:`style_guide`
+* :doc:`tag_guidelines`
-When making a backward incompatible change, please add a versioning directive in
-the docstring. The directives should be placed at the end of a description block.
-For example::
+Documentation is contributed through pull requests, so we recommend that you start
+at :ref:`how-to-pull-request`. If that feels intimidating, we encourage you to
+`open an issue`_ describing what improvements you would make. If you get stuck,
+please reach out on the :ref:`contributor_incubator`
- class Foo:
- """
- This is the summary.
+.. _`open an issue`: https://github.com/matplotlib/matplotlib/issues/new?assignees=&labels=Documentation&projects=&template=documentation.yml&title=%5BDoc%5D%3A+
- Followed by a longer description block.
+.. _contribute_triage:
- Consisting of multiple lines and paragraphs.
+Triage
+------
+We appreciate your help keeping the `issue tracker `_
+organized because it is our centralized location for feature requests,
+bug reports, tracking major projects, and discussing priorities. Some examples of what
+we mean by triage are:
- .. versionadded:: 3.5
+* labeling issues and pull requests
+* verifying bug reports
+* debugging and resolving issues
+* linking to related issues, discussion, and external work
- Parameters
- ----------
- a : int
- The first parameter.
- b: bool, default: False
- This was added later.
+Our triage process is discussed in detail in :ref:`bug_triaging`.
- .. versionadded:: 3.6
- """
+If you have any questions about the process, please reach out on the
+:ref:`contributor_incubator`
- 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.
-
-
-New modules and files: installation
------------------------------------
-
-* If you have added new files or directories, or reorganized existing ones, make sure the
- new files are included in the :file:`meson.build` in the corresponding directories.
-* New modules *may* be typed inline or using parallel stub file like existing modules.
-
-C/C++ extensions
-----------------
-
-* Extensions may be written in C or C++.
-
-* Code style should conform to PEP7 (understanding that PEP7 doesn't
- address C++, but most of its admonitions still apply).
-
-* Python/C interface code should be kept separate from the core C/C++
- code. The interface code should be named :file:`FOO_wrap.cpp` or
- :file:`FOO_wrapper.cpp`.
-
-* Header file documentation (aka docstrings) should be in Numpydoc
- format. We don't plan on using automated tools for these
- docstrings, and the Numpydoc format is well understood in the
- scientific Python community.
-
-* C/C++ code in the :file:`extern/` directory is vendored, and should be kept
- close to upstream whenever possible. It can be modified to fix bugs or
- implement new features only if the required changes cannot be made elsewhere
- in the codebase. In particular, avoid making style fixes to it.
+.. _other_ways_to_contribute:
-.. _keyword-argument-processing:
+Community
+---------
+Matplotlib's community is built by its members, if you would like to help out
+see our :ref:`communications-guidelines`.
-Keyword argument processing
----------------------------
+It helps us if you spread the word: reference the project from your blog
+and articles or link to it from your website!
-Matplotlib makes extensive use of ``**kwargs`` for pass-through customizations
-from one function to another. A typical example is
-`~matplotlib.axes.Axes.text`. The definition of `matplotlib.pyplot.text` is a
-simple pass-through to `matplotlib.axes.Axes.text`::
+If Matplotlib contributes to a project that leads to a scientific publication,
+please cite us following the :doc:`/project/citing` guidelines.
- # in pyplot.py
- def text(x, y, s, fontdict=None, **kwargs):
- return gca().text(x, y, s, fontdict=fontdict, **kwargs)
+If you have developed an extension to Matplotlib, please consider adding it to our
+`third party package `_ list.
-`matplotlib.axes.Axes.text` (simplified for illustration) just
-passes all ``args`` and ``kwargs`` on to ``matplotlib.text.Text.__init__``::
- # in axes/_axes.py
- def text(self, x, y, s, fontdict=None, **kwargs):
- t = Text(x=x, y=y, text=s, **kwargs)
+.. _generative_ai:
-and ``matplotlib.text.Text.__init__`` (again, simplified)
-just passes them on to the `matplotlib.artist.Artist.update` method::
- # in text.py
- def __init__(self, x=0, y=0, text='', **kwargs):
- super().__init__()
- self.update(kwargs)
+Restrictions on Generative AI Usage
+===================================
-``update`` does the work looking for methods named like
-``set_property`` if ``property`` is a keyword argument. i.e., no one
-looks at the keywords, they just get passed through the API to the
-artist constructor which looks for suitably named methods and calls
-them with the value.
+We expect authentic engagement in our community. Be wary of posting output
+from Large Language Models or similar generative AI as comments on GitHub or
+our discourse server, as such comments tend to be formulaic and low content.
+If you use generative AI tools as an aid in developing code or documentation
+changes, ensure that you fully understand the proposed changes and can explain
+why they are the correct approach and an improvement to the current state.
-As a general rule, the use of ``**kwargs`` should be reserved for
-pass-through keyword arguments, as in the example above. If all the
-keyword args are to be used in the function, and not passed
-on, use the key/value keyword args in the function definition rather
-than the ``**kwargs`` idiom.
-In some cases, you may want to consume some keys in the local
-function, and let others pass through. Instead of popping arguments to
-use off ``**kwargs``, specify them as keyword-only arguments to the local
-function. This makes it obvious at a glance which arguments will be
-consumed in the function. For example, in
-:meth:`~matplotlib.axes.Axes.plot`, ``scalex`` and ``scaley`` are
-local arguments and the rest are passed on as
-:meth:`~matplotlib.lines.Line2D` keyword arguments::
+.. _new_contributors:
- # in axes/_axes.py
- def plot(self, *args, scalex=True, scaley=True, **kwargs):
- lines = []
- for line in self._get_lines(*args, **kwargs):
- self.add_line(line)
- lines.append(line)
+New contributors
+================
-.. _using_logging:
+Everyone comes to the project from a different place — in terms of experience
+and interest — so there is no one-size-fits-all path to getting involved. We
+recommend looking at existing issue or pull request discussions, and following
+the conversations during pull request reviews to get context. Or you can
+deep-dive into a subset of the code-base to understand what is going on.
-Using logging for debug messages
---------------------------------
+.. _new_contributors_meeting:
-Matplotlib uses the standard Python `logging` library to write verbose
-warnings, information, and debug messages. Please use it! In all those places
-you write `print` calls to do your debugging, try using `logging.debug`
-instead!
+New contributors meeting
+------------------------
+Once a month, we host a meeting to discuss topics that interest new
+contributors. Anyone can attend, present, or sit in and listen to the call.
+Among our attendees are fellow new contributors, as well as maintainers, and
+veteran contributors, who are keen to support onboarding of new folks and
+share their experience. You can find our community calendar link at the
+`Scientific Python website `_, and
+you can browse previous meeting notes on `GitHub
+`_.
+We recommend joining the meeting to clarify any doubts, or lingering
+questions you might have, and to get to know a few of the people behind the
+GitHub handles 😉. You can reach out to us on gitter_ for any clarifications or
+suggestions. We ❤ feedback!
-To include `logging` in your module, at the top of the module, you need to
-``import logging``. Then calls in your code like::
+.. _contributor_incubator:
- _log = logging.getLogger(__name__) # right after the imports
+Contributor incubator
+---------------------
- # code
- # more code
- _log.info('Here is some information')
- _log.debug('Here is some more detailed information')
+The incubator is our non-public communication channel for new contributors. It
+is a private gitter_ (chat) room moderated by core Matplotlib developers where
+you can get guidance and support for your first few PRs. It's a place where you
+can ask questions about anything: how to use git, GitHub, how our PR review
+process works, technical questions about the code, what makes for good
+documentation or a blog post, how to get involved in community work, or get a
+"pre-review" on your PR.
-will log to a logger named ``matplotlib.yourmodulename``.
+To join, please go to our public community_ channel, and ask to be added to
+``#incubator``. One of our core developers will see your message and will add you.
-If an end-user of Matplotlib sets up `logging` to display at levels more
-verbose than ``logging.WARNING`` in their code with the Matplotlib-provided
-helper::
+.. _gitter: https://gitter.im/matplotlib/matplotlib
+.. _community: https://gitter.im/matplotlib/community
- plt.set_loglevel("debug")
+.. _good_first_issues:
-or manually with ::
+Good first issues
+-----------------
- import logging
- logging.basicConfig(level=logging.DEBUG)
- import matplotlib.pyplot as plt
+While any contributions are welcome, we have marked some issues as
+particularly suited for new contributors by the label `good first issue
+`_. These
+are well documented issues, that do not require a deep understanding of the
+internals of Matplotlib. The issues may additionally be tagged with a
+difficulty. ``Difficulty: Easy`` is suited for people with little Python
+experience. ``Difficulty: Medium`` and ``Difficulty: Hard`` require more
+programming experience. This could be for a variety of reasons, among them,
+though not necessarily all at the same time:
-Then they will receive messages like
+- The issue is in areas of the code base which have more interdependencies,
+ or legacy code.
+- It has less clearly defined tasks, which require some independent
+ exploration, making suggestions, or follow-up discussions to clarify a good
+ path to resolve the issue.
+- It involves Python features such as decorators and context managers, which
+ have subtleties due to our implementation decisions.
-.. code-block:: none
+.. _first_contribution:
- DEBUG:matplotlib.backends:backend MacOSX version unknown
- DEBUG:matplotlib.yourmodulename:Here is some information
- DEBUG:matplotlib.yourmodulename:Here is some more detailed information
+First contributions
+-------------------
-Avoid using pre-computed strings (``f-strings``, ``str.format``,etc.) for logging because
-of security and performance issues, and because they interfere with style handlers. For
-example, use ``_log.error('hello %s', 'world')`` rather than ``_log.error('hello
-{}'.format('world'))`` or ``_log.error(f'hello {s}')``.
+If this is your first open source contribution, or your first time contributing to Matplotlib,
+and you need help or guidance finding a good first issue, look no further. This section will
+guide you through each step:
-Which logging level to use?
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
+1. Navigate to the `issues page `_.
+2. Filter labels with `"Difficulty: Easy" `_
+ & `"Good first Issue" `_ (optional).
+3. Click on an issue you would like to work on, and check to see if the issue has a pull request opened to resolve it.
-There are five levels at which you can emit messages.
+ * A good way to judge if you chose a suitable issue is by asking yourself, "Can I independently submit a PR in 1-2 weeks?"
+4. Check existing pull requests (e.g., :ghpull:`28476`) and filter by the issue number to make sure the issue is not in progress:
-- `logging.critical` and `logging.error` are really only there for errors that
- will end the use of the library but not kill the interpreter.
-- `logging.warning` and `._api.warn_external` are used to warn the user,
- see below.
-- `logging.info` is for information that the user may want to know if the
- program behaves oddly. They are not displayed by default. For instance, if
- an object isn't drawn because its position is ``NaN``, that can usually
- be ignored, but a mystified user could call
- ``logging.basicConfig(level=logging.INFO)`` and get an error message that
- says why.
-- `logging.debug` is the least likely to be displayed, and hence can be the
- most verbose. "Expected" code paths (e.g., reporting normal intermediate
- steps of layouting or rendering) should only log at this level.
+ * If the issue has a pull request (is in progress), tag the user working on the issue, and ask to collaborate (optional).
+ * If a pull request does not exist, create a `draft pull request `_ and follow the `pull request guidelines `_.
+5. Please familiarize yourself with the pull request template (see below),
+ and ensure you understand/are able to complete the template when you open your pull request.
+ Additional information can be found in the `pull request guidelines `_.
-By default, `logging` displays all log messages at levels higher than
-``logging.WARNING`` to `sys.stderr`.
+.. dropdown:: `Pull request template `_
+ :open:
-The `logging tutorial`_ suggests that the difference between `logging.warning`
-and `._api.warn_external` (which uses `warnings.warn`) is that
-`._api.warn_external` should be used for things the user must change to stop
-the warning (typically in the source), whereas `logging.warning` can be more
-persistent. Moreover, note that `._api.warn_external` will by default only
-emit a given warning *once* for each line of user code, whereas
-`logging.warning` will display the message every time it is called.
+ .. literalinclude:: ../../.github/PULL_REQUEST_TEMPLATE.md
+ :language: markdown
-By default, `warnings.warn` displays the line of code that has the ``warn``
-call. This usually isn't more informative than the warning message itself.
-Therefore, Matplotlib uses `._api.warn_external` which uses `warnings.warn`,
-but goes up the stack and displays the first line of code outside of
-Matplotlib. For example, for the module::
+.. _get_connected:
- # in my_matplotlib_module.py
- import warnings
+Get connected
+=============
- def set_range(bottom, top):
- if bottom == top:
- warnings.warn('Attempting to set identical bottom==top')
+When in doubt, we recommend going together! Get connected with our community of
+active contributors, many of whom felt just like you when they started out and
+are happy to welcome you and support you as you get to know how we work, and
+where things are. You can reach out on any of our :ref:`communication-channels`.
+For development questions we recommend reaching out on our development gitter_
+chat room and for community questions reach out at community_.
-running the script::
+.. _gitter: https://gitter.im/matplotlib/matplotlib
+.. _community: https://gitter.im/matplotlib/community
- from matplotlib import my_matplotlib_module
- my_matplotlib_module.set_range(0, 0) # set range
+.. _managing_issues_prs:
-will display
+Choose an issue
+===============
-.. code-block:: none
+In general, the Matplotlib project does not assign issues. Issues are
+"assigned" or "claimed" by opening a PR; there is no other assignment
+mechanism. If you have opened such a PR, please comment on the issue thread to
+avoid duplication of work. Please check if there is an existing PR for the
+issue you are addressing. If there is, try to work with the author by
+submitting reviews of their code or commenting on the PR rather than opening
+a new PR; duplicate PRs are subject to being closed. However, if the existing
+PR is an outline, unlikely to work, or stalled, and the original author is
+unresponsive, feel free to open a new PR referencing the old one.
- UserWarning: Attempting to set identical bottom==top
- warnings.warn('Attempting to set identical bottom==top')
+.. _how-to-pull-request:
-Modifying the module to use `._api.warn_external`::
+Start a pull request
+====================
- from matplotlib import _api
+The preferred way to contribute to Matplotlib is to fork the `main
+repository `__ on GitHub,
+then submit a "pull request" (PR). To work on a a pull request:
- def set_range(bottom, top):
- if bottom == top:
- _api.warn_external('Attempting to set identical bottom==top')
+#. **First** set up a development environment, either by cloning a copy of the
+ Matplotlib repository to your own computer or by using Github codespaces, by
+ following the instructions in :ref:`installing_for_devs`
-and running the same script will display
+#. **Then** start solving the issue, following the guidance in
+ :ref:`development workflow `
-.. code-block:: none
+#. **As part of verifying your changes** check that your contribution meets
+ the :ref:`pull request guidelines `
+ and then :ref:`open a pull request `.
- UserWarning: Attempting to set identical bottom==top
- my_matplotlib_module.set_range(0, 0) # set range
+#. **Finally** follow up with maintainers on the PR if waiting more than a few days for
+ feedback. :ref:`Update the pull request ` as needed.
-.. _logging tutorial: https://docs.python.org/3/howto/logging.html#logging-basic-tutorial
-.. _gitter: https://gitter.im/matplotlib/matplotlib
-.. _community: https://gitter.im/matplotlib/community
+If you have questions of any sort, reach out on the :ref:`contributor_incubator` and join
+the :ref:`new_contributors_meeting`.
diff --git a/doc/devel/development_setup.rst b/doc/devel/development_setup.rst
index 6e24c085829d..45b95e48e7ff 100644
--- a/doc/devel/development_setup.rst
+++ b/doc/devel/development_setup.rst
@@ -1,3 +1,5 @@
+.. highlight:: bash
+
.. redirect-from:: /devel/gitwash/configure_git
.. redirect-from:: /devel/gitwash/dot2_dot3
.. redirect-from:: /devel/gitwash/following_latest
@@ -26,14 +28,37 @@ Fork the Matplotlib repository
Matplotlib is hosted at https://github.com/matplotlib/matplotlib.git. If you
plan on solving issues or submitting pull requests to the main Matplotlib
-repository, you should first *fork* this repository by visiting
-https://github.com/matplotlib/matplotlib.git and clicking on the
-``Fork`` :octicon:`repo-forked` button on the top right of the page. See
-`the GitHub documentation `__
-for more details.
+repository, you should first fork this repository by *clicking* the
+:octicon:`repo-forked` **Fork** button near the top of the `project repository `_ page.
+
+This creates a copy of the code under your account on the GitHub server. See `the GitHub
+documentation `__ for more details.
+
+Set up development environment
+==============================
+
+You can either work locally on your machine, or online in
+`GitHub Codespaces `_, a cloud-based in-browser development
+environment.
+
+
+:local: If you are making extensive or frequent contributions to Matplotlib then it
+ is probably worth taking the time to set up on your local machine: As well as
+ having the convenience of your local familiar tools, you will not need to worry
+ about Codespace's monthly usage limits.
+
+:codespaces: If you are making a one-off, relatively simple, change then working in
+ GitHub Codespaces can be a good option because most of the setting
+ up is done for you and you can skip the next few sections.
+
+If you want to use Codespaces, skip to :ref:`development-codespaces`,
+otherwise, continue with the next section.
+
+Create local environment
+------------------------
-Retrieve the latest version of the code
-=======================================
+Get most recent code
+^^^^^^^^^^^^^^^^^^^^
Now that your fork of the repository lives under your GitHub username, you can
retrieve the most recent version of the source code with one of the following
@@ -105,12 +130,14 @@ code, as described in :ref:`development-workflow`.
.. _dev-environment:
Create a dedicated environment
-==============================
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
You should set up a dedicated environment to decouple your Matplotlib
development from other Python and Matplotlib installations on your system.
-The simplest way to do this is to use either Python's virtual environment
-`venv`_ or `conda`_.
+We recommend using one of the following options for a dedicated development environment
+because these options are configured to install the Python dependencies as part of their
+setup.
.. _venv: https://docs.python.org/3/library/venv.html
.. _conda: https://docs.conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html
@@ -123,11 +150,27 @@ The simplest way to do this is to use either Python's virtual environment
python -m venv
- and activate it with one of the following ::
+ and activate it with one of the following :
+
+ .. tab-set::
+
+ .. tab-item:: Linux and macOS
+
+ .. code-block:: bash
+
+ source /bin/activate # Linux/macOS
+
+ .. tab-item:: Windows cmd.exe
+
+ .. code-block:: bat
+
+ \Scripts\activate.bat
+
+ .. tab-item:: Windows PowerShell
- source /bin/activate # Linux/macOS
- \Scripts\activate.bat # Windows cmd.exe
- \Scripts\Activate.ps1 # Windows PowerShell
+ .. code-block:: ps1con
+
+ \Scripts\Activate.ps1
On some systems, you may need to type ``python3`` instead of ``python``.
For a discussion of the technical reasons, see `PEP-394 `_.
@@ -136,6 +179,8 @@ The simplest way to do this is to use either Python's virtual environment
pip install -r requirements/dev/dev-requirements.txt
+ Remember to activate the environment whenever you start working on Matplotlib!
+
.. tab-item:: conda environment
Create a new `conda`_ environment and install the Python dependencies with ::
@@ -151,20 +196,71 @@ The simplest way to do this is to use either Python's virtual environment
conda activate mpl-dev
-Remember to activate the environment whenever you start working on Matplotlib.
+ Remember to activate the environment whenever you start working on Matplotlib!
+
+
+Install external dependencies
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Python dependencies were installed as part of :ref:`setting up the environment `.
+Additionally, the following non-Python dependencies must also be installed locally:
+
+.. rst-class:: checklist
+
+* :ref:`compile-build-dependencies`
+* :ref:`external tools used by the documentation build `
+
+
+For a full list of dependencies, see :ref:`dependencies`. External dependencies do not
+need to be installed when working in codespaces.
+
+.. _development-codespaces:
-Install Dependencies
-====================
+Create GitHub Codespace :octicon:`codespaces`
+---------------------------------------------
-Most Python dependencies will be installed when :ref:`setting up the environment `
-but non-Python dependencies like C++ compilers, LaTeX, and other system applications
-must be installed separately.
+`GitHub Codespaces `_ is a cloud-based
+in-browser development environment that comes with the appropriate setup to
+contribute to Matplotlib.
-.. toctree::
- :maxdepth: 2
+#. Open codespaces on your fork by clicking on the green :octicon:`code` ``Code``
+ button on the GitHub web interface and selecting the ``Codespaces`` tab.
- ../users/installing/dependencies
+#. Next, click on "Open codespaces on ". You will be
+ able to change branches later, so you can select the default
+ ``main`` branch.
+#. After the codespace is created, you will be taken to a new browser
+ tab where you can use the terminal to activate a pre-defined conda
+ environment called ``mpl-dev``::
+
+ conda activate mpl-dev
+
+Remember to activate the *mpl-dev* environment whenever you start working on
+Matplotlib.
+
+If you need to open a GUI window with Matplotlib output on Codespaces, our
+configuration includes a `light-weight Fluxbox-based desktop
+`_.
+You can use it by connecting to this desktop via your web browser. To do this:
+
+#. Press ``F1`` or ``Ctrl/Cmd+Shift+P`` and select
+ ``Ports: Focus on Ports View`` in the VSCode session to bring it into
+ focus. Open the ports view in your tool, select the ``noVNC`` port, and
+ click the Globe icon.
+#. In the browser that appears, click the Connect button and enter the desktop
+ password (``vscode`` by default).
+
+Check the `GitHub instructions
+`_
+for more details on connecting to the desktop.
+
+If you also built the documentation pages, you can view them using Codespaces.
+Use the "Extensions" icon in the activity bar to install the "Live Server"
+extension. Locate the ``doc/build/html`` folder in the Explorer, right click
+the file you want to open and select "Open with Live Server."
+
+.. _`github-codespaces`: https://docs.github.com/codespaces
.. _development-install:
@@ -174,7 +270,7 @@ Install Matplotlib in editable mode
Install Matplotlib in editable mode from the :file:`matplotlib` directory using the
command ::
- python -m pip install --verbose --no-build-isolation --editable .[dev]
+ python -m pip install --verbose --no-build-isolation --editable ".[dev]"
The 'editable/develop mode' builds everything and places links in your Python environment
so that Python will be able to import Matplotlib from your development source directory.
@@ -252,3 +348,9 @@ listed in ``.pre-commit-config.yaml``, against the full codebase with ::
To run a particular hook manually, run ``pre-commit run`` with the hook id ::
pre-commit run --all-files
+
+
+Please note that the ``mypy`` pre-commit hook cannot check the :ref:`type-hints`
+for new functions; instead the stubs for new functions are checked using the
+``stubtest`` :ref:`CI check ` and can be checked locally using
+``tox -e stubtest``.
diff --git a/doc/devel/development_workflow.rst b/doc/devel/development_workflow.rst
index edb21bb862cd..16766278f658 100644
--- a/doc/devel/development_workflow.rst
+++ b/doc/devel/development_workflow.rst
@@ -28,6 +28,30 @@ why you did it, we recommend the following:
Matplotlib developers can give feedback and eventually include your suggested
code into the ``main`` branch.
+Overview
+--------
+
+After :ref:`setting up a development environment `, the typical
+workflow is:
+
+#. Fetch all changes from ``upstream/main``::
+
+ git fetch upstream
+
+#. Start a new *feature branch* from ``upstream/main``::
+
+ git checkout -b my-feature upstream/main
+
+#. When you're done editing, e.g., ``lib/matplotlib/collections.py``, record your changes in Git::
+
+ git add lib/matplotlib/collections.py
+ git commit -m 'a commit message'
+
+#. Push the changes to your GitHub fork::
+
+ git push -u origin my-feature
+
+
.. _update-mirror-main:
Update the ``main`` branch
@@ -49,16 +73,14 @@ Make a new feature branch
When you are ready to make some changes to the code, you should start a new
branch. Branches that are for a collection of related edits are often called
-'feature branches'.
-
-Making a new branch for each set of related changes will make it easier for
-someone reviewing your branch to see what you are doing.
+'feature branches'. Making a new branch for each set of related changes will make it
+easier for someone reviewing your branch to see what you are doing.
Choose an informative name for the branch to remind yourself and the rest of us
what the changes in the branch are for. For example ``add-ability-to-fly``, or
``bugfix-for-issue-42``.
-::
+The process for creating a new feature branch is::
# Update the main branch
git fetch upstream
@@ -79,19 +101,6 @@ default, git will have a link to your fork of the GitHub repo, called
git push origin my-new-feature
-In git >= 1.7 you can ensure that the link is correctly set by using the
-``--set-upstream`` option::
-
- git push --set-upstream origin my-new-feature
-
-From now on git will know that ``my-new-feature`` is related to the
-``my-new-feature`` branch in the GitHub repo.
-
-If you first opened the pull request from your ``main`` branch and then
-converted it to a feature branch, you will need to close the original pull
-request and open a new pull request from the renamed branch. See
-`GitHub: working with branches
-`_.
.. _edit-flow:
@@ -129,13 +138,31 @@ The editing workflow
Note the ``-am`` options to ``commit``. The ``m`` flag signals that you are
going to type a message on the command line. The ``a`` flag stages every
file that has been modified, except files listed in ``.gitignore``. For more
- information, see `why the -a flag?`_ and the
- `git commit `_ manual page.
+ information, see the `git commit `_ manual page.
#. To push the changes up to your forked repo on GitHub, do a ``git
push``.
-.. _why the -a flag?: http://gitready.com/beginner/2009/01/18/the-staging-area.html
+Verify your changes
+===================
+
+Check that your change does what you intend. For code changes:
+
+* If the issue you are working on provided a code example, run that example
+ against your branch and check that you now get the desired result. Note that
+ adapting the issue example is often a good way to create a new test.
+
+* Run the tests to check that your change has not had unintended consequences
+ on existing functionality. See :ref:`run_tests`.
+
+For documentation changes, build the documentation locally to check that
+it renders how you intended and that any new links work correctly. See
+:ref:`build_docs`.
+
+This is also a good time to look through the :ref:`pr-author-guidelines` and
+address as many of the relevant points as you can.
+
+.. _open-pull-request:
Open a pull request
===================
@@ -143,6 +170,11 @@ Open a pull request
When you are ready to ask for someone to review your code and consider a merge,
`submit your Pull Request (PR) `_.
+Go to the web page of *your fork* of the Matplotlib repo, and click
+``Compare & pull request`` to send your changes to the maintainers for review.
+The base repository is ``matplotlib/matplotlib`` and the base branch is
+generally ``main``.
+
Enter a title for the set of changes with some explanation of what you've done.
Mention anything you'd like particular attention for - such as a
complicated change or some code you are not happy with.
@@ -151,6 +183,9 @@ If you don't think your request is ready to be merged, just say so in your pull
request message and use the "Draft PR" feature of GitHub. This is a good way of
getting some preliminary code review.
+For more guidance on the mechanics of making a pull request, see GitHub's
+`pull request tutorial `_.
+
.. _update-pull-request:
Update a pull request
@@ -167,6 +202,17 @@ You can achieve this by using
git commit -a --amend --no-edit
git push [your-remote-repo] [your-branch] --force-with-lease
+.. tip::
+ Instead of typing your branch name every time, you only need to type the following once to link the remote branch to the local branch::
+
+ git push --set-upstream origin my-new-feature
+
+ From now on git will know that ``my-new-feature`` is related to the
+ ``my-new-feature`` branch in the GitHub repo. After this, you will be able to
+ push your changes with::
+
+ git push
+
Manage commit history
=====================
@@ -452,48 +498,86 @@ Automated tests
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 ``WARNING``.
- - 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.
.. _tox: https://tox.readthedocs.io/
-* 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
- ``doc/`` or ``galleries/``).
- - ``[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
+* Codecov and CodeQL are currently for information only. Their failure is not
+ necessarily a blocker.
- - ``[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.
+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.
+
+.. list-table::
+ :header-rows: 1
+ :stub-columns: 1
+ :widths: 20 20 60
+
+ * - Name
+ - Check
+ - Tips for finding cause of failure
+ * - Linting
+ - :ref:`code style `
+ - Errors are displayed as annotations on the pull request diff.
+ * - | Mypy
+ | Stubtest
+ - :ref:`static type hints `
+ - Errors are displayed as annotations on the pull request diff.
+ * - CircleCI
+ - :ref:`documentation build `
+ - Search the CircleCI log for ``WARNING``.
+ * - | GitHub Actions
+ | AppVeyor
+ | Azure pipelines
+ - :ref:`tests `
+ - | Search the log for ``FAILURES``. Subsequent section should contain information
+ on failed tests.
+ |
+ | On Azure, find the images as *artifacts* of the Azure job:
+ | 1. Click *Details* on the check on the GitHub PR page.
+ | 2. Click *View more details on Azure Pipelines* to go to Azure.
+ | 3. On the overview page *artifacts* are listed in the section *Related*.
+
+Skip CI checks
+--------------
+
+If you know only a subset of CI checks need to be run, you can skip unneeded CI checks
+on individual commits by including the following strings in the commit message:
+
+.. list-table::
+ :header-rows: 1
+ :stub-columns: 1
+ :widths: 25 20 55
+
+ * - String
+ - Effect
+ - Notes
+ * - ``[ci doc]``
+ - Only run documentation checks.
+ - | For when you have only changed documentation.
+ | ``[ci doc]`` is applied automatically when the changes are only to files in
+ ``doc/**/`` or ``galleries/**/``
+ * - ``[skip doc]``
+ - Skip documentation checks.
+ - For when you didn't change documentation.
+ * - ``[skip appveyor]``
+ - Skip AppVeyor run.
+ - Substring must be in first line of commit message.
+ * - ``[skip azp]``
+ - Skip Azure Pipelines.
+ -
+ * - ``[skip actions]``
+ - Skip GitHub Actions.
+ -
+ * - ``[skip ci]``
+ - Skip all CI checks.
+ - Use only for changes where documentation checks and unit tests do not apply.
+
+
+``[skip actions]`` and ``[skip ci]`` only skip Github Actions CI workflows that are
+triggered on ``on: push`` and ``on: pull_request`` events. For more information,
+see `Skipping workflow runs`_.
+
+.. _`Skipping workflow runs`: https://docs.github.com/en/actions/managing-workflow-runs/skipping-workflow-runs
diff --git a/doc/devel/document.rst b/doc/devel/document.rst
index 476a40c320b8..20c30acf66aa 100644
--- a/doc/devel/document.rst
+++ b/doc/devel/document.rst
@@ -52,6 +52,8 @@ To build the documentation you will need to
particular the :ref:`additional dependencies ` required to
build the documentation.
+.. _build_docs:
+
Build the docs
--------------
@@ -64,6 +66,11 @@ used. To build the documentation in html format, cd into :file:`doc/` and run:
make html
+.. note::
+
+ Since the documentation is very large, the first build may take 10-20 minutes,
+ depending on your machine. Subsequent builds will be faster.
+
Other useful invocations include
.. code-block:: sh
@@ -234,7 +241,7 @@ Examples:
.. code-block:: rst
- See the :doc:`/users/installing/index`
+ See the :doc:`/install/index`
See the tutorial :ref:`quick_start`
@@ -242,14 +249,14 @@ Examples:
will render as:
- See the :doc:`/users/installing/index`
+ See the :doc:`/install/index`
See the tutorial :ref:`quick_start`
See the example :doc:`/gallery/lines_bars_and_markers/simple_plot`
Sections can also be given reference labels. For instance from the
-:doc:`/users/installing/index` link:
+:doc:`/install/index` link:
.. code-block:: rst
@@ -312,7 +319,10 @@ target is unambiguous you can simply leave them out:
`.LineCollection`
-and the link still works: `.LineCollection`.
+and the link still works: `.LineCollection`. Note that you should typically include
+the leading dot. It tells Sphinx to look for the given name in the whole project.
+See also the explanation at `Sphinx: Cross-referencing Python objects
+`_.
If there are multiple code elements with the same name (e.g. ``plot()`` is a
method in multiple classes), you'll have to extend the definition:
@@ -389,11 +399,14 @@ expression in the Matplotlib figure. In these cases, you can use the
.. _writing-docstrings:
-Write docstrings
-================
+Write API documentation
+=======================
-Most of the API documentation is written in docstrings. These are comment
-blocks in source code that explain how the code works.
+The API reference documentation describes the library interfaces, e.g. inputs, outputs,
+and expected behavior. Most of the API documentation is written in docstrings. These are
+comment blocks in source code that explain how the code works. All docstrings should
+conform to the `numpydoc docstring guide`_. Much of the ReST_ syntax discussed above
+(:ref:`writing-rest-pages`) can be used for links and references.
.. note::
@@ -402,11 +415,11 @@ blocks in source code that explain how the code works.
you may see in the source code. Pull requests updating docstrings to
the current style are very welcome.
-All new or edited docstrings should conform to the `numpydoc docstring guide`_.
-Much of the ReST_ syntax discussed above (:ref:`writing-rest-pages`) can be
-used for links and references. These docstrings eventually populate the
-:file:`doc/api` directory and form the reference documentation for the
-library.
+The pages in :file:`doc/api` are purely technical definitions of
+layout; therefore new API reference documentation should be added to the module
+docstrings. This placement keeps all API reference documentation about a module in the
+same file. These module docstrings eventually populate the :file:`doc/api` directory
+and form the reference documentation for the library.
Example docstring
-----------------
@@ -856,6 +869,26 @@ Plots can also be directly placed inside docstrings. Details are in
An advantage of this style over referencing an example script is that the
code will also appear in interactive docstrings.
+.. _inheritance-diagrams:
+
+Generate inheritance diagrams
+-----------------------------
+
+Class inheritance diagrams can be generated with the Sphinx
+`inheritance-diagram`_ directive.
+
+.. _inheritance-diagram: https://www.sphinx-doc.org/en/master/usage/extensions/inheritance.html
+
+Example:
+
+.. code-block:: rst
+
+ .. inheritance-diagram:: matplotlib.patches matplotlib.lines matplotlib.text
+ :parts: 2
+
+.. inheritance-diagram:: matplotlib.patches matplotlib.lines matplotlib.text
+ :parts: 2
+
.. _writing-examples-and-tutorials:
Write examples and tutorials
@@ -886,8 +919,6 @@ these ``*.rst`` files from the source location to the build location (see
In the Python files, to exclude an example from having a plot generated, insert
"sgskip" somewhere in the filename.
-Format examples
----------------
The format of these files is relatively straightforward. Properly
formatted comment blocks are treated as ReST_ text, the code is
@@ -929,7 +960,7 @@ like:
The first comment block is treated as ReST_ text. The other comment blocks
render as comments in :doc:`/gallery/lines_bars_and_markers/simple_plot`.
-Tutorials are made with the exact same mechanism, except they are longer, and
+Tutorials are made with the exact same mechanism, except they are longer and
typically have more than one comment block (i.e. :ref:`quick_start`). The
first comment block can be the same as the example above. Subsequent blocks of
ReST text are delimited by the line ``# %%`` :
@@ -1045,6 +1076,90 @@ subdirectory, but :file:`galleries/users_explain/artists` has a mix of
any ``*.rst`` files to a ``:toctree:``, either in the ``README.txt`` or in a
manual ``index.rst``.
+Examples guidelines
+-------------------
+
+The gallery of examples contains visual demonstrations of matplotlib features. Gallery
+examples exist so that users can scan through visual examples. Unlike tutorials or user
+guides, gallery examples teach by demonstration, rather than by explanation or
+instruction.
+
+Gallery examples should contain a very brief description of *what* is being demonstrated
+and, when relevant, *how* it is achieved. Explanations should be brief, providing only
+the minimal context necessary for understanding the example. Cross-link related
+documentation (e.g. tutorials, user guides and API entries) and tag the example with
+related concepts.
+
+Format
+^^^^^^
+
+All :ref:`examples-index` should aim to follow these guidelines:
+
+:Title: Describe content in a short sentence (approx. 1-6 words). Do not use *demo* as
+ this is implied by being an example. Avoid implied verbs such as *create*,
+ *make*, etc, e.g. *annotated heatmaps* is preferred to *create annotated
+ heatmaps*. Use the simple present tense when a verb is necessary, e.g. *Fill the
+ area between two curves*
+
+:Description: In a short paragraph (approx 1-3 sentences) describe what visualization
+ technique is being demonstrated and how library features are used to
+ execute the technique, e.g. *Set bar color and bar label entries using the
+ color and label parameters of ~Axes.bar*
+
+:Plot: Clearly demonstrate the subject and, when possible, show edge cases and different
+ applications. While the plot should be visually appealing, prioritize keeping the
+ plot uncluttered.
+
+:Code: Write the minimum necessary to showcase the feature that is the focus of the
+ example. Avoid custom styling and annotation (titles, legends, colors, etc.)
+ when it will not improve the clarity of the example.
+
+ Use short comments sparingly to describe what hard to follow parts of code are
+ doing. When more context or explanation is required, add a text paragraph before
+ the code example.
+
+:doc:`/gallery/misc/bbox_intersect` demonstrates the point of visual examples.
+This example is "messy" in that it's hard to categorize, but the gallery is the right
+spot for it because it makes sense to find it by visual search
+
+:doc:`/gallery/images_contours_and_fields/colormap_interactive_adjustment` is an
+example of a good descriptive title that briefly summarizes how the showcased
+library features are used to implement the demonstrated visualization technique.
+
+:doc:`/gallery/lines_bars_and_markers/lines_with_ticks_demo` is an example of having a
+minimal amount of code necessary to showcase the feature. The lack of extraneous code
+makes it easier for the reader to map which parts of code correspond to which parts of
+the plot.
+
+Figure size
+^^^^^^^^^^^
+When customizing figure sizes, we aim to avoid downscaling in rendered HTML docs.
+The current width limit (induced by *pydata-sphinx-theme*) is 720px, i.e.
+``figsize=(7.2, ...)``, or 896px if the page does not have subsections and
+thus does not have the "On this page" navigation on the right-hand side.
+
+
+Plot types guidelines
+---------------------
+
+The :ref:`plot_types` gallery provides an overview of the types of visualizations that
+Matplotlib provides out of the box, meaning that there is a high-level API for
+generating each type of chart. Additions to this gallery are generally discouraged
+because this gallery is heavily curated and tightly scoped to methods on
+`matplotlib.axes.Axes`.
+
+Format
+^^^^^^
+:title: Method signature with required arguments, e.g. ``plot(x, y)``
+:description: In one sentence, describe the visualization that the method produces and
+ link to the API documentation, e.g. *Draws a bar chart. See ~Axes.bar*.
+ When necessary, add an additional sentence explaining the use case for
+ this function vs a very similar one, e.g. stairs vs step.
+:plot: Use data with a self explanatory structure to illustrate the type of data this
+ plotting method is typically used for.
+:code: The code should be about 5-10 lines with minimal customization. Plots in
+ this gallery use the ``_mpl-gallery`` stylesheet for a uniform aesthetic.
+
Miscellaneous
=============
@@ -1081,28 +1196,6 @@ Use the full path for this directive, relative to the doc root at
found by users at ``http://matplotlib.org/stable/old_topic/old_info2``.
For clarity, do not use relative links.
-
-.. _inheritance-diagrams:
-
-Generate inheritance diagrams
------------------------------
-
-Class inheritance diagrams can be generated with the Sphinx
-`inheritance-diagram`_ directive.
-
-.. _inheritance-diagram: https://www.sphinx-doc.org/en/master/usage/extensions/inheritance.html
-
-Example:
-
-.. code-block:: rst
-
- .. inheritance-diagram:: matplotlib.patches matplotlib.lines matplotlib.text
- :parts: 2
-
-.. inheritance-diagram:: matplotlib.patches matplotlib.lines matplotlib.text
- :parts: 2
-
-
Navbar and style
----------------
@@ -1111,7 +1204,13 @@ are centralized as a sphinx theme at
`mpl_sphinx_theme `_. Changes to the
style or topbar should be made there to propagate across all subprojects.
-.. TODO: Add section about uploading docs
+
+Analytics
+==========
+
+Documentation page analytics are available at
+https://views.scientific-python.org/matplotlib.org.
+
.. _ReST: https://docutils.sourceforge.io/rst.html
.. _Sphinx: http://www.sphinx-doc.org
diff --git a/doc/devel/index.rst b/doc/devel/index.rst
index e6e16266968b..7591359ec811 100644
--- a/doc/devel/index.rst
+++ b/doc/devel/index.rst
@@ -13,76 +13,145 @@ Contribute
of this document as it will have the most up to date installation
instructions, workflow process, and contributing guidelines.
-Thank you for your interest in helping to improve Matplotlib! There are various
-ways to contribute: optimizing and refactoring code, detailing unclear
-documentation and writing new examples, reporting and fixing bugs and requesting
-and implementing new features, helping the community...
+:octicon:`heart;1em;sd-text-info` Thank you for your interest in helping to improve
+Matplotlib! :octicon:`heart;1em;sd-text-info`
-New contributors
-================
+This project is a community effort, and everyone is welcome to contribute. Everyone
+within the community is expected to abide by our :ref:`code of conduct `.
+
+There are various ways to contribute, such as optimizing and refactoring code,
+detailing unclear documentation and writing new examples, helping the community,
+reporting and fixing bugs, requesting and implementing new features...
+
+.. _submitting-a-bug-report:
+.. _request-a-new-feature:
+
+GitHub issue tracker
+====================
+
+The `issue tracker `_ serves as the
+centralized location for making feature requests, reporting bugs, identifying major
+projects to work on, and discussing priorities.
+
+We have preloaded the issue creation page with markdown forms requesting the information
+we need to triage issues and we welcome you to add any additional information or
+context that may be necessary for resolving the issue:
.. grid:: 1 1 2 2
- :class-row: sd-align-minor-center
- .. grid-item::
- :class: sd-fs-5
+ .. grid-item-card::
+ :class-header: sd-fs-5
+
+ :octicon:`bug;1em;sd-text-info` **Submit a bug report**
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ Thank you for your help in keeping bug reports targeted and descriptive.
+
+ .. button-link:: https://github.com/matplotlib/matplotlib/issues/new/choose
+ :expand:
+ :color: primary
+
+ Report a bug
+
+ .. grid-item-card::
+ :class-header: sd-fs-5
- :octicon:`info;1em;sd-text-info` :ref:`Where should I start? `
+ :octicon:`light-bulb;1em;sd-text-info` **Request a new feature**
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- :octicon:`question;1em;sd-text-info` :ref:`Where should I ask questions? `
+ Thank you for your help in keeping feature requests well defined and tightly scoped.
- :octicon:`issue-opened;1em;sd-text-info` :ref:`What are "good-first-issues"? `
+ .. button-link:: https://github.com/matplotlib/matplotlib/issues/new/choose
+ :expand:
+ :color: primary
- :octicon:`git-pull-request;1em;sd-text-info` :ref:`How do I claim an issue? `
+ Request a feature
- :octicon:`codespaces;1em;sd-text-info` :ref:`How do I start a pull request? `
+Since Matplotlib is an open source project with limited resources, we encourage users
+to also :ref:`participate ` in fixing bugs and implementing new
+features.
+
+Contributing guide
+==================
+
+We welcome you to get more involved with the Matplotlib project! If you are new
+to contributing, we recommend that you first read our
+:ref:`contributing guide`:
+
+.. toctree::
+ :hidden:
+
+ contribute
+
+.. grid:: 1 1 2 2
+ :class-row: sd-fs-5 sd-align-minor-center
.. grid-item::
.. grid:: 1
:gutter: 1
- :class-row: sd-fs-5
.. grid-item-card::
- :link: request-a-new-feature
+ :link: contribute_code
:link-type: ref
- :shadow: none
+ :class-card: sd-shadow-none
+ :class-body: sd-text-{primary}
- :octicon:`light-bulb;1em;sd-text-info` Request new feature
+ :octicon:`code;1em;sd-text-info` Contribute code
.. grid-item-card::
- :link: submitting-a-bug-report
+ :link: contribute_documentation
:link-type: ref
- :shadow: none
+ :class-card: sd-shadow-none
+ :class-body: sd-text-{primary}
- :octicon:`bug;1em;sd-text-info` Submit bug report
+ :octicon:`note;1em;sd-text-info` Write documentation
.. grid-item-card::
- :link: contributing-code
+ :link: contribute_triage
:link-type: ref
- :shadow: none
+ :class-card: sd-shadow-none
+ :class-body: sd-text-{primary}
- :octicon:`code;1em;sd-text-info` Contribute code
+ :octicon:`issue-opened;1em;sd-text-info` Triage issues
.. grid-item-card::
- :link: documenting-matplotlib
+ :link: other_ways_to_contribute
:link-type: ref
- :shadow: none
+ :class-card: sd-shadow-none
+ :class-body: sd-text-{primary}
- :octicon:`note;1em;sd-text-info` Write documentation
+ :octicon:`globe;1em;sd-text-info` Build community
-If you are new to contributing, we recommend that you first read our
-:ref:`contributing guide`. If you are contributing code or
-documentation, please follow our guides for setting up and managing a
-:ref:`development environment and workflow`.
-For code, documentation, or triage, please follow the corresponding
-:ref:`contribution guidelines `.
+ .. grid-item::
+
+ .. grid:: 1
+ :gutter: 1
+
+ .. grid-item::
+
+ :octicon:`info;1em;sd-text-info` :ref:`Is this my first contribution? `
+
+ .. grid-item::
+
+ :octicon:`question;1em;sd-text-info` :ref:`Where do I ask questions? `
+
+ .. grid-item::
+
+ :octicon:`git-pull-request;1em;sd-text-info` :ref:`How do I choose an issue? `
+
+ .. grid-item::
+
+ :octicon:`codespaces;1em;sd-text-info` :ref:`How do I start a pull request? `
.. _development_environment:
-Development environment
-=======================
+Development workflow
+====================
+
+If you are contributing code or documentation, please follow our guide for setting up
+and managing a development environment and workflow:
.. grid:: 1 1 2 2
@@ -91,9 +160,9 @@ Development environment
**Install**
^^^
-
+ .. rst-class:: section-toc
.. toctree::
- :maxdepth: 2
+ :maxdepth: 4
development_setup
@@ -120,6 +189,11 @@ Development environment
Policies and guidelines
=======================
+These policies and guidelines help us maintain consistency in the various types
+of maintenance work. If you are writing code or documentation, following these policies
+helps maintainers more easily review your work. If you are helping triage, community
+manage, or release manage, these guidelines describe how our current process works.
+
.. grid:: 1 1 2 2
:class-row: sf-fs-1
:gutter: 2
@@ -130,12 +204,11 @@ Policies and guidelines
**Code**
^^^
- | :ref:`coding_guidelines`
-
.. toctree::
:maxdepth: 1
coding_guide
+ api_changes
testing
.. grid-item-card::
@@ -154,12 +227,14 @@ Policies and guidelines
.. grid-item-card::
:shadow: none
- **Triage**
+ **Triage And Review**
^^^
- | :ref:`bug_triaging`
- | :ref:`triage_team`
- | :ref:`triage_workflow`
+ .. toctree::
+ :maxdepth: 1
+
+ triage
+ pr_guide
.. grid-item-card::
:shadow: none
@@ -174,11 +249,3 @@ Policies and guidelines
communication_guide
min_dep_policy
MEP/index
-
-.. toctree::
- :hidden:
-
- contribute
- triage
- license
- color_changes
diff --git a/doc/devel/license.rst b/doc/devel/license.rst
index 8474fa432ff4..7596f2f92348 100644
--- a/doc/devel/license.rst
+++ b/doc/devel/license.rst
@@ -1,7 +1,7 @@
.. _license-discussion:
-Licenses
-========
+Licenses for contributed code
+=============================
Matplotlib only uses BSD compatible code. If you bring in code from
another project make sure it has a PSF, BSD, MIT or compatible license
diff --git a/doc/devel/min_dep_policy.rst b/doc/devel/min_dep_policy.rst
index dd8e069f0b94..81a84491bc4a 100644
--- a/doc/devel/min_dep_policy.rst
+++ b/doc/devel/min_dep_policy.rst
@@ -4,10 +4,11 @@
Dependency version policy
=========================
-For the purpose of this document, 'minor version' is in the sense of
-SemVer (major, minor, patch) and includes both major and minor
-releases. For projects that use date-based versioning, every release
-is a 'minor version'.
+For the purpose of this document, 'minor version' is in the sense of SemVer
+(major, minor, patch) or 'meso version' in the sense of `EffVer
+`_ (macro, meso, micro). It includes both
+major/macro and minor/meso releases. For projects that use date-based
+versioning, every release is a 'minor version'.
Matplotlib follows `NEP 29
`__.
@@ -48,6 +49,17 @@ without compiled extensions
We will only bump these dependencies as we need new features or the old
versions no longer support our minimum NumPy or Python.
+We will work around bugs in our dependencies when practical.
+
+IPython and Matplotlib do not formally depend on each other, however there is
+practical coupling for the integration of Matplotlib's UI into IPython and
+IPykernel. We will ensure this integration works with at least minor or major
+versions of IPython and IPykernel released in the 24 months prior to our
+planned release date. Matplotlib may or may not work with older versions and
+we will not warn if used with IPython or IPykernel outside of this window.
+
+
+
Test and documentation dependencies
===================================
@@ -57,8 +69,10 @@ support for old versions. However, we need to be careful to not
over-run what down-stream packagers support (as most of the run the
tests and build the documentation as part of the packaging process).
-We will support at least minor versions of the development
-dependencies released in the 12 months prior to our planned release.
+We will support at least minor versions of the development dependencies
+released in the 12 months prior to our planned release. Specific versions that
+are known to be buggy may be excluded from support using the finest-grained
+filtering that is practical.
We will only bump these as needed or versions no longer support our
minimum Python and NumPy.
@@ -75,6 +89,20 @@ In the case of GUI frameworks for which we rely on Python bindings being
available, we will also drop support for bindings so old that they don't
support any Python version that we support.
+Security issues in dependencies
+===============================
+
+Generally, we do not adjust the supported versions of dependencies based on
+security vulnerabilities. We are a library not an application
+and the version constraints on our dependencies indicate what will work (not
+what is wise to use). Users and packagers can install newer versions of the
+dependencies at their discretion and evaluation of risk and impact. In
+contrast, if we were to adjust our minimum supported version it is very hard
+for a user to override our judgment.
+
+If Matplotlib aids in exploiting the underlying vulnerability we should treat
+that as a critical bug in Matplotlib.
+
.. _list-of-dependency-min-versions:
List of dependency versions
@@ -87,6 +115,9 @@ specification of the dependencies.
========== ======== ======
Matplotlib Python NumPy
========== ======== ======
+3.11 3.11 1.25.0
+`3.10`_ 3.10 1.23.0
+`3.9`_ 3.9 1.23.0
`3.8`_ 3.9 1.21.0
`3.7`_ 3.8 1.20.0
`3.6`_ 3.8 1.19.0
@@ -107,6 +138,8 @@ Matplotlib Python NumPy
1.0 2.4 1.1
========== ======== ======
+.. _`3.10`: https://matplotlib.org/3.10.0/devel/dependencies.html
+.. _`3.9`: https://matplotlib.org/3.9.0/devel/dependencies.html
.. _`3.8`: https://matplotlib.org/3.8.0/devel/dependencies.html
.. _`3.7`: https://matplotlib.org/3.7.0/devel/dependencies.html
.. _`3.6`: https://matplotlib.org/3.6.0/devel/dependencies.html
@@ -122,3 +155,50 @@ Matplotlib Python NumPy
.. _`1.5`: https://matplotlib.org/1.5.0/users/installing.html#required-dependencies
.. _`1.4`: https://matplotlib.org/1.4.0/users/installing.html#required-dependencies
.. _`1.3`: https://matplotlib.org/1.3.0/users/installing.html#build-requirements
+
+
+Updating Python and NumPy versions
+==================================
+
+To update the minimum versions of Python we need to update:
+
+- ``pyproject.toml`` (classifiers, requires-python, ``[tool.ruff]`` target-version)
+- ``environment.yml``
+- ``doc/install/dependencies.rst``
+- ``doc/devel/min_dep_policy.rst`` (this file)
+- CI configuration files (circle, GHA, azure)
+- ``tox.ini``
+
+To update the minimum NumPy we need to update:
+
+- ``pyproject.toml``
+- ``environment.yml``
+- ``doc/install/dependencies.rst``
+- ``doc/devel/min_dep_policy.rst`` (this file)
+- ``requirements/testing/minver.txt``
+- ``lib/matplotlib/__init__.py`` (matplotlib._check_versions())
+
+
+The work to leverage new features or remove workarounds for no-longer supported
+versions should be done in a follow-on PRs to keep the version bump PRs well
+scoped.
+
+In both cases add an api_changes/development with the following template:
+
+.. code-block:: rst
+
+ Increase to minimum supported versions of dependencies
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ For Matplotlib 3.ZZ, the :ref:`minimum supported versions ` are
+ being bumped:
+
+ +------------+-----------------+----------------+
+ | Dependency | min in mpl3.N | min in mpl3.M |
+ +============+=================+================+
+ | Python | 3.XX | 3.AA |
+ | NumPy | 1.YY | 1.BB |
+ +------------+-----------------+----------------+
+
+ This is consistent with our :ref:`min_deps_policy` and `SPEC0
+ `__
diff --git a/doc/devel/pr_guide.rst b/doc/devel/pr_guide.rst
new file mode 100644
index 000000000000..a02b52ad5a38
--- /dev/null
+++ b/doc/devel/pr_guide.rst
@@ -0,0 +1,378 @@
+.. _pr-guidelines:
+
+***********************
+Pull request guidelines
+***********************
+
+`Pull requests (PRs) on GitHub
+`__
+are the mechanism for contributing to Matplotlib's code and documentation.
+
+We value contributions from people with all levels of experience. In particular,
+if this is your first PR not everything has to be perfect. We'll guide you
+through the PR process. Nevertheless, please try to follow our guidelines as well
+as you can to help make the PR process quick and smooth. If your pull request is
+incomplete or a work-in-progress, please mark it as a `draft pull requests `_
+on GitHub and specify what feedback from the developers would be helpful.
+
+Please be patient with reviewers. We try our best to respond quickly, but we have
+limited bandwidth. If there is no feedback within a couple of days, please ping
+us by posting a comment to your PR or reaching out on a :ref:`communication channel `
+
+
+.. _pr-author-guidelines:
+
+Summary for pull request authors
+================================
+
+We recommend that you check that your contribution complies with the following
+guidelines before submitting a pull request:
+
+.. rst-class:: checklist
+
+* Changes, both new features and bugfixes, should have good test coverage. See
+ :ref:`testing` for more details.
+
+* Update the :ref:`documentation ` if necessary.
+
+* All public methods should have informative docstrings with sample usage when
+ appropriate. Use the :ref:`docstring standards `.
+
+* For high-level plotting functions, consider adding a small example to the
+ :ref:`examples gallery `.
+
+* If you add a new feature or change the API in a backward-incompatible
+ way, please document it as described in :ref:`api_changes`.
+
+* Code should follow our conventions as documented in our :ref:`coding_guidelines`.
+
+* When adding or changing public function signatures, add :ref:`type hints `.
+
+* When adding keyword arguments, see our guide to :ref:`keyword-argument-processing`.
+
+When opening a pull request on Github, please ensure that:
+
+.. rst-class:: checklist
+
+* Changes were made on a :ref:`feature branch `.
+
+* :ref:`pre-commit ` checks for spelling, formatting, etc pass
+
+* The pull request targets the :ref:`main branch `
+
+* 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. For more
+ details, see `linking an issue and pull request `__.
+
+* :ref:`pr-automated-tests` pass
+
+For guidance on creating and managing a pull request, please see our
+:ref:`contributing ` and :ref:`pull request workflow `
+guides.
+
+
+Summary for pull request reviewers
+==================================
+
+.. redirect-from:: /devel/maintainer_workflow
+
+**Please help review and merge PRs!**
+
+If you have commit rights, then you are trusted to use them. Please be patient
+and `kind `__ with contributors.
+
+When reviewing, please ensure that the pull request satisfies the following
+requirements before merging it:
+
+Content
+-------
+
+.. rst-class:: checklist
+
+* Is the feature / bugfix reasonable?
+* Does the PR conform with the :ref:`coding_guidelines`?
+* Is the :ref:`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.
+
+Workflow
+--------
+.. rst-class:: checklist
+
+* Make sure all :ref:`automated tests ` pass.
+* The PR should :ref:`target the main branch `.
+* Tag with descriptive :ref:`labels `.
+* Set the :ref:`milestone `.
+* Keep an eye on the :ref:`number of commits `.
+* Approve if all of the above topics are handled.
+* :ref:`Merge ` if a sufficient number of approvals is reached.
+
+.. _pr-guidelines-details:
+
+Detailed guidelines
+===================
+
+.. _pr-documentation:
+
+Documentation
+-------------
+
+* 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 ``Examples`` section 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 :file:`examples` directory, which will be
+ rendered to the examples gallery in the documentation.
+
+* Build the docs and make sure all formatting warnings are addressed.
+
+* See :ref:`documenting-matplotlib` for our documentation style guide.
+
+.. _pr-labels:
+
+Labels
+------
+
+* 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.
+
+.. _pr-milestones:
+
+Milestones
+----------
+
+Set the milestone according to these guidelines:
+
+* *New features and API changes* are milestoned for the next meso release
+ ``v3.N.0``.
+
+* *Bugfixes, tests for released code, and docstring changes* may be milestoned
+ for the next micro release ``v3.N.M``.
+
+* *Documentation changes* (only .rst files and examples) may be milestoned
+ ``v3.N-doc``.
+
+If multiple rules apply, choose the first matching from the above list. See
+:ref:`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 :ref:`automatic backport ` for milestones which have
+a corresponding branch.
+
+.. _pr-merging:
+
+Merging
+-------
+As a guiding principle, we require two `approvals`_ from core developers (those
+with commit rights) before merging a pull request. This two-pairs-of-eyes
+strategy shall ensure a consistent project direction and prevent accidental
+mistakes. It is permissible to merge with one approval if the change is not
+fundamental and can easily be reverted at any time in the future.
+
+.. _approvals: https://docs.github.com/en/github/collaborating-with-pull-requests/reviewing-changes-in-pull-requests
+
+Some explicit rules following from this:
+
+* *Documentation and examples* may be merged with a single approval. Use
+ the threshold "is this better than it was?" as the review criteria.
+
+* Minor *infrastructure updates*, e.g. temporary pinning of broken dependencies
+ or small changes to the CI configuration, may be merged with a single
+ approval.
+
+* *Code changes* (anything in ``src`` or ``lib``) must have two approvals.
+
+ Ensure that all API changes are documented in a file in one of the
+ subdirectories of :file:`doc/api/next_api_changes`, and significant new
+ features have an entry in :file:`doc/user/whats_new`.
+
+ - 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.
+
+After giving the last required approval, the author of the approval should
+merge the PR. PR authors should not self-merge except for when another reviewer
+explicitly allows it (e.g., "Approve modulo CI passing, may self merge when
+green", or "Take or leave the comments. You may self merge".).
+
+.. _pr-automated-tests:
+
+Automated tests
+---------------
+Before being merged, a PR should pass the :ref:`automated-tests`. If you are
+unsure why a test is failing, ask on the PR or in our :ref:`communication-channels`
+
+.. _pr-squashing:
+
+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:
+
+Branches and backports
+======================
+
+Current branches
+----------------
+The current active branches are
+
+*main*
+ The current development version. Future meso (*v3.N.0*) or macro (*v4.0.0*) will be
+ branched from this.
+
+*v3.N.x*
+ Maintenance branch for Matplotlib 3.N. Future micro releases will be
+ tagged from this.
+
+*v3.N.M-doc*
+ Documentation for the current micro release. On a micro release, this will be
+ replaced by a properly named branch for the new release.
+
+
+.. _pr-branch-selection:
+
+Branch selection for pull requests
+----------------------------------
+
+Generally, all pull requests should target the main branch.
+
+Other branches are fed through :ref:`automatic ` or
+:ref:`manual `. Directly
+targeting other branches is only rarely necessary for special maintenance
+work.
+
+.. _backport-strategy:
+
+Backport strategy
+-----------------
+
+Backports to the micro 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 meso 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 meso release and leave a comment explaining why.
+
+The only changes backported to the documentation branch (*v3.N.M-doc*)
+are changes to :file:`doc` or :file:`galleries`. Any changes to :file:`lib`
+or :file:`src`, including docstring-only changes, must not be backported to
+this branch.
+
+
+.. _automated-backports:
+
+Automated backports
+-------------------
+
+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
+manually.
+
+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 `__.
+
+
+.. _manual-backports:
+
+Manual backports
+----------------
+
+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
+message.
+
+We do a backport from main to v2.2.x assuming:
+
+* ``matplotlib`` is a read-only remote branch of the matplotlib/matplotlib repo
+
+The ``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 ``upstream``:
+
+.. code-block:: bash
+
+ 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 ``git status``,
+and will have to be fixed by hand (search on ``>>>>>``). Once
+the conflict is resolved, you will have to re-add the file(s) to the branch
+and then continue the cherry pick:
+
+.. code-block:: bash
+
+ 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 ``main``!
diff --git a/doc/devel/release_guide.rst b/doc/devel/release_guide.rst
index 4adc4546e879..6c45bfa56c64 100644
--- a/doc/devel/release_guide.rst
+++ b/doc/devel/release_guide.rst
@@ -12,10 +12,35 @@ Release guide
A guide for developers who are doing a Matplotlib release.
-.. note::
- This assumes that a read-only remote for the canonical repository is
- ``remote`` and a read/write remote is ``DANGER``
+Versioning Scheme
+=================
+
+Matplotlib follows the `Intended Effort Versioning (EffVer) `_
+versioning scheme: *macro.meso.micro*.
+
+
+*macro*
+ 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.
+
+ Future macro versions would include changes of a comparable scale that can not be done
+ incrementally in meso releases.
+
+*meso*
+ A release that we expect some effort from our users to upgrade to. We target a
+ *Meso* 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 :ref:`our policy `.
+
+*micro*
+ A release that we expect users to require little to no effort to upgrade to. Per
+ our :ref:`backport-strategy` 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 `bugs being used as features `_.
+
+ These are released as-needed, but typically every 1-2 months between meso releases.
.. _release_feature_freeze:
@@ -23,9 +48,15 @@ Release guide
Making the release branch
=========================
-When a new minor release (vX.Y.0) is approaching, a new release branch must be made.
+.. note::
+
+ This assumes that a read-only remote for the canonical repository is
+ ``remote`` and a read/write remote is ``DANGER``
+
+
+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 minor release are merged and you are entering a
+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.
@@ -50,12 +81,12 @@ Micro versions should instead read::
on-merge: backport to v3.7.x
Check all active milestones for consistency. Older milestones should also backport
-to higher minor versions (e.g. ``v3.6.3`` and ``v3.6-doc`` should backport to both
+to higher meso versions (e.g. ``v3.6.3`` and ``v3.6-doc`` should backport to both
``v3.6.x`` and ``v3.7.x`` once the ``v3.7.x`` branch exists and while PR backports are
still targeting ``v3.6.x``)
-Create the milestone for the next-next minor release (i.e. ``v3.9.0``, as ``v3.8.0``
-should already exist). While most active items should go in the next minor release,
+Create the milestone for the next-next meso release (i.e. ``v3.9.0``, as ``v3.8.0``
+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.
@@ -112,7 +143,8 @@ prepare this list:
--project 'matplotlib/matplotlib' --links > doc/users/github_stats.rst
3. Review and commit changes. Some issue/PR titles may not be valid reST (the most
- common issue is ``*`` which is interpreted as unclosed markup).
+ common issue is ``*`` which is interpreted as unclosed markup). Also confirm that
+ ``codespell`` does not find any issues.
.. note::
@@ -142,15 +174,15 @@ are going to tag on and delete the doc branch on GitHub.
Update supported versions in Security Policy
--------------------------------------------
-When making major or minor releases, update the supported versions in the Security
+When making macro or meso releases, update the supported versions in the Security
Policy in :file:`SECURITY.md`.
-For minor version release update the table in :file:`SECURITY.md` to specify that the
-two most recent minor releases in the current major version series are supported.
+For meso version release update the table in :file:`SECURITY.md` to specify that the
+two most recent meso releases in the current macro version series are supported.
-For a major version release update the table in :file:`SECURITY.md` to specify that the
-last minor version in the previous major version series is still supported. Dropping
-support for the last version of a major version series will be handled on an ad-hoc
+For a macro version release update the table in :file:`SECURITY.md` 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.
Update release notes
@@ -159,7 +191,7 @@ Update release notes
What's new
^^^^^^^^^^
-*Only needed for major and minor releases. Bugfix releases should not have new
+*Only needed for macro and meso releases. Bugfix releases should not have new
features.*
Merge the contents of all the files in :file:`doc/users/next_whats_new/` into a single
@@ -169,8 +201,8 @@ files.
API changes
^^^^^^^^^^^
-*Primarily needed for major and minor releases. We may sometimes have API
-changes in bugfix releases.*
+*Primarily needed for macro and meso releases. We may sometimes have API
+changes in micro releases.*
Merge the contents of all the files in :file:`doc/api/next_api_changes/` into a single
file :file:`doc/api/prev_api_changes/api_changes_{X}.{Y}.{Z}.rst` and delete the
@@ -181,7 +213,7 @@ Release notes TOC
Update :file:`doc/users/release_notes.rst`:
-- For major and minor releases add a new section
+- For macro and meso releases add a new section
.. code:: rst
@@ -193,7 +225,7 @@ Update :file:`doc/users/release_notes.rst`:
prev_whats_new/whats_new_X.Y.0.rst
../api/prev_api_changes/api_changes_X.Y.0.rst
prev_whats_new/github_stats_X.Y.0.rst
-- For bugfix releases add the GitHub stats and (if present) the API changes to
+- For micro releases add the GitHub stats and (if present) the API changes to
the existing X.Y section
.. code:: rst
@@ -201,15 +233,24 @@ Update :file:`doc/users/release_notes.rst`:
../api/prev_api_changes/api_changes_X.Y.Z.rst
prev_whats_new/github_stats_X.Y.Z.rst
+.. _update-version-switcher:
+
Update version switcher
-^^^^^^^^^^^^^^^^^^^^^^^
+-----------------------
+
+The version switcher is populated from https://matplotlib.org/devdocs/_static/switcher.json.
-Update ``doc/_static/switcher.json``:
+Since it's always taken from devdocs, update the file :file:`doc/_static/switcher.json`
+on the main branch through a regular PR:
-- If a bugfix release, :samp:`{X}.{Y}.{Z}`, no changes are needed.
-- If a major release, :samp:`{X}.{Y}.0`, change the name of :samp:`name: {X}.{Y+1}
- (dev)` and :samp:`name: {X}.{Y} (stable)` as well as adding a new version for the
- previous stable (:samp:`name: {X}.{Y-1}`).
+- If a micro release, update the version from :samp:`{X}.{Y}.{Z-1}` to :samp:`{X}.{Y}.{Z}`
+- If a meso release :samp:`{X}.{Y}.0`:
+
+ + update the dev entry to :samp:`name: {X}.{Y+1} (dev)`
+ + update the stable entry to :samp:`name: {X}.{Y} (stable)`
+ + add a new entry for the previous stable (:samp:`name: {X}.{Y-1}`).
+
+Once that PR is merged, the devdocs site will be updated automatically.
Verify that docs build
----------------------
@@ -259,8 +300,8 @@ Finally, push the tag to GitHub::
Congratulations, the scariest part is done!
This assumes the release branch has already been made.
-Usually this is done at the time of feature freeze for a minor release (which often
-coincides with the last patch release of the previous minor version)
+Usually this is done at the time of feature freeze for a meso release (which often
+coincides with the last micro release of the previous meso version)
.. [#] The tarball that is provided by GitHub is produced using `git archive`_.
We use setuptools_scm_ which uses a format string in
@@ -298,7 +339,7 @@ with the ``v3.7-doc`` milestone to both the ``v3.7.x`` branch and the ``v3.7.0-d
on-merge: backport to v3.7.0-doc
Check all active milestones for consistency. Older doc milestones should also backport to
-higher minor versions (e.g. ``v3.6-doc`` should backport to both ``v3.6.x`` and ``v3.7.x``
+higher meso versions (e.g. ``v3.6-doc`` should backport to both ``v3.6.x`` and ``v3.7.x``
if the ``v3.7.x`` branch exists)
@@ -315,8 +356,8 @@ automatically produce one once the tag is pushed). Add the DOI post-fix and vers
the dictionary in :file:`tools/cache_zenodo_svg.py` and run the script.
This will download the new SVG to :file:`doc/_static/zenodo_cache/{postfix}.svg` and
-edit :file:`doc/users/project/citing.rst`. Commit the new SVG, the change to
-:file:`tools/cache_zenodo_svg.py`, and the changes to :file:`doc/users/project/citing.rst`
+edit :file:`doc/project/citing.rst`. Commit the new SVG, the change to
+:file:`tools/cache_zenodo_svg.py`, and the changes to :file:`doc/project/citing.rst`
to the VER-doc branch and push to GitHub. ::
git checkout v3.7.0-doc
@@ -336,7 +377,8 @@ PyPI. Most builders should trigger automatically once the tag is pushed to GitHu
* Windows, macOS and manylinux wheels are built on GitHub Actions. Builds are triggered
by the GitHub Action defined in :file:`.github/workflows/cibuildwheel.yml`, and wheels
- will be available as artifacts of the build.
+ will be available as artifacts of the build. Both a source tarball and the wheels will
+ be automatically uploaded to PyPI once all of them have been built.
* The auto-tick bot should open a pull request into the `conda-forge feedstock
`__. Review and merge (if you
have the power to).
@@ -349,8 +391,14 @@ PyPI. Most builders should trigger automatically once the tag is pushed to GitHu
.. _release_upload_bin:
-Make distribution and upload to PyPI
-====================================
+Manually uploading to PyPI
+==========================
+
+.. note::
+
+ As noted above, the GitHub Actions workflow should build and upload source tarballs
+ and wheels automatically. If for some reason, you need to upload these artifacts
+ manually, then follow the instructions in this section.
Once you have collected all of the wheels (expect this to take a few hours), generate
the tarball::
@@ -412,7 +460,6 @@ which will copy the built docs over. If this is a final release, link the
rm stable
ln -s 3.7.0 stable
-You will need to manually edit :file:`versions.html` to show the released version.
You will also need to edit :file:`sitemap.xml` to include
the newly released version. Now commit and push everything to GitHub ::
@@ -427,6 +474,8 @@ If you have access, clear the CloudFlare caches.
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).
+Remember to :ref:`update the version switcher `!
+
.. _release_merge_up:
Merge up changes to main
diff --git a/doc/devel/style_guide.rst b/doc/devel/style_guide.rst
index 9dab7a6d99d2..e35112a65e42 100644
--- a/doc/devel/style_guide.rst
+++ b/doc/devel/style_guide.rst
@@ -155,14 +155,19 @@ reliability and consistency in documentation. They are not interchangeable.
| | | rotational | |
| | | motion." | |
+------------------+--------------------------+--------------+--------------+
- | Explicit, | Explicit approach of | - Explicit | - object |
- | Object Oriented | programming in | - explicit | oriented |
- | Programming (OOP)| Matplotlib. | - OOP | - OO-style |
+ | Axes interface | Usage pattern in which | - Axes | - explicit |
+ | | one calls methods on | interface | interface |
+ | | Axes and Figure (and | - call | - object |
+ | | sometimes other Artist) | methods on | oriented |
+ | | objects to configure the | the Axes / | - OO-style |
+ | | plot. | Figure | - OOP |
+ | | | object | |
+------------------+--------------------------+--------------+--------------+
- | Implicit, | Implicit approach of | - Implicit | - MATLAB like|
- | ``pyplot`` | programming in Matplotlib| - implicit | - Pyplot |
- | | with ``pyplot`` module. | - ``pyplot`` | - pyplot |
- | | | | interface |
+ | pyplot interface | Usage pattern in which | - ``pyplot`` | - implicit |
+ | | one only calls `.pyplot` | interface | interface |
+ | | functions to configure | - call | - MATLAB like|
+ | | the plot. | ``pyplot`` | - Pyplot |
+ | | | functions | |
+------------------+--------------------------+--------------+--------------+
.. |Figure| replace:: :class:`~matplotlib.figure.Figure`
diff --git a/doc/devel/tag_glossary.rst b/doc/devel/tag_glossary.rst
index 9b70a2a96159..b3d0ec2bcbda 100644
--- a/doc/devel/tag_glossary.rst
+++ b/doc/devel/tag_glossary.rst
@@ -1,19 +1,17 @@
-:orphan:
-
Tag Glossary
============
-I. API tags: what content from the API reference is in the example?
-II. Structural tags: what format is the example? What context can we provide?
-III. Domain tags: what discipline(s) might seek this example consistently?
-IV. Internal tags: what information is helpful for maintainers or contributors?
+.. contents::
+ :depth: 1
+ :local:
+ :backlinks: entry
API tags: what content from the API reference is in the example?
----------------------------------------------------------------
+-----------------------------------+---------------------------------------------+
-|``tag`` | use case - if not obvious |
+|``tag`` | use case |
+===================================+=============================================+
|**Primary or relevant plot component** |
+-----------------------------------+---------------------------------------------+
@@ -94,21 +92,21 @@ API tags: what content from the API reference is in the example?
+-----------------------------------+---------------------------------------------+
|**Plot Type** |
+-----------------------------------+---------------------------------------------+
-|``plot type: bar`` |example contains a bar plot |
+|``plot-type: bar`` |example contains a bar plot |
+-----------------------------------+---------------------------------------------+
-|``plot type: line`` |example contains a line plot |
+|``plot-type: line`` |example contains a line plot |
+-----------------------------------+---------------------------------------------+
-|``plot type: pie`` |example contains a pie plot |
+|``plot-type: pie`` |example contains a pie plot |
+-----------------------------------+---------------------------------------------+
-|``plot type: polar`` |example contains a polar plot |
+|``plot-type: polar`` |example contains a polar plot |
+-----------------------------------+---------------------------------------------+
-|``plot type: 3D`` |example contains a 3D plot |
+|``plot-type: 3D`` |example contains a 3D plot |
+-----------------------------------+---------------------------------------------+
-|``plot type: histogram`` |example contains a histogram |
+|``plot-type: histogram`` |example contains a histogram |
+-----------------------------------+---------------------------------------------+
-|``plot type: specialty`` | |
+|``plot-type: specialty`` | |
+-----------------------------------+---------------------------------------------+
-|``plot type: scatter`` | |
+|``plot-type: scatter`` | |
+-----------------------------------+---------------------------------------------+
@@ -142,7 +140,9 @@ Structural tags: what format is the example? What context can we provide?
Domain tags: what discipline(s) might seek this example consistently?
---------------------------------------------------------------------
-It's futile to draw fences around "who owns what", and that's not the point of domain tags. Domain tags help groups of people to privately organize relevant information, and so are not displayed publicly. See below for a list of existing domain tags. If you don't see the one you're looking for and you think it should exist, consider proposing it.
+It's futile to draw fences around "who owns what", and that's not the point of domain
+tags. See below for a list of existing domain tags. If you don't see the one you're
+looking for and you think it should exist, consider proposing it.
+-------------------------------+----------------------------------------+
|``tag`` | use case |
@@ -163,10 +163,18 @@ It's futile to draw fences around "who owns what", and that's not the point of d
Internal tags: what information is helpful for maintainers or contributors?
---------------------------------------------------------------------------
+These tags should be used only for development purposes; therefore please add them
+separately behind a version guard:
+
+.. code:: rst
+
+ .. ifconfig:: releaselevel == 'dev'
+ .. tags:: internal: needs-review
+
+-------------------------------+-----------------------------------------------------------------------+
|``tag`` | use case |
+===============================+=======================================================================+
-|``internal: low bandwidth`` |allows users to filter out bandwidth-intensive examples like animations|
+|``internal: high-bandwidth`` |allows users to filter out bandwidth-intensive examples like animations|
+-------------------------------+-----------------------------------------------------------------------+
|``internal: untagged`` |allows docs contributors to easily find untagged examples |
+-------------------------------+-----------------------------------------------------------------------+
diff --git a/doc/devel/tag_guidelines.rst b/doc/devel/tag_guidelines.rst
index ca6b8cfde01d..2c80065982bc 100644
--- a/doc/devel/tag_guidelines.rst
+++ b/doc/devel/tag_guidelines.rst
@@ -1,17 +1,30 @@
-Guidelines for assigning tags to gallery examples
-=================================================
+Tagging guidelines
+==================
Why do we need tags?
--------------------
Tags serve multiple purposes.
-Tags have a one-to-many organization (i.e. one example can have several tags), while the gallery structure requires that examples are placed in only one location. This means tags provide a secondary layer of organization and make the gallery of examples more flexible and more user-friendly.
+Tags have a one-to-many organization (i.e. one example can have several tags), while
+the gallery structure requires that examples are placed in only one location. This means
+tags provide a secondary layer of organization and make the gallery of examples more
+flexible and more user-friendly.
-They allow for better discoverability, search, and browse functionality. They are helpful for users struggling to write a search query for what they're looking for.
+They allow for better discoverability, search, and browse functionality. They are
+helpful for users struggling to write a search query for what they're looking for.
Hidden tags provide additional functionality for maintainers and contributors.
+How to tag?
+-----------
+Place the tag directive at the bottom of each page and add the tags underneath, e.g.:
+
+.. code-block:: rst
+
+ .. tags::
+ topic: tagging, purpose: reference
+
What gets a tag?
----------------
@@ -20,56 +33,38 @@ Every gallery example should be tagged with:
* 1+ content tags
* structural, domain, or internal tag(s) if helpful
-Tags can repeat existing forms of organization (e.g. an example is in the Animation folder and also gets an ``animation`` tag).
+Tags can repeat existing forms of organization (e.g. an example is in the Animation
+folder and also gets an ``animation`` tag).
+
+Tags are helpful to denote particularly good "byproduct" examples. E.g. the explicit
+purpose of a gallery example might be to demonstrate a colormap, but it's also a good
+demonstration of a legend. Tag ``legend`` to indicate that, rather than changing the
+title or the scope of the example.
-Tags are helpful to denote particularly good "byproduct" examples. E.g. the explicit purpose of a gallery example might be to demonstrate a colormap, but it's also a good demonstration of a legend. Tag ``legend`` to indicate that, rather than changing the title or the scope of the example.
+.. card::
-**Tag Categories** - See :doc:`Tag Glossary ` for a complete list of tags.
+ **Tag Categories**
+ ^^^
+ .. rst-class:: section-toc
-I. API tags: what content from the API reference is in the example?
-II. Structural tags: what format is the example? What context can we provide?
-III. Domain tags: what discipline(s) might seek this example consistently?
-IV. Internal tags: what information is helpful for maintainers or contributors?
+ .. toctree::
+ :maxdepth: 2
+
+ tag_glossary
+
+ +++
+ See :doc:`Tag Glossary ` for a complete list
Proposing new tags
------------------
1. Review existing tag list, looking out for similar entries (i.e. ``axes`` and ``axis``).
-2. If a relevant tag or subcategory does not yet exist, propose it. Each tag is two parts: ``subcategory: tag``. Tags should be one or two words.
-3. New tags should be be added when they are relevant to existing gallery entries too. Avoid tags that will link to only a single gallery entry.
+2. If a relevant tag or subcategory does not yet exist, propose it. Each tag is two
+ parts: ``subcategory: tag``. Tags should be one or two words.
+3. New tags should be be added when they are relevant to existing gallery entries too.
+ Avoid tags that will link to only a single gallery entry.
4. Tags can recreate other forms of organization.
-Note: Tagging organization aims to work for 80-90% of cases. Some examples fall outside of the tagging structure. Niche or specific examples shouldn't be given standalone tags that won't apply to other examples.
-
-How to tag?
------------
-Put each tag as a directive at the bottom of the page.
-
-Related content
----------------
-
-What is a gallery example?
-^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The gallery of examples contains visual demonstrations of matplotlib features. Gallery examples exist so that users can scan through visual examples.
-
-Unlike tutorials or user guides, gallery examples teach by demonstration, rather than by explanation or instruction.
-
-Gallery examples should avoid instruction or excessive explanation except for brief clarifying code comments. Instead, they can tag related concepts and/or link to relevant tutorials or user guides.
-
-Format
-^^^^^^
-
-All :ref:`examples-index` should aim to follow the following format:
-
-* Title: 1-6 words, descriptive of content
-* Subtitle: 10-50 words, action-oriented description of the example subject
-* Image: a clear demonstration of the subject, showing edge cases and different applications if possible
-* Code + Text (optional): code, commented as appropriate + written text to add context if necessary
-
-Example:
-
-The ``bbox_intersect`` gallery example demonstrates the point of visual examples:
-
-* this example is "messy" in that it's hard to categorize, but the gallery is the right spot for it because it makes sense to find it by visual search
-* https://matplotlib.org/devdocs/gallery/misc/bbox_intersect.html#sphx-glr-gallery-misc-bbox-intersect-py
+Tagging organization aims to work for 80-90% of cases. Some examples fall outside of the
+tagging structure. Niche or specific examples shouldn't be given standalone tags that
+won't apply to other examples.
diff --git a/doc/devel/testing.rst b/doc/devel/testing.rst
index 7a11c7c3eb18..1fef85260b12 100644
--- a/doc/devel/testing.rst
+++ b/doc/devel/testing.rst
@@ -32,16 +32,18 @@ particular the :ref:`additional dependencies ` for testing.
You have to additionally get the reference images from the repository,
because they are not distributed with pre-built Matplotlib packages.
+.. _run_tests:
+
Running the tests
-----------------
In the root directory of your development repository run::
- python -m pytest
+ pytest
-pytest can be configured via a lot of `command-line parameters`_. Some
-particularly useful ones are:
+``pytest`` can be configured via many :external+pytest:doc:`command-line parameters
+`. Some particularly useful ones are:
============================= ===========
``-v`` or ``--verbose`` Be more verbose
@@ -50,14 +52,49 @@ particularly useful ones are:
``--capture=no`` or ``-s`` Do not capture stdout
============================= ===========
-To run a single test from the command line, you can provide a file path,
-optionally followed by the function separated by two colons, e.g., (tests do
-not need to be installed, but Matplotlib should be)::
+To run a single test from the command line, you can provide a file path, optionally
+followed by the function separated by two colons, e.g., (tests do not need to be
+installed, but Matplotlib should be)::
pytest lib/matplotlib/tests/test_simplification.py::test_clipping
+If you want to use ``pytest`` as a module (via ``python -m pytest``), then you will need
+to avoid clashes between ``pytest``'s import mode and Python's search path:
+
+- On more recent Python, you may :external+python:std:option:`disable "unsafe import
+ paths" <-P>` (i.e., stop adding the current directory to the import path) with the
+ ``-P`` argument::
+
+ python -P -m pytest
+
+- On older Python, you may enable :external+python:std:option:`isolated mode <-I>`
+ (which stops adding the current directory to the import path, but has other
+ repercussions)::
+
+ python -I -m pytest
+
+- On any Python, set ``pytest``'s :external+pytest:doc:`import mode
+ ` to the older ``prepend`` mode (but note that this will break
+ ``pytest``'s assert rewriting)::
+
+ python -m pytest --import-mode prepend
+
+Viewing image test output
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The output of :ref:`image-based ` tests is stored in a
+``result_images`` directory. These images can be compiled into one HTML page, containing
+hundreds of images, using the ``visualize_tests`` tool::
+
+ python tools/visualize_tests.py
+
+Image test failures can also be analysed using the ``triage_tests`` tool::
-.. _command-line parameters: http://doc.pytest.org/en/latest/usage.html
+ python tools/triage_tests.py
+
+The triage tool allows you to accept or reject test failures and will copy the new image
+to the folder where the baseline test images are stored. The triage tool requires that
+:ref:`QT ` is installed.
Writing a simple test
@@ -94,7 +131,9 @@ For numpy's default random number generator use::
and then use ``rng`` when generating the random numbers.
-The seed is John Hunter's birthday.
+The seed is :ref:`John Hunter's ` birthday.
+
+.. _image-comparison:
Writing an image comparison test
--------------------------------
@@ -124,9 +163,14 @@ the tests, they should now pass.
It is preferred that new tests use ``style='mpl20'`` as this leads to smaller
figures and reflects the newer look of default Matplotlib plots. Also, if the
-texts (labels, tick labels, etc) are not really part of what is tested, use
-``remove_text=True`` as this will lead to smaller figures and reduce possible
-issues with font mismatch on different platforms.
+texts (labels, tick labels, etc) are not really part of what is tested, use the
+``remove_text=True`` argument or add the ``text_placeholders`` fixture as this
+will lead to smaller figures and reduce possible issues with font mismatch on
+different platforms.
+
+
+Compare two methods of creating an image
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Baseline images take a lot of space in the Matplotlib repository.
An alternative approach for image comparison tests is to use the
@@ -141,17 +185,28 @@ circle: plotting a circle using a `matplotlib.patches.Circle` patch
vs plotting the circle using the parametric equation of a circle ::
from matplotlib.testing.decorators import check_figures_equal
- import matplotib.patches as mpatches
+ import matplotlib.patches as mpatches
import matplotlib.pyplot as plt
import numpy as np
- @check_figures_equal(extensions=['png'], tol=100)
+ @check_figures_equal()
def test_parametric_circle_plot(fig_test, fig_ref):
- red_circle_ref = mpatches.Circle((0, 0), 0.2, color='r', clip_on=False)
- fig_ref.add_artist(red_circle_ref)
- theta = np.linspace(0, 2 * np.pi, 150)
+
+ xo = yo = 0.5
radius = 0.4
- fig_test.plot(radius * np.cos(theta), radius * np.sin(theta), color='r')
+
+ ax_test = fig_test.subplots()
+ theta = np.linspace(0, 2 * np.pi, 150)
+ l, = ax_test.plot(xo + (radius * np.cos(theta)),
+ yo + (radius * np.sin(theta)), c='r')
+
+ ax_ref = fig_ref.subplots()
+ red_circle_ref = mpatches.Circle((xo, yo), radius, ec='r', fc='none',
+ lw=l.get_linewidth())
+ ax_ref.add_artist(red_circle_ref)
+
+ for ax in [ax_ref, ax_test]:
+ ax.set(xlim=(0, 1), ylim=(0, 1), aspect='equal')
Both comparison decorators have a tolerance argument ``tol`` that is used to specify the
tolerance for difference in color value between the two images, where 255 is the maximal
@@ -200,7 +255,7 @@ Using tox
`Tox `_ is a tool for running tests
against multiple Python environments, including multiple versions of Python
-(e.g., 3.7, 3.8) and even different Python implementations altogether
+(e.g., 3.10, 3.11) and even different Python implementations altogether
(e.g., CPython, PyPy, Jython, etc.), as long as all these versions are
available on your system's $PATH (consider using your system package manager,
e.g. apt-get, yum, or Homebrew, to install them).
@@ -217,7 +272,7 @@ You can also run tox on a subset of environments:
.. code-block:: bash
- $ tox -e py38,py39
+ $ tox -e py310,py311
Tox processes everything serially so it can take a long time to test
several environments. To speed it up, you might try using a new,
@@ -274,16 +329,17 @@ The correct target folder can be found using::
python -c "import matplotlib.tests; print(matplotlib.tests.__file__.rsplit('/', 1)[0])"
-An analogous copying of :file:`lib/mpl_toolkits/tests/baseline_images`
+An analogous copying of :file:`lib/mpl_toolkits/*/tests/baseline_images`
is necessary for testing ``mpl_toolkits``.
Run the tests
^^^^^^^^^^^^^
-To run the all the tests on your installed version of Matplotlib::
- python -m pytest --pyargs matplotlib.tests
+To run all the tests on your installed version of Matplotlib::
+
+ pytest --pyargs matplotlib.tests
The test discovery scope can be narrowed to single test modules or even single
functions::
- python -m pytest --pyargs matplotlib.tests.test_simplification.py::test_clipping
+ pytest --pyargs matplotlib.tests.test_simplification.py::test_clipping
diff --git a/doc/devel/triage.rst b/doc/devel/triage.rst
index 94b6874af228..ca06fd515c79 100644
--- a/doc/devel/triage.rst
+++ b/doc/devel/triage.rst
@@ -1,8 +1,9 @@
.. _bug_triaging:
+*******************************
Bug triaging and issue curation
-===============================
+*******************************
The `issue tracker `_
is important to communication in the project because it serves as the
@@ -11,24 +12,28 @@ identifying major projects to work on, and discussing priorities. For
this reason, it is important to curate the issue list, adding labels
to issues and closing issues that are resolved or unresolvable.
+Writing well defined issues increases their chances of being successfully
+resolved. Guidelines on writing a good issue can be found in :ref:`here
+`. The recommendations in this page are adapted from
+the `scikit learn `_
+and `Pandas `_
+contributing guides.
+
+
+Improve issue reports
+=====================
+
Triaging issues does not require any particular expertise in the
internals of Matplotlib, is extremely valuable to the project, and we
welcome anyone to participate in issue triage! However, people who
are not part of the Matplotlib organization do not have `permissions
to change milestones, add labels, or close issue
`_.
+
If you do not have enough GitHub permissions do something (e.g. add a
label, close an issue), please leave a comment with your
recommendations!
-Working on issues to improve them
----------------------------------
-
-Improving issues increases their chances of being successfully resolved.
-Guidelines on submitting good issues can be found :ref:`here
-`.
-A third party can give useful feedback or even add
-comments on the issue.
The following actions are typically useful:
- documenting issues that are missing elements to reproduce the problem
@@ -62,30 +67,11 @@ The following actions are typically useful:
explores how to lead online discussions in the context of open source.
-.. _triage_team:
-
-Triage team
------------
-
-
-If you would like to join the triage team:
-
-1. Correctly triage 2-3 issues.
-2. Ask someone on in the Matplotlib organization (publicly or privately) to
- recommend you to the triage team (look for "Member" on the top-right of
- comments on GitHub). If you worked with someone on the issues triaged, they
- would be a good person to ask.
-3. Responsibly exercise your new power!
-
-Anyone with commit or triage rights may nominate a user to be invited to join
-the triage team by emailing matplotlib-steering-council@numfocus.org .
-
+Maintainers and triage team members
+-----------------------------------
-Triaging operations for members of the core and triage teams
-------------------------------------------------------------
-
-In addition to the above, members of the core team and the triage team
-can do the following important tasks:
+In addition to the above, maintainers and the triage team can do the following
+important tasks:
- Update labels for issues and PRs: see the list of `available GitHub
labels `_.
@@ -113,7 +99,6 @@ can do the following important tasks:
least a week) to add extra information
-
.. topic:: Closing issues: a tough call
When uncertain on whether an issue should be closed or not, it is
@@ -122,13 +107,19 @@ can do the following important tasks:
question or has been considered as unclear for many years, then it
should be closed.
+Preparing PRs for review
+========================
+
+Reviewing code is also encouraged. Contributors and users are welcome to
+participate to the review process following our :ref:`review guidelines
+`.
.. _triage_workflow:
-A typical workflow for triaging issues
---------------------------------------
+Triage workflow
+===============
-The following workflow [1]_ is a good way to approach issue triaging:
+The following workflow is a good way to approach issue triaging:
#. Thank the reporter for opening an issue
@@ -169,7 +160,7 @@ The following workflow [1]_ is a good way to approach issue triaging:
While we strive for a bug-free library, regressions are the highest
priority. If we have broken user-code that *used to* work, we should
- fix that in the next patch release!
+ fix that in the next micro release!
Try to determine when the regression happened by running the
reproduction code against older versions of Matplotlib. This can
@@ -208,22 +199,20 @@ The following workflow [1]_ is a good way to approach issue triaging:
An additional useful step can be to tag the corresponding module e.g.
the "GUI/Qt" label when relevant.
+.. _triage_team:
-.. [1] Adapted from the pandas project `maintainers guide
- `_ and
- `the scikit-learn project
- `_ .
-
+Triage team
+===========
-Working on PRs to help review
-------------------------------
-Reviewing code is also encouraged. Contributors and users are welcome to
-participate to the review process following our :ref:`review guidelines
-`.
+If you would like to join the triage team:
-Acknowledgments
----------------
+1. Correctly triage 2-3 issues.
+2. Ask someone on in the Matplotlib organization (publicly or privately) to
+ recommend you to the triage team (look for "Member" on the top-right of
+ comments on GitHub). If you worked with someone on the issues triaged, they
+ would be a good person to ask.
+3. Responsibly exercise your new power!
-This page is lightly adapted from `the scikit-learn project
-`_ .
+Anyone with commit or triage rights may nominate a user to be invited to join
+the triage team by emailing matplotlib-steering-council@numfocus.org .
diff --git a/doc/index.rst b/doc/index.rst
index 4f42273d3dcc..74a183d6cd7b 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -29,15 +29,44 @@ Install
conda install -c conda-forge matplotlib
+ .. tab-item:: pixi
+
+ .. code-block:: bash
+
+ pixi add matplotlib
+
+ .. tab-item:: uv
+
+ .. code-block:: bash
+
+ uv add matplotlib
+
+ .. warning::
+
+ If you install Python with ``uv`` then the ``tkagg`` backend
+ will not be available because python-build-standalone (used by uv
+ to distribute Python) does not contain tk bindings that are usable by
+ Matplotlib (see `this issue`_ for details). If you want Matplotlib
+ to be able to display plots in a window, you should install one of
+ the other :ref:`supported GUI frameworks `,
+ e.g.
+
+ .. code-block:: bash
+
+ uv add matplotlib pyside6
+
+ .. _this issue: https://github.com/astral-sh/uv/issues/6893#issuecomment-2565965851
+
.. tab-item:: other
+ .. rst-class:: section-toc
.. toctree::
:maxdepth: 2
- users/installing/index
+ install/index
For more detailed instructions, see the
-:doc:`installation guide `.
+:doc:`installation guide `.
Learn
=====
@@ -106,6 +135,7 @@ Community
.. grid-item::
+ .. rst-class:: section-toc
.. toctree::
:maxdepth: 2
@@ -144,11 +174,11 @@ Contribute
.. grid-item::
- Matplotlib is a community project maintained for and by its users.
-
- There are many ways you can help!
+ Matplotlib is a community project maintained for and by its users. See
+ :ref:`developers-guide-index` for the many ways you can help!
.. grid-item::
+ .. rst-class:: section-toc
.. toctree::
:maxdepth: 2
@@ -168,8 +198,8 @@ About us
and hard things possible.
.. grid-item::
-
+ .. rst-class:: section-toc
.. toctree::
:maxdepth: 2
- users/project/index.rst
+ project/index.rst
diff --git a/doc/users/installing/dependencies.rst b/doc/install/dependencies.rst
similarity index 63%
rename from doc/users/installing/dependencies.rst
rename to doc/install/dependencies.rst
index ce83454db08a..712846771cc6 100644
--- a/doc/users/installing/dependencies.rst
+++ b/doc/install/dependencies.rst
@@ -1,4 +1,5 @@
-.. redirect-from: /devel/dependencies
+.. redirect-from:: /devel/dependencies
+.. redirect-from:: /users/installing/dependencies
.. _dependencies:
@@ -19,18 +20,16 @@ When installing through a package manager like ``pip`` or ``conda``, the
mandatory dependencies are automatically installed. This list is mainly for
reference.
-* `Python `_ (>= 3.9)
+* `Python `_ (>= 3.11)
* `contourpy `_ (>= 1.0.1)
* `cycler `_ (>= 0.10.0)
* `dateutil `_ (>= 2.7)
* `fontTools `_ (>= 4.22.0)
* `kiwisolver `_ (>= 1.3.1)
-* `NumPy `_ (>= 1.21)
+* `NumPy `_ (>= 1.25)
* `packaging `_ (>= 20.0)
-* `Pillow `_ (>= 8.0)
-* `pyparsing `_ (>= 2.3.1)
-* `importlib-resources `_
- (>= 3.2.0; only required on Python < 3.10)
+* `Pillow `_ (>= 9.0)
+* `pyparsing `_ (>= 3)
.. _optional_dependencies:
@@ -41,6 +40,8 @@ Optional
The following packages and tools are not required but extend the capabilities
of Matplotlib.
+.. _backend_dependencies:
+
Backends
^^^^^^^^
@@ -51,7 +52,8 @@ and the capabilities they provide.
* Tk_ (>= 8.5, != 8.6.0 or 8.6.1): for the Tk-based backends. Tk is part of
most standard Python installations, but it's not part of Python itself and
thus may not be present in rare cases.
-* PyQt6_ (>= 6.1), PySide6_, PyQt5_, or PySide2_: for the Qt-based backends.
+* PyQt6_ (>= 6.1), PySide6_, PyQt5_ (>= 5.12), or PySide2_: for the Qt-based
+ backends.
* PyGObject_ and pycairo_ (>= 1.14.0): for the GTK-based backends. If using pip
(but not conda or system package manager) PyGObject must be built from
source; see `pygobject documentation
@@ -165,7 +167,7 @@ tool for locating FreeType:
If not using pkg-config (in particular on Windows), you may need to set the
include path (to the library headers) and link path (to the libraries)
explicitly, if they are not in standard locations. This can be done using
-standard environment variables -- on Linux and OSX:
+standard environment variables -- on Linux and macOS:
.. code-block:: sh
@@ -218,68 +220,77 @@ Build dependencies
Python
------
-By default, ``pip`` will build packages using build isolation, meaning that these
-build dependencies are temporally installed by pip for the duration of the
-Matplotlib build process. However, build isolation is disabled when :ref:`installing Matplotlib for development `;
-therefore we recommend using one of our :ref:`virtual environment configurations ` to
-create a development environment in which these packages are automatically installed.
-
-If you are developing Matplotlib and unable to use our environment configurations,
-then you must manually install the following packages into your development environment:
+``pip`` normally builds packages using :external+pip:doc:`build isolation `,
+which means that ``pip`` installs the dependencies listed here for the
+duration of the build process. However, build isolation is disabled via the the
+:external+pip:ref:`--no-build-isolation ` flag
+when :ref:`installing Matplotlib for development `, which
+means that the dependencies must be explicitly installed, either by :ref:`creating a virtual environment `
+(recommended) or by manually installing the following packages:
- `meson-python `_ (>= 0.13.1).
-- `ninja `_ (>= 1.8.2). This may be available in your package
- manager or bundled with Meson, but may be installed via ``pip`` if otherwise not
- available.
-- `PyBind11 `_ (>= 2.6). Used to connect C/C++ code
+- `PyBind11 `_ (>= 2.13.2). Used to connect C/C++ code
with Python.
- `setuptools_scm `_ (>= 7). Used to
update the reported ``mpl.__version__`` based on the current git commit.
Also a runtime dependency for editable installs.
-- `NumPy `_ (>= 1.21). Also a runtime dependency.
+- `NumPy `_ (>= 1.22). Also a runtime dependency.
+
+.. _compile-build-dependencies:
+
+Compilers and external build tools
+----------------------------------
+
+When setting up a virtual environment for development, `ninja `_
+(>= 1.8.2) may need to be installed separately. This may be available
+as a `pre-built binary `_ or from a
+`package manager `_
+or bundled with Meson. Ninja may also be installed via ``pip`` if otherwise not
+available.
.. _compile-dependencies:
-Compiled extensions
--------------------
+Compilers
+^^^^^^^^^
Matplotlib requires a C++ compiler that supports C++17, and each platform has a
development environment that must be installed before a compiler can be installed.
You may also need to install headers for various libraries used in the compiled extension
source files.
+.. _dev-compiler:
.. tab-set::
- .. tab-item:: Linux
+ .. tab-item:: Linux
- On some Linux systems, you can install a meta-build package. For example,
- on Ubuntu ``apt install build-essential``
+ On some Linux systems, you can install a meta-build package. For example,
+ on Ubuntu ``apt install build-essential`` with elevated privileges.
- Otherwise, use the system distribution's package manager to install
- :ref:`gcc `.
+ Otherwise, use the system distribution's package manager to install
+ :ref:`gcc `.
- .. tab-item:: macOS
+ .. tab-item:: macOS
- Install `Xcode `_ for Apple platform development.
+ Install `Xcode `_ for Apple platform development.
- .. tab-item:: Windows
+ .. tab-item:: Windows
- Install `Visual Studio Build Tools `_
+ Install `Visual Studio Build Tools `_
- Make sure "Desktop development with C++" is selected, and that the latest MSVC,
- "C++ CMake tools for Windows," and a Windows SDK compatible with your version
- of Windows are selected and installed. They should be selected by default under
- the "Optional" subheading, but are required to build Matplotlib from source.
+ Make sure "Desktop development with C++" is selected, and that the latest MSVC,
+ "C++ CMake tools for Windows," and a Windows SDK compatible with your version
+ of Windows are selected and installed. They should be selected by default under
+ the "Optional" subheading, but are required to build Matplotlib from source.
- Alternatively, you can install a Linux-like environment such as `CygWin `_
- or `Windows Subsystem for Linux `_.
- If using `MinGW-64 `_, we require **v6** of the
- ```Mingw-w64-x86_64-headers``.
+ Alternatively, you can install a Linux-like environment such as `CygWin `_
+ or `Windows Subsystem for Linux `_.
+ If using `MinGW-64 `_, we require **v6** of the
+ ```Mingw-w64-x86_64-headers``.
-We highly recommend that you install a compiler using your platform tool, i.e.,
-Xcode, VS Code or Linux package manager. Choose **one** compiler from this list:
+We highly recommend that you install a compiler using your platform tool, i.e., Xcode,
+VS Code or Linux package manager. Choose **one** compiler from this list:
.. _compiler-table:
@@ -306,7 +317,6 @@ Xcode, VS Code or Linux package manager. Choose **one** compiler from this list:
- `Visual Studio 2019 C++ `_
-
.. _test-dependencies:
Test dependencies
@@ -326,22 +336,29 @@ Optional
In addition to all of the optional dependencies on the main library, for
testing the following will be used if they are installed.
-- Ghostscript_ (>= 9.0, to render PDF files)
-- Inkscape_ (to render SVG files)
+Python
+^^^^^^
+These packages are installed when :ref:`creating a virtual environment `,
+otherwise they must be installed manually:
+
- nbformat_ and nbconvert_ used to test the notebook backend
- pandas_ used to test compatibility with Pandas
- pikepdf_ used in some tests for the pgf and pdf backends
- psutil_ used in testing the interactive backends
- pytest-cov_ (>= 2.3.1) to collect coverage information
-- pytest-flake8_ to test coding standards using flake8_
- pytest-timeout_ to limit runtime in case of stuck tests
- pytest-xdist_ to run tests in parallel
- pytest-xvfb_ to run tests without windows popping up (Linux)
- pytz_ used to test pytz int
- sphinx_ used to test our sphinx extensions
+- xarray_ used to test compatibility with xarray
+
+External tools
+^^^^^^^^^^^^^^
+- Ghostscript_ (>= 9.0, to render PDF files)
+- Inkscape_ (to render SVG files)
- `WenQuanYi Zen Hei`_ and `Noto Sans CJK`_ fonts for testing font fallback and
non-Western fonts
-- xarray_ used to test compatibility with xarray
If any of these dependencies are not discovered, then the tests that rely on
them will be skipped by pytest.
@@ -354,7 +371,7 @@ them will be skipped by pytest.
.. _Ghostscript: https://ghostscript.com/
.. _Inkscape: https://inkscape.org
-.. _flake8: https://pypi.org/project/flake8/
+.. _WenQuanYi Zen Hei: http://wenq.org/en/
.. _nbconvert: https://pypi.org/project/nbconvert/
.. _nbformat: https://pypi.org/project/nbformat/
.. _pandas: https://pypi.org/project/pandas/
@@ -362,13 +379,11 @@ them will be skipped by pytest.
.. _psutil: https://pypi.org/project/psutil/
.. _pytz: https://fonts.google.com/noto/use#faq
.. _pytest-cov: https://pytest-cov.readthedocs.io/en/latest/
-.. _pytest-flake8: https://pypi.org/project/pytest-flake8/
.. _pytest-timeout: https://pypi.org/project/pytest-timeout/
.. _pytest-xdist: https://pypi.org/project/pytest-xdist/
.. _pytest-xvfb: https://pypi.org/project/pytest-xvfb/
.. _pytest: http://doc.pytest.org/en/latest/
.. _sphinx: https://pypi.org/project/Sphinx/
-.. _WenQuanYi Zen Hei: http://wenq.org/en/
.. _Noto Sans CJK: https://fonts.google.com/noto/use
.. _xarray: https://pypi.org/project/xarray/
@@ -389,37 +404,75 @@ The additional Python packages required to build the
The content of :file:`doc-requirements.txt` is also shown below:
-.. include:: ../../../requirements/doc/doc-requirements.txt
+.. include:: ../../requirements/doc/doc-requirements.txt
:literal:
+.. _doc-dependencies-external:
+
External tools
--------------
-The documentation requires LaTeX and Graphviz. These are not
-Python packages and must be installed separately. The documentation can be
-built without Inkscape and optipng, but the build process will raise various
-warnings. If the build process warns that you are missing fonts, make sure
-your LaTeX distribution bundles cm-super or install it separately.
-
Required
^^^^^^^^
+The documentation requires LaTeX and Graphviz. These are not
+Python packages and must be installed separately.
* `Graphviz `_
-* a minimal working LaTeX distribution, e.g., `TeX Live `_ or
+* a LaTeX distribution, e.g. `TeX Live `_ or
`MikTeX `_
-* the following LaTeX packages (if your OS bundles TeX Live, the
- "complete" version of the installer, e.g. "texlive-full" or "texlive-all",
- will often automatically include these packages):
- * `cm-super `_
- * `dvipng `_
- * `underscore `_
+.. _tex-dependencies:
+
+LaTeX dependencies
+""""""""""""""""""
+
+The following collections must be installed. When using a distribution that does not
+support collections, the packages listed for each collection must be installed. You may
+need to install some packages that are not listed here. The complete version of many
+LaTeX distribution installers, e.g. "texlive-full" or "texlive-all",
+will often automatically include these collections.
+
++-----------------------------+--------------------------------------------------+
+| collection | packages |
++=============================+==================================================+
+| collection-basic | `cm `_, |
+| | luahbtex |
++-----------------------------+--------------------------------------------------+
+| collection-fontsrecommended | `cm-super `_, |
+| | `lm `_, |
+| | `txfonts `_ |
++-----------------------------+--------------------------------------------------+
+| collection-latex | `geometry `_, |
+| | `hyperref `_, |
+| | `latex `_, |
+| | latex-bin, |
+| | `psnfss `_ |
++-----------------------------+--------------------------------------------------+
+| collection-latexextra | `import `_, |
+| | `sfmath `_, |
+| | `type1cm `_ |
++-----------------------------+--------------------------------------------------+
+| collection-latexrecommended | `fontspec `_, |
+| | `underscore `_, |
++-----------------------------+--------------------------------------------------+
+| collection-xetex | `xetex `_, |
+| | xetex-bin |
++-----------------------------+--------------------------------------------------+
+
+The following packages must also be installed:
+
+* `dvipng `_
+* `pgf