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