diff options
author | Charles Harris <charlesr.harris@gmail.com> | 2017-04-14 19:29:44 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-14 19:29:44 -0600 |
commit | 6c91e9ee0d9e9fc16e504780ccf7ede26d1114c8 (patch) | |
tree | 78075c826d7ef3230a7743034d80cb87997ab84e /numpy | |
parent | 0f3846aaabc7c1278e9aeab7aafa0b8d4a1b264e (diff) | |
parent | d1bb606012b069600ae60e37b7675122fdde29b8 (diff) | |
download | numpy-6c91e9ee0d9e9fc16e504780ccf7ede26d1114c8.tar.gz |
Merge pull request #6632 from mcmtroffaes/feature/fromfile-ioopen-bug
TST/BUG: fromfile - fix test and expose bug with io class argument
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/include/numpy/npy_3kcompat.h | 48 | ||||
-rw-r--r-- | numpy/core/records.py | 3 | ||||
-rw-r--r-- | numpy/core/src/multiarray/methods.c | 2 | ||||
-rw-r--r-- | numpy/core/src/multiarray/multiarraymodule.c | 2 | ||||
-rw-r--r-- | numpy/core/tests/test_multiarray.py | 21 | ||||
-rw-r--r-- | numpy/lib/tests/test_io.py | 5 |
6 files changed, 45 insertions, 36 deletions
diff --git a/numpy/core/include/numpy/npy_3kcompat.h b/numpy/core/include/numpy/npy_3kcompat.h index cdab1bbe8..c0aa1eb2e 100644 --- a/numpy/core/include/numpy/npy_3kcompat.h +++ b/numpy/core/include/numpy/npy_3kcompat.h @@ -148,7 +148,7 @@ PyUnicode_Concat2(PyObject **left, PyObject *right) /* * PyFile_* compatibility */ -#if defined(NPY_PY3K) + /* * Get a FILE* handle to the file represented by the Python object */ @@ -160,6 +160,13 @@ npy_PyFile_Dup2(PyObject *file, char *mode, npy_off_t *orig_pos) npy_off_t pos; FILE *handle; + /* For Python 2 PyFileObject, use PyFile_AsFile */ +#if !defined(NPY_PY3K) + if (PyFile_Check(file)) { + return PyFile_AsFile(file); + } +#endif + /* Flush first to ensure things end up in the file in the correct order */ ret = PyObject_CallMethod(file, "flush", ""); if (ret == NULL) { @@ -257,6 +264,13 @@ npy_PyFile_DupClose2(PyObject *file, FILE* handle, npy_off_t orig_pos) PyObject *ret, *io, *io_raw; npy_off_t position; + /* For Python 2 PyFileObject, do nothing */ +#if !defined(NPY_PY3K) + if (PyFile_Check(file)) { + return 0; + } +#endif + position = npy_ftell(handle); /* Close the FILE* handle */ @@ -314,6 +328,12 @@ static NPY_INLINE int npy_PyFile_Check(PyObject *file) { int fd; + /* For Python 2, check if it is a PyFileObject */ +#if !defined(NPY_PY3K) + if (PyFile_Check(file)) { + return 1; + } +#endif fd = PyObject_AsFileDescriptor(file); if (fd == -1) { PyErr_Clear(); @@ -322,32 +342,6 @@ npy_PyFile_Check(PyObject *file) return 1; } -#else - -static NPY_INLINE FILE * -npy_PyFile_Dup2(PyObject *file, - const char *NPY_UNUSED(mode), npy_off_t *NPY_UNUSED(orig_pos)) -{ - FILE * fp = PyFile_AsFile(file); - if (fp == NULL) { - PyErr_SetString(PyExc_IOError, - "first argument must be an open file"); - return NULL; - } - return fp; -} - -static NPY_INLINE int -npy_PyFile_DupClose2(PyObject *NPY_UNUSED(file), FILE* NPY_UNUSED(handle), - npy_off_t NPY_UNUSED(orig_pos)) -{ - return 0; -} - -#define npy_PyFile_Check PyFile_Check - -#endif - static NPY_INLINE PyObject* npy_PyFile_OpenFile(PyObject *filename, const char *mode) { diff --git a/numpy/core/records.py b/numpy/core/records.py index 7ad0c111a..ecc293812 100644 --- a/numpy/core/records.py +++ b/numpy/core/records.py @@ -723,7 +723,8 @@ def fromfile(fd, dtype=None, shape=None, offset=0, formats=None, """Create an array from binary file data If file is a string then that file is opened, else it is assumed - to be a file object. + to be a file object. The file object must support random access + (i.e. it must have tell and seek methods). >>> from tempfile import TemporaryFile >>> a = np.empty(10,dtype='f8,i4,a5') diff --git a/numpy/core/src/multiarray/methods.c b/numpy/core/src/multiarray/methods.c index c30b38109..945ae9804 100644 --- a/numpy/core/src/multiarray/methods.c +++ b/numpy/core/src/multiarray/methods.c @@ -563,7 +563,7 @@ array_tofile(PyArrayObject *self, PyObject *args, PyObject *kwds) FILE *fd; char *sep = ""; char *format = ""; - npy_off_t orig_pos; + npy_off_t orig_pos = 0; static char *kwlist[] = {"file", "sep", "format", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|ss:tofile", kwlist, diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c index babbdf581..2fdabb187 100644 --- a/numpy/core/src/multiarray/multiarraymodule.c +++ b/numpy/core/src/multiarray/multiarraymodule.c @@ -2067,7 +2067,7 @@ array_fromfile(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *keywds) static char *kwlist[] = {"file", "dtype", "count", "sep", NULL}; PyArray_Descr *type = NULL; int own; - npy_off_t orig_pos; + npy_off_t orig_pos = 0; FILE *fp; if (!PyArg_ParseTupleAndKeywords(args, keywds, diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index df201f582..213ae7a52 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -3903,7 +3903,7 @@ class TestLexsort(TestCase): x = np.linspace(0., 1., 42*3).reshape(42, 3) assert_raises(np.AxisError, np.lexsort, x, axis=2) -class TestIO(object): +class TestIO(TestCase): """Test tofile, fromfile, tobytes, and fromstring""" def setUp(self): @@ -3994,17 +3994,23 @@ class TestIO(object): y = np.fromstring(s, sep="@") assert_array_equal(x, y) - def test_unbuffered_fromfile(self): + def test_unseekable_fromfile(self): # gh-6246 self.x.tofile(self.filename) def fail(*args, **kwargs): - raise io.IOError('Can not tell or seek') + raise IOError('Can not tell or seek') with io.open(self.filename, 'rb', buffering=0) as f: f.seek = fail f.tell = fail - y = np.fromfile(self.filename, dtype=self.dtype) + self.assertRaises(IOError, np.fromfile, f, dtype=self.dtype) + + def test_io_open_unbuffered_fromfile(self): + # gh-6632 + self.x.tofile(self.filename) + with io.open(self.filename, 'rb', buffering=0) as f: + y = np.fromfile(f, dtype=self.dtype) assert_array_equal(y, self.x.flat) def test_largish_file(self): @@ -4028,6 +4034,13 @@ class TestIO(object): assert_equal(os.path.getsize(self.filename), d.nbytes * 2) + def test_io_open_buffered_fromfile(self): + # gh-6632 + self.x.tofile(self.filename) + f = io.open(self.filename, 'rb', buffering=-1) + y = np.fromfile(f, dtype=self.dtype) + assert_array_equal(y, self.x.flat) + def test_file_position_after_fromfile(self): # gh-4118 sizes = [io.DEFAULT_BUFFER_SIZE//8, diff --git a/numpy/lib/tests/test_io.py b/numpy/lib/tests/test_io.py index 2a494fe08..868089551 100644 --- a/numpy/lib/tests/test_io.py +++ b/numpy/lib/tests/test_io.py @@ -103,8 +103,9 @@ class RoundtripTest(object): if not isinstance(target_file, BytesIO): target_file.close() # holds an open file descriptor so it can't be deleted on win - if not isinstance(arr_reloaded, np.lib.npyio.NpzFile): - os.remove(target_file.name) + if 'arr_reloaded' in locals(): + if not isinstance(arr_reloaded, np.lib.npyio.NpzFile): + os.remove(target_file.name) def check_roundtrips(self, a): self.roundtrip(a) |