summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Gerard DeRose <jderose@redhat.com>2008-08-01 20:42:35 +0000
committerJason Gerard DeRose <jderose@redhat.com>2008-08-01 20:42:35 +0000
commitf3762a76c0824296e90385eac27455aaf06af32d (patch)
treea4683b6b4b19a49882cc810799c7cb6f8515b0af
parent4fe8e52ecb61088bcff2a7c91db454621d6755f1 (diff)
downloadfreeipa.git-f3762a76c0824296e90385eac27455aaf06af32d.tar.gz
freeipa.git-f3762a76c0824296e90385eac27455aaf06af32d.tar.xz
freeipa.git-f3762a76c0824296e90385eac27455aaf06af32d.zip
40: Rewrote dictionary interface for plugable.NameSpace to better suite new architecture
-rw-r--r--ipalib/plugable.py89
-rw-r--r--ipalib/tests/test_plugable.py62
-rw-r--r--ipalib/tests/tstutil.py8
3 files changed, 104 insertions, 55 deletions
diff --git a/ipalib/plugable.py b/ipalib/plugable.py
index 9e94e96b..4923c621 100644
--- a/ipalib/plugable.py
+++ b/ipalib/plugable.py
@@ -130,75 +130,56 @@ class NameSpace(ReadOnly):
both as instance attributes and as dictionary items.
"""
- def __init__(self, kw):
- """
- The `kw` argument is a dict of the (key, value) pairs to be in this
- NameSpace instance. The optional `order` keyword argument specifies
- the order of the keys in this namespace; if omitted, the default is
- to sort the keys in ascending order.
- """
- assert isinstance(kw, dict)
- self.__kw = dict(kw)
- for (key, value) in self.__kw.items():
- assert not key.startswith('_')
- setattr(self, key, value)
- if order is None:
- self.__keys = sorted(self.__kw)
- else:
- self.__keys = list(order)
- assert set(self.__keys) == set(self.__kw)
- self.__locked = True
-
- def __setattr__(self, name, value):
+ def __init__(self, items):
"""
- Raises an exception if trying to set an attribute after the
- NameSpace has been locked; otherwise calls object.__setattr__().
"""
- if self.__locked:
- raise errors.SetError(name)
- super(NameSpace, self).__setattr__(name, value)
+ object.__setattr__(self, '_NameSpace__items', tuple(items))
- def __getitem__(self, key):
- """
- Returns item from namespace named `key`.
- """
- return self.__kw[key]
+ # dict mapping Python name to item:
+ object.__setattr__(self, '_NameSpace__pname', {})
- def __hasitem__(self, key):
- """
- Returns True if namespace has an item named `key`.
- """
- return bool(key in self.__kw)
+ # dict mapping human-readibly name to item:
+ object.__setattr__(self, '_NameSpace__hname', {})
+
+ for item in self.__items:
+ for (key, d) in [
+ (item.name, self.__pname),
+ (str(item), self.__hname),
+ ]:
+ assert key not in d
+ d[key] = item
def __iter__(self):
"""
- Yields the names in this NameSpace in ascending order, or in the
- the order specified in `order` kw arg.
-
- For example:
+ Iterates through the items in this NameSpace in the same order they
+ were passed in the contructor.
+ """
+ for item in self.__items:
+ yield item
- >>> ns = NameSpace(dict(attr_b='world', attr_a='hello'))
- >>> list(ns)
- ['attr_a', 'attr_b']
- >>> [ns[k] for k in ns]
- ['hello', 'world']
+ def __len__(self):
+ """
+ Returns number of items in this NameSpace.
"""
- for key in self.__keys:
- yield key
+ return len(self.__items)
- def __call__(self):
+ def __contains__(self, key):
"""
- Iterates through the values in this NameSpace in the same order as
- the keys.
+ Returns True if an item with pname or hname `key` is in this
+ NameSpace.
"""
- for key in self.__keys:
- yield self.__kw[key]
+ return (key in self.__pname) or (key in self.__hname)
- def __len__(self):
+ def __getitem__(self, key):
"""
- Returns number of items in this NameSpace.
+ Returns item with pname or hname `key`; otherwise raises KeyError.
"""
- return len(self.__keys)
+ if key in self.__pname:
+ return self.__pname[key]
+ if key in self.__hname:
+ return self.__hname[key]
+ raise KeyError('NameSpace has no item for key %r' % key)
+
class Registrar(object):
diff --git a/ipalib/tests/test_plugable.py b/ipalib/tests/test_plugable.py
index 99c9a4f6..4f92889c 100644
--- a/ipalib/tests/test_plugable.py
+++ b/ipalib/tests/test_plugable.py
@@ -21,7 +21,7 @@
Unit tests for `ipalib.plugable` module.
"""
-from tstutil import raises, no_set, no_del, read_only
+from tstutil import raises, getitem, no_set, no_del, read_only
from ipalib import plugable, errors
@@ -236,3 +236,63 @@ def test_Registrar():
assert len(d) == 3
assert r[base] == d
assert r[base.__name__] == d
+
+
+def test_NameSpace():
+ assert issubclass(plugable.NameSpace, plugable.ReadOnly)
+
+ class DummyProxy(object):
+ def __init__(self, name):
+ self.__name = name
+
+ def __get_name(self):
+ return self.__name
+ name = property(__get_name)
+
+ def __str__(self):
+ return plugable.to_cli(self.__name)
+
+ def get_name(i):
+ return 'noun_verb%d' % i
+
+ def get_cli(i):
+ return 'noun-verb%d' % i
+
+ def get_proxies(n):
+ for i in xrange(n):
+ yield DummyProxy(get_name(i))
+
+ cnt = 20
+ ns = plugable.NameSpace(get_proxies(cnt))
+
+ # Test __len__
+ assert len(ns) == cnt
+
+ # Test __iter__
+ i = None
+ for (i, item) in enumerate(ns):
+ assert type(item) is DummyProxy
+ assert item.name == get_name(i)
+ assert str(item) == get_cli(i)
+ assert i == cnt - 1
+
+ # Test __contains__, __getitem__:
+ for i in xrange(cnt):
+ name = get_name(i)
+ cli = get_cli(i)
+ assert name in ns
+ assert cli in ns
+ item = ns[name]
+ assert isinstance(item, DummyProxy)
+ assert item.name == name
+ assert str(item) == cli
+ assert ns[name] is item
+ assert ns[cli] is item
+
+ # Check that KeyError is raised:
+ name = get_name(cnt)
+ cli = get_cli(cnt)
+ assert name not in ns
+ assert cli not in ns
+ raises(KeyError, getitem, ns, name)
+ raises(KeyError, getitem, ns, cli)
diff --git a/ipalib/tests/tstutil.py b/ipalib/tests/tstutil.py
index 37b7745f..12ca119d 100644
--- a/ipalib/tests/tstutil.py
+++ b/ipalib/tests/tstutil.py
@@ -49,6 +49,14 @@ def raises(exception, callback, *args, **kw):
raise ExceptionNotRaised(exception)
+def getitem(obj, key):
+ """
+ Works like getattr but for dictionary interface. Uses this in combination
+ with raises() to test that, for example, KeyError is raised.
+ """
+ return obj[key]
+
+
def no_set(obj, name, value='some_new_obj'):
"""
Tests that attribute cannot be set.