summaryrefslogtreecommitdiff
path: root/fs/iotools.py
diff options
context:
space:
mode:
authorwillmcgugan@gmail.com <willmcgugan@gmail.com@67cdc799-7952-0410-af00-57a81ceafa0f>2013-03-31 21:30:34 +0000
committerwillmcgugan@gmail.com <willmcgugan@gmail.com@67cdc799-7952-0410-af00-57a81ceafa0f>2013-03-31 21:30:34 +0000
commit838bfcd555fd6e4cd7eceaa7ccdbbdc78986cc06 (patch)
tree5547f10f29e28894ae70ff5b97e858456f94103a /fs/iotools.py
parent8c1e089ad130972b7867b393226b276f56c82ecb (diff)
downloadpyfilesystem-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.py101
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')