9: Reorganized new work and unit tests based around base.Object being the plugin definining unit

This commit is contained in:
Jason Gerard DeRose 2008-07-19 23:40:23 +00:00
parent e76160b01d
commit ccd8eb3373
4 changed files with 178 additions and 252 deletions

View File

@ -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

View File

@ -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
import base
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 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 Attribute(ObjectMember):
def __get_full_name(self):
return '%s_%s' % (self.obj.name, self.name)
full_name = property(__get_full_name)
class retrieve(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)
class update(base.Command):
pass
def __get_commands(self):
return self.__commands
commands = property(__get_commands)
def __get_attributes(self):
return self.__attributes
attributes = property(__get_attributes)
class delete(base.Command):
pass
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):
return
class search(base.Command):
pass
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,
]

View File

@ -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
cls = cmd_some_command
i = add(user())
assert i.name == 'add'
assert i.full_name == 'add_user'
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)
def test_Attribute():
class user(object):
name = 'user'
class sn(base.Attribute):
pass
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
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

View File

@ -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)