summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Gerard DeRose <jderose@redhat.com>2008-10-30 01:11:33 -0600
committerJason Gerard DeRose <jderose@redhat.com>2008-10-30 01:11:33 -0600
commitddb5449c7faabbd4c1b71adfe84c386b943a163f (patch)
tree07a38af3cfbdd29d6df6adfae4169d9130c1086d
parente37760a27358021962a6e6a8a7fbdc5195ce5bbe (diff)
downloadfreeipa-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.py13
-rw-r--r--ipalib/__init__.py27
-rw-r--r--ipalib/backend.py14
-rw-r--r--ipalib/cli.py2
-rw-r--r--ipalib/plugable.py21
-rw-r--r--tests/test_ipalib/test_backend.py22
6 files changed, 83 insertions, 16 deletions
diff --git a/ipa_server/plugins/b_ldap.py b/ipa_server/plugins/b_ldap.py
index b58a644a..e53afc12 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 4593e581..a6664f73 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 82ed14f3..b1e15f33 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 021e01ad..39773d73 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 b0ba32b7..9ddcb30f 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 cd490fe0..88bd2da4 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()'