python-pyodata icon indicating copy to clipboard operation
python-pyodata copied to clipboard

service: fix navigation in EntityProxy

Open Masterchen09 opened this issue 3 years ago • 1 comments

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.

Masterchen09 avatar Aug 14 '22 20:08 Masterchen09

Codecov Report

Merging #226 (72f0416) into master (e18fc73) will decrease coverage by 0.05%. The diff coverage is 88.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.

codecov-commenter avatar Aug 14 '22 20:08 codecov-commenter

@filak-sap Hi, could you pls check this one as well?

phanak-sap avatar Aug 15 '22 12:08 phanak-sap