<s> import sys <EOL> import signal <EOL> from ssl import SSLError <EOL> from harpoon . dockerpty import io <EOL> from harpoon . dockerpty import tty <EOL> class WINCHHandler ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , pty ) : <EOL> """<STR_LIT>""" <EOL> self . pty = pty <EOL> self . original_handler = None <EOL> def __enter__ ( self ) : <EOL> """<STR_LIT>""" <EOL> self . start ( ) <EOL> return self <EOL> def __exit__ ( self , * _ ) : <EOL> """<STR_LIT>""" <EOL> self . stop ( ) <EOL> def start ( self ) : <EOL> """<STR_LIT>""" <EOL> def handle ( signum , frame ) : <EOL> if signum == signal . SIGWINCH : <EOL> self . pty . resize ( ) <EOL> self . original_handler = signal . signal ( signal . SIGWINCH , handle ) <EOL> def stop ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . original_handler is not None : <EOL> signal . signal ( signal . SIGWINCH , self . original_handler ) <EOL> class PseudoTerminal ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , client , container , interactive = True , stdout = None , stderr = None , stdin = None ) : <EOL> """<STR_LIT>""" <EOL> self . client = client <EOL> self . container = container <EOL> self . raw = None <EOL> self . interactive = interactive <EOL> self . stdout = stdout or sys . stdout <EOL> self . stderr = stderr or sys . stderr <EOL> self . stdin = stdin or sys . stdin <EOL> def start ( self , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> pty_stdin , pty_stdout , pty_stderr = self . sockets ( ) <EOL> pumps = [ ] <EOL> if pty_stdin and self . interactive : <EOL> pumps . append ( io . Pump ( io . Stream ( self . stdin ) , pty_stdin , wait_for_output = False ) ) <EOL> if pty_stdout : <EOL> pumps . append ( io . Pump ( pty_stdout , io . Stream ( self . stdout ) , propagate_close = False ) ) <EOL> if pty_stderr : <EOL> pumps . append ( io . Pump ( pty_stderr , io . Stream ( self . stderr ) , propagate_close = False ) ) <EOL> if not self . container_info ( ) [ '<STR_LIT>' ] [ '<STR_LIT>' ] : <EOL> self . client . start ( self . container , ** kwargs ) <EOL> flags = [ p . set_blocking ( False ) for p in pumps ] <EOL> try : <EOL> with WINCHHandler ( self ) : <EOL> self . _hijack_tty ( pumps ) <EOL> finally : <EOL> if flags : <EOL> for ( pump , flag ) in zip ( pumps , flags ) : <EOL> io . set_blocking ( pump , flag ) <EOL> def israw ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . raw is None : <EOL> info = self . container_info ( ) <EOL> self . raw = self . stdout . isatty ( ) and info [ '<STR_LIT>' ] [ '<STR_LIT>' ] <EOL> return self . raw <EOL> def sockets ( self ) : <EOL> """<STR_LIT>""" <EOL> info = self . container_info ( ) <EOL> def attach_socket ( key ) : <EOL> if info [ '<STR_LIT>' ] [ '<STR_LIT>' . format ( key . capitalize ( ) ) ] : <EOL> socket = self . client . attach_socket ( <EOL> self . container , <EOL> { key : <NUM_LIT:1> , '<STR_LIT>' : <NUM_LIT:1> , '<STR_LIT>' : <NUM_LIT:1> } , <EOL> ) <EOL> stream = io . Stream ( socket ) <EOL> if info [ '<STR_LIT>' ] [ '<STR_LIT>' ] : <EOL> return stream <EOL> else : <EOL> return io . Demuxer ( stream ) <EOL> else : <EOL> return None <EOL> return map ( attach_socket , ( '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ) ) <EOL> def resize ( self , size = None ) : <EOL> """<STR_LIT>""" <EOL> if not self . israw ( ) : <EOL> return <EOL> size = size or tty . size ( self . stdout ) <EOL> if size is not None : <EOL> rows , cols = size <EOL> try : <EOL> self . client . resize ( self . container , height = rows , width = cols ) <EOL> except IOError : <EOL> pass <EOL> def container_info ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . client . inspect_container ( self . container ) <EOL> def _hijack_tty ( self , pumps ) : <EOL> with tty . Terminal ( self . stdin , raw = self . israw ( ) ) : <EOL> self . resize ( ) <EOL> while True : <EOL> read_pumps = [ p for p in pumps if not p . eof ] <EOL> write_streams = [ p . to_stream for p in pumps if p . to_stream . needs_write ( ) ] <EOL> read_ready , write_ready = io . select ( read_pumps , write_streams , timeout = <NUM_LIT> ) <EOL> try : <EOL> for write_stream in write_ready : <EOL> write_stream . do_write ( ) <EOL> for pump in read_ready : <EOL> pump . flush ( ) <EOL> if all ( [ p . is_done ( ) for p in pumps ] ) : <EOL> break <EOL> except SSLError as e : <EOL> if '<STR_LIT>' not in e . strerror : <EOL> raise e </s>
