File: exceptions.py

package info (click to toggle)
python-podman 5.4.0.1-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,140 kB
  • sloc: python: 7,532; makefile: 82; sh: 75
file content (150 lines) | stat: -rw-r--r-- 4,208 bytes parent folder | download | duplicates (3)
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
"""Podman API Errors."""

from typing import Optional, Union, TYPE_CHECKING
from collections.abc import Iterable

from requests import Response
from requests.exceptions import HTTPError

# Break circular import
if TYPE_CHECKING:
    from podman.domain.containers import Container
    from podman.api.client import APIResponse


class APIError(HTTPError):
    """Wraps HTTP errors for processing by the API and clients."""

    def __init__(
        self,
        message: str,
        response: Union[Response, "APIResponse", None] = None,
        explanation: Optional[str] = None,
    ):
        """Initialize APIError.

        Args:
            message: Message from service. Default: response.text, may be enhanced or wrapped by
                bindings
            response: HTTP Response from service.
            explanation: An enhanced or wrapped version of message with additional context.
        """
        super().__init__(message, response=response)
        self.explanation = explanation

    def __str__(self):
        msg = super().__str__()

        if self.response is not None:
            msg = self.response.reason

        if self.is_client_error():
            msg = f"{self.status_code} Client Error: {msg}"

        elif self.is_server_error():
            msg = f"{self.status_code} Server Error: {msg}"

        if self.explanation:
            msg = f"{msg} ({self.explanation})"

        return msg

    @property
    def status_code(self):
        """Optional[int]: HTTP status code from response."""
        if self.response is not None:
            return self.response.status_code
        return None

    def is_error(self) -> bool:
        """Returns True when HTTP operation resulted in an error."""
        return self.is_client_error() or self.is_server_error()

    def is_client_error(self) -> bool:
        """Returns True when request is incorrect."""
        return 400 <= (self.status_code or 0) < 500

    def is_server_error(self) -> bool:
        """Returns True when error occurred in service."""
        return 500 <= (self.status_code or 0) < 600


class NotFound(APIError):
    """Resource not found on Podman service.

    Named for compatibility.
    """


class ImageNotFound(APIError):
    """Image not found on Podman service."""


class DockerException(Exception):
    """Base class for exception hierarchy.

    Provided for compatibility.
    """


class PodmanError(DockerException):
    """Base class for PodmanPy exceptions."""


class BuildError(PodmanError):
    """Error occurred during build operation."""

    def __init__(self, reason: str, build_log: Iterable[str]) -> None:
        """Initialize BuildError.

        Args:
            reason: describes the error
            build_log: build log output
        """
        super().__init__(reason)
        self.msg = reason
        self.build_log = build_log


class ContainerError(PodmanError):
    """Represents a container that has exited with a non-zero exit code."""

    def __init__(
        self,
        container: "Container",
        exit_status: int,
        command: Union[str, list[str]],
        image: str,
        stderr: Optional[Iterable[str]] = None,
    ):  # pylint: disable=too-many-positional-arguments
        """Initialize ContainerError.

        Args:
            container: Container that reported error.
            exit_status: Non-zero status code from Container exit.
            command: Command passed to container when created.
            image: Name of image that was used to create container.
            stderr: Errors reported by Container.
        """
        err = f": {stderr}" if stderr is not None else ""
        msg = (
            f"Command '{command}' in image '{image}' returned non-zero exit "
            f"status {exit_status}{err}"
        )

        super().__init__(msg)

        self.container = container
        self.exit_status: int = exit_status
        self.command = command
        self.image = image
        self.stderr = stderr


class InvalidArgument(PodmanError):
    """Parameter to method/function was not valid."""


class StreamParseError(RuntimeError):
    def __init__(self, reason):
        self.msg = reason