summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipalib/base.py113
-rw-r--r--ipalib/crud.py71
-rw-r--r--ipalib/tests/test_base.py155
-rw-r--r--ipalib/tests/test_crud.py89
4 files changed, 177 insertions, 251 deletions
diff --git a/ipalib/base.py b/ipalib/base.py
index 62949eef5..cac6797fe 100644
--- a/ipalib/base.py
+++ b/ipalib/base.py
@@ -25,51 +25,6 @@ import inspect
import exceptions
-class Named(object):
- prefix = None
-
- def __init__(self):
- clsname = self.__class__.__name__
- assert type(self.prefix) is str
- prefix = self.prefix + '_'
- if not clsname.startswith(prefix):
- raise exceptions.PrefixError(clsname, prefix)
- self.__name = clsname[len(prefix):]
- self.__name_cli = self.__name.replace('_', '-')
-
- def __get_name(self):
- return self.__name
- name = property(__get_name)
-
- def __get_name_cli(self):
- return self.__name_cli
- name_cli = property(__get_name_cli)
-
-
-class Command(Named):
- prefix = 'cmd'
-
- def normalize(self, kw):
- raise NotImplementedError
-
- def validate(self, kw):
- raise NotImplementedError
-
- def execute(self, kw):
- raise NotImplementedError
-
- def __call__(self, **kw):
- normalized = self.normalize(kw)
- invalid = self.validate(normalized)
- if invalid:
- return invalid
- return self.execute(normalize)
-
-
-class Argument(object):
- pass
-
-
class NameSpace(object):
"""
A read-only namespace of (key, value) pairs that can be accessed
@@ -103,8 +58,10 @@ class NameSpace(object):
def __init__(self, kw, order=None):
"""
- The single constructor argument `kw` is a dict of the (key, value)
- pairs to be in this NameSpace instance.
+ 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)
@@ -141,7 +98,8 @@ class NameSpace(object):
def __iter__(self):
"""
- Yields the names in this NameSpace in ascending order.
+ Yields the names in this NameSpace in ascending order, or in the
+ the order specified in `order` kw arg.
For example:
@@ -161,6 +119,65 @@ class NameSpace(object):
return len(self.__keys)
+class Named(object):
+ def __get_name(self):
+ return self.__class__.__name__
+ name = property(__get_name)
+
+
+class ObjectMember(Named):
+ def __init__(self, obj):
+ self.__obj = obj
+
+ def __get_obj(self):
+ return self.__obj
+ obj = property(__get_obj)
+
+
+class Command(ObjectMember):
+ def __get_full_name(self):
+ return '%s_%s' % (self.name, self.obj.name)
+ full_name = property(__get_full_name)
+
+
+class Attribute(ObjectMember):
+ def __get_full_name(self):
+ return '%s_%s' % (self.obj.name, self.name)
+ full_name = property(__get_full_name)
+
+
+class Object(Named):
+ def __init__(self):
+ self.__commands = self.__build_ns(self.get_commands)
+ self.__attributes = self.__build_ns(self.get_attributes, True)
+
+ def __get_commands(self):
+ return self.__commands
+ commands = property(__get_commands)
+
+ def __get_attributes(self):
+ return self.__attributes
+ attributes = property(__get_attributes)
+
+ def __build_ns(self, callback, preserve=False):
+ d = {}
+ o = []
+ for cls in callback():
+ i = cls(self)
+ assert i.name not in d
+ d[i.name] = i
+ o.append(i.name)
+ if preserve:
+ return NameSpace(d, order=o)
+ return NameSpace(d)
+
+ def get_commands(self):
+ raise NotImplementedError
+
+ def get_attributes(self):
+ raise NotImplementedError
+
+
class API(object):
__cmd = None
__objects = None
diff --git a/ipalib/crud.py b/ipalib/crud.py
index 1be727673..afbad47ac 100644
--- a/ipalib/crud.py
+++ b/ipalib/crud.py
@@ -18,66 +18,43 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
-
+Base classes for objects with CRUD functionality.
"""
-from base import NameSpace
-
-class Named(object):
- def __get_name(self):
- return self.__class__.__name__
- name = property(__get_name)
-
-class ObjectMember(Named):
- def __init__(self, obj):
- self.__obj = obj
+import base
- def __get_obj(self):
- return self.__obj
- obj = property(__get_obj)
+class create(base.Command):
+ pass
-class Command(ObjectMember):
- def __get_full_name(self):
- return '%s_%s' % (self.name, self.obj.name)
- full_name = property(__get_full_name)
+class retrieve(base.Command):
+ pass
-class Attribute(ObjectMember):
- def __get_full_name(self):
- return '%s_%s' % (self.obj.name, self.name)
- full_name = property(__get_full_name)
+class update(base.Command):
+ pass
-class Object(Named):
- def __init__(self):
- self.__commands = self.__build_ns(self.get_commands)
- self.__attributes = self.__build_ns(self.get_attributes, True)
- def __get_commands(self):
- return self.__commands
- commands = property(__get_commands)
+class delete(base.Command):
+ pass
- def __get_attributes(self):
- return self.__attributes
- attributes = property(__get_attributes)
- def __build_ns(self, callback, preserve=False):
- d = {}
- o = []
- for cls in callback():
- i = cls(self)
- assert i.name not in d
- d[i.name] = i
- o.append(i.name)
- if preserve:
- return NameSpace(d, order=o)
- return NameSpace(d)
+class search(base.Command):
+ pass
- def __get_commands(self):
- return
+class user(base.Object):
def get_commands(self):
- raise NotImplementedError
+ return [
+ create,
+ retrieve,
+ update,
+ delete,
+ ]
def get_attributes(self):
- raise NotImplementedError
+ return [
+ givenName,
+ sn,
+ login,
+ ]
diff --git a/ipalib/tests/test_base.py b/ipalib/tests/test_base.py
index 81794d7ac..31b109941 100644
--- a/ipalib/tests/test_base.py
+++ b/ipalib/tests/test_base.py
@@ -56,61 +56,6 @@ class ClassChecker(object):
return self.new(*self.args(), **self.kw())
-class test_Named:
- """
- Unit tests for `Named` class.
- """
- cls = base.Named
-
- def new(self):
- class tst_verb_object(self.cls):
- prefix = 'tst'
- return tst_verb_object()
-
- def test_prefix(self):
- """
- Test prefix exception.
- """
- # Test Example class:
- class Example(self.cls):
- prefix = 'eg'
-
- # Two test subclasses:
- class do_stuff(Example):
- pass
- class eg_do_stuff(Example):
- pass
-
- # Test that PrefixError is raised with incorrectly named subclass:
- raised = False
- try:
- do_stuff()
- except exceptions.PrefixError:
- raised = True
- assert raised
-
- # Test that correctly named subclass works:
- eg_do_stuff()
-
- def test_name(self):
- """
- Test Named.name property.
- """
- obj = self.new()
- assert read_only(obj, 'name') == 'verb_object'
-
- def test_name_cli(self):
- """
- Test Named.name_cli property.
- """
- obj = self.new()
- assert read_only(obj, 'name_cli') == 'verb-object'
-
-
-
-
-
-
class test_NameSpace:
"""
Unit tests for `NameSpace` class.
@@ -238,17 +183,93 @@ class test_NameSpace:
assert len(kw) == len(ns) == 3
-class test_Command(ClassChecker):
- class cmd_some_command(base.Command):
+def test_Command():
+ class user(object):
+ name = 'user'
+ class add(base.Command):
+ pass
+ i = add(user())
+ assert i.name == 'add'
+ assert i.full_name == 'add_user'
+
+
+def test_Attribute():
+ class user(object):
+ name = 'user'
+ class sn(base.Attribute):
pass
- cls = cmd_some_command
+ i = sn(user())
+ assert i.name == 'sn'
+ assert i.full_name == 'user_sn'
+
+
+def test_Object():
+ class create(base.Command):
+ pass
+
+ class retrieve(base.Command):
+ pass
+
+ class update(base.Command):
+ pass
+
+ class delete(base.Command):
+ pass
+
+ class givenName(base.Attribute):
+ pass
+
+ class sn(base.Attribute):
+ pass
+
+ class login(base.Attribute):
+ pass
+
- def test_fresh(self):
- c = self.new()
- assert isinstance(c, base.Named)
- assert c.name == 'some_command'
- assert c.name_cli == 'some-command'
- assert callable(c)
+ class user(base.Object):
+ def get_commands(self):
+ return [
+ create,
+ retrieve,
+ update,
+ delete,
+ ]
+
+ def get_attributes(self):
+ return [
+ givenName,
+ sn,
+ login,
+ ]
+
+ i = user()
+ assert i.name == 'user'
+
+ # Test commands:
+ commands = i.commands
+ assert isinstance(commands, base.NameSpace)
+ assert list(commands) == ['create', 'delete', 'retrieve', 'update']
+ assert len(commands) == 4
+ for name in commands:
+ cls = locals()[name]
+ cmd = commands[name]
+ assert type(cmd) is cls
+ assert getattr(commands, name) is cmd
+ assert cmd.name == name
+ assert cmd.full_name == ('%s_user' % name)
+
+ # Test attributes:
+ attributes = i.attributes
+ assert isinstance(attributes, base.NameSpace)
+ assert list(attributes) == ['givenName', 'sn', 'login']
+ assert len(attributes) == 3
+ for name in attributes:
+ cls = locals()[name]
+ attr = attributes[name]
+ assert type(attr) is cls
+ assert getattr(attributes, name) is attr
+ assert attr.name == name
+ assert attr.full_name == ('user_%s' % name)
class test_API:
@@ -262,14 +283,14 @@ class test_API:
"""
return base.API()
- def test_fresh(self):
+ def dont_fresh(self):
"""
Test expectations of a fresh API instance.
"""
api = self.new()
assert read_only(api, 'cmd') is None
- def test_register_command(self):
+ def dont_register_command(self):
api = self.new()
class cmd_my_command(base.Command):
@@ -314,7 +335,7 @@ class test_API:
# Check that override=True works:
api.register_command(cmd_my_command, override=True)
- def test_finalize(self):
+ def dont_finalize(self):
api = self.new()
assert read_only(api, 'cmd') is None
diff --git a/ipalib/tests/test_crud.py b/ipalib/tests/test_crud.py
index 12ee1009b..99113c4a4 100644
--- a/ipalib/tests/test_crud.py
+++ b/ipalib/tests/test_crud.py
@@ -20,92 +20,3 @@
"""
Unit tests for `ipalib.crud` module.
"""
-
-from ipalib import crud, base, exceptions
-
-class create(crud.Command):
- pass
-
-class retrieve(crud.Command):
- pass
-
-class update(crud.Command):
- pass
-
-class delete(crud.Command):
- pass
-
-class givenName(crud.Attribute):
- pass
-
-class sn(crud.Attribute):
- pass
-
-class login(crud.Attribute):
- pass
-
-
-class user(crud.Object):
- def get_commands(self):
- return [
- create,
- retrieve,
- update,
- delete,
- ]
-
- def get_attributes(self):
- return [
- givenName,
- sn,
- login,
- ]
-
-
-def test_Named():
- class named_class(crud.Named):
- pass
-
- n = named_class()
- assert n.name == 'named_class'
-
-
-def test_Command():
- class user(object):
- name = 'user'
- class add(crud.Command):
- pass
- i = add(user())
- assert i.name == 'add'
- assert i.full_name == 'add_user'
-
-
-def test_Object():
- i = user()
- assert i.name == 'user'
-
- # Test commands:
- commands = i.commands
- assert isinstance(commands, base.NameSpace)
- assert list(commands) == ['create', 'delete', 'retrieve', 'update']
- assert len(commands) == 4
- for name in commands:
- cls = globals()[name]
- cmd = commands[name]
- assert type(cmd) is cls
- assert getattr(commands, name) is cmd
- assert cmd.name == name
- assert cmd.full_name == ('%s_user' % name)
-
- # Test attributes:
- attributes = i.attributes
- assert isinstance(attributes, base.NameSpace)
- assert list(attributes) == ['givenName', 'sn', 'login']
- assert len(attributes) == 3
- for name in attributes:
- cls = globals()[name]
- attr = attributes[name]
- assert type(attr) is cls
- assert getattr(attributes, name) is attr
- assert attr.name == name
- assert attr.full_name == ('user_%s' % name)