Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 889951e

Browse files
committed
Fixes #1650 where using a file-like object on Python 3 fails. Use npy_PyFile_* compatibility methods instead of rolling it ourselves.
1 parent 51ac36b commit 889951e

File tree

1 file changed

+52
-52
lines changed

1 file changed

+52
-52
lines changed

src/_png.cpp

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

3132
// As reported in [3082058] build _png.so on aix
3233
#ifdef _AIX
@@ -104,6 +105,7 @@ Py::Object _png_module::write_png(const Py::Tuple& args)
104105

105106
FILE *fp = NULL;
106107
bool close_file = false;
108+
bool close_dup_file = false;
107109
Py::Object buffer_obj = Py::Object(args[0]);
108110
PyObject* buffer = buffer_obj.ptr();
109111
if (!PyObject_CheckReadBuffer(buffer))
@@ -128,41 +130,33 @@ Py::Object _png_module::write_png(const Py::Tuple& args)
128130
}
129131

130132
Py::Object py_fileobj = Py::Object(args[3]);
131-
#if PY3K
132-
int fd = PyObject_AsFileDescriptor(py_fileobj.ptr());
133-
PyErr_Clear();
134-
#endif
133+
PyObject* py_file = NULL;
135134
if (py_fileobj.isString())
136135
{
137-
std::string fileName = Py::String(py_fileobj);
138-
const char *file_name = fileName.c_str();
139-
if ((fp = fopen(file_name, "wb")) == NULL)
140-
{
141-
throw Py::RuntimeError(
142-
Printf("Could not open file %s", file_name).str());
136+
if ((py_file = npy_PyFile_OpenFile(py_file, (char *)"w")) == NULL) {
137+
throw Py::Exception();
143138
}
144139
close_file = true;
145140
}
146-
#if PY3K
147-
else if (fd != -1)
141+
else
148142
{
149-
fp = fdopen(fd, "w");
143+
py_file = py_fileobj.ptr();
150144
}
151-
#else
152-
else if (PyFile_CheckExact(py_fileobj.ptr()))
145+
146+
if ((fp = npy_PyFile_Dup(py_file, (char *)"w")))
153147
{
154-
fp = PyFile_AsFile(py_fileobj.ptr());
148+
close_dup_file = true;
155149
}
156-
#endif
157150
else
158151
{
159152
PyObject* write_method = PyObject_GetAttrString(
160-
py_fileobj.ptr(), "write");
153+
py_file, "write");
161154
if (!(write_method && PyCallable_Check(write_method)))
162155
{
163156
Py_XDECREF(write_method);
164157
throw Py::TypeError(
165-
"Object does not appear to be a 8-bit string path or a Python file-like object");
158+
"Object does not appear to be a 8-bit string path or "
159+
"a Python file-like object");
166160
}
167161
Py_XDECREF(write_method);
168162
}
@@ -205,7 +199,7 @@ Py::Object _png_module::write_png(const Py::Tuple& args)
205199
}
206200
else
207201
{
208-
png_set_write_fn(png_ptr, (void*)py_fileobj.ptr(),
202+
png_set_write_fn(png_ptr, (void*)py_file,
209203
&write_png_data, &flush_png_data);
210204
}
211205
png_set_IHDR(png_ptr, info_ptr,
@@ -241,9 +235,16 @@ Py::Object _png_module::write_png(const Py::Tuple& args)
241235
png_destroy_write_struct(&png_ptr, &info_ptr);
242236
}
243237
delete [] row_pointers;
244-
if (fp && close_file)
238+
239+
if (close_dup_file)
240+
{
241+
npy_PyFile_DupClose(py_file, fp);
242+
}
243+
244+
if (close_file)
245245
{
246-
fclose(fp);
246+
npy_PyFile_CloseFile(py_file);
247+
Py_DECREF(py_file);
247248
}
248249
/* Changed calls to png_destroy_write_struct to follow
249250
http://www.libpng.org/pub/png/libpng-manual.txt.
@@ -254,15 +255,15 @@ Py::Object _png_module::write_png(const Py::Tuple& args)
254255

255256
png_destroy_write_struct(&png_ptr, &info_ptr);
256257
delete [] row_pointers;
257-
#if PY3K
258-
if (fp)
258+
if (close_dup_file)
259259
{
260-
fflush(fp);
260+
npy_PyFile_DupClose(py_file, fp);
261261
}
262-
#endif
263-
if (fp && close_file)
262+
263+
if (close_file)
264264
{
265-
fclose(fp);
265+
npy_PyFile_CloseFile(py_file);
266+
Py_DECREF(py_file);
266267
}
267268

268269
if (PyErr_Occurred()) {
@@ -306,40 +307,32 @@ _png_module::_read_png(const Py::Object& py_fileobj, const bool float_result,
306307
png_byte header[8]; // 8 is the maximum size that can be checked
307308
FILE* fp = NULL;
308309
bool close_file = false;
309-
310-
#if PY3K
311-
int fd = PyObject_AsFileDescriptor(py_fileobj.ptr());
312-
PyErr_Clear();
313-
#endif
310+
bool close_dup_file = false;
311+
PyObject *py_file = NULL;
314312

315313
if (py_fileobj.isString())
316314
{
317-
std::string fileName = Py::String(py_fileobj);
318-
const char *file_name = fileName.c_str();
319-
if ((fp = fopen(file_name, "rb")) == NULL)
320-
{
321-
throw Py::RuntimeError(
322-
Printf("Could not open file %s for reading", file_name).str());
315+
if ((py_file = npy_PyFile_OpenFile(py_fileobj.ptr(), (char *)"r")) == NULL) {
316+
throw Py::Exception();
323317
}
324318
close_file = true;
319+
} else {
320+
py_file = py_fileobj.ptr();
325321
}
326-
#if PY3K
327-
else if (fd != -1) {
328-
fp = fdopen(fd, "r");
329-
}
330-
#else
331-
else if (PyFile_CheckExact(py_fileobj.ptr()))
322+
323+
if ((fp = npy_PyFile_Dup(py_file, "r")))
332324
{
333-
fp = PyFile_AsFile(py_fileobj.ptr());
325+
close_dup_file = true;
334326
}
335-
#endif
336327
else
337328
{
338-
PyObject* read_method = PyObject_GetAttrString(py_fileobj.ptr(), "read");
329+
PyObject* read_method = PyObject_GetAttrString(py_file, "read");
339330
if (!(read_method && PyCallable_Check(read_method)))
340331
{
341332
Py_XDECREF(read_method);
342-
throw Py::TypeError("Object does not appear to be a 8-bit string path or a Python file-like object");
333+
throw Py::TypeError(
334+
"Object does not appear to be a 8-bit string path or a Python "
335+
"file-like object");
343336
}
344337
Py_XDECREF(read_method);
345338
}
@@ -354,7 +347,7 @@ _png_module::_read_png(const Py::Object& py_fileobj, const bool float_result,
354347
}
355348
else
356349
{
357-
_read_png_data(py_fileobj.ptr(), header, 8);
350+
_read_png_data(py_file, header, 8);
358351
}
359352
if (png_sig_cmp(header, 0, 8))
360353
{
@@ -390,7 +383,7 @@ _png_module::_read_png(const Py::Object& py_fileobj, const bool float_result,
390383
}
391384
else
392385
{
393-
png_set_read_fn(png_ptr, (void*)py_fileobj.ptr(), &read_png_data);
386+
png_set_read_fn(png_ptr, (void*)py_file, &read_png_data);
394387
}
395388
png_set_sig_bytes(png_ptr, 8);
396389
png_read_info(png_ptr, info_ptr);
@@ -572,10 +565,17 @@ _png_module::_read_png(const Py::Object& py_fileobj, const bool float_result,
572565
#else
573566
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
574567
#endif
568+
if (close_dup_file)
569+
{
570+
npy_PyFile_DupClose(py_file, fp);
571+
}
572+
575573
if (close_file)
576574
{
577-
fclose(fp);
575+
npy_PyFile_CloseFile(py_file);
576+
Py_DECREF(py_file);
578577
}
578+
579579
for (row = 0; row < height; row++)
580580
{
581581
delete [] row_pointers[row];

0 commit comments

Comments
 (0)