Skip to content

CLN: _try_coerce_result, redundant dtypes.missing method #24619

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jan 5, 2019
11 changes: 5 additions & 6 deletions pandas/_libs/missing.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ cimport pandas._libs.util as util

from pandas._libs.tslibs.np_datetime cimport (
get_timedelta64_value, get_datetime64_value)
from pandas._libs.tslibs.nattype cimport checknull_with_nat
from pandas._libs.tslibs.nattype import NaT
from pandas._libs.tslibs.nattype cimport checknull_with_nat, c_NaT

cdef float64_t INF = <float64_t>np.inf
cdef float64_t NEGINF = -INF
Expand All @@ -27,7 +26,7 @@ cdef inline bint _check_all_nulls(object val):

if isinstance(val, (float, complex)):
res = val != val
elif val is NaT:
elif val is c_NaT:
res = 1
elif val is None:
res = 1
Expand Down Expand Up @@ -67,7 +66,7 @@ cpdef bint checknull(object val):
return val != val # and val != INF and val != NEGINF
elif util.is_datetime64_object(val):
return get_datetime64_value(val) == NPY_NAT
elif val is NaT:
elif val is c_NaT:
return True
elif util.is_timedelta64_object(val):
return get_timedelta64_value(val) == NPY_NAT
Expand Down Expand Up @@ -106,7 +105,7 @@ cpdef bint checknull_old(object val):
return val != val or val == INF or val == NEGINF
elif util.is_datetime64_object(val):
return get_datetime64_value(val) == NPY_NAT
elif val is NaT:
elif val is c_NaT:
return True
elif util.is_timedelta64_object(val):
return get_timedelta64_value(val) == NPY_NAT
Expand Down Expand Up @@ -190,7 +189,7 @@ def isnaobj_old(ndarray arr):
result = np.zeros(n, dtype=np.uint8)
for i in range(n):
val = arr[i]
result[i] = val is NaT or _check_none_nan_inf_neginf(val)
result[i] = val is c_NaT or _check_none_nan_inf_neginf(val)
return result.view(np.bool_)


Expand Down
2 changes: 1 addition & 1 deletion pandas/_libs/tslibs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# flake8: noqa

from .conversion import normalize_date, localize_pydatetime, tz_convert_single
from .nattype import NaT, iNaT
from .nattype import NaT, iNaT, is_null_datetimelike
from .np_datetime import OutOfBoundsDatetime
from .period import Period, IncompatibleFrequency
from .timestamps import Timestamp
Expand Down
2 changes: 1 addition & 1 deletion pandas/_libs/tslibs/nattype.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ cdef _NaT c_NaT


cdef bint checknull_with_nat(object val)
cdef bint is_null_datetimelike(object val)
cpdef bint is_null_datetimelike(object val)
2 changes: 1 addition & 1 deletion pandas/_libs/tslibs/nattype.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,7 @@ cdef inline bint checknull_with_nat(object val):
return val is None or util.is_nan(val) or val is c_NaT


cdef inline bint is_null_datetimelike(object val):
cpdef bint is_null_datetimelike(object val):
"""
Determine if we have a null for a timedelta/datetime (or integer versions)

Expand Down
18 changes: 1 addition & 17 deletions pandas/core/dtypes/missing.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
_NS_DTYPE, _TD_DTYPE, ensure_object, is_bool_dtype, is_complex_dtype,
is_datetime64_dtype, is_datetime64tz_dtype, is_datetimelike,
is_datetimelike_v_numeric, is_dtype_equal, is_extension_array_dtype,
is_float_dtype, is_integer, is_integer_dtype, is_object_dtype,
is_float_dtype, is_integer_dtype, is_object_dtype,
is_period_dtype, is_scalar, is_string_dtype, is_string_like_dtype,
is_timedelta64_dtype, needs_i8_conversion, pandas_dtype)
from .generic import (
Expand Down Expand Up @@ -339,22 +339,6 @@ def notna(obj):
notnull = notna


def is_null_datelike_scalar(other):
""" test whether the object is a null datelike, e.g. Nat
but guard against passing a non-scalar """
if other is NaT or other is None:
return True
elif is_scalar(other):

# a timedelta
if hasattr(other, 'dtype'):
return other.view('i8') == iNaT
elif is_integer(other) and other == iNaT:
return True
return isna(other)
return False


def _isna_compat(arr, fill_value=np.nan):
"""
Parameters
Expand Down
45 changes: 20 additions & 25 deletions pandas/core/internals/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import numpy as np

from pandas._libs import internals as libinternals, lib, tslib, tslibs
from pandas._libs.tslibs import Timedelta, conversion
from pandas._libs.tslibs import Timedelta, conversion, is_null_datetimelike
import pandas.compat as compat
from pandas.compat import range, zip
from pandas.util._validators import validate_bool_kwarg
Expand All @@ -31,7 +31,7 @@
ABCDataFrame, ABCDatetimeIndex, ABCExtensionArray, ABCIndexClass,
ABCSeries)
from pandas.core.dtypes.missing import (
_isna_compat, array_equivalent, is_null_datelike_scalar, isna, notna)
_isna_compat, array_equivalent, isna, notna)

import pandas.core.algorithms as algos
from pandas.core.arrays import (
Expand Down Expand Up @@ -2077,10 +2077,6 @@ def get_values(self, dtype=None):
return values
return self.values

@property
def asi8(self):
return self.values.view('i8')


class DatetimeBlock(DatetimeLikeBlockMixin, Block):
__slots__ = ()
Expand Down Expand Up @@ -2162,7 +2158,7 @@ def _try_coerce_args(self, values, other):

if isinstance(other, bool):
raise TypeError
elif is_null_datelike_scalar(other):
elif is_null_datetimelike(other):
other = tslibs.iNaT
elif isinstance(other, (datetime, np.datetime64, date)):
other = self._box_func(other)
Expand All @@ -2175,18 +2171,16 @@ def _try_coerce_args(self, values, other):
else:
# coercion issues
# let higher levels handle
raise TypeError
raise TypeError(other)

return values, other

def _try_coerce_result(self, result):
""" reverse of try_coerce_args """
if isinstance(result, np.ndarray):
if result.dtype.kind in ['i', 'f', 'O']:
try:
result = result.astype('M8[ns]')
except ValueError:
pass
if result.dtype.kind in ['i', 'f']:
result = result.astype('M8[ns]')

elif isinstance(result, (np.integer, np.float, np.datetime64)):
result = self._box_func(result)
return result
Expand Down Expand Up @@ -2250,6 +2244,8 @@ def __init__(self, values, placement, ndim=2, dtype=None):
# and just use DatetimeBlock's.
if dtype is not None:
values = self._maybe_coerce_values(values, dtype=dtype)
# TODO: this gets hit in msgpack tests, but in all cases the values
# are already DatetimeArrays with the appropriate dtype
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this comment should be removed before merging, but if someone well-informed says its OK we may be able to get rid of this check and get some further simplification.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where does this get hit?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in the tests the only place this comes up is in test_packers

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can certainly do this at a higher level. in packers you know the block type & have access to the _holder; can just construct it and pass fully formed values, then don't need to pass the dtype thru

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yah thats what Im thinking now, and it may actually make some of the other 24024 follow-ups easier. Anyway, just removed the comment.

super(DatetimeTZBlock, self).__init__(values, placement=placement,
ndim=ndim)

Expand Down Expand Up @@ -2364,8 +2360,7 @@ def _try_coerce_args(self, values, other):
# add the tz back
other = self._holder(other, dtype=self.dtype)

elif (is_null_datelike_scalar(other) or
(lib.is_scalar(other) and isna(other))):
elif is_null_datetimelike(other):
other = tslibs.iNaT
elif isinstance(other, self._holder):
if other.tz != self.values.tz:
Expand All @@ -2380,17 +2375,19 @@ def _try_coerce_args(self, values, other):
raise ValueError("incompatible or non tz-aware value")
other = other.value
else:
raise TypeError
raise TypeError(other)

return values, other

def _try_coerce_result(self, result):
""" reverse of try_coerce_args """
if isinstance(result, np.ndarray):
if result.dtype.kind in ['i', 'f', 'O']:
if result.dtype.kind in ['i', 'f']:
result = result.astype('M8[ns]')

elif isinstance(result, (np.integer, np.float, np.datetime64)):
result = self._box_func(result)

if isinstance(result, np.ndarray):
# allow passing of > 1dim if its trivial

Expand Down Expand Up @@ -2531,32 +2528,30 @@ def _try_coerce_args(self, values, other):

if isinstance(other, bool):
raise TypeError
elif is_null_datelike_scalar(other):
elif is_null_datetimelike(other):
other = tslibs.iNaT
elif isinstance(other, Timedelta):
other = other.value
elif isinstance(other, timedelta):
other = Timedelta(other).value
elif isinstance(other, np.timedelta64):
elif isinstance(other, (timedelta, np.timedelta64)):
other = Timedelta(other).value
elif hasattr(other, 'dtype') and is_timedelta64_dtype(other):
other = other.astype('i8', copy=False).view('i8')
else:
# coercion issues
# let higher levels handle
raise TypeError
raise TypeError(other)

return values, other

def _try_coerce_result(self, result):
""" reverse of try_coerce_args / try_operate """
if isinstance(result, np.ndarray):
mask = isna(result)
if result.dtype.kind in ['i', 'f', 'O']:
if result.dtype.kind in ['i', 'f']:
result = result.astype('m8[ns]')
result[mask] = tslibs.iNaT

elif isinstance(result, (np.integer, np.float)):
result = self._box_func(result)

return result

def should_store(self, value):
Expand Down
4 changes: 2 additions & 2 deletions pandas/core/sparse/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
from pandas.compat.numpy import function as nv
from pandas.util._decorators import Appender, Substitution

from pandas.core.dtypes.common import is_scalar
from pandas.core.dtypes.common import is_integer, is_scalar
from pandas.core.dtypes.generic import ABCSeries, ABCSparseSeries
from pandas.core.dtypes.missing import is_integer, isna, notna
from pandas.core.dtypes.missing import isna, notna

from pandas.core import generic
from pandas.core.arrays import SparseArray
Expand Down
1 change: 1 addition & 0 deletions pandas/tests/tslibs/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def test_namespace():

api = ['NaT',
'iNaT',
'is_null_datetimelike',
'OutOfBoundsDatetime',
'Period',
'IncompatibleFrequency',
Expand Down