10: Updated base.API to reflect the fact that base.Object is now the new unit of plugin functionality; updated corresponding unit tests

This commit is contained in:
Jason Gerard DeRose 2008-07-20 01:29:59 +00:00
parent ccd8eb3373
commit 7acf12e988
4 changed files with 91 additions and 107 deletions

View File

@ -20,7 +20,3 @@
""" """
IPA library. IPA library.
""" """
import base
api = base.API()

View File

@ -112,6 +112,14 @@ class NameSpace(object):
for key in self.__keys: for key in self.__keys:
yield key yield key
def __call__(self):
"""
Iterates through the values in this NameSpace in the same order as
the keys.
"""
for key in self.__keys:
yield self.__kw[key]
def __len__(self): def __len__(self):
""" """
Returns number of items in this NameSpace. Returns number of items in this NameSpace.
@ -172,57 +180,42 @@ class Object(Named):
return NameSpace(d) return NameSpace(d)
def get_commands(self): def get_commands(self):
raise NotImplementedError return []
def get_attributes(self): def get_attributes(self):
raise NotImplementedError return []
class API(object): class API(object):
__cmd = None
__objects = None __objects = None
__locked = False __commands = None
def __init__(self): def __init__(self):
self.__classes = set() self.__obj_d = {}
self.__names = set()
self.__stage = {}
def __get_objects(self): def __get_objects(self):
return self.__objects return self.__objects
objects = property(__get_objects) objects = property(__get_objects)
def __get_cmd(self): def __get_commands(self):
return self.__cmd return self.__commands
cmd = property(__get_cmd) commands = property(__get_commands)
def __merge(self, base, cls, override): def register_object(self, cls, override=False):
assert issubclass(base, Named)
assert type(override) is bool assert type(override) is bool
if not (inspect.isclass(cls) and issubclass(cls, base)): if not (inspect.isclass(cls) and issubclass(cls, Object)):
raise exceptions.RegistrationError(cls, base.__name__) raise exceptions.RegistrationError(cls, 'Object')
if cls in self.__classes: obj = cls()
raise exceptions.DuplicateError(cls.__name__, id(cls)) if obj.name in self.__obj_d and not override:
if cls.__name__ in self.__names and not override: raise exceptions.OverrideError(obj.name)
raise exceptions.OverrideError(cls.__name__) self.__obj_d[obj.name] = obj
prefix = base.prefix
assert cls.__name__.startswith(prefix)
self.__classes.add(cls)
self.__names.add(cls.__name__)
if prefix not in self.__stage:
self.__stage[prefix] = {}
self.__stage[prefix][cls.__name__] = cls
def register_command(self, cls, override=False):
self.__merge(Command, cls, override)
def finalize(self): def finalize(self):
for (prefix, d) in self.__stage.items(): cmd_d = {}
n = {} for obj in self.__obj_d.values():
for cls in d.values(): for cmd in obj.commands():
i = cls() assert cmd.full_name not in cmd_d
assert cls.__name__ == (prefix + '_' + i.name) cmd_d[cmd.full_name] = cmd
n[i.name] = i self.__commands = NameSpace(cmd_d)
if prefix == 'cmd': self.__objects = NameSpace(self.__obj_d)
self.__cmd = NameSpace(n) self.__obj_d = None

View File

@ -23,15 +23,15 @@ Base classes for objects with CRUD functionality.
import base import base
class create(base.Command): class add(base.Command):
pass pass
class retrieve(base.Command): class get(base.Command):
pass pass
class update(base.Command): class edit(base.Command):
pass pass
@ -39,22 +39,16 @@ class delete(base.Command):
pass pass
class search(base.Command): class find(base.Command):
pass pass
class user(base.Object): class CrudLike(base.Object):
def get_commands(self): def get_commands(self):
return [ return [
create, add,
retrieve, get,
update, edit,
delete, delete,
] find,
def get_attributes(self):
return [
givenName,
sn,
login,
] ]

View File

@ -21,7 +21,7 @@
Unit tests for `ipalib.base` module. Unit tests for `ipalib.base` module.
""" """
from ipalib import base, exceptions from ipalib import base, exceptions, crud
def read_only(obj, name): def read_only(obj, name):
@ -225,7 +225,6 @@ def test_Object():
class login(base.Attribute): class login(base.Attribute):
pass pass
class user(base.Object): class user(base.Object):
def get_commands(self): def get_commands(self):
return [ return [
@ -283,79 +282,81 @@ class test_API:
""" """
return base.API() return base.API()
def dont_fresh(self): def test_fresh(self):
""" """
Test expectations of a fresh API instance. Test expectations of a fresh API instance.
""" """
api = self.new() api = self.new()
assert read_only(api, 'cmd') is None assert read_only(api, 'objects') is None
assert read_only(api, 'commands') is None
def dont_register_command(self): def test_register_exception(self):
"""
Check that RegistrationError is raised when registering anything
other than a subclass of Command.
"""
api = self.new() api = self.new()
class cmd_my_command(base.Command): class my_command(base.Command):
pass
class cmd_another_command(base.Command):
pass pass
# Check that RegistrationError is raised when registering anything for obj in [object, my_command]:
# other than a subclass of Command:
for obj in [object, cmd_my_command()]:
raised = False raised = False
try: try:
api.register_command(obj) api.register_object(obj)
except exceptions.RegistrationError: except exceptions.RegistrationError:
raised = True raised = True
assert raised assert raised
# Check that command registration works: def test_override_exception(self):
api.register_command(cmd_my_command) class some_object(base.Object):
api.register_command(cmd_another_command) def get_commands(self):
return []
def get_attributes(self):
return []
# Check that DuplicateError is raised when registering the same class api = self.new()
# twice: api.register_object(some_object)
raised = False raised = False
try: try:
api.register_command(cmd_my_command) api.register_object(some_object)
except exceptions.DuplicateError:
raised = True
assert raised
# Check that OverrideError is raised when registering same name
# without override = True:
class cmd_my_command(base.Command):
pass
raised = False
try:
api.register_command(cmd_my_command)
except exceptions.OverrideError: except exceptions.OverrideError:
raised = True raised = True
assert raised assert raised
api.register_object(some_object, override=True)
def test_finalize(self):
class user(crud.CrudLike):
pass
class group(crud.CrudLike):
pass
class service(crud.CrudLike):
pass
names = list(user().commands)
assert len(names) == 5
full_names = set()
for o in ['user', 'group', 'service']:
full_names.update('%s_%s' % (v, o) for v in names)
assert len(full_names) == 15
# Check that override=True works:
api.register_command(cmd_my_command, override=True)
def dont_finalize(self):
api = self.new() api = self.new()
assert read_only(api, 'cmd') is None api.register_object(user)
api.register_object(group)
class cmd_my_command(base.Command): api.register_object(service)
pass
class cmd_another_command(base.Command):
pass
api.register_command(cmd_my_command)
api.register_command(cmd_another_command)
api.finalize() api.finalize()
cmd = read_only(api, 'cmd') # Test API.objects property:
assert isinstance(cmd, base.NameSpace) objects = read_only(api, 'objects')
assert api.cmd is cmd assert type(objects) is base.NameSpace
assert objects is api.objects # Same instance must be returned
assert len(objects) is 3
assert list(objects) == ['group', 'service', 'user']
assert len(cmd) == 2 # Test API.commands property:
assert list(cmd) == ['another_command', 'my_command'] commands = read_only(api, 'commands')
assert isinstance(cmd.my_command, cmd_my_command) assert type(commands) is base.NameSpace
assert cmd.my_command is cmd['my_command'] assert commands is api.commands # Same instance must be returned
assert isinstance(cmd.another_command, cmd_another_command) assert len(commands) is 15
assert cmd.another_command is cmd['another_command'] assert list(commands) == sorted(full_names)