Commit 8d1e513f by rfkelly0

more robustness (particularly cross-thread) for SimulateXAttr wrapper

parent 8697c1f5
...@@ -180,6 +180,8 @@ def convert_os_errors(func): ...@@ -180,6 +180,8 @@ def convert_os_errors(func):
raise ResourceInvalidError(path,opname=opname,details=e) raise ResourceInvalidError(path,opname=opname,details=e)
if e.errno == errno.EINVAL: if e.errno == errno.EINVAL:
raise ResourceInvalidError(path,opname=opname,details=e) raise ResourceInvalidError(path,opname=opname,details=e)
if e.errno == errno.EOPNOTSUPP:
raise UnsupportedError(opname,details=e)
# Sometimes windows gives some random errors... # Sometimes windows gives some random errors...
if sys.platform == "win32": if sys.platform == "win32":
if e.errno in (13,): if e.errno in (13,):
......
...@@ -196,19 +196,31 @@ class WrapFS(FS): ...@@ -196,19 +196,31 @@ class WrapFS(FS):
@rewrite_errors @rewrite_errors
def getxattr(self,path,name,default=None): def getxattr(self,path,name,default=None):
return self.wrapped_fs.getxattr(self._encode(path),name,default) try:
return self.wrapped_fs.getxattr(self._encode(path),name,default)
except AttributeError:
raise UnsupportedError("getxattr")
@rewrite_errors @rewrite_errors
def setxattr(self,path,name,value): def setxattr(self,path,name,value):
return self.wrapped_fs.setxattr(self._encode(path),name,value) try:
return self.wrapped_fs.setxattr(self._encode(path),name,value)
except AttributeError:
raise UnsupportedError("setxattr")
@rewrite_errors @rewrite_errors
def delxattr(self,path,name): def delxattr(self,path,name):
return self.wrapped_fs.delxattr(self._encode(path),name) try:
return self.wrapped_fs.delxattr(self._encode(path),name)
except AttributeError:
raise UnsupportedError("delxattr")
@rewrite_errors @rewrite_errors
def listxattrs(self,path): def listxattrs(self,path):
return self.wrapped_fs.listxattrs(self._encode(path)) try:
return self.wrapped_fs.listxattrs(self._encode(path))
except AttributeError:
raise UnsupportedError("listxattrs")
def __getattr__(self,attr): def __getattr__(self,attr):
return getattr(self.wrapped_fs,attr) return getattr(self.wrapped_fs,attr)
......
...@@ -31,6 +31,7 @@ except ImportError: ...@@ -31,6 +31,7 @@ except ImportError:
from fs.path import * from fs.path import *
from fs.errors import * from fs.errors import *
from fs.wrapfs import WrapFS from fs.wrapfs import WrapFS
from fs.base import synchronize
def ensure_xattrs(fs): def ensure_xattrs(fs):
...@@ -42,9 +43,9 @@ def ensure_xattrs(fs): ...@@ -42,9 +43,9 @@ def ensure_xattrs(fs):
""" """
try: try:
# This attr doesn't have to exist, None should be returned by default # This attr doesn't have to exist, None should be returned by default
fs.getxattr("/","testingx-xattr") fs.getxattr("/","testing-xattr")
return fs return fs
except Exception: except (AttributeError,UnsupportedError):
return SimulateXAttr(fs) return SimulateXAttr(fs)
...@@ -52,7 +53,7 @@ class SimulateXAttr(WrapFS): ...@@ -52,7 +53,7 @@ class SimulateXAttr(WrapFS):
"""FS wrapper class that simulates xattr support. """FS wrapper class that simulates xattr support.
The following methods are supplied for manipulating extended attributes: The following methods are supplied for manipulating extended attributes:
* xattrs: list all extended attribute names for a path * listxattrs: list all extended attribute names for a path
* getxattr: get an xattr of a path by name * getxattr: get an xattr of a path by name
* setxattr: set an xattr of a path by name * setxattr: set an xattr of a path by name
* delxattr: delete an xattr of a path by name * delxattr: delete an xattr of a path by name
...@@ -83,7 +84,10 @@ class SimulateXAttr(WrapFS): ...@@ -83,7 +84,10 @@ class SimulateXAttr(WrapFS):
"""Retrieve the xattr dictionary for the given path.""" """Retrieve the xattr dictionary for the given path."""
attr_path = self._get_attr_path(path) attr_path = self._get_attr_path(path)
if self.wrapped_fs.exists(attr_path): if self.wrapped_fs.exists(attr_path):
return pickle.loads(self.wrapped_fs.getcontents(attr_path)) try:
return pickle.loads(self.wrapped_fs.getcontents(attr_path))
except EOFError:
return {}
else: else:
return {} return {}
...@@ -92,6 +96,7 @@ class SimulateXAttr(WrapFS): ...@@ -92,6 +96,7 @@ class SimulateXAttr(WrapFS):
attr_path = self._get_attr_path(path) attr_path = self._get_attr_path(path)
self.wrapped_fs.setcontents(attr_path, pickle.dumps(attrs)) self.wrapped_fs.setcontents(attr_path, pickle.dumps(attrs))
@synchronize
def setxattr(self, path, key, value): def setxattr(self, path, key, value):
"""Set an extended attribute on the given path.""" """Set an extended attribute on the given path."""
if not self.exists(path): if not self.exists(path):
...@@ -100,6 +105,7 @@ class SimulateXAttr(WrapFS): ...@@ -100,6 +105,7 @@ class SimulateXAttr(WrapFS):
attrs[key] = str(value) attrs[key] = str(value)
self._set_attr_dict(path, attrs) self._set_attr_dict(path, attrs)
@synchronize
def getxattr(self, path, key, default=None): def getxattr(self, path, key, default=None):
"""Retrieve an extended attribute for the given path.""" """Retrieve an extended attribute for the given path."""
if not self.exists(path): if not self.exists(path):
...@@ -107,6 +113,7 @@ class SimulateXAttr(WrapFS): ...@@ -107,6 +113,7 @@ class SimulateXAttr(WrapFS):
attrs = self._get_attr_dict(path) attrs = self._get_attr_dict(path)
return attrs.get(key, default) return attrs.get(key, default)
@synchronize
def delxattr(self, path, key): def delxattr(self, path, key):
if not self.exists(path): if not self.exists(path):
raise ResourceNotFoundError(path) raise ResourceNotFoundError(path)
......
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