_error.py 2.8 KB

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