Skip to content

Commit 608fd32

Browse files
althonoswillmcgugan
authored andcommitted
Allow wrapping exceptions in CreateFailed (#148)
* Allow wrapping exceptions in `CreateFailed` * Make sure `ReadZipFS` and `ReadTarFS` raise CreateFailed * Show error message of wrapped exception in `CreateFailed`
1 parent 9b10eeb commit 608fd32

File tree

5 files changed

+45
-6
lines changed

5 files changed

+45
-6
lines changed

fs/errors.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
from __future__ import unicode_literals
1212
from __future__ import print_function
1313

14+
import functools
15+
1416
import six
1517
from six import text_type
1618

@@ -90,8 +92,24 @@ class CreateFailed(FSError):
9092
"""Filesystem could not be created.
9193
"""
9294

93-
default_message = "unable to create filesystem"
94-
95+
default_message = "unable to create filesystem, {details}"
96+
97+
@classmethod
98+
def catch_all(cls, func):
99+
@functools.wraps(func)
100+
def new_func(*args, **kwargs):
101+
try:
102+
return func(*args, **kwargs)
103+
except cls:
104+
raise
105+
except Exception as e:
106+
raise cls(exc=e)
107+
return new_func
108+
109+
def __init__(self, msg=None, exc=None):
110+
self._msg = msg or self.default_message
111+
self.details = '' if exc is None else text_type(exc)
112+
self.exc = exc
95113

96114
class PathError(FSError):
97115
"""Base exception for errors to do with a path string.

fs/osfs.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,12 @@ def __init__(self,
8888
os.makedirs(_root_path, mode=create_mode)
8989
except OSError as error:
9090
raise errors.CreateFailed(
91-
'unable to create {} ({})'.format(root_path, error)
91+
'unable to create {} ({})'.format(root_path, error),
92+
error,
9293
)
9394
else:
9495
if not os.path.isdir(_root_path):
95-
raise errors.CreateFailed(
96-
'root path does not exist'
97-
)
96+
raise errors.CreateFailed('root path does not exist')
9897

9998
_meta = self._meta = {
10099
'case_insensitive': os.path.normcase('Aa') != 'aa',

fs/tarfs.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ class ReadTarFS(FS):
204204
tarfile.LNKTYPE: ResourceType.symlink,
205205
}
206206

207+
@errors.CreateFailed.catch_all
207208
def __init__(self, file, encoding='utf-8'):
208209
super(ReadTarFS, self).__init__()
209210
self._file = file

fs/zipfs.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ class ReadZipFS(FS):
241241
'virtual': False,
242242
}
243243

244+
@errors.CreateFailed.catch_all
244245
def __init__(self, file, encoding='utf-8'):
245246
super(ReadZipFS, self).__init__()
246247
self._file = file

tests/test_errors.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from six import text_type
66

77
from fs import errors
8+
from fs.errors import CreateFailed
89

910

1011
class TestErrors(unittest.TestCase):
@@ -24,3 +25,22 @@ def test_unsupported(self):
2425
text_type(err),
2526
"not supported"
2627
)
28+
29+
30+
class TestCreateFailed(unittest.TestCase):
31+
32+
def test_catch_all(self):
33+
34+
errors = (ZeroDivisionError, ValueError, CreateFailed)
35+
36+
@CreateFailed.catch_all
37+
def test(x):
38+
raise errors[x]
39+
40+
for index, exc in enumerate(errors):
41+
try:
42+
test(index)
43+
except Exception as e:
44+
self.assertIsInstance(e, CreateFailed)
45+
if e.exc is not None:
46+
self.assertNotIsInstance(e.exc, CreateFailed)

0 commit comments

Comments
 (0)