def writer_thread(stream, queue): try: while True: to_write = queue.get() to_json = getattr(to_write, 'to_json', None) if to_json is not None: # Some protocol message to_write.seq = _next_seq() try: to_write = to_json() except: debug_exception('Error serializing %s to json.' % (to_write, )) continue if DEBUG: debug('Writing: %s\n' % (to_write, )) if to_write.__class__ == bytes: as_bytes = to_write else: as_bytes = to_write.encode('utf-8') stream.write('Content-Length: %s\r\n\r\n' % (len(as_bytes))) stream.write(as_bytes) stream.flush() except: debug_exception()
def _notify_on_exited(process, on_exited): try: process.wait() if DEBUG: debug('notify process exited\n') on_exited() except: debug_exception()
def _read_stream(stream, on_line, category): try: while True: output = stream.readline() if len(output) == 0: break on_line(output, category) except: debug_exception()
def reader_thread(stream, process_command): try: while True: data = read(stream) if data is None: break protocol_message = base_schema.from_dict(data) process_command(protocol_message) except: debug_exception()
def main(): ''' Starts the debug adapter (creates a thread to read from stdin and another to write to stdout as expected by the vscode debug protocol). We pass the command processor to the reader thread as the idea is that the reader thread will read a message, convert it to an instance of the message in the schema and then forward it to the command processor which will interpret and act on it, posting the results to the writer queue. ''' try: import sys try: from queue import Queue except ImportError: from Queue import Queue write_queue = Queue() command_processor = CommandProcessor(write_queue) if DEBUG: debug('Starting. Args: %s\n' % (', '.join(sys.argv), )) write_to = sys.stdout read_from = sys.stdin if sys.version_info[0] <= 2: if sys.platform == "win32": # must read streams as binary on windows import os, msvcrt msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY) msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) else: # Py3 write_to = sys.stdout.buffer read_from = sys.stdin.buffer writer = threading.Thread(target=writer_thread, args=(write_to, write_queue)) reader = threading.Thread(target=reader_thread, args=(read_from, command_processor)) reader.start() writer.start() reader.join() writer.join() except: debug_exception() debug('exiting main.\n')
def send_to_stdin(self, expression): popen = self._popen if popen is not None: import threading try: debug('Sending: %s to stdin.' % (expression,)) def write_to_stdin(popen, expression): popen.stdin.write(expression) if not expression.endswith('\r') and not expression.endswith('\n'): popen.stdin.write('\n') popen.stdin.flush() # Do it in a thread (in theory the OS could have that filled up and we would never complete # trying to write -- although probably a bit far fetched, let's code as if that could actually happen). t = threading.Thread(target=write_to_stdin, args=(popen, expression)) t.setDaemon(True) t.start() except: debug_exception('Error writing: >>%s<< to stdin.' % (expression,))
def __call__(self, protocol_message): if DEBUG: debug('Process json: %s\n' % (json.dumps(protocol_message.to_dict(), indent=4, encoding='utf-8', sort_keys=True), )) try: if protocol_message.type == 'request': method_name = 'on_%s_request' % (protocol_message.command, ) on_request = getattr(self, method_name, None) if on_request is not None: on_request(protocol_message) else: if DEBUG: debug( 'Unhandled: %s not available in CommandProcessor.\n' % (method_name, )) except: debug_exception()
def from_dict(dct): msg_type = dct.get('type') if msg_type is None: raise ValueError('Unable to make sense of message: %s' % (dct, )) if msg_type == 'request': cls = _requests_to_types[dct['command']] try: return cls(**dct) except: msg = 'Error creating %s from %s' % (cls, dct) debug_exception(msg) raise ValueError(msg) elif msg_type == 'response': cls = _responses_to_types[dct['command']] try: return cls(**dct) except: msg = 'Error creating %s from %s' % (cls, dct) debug_exception(msg) raise ValueError(msg) raise ValueError('Unable to create message from dict: %s' % (dct, ))