Package _emerge :: Module PipeReader
[hide private]

Source Code for Module _emerge.PipeReader

  1  # Copyright 1999-2013 Gentoo Foundation 
  2  # Distributed under the terms of the GNU General Public License v2 
  3   
  4  from portage import os 
  5  from _emerge.AbstractPollTask import AbstractPollTask 
  6  import fcntl 
  7   
8 -class PipeReader(AbstractPollTask):
9 10 """ 11 Reads output from one or more files and saves it in memory, 12 for retrieval via the getvalue() method. This is driven by 13 the scheduler's poll() loop, so it runs entirely within the 14 current process. 15 """ 16 17 __slots__ = ("input_files",) + \ 18 ("_read_data", "_reg_ids", "_use_array") 19
20 - def _start(self):
21 self._reg_ids = set() 22 self._read_data = [] 23 24 if self._use_array: 25 output_handler = self._array_output_handler 26 else: 27 output_handler = self._output_handler 28 29 fcntl_flags = os.O_NONBLOCK 30 try: 31 fcntl.FD_CLOEXEC 32 except AttributeError: 33 pass 34 else: 35 fcntl_flags |= fcntl.FD_CLOEXEC 36 37 for f in self.input_files.values(): 38 fd = isinstance(f, int) and f or f.fileno() 39 fcntl.fcntl(fd, fcntl.F_SETFL, 40 fcntl.fcntl(fd, fcntl.F_GETFL) | fcntl_flags) 41 self._reg_ids.add(self.scheduler.io_add_watch(fd, 42 self._registered_events, output_handler)) 43 self._registered = True
44
45 - def _cancel(self):
46 self._unregister() 47 if self.returncode is None: 48 self.returncode = self._cancelled_returncode
49
50 - def _wait(self):
51 if self.returncode is not None: 52 return self.returncode 53 self._wait_loop() 54 self.returncode = os.EX_OK 55 return self.returncode
56
57 - def getvalue(self):
58 """Retrieve the entire contents""" 59 return b''.join(self._read_data)
60
61 - def close(self):
62 """Free the memory buffer.""" 63 self._read_data = None
64
65 - def _output_handler(self, fd, event):
66 67 while True: 68 data = self._read_buf(fd, event) 69 if data is None: 70 break 71 if data: 72 self._read_data.append(data) 73 else: 74 self._unregister() 75 self.wait() 76 break 77 78 self._unregister_if_appropriate(event) 79 80 return True
81
82 - def _array_output_handler(self, fd, event):
83 84 for f in self.input_files.values(): 85 if f.fileno() == fd: 86 break 87 88 while True: 89 data = self._read_array(f, event) 90 if data is None: 91 break 92 if data: 93 self._read_data.append(data) 94 else: 95 self._unregister() 96 self.wait() 97 break 98 99 self._unregister_if_appropriate(event) 100 101 return True
102
103 - def _unregister(self):
104 """ 105 Unregister from the scheduler and close open files. 106 """ 107 108 self._registered = False 109 110 if self._reg_ids is not None: 111 for reg_id in self._reg_ids: 112 self.scheduler.source_remove(reg_id) 113 self._reg_ids = None 114 115 if self.input_files is not None: 116 for f in self.input_files.values(): 117 if isinstance(f, int): 118 os.close(f) 119 else: 120 f.close() 121 self.input_files = None
122