@@ -23,7 +23,26 @@ class ParslPoolExecutor(Executor, AbstractContextManager):
2323 2. Supplying an already-started Parsl :class:`~parsl.DataFlowKernel` (DFK).
2424 The executor assumes you will start and stop the Parsl DFK outside the Executor.
2525
26- Note: Parsl does not support canceling tasks. The :meth:`map` method does not cancel work
26+ The futures returned by :meth:`submit` and :meth:`map` are Parsl futures and will work
27+ with the same function chaining mechanisms as when using Parsl with decorators.
28+
29+ .. code-block:: python
30+
31+ def f(x):
32+ return x + 1
33+
34+ @python_app
35+ def parity(x):
36+ return 'odd' if x % 2 == 1 else 'even'
37+
38+ with ParslPoolExecutor(config=my_parsl_config) as executor:
39+ future_1 = executor.submit(f, 1)
40+ assert parity(future_1) == 'even' # Function chaining, as expected
41+
42+ future_2 = executor.submit(f, future_1)
43+ assert future_2.result() == 3 # Chaining works with `submit` too
44+
45+ Parsl does not support canceling tasks. The :meth:`map` method does not cancel work
2746 when one member of the run fails or a timeout is reached
2847 and :meth:`shutdown` does not cancel work on completion.
2948 """
@@ -63,7 +82,7 @@ def app_count(self):
6382 """Number of functions currently registered with the executor"""
6483 return len (self ._app_cache )
6584
66- def _get_app (self , fn : Callable ) -> PythonApp :
85+ def get_app (self , fn : Callable ) -> PythonApp :
6786 """Create a PythonApp for a function
6887
6988 Args:
@@ -78,19 +97,48 @@ def _get_app(self, fn: Callable) -> PythonApp:
7897 return app
7998
8099 def submit (self , fn , * args , ** kwargs ):
100+ """Submits a callable to be executed with the given arguments.
101+
102+ Schedules the callable to be executed as ``fn(*args, **kwargs)`` and returns
103+ a Future instance representing the execution of the callable.
104+
105+ Returns:
106+ A Future representing the given call.
107+ """
108+
81109 if self ._dfk is None :
82110 raise RuntimeError ('Executor has been shut down.' )
83- app = self ._get_app (fn )
111+ app = self .get_app (fn )
84112 return app (* args , ** kwargs )
85113
86114 # TODO (wardlt): This override can go away when Parsl supports cancel
87115 def map (self , fn : Callable , * iterables : Iterable , timeout : Optional [float ] = None , chunksize : int = 1 ) -> Iterator :
116+ """Returns an iterator equivalent to map(fn, iter).
117+
118+ Args:
119+ fn: A callable that will take as many arguments as there are
120+ passed iterables.
121+ timeout: The maximum number of seconds to wait. If None, then there
122+ is no limit on the wait time.
123+ chunksize: If greater than one, the iterables will be chopped into
124+ chunks of size chunksize and submitted to the process pool.
125+ If set to one, the items in the list will be sent one at a time.
126+
127+ Returns:
128+ An iterator equivalent to: map(func, ``*iterables``) but the calls may
129+ be evaluated out-of-order.
130+
131+ Raises:
132+ TimeoutError: If the entire result iterator could not be generated
133+ before the given timeout.
134+ Exception: If ``fn(*args)`` raises for any values.
135+ """
88136 # This is a version of the CPython 3.9 `.map` implementation modified to not use `cancel`
89137 if timeout is not None :
90138 end_time = timeout + time .monotonic ()
91139
92140 # Submit the applications
93- app = self ._get_app (fn )
141+ app = self .get_app (fn )
94142 fs = [app (* args ) for args in zip (* iterables )]
95143
96144 # Yield the futures as completed
0 commit comments