Coverage for /opt/homebrew/lib/python3.11/site-packages/_pytest/_py/error.py: 38%
56 statements
« prev ^ index » next coverage.py v7.2.3, created at 2023-05-04 13:14 +0700
« prev ^ index » next coverage.py v7.2.3, created at 2023-05-04 13:14 +0700
1"""create errno-specific classes for IO or os calls."""
2from __future__ import annotations
4import errno
5import os
6import sys
7from typing import Callable
8from typing import TYPE_CHECKING
9from typing import TypeVar
11if TYPE_CHECKING:
12 from typing_extensions import ParamSpec
14 P = ParamSpec("P")
16R = TypeVar("R")
19class Error(EnvironmentError):
20 def __repr__(self) -> str:
21 return "{}.{} {!r}: {} ".format(
22 self.__class__.__module__,
23 self.__class__.__name__,
24 self.__class__.__doc__,
25 " ".join(map(str, self.args)),
26 # repr(self.args)
27 )
29 def __str__(self) -> str:
30 s = "[{}]: {}".format(
31 self.__class__.__doc__,
32 " ".join(map(str, self.args)),
33 )
34 return s
37_winerrnomap = {
38 2: errno.ENOENT,
39 3: errno.ENOENT,
40 17: errno.EEXIST,
41 18: errno.EXDEV,
42 13: errno.EBUSY, # empty cd drive, but ENOMEDIUM seems unavailiable
43 22: errno.ENOTDIR,
44 20: errno.ENOTDIR,
45 267: errno.ENOTDIR,
46 5: errno.EACCES, # anything better?
47}
50class ErrorMaker:
51 """lazily provides Exception classes for each possible POSIX errno
52 (as defined per the 'errno' module). All such instances
53 subclass EnvironmentError.
54 """
56 _errno2class: dict[int, type[Error]] = {}
58 def __getattr__(self, name: str) -> type[Error]:
59 if name[0] == "_":
60 raise AttributeError(name)
61 eno = getattr(errno, name)
62 cls = self._geterrnoclass(eno)
63 setattr(self, name, cls)
64 return cls
66 def _geterrnoclass(self, eno: int) -> type[Error]:
67 try:
68 return self._errno2class[eno]
69 except KeyError:
70 clsname = errno.errorcode.get(eno, "UnknownErrno%d" % (eno,))
71 errorcls = type(
72 clsname,
73 (Error,),
74 {"__module__": "py.error", "__doc__": os.strerror(eno)},
75 )
76 self._errno2class[eno] = errorcls
77 return errorcls
79 def checked_call(
80 self, func: Callable[P, R], *args: P.args, **kwargs: P.kwargs
81 ) -> R:
82 """Call a function and raise an errno-exception if applicable."""
83 __tracebackhide__ = True
84 try:
85 return func(*args, **kwargs)
86 except Error:
87 raise
88 except OSError as value:
89 if not hasattr(value, "errno"):
90 raise
91 errno = value.errno
92 if sys.platform == "win32":
93 try:
94 cls = self._geterrnoclass(_winerrnomap[errno])
95 except KeyError:
96 raise value
97 else:
98 # we are not on Windows, or we got a proper OSError
99 cls = self._geterrnoclass(errno)
101 raise cls(f"{func.__name__}{args!r}")
104_error_maker = ErrorMaker()
105checked_call = _error_maker.checked_call
108def __getattr__(attr: str) -> type[Error]:
109 return getattr(_error_maker, attr) # type: ignore[no-any-return]