]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-112559: Avoid unnecessary conversion attempts to enum_klass in signal.py (#113040)
authorYilei Yang <yileiyang@google.com>
Sun, 24 Dec 2023 01:07:52 +0000 (17:07 -0800)
committerGitHub <noreply@github.com>
Sun, 24 Dec 2023 01:07:52 +0000 (17:07 -0800)
Lib/signal.py
Lib/test/test_asyncio/test_runners.py
Lib/test/test_signal.py
Misc/NEWS.d/next/Library/2023-12-12-20-15-57.gh-issue-112559.IgXkje.rst [new file with mode: 0644]

index 50b215b29d2fadf6ccc38e860242d04e5d946fb5..c8cd3d4f597ca500947b74541d2d96be21f9627d 100644 (file)
@@ -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:
index 13493d3c806d6a11b8256f5dea684a652b78243f..266f057f0776c3dfeaa728b2f7685dd96a9d2d63 100644 (file)
@@ -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()
index acb7e9d4c6074d108ca9c32a93132aa216e4a50a..637a0ca3b3697269af11761f4b5ebdecc80989ff 100644 (file)
@@ -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 (file)
index 0000000..c08cb7c
--- /dev/null
@@ -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.