Skip to content

Commit

Permalink
fix: make abstract types work now I have an example
Browse files Browse the repository at this point in the history
Was provided an output example which enabled me to fix this code.
  • Loading branch information
nigelm committed Jun 21, 2022
1 parent 63f1454 commit 5bff15c
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 38 deletions.
2 changes: 1 addition & 1 deletion broadworks_ocip/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ def decode_xml(self, xml) -> broadworks_ocip.base.OCICommand:
command = element.get("{http://www.w3.org/2001/XMLSchema-instance}type")
self.logger.debug(f"Decoding command {command}")
cls = self._despatch_table[command]
result = cls.build_from_etree_(element, extras)
result = cls.build_from_etree_(api=self, element=element, extras=extras)
self.logger.info(f"<<< {result.type_}")
result.post_xml_decode_()
return result
Expand Down
87 changes: 50 additions & 37 deletions broadworks_ocip/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,6 @@ def etree_sub_components_(self, element: etree._Element) -> etree._Element:
if value is not None:
for subvalue in value:
self.etree_sub_element_(element, sub_element, subvalue)
elif sub_element.is_abstract:
if value is not None:
# we pull the sub elements out of the abstract instance
# we do not support multi level abstracts - ths is not the matrix
for sub_sub_element in value._elements():
sub_value = getattr(value, sub_sub_element.name)
self.etree_sub_element_(element, sub_sub_element, sub_value)
else:
self.etree_sub_element_(element, sub_element, value)
return element
Expand Down Expand Up @@ -239,11 +232,19 @@ def etree_sub_element_(
col_item = etree.SubElement(row_item, "col")
col_item.text = col
elif sub_element.is_complex:
elem = etree.SubElement(
element,
sub_element.xmlname,
nsmap=self._default_nsmap(),
)
if sub_element.is_abstract:
elem = etree.SubElement(
element,
sub_element.xmlname,
{"{http://www.w3.org/2001/XMLSchema-instance}type": value.type_},
nsmap=self._default_nsmap(),
)
else:
elem = etree.SubElement(
element,
sub_element.xmlname,
nsmap=self._default_nsmap(),
)
value.etree_sub_components_(elem)
else:
elem = etree.SubElement(
Expand Down Expand Up @@ -326,7 +327,12 @@ def build_from_etree_non_parameters_(
pass

@classmethod
def build_from_node_(cls, elem: ElementInfo, node: etree._Element) -> Any:
def build_from_node_(
cls,
api: "BroadworksAPI", # type: ignore # noqa
elem: ElementInfo,
node: etree._Element,
) -> Any:
"""
Creates an OCI subelement from a single XML etree node
Expand All @@ -341,7 +347,19 @@ def build_from_node_(cls, elem: ElementInfo, node: etree._Element) -> Any:
if elem.is_table:
return cls.decode_table_(node)
elif elem.is_complex:
return elem.type.build_from_etree_(node)
if elem.is_abstract:
if "{http://www.w3.org/2001/XMLSchema-instance}type" in node.attrib:
thisclass = api.get_type_class(
node.attrib[
"{http://www.w3.org/2001/XMLSchema-instance}type"
],
)
logger.error(f"thisclass={thisclass}")
return thisclass.build_from_etree_(api=api, element=node)
else:
return ValueError("Cannot decode abstract object")
else:
return elem.type.build_from_etree_(api=api, element=node)
elif elem.type == bool:
return elem.type(
True if node.text == "true" else False,
Expand All @@ -352,7 +370,12 @@ def build_from_node_(cls, elem: ElementInfo, node: etree._Element) -> Any:
return None

@classmethod
def build_from_etree_(cls, element: etree._Element, extras: Dict[str, Any] = {}):
def build_from_etree_(
cls,
api: "BroadworksAPI", # type: ignore # noqa
element: etree._Element,
extras: Dict[str, Any] = {},
):
"""
Create an OciType based instance from an XML etree element
Expand All @@ -368,30 +391,20 @@ def build_from_etree_(cls, element: etree._Element, extras: Dict[str, Any] = {})
result = []
nodes = element.findall(elem.xmlname)
for node in nodes:
result.append(cls.build_from_node_(elem=elem, node=node))
result.append(cls.build_from_node_(api=api, elem=elem, node=node))
initialiser[elem.name] = result
else:
if elem.is_abstract:
logger.error("XML decode of abstract property not yet supported")
# for subclass in elem.type.__subclasses__():
# elem_name = cls.class_to_property_(subclass.__name__)
# node = element.find(elem_name)
# if node is not None:
# initialiser[elem.name] = subclass.build_from_node_(
# elem=elem,
# node=node,
# )
else:
node = element.find(elem.xmlname)
if node is not None:
initialiser[elem.name] = cls.build_from_node_(
elem=elem,
node=node,
)
# else...
# I am inclined to thow an error here - at least after checking if
# the thing is require, but the class builder should do that so lets
# let it do its thing
node = element.find(elem.xmlname)
if node is not None:
initialiser[elem.name] = cls.build_from_node_(
api=api,
elem=elem,
node=node,
)
# else:
# I am inclined to thow an error here - at least after checking if
# the thing is require, but the class builder should do that so lets
# let it do its thing
# now have a dict with all the bits in it.
# use that to build a new object
return cls(**initialiser)
Expand Down
38 changes: 38 additions & 0 deletions tests/test_basic_command_xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,8 +371,46 @@ def test_user_modify_department_key_xml():
b'<sessionId xmlns="">00000000-1111-2222-3333-444444444444</sessionId>'
b'<command xmlns="" xsi:type="UserModifyRequest16">'
b"<userId>fred.flintstone@boulder.org</userId>"
b'<department xsi:type="EnterpriseDepartmentKey">'
b"<serviceProviderId>mysp</serviceProviderId>"
b"<name>mydept</name>"
b"</department>"
b"</command>"
b"</BroadsoftDocument>"
),
cmd,
)


def test_group_department_add_xml():
cmd = api.get_command_object(
"GroupDepartmentAddRequest",
service_provider_id="mysp",
group_id="mygroup",
department_name="mydept",
parent_department_key=api.get_type_object(
"GroupDepartmentKey",
service_provider_id="mysp",
group_id="mygroup",
name="test-name",
),
calling_line_id_name="clid_name",
)
check_command_xml(
(
b'<?xml version="1.0" encoding="ISO-8859-1"?>\n'
b'<BroadsoftDocument protocol="OCI" xmlns="C" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'
b'<sessionId xmlns="">00000000-1111-2222-3333-444444444444</sessionId>'
b'<command xmlns="" xsi:type="GroupDepartmentAddRequest">'
b"<serviceProviderId>mysp</serviceProviderId>"
b"<groupId>mygroup</groupId>"
b"<departmentName>mydept</departmentName>"
b'<parentDepartmentKey xsi:type="GroupDepartmentKey">'
b"<serviceProviderId>mysp</serviceProviderId>"
b"<groupId>mygroup</groupId>"
b"<name>test-name</name>"
b"</parentDepartmentKey>"
b"<callingLineIdName>clid_name</callingLineIdName>"
b"</command>"
b"</BroadsoftDocument>"
),
Expand Down
33 changes: 33 additions & 0 deletions tests/test_xml_command_decode.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,4 +286,37 @@ def test_user_assigned_services_get_list_response():
)


def test_group_department_add_xml():
xml = (
b'<?xml version="1.0" encoding="ISO-8859-1"?>\n'
b'<BroadsoftDocument protocol="OCI" xmlns="C" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'
b'<sessionId xmlns="">00000000-1111-2222-3333-444444444444</sessionId>'
b'<command xmlns="" xsi:type="GroupDepartmentAddRequest">'
b"<serviceProviderId>mysp</serviceProviderId>"
b"<groupId>mygroup</groupId>"
b"<departmentName>mydept</departmentName>"
b'<parentDepartmentKey xsi:type="GroupDepartmentKey">'
b"<serviceProviderId>mysp</serviceProviderId>"
b"<groupId>mygroup</groupId>"
b"<name>test-name</name>"
b"</parentDepartmentKey>"
b"<callingLineIdName>clid_name</callingLineIdName>"
b"</command>"
b"</BroadsoftDocument>"
)
api = BroadworksAPI(**BASIC_API_PARAMS)
generated = api.decode_xml(xml)
assert generated.type_ == "GroupDepartmentAddRequest"

assert (
generated.parent_department_key.to_dict()
== api.get_type_object( # noqa: W503
"GroupDepartmentKey",
service_provider_id="mysp",
group_id="mygroup",
name="test-name",
).to_dict()
)


# end

0 comments on commit 5bff15c

Please sign in to comment.