Skip to content

Commit 1857cfd

Browse files
graingertyehoshuadimarsky
authored andcommitted
CLN/DOC: fix test_register_entrypoint (pandas-dev#46302)
1 parent eb768af commit 1857cfd

File tree

4 files changed

+63
-42
lines changed

4 files changed

+63
-42
lines changed

asv_bench/benchmarks/plotting.py

+46-14
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1-
import importlib
1+
import contextlib
2+
import importlib.machinery
3+
import importlib.util
4+
import os
5+
import pathlib
26
import sys
7+
import tempfile
8+
from unittest import mock
39

410
import matplotlib
511
import numpy as np
6-
import pkg_resources
712

813
from pandas import (
914
DataFrame,
@@ -111,22 +116,49 @@ class BackendLoading:
111116
warmup_time = 0
112117

113118
def setup(self):
114-
dist = pkg_resources.get_distribution("pandas")
115-
spec = importlib.machinery.ModuleSpec("my_backend", None)
116-
mod = importlib.util.module_from_spec(spec)
119+
mod = importlib.util.module_from_spec(
120+
importlib.machinery.ModuleSpec("pandas_dummy_backend", None)
121+
)
117122
mod.plot = lambda *args, **kwargs: 1
118123

119-
backends = pkg_resources.get_entry_map("pandas")
120-
my_entrypoint = pkg_resources.EntryPoint(
121-
"pandas_plotting_backend", mod.__name__, dist=dist
122-
)
123-
backends["pandas_plotting_backends"][mod.__name__] = my_entrypoint
124-
for i in range(10):
125-
backends["pandas_plotting_backends"][str(i)] = my_entrypoint
126-
sys.modules["my_backend"] = mod
124+
with contextlib.ExitStack() as stack:
125+
stack.enter_context(
126+
mock.patch.dict(sys.modules, {"pandas_dummy_backend": mod})
127+
)
128+
tmp_path = pathlib.Path(stack.enter_context(tempfile.TemporaryDirectory()))
129+
130+
sys.path.insert(0, os.fsdecode(tmp_path))
131+
stack.callback(sys.path.remove, os.fsdecode(tmp_path))
132+
133+
dist_info = tmp_path / "my_backend-0.0.0.dist-info"
134+
dist_info.mkdir()
135+
(dist_info / "entry_points.txt").write_bytes(
136+
b"[pandas_plotting_backends]\n"
137+
b"my_ep_backend = pandas_dummy_backend\n"
138+
b"my_ep_backend0 = pandas_dummy_backend\n"
139+
b"my_ep_backend1 = pandas_dummy_backend\n"
140+
b"my_ep_backend2 = pandas_dummy_backend\n"
141+
b"my_ep_backend3 = pandas_dummy_backend\n"
142+
b"my_ep_backend4 = pandas_dummy_backend\n"
143+
b"my_ep_backend5 = pandas_dummy_backend\n"
144+
b"my_ep_backend6 = pandas_dummy_backend\n"
145+
b"my_ep_backend7 = pandas_dummy_backend\n"
146+
b"my_ep_backend8 = pandas_dummy_backend\n"
147+
b"my_ep_backend9 = pandas_dummy_backend\n"
148+
)
149+
self.stack = stack.pop_all()
150+
151+
def teardown(self):
152+
self.stack.close()
127153

128154
def time_get_plot_backend(self):
129-
_get_plot_backend("my_backend")
155+
# finds the first my_ep_backend
156+
_get_plot_backend("my_ep_backend")
157+
158+
def time_get_plot_backend_fallback(self):
159+
# iterates through all the my_ep_backend[0-9] before falling back
160+
# to importlib.import_module
161+
_get_plot_backend("pandas_dummy_backend")
130162

131163

132164
from .pandas_vb_common import setup # noqa: F401 isort:skip

pandas/plotting/_core.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1769,7 +1769,7 @@ def _load_backend(backend: str) -> types.ModuleType:
17691769
----------
17701770
backend : str
17711771
The identifier for the backend. Either an entrypoint item registered
1772-
with pkg_resources, "matplotlib", or a module name.
1772+
with importlib.metadata, "matplotlib", or a module name.
17731773
17741774
Returns
17751775
-------

pandas/tests/plotting/test_backend.py

+14-27
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import sys
22
import types
33

4-
import pkg_resources
54
import pytest
65

76
import pandas.util._test_decorators as td
@@ -45,40 +44,28 @@ def test_backend_can_be_set_in_plot_call(monkeypatch, restore_backend):
4544
assert df.plot(backend="pandas_dummy_backend") == "used_dummy"
4645

4746

48-
@td.skip_if_no_mpl
49-
def test_register_entrypoint(restore_backend):
50-
51-
dist = pkg_resources.get_distribution("pandas")
52-
if dist.module_path not in pandas.__file__:
53-
# We are running from a non-installed pandas, and this test is invalid
54-
pytest.skip("Testing a non-installed pandas")
55-
56-
mod = types.ModuleType("my_backend")
57-
mod.plot = lambda *args, **kwargs: 1
47+
def test_register_entrypoint(restore_backend, tmp_path, monkeypatch):
48+
monkeypatch.syspath_prepend(tmp_path)
49+
monkeypatch.setitem(sys.modules, "pandas_dummy_backend", dummy_backend)
5850

59-
backends = pkg_resources.get_entry_map("pandas")
60-
my_entrypoint = pkg_resources.EntryPoint(
61-
"pandas_plotting_backend", mod.__name__, dist=dist
51+
dist_info = tmp_path / "my_backend-0.0.0.dist-info"
52+
dist_info.mkdir()
53+
# entry_point name should not match module name - otherwise pandas will
54+
# fall back to backend lookup by module name
55+
(dist_info / "entry_points.txt").write_bytes(
56+
b"[pandas_plotting_backends]\nmy_ep_backend = pandas_dummy_backend\n"
6257
)
63-
backends["pandas_plotting_backends"]["my_backend"] = my_entrypoint
64-
# TODO: the docs recommend importlib.util.module_from_spec. But this works for now.
65-
sys.modules["my_backend"] = mod
66-
67-
result = pandas.plotting._core._get_plot_backend("my_backend")
68-
assert result is mod
6958

70-
# TODO(GH#27517): https://github.com/pandas-dev/pandas/issues/27517
71-
# Remove the td.skip_if_no_mpl
72-
with pandas.option_context("plotting.backend", "my_backend"):
73-
result = pandas.plotting._core._get_plot_backend()
59+
assert pandas.plotting._core._get_plot_backend("my_ep_backend") is dummy_backend
7460

75-
assert result is mod
61+
with pandas.option_context("plotting.backend", "my_ep_backend"):
62+
assert pandas.plotting._core._get_plot_backend() is dummy_backend
7663

7764

78-
def test_setting_backend_without_plot_raises():
65+
def test_setting_backend_without_plot_raises(monkeypatch):
7966
# GH-28163
8067
module = types.ModuleType("pandas_plot_backend")
81-
sys.modules["pandas_plot_backend"] = module
68+
monkeypatch.setitem(sys.modules, "pandas_plot_backend", module)
8269

8370
assert pandas.options.plotting.backend == "matplotlib"
8471
with pytest.raises(

setup.cfg

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ per-file-ignores =
125125
doc/make.py:PDF008
126126
# import from pandas._testing
127127
pandas/testing.py:PDF014
128+
# can't use fixtures in asv
129+
asv_bench/*:PDF016
128130

129131

130132
[flake8-rst]

0 commit comments

Comments
 (0)