Repository: SAP/python-pyodata

Issue:
AttributeError in PyOData v1.11.0 When Executing CustomerCollection Query
After updating to PyOData version 1.11.0, I encountered a significant issue with a previously functional query. The purpose of the query is to retrieve a list of customers using the CustomerCollection.get_entities() method, with additional parameters for counting, filtering, ordering, and limiting the number of results.

**Issue Details:**
The following Python code, which worked flawlessly in version 1.10.1, started throwing an AttributeError in version 1.11.0:
`customers = accountService.entity_sets.CustomerCollection.get_entities().count(inline=True).filter("LifeCycleStatusCode eq '2'").custom("$orderby", "LastChangeDateTime desc").custom("$top", "8").execute()
`
**Error Message:**
The error message received is as follows:
`[ERROR] AttributeError: 'str' object has no attribute 'get'
Traceback (most recent call last):
  File "/var/task/GETAccountandContact.py", line 86, in lambda_handler
    customers = accountService.entity_sets.CustomerCollection.get_entities().count(inline=True).filter("LifeCycleStatusCode eq '2'").custom("$orderby", "LastChangeDateTime desc").custom("$top", "8").execute()
  File "/tmp/pyodata/v2/service.py", line 349, in execute
    return self._call_handler(response)
  File "/tmp/pyodata/v2/service.py", line 362, in _call_handler
    return self._handler(response)
  File "/tmp/pyodata/v2/service.py", line 1549, in get_entities_handler
    entity = EntityProxy(self._service, self._entity_set, self._entity_set.entity_type, props)
  File "/tmp/pyodata/v2/service.py", line 881, in __init__
    self._cache[prop.name].append(EntityProxy(service, None, prop_etype, entity))
  File "/tmp/pyodata/v2/service.py", line 825, in __init__
    etag_body = proprties.get('__metadata', dict()).get('etag', None)
`

**Temporary Solution:**
As a temporary workaround, I had to downgrade to version 1.10.1, after which the query started working again without any errors.

**Request:**
I believe this is a bug introduced in version 1.11.0. It would be greatly appreciated if the team could investigate this issue and provide a fix or guidance on how to resolve it in the newer version of PyOData.

Thank you for your attention to this matter.




Discussion:
phanak-sap: Hi @filak-sap, should this line be changed as well? I was not having time yet to create reproducing tests, resp finding service returning data in such format -  but struck me that this part also expects have entities returned only in ['results'] key.  

Is that line still correct? with the context of this PR and original issue #258?

https://github.com/SAP/python-pyodata/blame/0d5c9dabfc7e5b99837eaf7fdccc592bc344d623/pyodata/v2/service.py#L1543
phanak-sap: @manuelseeger thx for the check and confirming explanation, I see now, compared to the referenced spec from #238. 

Patch:
diff --git a/pyodata/v2/service.py b/pyodata/v2/service.py
index e84d2f7..0ed7741 100644
--- a/pyodata/v2/service.py
+++ b/pyodata/v2/service.py
@@ -876,7 +876,7 @@ class EntityProxy:
                             # available entities are serialized in results array
                             for entity in proprties[prop.name]['results']:
                                 self._cache[prop.name].append(EntityProxy(service, None, prop_etype, entity))
-                        else:
+                        elif isinstance(proprties[prop.name], list):
                             for entity in proprties[prop.name]:
                                 self._cache[prop.name].append(EntityProxy(service, None, prop_etype, entity))
                     else:


Test patch:
diff --git a/tests/test_service_v2.py b/tests/test_service_v2.py
index bc4e0e3..f0d5bc5 100644
--- a/tests/test_service_v2.py
+++ b/tests/test_service_v2.py
@@ -883,6 +883,38 @@ def test_get_entities(service):
     assert empls[0].NameFirst == 'Yennefer'
     assert empls[0].NameLast == 'De Vengerberg'
 
+@responses.activate
+def test_get_entities_with_deferred_nav_prop(service):
+    """Get entities but don't include deferred navigation property"""
+
+    # pylint: disable=redefined-outer-name
+
+    responses.add(
+        responses.GET,
+        f"{service.url}/Employees",
+        json={'d': {
+            'results': [
+                {
+                    'ID': 669,
+                    'NameFirst': 'Yennefer',
+                    'NameLast': 'De Vengerberg',        
+                    'Addresses': {
+                        '__deferred': {'uri': "https://remote.url/Employees(23)/Addresses"}
+                    }
+                }
+            ]
+        }},
+        status=200)
+
+    request = service.entity_sets.Employees.get_entities()
+
+    assert isinstance(request, pyodata.v2.service.QueryRequest)
+
+    empls = request.execute()
+    assert empls[0].ID == 669
+    assert empls[0].NameFirst == 'Yennefer'
+    assert empls[0].NameLast == 'De Vengerberg'
+    assert len(empls[0].Addresses) == 0
 
 @responses.activate
 def test_get_null_value_from_null_preserving_service(service_retain_null):
@@ -1533,7 +1565,6 @@ def test_get_entity_expanded(service):
                         'City': 'London'
                     }
                 ]
-            
         }},
         status=200)
 
@@ -1549,6 +1580,7 @@ def test_get_entity_expanded(service):
     assert emp.Addresses[0].ID == 456
     assert emp.Addresses[0].Street == 'Baker Street'
     assert emp.Addresses[0].City == 'London'
+    
 
 @responses.activate
 def test_batch_request(service):