8000 Copy over some of the Numpy file-handing compatibility functions. · matplotlib/matplotlib@bee6479 · GitHub
[go: up one dir, main page]

Skip to content

Commit bee6479

Browse files
committed
Copy over some of the Numpy file-handing compatibility functions.
1 parent cd6c8c9 commit bee6479

File tree

2 files changed

+137
-2
lines changed

2 files changed

+137
-2
lines changed

src/_png.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
#include "CXX/Extensions.hxx"
2828
#include "numpy/arrayobject.h"
2929
#include "mplutils.h"
30-
#include "numpy/npy_3kcompat.h"
30+
#include "file_compat.h"
3131

3232
// As reported in [3082058] build _png.so on aix
3333
#ifdef _AIX
@@ -133,7 +133,7 @@ Py::Object _png_module::write_png(const Py::Tuple& args)
133133
PyObject* py_file = NULL;
134134
if (py_fileobj.isString())
135135
{
136-
if ((py_file = npy_PyFile_OpenFile(py_file, (char *)"w")) == NULL) {
136+
if ((py_file = npy_PyFile_OpenFile(py_fileobj.ptr(), (char *)"w")) == NULL) {
137137
throw Py::Exception();
138138
}
139139
close_file = true;

src/file_compat.h

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
#ifndef __FILE_COMPAT_H__
2+
#define __FILE_COMPAT_H__
3+
4+
#include "numpy/npy_3kcompat.h"
5+
6+
#if NPY_API_VERSION < 0x4 /* corresponds to Numpy 1.5 */
7+
/*
8+
* PyFile_* compatibility
9+
*/
10+
#if defined(NPY_PY3K)
11+
12+
/*
13+
* Get a FILE* handle to the file represented by the Python object
14+
*/
15+
static NPY_INLINE FILE*
16+
npy_PyFile_Dup(PyObject *file, char *mode)
17+
{
18+
int fd, fd2;
19+
PyObject *ret, *os;
20+
Py_ssize_t pos;
21+
FILE *handle;
22+
/* Flush first to ensure things end up in the file in the correct order */
23+
ret = PyObject_CallMethod(file, "flush", "");
24+
if (ret == NULL) {
25+
return NULL;
26+
}
27+
Py_DECREF(ret);
28+
fd = PyObject_AsFileDescriptor(file);
29+
if (fd == -1) {
30+
return NULL;
31+
}
32+
os = PyImport_ImportModule("os");
33+
if (os == NULL) {
34+
return NULL;
35+
}
36+
ret = PyObject_CallMethod(os, "dup", "i", fd);
37+
Py_DECREF(os);
38+
if (ret == NULL) {
39+
return NULL;
40+
}
41+
fd2 = PyNumber_AsSsize_t(ret, NULL);
42+
Py_DECREF(ret);
43+
#ifdef _WIN32
44+
handle = _fdopen(fd2, mode);
45+
#else
46+
handle = fdopen(fd2, mode);
47+
#endif
48+
if (handle == NULL) {
49+
PyErr_SetString(PyExc_IOError,
50+
"Getting a FILE* from a Python file object failed");
51+
}
52+
ret = PyObject_CallMethod(file, "tell", "");
53+
if (ret == NULL) {
54+
fclose(handle);
55+
return NULL;
56+
}
57+
pos = PyNumber_AsSsize_t(ret, PyExc_OverflowError);
58+
Py_DECREF(ret);
59+
if (PyErr_Occurred()) {
60+
fclose(handle);
61+
return NULL;
62+
}
63+
npy_fseek(handle, pos, SEEK_SET);
64+
return handle;
65+
}
66+
67+
/*
68+
* Close the dup-ed file handle, and seek the Python one to the current position
69+
*/
70+
static NPY_INLINE int
71+
npy_PyFile_DupClose(PyObject *file, FILE* handle)
72+
{
73+
PyObject *ret;
74+
Py_ssize_t position;
75+
position = npy_ftell(handle);
76+
fclose(handle);
77+
78+
ret = PyObject_CallMethod(file, "seek", NPY_SSIZE_T_PYFMT "i", position, 0);
79+
if (ret == NULL) {
80+
return -1;
81+
}
82+
Py_DECREF(ret);
83+
return 0;
84+
}
85+
86+
static NPY_INLINE int
87+
npy_PyFile_Check(PyObject *file)
88+
{
89+
int fd;
90+
fd = PyObject_AsFileDescriptor(file);
91+
if (fd == -1) {
92+
PyErr_Clear();
93+
return 0;
94+
}
95+
return 1;
96+
}
97+
98+
#else
99+
100+
#define npy_PyFile_Dup(file, mode) PyFile_AsFile(file)
101+
#define npy_PyFile_DupClose(file, handle) (0)
102+
103+
#endif
104+
105+
static NPY_INLINE PyObject*
106+
npy_PyFile_OpenFile(PyObject *filename, const char *mode)
107+
{
108+
PyObject *open;
109+
open = PyDict_GetItemString(PyEval_GetBuiltins(), "open");
110+
if (open == NULL) {
111+
return NULL;
112+
}
113+
return PyObject_CallFunction(open, "Os", filename, mode);
114+
}
115+
116+
#endif /* NPY_API_VERSION < 0x4 */
117+
118+
#if NPY_API_VERSION < 0x7 /* corresponds to Numpy 1.7 */
119+
120+
static NPY_INLINE int
121+
npy_PyFile_CloseFile(PyObject *file)
122+
{
123+
PyObject *ret;
124+
125+
ret = PyObject_CallMethod(file, "close", NULL);
126+
if (ret == NULL) {
127+
return -1;
128+
}
129+
Py_DECREF(ret);
130+
return 0;
131+
}
132+
13 3F87 3+
#endif /* NPY_API_VERSION < 0x7 */
134+
135+
#endif /* ifndef __FILE_COMPAT_H__ */

0 commit comments

Comments
 (0)
0