Skip to content

Commit b60bddb

Browse files
[3.11] gh-112559: Avoid unnecessary conversion attempts to enum_klass in signal.py (GH-113040) (#113444)
gh-112559: Avoid unnecessary conversion attempts to enum_klass in signal.py (GH-113040) (cherry picked from commit 050783c) Co-authored-by: Yilei Yang <yileiyang@google.com>
1 parent 9000b8a commit b60bddb

File tree

4 files changed

+51
-2
lines changed

4 files changed

+51
-2
lines changed

Lib/signal.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@
2222

2323

2424
def _int_to_enum(value, enum_klass):
25-
"""Convert a numeric value to an IntEnum member.
26-
If it's not a known member, return the numeric value itself.
25+
"""Convert a possible numeric value to an IntEnum member.
26+
If it's not a known member, return the value itself.
2727
"""
28+
if not isinstance(value, int):
29+
return value
2830
try:
2931
return enum_klass(value)
3032
except ValueError:

Lib/test/test_asyncio/test_runners.py

+18
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,24 @@ async def coro():
473473
self.assertEqual(1, policy.set_event_loop.call_count)
474474
runner.close()
475475

476+
def test_no_repr_is_call_on_the_task_result(self):
477+
# See https://github.com/python/cpython/issues/112559.
478+
class MyResult:
479+
def __init__(self):
480+
self.repr_count = 0
481+
def __repr__(self):
482+
self.repr_count += 1
483+
return super().__repr__()
484+
485+
async def coro():
486+
return MyResult()
487+
488+
489+
with asyncio.Runner() as runner:
490+
result = runner.run(coro())
491+
492+
self.assertEqual(0, result.repr_count)
493+
476494

477495
if __name__ == '__main__':
478496
unittest.main()

Lib/test/test_signal.py

+26
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import enum
22
import errno
3+
import functools
34
import inspect
45
import os
56
import random
@@ -76,6 +77,9 @@ class PosixTests(unittest.TestCase):
7677
def trivial_signal_handler(self, *args):
7778
pass
7879

80+
def create_handler_with_partial(self, argument):
81+
return functools.partial(self.trivial_signal_handler, argument)
82+
7983
def test_out_of_range_signal_number_raises_error(self):
8084
self.assertRaises(ValueError, signal.getsignal, 4242)
8185

@@ -96,6 +100,28 @@ def test_getsignal(self):
96100
signal.signal(signal.SIGHUP, hup)
97101
self.assertEqual(signal.getsignal(signal.SIGHUP), hup)
98102

103+
def test_no_repr_is_called_on_signal_handler(self):
104+
# See https://github.com/python/cpython/issues/112559.
105+
106+
class MyArgument:
107+
def __init__(self):
108+
self.repr_count = 0
109+
110+
def __repr__(self):
111+
self.repr_count += 1
112+
return super().__repr__()
113+
114+
argument = MyArgument()
115+
self.assertEqual(0, argument.repr_count)
116+
117+
handler = self.create_handler_with_partial(argument)
118+
hup = signal.signal(signal.SIGHUP, handler)
119+
self.assertIsInstance(hup, signal.Handlers)
120+
self.assertEqual(signal.getsignal(signal.SIGHUP), handler)
121+
signal.signal(signal.SIGHUP, hup)
122+
self.assertEqual(signal.getsignal(signal.SIGHUP), hup)
123+
self.assertEqual(0, argument.repr_count)
124+
99125
def test_strsignal(self):
100126
self.assertIn("Interrupt", signal.strsignal(signal.SIGINT))
101127
self.assertIn("Terminated", signal.strsignal(signal.SIGTERM))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
:func:`signal.signal` and :func:`signal.getsignal` no longer call ``repr`` on
2+
callable handlers. :func:`asyncio.run` and :meth:`asyncio.Runner.run` no longer
3+
call ``repr`` on the task results. Patch by Yilei Yang.

0 commit comments

Comments
 (0)