mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
gh-132775: Use _PyObject_GetXIData (With Fallback) (gh-134440)
This change includes some semi-related refactoring of queues and channels.
This commit is contained in:
parent
d706eb9e0f
commit
d0eedfa10e
10 changed files with 485 additions and 437 deletions
|
@ -9,6 +9,7 @@ from test.support import import_helper, Py_DEBUG
|
|||
_queues = import_helper.import_module('_interpqueues')
|
||||
from test.support import interpreters
|
||||
from test.support.interpreters import queues, _crossinterp
|
||||
import test._crossinterp_definitions as defs
|
||||
from .utils import _run_output, TestBase as _TestBase
|
||||
|
||||
|
||||
|
@ -42,7 +43,7 @@ class LowLevelTests(TestBase):
|
|||
importlib.reload(queues)
|
||||
|
||||
def test_create_destroy(self):
|
||||
qid = _queues.create(2, 0, REPLACE)
|
||||
qid = _queues.create(2, REPLACE, -1)
|
||||
_queues.destroy(qid)
|
||||
self.assertEqual(get_num_queues(), 0)
|
||||
with self.assertRaises(queues.QueueNotFoundError):
|
||||
|
@ -56,7 +57,7 @@ class LowLevelTests(TestBase):
|
|||
'-c',
|
||||
dedent(f"""
|
||||
import {_queues.__name__} as _queues
|
||||
_queues.create(2, 0, {REPLACE})
|
||||
_queues.create(2, {REPLACE}, -1)
|
||||
"""),
|
||||
)
|
||||
self.assertEqual(stdout, '')
|
||||
|
@ -67,13 +68,13 @@ class LowLevelTests(TestBase):
|
|||
|
||||
def test_bind_release(self):
|
||||
with self.subTest('typical'):
|
||||
qid = _queues.create(2, 0, REPLACE)
|
||||
qid = _queues.create(2, REPLACE, -1)
|
||||
_queues.bind(qid)
|
||||
_queues.release(qid)
|
||||
self.assertEqual(get_num_queues(), 0)
|
||||
|
||||
with self.subTest('bind too much'):
|
||||
qid = _queues.create(2, 0, REPLACE)
|
||||
qid = _queues.create(2, REPLACE, -1)
|
||||
_queues.bind(qid)
|
||||
_queues.bind(qid)
|
||||
_queues.release(qid)
|
||||
|
@ -81,7 +82,7 @@ class LowLevelTests(TestBase):
|
|||
self.assertEqual(get_num_queues(), 0)
|
||||
|
||||
with self.subTest('nested'):
|
||||
qid = _queues.create(2, 0, REPLACE)
|
||||
qid = _queues.create(2, REPLACE, -1)
|
||||
_queues.bind(qid)
|
||||
_queues.bind(qid)
|
||||
_queues.release(qid)
|
||||
|
@ -89,7 +90,7 @@ class LowLevelTests(TestBase):
|
|||
self.assertEqual(get_num_queues(), 0)
|
||||
|
||||
with self.subTest('release without binding'):
|
||||
qid = _queues.create(2, 0, REPLACE)
|
||||
qid = _queues.create(2, REPLACE, -1)
|
||||
with self.assertRaises(queues.QueueError):
|
||||
_queues.release(qid)
|
||||
|
||||
|
@ -132,13 +133,13 @@ class QueueTests(TestBase):
|
|||
|
||||
with self.subTest('same interpreter'):
|
||||
queue2 = queues.create()
|
||||
queue1.put(queue2, syncobj=True)
|
||||
queue1.put(queue2)
|
||||
queue3 = queue1.get()
|
||||
self.assertIs(queue3, queue2)
|
||||
|
||||
with self.subTest('from current interpreter'):
|
||||
queue4 = queues.create()
|
||||
queue1.put(queue4, syncobj=True)
|
||||
queue1.put(queue4)
|
||||
out = _run_output(interp, dedent("""
|
||||
queue4 = queue1.get()
|
||||
print(queue4.id)
|
||||
|
@ -149,7 +150,7 @@ class QueueTests(TestBase):
|
|||
with self.subTest('from subinterpreter'):
|
||||
out = _run_output(interp, dedent("""
|
||||
queue5 = queues.create()
|
||||
queue1.put(queue5, syncobj=True)
|
||||
queue1.put(queue5)
|
||||
print(queue5.id)
|
||||
"""))
|
||||
qid = int(out)
|
||||
|
@ -198,7 +199,7 @@ class TestQueueOps(TestBase):
|
|||
def test_empty(self):
|
||||
queue = queues.create()
|
||||
before = queue.empty()
|
||||
queue.put(None, syncobj=True)
|
||||
queue.put(None)
|
||||
during = queue.empty()
|
||||
queue.get()
|
||||
after = queue.empty()
|
||||
|
@ -213,7 +214,7 @@ class TestQueueOps(TestBase):
|
|||
queue = queues.create(3)
|
||||
for _ in range(3):
|
||||
actual.append(queue.full())
|
||||
queue.put(None, syncobj=True)
|
||||
queue.put(None)
|
||||
actual.append(queue.full())
|
||||
for _ in range(3):
|
||||
queue.get()
|
||||
|
@ -227,16 +228,16 @@ class TestQueueOps(TestBase):
|
|||
queue = queues.create()
|
||||
for _ in range(3):
|
||||
actual.append(queue.qsize())
|
||||
queue.put(None, syncobj=True)
|
||||
queue.put(None)
|
||||
actual.append(queue.qsize())
|
||||
queue.get()
|
||||
actual.append(queue.qsize())
|
||||
queue.put(None, syncobj=True)
|
||||
queue.put(None)
|
||||
actual.append(queue.qsize())
|
||||
for _ in range(3):
|
||||
queue.get()
|
||||
actual.append(queue.qsize())
|
||||
queue.put(None, syncobj=True)
|
||||
queue.put(None)
|
||||
actual.append(queue.qsize())
|
||||
queue.get()
|
||||
actual.append(queue.qsize())
|
||||
|
@ -245,70 +246,32 @@ class TestQueueOps(TestBase):
|
|||
|
||||
def test_put_get_main(self):
|
||||
expected = list(range(20))
|
||||
for syncobj in (True, False):
|
||||
kwds = dict(syncobj=syncobj)
|
||||
with self.subTest(f'syncobj={syncobj}'):
|
||||
queue = queues.create()
|
||||
for i in range(20):
|
||||
queue.put(i, **kwds)
|
||||
actual = [queue.get() for _ in range(20)]
|
||||
queue = queues.create()
|
||||
for i in range(20):
|
||||
queue.put(i)
|
||||
actual = [queue.get() for _ in range(20)]
|
||||
|
||||
self.assertEqual(actual, expected)
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
def test_put_timeout(self):
|
||||
for syncobj in (True, False):
|
||||
kwds = dict(syncobj=syncobj)
|
||||
with self.subTest(f'syncobj={syncobj}'):
|
||||
queue = queues.create(2)
|
||||
queue.put(None, **kwds)
|
||||
queue.put(None, **kwds)
|
||||
with self.assertRaises(queues.QueueFull):
|
||||
queue.put(None, timeout=0.1, **kwds)
|
||||
queue.get()
|
||||
queue.put(None, **kwds)
|
||||
queue = queues.create(2)
|
||||
queue.put(None)
|
||||
queue.put(None)
|
||||
with self.assertRaises(queues.QueueFull):
|
||||
queue.put(None, timeout=0.1)
|
||||
queue.get()
|
||||
queue.put(None)
|
||||
|
||||
def test_put_nowait(self):
|
||||
for syncobj in (True, False):
|
||||
kwds = dict(syncobj=syncobj)
|
||||
with self.subTest(f'syncobj={syncobj}'):
|
||||
queue = queues.create(2)
|
||||
queue.put_nowait(None, **kwds)
|
||||
queue.put_nowait(None, **kwds)
|
||||
with self.assertRaises(queues.QueueFull):
|
||||
queue.put_nowait(None, **kwds)
|
||||
queue.get()
|
||||
queue.put_nowait(None, **kwds)
|
||||
queue = queues.create(2)
|
||||
queue.put_nowait(None)
|
||||
queue.put_nowait(None)
|
||||
with self.assertRaises(queues.QueueFull):
|
||||
queue.put_nowait(None)
|
||||
queue.get()
|
||||
queue.put_nowait(None)
|
||||
|
||||
def test_put_syncobj(self):
|
||||
for obj in [
|
||||
None,
|
||||
True,
|
||||
10,
|
||||
'spam',
|
||||
b'spam',
|
||||
(0, 'a'),
|
||||
]:
|
||||
with self.subTest(repr(obj)):
|
||||
queue = queues.create()
|
||||
|
||||
queue.put(obj, syncobj=True)
|
||||
obj2 = queue.get()
|
||||
self.assertEqual(obj2, obj)
|
||||
|
||||
queue.put(obj, syncobj=True)
|
||||
obj2 = queue.get_nowait()
|
||||
self.assertEqual(obj2, obj)
|
||||
|
||||
for obj in [
|
||||
[1, 2, 3],
|
||||
{'a': 13, 'b': 17},
|
||||
]:
|
||||
with self.subTest(repr(obj)):
|
||||
queue = queues.create()
|
||||
with self.assertRaises(interpreters.NotShareableError):
|
||||
queue.put(obj, syncobj=True)
|
||||
|
||||
def test_put_not_syncobj(self):
|
||||
def test_put_full_fallback(self):
|
||||
for obj in [
|
||||
None,
|
||||
True,
|
||||
|
@ -323,11 +286,11 @@ class TestQueueOps(TestBase):
|
|||
with self.subTest(repr(obj)):
|
||||
queue = queues.create()
|
||||
|
||||
queue.put(obj, syncobj=False)
|
||||
queue.put(obj)
|
||||
obj2 = queue.get()
|
||||
self.assertEqual(obj2, obj)
|
||||
|
||||
queue.put(obj, syncobj=False)
|
||||
queue.put(obj)
|
||||
obj2 = queue.get_nowait()
|
||||
self.assertEqual(obj2, obj)
|
||||
|
||||
|
@ -341,24 +304,9 @@ class TestQueueOps(TestBase):
|
|||
with self.assertRaises(queues.QueueEmpty):
|
||||
queue.get_nowait()
|
||||
|
||||
def test_put_get_default_syncobj(self):
|
||||
def test_put_get_full_fallback(self):
|
||||
expected = list(range(20))
|
||||
queue = queues.create(syncobj=True)
|
||||
for methname in ('get', 'get_nowait'):
|
||||
with self.subTest(f'{methname}()'):
|
||||
get = getattr(queue, methname)
|
||||
for i in range(20):
|
||||
queue.put(i)
|
||||
actual = [get() for _ in range(20)]
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
obj = [1, 2, 3] # lists are not shareable
|
||||
with self.assertRaises(interpreters.NotShareableError):
|
||||
queue.put(obj)
|
||||
|
||||
def test_put_get_default_not_syncobj(self):
|
||||
expected = list(range(20))
|
||||
queue = queues.create(syncobj=False)
|
||||
queue = queues.create()
|
||||
for methname in ('get', 'get_nowait'):
|
||||
with self.subTest(f'{methname}()'):
|
||||
get = getattr(queue, methname)
|
||||
|
@ -384,7 +332,7 @@ class TestQueueOps(TestBase):
|
|||
with self.subTest(f'{methname}()'):
|
||||
interp.exec(dedent(f"""
|
||||
orig = b'spam'
|
||||
queue.put(orig, syncobj=True)
|
||||
queue.put(orig)
|
||||
obj = queue.{methname}()
|
||||
assert obj == orig, 'expected: obj == orig'
|
||||
assert obj is not orig, 'expected: obj is not orig'
|
||||
|
@ -399,7 +347,7 @@ class TestQueueOps(TestBase):
|
|||
for methname in ('get', 'get_nowait'):
|
||||
with self.subTest(f'{methname}()'):
|
||||
obj1 = b'spam'
|
||||
queue1.put(obj1, syncobj=True)
|
||||
queue1.put(obj1)
|
||||
|
||||
out = _run_output(
|
||||
interp,
|
||||
|
@ -416,7 +364,7 @@ class TestQueueOps(TestBase):
|
|||
obj2 = b'eggs'
|
||||
print(id(obj2))
|
||||
assert queue2.qsize() == 0, 'expected: queue2.qsize() == 0'
|
||||
queue2.put(obj2, syncobj=True)
|
||||
queue2.put(obj2)
|
||||
assert queue2.qsize() == 1, 'expected: queue2.qsize() == 1'
|
||||
"""))
|
||||
self.assertEqual(len(queues.list_all()), 2)
|
||||
|
@ -433,11 +381,11 @@ class TestQueueOps(TestBase):
|
|||
if not unbound:
|
||||
extraargs = ''
|
||||
elif unbound is queues.UNBOUND:
|
||||
extraargs = ', unbound=queues.UNBOUND'
|
||||
extraargs = ', unbounditems=queues.UNBOUND'
|
||||
elif unbound is queues.UNBOUND_ERROR:
|
||||
extraargs = ', unbound=queues.UNBOUND_ERROR'
|
||||
extraargs = ', unbounditems=queues.UNBOUND_ERROR'
|
||||
elif unbound is queues.UNBOUND_REMOVE:
|
||||
extraargs = ', unbound=queues.UNBOUND_REMOVE'
|
||||
extraargs = ', unbounditems=queues.UNBOUND_REMOVE'
|
||||
else:
|
||||
raise NotImplementedError(repr(unbound))
|
||||
interp = interpreters.create()
|
||||
|
@ -447,8 +395,8 @@ class TestQueueOps(TestBase):
|
|||
queue = queues.Queue({queue.id})
|
||||
obj1 = b'spam'
|
||||
obj2 = b'eggs'
|
||||
queue.put(obj1, syncobj=True{extraargs})
|
||||
queue.put(obj2, syncobj=True{extraargs})
|
||||
queue.put(obj1{extraargs})
|
||||
queue.put(obj2{extraargs})
|
||||
"""))
|
||||
self.assertEqual(queue.qsize(), presize + 2)
|
||||
|
||||
|
@ -501,11 +449,11 @@ class TestQueueOps(TestBase):
|
|||
with self.assertRaises(queues.QueueEmpty):
|
||||
queue.get_nowait()
|
||||
|
||||
queue.put(b'ham', unbound=queues.UNBOUND_REMOVE)
|
||||
queue.put(b'ham', unbounditems=queues.UNBOUND_REMOVE)
|
||||
self.assertEqual(queue.qsize(), 1)
|
||||
interp = common(queue, queues.UNBOUND_REMOVE, 1)
|
||||
self.assertEqual(queue.qsize(), 3)
|
||||
queue.put(42, unbound=queues.UNBOUND_REMOVE)
|
||||
queue.put(42, unbounditems=queues.UNBOUND_REMOVE)
|
||||
self.assertEqual(queue.qsize(), 4)
|
||||
del interp
|
||||
self.assertEqual(queue.qsize(), 2)
|
||||
|
@ -523,11 +471,11 @@ class TestQueueOps(TestBase):
|
|||
_run_output(interp, dedent(f"""
|
||||
from test.support.interpreters import queues
|
||||
queue = queues.Queue({queue.id})
|
||||
queue.put(1, syncobj=True, unbound=queues.UNBOUND)
|
||||
queue.put(2, syncobj=True, unbound=queues.UNBOUND_ERROR)
|
||||
queue.put(3, syncobj=True)
|
||||
queue.put(4, syncobj=True, unbound=queues.UNBOUND_REMOVE)
|
||||
queue.put(5, syncobj=True, unbound=queues.UNBOUND)
|
||||
queue.put(1, unbounditems=queues.UNBOUND)
|
||||
queue.put(2, unbounditems=queues.UNBOUND_ERROR)
|
||||
queue.put(3)
|
||||
queue.put(4, unbounditems=queues.UNBOUND_REMOVE)
|
||||
queue.put(5, unbounditems=queues.UNBOUND)
|
||||
"""))
|
||||
self.assertEqual(queue.qsize(), 5)
|
||||
|
||||
|
@ -555,13 +503,13 @@ class TestQueueOps(TestBase):
|
|||
interp1 = interpreters.create()
|
||||
interp2 = interpreters.create()
|
||||
|
||||
queue.put(1, syncobj=True)
|
||||
queue.put(1)
|
||||
_run_output(interp1, dedent(f"""
|
||||
from test.support.interpreters import queues
|
||||
queue = queues.Queue({queue.id})
|
||||
obj1 = queue.get()
|
||||
queue.put(2, syncobj=True, unbound=queues.UNBOUND)
|
||||
queue.put(obj1, syncobj=True, unbound=queues.UNBOUND_REMOVE)
|
||||
queue.put(2, unbounditems=queues.UNBOUND)
|
||||
queue.put(obj1, unbounditems=queues.UNBOUND_REMOVE)
|
||||
"""))
|
||||
_run_output(interp2, dedent(f"""
|
||||
from test.support.interpreters import queues
|
||||
|
@ -572,21 +520,21 @@ class TestQueueOps(TestBase):
|
|||
self.assertEqual(queue.qsize(), 0)
|
||||
queue.put(3)
|
||||
_run_output(interp1, dedent("""
|
||||
queue.put(4, syncobj=True, unbound=queues.UNBOUND)
|
||||
queue.put(4, unbounditems=queues.UNBOUND)
|
||||
# interp closed here
|
||||
queue.put(5, syncobj=True, unbound=queues.UNBOUND_REMOVE)
|
||||
queue.put(6, syncobj=True, unbound=queues.UNBOUND)
|
||||
queue.put(5, unbounditems=queues.UNBOUND_REMOVE)
|
||||
queue.put(6, unbounditems=queues.UNBOUND)
|
||||
"""))
|
||||
_run_output(interp2, dedent("""
|
||||
queue.put(7, syncobj=True, unbound=queues.UNBOUND_ERROR)
|
||||
queue.put(7, unbounditems=queues.UNBOUND_ERROR)
|
||||
# interp closed here
|
||||
queue.put(obj1, syncobj=True, unbound=queues.UNBOUND_ERROR)
|
||||
queue.put(obj2, syncobj=True, unbound=queues.UNBOUND_REMOVE)
|
||||
queue.put(8, syncobj=True, unbound=queues.UNBOUND)
|
||||
queue.put(obj1, unbounditems=queues.UNBOUND_ERROR)
|
||||
queue.put(obj2, unbounditems=queues.UNBOUND_REMOVE)
|
||||
queue.put(8, unbounditems=queues.UNBOUND)
|
||||
"""))
|
||||
_run_output(interp1, dedent("""
|
||||
queue.put(9, syncobj=True, unbound=queues.UNBOUND_REMOVE)
|
||||
queue.put(10, syncobj=True, unbound=queues.UNBOUND)
|
||||
queue.put(9, unbounditems=queues.UNBOUND_REMOVE)
|
||||
queue.put(10, unbounditems=queues.UNBOUND)
|
||||
"""))
|
||||
self.assertEqual(queue.qsize(), 10)
|
||||
|
||||
|
@ -642,12 +590,12 @@ class TestQueueOps(TestBase):
|
|||
break
|
||||
except queues.QueueEmpty:
|
||||
continue
|
||||
queue2.put(obj, syncobj=True)
|
||||
queue2.put(obj)
|
||||
t = threading.Thread(target=f)
|
||||
t.start()
|
||||
|
||||
orig = b'spam'
|
||||
queue1.put(orig, syncobj=True)
|
||||
queue1.put(orig)
|
||||
obj = queue2.get()
|
||||
t.join()
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue