Hello community, here is the log from the commit of package python-futures for openSUSE:Factory checked in at 2017-09-22 21:32:30 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-futures (Old) and /work/SRC/openSUSE:Factory/.python-futures.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-futures" Fri Sep 22 21:32:30 2017 rev:12 rq:527391 version:3.1.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-futures/python-futures.changes 2017-03-16 09:51:04.297729465 +0100 +++ /work/SRC/openSUSE:Factory/.python-futures.new/python-futures.changes 2017-09-22 21:32:40.147167986 +0200 @@ -1,0 +2,11 @@ +Thu Jun 1 20:57:57 UTC 2017 - [email protected] + +- update to 3.1.1: +- Backported sanity checks for the ``max_workers`` constructor argument for ThreadPoolExecutor and + ProcessPoolExecutor +- Set the default value of ``max_workers`` in ThreadPoolExecutor to ``None``, as in upstream code + (computes the thread pool size based on the number of CPUs) +- Added support for old-style exception objects +- Switched to the PSF license + +------------------------------------------------------------------- Old: ---- futures-3.0.5.tar.gz New: ---- futures-3.1.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-futures.spec ++++++ --- /var/tmp/diff_new_pack.kn6w9S/_old 2017-09-22 21:32:43.778656794 +0200 +++ /var/tmp/diff_new_pack.kn6w9S/_new 2017-09-22 21:32:43.782656232 +0200 @@ -18,15 +18,16 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-futures -Version: 3.0.5 +Version: 3.1.1 Release: 0 Summary: Backport of the concurrent.futures package from Python 3.2 -License: BSD-2-Clause +License: Python-2.0 Group: Development/Languages/Python Url: http://code.google.com/p/pythonfutures -Source: http://pypi.python.org/packages/source/f/futures/futures-%{version}.tar.gz +Source: https://files.pythonhosted.org/packages/source/f/futures/futures-%{version}.tar.gz BuildRequires: %{python_module devel} BuildRequires: fdupes +BuildRequires: python-rpm-macros BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildArch: noarch ++++++ futures-3.0.5.tar.gz -> futures-3.1.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/futures-3.0.5/CHANGES new/futures-3.1.1/CHANGES --- old/futures-3.0.5/CHANGES 2016-02-14 22:40:14.000000000 +0100 +++ new/futures-3.1.1/CHANGES 2017-04-14 16:32:09.000000000 +0200 @@ -1,3 +1,20 @@ +3.1.1 +===== + +- Backported sanity checks for the ``max_workers`` constructor argument for ThreadPoolExecutor and + ProcessPoolExecutor +- Set the default value of ``max_workers`` in ThreadPoolExecutor to ``None``, as in upstream code + (computes the thread pool size based on the number of CPUs) +- Added support for old-style exception objects +- Switched to the PSF license + + +3.1.0 +===== + +(Failed release) + + 3.0.5 ===== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/futures-3.0.5/LICENSE new/futures-3.1.1/LICENSE --- old/futures-3.0.5/LICENSE 2015-03-15 04:51:56.000000000 +0100 +++ new/futures-3.1.1/LICENSE 2017-04-14 16:32:09.000000000 +0200 @@ -1,21 +1,48 @@ -Copyright 2009 Brian Quinlan. All rights reserved. +PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 +-------------------------------------------- -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: +1. This LICENSE AGREEMENT is between the Python Software Foundation +("PSF"), and the Individual or Organization ("Licensee") accessing and +otherwise using this software ("Python") in source or binary form and +its associated documentation. - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY BRIAN QUINLAN "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -HALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file +2. Subject to the terms and conditions of this License Agreement, PSF +hereby grants Licensee a nonexclusive, royalty-free, world-wide +license to reproduce, analyze, test, perform and/or display publicly, +prepare derivative works, distribute, and otherwise use Python +alone or in any derivative version, provided, however, that PSF's +License Agreement and PSF's notice of copyright, i.e., "Copyright (c) +2001, 2002, 2003, 2004, 2005, 2006 Python Software Foundation; All Rights +Reserved" are retained in Python alone or in any derivative version +prepared by Licensee. + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python. + +4. PSF is making Python available to Licensee on an "AS IS" +basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any +relationship of agency, partnership, or joint venture between PSF and +Licensee. This License Agreement does not grant permission to use PSF +trademarks or trade name in a trademark sense to endorse or promote +products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using Python, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/futures-3.0.5/PKG-INFO new/futures-3.1.1/PKG-INFO --- old/futures-3.0.5/PKG-INFO 2016-02-14 22:51:15.000000000 +0100 +++ new/futures-3.1.1/PKG-INFO 2017-04-14 16:33:21.000000000 +0200 @@ -1,14 +1,14 @@ -Metadata-Version: 1.0 +Metadata-Version: 1.1 Name: futures -Version: 3.0.5 +Version: 3.1.1 Summary: Backport of the concurrent.futures package from Python 3.2 Home-page: https://github.com/agronholm/pythonfutures Author: Alex Gronholm Author-email: [email protected] -License: BSD +License: PSF Description: UNKNOWN Platform: UNKNOWN -Classifier: License :: OSI Approved :: BSD License +Classifier: License :: OSI Approved :: Python Software Foundation License Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: Programming Language :: Python :: 2.6 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/futures-3.0.5/concurrent/futures/_base.py new/futures-3.1.1/concurrent/futures/_base.py --- old/futures-3.0.5/concurrent/futures/_base.py 2016-01-18 01:35:19.000000000 +0100 +++ new/futures-3.1.1/concurrent/futures/_base.py 2017-04-14 16:32:09.000000000 +0200 @@ -6,6 +6,7 @@ import threading import itertools import time +import types __author__ = 'Brian Quinlan ([email protected])' @@ -300,6 +301,22 @@ callback(self) except Exception: LOGGER.exception('exception calling callback for %r', self) + except BaseException: + # Explicitly let all other new-style exceptions through so + # that we can catch all old-style exceptions with a simple + # "except:" clause below. + # + # All old-style exception objects are instances of + # types.InstanceType, but "except types.InstanceType:" does + # not catch old-style exceptions for some reason. Thus, the + # only way to catch all old-style exceptions without catching + # any new-style exceptions is to filter out the new-style + # exceptions, which all derive from BaseException. + raise + except: + # Because of the BaseException clause above, this handler only + # executes for old-style exception objects. + LOGGER.exception('exception calling callback for %r', self) def __repr__(self): with self._condition: @@ -354,7 +371,14 @@ def __get_result(self): if self._exception: - raise type(self._exception), self._exception, self._traceback + if isinstance(self._exception, types.InstanceType): + # The exception is an instance of an old-style class, which + # means type(self._exception) returns types.ClassType instead + # of the exception's actual class type. + exception_type = self._exception.__class__ + else: + exception_type = type(self._exception) + raise exception_type, self._exception, self._traceback else: return self._result diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/futures-3.0.5/concurrent/futures/process.py new/futures-3.1.1/concurrent/futures/process.py --- old/futures-3.0.5/concurrent/futures/process.py 2016-02-14 22:40:41.000000000 +0100 +++ new/futures-3.1.1/concurrent/futures/process.py 2017-04-14 16:32:09.000000000 +0200 @@ -126,7 +126,7 @@ return try: r = call_item.fn(*call_item.args, **call_item.kwargs) - except BaseException: + except: e = sys.exc_info()[1] result_queue.put(_ResultItem(call_item.work_id, exception=e)) @@ -262,6 +262,7 @@ _system_limited = "system provides too few semaphores (%d available, 256 necessary)" % nsems_max raise NotImplementedError(_system_limited) + class ProcessPoolExecutor(_base.Executor): def __init__(self, max_workers=None): """Initializes a new ProcessPoolExecutor instance. @@ -276,6 +277,9 @@ if max_workers is None: self._max_workers = multiprocessing.cpu_count() else: + if max_workers <= 0: + raise ValueError("max_workers must be greater than 0") + self._max_workers = max_workers # Make the call queue slightly larger than the number of processes to diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/futures-3.0.5/concurrent/futures/thread.py new/futures-3.1.1/concurrent/futures/thread.py --- old/futures-3.0.5/concurrent/futures/thread.py 2016-01-18 01:38:32.000000000 +0100 +++ new/futures-3.1.1/concurrent/futures/thread.py 2017-04-14 16:32:09.000000000 +0200 @@ -10,6 +10,13 @@ import weakref import sys +try: + from multiprocessing import cpu_count +except ImportError: + # some platforms don't have multiprocessing + def cpu_count(): + return None + __author__ = 'Brian Quinlan ([email protected])' # Workers are created as daemon threads. This is done to allow the interpreter @@ -53,7 +60,7 @@ try: result = self.fn(*self.args, **self.kwargs) - except BaseException: + except: e, tb = sys.exc_info()[1:] self.future.set_exception_info(e, tb) else: @@ -78,17 +85,25 @@ work_queue.put(None) return del executor - except BaseException: + except: _base.LOGGER.critical('Exception in worker', exc_info=True) + class ThreadPoolExecutor(_base.Executor): - def __init__(self, max_workers): + def __init__(self, max_workers=None): """Initializes a new ThreadPoolExecutor instance. Args: max_workers: The maximum number of threads that can be used to execute the given calls. """ + if max_workers is None: + # Use this number because ThreadPoolExecutor is often + # used to overlap I/O instead of CPU work. + max_workers = (cpu_count() or 1) * 5 + if max_workers <= 0: + raise ValueError("max_workers must be greater than 0") + self._max_workers = max_workers self._work_queue = queue.Queue() self._threads = set() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/futures-3.0.5/docs/index.rst new/futures-3.1.1/docs/index.rst --- old/futures-3.0.5/docs/index.rst 2016-01-18 01:35:19.000000000 +0100 +++ new/futures-3.1.1/docs/index.rst 2017-04-14 16:32:09.000000000 +0200 @@ -8,7 +8,7 @@ asynchronously executing callables. The asynchronous execution can be be performed by threads using -:class:`ThreadPoolExecutor` or seperate processes using +:class:`ThreadPoolExecutor` or separate processes using :class:`ProcessPoolExecutor`. Both implement the same interface, which is defined by the abstract :class:`Executor` class. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/futures-3.0.5/futures.egg-info/PKG-INFO new/futures-3.1.1/futures.egg-info/PKG-INFO --- old/futures-3.0.5/futures.egg-info/PKG-INFO 2016-02-14 22:51:15.000000000 +0100 +++ new/futures-3.1.1/futures.egg-info/PKG-INFO 2017-04-14 16:33:21.000000000 +0200 @@ -1,14 +1,14 @@ -Metadata-Version: 1.0 +Metadata-Version: 1.1 Name: futures -Version: 3.0.5 +Version: 3.1.1 Summary: Backport of the concurrent.futures package from Python 3.2 Home-page: https://github.com/agronholm/pythonfutures Author: Alex Gronholm Author-email: [email protected] -License: BSD +License: PSF Description: UNKNOWN Platform: UNKNOWN -Classifier: License :: OSI Approved :: BSD License +Classifier: License :: OSI Approved :: Python Software Foundation License Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: Programming Language :: Python :: 2.6 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/futures-3.0.5/futures.egg-info/SOURCES.txt new/futures-3.1.1/futures.egg-info/SOURCES.txt --- old/futures-3.0.5/futures.egg-info/SOURCES.txt 2016-02-14 22:51:15.000000000 +0100 +++ new/futures-3.1.1/futures.egg-info/SOURCES.txt 2017-04-14 16:33:21.000000000 +0200 @@ -20,5 +20,4 @@ futures.egg-info/SOURCES.txt futures.egg-info/dependency_links.txt futures.egg-info/not-zip-safe -futures.egg-info/pbr.json futures.egg-info/top_level.txt \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/futures-3.0.5/futures.egg-info/pbr.json new/futures-3.1.1/futures.egg-info/pbr.json --- old/futures-3.0.5/futures.egg-info/pbr.json 2015-06-12 23:44:51.000000000 +0200 +++ new/futures-3.1.1/futures.egg-info/pbr.json 1970-01-01 01:00:00.000000000 +0100 @@ -1 +0,0 @@ -{"is_release": false, "git_version": "6532a74"} \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/futures-3.0.5/setup.cfg new/futures-3.1.1/setup.cfg --- old/futures-3.0.5/setup.cfg 2016-02-14 22:51:15.000000000 +0100 +++ new/futures-3.1.1/setup.cfg 2017-04-14 16:33:21.000000000 +0200 @@ -1,12 +1,12 @@ [build_sphinx] -build-dir = build/sphinx source-dir = docs +build-dir = build/sphinx + +[upload_docs] +upload-dir = build/sphinx/html [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 -[upload_docs] -upload-dir = build/sphinx/html - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/futures-3.0.5/setup.py new/futures-3.1.1/setup.py --- old/futures-3.0.5/setup.py 2016-02-14 22:40:23.000000000 +0100 +++ new/futures-3.1.1/setup.py 2017-04-14 16:32:09.000000000 +0200 @@ -15,7 +15,7 @@ from distutils.core import setup setup(name='futures', - version='3.0.5', + version='3.1.1', description='Backport of the concurrent.futures package from Python 3.2', author='Brian Quinlan', author_email='[email protected]', @@ -23,8 +23,8 @@ maintainer_email='[email protected]', url='https://github.com/agronholm/pythonfutures', packages=['concurrent', 'concurrent.futures'], - license='BSD', - classifiers=['License :: OSI Approved :: BSD License', + license='PSF', + classifiers=['License :: OSI Approved :: Python Software Foundation License', 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'Programming Language :: Python :: 2.6', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/futures-3.0.5/test_futures.py new/futures-3.1.1/test_futures.py --- old/futures-3.0.5/test_futures.py 2015-06-12 23:48:50.000000000 +0200 +++ new/futures-3.1.1/test_futures.py 2017-04-14 16:32:09.000000000 +0200 @@ -8,12 +8,14 @@ import re import time import gc +import traceback 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) +from concurrent.futures.thread import cpu_count try: import unittest2 as unittest @@ -478,6 +480,13 @@ self.assertEqual([None, None], results) + def test_max_workers_negative(self): + for number in (0, -1): + with self.assertRaises(ValueError) as cm: + self.executor_type(max_workers=number) + + assert str(cm.exception) == "max_workers must be greater than 0" + class ThreadPoolExecutorTest(ThreadPoolMixin, ExecutorTest): def test_map_submits_without_iteration(self): @@ -490,6 +499,11 @@ self.executor.shutdown(wait=True) self.assertEqual(len(finished), 10) + def test_default_workers(self): + executor = self.executor_type() + self.assertEqual(executor._max_workers, + (cpu_count() or 1) * 5) + class ProcessPoolExecutorTest(ProcessPoolMixin, ExecutorTest): pass @@ -529,22 +543,33 @@ def test_done_callback_raises(self): with captured_stderr() as stderr: raising_was_called = [False] + raising_old_style_was_called = [False] fn_was_called = [False] def raising_fn(callback_future): raising_was_called[0] = True raise Exception('doh!') + def raising_old_style_fn(callback_future): + raising_old_style_was_called[0] = True + class OldStyle: # Does not inherit from object + def __str__(self): + return 'doh!' + raise OldStyle() + def fn(callback_future): fn_was_called[0] = True f = Future() f.add_done_callback(raising_fn) + f.add_done_callback(raising_old_style_fn) f.add_done_callback(fn) f.set_result(5) self.assertTrue(raising_was_called) + self.assertTrue(raising_old_style_was_called) self.assertTrue(fn_was_called) self.assertIn('Exception: doh!', stderr.getvalue()) + self.assertIn('OldStyle: doh!', stderr.getvalue()) def test_done_callback_already_successful(self): callback_result = [None] @@ -708,6 +733,33 @@ self.assertTrue(isinstance(f1.exception(timeout=5), IOError)) + def test_old_style_exception(self): + class OldStyle: # Does not inherit from object + def __str__(self): + return 'doh!' + callback_exc_info = [None] + def fn(callback_future): + callback_exc_info[0] = callback_future.exception_info() + f = Future() + f.add_done_callback(fn) + try: + raise OldStyle() + except OldStyle: + want_exc_info = sys.exc_info() + f.set_exception_info(*want_exc_info[1:]) + self.assertEqual(f.exception_info(), want_exc_info[1:]) + self.assertEqual(callback_exc_info[0], want_exc_info[1:]) + try: + f.result() + except OldStyle: + got_exc_info = sys.exc_info() + else: + self.fail('OldStyle exception not raised') + self.assertEqual(got_exc_info[:2], want_exc_info[:2]) + got_tb = traceback.extract_tb(got_exc_info[2]) + want_tb = traceback.extract_tb(want_exc_info[2]) + self.assertEqual(got_tb[-len(want_tb):], want_tb) + @reap_threads def test_main(): try: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/futures-3.0.5/tox.ini new/futures-3.1.1/tox.ini --- old/futures-3.0.5/tox.ini 2015-06-12 23:35:55.000000000 +0200 +++ new/futures-3.1.1/tox.ini 2017-04-14 16:32:09.000000000 +0200 @@ -1,8 +1,12 @@ [tox] envlist = py26,py27,pypy,jython +[tox:travis] +2.6 = py26 +2.7 = py27 + [testenv] -commands={envpython} test_futures.py [] +commands = {envpython} test_futures.py {posargs} [testenv:py26] -deps=unittest2 +deps = unittest2
