Skip to content

Commit 2c03c5e

Browse files
committed
COMPAT: numpy_compat for >= 1.11 for np.datetime64 tz changes, #12100
closes #12100 Author: Jeff Reback <[email protected]> Closes #12127 from jreback/dt64_compat and squashes the following commits: acb7cfd [Jeff Reback] COMPAT: numpy_compat for >= 1.11 for np.datetime64 tz changes, #12100
1 parent 81bb972 commit 2c03c5e

File tree

7 files changed

+124
-59
lines changed

7 files changed

+124
-59
lines changed

pandas/__init__.py

+9-27
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@
44

55
__docformat__ = 'restructuredtext'
66

7+
# use the closest tagged version if possible
8+
from ._version import get_versions
9+
v = get_versions()
10+
__version__ = v.get('closest-tag',v['version'])
11+
del get_versions, v
12+
13+
# numpy compat
14+
from pandas.compat.numpy_compat import *
15+
716
try:
817
from pandas import hashtable, tslib, lib
918
except ImportError as e: # pragma: no cover
@@ -16,29 +25,8 @@
1625
from datetime import datetime
1726
import numpy as np
1827

19-
20-
# XXX: HACK for NumPy 1.5.1 to suppress warnings
21-
try:
22-
np.seterr(all='ignore')
23-
except Exception: # pragma: no cover
24-
pass
25-
26-
# numpy versioning
27-
from distutils.version import LooseVersion
28-
_np_version = np.version.short_version
29-
_np_version_under1p8 = LooseVersion(_np_version) < '1.8'
30-
_np_version_under1p9 = LooseVersion(_np_version) < '1.9'
31-
32-
3328
from pandas.info import __doc__
3429

35-
36-
if LooseVersion(_np_version) < '1.7.0':
37-
raise ImportError('pandas {0} is incompatible with numpy < 1.7.0, '
38-
'your numpy version is {1}. Please upgrade numpy to'
39-
' >= 1.7.0 to use pandas version {0}'.format(__version__,
40-
_np_version))
41-
4230
# let init-time option registration happen
4331
import pandas.core.config_init
4432

@@ -62,9 +50,3 @@
6250
from pandas.util.nosetester import NoseTester
6351
test = NoseTester().test
6452
del NoseTester
65-
66-
# use the closest tagged version if possible
67-
from ._version import get_versions
68-
v = get_versions()
69-
__version__ = v.get('closest-tag',v['version'])
70-
del get_versions, v

pandas/compat/numpy_compat.py

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
""" support numpy compatiblitiy across versions """
2+
3+
from distutils.version import LooseVersion
4+
from pandas.compat import string_types, string_and_binary_types
5+
import numpy as np
6+
7+
# TODO: HACK for NumPy 1.5.1 to suppress warnings
8+
# is this necessary?
9+
try:
10+
np.seterr(all='ignore')
11+
except Exception: # pragma: no cover
12+
pass
13+
14+
# numpy versioning
15+
_np_version = np.version.short_version
16+
_np_version_under1p8 = LooseVersion(_np_version) < '1.8'
17+
_np_version_under1p9 = LooseVersion(_np_version) < '1.9'
18+
_np_version_under1p10 = LooseVersion(_np_version) < '1.10'
19+
_np_version_under1p11 = LooseVersion(_np_version) < '1.11'
20+
21+
if LooseVersion(_np_version) < '1.7.0':
22+
from pandas import __version__
23+
raise ImportError('pandas {0} is incompatible with numpy < 1.7.0\n'
24+
'your numpy version is {1}.\n'
25+
'Please upgrade numpy to >= 1.7.0 to use '
26+
'this pandas version'.format(__version__, _np_version))
27+
28+
29+
def tz_replacer(s):
30+
if isinstance(s, string_types):
31+
if s.endswith('Z'):
32+
s = s[:-1]
33+
elif s.endswith('-0000'):
34+
s = s[:-5]
35+
return s
36+
37+
38+
def np_datetime64_compat(s, *args, **kwargs):
39+
"""
40+
provide compat for construction of strings to numpy datetime64's with
41+
tz-changes in 1.11 that make '2015-01-01 09:00:00Z' show a deprecation
42+
warning, when need to pass '2015-01-01 09:00:00'
43+
"""
44+
45+
if not _np_version_under1p11:
46+
s = tz_replacer(s)
47+
return np.datetime64(s, *args, **kwargs)
48+
49+
50+
def np_array_datetime64_compat(arr, *args, **kwargs):
51+
"""
52+
provide compat for construction of an array of strings to a
53+
np.array(..., dtype=np.datetime64(..))
54+
tz-changes in 1.11 that make '2015-01-01 09:00:00Z' show a deprecation
55+
warning, when need to pass '2015-01-01 09:00:00'
56+
"""
57+
58+
if not _np_version_under1p11:
59+
60+
# is_list_like
61+
if hasattr(arr, '__iter__') and not \
62+
isinstance(arr, string_and_binary_types):
63+
arr = [tz_replacer(s) for s in arr]
64+
else:
65+
arr = tz_replacer(s)
66+
67+
return np.array(arr, *args, **kwargs)
68+
69+
__all__ = ['_np_version',
70+
'_np_version_under1p8',
71+
'_np_version_under1p9',
72+
'_np_version_under1p10',
73+
'_np_version_under1p11',
74+
]

pandas/io/tests/test_date_converters.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from pandas.util.testing import assert_frame_equal
1111
import pandas.io.date_converters as conv
1212
import pandas.util.testing as tm
13+
from pandas.compat.numpy_compat import np_array_datetime64_compat
1314

1415

1516
class TestConverters(tm.TestCase):
@@ -119,15 +120,16 @@ def test_dateparser_resolution_if_not_ns(self):
119120
"""
120121

121122
def date_parser(date, time):
122-
datetime = np.array(date + 'T' + time + 'Z', dtype='datetime64[s]')
123+
datetime = np_array_datetime64_compat(
124+
date + 'T' + time + 'Z', dtype='datetime64[s]')
123125
return datetime
124126

125127
df = read_csv(StringIO(data), date_parser=date_parser,
126128
parse_dates={'datetime': ['date', 'time']},
127129
index_col=['datetime', 'prn'])
128130

129-
datetimes = np.array(['2013-11-03T19:00:00Z'] * 3,
130-
dtype='datetime64[s]')
131+
datetimes = np_array_datetime64_compat(['2013-11-03T19:00:00Z'] * 3,
132+
dtype='datetime64[s]')
131133
df_correct = DataFrame(data={'rxstatus': ['00E80000'] * 3},
132134
index=MultiIndex.from_tuples(
133135
[(datetimes[0], 126),

pandas/tseries/tests/test_offsets.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import numpy as np
1010

11+
from pandas.compat.numpy_compat import np_datetime64_compat
1112
from pandas.core.datetools import (bday, BDay, CDay, BQuarterEnd, BMonthEnd,
1213
BusinessHour, CBMonthEnd, CBMonthBegin,
1314
BYearEnd, MonthEnd, MonthBegin, BYearBegin,
@@ -201,7 +202,7 @@ def setUp(self):
201202
'Second': Timestamp('2011-01-01 09:00:01'),
202203
'Milli': Timestamp('2011-01-01 09:00:00.001000'),
203204
'Micro': Timestamp('2011-01-01 09:00:00.000001'),
204-
'Nano': Timestamp(np.datetime64(
205+
'Nano': Timestamp(np_datetime64_compat(
205206
'2011-01-01T09:00:00.000000001Z'))}
206207

207208
def test_return_type(self):
@@ -292,7 +293,7 @@ def _check_offsetfunc_works(self, offset, funcname, dt, expected,
292293

293294
def test_apply(self):
294295
sdt = datetime(2011, 1, 1, 9, 0)
295-
ndt = np.datetime64('2011-01-01 09:00Z')
296+
ndt = np_datetime64_compat('2011-01-01 09:00Z')
296297

297298
for offset in self.offset_types:
298299
for dt in [sdt, ndt]:
@@ -333,7 +334,7 @@ def test_rollforward(self):
333334
norm_expected.update(normalized)
334335

335336
sdt = datetime(2011, 1, 1, 9, 0)
336-
ndt = np.datetime64('2011-01-01 09:00Z')
337+
ndt = np_datetime64_compat('2011-01-01 09:00Z')
337338

338339
for offset in self.offset_types:
339340
for dt in [sdt, ndt]:
@@ -391,7 +392,7 @@ def test_rollback(self):
391392
norm_expected.update(normalized)
392393

393394
sdt = datetime(2011, 1, 1, 9, 0)
394-
ndt = np.datetime64('2011-01-01 09:00Z')
395+
ndt = np_datetime64_compat('2011-01-01 09:00Z')
395396

396397
for offset in self.offset_types:
397398
for dt in [sdt, ndt]:
@@ -1394,7 +1395,7 @@ class TestCustomBusinessDay(Base):
13941395

13951396
def setUp(self):
13961397
self.d = datetime(2008, 1, 1)
1397-
self.nd = np.datetime64('2008-01-01 00:00:00Z')
1398+
self.nd = np_datetime64_compat('2008-01-01 00:00:00Z')
13981399

13991400
tm._skip_if_no_cday()
14001401
self.offset = CDay()

pandas/tseries/tests/test_period.py

+15-13
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@
2222
import pandas as pd
2323
import numpy as np
2424
from numpy.random import randn
25-
from pandas.compat import range, lrange, lmap, zip
25+
from pandas.compat import range, lrange, lmap, zip, text_type, PY3
26+
from pandas.compat.numpy_compat import np_datetime64_compat
2627

2728
from pandas import Series, DataFrame, _np_version_under1p9
2829
from pandas import tslib
2930
from pandas.util.testing import (assert_series_equal, assert_almost_equal,
3031
assertRaisesRegexp)
3132
import pandas.util.testing as tm
32-
from pandas import compat
3333

3434

3535
class TestPeriodProperties(tm.TestCase):
@@ -329,8 +329,8 @@ def test_period_constructor(self):
329329
i1 = Period(date(2007, 1, 1), freq='M')
330330
i2 = Period(datetime(2007, 1, 1), freq='M')
331331
i3 = Period(np.datetime64('2007-01-01'), freq='M')
332-
i4 = Period(np.datetime64('2007-01-01 00:00:00Z'), freq='M')
333-
i5 = Period(np.datetime64('2007-01-01 00:00:00.000Z'), freq='M')
332+
i4 = Period(np_datetime64_compat('2007-01-01 00:00:00Z'), freq='M')
333+
i5 = Period(np_datetime64_compat('2007-01-01 00:00:00.000Z'), freq='M')
334334
self.assertEqual(i1, i2)
335335
self.assertEqual(i1, i3)
336336
self.assertEqual(i1, i4)
@@ -340,14 +340,15 @@ def test_period_constructor(self):
340340
expected = Period(datetime(2007, 1, 1, 9, 0, 0, 1000), freq='L')
341341
self.assertEqual(i1, expected)
342342

343-
expected = Period(np.datetime64('2007-01-01 09:00:00.001Z'), freq='L')
343+
expected = Period(np_datetime64_compat(
344+
'2007-01-01 09:00:00.001Z'), freq='L')
344345
self.assertEqual(i1, expected)
345346

346347
i1 = Period('2007-01-01 09:00:00.00101')
347348
expected = Period(datetime(2007, 1, 1, 9, 0, 0, 1010), freq='U')
348349
self.assertEqual(i1, expected)
349350

350-
expected = Period(np.datetime64('2007-01-01 09:00:00.00101Z'),
351+
expected = Period(np_datetime64_compat('2007-01-01 09:00:00.00101Z'),
351352
freq='U')
352353
self.assertEqual(i1, expected)
353354

@@ -406,8 +407,8 @@ def test_period_constructor_offsets(self):
406407
i1 = Period(date(2007, 1, 1), freq='M')
407408
i2 = Period(datetime(2007, 1, 1), freq='M')
408409
i3 = Period(np.datetime64('2007-01-01'), freq='M')
409-
i4 = Period(np.datetime64('2007-01-01 00:00:00Z'), freq='M')
410-
i5 = Period(np.datetime64('2007-01-01 00:00:00.000Z'), freq='M')
410+
i4 = Period(np_datetime64_compat('2007-01-01 00:00:00Z'), freq='M')
411+
i5 = Period(np_datetime64_compat('2007-01-01 00:00:00.000Z'), freq='M')
411412
self.assertEqual(i1, i2)
412413
self.assertEqual(i1, i3)
413414
self.assertEqual(i1, i4)
@@ -417,14 +418,15 @@ def test_period_constructor_offsets(self):
417418
expected = Period(datetime(2007, 1, 1, 9, 0, 0, 1000), freq='L')
418419
self.assertEqual(i1, expected)
419420

420-
expected = Period(np.datetime64('2007-01-01 09:00:00.001Z'), freq='L')
421+
expected = Period(np_datetime64_compat(
422+
'2007-01-01 09:00:00.001Z'), freq='L')
421423
self.assertEqual(i1, expected)
422424

423425
i1 = Period('2007-01-01 09:00:00.00101')
424426
expected = Period(datetime(2007, 1, 1, 9, 0, 0, 1010), freq='U')
425427
self.assertEqual(i1, expected)
426428

427-
expected = Period(np.datetime64('2007-01-01 09:00:00.00101Z'),
429+
expected = Period(np_datetime64_compat('2007-01-01 09:00:00.00101Z'),
428430
freq='U')
429431
self.assertEqual(i1, expected)
430432

@@ -462,7 +464,7 @@ def test_strftime(self):
462464
p = Period('2000-1-1 12:34:12', freq='S')
463465
res = p.strftime('%Y-%m-%d %H:%M:%S')
464466
self.assertEqual(res, '2000-01-01 12:34:12')
465-
tm.assertIsInstance(res, compat.text_type) # GH3363
467+
tm.assertIsInstance(res, text_type) # GH3363
466468

467469
def test_sub_delta(self):
468470
left, right = Period('2011', freq='A'), Period('2007', freq='A')
@@ -2957,9 +2959,9 @@ def test_map_with_string_constructor(self):
29572959
index = PeriodIndex(raw, freq='A')
29582960
types = str,
29592961

2960-
if compat.PY3:
2962+
if PY3:
29612963
# unicode
2962-
types += compat.text_type,
2964+
types += text_type,
29632965

29642966
for t in types:
29652967
expected = np.array(lmap(t, raw), dtype=object)

pandas/tseries/tests/test_timeseries.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
Period, DatetimeIndex, Int64Index, to_datetime,
1616
bdate_range, Float64Index, NaT, timedelta_range, Timedelta)
1717

18+
from pandas.compat.numpy_compat import np_datetime64_compat
1819
import pandas.core.datetools as datetools
1920
import pandas.tseries.offsets as offsets
2021
import pandas.tseries.tools as tools
@@ -2496,11 +2497,11 @@ def test_comparisons_nat(self):
24962497
'2014-05-01', '2014-07-01'])
24972498
didx2 = pd.DatetimeIndex(['2014-02-01', '2014-03-01', pd.NaT, pd.NaT,
24982499
'2014-06-01', '2014-07-01'])
2499-
darr = np.array([np.datetime64('2014-02-01 00:00Z'),
2500-
np.datetime64('2014-03-01 00:00Z'),
2501-
np.datetime64('nat'), np.datetime64('nat'),
2502-
np.datetime64('2014-06-01 00:00Z'),
2503-
np.datetime64('2014-07-01 00:00Z')])
2500+
darr = np.array([np_datetime64_compat('2014-02-01 00:00Z'),
2501+
np_datetime64_compat('2014-03-01 00:00Z'),
2502+
np_datetime64_compat('nat'), np.datetime64('nat'),
2503+
np_datetime64_compat('2014-06-01 00:00Z'),
2504+
np_datetime64_compat('2014-07-01 00:00Z')])
25042505

25052506
if _np_version_under1p8:
25062507
# cannot test array because np.datetime('nat') returns today's date

pandas/tseries/tests/test_tslib.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
import pandas.tseries.offsets as offsets
1616
import pandas.util.testing as tm
1717
import pandas.compat as compat
18+
from pandas.compat.numpy_compat import (np_datetime64_compat,
19+
np_array_datetime64_compat)
20+
1821
from pandas.util.testing import assert_series_equal, _skip_if_has_locale
1922

2023

@@ -694,7 +697,7 @@ def test_parsing_valid_dates(self):
694697
arr = np.array(['01-01-2013', '01-02-2013'], dtype=object)
695698
self.assert_numpy_array_equal(
696699
tslib.array_to_datetime(arr),
697-
np.array(
700+
np_array_datetime64_compat(
698701
[
699702
'2013-01-01T00:00:00.000000000-0000',
700703
'2013-01-02T00:00:00.000000000-0000'
@@ -706,7 +709,7 @@ def test_parsing_valid_dates(self):
706709
arr = np.array(['Mon Sep 16 2013', 'Tue Sep 17 2013'], dtype=object)
707710
self.assert_numpy_array_equal(
708711
tslib.array_to_datetime(arr),
709-
np.array(
712+
np_array_datetime64_compat(
710713
[
711714
'2013-09-16T00:00:00.000000000-0000',
712715
'2013-09-17T00:00:00.000000000-0000'
@@ -752,7 +755,7 @@ def test_coercing_dates_outside_of_datetime64_ns_bounds(self):
752755
arr = np.array(['1/1/1000', '1/1/2000'], dtype=object)
753756
self.assert_numpy_array_equal(
754757
tslib.array_to_datetime(arr, errors='coerce'),
755-
np.array(
758+
np_array_datetime64_compat(
756759
[
757760
tslib.iNaT,
758761
'2000-01-01T00:00:00.000000000-0000'
@@ -772,7 +775,7 @@ def test_coerce_of_invalid_datetimes(self):
772775
# With coercing, the invalid dates becomes iNaT
773776
self.assert_numpy_array_equal(
774777
tslib.array_to_datetime(arr, errors='coerce'),
775-
np.array(
778+
np_array_datetime64_compat(
776779
[
777780
'2013-01-01T00:00:00.000000000-0000',
778781
tslib.iNaT,
@@ -863,7 +866,7 @@ def test_nanosecond_timestamp(self):
863866
self.assertEqual(t.value, expected)
864867
self.assertEqual(t.nanosecond, 5)
865868

866-
t = Timestamp(np.datetime64('2011-01-01 00:00:00.000000005Z'))
869+
t = Timestamp(np_datetime64_compat('2011-01-01 00:00:00.000000005Z'))
867870
self.assertEqual(repr(t), "Timestamp('2011-01-01 00:00:00.000000005')")
868871
self.assertEqual(t.value, expected)
869872
self.assertEqual(t.nanosecond, 5)
@@ -879,7 +882,7 @@ def test_nanosecond_timestamp(self):
879882
self.assertEqual(t.value, expected)
880883
self.assertEqual(t.nanosecond, 10)
881884

882-
t = Timestamp(np.datetime64('2011-01-01 00:00:00.000000010Z'))
885+
t = Timestamp(np_datetime64_compat('2011-01-01 00:00:00.000000010Z'))
883886
self.assertEqual(repr(t), "Timestamp('2011-01-01 00:00:00.000000010')")
884887
self.assertEqual(t.value, expected)
885888
self.assertEqual(t.nanosecond, 10)

0 commit comments

Comments
 (0)