diff --git a/.coveragerc b/.coveragerc index 8882c45d..1fe261f2 100644 --- a/.coveragerc +++ b/.coveragerc @@ -10,6 +10,7 @@ omit = cf_units/_version.py cf_units/etc/* cf_units/tests/* + .eggs [report] diff --git a/.gitignore b/.gitignore index 74b49262..df1298c6 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,6 @@ cf_units/etc/site.cfg \#* \.\#* *.swp +.coverage +.eggs +.pytest_cache \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 52743327..77bbcce8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,18 +18,13 @@ install: # Create the basic testing environment # ------------------------------------ - - conda config --set always_yes yes --set changeps1 no - - conda config --set show_channel_urls True + - conda config --set always_yes yes --set changeps1 no --set show_channel_urls True - conda update --quiet conda + - conda config --add channels conda-forge - ENV_NAME='test-environment' - - conda create --quiet -n $ENV_NAME python=$TRAVIS_PYTHON_VERSION + - conda create --name $ENV_NAME python=$TRAVIS_PYTHON_VERSION udunits2 --file requirements.txt --file requirements-dev.txt - source activate $ENV_NAME - # Customise the testing environment. - # ---------------------------------- - - conda install --quiet udunits2 --file requirements.txt --file requirements-dev.txt - - pip install coveralls - # Output debug info. - conda list - conda info -a diff --git a/cf_units/__init__.py b/cf_units/__init__.py index d0d9125e..1234d257 100644 --- a/cf_units/__init__.py +++ b/cf_units/__init__.py @@ -18,7 +18,7 @@ Units of measure. Provision of a wrapper class to support Unidata/UCAR UDUNITS-2, and the -netcdftime calendar functionality. +cftime calendar functionality. See also: `UDUNITS-2 `_. @@ -36,7 +36,7 @@ import sys import warnings -import netcdftime +import cftime import numpy as np from . import config @@ -109,7 +109,7 @@ UT_DEFINITION] # -# netcdftime constants +# cftime constants # CALENDAR_STANDARD = 'standard' CALENDAR_GREGORIAN = 'gregorian' @@ -319,7 +319,7 @@ def decode_time(time): def julian_day2date(julian_day, calendar): """ - Return a netcdftime datetime-like object representing the Julian day. + Return a cftime datetime-like object representing the Julian day. If calendar is 'standard' or 'gregorian', Julian day follows Julian calendar on and before 1582-10-5, Gregorian calendar after @@ -332,7 +332,7 @@ def julian_day2date(julian_day, calendar): the Gregorian calendar (i.e. calendar is 'proleptic_gregorian', or calendar is 'standard'/'gregorian' and the date is after 1582-10-15). Otherwise, it's a 'phony' datetime object which is actually an instance - of netcdftime.datetime. + of cftime.datetime. Algorithm: Meeus, Jean (1998) Astronomical Algorithms (2nd Edition). @@ -346,7 +346,7 @@ def julian_day2date(julian_day, calendar): Name of the calendar, see cf_units.CALENDARS. Returns: - datetime or netcdftime.datetime. + datetime or cftime.datetime. For example: @@ -360,12 +360,12 @@ def julian_day2date(julian_day, calendar): """ - return netcdftime.DateFromJulianDay(julian_day, calendar) + return cftime.DateFromJulianDay(julian_day, calendar) def date2julian_day(date, calendar): """ - Return the Julian day (resolution of 1 second) from a netcdftime + Return the Julian day (resolution of 1 second) from a cftime datetime-like object. If calendar is 'standard' or 'gregorian', Julian day follows Julian @@ -380,7 +380,7 @@ def date2julian_day(date, calendar): Args: - * date (netcdftime.date): + * date (cftime.date): Date and time representation. * calendar (string): Name of the calendar, see cf_units.CALENDARS. @@ -398,7 +398,7 @@ def date2julian_day(date, calendar): """ - return netcdftime.JulianDayFromDate(date, calendar) + return cftime.JulianDayFromDate(date, calendar) def date2num(date, unit, calendar): @@ -449,7 +449,7 @@ def date2num(date, unit, calendar): # # ensure to strip out any 'UTC' postfix which is generated by - # UDUNITS-2 formatted output and causes the netcdftime parser + # UDUNITS-2 formatted output and causes the cftime parser # to choke # unit_string = unit.rstrip(" UTC") @@ -468,7 +468,7 @@ def _discard_microsecond(date): Args: - * date (datetime.datetime or netcdftime.datetime): + * date (datetime.datetime or cftime.datetime): Date value/s Returns: @@ -479,7 +479,7 @@ def _discard_microsecond(date): shape = dates.shape dates = dates.ravel() # Create date objects of the same type returned by utime.num2date() - # (either datetime.datetime or netcdftime.datetime), discarding the + # (either datetime.datetime or cftime.datetime), discarding the # microseconds dates = np.array([d and d.__class__(d.year, d.month, d.day, d.hour, d.minute, d.second) @@ -548,7 +548,7 @@ def num2date(time_value, unit, calendar): # # ensure to strip out any 'UTC' postfix which is generated by - # UDUNITS-2 formatted output and causes the netcdftime parser + # UDUNITS-2 formatted output and causes the cftime parser # to choke # unit_string = unit.rstrip(" UTC") @@ -565,7 +565,7 @@ def _num2date_to_nearest_second(time_value, utime): * time_value (float): Numeric time value/s. - * utime (netcdftime.utime): + * utime (cftime.utime): netcdf.utime object with which to perform the conversion/s. Returns: @@ -580,7 +580,7 @@ def _num2date_to_nearest_second(time_value, utime): # down. # # Note that this behaviour is different to the num2date function in version - # 1.1 and earlier of netcdftime that didn't have microsecond precision. In + # 1.1 and earlier of cftime that didn't have microsecond precision. In # those versions, a half-second value would be rounded up or down # arbitrarily. It is probably not possible to replicate that behaviour with # later versions, if one wished to do so for the sake of consistency. @@ -969,7 +969,7 @@ def is_long_time_interval(self): """ Defines whether this unit describes a time unit with a long time interval ("months" or "years"). These long time intervals *are* - supported by `UDUNITS2` but are not supported by `netcdftime`. This + supported by `UDUNITS2` but are not supported by `cftime`. This discrepancy means we cannot run self.num2date() on a time unit with a long time interval. @@ -1832,7 +1832,7 @@ def convert(self, value, other, ctype=FLOAT64, inplace=False): def utime(self): """ - Returns a netcdftime.utime object which performs conversions of + Returns a cftime.utime object which performs conversions of numeric time values to/from datetime objects given the current calendar and unit time reference. @@ -1841,7 +1841,7 @@ def utime(self): i.e. 'hours since 1970-01-01 00:00:00' Returns: - netcdftime.utime. + cftime.utime. For example: @@ -1856,7 +1856,7 @@ def utime(self): if self.calendar is None: raise ValueError('Unit has undefined calendar') - # `netcdftime` cannot parse long time intervals ("months" or "years"). + # `cftime` cannot parse long time intervals ("months" or "years"). if self.is_long_time_interval(): interval = self.origin.split(' ')[0] emsg = ('Time units with interval of "months", "years" ' @@ -1867,7 +1867,7 @@ def utime(self): # ensure to strip out non-parsable 'UTC' postfix, which # is generated by UDUNITS-2 formatted output # - return netcdftime.utime(str(self).rstrip(" UTC"), self.calendar) + return cftime.utime(str(self).rstrip(" UTC"), self.calendar) def date2num(self, date): """ @@ -1921,7 +1921,7 @@ def num2date(self, time_value): if the date falls in the Gregorian calendar (i.e. the calendar is 'standard', 'gregorian', or 'proleptic_gregorian' and the date is after 1582-10-15). Otherwise a 'phoney' datetime-like - object (netcdftime.datetime) is returned which can handle dates + object (cftime.datetime) is returned which can handle dates that don't exist in the Proleptic Gregorian calendar. Works for scalars, sequences and numpy arrays. Returns a scalar diff --git a/cf_units/tests/__init__.py b/cf_units/tests/__init__.py index 53d1356a..abe705fe 100644 --- a/cf_units/tests/__init__.py +++ b/cf_units/tests/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2015, Met Office +# (C) British Crown Copyright 2010 - 2018, Met Office # # This file is part of cf_units. # diff --git a/cf_units/tests/integration/test__num2date_to_nearest_second.py b/cf_units/tests/integration/test__num2date_to_nearest_second.py index e8ab99bd..9138537c 100644 --- a/cf_units/tests/integration/test__num2date_to_nearest_second.py +++ b/cf_units/tests/integration/test__num2date_to_nearest_second.py @@ -24,17 +24,17 @@ import numpy as np import numpy.testing -import netcdftime +import cftime from cf_units import _num2date_to_nearest_second, Unit class Test(unittest.TestCase): def setup_units(self, calendar): - self.useconds = netcdftime.utime('seconds since 1970-01-01', calendar) - self.uminutes = netcdftime.utime('minutes since 1970-01-01', calendar) - self.uhours = netcdftime.utime('hours since 1970-01-01', calendar) - self.udays = netcdftime.utime('days since 1970-01-01', calendar) + self.useconds = cftime.utime('seconds since 1970-01-01', calendar) + self.uminutes = cftime.utime('minutes since 1970-01-01', calendar) + self.uhours = cftime.utime('hours since 1970-01-01', calendar) + self.udays = cftime.utime('days since 1970-01-01', calendar) def check_dates(self, nums, utimes, expected): for num, utime, exp in zip(nums, utimes, expected): @@ -50,14 +50,14 @@ def check_timedelta(self, nums, utimes, expected): self.assertEqual((delta.days, seconds), exp) def test_scalar(self): - utime = netcdftime.utime('seconds since 1970-01-01', 'gregorian') + utime = cftime.utime('seconds since 1970-01-01', 'gregorian') num = 5. exp = datetime.datetime(1970, 1, 1, 0, 0, 5) res = _num2date_to_nearest_second(num, utime) self.assertEqual(exp, res) def test_sequence(self): - utime = netcdftime.utime('seconds since 1970-01-01', 'gregorian') + utime = cftime.utime('seconds since 1970-01-01', 'gregorian') nums = [20., 40., 60., 80, 100.] exp = [datetime.datetime(1970, 1, 1, 0, 0, 20), datetime.datetime(1970, 1, 1, 0, 0, 40), @@ -68,7 +68,7 @@ def test_sequence(self): np.testing.assert_array_equal(exp, res) def test_multidim_sequence(self): - utime = netcdftime.utime('seconds since 1970-01-01', 'gregorian') + utime = cftime.utime('seconds since 1970-01-01', 'gregorian') nums = [[20., 40., 60.], [80, 100., 120.]] exp_shape = (2, 3) @@ -76,7 +76,7 @@ def test_multidim_sequence(self): self.assertEqual(exp_shape, res.shape) def test_masked_ndarray(self): - utime = netcdftime.utime('seconds since 1970-01-01', 'gregorian') + utime = cftime.utime('seconds since 1970-01-01', 'gregorian') nums = np.ma.masked_array([20., 40., 60.], [False, True, False]) exp = [datetime.datetime(1970, 1, 1, 0, 0, 20), None, diff --git a/cf_units/tests/integration/test_date2num.py b/cf_units/tests/integration/test_date2num.py index aa31f21e..caec9be8 100644 --- a/cf_units/tests/integration/test_date2num.py +++ b/cf_units/tests/integration/test_date2num.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2016 - 2017, Met Office +# (C) British Crown Copyright 2016 - 2018, Met Office # # This file is part of cf_units. # @@ -24,7 +24,7 @@ import numpy as np import numpy.testing -import netcdftime +import cftime from cf_units import date2num, Unit diff --git a/requirements-dev.txt b/requirements-dev.txt index f90f72f7..83cb6a1f 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,2 +1,3 @@ +coveralls pep8 pip diff --git a/requirements.txt b/requirements.txt index 15848c84..3c589d44 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ six -netcdf4 +cftime cython numpy # udunits2 cannot be installed with pip, and it is expected to be installed separately.