mitel_ommclient2/mitel_ommclient2/messages/__init__.py

209 lines
5.9 KiB
Python
Raw Normal View History

2022-01-06 16:09:55 +01:00
#!/usr/bin/env python3
from xml.dom.minidom import getDOMImplementation, parseString
2022-01-06 17:28:19 +01:00
from ..exceptions import exception_classes, OMResponseException
2022-05-01 23:55:18 +02:00
from ..types import cast_dict_to_childtype
2022-01-06 17:28:19 +01:00
2022-01-06 16:09:55 +01:00
class Message:
2022-01-06 16:09:55 +01:00
"""
Base message class
2022-01-06 16:09:55 +01:00
:param name: Name of the message
:param attrs: Message attributes
:param childs: Message children
2022-01-06 16:09:55 +01:00
"""
# Fields defined by the base type class
BASE_FIELDS = {}
# Fields defined by subclasses
FIELDS = {}
# Child types
CHILDS = {}
# Fields dicts consist of the field name as name and the field type as value
# Use None if the field type is unknown, any type is allowed then
class Childs:
"""
Contains message childs
"""
2022-01-06 16:09:55 +01:00
CHILDS = {}
2022-01-06 16:09:55 +01:00
def __init__(self, child_types, child_dict):
self.CHILDS = child_types
self._child_dict = child_dict
def __getattr__(self, name):
if name in self.CHILDS.keys():
return self._child_dict.get(name)
else:
raise AttributeError()
def __setattr__(self, name, value):
if name in self.CHILDS.keys():
2022-05-02 18:33:21 +02:00
if not isinstance(value, list):
raise TypeError()
2022-05-02 18:33:21 +02:00
for v in value:
if self.CHILDS[name] is not None and type(v) != self.CHILDS[name]:
raise TypeError()
self._child_dict[name] = value
else:
object.__setattr__(self, name, value)
def __init__(self, name=None, attrs={}, childs={}):
self.name = name
if not self.name:
self.name = self.__class__.__name__
self._attrs = {} | attrs
self._childs = {} | childs
self.childs = self.Childs(self.CHILDS, self._childs)
def __getattr__(self, name):
fields = self.FIELDS | self.BASE_FIELDS
if name in fields.keys():
return self._attrs.get(name)
else:
raise AttributeError()
def __setattr__(self, name, value):
fields = self.FIELDS | self.BASE_FIELDS
if name in fields.keys():
if fields[name] is not None and type(value) != fields[name]:
raise TypeError()
self._attrs[name] = value
else:
object.__setattr__(self, name, value)
2022-01-06 16:09:55 +01:00
2022-05-01 23:55:18 +02:00
def __repr__(self):
2022-05-02 18:08:31 +02:00
return "{}({}, {}, {})".format(self.__class__.__name__, repr(self.name), repr(self._attrs), repr(self._childs))
2022-05-01 23:55:18 +02:00
class Request(Message):
"""
Request message type class
2022-01-06 16:09:55 +01:00
"""
BASE_FIELDS = {
"seq": int,
}
class Response(Message):
"""
Response message type class
2022-01-06 16:09:55 +01:00
"""
BASE_FIELDS = {
"seq": int,
"errCode": None,
"info": None,
"bad": None,
"maxLen": None,
}
2022-01-06 16:09:55 +01:00
2022-01-06 17:28:19 +01:00
def raise_on_error(self):
"""
Raises an exception if the response contains an error.
Usage::
>>> try:
>>> r.raise_on_error()
>>> except mitel_ommclient2.exceptions.EAuth as e:
>>> print("We don't care about authentication!")
See children of :class:`mitel_ommclient2.exceptions.OMResponseException` for all possible exceptions.
"""
if self.errCode is not None:
raise exception_classes.get(self.errCode, OMResponseException)(response=self)
2022-01-06 17:28:19 +01:00
2022-01-06 16:09:55 +01:00
REQUEST_TYPES = {}
RESPONSE_TYPES = {}
2022-01-06 16:09:55 +01:00
def request_type(c):
REQUEST_TYPES[c.__name__] = c
return c
2022-01-06 16:09:55 +01:00
def response_type(c):
RESPONSE_TYPES[c.__name__] = c
return c
2022-01-06 16:09:55 +01:00
2022-06-16 21:29:21 +02:00
from .createppuser import CreatePPUser, CreatePPUserResp
2022-01-06 18:13:48 +01:00
from .getaccount import GetAccount, GetAccountResp
2022-01-16 13:52:08 +01:00
from .getppdev import GetPPDev, GetPPDevResp
2022-05-01 13:27:56 +02:00
from .getppuser import GetPPUser, GetPPUserResp
from .getpublickey import GetPublicKey, GetPublicKeyResp
2022-01-06 23:53:52 +01:00
from .open import Open, OpenResp
2022-01-06 16:09:55 +01:00
from .ping import Ping, PingResp
from .setpp import SetPP, SetPPResp
2022-05-02 18:33:21 +02:00
from .setppuser import SetPPUser, SetPPUserResp
2022-06-17 00:08:40 +02:00
from .setppuserdevrelation import SetPPUserDevRelation, SetPPUserDevRelationResp
2022-01-06 16:09:55 +01:00
def construct(request):
"""
Builds the XML message DOM and returns as string
"""
impl = getDOMImplementation()
message = impl.createDocument(None, request.name, None)
root = message.documentElement
for k, v in request._attrs.items():
2022-01-06 16:09:55 +01:00
root.setAttribute(str(k), str(v))
2022-05-02 18:33:21 +02:00
for child_name, child_list in request._childs.items():
if child_list is not None:
for child_list_item in child_list:
child = message.createElement(child_name)
for child_item_key, child_item_value in child_list_item._attrs.items():
child.setAttribute(str(child_item_key), str(child_item_value))
root.appendChild(child)
2022-01-06 16:09:55 +01:00
return root.toxml()
def parse(message):
message = parseString(message)
root = message.documentElement
name = root.tagName
attrs = {}
childs = {}
response_type = RESPONSE_TYPES.get(name)
fields = response_type.FIELDS | response_type.BASE_FIELDS
2022-01-06 16:09:55 +01:00
for i in range(0, root.attributes.length):
item = root.attributes.item(i)
if fields.get(item.name) is not None:
attrs[item.name] = fields[item.name](item.value)
else:
attrs[item.name] = item.value
2022-01-06 16:09:55 +01:00
child = root.firstChild
while child is not None:
new_child = {}
for i in range(0, child.attributes.length):
item = child.attributes.item(i)
new_child[item.name] = item.value
childname = child.tagName
2022-05-01 23:55:18 +02:00
# cast dict into child type
if response_type.CHILDS.get(childname) is not None:
new_child = cast_dict_to_childtype(response_type.CHILDS[childname], new_child)
2022-01-06 16:09:55 +01:00
if childname in childs:
childs[childname].append(new_child)
else:
childs[childname] = [new_child]
child = child.nextSibling
return response_type(name, attrs, childs)