def test_atomic_update(self): self.assertEquals( modify_modlist({"a":["val1", "val2"]}, {"a":["val2", "val3"]}, True), [(MOD_DELETE, "a", "val1"), (MOD_ADD, "a", "val3")]) self.assertEquals( modify_modlist({"a":["val1"]}, {}, True), [(MOD_DELETE, "a", "val1")])
def save(self, atomic=False): """ Attempt to save this object to the server. Params: - atomic: if supplied and true, force explicit value replacements, which will fail if the data has changed on the server. """ if self._ldap.is_dry_run(): #Save the changed attributes as being "clean" self._origattrs = self._attrs.copy() return #Check if uid has changed. If so, rename new = self._attrs.copy() old = self._origattrs.copy() #Get the field that is used to calculate the RDN rdn_field = self._get_rdn_field() #Remove it from the attributes to change, rename will do it instead if new.has_key(rdn_field): del new[rdn_field] if old.has_key(rdn_field): del old[rdn_field] #If we changed a field that is used in the DN, we need to detect it # and perform a rename #Generate the full attr=value,attr=value strings for the rdn field olduid = self._get_rdn(orig=True) newuid = self._get_rdn(orig=False) #Perform the rename if the value has changed if olduid != newuid: self._rename(newuid) #Update values on the server if we changed other attributes if new != old: mod = modify_modlist(old, new, atomic) if mod: self._ldap.modify(self._dn, mod) #Save the changed attributes as being "clean" self._origattrs = self._attrs.copy()
def test_normal_update(self): self.assertEquals( modify_modlist({"a":["val1", "val2"]}, {"a":["val2", "val3"]}), [(MOD_REPLACE, "a", ["val2", "val3"])])
def save(self, atomic=False, preserve_rdn=False): """ Attempt to save this object to the server. Params: - atomic: force explicit attribute value replacements, which will fail if the data has changed on the server. - preserve_rdn: attempt to keep the rdn format """ new = self._attrs.copy() old = self._origattrs.copy() # Generate new rdn rdn_field = self._get_rdn_field() dn_parts = ldap.dn.str2dn(self.dn) cur_rdn = ldap.dn.str2dn(self.dn)[0] new_rdn = [] if preserve_rdn: for attr, value, atype in cur_rdn: if not new.get(attr): continue # Make sure the current values are in the "old" values if not value in old.get(attr, []): old.setdefault(attr, []).append(value) if value in new[attr]: new_rdn.append((attr, value, atype)) else: new_rdn.append((attr, new[attr][0], atype)) if not new_rdn: if not new.get(rdn_field): raise Exception("No suitable rdn value") else: new_rdn.append((rdn_field, new[rdn_field][0], 1)) if cur_rdn != new_rdn: delold = int(self._ldap.require_delold) try: self._ldap.rename(self.dn, ldap.dn.dn2str([new_rdn]), newsuperior=None, delold=delold) except ldap.ALREADY_EXISTS: raise DNConflict("DNConflict when changing rdn of {0} to {1}" .format(self.dn, new_rdn)) else: self._dn = ldap.dn.dn2str([new_rdn] + dn_parts[1:]) # Since rename with delold=0 will modify the object with the # new values, we have to add them to the "old" to prevent a # "double add". If delold=1, we remove from old and new to # prevent further changes for key, val, _ in new_rdn: if delold: old.pop(key, None) new.pop(key, None) else: attrval = old.setdefault(key, []) if val not in attrval: attrval.append(val) #Update values on the server if we changed other attributes if new != old: mod = modify_modlist(old, new, atomic) if mod: self._ldap.modify(self._dn, mod) #Save the changed attributes as being "clean" self._origattrs = self._attrs.copy()