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"""