2727#include " CXX/Extensions.hxx"
2828#include " numpy/arrayobject.h"
2929#include " mplutils.h"
30+ #include " file_compat.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,34 @@ 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_fileobj.ptr (), (char *)" wb" )) == 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 *) " wb " )))
153147 {
154- fp = PyFile_AsFile (py_fileobj. ptr ()) ;
148+ close_dup_file = true ;
155149 }
156- #endif
157150 else
158151 {
152+ PyErr_Clear ();
159153 PyObject* write_method = PyObject_GetAttrString (
160- py_fileobj. ptr () , " write" );
154+ py_file , " write" );
161155 if (!(write_method && PyCallable_Check (write_method)))
162156 {
163157 Py_XDECREF (write_method);
164158 throw Py::TypeError (
165- " Object does not appear to be a 8-bit string path or a Python file-like object" );
159+ " Object does not appear to be a 8-bit string path or "
160+ " a Python file-like object" );
166161 }
167162 Py_XDECREF (write_method);
168163 }
@@ -205,7 +200,7 @@ Py::Object _png_module::write_png(const Py::Tuple& args)
205200 }
206201 else
207202 {
208- png_set_write_fn (png_ptr, (void *)py_fileobj. ptr () ,
203+ png_set_write_fn (png_ptr, (void *)py_file ,
209204 &write_png_data, &flush_png_data);
210205 }
211206 png_set_IHDR (png_ptr, info_ptr,
@@ -241,9 +236,16 @@ Py::Object _png_module::write_png(const Py::Tuple& args)
241236 png_destroy_write_struct (&png_ptr, &info_ptr);
242237 }
243238 delete [] row_pointers;
244- if (fp && close_file)
239+
240+ if (close_dup_file)
241+ {
242+ npy_PyFile_DupClose (py_file, fp);
243+ }
244+
245+ if (close_file)
245246 {
246- fclose (fp);
247+ npy_PyFile_CloseFile (py_file);
248+ Py_DECREF (py_file);
247249 }
248250 /* Changed calls to png_destroy_write_struct to follow
249251 http://www.libpng.org/pub/png/libpng-manual.txt.
@@ -254,15 +256,15 @@ Py::Object _png_module::write_png(const Py::Tuple& args)
254256
255257 png_destroy_write_struct (&png_ptr, &info_ptr);
256258 delete [] row_pointers;
257- #if PY3K
258- if (fp)
259+ if (close_dup_file)
259260 {
260- fflush ( fp);
261+ npy_PyFile_DupClose (py_file, fp);
261262 }
262- # endif
263- if (fp && close_file)
263+
264+ if (close_file)
264265 {
265- fclose (fp);
266+ npy_PyFile_CloseFile (py_file);
267+ Py_DECREF (py_file);
266268 }
267269
268270 if (PyErr_Occurred ()) {
@@ -306,40 +308,33 @@ _png_module::_read_png(const Py::Object& py_fileobj, const bool float_result,
306308 png_byte header[8 ]; // 8 is the maximum size that can be checked
307309 FILE* fp = NULL ;
308310 bool close_file = false ;
309-
310- #if PY3K
311- int fd = PyObject_AsFileDescriptor (py_fileobj.ptr ());
312- PyErr_Clear ();
313- #endif
311+ bool close_dup_file = false ;
312+ PyObject *py_file = NULL ;
314313
315314 if (py_fileobj.isString ())
316315 {
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 ());
316+ if ((py_file = npy_PyFile_OpenFile (py_fileobj.ptr (), (char *)" rb" )) == NULL ) {
317+ throw Py::Exception ();
323318 }
324319 close_file = true ;
320+ } else {
321+ py_file = py_fileobj.ptr ();
325322 }
326- #if PY3K
327- else if (fd != -1 ) {
328- fp = fdopen (fd, " r" );
329- }
330- #else
331- else if (PyFile_CheckExact (py_fileobj.ptr ()))
323+
324+ if ((fp = npy_PyFile_Dup (py_file, " rb" )))
332325 {
333- fp = PyFile_AsFile (py_fileobj. ptr ()) ;
326+ close_dup_file = true ;
334327 }
335- #endif
336328 else
337329 {
338- PyObject* read_method = PyObject_GetAttrString (py_fileobj.ptr (), " read" );
330+ PyErr_Clear ();
331+ PyObject* read_method = PyObject_GetAttrString (py_file, " read" );
339332 if (!(read_method && PyCallable_Check (read_method)))
340333 {
341334 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" );
335+ throw Py::TypeError (
336+ " Object does not appear to be a 8-bit string path or a Python "
337+ " file-like object" );
343338 }
344339 Py_XDECREF (read_method);
345340 }
@@ -354,7 +349,7 @@ _png_module::_read_png(const Py::Object& py_fileobj, const bool float_result,
354349 }
355350 else
356351 {
357- _read_png_data (py_fileobj. ptr () , header, 8 );
352+ _read_png_data (py_file , header, 8 );
358353 }
359354 if (png_sig_cmp (header, 0 , 8 ))
360355 {
@@ -390,7 +385,7 @@ _png_module::_read_png(const Py::Object& py_fileobj, const bool float_result,
390385 }
391386 else
392387 {
393- png_set_read_fn (png_ptr, (void *)py_fileobj. ptr () , &read_png_data);
388+ png_set_read_fn (png_ptr, (void *)py_file , &read_png_data);
394389 }
395390 png_set_sig_bytes (png_ptr, 8 );
396391 png_read_info (png_ptr, info_ptr);
@@ -572,10 +567,17 @@ _png_module::_read_png(const Py::Object& py_fileobj, const bool float_result,
572567#else
573568 png_destroy_read_struct (&png_ptr, &info_ptr, png_infopp_NULL);
574569#endif
570+ if (close_dup_file)
571+ {
572+ npy_PyFile_DupClose (py_file, fp);
573+ }
574+
575575 if (close_file)
576576 {
577- fclose (fp);
577+ npy_PyFile_CloseFile (py_file);
578+ Py_DECREF (py_file);
578579 }
580+
579581 for (row = 0 ; row < height; row++)
580582 {
581583 delete [] row_pointers[row];
0 commit comments