84 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			84 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Python
		
	
	
	
| """
 | |
| create errno-specific classes for IO or os calls.
 | |
| 
 | |
| """
 | |
| import sys, os, errno
 | |
| 
 | |
| class Error(EnvironmentError):
 | |
|     def __repr__(self):
 | |
|         return "%s.%s %r: %s " %(self.__class__.__module__,
 | |
|                                self.__class__.__name__,
 | |
|                                self.__class__.__doc__,
 | |
|                                " ".join(map(str, self.args)),
 | |
|                                #repr(self.args)
 | |
|                                 )
 | |
| 
 | |
|     def __str__(self):
 | |
|         s = "[%s]: %s" %(self.__class__.__doc__,
 | |
|                           " ".join(map(str, self.args)),
 | |
|                           )
 | |
|         return s
 | |
| 
 | |
| _winerrnomap = {
 | |
|     2: errno.ENOENT,
 | |
|     3: errno.ENOENT,
 | |
|     17: errno.EEXIST,
 | |
|     22: errno.ENOTDIR,
 | |
|     267: errno.ENOTDIR,
 | |
|     5: errno.EACCES,  # anything better?
 | |
| }
 | |
| 
 | |
| class ErrorMaker(object):
 | |
|     """ lazily provides Exception classes for each possible POSIX errno
 | |
|         (as defined per the 'errno' module).  All such instances
 | |
|         subclass EnvironmentError.
 | |
|     """
 | |
|     Error = Error
 | |
|     _errno2class = {}
 | |
| 
 | |
|     def __getattr__(self, name):
 | |
|         eno = getattr(errno, name)
 | |
|         cls = self._geterrnoclass(eno)
 | |
|         setattr(self, name, cls)
 | |
|         return cls
 | |
| 
 | |
|     def _geterrnoclass(self, eno):
 | |
|         try:
 | |
|             return self._errno2class[eno]
 | |
|         except KeyError:
 | |
|             clsname = errno.errorcode.get(eno, "UnknownErrno%d" %(eno,))
 | |
|             errorcls = type(Error)(clsname, (Error,),
 | |
|                     {'__module__':'py.error',
 | |
|                      '__doc__': os.strerror(eno)})
 | |
|             self._errno2class[eno] = errorcls
 | |
|             return errorcls
 | |
| 
 | |
|     def checked_call(self, func, *args, **kwargs):
 | |
|         """ call a function and raise an errno-exception if applicable. """
 | |
|         __tracebackhide__ = True
 | |
|         try:
 | |
|             return func(*args, **kwargs)
 | |
|         except self.Error:
 | |
|             raise
 | |
|         except EnvironmentError:
 | |
|             cls, value, tb = sys.exc_info()
 | |
|             if not hasattr(value, 'errno'):
 | |
|                 raise
 | |
|             __tracebackhide__ = False
 | |
|             errno = value.errno
 | |
|             try:
 | |
|                 if not isinstance(value, WindowsError):
 | |
|                     raise NameError
 | |
|             except NameError:
 | |
|                 # we are not on Windows, or we got a proper OSError
 | |
|                 cls = self._geterrnoclass(errno)
 | |
|             else:
 | |
|                 try:
 | |
|                     cls = self._geterrnoclass(_winerrnomap[errno])
 | |
|                 except KeyError:
 | |
|                     raise value
 | |
|             raise cls("%s%r" % (func.__name__, args))
 | |
|             __tracebackhide__ = True
 | |
| 
 | |
| error = ErrorMaker()
 |