Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 889951e

Browse filesBrowse 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
Copy full SHA for 889951e

File tree

Expand file treeCollapse file tree

1 file changed

+52
-52
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+52
-52
lines changed

‎src/_png.cpp

Copy file name to clipboardExpand all lines: src/_png.cpp
+52-52Lines 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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.