Skip to content

Commit

Permalink
MNT: Add provisional get_backend(resolve=False) flag
Browse files Browse the repository at this point in the history
The default is `resolve=True` for now, so that this introduction
is completely backward-compatible.

The provisional introduction anticipates planned changes for the
backend resolution (matplotlib#26406 (comment)).

If all plays out as intended, this prolongs the range of releases
for the migration: If we start deprecating `rcParams._get("backend")` say in 3.11, people can immediately switch to
`get_backend(resolve=False)` and their code still runs on 3.10
without version gating.
The worst that can happen is that the introduced flag was not
helpful and we remove it again, which is easy because it's provisional.
  • Loading branch information
timhoffm committed Oct 29, 2024
1 parent 202a277 commit 3e363f2
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 4 deletions.
26 changes: 24 additions & 2 deletions lib/matplotlib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1296,15 +1296,37 @@ def use(backend, *, force=True):
rcParams['backend'] = os.environ.get('MPLBACKEND')


def get_backend():
def get_backend(resolve: bool = True):
"""
Return the name of the current backend.
Parameters
----------
resolve : bool, default: True
Whether to trigger backend resolution if no backend has been
selected so far. If True, this ensures that a valid backend
is returned. If False, this returns None if no backend has been
selected so far.
.. admonition:: Provisional resolve flag
The *resolve* flag is introduced provisionally in the anticipation
of backend resolution refactoring. We don't guarantee API stability
for now, but if all plays out well, the provisional availability
will prolong the range of supported releases for the migration period.
See Also
--------
matplotlib.use
"""
return rcParams['backend']
if resolve:
return rcParams['backend']
else:
backend = rcParams._get('backend')
if backend is rcsetup._auto_backend_sentinel():
return None
else:
return backend


def interactive(b):
Expand Down
6 changes: 4 additions & 2 deletions lib/matplotlib/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import contextlib
from packaging.version import Version

from matplotlib._api import MatplotlibDeprecationWarning
from typing import Any, NamedTuple
from typing import Any, Literal, NamedTuple, overload

class _VersionInfo(NamedTuple):
major: int
Expand Down Expand Up @@ -104,7 +104,9 @@ def rc_context(
rc: dict[str, Any] | None = ..., fname: str | Path | os.PathLike | None = ...
) -> Generator[None, None, None]: ...
def use(backend: str, *, force: bool = ...) -> None: ...
def get_backend() -> str: ...
@overload
def get_backend(*, resolve: Literal[True] = True) -> str: ...
def get_backend(*, resolve: bool = True) -> str | None: ...
def interactive(b: bool) -> None: ...
def is_interactive() -> bool: ...

Expand Down
1 change: 1 addition & 0 deletions lib/matplotlib/tests/test_rcparams.py
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,7 @@ def test_backend_fallback_headful(tmp_path):
# Check that access on another instance does not resolve the sentinel.
"assert mpl.RcParams({'backend': sentinel})['backend'] == sentinel; "
"assert mpl.rcParams._get('backend') == sentinel; "
"assert matplotlib.get_backend(resolve=False) is None; "
"import matplotlib.pyplot; "
"print(matplotlib.get_backend())"],
env=env, text=True, check=True, capture_output=True).stdout
Expand Down

0 comments on commit 3e363f2

Please sign in to comment.