Return a list of EntityProxies when FunctionImport return type is a Collection#298
Return a list of EntityProxies when FunctionImport return type is a Collection#298Ixaruz wants to merge 1 commit into
Conversation
7d183de to
3d5ea27
Compare
There was a problem hiding this comment.
Hi @Ixaruz
You definitely hit a unfinished implementation and thanks for submitting a PR directly instead of just issue.
I was away on vacation and then having post-vacation more intense work, so had time just now to look at this.
The PR is going to right place with handling Collections as return type. However, comparing with odata v2 spec and current implementation from PR #188 there is some information lost in current PR.
Before this PR: FunctionImport with Collection return type returned raw JSON,
so users could still access response_data['__next'] manually.
After this PR: Only results array is extracted; __next is discarded.
Suggested fix: Return ListWithTotalCount (like get_entities() does) instead of plain list:
Same problem is for __count, which was possible to be present in raw response so far .__count can be present in Collection responses when $inlinecount=allpages was requested
OData v2 spec JSON format
Odata v2 spec inlinecount
I have generated with Claude sample test that you may include into PR that should expose this problem in PR code.
@responses.activate
def test_function_import_collection_with_pagination_metadata(service):
"""Function call with collection return type including pagination metadata
This test demonstrates that both __next and __count metadata should be preserved
when a FunctionImport returns a partial Collection with inline count.
Per OData v2 spec, this metadata is part of the Collection response format.
"""
# pylint: disable=redefined-outer-name
responses.add(
responses.GET,
f'{service.url}/get_best_measurements',
headers={'Content-type': 'application/json'},
json={'d': {
'results': [{
'Sensor': 'sensor1',
'Date': "/Date(1776417069000)/",
'Value': '29.8d'
}, {
'Sensor': 'sensor2',
'Date': "/Date(1776417578000)/",
'Value': '30.2d'
}],
'__count': '50',
'__next': 'https://example.com/service/get_best_measurements?$skiptoken=2'
}},
status=200)
result = service.functions.get_best_measurements.execute()
assert isinstance(result, list)
assert len(result) == 2
assert isinstance(result[0], pyodata.v2.service.EntityProxy)
assert isinstance(result[1], pyodata.v2.service.EntityProxy)
# FAIL: Collection should be ListWithTotalCount to preserve pagination metadata
# This matches the behavior of EntitySetRequest.get_entities()
assert hasattr(result, 'total_count'), \
"FunctionImport Collection should preserve __count like get_entities()"
assert result.total_count == 50
assert hasattr(result, 'next_url'), \
"FunctionImport Collection should preserve __next like get_entities()"
assert result.next_url == 'https://example.com/service/get_best_measurements?$skiptoken=2'
What the title says.
I had to rename the
EntitySetof theFunctionImportin the test metadata.xml to not include the namespace, or else the constructor ofEntityProxywould be unable to find the right entity set...since the
EntitySetin theFunctionImportofget_maxalso was just"TemperatureMeasurements"(not"EXAMPLE_SRV.TemperatureMeasurements"), I assume it was just an oversight in the xml (as it wasn't tested before).I don't know if my "fix" approach is too short sighted, I just wanted to provide potential fixes, as we needed them in our production.