diff options
author | willmcgugan@gmail.com <willmcgugan@gmail.com@67cdc799-7952-0410-af00-57a81ceafa0f> | 2013-03-31 21:30:34 +0000 |
---|---|---|
committer | willmcgugan@gmail.com <willmcgugan@gmail.com@67cdc799-7952-0410-af00-57a81ceafa0f> | 2013-03-31 21:30:34 +0000 |
commit | 838bfcd555fd6e4cd7eceaa7ccdbbdc78986cc06 (patch) | |
tree | 5547f10f29e28894ae70ff5b97e858456f94103a /fs/iotools.py | |
parent | 8c1e089ad130972b7867b393226b276f56c82ecb (diff) | |
download | pyfilesystem-838bfcd555fd6e4cd7eceaa7ccdbbdc78986cc06.tar.gz |
Change of api (fs.open, fs.setcontent, fs.getcontents) to support io module in Py2.6+ and Py3
git-svn-id: http://pyfilesystem.googlecode.com/svn/trunk@854 67cdc799-7952-0410-af00-57a81ceafa0f
Diffstat (limited to 'fs/iotools.py')
-rw-r--r-- | fs/iotools.py | 101 |
1 files changed, 92 insertions, 9 deletions
diff --git a/fs/iotools.py b/fs/iotools.py index 4cd8b24..93b90c3 100644 --- a/fs/iotools.py +++ b/fs/iotools.py @@ -1,18 +1,22 @@ from __future__ import unicode_literals from __future__ import print_function + import io +from functools import wraps + +import six class RawWrapper(object): """Convert a Python 2 style file-like object in to a IO object""" def __init__(self, f, mode=None, name=None): self._f = f + self.is_io = isinstance(f, io.IOBase) if mode is None and hasattr(f, 'mode'): mode = f.mode self.mode = mode self.name = name self.closed = False - super(RawWrapper, self).__init__() def __repr__(self): @@ -35,12 +39,18 @@ class RawWrapper(object): return self._f.seek(offset, whence) def readable(self): + if hasattr(self._f, 'readable'): + return self._f.readable() return 'r' in self.mode def writable(self): + if hasattr(self._f, 'writeable'): + return self._fs.writeable() return 'w' in self.mode def seekable(self): + if hasattr(self._f, 'seekable'): + return self._f.seekable() try: self.seek(0, io.SEEK_CUR) except IOError: @@ -51,11 +61,14 @@ class RawWrapper(object): def tell(self): return self._f.tell() - def truncate(self, size): + def truncate(self, size=None): return self._f.truncate(size) def write(self, data): - return self._f.write(data) + if self.is_io: + return self._f.write(data) + self._f.write(data) + return len(data) def read(self, n=-1): if n == -1: @@ -63,21 +76,21 @@ class RawWrapper(object): return self._f.read(n) def read1(self, n=-1): + if self.is_io: + return self.read1(n) return self.read(n) def readall(self): return self._f.read() def readinto(self, b): + if self.is_io: + return self._f.readinto(b) data = self._f.read(len(b)) bytes_read = len(data) b[:len(data)] = data return bytes_read - def write(self, b): - bytes_written = self._f.write(b) - return bytes_written - def writelines(self, sequence): return self._f.writelines(sequence) @@ -87,6 +100,32 @@ class RawWrapper(object): def __exit__(self, *args, **kwargs): self.close() + def __iter__(self): + return iter(self._f) + + +def filelike_to_stream(f): + @wraps(f) + def wrapper(self, path, mode='rt', buffering=-1, encoding=None, errors=None, newline=None, line_buffering=False, **kwargs): + file_like = f(self, + path, + mode=mode, + buffering=buffering, + encoding=encoding, + errors=errors, + newline=newline, + line_buffering=line_buffering, + **kwargs) + return make_stream(path, + file_like, + mode=mode, + buffering=buffering, + encoding=encoding, + errors=errors, + newline=newline, + line_buffering=line_buffering) + return wrapper + def make_stream(name, f, @@ -95,9 +134,8 @@ def make_stream(name, encoding=None, errors=None, newline=None, - closefd=True, line_buffering=False, - **params): + **kwargs): """Take a Python 2.x binary file and returns an IO Stream""" r, w, a, binary = 'r' in mode, 'w' in mode, 'a' in mode, 'b' in mode if '+' in mode: @@ -122,6 +160,51 @@ def make_stream(name, return io_object +def decode_binary(data, encoding=None, errors=None, newline=None): + """Decode bytes as though read from a text file""" + return io.TextIOWrapper(io.BytesIO(data), encoding=encoding, errors=errors, newline=newline).read() + + +def make_bytes_io(data, encoding=None, errors=None): + """Make a bytes IO object from either a string or an open file""" + if hasattr(data, 'mode') and 'b' in data.mode: + # It's already a binary file + return data + if not isinstance(data, basestring): + # It's a file, but we don't know if its binary + # TODO: Is there a better way than reading the entire file? + data = data.read() or b'' + if isinstance(data, six.text_type): + # If its text, encoding in to bytes + data = data.encode(encoding=encoding, errors=errors) + return io.BytesIO(data) + + + + +def copy_file_to_fs(f, fs, path, encoding=None, errors=None, progress_callback=None, chunk_size=64 * 1024): + """Copy an open file to a path on an FS""" + if progress_callback is None: + progress_callback = lambda bytes_written: None + read = f.read + chunk = read(chunk_size) + if isinstance(chunk, six.text_type): + f = fs.open(path, 'wt', encoding=encoding, errors=errors) + else: + f = fs.open(path, 'wb') + write = f.write + bytes_written = 0 + try: + while chunk: + write(chunk) + bytes_written += len(chunk) + progress_callback(bytes_written) + chunk = read(chunk_size) + finally: + f.close() + return bytes_written + + if __name__ == "__main__": print("Reading a binary file") bin_file = open('tests/data/UTF-8-demo.txt', 'rb') |