Hi, these patches are for master only, see commit messages for details.
Honza -- Jan Cholasta
From 49f3e365dc56ccda7d8aec7cf9d8e2d98791b031 Mon Sep 17 00:00:00 2001 From: Jan Cholasta <jchol...@redhat.com> Date: Wed, 2 Mar 2016 11:00:23 +0100 Subject: [PATCH 1/2] 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. --- ipalib/frontend.py | 10 ++++++++++ ipalib/request.py | 21 +++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/ipalib/frontend.py b/ipalib/frontend.py index 5b730b1..e91660d 100644 --- a/ipalib/frontend.py +++ b/ipalib/frontend.py @@ -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'])) diff --git a/ipalib/request.py b/ipalib/request.py index 9484be5..d851ba8 100644 --- a/ipalib/request.py +++ b/ipalib/request.py @@ -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`. -- 2.5.0
From 8ca33656a7ebb7819af9a8101befb20396d2bd75 Mon Sep 17 00:00:00 2001 From: Jan Cholasta <jchol...@redhat.com> Date: Wed, 2 Mar 2016 12:44:15 +0100 Subject: [PATCH 2/2] ipalib: add convenient Command method for adding messages Call the add_message() method of Command from anywhere in the implementation of a command to add a message to the result of the command. --- ipalib/frontend.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/ipalib/frontend.py b/ipalib/frontend.py index e91660d..ba830f2 100644 --- a/ipalib/frontend.py +++ b/ipalib/frontend.py @@ -434,13 +434,17 @@ class Command(HasParam): return self.__do_call(*args, **options) def __do_call(self, *args, **options): - version_provided = 'version' in options - if version_provided: + self.context.__messages = [] + if 'version' in options: self.verify_client_version(unicode(options['version'])) elif self.api.env.skip_version_check and not self.api.env.in_server: options['version'] = u'2.0' else: options['version'] = API_VERSION + if self.api.env.in_server: + # add message only on server side + self.add_message( + messages.VersionMissing(server_version=API_VERSION)) params = self.args_options_2_params(*args, **options) self.debug( 'raw: %s(%s)', self.name, ', '.join(self._repr_iter(**params)) @@ -454,12 +458,9 @@ class Command(HasParam): self.validate(**params) (args, options) = self.params_2_args_options(**params) ret = self.run(*args, **options) - if (not version_provided and isinstance(ret, dict) and - self.api.env.in_server): - # add message only on server side - messages.add_message( - API_VERSION, ret, - messages.VersionMissing(server_version=API_VERSION)) + if isinstance(ret, dict): + for message in self.context.__messages: + messages.add_message(options['version'], ret, message) if ( isinstance(ret, dict) and 'summary' in self.output @@ -470,6 +471,9 @@ class Command(HasParam): self.validate_output(ret, options['version']) return ret + def add_message(self, message): + self.context.__messages.append(message) + def soft_validate(self, values): errors = dict() for p in self.params(): -- 2.5.0
-- Manage your subscription for the Freeipa-devel mailing list: https://www.redhat.com/mailman/listinfo/freeipa-devel Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code