| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  | import collections | 
					
						
							|  |  |  | import subprocess | 
					
						
							| 
									
										
										
										
											2015-01-29 17:50:58 +01:00
										 |  |  | import warnings | 
					
						
							| 
									
										
										
										
											2024-07-01 10:17:36 +05:30
										 |  |  | import os | 
					
						
							|  |  |  | import signal | 
					
						
							|  |  |  | import sys | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | from . import protocols | 
					
						
							|  |  |  | from . import transports | 
					
						
							| 
									
										
										
										
											2014-07-14 18:33:40 +02:00
										 |  |  | from .log import logger | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class BaseSubprocessTransport(transports.SubprocessTransport): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, loop, protocol, args, shell, | 
					
						
							|  |  |  |                  stdin, stdout, stderr, bufsize, | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  |                  waiter=None, extra=None, **kwargs): | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  |         super().__init__(extra) | 
					
						
							| 
									
										
										
										
											2015-01-29 17:50:58 +01:00
										 |  |  |         self._closed = False | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  |         self._protocol = protocol | 
					
						
							|  |  |  |         self._loop = loop | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  |         self._proc = None | 
					
						
							| 
									
										
										
										
											2014-07-14 18:33:40 +02:00
										 |  |  |         self._pid = None | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  |         self._returncode = None | 
					
						
							|  |  |  |         self._exit_waiters = [] | 
					
						
							|  |  |  |         self._pending_calls = collections.deque() | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  |         self._pipes = {} | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  |         self._finished = False | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  |         if stdin == subprocess.PIPE: | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  |             self._pipes[0] = None | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  |         if stdout == subprocess.PIPE: | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  |             self._pipes[1] = None | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  |         if stderr == subprocess.PIPE: | 
					
						
							| 
									
										
										
										
											2014-02-01 22:49:59 +01:00
										 |  |  |             self._pipes[2] = None | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # Create the child process: set the _proc attribute | 
					
						
							| 
									
										
										
										
											2015-07-31 17:49:43 +02:00
										 |  |  |         try: | 
					
						
							|  |  |  |             self._start(args=args, shell=shell, stdin=stdin, stdout=stdout, | 
					
						
							|  |  |  |                         stderr=stderr, bufsize=bufsize, **kwargs) | 
					
						
							|  |  |  |         except: | 
					
						
							|  |  |  |             self.close() | 
					
						
							|  |  |  |             raise | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-14 18:33:40 +02:00
										 |  |  |         self._pid = self._proc.pid | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  |         self._extra['subprocess'] = self._proc | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-14 18:33:40 +02:00
										 |  |  |         if self._loop.get_debug(): | 
					
						
							|  |  |  |             if isinstance(args, (bytes, str)): | 
					
						
							|  |  |  |                 program = args | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 program = args[0] | 
					
						
							|  |  |  |             logger.debug('process %r created: pid %s', | 
					
						
							|  |  |  |                          program, self._pid) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  |         self._loop.create_task(self._connect_pipes(waiter)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-14 18:33:40 +02:00
										 |  |  |     def __repr__(self): | 
					
						
							| 
									
										
										
										
											2015-01-29 17:50:58 +01:00
										 |  |  |         info = [self.__class__.__name__] | 
					
						
							|  |  |  |         if self._closed: | 
					
						
							|  |  |  |             info.append('closed') | 
					
						
							| 
									
										
										
										
											2015-03-10 16:32:29 +01:00
										 |  |  |         if self._pid is not None: | 
					
						
							| 
									
										
										
										
											2018-05-20 19:57:13 +02:00
										 |  |  |             info.append(f'pid={self._pid}') | 
					
						
							| 
									
										
										
										
											2014-07-14 18:33:40 +02:00
										 |  |  |         if self._returncode is not None: | 
					
						
							| 
									
										
										
										
											2017-12-10 18:36:12 -05:00
										 |  |  |             info.append(f'returncode={self._returncode}') | 
					
						
							| 
									
										
										
										
											2015-03-10 16:32:29 +01:00
										 |  |  |         elif self._pid is not None: | 
					
						
							| 
									
										
										
										
											2015-02-17 22:50:33 +01:00
										 |  |  |             info.append('running') | 
					
						
							| 
									
										
										
										
											2015-03-10 16:32:29 +01:00
										 |  |  |         else: | 
					
						
							|  |  |  |             info.append('not started') | 
					
						
							| 
									
										
										
										
											2014-07-14 18:33:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         stdin = self._pipes.get(0) | 
					
						
							|  |  |  |         if stdin is not None: | 
					
						
							| 
									
										
										
										
											2017-12-10 18:36:12 -05:00
										 |  |  |             info.append(f'stdin={stdin.pipe}') | 
					
						
							| 
									
										
										
										
											2014-07-14 18:33:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         stdout = self._pipes.get(1) | 
					
						
							|  |  |  |         stderr = self._pipes.get(2) | 
					
						
							|  |  |  |         if stdout is not None and stderr is stdout: | 
					
						
							| 
									
										
										
										
											2017-12-10 18:36:12 -05:00
										 |  |  |             info.append(f'stdout=stderr={stdout.pipe}') | 
					
						
							| 
									
										
										
										
											2014-07-14 18:33:40 +02:00
										 |  |  |         else: | 
					
						
							|  |  |  |             if stdout is not None: | 
					
						
							| 
									
										
										
										
											2017-12-10 18:36:12 -05:00
										 |  |  |                 info.append(f'stdout={stdout.pipe}') | 
					
						
							| 
									
										
										
										
											2014-07-14 18:33:40 +02:00
										 |  |  |             if stderr is not None: | 
					
						
							| 
									
										
										
										
											2017-12-10 18:36:12 -05:00
										 |  |  |                 info.append(f'stderr={stderr.pipe}') | 
					
						
							| 
									
										
										
										
											2014-07-14 18:33:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-10 18:36:12 -05:00
										 |  |  |         return '<{}>'.format(' '.join(info)) | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _start(self, args, shell, stdin, stdout, stderr, bufsize, **kwargs): | 
					
						
							|  |  |  |         raise NotImplementedError | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-11 21:11:02 -04:00
										 |  |  |     def set_protocol(self, protocol): | 
					
						
							|  |  |  |         self._protocol = protocol | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_protocol(self): | 
					
						
							|  |  |  |         return self._protocol | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-16 12:43:21 -05:00
										 |  |  |     def is_closing(self): | 
					
						
							|  |  |  |         return self._closed | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  |     def close(self): | 
					
						
							| 
									
										
										
										
											2015-01-30 01:20:44 +01:00
										 |  |  |         if self._closed: | 
					
						
							|  |  |  |             return | 
					
						
							| 
									
										
										
										
											2015-01-29 17:50:58 +01:00
										 |  |  |         self._closed = True | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  |         for proto in self._pipes.values(): | 
					
						
							| 
									
										
										
										
											2015-01-15 00:04:21 +01:00
										 |  |  |             if proto is None: | 
					
						
							|  |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  |             proto.pipe.close() | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-10 18:36:12 -05:00
										 |  |  |         if (self._proc is not None and | 
					
						
							|  |  |  |                 # has the child process finished? | 
					
						
							|  |  |  |                 self._returncode is None and | 
					
						
							|  |  |  |                 # the child process has finished, but the | 
					
						
							|  |  |  |                 # transport hasn't been notified yet? | 
					
						
							|  |  |  |                 self._proc.poll() is None): | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  |             if self._loop.get_debug(): | 
					
						
							|  |  |  |                 logger.warning('Close running child process: kill %r', self) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 self._proc.kill() | 
					
						
							| 
									
										
										
										
											2023-12-24 01:43:39 +01:00
										 |  |  |             except (ProcessLookupError, PermissionError): | 
					
						
							|  |  |  |                 # the process may have already exited or may be running setuid | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-30 01:20:44 +01:00
										 |  |  |             # Don't clear the _proc reference yet: _post_init() may still run | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 11:24:40 +01:00
										 |  |  |     def __del__(self, _warn=warnings.warn): | 
					
						
							| 
									
										
										
										
											2017-04-25 10:57:18 +09:00
										 |  |  |         if not self._closed: | 
					
						
							| 
									
										
										
										
											2019-01-10 11:24:40 +01:00
										 |  |  |             _warn(f"unclosed transport {self!r}", ResourceWarning, source=self) | 
					
						
							| 
									
										
										
										
											2017-04-25 10:57:18 +09:00
										 |  |  |             self.close() | 
					
						
							| 
									
										
										
										
											2015-01-29 17:50:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  |     def get_pid(self): | 
					
						
							| 
									
										
										
										
											2014-07-14 18:33:40 +02:00
										 |  |  |         return self._pid | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def get_returncode(self): | 
					
						
							|  |  |  |         return self._returncode | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_pipe_transport(self, fd): | 
					
						
							|  |  |  |         if fd in self._pipes: | 
					
						
							|  |  |  |             return self._pipes[fd].pipe | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  |     def _check_proc(self): | 
					
						
							|  |  |  |         if self._proc is None: | 
					
						
							|  |  |  |             raise ProcessLookupError() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-01 10:17:36 +05:30
										 |  |  |     if sys.platform == 'win32': | 
					
						
							|  |  |  |         def send_signal(self, signal): | 
					
						
							|  |  |  |             self._check_proc() | 
					
						
							|  |  |  |             self._proc.send_signal(signal) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def terminate(self): | 
					
						
							|  |  |  |             self._check_proc() | 
					
						
							|  |  |  |             self._proc.terminate() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def kill(self): | 
					
						
							|  |  |  |             self._check_proc() | 
					
						
							|  |  |  |             self._proc.kill() | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         def send_signal(self, signal): | 
					
						
							|  |  |  |             self._check_proc() | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 os.kill(self._proc.pid, signal) | 
					
						
							|  |  |  |             except ProcessLookupError: | 
					
						
							|  |  |  |                 pass | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-01 10:17:36 +05:30
										 |  |  |         def terminate(self): | 
					
						
							|  |  |  |             self.send_signal(signal.SIGTERM) | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-01 10:17:36 +05:30
										 |  |  |         def kill(self): | 
					
						
							|  |  |  |             self.send_signal(signal.SIGKILL) | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |     async def _connect_pipes(self, waiter): | 
					
						
							| 
									
										
										
										
											2015-01-14 02:10:33 +01:00
										 |  |  |         try: | 
					
						
							|  |  |  |             proc = self._proc | 
					
						
							|  |  |  |             loop = self._loop | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-14 02:10:33 +01:00
										 |  |  |             if proc.stdin is not None: | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |                 _, pipe = await loop.connect_write_pipe( | 
					
						
							| 
									
										
										
										
											2015-01-14 02:10:33 +01:00
										 |  |  |                     lambda: WriteSubprocessPipeProto(self, 0), | 
					
						
							|  |  |  |                     proc.stdin) | 
					
						
							|  |  |  |                 self._pipes[0] = pipe | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-14 02:10:33 +01:00
										 |  |  |             if proc.stdout is not None: | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |                 _, pipe = await loop.connect_read_pipe( | 
					
						
							| 
									
										
										
										
											2015-01-14 02:10:33 +01:00
										 |  |  |                     lambda: ReadSubprocessPipeProto(self, 1), | 
					
						
							|  |  |  |                     proc.stdout) | 
					
						
							|  |  |  |                 self._pipes[1] = pipe | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-14 02:10:33 +01:00
										 |  |  |             if proc.stderr is not None: | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |                 _, pipe = await loop.connect_read_pipe( | 
					
						
							| 
									
										
										
										
											2015-01-14 02:10:33 +01:00
										 |  |  |                     lambda: ReadSubprocessPipeProto(self, 2), | 
					
						
							|  |  |  |                     proc.stderr) | 
					
						
							|  |  |  |                 self._pipes[2] = pipe | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             assert self._pending_calls is not None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  |             loop.call_soon(self._protocol.connection_made, self) | 
					
						
							| 
									
										
										
										
											2015-01-14 02:10:33 +01:00
										 |  |  |             for callback, data in self._pending_calls: | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  |                 loop.call_soon(callback, *data) | 
					
						
							| 
									
										
										
										
											2015-01-14 02:10:33 +01:00
										 |  |  |             self._pending_calls = None | 
					
						
							| 
									
										
										
										
											2019-05-27 14:45:12 +02:00
										 |  |  |         except (SystemExit, KeyboardInterrupt): | 
					
						
							|  |  |  |             raise | 
					
						
							|  |  |  |         except BaseException as exc: | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  |             if waiter is not None and not waiter.cancelled(): | 
					
						
							|  |  |  |                 waiter.set_exception(exc) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             if waiter is not None and not waiter.cancelled(): | 
					
						
							|  |  |  |                 waiter.set_result(None) | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _call(self, cb, *data): | 
					
						
							|  |  |  |         if self._pending_calls is not None: | 
					
						
							|  |  |  |             self._pending_calls.append((cb, data)) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self._loop.call_soon(cb, *data) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _pipe_connection_lost(self, fd, exc): | 
					
						
							|  |  |  |         self._call(self._protocol.pipe_connection_lost, fd, exc) | 
					
						
							|  |  |  |         self._try_finish() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _pipe_data_received(self, fd, data): | 
					
						
							|  |  |  |         self._call(self._protocol.pipe_data_received, fd, data) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _process_exited(self, returncode): | 
					
						
							|  |  |  |         assert returncode is not None, returncode | 
					
						
							|  |  |  |         assert self._returncode is None, self._returncode | 
					
						
							| 
									
										
										
										
											2014-07-14 18:33:40 +02:00
										 |  |  |         if self._loop.get_debug(): | 
					
						
							| 
									
										
										
										
											2017-12-10 18:36:12 -05:00
										 |  |  |             logger.info('%r exited with return code %r', self, returncode) | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  |         self._returncode = returncode | 
					
						
							| 
									
										
										
										
											2016-05-20 13:05:48 +02:00
										 |  |  |         if self._proc.returncode is None: | 
					
						
							|  |  |  |             # asyncio uses a child watcher: copy the status into the Popen | 
					
						
							|  |  |  |             # object. On Python 3.6, it is required to avoid a ResourceWarning. | 
					
						
							|  |  |  |             self._proc.returncode = returncode | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  |         self._call(self._protocol.process_exited) | 
					
						
							| 
									
										
										
										
											2022-10-06 22:48:19 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  |         self._try_finish() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |     async def _wait(self): | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  |         """Wait until the process exit and return the process return code.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         This method is a coroutine."""
 | 
					
						
							|  |  |  |         if self._returncode is not None: | 
					
						
							|  |  |  |             return self._returncode | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-16 15:38:39 -04:00
										 |  |  |         waiter = self._loop.create_future() | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  |         self._exit_waiters.append(waiter) | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |         return await waiter | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  |     def _try_finish(self): | 
					
						
							|  |  |  |         assert not self._finished | 
					
						
							|  |  |  |         if self._returncode is None: | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         if all(p is not None and p.disconnected | 
					
						
							|  |  |  |                for p in self._pipes.values()): | 
					
						
							|  |  |  |             self._finished = True | 
					
						
							| 
									
										
										
										
											2014-12-18 23:47:27 +01:00
										 |  |  |             self._call(self._call_connection_lost, None) | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _call_connection_lost(self, exc): | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             self._protocol.connection_lost(exc) | 
					
						
							|  |  |  |         finally: | 
					
						
							| 
									
										
										
										
											2022-10-05 22:45:31 +05:30
										 |  |  |             # wake up futures waiting for wait() | 
					
						
							|  |  |  |             for waiter in self._exit_waiters: | 
					
						
							|  |  |  |                 if not waiter.cancelled(): | 
					
						
							|  |  |  |                     waiter.set_result(self._returncode) | 
					
						
							|  |  |  |             self._exit_waiters = None | 
					
						
							| 
									
										
										
										
											2015-01-30 00:05:19 +01:00
										 |  |  |             self._loop = None | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  |             self._proc = None | 
					
						
							|  |  |  |             self._protocol = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class WriteSubprocessPipeProto(protocols.BaseProtocol): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, proc, fd): | 
					
						
							|  |  |  |         self.proc = proc | 
					
						
							|  |  |  |         self.fd = fd | 
					
						
							| 
									
										
										
										
											2014-01-29 14:22:56 -08:00
										 |  |  |         self.pipe = None | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  |         self.disconnected = False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def connection_made(self, transport): | 
					
						
							|  |  |  |         self.pipe = transport | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-14 18:33:40 +02:00
										 |  |  |     def __repr__(self): | 
					
						
							| 
									
										
										
										
											2017-12-10 18:36:12 -05:00
										 |  |  |         return f'<{self.__class__.__name__} fd={self.fd} pipe={self.pipe!r}>' | 
					
						
							| 
									
										
										
										
											2014-07-14 18:33:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  |     def connection_lost(self, exc): | 
					
						
							|  |  |  |         self.disconnected = True | 
					
						
							|  |  |  |         self.proc._pipe_connection_lost(self.fd, exc) | 
					
						
							| 
									
										
										
										
											2015-01-09 21:34:27 +01:00
										 |  |  |         self.proc = None | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-29 14:28:15 -08:00
										 |  |  |     def pause_writing(self): | 
					
						
							|  |  |  |         self.proc._protocol.pause_writing() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def resume_writing(self): | 
					
						
							|  |  |  |         self.proc._protocol.resume_writing() | 
					
						
							| 
									
										
										
										
											2013-10-30 14:56:49 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ReadSubprocessPipeProto(WriteSubprocessPipeProto, | 
					
						
							|  |  |  |                               protocols.Protocol): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def data_received(self, data): | 
					
						
							|  |  |  |         self.proc._pipe_data_received(self.fd, data) |