Skip to content

Commit d8280c1

Browse files
committed
CLN: refactored locations of timedeltas to core/tseries/timedeltas (from a series of functions in core/common)
1 parent bd0369f commit d8280c1

File tree

10 files changed

+156
-140
lines changed

10 files changed

+156
-140
lines changed

pandas/__init__.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,19 @@
1818
from datetime import datetime
1919
import numpy as np
2020

21+
# XXX: HACK for NumPy 1.5.1 to suppress warnings
22+
try:
23+
np.seterr(all='ignore')
24+
# np.set_printoptions(suppress=True)
25+
except Exception: # pragma: no cover
26+
pass
27+
28+
# numpy versioning
29+
from distutils.version import LooseVersion
30+
_np_version = np.version.short_version
31+
_np_version_under1p6 = LooseVersion(_np_version) < '1.6'
32+
_np_version_under1p7 = LooseVersion(_np_version) < '1.7'
33+
2134
from pandas.version import version as __version__
2235
from pandas.info import __doc__
2336

pandas/core/common.py

Lines changed: 4 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -11,34 +11,20 @@
1111
import pandas.algos as algos
1212
import pandas.lib as lib
1313
import pandas.tslib as tslib
14-
from distutils.version import LooseVersion
1514
from pandas import compat
1615
from pandas.compat import StringIO, BytesIO, range, long, u, zip, map
1716
from datetime import timedelta
1817

1918
from pandas.core.config import get_option
2019
from pandas.core import array as pa
2120

22-
# XXX: HACK for NumPy 1.5.1 to suppress warnings
23-
try:
24-
np.seterr(all='ignore')
25-
# np.set_printoptions(suppress=True)
26-
except Exception: # pragma: no cover
27-
pass
28-
29-
3021
class PandasError(Exception):
3122
pass
3223

3324

3425
class AmbiguousIndexError(PandasError, KeyError):
3526
pass
3627

37-
# versioning
38-
_np_version = np.version.short_version
39-
_np_version_under1p6 = LooseVersion(_np_version) < '1.6'
40-
_np_version_under1p7 = LooseVersion(_np_version) < '1.7'
41-
4228
_POSSIBLY_CAST_DTYPES = set([np.dtype(t)
4329
for t in ['M8[ns]', 'm8[ns]', 'O', 'int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int64', 'uint64']])
4430

@@ -703,50 +689,13 @@ def diff(arr, n, axis=0):
703689

704690
return out_arr
705691

706-
timedelta_search = re.compile(
707-
"^(?P<value>-?\d*\.?\d*)(?P<unit>D|s|ms|us|ns)?$")
708-
709-
def _coerce_scalar_to_timedelta_type(r, unit='ns'):
710-
# kludgy here until we have a timedelta scalar
711-
# handle the numpy < 1.7 case
712-
713-
if isinstance(r, compat.string_types):
714-
m = timedelta_search.search(r)
715-
if m:
716-
r = float(m.groupdict()['value'])
717-
u = m.groupdict().get('unit')
718-
if u is not None:
719-
unit = u
720-
else:
721-
raise ValueError("cannot convert timedelta scalar value!")
722-
723-
r = tslib.cast_from_unit(unit, r)
724-
r = timedelta(microseconds=int(r)/1000)
725-
726-
if is_integer(r):
727-
r = tslib.cast_from_unit(unit, r)
728-
r = timedelta(microseconds=int(r)/1000)
729-
730-
if _np_version_under1p7:
731-
if not isinstance(r, timedelta):
732-
raise AssertionError("Invalid type for timedelta scalar: %s" % type(r))
733-
if compat.PY3:
734-
# convert to microseconds in timedelta64
735-
r = np.timedelta64(int(r.total_seconds()*1e9 + r.microseconds*1000))
736-
else:
737-
return r
738-
739-
if isinstance(r, timedelta):
740-
r = np.timedelta64(r)
741-
elif not isinstance(r, np.timedelta64):
742-
raise AssertionError("Invalid type for timedelta scalar: %s" % type(r))
743-
return r.astype('timedelta64[ns]')
744-
745692
def _coerce_to_dtypes(result, dtypes):
746693
""" given a dtypes and a result set, coerce the result elements to the dtypes """
747694
if len(result) != len(dtypes):
748695
raise AssertionError("_coerce_to_dtypes requires equal len arrays")
749696

697+
from pandas.tseries.timedeltas import _coerce_scalar_to_timedelta_type
698+
750699
def conv(r,dtype):
751700
try:
752701
if isnull(r):
@@ -1339,68 +1288,6 @@ def _possibly_convert_platform(values):
13391288

13401289
return values
13411290

1342-
1343-
def _possibly_cast_to_timedelta(value, coerce=True):
1344-
""" try to cast to timedelta64, if already a timedeltalike, then make
1345-
sure that we are [ns] (as numpy 1.6.2 is very buggy in this regards,
1346-
don't force the conversion unless coerce is True
1347-
1348-
if coerce='compat' force a compatibilty coercerion (to timedeltas) if needeed
1349-
"""
1350-
1351-
# coercion compatability
1352-
if coerce == 'compat' and _np_version_under1p7:
1353-
1354-
def convert(td, dtype):
1355-
1356-
# we have an array with a non-object dtype
1357-
if hasattr(td,'item'):
1358-
td = td.astype(np.int64).item()
1359-
if td == tslib.iNaT:
1360-
return td
1361-
if dtype == 'm8[us]':
1362-
td *= 1000
1363-
return td
1364-
1365-
if td == tslib.compat_NaT:
1366-
return tslib.iNaT
1367-
1368-
# convert td value to a nanosecond value
1369-
d = td.days
1370-
s = td.seconds
1371-
us = td.microseconds
1372-
1373-
if dtype == 'object' or dtype == 'm8[ns]':
1374-
td = 1000*us + (s + d * 24 * 3600) * 10 ** 9
1375-
else:
1376-
raise ValueError("invalid conversion of dtype in np < 1.7 [%s]" % dtype)
1377-
1378-
return td
1379-
1380-
# < 1.7 coercion
1381-
if not is_list_like(value):
1382-
value = np.array([ value ])
1383-
1384-
dtype = value.dtype
1385-
return np.array([ convert(v,dtype) for v in value ], dtype='m8[ns]')
1386-
1387-
# deal with numpy not being able to handle certain timedelta operations
1388-
if isinstance(value, (ABCSeries, np.ndarray)) and value.dtype.kind == 'm':
1389-
if value.dtype != 'timedelta64[ns]':
1390-
value = value.astype('timedelta64[ns]')
1391-
return value
1392-
1393-
# we don't have a timedelta, but we want to try to convert to one (but
1394-
# don't force it)
1395-
if coerce:
1396-
new_value = tslib.array_to_timedelta64(
1397-
_values_from_object(value).astype(object), coerce=False)
1398-
if new_value.dtype == 'i8':
1399-
value = np.array(new_value, dtype='timedelta64[ns]')
1400-
1401-
return value
1402-
1403-
14041291
def _possibly_cast_to_datetime(value, dtype, coerce=False):
14051292
""" try to cast the array/value to a datetimelike dtype, converting float nan to iNaT """
14061293

@@ -1438,6 +1325,7 @@ def _possibly_cast_to_datetime(value, dtype, coerce=False):
14381325
from pandas.tseries.tools import to_datetime
14391326
value = to_datetime(value, coerce=coerce).values
14401327
elif is_timedelta64:
1328+
from pandas.tseries.timedeltas import _possibly_cast_to_timedelta
14411329
value = _possibly_cast_to_timedelta(value)
14421330
except:
14431331
pass
@@ -1463,6 +1351,7 @@ def _possibly_cast_to_datetime(value, dtype, coerce=False):
14631351
except:
14641352
pass
14651353
elif inferred_type in ['timedelta', 'timedelta64']:
1354+
from pandas.tseries.timedeltas import _possibly_cast_to_timedelta
14661355
value = _possibly_cast_to_timedelta(value)
14671356

14681357
return value

pandas/core/generic.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from pandas.tseries.index import DatetimeIndex
1414
from pandas.core.internals import BlockManager
1515
import pandas.core.common as com
16-
from pandas import compat
16+
from pandas import compat, _np_version_under1p7
1717
from pandas.compat import map, zip, lrange
1818
from pandas.core.common import (isnull, notnull, is_list_like,
1919
_values_from_object,
@@ -1908,7 +1908,7 @@ def abs(self):
19081908
obj = np.abs(self)
19091909

19101910
# suprimo numpy 1.6 hacking
1911-
if com._np_version_under1p7:
1911+
if _np_version_under1p7:
19121912
if self.ndim == 1:
19131913
if obj.dtype == 'm8[us]':
19141914
obj = obj.astype('m8[ns]')

pandas/core/series.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
_asarray_tuplesafe, is_integer_dtype,
2020
_NS_DTYPE, _TD_DTYPE,
2121
_infer_dtype_from_scalar, is_list_like, _values_from_object,
22+
_possibly_cast_to_datetime, _possibly_castable, _possibly_convert_platform,
2223
ABCSparseArray)
2324
from pandas.core.index import (Index, MultiIndex, InvalidIndexError,
2425
_ensure_index, _handle_legacy_indexes)
@@ -32,6 +33,7 @@
3233
from pandas.tseries.index import DatetimeIndex
3334
from pandas.tseries.period import PeriodIndex, Period
3435
from pandas.tseries.offsets import DateOffset
36+
from pandas.tseries.timedeltas import _possibly_cast_to_timedelta
3537
from pandas import compat
3638
from pandas.util.terminal import get_terminal_size
3739
from pandas.compat import zip, lzip, u, OrderedDict
@@ -142,7 +144,7 @@ def _convert_to_array(self, values, name=None):
142144
values = values.to_series()
143145
elif inferred_type in ('timedelta', 'timedelta64'):
144146
# have a timedelta, convert to to ns here
145-
values = com._possibly_cast_to_timedelta(values, coerce=coerce)
147+
values = _possibly_cast_to_timedelta(values, coerce=coerce)
146148
elif inferred_type == 'integer':
147149
# py3 compat where dtype is 'm' but is an integer
148150
if values.dtype.kind == 'm':
@@ -160,7 +162,7 @@ def _convert_to_array(self, values, name=None):
160162
raise TypeError("cannot use a non-absolute DateOffset in "
161163
"datetime/timedelta operations [{0}]".format(
162164
','.join([ com.pprint_thing(v) for v in values[mask] ])))
163-
values = com._possibly_cast_to_timedelta(os, coerce=coerce)
165+
values = _possibly_cast_to_timedelta(os, coerce=coerce)
164166
else:
165167
raise TypeError("incompatible type [{0}] for a datetime/timedelta operation".format(pa.array(values).dtype))
166168

@@ -3215,11 +3217,11 @@ def _try_cast(arr, take_fast_path):
32153217

32163218
# perf shortcut as this is the most common case
32173219
if take_fast_path:
3218-
if com._possibly_castable(arr) and not copy and dtype is None:
3220+
if _possibly_castable(arr) and not copy and dtype is None:
32193221
return arr
32203222

32213223
try:
3222-
arr = com._possibly_cast_to_datetime(arr, dtype)
3224+
arr = _possibly_cast_to_datetime(arr, dtype)
32233225
subarr = pa.array(arr, dtype=dtype, copy=copy)
32243226
except (ValueError, TypeError):
32253227
if dtype is not None and raise_cast_failure:
@@ -3266,9 +3268,9 @@ def _try_cast(arr, take_fast_path):
32663268
subarr = lib.maybe_convert_objects(subarr)
32673269

32683270
else:
3269-
subarr = com._possibly_convert_platform(data)
3271+
subarr = _possibly_convert_platform(data)
32703272

3271-
subarr = com._possibly_cast_to_datetime(subarr, dtype)
3273+
subarr = _possibly_cast_to_datetime(subarr, dtype)
32723274

32733275
else:
32743276
subarr = _try_cast(data, False)
@@ -3285,7 +3287,7 @@ def _try_cast(arr, take_fast_path):
32853287
dtype, value = _infer_dtype_from_scalar(value)
32863288
else:
32873289
# need to possibly convert the value here
3288-
value = com._possibly_cast_to_datetime(value, dtype)
3290+
value = _possibly_cast_to_datetime(value, dtype)
32893291

32903292
subarr = pa.empty(len(index), dtype=dtype)
32913293
subarr.fill(value)

pandas/io/pytables.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,19 @@
1717
import numpy as np
1818
import pandas
1919
from pandas import (Series, TimeSeries, DataFrame, Panel, Panel4D, Index,
20-
MultiIndex, Int64Index, Timestamp)
20+
MultiIndex, Int64Index, Timestamp, _np_version_under1p7)
2121
from pandas.sparse.api import SparseSeries, SparseDataFrame, SparsePanel
2222
from pandas.sparse.array import BlockIndex, IntIndex
2323
from pandas.tseries.api import PeriodIndex, DatetimeIndex
2424
from pandas.core.base import StringMixin
2525
from pandas.core.common import adjoin, is_list_like, pprint_thing
2626
from pandas.core.algorithms import match, unique
2727
from pandas.core.categorical import Categorical
28-
from pandas.core.common import _asarray_tuplesafe, _np_version_under1p7
28+
from pandas.core.common import _asarray_tuplesafe
2929
from pandas.core.internals import BlockManager, make_block
3030
from pandas.core.reshape import block2d_to_blocknd, factor_indexer
3131
from pandas.core.index import _ensure_index
32+
from pandas.tseries.timedeltas import _coerce_scalar_to_timedelta_type
3233
import pandas.core.common as com
3334
from pandas.tools.merge import concat
3435
from pandas import compat
@@ -4093,7 +4094,7 @@ def stringify(value):
40934094
v = v.tz_convert('UTC')
40944095
return TermValue(v, v.value, kind)
40954096
elif kind == u('timedelta64') or kind == u('timedelta'):
4096-
v = com._coerce_scalar_to_timedelta_type(v,unit='s').item()
4097+
v = _coerce_scalar_to_timedelta_type(v,unit='s').item()
40974098
return TermValue(int(v), v, kind)
40984099
elif (isinstance(v, datetime) or hasattr(v, 'timetuple')
40994100
or kind == u('date')):

pandas/io/tests/test_pytables.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
assert_frame_equal,
2323
assert_series_equal)
2424
from pandas import concat, Timestamp
25-
from pandas import compat
25+
from pandas import compat, _np_version_under1p7
2626
from pandas.core import common as com
2727

2828
from numpy.testing.decorators import slow
@@ -1800,7 +1800,7 @@ def compare(a,b):
18001800
assert_frame_equal(result,df)
18011801

18021802
def test_append_with_timedelta(self):
1803-
if com._np_version_under1p7:
1803+
if _np_version_under1p7:
18041804
raise nose.SkipTest("requires numpy >= 1.7")
18051805

18061806
# GH 3577

pandas/tests/test_frame.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3248,9 +3248,10 @@ def test_operators_timedelta64(self):
32483248
mixed['F'] = Timestamp('20130101')
32493249

32503250
# results in an object array
3251+
from pandas.tseries.timedeltas import _coerce_scalar_to_timedelta_type
32513252
result = mixed.min()
3252-
expected = Series([com._coerce_scalar_to_timedelta_type(timedelta(seconds=5*60+5)),
3253-
com._coerce_scalar_to_timedelta_type(timedelta(days=-1)),
3253+
expected = Series([_coerce_scalar_to_timedelta_type(timedelta(seconds=5*60+5)),
3254+
_coerce_scalar_to_timedelta_type(timedelta(days=-1)),
32543255
'foo',
32553256
1,
32563257
1.0,

0 commit comments

Comments
 (0)