summaryrefslogtreecommitdiff
path: root/fs/filelike.py
diff options
context:
space:
mode:
Diffstat (limited to 'fs/filelike.py')
-rw-r--r--fs/filelike.py74
1 files changed, 38 insertions, 36 deletions
diff --git a/fs/filelike.py b/fs/filelike.py
index be2bfac..37be374 100644
--- a/fs/filelike.py
+++ b/fs/filelike.py
@@ -20,14 +20,14 @@ Other useful classes include:
(think e.g. compression or decryption).
* SpooledTemporaryFile: a version of the builtin SpooledTemporaryFile
- class, patched to more closely preserve the
+ class, patched to more closely preserve the
semantics of a standard file.
* LimitBytesFile: a filelike wrapper that limits the total bytes read
from a file; useful for turning a socket into a file
without reading past end-of-data.
-"""
+"""
# Copyright (C) 2006-2009, Ryan Kelly
# All rights reserved; available under the terms of the MIT License.
@@ -55,24 +55,24 @@ else:
from cStringIO import StringIO as _StringIO
except ImportError:
from StringIO import StringIO as _StringIO
-
+
class FileLikeBase(object):
"""Base class for implementing file-like objects.
-
+
This class takes a lot of the legwork out of writing file-like objects
with a rich interface. It implements the higher-level file-like methods
on top of five primitive methods: _read, _write, _seek, _tell and
_truncate. See their docstrings for precise details on how these methods
behave.
-
+
Subclasses then need only implement some subset of these methods for
rich file-like interface compatibility. They may of course override
other methods as desired.
The class is missing the following attributes and methods, which don't
really make sense for anything but real files:
-
+
* fileno()
* isatty()
* encoding
@@ -104,7 +104,7 @@ class FileLikeBase(object):
expensive to simulate (e.g. compressed files). Note that any file
opened for both reading and writing must also support seeking.
"""
-
+
def __init__(self,bufsize=1024*64):
"""FileLikeBase Constructor.
@@ -121,8 +121,8 @@ class FileLikeBase(object):
self._rbuffer = None # data that's been read but not returned
self._wbuffer = None # data that's been given but not written
self._sbuffer = None # data between real & apparent file pos
- self._soffset = 0 # internal offset of file pointer
-
+ self._soffset = 0 # internal offset of file pointer
+
#
# The following five methods are the ones that subclasses are expected
# to implement. Carefully check their docstrings.
@@ -130,33 +130,33 @@ class FileLikeBase(object):
def _read(self,sizehint=-1):
"""Read approximately <sizehint> bytes from the file-like object.
-
+
This method is to be implemented by subclasses that wish to be
readable. It should read approximately <sizehint> bytes from the
file and return them as a string. If <sizehint> is missing or
less than or equal to zero, try to read all the remaining contents.
-
+
The method need not guarantee any particular number of bytes -
it may return more bytes than requested, or fewer. If needed the
size hint may be completely ignored. It may even return an empty
string if no data is yet available.
-
+
Because of this, the method must return None to signify that EOF
has been reached. The higher-level methods will never indicate EOF
until None has been read from _read(). Once EOF is reached, it
should be safe to call _read() again, immediately returning None.
"""
raise NotReadableError("Object not readable")
-
+
def _write(self,string,flushing=False):
"""Write the given string to the file-like object.
-
+
This method must be implemented by subclasses wishing to be writable.
It must attempt to write as much of the given data as possible to the
file, but need not guarantee that it is all written. It may return
None to indicate that all data was written, or return as a string any
data that could not be written.
-
+
If the keyword argument 'flushing' is true, it indicates that the
internal write buffers are being flushed, and *all* the given data
is expected to be written to the file. If unwritten data is returned
@@ -166,7 +166,7 @@ class FileLikeBase(object):
def _seek(self,offset,whence):
"""Set the file's internal position pointer, approximately.
-
+
This method should set the file's position to approximately 'offset'
bytes relative to the position specified by 'whence'. If it is
not possible to position the pointer exactly at the given offset,
@@ -234,15 +234,15 @@ class FileLikeBase(object):
if "+" in mstr:
return True
if "-" in mstr and "-" not in mode:
- return False
+ return False
if "r" in mode:
if "r" not in mstr:
- return False
+ return False
if "w" in mode:
if "w" not in mstr and "a" not in mstr:
return False
return True
-
+
def _assert_mode(self,mode,mstr=None):
"""Check whether the file may be accessed in the given mode.
@@ -265,7 +265,7 @@ class FileLikeBase(object):
if "w" not in mstr and "a" not in mstr:
raise NotWritableError("File not opened for writing")
return True
-
+
def flush(self):
"""Flush internal write buffer, if necessary."""
if self.closed:
@@ -280,7 +280,7 @@ class FileLikeBase(object):
leftover = self._write(buffered,flushing=True)
if leftover and not isinstance(leftover, int):
raise IOError("Could not flush write buffer.")
-
+
def close(self):
"""Flush write buffers and close the file.
@@ -304,7 +304,7 @@ class FileLikeBase(object):
def __exit__(self,exc_type,exc_val,exc_tb):
self.close()
return False
-
+
def next(self):
"""next() method complying with the iterator protocol.
@@ -315,7 +315,7 @@ class FileLikeBase(object):
if ln == b(""):
raise StopIteration()
return ln
-
+
def __iter__(self):
return self
@@ -402,7 +402,7 @@ class FileLikeBase(object):
if self._soffset:
pos = pos + self._soffset
return pos
-
+
def read(self,size=-1):
"""Read at most 'size' bytes from the file.
@@ -484,7 +484,7 @@ class FileLikeBase(object):
data = self._do_read(self._bufsize)
while data != b(""):
data = self._do_read(self._bufsize)
-
+
def readline(self,size=-1):
"""Read a line from the file, or at most <size> bytes."""
bits = []
@@ -515,11 +515,11 @@ class FileLikeBase(object):
bits[-1] = bits[-1][:indx]
self._rbuffer = extra + self._rbuffer
return b("").join(bits)
-
+
def readlines(self,sizehint=-1):
"""Return a list of all lines in the file."""
return [ln for ln in self]
-
+
def xreadlines(self):
"""Iterator over lines in the file - equivalent to iter(self)."""
return iter(self)
@@ -531,7 +531,7 @@ class FileLikeBase(object):
self._assert_mode("w-")
# If we were previously reading, ensure position is correct
if self._rbuffer is not None:
- self.seek(0,1)
+ self.seek(0, 1)
# If we're actually behind the apparent position, we must also
# write the data in the gap.
if self._sbuffer:
@@ -544,15 +544,17 @@ class FileLikeBase(object):
string = self._do_read(s) + string
except NotReadableError:
raise NotSeekableError("File not readable, could not complete simulation of seek")
- self.seek(0,0)
+ self.seek(0, 0)
if self._wbuffer:
string = self._wbuffer + string
leftover = self._write(string)
if leftover is None or isinstance(leftover, int):
self._wbuffer = b("")
+ return len(string) - (leftover or 0)
else:
self._wbuffer = leftover
-
+ return len(string) - len(leftover)
+
def writelines(self,seq):
"""Write a sequence of lines to the file."""
for ln in seq:
@@ -561,7 +563,7 @@ class FileLikeBase(object):
class FileWrapper(FileLikeBase):
"""Base class for objects that wrap a file-like object.
-
+
This class provides basic functionality for implementing file-like
objects that wrap another file-like object to alter its functionality
in some way. It takes care of house-keeping duties such as flushing
@@ -571,7 +573,7 @@ class FileWrapper(FileLikeBase):
By convention, the subclass's constructor should accept this as its
first argument and pass it to its superclass's constructor in the
same position.
-
+
This class provides a basic implementation of _read() and _write()
which just calls read() and write() on the wrapped object. Subclasses
will probably want to override these.
@@ -581,10 +583,10 @@ class FileWrapper(FileLikeBase):
def __init__(self,wrapped_file,mode=None):
"""FileWrapper constructor.
-
+
'wrapped_file' must be a file-like object, which is to be wrapped
in another file-like object to provide additional functionality.
-
+
If given, 'mode' must be the access mode string under which
the wrapped file is to be accessed. If not given or None, it
is looked up on the wrapped file if possible. Otherwise, it
@@ -660,7 +662,7 @@ class FileWrapper(FileLikeBase):
return data
def _write(self,string,flushing=False):
- return self.wrapped_file.write(string)
+ self.wrapped_file.write(string)
def _seek(self,offset,whence):
self.wrapped_file.seek(offset,whence)
@@ -669,7 +671,7 @@ class FileWrapper(FileLikeBase):
return self.wrapped_file.tell()
def _truncate(self,size):
- return self.wrapped_file.truncate(size)
+ return self.wrapped_file.truncate(size)
class StringIO(FileWrapper):