From a34807bfc65331da4b3713a619836726aefb50ab Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Thu, 8 Mar 2018 14:29:36 +0100 Subject: [PATCH 1/3] Allow wrapping exceptions in `CreateFailed` --- fs/errors.py | 17 +++++++++++++++++ fs/osfs.py | 12 +++++++----- tests/test_errors.py | 20 ++++++++++++++++++++ 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/fs/errors.py b/fs/errors.py index 3ed4fe46..be44e2d3 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 @@ -92,6 +94,21 @@ class CreateFailed(FSError): default_message = "unable to create filesystem" + @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: + six.raise_from(cls(exc=e), None) + return new_func + + def __init__(self, msg=None, exc=None): + self._msg = msg or self.default_message + 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..d04241bd 100644 --- a/fs/osfs.py +++ b/fs/osfs.py @@ -87,14 +87,16 @@ def __init__(self, if not os.path.isdir(_root_path): os.makedirs(_root_path, mode=create_mode) except OSError as error: - raise errors.CreateFailed( - 'unable to create {} ({})'.format(root_path, error) + six.raise_from( + errors.CreateFailed( + 'unable to create {} ({})'.format(root_path, error), + error, + ), + None, ) 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/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) From 7a624dc7c22b985e77cb9e9f3f74d039288c85f0 Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Thu, 8 Mar 2018 14:45:11 +0100 Subject: [PATCH 2/3] Make sure `ReadZipFS` and `ReadTarFS` raise CreateFailed --- fs/errors.py | 2 +- fs/osfs.py | 9 +++------ fs/tarfs.py | 1 + fs/zipfs.py | 1 + 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/fs/errors.py b/fs/errors.py index be44e2d3..a2331e9b 100644 --- a/fs/errors.py +++ b/fs/errors.py @@ -103,7 +103,7 @@ def new_func(*args, **kwargs): except cls: raise except Exception as e: - six.raise_from(cls(exc=e), None) + raise cls(exc=e) return new_func def __init__(self, msg=None, exc=None): diff --git a/fs/osfs.py b/fs/osfs.py index d04241bd..f110eb00 100644 --- a/fs/osfs.py +++ b/fs/osfs.py @@ -87,12 +87,9 @@ def __init__(self, if not os.path.isdir(_root_path): os.makedirs(_root_path, mode=create_mode) except OSError as error: - six.raise_from( - errors.CreateFailed( - 'unable to create {} ({})'.format(root_path, error), - error, - ), - None, + raise errors.CreateFailed( + 'unable to create {} ({})'.format(root_path, error), + error, ) else: if not os.path.isdir(_root_path): 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 From 138ce35da8b5a3285b5fbdefe86d0a4271df0ca2 Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Thu, 8 Mar 2018 14:46:31 +0100 Subject: [PATCH 3/3] Show error message of wrapped exception in `CreateFailed` --- fs/errors.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/errors.py b/fs/errors.py index a2331e9b..47fd3ce9 100644 --- a/fs/errors.py +++ b/fs/errors.py @@ -92,7 +92,7 @@ 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): @@ -108,6 +108,7 @@ def new_func(*args, **kwargs): 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):