ipalib: provide per-call command context

Add context which is valid for the duration of command call. The context
is accessible using the `context` attribute of Command and Object plugins.

Reviewed-By: Martin Basti <mbasti@redhat.com>
This commit is contained in:
Jan Cholasta
2016-03-02 11:00:23 +01:00
committed by Martin Basti
parent 6851e560dd
commit e5520dc347
2 changed files with 31 additions and 0 deletions

View File

@@ -38,6 +38,7 @@ from ipalib.errors import (ZeroArgumentError, MaxArgumentError, OverlapError,
VersionError, OptionError, InvocationError,
ValidationError, ConversionError)
from ipalib import messages
from ipalib.request import context, context_frame
from ipalib.util import json_serialize
if six.PY3:
@@ -370,6 +371,10 @@ class HasParam(Plugin):
check(namespace)
setattr(self, name, namespace)
@property
def context(self):
return context.current_frame
class Command(HasParam):
"""
@@ -424,6 +429,11 @@ class Command(HasParam):
XML-RPC and the executed an the nearest IPA server.
"""
self.ensure_finalized()
with context_frame():
self.context.principal = getattr(context, 'principal', None)
return self.__do_call(*args, **options)
def __do_call(self, *args, **options):
version_provided = 'version' in options
if version_provided:
self.verify_client_version(unicode(options['version']))

View File

@@ -22,6 +22,7 @@
Per-request thread-local data.
"""
import contextlib
import threading
from ipalib.base import ReadOnly, lock
@@ -32,6 +33,26 @@ from ipalib.constants import CALLABLE_ERROR
context = threading.local()
class _FrameContext(object):
pass
@contextlib.contextmanager
def context_frame():
try:
frame_back = context.current_frame
except AttributeError:
pass
context.current_frame = _FrameContext()
try:
yield
finally:
try:
context.current_frame = frame_back
except UnboundLocalError:
del context.current_frame
class Connection(ReadOnly):
"""
Base class for connection objects stored on `request.context`.