Skip to content

Commit 2b1d0f1

Browse files
committed
Convert singleton object to a noremal object.
1 parent 4a7e0ee commit 2b1d0f1

File tree

3 files changed

+27
-57
lines changed

3 files changed

+27
-57
lines changed

Lib/concurrent/interpreters/_crossinterp.py

Lines changed: 5 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,6 @@ class ItemInterpreterDestroyed(Exception):
55
"""Raised when trying to get an item whose interpreter was destroyed."""
66

77

8-
class classonly:
9-
"""A non-data descriptor that makes a value only visible on the class.
10-
11-
This is like the "classmethod" builtin, but does not show up on
12-
instances of the class. It may be used as a decorator.
13-
"""
14-
15-
def __init__(self, value):
16-
self.value = value
17-
self.getter = classmethod(value).__get__
18-
self.name = None
19-
20-
def __set_name__(self, cls, name):
21-
if self.name is not None:
22-
raise TypeError('already used')
23-
self.name = name
24-
25-
def __get__(self, obj, cls):
26-
if obj is not None:
27-
raise AttributeError(self.name)
28-
# called on the class
29-
return self.getter(None, cls)
30-
31-
328
class UnboundItem:
339
"""Represents a cross-interpreter item no longer bound to an interpreter.
3410
@@ -37,37 +13,9 @@ class UnboundItem:
3713
"""
3814

3915
__slots__ = ()
40-
41-
@classonly
42-
def singleton(cls, kind, module, name='UNBOUND'):
43-
doc = cls.__doc__
44-
if doc:
45-
doc = doc.replace(
46-
'cross-interpreter container', kind,
47-
).replace(
48-
'cross-interpreter', kind,
49-
)
50-
subclass = type(
51-
f'Unbound{kind.capitalize()}Item',
52-
(cls,),
53-
{
54-
"_MODULE": module,
55-
"_NAME": name,
56-
"__doc__": doc,
57-
},
58-
)
59-
return object.__new__(subclass)
60-
6116
_MODULE = __name__
6217
_NAME = 'UNBOUND'
6318

64-
def __new__(cls):
65-
raise Exception(f'use {cls._MODULE}.{cls._NAME}')
66-
67-
def __repr__(self):
68-
return f'{self._MODULE}.{self._NAME}'
69-
# return f'interpreters._queues.UNBOUND'
70-
7119
def __hash__(self):
7220
return hash((self._NAME, self._MODULE))
7321

@@ -79,8 +27,12 @@ def __eq__(self, other):
7927
return True
8028
return repr(other) == repr(self)
8129

30+
def __repr__(self):
31+
return f'{self._MODULE}.{self._NAME}'
32+
# return f'interpreters._queues.UNBOUND'
33+
8234

83-
UNBOUND = object.__new__(UnboundItem)
35+
UNBOUND = UnboundItem()
8436
UNBOUND_ERROR = object()
8537
UNBOUND_REMOVE = object()
8638

Lib/test/support/channels.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
ChannelEmptyError, ChannelNotEmptyError, # noqa: F401
1111
)
1212
from concurrent.interpreters._crossinterp import (
13-
UNBOUND_ERROR, UNBOUND_REMOVE,
13+
UNBOUND, UNBOUND_ERROR, UNBOUND_REMOVE,
1414
)
1515

1616

@@ -28,9 +28,6 @@ class ItemInterpreterDestroyed(ChannelError,
2828
"""Raised from get() and get_nowait()."""
2929

3030

31-
UNBOUND = _crossinterp.UnboundItem.singleton('queue', __name__)
32-
33-
3431
def _serialize_unbound(unbound):
3532
if unbound is UNBOUND:
3633
unbound = _crossinterp.UNBOUND

Lib/test/test_concurrent_futures/test_interpreter_pool.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,27 @@ def get_thread_name():
516516
self.assertStartsWith(self.executor.submit(get_thread_name).result(),
517517
"InterpreterPoolExecutor-"[:15])
518518

519+
def test_cross_interpreter_unbound_identity(self):
520+
# Prepare shared queues.
521+
input_q = interpreters.create_queue()
522+
input_q.put(queues.UNBOUND)
523+
result_q = interpreters.create_queue()
524+
525+
# Create a sub-interpreter.
526+
interp = interpreters.create()
527+
interp.prepare_main({"input_q": input_q, "result_q": result_q})
528+
529+
# Run and compare the items in queue.
530+
interp.exec("""
531+
from concurrent.interpreters import _queues as queues
532+
obj = input_q.get()
533+
is_identical = (obj is queues.UNBOUND)
534+
result_q.put(is_identical)
535+
""")
536+
is_identical = result_q.get()
537+
self.assertTrue(is_identical, "UNBOUND identity mismatch across interpreters")
538+
539+
519540
class AsyncioTest(InterpretersMixin, testasyncio_utils.TestCase):
520541

521542
@classmethod

0 commit comments

Comments
 (0)