https://github.com/python/cpython/commit/0f94b186a55a7a71eb202c42098262f6dfafd077
commit: 0f94b186a55a7a71eb202c42098262f6dfafd077
branch: 3.14
author: Miss Islington (bot) <[email protected]>
committer: hugovk <[email protected]>
date: 2025-09-08T18:37:39+03:00
summary:

[3.14] gh-138253: Fix compatibility of sub-interpreters queues with queue.Queue 
(GH-138256) (#138367)

Co-authored-by: Serhiy Storchaka <[email protected]>

files:
A Misc/NEWS.d/next/Library/2025-08-30-10-58-15.gh-issue-138253.9Ehj-N.rst
M Lib/concurrent/interpreters/_queues.py
M Lib/test/test_interpreters/test_queues.py

diff --git a/Lib/concurrent/interpreters/_queues.py 
b/Lib/concurrent/interpreters/_queues.py
index ee830973f2a36e..81ea1098d7f9f3 100644
--- a/Lib/concurrent/interpreters/_queues.py
+++ b/Lib/concurrent/interpreters/_queues.py
@@ -171,13 +171,13 @@ def full(self):
     def qsize(self):
         return _queues.get_count(self._id)
 
-    def put(self, obj, timeout=None, *,
+    def put(self, obj, block=True, timeout=None, *,
             unbounditems=None,
             _delay=10 / 1000,  # 10 milliseconds
             ):
         """Add the object to the queue.
 
-        This blocks while the queue is full.
+        If "block" is true, this blocks while the queue is full.
 
         For most objects, the object received through Queue.get() will
         be a new one, equivalent to the original and not sharing any
@@ -210,6 +210,8 @@ def put(self, obj, timeout=None, *,
         If "unbounditems" is UNBOUND then it is returned by get() in place
         of the unbound item.
         """
+        if not block:
+            return self.put_nowait(obj, unbounditems=unbounditems)
         if unbounditems is None:
             unboundop = -1
         else:
@@ -236,17 +238,19 @@ def put_nowait(self, obj, *, unbounditems=None):
             unboundop, = _serialize_unbound(unbounditems)
         _queues.put(self._id, obj, unboundop)
 
-    def get(self, timeout=None, *,
+    def get(self, block=True, timeout=None, *,
             _delay=10 / 1000,  # 10 milliseconds
             ):
         """Return the next object from the queue.
 
-        This blocks while the queue is empty.
+        If "block" is true, this blocks while the queue is empty.
 
         If the next item's original interpreter has been destroyed
         then the "next object" is determined by the value of the
         "unbounditems" argument to put().
         """
+        if not block:
+            return self.get_nowait()
         if timeout is not None:
             timeout = int(timeout)
             if timeout < 0:
diff --git a/Lib/test/test_interpreters/test_queues.py 
b/Lib/test/test_interpreters/test_queues.py
index 815d38d8bd7a4a..8c6a0efbb920d8 100644
--- a/Lib/test/test_interpreters/test_queues.py
+++ b/Lib/test/test_interpreters/test_queues.py
@@ -12,7 +12,7 @@
 import test._crossinterp_definitions as defs
 from .utils import _run_output, TestBase as _TestBase
 
-
+HUGE_TIMEOUT = 3600
 REPLACE = _crossinterp._UNBOUND_CONSTANT_TO_FLAG[_crossinterp.UNBOUND]
 
 
@@ -307,6 +307,8 @@ def test_put_timeout(self):
         queue.put(None)
         with self.assertRaises(queues.QueueFull):
             queue.put(None, timeout=0.1)
+        with self.assertRaises(queues.QueueFull):
+            queue.put(None, HUGE_TIMEOUT, 0.1)
         queue.get()
         queue.put(None)
 
@@ -316,6 +318,10 @@ def test_put_nowait(self):
         queue.put_nowait(None)
         with self.assertRaises(queues.QueueFull):
             queue.put_nowait(None)
+        with self.assertRaises(queues.QueueFull):
+            queue.put(None, False)
+        with self.assertRaises(queues.QueueFull):
+            queue.put(None, False, timeout=HUGE_TIMEOUT)
         queue.get()
         queue.put_nowait(None)
 
@@ -346,11 +352,17 @@ def test_get_timeout(self):
         queue = queues.create()
         with self.assertRaises(queues.QueueEmpty):
             queue.get(timeout=0.1)
+        with self.assertRaises(queues.QueueEmpty):
+            queue.get(HUGE_TIMEOUT, 0.1)
 
     def test_get_nowait(self):
         queue = queues.create()
         with self.assertRaises(queues.QueueEmpty):
             queue.get_nowait()
+        with self.assertRaises(queues.QueueEmpty):
+            queue.get(False)
+        with self.assertRaises(queues.QueueEmpty):
+            queue.get(False, timeout=HUGE_TIMEOUT)
 
     def test_put_get_full_fallback(self):
         expected = list(range(20))
diff --git 
a/Misc/NEWS.d/next/Library/2025-08-30-10-58-15.gh-issue-138253.9Ehj-N.rst 
b/Misc/NEWS.d/next/Library/2025-08-30-10-58-15.gh-issue-138253.9Ehj-N.rst
new file mode 100644
index 00000000000000..be810b759f44f2
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-08-30-10-58-15.gh-issue-138253.9Ehj-N.rst
@@ -0,0 +1,3 @@
+Add the *block* parameter in the :meth:`!put` and :meth:`!get` methods
+of the :mod:`concurrent.interpreters` queues for compatibility with the
+:class:`queue.Queue` interface.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to