summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Dennis <jdennis@redhat.com>2011-08-03 19:26:19 -0400
committerRob Crittenden <rcritten@redhat.com>2011-08-16 23:27:46 -0400
commit97f0671ce9dd1d260fea4e95f6e6e017a1ef1048 (patch)
treed31677862b116cca6e648009ae1816b0803fa1bf
parentb13899ebc523cbb5f1ec09cc78ac92d696ee966f (diff)
downloadfreeipa-97f0671ce9dd1d260fea4e95f6e6e017a1ef1048.zip
freeipa-97f0671ce9dd1d260fea4e95f6e6e017a1ef1048.tar.gz
freeipa-97f0671ce9dd1d260fea4e95f6e6e017a1ef1048.tar.xz
ticket 1569 - Test DN object non-latin Unicode support
The DN unittest was lacking a test for i18n. The unittest was updated to store "Hello" in Arabic with both utf-8 and unicode and verify the values could be properly retrieved and converted to dn string syntax. During the testing a few problems were discovered and corrected. * passing in utf-8 caused an ASCII decode error becuase of Python's silly default encoding of ASCII. The fix was to explictly use the utf-8 codec. * there were a couple of places where encode/decode were not called correctly. * the internal attr and value members of the AVA class were renamed to explicitly show they are stored as unicode. Of course the unittest was updated as well.
-rw-r--r--ipalib/dn.py38
-rw-r--r--tests/test_ipalib/test_dn.py94
2 files changed, 116 insertions, 16 deletions
diff --git a/ipalib/dn.py b/ipalib/dn.py
index 0eac711..dc3119d 100644
--- a/ipalib/dn.py
+++ b/ipalib/dn.py
@@ -19,8 +19,11 @@
from ldap.dn import str2dn, dn2str
from ldap import DECODING_ERROR
+import codecs
import sys
+utf8_codec = codecs.lookup('utf-8')
+
__all__ = ['AVA', 'RDN', 'DN']
'''
@@ -519,44 +522,47 @@ class AVA(object):
if not isinstance(value, basestring):
raise TypeError("value must be basestring, got %s instead" % value.__class__.__name__)
- attr = attr.decode('utf-8')
- value = value.decode('utf-8')
-
- self._attr = attr
- self._value = value
+ self.attr = attr
+ self.value = value
def _get_attr(self):
- return self._attr
+ return self._attr_unicode
def _set_attr(self, new_attr):
if not isinstance(new_attr, basestring):
raise TypeError("attr must be basestring, got %s instead" % new_attr.__class__.__name__)
- self._attr = new_attr
+ if isinstance(new_attr, unicode):
+ self._attr_unicode = new_attr
+ else:
+ self._attr_unicode = utf8_codec.decode(new_attr)[0]
attr = property(_get_attr, _set_attr)
def _get_value(self):
- return self._value
+ return self._value_unicode
def _set_value(self, new_value):
if not isinstance(new_value, basestring):
raise TypeError("value must be basestring, got %s instead" % new_value.__class__.__name__)
- self._value = new_value
+ if isinstance(new_value, unicode):
+ self._value_unicode = new_value
+ else:
+ self._value_unicode = utf8_codec.decode(new_value)[0]
value = property(_get_value, _set_value)
def _to_openldap(self):
- return [[(self._attr.encode('utf-8'), self._value.encode('utf-8'), self.flags)]]
+ return [[(self._attr_unicode.encode('utf-8'), self._value_unicode.encode('utf-8'), self.flags)]]
def __str__(self):
return dn2str(self._to_openldap())
def __getitem__(self, key):
if isinstance(key, basestring):
- if key == self._attr:
- return self._value
+ if key == self._attr_unicode:
+ return self._value_unicode
raise KeyError("\"%s\" not found in %s" % (key, self.__str__()))
else:
raise TypeError("unsupported type for AVA indexing, must be basestring; not %s" % \
@@ -578,8 +584,8 @@ class AVA(object):
if not isinstance(other, self.__class__):
raise TypeError("expected AVA but got %s" % (other.__class__.__name__))
- return self._attr.lower() == other.attr.lower() and \
- self._value.lower() == other.value.lower()
+ return self._attr_unicode.lower() == other.attr.lower() and \
+ self._value_unicode.lower() == other.value.lower()
def __cmp__(self, other):
'comparision is case insensitive, see __eq__ doc for explanation'
@@ -587,10 +593,10 @@ class AVA(object):
if not isinstance(other, self.__class__):
raise TypeError("expected AVA but got %s" % (other.__class__.__name__))
- result = cmp(self._attr.lower(), other.attr.lower())
+ result = cmp(self._attr_unicode.lower(), other.attr.lower())
if result != 0:
return result
- result = cmp(self._value.lower(), other.value.lower())
+ result = cmp(self._value_unicode.lower(), other.value.lower())
return result
class RDN(object):
diff --git a/tests/test_ipalib/test_dn.py b/tests/test_ipalib/test_dn.py
index f4aa0aa..04e442f 100644
--- a/tests/test_ipalib/test_dn.py
+++ b/tests/test_ipalib/test_dn.py
@@ -987,5 +987,99 @@ class TestEscapes(unittest.TestCase):
self.assertEqual(dn['cn'], self.privilege)
self.assertEqual(dn[0].value, self.privilege)
+class TestInternationalization(unittest.TestCase):
+ def setUp(self):
+ # Hello in Arabic
+ self.arabic_hello_utf8 = '\xd9\x85\xd9\x83\xd9\x8a\xd9\x84' + \
+ '\xd8\xb9\x20\xd9\x85\xd8\xa7\xd9' + \
+ '\x84\xd9\x91\xd8\xb3\xd9\x84\xd8\xa7'
+
+ self.arabic_hello_unicode = self.arabic_hello_utf8.decode('utf-8')
+
+ def test_i18n(self):
+ self.assertEqual(self.arabic_hello_utf8,
+ self.arabic_hello_unicode.encode('utf-8'))
+
+ # AVA's
+ # test attr i18n
+ ava1 = AVA(self.arabic_hello_unicode, 'foo')
+ self.assertIsInstance(ava1.attr, unicode)
+ self.assertIsInstance(ava1.value, unicode)
+ self.assertEqual(ava1.attr, self.arabic_hello_unicode)
+ self.assertEqual(str(ava1), self.arabic_hello_utf8+'=foo')
+
+ ava1 = AVA(self.arabic_hello_utf8, 'foo')
+ self.assertIsInstance(ava1.attr, unicode)
+ self.assertIsInstance(ava1.value, unicode)
+ self.assertEqual(ava1.attr, self.arabic_hello_unicode)
+ self.assertEqual(str(ava1), self.arabic_hello_utf8+'=foo')
+
+ # test value i18n
+ ava1 = AVA('cn', self.arabic_hello_unicode)
+ self.assertIsInstance(ava1.attr, unicode)
+ self.assertIsInstance(ava1.value, unicode)
+ self.assertEqual(ava1.value, self.arabic_hello_unicode)
+ self.assertEqual(str(ava1), 'cn='+self.arabic_hello_utf8)
+
+ ava1 = AVA('cn', self.arabic_hello_utf8)
+ self.assertIsInstance(ava1.attr, unicode)
+ self.assertIsInstance(ava1.value, unicode)
+ self.assertEqual(ava1.value, self.arabic_hello_unicode)
+ self.assertEqual(str(ava1), 'cn='+self.arabic_hello_utf8)
+
+ # RDN's
+ # test attr i18n
+ rdn1 = RDN((self.arabic_hello_unicode, 'foo'))
+ self.assertIsInstance(rdn1.attr, unicode)
+ self.assertIsInstance(rdn1.value, unicode)
+ self.assertEqual(rdn1.attr, self.arabic_hello_unicode)
+ self.assertEqual(str(rdn1), self.arabic_hello_utf8+'=foo')
+
+ rdn1 = RDN((self.arabic_hello_utf8, 'foo'))
+ self.assertIsInstance(rdn1.attr, unicode)
+ self.assertIsInstance(rdn1.value, unicode)
+ self.assertEqual(rdn1.attr, self.arabic_hello_unicode)
+ self.assertEqual(str(rdn1), self.arabic_hello_utf8+'=foo')
+
+ # test value i18n
+ rdn1 = RDN(('cn', self.arabic_hello_unicode))
+ self.assertIsInstance(rdn1.attr, unicode)
+ self.assertIsInstance(rdn1.value, unicode)
+ self.assertEqual(rdn1.value, self.arabic_hello_unicode)
+ self.assertEqual(str(rdn1), 'cn='+self.arabic_hello_utf8)
+
+ rdn1 = RDN(('cn', self.arabic_hello_utf8))
+ self.assertIsInstance(rdn1.attr, unicode)
+ self.assertIsInstance(rdn1.value, unicode)
+ self.assertEqual(rdn1.value, self.arabic_hello_unicode)
+ self.assertEqual(str(rdn1), 'cn='+self.arabic_hello_utf8)
+
+ # DN's
+ # test attr i18n
+ dn1 = DN((self.arabic_hello_unicode, 'foo'))
+ self.assertIsInstance(dn1[0].attr, unicode)
+ self.assertIsInstance(dn1[0].value, unicode)
+ self.assertEqual(dn1[0].attr, self.arabic_hello_unicode)
+ self.assertEqual(str(dn1), self.arabic_hello_utf8+'=foo')
+
+ dn1 = DN((self.arabic_hello_utf8, 'foo'))
+ self.assertIsInstance(dn1[0].attr, unicode)
+ self.assertIsInstance(dn1[0].value, unicode)
+ self.assertEqual(dn1[0].attr, self.arabic_hello_unicode)
+ self.assertEqual(str(dn1), self.arabic_hello_utf8+'=foo')
+
+ # test value i18n
+ dn1 = DN(('cn', self.arabic_hello_unicode))
+ self.assertIsInstance(dn1[0].attr, unicode)
+ self.assertIsInstance(dn1[0].value, unicode)
+ self.assertEqual(dn1[0].value, self.arabic_hello_unicode)
+ self.assertEqual(str(dn1), 'cn='+self.arabic_hello_utf8)
+
+ dn1 = DN(('cn', self.arabic_hello_utf8))
+ self.assertIsInstance(dn1[0].attr, unicode)
+ self.assertIsInstance(dn1[0].value, unicode)
+ self.assertEqual(dn1[0].value, self.arabic_hello_unicode)
+ self.assertEqual(str(dn1), 'cn='+self.arabic_hello_utf8)
+
if __name__ == '__main__':
unittest.main()