diff --git a/dsp_permissions_scripts/oap/oap_get.py b/dsp_permissions_scripts/oap/oap_get.py index 2e8f78eb..25f940c7 100644 --- a/dsp_permissions_scripts/oap/oap_get.py +++ b/dsp_permissions_scripts/oap/oap_get.py @@ -1,4 +1,6 @@ +import copy from typing import Any +from urllib.parse import quote from urllib.parse import quote_plus from dsp_permissions_scripts.models.errors import ApiError @@ -30,6 +32,87 @@ "knora-api:userHasPermission", "knora-api:hasPermissions", ] +KB_RESCLASSES = [ + "knora-api:VideoSegment", + "knora-api:AudioSegment", + "knora-api:Region", + "knora-api:Annotation", + "knora-api:LinkObj", +] + + +def get_oaps_of_kb_resclasses(dsp_client: DspClient, project_iri: str, oap_config: OapRetrieveConfig) -> list[Oap]: + match oap_config.retrieve_resources: + case "specified_res_classes": + specified_kb_resclasses = [x for x in KB_RESCLASSES if x in oap_config.specified_res_classes] + res_only_oaps = _get_oaps_of_specified_kb_resclasses(dsp_client, project_iri, specified_kb_resclasses) + case "all": + res_only_oaps = _get_oaps_of_specified_kb_resclasses(dsp_client, project_iri, KB_RESCLASSES) + + match oap_config.retrieve_values: + case "none": + return res_only_oaps + case "specified_props": + enriched_oaps = _enrich_with_value_oaps(dsp_client, res_only_oaps, oap_config.specified_props) + case "all": + enriched_oaps = _enrich_with_value_oaps(dsp_client, res_only_oaps) + + return enriched_oaps + + +def _get_oaps_of_specified_kb_resclasses( + dsp_client: DspClient, project_iri: str, kb_resclasses: list[str] +) -> list[Oap]: + logger.info(f"Retrieving OAPs from the knora-base resource classes {kb_resclasses}...") + all_oaps: list[Oap] = [] + for resclass in kb_resclasses: + oaps = _get_oaps_of_one_kb_resclass(dsp_client, project_iri, resclass) + logger.info(f"Retrieved {len(oaps)} OAPs from class {resclass}.") + all_oaps.extend(oaps) + logger.info(f"Retrieved a total of {len(all_oaps)} OAPs from knora-base resource classes.") + return all_oaps + + +def _enrich_with_value_oaps( + dsp_client: DspClient, res_only_oaps: list[Oap], restrict_to_props: list[str] | None = None +) -> list[Oap]: + logger.info(f"Enriching {len(res_only_oaps)} OAPs of knora-base resources with their value OAPs...") + complete_oaps = copy.deepcopy(res_only_oaps) + for oap in complete_oaps: + full_resource = dsp_client.get(f"/v2/resources/{quote_plus(oap.resource_oap.resource_iri)}") + oap.value_oaps = _get_value_oaps(full_resource, restrict_to_props) + logger.info(f"Enriched {len(complete_oaps)} OAPs of knora-base resources with their value OAPs.") + return complete_oaps + + +def _get_oaps_of_one_kb_resclass(dsp_client: DspClient, project_iri: str, resclass: str) -> list[Oap]: + oaps: list[Oap] = [] + mayHaveMoreResults: bool = True + offset = 0 + while mayHaveMoreResults: + sparql_query = """ + PREFIX knora-api: + + CONSTRUCT { + ?kb_resclass knora-api:isMainResource true . + } WHERE { + BIND(<%(project_iri)s> as ?project_iri) . + ?kb_resclass a %(resclass)s . + ?kb_resclass knora-api:attachedToProject ?project_iri . + } + OFFSET %(offset)s + """ % {"resclass": resclass, "project_iri": project_iri, "offset": offset} # noqa: UP031 (printf-string-formatting) + if not (response := dsp_client.get(f"/v2/searchextended/{quote(sparql_query, safe='')}")): + break # if there are 0 results, the response is an empty dict + # 1 result: the resource is returned as a single dict + # >1 results: the resource is returned as a list of dicts + for json_resource in response.get("@graph", [response]): + scope = create_scope_from_string(json_resource["knora-api:hasPermissions"]) + res_oap = ResourceOap(scope=scope, resource_iri=json_resource["@id"]) + oaps.append(Oap(resource_oap=res_oap, value_oaps=[])) + mayHaveMoreResults = bool(response.get("knora-api:mayHaveMoreResults", False)) + offset += 1 + return oaps def _get_all_oaps_of_resclass( @@ -156,5 +239,6 @@ def get_all_oaps_of_project( for resclass_localname in resclass_localnames: oaps = _get_all_oaps_of_resclass(resclass_localname, project_iri, dsp_client, oap_config) all_oaps.extend(oaps) + all_oaps.extend(get_oaps_of_kb_resclasses(dsp_client, project_iri, oap_config)) logger.info(f"Retrieved a TOTAL of {len(all_oaps)} OAPs") return all_oaps diff --git a/tests/test_oap_get.py b/tests/test_oap_get.py index 2f075722..7bd1f565 100644 --- a/tests/test_oap_get.py +++ b/tests/test_oap_get.py @@ -1,15 +1,23 @@ from typing import Any +from unittest.mock import Mock +from urllib.parse import quote import pytest +from pytest_unordered import unordered from dsp_permissions_scripts.models import group from dsp_permissions_scripts.models.scope import PermissionScope +from dsp_permissions_scripts.oap import oap_get +from dsp_permissions_scripts.oap.oap_get import KB_RESCLASSES from dsp_permissions_scripts.oap.oap_get import _get_oap_of_one_resource +from dsp_permissions_scripts.oap.oap_get import _get_oaps_of_one_kb_resclass from dsp_permissions_scripts.oap.oap_get import _get_value_oaps +from dsp_permissions_scripts.oap.oap_get import get_oaps_of_kb_resclasses from dsp_permissions_scripts.oap.oap_model import Oap from dsp_permissions_scripts.oap.oap_model import OapRetrieveConfig from dsp_permissions_scripts.oap.oap_model import ResourceOap from dsp_permissions_scripts.oap.oap_model import ValueOap +from dsp_permissions_scripts.utils.dsp_client import DspClient @pytest.fixture() @@ -31,6 +39,129 @@ def resource() -> dict[str, Any]: } +@pytest.fixture() +def gravsearch_1_link_obj() -> dict[str, Any]: + return { + "knora-api:hasPermissions": "CR knora-admin:ProjectAdmin|D knora-admin:ProjectMember", + "@type": "knora-api:LinkObj", + "@id": "http://rdfh.ch/0806/5moPQcfeS0mfhh-Oed3tPA", + } + + +@pytest.fixture() +def gravsearch_4_link_objs_on_2_pages() -> list[dict[str, Any]]: + page_1 = { + "@graph": [ + { + "knora-api:hasPermissions": "CR knora-admin:ProjectAdmin|D knora-admin:ProjectMember", + "@type": "knora-api:LinkObj", + "@id": "http://rdfh.ch/0806/5moPQcfeS0mfhh-Oed3tPA", + }, + { + "knora-api:hasPermissions": "CR knora-admin:ProjectAdmin|D knora-admin:ProjectMember", + "@type": "knora-api:LinkObj", + "@id": "http://rdfh.ch/0806/8DGe7ai1TFmyTD0XN56ubg", + }, + ], + "knora-api:mayHaveMoreResults": True, + } + page_2 = { + "@graph": [ + { + "knora-api:hasPermissions": "CR knora-admin:ProjectAdmin|D knora-admin:ProjectMember", + "@type": "knora-api:LinkObj", + "@id": "http://rdfh.ch/0806/BmnN7X_zR7C0f7B4ibAZ6A", + }, + { + "knora-api:hasPermissions": "CR knora-admin:ProjectAdmin|D knora-admin:ProjectMember", + "@type": "knora-api:LinkObj", + "@id": "http://rdfh.ch/0806/_n8QtGaXTVG14jtYU5H33Q", + }, + ] + } + return [page_1, page_2] + + +@pytest.fixture() +def video_segment() -> dict[str, Any]: # https://ark.stage.dasch.swiss/ark:/72163/1/0812/l32ehsHuTfaQAKVTRiuBRAR + return { + "knora-api:hasSegmentBounds": { + "knora-api:hasPermissions": "CR knora-admin:Creator|V knora-admin:KnownUser,knora-admin:UnknownUser", + "@type": "knora-api:IntervalValue", + "@id": "http://rdfh.ch/0812/l32ehsHuTfaQAKVTRiuBRA/values/vBYk7HEERHWNMy0IagG97A", + }, + "knora-api:relatesToValue": { + "knora-api:linkValueHasTarget": { + "knora-api:hasPermissions": "CR knora-admin:Creator|V knora-admin:KnownUser,knora-admin:UnknownUser", + "@type": "ekws:Agent", + "@id": "http://rdfh.ch/0812/DUB459kJWDmO8o_GyvQJMg", + }, + "knora-api:hasPermissions": "CR knora-admin:Creator|V knora-admin:KnownUser,knora-admin:UnknownUser", + "@type": "knora-api:LinkValue", + "@id": "http://rdfh.ch/0812/l32ehsHuTfaQAKVTRiuBRA/values/stMJC52VRYSAJEI_bllNmQ", + }, + "knora-api:hasTitle": { + "knora-api:hasPermissions": "CR knora-admin:Creator|V knora-admin:KnownUser,knora-admin:UnknownUser", + "@type": "knora-api:TextValue", + "@id": "http://rdfh.ch/0812/l32ehsHuTfaQAKVTRiuBRA/values/ggBMLia9Q-iZFzj5T1zsgg", + }, + "knora-api:hasPermissions": "CR knora-admin:Creator|V knora-admin:KnownUser,knora-admin:UnknownUser", + "knora-api:isVideoSegmentOfValue": { + "knora-api:linkValueHasTarget": { + "knora-api:hasPermissions": "CR knora-admin:Creator|V knora-admin:KnownUser,knora-admin:UnknownUser", + "@type": "ekws:MovingImageRepresentation", + "@id": "http://rdfh.ch/0812/eIsPNAgNQLCoczIkuos9zw", + }, + "knora-api:hasPermissions": "CR knora-admin:Creator|V knora-admin:KnownUser,knora-admin:UnknownUser", + "@type": "knora-api:LinkValue", + "@id": "http://rdfh.ch/0812/l32ehsHuTfaQAKVTRiuBRA/values/eylWw-RCQOOdircrcfCzFA", + }, + "@type": "knora-api:VideoSegment", + "knora-api:hasDescription": { + "knora-api:hasPermissions": "CR knora-admin:Creator|V knora-admin:KnownUser,knora-admin:UnknownUser", + "@id": "http://rdfh.ch/0812/l32ehsHuTfaQAKVTRiuBRA/values/WP1q4naiTty1CEcv9cglaA", + "@type": "knora-api:TextValue", + }, + "@id": "http://rdfh.ch/0812/l32ehsHuTfaQAKVTRiuBRA", + } + + +@pytest.fixture() +def linkobj() -> dict[str, Any]: # https://app.test.dasch.swiss/resource/F18E/Os_5VvgkSC2saUlSUdcLhA + return { + "knora-api:hasPermissions": "CR knora-admin:ProjectAdmin|V knora-admin:KnownUser", + "@type": "knora-api:LinkObj", + "knora-api:hasLinkToValue": [ + { + "knora-api:linkValueHasTarget": { + "knora-api:hasPermissions": "CR knora-admin:ProjectAdmin|V knora-admin:KnownUser", + "@type": "invalid-jwt-token:DocumentRepresentation", + "@id": "http://rdfh.ch/F18E/1ft22XVzQ1Gk2eYMvybhGA", + }, + "knora-api:hasPermissions": "CR knora-admin:ProjectAdmin|V knora-admin:KnownUser", + "@type": "knora-api:LinkValue", + "@id": "http://rdfh.ch/F18E/Os_5VvgkSC2saUlSUdcLhA/values/YlwXFucHSVq5VfETR3dc0Q", + }, + { + "knora-api:linkValueHasTarget": { + "knora-api:hasPermissions": "CR knora-admin:ProjectAdmin|V knora-admin:KnownUser", + "@type": "invalid-jwt-token:DocumentRepresentation", + "@id": "http://rdfh.ch/F18E/3BlLqRdlRZCpYcGzTlK8Iw", + }, + "knora-api:hasPermissions": "CR knora-admin:ProjectAdmin|V knora-admin:KnownUser", + "@type": "knora-api:LinkValue", + "@id": "http://rdfh.ch/F18E/Os_5VvgkSC2saUlSUdcLhA/values/yUA0UsnBReuYJ8zmQjvG3A", + }, + ], + "@id": "http://rdfh.ch/F18E/Os_5VvgkSC2saUlSUdcLhA", + "knora-api:hasComment": { + "knora-api:hasPermissions": "CR knora-admin:ProjectAdmin|V knora-admin:KnownUser", + "@type": "knora-api:TextValue", + "@id": "http://rdfh.ch/F18E/Os_5VvgkSC2saUlSUdcLhA/values/TGyIeaV2QBqxAl8NxCs_Vw", + }, + } + + class Test_get_value_oaps: def test_oap_get_multiple_values_per_prop(self) -> None: resource = { @@ -79,6 +210,107 @@ def test_oap_get_multiple_values_per_prop(self) -> None: returned = _get_value_oaps(resource) assert expected == returned + def test_linkobj_full(self, linkobj: dict[str, Any]) -> None: + perm_scope_expected = PermissionScope.create(CR=[group.PROJECT_ADMIN], V=[group.KNOWN_USER]) + exp_1 = ValueOap( + scope=perm_scope_expected, + property="knora-api:hasLinkToValue", + value_type="knora-api:LinkValue", + value_iri="http://rdfh.ch/F18E/Os_5VvgkSC2saUlSUdcLhA/values/YlwXFucHSVq5VfETR3dc0Q", + resource_iri="http://rdfh.ch/F18E/Os_5VvgkSC2saUlSUdcLhA", + ) + exp_2 = ValueOap( + scope=perm_scope_expected, + property="knora-api:hasLinkToValue", + value_type="knora-api:LinkValue", + value_iri="http://rdfh.ch/F18E/Os_5VvgkSC2saUlSUdcLhA/values/yUA0UsnBReuYJ8zmQjvG3A", + resource_iri="http://rdfh.ch/F18E/Os_5VvgkSC2saUlSUdcLhA", + ) + exp_3 = ValueOap( + scope=perm_scope_expected, + property="knora-api:hasComment", + value_type="knora-api:TextValue", + value_iri="http://rdfh.ch/F18E/Os_5VvgkSC2saUlSUdcLhA/values/TGyIeaV2QBqxAl8NxCs_Vw", + resource_iri="http://rdfh.ch/F18E/Os_5VvgkSC2saUlSUdcLhA", + ) + expected = [exp_1, exp_2, exp_3] + returned = _get_value_oaps(linkobj) + assert returned == unordered(expected) + + def test_video_segment_full(self, video_segment: dict[str, Any]) -> None: + perm_scope_expected = PermissionScope.create(CR=[group.CREATOR], V=[group.KNOWN_USER, group.UNKNOWN_USER]) + exp_1 = ValueOap( + scope=perm_scope_expected, + property="knora-api:hasSegmentBounds", + value_type="knora-api:IntervalValue", + value_iri="http://rdfh.ch/0812/l32ehsHuTfaQAKVTRiuBRA/values/vBYk7HEERHWNMy0IagG97A", + resource_iri="http://rdfh.ch/0812/l32ehsHuTfaQAKVTRiuBRA", + ) + exp_2 = ValueOap( + scope=perm_scope_expected, + property="knora-api:relatesToValue", + value_type="knora-api:LinkValue", + value_iri="http://rdfh.ch/0812/l32ehsHuTfaQAKVTRiuBRA/values/stMJC52VRYSAJEI_bllNmQ", + resource_iri="http://rdfh.ch/0812/l32ehsHuTfaQAKVTRiuBRA", + ) + exp_3 = ValueOap( + scope=perm_scope_expected, + property="knora-api:isVideoSegmentOfValue", + value_type="knora-api:LinkValue", + value_iri="http://rdfh.ch/0812/l32ehsHuTfaQAKVTRiuBRA/values/eylWw-RCQOOdircrcfCzFA", + resource_iri="http://rdfh.ch/0812/l32ehsHuTfaQAKVTRiuBRA", + ) + exp_4 = ValueOap( + scope=perm_scope_expected, + property="knora-api:hasTitle", + value_type="knora-api:TextValue", + value_iri="http://rdfh.ch/0812/l32ehsHuTfaQAKVTRiuBRA/values/ggBMLia9Q-iZFzj5T1zsgg", + resource_iri="http://rdfh.ch/0812/l32ehsHuTfaQAKVTRiuBRA", + ) + exp_5 = ValueOap( + scope=perm_scope_expected, + property="knora-api:hasDescription", + value_type="knora-api:TextValue", + value_iri="http://rdfh.ch/0812/l32ehsHuTfaQAKVTRiuBRA/values/WP1q4naiTty1CEcv9cglaA", + resource_iri="http://rdfh.ch/0812/l32ehsHuTfaQAKVTRiuBRA", + ) + expected = [exp_1, exp_2, exp_3, exp_4, exp_5] + returned = _get_value_oaps(video_segment) + assert returned == unordered(expected) + + def test_video_segment_restrict_to_1_prop(self, video_segment: dict[str, Any]) -> None: + perm_scope_expected = PermissionScope.create(CR=[group.CREATOR], V=[group.KNOWN_USER, group.UNKNOWN_USER]) + exp_1 = ValueOap( + scope=perm_scope_expected, + property="knora-api:relatesToValue", + value_type="knora-api:LinkValue", + value_iri="http://rdfh.ch/0812/l32ehsHuTfaQAKVTRiuBRA/values/stMJC52VRYSAJEI_bllNmQ", + resource_iri="http://rdfh.ch/0812/l32ehsHuTfaQAKVTRiuBRA", + ) + expected = [exp_1] + returned = _get_value_oaps(video_segment, ["knora-api:relatesToValue"]) + assert returned == unordered(expected) + + def test_video_segment_restrict_to_2_props(self, video_segment: dict[str, Any]) -> None: + perm_scope_expected = PermissionScope.create(CR=[group.CREATOR], V=[group.KNOWN_USER, group.UNKNOWN_USER]) + exp_1 = ValueOap( + scope=perm_scope_expected, + property="knora-api:relatesToValue", + value_type="knora-api:LinkValue", + value_iri="http://rdfh.ch/0812/l32ehsHuTfaQAKVTRiuBRA/values/stMJC52VRYSAJEI_bllNmQ", + resource_iri="http://rdfh.ch/0812/l32ehsHuTfaQAKVTRiuBRA", + ) + exp_2 = ValueOap( + scope=perm_scope_expected, + property="knora-api:hasTitle", + value_type="knora-api:TextValue", + value_iri="http://rdfh.ch/0812/l32ehsHuTfaQAKVTRiuBRA/values/ggBMLia9Q-iZFzj5T1zsgg", + resource_iri="http://rdfh.ch/0812/l32ehsHuTfaQAKVTRiuBRA", + ) + expected = [exp_1, exp_2] + returned = _get_value_oaps(video_segment, ["knora-api:relatesToValue", "knora-api:hasTitle"]) + assert returned == unordered(expected) + def test_get_oap_of_one_resource_all_classes_all_values(resource: dict[str, Any]) -> None: config = OapRetrieveConfig(retrieve_resources="all", retrieve_values="all") @@ -137,3 +369,142 @@ def test_get_oap_of_one_resource_some_classes_some_values(resource: dict[str, An expected = Oap(resource_oap=expected_res_oap, value_oaps=[expected_val_oap]) res = _get_oap_of_one_resource(resource, config) assert res == expected + + +class Test_get_oaps_of_one_kb_resclass: + def test_get_oaps_of_one_kb_resclass_0_results(self) -> None: + dsp_client = Mock(spec=DspClient) + dsp_client.get = Mock(side_effect=[{}]) + res = _get_oaps_of_one_kb_resclass(dsp_client, "proj_iri", "resclass") + assert res == [] + assert len(dsp_client.get.call_args_list) == 1 + called_route = dsp_client.get.call_args_list[0].args[0] + assert called_route.startswith("/v2/searchextended/") + assert "proj_iri" in called_route + assert "resclass" in called_route + assert quote("OFFSET 0", safe="") in called_route + + def test_get_oaps_of_one_kb_resclass_1_result(self, gravsearch_1_link_obj: dict[str, Any]) -> None: + dsp_client = Mock(spec=DspClient) + dsp_client.get = Mock(side_effect=[gravsearch_1_link_obj]) + res = _get_oaps_of_one_kb_resclass(dsp_client, "proj_iri", "resclass") + expected = Oap( + resource_oap=ResourceOap( + scope=PermissionScope.create(CR=[group.PROJECT_ADMIN], D=[group.PROJECT_MEMBER]), + resource_iri="http://rdfh.ch/0806/5moPQcfeS0mfhh-Oed3tPA", + ), + value_oaps=[], + ) + assert res == [expected] + + def test_get_oaps_of_one_kb_resclass_4_results_on_2_pages( + self, + gravsearch_4_link_objs_on_2_pages: list[dict[str, Any]], + ) -> None: + dsp_client = Mock(spec=DspClient) + dsp_client.get = Mock(side_effect=gravsearch_4_link_objs_on_2_pages) + res = _get_oaps_of_one_kb_resclass(dsp_client, "proj_iri", "resclass") + expected_scope = PermissionScope.create(CR=[group.PROJECT_ADMIN], D=[group.PROJECT_MEMBER]) + expected_res_oaps = [ + ResourceOap(scope=expected_scope, resource_iri="http://rdfh.ch/0806/5moPQcfeS0mfhh-Oed3tPA"), + ResourceOap(scope=expected_scope, resource_iri="http://rdfh.ch/0806/8DGe7ai1TFmyTD0XN56ubg"), + ResourceOap(scope=expected_scope, resource_iri="http://rdfh.ch/0806/BmnN7X_zR7C0f7B4ibAZ6A"), + ResourceOap(scope=expected_scope, resource_iri="http://rdfh.ch/0806/_n8QtGaXTVG14jtYU5H33Q"), + ] + expected = [Oap(resource_oap=res_oap, value_oaps=[]) for res_oap in expected_res_oaps] + assert res == expected + + assert len(dsp_client.get.call_args_list) == 2 # noqa: PLR2004 (magic value used in comparison) + called_route_1 = dsp_client.get.call_args_list[0].args[0] + called_route_2 = dsp_client.get.call_args_list[1].args[0] + assert quote("OFFSET 0", safe="") in called_route_1 + assert quote("OFFSET 1", safe="") in called_route_2 + + +class Test_get_oaps_of_kb_resclasses: + def test_get_oaps_of_kb_resclasses_all_resclasses_all_values(self) -> None: + oap_get._get_oaps_of_specified_kb_resclasses = Mock(side_effect=[["res_only_oap_1", "res_only_oap_2"]]) + oap_get._enrich_with_value_oaps = Mock(side_effect=[["enriched_oap_1", "enriched_oap_2"]]) + dsp_client = Mock(spec=DspClient) + oap_config = OapRetrieveConfig( + retrieve_resources="all", + retrieve_values="all", + ) + _ = get_oaps_of_kb_resclasses(dsp_client, "proj_iri", oap_config) + oap_get._get_oaps_of_specified_kb_resclasses.assert_called_once_with(dsp_client, "proj_iri", KB_RESCLASSES) + oap_get._enrich_with_value_oaps.assert_called_once_with(dsp_client, ["res_only_oap_1", "res_only_oap_2"]) + + def test_get_oaps_of_kb_resclasses_all_resclasses_specified_values(self) -> None: + oap_get._get_oaps_of_specified_kb_resclasses = Mock(side_effect=[["res_only_oap_1", "res_only_oap_2"]]) + oap_get._enrich_with_value_oaps = Mock(side_effect=[["enriched_oap_1", "enriched_oap_2"]]) + dsp_client = Mock(spec=DspClient) + oap_config = OapRetrieveConfig( + retrieve_resources="all", + retrieve_values="specified_props", + specified_props=["onto:prop_1", "onto:prop_2"], + ) + _ = get_oaps_of_kb_resclasses(dsp_client, "proj_iri", oap_config) + oap_get._get_oaps_of_specified_kb_resclasses.assert_called_once_with(dsp_client, "proj_iri", KB_RESCLASSES) + oap_get._enrich_with_value_oaps.assert_called_once_with( + dsp_client, ["res_only_oap_1", "res_only_oap_2"], ["onto:prop_1", "onto:prop_2"] + ) + + def test_get_oaps_of_kb_resclasses_all_resclasses_no_values(self) -> None: + oap_get._get_oaps_of_specified_kb_resclasses = Mock(side_effect=[["res_only_oap_1", "res_only_oap_2"]]) + oap_get._enrich_with_value_oaps = Mock(side_effect=[["enriched_oap_1", "enriched_oap_2"]]) + dsp_client = Mock(spec=DspClient) + oap_config = OapRetrieveConfig( + retrieve_resources="all", + retrieve_values="none", + ) + _ = get_oaps_of_kb_resclasses(dsp_client, "proj_iri", oap_config) + oap_get._get_oaps_of_specified_kb_resclasses.assert_called_once_with(dsp_client, "proj_iri", KB_RESCLASSES) + oap_get._enrich_with_value_oaps.assert_not_called() + + def test_get_oaps_of_kb_resclasses_some_resclasses_all_values(self) -> None: + oap_get._get_oaps_of_specified_kb_resclasses = Mock(side_effect=[["res_only_oap_1", "res_only_oap_2"]]) + oap_get._enrich_with_value_oaps = Mock(side_effect=[["enriched_oap_1", "enriched_oap_2"]]) + dsp_client = Mock(spec=DspClient) + oap_config = OapRetrieveConfig( + retrieve_resources="specified_res_classes", + specified_res_classes=["knora-api:Region", "custom-onto:foo"], + retrieve_values="all", + ) + _ = get_oaps_of_kb_resclasses(dsp_client, "proj_iri", oap_config) + oap_get._get_oaps_of_specified_kb_resclasses.assert_called_once_with( + dsp_client, "proj_iri", ["knora-api:Region"] + ) + oap_get._enrich_with_value_oaps.assert_called_once_with(dsp_client, ["res_only_oap_1", "res_only_oap_2"]) + + def test_get_oaps_of_kb_resclasses_some_resclasses_some_values(self) -> None: + oap_get._get_oaps_of_specified_kb_resclasses = Mock(side_effect=[["res_only_oap_1", "res_only_oap_2"]]) + oap_get._enrich_with_value_oaps = Mock(side_effect=[["enriched_oap_1", "enriched_oap_2"]]) + dsp_client = Mock(spec=DspClient) + oap_config = OapRetrieveConfig( + retrieve_resources="specified_res_classes", + specified_res_classes=["knora-api:Region", "custom-onto:foo"], + retrieve_values="specified_props", + specified_props=["onto:prop_1", "onto:prop_2"], + ) + _ = get_oaps_of_kb_resclasses(dsp_client, "proj_iri", oap_config) + oap_get._get_oaps_of_specified_kb_resclasses.assert_called_once_with( + dsp_client, "proj_iri", ["knora-api:Region"] + ) + oap_get._enrich_with_value_oaps.assert_called_once_with( + dsp_client, ["res_only_oap_1", "res_only_oap_2"], ["onto:prop_1", "onto:prop_2"] + ) + + def test_get_oaps_of_kb_resclasses_some_resclasses_no_values(self) -> None: + oap_get._get_oaps_of_specified_kb_resclasses = Mock(side_effect=[["res_only_oap_1", "res_only_oap_2"]]) + oap_get._enrich_with_value_oaps = Mock(side_effect=[["enriched_oap_1", "enriched_oap_2"]]) + dsp_client = Mock(spec=DspClient) + oap_config = OapRetrieveConfig( + retrieve_resources="specified_res_classes", + specified_res_classes=["knora-api:Region", "custom-onto:foo"], + retrieve_values="none", + ) + _ = get_oaps_of_kb_resclasses(dsp_client, "proj_iri", oap_config) + oap_get._get_oaps_of_specified_kb_resclasses.assert_called_once_with( + dsp_client, "proj_iri", ["knora-api:Region"] + ) + oap_get._enrich_with_value_oaps.assert_not_called()