From d057d91f391981fb0564873c471d550f2f62edf5 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Mon, 22 Jun 2009 16:43:52 +0000 Subject: Bug #275047 - Split _emerge/__init__.py into smaller pieces. Thanks to Sebastian Mingramm (few) for this patch. svn path=/main/trunk/; revision=13663 --- pym/_emerge/PipeReader.py | 98 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 pym/_emerge/PipeReader.py (limited to 'pym/_emerge/PipeReader.py') diff --git a/pym/_emerge/PipeReader.py b/pym/_emerge/PipeReader.py new file mode 100644 index 000000000..4b2e2f141 --- /dev/null +++ b/pym/_emerge/PipeReader.py @@ -0,0 +1,98 @@ +from _emerge.AbstractPollTask import AbstractPollTask +from _emerge.PollConstants import PollConstants +import sys +import os +import fcntl +import array +class PipeReader(AbstractPollTask): + + """ + Reads output from one or more files and saves it in memory, + for retrieval via the getvalue() method. This is driven by + the scheduler's poll() loop, so it runs entirely within the + current process. + """ + + __slots__ = ("input_files",) + \ + ("_read_data", "_reg_ids") + + def _start(self): + self._reg_ids = set() + self._read_data = [] + for k, f in self.input_files.iteritems(): + 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 = True + + def isAlive(self): + return self._registered + + def cancel(self): + if self.returncode is None: + self.returncode = 1 + self.cancelled = True + self.wait() + + def _wait(self): + if self.returncode is not None: + return self.returncode + + if self._registered: + self.scheduler.schedule(self._reg_ids) + self._unregister() + + self.returncode = os.EX_OK + return self.returncode + + def getvalue(self): + """Retrieve the entire contents""" + if sys.hexversion >= 0x3000000: + return bytes().join(self._read_data) + return "".join(self._read_data) + + def close(self): + """Free the memory buffer.""" + self._read_data = None + + def _output_handler(self, fd, event): + + if event & PollConstants.POLLIN: + + for f in self.input_files.itervalues(): + if fd == f.fileno(): + break + + buf = array.array('B') + try: + buf.fromfile(f, self._bufsize) + except EOFError: + pass + + if buf: + self._read_data.append(buf.tostring()) + else: + self._unregister() + self.wait() + + self._unregister_if_appropriate(event) + return self._registered + + def _unregister(self): + """ + Unregister from the scheduler and close open files. + """ + + self._registered = False + + if self._reg_ids is not None: + for reg_id in self._reg_ids: + self.scheduler.unregister(reg_id) + self._reg_ids = None + + if self.input_files is not None: + for f in self.input_files.itervalues(): + f.close() + self.input_files = None + -- cgit v1.2.3-1-g7c22