From 5a5deff12838a29e3388b45826f3dfc33b31595f Mon Sep 17 00:00:00 2001 From: Jonathan Moyes Date: Wed, 9 Oct 2024 16:46:46 -0600 Subject: [PATCH] save(): set omit_null_props=True, or list of keys to omit from request --- odata/context.py | 14 +++++++------- odata/service.py | 4 ++-- odata/state.py | 33 ++++++++++++++++++++++++++------- 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/odata/context.py b/odata/context.py index 6cc8441..9ec5d1b 100644 --- a/odata/context.py +++ b/odata/context.py @@ -49,7 +49,7 @@ def delete(self, entity): entity.__odata__.persisted = False self.log.info(u'Success') - def save(self, entity, force_refresh=True, extra_headers=None): + def save(self, entity, force_refresh=True, extra_headers=None, omit_null_props=[]): """ Creates a POST or PATCH call to the service. If the entity already has a primary key, an update is called. Otherwise the entity is inserted @@ -63,14 +63,14 @@ def save(self, entity, force_refresh=True, extra_headers=None): """ if self.is_entity_saved(entity): - self._update_existing(entity, force_refresh=force_refresh, extra_headers=extra_headers) + self._update_existing(entity, force_refresh=force_refresh, extra_headers=extra_headers, omit_null_props=omit_null_props) else: - self._insert_new(entity) + self._insert_new(entity, omit_null_props=omit_null_props) def is_entity_saved(self, entity): return entity.__odata__.persisted - def _insert_new(self, entity): + def _insert_new(self, entity, omit_null_props=[]): """ Creates a POST call to the service, sending the complete new entity @@ -84,7 +84,7 @@ def _insert_new(self, entity): self.log.info(u'Saving new entity') es = entity.__odata__ - insert_data = es.data_for_insert() + insert_data = es.data_for_insert(omit_null_props) saved_data = self.connection.execute_post(url, insert_data) es.reset() es.connection = self.connection @@ -95,7 +95,7 @@ def _insert_new(self, entity): self.log.info(u'Success') - def _update_existing(self, entity, force_refresh=True, extra_headers=None): + def _update_existing(self, entity, force_refresh=True, extra_headers=None, omit_null_props=[]): """ Creates a PATCH call to the service, sending only the modified values @@ -106,7 +106,7 @@ def _update_existing(self, entity, force_refresh=True, extra_headers=None): msg = 'Cannot update Entity that does not belong to EntitySet: {0}'.format(entity) raise ODataError(msg) - patch_data = es.data_for_update() + patch_data = es.data_for_update(omit_null_props) if len([i for i in patch_data if not i.startswith('@')]) == 0: self.log.debug(u'Nothing to update: {0}'.format(entity)) diff --git a/odata/service.py b/odata/service.py index 9c2fb0a..e94b53a 100644 --- a/odata/service.py +++ b/odata/service.py @@ -244,7 +244,7 @@ def delete(self, entity): """ return self.default_context.delete(entity) - def save(self, entity, force_refresh=True): + def save(self, entity, force_refresh=True, omit_null_props=[]): """ Creates a POST or PATCH call to the service. If the entity already has a primary key, an update is called. Otherwise the entity is inserted @@ -254,4 +254,4 @@ def save(self, entity, force_refresh=True): :param force_refresh: Read full entity data again from service after PATCH call :raises ODataConnectionError: Invalid data or serverside error. Server returned an HTTP error code """ - return self.default_context.save(entity, force_refresh=force_refresh) + return self.default_context.save(entity, force_refresh=force_refresh, omit_null_props=omit_null_props) diff --git a/odata/state.py b/odata/state.py index 2162f0e..bf02748 100644 --- a/odata/state.py +++ b/odata/state.py @@ -188,10 +188,10 @@ def set_property_dirty(self, prop): if prop.name not in self.dirty: self.dirty.append(prop.name) - def data_for_insert(self): - return self._clean_new_entity(self.entity) + def data_for_insert(self, omit_null_props=[]): + return self._clean_new_entity(self.entity, omit_null_props) - def data_for_update(self): + def data_for_update(self, omit_null_props=[]): update_data = OrderedDict() update_data['@odata.type'] = self.entity.__odata_type__ @@ -211,9 +211,19 @@ def data_for_update(self): update_data[key] = [i.__odata__.id for i in value] else: update_data[key] = value.__odata__.id - return update_data - - def _clean_new_entity(self, entity): + + update_data_filtered = {} + for prop_name, prop in update_data.items(): + if omit_null_props is True or prop_name in omit_null_props: + # Should omit unless not None + if prop is None: + # Omit from request + continue + update_data_filtered[prop_name] = prop + + return update_data_filtered + + def _clean_new_entity(self, entity, omit_null_props=[]): """:type entity: odata.entity.EntityBase """ insert_data = OrderedDict() insert_data['@odata.type'] = entity.__odata_type__ @@ -262,4 +272,13 @@ def _clean_new_entity(self, entity): else: insert_data[prop.name] = self._clean_new_entity(value) - return insert_data + insert_data_filtered = {} + for prop_name, prop in insert_data.items(): + if omit_null_props is True or prop_name in omit_null_props: + # Should omit unless not None + if prop is None: + # Omit from request + continue + insert_data_filtered[prop_name] = prop + + return insert_data_filtered