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):
 | 
						|
        """ call a function and raise an errno-exception if applicable. """
 | 
						|
        __tracebackhide__ = True
 | 
						|
        try:
 | 
						|
            return func(*args)
 | 
						|
        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[eno]) 
 | 
						|
                except KeyError:    
 | 
						|
                    raise value 
 | 
						|
            raise cls("%s%r" % (func.__name__, args))
 | 
						|
            __tracebackhide__ = True
 | 
						|
 | 
						|
error = ErrorMaker()
 |