Did some initial work for Context plugins

This commit is contained in:
Jason Gerard DeRose 2008-10-30 01:11:33 -06:00
parent e37760a273
commit ddb5449c7f
6 changed files with 82 additions and 15 deletions

View File

@ -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.

View File

@ -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
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
api = plugable.API(
frontend.Command,
frontend.Object,
frontend.Method,
frontend.Property,
frontend.Application,
backend.Backend,
)
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()

View File

@ -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__
)

View File

@ -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)

View File

@ -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):

View File

@ -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()'