From e103eb90c24901d06b8a8abc48201aa2dbba890c Mon Sep 17 00:00:00 2001 From: "willmcgugan@gmail.com" Date: Thu, 16 Oct 2014 14:07:23 +0000 Subject: Fixes, including hang bug in readline git-svn-id: http://pyfilesystem.googlecode.com/svn/trunk@899 67cdc799-7952-0410-af00-57a81ceafa0f --- CHANGES.txt | 7 ++++++- fs/commands/runner.py | 2 +- fs/filelike.py | 2 +- fs/ftpfs.py | 39 +++++++-------------------------------- fs/iotools.py | 24 ++++++++++++++++++++++++ fs/path.py | 2 +- fs/tests/__init__.py | 7 +++++++ 7 files changed, 47 insertions(+), 36 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index d6b28bd..df34fd7 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -79,7 +79,7 @@ * Removed obsolete module fs.objectree; use fs.path.PathMap instead. * Added setcontents_async method to base * Added `appdirfs` module to abstract per-user application directories - + 0.5: * Ported to Python 3.X @@ -88,3 +88,8 @@ * Added sqlitefs to fs.contrib, contributed by Nitin Bhide * Added archivefs to fs.contrib, contributed by btimby * Added some polish to fstree command and unicode box lines rather than ascii art + +0.5: + + * Fixed a hang bug in readline + diff --git a/fs/commands/runner.py b/fs/commands/runner.py index 57d6e99..fa50272 100644 --- a/fs/commands/runner.py +++ b/fs/commands/runner.py @@ -258,7 +258,7 @@ class Command(object): def error(self, *msgs): for msg in msgs: - self.error_file.write('%s: %s' % (self.name, self.text_encode(msg))) + self.error_file.write("{}: {}".format(self.name, msg).encode(self.encoding)) def get_optparse(self): optparse = OptionParser(usage=self.usage, version=self.version) diff --git a/fs/filelike.py b/fs/filelike.py index dc3706f..6714746 100644 --- a/fs/filelike.py +++ b/fs/filelike.py @@ -494,7 +494,7 @@ class FileLikeBase(object): nextBit = self.read(self._bufsize) bits.append(nextBit) sizeSoFar += len(nextBit) - if nextBit == b(""): + if not nextBit: break if size > 0 and sizeSoFar >= size: break diff --git a/fs/ftpfs.py b/fs/ftpfs.py index 8a32db5..830c119 100644 --- a/fs/ftpfs.py +++ b/fs/ftpfs.py @@ -804,40 +804,15 @@ class _FTPFile(object): pass self.closed = True - def __iter__(self): - return self.next() - - @synchronize def next(self): - """ Line iterator + return self.readline() + + def readline(self, size=None): + return next(iotools.line_iterator(self, size)) + + def __iter__(self): + return iotools.line_iterator(self) - This isn't terribly efficient. It would probably be better to do - a read followed by splitlines. - """ - endings = b('\r\n') - chars = [] - append = chars.append - read = self.read - join = b('').join - while True: - char = read(1) - if not char: - if chars: - yield join(chars) - break - append(char) - if char in endings: - line = join(chars) - del chars[:] - c = read(1) - if not char: - yield line - break - if c in endings and c != char: - yield line + c - else: - yield line - append(c) def ftperrors(f): @wraps(f) diff --git a/fs/iotools.py b/fs/iotools.py index f2e0f6e..bf91ec3 100644 --- a/fs/iotools.py +++ b/fs/iotools.py @@ -211,6 +211,30 @@ def copy_file_to_fs(f, fs, path, encoding=None, errors=None, progress_callback=N return bytes_written +def line_iterator(f, size=None): + """A not terribly efficient char by char line iterator""" + read = f.read + line = [] + append = line.append + c = 1 + if size is None or size < 0: + while c: + c = read(1) + if c: + append(c) + if c in (b'\n', b''): + yield b''.join(line) + del line[:] + else: + while c: + c = read(1) + if c: + append(c) + if c in (b'\n', b'') or len(line) >= size: + yield b''.join(line) + del line[:] + + if __name__ == "__main__": print("Reading a binary file") bin_file = open('tests/data/UTF-8-demo.txt', 'rb') diff --git a/fs/path.py b/fs/path.py index 57c587e..1b5c072 100644 --- a/fs/path.py +++ b/fs/path.py @@ -376,7 +376,7 @@ def isprefix(path1, path2): def forcedir(path): - """Ensure the path ends with a trailing / + """Ensure the path ends with a trailing formward slash :param path: An FS path diff --git a/fs/tests/__init__.py b/fs/tests/__init__.py index 3aa8ec8..7af1476 100644 --- a/fs/tests/__init__.py +++ b/fs/tests/__init__.py @@ -147,6 +147,13 @@ class FSTestCases(object): self.fs.createfile("test.txt", wipe=True) self.assertEqual(self.fs.getcontents("test.txt", "rb"), b('')) + def test_readline(self): + text = b"Hello\nWorld\n" + self.fs.setcontents('a.txt', text) + with self.fs.open('a.txt', 'rb') as f: + line = f.readline() + self.assertEqual(line, b"Hello\n") + def test_setcontents(self): # setcontents() should accept both a string... self.fs.setcontents("hello", b("world")) -- cgit v1.2.1