diff options
author | Jason Gerard DeRose <jderose@redhat.com> | 2008-07-31 22:36:15 +0000 |
---|---|---|
committer | Jason Gerard DeRose <jderose@redhat.com> | 2008-07-31 22:36:15 +0000 |
commit | a131ebf72469d416d4c08e23a7f3ac70854b237b (patch) | |
tree | acc48054c74380f194f2fa2b934c878d06270101 | |
parent | d7569a84b94ab304a1b7f353ea71c15061ebd5d4 (diff) | |
download | freeipa.git-a131ebf72469d416d4c08e23a7f3ac70854b237b.tar.gz freeipa.git-a131ebf72469d416d4c08e23a7f3ac70854b237b.tar.xz freeipa.git-a131ebf72469d416d4c08e23a7f3ac70854b237b.zip |
32: Added Plugin and Proxy base classes in plugable module, along with to_cli() and from_cli() functions; added correspending unit tests
-rw-r--r-- | ipalib/plugable.py | 84 | ||||
-rw-r--r-- | ipalib/tests/test_plugable.py | 47 |
2 files changed, 131 insertions, 0 deletions
diff --git a/ipalib/plugable.py b/ipalib/plugable.py index 0de31d82..054b12db 100644 --- a/ipalib/plugable.py +++ b/ipalib/plugable.py @@ -21,10 +21,94 @@ Utility classes for registering plugins, base classe for writing plugins. """ + import inspect import errors +def to_cli(name): + assert isinstance(name, basestring) + return name.replace('__', '.').replace('_', '-') + +def from_cli(cli_name): + assert isinstance(cli_name, basestring) + return cli_name.replace('-', '_').replace('.', '__') + + +class Plugin(object): + """ + Base class for all plugins. + """ + + def __get_name(self): + """ + Returns the class name of this instance. + """ + return self.__class__.__name__ + name = property(__get_name) + + def __repr__(self): + """ + Returns a valid Python expression that could create this plugin + instance given the appropriate environment. + """ + return '%s.%s()' % ( + self.__class__.__module__, + self.__class__.__name__ + ) + + +class Proxy(object): + """ + Used to only export certain attributes into the dynamic API. + + Subclasses must list names of attributes to be proxied in the __slots__ + class attribute. + """ + + __slots__ = ( + '__obj', + 'name', + 'cli_name', + ) + + def __init__(self, obj, proxy_name=None): + """ + Proxy attributes on `obj`. + """ + if proxy_name is None: + proxy_name = obj.name + assert isinstance(proxy_name, str) + object.__setattr__(self, '_Proxy__obj', obj) + object.__setattr__(self, 'name', proxy_name) + object.__setattr__(self, 'cli_name', to_cli(proxy_name)) + for name in self.__slots__: + object.__setattr__(self, name, getattr(obj, name)) + + def __setattr__(self, name, value): + """ + Proxy instances are read-only. This raises an AttributeError + anytime an attempt is made to set an attribute. + """ + raise AttributeError('cannot set %s.%s' % + (self.__class__.__name__, name) + ) + + def __delattr__(self, name): + """ + Proxy instances are read-only. This raises an AttributeError + anytime an attempt is made to delete an attribute. + """ + raise AttributeError('cannot del %s.%s' % + (self.__class__.__name__, name) + ) + + def __repr__(self): + return '%s(%r)' % (self.__class__.__name__, self.__obj) + + def __str__(self): + return self.cli_name + class Registrar(object): def __init__(self, *allowed): diff --git a/ipalib/tests/test_plugable.py b/ipalib/tests/test_plugable.py index f0bdeb4a..0421e72b 100644 --- a/ipalib/tests/test_plugable.py +++ b/ipalib/tests/test_plugable.py @@ -24,6 +24,53 @@ Unit tests for `ipalib.plugable` module. from ipalib import plugable, errors +def test_to_cli(): + f = plugable.to_cli + assert f('initialize') == 'initialize' + assert f('find_everything') == 'find-everything' + assert f('user__add') == 'user.add' + assert f('meta_service__do_something') == 'meta-service.do-something' + + +def test_from_cli(): + f = plugable.from_cli + assert f('initialize') == 'initialize' + assert f('find-everything') == 'find_everything' + assert f('user.add') == 'user__add' + assert f('meta-service.do-something') == 'meta_service__do_something' + + +def test_Plugin(): + p = plugable.Plugin() + assert p.name == 'Plugin' + assert repr(p) == '%s.Plugin()' % plugable.__name__ + + class some_plugin(plugable.Plugin): + pass + p = some_plugin() + assert p.name == 'some_plugin' + assert repr(p) == '%s.some_plugin()' % __name__ + + +def test_Proxy(): + class CommandProxy(plugable.Proxy): + __slots__ = ( + 'get_label', + '__call__', + ) + + class Command(plugable.Plugin): + def get_label(self): + return 'Add User' + def __call__(self, *argv, **kw): + return (argv, kw) + + i = Command() + p = CommandProxy(i, 'hello') + assert '__dict__' not in dir(p) + #assert repr(p) == 'CommandProxy(%s.Command())' % __name__ + + def test_Registrar(): class Base1(object): pass |