_result.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. """
  2. Hook wrapper "result" utilities.
  3. """
  4. from __future__ import annotations
  5. from types import TracebackType
  6. from typing import Callable
  7. from typing import cast
  8. from typing import final
  9. from typing import Generic
  10. from typing import Optional
  11. from typing import Tuple
  12. from typing import Type
  13. from typing import TypeVar
  14. _ExcInfo = Tuple[Type[BaseException], BaseException, Optional[TracebackType]]
  15. ResultType = TypeVar("ResultType")
  16. class HookCallError(Exception):
  17. """Hook was called incorrectly."""
  18. @final
  19. class Result(Generic[ResultType]):
  20. """An object used to inspect and set the result in a :ref:`hook wrapper
  21. <hookwrappers>`."""
  22. __slots__ = ("_result", "_exception")
  23. def __init__(
  24. self,
  25. result: ResultType | None,
  26. exception: BaseException | None,
  27. ) -> None:
  28. """:meta private:"""
  29. self._result = result
  30. self._exception = exception
  31. @property
  32. def excinfo(self) -> _ExcInfo | None:
  33. """:meta private:"""
  34. exc = self._exception
  35. if exc is None:
  36. return None
  37. else:
  38. return (type(exc), exc, exc.__traceback__)
  39. @property
  40. def exception(self) -> BaseException | None:
  41. """:meta private:"""
  42. return self._exception
  43. @classmethod
  44. def from_call(cls, func: Callable[[], ResultType]) -> Result[ResultType]:
  45. """:meta private:"""
  46. __tracebackhide__ = True
  47. result = exception = None
  48. try:
  49. result = func()
  50. except BaseException as exc:
  51. exception = exc
  52. return cls(result, exception)
  53. def force_result(self, result: ResultType) -> None:
  54. """Force the result(s) to ``result``.
  55. If the hook was marked as a ``firstresult`` a single value should
  56. be set, otherwise set a (modified) list of results. Any exceptions
  57. found during invocation will be deleted.
  58. This overrides any previous result or exception.
  59. """
  60. self._result = result
  61. self._exception = None
  62. def force_exception(self, exception: BaseException) -> None:
  63. """Force the result to fail with ``exception``.
  64. This overrides any previous result or exception.
  65. .. versionadded:: 1.1.0
  66. """
  67. self._result = None
  68. self._exception = exception
  69. def get_result(self) -> ResultType:
  70. """Get the result(s) for this hook call.
  71. If the hook was marked as a ``firstresult`` only a single value
  72. will be returned, otherwise a list of results.
  73. """
  74. __tracebackhide__ = True
  75. exc = self._exception
  76. if exc is None:
  77. return cast(ResultType, self._result)
  78. else:
  79. raise exc.with_traceback(exc.__traceback__)
  80. # Historical name (pluggy<=1.2), kept for backward compatibility.
  81. _Result = Result