ldap.modlist.modifyModlist(): New key-word argument
case_ignore_attr_types used to define attribute types for which comparison of old and new values should be case-insensitive
This commit is contained in:
		
							
								
								
									
										126
									
								
								Lib/ldap/modlist.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								Lib/ldap/modlist.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,126 @@ | |||||||
|  | """ | ||||||
|  | ldap.modlist - create add/modify modlist's | ||||||
|  |  | ||||||
|  | See http://www.python-ldap.org/ for details. | ||||||
|  |  | ||||||
|  | $Id: modlist.py,v 1.18 2011/06/06 13:07:38 stroeder Exp $ | ||||||
|  |  | ||||||
|  | Python compability note: | ||||||
|  | This module is known to work with Python 2.0+ but should work | ||||||
|  | with Python 1.5.2 as well. | ||||||
|  | """ | ||||||
|  |  | ||||||
|  | from ldap import __version__ | ||||||
|  |  | ||||||
|  | import string,ldap,ldap.cidict | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def list_dict(l,case_insensitive=0): | ||||||
|  |   """ | ||||||
|  |   return a dictionary with all items of l being the keys of the dictionary | ||||||
|  |  | ||||||
|  |   If argument case_insensitive is non-zero ldap.cidict.cidict will be | ||||||
|  |   used for case-insensitive string keys | ||||||
|  |   """ | ||||||
|  |   if case_insensitive: | ||||||
|  |     d = ldap.cidict.cidict() | ||||||
|  |   else: | ||||||
|  |     d = {} | ||||||
|  |   for i in l: | ||||||
|  |     d[i]=None | ||||||
|  |   return d | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def addModlist(entry,ignore_attr_types=None): | ||||||
|  |   """Build modify list for call of method LDAPObject.add()""" | ||||||
|  |   ignore_attr_types = list_dict(map(string.lower,(ignore_attr_types or []))) | ||||||
|  |   modlist = [] | ||||||
|  |   for attrtype in entry.keys(): | ||||||
|  |     if ignore_attr_types.has_key(string.lower(attrtype)): | ||||||
|  |       # This attribute type is ignored | ||||||
|  |       continue | ||||||
|  |     # Eliminate empty attr value strings in list | ||||||
|  |     attrvaluelist = filter(lambda x:x!=None,entry[attrtype]) | ||||||
|  |     if attrvaluelist: | ||||||
|  |       modlist.append((attrtype,entry[attrtype])) | ||||||
|  |   return modlist # addModlist() | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def modifyModlist( | ||||||
|  |   old_entry,new_entry,ignore_attr_types=None,ignore_oldexistent=0,case_ignore_attr_types=None | ||||||
|  | ): | ||||||
|  |   """ | ||||||
|  |   Build differential modify list for calling LDAPObject.modify()/modify_s() | ||||||
|  |  | ||||||
|  |   old_entry | ||||||
|  |       Dictionary holding the old entry | ||||||
|  |   new_entry | ||||||
|  |       Dictionary holding what the new entry should be | ||||||
|  |   ignore_attr_types | ||||||
|  |       List of attribute type names to be ignored completely | ||||||
|  |   ignore_oldexistent | ||||||
|  |       If non-zero attribute type names which are in old_entry | ||||||
|  |       but are not found in new_entry at all are not deleted. | ||||||
|  |       This is handy for situations where your application | ||||||
|  |       sets attribute value to '' for deleting an attribute. | ||||||
|  |       In most cases leave zero. | ||||||
|  |   case_ignore_attr_types | ||||||
|  |       List of attribute type names for which comparison will be made | ||||||
|  |       case-insensitive | ||||||
|  |   """ | ||||||
|  |   ignore_attr_types = list_dict(map(string.lower,(ignore_attr_types or []))) | ||||||
|  |   case_ignore_attr_types = list_dict(map(string.lower,(case_ignore_attr_types or []))) | ||||||
|  |   modlist = [] | ||||||
|  |   attrtype_lower_map = {} | ||||||
|  |   for a in old_entry.keys(): | ||||||
|  |     attrtype_lower_map[string.lower(a)]=a | ||||||
|  |   for attrtype in new_entry.keys(): | ||||||
|  |     attrtype_lower = string.lower(attrtype) | ||||||
|  |     if ignore_attr_types.has_key(attrtype_lower): | ||||||
|  |       # This attribute type is ignored | ||||||
|  |       continue | ||||||
|  |     # Filter away null-strings | ||||||
|  |     new_value = filter(lambda x:x!=None,new_entry[attrtype]) | ||||||
|  |     if attrtype_lower_map.has_key(attrtype_lower): | ||||||
|  |       old_value = old_entry.get(attrtype_lower_map[attrtype_lower],[]) | ||||||
|  |       old_value = filter(lambda x:x!=None,old_value) | ||||||
|  |       del attrtype_lower_map[attrtype_lower] | ||||||
|  |     else: | ||||||
|  |       old_value = [] | ||||||
|  |     if not old_value and new_value: | ||||||
|  |       # Add a new attribute to entry | ||||||
|  |       modlist.append((ldap.MOD_ADD,attrtype,new_value)) | ||||||
|  |     elif old_value and new_value: | ||||||
|  |       # Replace existing attribute | ||||||
|  |       replace_attr_value = len(old_value)!=len(new_value) | ||||||
|  |       if not replace_attr_value: | ||||||
|  |         case_insensitive = case_ignore_attr_types.has_key(attrtype_lower) | ||||||
|  |         old_value_dict=list_dict(old_value,case_insensitive) | ||||||
|  |         new_value_dict=list_dict(new_value,case_insensitive) | ||||||
|  |         delete_values = [] | ||||||
|  |         for v in old_value: | ||||||
|  |           if not new_value_dict.has_key(v): | ||||||
|  |             replace_attr_value = 1 | ||||||
|  |             break | ||||||
|  |         add_values = [] | ||||||
|  |         if not replace_attr_value: | ||||||
|  |           for v in new_value: | ||||||
|  |             if not old_value_dict.has_key(v): | ||||||
|  |               replace_attr_value = 1 | ||||||
|  |               break | ||||||
|  |       if replace_attr_value: | ||||||
|  |         modlist.append((ldap.MOD_DELETE,attrtype,None)) | ||||||
|  |         modlist.append((ldap.MOD_ADD,attrtype,new_value)) | ||||||
|  |     elif old_value and not new_value: | ||||||
|  |       # Completely delete an existing attribute | ||||||
|  |       modlist.append((ldap.MOD_DELETE,attrtype,None)) | ||||||
|  |   if not ignore_oldexistent: | ||||||
|  |     # Remove all attributes of old_entry which are not present | ||||||
|  |     # in new_entry at all | ||||||
|  |     for a in attrtype_lower_map.keys(): | ||||||
|  |       if ignore_attr_types.has_key(a): | ||||||
|  |         # This attribute type is ignored | ||||||
|  |         continue | ||||||
|  |       attrtype = attrtype_lower_map[a] | ||||||
|  |       modlist.append((ldap.MOD_DELETE,attrtype,None)) | ||||||
|  |   return modlist # modifyModlist() | ||||||
							
								
								
									
										137
									
								
								Tests/Lib/ldap/test_modlist.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								Tests/Lib/ldap/test_modlist.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,137 @@ | |||||||
|  | """ | ||||||
|  | Tests for module ldap.modlist | ||||||
|  | """ | ||||||
|  |  | ||||||
|  | import ldap | ||||||
|  |  | ||||||
|  | from ldap.modlist import addModlist,modifyModlist | ||||||
|  |    | ||||||
|  | print '\nTesting function addModlist():' | ||||||
|  | addModlist_tests = [ | ||||||
|  |   ( | ||||||
|  |     { | ||||||
|  |       'objectClass':['person','pilotPerson'], | ||||||
|  |       'cn':['Michael Str\303\266der','Michael Stroeder'], | ||||||
|  |       'sn':['Str\303\266der'], | ||||||
|  |       'dummy1':[], | ||||||
|  |       'dummy2':['2'], | ||||||
|  |       'dummy3':[''], | ||||||
|  |     }, | ||||||
|  |     [ | ||||||
|  |       ('objectClass',['person','pilotPerson']), | ||||||
|  |       ('cn',['Michael Str\303\266der','Michael Stroeder']), | ||||||
|  |       ('sn',['Str\303\266der']), | ||||||
|  |       ('dummy2',['2']), | ||||||
|  |       ('dummy3',['']), | ||||||
|  |     ] | ||||||
|  |   ), | ||||||
|  | ] | ||||||
|  | for entry,test_modlist in addModlist_tests: | ||||||
|  |   test_modlist.sort() | ||||||
|  |   result_modlist = addModlist(entry) | ||||||
|  |   result_modlist.sort() | ||||||
|  |   if test_modlist!=result_modlist: | ||||||
|  |     print 'addModlist(%s) returns\n%s\ninstead of\n%s.' % ( | ||||||
|  |       repr(entry),repr(result_modlist),repr(test_modlist) | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  | print '\nTesting function modifyModlist():' | ||||||
|  | modifyModlist_tests = [ | ||||||
|  |  | ||||||
|  |   ( | ||||||
|  |     { | ||||||
|  |       'objectClass':['person','pilotPerson'], | ||||||
|  |       'cn':['Michael Str\303\266der','Michael Stroeder'], | ||||||
|  |       'sn':['Str\303\266der'], | ||||||
|  |       'enum':['a','b','c'], | ||||||
|  |       'c':['DE'], | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       'objectClass':['person','inetOrgPerson'], | ||||||
|  |       'cn':['Michael Str\303\266der','Michael Stroeder'], | ||||||
|  |       'sn':[], | ||||||
|  |       'enum':['a','b','d'], | ||||||
|  |       'mail':['michael@stroeder.com'], | ||||||
|  |     }, | ||||||
|  |     [], | ||||||
|  |     [ | ||||||
|  |       (ldap.MOD_DELETE,'objectClass',None), | ||||||
|  |       (ldap.MOD_ADD,'objectClass',['person','inetOrgPerson']), | ||||||
|  |       (ldap.MOD_DELETE,'c',None), | ||||||
|  |       (ldap.MOD_DELETE,'sn',None), | ||||||
|  |       (ldap.MOD_ADD,'mail',['michael@stroeder.com']), | ||||||
|  |       (ldap.MOD_DELETE,'enum',None), | ||||||
|  |       (ldap.MOD_ADD,'enum',['a','b','d']), | ||||||
|  |     ] | ||||||
|  |   ), | ||||||
|  |  | ||||||
|  |   ( | ||||||
|  |     { | ||||||
|  |       'c':['DE'], | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       'c':['FR'], | ||||||
|  |     }, | ||||||
|  |     [], | ||||||
|  |     [ | ||||||
|  |       (ldap.MOD_DELETE,'c',None), | ||||||
|  |       (ldap.MOD_ADD,'c',['FR']), | ||||||
|  |     ] | ||||||
|  |   ), | ||||||
|  |  | ||||||
|  |   # Now a weird test-case for catching all possibilities | ||||||
|  |   # of removing an attribute with MOD_DELETE,attr_type,None | ||||||
|  |   ( | ||||||
|  |     { | ||||||
|  |       'objectClass':['person'], | ||||||
|  |       'cn':[None], | ||||||
|  |       'sn':[''], | ||||||
|  |       'c':['DE'], | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       'objectClass':[], | ||||||
|  |       'cn':[], | ||||||
|  |       'sn':[None], | ||||||
|  |     }, | ||||||
|  |     [], | ||||||
|  |     [ | ||||||
|  |       (ldap.MOD_DELETE,'c',None), | ||||||
|  |       (ldap.MOD_DELETE,'objectClass',None), | ||||||
|  |       (ldap.MOD_DELETE,'sn',None), | ||||||
|  |     ] | ||||||
|  |   ), | ||||||
|  |  | ||||||
|  |   ( | ||||||
|  |     { | ||||||
|  |       'objectClass':['person'], | ||||||
|  |       'cn':['Michael Str\303\266der','Michael Stroeder'], | ||||||
|  |       'sn':['Str\303\266der'], | ||||||
|  |       'enum':['a','b','C'], | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       'objectClass':['Person'], | ||||||
|  |       'cn':['Michael Str\303\266der','Michael Stroeder'], | ||||||
|  |       'sn':[], | ||||||
|  |       'enum':['a','b','c'], | ||||||
|  |     }, | ||||||
|  |     ['objectClass'], | ||||||
|  |     [ | ||||||
|  |       (ldap.MOD_DELETE,'sn',None), | ||||||
|  |       (ldap.MOD_DELETE,'enum',None), | ||||||
|  |       (ldap.MOD_ADD,'enum',['a','b','c']), | ||||||
|  |     ] | ||||||
|  |   ), | ||||||
|  |  | ||||||
|  | ] | ||||||
|  | for old_entry,new_entry,case_ignore_attr_types,test_modlist in modifyModlist_tests: | ||||||
|  |   test_modlist.sort() | ||||||
|  |   result_modlist = modifyModlist(old_entry,new_entry,case_ignore_attr_types=case_ignore_attr_types) | ||||||
|  |   result_modlist.sort() | ||||||
|  |  | ||||||
|  |   if test_modlist!=result_modlist: | ||||||
|  |     print 'modifyModlist(%s,%s) returns\n%s\ninstead of\n%s.' % ( | ||||||
|  |       repr(old_entry), | ||||||
|  |       repr(new_entry), | ||||||
|  |       repr(result_modlist), | ||||||
|  |       repr(test_modlist) | ||||||
|  |     ) | ||||||
		Reference in New Issue
	
	Block a user
	 stroeder
					stroeder