@@ -2369,11 +2369,8 @@ arraydescr_setstate(PyArray_Descr *self, PyObject *args)
2369
2369
{
2370
2370
int elsize = -1 , alignment = -1 ;
2371
2371
int version = 4 ;
2372
- #if defined(NPY_PY3K )
2373
- int endian ;
2374
- #else
2375
2372
char endian ;
2376
- #endif
2373
+ PyObject * endian_obj ;
2377
2374
PyObject * subarray , * fields , * names = NULL , * metadata = NULL ;
2378
2375
int incref_names = 1 ;
2379
2376
int int_dtypeflags = 0 ;
@@ -2390,68 +2387,39 @@ arraydescr_setstate(PyArray_Descr *self, PyObject *args)
2390
2387
}
2391
2388
switch (PyTuple_GET_SIZE (PyTuple_GET_ITEM (args ,0 ))) {
2392
2389
case 9 :
2393
- #if defined(NPY_PY3K )
2394
- #define _ARGSTR_ "(iCOOOiiiO)"
2395
- #else
2396
- #define _ARGSTR_ "(icOOOiiiO)"
2397
- #endif
2398
- if (!PyArg_ParseTuple (args , _ARGSTR_ , & version , & endian ,
2390
+ if (!PyArg_ParseTuple (args , "(iOOOOiiiO)" , & version , & endian_obj ,
2399
2391
& subarray , & names , & fields , & elsize ,
2400
2392
& alignment , & int_dtypeflags , & metadata )) {
2393
+ PyErr_Clear ();
2401
2394
return NULL ;
2402
- #undef _ARGSTR_
2403
2395
}
2404
2396
break ;
2405
2397
case 8 :
2406
- #if defined(NPY_PY3K )
2407
- #define _ARGSTR_ "(iCOOOiii)"
2408
- #else
2409
- #define _ARGSTR_ "(icOOOiii)"
2410
- #endif
2411
- if (!PyArg_ParseTuple (args , _ARGSTR_ , & version , & endian ,
2398
+ if (!PyArg_ParseTuple (args , "(iOOOOiii)" , & version , & endian_obj ,
2412
2399
& subarray , & names , & fields , & elsize ,
2413
2400
& alignment , & int_dtypeflags )) {
2414
2401
return NULL ;
2415
- #undef _ARGSTR_
2416
2402
}
2417
2403
break ;
2418
2404
case 7 :
2419
- #if defined(NPY_PY3K )
2420
- #define _ARGSTR_ "(iCOOOii)"
2421
- #else
2422
- #define _ARGSTR_ "(icOOOii)"
2423
- #endif
2424
- if (!PyArg_ParseTuple (args , _ARGSTR_ , & version , & endian ,
2405
+ if (!PyArg_ParseTuple (args , "(iOOOOii)" , & version , & endian_obj ,
2425
2406
& subarray , & names , & fields , & elsize ,
2426
2407
& alignment )) {
2427
2408
return NULL ;
2428
- #undef _ARGSTR_
2429
2409
}
2430
2410
break ;
2431
2411
case 6 :
2432
- #if defined(NPY_PY3K )
2433
- #define _ARGSTR_ "(iCOOii)"
2434
- #else
2435
- #define _ARGSTR_ "(icOOii)"
2436
- #endif
2437
- if (!PyArg_ParseTuple (args , _ARGSTR_ , & version ,
2438
- & endian , & subarray , & fields ,
2412
+ if (!PyArg_ParseTuple (args , "(iOOOii)" , & version ,
2413
+ & endian_obj , & subarray , & fields ,
2439
2414
& elsize , & alignment )) {
2440
- PyErr_Clear ();
2441
- #undef _ARGSTR_
2415
+ return NULL ;
2442
2416
}
2443
2417
break ;
2444
2418
case 5 :
2445
2419
version = 0 ;
2446
- #if defined(NPY_PY3K )
2447
- #define _ARGSTR_ "(COOii)"
2448
- #else
2449
- #define _ARGSTR_ "(cOOii)"
2450
- #endif
2451
- if (!PyArg_ParseTuple (args , _ARGSTR_ ,
2452
- & endian , & subarray , & fields , & elsize ,
2420
+ if (!PyArg_ParseTuple (args , "(OOOii)" ,
2421
+ & endian_obj , & subarray , & fields , & elsize ,
2453
2422
& alignment )) {
2454
- #undef _ARGSTR_
2455
2423
return NULL ;
2456
2424
}
2457
2425
break ;
@@ -2494,11 +2462,55 @@ arraydescr_setstate(PyArray_Descr *self, PyObject *args)
2494
2462
}
2495
2463
}
2496
2464
2465
+ /* Parse endian */
2466
+ if (PyUnicode_Check (endian_obj ) || PyBytes_Check (endian_obj )) {
2467
+ PyObject * tmp = NULL ;
2468
+ char * str ;
2469
+ Py_ssize_t len ;
2470
+
2471
+ if (PyUnicode_Check (endian_obj )) {
2472
+ tmp = PyUnicode_AsASCIIString (endian_obj );
2473
+ if (tmp == NULL ) {
2474
+ return NULL ;
2475
+ }
2476
+ endian_obj = tmp ;
2477
+ }
2478
+
2479
+ if (PyBytes_AsStringAndSize (endian_obj , & str , & len ) == -1 ) {
2480
+ Py_XDECREF (tmp );
2481
+ return NULL ;
2482
+ }
2483
+ if (len != 1 ) {
2484
+ PyErr_SetString (PyExc_ValueError ,
2485
+ "endian is not 1-char string in Numpy dtype unpickling" );
2486
+ Py_XDECREF (tmp );
2487
+ return NULL ;
2488
+ }
2489
+ endian = str [0 ];
2490
+ Py_XDECREF (tmp );
2491
+ }
2492
+ else {
2493
+ PyErr_SetString (PyExc_ValueError ,
2494
+ "endian is not a string in Numpy dtype unpickling" );
2495
+ return NULL ;
2496
+ }
2497
2497
2498
2498
if ((fields == Py_None && names != Py_None ) ||
2499
2499
(names == Py_None && fields != Py_None )) {
2500
2500
PyErr_Format (PyExc_ValueError ,
2501
- "inconsistent fields and names" );
2501
+ "inconsistent fields and names in Numpy dtype unpickling" );
2502
+ return NULL ;
2503
+ }
2504
+
2505
+ if (names != Py_None && !PyTuple_Check (names )) {
2506
+ PyErr_Format (PyExc_ValueError ,
2507
+ "non-tuple names in Numpy dtype unpickling" );
2508
+ return NULL ;
2509
+ }
2510
+
2511
+ if (fields != Py_None && !PyDict_Check (fields )) {
2512
+ PyErr_Format (PyExc_ValueError ,
2513
+ "non-dict fields in Numpy dtype unpickling" );
2502
2514
return NULL ;
2503
2515
}
2504
2516
@@ -2563,13 +2575,82 @@ arraydescr_setstate(PyArray_Descr *self, PyObject *args)
2563
2575
}
2564
2576
2565
2577
if (fields != Py_None ) {
2566
- Py_XDECREF (self -> fields );
2567
- self -> fields = fields ;
2568
- Py_INCREF (fields );
2569
- Py_XDECREF (self -> names );
2570
- self -> names = names ;
2571
- if (incref_names ) {
2572
- Py_INCREF (names );
2578
+ /*
2579
+ * Ensure names are of appropriate string type
2580
+ */
2581
+ Py_ssize_t i ;
2582
+ int names_ok = 1 ;
2583
+ PyObject * name ;
2584
+
2585
+ for (i = 0 ; i < PyTuple_GET_SIZE (names ); ++ i ) {
2586
+ name = PyTuple_GET_ITEM (names , i );
2587
+ if (!PyUString_Check (name )) {
2588
+ names_ok = 0 ;
2589
+ break ;
2590
+ }
2591
+ }
2592
+
2593
+ if (names_ok ) {
2594
+ Py_XDECREF (self -> fields );
2595
+ self -> fields = fields ;
2596
+ Py_INCREF (fields );
2597
+ Py_XDECREF (self -> names );
2598
+ self -> names = names ;
2599
+ if (incref_names ) {
2600
+ Py_INCREF (names );
2601
+ }
2602
+ }
2603
+ else {
2604
+ #if defined(NPY_PY3K )
2605
+ /*
2606
+ * To support pickle.load(f, encoding='bytes') for loading Py2
2607
+ * generated pickles on Py3, we need to be more lenient and convert
2608
+ * field names from byte strings to unicode.
2609
+ */
2610
+ PyObject * tmp , * new_name , * field ;
2611
+
2612
+ tmp = PyDict_New ();
2613
+ if (tmp == NULL ) {
2614
+ return NULL ;
2615
+ }
2616
+ Py_XDECREF (self -> fields );
2617
+ self -> fields = tmp ;
2618
+
2619
+ tmp = PyTuple_New (PyTuple_GET_SIZE (names ));
2620
+ if (tmp == NULL ) {
2621
+ return NULL ;
2622
+ }
2623
+ Py_XDECREF (self -> names );
2624
+ self -> names = tmp ;
2625
+
2626
+ for (i = 0 ; i < PyTuple_GET_SIZE (names ); ++ i ) {
2627
+ name = PyTuple_GET_ITEM (names , i );
2628
+ field = PyDict_GetItem (fields , name );
2629
+ if (!field ) {
2630
+ return NULL ;
2631
+ }
2632
+
2633
+ if (PyUnicode_Check (name )) {
2634
+ new_name = name ;
2635
+ Py_INCREF (new_name );
2636
+ }
2637
+ else {
2638
+ new_name = PyUnicode_FromEncodedObject (name , "ASCII" , "strict" );
2639
+ if (new_name == NULL ) {
2640
+ return NULL ;
2641
+ }
2642
+ }
2643
+
2644
+ PyTuple_SET_ITEM (self -> names , i , new_name );
2645
+ if (PyDict_SetItem (self -> fields , new_name , field ) != 0 ) {
2646
+ return NULL ;
2647
+ }
2648
+ }
2649
+ #else
2650
+ PyErr_Format (PyExc_ValueError ,
2651
+ "non-string names in Numpy dtype unpickling" );
2652
+ return NULL ;
2653
+ #endif
2573
2654
}
2574
2655
}
2575
2656
0 commit comments