diff --git a/fs/errors.py b/fs/errors.py index 3ed4fe46..47fd3ce9 100644 --- a/fs/errors.py +++ b/fs/errors.py @@ -11,6 +11,8 @@ from __future__ import unicode_literals from __future__ import print_function +import functools + import six from six import text_type @@ -90,8 +92,24 @@ class CreateFailed(FSError): """Filesystem could not be created. """ - default_message = "unable to create filesystem" - + default_message = "unable to create filesystem, {details}" + + @classmethod + def catch_all(cls, func): + @functools.wraps(func) + def new_func(*args, **kwargs): + try: + return func(*args, **kwargs) + except cls: + raise + except Exception as e: + raise cls(exc=e) + return new_func + + def __init__(self, msg=None, exc=None): + self._msg = msg or self.default_message + self.details = '' if exc is None else text_type(exc) + self.exc = exc class PathError(FSError): """Base exception for errors to do with a path string. diff --git a/fs/osfs.py b/fs/osfs.py index 09cf2bf5..f110eb00 100644 --- a/fs/osfs.py +++ b/fs/osfs.py @@ -88,13 +88,12 @@ def __init__(self, os.makedirs(_root_path, mode=create_mode) except OSError as error: raise errors.CreateFailed( - 'unable to create {} ({})'.format(root_path, error) + 'unable to create {} ({})'.format(root_path, error), + error, ) else: if not os.path.isdir(_root_path): - raise errors.CreateFailed( - 'root path does not exist' - ) + raise errors.CreateFailed('root path does not exist') _meta = self._meta = { 'case_insensitive': os.path.normcase('Aa') != 'aa', diff --git a/fs/tarfs.py b/fs/tarfs.py index 24f85a75..bde76c54 100644 --- a/fs/tarfs.py +++ b/fs/tarfs.py @@ -198,6 +198,7 @@ class ReadTarFS(FS): tarfile.LNKTYPE: ResourceType.symlink, } + @errors.CreateFailed.catch_all def __init__(self, file, encoding='utf-8'): super(ReadTarFS, self).__init__() self._file = file diff --git a/fs/zipfs.py b/fs/zipfs.py index 367597f6..9588e5df 100644 --- a/fs/zipfs.py +++ b/fs/zipfs.py @@ -241,6 +241,7 @@ class ReadZipFS(FS): 'virtual': False, } + @errors.CreateFailed.catch_all def __init__(self, file, encoding='utf-8'): super(ReadZipFS, self).__init__() self._file = file diff --git a/tests/test_errors.py b/tests/test_errors.py index b27542f3..4fad45b8 100644 --- a/tests/test_errors.py +++ b/tests/test_errors.py @@ -5,6 +5,7 @@ from six import text_type from fs import errors +from fs.errors import CreateFailed class TestErrors(unittest.TestCase): @@ -24,3 +25,22 @@ def test_unsupported(self): text_type(err), "not supported" ) + + +class TestCreateFailed(unittest.TestCase): + + def test_catch_all(self): + + errors = (ZeroDivisionError, ValueError, CreateFailed) + + @CreateFailed.catch_all + def test(x): + raise errors[x] + + for index, exc in enumerate(errors): + try: + test(index) + except Exception as e: + self.assertIsInstance(e, CreateFailed) + if e.exc is not None: + self.assertNotIsInstance(e.exc, CreateFailed)