Skip to content

Commit

Permalink
TST: Skipif decorator for matplotlib #18190
Browse files Browse the repository at this point in the history
  • Loading branch information
WillAyd committed Nov 26, 2017
1 parent 982ad07 commit 6d7ff3c
Show file tree
Hide file tree
Showing 14 changed files with 111 additions and 29 deletions.
3 changes: 2 additions & 1 deletion pandas/tests/io/formats/test_style.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import pandas as pd
from pandas import DataFrame
import pandas.util.testing as tm
from pandas.util._test_decorators import skip_if_no_mpl

jinja2 = pytest.importorskip('jinja2')
from pandas.io.formats.style import Styler, _get_level_lengths # noqa
Expand Down Expand Up @@ -1011,8 +1012,8 @@ def test_hide_columns_mult_levels(self):

class TestStylerMatplotlibDep(object):

@skip_if_no_mpl
def test_background_gradient(self):
tm._skip_if_no_mpl()
df = pd.DataFrame([[1, 2], [2, 4]], columns=['A', 'B'])

for c_map in [None, 'YlOrRd']:
Expand Down
4 changes: 2 additions & 2 deletions pandas/tests/plotting/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import pandas.util.testing as tm
from pandas.util.testing import (ensure_clean,
assert_is_valid_plot_return_object)
from pandas.util._test_decorators import skip_if_no_mpl

import numpy as np
from numpy import random
Expand All @@ -23,8 +24,6 @@
This is a common base class used for various plotting tests
"""

tm._skip_if_no_mpl()


def _skip_if_no_scipy_gaussian_kde():
try:
Expand All @@ -43,6 +42,7 @@ def _ok_for_gaussian_kde(kind):
return plotting._compat._mpl_ge_1_5_0()


@skip_if_no_mpl
class TestPlotBase(object):

def setup_method(self, method):
Expand Down
5 changes: 3 additions & 2 deletions pandas/tests/plotting/test_boxplot_method.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from pandas import Series, DataFrame, MultiIndex
from pandas.compat import range, lzip
import pandas.util.testing as tm
from pandas.util._test_decorators import skip_if_no_mpl

import numpy as np
from numpy import random
Expand All @@ -19,8 +20,6 @@

""" Test cases for .boxplot method """

tm._skip_if_no_mpl()


def _skip_if_mpl_14_or_dev_boxplot():
# GH 8382
Expand All @@ -31,6 +30,7 @@ def _skip_if_mpl_14_or_dev_boxplot():
pytest.skip("Matplotlib Regression in 1.4 and current dev.")


@skip_if_no_mpl
class TestDataFramePlots(TestPlotBase):

@pytest.mark.slow
Expand Down Expand Up @@ -174,6 +174,7 @@ def test_fontsize(self):
xlabelsize=16, ylabelsize=16)


@skip_if_no_mpl
class TestDataFrameGroupByPlots(TestPlotBase):

@pytest.mark.slow
Expand Down
4 changes: 2 additions & 2 deletions pandas/tests/plotting/test_datetimelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@

from pandas.util.testing import assert_series_equal, ensure_clean
import pandas.util.testing as tm
from pandas.util._test_decorators import skip_if_no_mpl

from pandas.tests.plotting.common import (TestPlotBase,
_skip_if_no_scipy_gaussian_kde)

tm._skip_if_no_mpl()


@skip_if_no_mpl
class TestTSPlot(TestPlotBase):

def setup_method(self, method):
Expand Down
4 changes: 2 additions & 2 deletions pandas/tests/plotting/test_deprecated.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import pandas as pd
import pandas.util.testing as tm
from pandas.util._test_decorators import skip_if_no_mpl
import pytest

from numpy.random import randn
Expand All @@ -18,9 +19,8 @@
pandas.tools.plotting
"""

tm._skip_if_no_mpl()


@skip_if_no_mpl
class TestDeprecatedNameSpace(TestPlotBase):

@pytest.mark.slow
Expand Down
4 changes: 2 additions & 2 deletions pandas/tests/plotting/test_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from pandas.compat import range, lrange, lmap, lzip, u, zip, PY3
from pandas.io.formats.printing import pprint_thing
import pandas.util.testing as tm
from pandas.util._test_decorators import skip_if_no_mpl

import numpy as np
from numpy.random import rand, randn
Expand All @@ -24,9 +25,8 @@
_skip_if_no_scipy_gaussian_kde,
_ok_for_gaussian_kde)

tm._skip_if_no_mpl()


@skip_if_no_mpl
class TestDataFramePlots(TestPlotBase):

def setup_method(self, method):
Expand Down
4 changes: 2 additions & 2 deletions pandas/tests/plotting/test_groupby.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@

from pandas import Series, DataFrame
import pandas.util.testing as tm
from pandas.util._test_decorators import skip_if_no_mpl

import numpy as np

from pandas.tests.plotting.common import TestPlotBase

tm._skip_if_no_mpl()


@skip_if_no_mpl
class TestDataFrameGroupByPlots(TestPlotBase):

def test_series_groupby_plotting_nominally_works(self):
Expand Down
7 changes: 4 additions & 3 deletions pandas/tests/plotting/test_hist_method.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from pandas import Series, DataFrame
import pandas.util.testing as tm
from pandas.util._test_decorators import skip_if_no_mpl

import numpy as np
from numpy.random import randn
Expand All @@ -14,9 +15,7 @@
from pandas.tests.plotting.common import (TestPlotBase, _check_plot_works)


tm._skip_if_no_mpl()


@skip_if_no_mpl
class TestSeriesPlots(TestPlotBase):

def setup_method(self, method):
Expand Down Expand Up @@ -141,6 +140,7 @@ def test_plot_fails_when_ax_differs_from_figure(self):
self.ts.hist(ax=ax1, figure=fig2)


@skip_if_no_mpl
class TestDataFramePlots(TestPlotBase):

@pytest.mark.slow
Expand Down Expand Up @@ -251,6 +251,7 @@ def test_tight_layout(self):
tm.close()


@skip_if_no_mpl
class TestDataFrameGroupByPlots(TestPlotBase):

@pytest.mark.slow
Expand Down
5 changes: 3 additions & 2 deletions pandas/tests/plotting/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from pandas import DataFrame
from pandas.compat import lmap
import pandas.util.testing as tm
from pandas.util._test_decorators import skip_if_no_mpl

import numpy as np
from numpy import random
Expand All @@ -15,9 +16,8 @@
import pandas.plotting as plotting
from pandas.tests.plotting.common import TestPlotBase, _check_plot_works

tm._skip_if_no_mpl()


@skip_if_no_mpl
class TestSeriesPlots(TestPlotBase):

def setup_method(self, method):
Expand Down Expand Up @@ -49,6 +49,7 @@ def test_bootstrap_plot(self):
_check_plot_works(bootstrap_plot, series=self.ts, size=10)


@skip_if_no_mpl
class TestDataFramePlots(TestPlotBase):

def test_scatter_matrix_axis(self):
Expand Down
4 changes: 2 additions & 2 deletions pandas/tests/plotting/test_series.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from pandas import Series, DataFrame, date_range
from pandas.compat import range, lrange
import pandas.util.testing as tm
from pandas.util._test_decorators import skip_if_no_mpl

import numpy as np
from numpy.random import randn
Expand All @@ -21,9 +22,8 @@
_skip_if_no_scipy_gaussian_kde,
_ok_for_gaussian_kde)

tm._skip_if_no_mpl()


@skip_if_no_mpl
class TestSeriesPlots(TestPlotBase):

def setup_method(self, method):
Expand Down
4 changes: 2 additions & 2 deletions pandas/tests/test_resample.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import pandas as pd
import pandas.tseries.offsets as offsets
import pandas.util.testing as tm
from pandas.util._test_decorators import skip_if_no_mpl
from pandas import (Series, DataFrame, Panel, Index, isna,
notna, Timestamp)

Expand Down Expand Up @@ -234,9 +235,8 @@ def test_groupby_resample_on_api(self):
result = df.groupby('key').resample('D', on='dates').mean()
assert_frame_equal(result, expected)

@skip_if_no_mpl
def test_plot_api(self):
tm._skip_if_no_mpl()

# .resample(....).plot(...)
# hitting warnings
# GH 12448
Expand Down
18 changes: 18 additions & 0 deletions pandas/tests/util/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
validate_bool_kwarg)

import pandas.util.testing as tm
from pandas.util._test_decorators import safe_import


class TestDecorators(object):
Expand Down Expand Up @@ -482,3 +483,20 @@ def test_make_signature():
assert sig == (['old_arg_name', 'new_arg_name',
'mapping=None', 'stacklevel=2'],
['old_arg_name', 'new_arg_name', 'mapping', 'stacklevel'])


def test_safe_import(monkeypatch):
assert not safe_import("foo")
assert not safe_import("pandas", min_version="99.99.99")

# Create dummy module to be imported
import types
import sys
mod_name = "hello123"
mod = types.ModuleType(mod_name)
mod.__version__ = "1.5"

assert not safe_import(mod_name)
monkeypatch.setitem(sys.modules, mod_name, mod)
assert not safe_import(mod_name, min_version="2.0")
assert safe_import(mod_name, min_version="1.0")
67 changes: 67 additions & 0 deletions pandas/util/_test_decorators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"""
This module provides decorator functions which can be applied to test objects
in order to skip those objects when certain conditions occur. A sample use case
is to detect if the platform is missing ``matplotlib``. If so, any test objects
which require ``matplotlib`` and marked with ``skip_if_no_mpl`` will be skipped
by ``pytest`` during the execution of the test suite.
The decorators can be applied to classes:
@skip_if_some_reason
class Foo():
...
Or individual functions:
@skip_if_some_reason
def test_foo():
...
For more information, refer to the ``pytest`` documentation on ``skipif``.
"""

import pytest


def safe_import(mod_name, min_version=None):
"""
Parameters:
-----------
mod_name : str
Name of the module to be imported
min_version : str, default None
Minimum required version of the specified mod_name
Returns:
--------
object
The imported module if successful, or False
"""
try:
mod = __import__(mod_name)
except ImportError:
return False

if not min_version:
return mod
else:
import sys
version = getattr(sys.modules[mod_name], '__version__')
if version:
from distutils.version import LooseVersion
if LooseVersion(version) >= LooseVersion(min_version):
return mod

return False


def _skip_if_no_mpl():
mod = safe_import("matplotlib")
if mod:
mod.use("Agg", warn=False)
else:
return True


skip_if_no_mpl = pytest.mark.skipif(_skip_if_no_mpl(),
reason="Missing matplotlib dependency")
7 changes: 0 additions & 7 deletions pandas/util/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,13 +325,6 @@ def _skip_if_32bit():
pytest.skip("skipping for 32 bit")


def _skip_if_no_mpl():
import pytest

mpl = pytest.importorskip("matplotlib")
mpl.use("Agg", warn=False)


def _skip_if_mpl_1_5():
import matplotlib as mpl

Expand Down

0 comments on commit 6d7ff3c

Please sign in to comment.