Skip to content

Commit

Permalink
[3.11] pythongh-112559: Avoid unnecessary conversion attempts to enum…
Browse files Browse the repository at this point in the history
…_klass in signal.py (pythonGH-113040) (python#113444)

pythongh-112559: Avoid unnecessary conversion attempts to enum_klass in signal.py (pythonGH-113040)
(cherry picked from commit 050783c)

Co-authored-by: Yilei Yang <yileiyang@google.com>
  • Loading branch information
miss-islington and yilei committed Dec 24, 2023
1 parent 9000b8a commit b60bddb
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 2 deletions.
6 changes: 4 additions & 2 deletions Lib/signal.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@


def _int_to_enum(value, enum_klass):
"""Convert a numeric value to an IntEnum member.
If it's not a known member, return the numeric value itself.
"""Convert a possible numeric value to an IntEnum member.
If it's not a known member, return the value itself.
"""
if not isinstance(value, int):
return value
try:
return enum_klass(value)
except ValueError:
Expand Down
18 changes: 18 additions & 0 deletions Lib/test/test_asyncio/test_runners.py
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,24 @@ async def coro():
self.assertEqual(1, policy.set_event_loop.call_count)
runner.close()

def test_no_repr_is_call_on_the_task_result(self):
# See https://github.com/python/cpython/issues/112559.
class MyResult:
def __init__(self):
self.repr_count = 0
def __repr__(self):
self.repr_count += 1
return super().__repr__()

async def coro():
return MyResult()


with asyncio.Runner() as runner:
result = runner.run(coro())

self.assertEqual(0, result.repr_count)


if __name__ == '__main__':
unittest.main()
26 changes: 26 additions & 0 deletions Lib/test/test_signal.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import enum
import errno
import functools
import inspect
import os
import random
Expand Down Expand Up @@ -76,6 +77,9 @@ class PosixTests(unittest.TestCase):
def trivial_signal_handler(self, *args):
pass

def create_handler_with_partial(self, argument):
return functools.partial(self.trivial_signal_handler, argument)

def test_out_of_range_signal_number_raises_error(self):
self.assertRaises(ValueError, signal.getsignal, 4242)

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

def test_no_repr_is_called_on_signal_handler(self):
# See https://github.com/python/cpython/issues/112559.

class MyArgument:
def __init__(self):
self.repr_count = 0

def __repr__(self):
self.repr_count += 1
return super().__repr__()

argument = MyArgument()
self.assertEqual(0, argument.repr_count)

handler = self.create_handler_with_partial(argument)
hup = signal.signal(signal.SIGHUP, handler)
self.assertIsInstance(hup, signal.Handlers)
self.assertEqual(signal.getsignal(signal.SIGHUP), handler)
signal.signal(signal.SIGHUP, hup)
self.assertEqual(signal.getsignal(signal.SIGHUP), hup)
self.assertEqual(0, argument.repr_count)

def test_strsignal(self):
self.assertIn("Interrupt", signal.strsignal(signal.SIGINT))
self.assertIn("Terminated", signal.strsignal(signal.SIGTERM))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:func:`signal.signal` and :func:`signal.getsignal` no longer call ``repr`` on
callable handlers. :func:`asyncio.run` and :meth:`asyncio.Runner.run` no longer
call ``repr`` on the task results. Patch by Yilei Yang.

0 comments on commit b60bddb

Please sign in to comment.