From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from pigeon.gentoo.org ([208.92.234.80] helo=lists.gentoo.org) by finch.gentoo.org with esmtp (Exim 4.60) (envelope-from ) id 1RbflP-0003zB-AJ for garchives@archives.gentoo.org; Fri, 16 Dec 2011 21:56:23 +0000 Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 08F1821C0C7; Fri, 16 Dec 2011 21:56:15 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) by pigeon.gentoo.org (Postfix) with ESMTP id B553F21C0C7 for ; Fri, 16 Dec 2011 21:56:15 +0000 (UTC) Received: from pelican.gentoo.org (unknown [66.219.59.40]) (using TLSv1 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 23DD71B4047 for ; Fri, 16 Dec 2011 21:56:15 +0000 (UTC) Received: from localhost.localdomain (localhost [127.0.0.1]) by pelican.gentoo.org (Postfix) with ESMTP id 5C4848004A for ; Fri, 16 Dec 2011 21:56:14 +0000 (UTC) From: "Zac Medico" To: gentoo-commits@lists.gentoo.org Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Zac Medico" Message-ID: <47247149a48d8b4267ad849ff10924e7b6a6f3e2.zmedico@gentoo> Subject: [gentoo-commits] proj/portage:master commit in: pym/portage/tests/process/, pym/_emerge/ X-VCS-Repository: proj/portage X-VCS-Files: pym/_emerge/AbstractPollTask.py pym/_emerge/PipeReader.py pym/portage/tests/process/test_poll.py X-VCS-Directories: pym/portage/tests/process/ pym/_emerge/ X-VCS-Committer: zmedico X-VCS-Committer-Name: Zac Medico X-VCS-Revision: 47247149a48d8b4267ad849ff10924e7b6a6f3e2 Date: Fri, 16 Dec 2011 21:56:14 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: quoted-printable X-Archives-Salt: 98eca71d-e03c-43e6-ad50-d8833061291a X-Archives-Hash: 2ee610ec8670172f5ff7b12635cd8e79 commit: 47247149a48d8b4267ad849ff10924e7b6a6f3e2 Author: Zac Medico gentoo org> AuthorDate: Fri Dec 16 21:56:03 2011 +0000 Commit: Zac Medico gentoo org> CommitDate: Fri Dec 16 21:56:03 2011 +0000 URL: http://git.overlays.gentoo.org/gitweb/?p=3Dproj/portage.git;a= =3Dcommit;h=3D47247149 test_poll: fix array test Since SpawnProcess no longer uses array, add conditional array support to PipeReader and use that for tests. --- pym/_emerge/AbstractPollTask.py | 49 +++++++++++++++++++ pym/_emerge/PipeReader.py | 29 ++++++++++- pym/portage/tests/process/test_poll.py | 82 ++++++++------------------= ------ 3 files changed, 96 insertions(+), 64 deletions(-) diff --git a/pym/_emerge/AbstractPollTask.py b/pym/_emerge/AbstractPollTa= sk.py index b3c0b2d..83e6c7b 100644 --- a/pym/_emerge/AbstractPollTask.py +++ b/pym/_emerge/AbstractPollTask.py @@ -1,6 +1,7 @@ # Copyright 1999-2011 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 =20 +import array import errno import logging import os @@ -21,6 +22,54 @@ class AbstractPollTask(AsynchronousTask): def isAlive(self): return bool(self._registered) =20 + def _read_array(self, f, event): + """ + NOTE: array.fromfile() is used here only for testing purposes, + because it has bugs in all known versions of Python (including + Python 2.7 and Python 3.2). + + | POLLIN | RETURN + | BIT | VALUE + | --------------------------------------------------- + | 1 | Read self._bufsize into an instance of + | | array.array('B') and return it, ignoring + | | EOFError and IOError. An empty array + | | indicates EOF. + | --------------------------------------------------- + | 0 | None + """ + buf =3D None + if event & PollConstants.POLLIN: + buf =3D array.array('B') + try: + buf.fromfile(f, self._bufsize) + except EOFError: + pass + except TypeError: + # Python 3.2: + # TypeError: read() didn't return bytes + pass + except IOError as e: + # EIO happens with pty on Linux after the + # slave end of the pty has been closed. + if e.errno =3D=3D errno.EIO: + # EOF: return empty string of bytes + pass + elif e.errno =3D=3D errno.EAGAIN: + # EAGAIN: return None + buf =3D None + else: + raise + + if buf is not None: + try: + # Python >=3D3.2 + buf =3D buf.tobytes() + except AttributeError: + buf =3D buf.tostring() + + return buf + def _read_buf(self, fd, event): """ | POLLIN | RETURN diff --git a/pym/_emerge/PipeReader.py b/pym/_emerge/PipeReader.py index 9fedbff..b162fe5 100644 --- a/pym/_emerge/PipeReader.py +++ b/pym/_emerge/PipeReader.py @@ -15,16 +15,22 @@ class PipeReader(AbstractPollTask): """ =20 __slots__ =3D ("input_files",) + \ - ("_read_data", "_reg_ids") + ("_read_data", "_reg_ids", "_use_array") =20 def _start(self): self._reg_ids =3D set() self._read_data =3D [] + + if self._use_array: + output_handler =3D self._array_output_handler + else: + output_handler =3D self._output_handler + for k, f in self.input_files.items(): fcntl.fcntl(f.fileno(), fcntl.F_SETFL, fcntl.fcntl(f.fileno(), fcntl.F_GETFL) | os.O_NONBLOCK) self._reg_ids.add(self.scheduler.register(f.fileno(), - self._registered_events, self._output_handler)) + self._registered_events, output_handler)) self._registered =3D True =20 def isAlive(self): @@ -68,6 +74,25 @@ class PipeReader(AbstractPollTask): =20 self._unregister_if_appropriate(event) =20 + def _array_output_handler(self, fd, event): + + for f in self.input_files.values(): + if f.fileno() =3D=3D fd: + break + + while True: + data =3D self._read_array(f, event) + if data is None: + break + if data: + self._read_data.append(data) + else: + self._unregister() + self.wait() + break + + self._unregister_if_appropriate(event) + def _unregister(self): """ Unregister from the scheduler and close open files. diff --git a/pym/portage/tests/process/test_poll.py b/pym/portage/tests/p= rocess/test_poll.py index 9b1f9cb..f1ddcb3 100644 --- a/pym/portage/tests/process/test_poll.py +++ b/pym/portage/tests/process/test_poll.py @@ -1,8 +1,6 @@ # Copyright 1998-2011 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 =20 -import tempfile - from portage import os from portage.tests import TestCase from portage.util._pty import _create_pty_or_pipe @@ -10,15 +8,10 @@ from _emerge.PollScheduler import PollScheduler from _emerge.PipeReader import PipeReader from _emerge.SpawnProcess import SpawnProcess =20 -class _SpawnProcessPty(SpawnProcess): - __slots__ =3D ("got_pty",) - def _pipe(self, fd_pipes): - got_pty, master_fd, slave_fd =3D _create_pty_or_pipe() - self.got_pty =3D got_pty - return (master_fd, slave_fd) - class PipeReaderTestCase(TestCase): =20 + _use_array =3D False + def _testPipeReader(self, test_string, use_pty): """ Use a poll loop to read data from a pipe and assert that @@ -43,7 +36,7 @@ class PipeReaderTestCase(TestCase): =20 consumer =3D PipeReader( input_files=3D{"producer" : master_file}, - scheduler=3Dscheduler) + scheduler=3Dscheduler, _use_array=3Dself._use_array) =20 consumer.start() =20 @@ -58,57 +51,22 @@ class PipeReaderTestCase(TestCase): output =3D consumer.getvalue().decode('ascii', 'replace') return (output, got_pty) =20 - def _testPipeReaderArray(self, test_string, use_pty): - """ - Use a poll loop to read data from a pipe and assert that - the data written to the pipe is identical to the data - read from the pipe. - """ - - scheduler =3D PollScheduler().sched_iface - if use_pty: - spawn_process =3D _SpawnProcessPty - else: - spawn_process =3D SpawnProcess - - fd, logfile =3D tempfile.mkstemp() - os.close(fd) - producer =3D spawn_process( - background=3DTrue, - args=3D["bash", "-c", "echo -n '%s'" % test_string], - env=3Dos.environ, - scheduler=3Dscheduler, logfile=3Dlogfile) - - try: - producer.start() - scheduler.schedule() - self.assertEqual(producer.returncode, os.EX_OK) - - if use_pty: - got_pty =3D producer.got_pty - else: - got_pty =3D False - - with open(logfile, 'rb') as f: - output =3D f.read().decode('ascii') - return (output, got_pty) - finally: - try: - os.unlink(logfile) - except OSError: - pass - def testPipeReader(self): for use_pty in (False, True): - for use_array in (False, True): - for x in (1, 2, 5, 6, 7, 8, 2**5, 2**10, 2**12, 2**13, 2**14): - test_string =3D x * "a" - if use_array: - method =3D self._testPipeReaderArray - else: - method =3D self._testPipeReader - output, got_pty =3D method(test_string, use_pty) - self.assertEqual(test_string, output, - "x =3D %s, len(output) =3D %s, use_array =3D %s, " - "use_pty =3D %s, got_pty =3D %s" % - (x, len(output), use_array, use_pty, got_pty)) + for x in (1, 2, 5, 6, 7, 8, 2**5, 2**10, 2**12, 2**13, 2**14): + test_string =3D x * "a" + output, got_pty =3D self._testPipeReader(test_string, use_pty) + self.assertEqual(test_string, output, + "x =3D %s, len(output) =3D %s, " + "use_pty =3D %s, got_pty =3D %s" % + (x, len(output), use_pty, got_pty)) + +class PipeReaderArrayTestCase(PipeReaderTestCase): + + _use_array =3D True + + def __init__(self, *args, **kwargs): + super(PipeReaderArrayTestCase, self).__init__(*args, **kwargs) + # http://bugs.python.org/issue5380 + # https://bugs.pypy.org/issue956 + self.todo =3D True