1
1
// this is included first so that we do include without NO_IMPORT_ARRAY defined, which is done in NumpyConversions.h
2
2
#include < numpy/ndarrayobject.h>
3
+ #include < numpy/npy_2_compat.h>
3
4
4
5
5
6
#include < csp/core/Time.h>
8
9
#include < locale>
9
10
#include < codecvt>
10
11
11
- namespace csp ::python
12
+ static void * init_nparray ()
12
13
{
14
+ csp::python::AcquireGIL gil;
15
+ import_array ();
16
+ return nullptr ;
17
+ }
18
+ static void * s_init_array = init_nparray();
13
19
14
- static bool numpy_initialized = false ;
20
+ namespace csp ::python
21
+ {
15
22
16
23
PyObject * valuesAtIndexToNumpy ( ValueType valueType, const csp::TimeSeriesProvider * ts, int32_t startIndex, int32_t endIndex,
17
24
autogen::TimeIndexPolicy startPolicy, autogen::TimeIndexPolicy endPolicy,
18
25
DateTime startDt, DateTime endDt )
19
26
{
20
- if ( !numpy_initialized )
21
- {
22
- import_array ()
23
- numpy_initialized = true ;
24
- }
25
-
26
27
return switchCspType ( ts -> type (),
27
28
[ valueType, ts, startIndex, endIndex, startPolicy, endPolicy, startDt, endDt ]( auto tag )
28
29
{
@@ -35,40 +36,77 @@ int64_t scalingFromNumpyDtUnit( NPY_DATETIMEUNIT base )
35
36
{
36
37
switch ( base )
37
38
{
38
- case NPY_FR_ns:
39
- return 1 ;
40
- case NPY_FR_us:
41
- return csp::TimeDelta::fromMicroseconds (1 ).asNanoseconds ();
42
- case NPY_FR_ms:
43
- return csp::TimeDelta::fromMilliseconds (1 ).asNanoseconds ();
44
- case NPY_FR_s:
45
- return csp::TimeDelta::fromSeconds (1 ).asNanoseconds ();
46
- case NPY_FR_m:
47
- return csp::TimeDelta::fromMinutes (1 ).asNanoseconds ();
48
- case NPY_FR_h:
49
- return csp::TimeDelta::fromHours (1 ).asNanoseconds ();
50
- case NPY_FR_D:
51
- return csp::TimeDelta::fromDays (1 ).asNanoseconds ();
39
+ // https://github.com/numpy/numpy/blob/v2.0.0/numpy/__init__.pxd#L794
40
+ case NPY_FR_Y:
41
+ return csp::TimeDelta::fromDays (365 ).asNanoseconds ();
42
+ case NPY_FR_M:
43
+ return csp::TimeDelta::fromDays (30 ).asNanoseconds ();
52
44
case NPY_FR_W:
53
45
return csp::TimeDelta::fromDays (7 ).asNanoseconds ();
46
+ #ifdef NPY_FR_B
47
+ case NPY_FR_B:
48
+ return csp::TimeDelta::fromDays (5 ).asNanoseconds ();
49
+ #endif
50
+ case NPY_FR_D:
51
+ return csp::TimeDelta::fromDays (1 ).asNanoseconds ();
52
+ case NPY_FR_h:
53
+ return csp::TimeDelta::fromHours (1 ).asNanoseconds ();
54
+ case NPY_FR_m:
55
+ return csp::TimeDelta::fromMinutes (1 ).asNanoseconds ();
56
+ case NPY_FR_s:
57
+ return csp::TimeDelta::fromSeconds (1 ).asNanoseconds ();
58
+ case NPY_FR_ms:
59
+ return csp::TimeDelta::fromMilliseconds (1 ).asNanoseconds ();
60
+ case NPY_FR_us:
61
+ return csp::TimeDelta::fromMicroseconds (1 ).asNanoseconds ();
62
+ case NPY_FR_ns:
63
+ return 1 ;
64
+ // unsupported or invalid units
65
+ // enumerated here for clarity in error messages
66
+ case NPY_FR_ps:
67
+ CSP_THROW (csp::NotImplemented, " datetime resolution not supported or invalid - saw NPY_DATETIMEUNIT value NPY_FR_ps" );
68
+ return 0 ;
69
+ case NPY_FR_fs:
70
+ CSP_THROW (csp::NotImplemented, " datetime resolution not supported or invalid - saw NPY_DATETIMEUNIT value NPY_FR_fs" );
71
+ return 0 ;
72
+ case NPY_FR_GENERIC:
73
+ CSP_THROW (csp::NotImplemented, " datetime resolution not supported or invalid - saw NPY_DATETIMEUNIT value NPY_FR_generic" );
74
+ return 0 ;
75
+ case NPY_FR_ERROR:
76
+ CSP_THROW (csp::NotImplemented, " datetime resolution not supported or invalid - saw NPY_DATETIMEUNIT value NPY_FR_error" );
77
+ return 0 ;
54
78
default :
55
- CSP_THROW (csp::NotImplemented, " datetime resolution not supported or invalid - saw NPY_DATETIMEUNIT value " << base );
56
- return 0 ; // never reached, but keeps compiler happy
79
+ if (static_cast <int >(base) == 3 ) {
80
+ // NPY_FR_B was removed in numpy 1.20
81
+ return csp::TimeDelta::fromDays (5 ).asNanoseconds ();
82
+ }
83
+ CSP_THROW (csp::NotImplemented, " datetime resolution not supported or invalid - saw NPY_DATETIMEUNIT value " << static_cast <int32_t >(base) );
84
+ return 0 ;
57
85
}
58
86
}
59
87
60
88
NPY_DATETIMEUNIT datetimeUnitFromDescr ( PyArray_Descr* descr )
61
89
{
62
- PyArray_DatetimeDTypeMetaData* dtypeMeta = (PyArray_DatetimeDTypeMetaData*)(descr -> c_metadata);
63
- PyArray_DatetimeMetaData* dtMeta = &(dtypeMeta -> meta);
90
+ PyArray_DatetimeDTypeMetaData* dtypeMeta;
91
+ if (PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION)
92
+ {
93
+ // NumPy 2.x way
94
+ dtypeMeta = ( PyArray_DatetimeDTypeMetaData * ) ( ( (_PyArray_LegacyDescr *) descr ) -> c_metadata );
95
+ }
96
+ else
97
+ {
98
+ // NumPy 1.x way
99
+ dtypeMeta = ( PyArray_DatetimeDTypeMetaData * ) ( ( (PyArray_DescrProto *) descr ) -> c_metadata );
100
+ }
101
+ PyArray_DatetimeMetaData* dtMeta = &( dtypeMeta -> meta );
64
102
return dtMeta -> base;
65
103
}
66
104
67
105
static std::wstring_convert<std::codecvt_utf8<char32_t >, char32_t > wstr_converter;
68
106
69
107
void stringFromNumpyStr ( void * data, std::string& out, char numpy_type, int elem_size_bytes )
70
108
{
71
- // strings from numpy arrays are fixed width and zero filled.
109
+ // strings from numpy arrays are fixed width and zero filled.
72
110
// if the last char is 0, can treat as null terminated, else use full width
73
111
74
112
if ( numpy_type == NPY_UNICODELTR)
@@ -87,7 +125,7 @@ void stringFromNumpyStr( void* data, std::string& out, char numpy_type, int elem
87
125
out = wstr_converter.to_bytes ( wstr );
88
126
}
89
127
}
90
- else if ( numpy_type == NPY_STRINGLTR || numpy_type == NPY_STRINGLTR2 )
128
+ else if ( numpy_type == NPY_STRINGLTR )
91
129
{
92
130
const char * const raw_value = (const char *) data;
93
131
@@ -120,13 +158,13 @@ void validateNumpyTypeVsCspType( const CspTypePtr & type, char numpy_type_char )
120
158
case NPY_INTLTR:
121
159
case NPY_UINTLTR:
122
160
case NPY_LONGLTR:
161
+ case NPY_LONGLONGLTR:
123
162
if ( cspType != csp::CspType::Type::INT64 )
124
163
CSP_THROW ( ValueError, " numpy type " << numpy_type_char << " requires int output type" );
125
164
break ;
126
165
case NPY_ULONGLTR:
127
- case NPY_LONGLONGLTR:
128
166
case NPY_ULONGLONGLTR:
129
- CSP_THROW ( ValueError, " numpy type " << numpy_type_char << " (int type that can't cleanly convert to long ) not supported" );
167
+ CSP_THROW ( ValueError, " numpy type " << numpy_type_char << " (int type that can't cleanly convert to int64 ) not supported" );
130
168
case NPY_HALFLTR:
131
169
CSP_THROW ( ValueError, " numpy type " << numpy_type_char << " (numpy half float) not supported" );
132
170
case NPY_FLOATLTR:
@@ -144,7 +182,6 @@ void validateNumpyTypeVsCspType( const CspTypePtr & type, char numpy_type_char )
144
182
// everything works as object
145
183
break ;
146
184
case NPY_STRINGLTR:
147
- case NPY_STRINGLTR2:
148
185
case NPY_UNICODELTR:
149
186
case NPY_CHARLTR:
150
187
if ( cspType != csp::CspType::Type::STRING )
0 commit comments