diff --git a/ldapom/connection.py b/ldapom/connection.py index b6fdda0..66ac071 100644 --- a/ldapom/connection.py +++ b/ldapom/connection.py @@ -402,20 +402,16 @@ def save(self, entry): raise error.LDAPomError("Cannot save without attributes " "previously fetched or set.") - # Temporary attribute set that will contain deleted attributes as - # LDAPAttribute objects without any values. - save_attributes = entry.attributes.copy() - if entry_exists: - deleted_attribute_names = entry._old_attribute_names.difference( - [a.name for a in entry.attributes]) - for name in deleted_attribute_names: - attribute_type = self.get_attribute_type(name) - save_attributes.add(attribute_type(name)) - - if not entry_exists: - # Don't try to save empty attributes as this fails if the entry - # does not exist on the server yet. - save_attributes = filter(lambda a: a._values > 0, save_attributes) + # remove empty attributes as ldap_add_ext_s can't handle them + is_empty = lambda attr: len(attr._get_ldap_values()) > 0 + save_attributes = set(filter(is_empty, entry.attributes)) + + # add deleted attributes as empty attributes (LDAPAttribute objects without any values) + deleted_attribute_names = entry._old_attribute_names.difference( + [a.name for a in save_attributes]) + for name in deleted_attribute_names: + attribute_type = self.get_attribute_type(name) + save_attributes.add(attribute_type(name)) # Keep around references to pointers to owned memory with data that is # still needed. @@ -444,7 +440,7 @@ def save(self, entry): mods[i] = mod mods[len(save_attributes)] = ffi.NULL - if entry_exists: + if entry.exists(): err = ldap.ldap_modify_ext_s(self._ld, compat._encode_utf8(entry.dn), mods, diff --git a/ldapom/entry.py b/ldapom/entry.py index 75df7f2..7072c42 100644 --- a/ldapom/entry.py +++ b/ldapom/entry.py @@ -25,7 +25,7 @@ def __init__(self, connection, dn, attributes=None): super(LDAPEntry, self).__setattr__('attributes', set(attributes) if attributes is not None else None) super(LDAPEntry, self).__setattr__('_old_attribute_names', - set([a.name for a in attributes]) if attributes else None) + set([a.name for a in attributes]) if attributes else set()) ## Expose dn as a ready-only property dn = property(lambda self: self._dn)