Commit 991cf3e8 by willmcgugan

More work on xattr support

parent bd63700f
...@@ -36,6 +36,7 @@ error_msgs = { ...@@ -36,6 +36,7 @@ error_msgs = {
"GETSIZE_FAILED" : "Unable to retrieve size of resource: %(path)s", "GETSIZE_FAILED" : "Unable to retrieve size of resource: %(path)s",
"COPYFILE_FAILED" : "Unable to copy file: %(path)s", "COPYFILE_FAILED" : "Unable to copy file: %(path)s",
"READ_FAILED" : "Unable to read from file: %(path)s", "READ_FAILED" : "Unable to read from file: %(path)s",
"XATTR_FAILED" : "Unable to access extended-attribute: %(path)s",
# NoSysPathError # NoSysPathError
"NO_SYS_PATH" : "No mapping to OS filesytem: %(path)s,", "NO_SYS_PATH" : "No mapping to OS filesytem: %(path)s,",
...@@ -621,10 +622,10 @@ class FS(object): ...@@ -621,10 +622,10 @@ class FS(object):
def _get_attr_path(self, path): def _get_attr_path(self, path):
if self.isdir(path): if self.isdir(path):
return pathjoin(path, '.dirattrs') return pathjoin(path, '.dirxattrs')
else: else:
dir_path, file_path = pathsplit(path) dir_path, file_path = pathsplit(path)
return pathjoin(path, '.attrs.'+file_path) return pathjoin(dir_path, '.xattrs.'+file_path)
def _get_attr_dict(self, path): def _get_attr_dict(self, path):
attr_path = self._get_attr_path(path) attr_path = self._get_attr_path(path)
...@@ -633,27 +634,38 @@ class FS(object): ...@@ -633,27 +634,38 @@ class FS(object):
else: else:
return {} return {}
def _set_attr_dict(self, path, attrs): def _set_attr_dict(self, path, attrs):
attr_path = self._get_attr_path(path) attr_path = self._get_attr_path(path)
self.setcontents(path, self.pickle.dumps(attrs)) self.setcontents(self._get_attr_path(path), pickle.dumps(attrs))
def setattr(self, path, key, value): def setxattr(self, path, key, value):
attrs = self._get_attr_dict(path) attrs = self._get_attr_dict(path)
attrs[key] = value attrs[key] = value
self._set_attr_dict(path, attrs) self._set_attr_dict(path, attrs)
def getattr(self, path, key, default): def getxattr(self, path, key, default):
return self._get_attr_dict(path).get(key, default) attrs = self._get_attr_dict(path)
return attrs.get(key, default)
def removeattr(self, path, key): def removexattr(self, path, key):
attrs = self._get_attrs() attrs = self._get_attr_dict(path)
if path in self._get_attrs(): try:
del attrs[key] del attrs[key]
except KeyError:
pass
self._set_attr_dict(path, attrs)
def listattrs(self, path): def listxattrs(self, path):
attrs = self._get_attr_dict(path)
return self._get_attr_dict(path).keys() return self._get_attr_dict(path).keys()
def updatexattrs(self, path, update_dict):
d = self._get_attr_dict()
d.update( dict([(k, v) for k,v in update_dict.iteritems()]) )
self.set_attr_dict(self, path, d)
def getxattrs(self, path):
return dict( [(k, self.getxattr(path, k)) for k in self.listxattrs(path)] )
def movedir(self, src, dst, overwrite=False, ignore_errors=False, chunk_size=16384): def movedir(self, src, dst, overwrite=False, ignore_errors=False, chunk_size=16384):
"""Moves a directory from one location to another. """Moves a directory from one location to another.
......
...@@ -3,6 +3,11 @@ ...@@ -3,6 +3,11 @@
from base import * from base import *
from helpers import * from helpers import *
try:
import xattr
except ImportError:
xattr = None
class OSFS(FS): class OSFS(FS):
"""The most basic of filesystems. Simply shadows the underlaying filesytem """The most basic of filesystems. Simply shadows the underlaying filesytem
...@@ -87,7 +92,7 @@ class OSFS(FS): ...@@ -87,7 +92,7 @@ class OSFS(FS):
raise OperationFailedError("MAKEDIR_FAILED", path) raise OperationFailedError("MAKEDIR_FAILED", path)
else: else:
raise OperationFailedError("MAKEDIR_FAILED", path) raise OperationFailedError("MAKEDIR_FAILED", path)
except OSError, e: except OSError, e:
if e.errno == 17: if e.errno == 17:
return return
...@@ -171,39 +176,122 @@ class OSFS(FS): ...@@ -171,39 +176,122 @@ class OSFS(FS):
return stats.st_size return stats.st_size
def setxattr(self, path, key, value):
self._lock.acquire()
try:
if xattr is None:
return FS.setxattr(self, path, key, value)
try:
xattr.xattr(self.getsyspath(path))[key]=value
except IOError, e:
if e.errno == 95:
return FS.setxattr(self, path, key, value)
else:
raise OperationFailedError('XATTR_FAILED', path, details=e)
finally:
self._lock.release()
def getxattr(self, path, key, default=None):
self._lock.acquire()
try:
if xattr is None:
return FS.getxattr(self, path, key, default)
try:
return xattr.xattr(self.getsyspath(path)).get(key)
except IOError, e:
if e.errno == 95:
return FS.getxattr(self, path, key, default)
else:
raise OperationFailedError('XATTR_FAILED', path, details=e)
finally:
self._lock.release()
def removexattr(self, path, key):
self._lock.acquire()
try:
if xattr is None:
return FS.removexattr(self, path, key)
try:
del xattr.xattr(self.getsyspath(path))[key]
except KeyError:
pass
except IOError, e:
if e.errono == 95:
return FS.removexattr(self, path, key)
else:
raise OperationFailedError('XATTR_FAILED', path, details=e)
finally:
self._lock.release()
def listxattrs(self, path):
self._lock.acquire()
try:
if xattr is None:
return FS.listxattrs(self, path)
try:
return xattr.xattr(self.getsyspath(path)).keys()
except IOError, e:
if errono == 95:
return FS.listxattrs(self, path)
else:
raise OperationFailedError('XATTR_FAILED', path, details=e)
finally:
self._lock.release()
if __name__ == "__main__":
osfs = OSFS("~/projects")
for p in osfs.walk("tagging-trunk", search='depth'):
print p
import browsewin
browsewin.browse(osfs)
print_fs(osfs)
#print osfs.listdir("/projects/fs")
#sub_fs = osfs.open_dir("projects/")
#print sub_fs
#sub_fs.open('test.txt')
#print sub_fs.listdir(dirs_only=True)
#print sub_fs.listdir()
#print_fs(sub_fs, max_levels=2)
#for f in osfs.listdir():
# print f
#print osfs.listdir('projects', dirs_only=True, wildcard="d*")
#print_fs(osfs, 'projects/') if __name__ == "__main__":
print pathjoin('/', 'a')
print pathjoin('a/b/c', '../../e/f') osfs = OSFS('testfs')
#a = xattr.xattr('/home/will/projects/pyfilesystem/fs/testfs/test.txt')
#a['user.comment'] = 'world'
#print xattr.xattr('/home/will/projects/pyfilesystem/fs/testfs/test.txt').keys()
print osfs.listxattrs('test.txt')
osfs.removexattr('test.txt', 'user.foo')
#print osfs.listxattrs('test.txt')
osfs.setxattr('test.txt', 'user.foo', 'bar')
print osfs.getxattr('test.txt', 'user.foo')
print osfs.listxattrs('test.txt')
print osfs.getxattrs('test.txt')
#
#osfs = OSFS("~/projects")
#
#
##for p in osfs.walk("tagging-trunk", search='depth'):
## print p
#
#import browsewin
#browsewin.browse(osfs)
#
#print_fs(osfs)
#
##print osfs.listdir("/projects/fs")
#
##sub_fs = osfs.open_dir("projects/")
#
##print sub_fs
#
##sub_fs.open('test.txt')
#
##print sub_fs.listdir(dirs_only=True)
##print sub_fs.listdir()
##print_fs(sub_fs, max_levels=2)
#
##for f in osfs.listdir():
## print f
#
##print osfs.listdir('projects', dirs_only=True, wildcard="d*")
#
##print_fs(osfs, 'projects/')
#
#print pathjoin('/', 'a')
#
#print pathjoin('a/b/c', '../../e/f')
...@@ -145,7 +145,7 @@ class TestOSFS(unittest.TestCase): ...@@ -145,7 +145,7 @@ class TestOSFS(unittest.TestCase):
self.fs = osfs.OSFS(self.temp_dir) self.fs = osfs.OSFS(self.temp_dir)
print "Temp dir is", self.temp_dir print "Temp dir is", self.temp_dir
def tearDown(self): def tearDown(self):
shutil.rmtree(self.temp_dir) shutil.rmtree(self.temp_dir)
def check(self, p): def check(self, p):
...@@ -349,7 +349,7 @@ class TestOSFS(unittest.TestCase): ...@@ -349,7 +349,7 @@ class TestOSFS(unittest.TestCase):
self.assert_(check("a/2.txt")) self.assert_(check("a/2.txt"))
self.assert_(check("a/3.txt")) self.assert_(check("a/3.txt"))
self.assert_(check("a/foo/bar/baz.txt")) self.assert_(check("a/foo/bar/baz.txt"))
def test_copyfile(self): def test_copyfile(self):
check = self.check check = self.check
...@@ -420,7 +420,7 @@ class TestOSFS(unittest.TestCase): ...@@ -420,7 +420,7 @@ class TestOSFS(unittest.TestCase):
self.assert_(check("b/2.txt")) self.assert_(check("b/2.txt"))
self.assert_(check("b/3.txt")) self.assert_(check("b/3.txt"))
self.assert_(check("b/foo/bar/baz.txt")) self.assert_(check("b/foo/bar/baz.txt"))
def test_copydir_with_hidden(self): def test_copydir_with_hidden(self):
check = self.check check = self.check
...@@ -489,7 +489,7 @@ class TestOSFS(unittest.TestCase): ...@@ -489,7 +489,7 @@ class TestOSFS(unittest.TestCase):
for s in test_strings: for s in test_strings:
f5.write(s+"\n") f5.write(s+"\n")
f5.close() f5.close()
f6 = self.fs.open("c.txt", "rb") f6 = self.fs.open("c.txt", "rb")
for s, t in zip(f6, test_strings): for s, t in zip(f6, test_strings):
self.assertEqual(s, t+"\n") self.assertEqual(s, t+"\n")
f6.close() f6.close()
...@@ -504,7 +504,7 @@ class TestOSFS(unittest.TestCase): ...@@ -504,7 +504,7 @@ class TestOSFS(unittest.TestCase):
word = f7.read(7) word = f7.read(7)
self.assertEqual(word, "complex") self.assertEqual(word, "complex")
f7.close() f7.close()
self.assertEqual(self.fs.getcontents("a.txt"), all_strings) self.assertEqual(self.fs.getcontents("a.txt"), all_strings)
...@@ -753,7 +753,7 @@ class TestS3FS(TestOSFS): ...@@ -753,7 +753,7 @@ class TestS3FS(TestOSFS):
code = compile(code,"<string>",'exec') code = compile(code,"<string>",'exec')
self.assertRaises(ValueError,eval,code,globals(),locals()) self.assertRaises(ValueError,eval,code,globals(),locals())
self.assertEquals(self.fs.getcontents('f.txt'),contents) self.assertEquals(self.fs.getcontents('f.txt'),contents)
import rpcfs import rpcfs
......
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