python-pyodata
python-pyodata copied to clipboard
service: fix navigation in EntityProxy
When I continued playing around with the OData API of the SAP Analytics Cloud, I might have found another bug or at least some inconsistencies between the different classes: The nav method of the EntityProxy is behaving differently than the nav method of the EntitySetProxy or the nav method of the EntityGetRequest (i.e. does not work correctly?).
In case of one to one or many to one relationships, the EntityProxy is directly returning a NavEntityProxy, while the EntitySetProxy is returning a NavEntityGetRequest. The EntityGetRequest is calling the nav method of the entity set, thus this method is also returning a NavEntityGetRequest.
Unfortunately the returned NavEntityProxy is instantiated without any properties, therefore when accessing a property the NavEntityProxy (i.e. the parent EntityProxy) is requesting the missing property (which does not work with the OData API of the SAC, but I am not sure if this usually should work?). This is also an issue if you want to access multiple properties of the navigation entity, as each property would be requested individually. In contrast to this, the NavEntityGetRequest returned by the nav method of the EntitySetProxy can be modified e.g. using the select method and can then be requested once using the execute method.
I am not sure if I am allowed to upload the metadata of the SAC OData API (the metadata is only accessible after authentication), but I will try to give an example without it:
for entity in client.entity_sets.Resources.get_entities().select('resourceId').execute():
nav_entity = entity.nav('createdByUser') # entity is an EntityProxy
print(type(nav_entity)) # NavEntityProxy
print(nav_entity.userId) # Does not work, the NavEntityProxy tries to request the missing property using the url /Resources('{resourceId}')/createdByUser/userId
request = client.entity_sets.Resources.get_entity(entity.resourceId).nav('createdByUser') # get_entity returns an EntityGetRequest and the nav method is using the nav method of the EntitySetProxy
print(type(request)) # NavEntityGetRequest
nav_entity = request.execute()
print(type(nav_entity)) # NavEntityProxy
print(nav_entity.userId) # Works fine
# With the changes of this PR the nav method of the EntityProxy work the same as the nav method of the EntitySetProxy
request = entity.nav('createdByUser')
print(type(request)) # NavEntityGetRequest
nav_entity = request.execute()
print(type(nav_entity)) # NavEntityProxy
print(nav_entity.userId) # Works fine
There is also now a test which should cover this case.
Codecov Report
Merging #226 (72f0416) into master (e18fc73) will decrease coverage by
0.05%. The diff coverage is88.88%.
@@ Coverage Diff @@
## master #226 +/- ##
==========================================
- Coverage 92.90% 92.85% -0.06%
==========================================
Files 6 6
Lines 2792 2800 +8
==========================================
+ Hits 2594 2600 +6
- Misses 198 200 +2
| Impacted Files | Coverage Δ | |
|---|---|---|
| pyodata/v2/service.py | 91.23% <88.88%> (-0.15%) |
:arrow_down: |
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.
@filak-sap Hi, could you pls check this one as well?