commit: 6b4252d3a0f12808a5bcce888b7f68e1f84b5301
Author: Zac Medico gentoo org>
AuthorDate: Sat Jul 28 21:22:42 2018 +
Commit: Zac Medico gentoo org>
CommitDate: Mon Aug 6 04:38:41 2018 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=6b4252d3
Add asyncio.create_subprocess_exec support for python2 (bug 662388)
The asyncio.create_subprocess_exec function is essential for
using subprocesses in coroutines, so add support to do this
for python2. This paves the way for extensive use of coroutines
in portage, since coroutines are well-suited for many portage
tasks that involve subprocesses.
Bug: https://bugs.gentoo.org/662388
.../util/futures/asyncio/test_subprocess_exec.py | 184 ++---
lib/portage/util/futures/_asyncio/__init__.py | 53 ++
lib/portage/util/futures/_asyncio/process.py | 107
lib/portage/util/futures/_asyncio/streams.py | 96 +++
lib/portage/util/futures/compat_coroutine.py | 6 +-
5 files changed, 315 insertions(+), 131 deletions(-)
diff --git a/lib/portage/tests/util/futures/asyncio/test_subprocess_exec.py
b/lib/portage/tests/util/futures/asyncio/test_subprocess_exec.py
index 5a812ba6a..61646cb92 100644
--- a/lib/portage/tests/util/futures/asyncio/test_subprocess_exec.py
+++ b/lib/portage/tests/util/futures/asyncio/test_subprocess_exec.py
@@ -3,61 +3,16 @@
import os
import subprocess
-
-try:
- from asyncio import create_subprocess_exec
-except ImportError:
- create_subprocess_exec = None
+import sys
from portage.process import find_binary
from portage.tests import TestCase
from portage.util._eventloop.global_event_loop import global_event_loop
from portage.util.futures import asyncio
-from portage.util.futures.executor.fork import ForkExecutor
+from portage.util.futures._asyncio import create_subprocess_exec
+from portage.util.futures._asyncio.streams import _reader as reader
+from portage.util.futures.compat_coroutine import coroutine, coroutine_return
from portage.util.futures.unix_events import DefaultEventLoopPolicy
-from _emerge.PipeReader import PipeReader
-
-
-def reader(input_file, loop=None):
- """
- Asynchronously read a binary input file.
-
- @param input_file: binary input file
- @type input_file: file
- @param loop: event loop
- @type loop: EventLoop
- @return: bytes
- @rtype: asyncio.Future (or compatible)
- """
- loop = asyncio._wrap_loop(loop)
- future = loop.create_future()
- _Reader(future, input_file, loop)
- return future
-
-
-class _Reader(object):
- def __init__(self, future, input_file, loop):
- self._future = future
- self._pipe_reader = PipeReader(
- input_files={'input_file':input_file}, scheduler=loop)
-
- self._future.add_done_callback(self._cancel_callback)
- self._pipe_reader.addExitListener(self._eof)
- self._pipe_reader.start()
-
- def _cancel_callback(self, future):
- if future.cancelled():
- self._cancel()
-
- def _eof(self, pipe_reader):
- self._pipe_reader = None
- self._future.set_result(pipe_reader.getvalue())
-
- def _cancel(self):
- if self._pipe_reader is not None and self._pipe_reader.poll()
is None:
- self._pipe_reader.removeExitListener(self._eof)
- self._pipe_reader.cancel()
- self._pipe_reader = None
class SubprocessExecTestCase(TestCase):
@@ -76,99 +31,66 @@ class SubprocessExecTestCase(TestCase):
self.assertFalse(global_event_loop().is_closed())
def testEcho(self):
- if create_subprocess_exec is None:
- self.skipTest('create_subprocess_exec not implemented
for python2')
-
args_tuple = (b'hello', b'world')
echo_binary = find_binary("echo")
self.assertNotEqual(echo_binary, None)
echo_binary = echo_binary.encode()
- # Use os.pipe(), since this loop does not implement the
- # ReadTransport necessary for subprocess.PIPE support.
- stdout_pr, stdout_pw = os.pipe()
- stdout_pr = os.fdopen(stdout_pr, 'rb', 0)
- stdout_pw = os.fdopen(stdout_pw, 'wb', 0)
- files = [stdout_pr, stdout_pw]
-
def test(loop):
- output = None
- try:
- with open(os.devnull, 'rb', 0) as devnull:
- proc = loop.run_until_complete(
- create_subprocess_exec(
- echo_binary, *args_tuple,
- stdin=devnull,