From 94f507dd327a842d0fffaac6e324328430f6a2fa Mon Sep 17 00:00:00 2001 From: Nick Henderson Date: Thu, 9 Apr 2020 10:40:54 -0700 Subject: [PATCH 01/10] add _MemoryFile.readinto method --- fs/memoryfs.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fs/memoryfs.py b/fs/memoryfs.py index 2a011b21..5c71deb9 100644 --- a/fs/memoryfs.py +++ b/fs/memoryfs.py @@ -142,6 +142,14 @@ def readable(self): # type: () -> bool return self._mode.reading + def readinto(self, b): + # type (bytes) -> Optional[int] + if not self._mode.reading: + raise IOError("File not open for reading") + with self._seek_lock(): + self.on_access() + return self._bytes_io.readinto(b) + def readlines(self, hint=-1): # type: (int) -> List[bytes] with self._seek_lock(): From df23bd9f288e93f52c9fdd6041f3640468f1b88d Mon Sep 17 00:00:00 2001 From: Nick Henderson Date: Thu, 9 Apr 2020 10:52:48 -0700 Subject: [PATCH 02/10] update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa072e2e..3b965c9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - Missing `mode` attribute to `_MemoryFile` objects returned by `MemoryFS.openbin`. +- Missing `readinto` method for `MemoryFS` and `FTPFS` file objects. Closes + [#380](https://github.com/PyFilesystem/pyfilesystem2/issues/380). ### Changed From 33692ab0717ed4c96be88c4a00779b207cc56d80 Mon Sep 17 00:00:00 2001 From: Nick Henderson Date: Fri, 10 Apr 2020 09:25:30 -0700 Subject: [PATCH 03/10] call on_access in _MemoryFile next and readlines methods --- fs/memoryfs.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/memoryfs.py b/fs/memoryfs.py index 5c71deb9..78ab33dd 100644 --- a/fs/memoryfs.py +++ b/fs/memoryfs.py @@ -113,6 +113,7 @@ def __iter__(self): def next(self): # type: () -> bytes with self._seek_lock(): + self.on_access() return next(self._bytes_io) __next__ = next @@ -153,6 +154,7 @@ def readinto(self, b): def readlines(self, hint=-1): # type: (int) -> List[bytes] with self._seek_lock(): + self.on_access() return self._bytes_io.readlines(hint) def seekable(self): From f04ec4e9e7bc5f5a16c8a22be47f3d326d8743e2 Mon Sep 17 00:00:00 2001 From: Nick Henderson Date: Fri, 10 Apr 2020 10:26:36 -0700 Subject: [PATCH 04/10] add myself to CONTRIBUTORS.md --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 3b3e8c2d..ba15fd73 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -9,6 +9,7 @@ Many thanks to the following developers for contributing to this project: - [Justin Charlong](https://github.com/jcharlong) - [Louis Sautier](https://github.com/sbraz) - [Martin Larralde](https://github.com/althonos) +- [Nick Henderson](https://github.com/nwh) - [Will McGugan](https://github.com/willmcgugan) - [Zmej Serow](https://github.com/zmej-serow) - [Morten Engelhardt Olsen](https://github.com/xoriath) From ff33f9957eaaac14f1a040113e551901b7b8664a Mon Sep 17 00:00:00 2001 From: Nick Henderson Date: Fri, 10 Apr 2020 10:33:47 -0700 Subject: [PATCH 05/10] add mode checks for _MemoryFile readline and readlines methods --- fs/memoryfs.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/memoryfs.py b/fs/memoryfs.py index 78ab33dd..a5d0eedf 100644 --- a/fs/memoryfs.py +++ b/fs/memoryfs.py @@ -120,6 +120,8 @@ def next(self): def readline(self, size=-1): # type: (int) -> bytes + if not self._mode.reading: + raise IOError("File not open for reading") with self._seek_lock(): self.on_access() return self._bytes_io.readline(size) @@ -153,6 +155,8 @@ def readinto(self, b): def readlines(self, hint=-1): # type: (int) -> List[bytes] + if not self._mode.reading: + raise IOError("File not open for reading") with self._seek_lock(): self.on_access() return self._bytes_io.readlines(hint) From 59351607c21dcff7dde15a16cbea942287ad70d6 Mon Sep 17 00:00:00 2001 From: Nick Henderson Date: Fri, 10 Apr 2020 10:34:08 -0700 Subject: [PATCH 06/10] fix type annotation for _MemoryFile.readinto --- fs/memoryfs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/memoryfs.py b/fs/memoryfs.py index a5d0eedf..3c22d0c2 100644 --- a/fs/memoryfs.py +++ b/fs/memoryfs.py @@ -146,7 +146,7 @@ def readable(self): return self._mode.reading def readinto(self, b): - # type (bytes) -> Optional[int] + # type (bytearray) -> Optional[int] if not self._mode.reading: raise IOError("File not open for reading") with self._seek_lock(): From 7a113fc7d298bbd05ec0e5932e6cdb755869bd1f Mon Sep 17 00:00:00 2001 From: Nick Henderson Date: Fri, 10 Apr 2020 10:44:06 -0700 Subject: [PATCH 07/10] add test for readinto method in open file object --- fs/test.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/test.py b/fs/test.py index 37751731..3508709a 100644 --- a/fs/test.py +++ b/fs/test.py @@ -870,6 +870,11 @@ def test_open_files(self): self.assertTrue(f.readable()) self.assertFalse(f.closed) self.assertEqual(f.readlines(8), [b"Hello\n", b"World\n"]) + self.assertEqual(f.tell(), 12) + b = bytearray(4) + self.assertEqual(f.readinto(b), 4) + self.assertEqual(f.tell(), 16) + self.assertEqual(b, b"foo\n") with self.assertRaises(IOError): f.write(b"no") self.assertTrue(f.closed) From 9bfbd6ae7f3f13f4b918d989bc2a21ffdeae28c3 Mon Sep 17 00:00:00 2001 From: Nick Henderson Date: Fri, 10 Apr 2020 11:26:36 -0700 Subject: [PATCH 08/10] add FTPFile.readinto method --- fs/ftpfs.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fs/ftpfs.py b/fs/ftpfs.py index 6442a1ba..2a1fabe6 100644 --- a/fs/ftpfs.py +++ b/fs/ftpfs.py @@ -235,6 +235,13 @@ def read(self, size=-1): remaining -= len(chunk) return b"".join(chunks) + def readinto(self, buffer): + # type: (bytearray) -> int + data = self.read(len(buffer)) + bytes_read = len(data) + buffer[: len(data)] = data + return bytes_read + def readline(self, size=-1): # type: (int) -> bytes return next(line_iterator(self, size)) # type: ignore From c9d71f214aacdfbed8ada2ae3fbcfddb82b5d90f Mon Sep 17 00:00:00 2001 From: Nick Henderson Date: Fri, 10 Apr 2020 11:30:13 -0700 Subject: [PATCH 09/10] use buffer as variable name for bytearray objects --- fs/memoryfs.py | 4 ++-- fs/test.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/memoryfs.py b/fs/memoryfs.py index 3c22d0c2..d1c23724 100644 --- a/fs/memoryfs.py +++ b/fs/memoryfs.py @@ -145,13 +145,13 @@ def readable(self): # type: () -> bool return self._mode.reading - def readinto(self, b): + def readinto(self, buffer): # type (bytearray) -> Optional[int] if not self._mode.reading: raise IOError("File not open for reading") with self._seek_lock(): self.on_access() - return self._bytes_io.readinto(b) + return self._bytes_io.readinto(buffer) def readlines(self, hint=-1): # type: (int) -> List[bytes] diff --git a/fs/test.py b/fs/test.py index 3508709a..9d8e7ed7 100644 --- a/fs/test.py +++ b/fs/test.py @@ -871,10 +871,10 @@ def test_open_files(self): self.assertFalse(f.closed) self.assertEqual(f.readlines(8), [b"Hello\n", b"World\n"]) self.assertEqual(f.tell(), 12) - b = bytearray(4) - self.assertEqual(f.readinto(b), 4) + buffer = bytearray(4) + self.assertEqual(f.readinto(buffer), 4) self.assertEqual(f.tell(), 16) - self.assertEqual(b, b"foo\n") + self.assertEqual(buffer, b"foo\n") with self.assertRaises(IOError): f.write(b"no") self.assertTrue(f.closed) From a81f545bda5edc519f1752f6000386f114bbc1e2 Mon Sep 17 00:00:00 2001 From: Nick Henderson Date: Thu, 15 Oct 2020 12:08:45 -0700 Subject: [PATCH 10/10] use bytes_read variable in readinto methods --- fs/ftpfs.py | 2 +- fs/iotools.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/ftpfs.py b/fs/ftpfs.py index 2a1fabe6..e3a39411 100644 --- a/fs/ftpfs.py +++ b/fs/ftpfs.py @@ -239,7 +239,7 @@ def readinto(self, buffer): # type: (bytearray) -> int data = self.read(len(buffer)) bytes_read = len(data) - buffer[: len(data)] = data + buffer[:bytes_read] = data return bytes_read def readline(self, size=-1): diff --git a/fs/iotools.py b/fs/iotools.py index 26402ff3..44849680 100644 --- a/fs/iotools.py +++ b/fs/iotools.py @@ -117,7 +117,7 @@ def readinto(self, b): except AttributeError: data = self._f.read(len(b)) bytes_read = len(data) - b[: len(data)] = data + b[:bytes_read] = data return bytes_read @typing.no_type_check @@ -128,7 +128,7 @@ def readinto1(self, b): except AttributeError: data = self._f.read1(len(b)) bytes_read = len(data) - b[: len(data)] = data + b[:bytes_read] = data return bytes_read def readline(self, limit=-1):