Commit dd808d70 by willmcgugan

implemented auto closing for multi/mount fs

parent bdcfff98
...@@ -51,7 +51,7 @@ from fs import _thread_synchronize_default ...@@ -51,7 +51,7 @@ from fs import _thread_synchronize_default
class DirMount(object): class DirMount(object):
def __init__(self, path, fs): def __init__(self, path, fs):
self.path = path self.path = path
self.fs = fs self.fs = fs
def __str__(self): def __str__(self):
return "Mount point: <%s,%s>" % (self.path,self.fs,) return "Mount point: <%s,%s>" % (self.path,self.fs,)
...@@ -71,7 +71,6 @@ class FileMount(object): ...@@ -71,7 +71,6 @@ class FileMount(object):
class MountFS(FS): class MountFS(FS):
"""A filesystem that delegates to other filesystems.""" """A filesystem that delegates to other filesystems."""
_meta = { 'virtual': True, _meta = { 'virtual': True,
'read_only' : False, 'read_only' : False,
'unicode_paths' : True, 'unicode_paths' : True,
...@@ -81,9 +80,10 @@ class MountFS(FS): ...@@ -81,9 +80,10 @@ class MountFS(FS):
DirMount = DirMount DirMount = DirMount
FileMount = FileMount FileMount = FileMount
def __init__(self, thread_synchronize=_thread_synchronize_default): def __init__(self, auto_close=True, thread_synchronize=_thread_synchronize_default):
self.auto_close = auto_close
super(MountFS, self).__init__(thread_synchronize=thread_synchronize) super(MountFS, self).__init__(thread_synchronize=thread_synchronize)
self.mount_tree = PathMap() self.mount_tree = PathMap()
def __str__(self): def __str__(self):
return "<%s [%s]>" % (self.__class__.__name__,self.mount_tree.items(),) return "<%s [%s]>" % (self.__class__.__name__,self.mount_tree.items(),)
...@@ -121,6 +121,16 @@ class MountFS(FS): ...@@ -121,6 +121,16 @@ class MountFS(FS):
else: else:
return self, "/", path return self, "/", path
@synchronize
def close(self):
# Explicitly closes children if requested
if self.auto_close:
for mount in self.mount_tree.itervalues():
mount.fs.close()
# Free references (which may incidently call the close method of the child filesystems)
self.mount_tree.clear()
super(MountFS, self).close()
def getsyspath(self, path, allow_none=False): def getsyspath(self, path, allow_none=False):
fs, _mount_path, delegate_path = self._delegate(path) fs, _mount_path, delegate_path = self._delegate(path)
if fs is self or fs is None: if fs is self or fs is None:
...@@ -341,7 +351,6 @@ class MountFS(FS): ...@@ -341,7 +351,6 @@ class MountFS(FS):
if object is None: if object is None:
raise ResourceNotFoundError(src) raise ResourceNotFoundError(src)
# TODO!
raise UnsupportedError("rename resource", path=src) raise UnsupportedError("rename resource", path=src)
@synchronize @synchronize
...@@ -385,7 +394,7 @@ class MountFS(FS): ...@@ -385,7 +394,7 @@ class MountFS(FS):
"""Mounts a host FS object on a given path. """Mounts a host FS object on a given path.
:param path: A path within the MountFS :param path: A path within the MountFS
:param fs: A filesystem object to mount :param fs: A filesystem object to mount
""" """
self.mount_tree[path] = MountFS.DirMount(path, fs) self.mount_tree[path] = MountFS.DirMount(path, fs)
......
...@@ -83,12 +83,18 @@ class MultiFS(FS): ...@@ -83,12 +83,18 @@ class MultiFS(FS):
'case_insensitive_paths' : False 'case_insensitive_paths' : False
} }
def __init__(self): def __init__(self, auto_close=True):
"""
:param auto_close: If True the child filesystems will be closed when the MultiFS is closed
"""
super(MultiFS, self).__init__(thread_synchronize=_thread_synchronize_default) super(MultiFS, self).__init__(thread_synchronize=_thread_synchronize_default)
self.auto_close = auto_close
self.fs_sequence = [] self.fs_sequence = []
self.fs_lookup = {} self.fs_lookup = {}
self.write_fs = None self.write_fs = None
@synchronize @synchronize
def __str__(self): def __str__(self):
...@@ -100,7 +106,20 @@ class MultiFS(FS): ...@@ -100,7 +106,20 @@ class MultiFS(FS):
def __unicode__(self): def __unicode__(self):
return u"<MultiFS: %s>" % ", ".join(unicode(fs) for fs in self.fs_sequence) return u"<MultiFS: %s>" % ", ".join(unicode(fs) for fs in self.fs_sequence)
@synchronize
def close(self):
# Explicitly close if requested
if self.auto_close:
for fs in self.fs_sequence:
fs.close()
if self.write_fs is not None:
self.write_fs.close()
# Discard any references
del self.fs_sequence[:]
self.fs_lookup.clear()
self.write_fs = None
super(MultiFS, self).close()
@synchronize @synchronize
def addfs(self, name, fs, write=False): def addfs(self, name, fs, write=False):
"""Adds a filesystem to the MultiFS. """Adds a filesystem to the MultiFS.
......
from fs.mountfs import MountFS
from fs.memoryfs import MemoryFS
import unittest
class TestMultiFS(unittest.TestCase):
def test_auto_close(self):
"""Test MultiFS auto close is working"""
multi_fs = MountFS()
m1 = MemoryFS()
m2 = MemoryFS()
multi_fs.mount('/m1', m1)
multi_fs.mount('/m2', m2)
self.assert_(not m1.closed)
self.assert_(not m2.closed)
multi_fs.close()
self.assert_(m1.closed)
self.assert_(m2.closed)
def test_no_auto_close(self):
"""Test MultiFS auto close can be disabled"""
multi_fs = MountFS(auto_close=False)
m1 = MemoryFS()
m2 = MemoryFS()
multi_fs.mount('/m1', m1)
multi_fs.mount('/m2', m2)
self.assert_(not m1.closed)
self.assert_(not m2.closed)
multi_fs.close()
self.assert_(not m1.closed)
self.assert_(not m2.closed)
from fs.multifs import MultiFS
from fs.memoryfs import MemoryFS
import unittest
class TestMultiFS(unittest.TestCase):
def test_auto_close(self):
"""Test MultiFS auto close is working"""
multi_fs = MultiFS()
m1 = MemoryFS()
m2 = MemoryFS()
multi_fs.addfs('m1', m1)
multi_fs.addfs('m2', m2)
self.assert_(not m1.closed)
self.assert_(not m2.closed)
multi_fs.close()
self.assert_(m1.closed)
self.assert_(m2.closed)
def test_no_auto_close(self):
"""Test MultiFS auto close can be disables"""
multi_fs = MultiFS(auto_close=False)
m1 = MemoryFS()
m2 = MemoryFS()
multi_fs.addfs('m1', m1)
multi_fs.addfs('m2', m2)
self.assert_(not m1.closed)
self.assert_(not m2.closed)
multi_fs.close()
self.assert_(not m1.closed)
self.assert_(not m2.closed)
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