diff options
-rw-r--r-- | ipalib/public.py | 39 | ||||
-rw-r--r-- | ipalib/tests/test_public.py | 33 |
2 files changed, 72 insertions, 0 deletions
diff --git a/ipalib/public.py b/ipalib/public.py index c2c3a449..c6611ab7 100644 --- a/ipalib/public.py +++ b/ipalib/public.py @@ -380,3 +380,42 @@ class Property(Attribute): attr = getattr(self, name) if is_rule(attr): yield attr + + +class Application(Command): + """ + Base class for commands register by an external application. + + Special commands that only apply to a particular application built atop + `ipalib` should subclass from ``Application``. + + Because ``Application`` subclasses from `Command', plugins that subclass + from ``Application`` with be available in both the ``api.Command`` and + ``api.Application`` namespaces. + """ + + __public__ = frozenset(( + 'application', + )).union(Command.__public__) + __application = None + + def __get_application(self): + """ + Returns external ``application`` object. + """ + return self.__application + def __set_application(self, application): + """ + Sets the external application object to ``application``. + """ + if self.__application is not None: + raise AttributeError( + '%s.application can only be set once' % self.name + ) + if application is None: + raise TypeError( + '%s.application cannot be None' % self.name + ) + object.__setattr__(self, '_Application__application', application) + assert self.application is application + application = property(__get_application, __set_application) diff --git a/ipalib/tests/test_public.py b/ipalib/tests/test_public.py index ac1ae818..52fb9336 100644 --- a/ipalib/tests/test_public.py +++ b/ipalib/tests/test_public.py @@ -690,3 +690,36 @@ class test_Property(ClassChecker): assert isinstance(opt, public.Option) assert opt.name == 'givenname' assert opt.doc == 'User first name' + + +class test_Application(ClassChecker): + """ + Tests the `public.Application` class. + """ + _cls = public.Application + + def test_class(self): + assert self.cls.__bases__ == (public.Command,) + assert type(self.cls.application) is property + + def test_application(self): + """ + Tests the `public.Application.application` property. + """ + assert 'application' in self.cls.__public__ # Public + app = 'The external application' + class example(self.cls): + 'A subclass' + for o in (self.cls(), example()): + assert o.application is None + e = raises(TypeError, setattr, o, 'application', None) + assert str(e) == ( + '%s.application cannot be None' % o.__class__.__name__ + ) + o.application = app + assert o.application is app + e = raises(AttributeError, setattr, o, 'application', app) + assert str(e) == ( + '%s.application can only be set once' % o.__class__.__name__ + ) + assert o.application is app |