Skip to content

Commit b6fdbb6

Browse files
authored
service: associations relationship fixes
- fix navigation for associations with many to one relationships - fix navigation for associations with relationships to same entity PR #223
1 parent 9a72f93 commit b6fdbb6

File tree

4 files changed

+53
-19
lines changed

4 files changed

+53
-19
lines changed

pyodata/v2/service.py

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -874,16 +874,10 @@ def nav(self, nav_property):
874874
association_info.name,
875875
association_info.namespace)
876876

877-
navigation_entity_set = None
878-
for end in association_set.end_roles:
879-
if association_set.end_by_entity_set(end.entity_set_name).role == navigation_property.to_role.role:
880-
navigation_entity_set = self._service.schema.entity_set(end.entity_set_name, association_info.namespace)
877+
end = association_set.end_by_role(navigation_property.to_role.role)
878+
navigation_entity_set = self._service.schema.entity_set(end.entity_set_name)
881879

882-
if not navigation_entity_set:
883-
raise PyODataException(f'No association set for role {navigation_property.to_role}')
884-
885-
roles = navigation_property.association.end_roles
886-
if all((role.multiplicity != model.EndRole.MULTIPLICITY_ZERO_OR_MORE for role in roles)):
880+
if navigation_property.to_role.multiplicity != model.EndRole.MULTIPLICITY_ZERO_OR_MORE:
887881
return NavEntityProxy(self, nav_property, navigation_entity_set.entity_type, {})
888882

889883
return EntitySetProxy(
@@ -1349,17 +1343,10 @@ def nav(self, nav_property, key):
13491343
association_set = self._service.schema.association_set_by_association(
13501344
association_info.name)
13511345

1352-
navigation_entity_set = None
1353-
for end in association_set.end_roles:
1354-
if association_set.end_by_entity_set(end.entity_set_name).role == navigation_property.to_role.role:
1355-
navigation_entity_set = self._service.schema.entity_set(end.entity_set_name)
1356-
1357-
if not navigation_entity_set:
1358-
raise PyODataException(
1359-
f'No association set for role {navigation_property.to_role} {association_set.end_roles}')
1346+
end = association_set.end_by_role(navigation_property.to_role.role)
1347+
navigation_entity_set = self._service.schema.entity_set(end.entity_set_name)
13601348

1361-
roles = navigation_property.association.end_roles
1362-
if all((role.multiplicity != model.EndRole.MULTIPLICITY_ZERO_OR_MORE for role in roles)):
1349+
if navigation_property.to_role.multiplicity != model.EndRole.MULTIPLICITY_ZERO_OR_MORE:
13631350
return self._get_nav_entity(key, nav_property, navigation_entity_set)
13641351

13651352
return EntitySetProxy(

tests/metadata.xml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@
109109
<Property Name="City" Type="Edm.String" MaxLength="15" FixedLength="false" />
110110
<NavigationProperty Name="Orders" Relationship="EXAMPLE_SRV.CustomerOrders" FromRole="CustomerRole"
111111
ToRole="OrdersRole"/>
112+
<NavigationProperty Name="ReferredBy" Relationship="EXAMPLE_SRV.CustomerReferredBy" FromRole="CustomerRole"
113+
ToRole="ReferredByRole"/>
112114
</EntityType>
113115

114116
<EntityType Name="Order">
@@ -186,6 +188,16 @@
186188
</Dependent>
187189
</ReferentialConstraint>
188190
</Association>
191+
<Association Name="CustomerReferredBy">
192+
<End Type="EXAMPLE_SRV.Customer" Multiplicity="*" Role="CustomerRole"/>
193+
<End Type="EXAMPLE_SRV.Customer" Multiplicity="0..1" Role="ReferredByRole"/>
194+
<Principal Role="CustomerRole">
195+
<PropertyRef Name="Name"/>
196+
</Principal>
197+
<Dependent Role="ReferredByRole">
198+
<PropertyRef Name="Name"/>
199+
</Dependent>
200+
</Association>
189201
<Association Name="toSelfMaster" sap:content-version="1">
190202
<End Type="EXAMPLE_SRV.MasterEntity" Multiplicity="1" Role="FromRole_toSelfMaster"/>
191203
<End Type="EXAMPLE_SRV.MasterEntity" Multiplicity="0..1" Role="ToRole_toSelfMaster"/>
@@ -396,6 +408,11 @@
396408
<End Role="OrdersRole" EntitySet="Orders"/>
397409
</AssociationSet>
398410

411+
<AssociationSet Name="CustomerReferredBy_AssocSet" Association="EXAMPLE_SRV.CustomerReferredBy">
412+
<End Role="CustomerRole" EntitySet="Customers"/>
413+
<End Role="ReferredByRole" EntitySet="Customers"/>
414+
</AssociationSet>
415+
399416
</EntityContainer>
400417

401418
</Schema>

tests/test_model_v2.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ def test_edmx_associations(schema):
214214
'toCarIDPic',
215215
'toDataEntity',
216216
'CustomerOrders',
217+
'CustomerReferredBy',
217218
'AssociationEmployeeAddress',
218219
'toSelfMaster'
219220
}
@@ -241,6 +242,7 @@ def test_edmx_associations(schema):
241242
'toDataEntitySet',
242243
'AssociationEmployeeAddress_AssocSet',
243244
'CustomerOrder_AssocSet',
245+
'CustomerReferredBy_AssocSet',
244246
'toCarIDPicSet',
245247
'toSelfMasterSet'
246248
}

tests/test_service_v2.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,6 +1045,34 @@ def test_navigation(service):
10451045
assert addr.City == 'London'
10461046

10471047

1048+
@responses.activate
1049+
def test_navigation_multi_on1(service):
1050+
"""Check getting entity via navigation property"""
1051+
1052+
# pylint: disable=redefined-outer-name
1053+
1054+
responses.add(
1055+
responses.GET,
1056+
f"{service.url}/Customers('Mammon')/ReferredBy",
1057+
headers={'Content-type': 'application/json'},
1058+
json = { 'd': {
1059+
'Name': 'John',
1060+
}
1061+
},
1062+
status=200)
1063+
1064+
request = service.entity_sets.Customers.get_entity('Mammon').nav('ReferredBy')
1065+
assert isinstance(request, pyodata.v2.service.EntityGetRequest)
1066+
1067+
referred_by_proxy = request.execute()
1068+
assert isinstance(referred_by_proxy, pyodata.v2.service.NavEntityProxy)
1069+
1070+
assert referred_by_proxy.entity_set._name == 'Customers'
1071+
assert referred_by_proxy._entity_type.name == 'Customer'
1072+
1073+
assert referred_by_proxy.Name == 'John'
1074+
1075+
10481076
@responses.activate
10491077
def test_navigation_1on1(service):
10501078
"""Check getting entity via navigation property"""

0 commit comments

Comments
 (0)