@@ -3385,63 +3385,86 @@ dtype_from_element(PyObject *Py_UNUSED(m), PyObject *arg)
3385
3385
return (PyObject * )PyArray_DescrFromType (NPY_OBJECT );
3386
3386
}
3387
3387
3388
+ static char * isna_element_kwarg_names [] = {
3389
+ "element" ,
3390
+ "include_none" ,
3391
+ NULL
3392
+ };
3393
+
3388
3394
static PyObject *
3389
- isna_element (PyObject * Py_UNUSED ( m ) , PyObject * arg )
3395
+ isna_element (PyObject * m , PyObject * args , PyObject * kwargs )
3390
3396
{
3397
+ PyObject * element ;
3398
+ int include_none = 1 ;
3399
+ if (!PyArg_ParseTupleAndKeywords (args , kwargs ,
3400
+ "O|p:isna_element" , isna_element_kwarg_names ,
3401
+ & element ,
3402
+ & include_none )) {
3403
+ return NULL ;
3404
+ }
3405
+
3391
3406
// None
3392
- if (arg == Py_None ) {
3407
+ if (include_none && element == Py_None ) {
3393
3408
Py_RETURN_TRUE ;
3394
3409
}
3395
3410
3396
3411
// NaN
3397
- if (PyFloat_Check (arg )) {
3398
- return PyBool_FromLong (isnan (PyFloat_AS_DOUBLE (arg )));
3412
+ if (PyFloat_Check (element )) {
3413
+ return PyBool_FromLong (isnan (PyFloat_AS_DOUBLE (element )));
3399
3414
}
3400
- if (PyArray_IsScalar (arg , Half )) {
3401
- return PyBool_FromLong (npy_half_isnan (PyArrayScalar_VAL (arg , Half )));
3415
+ if (PyArray_IsScalar (element , Half )) {
3416
+ return PyBool_FromLong (npy_half_isnan (PyArrayScalar_VAL (element , Half )));
3402
3417
}
3403
- if (PyArray_IsScalar (arg , Float32 )) {
3404
- return PyBool_FromLong (isnan (PyArrayScalar_VAL (arg , Float32 )));
3418
+ if (PyArray_IsScalar (element , Float32 )) {
3419
+ return PyBool_FromLong (isnan (PyArrayScalar_VAL (element , Float32 )));
3405
3420
}
3406
- if (PyArray_IsScalar (arg , Float64 )) {
3407
- return PyBool_FromLong (isnan (PyArrayScalar_VAL (arg , Float64 )));
3421
+ if (PyArray_IsScalar (element , Float64 )) {
3422
+ return PyBool_FromLong (isnan (PyArrayScalar_VAL (element , Float64 )));
3408
3423
}
3409
3424
# ifdef PyFloat128ArrType_Type
3410
- if (PyArray_IsScalar (arg , Float128 )) {
3411
- return PyBool_FromLong (isnan (PyArrayScalar_VAL (arg , Float128 )));
3425
+ if (PyArray_IsScalar (element , Float128 )) {
3426
+ return PyBool_FromLong (isnan (PyArrayScalar_VAL (element , Float128 )));
3412
3427
}
3413
3428
# endif
3414
3429
3415
3430
// Complex NaN
3416
- if (PyComplex_Check (arg )) {
3417
- Py_complex val = ((PyComplexObject * )arg )-> cval ;
3431
+ if (PyComplex_Check (element )) {
3432
+ Py_complex val = ((PyComplexObject * )element )-> cval ;
3418
3433
return PyBool_FromLong (isnan (val .real ) || isnan (val .imag ));
3419
3434
}
3420
- if (PyArray_IsScalar (arg , Complex64 )) {
3421
- npy_cfloat val = PyArrayScalar_VAL (arg , Complex64 );
3435
+ if (PyArray_IsScalar (element , Complex64 )) {
3436
+ npy_cfloat val = PyArrayScalar_VAL (element , Complex64 );
3422
3437
return PyBool_FromLong (isnan (val .real ) || isnan (val .imag ));
3423
3438
}
3424
- if (PyArray_IsScalar (arg , Complex128 )) {
3425
- npy_cdouble val = PyArrayScalar_VAL (arg , Complex128 );
3439
+ if (PyArray_IsScalar (element , Complex128 )) {
3440
+ npy_cdouble val = PyArrayScalar_VAL (element , Complex128 );
3426
3441
return PyBool_FromLong (isnan (val .real ) || isnan (val .imag ));
3427
3442
}
3428
3443
# ifdef PyComplex256ArrType_Type
3429
- if (PyArray_IsScalar (arg , Complex256 )) {
3430
- npy_clongdouble val = PyArrayScalar_VAL (arg , Complex256 );
3444
+ if (PyArray_IsScalar (element , Complex256 )) {
3445
+ npy_clongdouble val = PyArrayScalar_VAL (element , Complex256 );
3431
3446
return PyBool_FromLong (isnan (val .real ) || isnan (val .imag ));
3432
3447
}
3433
3448
# endif
3434
3449
3435
3450
// NaT - Datetime
3436
- if (PyArray_IsScalar (arg , Datetime )) {
3437
- return PyBool_FromLong (PyArrayScalar_VAL (arg , Datetime ) == NPY_DATETIME_NAT );
3451
+ if (PyArray_IsScalar (element , Datetime )) {
3452
+ return PyBool_FromLong (PyArrayScalar_VAL (element , Datetime ) == NPY_DATETIME_NAT );
3438
3453
}
3439
-
3440
3454
// NaT - Timedelta
3441
- if (PyArray_IsScalar (arg , Timedelta )) {
3442
- return PyBool_FromLong (PyArrayScalar_VAL (arg , Timedelta ) == NPY_DATETIME_NAT );
3455
+ if (PyArray_IsScalar (element , Timedelta )) {
3456
+ return PyBool_FromLong (PyArrayScalar_VAL (element , Timedelta ) == NPY_DATETIME_NAT );
3457
+ }
3458
+ // Try to identify Pandas Timestamp NATs
3459
+ if (PyObject_HasAttrString (element , "to_numpy" )) {
3460
+ PyObject * to_numpy = PyObject_GetAttrString (element , "to_numpy" );
3461
+ if (!PyCallable_Check (to_numpy )) {
3462
+ Py_RETURN_FALSE ;
3463
+ }
3464
+ PyObject * post = PyObject_CallFunction (to_numpy , NULL );
3465
+ if (post == NULL ) return NULL ;
3466
+ return PyBool_FromLong (PyArrayScalar_VAL (post , Datetime ) == NPY_DATETIME_NAT );
3443
3467
}
3444
-
3445
3468
Py_RETURN_FALSE ;
3446
3469
}
3447
3470
@@ -4042,7 +4065,10 @@ static PyMethodDef arraykit_methods[] = {
4042
4065
METH_VARARGS | METH_KEYWORDS ,
4043
4066
NULL },
4044
4067
{"count_iteration" , count_iteration , METH_O , NULL },
4045
- {"isna_element" , isna_element , METH_O , NULL },
4068
+ {"isna_element" ,
4069
+ (PyCFunction )isna_element ,
4070
+ METH_VARARGS | METH_KEYWORDS ,
4071
+ NULL },
4046
4072
{"dtype_from_element" , dtype_from_element , METH_O , NULL },
4047
4073
{"get_new_indexers_and_screen" ,
4048
4074
(PyCFunction )get_new_indexers_and_screen ,
0 commit comments