summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYilei Yang <yileiyang@google.com>2023-12-24 01:07:52 (GMT)
committerGitHub <noreply@github.com>2023-12-24 01:07:52 (GMT)
commit050783cb37d6a09d8238fa640814df8a915f6a68 (patch)
tree7560dc77405b33a58cd7fccd6f0f74c49a083591
parent0187a7e4ec9550a6e35dd06b26f22863520242ab (diff)
downloadcpython-050783cb37d6a09d8238fa640814df8a915f6a68.zip
cpython-050783cb37d6a09d8238fa640814df8a915f6a68.tar.gz
cpython-050783cb37d6a09d8238fa640814df8a915f6a68.tar.bz2
gh-112559: Avoid unnecessary conversion attempts to enum_klass in signal.py (#113040)
-rw-r--r--Lib/signal.py6
-rw-r--r--Lib/test/test_asyncio/test_runners.py18
-rw-r--r--Lib/test/test_signal.py26
-rw-r--r--Misc/NEWS.d/next/Library/2023-12-12-20-15-57.gh-issue-112559.IgXkje.rst3
4 files changed, 51 insertions, 2 deletions
diff --git a/Lib/signal.py b/Lib/signal.py
index 50b215b..c8cd3d4 100644
--- a/Lib/signal.py
+++ b/Lib/signal.py
@@ -22,9 +22,11 @@ if 'pthread_sigmask' in _globals:
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:
diff --git a/Lib/test/test_asyncio/test_runners.py b/Lib/test/test_asyncio/test_runners.py
index 13493d3..266f057 100644
--- a/Lib/test/test_asyncio/test_runners.py
+++ b/Lib/test/test_asyncio/test_runners.py
@@ -495,6 +495,24 @@ class RunnerTests(BaseTest):
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()
diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py
index acb7e9d..637a0ca 100644
--- a/Lib/test/test_signal.py
+++ b/Lib/test/test_signal.py
@@ -1,5 +1,6 @@
import enum
import errno
+import functools
import inspect
import os
import random
@@ -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)
@@ -96,6 +100,28 @@ class PosixTests(unittest.TestCase):
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))
diff --git a/Misc/NEWS.d/next/Library/2023-12-12-20-15-57.gh-issue-112559.IgXkje.rst b/Misc/NEWS.d/next/Library/2023-12-12-20-15-57.gh-issue-112559.IgXkje.rst
new file mode 100644
index 0000000..c08cb7c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-12-12-20-15-57.gh-issue-112559.IgXkje.rst
@@ -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.