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 2024-04-02 16:41:05
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-Pebble (Old)
 and      /work/SRC/openSUSE:Factory/.python-Pebble.new.1905 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-Pebble"

Tue Apr  2 16:41:05 2024 rev:16 rq:1163617 version:5.0.7

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-Pebble/python-Pebble.changes      
2023-12-28 23:03:41.071313043 +0100
+++ /work/SRC/openSUSE:Factory/.python-Pebble.new.1905/python-Pebble.changes    
2024-04-02 16:42:36.793584257 +0200
@@ -1,0 +2,10 @@
+Fri Mar 22 21:01:33 UTC 2024 - Dirk Müller <dmuel...@suse.com>
+
+- update to 5.0.7:
+  * issue #96: handle race condition under different interpreters
+  * issue #125: handle frozen classes as exceptions
+  * issue #127: handle unexpected errors when reading from pipe in
+                process decorators
+  * issue #128: allow different context from `multiprocessing` ones
+
+-------------------------------------------------------------------

Old:
----
  Pebble-5.0.6.tar.gz

New:
----
  Pebble-5.0.7.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-Pebble.spec ++++++
--- /var/tmp/diff_new_pack.FDGHc1/_old  2024-04-02 16:42:38.313638516 +0200
+++ /var/tmp/diff_new_pack.FDGHc1/_new  2024-04-02 16:42:38.317638658 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-Pebble
 #
-# Copyright (c) 2023 SUSE LLC
+# Copyright (c) 2024 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -17,7 +17,7 @@
 
 
 Name:           python-Pebble
-Version:        5.0.6
+Version:        5.0.7
 Release:        0
 Summary:        Threading and multiprocessing eye-candy for Python
 License:        LGPL-3.0-only

++++++ Pebble-5.0.6.tar.gz -> Pebble-5.0.7.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Pebble-5.0.6/PKG-INFO new/Pebble-5.0.7/PKG-INFO
--- old/Pebble-5.0.6/PKG-INFO   2023-12-25 17:22:05.110159200 +0100
+++ new/Pebble-5.0.7/PKG-INFO   2024-03-21 23:33:58.758192300 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: Pebble
-Version: 5.0.6
+Version: 5.0.7
 Summary: Threading and multiprocessing eye-candy.
 Home-page: https://github.com/noxdafox/pebble
 Author: Matteo Cafasso
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Pebble-5.0.6/Pebble.egg-info/PKG-INFO 
new/Pebble-5.0.7/Pebble.egg-info/PKG-INFO
--- old/Pebble-5.0.6/Pebble.egg-info/PKG-INFO   2023-12-25 17:22:05.000000000 
+0100
+++ new/Pebble-5.0.7/Pebble.egg-info/PKG-INFO   2024-03-21 23:33:58.000000000 
+0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: Pebble
-Version: 5.0.6
+Version: 5.0.7
 Summary: Threading and multiprocessing eye-candy.
 Home-page: https://github.com/noxdafox/pebble
 Author: Matteo Cafasso
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Pebble-5.0.6/pebble/__init__.py 
new/Pebble-5.0.7/pebble/__init__.py
--- old/Pebble-5.0.6/pebble/__init__.py 2023-12-25 17:18:15.000000000 +0100
+++ new/Pebble-5.0.7/pebble/__init__.py 2024-03-21 23:20:27.000000000 +0100
@@ -1,5 +1,5 @@
 __author__ = 'Matteo Cafasso'
-__version__ = '5.0.6'
+__version__ = '5.0.7'
 __license__ = 'LGPL'
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Pebble-5.0.6/pebble/asynchronous/process.py 
new/Pebble-5.0.7/pebble/asynchronous/process.py
--- old/Pebble-5.0.6/pebble/asynchronous/process.py     2023-12-06 
17:32:40.000000000 +0100
+++ new/Pebble-5.0.7/pebble/asynchronous/process.py     2024-03-11 
22:23:47.000000000 +0100
@@ -1,5 +1,5 @@
 # This file is part of Pebble.
-# Copyright (c) 2013-2023, Matteo Cafasso
+# Copyright (c) 2013-2024, Matteo Cafasso
 
 # Pebble is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Lesser General Public License
@@ -62,7 +62,7 @@
         return _process_wrapper(args[0], timeout, name, daemon, 
multiprocessing)
 
     # decorator with parameters
-    _validate_parameters(timeout, name, daemon, mp_context)
+    _validate_parameters(timeout, name, daemon)
     mp_context = mp_context if mp_context is not None else multiprocessing
 
     # without @pie syntax
@@ -163,7 +163,7 @@
     except (EOFError, OSError):
         return Result(ERROR, ProcessExpired('Abnormal termination'))
     except Exception as error:
-        return error
+        return Result(ERROR, error)
 
 
 def _function_handler(
@@ -183,21 +183,13 @@
     send_result(writer, result)
 
 
-def _validate_parameters(
-        timeout: float,
-        name: str,
-        daemon: bool,
-        mp_context: multiprocessing.context.BaseContext
-):
+def _validate_parameters(timeout: float, name: str, daemon: bool):
     if timeout is not None and not isinstance(timeout, (int, float)):
         raise TypeError('Timeout expected to be None or integer or float')
     if name is not None and not isinstance(name, str):
         raise TypeError('Name expected to be None or string')
     if daemon is not None and not isinstance(daemon, bool):
         raise TypeError('Daemon expected to be None or bool')
-    if mp_context is not None and not isinstance(
-            mp_context, multiprocessing.context.BaseContext):
-        raise TypeError('Context expected to be None or 
multiprocessing.context')
 
 
 def _get_asyncio_loop() -> asyncio.BaseEventLoop:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Pebble-5.0.6/pebble/asynchronous/thread.py 
new/Pebble-5.0.7/pebble/asynchronous/thread.py
--- old/Pebble-5.0.6/pebble/asynchronous/thread.py      2023-12-06 
17:33:03.000000000 +0100
+++ new/Pebble-5.0.7/pebble/asynchronous/thread.py      2024-03-20 
22:35:22.000000000 +0100
@@ -1,5 +1,5 @@
 # This file is part of Pebble.
-# Copyright (c) 2013-2023, Matteo Cafasso
+# Copyright (c) 2013-2024, Matteo Cafasso
 
 # Pebble is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Lesser General Public License
@@ -20,7 +20,7 @@
 from functools import wraps
 from traceback import format_exc
 
-from pebble.common import launch_thread
+from pebble.common import execute, launch_thread, SUCCESS
 
 
 def thread(*args, **kwargs) -> Callable:
@@ -79,13 +79,12 @@
     """Runs the actual function in separate thread and returns its result."""
     loop = future.get_loop()
 
-    try:
-        result = function(*args, **kwargs)
-    except BaseException as error:
-        error.traceback = format_exc()
-        loop.call_soon_threadsafe(future.set_exception, error)
+    result = execute(function, *args, **kwargs)
+
+    if result.status == SUCCESS:
+        loop.call_soon_threadsafe(future.set_result, result.value)
     else:
-        loop.call_soon_threadsafe(future.set_result, result)
+        loop.call_soon_threadsafe(future.set_exception, result.value)
 
 
 def _validate_parameters(name: str, daemon: bool):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Pebble-5.0.6/pebble/common.py 
new/Pebble-5.0.7/pebble/common.py
--- old/Pebble-5.0.6/pebble/common.py   2023-12-25 11:45:33.000000000 +0100
+++ new/Pebble-5.0.7/pebble/common.py   2024-03-21 23:14:01.000000000 +0100
@@ -1,5 +1,5 @@
 # This file is part of Pebble.
-# Copyright (c) 2013-2023, Matteo Cafasso
+# Copyright (c) 2013-2024, Matteo Cafasso
 
 # Pebble is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Lesser General Public License
@@ -122,7 +122,11 @@
 
 
 def rebuild_exception(exception, traceback):
-    exception.__cause__ = RemoteTraceback(traceback)
+    try:
+        exception.traceback = traceback
+        exception.__cause__ = RemoteTraceback(traceback)
+    except AttributeError:  # Frozen exception
+        pass
 
     return exception
 
@@ -165,7 +169,11 @@
     try:
         return Result(SUCCESS, function(*args, **kwargs))
     except BaseException as error:
-        error.traceback = format_exc()
+        try:
+            error.traceback = format_exc()
+        except AttributeError:  # Frozen exception
+            pass
+
         return Result(FAILURE, error)
 
 
@@ -174,8 +182,7 @@
     try:
         return Result(SUCCESS, function(*args, **kwargs))
     except BaseException as error:
-        error.traceback = format_exc()
-        return Result(FAILURE, RemoteException(error, error.traceback))
+        return Result(FAILURE, RemoteException(error, format_exc()))
 
 
 def send_result(pipe, data):
@@ -183,8 +190,7 @@
     try:
         pipe.send(data)
     except (pickle.PicklingError, TypeError) as error:
-        error.traceback = format_exc()
-        pipe.send(Result(ERROR, RemoteException(error, error.traceback)))
+        pipe.send(Result(ERROR, RemoteException(error, format_exc())))
 
 
 Result = namedtuple('Result', ('status', 'value'))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Pebble-5.0.6/pebble/concurrent/process.py 
new/Pebble-5.0.7/pebble/concurrent/process.py
--- old/Pebble-5.0.6/pebble/concurrent/process.py       2023-12-06 
17:40:14.000000000 +0100
+++ new/Pebble-5.0.7/pebble/concurrent/process.py       2024-03-11 
22:23:38.000000000 +0100
@@ -1,5 +1,5 @@
 # This file is part of Pebble.
-# Copyright (c) 2013-2023, Matteo Cafasso
+# Copyright (c) 2013-2024, Matteo Cafasso
 
 # Pebble is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Lesser General Public License
@@ -62,7 +62,7 @@
         return _process_wrapper(args[0], timeout, name, daemon, 
multiprocessing)
 
     # decorator with parameters
-    _validate_parameters(timeout, name, daemon, mp_context)
+    _validate_parameters(timeout, name, daemon)
     mp_context = mp_context if mp_context is not None else multiprocessing
 
     # without @pie syntax
@@ -179,24 +179,16 @@
     except (EOFError, OSError):
         return Result(ERROR, ProcessExpired('Abnormal termination'))
     except Exception as error:
-        return error
+        return Result(ERROR, error)
 
 
-def _validate_parameters(
-        timeout: float,
-        name: str,
-        daemon: bool,
-        mp_context: multiprocessing.context.BaseContext
-):
+def _validate_parameters(timeout: float, name: str, daemon: bool):
     if timeout is not None and not isinstance(timeout, (int, float)):
         raise TypeError('Timeout expected to be None or integer or float')
     if name is not None and not isinstance(name, str):
         raise TypeError('Name expected to be None or string')
     if daemon is not None and not isinstance(daemon, bool):
         raise TypeError('Daemon expected to be None or bool')
-    if mp_context is not None and not isinstance(
-            mp_context, multiprocessing.context.BaseContext):
-        raise TypeError('Context expected to be None or 
multiprocessing.context')
 
 
 
################################################################################
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Pebble-5.0.6/pebble/concurrent/thread.py 
new/Pebble-5.0.7/pebble/concurrent/thread.py
--- old/Pebble-5.0.6/pebble/concurrent/thread.py        2023-12-06 
17:32:06.000000000 +0100
+++ new/Pebble-5.0.7/pebble/concurrent/thread.py        2024-03-20 
22:19:09.000000000 +0100
@@ -1,5 +1,5 @@
 # This file is part of Pebble.
-# Copyright (c) 2013-2023, Matteo Cafasso
+# Copyright (c) 2013-2024, Matteo Cafasso
 
 # Pebble is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Lesser General Public License
@@ -19,7 +19,7 @@
 from traceback import format_exc
 from concurrent.futures import Future
 
-from pebble.common import launch_thread, SUCCESS
+from pebble.common import execute, launch_thread, SUCCESS
 
 
 def thread(*args, **kwargs) -> Callable:
@@ -77,13 +77,12 @@
     """Runs the actual function in separate thread and returns its result."""
     future.set_running_or_notify_cancel()
 
-    try:
-        result = function(*args, **kwargs)
-    except BaseException as error:
-        error.traceback = format_exc()
-        future.set_exception(error)
+    result = execute(function, *args, **kwargs)
+
+    if result.status == SUCCESS:
+        future.set_result(result.value)
     else:
-        future.set_result(result)
+        future.set_exception(result.value)
 
 
 def _validate_parameters(name: str, daemon: bool):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Pebble-5.0.6/pebble/decorators.py 
new/Pebble-5.0.7/pebble/decorators.py
--- old/Pebble-5.0.6/pebble/decorators.py       2023-11-21 17:34:59.000000000 
+0100
+++ new/Pebble-5.0.7/pebble/decorators.py       2024-02-28 22:12:32.000000000 
+0100
@@ -1,5 +1,5 @@
 # This file is part of Pebble.
-# Copyright (c) 2013-2023, Matteo Cafasso
+# Copyright (c) 2013-2024, Matteo Cafasso
 
 # Pebble is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Lesser General Public License
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Pebble-5.0.6/pebble/functions.py 
new/Pebble-5.0.7/pebble/functions.py
--- old/Pebble-5.0.6/pebble/functions.py        2023-11-21 17:34:59.000000000 
+0100
+++ new/Pebble-5.0.7/pebble/functions.py        2024-02-28 22:12:32.000000000 
+0100
@@ -1,5 +1,5 @@
 # This file is part of Pebble.
-# Copyright (c) 2013-2023, Matteo Cafasso
+# Copyright (c) 2013-2024, Matteo Cafasso
 
 # Pebble is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Lesser General Public License
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Pebble-5.0.6/pebble/pool/base_pool.py 
new/Pebble-5.0.7/pebble/pool/base_pool.py
--- old/Pebble-5.0.6/pebble/pool/base_pool.py   2023-12-25 11:57:19.000000000 
+0100
+++ new/Pebble-5.0.7/pebble/pool/base_pool.py   2024-02-28 22:12:32.000000000 
+0100
@@ -1,5 +1,5 @@
 # This file is part of Pebble.
-# Copyright (c) 2013-2023, Matteo Cafasso
+# Copyright (c) 2013-2024, Matteo Cafasso
 
 # Pebble is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Lesser General Public License
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Pebble-5.0.6/pebble/pool/channel.py 
new/Pebble-5.0.7/pebble/pool/channel.py
--- old/Pebble-5.0.6/pebble/pool/channel.py     2023-11-21 17:34:59.000000000 
+0100
+++ new/Pebble-5.0.7/pebble/pool/channel.py     2024-02-28 22:12:32.000000000 
+0100
@@ -1,5 +1,5 @@
 # This file is part of Pebble.
-# Copyright (c) 2013-2023, Matteo Cafasso
+# Copyright (c) 2013-2024, Matteo Cafasso
 
 # Pebble is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Lesser General Public License
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Pebble-5.0.6/pebble/pool/process.py 
new/Pebble-5.0.7/pebble/pool/process.py
--- old/Pebble-5.0.6/pebble/pool/process.py     2023-11-26 17:46:20.000000000 
+0100
+++ new/Pebble-5.0.7/pebble/pool/process.py     2024-02-28 22:12:32.000000000 
+0100
@@ -1,5 +1,5 @@
 # This file is part of Pebble.
-# Copyright (c) 2013-2023, Matteo Cafasso
+# Copyright (c) 2013-2024, Matteo Cafasso
 
 # Pebble is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Lesser General Public License
@@ -266,13 +266,12 @@
             self.task_manager.task_done(task.id, Result(TASK_ERROR, error))
 
     def find_expired_task(self, worker_id: int) -> Task:
-        tasks = tuple(self.task_manager.tasks.values())
+        tasks = dictionary_values(self.task_manager.tasks)
         running_tasks = tuple(t for t in tasks if t.worker_id != 0)
-
         if running_tasks:
             return task_worker_lookup(running_tasks, worker_id)
-        else:
-            raise BrokenProcessPool("All workers expired")
+
+        raise BrokenProcessPool("All workers expired")
 
 
 class TaskManager:
@@ -317,10 +316,11 @@
         self.task_done(task_id, Result(TASK_ERROR, error))
 
     def timeout_tasks(self) -> tuple:
-        return tuple(t for t in tuple(self.tasks.values()) if self.timeout(t))
+        return tuple(t for t in dictionary_values(self.tasks)
+                     if self.timeout(t))
 
     def cancelled_tasks(self) -> tuple:
-        return tuple(t for t in tuple(self.tasks.values())
+        return tuple(t for t in dictionary_values(self.tasks)
                      if t.timestamp != 0 and t.future.cancelled())
 
     @staticmethod
@@ -371,8 +371,8 @@
         Returns the workers which have unexpectedly ended.
 
         """
-        workers = tuple(self.workers.values())
-        expired = tuple(w for w in workers if not w.is_alive())
+        expired = tuple(w for w in dictionary_values(self.workers)
+                        if not w.is_alive())
 
         for worker in expired:
             self.workers.pop(worker.pid)
@@ -495,6 +495,15 @@
         stop_process(worker)
 
 
+def dictionary_values(dictionary: dict) -> tuple:
+    """Returns a snapshot of the dictionary values handling race conditions."""
+    while True:
+        try:
+            return tuple(dictionary.values())
+        except RuntimeError:  # race condition
+            pass
+
+
 atexit.register(interpreter_shutdown)
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Pebble-5.0.6/pebble/pool/thread.py 
new/Pebble-5.0.7/pebble/pool/thread.py
--- old/Pebble-5.0.6/pebble/pool/thread.py      2023-11-26 17:17:06.000000000 
+0100
+++ new/Pebble-5.0.7/pebble/pool/thread.py      2024-02-28 22:12:32.000000000 
+0100
@@ -1,5 +1,5 @@
 # This file is part of Pebble.
-# Copyright (c) 2013-2023, Matteo Cafasso
+# Copyright (c) 2013-2024, Matteo Cafasso
 
 # Pebble is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Lesser General Public License
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Pebble-5.0.6/test/test_asynchronous_process_fork.py 
new/Pebble-5.0.7/test/test_asynchronous_process_fork.py
--- old/Pebble-5.0.6/test/test_asynchronous_process_fork.py     2023-12-25 
12:20:13.000000000 +0100
+++ new/Pebble-5.0.7/test/test_asynchronous_process_fork.py     2024-03-20 
22:29:58.000000000 +0100
@@ -5,6 +5,7 @@
 import asyncio
 import unittest
 import threading
+import dataclasses
 import multiprocessing
 from concurrent.futures import CancelledError, TimeoutError
 
@@ -55,6 +56,16 @@
     return event
 
 
+@dataclasses.dataclass(frozen=True)
+class FrozenError(Exception):
+    pass
+
+
+@asynchronous.process(context=mp_context)
+def frozen_error_decorated():
+    raise FrozenError()
+
+
 @asynchronous.process(context=mp_context)
 def critical_decorated():
     os._exit(123)
@@ -303,6 +314,14 @@
         with self.assertRaises((pickle.PicklingError, TypeError)):
             asyncio.run(test())
 
+    def test_frozen_error_decorated(self):
+        """Process Fork frozen errors are raised by future.result."""
+        async def test():
+            return await frozen_error_decorated()
+
+        with self.assertRaises(FrozenError):
+            asyncio.run(test())
+
     def test_timeout_decorated(self):
         """Process Fork raises TimeoutError if so."""
         async def test():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/Pebble-5.0.6/test/test_asynchronous_process_forkserver.py 
new/Pebble-5.0.7/test/test_asynchronous_process_forkserver.py
--- old/Pebble-5.0.6/test/test_asynchronous_process_forkserver.py       
2023-11-26 16:14:24.000000000 +0100
+++ new/Pebble-5.0.7/test/test_asynchronous_process_forkserver.py       
2024-03-20 22:31:00.000000000 +0100
@@ -5,6 +5,7 @@
 import asyncio
 import unittest
 import threading
+import dataclasses
 import multiprocessing
 from concurrent.futures import CancelledError, TimeoutError
 
@@ -55,6 +56,16 @@
     return event
 
 
+@dataclasses.dataclass(frozen=True)
+class FrozenError(Exception):
+    pass
+
+
+@asynchronous.process(context=mp_context)
+def frozen_error_decorated():
+    raise FrozenError()
+
+
 @asynchronous.process(context=mp_context)
 def critical_decorated():
     os._exit(123)
@@ -286,6 +297,14 @@
         with self.assertRaises((pickle.PicklingError, TypeError)):
             asyncio.run(test())
 
+    def test_frozen_error_decorated(self):
+        """Process Fork frozen errors are raised by future.result."""
+        async def test():
+            return await frozen_error_decorated()
+
+        with self.assertRaises(FrozenError):
+            asyncio.run(test())
+
     def test_timeout_decorated(self):
         """Process Forkserver raises TimeoutError if so."""
         async def test():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Pebble-5.0.6/test/test_asynchronous_process_spawn.py 
new/Pebble-5.0.7/test/test_asynchronous_process_spawn.py
--- old/Pebble-5.0.6/test/test_asynchronous_process_spawn.py    2023-11-26 
16:13:50.000000000 +0100
+++ new/Pebble-5.0.7/test/test_asynchronous_process_spawn.py    2024-03-20 
22:39:09.000000000 +0100
@@ -5,6 +5,7 @@
 import asyncio
 import unittest
 import threading
+import dataclasses
 import multiprocessing
 from concurrent.futures import CancelledError, TimeoutError
 
@@ -55,6 +56,16 @@
     return event
 
 
+@dataclasses.dataclass(frozen=True)
+class FrozenError(Exception):
+    pass
+
+
+@asynchronous.process(context=mp_context)
+def frozen_error_decorated():
+    raise FrozenError()
+
+
 @asynchronous.process(context=mp_context)
 def critical_decorated():
     os._exit(123)
@@ -286,6 +297,14 @@
         with self.assertRaises((pickle.PicklingError, TypeError)):
             asyncio.run(test())
 
+    def test_frozen_error_decorated(self):
+        """Process Spawn frozen errors are raised by future.result."""
+        async def test():
+            return await frozen_error_decorated()
+
+        with self.assertRaises(FrozenError):
+            asyncio.run(test())
+
     def test_timeout_decorated(self):
         """Process Spawn raises TimeoutError if so."""
         async def test():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Pebble-5.0.6/test/test_asynchronous_thread.py 
new/Pebble-5.0.7/test/test_asynchronous_thread.py
--- old/Pebble-5.0.6/test/test_asynchronous_thread.py   2023-11-26 
16:14:05.000000000 +0100
+++ new/Pebble-5.0.7/test/test_asynchronous_thread.py   2024-03-20 
22:52:16.000000000 +0100
@@ -1,6 +1,7 @@
 import asyncio
 import unittest
 import threading
+import dataclasses
 
 from pebble import asynchronous
 
@@ -25,6 +26,16 @@
     return RuntimeError("BOOM!")
 
 
+@dataclasses.dataclass(frozen=True)
+class FrozenError(Exception):
+    pass
+
+
+@asynchronous.thread()
+def frozen_error_decorated():
+    raise FrozenError()
+
+
 @asynchronous.thread()
 def name_keyword_argument(name='function_kwarg'):
     return name
@@ -168,6 +179,14 @@
         self.assertTrue(isinstance(self.exception, RuntimeError),
                         msg=str(self.exception))
 
+    def test_frozen_error_decorated(self):
+        """Thread frozen errors are raised by future.result."""
+        async def test():
+            return await frozen_error_decorated()
+
+        with self.assertRaises(FrozenError):
+            asyncio.run(test())
+
     def test_name_keyword_argument(self):
         """name keyword can be passed to a decorated function process without 
name """
         async def test():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Pebble-5.0.6/test/test_concurrent_process_fork.py 
new/Pebble-5.0.7/test/test_concurrent_process_fork.py
--- old/Pebble-5.0.6/test/test_concurrent_process_fork.py       2023-11-26 
16:06:08.000000000 +0100
+++ new/Pebble-5.0.7/test/test_concurrent_process_fork.py       2024-03-20 
22:11:01.000000000 +0100
@@ -4,6 +4,7 @@
 import signal
 import unittest
 import threading
+import dataclasses
 import multiprocessing
 from concurrent.futures import CancelledError, TimeoutError
 
@@ -54,6 +55,16 @@
     return event
 
 
+@dataclasses.dataclass(frozen=True)
+class FrozenError(Exception):
+    pass
+
+
+@concurrent.process(context=mp_context)
+def frozen_error_decorated():
+    raise FrozenError()
+
+
 @concurrent.process(context=mp_context)
 def critical_decorated():
     os._exit(123)
@@ -253,6 +264,12 @@
         with self.assertRaises((pickle.PicklingError, TypeError)):
             future.result()
 
+    def test_frozen_error_decorated(self):
+        """Process Fork frozen errors are raised by future.result."""
+        future = frozen_error_decorated()
+        with self.assertRaises(FrozenError):
+            future.result()
+
     def test_timeout_decorated(self):
         """Process Fork raises TimeoutError if so."""
         future = long_decorated()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/Pebble-5.0.6/test/test_concurrent_process_forkserver.py 
new/Pebble-5.0.7/test/test_concurrent_process_forkserver.py
--- old/Pebble-5.0.6/test/test_concurrent_process_forkserver.py 2023-11-26 
16:10:09.000000000 +0100
+++ new/Pebble-5.0.7/test/test_concurrent_process_forkserver.py 2024-03-20 
22:27:50.000000000 +0100
@@ -4,6 +4,7 @@
 import signal
 import unittest
 import threading
+import dataclasses
 import multiprocessing
 from concurrent.futures import CancelledError, TimeoutError
 
@@ -54,6 +55,16 @@
     return event
 
 
+@dataclasses.dataclass(frozen=True)
+class FrozenError(Exception):
+    pass
+
+
+@concurrent.process(context=mp_context)
+def frozen_error_decorated():
+    raise FrozenError()
+
+
 @concurrent.process(context=mp_context)
 def critical_decorated():
     os._exit(123)
@@ -214,6 +225,12 @@
         with self.assertRaises((pickle.PicklingError, TypeError)):
             future.result()
 
+    def test_frozen_error_decorated(self):
+        """Process Fork frozen errors are raised by future.result."""
+        future = frozen_error_decorated()
+        with self.assertRaises(FrozenError):
+            future.result()
+
     def test_timeout_decorated(self):
         """Process Forkserver raises TimeoutError if so."""
         future = long_decorated()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Pebble-5.0.6/test/test_concurrent_process_spawn.py 
new/Pebble-5.0.7/test/test_concurrent_process_spawn.py
--- old/Pebble-5.0.6/test/test_concurrent_process_spawn.py      2023-11-26 
16:09:54.000000000 +0100
+++ new/Pebble-5.0.7/test/test_concurrent_process_spawn.py      2024-03-20 
22:28:32.000000000 +0100
@@ -4,6 +4,7 @@
 import signal
 import unittest
 import threading
+import dataclasses
 import multiprocessing
 from concurrent.futures import CancelledError, TimeoutError
 
@@ -54,6 +55,16 @@
     return event
 
 
+@dataclasses.dataclass(frozen=True)
+class FrozenError(Exception):
+    pass
+
+
+@concurrent.process(context=mp_context)
+def frozen_error_decorated():
+    raise FrozenError()
+
+
 @concurrent.process(context=mp_context)
 def critical_decorated():
     os._exit(123)
@@ -214,6 +225,12 @@
         with self.assertRaises((pickle.PicklingError, TypeError)):
             future.result()
 
+    def test_error_decorated(self):
+        """Process Fork errors are raised by future.result."""
+        future = error_decorated()
+        with self.assertRaises(RuntimeError):
+            future.result()
+
     def test_timeout_decorated(self):
         """Process Spawn raises TimeoutError if so."""
         future = long_decorated()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Pebble-5.0.6/test/test_process_pool_fork.py 
new/Pebble-5.0.7/test/test_process_pool_fork.py
--- old/Pebble-5.0.6/test/test_process_pool_fork.py     2023-12-25 
12:05:45.000000000 +0100
+++ new/Pebble-5.0.7/test/test_process_pool_fork.py     2024-03-20 
21:43:09.000000000 +0100
@@ -6,6 +6,7 @@
 import asyncio
 import unittest
 import threading
+import dataclasses
 import multiprocessing
 
 from concurrent.futures import CancelledError, TimeoutError
@@ -64,6 +65,15 @@
     return BaseException("BOOM!")
 
 
+@dataclasses.dataclass(frozen=True)
+class FrozenError(Exception):
+    pass
+
+
+def frozen_error_function():
+    raise FrozenError()
+
+
 def pickle_error_function():
     return threading.Lock()
 
@@ -187,6 +197,12 @@
             future = pool.schedule(pickle_error_function)
             self.assertRaises((pickle.PicklingError, TypeError), future.result)
 
+    def test_process_pool_frozen_error(self):
+        """Process Pool Fork frozen errors are raised by future get."""
+        with ProcessPool(max_workers=1, context=mp_context) as pool:
+            future = pool.schedule(frozen_error_function)
+        self.assertRaises(FrozenError, future.result)
+
     def test_process_pool_timeout(self):
         """Process Pool Fork future raises TimeoutError if so."""
         with ProcessPool(max_workers=1, context=mp_context) as pool:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Pebble-5.0.6/test/test_process_pool_forkserver.py 
new/Pebble-5.0.7/test/test_process_pool_forkserver.py
--- old/Pebble-5.0.6/test/test_process_pool_forkserver.py       2023-12-25 
12:37:54.000000000 +0100
+++ new/Pebble-5.0.7/test/test_process_pool_forkserver.py       2024-03-20 
22:45:06.000000000 +0100
@@ -6,6 +6,7 @@
 import asyncio
 import unittest
 import threading
+import dataclasses
 import multiprocessing
 
 from concurrent.futures import CancelledError, TimeoutError
@@ -70,6 +71,15 @@
     return threading.Lock()
 
 
+@dataclasses.dataclass(frozen=True)
+class FrozenError(Exception):
+    pass
+
+
+def frozen_error_function():
+    raise FrozenError()
+
+
 def long_function(value=1):
     time.sleep(value)
     return value
@@ -189,6 +199,12 @@
             future = pool.schedule(pickle_error_function)
             self.assertRaises((pickle.PicklingError, TypeError), future.result)
 
+    def test_process_pool_frozen_error(self):
+        """Process Pool Forkserver frozen errors are raised by future get."""
+        with ProcessPool(max_workers=1, context=mp_context) as pool:
+            future = pool.schedule(frozen_error_function)
+        self.assertRaises(FrozenError, future.result)
+
     def test_process_pool_timeout(self):
         """Process Pool Forkserver future raises TimeoutError if so."""
         with ProcessPool(max_workers=1, context=mp_context) as pool:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Pebble-5.0.6/test/test_process_pool_spawn.py 
new/Pebble-5.0.7/test/test_process_pool_spawn.py
--- old/Pebble-5.0.6/test/test_process_pool_spawn.py    2023-12-25 
12:39:14.000000000 +0100
+++ new/Pebble-5.0.7/test/test_process_pool_spawn.py    2024-03-20 
22:48:47.000000000 +0100
@@ -6,6 +6,7 @@
 import asyncio
 import unittest
 import threading
+import dataclasses
 import multiprocessing
 
 from concurrent.futures import CancelledError, TimeoutError
@@ -68,6 +69,15 @@
     return threading.Lock()
 
 
+@dataclasses.dataclass(frozen=True)
+class FrozenError(Exception):
+    pass
+
+
+def frozen_error_function():
+    raise FrozenError()
+
+
 def long_function(value=1):
     time.sleep(value)
     return value
@@ -187,6 +197,12 @@
             future = pool.schedule(pickle_error_function)
             self.assertRaises((pickle.PicklingError, TypeError), future.result)
 
+    def test_process_pool_frozen_error(self):
+        """Process Pool Spawn frozen errors are raised by future get."""
+        with ProcessPool(max_workers=1, context=mp_context) as pool:
+            future = pool.schedule(frozen_error_function)
+        self.assertRaises(FrozenError, future.result)
+
     def test_process_pool_timeout(self):
         """Process Pool Spawn future raises TimeoutError if so."""
         with ProcessPool(max_workers=1, context=mp_context) as pool:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Pebble-5.0.6/test/test_thread_pool.py 
new/Pebble-5.0.7/test/test_thread_pool.py
--- old/Pebble-5.0.6/test/test_thread_pool.py   2023-12-25 11:55:53.000000000 
+0100
+++ new/Pebble-5.0.7/test/test_thread_pool.py   2024-03-20 22:43:08.000000000 
+0100
@@ -2,6 +2,7 @@
 import asyncio
 import unittest
 import threading
+import dataclasses
 
 from pebble import ThreadPool
 
@@ -38,6 +39,15 @@
     raise BaseException("BOOM!")
 
 
+@dataclasses.dataclass(frozen=True)
+class FrozenError(Exception):
+    pass
+
+
+def frozen_error_function():
+    raise FrozenError()
+
+
 def long_function(value=0):
     time.sleep(1)
     return value
@@ -105,6 +115,12 @@
         self.event.wait()
         self.assertTrue(isinstance(self.exception, BaseException))
 
+    def test_process_pool_frozen_error(self):
+        """Thread Pool frozen errors are raised by future get."""
+        with ThreadPool(max_workers=1) as pool:
+            future = pool.schedule(frozen_error_function)
+        self.assertRaises(FrozenError, future.result)
+
     def test_thread_pool_cancel_callback(self):
         """Thread Pool FutureCancelled is forwarded to callback."""
         with ThreadPool(max_workers=1) as pool:

Reply via email to