mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-01-23 14:53:12 -06:00
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:
parent
ccd8eb3373
commit
7acf12e988
@ -20,7 +20,3 @@
|
|||||||
"""
|
"""
|
||||||
IPA library.
|
IPA library.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import base
|
|
||||||
|
|
||||||
api = base.API()
|
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
|
||||||
]
|
]
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user