Commits

Cameron Simpson committed b093867

cs.threada, cs.app.pilfers: add func_sig optional parameter to RunTreeOp factory function to allow easy submission of functions other than many-to-many; import convertors from cs.app.pilfer and adapt the latter to use func_sig

Comments (0)

Files changed (2)

lib/python/cs/app/pilfer.py

 from cs.later import Later
 from cs.lex import get_identifier
 from cs.logutils import setup_logging, logTo, Pfx, debug, error, warning, exception, pfx_iter, D
-from cs.threads import runTree, RunTreeOp
+from cs.threads import runTree, RunTreeOp, RUN_TREE_OP_MANY_TO_MANY, \
+                        RUN_TREE_OP_ONE_TO_MANY, RUN_TREE_OP_ONE_TO_ONE, \
+                        RUN_TREE_OP_SELECT
 from cs.urlutils import URL
 from cs.misc import O
 
 re_COMPARE = re.compile(r'([a-z]\w*)==')
 re_ASSIGN  = re.compile(r'([a-z]\w*)=')
 
-def conv_one_to_one(func):
-  ''' Convert a one-to-one function to a many to many.
-  '''
-  def converted(items, *a, **kw):
-    results = []
-    for item in items:
-      yield func(item, *a, **kw)
-  return converted
-
-def conv_one_test(func):
-  ''' Convert a test-one function to one-to-many.
-  '''
-  def converted(items, *a, **kw):
-    for item in items:
-      if func(item, *a, **kw):
-        yield item
-  return converted
-
-def conv_one_to_many(func):
-  def converted(items, *a, **kw):
-    for item in items:
-      for result in func(item, *a, **kw):
-        yield result
-  return converted
-
 def action_operator(action,
                     many_to_many=None,
                     one_to_many=None,
     if action in many_to_many:
       # many-to-many functions get passed straight in
       func = many_to_many[action]
-      if kwargs:
-        func = partial(func, **kwargs)
+      func_sig = RUN_TREE_OP_MANY_TO_MANY
     elif action in one_to_many:
       # one-to-many is converted into many-to-many
       fork_input = True
       func = one_to_many[action]
-      if kwargs:
-        func = partial(func, **kwargs)
-      func = conv_one_to_many(func)
+      func_sig = RUN_TREE_OP_ONE_TO_MANY
     elif action in one_to_one:
       fork_input = True
       func = one_to_one[action]
-      if kwargs:
-        func = partial(func, **kwargs)
-      func = conv_one_to_one(func)
+      func_sig = RUN_TREE_OP_ONE_TO_ONE
     elif action in one_test:
       fork_input = True
       func = one_test[action]
-      if kwargs:
-        func = partial(func, **kwargs)
-      func = conv_one_test(func)
+      func_sig = RUN_TREE_OP_SELECT
     else:
       raise ValueError("unknown action")
-    return RunTreeOp(func, fork_input, fork_state)
+    if kwargs:
+      func = partial(func, **kwargs)
+    return RunTreeOp(func, fork_input, fork_state, func_sig)
 
 if __name__ == '__main__':
   import sys

lib/python/cs/threads.py

 
 _RunTreeOp = namedtuple('RunTreeOp', 'func fork_input fork_state')
 
-def RunTreeOp(func, fork_input, fork_state):
+RUN_TREE_OP_MANY_TO_MANY = 0
+RUN_TREE_OP_ONE_TO_MANY = 1
+RUN_TREE_OP_ONE_TO_ONE = 2
+RUN_TREE_OP_SELECT = 3
+
+def _conv_one_to_many(func):
+  def converted(items, *a, **kw):
+    for item in items:
+      for result in func(item, *a, **kw):
+        yield result
+  return converted
+
+def _conv_one_to_one(func):
+  ''' Convert a one-to-one function to a many to many.
+  '''
+  def converted(items, *a, **kw):
+    results = []
+    for item in items:
+      yield func(item, *a, **kw)
+  return converted
+
+def _conv_select(func):
+  ''' Convert a test-one function to one-to-many.
+  '''
+  def converted(items, *a, **kw):
+    for item in items:
+      if func(item, *a, **kw):
+        yield item
+  return converted
+
+def RunTreeOp(func, fork_input, fork_state, func_sig=None):
+  if func_sig is None:
+    func_sig = RUN_TREE_OP_MANY_TO_MANY
+
   ok = True
+
   if func is not None and not callable(func):
     error("RunTreeOp: bad func: %r", func)
     ok = False
+  if func_sig == RUN_TREE_OP_MANY_TO_MANY:
+    pass
+  elif func_sig == RUN_TREE_OP_ONE_TO_MANY:
+    func = _conv_one_to_many(func)
+  elif func_sig == RUN_TREE_OP_ONE_TO_ONE:
+    func = _conv_one_to_one(func)
+  elif func_sig == RUN_TREE_OP_SELECT:
+    func = _conv_select(func)
+  else:
+    error("RunTreeOp: invalid function signature")
+    ok = False
+
   if not ok:
     raise ValueError("invalid RunTreeOp() call")
+
   return _RunTreeOp(func, fork_input, fork_state)
 
 def runTree(input, operators, state, funcQ):