summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipalib/dn.py262
-rw-r--r--tests/test_ipalib/test_dn.py89
2 files changed, 211 insertions, 140 deletions
diff --git a/ipalib/dn.py b/ipalib/dn.py
index 47c66198e..1311b6ae0 100644
--- a/ipalib/dn.py
+++ b/ipalib/dn.py
@@ -19,7 +19,6 @@
from ldap.dn import str2dn, dn2str
from ldap import DECODING_ERROR
-from copy import deepcopy
import sys
__all__ = ['AVA', 'RDN', 'DN']
@@ -392,7 +391,7 @@ if container_dn in dn:
# (e.g. cmp()). The general rule is for objects supporting multiple
# values first their lengths are compared, then if the lengths match
# the respective components of each are pair-wise compared until one
-# is discovered to be non-equal
+# is discovered to be non-equal. The comparision is case insensitive.
Concatenation and In-Place Addition:
@@ -412,13 +411,35 @@ manipulate these objects.
'''
+def _adjust_indices(start, end, length):
+ 'helper to fixup start/end slice values'
+
+ if end > length:
+ end = length
+ elif end < 0:
+ end += length
+ if end < 0:
+ end = 0
+
+ if start < 0:
+ start += length
+ if start < 0:
+ start = 0
+
+ return start, end
+
class AVA(object):
'''
+ AVA(arg0, ...)
+
An AVA is an LDAP Attribute Value Assertion. It is convenient to think of
AVA's as a <attr,value> pair. AVA's are members of RDN's (Relative
Distinguished Name).
- The AVA constructor may be invoked with any of the following methods:
+ The AVA constructor is passed a sequence of args and a set of
+ keyword parameters used for configuration.
+
+ The arg sequence may be:
1) With 2 string (or unicode) arguments, the first argument will be the
attr, the 2nd the value.
@@ -454,14 +475,16 @@ class AVA(object):
AVA objects support equality testing and comparsion (e.g. cmp()). When they
are compared the attr is compared first, if the 2 attr's are equal then the
- values are compared.
+ values are compared. The comparision is case insensitive (because attr's map
+ to numeric OID's and their values derive from from the 'name' atribute type
+ (OID 2.5.4.41) whose EQUALITY MATCH RULE is caseIgnoreMatch.
The str method of an AVA returns the string representation in RFC 4514 DN
syntax with proper escaping.
'''
flags = 0
- def __init__(self, *args):
+ def __init__(self, *args, **kwds):
if len(args) == 1:
arg = args[0]
if isinstance(arg, basestring):
@@ -496,42 +519,84 @@ class AVA(object):
if not isinstance(value, basestring):
raise TypeError("value must be basestring, got %s instead" % value.__class__.__name__)
- self.attr = attr.decode('utf-8')
- self.value = value.decode('utf-8')
+ attr = attr.decode('utf-8')
+ value = value.decode('utf-8')
+
+ self._attr = attr
+ self._value = value
+
+ def _get_attr(self):
+ return self._attr
+
+ 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
+ attr = property(_get_attr, _set_attr)
+
+ def _get_value(self):
+ return self._value
+
+ 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
+
+ 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.encode('utf-8'), self._value.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:
+ return self._value
raise KeyError("\"%s\" not found in %s" % (key, self.__str__()))
else:
raise TypeError("unsupported type for AVA indexing, must be basestring; not %s" % \
(key.__class__.__name__))
def __eq__(self, other):
+ '''
+ The attr comparison is case insensitive because attr is
+ really an LDAP attribute type which means it's specified with
+ an OID (dotted number) and not a string. Since OID's are
+ numeric the human readable name which maps to the OID is not
+ significant in case.
+
+ The value comparison is also case insensitive because the all
+ attribute types used in a DN are derived from the 'name'
+ atribute type (OID 2.5.4.41) whose EQUALITY MATCH RULE is
+ caseIgnoreMatch.
+ '''
if not isinstance(other, self.__class__):
raise TypeError("expected AVA but got %s" % (other.__class__.__name__))
- return self.attr == other.attr and self.value == other.value
+ return self._attr.lower() == other.attr.lower() and \
+ self._value.lower() == other.value.lower()
def __cmp__(self, other):
+ 'comparision is case insensitive, see __eq__ doc for explanation'
+
if not isinstance(other, self.__class__):
raise TypeError("expected AVA but got %s" % (other.__class__.__name__))
- result = cmp(self.attr, other.attr)
- if result != 0: return result
- result = cmp(self.value, other.value)
+ result = cmp(self._attr.lower(), other.attr.lower())
+ if result != 0:
+ return result
+ result = cmp(self._value.lower(), other.value.lower())
return result
class RDN(object):
'''
+ RDN(arg0, ..., first_key_match=True)
+
An RDN is a LDAP Relative Distinguished Name. RDN's are members of DN's
(Distinguished Name). An RDN contains 1 or more AVA's. If the RDN contains
more than one AVA it is said to be a multi-valued RDN. When an RDN is
@@ -542,13 +607,12 @@ class RDN(object):
within an RDN). Single valued RDN's are the norm and thus the RDN
constructor has simple syntax for them.
- The RDN constructor may be invoked in a variety of different ways.
+ The RDN constructor is passed a sequence of args and a set of
+ keyword parameters used for configuration.
+
+ The constructor iterates though the sequence and adds AVA's to the RDN.
- * When two adjacent string (or unicode) argument appear together in the
- argument list they are taken to be the <attr,value> pair of an AVA. An AVA
- object is constructed and inserted into the RDN. Multiple pairs of strings
- arguments may appear in the argument list, each pair adds one additional AVA
- to the RDN.
+ The arg sequence may be:
* A 2-valued tuple or list denotes the <attr,value> pair of an AVA. The
first member is the attr and the second member is the value, both members
@@ -562,28 +626,26 @@ class RDN(object):
more AVA <attr,value> pairs. The parsing recognizes the DN syntax escaping
rules.
- Note, a DN syntax argument is distguished from AVA string pairs by testing
- to see if two strings appear adjacent in the argument list, if so those two
- strings are interpretted as an <attr,value> AVA pair and consumed.
+ * A AVA object, the AVA will be copied into the new RDN respecting
+ the constructors keyword configuration parameters.
- * A AVA object. Each AVA object in the argument list will be added to the RDN.
+ * A RDN object, the AVA's in the RDN are copied into the new RDN
+ respecting the constructors keyword configuration parameters.
Single AVA Examples:
- RDN('cn', 'Bob') # 2 adjacent strings yield 1 AVA
RDN(('cn', 'Bob')) # tuple yields 1 AVA
RDN('cn=Bob') # DN syntax with 1 AVA
RDN(AVA('cn', 'Bob')) # AVA object adds 1 AVA
Multiple AVA Examples:
- RDN('cn', 'Bob', 'ou', 'people') # 2 strings pairs yield 2 AVA's
RDN(('cn', 'Bob'),('ou', 'people')) # 2 tuples yields 2 AVA's
RDN('cn=Bob+ou=people') # DN syntax with 2 AVA's
RDN(AVA('cn', 'Bob'),AVA('ou', 'people')) # 2 AVA objects adds 2 AVA's
- RDN('cn', 'Bob', "ou=people') # 3 strings, 1st two strings form 1 AVA
- # 3rd string DN syntax for 1 AVA,
- # adds 2 AVA's in total
+ RDN(('cn', 'Bob'), 'ou=people') # 2 args, 1st tuple forms 1 AVA,
+ # 2nd DN syntax string adds 1 AVA,
+ # 2 AVA's in total
Note: The RHS of a slice assignment is interpreted exactly in the
same manner as the constructor argument list (see above examples).
@@ -613,7 +675,7 @@ class RDN(object):
and value properties return the attr and value properties of the first AVA
in the RDN, for example:
- rdn = RDN('cn', 'Bob') # rdn has 1 AVA whose attr == 'cn' and value == 'Bob'
+ rdn = RDN(('cn', 'Bob')) # rdn has 1 AVA whose attr == 'cn' and value == 'Bob'
len(rdn) -> 1
rdn.attr -> u'cn' # exactly equivalent to rdn[0].attr
rdn.value -> u'Bob' # exactly equivalent to rdn[0].value
@@ -644,14 +706,22 @@ class RDN(object):
flags = 0
- def __init__(self, *args):
- self.first_key_match = True
+ def __init__(self, *args, **kwds):
+ self.first_key_match = kwds.get('first_key_match', True)
self.avas = self._avas_from_sequence(args)
self.avas.sort()
def _ava_from_value(self, value):
if isinstance(value, AVA):
- return deepcopy(value)
+ return AVA(value.attr, value.value)
+ elif isinstance(value, RDN):
+ avas = []
+ for ava in value.avas:
+ avas.append(AVA(ava.attr, ava.value))
+ if len(avas) == 1:
+ return avas[0]
+ else:
+ return avas
elif isinstance(value, basestring):
try:
rdns = str2dn(value.encode('utf-8'))
@@ -679,22 +749,12 @@ class RDN(object):
def _avas_from_sequence(self, seq):
avas = []
- i = 0
- while i < len(seq):
- if i+1 < len(seq) and \
- isinstance(seq[i], basestring) and \
- isinstance(seq[i+1], basestring):
- ava = AVA(seq[i], seq[i+1])
- avas.append(ava)
- i += 2
+ for item in seq:
+ ava = self._ava_from_value(item)
+ if isinstance(ava, list):
+ avas.extend(ava)
else:
- arg = seq[i]
- ava = self._ava_from_value(arg)
- if isinstance(ava, list):
- avas.extend(ava)
- else:
- avas.append(ava)
- i += 1
+ avas.append(ava)
return avas
def _to_openldap(self):
@@ -753,7 +813,8 @@ class RDN(object):
if key == self.avas[i].attr:
found = True
self.avas[i] = new_ava
- if self.first_key_match: break
+ if self.first_key_match:
+ break
i += 1
if not found:
raise KeyError("\"%s\" not found in %s" % (key, self.__str__()))
@@ -805,25 +866,27 @@ class RDN(object):
raise TypeError("expected RDN but got %s" % (other.__class__.__name__))
result = cmp(len(self), len(other))
- if result != 0: return result
+ if result != 0:
+ return result
i = 0
while i < len(self):
result = cmp(self[i], other[i])
- if result != 0: return result
+ if result != 0:
+ return result
i += 1
return 0
def __add__(self, other):
- result = deepcopy(self)
- if isinstance(other, self.__class__):
+ result = RDN(self, first_key_match=self.first_key_match)
+ if isinstance(other, RDN):
for ava in other.avas:
- result.avas.append(deepcopy(ava))
+ result.avas.append(AVA(ava.attr, ava.value))
elif isinstance(other, AVA):
- result.avas.append(deepcopy(other))
+ result.avas.append(AVA(other.attr, other.value))
elif isinstance(other, basestring):
rdn = RDN(other)
for ava in rdn.avas:
- result.avas.append(deepcopy(ava))
+ result.avas.append(AVA(ava.attr, ava.value))
else:
raise TypeError("expected RDN, AVA or basestring but got %s" % (other.__class__.__name__))
@@ -831,15 +894,15 @@ class RDN(object):
return result
def __iadd__(self, other):
- if isinstance(other, self.__class__):
+ if isinstance(other, RDN):
for ava in other.avas:
- self.avas.append(deepcopy(ava))
+ self.avas.append(AVA(ava.attr, ava.value))
elif isinstance(other, AVA):
- self.avas.append(deepcopy(other))
+ self.avas.append(AVA(other.attr, other.value))
elif isinstance(other, basestring):
rdn = RDN(other)
for ava in rdn.avas:
- self.avas.append(deepcopy(ava))
+ self.avas.append(AVA(ava.attr, ava.value))
else:
raise TypeError("expected RDN, AVA or basestring but got %s" % (other.__class__.__name__))
@@ -848,11 +911,17 @@ class RDN(object):
class DN(object):
'''
+ DN(arg0, ..., first_key_match=True)
+
A DN is a LDAP Distinguished Name. A DN is an ordered sequence of RDN's.
- The DN constructor accepts a sequence. The constructor iterates
- through the sequence and adds the RDN's it finds in order to the
- DN object. Each item in the sequence may be:
+ The DN constructor is passed a sequence of args and a set of
+ keyword parameters used for configuration. normalize means the
+ attr and value will be converted to lower case.
+
+ The constructor iterates through the sequence and adds the RDN's
+ it finds in order to the DN object. Each item in the sequence may
+ be:
* A 2-valued tuple or list. The first member is the attr and the
second member is the value of an RDN, both members must be
@@ -866,11 +935,12 @@ class DN(object):
to yield one or more RDN's which will be appended in order to
the DN. The parsing recognizes the DN syntax escaping rules.
- * A RDN object. Each RDN object in the argument list will be
- appended to the DN in order.
+ * A RDN object, the RDN will copied respecting the constructors
+ keyword configuration parameters and appended in order.
- * A DN object. Each DN object in the argument list will append in order
- it's RDN's to the DN.
+ * A DN object, the RDN's in the DN are copied respecting the
+ constructors keyword configuration parameters and appended in
+ order.
Single DN Examples:
@@ -972,17 +1042,18 @@ class DN(object):
flags = 0
- def __init__(self, *args):
+ def __init__(self, *args, **kwds):
+ self.first_key_match = kwds.get('first_key_match', True)
self.first_key_match = True
self.rdns = self._rdns_from_sequence(args)
def _rdn_from_value(self, value):
if isinstance(value, RDN):
- return deepcopy(value)
+ return RDN(value, first_key_match=self.first_key_match)
elif isinstance(value, DN):
rdns = []
for rdn in value.rdns:
- rdns.append(deepcopy(rdn))
+ rdns.append(RDN(rdn, first_key_match=self.first_key_match))
if len(rdns) == 1:
return rdns[0]
else:
@@ -995,7 +1066,7 @@ class DN(object):
avas = []
for ava_tuple in rdn_list:
avas.append(AVA(ava_tuple[0], ava_tuple[1]))
- rdn = RDN(*avas)
+ rdn = RDN(*avas, first_key_match=self.first_key_match)
rdns.append(rdn)
except DECODING_ERROR:
raise ValueError("malformed RDN string = \"%s\"" % value)
@@ -1006,7 +1077,7 @@ class DN(object):
elif isinstance(value, (tuple, list)):
if len(value) != 2:
raise ValueError("tuple or list must be 2-valued, not \"%s\"" % (rdn))
- rdn = RDN(value)
+ rdn = RDN(value, first_key_match=self.first_key_match)
return rdn
else:
raise TypeError("must be str,unicode,tuple, or RDN, got %s instead" % \
@@ -1098,7 +1169,8 @@ class DN(object):
raise TypeError("expected DN but got %s" % (other.__class__.__name__))
result = cmp(len(self), len(other))
- if result != 0: return result
+ if result != 0:
+ return result
return self._cmp_sequence(other, 0, len(self))
def _cmp_sequence(self, pattern, self_start, pat_len):
@@ -1106,35 +1178,36 @@ class DN(object):
pat_idx = 0
while pat_idx < pat_len:
result = cmp(self[self_idx], pattern[pat_idx])
- if result != 0: return result
+ if result != 0:
+ return result
self_idx += 1
pat_idx += 1
return 0
def __add__(self, other):
- result = deepcopy(self)
+ result = DN(self, first_key_match=self.first_key_match)
if isinstance(other, self.__class__):
for rdn in other.rdns:
- result.rdns.append(deepcopy(rdn))
+ result.rdns.append(RDN(rdn, first_key_match=self.first_key_match))
elif isinstance(other, RDN):
- result.rdns.append(deepcopy(other))
+ result.rdns.append(RDN(other, first_key_match=self.first_key_match))
elif isinstance(other, basestring):
- dn = DN(other)
+ dn = DN(other, first_key_match=self.first_key_match)
for rdn in dn.rdns:
- result.rdns.append(deepcopy(rdn))
+ result.rdns.append(rdn)
else:
raise TypeError("expected DN, RDN or basestring but got %s" % (other.__class__.__name__))
return result
def __iadd__(self, other):
- if isinstance(other, self.__class__):
+ if isinstance(other, DN):
for rdn in other.rdns:
- self.rdns.append(deepcopy(rdn))
+ self.rdns.append(RDN(rdn, first_key_match=self.first_key_match))
elif isinstance(other, RDN):
- self.rdns.append(deepcopy(other))
+ self.rdns.append(RDN(other, first_key_match=self.first_key_match))
elif isinstance(other, basestring):
- dn = DN(other)
+ dn = DN(other, first_key_match=self.first_key_match)
self.__iadd__(dn)
else:
raise TypeError("expected DN, RDN or basestring but got %s" % (other.__class__.__name__))
@@ -1174,23 +1247,6 @@ class DN(object):
return self._tailmatch(suffix, start, end, +1)
- def _adjust_indices(self, start, end, length):
- 'helper to fixup start/end slice values'
-
- if end > length:
- end = length
- elif end < 0:
- end += length
- if end < 0:
- end = 0
-
- if start < 0:
- start += length
- if start < 0:
- start = 0
-
- return start, end
-
def _tailmatch(self, pattern, start, end, direction):
'''
Matches the end (direction >= 0) or start (direction < 0) of self
@@ -1207,11 +1263,11 @@ class DN(object):
self_len = len(self)
- start, end = self._adjust_indices(start, end, self_len)
+ start, end = _adjust_indices(start, end, self_len)
if direction < 0: # starswith
if start+pat_len > self_len:
- return 0;
+ return 0
else: # endswith
if end-start < pat_len or start > self_len:
return 0
@@ -1222,7 +1278,7 @@ class DN(object):
if isinstance(pattern, DN):
if end-start >= pat_len:
return not self._cmp_sequence(pattern, start, pat_len)
- return 0;
+ return 0
else:
return self.rdns[start] == pattern
diff --git a/tests/test_ipalib/test_dn.py b/tests/test_ipalib/test_dn.py
index 029297f69..c647460ab 100644
--- a/tests/test_ipalib/test_dn.py
+++ b/tests/test_ipalib/test_dn.py
@@ -37,7 +37,7 @@ def make_rdn_args(low, high, kind, attr=None, value=None):
elif kind == 'list':
result.append([new_attr, new_value])
elif kind == 'RDN':
- result.append(RDN(new_attr, new_value))
+ result.append(RDN((new_attr, new_value)))
else:
raise ValueError("Unknown kind = %s" % kind)
@@ -162,6 +162,28 @@ class TestAVA(unittest.TestCase):
result = cmp(ava1, self.ava1)
self.assertEqual(result, 0)
+ # Upper case attr should still be equal
+ ava1 = AVA(self.attr1.upper(), self.value1)
+
+ self.assertFalse(ava1.attr == self.attr1)
+ self.assertTrue(ava1.value == self.value1)
+ self.assertTrue(ava1 == self.ava1)
+ self.assertFalse(ava1 != self.ava1)
+
+ result = cmp(ava1, self.ava1)
+ self.assertEqual(result, 0)
+
+ # Upper case value should still be equal
+ ava1 = AVA(self.attr1, self.value1.upper())
+
+ self.assertTrue(ava1.attr == self.attr1)
+ self.assertFalse(ava1.value == self.value1)
+ self.assertTrue(ava1 == self.ava1)
+ self.assertFalse(ava1 != self.ava1)
+
+ result = cmp(ava1, self.ava1)
+ self.assertEqual(result, 0)
+
# Make ava1's attr greater
ava1.attr = self.attr1 + "1"
@@ -199,7 +221,7 @@ class TestRDN(unittest.TestCase):
self.ava1 = AVA(self.attr1, self.value1)
self.str_rdn1 = '%s=%s' % (self.attr1, self.value1)
- self.rdn1 = RDN(self.attr1, self.value1)
+ self.rdn1 = RDN((self.attr1, self.value1))
self.attr2 = 'ou'
self.value2 = 'people'
@@ -207,7 +229,7 @@ class TestRDN(unittest.TestCase):
self.ava2 = AVA(self.attr2, self.value2)
self.str_rdn2 = '%s=%s' % (self.attr2, self.value2)
- self.rdn2 = RDN(self.attr2, self.value2)
+ self.rdn2 = RDN((self.attr2, self.value2))
self.str_ava3 = '%s=%s+%s=%s' % (self.attr1, self.value1, self.attr2, self.value2)
@@ -216,13 +238,6 @@ class TestRDN(unittest.TestCase):
def test_create(self):
# Create with single attr,value pair
- rdn1 = RDN(self.attr1, self.value1)
- self.assertEqual(len(rdn1), 1)
- self.assertEqual(rdn1, self.rdn1)
- self.assertIsInstance(rdn1[0], AVA)
- self.assertEqual(rdn1[0], self.ava1)
-
- # Create with single attr,value pair passed as a tuple
rdn1 = RDN((self.attr1, self.value1))
self.assertEqual(len(rdn1), 1)
self.assertEqual(rdn1, self.rdn1)
@@ -230,7 +245,7 @@ class TestRDN(unittest.TestCase):
self.assertEqual(rdn1[0], self.ava1)
# Create with multiple attr,value pairs
- rdn3 = RDN(self.attr1, self.value1, self.attr2, self.value2)
+ rdn3 = RDN((self.attr1, self.value1), (self.attr2, self.value2))
self.assertEqual(len(rdn3), 2)
self.assertEqual(rdn3, self.rdn3)
self.assertIsInstance(rdn3[0], AVA)
@@ -250,7 +265,7 @@ class TestRDN(unittest.TestCase):
# Create with multiple attr,value pairs but reverse
# constructor parameter ordering. RDN canonical ordering
# should remain the same
- rdn3 = RDN(self.attr2, self.value2, self.attr1, self.value1)
+ rdn3 = RDN((self.attr2, self.value2), (self.attr1, self.value1))
self.assertEqual(len(rdn3), 2)
self.assertEqual(rdn3, self.rdn3)
self.assertIsInstance(rdn3[0], AVA)
@@ -333,7 +348,7 @@ class TestRDN(unittest.TestCase):
def test_cmp(self):
# Equality
- rdn1 = RDN(self.attr1, self.value1)
+ rdn1 = RDN((self.attr1, self.value1))
self.assertTrue(rdn1 == self.rdn1)
self.assertFalse(rdn1 != self.rdn1)
@@ -404,50 +419,50 @@ class TestRDN(unittest.TestCase):
self.assertEqual(self.rdn3[:], [self.ava1, self.ava2])
def test_assignments(self):
- rdn = RDN(self.attr1, self.value1)
+ rdn = RDN((self.attr1, self.value1))
rdn[0] = self.ava2
self.assertEqual(rdn, self.rdn2)
- rdn = RDN(self.attr1, self.value1)
+ rdn = RDN((self.attr1, self.value1))
rdn[0] = (self.attr2, self.value2)
self.assertEqual(rdn, self.rdn2)
- rdn = RDN(self.attr1, self.value1)
+ rdn = RDN((self.attr1, self.value1))
rdn[self.attr1] = self.str_ava2
self.assertEqual(rdn[0], self.ava2)
# Can't assign multiples to single entry
- rdn = RDN(self.attr1, self.value1)
+ rdn = RDN((self.attr1, self.value1))
with self.assertRaises(TypeError):
rdn[self.attr1] = self.str_ava3
- rdn = RDN(self.attr1, self.value1)
+ rdn = RDN((self.attr1, self.value1))
with self.assertRaises(TypeError):
rdn[self.attr1] = (self.attr1, self.value1, self.attr2, self.value2)
- rdn = RDN(self.attr1, self.value1)
+ rdn = RDN((self.attr1, self.value1))
with self.assertRaises(TypeError):
rdn[self.attr1] = [(self.attr1, self.value1), (self.attr2, self.value2)]
# Slices
- rdn = RDN(self.attr1, self.value1)
+ rdn = RDN((self.attr1, self.value1))
self.assertEqual(rdn, self.rdn1)
rdn[0:1] = [self.ava2]
self.assertEqual(rdn, self.rdn2)
- rdn = RDN(self.attr1, self.value1)
+ rdn = RDN((self.attr1, self.value1))
self.assertEqual(rdn, self.rdn1)
rdn[:] = [(self.attr2, self.value2)]
self.assertEqual(rdn, self.rdn2)
- rdn = RDN(self.attr1, self.value1)
+ rdn = RDN((self.attr1, self.value1))
self.assertEqual(rdn, self.rdn1)
rdn[:] = [(self.attr1, self.value1),(self.attr2, self.value2)]
self.assertEqual(rdn, self.rdn3)
- rdn = RDN(self.attr1, self.value1)
+ rdn = RDN((self.attr1, self.value1))
self.assertEqual(rdn, self.rdn1)
- rdn[0:1] = [self.attr1, self.value1, self.attr2, self.value2]
+ rdn[0:1] = [(self.attr1, self.value1), (self.attr2, self.value2)]
self.assertEqual(rdn, self.rdn3)
@@ -480,23 +495,23 @@ class TestRDN(unittest.TestCase):
def test_concat(self):
- rdn1 = RDN(self.attr1, self.value1)
- rdn2 = RDN(self.attr2, self.value2)
+ rdn1 = RDN((self.attr1, self.value1))
+ rdn2 = RDN((self.attr2, self.value2))
# in-place addtion
rdn1 += rdn2
self.assertEqual(rdn1, self.rdn3)
- rdn1 = RDN(self.attr1, self.value1)
+ rdn1 = RDN((self.attr1, self.value1))
rdn1 += self.ava2
self.assertEqual(rdn1, self.rdn3)
- rdn1 = RDN(self.attr1, self.value1)
+ rdn1 = RDN((self.attr1, self.value1))
rdn1 += self.str_ava2
self.assertEqual(rdn1, self.rdn3)
# concatenation
- rdn1 = RDN(self.attr1, self.value1)
+ rdn1 = RDN((self.attr1, self.value1))
rdn3 = rdn1 + rdn2
self.assertEqual(rdn3, self.rdn3)
@@ -516,7 +531,7 @@ class TestDN(unittest.TestCase):
self.ava1 = AVA(self.attr1, self.value1)
self.str_rdn1 = '%s=%s' % (self.attr1, self.value1)
- self.rdn1 = RDN(self.attr1, self.value1)
+ self.rdn1 = RDN((self.attr1, self.value1))
self.attr2 = 'ou'
self.value2 = 'people'
@@ -524,7 +539,7 @@ class TestDN(unittest.TestCase):
self.ava2 = AVA(self.attr2, self.value2)
self.str_rdn2 = '%s=%s' % (self.attr2, self.value2)
- self.rdn2 = RDN(self.attr2, self.value2)
+ self.rdn2 = RDN((self.attr2, self.value2))
self.str_dn1 = self.str_rdn1
self.dn1 = DN(self.rdn1)
@@ -535,12 +550,12 @@ class TestDN(unittest.TestCase):
self.str_dn3 = '%s,%s' % (self.str_rdn1, self.str_rdn2)
self.dn3 = DN(self.rdn1, self.rdn2)
- self.base_rdn1 = RDN('dc', 'redhat')
- self.base_rdn2 = RDN('dc', 'com')
+ self.base_rdn1 = RDN(('dc', 'redhat'))
+ self.base_rdn2 = RDN(('dc', 'com'))
self.base_dn = DN(self.base_rdn1, self.base_rdn2)
- self.container_rdn1 = RDN('cn', 'sudorules')
- self.container_rdn2 = RDN('cn', 'sudo')
+ self.container_rdn1 = RDN(('cn', 'sudorules'))
+ self.container_rdn2 = RDN(('cn', 'sudo'))
self.container_dn = DN(self.container_rdn1, self.container_rdn2)
self.base_container_dn = DN((self.attr1, self.value1),
@@ -581,7 +596,7 @@ class TestDN(unittest.TestCase):
self.assertEqual(dn1[1], self.rdn2)
# Create with multiple attr,value pairs passed as tuple and RDN
- dn1 = DN((self.attr1, self.value1), RDN(self.attr2, self.value2))
+ dn1 = DN((self.attr1, self.value1), RDN((self.attr2, self.value2)))
self.assertEqual(len(dn1), 2)
self.assertIsInstance(dn1[0], RDN)
self.assertIsInstance(dn1[0].attr, unicode)
@@ -809,7 +824,7 @@ class TestDN(unittest.TestCase):
value = alt_rdn_value_arg(i)
dn1[i] = attr, value
dn2[orig_attr] = (attr, value)
- dn3[i] = RDN(attr, value)
+ dn3[i] = RDN((attr, value))
self.assertEqual(dn1, dn2)
self.assertEqual(dn1, dn3)