Skip to content

Commit

Permalink
Merge pull request #357 from RWTH-EBC/356-post-entity-has-an-unused-v…
Browse files Browse the repository at this point in the history
…ariable-update-need-to-check-the-spec-for-the-expected-behavior

356 post entity has an unused variable update need to check the spec for the expected behavior
  • Loading branch information
djs0109 authored Nov 20, 2024
2 parents 21c954f + f7a48d4 commit f624d33
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 48 deletions.
22 changes: 17 additions & 5 deletions filip/clients/ngsi_ld/cb.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ def post_entity(self,
"""
Function registers an Object with the NGSI-LD Context Broker,
if it already exists it can be automatically updated
if the overwrite bool is True
if the update flag bool is True.
First a post request with the entity is tried, if the response code
is 422 the entity is uncrossable, as it already exists there are two
options, either overwrite it, if the attribute have changed
Expand All @@ -223,13 +223,23 @@ def post_entity(self,
return res.headers.get('Location')
res.raise_for_status()
except requests.RequestException as err:
if append and err.response.status_code == 409:
return self.append_entity_attributes(entity=entity)
if err.response.status_code == 409:
if append: # 409 entity already exists
return self.append_entity_attributes(entity=entity)
elif update:
return self.override_entities(entities=[entity])
msg = f"Could not post entity {entity.id}"
self.log_error(err=err, msg=msg)
raise

GeometryShape = Literal["Point", "MultiPoint", "LineString", "MultiLineString", "Polygon", "MultiPolygon"]
def override_entities(self, entities: List[ContextLDEntity]):
"""
Function to create or override existing entites with the NGSI-LD Context Broker.
The batch operation with Upsert will be used.
"""
return self.entity_batch_operation(entities=entities,
action_type=ActionTypeLD.UPSERT,
options="replace")

def get_entity(self,
entity_id: str,
Expand Down Expand Up @@ -289,14 +299,16 @@ def get_entity(self,
self.log_error(err=err, msg=msg)
raise

GeometryShape = Literal["Point", "MultiPoint", "LineString", "MultiLineString", "Polygon", "MultiPolygon"]

def get_entity_list(self,
entity_id: Optional[str] = None,
id_pattern: Optional[str] = ".*",
entity_type: Optional[str] = None,
attrs: Optional[List[str]] = None,
q: Optional[str] = None,
georel: Optional[str] = None,
geometry: Optional[GeometryShape] = None, # So machen oder wie auch für response_format
geometry: Optional[GeometryShape] = None,
coordinates: Optional[str] = None,
geoproperty: Optional[str] = None,
csf: Optional[str] = None,
Expand Down
6 changes: 3 additions & 3 deletions filip/models/ngsi_ld/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import logging
from typing import Any, List, Dict, Union, Optional
from geojson_pydantic import Point, MultiPoint, LineString, MultiLineString, Polygon, \
MultiPolygon, GeometryCollection
MultiPolygon
from typing_extensions import Self
from aenum import Enum
from pydantic import field_validator, ConfigDict, BaseModel, Field, model_validator
Expand Down Expand Up @@ -190,7 +190,7 @@ def check_geoproperty_value(self) -> Self:
elif self.model_dump().get("type") == "MultiPolygon":
return MultiPolygon(**self.model_dump())
elif self.model_dump().get("type") == "GeometryCollection":
return GeometryCollection(**self.model_dump())
raise ValueError("GeometryCollection is not supported")


class ContextGeoProperty(BaseModel):
Expand Down Expand Up @@ -221,7 +221,7 @@ class ContextGeoProperty(BaseModel):
value: Optional[Union[ContextGeoPropertyValue,
Point, LineString, Polygon,
MultiPoint, MultiPolygon,
MultiLineString, GeometryCollection]] = Field(
MultiLineString]] = Field(
default=None,
title="GeoProperty value",
description="the actual data"
Expand Down
58 changes: 29 additions & 29 deletions tests/clients/test_ngsi_ld_cb.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,33 +190,7 @@ def test_post_entity(self):
- Post an entity again -> Does it return 409?
- Post an entity without requires args -> Does it return 422?
"""
"""
Test 1:
Post enitity with entity_ID and entity_type
if return != 201:
Raise Error
Get entity list
If entity with entity_ID is not on entity list:
Raise Error
Test 2:
Post entity with entity_ID and entity_type
Post entity with the same entity_ID and entity_type as before
If return != 409:
Raise Error
Get entity list
If there are duplicates on entity list:
Raise Error
Test 3:
Post an entity with an entity_ID and without an entity_type
If return != 422:
Raise Error
Get entity list
If the entity list does contain the posted entity:
Raise Error
Test Additonal:
post two entities with the same enitity id but different entity type-> should throw error.
"""
"""Test1"""
# create entity
self.client.post_entity(entity=self.entity)
entity_list = self.client.get_entity_list(entity_type=self.entity.type)
self.assertEqual(len(entity_list), 1)
Expand All @@ -225,7 +199,7 @@ def test_post_entity(self):
self.assertEqual(entity_list[0].testtemperature.value,
self.entity.testtemperature.value)

"""Test2"""
# existed entity
self.entity_identical = self.entity.model_copy()
with self.assertRaises(requests.exceptions.HTTPError) as contextmanager:
self.client.post_entity(entity=self.entity_identical)
Expand All @@ -236,7 +210,33 @@ def test_post_entity(self):
entity_type=self.entity_identical.type)
self.assertEqual(len(entity_list), 1)

"""Test3"""
# append new attribute to existed entity
self.entity_append = self.entity.model_copy()
self.entity_append.delete_properties(['testtemperature'])
self.entity_append.add_properties(
{'humidity': ContextProperty(**{
'type': 'Property',
'value': 50})})
self.client.post_entity(entity=self.entity_append, append=True)
entity_append_res = self.client.get_entity(entity_id=self.entity_append.id)
self.assertEqual(entity_append_res.humidity.value,
self.entity_append.humidity.value)
self.assertEqual(entity_append_res.testtemperature.value,
self.entity.testtemperature.value)

# override existed entity
new_attr = {'newattr':
{'type': 'Property', 'value': 999}
}
self.entity_override = ContextLDEntity(
id=self.entity.id, type=self.entity.type, **new_attr)
self.client.post_entity(entity=self.entity_override, update=True)
entity_override_res = self.client.get_entity(entity_id=self.entity.id)
self.assertEqual(entity_override_res.newattr.value,
self.entity_override.newattr.value)
self.assertNotIn('testtemperature', entity_override_res.model_dump())

# post without entity type is not allowed
with self.assertRaises(Exception):
self.client.post_entity(ContextLDEntity(id="room2"))
entity_list = self.client.get_entity_list()
Expand Down
18 changes: 7 additions & 11 deletions tests/models/test_ngsi_ld_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,11 +223,6 @@ def setUp(self) -> None:
"type": "GeoProperty",
"value": self.testpolygon_value,
"observedAt": "2023-09-12T12:36:00Z"
},
"testgeometrycollection": {
"type": "GeoProperty",
"value": self.testgeometrycollection_value,
"observedAt": "2023-09-12T12:36:30Z"
}
}

Expand Down Expand Up @@ -272,13 +267,14 @@ def test_geo_property(self) -> None:
type="GeoProperty",
value=Polygon(**self.testpolygon_value)
)
test_GeometryCollection = NamedContextGeoProperty(
name="testgeometrycollection",
type="GeoProperty",
value=GeometryCollection(**self.testgeometrycollection_value)
)
with self.assertRaises(ValidationError):
test_GeometryCollection = NamedContextGeoProperty(
name="testgeometrycollection",
type="GeoProperty",
value=GeometryCollection(**self.testgeometrycollection_value)
)
new_entity.add_geo_properties([test_point, test_MultiPoint, test_LineString,
test_Polygon, test_GeometryCollection])
test_Polygon])

def test_cb_entity(self) -> None:
"""
Expand Down

0 comments on commit f624d33

Please sign in to comment.