Esempio n. 1
0
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
Esempio n. 3
0
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
Esempio n. 8
0
    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():
Esempio n. 9
0
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")