Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-Pebble for openSUSE:Factory checked in at 2022-08-17 18:17:00 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-Pebble (Old) and /work/SRC/openSUSE:Factory/.python-Pebble.new.1521 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-Pebble" Wed Aug 17 18:17:00 2022 rev:9 rq:997501 version:4.6.3 Changes: -------- --- /work/SRC/openSUSE:Factory/python-Pebble/python-Pebble.changes 2021-01-14 15:06:46.594910017 +0100 +++ /work/SRC/openSUSE:Factory/.python-Pebble.new.1521/python-Pebble.changes 2022-08-17 18:23:38.059238713 +0200 @@ -1,0 +2,23 @@ +Tue Aug 16 23:32:48 UTC 2022 - Yogalakshmi Arunachalam <yarunacha...@suse.com> + +- Update to 4.6.3 + + issue #84: fix import bug on Windows +- Update to 4.6.2 + * Fixes: + + issue #82: fix issue with poll mechanism in MAC OS Mojave (@sam-harding) + + Fix polling timeout resolution (@sam-harding) + +- Update to 4.6.1 + * Improvements: + + issue #76: allow spawning processes within `ProcessPool` workers + + Few minor improvements + + * Fixes: + + issues #75: fix error when cancelling futures in Python >= 3.8 + + issue #80: fix error when using decorators without @pie notation + + Several minor fixes on MAC OS + + * Tests: + + Add Windows and MAC OS test automation support + +------------------------------------------------------------------- Old: ---- Pebble-4.6.0.tar.gz New: ---- Pebble-4.6.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-Pebble.spec ++++++ --- /var/tmp/diff_new_pack.DDeQb2/_old 2022-08-17 18:23:38.451239526 +0200 +++ /var/tmp/diff_new_pack.DDeQb2/_new 2022-08-17 18:23:38.459239542 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-Pebble # -# Copyright (c) 2021 SUSE LLC +# Copyright (c) 2022 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %bcond_without python2 Name: python-Pebble -Version: 4.6.0 +Version: 4.6.3 Release: 0 Summary: Threading and multiprocessing eye-candy for Python License: LGPL-3.0-only ++++++ Pebble-4.6.0.tar.gz -> Pebble-4.6.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pebble-4.6.0/MANIFEST.in new/Pebble-4.6.3/MANIFEST.in --- old/Pebble-4.6.0/MANIFEST.in 2020-12-27 11:44:20.000000000 +0100 +++ new/Pebble-4.6.3/MANIFEST.in 2021-02-17 22:49:09.000000000 +0100 @@ -1 +1 @@ -include version.py LICENSE \ No newline at end of file +include LICENSE \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pebble-4.6.0/PKG-INFO new/Pebble-4.6.3/PKG-INFO --- old/Pebble-4.6.0/PKG-INFO 2020-12-27 11:51:17.000000000 +0100 +++ new/Pebble-4.6.3/PKG-INFO 2021-08-24 22:49:56.411429400 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: Pebble -Version: 4.6.0 +Version: 4.6.3 Summary: Threading and multiprocessing eye-candy. Home-page: https://github.com/noxdafox/pebble Author: Matteo Cafasso @@ -13,12 +13,12 @@ :Source: https://github.com/noxdafox/pebble :Documentation: https://pebble.readthedocs.io - :Download: https://pypi.python.org/pypi/pebble + :Download: https://pypi.org/project/Pebble/ - |travis badge| |docs badge| + |build badge| |docs badge| - .. |travis badge| image:: https://travis-ci.org/noxdafox/pebble.svg?branch=master - :target: https://travis-ci.org/noxdafox/pebble + .. |build badge| image:: https://github.com/noxdafox/pebble/actions/workflows/action.yml/badge.svg + :target: https://github.com/noxdafox/pebble/actions/workflows/action.yml :alt: Build Status .. |docs badge| image:: https://readthedocs.org/projects/pebble/badge/?version=latest :target: https://pebble.readthedocs.io @@ -70,7 +70,7 @@ from concurrent.futures import TimeoutError def function(foo, bar=0): - return foo + bar + return foo + bar def task_done(future): try: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pebble-4.6.0/Pebble.egg-info/PKG-INFO new/Pebble-4.6.3/Pebble.egg-info/PKG-INFO --- old/Pebble-4.6.0/Pebble.egg-info/PKG-INFO 2020-12-27 11:51:17.000000000 +0100 +++ new/Pebble-4.6.3/Pebble.egg-info/PKG-INFO 2021-08-24 22:49:56.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: Pebble -Version: 4.6.0 +Version: 4.6.3 Summary: Threading and multiprocessing eye-candy. Home-page: https://github.com/noxdafox/pebble Author: Matteo Cafasso @@ -13,12 +13,12 @@ :Source: https://github.com/noxdafox/pebble :Documentation: https://pebble.readthedocs.io - :Download: https://pypi.python.org/pypi/pebble + :Download: https://pypi.org/project/Pebble/ - |travis badge| |docs badge| + |build badge| |docs badge| - .. |travis badge| image:: https://travis-ci.org/noxdafox/pebble.svg?branch=master - :target: https://travis-ci.org/noxdafox/pebble + .. |build badge| image:: https://github.com/noxdafox/pebble/actions/workflows/action.yml/badge.svg + :target: https://github.com/noxdafox/pebble/actions/workflows/action.yml :alt: Build Status .. |docs badge| image:: https://readthedocs.org/projects/pebble/badge/?version=latest :target: https://pebble.readthedocs.io @@ -70,7 +70,7 @@ from concurrent.futures import TimeoutError def function(foo, bar=0): - return foo + bar + return foo + bar def task_done(future): try: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pebble-4.6.0/README.rst new/Pebble-4.6.3/README.rst --- old/Pebble-4.6.0/README.rst 2020-12-27 11:44:20.000000000 +0100 +++ new/Pebble-4.6.3/README.rst 2021-08-23 21:47:34.000000000 +0200 @@ -5,12 +5,12 @@ :Source: https://github.com/noxdafox/pebble :Documentation: https://pebble.readthedocs.io -:Download: https://pypi.python.org/pypi/pebble +:Download: https://pypi.org/project/Pebble/ -|travis badge| |docs badge| +|build badge| |docs badge| -.. |travis badge| image:: https://travis-ci.org/noxdafox/pebble.svg?branch=master - :target: https://travis-ci.org/noxdafox/pebble +.. |build badge| image:: https://github.com/noxdafox/pebble/actions/workflows/action.yml/badge.svg + :target: https://github.com/noxdafox/pebble/actions/workflows/action.yml :alt: Build Status .. |docs badge| image:: https://readthedocs.org/projects/pebble/badge/?version=latest :target: https://pebble.readthedocs.io @@ -62,7 +62,7 @@ from concurrent.futures import TimeoutError def function(foo, bar=0): - return foo + bar + return foo + bar def task_done(future): try: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pebble-4.6.0/pebble/__init__.py new/Pebble-4.6.3/pebble/__init__.py --- old/Pebble-4.6.0/pebble/__init__.py 2020-12-27 11:45:46.000000000 +0100 +++ new/Pebble-4.6.3/pebble/__init__.py 2021-08-24 22:46:26.000000000 +0200 @@ -1,5 +1,5 @@ __author__ = 'Matteo Cafasso' -__version__ = '4.6.0' +__version__ = '4.6.3' __license__ = 'LGPL' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pebble-4.6.0/pebble/concurrent/process.py new/Pebble-4.6.3/pebble/concurrent/process.py --- old/Pebble-4.6.0/pebble/concurrent/process.py 2020-12-27 11:44:21.000000000 +0100 +++ new/Pebble-4.6.3/pebble/concurrent/process.py 2021-03-06 12:18:50.000000000 +0100 @@ -40,8 +40,15 @@ The timeout parameter will set a maximum execution time for the decorated function. If the execution exceeds the timeout, the process will be stopped and the Future will raise TimeoutError. + The name parameter will set the process name. + The daemon parameter controls the underlying process daemon flag. + Default is True. + + The context parameter allows to provide the multiprocessing.context + object used for starting the process. + """ timeout = kwargs.get('timeout') name = kwargs.get('name') @@ -49,13 +56,18 @@ mp_context = kwargs.get('context') # decorator without parameters - if len(args) == 1 and not kwargs and callable(args[0]): + if not kwargs and len(args) == 1 and callable(args[0]): return _process_wrapper(args[0], timeout, name, daemon, multiprocessing) # decorator with parameters _validate_parameters(timeout, name, daemon, mp_context) mp_context = mp_context if mp_context is not None else multiprocessing + # without @pie syntax + if len(args) == 1 and callable(args[0]): + return _process_wrapper(args[0], timeout, name, daemon, multiprocessing) + + # with @pie syntax def decorating_function(function): return _process_wrapper(function, timeout, name, daemon, mp_context) @@ -83,7 +95,7 @@ worker = launch_process( name, _function_handler, daemon, mp_context, - target, args, kwargs, writer) + target, args, kwargs, (reader, writer)) writer.close() @@ -108,8 +120,8 @@ if isinstance(result, BaseException): if isinstance(result, ProcessExpired): result.exitcode = worker.exitcode - - future.set_exception(result) + if not isinstance(result, CancelledError): + future.set_exception(result) else: future.set_result(result) @@ -121,9 +133,12 @@ """Runs the actual function in separate process and returns its result.""" signal.signal(signal.SIGINT, signal.SIG_IGN) + reader, writer = pipe + reader.close() + result = process_execute(function, *args, **kwargs) - send_result(pipe, result) + send_result(writer, result) def _get_result(future, pipe, timeout): @@ -159,14 +174,15 @@ ################################################################################ # Spawn process start method handling logic ################################################################################ + _registered_functions = {} def _register_function(function): - global _registered_functions - _registered_functions[_qualname(function)] = function + return function + def _trampoline(name, module, *args, **kwargs): """Trampoline function for decorators. @@ -190,9 +206,12 @@ except KeyError: # force function registering __import__(module) mod = sys.modules[module] - getattr(mod, name) + function = getattr(mod, name) - return _registered_functions[name] + try: + return _registered_functions[name] + except KeyError: # decorator without @pie syntax + return _register_function(function) def _qualname(function): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pebble-4.6.0/pebble/concurrent/thread.py new/Pebble-4.6.3/pebble/concurrent/thread.py --- old/Pebble-4.6.0/pebble/concurrent/thread.py 2020-12-27 11:44:21.000000000 +0100 +++ new/Pebble-4.6.3/pebble/concurrent/thread.py 2021-03-06 12:19:25.000000000 +0100 @@ -28,19 +28,27 @@ Decorated functions will return a concurrent.futures.Future object once called. - The name parameter will set the process name. + The name parameter will set the thread name. + + The daemon parameter controls the underlying thread daemon flag. + Default is True. + """ name = kwargs.get('name') daemon = kwargs.get('daemon', True) # decorator without parameters - if len(args) == 1 and not kwargs and callable(args[0]): + if not kwargs and len(args) == 1 and callable(args[0]): return _thread_wrapper(args[0], name, daemon) # decorator with parameters _validate_parameters(name, daemon) - # decorator with parameters + # without @pie syntax + if len(args) == 1 and callable(args[0]): + return _thread_wrapper(args[0], name, daemon) + + # with @pie syntax def decorating_function(function): return _thread_wrapper(function, name, daemon) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pebble-4.6.0/pebble/pool/channel.py new/Pebble-4.6.3/pebble/pool/channel.py --- old/Pebble-4.6.0/pebble/pool/channel.py 2020-12-27 11:44:21.000000000 +0100 +++ new/Pebble-4.6.3/pebble/pool/channel.py 2021-08-24 22:29:05.000000000 +0200 @@ -30,7 +30,8 @@ read0, write0 = mp_context.Pipe(duplex=False) read1, write1 = mp_context.Pipe(duplex=False) - return Channel(read1, write0), WorkerChannel(read0, write1, mp_context) + return (Channel(read1, write0), + WorkerChannel(read0, write1, (read1, write0), mp_context)) class Channel(object): @@ -41,8 +42,18 @@ def _make_poll_method(self): def unix_poll(timeout=None): + readonly_mask = (select.POLLIN | + select.POLLPRI | + select.POLLHUP | + select.POLLERR) + poll = select.poll() - poll.register(self.reader) + poll.register(self.reader, readonly_mask) + + # Convert from Seconds to Milliseconds + if timeout is not None: + timeout *= MILLISECONDS + try: return bool(poll.poll(timeout)) except OSError: @@ -70,17 +81,18 @@ class WorkerChannel(Channel): - def __init__(self, reader, writer, mp_context): + def __init__(self, reader, writer, unused, mp_context): super(WorkerChannel, self).__init__(reader, writer) self.mutex = ChannelMutex(mp_context) self.recv = self._make_recv_method() self.send = self._make_send_method() + self.unused = unused def __getstate__(self): - return self.reader, self.writer, self.mutex + return self.reader, self.writer, self.mutex, self.unused def __setstate__(self, state): - self.reader, self.writer, self.mutex = state + self.reader, self.writer, self.mutex, self.unused = state self.poll = self._make_poll_method() self.recv = self._make_recv_method() @@ -109,6 +121,11 @@ with self.mutex: yield self + def initialize(self): + """Close unused connections.""" + for connection in self.unused: + connection.close() + class ChannelMutex: def __init__(self, mp_context): @@ -177,4 +194,5 @@ raise ChannelError("Channel mutex time out") +MILLISECONDS = 1000 LOCK_TIMEOUT = 60 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pebble-4.6.0/pebble/pool/process.py new/Pebble-4.6.3/pebble/pool/process.py --- old/Pebble-4.6.0/pebble/pool/process.py 2020-12-27 11:44:21.000000000 +0100 +++ new/Pebble-4.6.3/pebble/pool/process.py 2021-02-27 12:13:59.000000000 +0100 @@ -16,6 +16,7 @@ import os import time +import atexit import pickle import multiprocessing @@ -77,10 +78,13 @@ self._context.state = RUNNING def _stop_pool(self): - self._pool_manager_loop.join() + if self._pool_manager_loop is not None: + self._pool_manager_loop.join() self._pool_manager.close() - self._task_scheduler_loop.join() - self._message_manager_loop.join() + if self._task_scheduler_loop is not None: + self._task_scheduler_loop.join() + if self._message_manager_loop is not None: + self._message_manager_loop.join() self._pool_manager.stop() def schedule(self, function, args=(), kwargs={}, timeout=None): @@ -152,7 +156,7 @@ task_queue = context.task_queue try: - while context.alive: + while context.alive and not global_shutdown: task = task_queue.get() if task is not None: @@ -171,7 +175,7 @@ context = pool_manager.context try: - while context.alive: + while context.alive and not global_shutdown: pool_manager.update_status() time.sleep(SLEEP_UNIT) except BrokenProcessPool: @@ -182,7 +186,7 @@ context = pool_manager.context try: - while context.alive: + while context.alive and not global_shutdown: pool_manager.process_next_message(SLEEP_UNIT) except BrokenProcessPool: context.state = ERROR @@ -354,6 +358,8 @@ return NoMessage() except (OSError, EnvironmentError, TypeError) as error: raise BrokenProcessPool(error) + except EOFError: # Pool shutdown + return NoMessage() def inspect_workers(self): """Updates the workers status. @@ -384,7 +390,7 @@ def new_worker(self): try: worker = launch_process( - None, worker_process, True, self.mp_context, + WORKERS_NAME, worker_process, False, self.mp_context, self.worker_parameters, self.workers_channel) self.workers[worker.pid] = worker except (OSError, EnvironmentError) as error: @@ -407,6 +413,8 @@ """The worker process routines.""" signal(SIGINT, SIG_IGN) + channel.initialize() + if params.initializer is not None: if not run_initializer(params.initializer, params.initargs): os._exit(1) @@ -418,8 +426,9 @@ payload.function, *payload.args, **payload.kwargs) send_result(channel, Result(task.id, result)) except (EnvironmentError, OSError, RuntimeError) as error: - os._exit(error.errno if error.errno else 1) - except EOFError: + errno = getattr(error, 'errno', 1) + os._exit(errno if isinstance(errno, int) else 1) + except EOFError as error: os._exit(0) @@ -471,6 +480,22 @@ return [process_execute(function, *args) for args in chunk] +def interpreter_shutdown(): + global global_shutdown + global_shutdown = True + + workers = [p for p in multiprocessing.active_children() + if p.name == WORKERS_NAME] + + for worker in workers: + stop_process(worker) + + +atexit.register(interpreter_shutdown) + + +global_shutdown = False +WORKERS_NAME = 'pebble_pool_worker' NoMessage = namedtuple('NoMessage', ()) Result = namedtuple('Result', ('task', 'result')) Problem = namedtuple('Problem', ('task', 'error')) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pebble-4.6.0/pebble/pool/thread.py new/Pebble-4.6.3/pebble/pool/thread.py --- old/Pebble-4.6.0/pebble/pool/thread.py 2020-12-27 11:44:21.000000000 +0100 +++ new/Pebble-4.6.3/pebble/pool/thread.py 2021-02-22 19:53:19.000000000 +0100 @@ -56,7 +56,8 @@ self._context.state = RUNNING def _stop_pool(self): - self._pool_manager_loop.join() + if self._pool_manager_loop is not None: + self._pool_manager_loop.join() self._pool_manager.stop() def schedule(self, function, args=(), kwargs={}): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pebble-4.6.0/test/test_concurrent_process_fork.py new/Pebble-4.6.3/test/test_concurrent_process_fork.py --- old/Pebble-4.6.0/test/test_concurrent_process_fork.py 2020-12-27 11:44:20.000000000 +0100 +++ new/Pebble-4.6.3/test/test_concurrent_process_fork.py 2021-03-04 22:33:53.000000000 +0100 @@ -30,6 +30,10 @@ supported = True +def not_decorated(argument, keyword_argument=0): + return argument + keyword_argument + + @concurrent.process(context=mp_context) def decorated(argument, keyword_argument=0): """A docstring.""" @@ -198,6 +202,12 @@ future = self.concurrentobj2.stcmethod() self.assertEqual(future.result(), 4) + def test_not_decorated_results(self): + """Process Fork results are produced.""" + non_decorated = concurrent.process(not_decorated, context=mp_context) + future = non_decorated(1, 1) + self.assertEqual(future.result(), 2) + def test_decorated_results(self): """Process Fork results are produced.""" future = decorated(1, 1) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pebble-4.6.0/test/test_concurrent_process_forkserver.py new/Pebble-4.6.3/test/test_concurrent_process_forkserver.py --- old/Pebble-4.6.0/test/test_concurrent_process_forkserver.py 2020-12-27 11:44:20.000000000 +0100 +++ new/Pebble-4.6.3/test/test_concurrent_process_forkserver.py 2021-03-04 22:37:02.000000000 +0100 @@ -28,6 +28,10 @@ pass +def not_decorated(argument, keyword_argument=0): + return argument + keyword_argument + + @concurrent.process(context=mp_context) def decorated(argument, keyword_argument=0): """A docstring.""" @@ -157,6 +161,12 @@ future = self.concurrentobj2.instmethod() self.assertEqual(future.result(), 3) + def test_not_decorated_results(self): + """Process Forkserver results are produced.""" + non_decorated = concurrent.process(not_decorated, context=mp_context) + future = non_decorated(1, 1) + self.assertEqual(future.result(), 2) + def test_decorated_results(self): """Process Forkserver results are produced.""" future = decorated(1, 1) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pebble-4.6.0/test/test_concurrent_process_spawn.py new/Pebble-4.6.3/test/test_concurrent_process_spawn.py --- old/Pebble-4.6.0/test/test_concurrent_process_spawn.py 2020-12-27 11:44:20.000000000 +0100 +++ new/Pebble-4.6.3/test/test_concurrent_process_spawn.py 2021-03-04 22:37:16.000000000 +0100 @@ -28,6 +28,10 @@ pass +def not_decorated(argument, keyword_argument=0): + return argument + keyword_argument + + @concurrent.process(context=mp_context) def decorated(argument, keyword_argument=0): """A docstring.""" @@ -157,6 +161,12 @@ future = self.concurrentobj2.instmethod() self.assertEqual(future.result(), 3) + def test_not_decorated_results(self): + """Process Spawn results are produced.""" + non_decorated = concurrent.process(not_decorated, context=mp_context) + future = non_decorated(1, 1) + self.assertEqual(future.result(), 2) + def test_decorated_results(self): """Process Spawn results are produced.""" future = decorated(1, 1) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pebble-4.6.0/test/test_concurrent_thread.py new/Pebble-4.6.3/test/test_concurrent_thread.py --- old/Pebble-4.6.0/test/test_concurrent_thread.py 2020-12-27 11:44:20.000000000 +0100 +++ new/Pebble-4.6.3/test/test_concurrent_thread.py 2021-03-04 22:33:26.000000000 +0100 @@ -4,6 +4,10 @@ from pebble import concurrent +def not_decorated(argument, keyword_argument=0): + return argument + keyword_argument + + @concurrent.thread def decorated(argument, keyword_argument=0): """A docstring.""" @@ -91,6 +95,12 @@ future = self.concurrentobj.stcmethod() self.assertEqual(future.result(), 2) + def test_not_decorated_results(self): + """Process Fork results are produced.""" + non_decorated = concurrent.thread(not_decorated) + future = non_decorated(1, 1) + self.assertEqual(future.result(), 2) + def test_decorated_results(self): """Thread results are produced.""" future = decorated(1, 1) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pebble-4.6.0/test/test_process_pool_fork.py new/Pebble-4.6.3/test/test_process_pool_fork.py --- old/Pebble-4.6.0/test/test_process_pool_fork.py 2020-12-27 11:44:20.000000000 +0100 +++ new/Pebble-4.6.3/test/test_process_pool_fork.py 2021-02-27 16:24:53.000000000 +0100 @@ -85,6 +85,30 @@ os._exit(1) +def process_function(): + p = multiprocessing.Process(target=function, args=[1]) + p.start() + p.join() + + return 1 + + +def pool_function(): + pool = multiprocessing.Pool(1) + result = pool.apply(function, args=[1]) + pool.close() + pool.join() + + return result + + +def pebble_function(): + with ProcessPool(max_workers=1) as pool: + f = pool.schedule(function, args=[1]) + + return f.result() + + @unittest.skipIf(not supported, "Start method is not supported") class TestProcessPool(unittest.TestCase): def setUp(self): @@ -113,7 +137,7 @@ def test_process_pool_multiple_futures(self): """Process Pool Fork multiple futures.""" futures = [] - with ProcessPool(max_workers=1, context=mp_context) as pool: + with ProcessPool(max_workers=2, context=mp_context) as pool: for _ in range(5): futures.append(pool.schedule(function, args=[1])) self.assertEqual(sum([f.result() for f in futures]), 5) @@ -187,6 +211,7 @@ self.event.wait() self.assertTrue(isinstance(self.exception, CancelledError)) + @unittest.skipIf(sys.platform == 'darwin', "Not supported on MAC OS") def test_process_pool_different_process(self): """Process Pool Fork multiple futures are handled by different processes.""" futures = [] @@ -450,12 +475,12 @@ def test_process_pool_map_timeout_chunks(self): """Process Pool Fork map timeout is assigned per chunk.""" - elements = [0.1]*10 + elements = [0.2]*10 with ProcessPool(max_workers=1, context=mp_context) as pool: - # it takes 0.5s to process a chunk + # it takes 1s to process a chunk future = pool.map( - long_function, elements, chunksize=5, timeout=0.8) + long_function, elements, chunksize=5, timeout=1.6) generator = future.result() self.assertEqual(list(generator), elements) @@ -510,6 +535,24 @@ except StopIteration: break + def test_process_pool_child_process(self): + """Process Pool Fork worker starts process.""" + with ProcessPool(max_workers=1, context=mp_context) as pool: + future = pool.schedule(process_function) + self.assertEqual(future.result(), 1) + + def test_process_pool_child_pool(self): + """Process Pool Fork worker starts multiprocessing.Pool.""" + with ProcessPool(max_workers=1, context=mp_context) as pool: + future = pool.schedule(pool_function) + self.assertEqual(future.result(), 1) + + def test_process_pool_child_pebble(self): + """Process Pool Fork worker starts pebble.ProcessPool.""" + with ProcessPool(max_workers=1, context=mp_context) as pool: + future = pool.schedule(pebble_function) + self.assertEqual(future.result(), 1) + # DEADLOCK TESTS diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pebble-4.6.0/test/test_process_pool_forkserver.py new/Pebble-4.6.3/test/test_process_pool_forkserver.py --- old/Pebble-4.6.0/test/test_process_pool_forkserver.py 2020-12-27 11:44:20.000000000 +0100 +++ new/Pebble-4.6.3/test/test_process_pool_forkserver.py 2021-02-27 16:21:24.000000000 +0100 @@ -85,6 +85,30 @@ os._exit(1) +def process_function(): + p = multiprocessing.Process(target=function, args=[1]) + p.start() + p.join() + + return 1 + + +def pool_function(): + pool = multiprocessing.Pool(1) + result = pool.apply(function, args=[1]) + pool.close() + pool.join() + + return result + + +def pebble_function(): + with ProcessPool(max_workers=1) as pool: + f = pool.schedule(function, args=[1]) + + return f.result() + + @unittest.skipIf(not supported, "Start method is not supported") class TestProcessPool(unittest.TestCase): def setUp(self): @@ -187,6 +211,7 @@ self.event.wait() self.assertTrue(isinstance(self.exception, CancelledError)) + @unittest.skipIf(sys.platform == 'darwin', "Not supported on MAC OS") def test_process_pool_different_process(self): """Process Pool Forkserver multiple futures are handled by different processes.""" futures = [] @@ -492,7 +517,7 @@ next(generator) def test_process_pool_map_broken_pool(self): - """Process Pool Fork Broken Pool.""" + """Process Pool Forkserver Broken Pool.""" elements = [1, 2, 3] with ProcessPool(max_workers=1, context=mp_context) as pool: @@ -508,3 +533,21 @@ break except StopIteration: break + + def test_process_pool_child_process(self): + """Process Pool Forkserver worker starts process.""" + with ProcessPool(max_workers=1, context=mp_context) as pool: + future = pool.schedule(process_function) + self.assertEqual(future.result(), 1) + + def test_process_pool_child_pool(self): + """Process Pool Forkserver worker starts multiprocessing.Pool.""" + with ProcessPool(max_workers=1, context=mp_context) as pool: + future = pool.schedule(pool_function) + self.assertEqual(future.result(), 1) + + def test_process_pool_child_pebble(self): + """Process Pool Forkserver worker starts pebble.ProcessPool.""" + with ProcessPool(max_workers=1, context=mp_context) as pool: + future = pool.schedule(pebble_function) + self.assertEqual(future.result(), 1) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pebble-4.6.0/test/test_process_pool_spawn.py new/Pebble-4.6.3/test/test_process_pool_spawn.py --- old/Pebble-4.6.0/test/test_process_pool_spawn.py 2020-12-27 11:44:20.000000000 +0100 +++ new/Pebble-4.6.3/test/test_process_pool_spawn.py 2021-02-27 16:21:04.000000000 +0100 @@ -83,6 +83,30 @@ os._exit(1) +def process_function(): + p = multiprocessing.Process(target=function, args=[1]) + p.start() + p.join() + + return 1 + + +def pool_function(): + pool = multiprocessing.Pool(1) + result = pool.apply(function, args=[1]) + pool.close() + pool.join() + + return result + + +def pebble_function(): + with ProcessPool(max_workers=1) as pool: + f = pool.schedule(function, args=[1]) + + return f.result() + + @unittest.skipIf(not supported, "Start method is not supported") class TestProcessPool(unittest.TestCase): def setUp(self): @@ -185,6 +209,7 @@ self.event.wait() self.assertTrue(isinstance(self.exception, CancelledError)) + @unittest.skipIf(sys.platform == 'darwin', "Not supported on MAC OS") def test_process_pool_different_process(self): """Process Pool Spawn futures are handled by different processes.""" futures = [] @@ -490,7 +515,7 @@ next(generator) def test_process_pool_map_broken_pool(self): - """Process Pool Fork Broken Pool.""" + """Process Pool Spawn Broken Pool.""" elements = [1, 2, 3] with ProcessPool(max_workers=1, context=mp_context) as pool: @@ -506,3 +531,21 @@ break except StopIteration: break + + def test_process_pool_child_process(self): + """Process Pool Spawn worker starts process.""" + with ProcessPool(max_workers=1, context=mp_context) as pool: + future = pool.schedule(process_function) + self.assertEqual(future.result(), 1) + + def test_process_pool_child_pool(self): + """Process Pool Spawn worker starts multiprocessing.Pool.""" + with ProcessPool(max_workers=1, context=mp_context) as pool: + future = pool.schedule(pool_function) + self.assertEqual(future.result(), 1) + + def test_process_pool_child_pebble(self): + """Process Pool Spawn worker starts pebble.ProcessPool.""" + with ProcessPool(max_workers=1, context=mp_context) as pool: + future = pool.schedule(pebble_function) + self.assertEqual(future.result(), 1)