Bug 1309060 - Update futures to version 3.0.5, r?gps
We need the fix from https://github.com/agronholm/pythonfutures/issues/25
to allow sending KeyboardInterrupts to thread pools.
MozReview-Commit-ID: 5VfBttLbKOr
--- a/python/futures/CHANGES
+++ b/python/futures/CHANGES
@@ -1,8 +1,26 @@
+3.0.5
+=====
+
+- Fixed OverflowError with ProcessPoolExecutor on Windows (regression introduced in 3.0.4)
+
+
+3.0.4
+=====
+
+- Fixed inability to forcibly terminate the process if there are pending workers
+
+
+3.0.3
+=====
+
+- Fixed AttributeErrors on exit on Python 2.x
+
+
3.0.2
=====
- Made multiprocessing optional again on implementations other than just Jython
3.0.1
=====
--- a/python/futures/PKG-INFO
+++ b/python/futures/PKG-INFO
@@ -1,11 +1,11 @@
Metadata-Version: 1.0
Name: futures
-Version: 3.0.2
+Version: 3.0.5
Summary: Backport of the concurrent.futures package from Python 3.2
Home-page: https://github.com/agronholm/pythonfutures
Author: Alex Gronholm
Author-email: alex.gronholm+pypi@nextday.fi
License: BSD
Description: UNKNOWN
Platform: UNKNOWN
Classifier: License :: OSI Approved :: BSD License
--- a/python/futures/concurrent/futures/_base.py
+++ b/python/futures/concurrent/futures/_base.py
@@ -222,17 +222,18 @@ def as_completed(fs, timeout=None):
waiter.event.clear()
for future in finished:
yield future
pending.remove(future)
finally:
for f in fs:
- f._waiters.remove(waiter)
+ with f._condition:
+ f._waiters.remove(waiter)
DoneAndNotDoneFutures = collections.namedtuple(
'DoneAndNotDoneFutures', 'done not_done')
def wait(fs, timeout=None, return_when=ALL_COMPLETED):
"""Wait for the futures in the given sequence to complete.
Args:
fs: The sequence of Futures (possibly created by different Executors) to
@@ -269,17 +270,18 @@ def wait(fs, timeout=None, return_when=A
if len(done) == len(fs):
return DoneAndNotDoneFutures(done, not_done)
waiter = _create_and_install_waiters(fs, return_when)
waiter.event.wait(timeout)
for f in fs:
- f._waiters.remove(waiter)
+ with f._condition:
+ f._waiters.remove(waiter)
done.update(waiter.finished_futures)
return DoneAndNotDoneFutures(done, set(fs) - done)
class Future(object):
"""Represents the result of an asynchronous computation."""
def __init__(self):
--- a/python/futures/concurrent/futures/process.py
+++ b/python/futures/concurrent/futures/process.py
@@ -68,21 +68,21 @@ import sys
# threads/processes finish.
_threads_queues = weakref.WeakKeyDictionary()
_shutdown = False
def _python_exit():
global _shutdown
_shutdown = True
- items = list(_threads_queues.items())
+ items = list(_threads_queues.items()) if _threads_queues else ()
for t, q in items:
q.put(None)
for t, q in items:
- t.join()
+ t.join(sys.maxint)
# Controls how many more calls than processes will be queued in the call queue.
# A smaller number will mean that processes spend more time idle waiting for
# work while a larger number will make Future.cancel() succeed less frequently
# (Futures in the call queue cannot be cancelled).
EXTRA_QUEUED_CALLS = 1
class _WorkItem(object):
@@ -342,17 +342,17 @@ class ProcessPoolExecutor(_base.Executor
def shutdown(self, wait=True):
with self._shutdown_lock:
self._shutdown_thread = True
if self._queue_management_thread:
# Wake up queue management thread
self._result_queue.put(None)
if wait:
- self._queue_management_thread.join()
+ self._queue_management_thread.join(sys.maxint)
# To reduce the risk of openning too many files, remove references to
# objects that use file descriptors.
self._queue_management_thread = None
self._call_queue = None
self._result_queue = None
self._processes = None
shutdown.__doc__ = _base.Executor.shutdown.__doc__
--- a/python/futures/concurrent/futures/thread.py
+++ b/python/futures/concurrent/futures/thread.py
@@ -27,21 +27,21 @@ import sys
# threads finish.
_threads_queues = weakref.WeakKeyDictionary()
_shutdown = False
def _python_exit():
global _shutdown
_shutdown = True
- items = list(_threads_queues.items())
+ items = list(_threads_queues.items()) if _threads_queues else ()
for t, q in items:
q.put(None)
for t, q in items:
- t.join()
+ t.join(sys.maxint)
atexit.register(_python_exit)
class _WorkItem(object):
def __init__(self, future, fn, args, kwargs):
self.future = future
self.fn = fn
self.args = args
@@ -125,10 +125,10 @@ class ThreadPoolExecutor(_base.Executor)
_threads_queues[t] = self._work_queue
def shutdown(self, wait=True):
with self._shutdown_lock:
self._shutdown = True
self._work_queue.put(None)
if wait:
for t in self._threads:
- t.join()
+ t.join(sys.maxint)
shutdown.__doc__ = _base.Executor.shutdown.__doc__
--- a/python/futures/docs/index.rst
+++ b/python/futures/docs/index.rst
@@ -107,17 +107,17 @@ And:
# it is executing this function.
print(f.result())
executor = ThreadPoolExecutor(max_workers=1)
executor.submit(wait_on_future)
.. class:: ThreadPoolExecutor(max_workers)
- Executes calls asynchronously using at pool of at most *max_workers* threads.
+ Executes calls asynchronously using a pool of at most *max_workers* threads.
.. _threadpoolexecutor-example:
ThreadPoolExecutor Example
^^^^^^^^^^^^^^^^^^^^^^^^^^
::
from concurrent import futures
--- a/python/futures/futures.egg-info/PKG-INFO
+++ b/python/futures/futures.egg-info/PKG-INFO
@@ -1,11 +1,11 @@
Metadata-Version: 1.0
Name: futures
-Version: 3.0.2
+Version: 3.0.5
Summary: Backport of the concurrent.futures package from Python 3.2
Home-page: https://github.com/agronholm/pythonfutures
Author: Alex Gronholm
Author-email: alex.gronholm+pypi@nextday.fi
License: BSD
Description: UNKNOWN
Platform: UNKNOWN
Classifier: License :: OSI Approved :: BSD License
--- a/python/futures/futures.egg-info/pbr.json
+++ b/python/futures/futures.egg-info/pbr.json
@@ -1,1 +1,1 @@
-{"is_release": false, "git_version": "fdbc9c3"}
\ No newline at end of file
+{"is_release": false, "git_version": "6532a74"}
\ No newline at end of file
--- a/python/futures/setup.py
+++ b/python/futures/setup.py
@@ -1,19 +1,26 @@
#!/usr/bin/env python
+from warnings import warn
+import sys
+
+if sys.version_info[0] > 2:
+ warn('This backport is meant only for Python 2.\n'
+ 'Python 3 users do not need it, as the concurrent.futures '
+ 'package is available in the standard library.')
extras = {}
try:
from setuptools import setup
extras['zip_safe'] = False
except ImportError:
from distutils.core import setup
setup(name='futures',
- version='3.0.2',
+ version='3.0.5',
description='Backport of the concurrent.futures package from Python 3.2',
author='Brian Quinlan',
author_email='brian@sweetapp.com',
maintainer='Alex Gronholm',
maintainer_email='alex.gronholm+pypi@nextday.fi',
url='https://github.com/agronholm/pythonfutures',
packages=['concurrent', 'concurrent.futures'],
license='BSD',
--- a/python/futures/test_futures.py
+++ b/python/futures/test_futures.py
@@ -2,16 +2,17 @@ import os
import subprocess
import sys
import threading
import functools
import contextlib
import logging
import re
import time
+import gc
from StringIO import StringIO
from test import test_support
from concurrent import futures
from concurrent.futures._base import (
PENDING, RUNNING, CANCELLED, CANCELLED_AND_NOTIFIED, FINISHED, Future)
try:
@@ -217,16 +218,17 @@ class ThreadPoolShutdownTest(ThreadPoolM
for t in executor._threads:
t.join()
def test_del_shutdown(self):
executor = futures.ThreadPoolExecutor(max_workers=5)
executor.map(abs, range(-5, 5))
threads = executor._threads
del executor
+ gc.collect()
for t in threads:
t.join()
class ProcessPoolShutdownTest(ProcessPoolMixin, ExecutorShutdownTest):
def _prime_executor(self):
pass
@@ -252,16 +254,17 @@ class ProcessPoolShutdownTest(ProcessPoo
p.join()
def test_del_shutdown(self):
executor = futures.ProcessPoolExecutor(max_workers=5)
list(executor.map(abs, range(-5, 5)))
queue_management_thread = executor._queue_management_thread
processes = executor._processes
del executor
+ gc.collect()
queue_management_thread.join()
for p in processes:
p.join()
class WaitTests(unittest.TestCase):
@@ -570,29 +573,29 @@ class FutureTests(unittest.TestCase):
f = Future()
self.assertTrue(f.cancel())
f.add_done_callback(fn)
self.assertTrue(was_cancelled[0])
def test_repr(self):
self.assertRegexpMatches(repr(PENDING_FUTURE),
- '<Future at 0x[0-9a-f]+ state=pending>')
+ '<Future at 0x[0-9a-f]+L? state=pending>')
self.assertRegexpMatches(repr(RUNNING_FUTURE),
- '<Future at 0x[0-9a-f]+ state=running>')
+ '<Future at 0x[0-9a-f]+L? state=running>')
self.assertRegexpMatches(repr(CANCELLED_FUTURE),
- '<Future at 0x[0-9a-f]+ state=cancelled>')
+ '<Future at 0x[0-9a-f]+L? state=cancelled>')
self.assertRegexpMatches(repr(CANCELLED_AND_NOTIFIED_FUTURE),
- '<Future at 0x[0-9a-f]+ state=cancelled>')
+ '<Future at 0x[0-9a-f]+L? state=cancelled>')
self.assertRegexpMatches(
repr(EXCEPTION_FUTURE),
- '<Future at 0x[0-9a-f]+ state=finished raised IOError>')
+ '<Future at 0x[0-9a-f]+L? state=finished raised IOError>')
self.assertRegexpMatches(
repr(SUCCESSFUL_FUTURE),
- '<Future at 0x[0-9a-f]+ state=finished returned int>')
+ '<Future at 0x[0-9a-f]+L? state=finished returned int>')
def test_cancel(self):
f1 = create_future(state=PENDING)
f2 = create_future(state=RUNNING)
f3 = create_future(state=CANCELLED)
f4 = create_future(state=CANCELLED_AND_NOTIFIED)
f5 = create_future(state=FINISHED, exception=IOError())
f6 = create_future(state=FINISHED, result=5)
--- a/python/futures/tox.ini
+++ b/python/futures/tox.ini
@@ -1,8 +1,8 @@
[tox]
-envlist = py26,py27
+envlist = py26,py27,pypy,jython
[testenv]
commands={envpython} test_futures.py []
[testenv:py26]
deps=unittest2