[kupfer: 32/38] commatrick: Combine the result of multiple actions
- From: Ulrik Sverdrup <usverdrup src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [kupfer: 32/38] commatrick: Combine the result of multiple actions
- Date: Sat, 16 Jan 2010 17:14:29 +0000 (UTC)
commit 1459083d72f32bfb3eaea473fe2db7a6488569ae
Author: Ulrik Sverdrup <ulrik sverdrup gmail com>
Date: Sat Jan 16 03:49:27 2010 +0100
commatrick: Combine the result of multiple actions
kupfer/commandexec.py | 89 +++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 82 insertions(+), 7 deletions(-)
---
diff --git a/kupfer/commandexec.py b/kupfer/commandexec.py
index dcf8520..3d52299 100644
--- a/kupfer/commandexec.py
+++ b/kupfer/commandexec.py
@@ -4,7 +4,11 @@ import contextlib
import gobject
+from kupfer import pretty
from kupfer import task
+from kupfer.obj.objects import SourceLeaf
+from kupfer.obj.sources import MultiSource
+from kupfer.obj.compose import MultipleLeaf
RESULT_NONE, RESULT_OBJECT, RESULT_SOURCE, RESULT_ASYNC = (1, 2, 3, 4)
RESULTS_SYNC = (RESULT_OBJECT, RESULT_SOURCE)
@@ -48,12 +52,9 @@ def _activate_action_single(obj, action, iobj):
def _activate_action_multiple(obj, action, iobj):
if not hasattr(action, "activate_multiple"):
- ret = None
iobjs = (None, ) if iobj is None else _get_leaf_members(iobj)
- for L in _get_leaf_members(obj):
- for I in iobjs:
- ret = _activate_action_single(L, action, I) or ret
- return ret
+ return _activate_action_multiple_multiplied(_get_leaf_members(obj),
+ action, iobjs)
if action.requires_object():
ret = action.activate_multiple(_get_leaf_members(obj), _get_leaf_members(iobj))
@@ -61,6 +62,21 @@ def _activate_action_multiple(obj, action, iobj):
ret = action.activate_multiple(_get_leaf_members(obj))
return ret
+def _activate_action_multiple_multiplied(objs, action, iobjs):
+ """
+ Multiple dispatch by "mulitplied" invocation of the simple activation
+
+ Return an iterable of the return values.
+ """
+ rets = []
+ for L in objs:
+ for I in iobjs:
+ ret = _activate_action_single(L, action, I)
+ rets.append(ret)
+ ctx = DefaultActionExecutionContext()
+ ret = ctx._combine_action_result_multiple(action, rets)
+ return ret
+
def parse_action_result(action, ret):
"""Return result type for @action and return value @ret"""
def valid_result(ret):
@@ -72,12 +88,12 @@ def parse_action_result(action, ret):
res = RESULT_SOURCE
if action.has_result() and valid_result(ret):
res = RESULT_OBJECT
- elif action.is_async():
+ elif action.is_async() and valid_result(ret):
res = RESULT_ASYNC
return res
-class ActionExecutionContext (gobject.GObject):
+class ActionExecutionContext (gobject.GObject, pretty.OutputMixin):
"""
command-result (result_type, result)
Emitted when a command is carried out, with its resulting value
@@ -134,7 +150,10 @@ class ActionExecutionContext (gobject.GObject):
res = parse_action_result(action, ret)
if res == RESULT_ASYNC:
+ # Register the task then "clear" the result
+ self.output_debug("Registering async task", ret)
self.task_runner.add_task(ret)
+ res, ret = RESULT_NONE, None
# Delegated command execution was requested: we pass
# through the result of the action to the parent execution context
@@ -149,6 +168,62 @@ class ActionExecutionContext (gobject.GObject):
self.emit("command-result", res, ret)
return res, ret
+
+ def _combine_action_result_multiple(self, action, retvals):
+ self.output_debug("Combining", repr(action), retvals,
+ "delegate=%s" % self._delegate)
+
+ def _make_retvalue(res, values):
+ "Construct a return value for type res"
+ if res == RESULT_SOURCE:
+ return values[0] if len(values) == 1 else MultiSource(values)
+ if res == RESULT_OBJECT:
+ return values[0] if len(values) == 1 else MultipleLeaf(values)
+ if res == RESULT_ASYNC:
+ # Register all tasks now, and return None upwards
+ for task in values:
+ self.output_debug("Registering async task", task)
+ self.task_runner.add_task(task)
+ return None
+
+ if not self._delegate:
+ values = []
+ res = RESULT_NONE
+ for ret in retvals:
+ res_type = parse_action_result(action, ret)
+ if res_type != RESULT_NONE:
+ values.append(ret)
+ res = res_type
+ return _make_retvalue(res, values)
+ else:
+ # Re-parse result values
+ res = RESULT_NONE
+ resmap = {}
+ for ret in retvals:
+ if ret is None:
+ continue
+ res_type, ret_obj = ret
+ if res_type != RESULT_NONE:
+ res = res_type
+ resmap.setdefault(res_type, []).append(ret_obj)
+
+ # register tasks
+ tasks = resmap.pop(RESULT_ASYNC, [])
+ _make_retvalue(RESULT_ASYNC, tasks)
+
+ if len(resmap) == 1:
+ # Return the only of the Source or Object case
+ key, values = resmap.items()[0]
+ return key, _make_retvalue(key, values)
+ elif len(resmap) > 1:
+ # Put the source in a leaf and return a multiple leaf
+ source = _make_retvalue(RESULT_SOURCE, resmap[RESULT_SOURCE])
+ objects = resmap[RESULT_OBJECT]
+ objects.append(SourceLeaf(source))
+ return RESULT_OBJECT, _make_retvalue(RESULT_OBJECT, objects)
+ return RESULT_NONE, None
+
+
# Action result type, action result
gobject.signal_new("command-result", ActionExecutionContext,
gobject.SIGNAL_RUN_LAST,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]