diff options
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/src/multiarray/conversion_utils.c | 35 | ||||
-rw-r--r-- | numpy/core/src/multiarray/conversion_utils.h | 16 | ||||
-rw-r--r-- | numpy/core/src/multiarray/multiarraymodule.c | 7 | ||||
-rw-r--r-- | numpy/core/tests/test_multiarray.py | 2 |
4 files changed, 52 insertions, 8 deletions
diff --git a/numpy/core/src/multiarray/conversion_utils.c b/numpy/core/src/multiarray/conversion_utils.c index 68d6e75fb..35595005c 100644 --- a/numpy/core/src/multiarray/conversion_utils.c +++ b/numpy/core/src/multiarray/conversion_utils.c @@ -1000,6 +1000,18 @@ PyArray_IntpFromSequence(PyObject *seq, npy_intp *vals, int maxvals) return nd; } +/** + * WARNING: This flag is a bad idea, but was the only way to both + * 1) Support unpickling legacy pickles with object types. + * 2) Deprecate (and later disable) usage of O4 and O8 + * + * The key problem is that the pickled representation unpickles by + * directly calling the dtype constructor, which has no way of knowing + * that it is in an unpickle context instead of a normal context without + * evil global state like we create here. + */ +NPY_NO_EXPORT int evil_global_disable_warn_O4O8_flag = 0; + /*NUMPY_API * Typestr converter */ @@ -1007,7 +1019,6 @@ NPY_NO_EXPORT int PyArray_TypestrConvert(int itemsize, int gentype) { int newtype = NPY_NOTYPE; - int ret; switch (gentype) { case NPY_GENBOOLLTR: @@ -1116,12 +1127,22 @@ PyArray_TypestrConvert(int itemsize, int gentype) break; case NPY_OBJECTLTR: - /* raise PyErr_Warn|Ex depending on version */ - ret = DEPRECATE("DType strings 'O4' and 'O8' are deprecated " - "because they are platform specific. Use " - "'O' instead"); - if (ret == 0 && (itemsize == 4 || itemsize == 8)) { - newtype = NPY_OBJECT; + /* + * For 'O4' and 'O8', let it pass, but raise a + * deprecation warning. For all other cases, raise + * an exception by leaving newtype unset. + */ + if (itemsize == 4 || itemsize == 8) { + int ret = 0; + if (evil_global_disable_warn_O4O8_flag) { + ret = DEPRECATE("DType strings 'O4' and 'O8' are " + "deprecated because they are platform " + "specific. Use 'O' instead"); + } + + if (ret == 0) { + newtype = NPY_OBJECT; + } } break; diff --git a/numpy/core/src/multiarray/conversion_utils.h b/numpy/core/src/multiarray/conversion_utils.h index e344a19b0..3ecc46a12 100644 --- a/numpy/core/src/multiarray/conversion_utils.h +++ b/numpy/core/src/multiarray/conversion_utils.h @@ -45,4 +45,20 @@ PyArray_IntTupleFromIntp(int len, intp *vals); NPY_NO_EXPORT int PyArray_ConvertMultiAxis(PyObject *axis_in, int ndim, npy_bool *out_axis_flags); +/** + * WARNING: This flag is a bad idea, but was the only way to both + * 1) Support unpickling legacy pickles with object types. + * 2) Deprecate (and later disable) usage of O4 and O8 + * + * The key problem is that the pickled representation unpickles by + * directly calling the dtype constructor, which has no way of knowing + * that it is in an unpickle context instead of a normal context without + * evil global state like we create here. + */ +#ifdef NPY_ENABLE_SEPARATE_COMPILATION +extern NPY_NO_EXPORT int evil_global_disable_warn_O4O8_flag; +#else +NPY_NO_EXPORT int evil_global_disable_warn_O4O8_flag; +#endif + #endif diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c index fff1c5ce3..53d03ae8e 100644 --- a/numpy/core/src/multiarray/multiarraymodule.c +++ b/numpy/core/src/multiarray/multiarraymodule.c @@ -2778,6 +2778,8 @@ array__reconstruct(PyObject *NPY_UNUSED(dummy), PyObject *args) PyArray_Dims shape = {NULL, 0}; PyArray_Descr *dtype = NULL; + evil_global_disable_warn_O4O8_flag = 1; + if (!PyArg_ParseTuple(args, "O!O&O&", &PyType_Type, &subtype, PyArray_IntpConverter, &shape, @@ -2794,9 +2796,14 @@ array__reconstruct(PyObject *NPY_UNUSED(dummy), PyObject *args) if (shape.ptr) { PyDimMem_FREE(shape.ptr); } + + evil_global_disable_warn_O4O8_flag = 0; + return ret; fail: + evil_global_disable_warn_O4O8_flag = 0; + Py_XDECREF(dtype); if (shape.ptr) { PyDimMem_FREE(shape.ptr); diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index d3d517841..adcd73872 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -827,7 +827,7 @@ class TestPickling(TestCase): def test_version0_object(self): s = '\x80\x02cnumpy.core._internal\n_reconstruct\nq\x01cnumpy\nndarray\nq\x02K\x00\x85U\x01b\x87Rq\x03(K\x02\x85cnumpy\ndtype\nq\x04U\x02O8K\x00K\x01\x87Rq\x05(U\x01|NNJ\xff\xff\xff\xffJ\xff\xff\xff\xfftb\x89]q\x06(}q\x07U\x01aK\x01s}q\x08U\x01bK\x02setb.' - a = array([{'a':1}, {'b':2}]) + a = np.array([{'a':1}, {'b':2}]) p = self._loads(asbytes(s)) assert_equal(a, p) |