Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

""" 

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, 

    13: errno.EBUSY, # empty cd drive, but ENOMEDIUM seems unavailiable 

    22: errno.ENOTDIR, 

    20: 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): 

44        if name[0] == "_": 

            raise AttributeError(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 (OSError, 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()