Skip to content

Commit

Permalink
Merge pull request #138 from RWTH-EBC/137_subscription_update
Browse files Browse the repository at this point in the history
feat: compare subscriptions for different dict formats
  • Loading branch information
FWuellhorst authored Feb 5, 2024
2 parents a263c55 + 56dbd45 commit 5a97e4f
Show file tree
Hide file tree
Showing 4 changed files with 334 additions and 34 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#### v0.3.1
- add tutorial for protected endpoint with bearer authentication ([#208](https://github.com/RWTH-EBC/FiLiP/issues/208))
- fix: compare subscriptions to prevent duplicated notifications @FWuellhorst, @RCX112 ([#138](https://github.com/RWTH-EBC/FiLiP/pull/138))
- update pandas version to `~=2.1.4` for `python>=3.9` ([#231](https://github.com/RWTH-EBC/FiLiP/pull/231))
- fix: wrong msg in iotac post device ([#214](https://github.com/RWTH-EBC/FiLiP/pull/214))

Expand Down
65 changes: 63 additions & 2 deletions filip/clients/ngsi_v2/cb.py
Original file line number Diff line number Diff line change
Expand Up @@ -1165,9 +1165,13 @@ def post_subscription(self,
"""
existing_subscriptions = self.get_subscription_list()

sub_hash = subscription.model_dump_json(include={'subject', 'notification'})
sub_dict = subscription.model_dump(include={'subject',
'notification'})
for ex_sub in existing_subscriptions:
if sub_hash == ex_sub.model_dump_json(include={'subject', 'notification'}):
if self._subscription_dicts_are_equal(
sub_dict,
ex_sub.model_dump(include={'subject', 'notification'})
):
self.logger.info("Subscription already exists")
if update:
self.logger.info("Updated subscription")
Expand Down Expand Up @@ -1659,6 +1663,7 @@ def does_entity_exist(self,
raise
return False


def patch_entity(self,
entity: ContextEntity,
old_entity: Optional[ContextEntity] = None,
Expand Down Expand Up @@ -1785,6 +1790,62 @@ def patch_entity(self,
if update_needed:
self.update_entity(update_entity)

def _subscription_dicts_are_equal(self, first: dict, second: dict):
"""
Check if two dictionaries and all sub-dictionaries are equal.
Logs a warning if the keys are not equal, but ignores the
comparison of such keys.
Args:
first dict: Dictionary of first subscription
second dict: Dictionary of second subscription
Returns:
True if equal, else False
"""

def _value_is_not_none(value):
"""
Recursive function to check if a value equals none.
If the value is a dict and any value of the dict is not none,
the value is not none.
If the value is a list and any item is not none, the value is not none.
If it's neither dict nore list, bool is used.
"""
if isinstance(value, dict):
return any([_value_is_not_none(value=_v)
for _v in value.values()])
if isinstance(value, list):
return any([_value_is_not_none(value=_v)for _v in value])
else:
return bool(value)
if first.keys() != second.keys():
warnings.warn(
"Subscriptions contain a different set of fields. "
"Only comparing to new fields of the new one."
)
for k, v in first.items():
ex_value = second.get(k, None)
if isinstance(v, dict) and isinstance(ex_value, dict):
equal = self._subscription_dicts_are_equal(v, ex_value)
if equal:
continue
else:
return False
if not _value_is_not_none(v) or not _value_is_not_none(ex_value):
warnings.warn(
"Different field found:{"
f"{k}: ({v}, {ex_value})"
"}"
)
if v != ex_value:
self.logger.debug(f"Not equal fields for key {k}: ({v}, {ex_value})")
if not _value_is_not_none(v) and not _value_is_not_none(ex_value) or k == "timesSent":
continue
return False
return True


#
#
# def check_duplicate_subscription(self, subscription_body, limit: int = 20):
Expand Down
5 changes: 5 additions & 0 deletions filip/models/ngsi_v2/subscriptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ class Notification(BaseModel):
be included.
"""
model_config = ConfigDict(validate_assignment=True)
timesSent: Optional[Any] = Field(
default=None,
description="Not editable, only present in GET operations. "
"Number of notifications sent due to this subscription."
)
http: Optional[Http] = Field(
default=None,
description='It is used to convey parameters for notifications '
Expand Down
Loading

0 comments on commit 5a97e4f

Please sign in to comment.