diff options
author | Jason Gerard DeRose <jderose@redhat.com> | 2008-10-30 01:11:33 -0600 |
---|---|---|
committer | Jason Gerard DeRose <jderose@redhat.com> | 2008-10-30 01:11:33 -0600 |
commit | ddb5449c7faabbd4c1b71adfe84c386b943a163f (patch) | |
tree | 07a38af3cfbdd29d6df6adfae4169d9130c1086d | |
parent | e37760a27358021962a6e6a8a7fbdc5195ce5bbe (diff) | |
download | freeipa-ddb5449c7faabbd4c1b71adfe84c386b943a163f.tar.gz freeipa-ddb5449c7faabbd4c1b71adfe84c386b943a163f.tar.xz freeipa-ddb5449c7faabbd4c1b71adfe84c386b943a163f.zip |
Did some initial work for Context plugins
-rw-r--r-- | ipa_server/plugins/b_ldap.py | 13 | ||||
-rw-r--r-- | ipalib/__init__.py | 27 | ||||
-rw-r--r-- | ipalib/backend.py | 14 | ||||
-rw-r--r-- | ipalib/cli.py | 2 | ||||
-rw-r--r-- | ipalib/plugable.py | 21 | ||||
-rw-r--r-- | tests/test_ipalib/test_backend.py | 22 |
6 files changed, 83 insertions, 16 deletions
diff --git a/ipa_server/plugins/b_ldap.py b/ipa_server/plugins/b_ldap.py index b58a644a3..e53afc125 100644 --- a/ipa_server/plugins/b_ldap.py +++ b/ipa_server/plugins/b_ldap.py @@ -25,13 +25,24 @@ This wraps the python-ldap bindings. """ import ldap as _ldap -from ipalib import api +from ipalib import api, Context from ipalib import errors from ipalib.crud import CrudBackend from ipa_server import servercore from ipa_server import ipaldap +class conn(Context): + """ + Thread-local LDAP connection. + """ + + def get_value(self): + return 'it worked' + +api.register(conn) + + class ldap(CrudBackend): """ LDAP backend plugin. diff --git a/ipalib/__init__.py b/ipalib/__init__.py index 4593e581d..a6664f73b 100644 --- a/ipalib/__init__.py +++ b/ipalib/__init__.py @@ -30,15 +30,18 @@ To learn about the ``ipalib`` library, you should read the code in this order: """ import plugable -import frontend -import backend -import config - -api = plugable.API( - frontend.Command, - frontend.Object, - frontend.Method, - frontend.Property, - frontend.Application, - backend.Backend, -) +from backend import Backend, Context +from frontend import Command, Object, Method, Property, Application +from ipa_types import Bool, Int, Unicode, Enum +from frontend import Param, DefaultFrom + +def get_standard_api(unit_test=False): + api = plugable.API( + Command, Object, Method, Property, Application, + Backend, Context, + ) + if unit_test is True: + api.env.mode = 'unit_test' + return api + +api = get_standard_api() diff --git a/ipalib/backend.py b/ipalib/backend.py index 82ed14f3f..b1e15f337 100644 --- a/ipalib/backend.py +++ b/ipalib/backend.py @@ -23,9 +23,23 @@ Base classes for all backed-end plugins. import plugable + class Backend(plugable.Plugin): """ Base class for all backend plugins. """ __proxy__ = False # Backend plugins are not wrapped in a PluginProxy + + +class Context(plugable.Plugin): + """ + Base class for plugable context components. + """ + + __proxy__ = False # Backend plugins are not wrapped in a PluginProxy + + def get_value(self): + raise NotImplementedError( + '%s.get_value()' % self.__class__.__name__ + ) diff --git a/ipalib/cli.py b/ipalib/cli.py index 021e01ada..39773d739 100644 --- a/ipalib/cli.py +++ b/ipalib/cli.py @@ -331,7 +331,7 @@ class CLI(object): if len(a) < 2: parser.error('badly specified environment string,'\ 'use var1=val1[,var2=val2]..') - overrides[a[0].strip()] = a[1].strip() + overrides[str(a[0].strip())] = a[1].strip() overrides['context'] = 'cli' self.api.bootstrap(**overrides) diff --git a/ipalib/plugable.py b/ipalib/plugable.py index b0ba32b7e..9ddcb30f6 100644 --- a/ipalib/plugable.py +++ b/ipalib/plugable.py @@ -27,6 +27,7 @@ http://docs.python.org/ref/sequence-types.html import re import inspect +import threading import errors from errors import check_type, check_isinstance from config import Environment, Env @@ -705,6 +706,25 @@ class Registrar(DictProxy): self.__registered.add(klass) +class LazyContext(object): + """ + On-demand creation of thread-local context attributes. + """ + + def __init__(self, api): + self.__api = api + self.__context = threading.local() + + def __getattr__(self, name): + if name not in self.__context.__dict__: + if name not in self.__api.Context: + raise AttributeError('no Context plugin for %r' % name) + value = self.__api.Context[name].get_value() + self.__context.__dict__[name] = value + return self.__context.__dict__[name] + + + class API(DictProxy): """ Dynamic API object through which `Plugin` instances are accessed. @@ -715,6 +735,7 @@ class API(DictProxy): self.__done = set() self.register = Registrar(*allowed) self.env = Env() + self.context = LazyContext(self) super(API, self).__init__(self.__d) def __doing(self, name): diff --git a/tests/test_ipalib/test_backend.py b/tests/test_ipalib/test_backend.py index cd490fe04..88bd2da47 100644 --- a/tests/test_ipalib/test_backend.py +++ b/tests/test_ipalib/test_backend.py @@ -22,12 +22,12 @@ Test the `ipalib.backend` module. """ from ipalib import backend, plugable, errors -from tests.util import ClassChecker +from tests.util import ClassChecker, raises class test_Backend(ClassChecker): """ - Test the `backend.Backend` class. + Test the `ipalib.backend.Backend` class. """ _cls = backend.Backend @@ -35,3 +35,21 @@ class test_Backend(ClassChecker): def test_class(self): assert self.cls.__bases__ == (plugable.Plugin,) assert self.cls.__proxy__ is False + + +class test_Context(ClassChecker): + """ + Test the `ipalib.backend.Context` class. + """ + + _cls = backend.Context + + def test_get_value(self): + """ + Test the `ipalib.backend.Context.get_value` method. + """ + class Subclass(self.cls): + pass + o = Subclass() + e = raises(NotImplementedError, o.get_value) + assert str(e) == 'Subclass.get_value()' |