Gentoo Archives: gentoo-commits

From: Zac Medico <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:master commit in: pym/portage/tests/ebuild/, pym/_emerge/
Date: Thu, 26 Apr 2018 03:45:41
Message-Id: 1524712762.71a5a82313226f7be0d966d49392a53139a96f6b.zmedico@gentoo
1 commit: 71a5a82313226f7be0d966d49392a53139a96f6b
2 Author: Zac Medico <zmedico <AT> gentoo <DOT> org>
3 AuthorDate: Tue Apr 24 02:47:11 2018 +0000
4 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org>
5 CommitDate: Thu Apr 26 03:19:22 2018 +0000
6 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=71a5a823
7
8 AsynchronousTask: add async_wait() method (bug 653856)
9
10 Since the AsynchronousTask.wait() method is prone to event loop
11 recursion, deprecate it, and add an async_wait() method method to
12 replace it. Instead of using task.wait() in order to implicitly run
13 the event loop, now loop.run_until_complete(task.async_wait()) will
14 be used to explicitly run the event loop. This explicit approach will
15 make it more obvious when code will trigger event loop recursion
16 which would not be compatible with asyncio's default event loop.
17
18 Bug: https://bugs.gentoo.org/653856
19
20 pym/_emerge/AsynchronousTask.py | 23 +++++++++++++++++++++++
21 pym/portage/tests/ebuild/test_ipc_daemon.py | 2 +-
22 2 files changed, 24 insertions(+), 1 deletion(-)
23
24 diff --git a/pym/_emerge/AsynchronousTask.py b/pym/_emerge/AsynchronousTask.py
25 index e29324440..7d2e6253b 100644
26 --- a/pym/_emerge/AsynchronousTask.py
27 +++ b/pym/_emerge/AsynchronousTask.py
28 @@ -29,6 +29,26 @@ class AsynchronousTask(SlotObject):
29 self._start_hook()
30 self._start()
31
32 + def async_wait(self):
33 + """
34 + Wait for returncode asynchronously. Notification is available
35 + via the add_done_callback method of the returned Future instance.
36 +
37 + @returns: Future, result is self.returncode
38 + """
39 + waiter = self.scheduler.create_future()
40 + exit_listener = lambda self: waiter.set_result(self.returncode)
41 + self.addExitListener(exit_listener)
42 + waiter.add_done_callback(lambda waiter:
43 + self.removeExitListener(exit_listener) if waiter.cancelled() else None)
44 + if self.returncode is not None:
45 + # If the returncode is not None, it means the exit event has already
46 + # happened, so use _async_wait() to guarantee that the exit_listener
47 + # is called. This does not do any harm because a given exit listener
48 + # is never called more than once.
49 + self._async_wait()
50 + return waiter
51 +
52 def _start(self):
53 self.returncode = os.EX_OK
54 self.wait()
55 @@ -47,6 +67,9 @@ class AsynchronousTask(SlotObject):
56 return self.returncode
57
58 def wait(self):
59 + """
60 + Deprecated. Use async_wait() instead.
61 + """
62 if self.returncode is None:
63 if not self._waiting:
64 self._waiting = True
65
66 diff --git a/pym/portage/tests/ebuild/test_ipc_daemon.py b/pym/portage/tests/ebuild/test_ipc_daemon.py
67 index bc18cdf64..e6da51a76 100644
68 --- a/pym/portage/tests/ebuild/test_ipc_daemon.py
69 +++ b/pym/portage/tests/ebuild/test_ipc_daemon.py
70 @@ -157,6 +157,6 @@ class IpcDaemonTestCase(TestCase):
71 try:
72 task_scheduler.start()
73 event_loop.run_until_complete(self._run_done)
74 - task_scheduler.wait()
75 + event_loop.run_until_complete(task_scheduler.async_wait())
76 finally:
77 timeout_handle.cancel()