Commit 8fcf4df8 by rfkelly0

add module "fs.filelike" with utils for building file-like objects.

This is a local copy of the guts of my "filelike" module, re-licensed under
the MIT license.

This commit also uses it to fix a few edge-cases in various filesystem
implementations (e.g. truncating StringIO objects).
parent 739272ca
......@@ -57,4 +57,6 @@
* Added utils.isdir(fs,path,info) and utils.isfile(fs,path,info); these
can often determine whether a path is a file or directory by inspecting
the info dict and avoid an additional query to the filesystem.
* Added utility module 'fs.filelike' with some helpers for building and
manipulating file-like objects.
......@@ -12,15 +12,13 @@ Contributed under the terms of the BSD License:
http://www.opensource.org/licenses/bsd-license.php
"""
from struct import pack, unpack
from fs.base import *
from fs.memoryfs import MemoryFS
from fs.contrib.bigfs.subrangefile import SubrangeFile
from fs.filelike import StringIO
from struct import pack, unpack
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
from fs.contrib.bigfs.subrangefile import SubrangeFile
class BIGEntry:
def __init__(self, filename, offset, storedSize, isCompressed, realSize):
......
......@@ -29,7 +29,6 @@ import stat as statinfo
import time
import SocketServer as sockserv
import threading
from StringIO import StringIO
import paramiko
......@@ -37,6 +36,7 @@ from fs.base import flags_to_mode
from fs.path import *
from fs.errors import *
from fs.local_functools import wraps
from fs.filelike import StringIO
# Default host key used by BaseSFTPServer
......
This diff is collapsed. Click to expand it.
......@@ -29,11 +29,6 @@ import re
from socket import error as socket_error
from fs.local_functools import wraps
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
import time
import sys
......
......@@ -16,11 +16,7 @@ from fs.path import iteratepath, pathsplit, normpath
from fs.base import *
from fs.errors import *
from fs import _thread_synchronize_default
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
from fs.filelike import StringIO
def _check_mode(mode, mode_chars):
......
......@@ -3,9 +3,10 @@ fs.multifs
==========
A MultiFS is a filesytem composed of a sequence of other filesystems, where
the directory structure of each filesystem is overlaid over the previous filesystem.
When you attempt to access a file from the MultiFS it will try each 'child'
FS in order, until it either finds a path that exists or raises a ResourceNotFoundError.
the directory structure of each filesystem is overlaid over the previous
filesystem. When you attempt to access a file from the MultiFS it will try
each 'child' FS in order, until it either finds a path that exists or raises a
ResourceNotFoundError.
One use for such a filesystem would be to selectively override a set of files,
to customize behaviour. For example, to create a filesystem that could be used
......@@ -61,11 +62,11 @@ from fs.errors import ResourceNotFoundError
class MultiFS(FS):
"""A MultiFS is a filesystem that delegates to a sequence of other filesystems.
Operations on the MultiFS will try each 'child' filesystem in order, until it
succeeds. In effect, creating a filesystem that combines the files and dirs of
its children.
"""A filesystem that delegates to a sequence of other filesystems.
Operations on the MultiFS will try each 'child' filesystem in order, until
it succeeds. In effect, creating a filesystem that combines the files and
dirs of its children.
"""
def __init__(self):
......
......@@ -14,17 +14,7 @@ from fs.base import *
from fs.errors import *
from fs.path import *
from StringIO import StringIO
if hasattr(StringIO,"__exit__"):
class StringIO(StringIO):
pass
else:
class StringIO(StringIO):
def __enter__(self):
return self
def __exit__(self,exc_type,exc_value,traceback):
self.close()
return False
from fs.filelike import StringIO
def re_raise_faults(func):
......@@ -173,14 +163,19 @@ class RPCFS(FS):
f.seek(0,2)
oldflush = f.flush
oldclose = f.close
oldtruncate = f.truncate
def newflush():
oldflush()
self.proxy.set_contents(path,xmlrpclib.Binary(f.getvalue()))
def newclose():
f.flush()
oldclose()
def newtruncate(size=None):
oldtruncate(size)
f.flush()
f.flush = newflush
f.close = newclose
f.truncate = newtruncate
return f
def exists(self, path):
......
......@@ -36,7 +36,7 @@ class RemoteTempFS(TempFS):
f = None
return RemoteFileBuffer(self, path, mode, f,
write_on_flush=write_on_flush)
write_on_flush=write_on_flush)
def setcontents(self, path, content):
f = super(RemoteTempFS, self).open(path, 'wb')
......@@ -109,7 +109,7 @@ class TestRemoteFileBuffer(unittest.TestCase, FSTestCases, ThreadingTestCases):
f = self.fs.open('test.txt', 'rb')
self.assertEquals(f.read(10), contents[:10])
f.file.seek(0, SEEK_END)
f.wrapped_file.seek(0, SEEK_END)
self.assertEquals(f._rfile.tell(), 10)
f.seek(20)
self.assertEquals(f.tell(), 20)
......@@ -136,9 +136,9 @@ class TestRemoteFileBuffer(unittest.TestCase, FSTestCases, ThreadingTestCases):
f._rfile.seek(len(contents[:-5]))
# Write 10 new characters (will make contents longer for 5 chars)
f.write(u'1234567890')
f.flush()
# We are on the end of file (and buffer not serve anything anymore)
self.assertEquals(f.read(), '')
f.close()
self.fakeOn()
......
......@@ -11,15 +11,11 @@ import datetime
from fs.base import *
from fs.path import *
from fs.errors import *
from fs.filelike import StringIO
from zipfile import ZipFile, ZIP_DEFLATED, ZIP_STORED, BadZipfile, LargeZipFile
from memoryfs import MemoryFS
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
import tempfs
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment