Skip to content

Commit

Permalink
chore(xmlupload): improve user feedback when shortcode or onto are in…
Browse files Browse the repository at this point in the history
…existent (DEV-1827) (#321)
  • Loading branch information
jnussbaum committed Mar 14, 2023
1 parent 2111d21 commit f21a64e
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 4 deletions.
5 changes: 3 additions & 2 deletions src/dsp_tools/utils/shared.py
Expand Up @@ -87,14 +87,14 @@ def try_network_action(
else:
err_message = str(err).replace('\n', ' ')
err_message = err_message[:150] if len(err_message) > 150 else err_message
raise BaseError(f"{failure_msg} Error message: {err_message}")
raise UserError(f"{failure_msg}.\nOriginal error message for diagnostic purposes:\n{err_message}") from None
except Exception as exc:
if hasattr(exc, 'message'):
exc_message = exc.message
else:
exc_message = str(exc).replace('\n', ' ')
exc_message = exc_message[:150] if len(exc_message) > 150 else exc_message
raise BaseError(f"{failure_msg} Error message: {exc_message}")
raise UserError(f"{failure_msg}.\nOriginal error message for diagnostic purposes:\n{exc_message}") from None

raise BaseError(failure_msg)

Expand Down Expand Up @@ -126,6 +126,7 @@ def validate_xml_against_schema(input_file: Union[str, etree._ElementTree[Any]])
error_msg = "The XML file cannot be uploaded due to the following validation error(s):"
for error in xmlschema.error_log:
error_msg = error_msg + f"\n Line {error.line}: {error.message}"
error_msg = error_msg.replace("{https://dasch.swiss/schema}", "")
raise UserError(error_msg)

# make sure there are no XML tags in simple texts
Expand Down
16 changes: 15 additions & 1 deletion src/dsp_tools/utils/xml_upload.py
Expand Up @@ -246,6 +246,8 @@ def _parse_xml_file(input_file: Union[str, etree._ElementTree[Any]]) -> etree._E
def _check_consistency_with_ontology(
resources: list[XMLResource],
resclass_name_2_type: dict[str, type],
shortcode: str,
ontoname: str,
verbose: bool = False
) -> None:
"""
Expand All @@ -254,6 +256,8 @@ def _check_consistency_with_ontology(
Args:
resources: a list of parsed XMLResources
resclass_name_2_type: infos about the resource classes that exist on the DSP server for the current ontology
shortcode: the shortcode of the project as referenced in the attribute "shortcode" of the <knora> tag of the XML file
ontoname: the name of the ontology as referenced in the attribute "default-ontology" of the <knora> tag of the XML file
verbose: verbose switch
Raises:
Expand All @@ -264,6 +268,11 @@ def _check_consistency_with_ontology(
"""
if verbose:
print("Check if the resource types and properties are consistent with the ontology...")
if not any([x.startswith(ontoname) for x in resclass_name_2_type.keys()]):
raise UserError(
f"The <knora> tag of your XML file references the ontology '{ontoname}', "
f"but the project {shortcode} on the DSP server doesn't contain an ontology with this name."
)
knora_properties = resclass_name_2_type[resources[0].restype].knora_properties # type: ignore

for resource in resources:
Expand Down Expand Up @@ -376,14 +385,19 @@ def xml_upload(
resources.append(XMLResource(child, default_ontology))

# get the project information and project ontology from the server
res_inst_factory = try_network_action("", lambda: ResourceInstanceFactory(con, shortcode))
res_inst_factory = try_network_action(
failure_msg=f"A project with shortcode {shortcode} could not be found on the DSP server",
action=lambda: ResourceInstanceFactory(con, shortcode)
)
permissions_lookup: dict[str, Permissions] = {s: perm.get_permission_instance() for s, perm in permissions.items()}
resclass_name_2_type: dict[str, type] = {s: res_inst_factory.get_resclass_type(s) for s in res_inst_factory.get_resclass_names()}

# check if the data in the XML is consistent with the ontology
_check_consistency_with_ontology(
resources=resources,
resclass_name_2_type=resclass_name_2_type,
shortcode=shortcode,
ontoname=default_ontology,
verbose=verbose
)

Expand Down
2 changes: 1 addition & 1 deletion test/unittests/test_shared.py
Expand Up @@ -17,7 +17,7 @@ def test_validate_xml_against_schema(self) -> None:

with self.assertRaisesRegex(
UserError,
"Line 12: Element '{https://dasch.swiss/schema}resource', attribute 'invalidtag': "
"Line 12: Element 'resource', attribute 'invalidtag': "
"The attribute 'invalidtag' is not allowed"
):
shared.validate_xml_against_schema(input_file="testdata/invalid-testdata/xml-data/invalid-resource-tag.xml")
Expand Down
14 changes: 14 additions & 0 deletions testdata/invalid-testdata/xml-data/inexistent-ontoname.xml
@@ -0,0 +1,14 @@
<?xml version='1.0' encoding='utf-8'?>

<knora xmlns="https://dasch.swiss/schema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://dasch.swiss/schema ../src/dsp_tools/schemas/data.xsd"
shortcode="4124"
default-ontology="notexistingfantasyonto">

<resource label="The only resource"
restype=":minimalResource"
id="the_only_resource">
</resource>

</knora>
14 changes: 14 additions & 0 deletions testdata/invalid-testdata/xml-data/inexistent-shortcode.xml
@@ -0,0 +1,14 @@
<?xml version='1.0' encoding='utf-8'?>

<knora xmlns="https://dasch.swiss/schema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://dasch.swiss/schema ../src/dsp_tools/schemas/data.xsd"
shortcode="9999"
default-ontology="testonto">

<resource label="The only resource"
restype=":minimalResource"
id="the_only_resource">
</resource>

</knora>

0 comments on commit f21a64e

Please sign in to comment.