summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipalib/__init__.py4
-rw-r--r--ipalib/base.py67
-rw-r--r--ipalib/crud.py24
-rw-r--r--ipalib/tests/test_base.py101
4 files changed, 90 insertions, 106 deletions
diff --git a/ipalib/__init__.py b/ipalib/__init__.py
index 1337d8123..ddce3ac92 100644
--- a/ipalib/__init__.py
+++ b/ipalib/__init__.py
@@ -20,7 +20,3 @@
"""
IPA library.
"""
-
-import base
-
-api = base.API()
diff --git a/ipalib/base.py b/ipalib/base.py
index cac6797fe..3cadc70e8 100644
--- a/ipalib/base.py
+++ b/ipalib/base.py
@@ -112,6 +112,14 @@ class NameSpace(object):
for key in self.__keys:
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):
"""
Returns number of items in this NameSpace.
@@ -172,57 +180,42 @@ class Object(Named):
return NameSpace(d)
def get_commands(self):
- raise NotImplementedError
+ return []
def get_attributes(self):
- raise NotImplementedError
+ return []
class API(object):
- __cmd = None
__objects = None
- __locked = False
+ __commands = None
def __init__(self):
- self.__classes = set()
- self.__names = set()
- self.__stage = {}
+ self.__obj_d = {}
def __get_objects(self):
return self.__objects
objects = property(__get_objects)
- def __get_cmd(self):
- return self.__cmd
- cmd = property(__get_cmd)
+ def __get_commands(self):
+ return self.__commands
+ commands = property(__get_commands)
- def __merge(self, base, cls, override):
- assert issubclass(base, Named)
+ def register_object(self, cls, override=False):
assert type(override) is bool
- if not (inspect.isclass(cls) and issubclass(cls, base)):
- raise exceptions.RegistrationError(cls, base.__name__)
- if cls in self.__classes:
- raise exceptions.DuplicateError(cls.__name__, id(cls))
- if cls.__name__ in self.__names and not override:
- raise exceptions.OverrideError(cls.__name__)
- 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)
+ if not (inspect.isclass(cls) and issubclass(cls, Object)):
+ raise exceptions.RegistrationError(cls, 'Object')
+ obj = cls()
+ if obj.name in self.__obj_d and not override:
+ raise exceptions.OverrideError(obj.name)
+ self.__obj_d[obj.name] = obj
def finalize(self):
- for (prefix, d) in self.__stage.items():
- n = {}
- for cls in d.values():
- i = cls()
- assert cls.__name__ == (prefix + '_' + i.name)
- n[i.name] = i
- if prefix == 'cmd':
- self.__cmd = NameSpace(n)
+ cmd_d = {}
+ for obj in self.__obj_d.values():
+ for cmd in obj.commands():
+ assert cmd.full_name not in cmd_d
+ cmd_d[cmd.full_name] = cmd
+ self.__commands = NameSpace(cmd_d)
+ self.__objects = NameSpace(self.__obj_d)
+ self.__obj_d = None
diff --git a/ipalib/crud.py b/ipalib/crud.py
index afbad47ac..c20b4cc16 100644
--- a/ipalib/crud.py
+++ b/ipalib/crud.py
@@ -23,15 +23,15 @@ Base classes for objects with CRUD functionality.
import base
-class create(base.Command):
+class add(base.Command):
pass
-class retrieve(base.Command):
+class get(base.Command):
pass
-class update(base.Command):
+class edit(base.Command):
pass
@@ -39,22 +39,16 @@ class delete(base.Command):
pass
-class search(base.Command):
+class find(base.Command):
pass
-class user(base.Object):
+class CrudLike(base.Object):
def get_commands(self):
return [
- create,
- retrieve,
- update,
+ add,
+ get,
+ edit,
delete,
- ]
-
- def get_attributes(self):
- return [
- givenName,
- sn,
- login,
+ find,
]
diff --git a/ipalib/tests/test_base.py b/ipalib/tests/test_base.py
index 31b109941..aefe4fa3f 100644
--- a/ipalib/tests/test_base.py
+++ b/ipalib/tests/test_base.py
@@ -21,7 +21,7 @@
Unit tests for `ipalib.base` module.
"""
-from ipalib import base, exceptions
+from ipalib import base, exceptions, crud
def read_only(obj, name):
@@ -225,7 +225,6 @@ def test_Object():
class login(base.Attribute):
pass
-
class user(base.Object):
def get_commands(self):
return [
@@ -283,79 +282,81 @@ class test_API:
"""
return base.API()
- def dont_fresh(self):
+ def test_fresh(self):
"""
Test expectations of a fresh API instance.
"""
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()
- class cmd_my_command(base.Command):
- pass
- class cmd_another_command(base.Command):
+ class my_command(base.Command):
pass
- # Check that RegistrationError is raised when registering anything
- # other than a subclass of Command:
- for obj in [object, cmd_my_command()]:
+ for obj in [object, my_command]:
raised = False
try:
- api.register_command(obj)
+ api.register_object(obj)
except exceptions.RegistrationError:
raised = True
assert raised
- # Check that command registration works:
- api.register_command(cmd_my_command)
- api.register_command(cmd_another_command)
-
- # Check that DuplicateError is raised when registering the same class
- # twice:
- raised = False
- try:
- api.register_command(cmd_my_command)
- except exceptions.DuplicateError:
- raised = True
- assert raised
+ def test_override_exception(self):
+ class some_object(base.Object):
+ def get_commands(self):
+ return []
+ def get_attributes(self):
+ return []
- # Check that OverrideError is raised when registering same name
- # without override = True:
- class cmd_my_command(base.Command):
- pass
+ api = self.new()
+ api.register_object(some_object)
raised = False
try:
- api.register_command(cmd_my_command)
+ api.register_object(some_object)
except exceptions.OverrideError:
raised = True
assert raised
+ api.register_object(some_object, override=True)
- # Check that override=True works:
- api.register_command(cmd_my_command, override=True)
-
- def dont_finalize(self):
- api = self.new()
- assert read_only(api, 'cmd') is None
-
- class cmd_my_command(base.Command):
+ def test_finalize(self):
+ class user(crud.CrudLike):
pass
- class cmd_another_command(base.Command):
+ class group(crud.CrudLike):
+ pass
+ class service(crud.CrudLike):
pass
- api.register_command(cmd_my_command)
- api.register_command(cmd_another_command)
+ 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
- api.finalize()
- cmd = read_only(api, 'cmd')
- assert isinstance(cmd, base.NameSpace)
- assert api.cmd is cmd
+ api = self.new()
+ api.register_object(user)
+ api.register_object(group)
+ api.register_object(service)
+ api.finalize()
- assert len(cmd) == 2
- assert list(cmd) == ['another_command', 'my_command']
- assert isinstance(cmd.my_command, cmd_my_command)
- assert cmd.my_command is cmd['my_command']
- assert isinstance(cmd.another_command, cmd_another_command)
- assert cmd.another_command is cmd['another_command']
+ # Test API.objects property:
+ objects = read_only(api, 'objects')
+ 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']
+
+ # Test API.commands property:
+ commands = read_only(api, 'commands')
+ assert type(commands) is base.NameSpace
+ assert commands is api.commands # Same instance must be returned
+ assert len(commands) is 15
+ assert list(commands) == sorted(full_names)