summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipalib/base.py76
-rw-r--r--ipalib/tests/test_base.py71
2 files changed, 145 insertions, 2 deletions
diff --git a/ipalib/base.py b/ipalib/base.py
index 09355f41b..b4d20450a 100644
--- a/ipalib/base.py
+++ b/ipalib/base.py
@@ -21,6 +21,7 @@
Base classes for plug-in architecture and generative API.
"""
+import re
import inspect
import exceptions
@@ -141,6 +142,53 @@ class Named(object):
name = property(__get_name)
+class AbstractCommand(object):
+ def __call__(self):
+ print 'You called %s()' % self.name
+
+class Attribute(Named):
+ __locked = False
+ __obj = None
+
+ def __init__(self):
+ m = re.match('^([a-z]+)__([a-z]+)$', self.__class__.__name__)
+ assert m
+ self.__obj_name = m.group(1)
+ self.__attr_name = m.group(2)
+
+ def __get_obj(self):
+ return self.__obj
+ obj = property(__get_obj)
+
+ def set_obj(self, obj=None):
+ if self.__locked:
+ raise exceptions.TwiceSetError(self.__class__.__name__, 'obj')
+ self.__locked = True
+ if obj is None:
+ return
+ assert isinstance(obj, Object)
+ assert obj.name == self.__obj_name
+ self.__obj = obj
+
+ def __get_obj_name(self):
+ return self.__obj_name
+ obj_name = property(__get_obj_name)
+
+ def __get_attr_name(self):
+ return self.__attr_name
+ attr_name = property(__get_attr_name)
+
+
+class Method(AbstractCommand, Attribute):
+ def _get_name(self):
+ return '%s_%s' % (self.attr_name, self.obj_name)
+
+
+class Property(Attribute):
+ def _get_name(self):
+ return self.attr_name
+
+
class WithObj(Named):
_obj = None
__obj = None
@@ -168,8 +216,7 @@ class Command(WithObj):
def __call__(self):
print 'You called %s()' % self.name
-class Property(WithObj):
- pass
+
class Object(Named):
__commands = None
@@ -187,6 +234,31 @@ class Object(Named):
commands = property(__get_commands, __set_commands)
+
+
+class AttributeCollector(object):
+ def __init__(self):
+ self.__d = {}
+
+ def __getitem__(self, key):
+ assert isinstance(key, str)
+ if key not in self.__d:
+ self.__d[key] = {}
+ return self.__d[key]
+
+ def __iter__(self):
+ for key in self.__d:
+ yield key
+
+ def add(self, i):
+ assert isinstance(i, Attribute)
+ self[i.obj_name][i.attr_name] = i
+
+ def namespaces(self):
+ for key in self:
+ yield (key, NameSpace(self[key]))
+
+
class Collector(object):
def __init__(self):
self.__d = {}
diff --git a/ipalib/tests/test_base.py b/ipalib/tests/test_base.py
index d06847a26..9d2c1b051 100644
--- a/ipalib/tests/test_base.py
+++ b/ipalib/tests/test_base.py
@@ -191,6 +191,77 @@ def test_Named():
assert i.name == 'named_class'
+def test_Attribute():
+ class user__add(base.Attribute):
+ pass
+ i = user__add()
+ assert i.obj_name == 'user'
+ assert i.attr_name == 'add'
+ assert read_only(i, 'obj') is None
+ class user(base.Object):
+ pass
+ u = user()
+ i.set_obj(u)
+ assert read_only(i, 'obj') is u
+ raised = False
+ try:
+ i.set_obj(u)
+ except exceptions.TwiceSetError:
+ raised = True
+ assert raised
+
+
+def test_Method():
+ class user__mod(base.Method):
+ pass
+ i = user__mod()
+ assert isinstance(i, base.Attribute)
+ assert isinstance(i, base.AbstractCommand)
+ assert i.obj_name == 'user'
+ assert i.attr_name == 'mod'
+ assert i.name == 'mod_user'
+
+
+def test_Property():
+ class user__firstname(base.Property):
+ pass
+ i = user__firstname()
+ assert isinstance(i, base.Attribute)
+ assert i.obj_name == 'user'
+ assert i.attr_name == 'firstname'
+ assert i.name == 'firstname'
+
+
+def test_AttributeCollector():
+ class user__add(base.Attribute):
+ pass
+ class user__mod(base.Attribute):
+ pass
+ class group__add(base.Attribute):
+ pass
+ u_a = user__add()
+ u_m = user__mod()
+ g_a = group__add()
+
+ ac = base.AttributeCollector()
+ ac.add(u_a)
+ ac.add(u_m)
+ ac.add(g_a)
+
+ assert set(ac) == set(['user', 'group'])
+
+ u = ac['user']
+ assert set(u) == set(['add', 'mod'])
+ assert set(u.values()) == set([u_a, u_m])
+
+ g = ac['group']
+ assert g.keys() == ['add']
+ assert g.values() == [g_a]
+
+
+
+
+
def test_WithObj():
class some_object(base.Named):
pass