def test_log(tmpdir): from robotframework_ls.robotframework_log import get_logger from robotframework_ls.robotframework_log import configure_logger from robotframework_ls._utils import wait_for_condition somedir = str(tmpdir.join("somedir")) configure_logger("test", 2, os.path.join(somedir, "foo.log")) log = get_logger("my_logger") log.info("something\nfoo\nbar") try: raise AssertionError("someerror") except: log.exception("rara: %s - %s", "str1", "str2") def get_log_files(): log_files = [ x for x in os.listdir(somedir) if x.startswith("foo") and x.endswith(".log") ] return log_files if log_files else None wait_for_condition(get_log_files, msg=lambda: "Found: %s in %s" % (get_log_files(), somedir)) log_files = get_log_files() with open(os.path.join(somedir, log_files[0]), "r") as stream: contents = stream.read() assert "someerror" in contents assert "something" in contents assert "rara" in contents assert "rara: str1 - str2" in contents
def start_server_process(args=(), python_exe=None, env=None): """ Calls this __main__ in another process. :param args: The list of arguments for the server process. i.e.: ["-vv", "--log-file=%s" % log_file] """ from robotframework_ls.robotframework_log import get_logger from robotframework_ls.subprocess_wrapper import subprocess import threading from robotframework_ls.options import Setup log = get_logger(__name__) if python_exe: if not os.path.exists(python_exe): raise RuntimeError("Expected %s to exist" % (python_exe, )) args = [python_exe or sys.executable, "-u", __file__] + list(args) log.debug('Starting server api process with args: "%s"' % ('" "'.join(args), )) environ = os.environ.copy() environ.pop("PYTHONPATH", "") environ.pop("PYTHONHOME", "") environ.pop("VIRTUAL_ENV", "") if env is not None: for key, val in env.items(): environ[key] = val environ["PYTHONIOENCODING"] = "utf-8" environ["PYTHONUNBUFFERED"] = "1" env_log = ["Environ:"] for key, val in environ.items(): env_log.append(" %s=%s" % (key, val)) if Setup.options.DEBUG_PROCESS_ENVIRON: log.debug("\n".join(env_log)) language_server_process = subprocess.Popen( args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, env=environ, bufsize=0, ) t = threading.Thread(target=_stderr_reader, args=(language_server_process.stderr, )) t.setName("Stderr from ServerAPI (%s)" % (args, )) t.setDaemon(True) t.start() return language_server_process
def main(args=None, after_bind=lambda server: None, language_server_class=None): original_args = args if args is not None else sys.argv[1:] try: import robotframework_ls except ImportError: # Automatically add it to the path if __main__ is being executed. sys.path.append( os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import robotframework_ls # @UnusedImport from robotframework_ls.options import Setup, Options from robotframework_ls.robotframework_log import ( configure_logger, log_args_and_python, ) from robotframework_ls.robotframework_log import get_logger from robotframework_ls.python_ls import ( start_io_lang_server, start_tcp_lang_server, binary_stdio, ) if language_server_class is None: from robotframework_ls.robotframework_ls_impl import ( RobotFrameworkLanguageServer, ) language_server_class = RobotFrameworkLanguageServer parser = argparse.ArgumentParser() add_arguments(parser) args = parser.parse_args(args=original_args) Setup.options = Options(args) verbose = args.verbose log_file = args.log_file or "" configure_logger("lsp", verbose, log_file) log = get_logger("robotframework_ls.__main__") log_args_and_python(log, original_args) if args.tcp: start_tcp_lang_server(args.host, args.port, language_server_class, after_bind=after_bind) else: stdin, stdout = binary_stdio() start_io_lang_server(stdin, stdout, language_server_class)
def main(): try: import robotframework_ls except ImportError: # Automatically add it to the path if __main__ is being executed. sys.path.append( os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import robotframework_ls # @UnusedImport from robotframework_ls.robotframework_log import ( configure_logger, log_args_and_python, ) from robotframework_ls.robotframework_log import get_logger configure_logger("robot") log = get_logger("robotframework_debug_adapter.run_robot__main__.py") log_args_and_python(log, sys.argv) from robotframework_ls.options import DEFAULT_TIMEOUT args = sys.argv[1:] assert args[0] == "--port" port = args[1] robot_args = args[2:] s = connect(int(port)) processor = _DAPCommandProcessor(s) processor.start_communication_threads() if not processor.configuration_done.wait(DEFAULT_TIMEOUT): sys.stderr.write( "Process not configured for launch in the available timeout.\n") sys.exit(1) try: from robot import run_cli exitcode = run_cli(robot_args, exit=False) finally: processor.terminate() if processor.terminated.wait(2): log.debug("Processed dap terminate event in robot.") sys.exit(exitcode)
def _stderr_reader(stream): from robotframework_ls.constants import IS_PY2 from robotframework_ls.robotframework_log import get_logger log = get_logger(__name__) try: while True: line = stream.readline() if IS_PY2: sys.stderr.write(line) else: sys.stderr.buffer.write(line) if not line: break except: log.exception("Error reading from server api process stream.") finally: log.debug("Finished reading from server api process stream.")
def process_message(self, protocol_message): from robotframework_ls.robotframework_log import get_logger from robotframework_debug_adapter.constants import DEBUG from robotframework_debug_adapter.debug_adapter_threads import ( READER_THREAD_STOPPED, ) log = get_logger("robotframework_debug_adapter.run_robot__main__.py") if protocol_message is READER_THREAD_STOPPED: if DEBUG: log.debug("_DAPCommandProcessor: READER_THREAD_STOPPED.") return if DEBUG: log.debug("Process json: %s\n" % (json.dumps( protocol_message.to_dict(), indent=4, sort_keys=True), )) try: if protocol_message.type == "request": method_name = "on_%s_request" % (protocol_message.command, ) elif protocol_message.type == "event": method_name = "on_%s_event" % (protocol_message.event, ) else: if DEBUG: log.debug( "Unable to decide how to deal with protocol type: %s in _DAPCommandProcessor.\n" % (protocol_message.type, )) return on_request = getattr(self, method_name, None) if on_request is not None: on_request(protocol_message) else: if DEBUG: log.debug( "Unhandled: %s not available in CommandProcessor.\n" % (method_name, )) except: log.exception("Error")
def connect(port): from robotframework_ls.options import DEFAULT_TIMEOUT from robotframework_ls.impl.robot_lsp_constants import ENV_OPTION_ROBOT_DAP_TIMEOUT from robotframework_ls.robotframework_log import get_logger log = get_logger("robotframework_debug_adapter.run_robot__main__.py") # Set TCP keepalive on an open socket. # It activates after 1 second (TCP_KEEPIDLE,) of idleness, # then sends a keepalive ping once every 3 seconds (TCP_KEEPINTVL), # and closes the connection after 5 failed ping (TCP_KEEPCNT), or 15 seconds s = socket_module.socket(socket_module.AF_INET, socket_module.SOCK_STREAM) try: IPPROTO_TCP, SO_KEEPALIVE, TCP_KEEPIDLE, TCP_KEEPINTVL, TCP_KEEPCNT = ( socket_module.IPPROTO_TCP, socket_module.SO_KEEPALIVE, socket_module.TCP_KEEPIDLE, # @UndefinedVariable socket_module.TCP_KEEPINTVL, # @UndefinedVariable socket_module.TCP_KEEPCNT, # @UndefinedVariable ) s.setsockopt(socket_module.SOL_SOCKET, SO_KEEPALIVE, 1) s.setsockopt(IPPROTO_TCP, TCP_KEEPIDLE, 1) s.setsockopt(IPPROTO_TCP, TCP_KEEPINTVL, 3) s.setsockopt(IPPROTO_TCP, TCP_KEEPCNT, 5) except AttributeError: pass # May not be available everywhere. try: # 10 seconds default timeout timeout = int( os.environ.get(ENV_OPTION_ROBOT_DAP_TIMEOUT, DEFAULT_TIMEOUT)) s.settimeout(timeout) s.connect(("127.0.0.1", port)) s.settimeout(None) # no timeout after connected log.info("Connected.") return s except: log.exception("Could not connect to: %s", (port, )) raise
def as_str(s): if isinstance(s, unicode): return s.encode("utf-8", "replace") return s else: import pathlib def as_str(s): if isinstance(s, bytes): return s.decode("utf-8", "replace") return s log = get_logger(__name__) def debounce(interval_s, keyed_by=None): """Debounce calls to this function until interval_s seconds have passed.""" def wrapper(func): timers = {} lock = threading.Lock() @functools.wraps(func) def debounced(*args, **kwargs): call_args = inspect.getcallargs(func, *args, **kwargs) key = call_args[keyed_by] if keyed_by else None def run():
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. """ log = None try: import sys try: import robotframework_debug_adapter except ImportError: # Automatically add it to the path if __main__ is being executed. sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import robotframework_debug_adapter # @UnusedImport from robotframework_debug_adapter.debug_adapter_threads import ( STOP_WRITER_THREAD, ) from robotframework_ls.robotframework_log import ( get_logger, configure_logger, log_args_and_python, ) import traceback configure_logger("dap") log = get_logger("robotframework_debug_adapter.__main__") log_args_and_python(log, sys.argv) from robotframework_debug_adapter.debug_adapter_threads import reader_thread from robotframework_debug_adapter.debug_adapter_threads import writer_thread from robotframework_debug_adapter.command_processor import CommandProcessor try: from queue import Queue except ImportError: from Queue import Queue write_queue = Queue() command_processor = CommandProcessor(write_queue) 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 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, "write to client"), name="Write to client", ) reader = threading.Thread( target=reader_thread, args=(read_from, command_processor, write_queue, b"read from client"), name="Read from client", ) reader.start() writer.start() reader.join() log.debug("Exited reader.\n") write_queue.put(STOP_WRITER_THREAD) writer.join() log.debug("Exited writer.\n") except: if log is not None: log.exception("Error") # Critical error (the logging may not be set up properly). # Print to file and stderr. with open(_critical_error_log_file, "a+") as stream: traceback.print_exc(file=stream) traceback.print_exc() finally: if log is not None: log.debug("Exited main.\n")