From b63b156ac8300a591114e81c45f7aea832a16274 Mon Sep 17 00:00:00 2001 From: Christopher Ariza Date: Mon, 1 May 2023 19:28:28 -0700 Subject: [PATCH 1/3] properly use PyArray_IsScalar before PyArrayScalar_VAL --- src/_arraykit.c | 15 ++++++++++++--- test/test_util.py | 4 ++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/_arraykit.c b/src/_arraykit.c index fe94c943..fa29c45c 100644 --- a/src/_arraykit.c +++ b/src/_arraykit.c @@ -3777,10 +3777,19 @@ isna_element(PyObject *m, PyObject *args, PyObject *kwargs) if (!PyCallable_Check(to_numpy)) { Py_RETURN_FALSE; } - PyObject* post = PyObject_CallFunction(to_numpy, NULL); + + PyObject* scalar = PyObject_CallFunction(to_numpy, NULL); Py_DECREF(to_numpy); - if (post == NULL) return NULL; - return PyBool_FromLong(PyArrayScalar_VAL(post, Datetime) == NPY_DATETIME_NAT); + if (scalar == NULL) { + return NULL; + } + if (!PyArray_IsScalar(scalar, Datetime)) { + Py_DECREF(scalar); + Py_RETURN_FALSE; + } + PyObject* pb = PyBool_FromLong(PyArrayScalar_VAL(scalar, Datetime) == NPY_DATETIME_NAT); + Py_DECREF(scalar); + return pb; } Py_RETURN_FALSE; } diff --git a/test/test_util.py b/test/test_util.py index d778d80d..810f845c 100644 --- a/test/test_util.py +++ b/test/test_util.py @@ -351,6 +351,10 @@ def test_isna_element_d(self) -> None: ts = pd.Timestamp('nat') self.assertTrue(isna_element(ts)) + s1 = pd.Series((0,)) + self.assertFalse(isna_element(s1)) + + def test_isna_element_e(self) -> None: from types import SimpleNamespace From 875d027c7774fc31de02cdad33c0ba48eca63849 Mon Sep 17 00:00:00 2001 From: Christopher Ariza Date: Mon, 1 May 2023 19:33:26 -0700 Subject: [PATCH 2/3] code cleanup --- src/_arraykit.c | 4 +++- test/test_util.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/_arraykit.c b/src/_arraykit.c index fa29c45c..14feb39b 100644 --- a/src/_arraykit.c +++ b/src/_arraykit.c @@ -3770,14 +3770,16 @@ isna_element(PyObject *m, PyObject *args, PyObject *kwargs) } // Try to identify Pandas Timestamp NATs if (PyObject_HasAttrString(element, "to_numpy")) { + // can we match the class name NaTType? + PyObject *to_numpy = PyObject_GetAttrString(element, "to_numpy"); if (to_numpy == NULL) { return NULL; } if (!PyCallable_Check(to_numpy)) { + Py_DECREF(to_numpy); Py_RETURN_FALSE; } - PyObject* scalar = PyObject_CallFunction(to_numpy, NULL); Py_DECREF(to_numpy); if (scalar == NULL) { diff --git a/test/test_util.py b/test/test_util.py index 810f845c..f388e4b2 100644 --- a/test/test_util.py +++ b/test/test_util.py @@ -355,13 +355,13 @@ def test_isna_element_d(self) -> None: self.assertFalse(isna_element(s1)) - def test_isna_element_e(self) -> None: from types import SimpleNamespace sn = SimpleNamespace() sn.to_numpy = None self.assertFalse(isna_element(sn)) + #--------------------------------------------------------------------------- def test_dtype_from_element_core_dtypes(self) -> None: From e312b3395133842ed7f11076209347350b0f69ec Mon Sep 17 00:00:00 2001 From: Christopher Ariza Date: Mon, 1 May 2023 19:51:18 -0700 Subject: [PATCH 3/3] alternate approach --- src/_arraykit.c | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/src/_arraykit.c b/src/_arraykit.c index 14feb39b..0a424aca 100644 --- a/src/_arraykit.c +++ b/src/_arraykit.c @@ -3770,28 +3770,29 @@ isna_element(PyObject *m, PyObject *args, PyObject *kwargs) } // Try to identify Pandas Timestamp NATs if (PyObject_HasAttrString(element, "to_numpy")) { - // can we match the class name NaTType? - - PyObject *to_numpy = PyObject_GetAttrString(element, "to_numpy"); - if (to_numpy == NULL) { - return NULL; - } - if (!PyCallable_Check(to_numpy)) { - Py_DECREF(to_numpy); - Py_RETURN_FALSE; - } - PyObject* scalar = PyObject_CallFunction(to_numpy, NULL); - Py_DECREF(to_numpy); - if (scalar == NULL) { - return NULL; - } - if (!PyArray_IsScalar(scalar, Datetime)) { - Py_DECREF(scalar); - Py_RETURN_FALSE; - } - PyObject* pb = PyBool_FromLong(PyArrayScalar_VAL(scalar, Datetime) == NPY_DATETIME_NAT); - Py_DECREF(scalar); - return pb; + // strcmp returns 0 on match + return PyBool_FromLong(strcmp(element->ob_type->tp_name, "NaTType") == 0); + // the long way + // PyObject *to_numpy = PyObject_GetAttrString(element, "to_numpy"); + // if (to_numpy == NULL) { + // return NULL; + // } + // if (!PyCallable_Check(to_numpy)) { + // Py_DECREF(to_numpy); + // Py_RETURN_FALSE; + // } + // PyObject* scalar = PyObject_CallFunction(to_numpy, NULL); + // Py_DECREF(to_numpy); + // if (scalar == NULL) { + // return NULL; + // } + // if (!PyArray_IsScalar(scalar, Datetime)) { + // Py_DECREF(scalar); + // Py_RETURN_FALSE; + // } + // PyObject* pb = PyBool_FromLong(PyArrayScalar_VAL(scalar, Datetime) == NPY_DATETIME_NAT); + // Py_DECREF(scalar); + // return pb; } Py_RETURN_FALSE; }