Skip to content

Commit 1d7aedc

Browse files
authored
TST: Ensure Matplotlib is always cleaned up (#57389)
The seaborn test also uses Matplotlib but was not wrapped in the cleanup fixture, As there are now 3 files that need this fixture, refactor to reduce code duplication.
1 parent baf98b8 commit 1d7aedc

File tree

4 files changed

+38
-41
lines changed

4 files changed

+38
-41
lines changed

pandas/conftest.py

+34
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
timezone,
2929
)
3030
from decimal import Decimal
31+
import gc
3132
import operator
3233
import os
3334
from typing import (
@@ -1863,6 +1864,39 @@ def ip():
18631864
return InteractiveShell(config=c)
18641865

18651866

1867+
@pytest.fixture
1868+
def mpl_cleanup():
1869+
"""
1870+
Ensure Matplotlib is cleaned up around a test.
1871+
1872+
Before a test is run:
1873+
1874+
1) Set the backend to "template" to avoid requiring a GUI.
1875+
1876+
After a test is run:
1877+
1878+
1) Reset units registry
1879+
2) Reset rc_context
1880+
3) Close all figures
1881+
1882+
See matplotlib/testing/decorators.py#L24.
1883+
"""
1884+
mpl = pytest.importorskip("matplotlib")
1885+
mpl_units = pytest.importorskip("matplotlib.units")
1886+
plt = pytest.importorskip("matplotlib.pyplot")
1887+
orig_units_registry = mpl_units.registry.copy()
1888+
try:
1889+
with mpl.rc_context():
1890+
mpl.use("template")
1891+
yield
1892+
finally:
1893+
mpl_units.registry.clear()
1894+
mpl_units.registry.update(orig_units_registry)
1895+
plt.close("all")
1896+
# https://matplotlib.org/stable/users/prev_whats_new/whats_new_3.6.0.html#garbage-collection-is-no-longer-run-on-figure-close # noqa: E501
1897+
gc.collect(1)
1898+
1899+
18661900
@pytest.fixture(
18671901
params=[
18681902
getattr(pd.offsets, o)

pandas/tests/io/formats/style/test_matplotlib.py

+1-21
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import gc
2-
31
import numpy as np
42
import pytest
53

@@ -16,25 +14,7 @@
1614

1715
from pandas.io.formats.style import Styler
1816

19-
20-
@pytest.fixture(autouse=True)
21-
def mpl_cleanup():
22-
# matplotlib/testing/decorators.py#L24
23-
# 1) Resets units registry
24-
# 2) Resets rc_context
25-
# 3) Closes all figures
26-
mpl = pytest.importorskip("matplotlib")
27-
mpl_units = pytest.importorskip("matplotlib.units")
28-
plt = pytest.importorskip("matplotlib.pyplot")
29-
orig_units_registry = mpl_units.registry.copy()
30-
with mpl.rc_context():
31-
mpl.use("template")
32-
yield
33-
mpl_units.registry.clear()
34-
mpl_units.registry.update(orig_units_registry)
35-
plt.close("all")
36-
# https://matplotlib.org/stable/users/prev_whats_new/whats_new_3.6.0.html#garbage-collection-is-no-longer-run-on-figure-close # noqa: E501
37-
gc.collect(1)
17+
pytestmark = pytest.mark.usefixtures("mpl_cleanup")
3818

3919

4020
@pytest.fixture

pandas/tests/plotting/conftest.py

+2-19
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import gc
2-
31
import numpy as np
42
import pytest
53

@@ -10,23 +8,8 @@
108

119

1210
@pytest.fixture(autouse=True)
13-
def mpl_cleanup():
14-
# matplotlib/testing/decorators.py#L24
15-
# 1) Resets units registry
16-
# 2) Resets rc_context
17-
# 3) Closes all figures
18-
mpl = pytest.importorskip("matplotlib")
19-
mpl_units = pytest.importorskip("matplotlib.units")
20-
plt = pytest.importorskip("matplotlib.pyplot")
21-
orig_units_registry = mpl_units.registry.copy()
22-
with mpl.rc_context():
23-
mpl.use("template")
24-
yield
25-
mpl_units.registry.clear()
26-
mpl_units.registry.update(orig_units_registry)
27-
plt.close("all")
28-
# https://matplotlib.org/stable/users/prev_whats_new/whats_new_3.6.0.html#garbage-collection-is-no-longer-run-on-figure-close # noqa: E501
29-
gc.collect(1)
11+
def autouse_mpl_cleanup(mpl_cleanup):
12+
pass
3013

3114

3215
@pytest.fixture

pandas/tests/test_downstream.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ def test_scikit_learn():
155155
clf.predict(digits.data[-1:])
156156

157157

158-
def test_seaborn():
158+
def test_seaborn(mpl_cleanup):
159159
seaborn = pytest.importorskip("seaborn")
160160
tips = DataFrame(
161161
{"day": pd.date_range("2023", freq="D", periods=5), "total_bill": range(5)}

0 commit comments

Comments
 (0)