8000 BUG: restore api for file npy_PyFile_Dup and npy_PyFile_DupClose · numpy/numpy@ea89757 · GitHub
[go: up one dir, main page]

Skip to content

Commit ea89757

Browse files
committed
BUG: restore api for file npy_PyFile_Dup and npy_PyFile_DupClose
breaking the api breaks matplotlib build and pip installation. Introduce npy_PyFile_Dup2 and npy_PyFile_DupClose2 as replacements
1 parent fea6079 commit ea89757

File tree

4 files changed

+59
-10
lines changed

4 files changed

+59
-10
lines changed

doc/release/1.9.0-notes.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,12 @@ For example ``np.float_(2) * [1]`` will be an error in the future.
242242
C-API
243243
~~~~~
244244

245-
None
245+
The utility function npy_PyFile_Dup and npy_PyFile_DupClose are broken by the
246+
internal buffering python 3 applies to its file objects.
247+
To fix this two new functions npy_PyFile_Dup2 and npy_PyFile_DupClose2 are
248+
declared in npy_3kcompat.h and the old functions are deprecate 8000 d.
249+
Due to the fragile nature of these functions it is recommended to instead use
250+
the python API when possible.
246251

247252

248253
New Features

numpy/core/include/numpy/npy_3kcompat.h

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -141,12 +141,11 @@ PyUnicode_Concat2(PyObject **left, PyObject *right)
141141
* PyFile_* compatibility
142142
*/
143143
#if defined(NPY_PY3K)
144-
145144
/*
146145
* Get a FILE* handle to the file represented by the Python object
147146
*/
148147
static NPY_INLINE FILE*
149-
npy_PyFile_Dup(PyObject *file, char *mode, npy_off_t *orig_pos)
148+
npy_PyFile_Dup2(PyObject *file, char *mode, npy_off_t *orig_pos)
150149
{
151150
int fd, fd2;
152151
PyObject *ret, *os;
@@ -221,7 +220,7 @@ npy_PyFile_Dup(PyObject *file, char *mode, npy_off_t *orig_pos)
221220
* Close the dup-ed file handle, and seek the Python one to the current position
222221
*/
223222
static NPY_INLINE int
224-
npy_PyFile_DupClose(PyObject *file, FILE* handle, npy_off_t orig_pos)
223+
npy_PyFile_DupClose2(PyObject *file, FILE* handle, npy_off_t orig_pos)
225224
{
226225
int fd;
227226
PyObject *ret;
@@ -269,10 +268,55 @@ npy_PyFile_Check(PyObject *file)
269268
return 1;
270269
}
271270

271+
/*
272+
* DEPRECATED DO NOT USE
273+
* use npy_PyFile_Dup2 instead
274+
* this function will mess ups python3 internal file object buffering
275+
* Get a FILE* handle to the file represented by the Python object
276+
*/
277+
static NPY_INLINE FILE*
278+
npy_PyFile_Dup(PyObject *file, char *mode)
279+
{
280+
npy_off_t orig;
281+
if (DEPRECATE("npy_PyFile_Dup is deprecated, use "
282+
"npy_PyFile_Dup2") < 0) {
283+
return NULL;
284+
}
285+
286+
return npy_PyFile_Dup2(file, mode, &orig);
287+
}
288+
289+
/*
290+
* DEPRECATED DO NOT USE
291+
* use npy_PyFile_DupClose2 instead
292+
* this function will mess ups python3 internal file object buffering
293+
* Close the dup-ed file handle, and seek the Python one to the current position
294+
*/
295+
static NPY_INLINE int
296+
npy_PyFile_DupClose(PyObject *file, FILE* handle)
297+
{
298+
PyObject *ret;
299+
Py_ssize_t position;
300+
position = npy_ftell(handle);
301+
fclose(handle);
302+
303+
ret = PyObject_CallMethod(file, "seek", NPY_SSIZE_T_PYFMT "i", position, 0);
304+
if (ret == NULL) {
305+
return -1;
306+
}
307+
Py_DECREF(ret);
308+
return 0;
309+
}
310+
311+
272312
#else
273313

274-
#define npy_PyFile_Dup(file, mode, orig_pos_p) PyFile_AsFile(file)
275-
#define npy_PyFile_DupClose(file, handle, orig_pos) (0)
314+
/* DEPRECATED DO NOT USE */
315+
#define npy_PyFile_Dup(file, mode) PyFile_AsFile(file)
316+
#define npy_PyFile_DupClose(file, handle) (0)
317+
/* use these */
318+
#define npy_PyFile_Dup2(file, mode, orig_pos_p) PyFile_AsFile(file)
319+
#define npy_PyFile_DupClose2(file, handle, orig_pos) (0)
276320
#define npy_PyFile_Check PyFile_Check
277321

278322
#endif

numpy/core/src/multiarray/methods.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ array_tofile(PyArrayObject *self, PyObject *args, PyObject *kwds)
588588
own = 0;
589589
}
590590

591-
fd = npy_PyFile_Dup(file, "wb", &orig_pos);
591+
fd = npy_PyFile_Dup2(file, "wb", &orig_pos);
592592
if (fd == NULL) {
593593
PyErr_SetString(PyExc_IOError,
594594
"first argument must be a string or open file");
@@ -597,7 +597,7 @@ array_tofile(PyArrayObject *self, PyObject *args, PyObject *kwds)
597597
if (PyArray_ToFile(self, fd, sep, format) < 0) {
598598
goto fail;
599599
}
600-
if (npy_PyFile_DupClose(file, fd, orig_pos) < 0) {
600+
if (npy_PyFile_DupClose2(file, fd, orig_pos) < 0) {
601601
goto fail;
602602
}
603603
if (own && npy_PyFile_CloseFile(file) < 0) {

numpy/core/src/multiarray/multiarraymodule.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1999,7 +1999,7 @@ array_fromfile(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *keywds)
19991999
Py_INCREF(file);
20002000
own = 0;
20012001
}
2002-
fp = npy_PyFile_Dup(file, "rb", &orig_pos);
2002+
fp = npy_PyFile_Dup2(file, "rb", &orig_pos);
20032003
if (fp == NULL) {
20042004
PyErr_SetString(PyExc_IOError,
20052005
"first argument must be an open file");
@@ -2011,7 +2011,7 @@ array_fromfile(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *keywds)
20112011
}
20122012
ret = PyArray_FromFile(fp, type, (npy_intp) nin, sep);
20132013

2014-
if (npy_PyFile_DupClose(file, fp, orig_pos) < 0) {
2014+
if (npy_PyFile_DupClose2(file, fp, orig_pos) < 0) {
20152015
goto fail;
20162016
}
20172017
if (own && npy_PyFile_CloseFile(file) < 0) {

0 commit comments

Comments
 (0)
0