From abe9a81c5f9647e96a9a9af777c373fbf1fff6cf Mon Sep 17 00:00:00 2001 From: Daniel <d.hornung@indiscale.com> Date: Thu, 3 Mar 2022 17:23:07 +0100 Subject: [PATCH] ENH: Better error output in case of wrong server XML. --- src/caosdb/common/models.py | 15 ++++++++++++--- unittests/data/list_in_value.xml | 2 ++ unittests/test_issues.py | 8 +++++++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/caosdb/common/models.py b/src/caosdb/common/models.py index ec45dec0..80a6ee11 100644 --- a/src/caosdb/common/models.py +++ b/src/caosdb/common/models.py @@ -55,6 +55,7 @@ from caosdb.exceptions import (AmbiguousEntityError, AuthorizationError, EntityDoesNotExistError, EntityError, EntityHasNoDatatypeError, HTTPURITooLongError, MismatchingEntitiesError, QueryNotUniqueError, + ServerConfigurationException, TransactionError, UniqueNamesError, UnqualifiedParentsError, UnqualifiedPropertiesError) @@ -1195,6 +1196,10 @@ class Entity(object): def _parse_value(datatype, value): + """Parse the value (from XML input) according to the given datatype + """ + + # Simple values if value is None: return value @@ -1215,12 +1220,12 @@ def _parse_value(datatype, value): else: raise ValueError("Boolean value was {}.".format(value)) + # Datetime and text are returned as-is if datatype in [DATETIME, TEXT]: if isinstance(value, str): return value # deal with collections - if isinstance(datatype, str): matcher = re.compile(r"^(?P<col>[^<]+)<(?P<dt>[^>]+)>$") m = matcher.match(datatype) @@ -1245,12 +1250,10 @@ def _parse_value(datatype, value): # This is for a special case, where the xml parser could not differentiate # between single values and lists with one element. As - if hasattr(value, "__len__") and len(value) == 1: return _parse_value(datatype, value[0]) # deal with references - if isinstance(value, Entity): return value @@ -1266,6 +1269,12 @@ def _parse_value(datatype, value): # reference via name return str(value) + except TypeError: + # deal with invalid XML: List of values without appropriate datatype + if isinstance(value, list): + raise ServerConfigurationException( + "The server sent an invalid XML: List valued properties must be announced by " + "the datatype.\n" + f"Datatype: {datatype}\nvalue: {value}") def _log_request(request, xml_body=None): diff --git a/unittests/data/list_in_value.xml b/unittests/data/list_in_value.xml index c3627cad..0f92610d 100644 --- a/unittests/data/list_in_value.xml +++ b/unittests/data/list_in_value.xml @@ -8,3 +8,5 @@ <Value>1005</Value> </Property> </Record> + +<!-- Note: This XML is invalid, because list-valued Properties must have a LIST-Datatype --> diff --git a/unittests/test_issues.py b/unittests/test_issues.py index 84573c79..1e649db4 100644 --- a/unittests/test_issues.py +++ b/unittests/test_issues.py @@ -24,10 +24,16 @@ import os import lxml import caosdb as db +from pytest import raises + def test_issue_100(): """_parse_value() fails for some list-valued content """ + + # Parse from (invalid) XML file filename = os.path.join(os.path.dirname(__file__), "data", "list_in_value.xml") xml_el = lxml.etree.parse(filename).getroot() - rec = db.common.models._parse_single_xml_element(xml_el) + with raises(db.ServerConfigurationException) as exc_info: + db.common.models._parse_single_xml_element(xml_el) + assert "invalid XML: List valued properties" in exc_info.value.msg -- GitLab