From 34825a97fb4dbb305a724cfd7676e391adb38a78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20L=C3=BCdin?= <13187726+Masterchen09@users.noreply.github.com> Date: Mon, 8 Aug 2022 19:56:48 +0200 Subject: [PATCH] service: fix navigation for associations with many to one relationships and for associations with relationships to same entity --- pyodata/v2/service.py | 25 ++++++------------------- tests/metadata.xml | 17 +++++++++++++++++ tests/test_model_v2.py | 2 ++ tests/test_service_v2.py | 28 ++++++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 19 deletions(-) diff --git a/pyodata/v2/service.py b/pyodata/v2/service.py index f75f0d92..36483362 100644 --- a/pyodata/v2/service.py +++ b/pyodata/v2/service.py @@ -874,16 +874,10 @@ def nav(self, nav_property): association_info.name, association_info.namespace) - navigation_entity_set = None - for end in association_set.end_roles: - if association_set.end_by_entity_set(end.entity_set_name).role == navigation_property.to_role.role: - navigation_entity_set = self._service.schema.entity_set(end.entity_set_name, association_info.namespace) + end = association_set.end_by_role(navigation_property.to_role.role) + navigation_entity_set = self._service.schema.entity_set(end.entity_set_name) - if not navigation_entity_set: - raise PyODataException(f'No association set for role {navigation_property.to_role}') - - roles = navigation_property.association.end_roles - if all((role.multiplicity != model.EndRole.MULTIPLICITY_ZERO_OR_MORE for role in roles)): + if navigation_property.to_role.multiplicity != model.EndRole.MULTIPLICITY_ZERO_OR_MORE: return NavEntityProxy(self, nav_property, navigation_entity_set.entity_type, {}) return EntitySetProxy( @@ -1349,17 +1343,10 @@ def nav(self, nav_property, key): association_set = self._service.schema.association_set_by_association( association_info.name) - navigation_entity_set = None - for end in association_set.end_roles: - if association_set.end_by_entity_set(end.entity_set_name).role == navigation_property.to_role.role: - navigation_entity_set = self._service.schema.entity_set(end.entity_set_name) - - if not navigation_entity_set: - raise PyODataException( - f'No association set for role {navigation_property.to_role} {association_set.end_roles}') + end = association_set.end_by_role(navigation_property.to_role.role) + navigation_entity_set = self._service.schema.entity_set(end.entity_set_name) - roles = navigation_property.association.end_roles - if all((role.multiplicity != model.EndRole.MULTIPLICITY_ZERO_OR_MORE for role in roles)): + if navigation_property.to_role.multiplicity != model.EndRole.MULTIPLICITY_ZERO_OR_MORE: return self._get_nav_entity(key, nav_property, navigation_entity_set) return EntitySetProxy( diff --git a/tests/metadata.xml b/tests/metadata.xml index 79a86cd8..a9814699 100644 --- a/tests/metadata.xml +++ b/tests/metadata.xml @@ -109,6 +109,8 @@ + @@ -186,6 +188,16 @@ + + + + + + + + + + @@ -396,6 +408,11 @@ + + + + + diff --git a/tests/test_model_v2.py b/tests/test_model_v2.py index 6da27b7a..5bdef48d 100644 --- a/tests/test_model_v2.py +++ b/tests/test_model_v2.py @@ -214,6 +214,7 @@ def test_edmx_associations(schema): 'toCarIDPic', 'toDataEntity', 'CustomerOrders', + 'CustomerReferredBy', 'AssociationEmployeeAddress', 'toSelfMaster' } @@ -241,6 +242,7 @@ def test_edmx_associations(schema): 'toDataEntitySet', 'AssociationEmployeeAddress_AssocSet', 'CustomerOrder_AssocSet', + 'CustomerReferredBy_AssocSet', 'toCarIDPicSet', 'toSelfMasterSet' } diff --git a/tests/test_service_v2.py b/tests/test_service_v2.py index 803f582a..1d6e0e77 100644 --- a/tests/test_service_v2.py +++ b/tests/test_service_v2.py @@ -1045,6 +1045,34 @@ def test_navigation(service): assert addr.City == 'London' +@responses.activate +def test_navigation_multi_on1(service): + """Check getting entity via navigation property""" + + # pylint: disable=redefined-outer-name + + responses.add( + responses.GET, + f"{service.url}/Customers('Mammon')/ReferredBy", + headers={'Content-type': 'application/json'}, + json = { 'd': { + 'Name': 'John', + } + }, + status=200) + + request = service.entity_sets.Customers.get_entity('Mammon').nav('ReferredBy') + assert isinstance(request, pyodata.v2.service.EntityGetRequest) + + referred_by_proxy = request.execute() + assert isinstance(referred_by_proxy, pyodata.v2.service.NavEntityProxy) + + assert referred_by_proxy.entity_set._name == 'Customers' + assert referred_by_proxy._entity_type.name == 'Customer' + + assert referred_by_proxy.Name == 'John' + + @responses.activate def test_navigation_1on1(service): """Check getting entity via navigation property"""