|
1 """ |
|
2 create errno-specific classes for IO or os calls. |
|
3 |
|
4 """ |
|
5 import sys, os, errno |
|
6 |
|
7 class Error(EnvironmentError): |
|
8 def __repr__(self): |
|
9 return "%s.%s %r: %s " %(self.__class__.__module__, |
|
10 self.__class__.__name__, |
|
11 self.__class__.__doc__, |
|
12 " ".join(map(str, self.args)), |
|
13 #repr(self.args) |
|
14 ) |
|
15 |
|
16 def __str__(self): |
|
17 s = "[%s]: %s" %(self.__class__.__doc__, |
|
18 " ".join(map(str, self.args)), |
|
19 ) |
|
20 return s |
|
21 |
|
22 _winerrnomap = { |
|
23 2: errno.ENOENT, |
|
24 3: errno.ENOENT, |
|
25 17: errno.EEXIST, |
|
26 22: errno.ENOTDIR, |
|
27 267: errno.ENOTDIR, |
|
28 5: errno.EACCES, # anything better? |
|
29 } |
|
30 |
|
31 class ErrorMaker(object): |
|
32 """ lazily provides Exception classes for each possible POSIX errno |
|
33 (as defined per the 'errno' module). All such instances |
|
34 subclass EnvironmentError. |
|
35 """ |
|
36 Error = Error |
|
37 _errno2class = {} |
|
38 |
|
39 def __getattr__(self, name): |
|
40 eno = getattr(errno, name) |
|
41 cls = self._geterrnoclass(eno) |
|
42 setattr(self, name, cls) |
|
43 return cls |
|
44 |
|
45 def _geterrnoclass(self, eno): |
|
46 try: |
|
47 return self._errno2class[eno] |
|
48 except KeyError: |
|
49 clsname = errno.errorcode.get(eno, "UnknownErrno%d" %(eno,)) |
|
50 errorcls = type(Error)(clsname, (Error,), |
|
51 {'__module__':'py.error', |
|
52 '__doc__': os.strerror(eno)}) |
|
53 self._errno2class[eno] = errorcls |
|
54 return errorcls |
|
55 |
|
56 def checked_call(self, func, *args, **kwargs): |
|
57 """ call a function and raise an errno-exception if applicable. """ |
|
58 __tracebackhide__ = True |
|
59 try: |
|
60 return func(*args, **kwargs) |
|
61 except self.Error: |
|
62 raise |
|
63 except EnvironmentError: |
|
64 cls, value, tb = sys.exc_info() |
|
65 if not hasattr(value, 'errno'): |
|
66 raise |
|
67 __tracebackhide__ = False |
|
68 errno = value.errno |
|
69 try: |
|
70 if not isinstance(value, WindowsError): |
|
71 raise NameError |
|
72 except NameError: |
|
73 # we are not on Windows, or we got a proper OSError |
|
74 cls = self._geterrnoclass(errno) |
|
75 else: |
|
76 try: |
|
77 cls = self._geterrnoclass(_winerrnomap[errno]) |
|
78 except KeyError: |
|
79 raise value |
|
80 raise cls("%s%r" % (func.__name__, args)) |
|
81 __tracebackhide__ = True |
|
82 |
|
83 error = ErrorMaker() |