Skip to content

Commit 45624f2

Browse files
committed
Use typed descriptors for empty temporal arrays
Add empty_array(PyArray_Descr*) overload and use it for DateTime/TimeDelta empty arrays, ensuring proper unit metadata (datetime64[ns]/timedelta64[ns]) instead of unitless datetime64/timedelta64. Signed-off-by: Arham Chopra <arham.chopra@cubistsystematic.com>
1 parent 65d2a59 commit 45624f2

2 files changed

Lines changed: 23 additions & 12 deletions

File tree

cpp/csp/python/NumpyConversions.h

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ inline PyObject * empty_array( const int value )
5151
return PyArray_SimpleNew( 1, dims, value );
5252
}
5353

54+
inline PyObject * empty_array( PyArray_Descr * descr )
55+
{
56+
npy_intp dims[]{ ( npy_intp ) 0 };
57+
Py_INCREF( descr );
58+
return PyArray_NewFromDescr( &PyArray_Type, descr, 1, dims, nullptr, nullptr, 0, nullptr );
59+
}
60+
5461
template<typename T>
5562
inline T * getValues( const TickBuffer<T> * tickBuffer, const T & lastValue, int32_t startIndex, int32_t endIndex, int32_t * len, bool tailPadding )
5663
{
@@ -95,18 +102,20 @@ inline PyObject * as_nparray( const csp::TimeSeriesProvider * ts, const TickBuff
95102
int32_t startIndex, int32_t endIndex, bool tailPadding )
96103
{
97104
int32_t len = startIndex - endIndex + 1;
98-
if( len <= 0 || !ts -> valid() || ( !tickBuffer && endIndex != 0 ) )
99-
return empty_array( NPY_TYPE<DateTime>::value );
100-
101-
DateTime * values = getValues( tickBuffer, lastValue, startIndex, endIndex, &len, tailPadding );
102-
npy_intp dims[]{ ( npy_intp ) len };
103105

104106
// init datetime_descr once, since datetimes will be used commonly
105107
if( !datetime_descr )
106108
{
107109
auto date_type = PyPtr<PyObject>::own( PyUnicode_FromString( "<M8[ns]" ) );
108110
PyArray_DescrConverter( date_type.get(), &datetime_descr );
109111
}
112+
113+
if( len <= 0 || !ts -> valid() || ( !tickBuffer && endIndex != 0 ) )
114+
return empty_array( datetime_descr );
115+
116+
DateTime * values = getValues( tickBuffer, lastValue, startIndex, endIndex, &len, tailPadding );
117+
npy_intp dims[]{ ( npy_intp ) len };
118+
110119
// PyArray_NewFromDescr steals a reference
111120
Py_INCREF( datetime_descr );
112121
auto * array = PyArray_NewFromDescr( &PyArray_Type, datetime_descr, 1, dims, nullptr, values, 0, nullptr );
@@ -118,18 +127,20 @@ inline PyObject * as_nparray( const csp::TimeSeriesProvider * ts, const TickBuff
118127
int32_t startIndex, int32_t endIndex, bool tailPadding )
119128
{
120129
int32_t len = startIndex - endIndex + 1;
121-
if( len <= 0 || !ts -> valid()|| ( !tickBuffer && endIndex != 0 ) )
122-
return empty_array( NPY_TYPE<TimeDelta>::value );
123-
124-
TimeDelta * values = getValues( tickBuffer, lastValue, startIndex, endIndex, &len, tailPadding );
125-
npy_intp dims[]{ ( npy_intp ) len };
126130

127131
// init timedelta_descr once
128132
if( !timedelta_descr )
129133
{
130134
auto timedelta_type = PyPtr<PyObject>::own( PyUnicode_FromString( "<m8[ns]" ) );
131135
PyArray_DescrConverter( timedelta_type.get(), &timedelta_descr );
132136
}
137+
138+
if( len <= 0 || !ts -> valid()|| ( !tickBuffer && endIndex != 0 ) )
139+
return empty_array( timedelta_descr );
140+
141+
TimeDelta * values = getValues( tickBuffer, lastValue, startIndex, endIndex, &len, tailPadding );
142+
npy_intp dims[]{ ( npy_intp ) len };
143+
133144
Py_INCREF( timedelta_descr );
134145
auto * array = PyArray_NewFromDescr( &PyArray_Type, timedelta_descr, 1, dims, nullptr, values, 0, nullptr );
135146
PyArray_ENABLEFLAGS( ( PyArrayObject * ) array, NPY_ARRAY_OWNDATA);

cpp/csp/python/adapters/ArrowNumpyListWriter.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -393,8 +393,8 @@ class NumpyNDArrayWriter final : public csp::adapters::arrow::FieldWriter
393393
// These write all elements of a numpy array into an arrow value builder
394394
// (list start/end is handled by the caller, e.g. ListColumnArrayBuilder).
395395

396-
template<typename T> struct ArrowArrayType { using type = T; };
397-
template<> struct ArrowArrayType<bool> { using type = uint8_t; };
396+
template<typename T> struct ArrowArrayType { using type = T; };
397+
template<> struct ArrowArrayType<bool> { using type = uint8_t; };
398398

399399
template<typename CspT, typename ArrowBuilderT>
400400
inline csp::adapters::arrow::ListItemsWriter makeNativeListItemsWriter(

0 commit comments

Comments
 (0)