1010#include < csp/adapters/arrow/StructToRecordBatch.h>
1111#include < csp/engine/CppNode.h>
1212#include < csp/engine/Dictionary.h>
13- #include < csp/engine/PartialSwitchCspType.h>
1413#include < csp/python/Conversions.h>
1514#include < csp/python/Exception.h>
1615#include < csp/python/InitHelper.h>
@@ -27,76 +26,6 @@ using namespace csp::adapters::arrow;
2726namespace csp ::cppnodes
2827{
2928
30- // Reshape callback that uses numpy's PyArray_Newshape (avoids allocating a dims array per call)
31- static DialectGenericType numpyReshape ( DialectGenericType flatData, const std::vector<int64_t > & dims )
32- {
33- // PyArray_Newshape accepts a PyArray_Dims struct directly, avoiding a numpy array allocation for dims.
34- // Stack-allocate the dims for typical 2-8 dimensional arrays.
35- npy_intp dimsBuf[8 ];
36- npy_intp ndims = static_cast <npy_intp>( dims.size () );
37- npy_intp * dimsPtr;
38-
39- std::vector<npy_intp> heapDims;
40- if ( ndims <= 8 )
41- {
42- for ( npy_intp i = 0 ; i < ndims; ++i )
43- dimsBuf[i] = static_cast <npy_intp>( dims[i] );
44- dimsPtr = dimsBuf;
45- }
46- else
47- {
48- heapDims.resize ( ndims );
49- for ( npy_intp i = 0 ; i < ndims; ++i )
50- heapDims[i] = static_cast <npy_intp>( dims[i] );
51- dimsPtr = heapDims.data ();
52- }
53-
54- PyArray_Dims newshape{ dimsPtr, static_cast <int >( ndims ) };
55- auto * flatPyArr = reinterpret_cast <PyArrayObject *>( csp::python::toPythonBorrowed ( flatData ) );
56- csp::python::PyObjectPtr reshaped{ csp::python::PyObjectPtr::own (
57- reinterpret_cast <PyObject *>( PyArray_Newshape ( flatPyArr, &newshape, NPY_CORDER ) ) ) };
58- if ( !reshaped.get () )
59- CSP_THROW ( csp::python::PythonPassthrough, " " );
60-
61- return csp::python::fromPython<DialectGenericType>( reshaped.get () );
62- }
63-
64- // Shape callback: extract shape from a numpy NDArray
65- static std::vector<int64_t > numpyShape ( DialectGenericType ndarray )
66- {
67- auto * pyArr = reinterpret_cast <PyArrayObject *>( csp::python::toPythonBorrowed ( ndarray ) );
68- int ndim = PyArray_NDIM ( pyArr );
69- npy_intp * shape = PyArray_SHAPE ( pyArr );
70- std::vector<int64_t > result ( ndim );
71- for ( int i = 0 ; i < ndim; ++i )
72- result[i] = shape[i];
73- return result;
74- }
75-
76- // Convert a Python type object (passed as DialectGenericType) to an NPY type constant
77- // using the same pyTypeAsCspType + PartialSwitchCspType pattern as the parquet adapter.
78- static int npyTypeFromPyType ( DialectGenericType pyTypeObj )
79- {
80- auto & cspType = csp::python::pyTypeAsCspType ( csp::python::toPythonBorrowed ( pyTypeObj ) );
81- auto cspTypeEnum = cspType -> type ();
82-
83- // Temporal types don't have NPY_TYPE<> specializations — handle them explicitly
84- if ( cspTypeEnum == CspType::Type::DATETIME || cspTypeEnum == CspType::Type::DATE )
85- return NPY_DATETIME ;
86- if ( cspTypeEnum == CspType::Type::TIMEDELTA )
87- return NPY_TIMEDELTA ;
88-
89- return csp::PartialSwitchCspType<csp::CspType::Type::DOUBLE , csp::CspType::Type::INT64 ,
90- csp::CspType::Type::BOOL , csp::CspType::Type::STRING >::invoke (
91- cspType.get (),
92- []( auto tag ) -> int
93- {
94- using CValueType = typename decltype ( tag )::type;
95- return csp::python::NPY_TYPE <CValueType>::value;
96- }
97- );
98- }
99-
10029// PyCapsule destructors for ArrowSchema/ArrowArray (local copies to avoid including ArrowInputAdapter.h)
10130static void releaseArrowSchemaCapsule ( PyObject * capsule )
10231{
@@ -172,7 +101,7 @@ DECLARE_CPPNODE( record_batches_to_struct )
172101 {
173102 auto dimsColName = numpyDimensionNames -> get<std::string>( colName );
174103 customReaders.push_back (
175- csp::python::createNumpyNDArrayReader ( s_schema, colName, dimsColName, structField, numpyReshape ) );
104+ csp::python::createNumpyNDArrayReader ( s_schema, colName, dimsColName, structField, csp::python:: numpyReshape ) );
176105 }
177106 else
178107 {
@@ -285,13 +214,13 @@ DECLARE_CPPNODE( struct_to_record_batches )
285214 " Struct field '" << fieldName << " ' not found on struct type '" << structMeta -> name () << " '" );
286215
287216 auto pyTypeObj = numpyElementTypes -> get<DialectGenericType>( fieldName );
288- int npyType = npyTypeFromPyType ( pyTypeObj );
217+ int npyType = csp::python:: npyTypeFromPyType ( pyTypeObj );
289218
290219 if ( numpyDimensionNames && numpyDimensionNames -> exists ( colName ) )
291220 {
292221 auto dimsColName = numpyDimensionNames -> get<std::string>( colName );
293222 customWriters.push_back (
294- csp::python::createNumpyNDArrayWriter ( colName, dimsColName, structField, npyType, numpyShape ) );
223+ csp::python::createNumpyNDArrayWriter ( colName, dimsColName, structField, npyType, csp::python:: numpyShape ) );
295224 }
296225 else
297226 {
0 commit comments