Skip to content

Commit 69c9206

Browse files
committed
Better separate backend loading.
Introduces `_load_backend` instead of `_find_backend`, which has a better defined role, and can also handle backend='matplotlib'
1 parent 9922e7f commit 69c9206

File tree

1 file changed

+39
-41
lines changed

1 file changed

+39
-41
lines changed

pandas/plotting/_core.py

Lines changed: 39 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1727,15 +1727,15 @@ def hexbin(self, x, y, C=None, reduce_C_function=None, gridsize=None, **kwargs):
17271727
_backends = {}
17281728

17291729

1730-
def _find_backend(backend: str):
1730+
def _load_backend(backend: str):
17311731
"""
1732-
Find a pandas plotting backend.
1732+
Load a pandas plotting backend.
17331733
17341734
Parameters
17351735
----------
17361736
backend : str
17371737
The identifier for the backend. Either an entrypoint item registered
1738-
with pkg_resources, or a module name.
1738+
with pkg_resources, "matplotlib", or a module name.
17391739
17401740
Notes
17411741
-----
@@ -1746,32 +1746,45 @@ def _find_backend(backend: str):
17461746
types.ModuleType
17471747
The imported backend.
17481748
"""
1749-
import pkg_resources # Delay import for performance.
1750-
1751-
for entry_point in pkg_resources.iter_entry_points("pandas_plotting_backends"):
1752-
if entry_point.name == backend:
1753-
_backends[entry_point.name] = entry_point.load()
1754-
1755-
try:
1756-
return _backends[backend]
1757-
except KeyError:
1758-
# Fall back to unregistered, module name approach.
1749+
if backend == "matplotlib":
1750+
# Because matplotlib is an optional dependency and first-party backend,
1751+
# we need to attempt an import here to raise an ImportError if needed.
17591752
try:
1760-
module = importlib.import_module(backend)
1753+
import pandas.plotting._matplotlib as module
17611754
except ImportError:
1762-
# We re-raise later on.
1763-
pass
1764-
else:
1765-
if hasattr(module, "plot"):
1766-
# Validate that the interface is implemented when the option
1767-
# is set, rather than at plot time.
1768-
_backends[backend] = module
1769-
return module
1755+
raise ImportError(
1756+
"matplotlib is required for plotting when the "
1757+
'default backend "matplotlib" is selected.'
1758+
) from None
1759+
1760+
else:
1761+
module = None
1762+
# Delay import for performance.
1763+
# TODO: replace with `importlib.metadata` when python_requires >= 3.8.
1764+
from pkg_resources import iter_entry_points
1765+
1766+
for entry_point in iter_entry_points("pandas_plotting_backends"):
1767+
if entry_point.name == backend:
1768+
module = entry_point.load()
1769+
1770+
if module is None:
1771+
# Fall back to unregistered, module name approach.
1772+
try:
1773+
module = importlib.import_module(backend)
1774+
except ImportError:
1775+
# We re-raise later on.
1776+
pass
1777+
1778+
if hasattr(module, "plot"):
1779+
# Validate that the interface is implemented when the option is set,
1780+
# rather than at plot time.
1781+
_backends[backend] = module
1782+
return module
17701783

17711784
raise ValueError(
1772-
f"Could not find plotting backend '{backend}'. Ensure that you've installed "
1773-
f"the package providing the '{backend}' entrypoint, or that the package has a "
1774-
"top-level `.plot` method."
1785+
f"Could not find plotting backend '{backend}'. Ensure that you've "
1786+
f"installed the package providing the '{backend}' entrypoint, or that "
1787+
"the package has a top-level `.plot` method."
17751788
)
17761789

17771790

@@ -1795,19 +1808,4 @@ def _get_plot_backend(backend: str | None = None):
17951808
if backend in _backends:
17961809
return _backends[backend]
17971810

1798-
if backend == "matplotlib":
1799-
# Because matplotlib is an optional dependency and first-party backend,
1800-
# we need to attempt an import here to raise an ImportError if needed.
1801-
try:
1802-
import pandas.plotting._matplotlib as module
1803-
except ImportError:
1804-
raise ImportError(
1805-
"matplotlib is required for plotting when the "
1806-
'default backend "matplotlib" is selected.'
1807-
) from None
1808-
1809-
_backends["matplotlib"] = module
1810-
return module
1811-
1812-
module = _find_backend(backend)
1813-
return module
1811+
return _load_backend(backend)

0 commit comments

Comments
 (0)