From e5f7982245dadce181e885228e5b68e3e0beefa5 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Thu, 28 Dec 2017 20:53:26 -0500 Subject: [PATCH 1/3] TST: centralize and standardize pandas imports Added a decorator to handle: - importorskip - using the correct unit-handler registration function to deal with: - pandas not auto-registering - pandas moving an renaming the registration function --- lib/matplotlib/tests/test_axes.py | 50 +++++++++++++++++++------------ 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 712751367c31..6cdb507efd10 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -5091,11 +5091,27 @@ def test_broken_barh_empty(): ax.broken_barh([], (.1, .5)) -def test_pandas_pcolormesh(): - pd = pytest.importorskip('pandas') - from pandas.tseries import converter - converter.register() +def _pandas_wrapper(func): + '''Decorator to centralize pandas setup / conditional import''' + import functools + + @functools.wraps(func) + def wrapped_for_pandas(*args, **kwargs): + pytest.importorskip('pandas') + try: + from pandas.plotting import ( + register_matplotlib_converters as register) + except ImportError: + from pandas.tseries.converter import register + register() + return func(*args, **kwargs) + + return wrapped_for_pandas + +@_pandas_wrapper +def test_pandas_pcolormesh(): + import pandas as pd time = pd.date_range('2000-01-01', periods=10) depth = np.arange(20) data = np.random.rand(20, 10) @@ -5104,10 +5120,9 @@ def test_pandas_pcolormesh(): ax.pcolormesh(time, depth, data) +@_pandas_wrapper def test_pandas_indexing_dates(): - pd = pytest.importorskip('pandas') - from pandas.tseries import converter - converter.register() + import pandas as pd dates = np.arange('2005-02', '2005-03', dtype='datetime64[D]') values = np.sin(np.array(range(len(dates)))) @@ -5119,10 +5134,9 @@ def test_pandas_indexing_dates(): ax.plot('dates', 'values', data=without_zero_index) +@_pandas_wrapper def test_pandas_errorbar_indexing(): - pd = pytest.importorskip('pandas') - from pandas.tseries import converter - converter.register() + import pandas as pd df = pd.DataFrame(np.random.uniform(size=(5, 4)), columns=['x', 'y', 'xe', 'ye'], @@ -5131,10 +5145,9 @@ def test_pandas_errorbar_indexing(): ax.errorbar('x', 'y', xerr='xe', yerr='ye', data=df) +@_pandas_wrapper def test_pandas_indexing_hist(): - pd = pytest.importorskip('pandas') - from pandas.tseries import converter - converter.register() + import pandas as pd ser_1 = pd.Series(data=[1, 2, 2, 3, 3, 4, 4, 4, 4, 5]) ser_2 = ser_1.iloc[1:] @@ -5142,19 +5155,18 @@ def test_pandas_indexing_hist(): axes.hist(ser_2) +@_pandas_wrapper def test_pandas_bar_align_center(): # Tests fix for issue 8767 - pd = pytest.importorskip('pandas') - from pandas.tseries import converter - converter.register() + import pandas as pd df = pd.DataFrame({'a': range(2), 'b': range(2)}) fig, ax = plt.subplots(1) - rect = ax.bar(df.loc[df['a'] == 1, 'b'], - df.loc[df['a'] == 1, 'b'], - align='center') + ax.bar(df.loc[df['a'] == 1, 'b'], + df.loc[df['a'] == 1, 'b'], + align='center') fig.canvas.draw() From d31ec5fb230cd39fc9e763b269b833a0fb66906b Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Sun, 31 Dec 2017 18:20:50 -0500 Subject: [PATCH 2/3] TST: move from decorator to fixture --- lib/matplotlib/testing/conftest.py | 23 ++++++++++++++++ lib/matplotlib/tests/conftest.py | 3 ++- lib/matplotlib/tests/test_axes.py | 42 ++++-------------------------- 3 files changed, 30 insertions(+), 38 deletions(-) diff --git a/lib/matplotlib/testing/conftest.py b/lib/matplotlib/testing/conftest.py index b3045f37bcf1..0c161b577e9e 100644 --- a/lib/matplotlib/testing/conftest.py +++ b/lib/matplotlib/testing/conftest.py @@ -76,3 +76,26 @@ def mpl_image_comparison_parameters(request, extension): yield finally: delattr(func.__wrapped__, 'parameters') + + +@pytest.fixture +def pd(request): + '''fixture to import and configure pandas''' + + pd = pytest.importorskip('pandas') + if pd: + try: + from pandas.plotting import ( + register_matplotlib_converters as register) + except ImportError: + from pandas.tseries.converter import register + register() + + try: + from pandas.plotting import ( + deregister_matplotlib_converters as deregister) + request.addfinalizer(deregister) + except ImportError: + pass + + return pd diff --git a/lib/matplotlib/tests/conftest.py b/lib/matplotlib/tests/conftest.py index b946c269bd18..c20d626ae2e1 100644 --- a/lib/matplotlib/tests/conftest.py +++ b/lib/matplotlib/tests/conftest.py @@ -2,4 +2,5 @@ from matplotlib.testing.conftest import (mpl_test_settings, mpl_image_comparison_parameters, - pytest_configure, pytest_unconfigure) + pytest_configure, pytest_unconfigure, + pd) diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 6cdb507efd10..6f3d513e4fbf 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -5091,27 +5091,7 @@ def test_broken_barh_empty(): ax.broken_barh([], (.1, .5)) -def _pandas_wrapper(func): - '''Decorator to centralize pandas setup / conditional import''' - import functools - - @functools.wraps(func) - def wrapped_for_pandas(*args, **kwargs): - pytest.importorskip('pandas') - try: - from pandas.plotting import ( - register_matplotlib_converters as register) - except ImportError: - from pandas.tseries.converter import register - register() - return func(*args, **kwargs) - - return wrapped_for_pandas - - -@_pandas_wrapper -def test_pandas_pcolormesh(): - import pandas as pd +def test_pandas_pcolormesh(pd): time = pd.date_range('2000-01-01', periods=10) depth = np.arange(20) data = np.random.rand(20, 10) @@ -5120,10 +5100,7 @@ def test_pandas_pcolormesh(): ax.pcolormesh(time, depth, data) -@_pandas_wrapper -def test_pandas_indexing_dates(): - import pandas as pd - +def test_pandas_indexing_dates(pd): dates = np.arange('2005-02', '2005-03', dtype='datetime64[D]') values = np.sin(np.array(range(len(dates)))) df = pd.DataFrame({'dates': dates, 'values': values}) @@ -5134,10 +5111,7 @@ def test_pandas_indexing_dates(): ax.plot('dates', 'values', data=without_zero_index) -@_pandas_wrapper -def test_pandas_errorbar_indexing(): - import pandas as pd - +def test_pandas_errorbar_indexing(pd): df = pd.DataFrame(np.random.uniform(size=(5, 4)), columns=['x', 'y', 'xe', 'ye'], index=[1, 2, 3, 4, 5]) @@ -5145,21 +5119,15 @@ def test_pandas_errorbar_indexing(): ax.errorbar('x', 'y', xerr='xe', yerr='ye', data=df) -@_pandas_wrapper -def test_pandas_indexing_hist(): - import pandas as pd - +def test_pandas_indexing_hist(pd): ser_1 = pd.Series(data=[1, 2, 2, 3, 3, 4, 4, 4, 4, 5]) ser_2 = ser_1.iloc[1:] fig, axes = plt.subplots() axes.hist(ser_2) -@_pandas_wrapper -def test_pandas_bar_align_center(): +def test_pandas_bar_align_center(pd): # Tests fix for issue 8767 - import pandas as pd - df = pd.DataFrame({'a': range(2), 'b': range(2)}) fig, ax = plt.subplots(1) From 34ad36cf460e4e4693e75c4ad0371bea15a74af0 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Sun, 31 Dec 2017 18:44:14 -0500 Subject: [PATCH 3/3] TST: move all pandas imports to use pd fixture --- lib/matplotlib/tests/test_collections.py | 3 +-- lib/matplotlib/tests/test_colors.py | 3 +-- lib/matplotlib/tests/test_dates.py | 5 +---- lib/matplotlib/tests/test_preprocess_data.py | 4 +--- 4 files changed, 4 insertions(+), 11 deletions(-) diff --git a/lib/matplotlib/tests/test_collections.py b/lib/matplotlib/tests/test_collections.py index abc49e2f1be4..37072a72fb45 100644 --- a/lib/matplotlib/tests/test_collections.py +++ b/lib/matplotlib/tests/test_collections.py @@ -593,8 +593,7 @@ def test_size_in_xy(): ax.set_ylim(0, 30) -def test_pandas_indexing(): - pd = pytest.importorskip('pandas') +def test_pandas_indexing(pd): # Should not fail break when faced with a # non-zero indexed series diff --git a/lib/matplotlib/tests/test_colors.py b/lib/matplotlib/tests/test_colors.py index b269157c05b5..e17fe0924b4b 100644 --- a/lib/matplotlib/tests/test_colors.py +++ b/lib/matplotlib/tests/test_colors.py @@ -604,8 +604,7 @@ def _azimuth2math(azimuth, elevation): return theta, phi -def test_pandas_iterable(): - pd = pytest.importorskip('pandas') +def test_pandas_iterable(pd): # Using a list or series yields equivalent # color maps, i.e the series isn't seen as # a single color diff --git a/lib/matplotlib/tests/test_dates.py b/lib/matplotlib/tests/test_dates.py index d7231e61ec47..73c8de9ae007 100644 --- a/lib/matplotlib/tests/test_dates.py +++ b/lib/matplotlib/tests/test_dates.py @@ -552,12 +552,9 @@ def tz_convert(dt_list, tzinfo): _test_date2num_dst(date_range, tz_convert) -def test_date2num_dst_pandas(): +def test_date2num_dst_pandas(pd): # Test for github issue #3896, but in date2num around DST transitions # with a timezone-aware pandas date_range object. - pd = pytest.importorskip('pandas') - from pandas.tseries import converter - converter.register() def tz_convert(*args): return pd.DatetimeIndex.tz_convert(*args).astype(object) diff --git a/lib/matplotlib/tests/test_preprocess_data.py b/lib/matplotlib/tests/test_preprocess_data.py index 553f9e21b554..86353f51401e 100644 --- a/lib/matplotlib/tests/test_preprocess_data.py +++ b/lib/matplotlib/tests/test_preprocess_data.py @@ -162,10 +162,8 @@ def test_function_call_with_dict_data_not_in_data(func): @pytest.mark.parametrize('func', all_funcs, ids=all_func_ids) -def test_function_call_with_pandas_data(func): +def test_function_call_with_pandas_data(func, pd): """test with pandas dataframe -> label comes from data["col"].name """ - pd = pytest.importorskip('pandas') - data = pd.DataFrame({"a": np.array([1, 2], dtype=np.int32), "b": np.array([8, 9], dtype=np.int32), "w": ["NOT", "NOT"]})