Gentoo Archives: gentoo-commits

From: Zac Medico <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:master commit in: lib/portage/tests/util/futures/, lib/_emerge/
Date: Fri, 06 Mar 2020 09:01:15
Message-Id: 1583484917.5d476c4e500248929d6b042de302b1e7c923dc60.zmedico@gentoo
1 commit: 5d476c4e500248929d6b042de302b1e7c923dc60
2 Author: Zac Medico <zmedico <AT> gentoo <DOT> org>
3 AuthorDate: Fri Mar 6 08:11:05 2020 +0000
4 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org>
5 CommitDate: Fri Mar 6 08:55:17 2020 +0000
6 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=5d476c4e
7
8 AsynchronousTask: handle addExistListener after exit
9
10 When addExistListener is called after the task has already exited with
11 a returncode, immediately schedule the listener to be invoked via
12 call_soon. This behavior is similar to the Future add_done_callback
13 method.
14
15 Signed-off-by: Zac Medico <zmedico <AT> gentoo.org>
16
17 lib/_emerge/AsynchronousTask.py | 2 ++
18 .../util/futures/test_done_callback_after_exit.py | 40 ++++++++++++++++++++++
19 2 files changed, 42 insertions(+)
20
21 diff --git a/lib/_emerge/AsynchronousTask.py b/lib/_emerge/AsynchronousTask.py
22 index 799e66a4a..97db02587 100644
23 --- a/lib/_emerge/AsynchronousTask.py
24 +++ b/lib/_emerge/AsynchronousTask.py
25 @@ -176,6 +176,8 @@ class AsynchronousTask(SlotObject):
26 if self._exit_listeners is None:
27 self._exit_listeners = []
28 self._exit_listeners.append(f)
29 + if self.returncode is not None:
30 + self._wait_hook()
31
32 def removeExitListener(self, f):
33 if self._exit_listeners is not None:
34
35 diff --git a/lib/portage/tests/util/futures/test_done_callback_after_exit.py b/lib/portage/tests/util/futures/test_done_callback_after_exit.py
36 new file mode 100644
37 index 000000000..46a51c271
38 --- /dev/null
39 +++ b/lib/portage/tests/util/futures/test_done_callback_after_exit.py
40 @@ -0,0 +1,40 @@
41 +# Copyright 2020 Gentoo Foundation
42 +# Distributed under the terms of the GNU General Public License v2
43 +
44 +from _emerge.AsynchronousTask import AsynchronousTask
45 +from portage.tests import TestCase
46 +from portage.util.futures import asyncio
47 +
48 +
49 +class DoneCallbackAfterExitTestCase(TestCase):
50 +
51 + def test_done_callback_after_exit(self):
52 + """
53 + Test that callbacks can be registered via the Future
54 + add_done_callback method even after the future is done, and
55 + verify that the callbacks are called.
56 + """
57 + loop = asyncio._wrap_loop()
58 + future = loop.create_future()
59 + future.set_result(None)
60 +
61 + for i in range(3):
62 + event = loop.create_future()
63 + future.add_done_callback(lambda future: event.set_result(None))
64 + loop.run_until_complete(event)
65 +
66 + def test_exit_listener_after_exit(self):
67 + """
68 + Test that callbacks can be registered via the AsynchronousTask
69 + addExitListener method even after the task is done, and
70 + verify that the callbacks are called.
71 + """
72 + loop = asyncio._wrap_loop()
73 + task = AsynchronousTask(scheduler=loop)
74 + loop.run_until_complete(task.async_start())
75 + loop.run_until_complete(task.async_wait())
76 +
77 + for i in range(3):
78 + event = loop.create_future()
79 + task.addExitListener(lambda task: event.set_result(None))
80 + loop.run_until_complete(event)