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
|
# SPDX-FileCopyrightText: 2024 Greenbone AG
#
# SPDX-License-Identifier: GPL-3.0-or-later
from functools import cached_property
from typing import Optional, TypeVar
from gvm.errors import GvmError
from gvm.xml import Element, parse_xml
from ._request import Request
class StatusError(GvmError):
"""
The response had an error status
May be raised when calling `response.raise_for_status()`
"""
def __init__(self, message: Optional[str], *args, response: "Response"):
super().__init__(message, *args)
self.response = response
self.request = response.request
Self = TypeVar("Self", bound="Response")
class Response:
"""
A GMP Response
"""
def __init__(self, *, request: Request, data: bytes) -> None:
"""
Create a Response object
Args:
request: The request corresponding to this response
data: The data of the response
"""
self._request = request
self._data = data
self.__xml: Optional[Element] = None
def __root_element(self) -> Element:
if self.__xml is None:
self.__xml = self.xml()
return self.__xml
def xml(self) -> Element:
"""
Return the response data as XML Element
Raises XmlError if the data is not valid XML.
"""
return parse_xml(self.data)
@property
def data(self) -> bytes:
"""
Return the data of the response as bytes
"""
return self._data
@property
def request(self) -> Request:
"""
Return the corresponding request of this response
"""
return self._request
@cached_property
def status_code(self) -> Optional[int]:
"""
The status code of the response
Returns:
The status code or None if the response data doesn't contain a valid
status code.
"""
root = self.__root_element()
try:
status = root.attrib["status"]
return int(status)
except (KeyError, ValueError):
return None
@property
def is_success(self) -> bool:
"""
Returns True if the response contains a success status code
"""
status = self.status_code
return status is not None and 200 <= status <= 299
def raise_for_status(self: Self) -> Self:
if self.is_success:
return self
raise StatusError(
f"Invalid status code {self.status_code}", response=self
)
def __bytes__(self) -> bytes:
"""
Return the data as bytes
"""
return self._data
def __str__(self) -> str:
"""
Return the data as string
"""
return self._data.decode()
|