4 This module provides simplistic data classes that represent the few
5 structures that the QMP spec mandates; they are used to verify incoming
6 data to make sure it conforms to spec.
8 # pylint: disable=too-few-public-methods
10 from collections import abc
23 Abstract data model, representing some QMP object of some kind.
25 :param raw: The raw object to be validated.
26 :raise KeyError: If any required fields are absent.
27 :raise TypeError: If any required fields have the wrong type.
29 def __init__(self, raw: Mapping[str, Any]):
32 def _check_key(self, key: str) -> None:
33 if key not in self._raw:
34 raise KeyError(f"'{self._name}' object requires '{key}' member")
36 def _check_value(self, key: str, type_: type, typestr: str) -> None:
37 assert key in self._raw
38 if not isinstance(self._raw[key], type_):
40 f"'{self._name}' member '{key}' must be a {typestr}"
43 def _check_member(self, key: str, type_: type, typestr: str) -> None:
45 self._check_value(key, type_, typestr)
48 def _name(self) -> str:
49 return type(self).__name__
51 def __repr__(self) -> str:
52 return f"{self._name}({self._raw!r})"
55 class Greeting(Model):
57 Defined in qmp-spec.txt, section 2.2, "Server Greeting".
59 :param raw: The raw Greeting object.
60 :raise KeyError: If any required fields are absent.
61 :raise TypeError: If any required fields have the wrong type.
63 def __init__(self, raw: Mapping[str, Any]):
66 self.QMP: QMPGreeting # pylint: disable=invalid-name
68 self._check_member('QMP', abc.Mapping, "JSON object")
69 self.QMP = QMPGreeting(self._raw['QMP'])
71 def _asdict(self) -> Dict[str, object]:
73 For compatibility with the iotests sync QMP wrapper.
75 The legacy QMP interface needs Greetings as a garden-variety Dict.
77 This interface is private in the hopes that it will be able to
78 be dropped again in the near-future. Caller beware!
80 return dict(copy.deepcopy(self._raw))
83 class QMPGreeting(Model):
85 Defined in qmp-spec.txt, section 2.2, "Server Greeting".
87 :param raw: The raw QMPGreeting object.
88 :raise KeyError: If any required fields are absent.
89 :raise TypeError: If any required fields have the wrong type.
91 def __init__(self, raw: Mapping[str, Any]):
94 self.version: Mapping[str, object]
95 #: 'capabilities' member
96 self.capabilities: Sequence[object]
98 self._check_member('version', abc.Mapping, "JSON object")
99 self.version = self._raw['version']
101 self._check_member('capabilities', abc.Sequence, "JSON array")
102 self.capabilities = self._raw['capabilities']
105 class ErrorResponse(Model):
107 Defined in qmp-spec.txt, section 2.4.2, "error".
109 :param raw: The raw ErrorResponse object.
110 :raise KeyError: If any required fields are absent.
111 :raise TypeError: If any required fields have the wrong type.
113 def __init__(self, raw: Mapping[str, Any]):
114 super().__init__(raw)
116 self.error: ErrorInfo
118 self.id: Optional[object] = None # pylint: disable=invalid-name
120 self._check_member('error', abc.Mapping, "JSON object")
121 self.error = ErrorInfo(self._raw['error'])
127 class ErrorInfo(Model):
129 Defined in qmp-spec.txt, section 2.4.2, "error".
131 :param raw: The raw ErrorInfo object.
132 :raise KeyError: If any required fields are absent.
133 :raise TypeError: If any required fields have the wrong type.
135 def __init__(self, raw: Mapping[str, Any]):
136 super().__init__(raw)
137 #: 'class' member, with an underscore to avoid conflicts in Python.
142 self._check_member('class', str, "string")
143 self.class_ = self._raw['class']
145 self._check_member('desc', str, "string")
146 self.desc = self._raw['desc']