summaryrefslogtreecommitdiffstats
path: root/ipalib
diff options
context:
space:
mode:
Diffstat (limited to 'ipalib')
-rw-r--r--ipalib/plugable.py36
-rw-r--r--ipalib/tests/test_plugable.py107
2 files changed, 72 insertions, 71 deletions
diff --git a/ipalib/plugable.py b/ipalib/plugable.py
index 438815bb3..66e5fadad 100644
--- a/ipalib/plugable.py
+++ b/ipalib/plugable.py
@@ -518,32 +518,50 @@ class NameSpace(DictProxy):
True
"""
- def __init__(self, members):
+ def __init__(self, members, sort=True):
"""
:param members: An iterable providing the members.
+ :param sort: Whether to sort the members by member name.
"""
+ self.__members = tuple(members)
+ self.__sort = check_type(sort, bool, 'sort')
+ names = (m.name for m in self.__members)
+ if self.__sort:
+ self.__names = tuple(sorted(names))
+ else:
+ self.__names = tuple(names)
super(NameSpace, self).__init__(
- dict(self.__member_iter(members))
+ dict(self.__member_iter())
)
- def __member_iter(self, members):
+ def __member_iter(self):
"""
Helper method called only from `NameSpace.__init__()`.
-
- :param members: Same iterable passed to `NameSpace.__init__()`.
"""
- for member in members:
+ for member in self.__members:
name = check_name(member.name)
assert not hasattr(self, name), 'already has attribute %r' % name
setattr(self, name, member)
yield (name, member)
+ def __iter__(self):
+ """
+ Iterates through member names.
+
+ In this instance was created with ``sort=True``,
+ """
+ for name in self.__names:
+ yield name
+
def __repr__(self):
"""
- Returns pseudo-valid Python expression that could be used to construct
- this NameSpace instance.
+ Returns a pseudo-valid expression that could create this instance.
"""
- return '%s(<%d members>)' % (self.__class__.__name__, len(self))
+ return '%s(<%d members>, sort=%r)' % (
+ self.__class__.__name__,
+ len(self),
+ self.__sort,
+ )
class Registrar(DictProxy):
diff --git a/ipalib/tests/test_plugable.py b/ipalib/tests/test_plugable.py
index ec33989d6..62a78e369 100644
--- a/ipalib/tests/test_plugable.py
+++ b/ipalib/tests/test_plugable.py
@@ -556,6 +556,11 @@ def test_check_name():
for name in okay:
raises(errors.NameSpaceError, f, name.upper())
+class DummyMember(object):
+ def __init__(self, i):
+ assert type(i) is int
+ self.name = 'member_%02d' % i
+
class test_NameSpace(ClassChecker):
"""
@@ -566,68 +571,46 @@ class test_NameSpace(ClassChecker):
def test_class(self):
assert self.cls.__bases__ == (plugable.DictProxy,)
- def test_namespace(self):
- class base(object):
- __public__ = frozenset((
- 'plusplus',
- ))
- doc = 'doc'
-
- def plusplus(self, n):
- return n + 1
-
- class plugin(base):
- def __init__(self, name):
- self.name = name
-
- def get_name(i):
- return 'noun_verb%d' % i
-
- def get_proxies(n):
- for i in xrange(n):
- yield plugable.PluginProxy(base, plugin(get_name(i)))
-
- cnt = 10
- ns = self.cls(get_proxies(cnt))
- assert ns.__islocked__() is True
-
- # Test __len__
- assert len(ns) == cnt
-
- # Test __iter__
- i = None
- for (i, key) in enumerate(ns):
- assert type(key) is str
- assert key == get_name(i)
- assert i == cnt - 1
-
- # Test __call__
- i = None
- for (i, proxy) in enumerate(ns()):
- assert type(proxy) is plugable.PluginProxy
- assert proxy.name == get_name(i)
- assert i == cnt - 1
-
- # Test __contains__, __getitem__, getattr():
- proxies = frozenset(ns())
- for i in xrange(cnt):
- name = get_name(i)
- assert name in ns
- proxy = ns[name]
- assert proxy.name == name
- assert type(proxy) is plugable.PluginProxy
- assert proxy in proxies
- assert read_only(ns, name) is proxy
-
- # Test dir():
- assert set(get_name(i) for i in xrange(cnt)).issubset(dir(ns))
-
- # Test that KeyError, AttributeError is raised:
- name = get_name(cnt)
- assert name not in ns
- raises(KeyError, getitem, ns, name)
- raises(AttributeError, getattr, ns, name)
- no_set(ns, name)
+ def test_init(self):
+ """
+ Tests the `plugable.NameSpace.__init__` method.
+ """
+ o = self.cls(tuple())
+ assert list(o) == []
+ assert list(o()) == []
+ for cnt in (10, 25):
+ members = tuple(DummyMember(cnt - i) for i in xrange(cnt))
+ names = tuple(m.name for m in members)
+ for sort in (True, False):
+ o = self.cls(members, sort=sort)
+
+ # Test __len__:
+ assert len(o) == cnt
+
+ # Test __contains__:
+ for name in names:
+ assert name in o
+ assert ('member_00') not in o
+
+ # Test __iter__, __call__:
+ if sort:
+ assert tuple(o) == tuple(sorted(names))
+ assert tuple(o()) == tuple(
+ sorted(members, key=lambda m: m.name)
+ )
+ else:
+ assert tuple(o) == names
+ assert tuple(o()) == members
+
+ # Test __getitem__, getattr:
+ for member in members:
+ name = member.name
+ assert o[name] is member
+ assert read_only(o, name) is member
+
+ # Test __repr__:
+ assert repr(o) == \
+ 'NameSpace(<%d members>, sort=%r)' % (cnt, sort)
def test_Registrar():