Skip to content

Commit

Permalink
allow timeout + buffersize
Browse files Browse the repository at this point in the history
  • Loading branch information
ebonnal committed Oct 18, 2024
1 parent fb33d56 commit e5c867a
Show file tree
Hide file tree
Showing 4 changed files with 9 additions and 11 deletions.
3 changes: 1 addition & 2 deletions Doc/library/concurrent.futures.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ Executor Objects
if :meth:`~iterator.__next__` is called and the result isn't available
after *timeout* seconds from the original call to :meth:`Executor.map`.
*timeout* can be an int or a float. If *timeout* is not specified or
``None``, there is no limit to the wait time. Incompatible with
*buffersize*.
``None``, there is no limit to the wait time.

If a *fn* call raises an exception, then that exception will be
raised when its value is retrieved from the iterator.
Expand Down
5 changes: 1 addition & 4 deletions Lib/concurrent/futures/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ def map(self, fn, *iterables, timeout=None, chunksize=1, buffersize=None):
fn: A callable that will take as many arguments as there are
passed iterables.
timeout: The maximum number of seconds to wait. If None, then there
is no limit on the wait time. Incompatible with buffersize.
is no limit on the wait time.
chunksize: The size of the chunks the iterable will be broken into
before being passed to a child process. This argument is only
used by ProcessPoolExecutor; it is ignored by
Expand All @@ -603,9 +603,6 @@ def map(self, fn, *iterables, timeout=None, chunksize=1, buffersize=None):
if buffersize is not None and buffersize < 1:
raise ValueError("buffersize must be None or >= 1.")

if buffersize is not None and timeout is not None:
raise ValueError("cannot specify both buffersize and timeout.")

if timeout is not None:
end_time = timeout + time.monotonic()

Expand Down
2 changes: 1 addition & 1 deletion Lib/concurrent/futures/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -820,7 +820,7 @@ def map(self, fn, *iterables, timeout=None, chunksize=1, buffersize=None):
fn: A callable that will take as many arguments as there are
passed iterables.
timeout: The maximum number of seconds to wait. If None, then there
is no limit on the wait time. Incompatible with buffersize.
is no limit on the wait time.
chunksize: If greater than one, the iterables will be chopped into
chunks of size chunksize and submitted to the process pool.
If set to one, the items in the list will be sent one at a time.
Expand Down
10 changes: 6 additions & 4 deletions Lib/test/test_concurrent_futures/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,19 @@ def test_map_timeout(self):
def test_map_with_buffersize(self):
with self.assertRaisesRegex(ValueError, "buffersize must be None or >= 1."):
self.executor.map(bool, [], buffersize=0)
with self.assertRaisesRegex(
ValueError, "cannot specify both buffersize and timeout."
):
self.executor.map(bool, [], timeout=1, buffersize=1)

it = range(4)
self.assertEqual(
list(self.executor.map(str, it, buffersize=1)),
list(map(str, it)),
)

def test_map_with_buffersize_and_timeout(self):
it = self.executor.map(time.sleep, (0, 1), timeout=0.5)
next(it)
with self.assertRaises(TimeoutError):
next(it)

def test_map_with_buffersize_on_infinite_iterable(self):
results = self.executor.map(str, itertools.count(1), buffersize=1)
self.assertEqual(next(iter(results)), "1")
Expand Down

0 comments on commit e5c867a

Please sign in to comment.