diff --git a/src/ldaptools/ldif_utils.py b/src/ldaptools/ldif_utils.py index 714fa08..21c324b 100644 --- a/src/ldaptools/ldif_utils.py +++ b/src/ldaptools/ldif_utils.py @@ -2,7 +2,8 @@ import ldap import ldif from ldap.dn import dn2str -from ldaptools.utils import idict, str2dn, bytes2str_entry, str2bytes_entry +from ldaptools.utils import idict, str2dn, str2bytes_entry, bytes2str_entry + class AddError(Exception): pass diff --git a/src/ldaptools/utils.py b/src/ldaptools/utils.py index c3c5370..d0e6397 100644 --- a/src/ldaptools/utils.py +++ b/src/ldaptools/utils.py @@ -1,5 +1,5 @@ import ldap.dn -from six import string_types +import six # Copied from http://code.activestate.com/recipes/194371-case-insensitive-strings/ @@ -76,17 +76,19 @@ class idict(dict): dict.__init__(self) self._keydict = {} # not self.__keydict because I want it to be easily accessible by subclasses for entry in indict: - self[entry] = indict[entry] # not dict.__setitem__(self, entry, indict[entry]) becasue this causes errors (phantom entries) where indict has overlapping keys + # not dict.__setitem__(self, entry, indict[entry]) becasue this + # causes errors (phantom entries) where indict has overlapping keys + self[entry] = indict[entry] def findkey(self, item): """A caseless way of checking if a key exists or not. It returns None or the correct key.""" - if not isinstance(item, string_types): + if not isinstance(item, six.string_types): raise TypeError('Keywords for this object must be strings. You supplied %s' % type(item)) key = item.lower() try: return self._keydict[key] - except: + except Exception: return None def changekey(self, item): @@ -148,13 +150,13 @@ class idict(dict): def has_key(self, item): """A case insensitive test for keys.""" - if not isinstance(item, string_types): + if not isinstance(item, six.string_types): return False # should never have a non-string key return item.lower() in self._keydict # does the key exist def __contains__(self, item): """A case insensitive __contains__.""" - if not isinstance(item, string_types): + if not isinstance(item, six.string_types): return False # should never have a non-string key return item.lower() in self._keydict # does the key exist @@ -202,14 +204,14 @@ class idict(dict): def __eq__(self, other): for k in self: if k not in other: - return False + return False if self[k] != other[k]: - return False + return False for k in other: if k not in self: - return False + return False if self[k] != other[k]: - return False + return False return True def __ne__(self, other): @@ -240,15 +242,23 @@ def str2dn(s): return tuple(map(tuple, ldap.dn.str2dn(s))) +def decode_if_possible(s): + try: + return s.decode('utf-8') + except UnicodeDecodeError: + return s + + def bytes2str_entry(entry): str_entry = {} for key, values in entry.items(): - str_entry[key] = [v.decode('utf-8') if isinstance(v, bytes) else v for v in values] + str_entry[key] = [decode_if_possible(v) if isinstance(v, bytes) else v for v in values] return str_entry + def str2bytes_entry(entry): bytes_entry = {} for key, values in entry.items(): - bytes_entry[key] = [v.encode('utf-8') if isinstance(v, string_types) else v for v in values] + bytes_entry[key] = [v.encode('utf-8') if isinstance(v, six.text_type) else v for v in values] return bytes_entry diff --git a/tests/test_ldif_utils.py b/tests/test_ldif_utils.py index 0ed157c..fd23124 100644 --- a/tests/test_ldif_utils.py +++ b/tests/test_ldif_utils.py @@ -9,9 +9,11 @@ from ldaptools.ldif_utils import ListLDIFParser def test_ldifparser(): parser = ListLDIFParser(StringIO('''dn: o=orga objectClass: organization +jpegPhoto:: E+o9UYDeUDNblBzchRD/1+2HMdI= ''')) parser.parse() assert len(list(parser)) == 1 assert list(parser)[0][0] == 'o=orga' - assert list(parser)[0][1] == {'objectClass': ['organization']} + assert list(parser)[0][1]['objectClass'] == ['organization'] + assert list(parser)[0][1]['jpegPhoto']