From c7f1c99cefbe479a68c3f36c16bd1c9b3f040f88 Mon Sep 17 00:00:00 2001 From: Spencer Clark Date: Tue, 20 Feb 2018 15:57:11 -0500 Subject: [PATCH 1/2] Switch requires_netCDF4 decorators to requires_netcdftime decorators in test_coding_times.py --- xarray/tests/test_coding_times.py | 56 +++++++++++++++---------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/xarray/tests/test_coding_times.py b/xarray/tests/test_coding_times.py index eb5c03b1f95..0211fb53ae1 100644 --- a/xarray/tests/test_coding_times.py +++ b/xarray/tests/test_coding_times.py @@ -8,8 +8,9 @@ import pandas as pd from xarray import Variable, coding +from xarray.coding.times import _import_netcdftime from . import ( - TestCase, requires_netCDF4, assert_array_equal) + TestCase, requires_netcdftime, assert_array_equal) import pytest @@ -22,9 +23,9 @@ def _ensure_naive_tz(dt): class TestDatetime(TestCase): - @requires_netCDF4 + @requires_netcdftime def test_cf_datetime(self): - import netCDF4 as nc4 + nctime = _import_netcdftime() for num_dates, units in [ (np.arange(10), 'days since 2000-01-01'), (np.arange(10).astype('float64'), 'days since 2000-01-01'), @@ -53,7 +54,7 @@ def test_cf_datetime(self): ]: for calendar in ['standard', 'gregorian', 'proleptic_gregorian']: expected = _ensure_naive_tz( - nc4.num2date(num_dates, units, calendar)) + nctime.num2date(num_dates, units, calendar)) print(num_dates, units, calendar) with warnings.catch_warnings(): warnings.filterwarnings('ignore', @@ -88,7 +89,7 @@ def test_cf_datetime(self): pd.Index(actual), units, calendar) assert_array_equal(num_dates, np.around(encoded, 1)) - @requires_netCDF4 + @requires_netcdftime def test_decode_cf_datetime_overflow(self): # checks for # https://github.com/pydata/pandas/issues/14068 @@ -113,7 +114,7 @@ def test_decode_cf_datetime_non_standard_units(self): actual = coding.times.decode_cf_datetime(np.arange(100), units) assert_array_equal(actual, expected) - @requires_netCDF4 + @requires_netcdftime def test_decode_cf_datetime_non_iso_strings(self): # datetime strings that are _almost_ ISO compliant but not quite, # but which netCDF4.num2date can still parse correctly @@ -125,17 +126,17 @@ def test_decode_cf_datetime_non_iso_strings(self): actual = coding.times.decode_cf_datetime(num_dates, units) assert_array_equal(actual, expected) - @requires_netCDF4 + @requires_netcdftime def test_decode_non_standard_calendar(self): - import netCDF4 as nc4 + nctime = _import_netcdftime() for calendar in ['noleap', '365_day', '360_day', 'julian', 'all_leap', '366_day']: units = 'days since 0001-01-01' times = pd.date_range('2001-04-01-00', end='2001-04-30-23', freq='H') - noleap_time = nc4.date2num(times.to_pydatetime(), units, - calendar=calendar) + noleap_time = nctime.date2num(times.to_pydatetime(), units, + calendar=calendar) expected = times.values with warnings.catch_warnings(): warnings.filterwarnings('ignore', 'Unable to decode time axis') @@ -148,7 +149,7 @@ def test_decode_non_standard_calendar(self): # https://github.com/Unidata/netcdf4-python/issues/355 assert (abs_diff <= np.timedelta64(1, 's')).all() - @requires_netCDF4 + @requires_netcdftime def test_decode_non_standard_calendar_single_element(self): units = 'days since 0001-01-01' for calendar in ['noleap', '365_day', '360_day', 'julian', 'all_leap', @@ -161,34 +162,33 @@ def test_decode_non_standard_calendar_single_element(self): calendar=calendar) assert actual.dtype == np.dtype('M8[ns]') - @requires_netCDF4 + @requires_netcdftime def test_decode_non_standard_calendar_single_element_fallback(self): - import netCDF4 as nc4 + nctime = _import_netcdftime() units = 'days since 0001-01-01' - dt = nc4.netcdftime.datetime(2001, 2, 29) + dt = nctime.netcdftime.datetime(2001, 2, 29) for calendar in ['360_day', 'all_leap', '366_day']: - num_time = nc4.date2num(dt, units, calendar) + num_time = nctime.date2num(dt, units, calendar) with pytest.warns(Warning, match='Unable to decode time axis'): actual = coding.times.decode_cf_datetime(num_time, units, calendar=calendar) - expected = np.asarray(nc4.num2date(num_time, units, calendar)) - print(num_time, calendar, actual, expected) + expected = np.asarray(nctime.num2date(num_time, units, calendar)) assert actual.dtype == np.dtype('O') assert expected == actual - @requires_netCDF4 + @requires_netcdftime def test_decode_non_standard_calendar_multidim_time(self): - import netCDF4 as nc4 + nctime = _import_netcdftime() calendar = 'noleap' units = 'days since 0001-01-01' times1 = pd.date_range('2001-04-01', end='2001-04-05', freq='D') times2 = pd.date_range('2001-05-01', end='2001-05-05', freq='D') - noleap_time1 = nc4.date2num(times1.to_pydatetime(), units, - calendar=calendar) - noleap_time2 = nc4.date2num(times2.to_pydatetime(), units, - calendar=calendar) + noleap_time1 = nctime.date2num(times1.to_pydatetime(), units, + calendar=calendar) + noleap_time2 = nctime.date2num(times2.to_pydatetime(), units, + calendar=calendar) mdim_time = np.empty((len(noleap_time1), 2), ) mdim_time[:, 0] = noleap_time1 mdim_time[:, 1] = noleap_time2 @@ -203,16 +203,16 @@ def test_decode_non_standard_calendar_multidim_time(self): assert_array_equal(actual[:, 0], expected1) assert_array_equal(actual[:, 1], expected2) - @requires_netCDF4 + @requires_netcdftime def test_decode_non_standard_calendar_fallback(self): - import netCDF4 as nc4 + nctime = _import_netcdftime() # ensure leap year doesn't matter for year in [2010, 2011, 2012, 2013, 2014]: for calendar in ['360_day', '366_day', 'all_leap']: calendar = '360_day' units = 'days since {0}-01-01'.format(year) num_times = np.arange(100) - expected = nc4.num2date(num_times, units, calendar) + expected = nctime.num2date(num_times, units, calendar) with warnings.catch_warnings(record=True) as w: warnings.simplefilter('always') @@ -225,7 +225,7 @@ def test_decode_non_standard_calendar_fallback(self): assert actual.dtype == np.dtype('O') assert_array_equal(actual, expected) - @requires_netCDF4 + @requires_netcdftime def test_cf_datetime_nan(self): for num_dates, units, expected_list in [ ([np.nan], 'days since 2000-01-01', ['NaT']), @@ -240,7 +240,7 @@ def test_cf_datetime_nan(self): expected = np.array(expected_list, dtype='datetime64[ns]') assert_array_equal(expected, actual) - @requires_netCDF4 + @requires_netcdftime def test_decoded_cf_datetime_array_2d(self): # regression test for GH1229 variable = Variable(('x', 'y'), np.array([[0, 1], [2, 3]]), From 93f2e03aeb18e79488026464798b95328856c8a1 Mon Sep 17 00:00:00 2001 From: Spencer Clark Date: Tue, 20 Feb 2018 16:20:44 -0500 Subject: [PATCH 2/2] Fix 'netcdftime' has no attribute 'netcdftime' error --- xarray/tests/test_coding_times.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/xarray/tests/test_coding_times.py b/xarray/tests/test_coding_times.py index 0211fb53ae1..092559ce9da 100644 --- a/xarray/tests/test_coding_times.py +++ b/xarray/tests/test_coding_times.py @@ -167,7 +167,11 @@ def test_decode_non_standard_calendar_single_element_fallback(self): nctime = _import_netcdftime() units = 'days since 0001-01-01' - dt = nctime.netcdftime.datetime(2001, 2, 29) + try: + dt = nctime.netcdftime.datetime(2001, 2, 29) + except AttributeError: + # Must be using standalone netcdftime library + dt = nctime.datetime(2001, 2, 29) for calendar in ['360_day', 'all_leap', '366_day']: num_time = nctime.date2num(dt, units, calendar) with pytest.warns(Warning, match='Unable to decode time axis'):