def server_process(tmpdir):
    import os.path
    from robotframework_ls._utils import kill_process_and_subprocesses
    from robotframework_ls.server_api.server__main__ import start_server_process

    log_file = str(tmpdir.join("robotframework_api_tests.log"))

    import robot

    env = {
        "PYTHONPATH":
        os.path.dirname(os.path.dirname(os.path.abspath(robot.__file__)))
    }

    language_server_api_process = start_server_process(
        args=["-vv", "--log-file=%s" % log_file], env=env)
    returncode = language_server_api_process.poll()
    assert returncode is None
    yield language_server_api_process
    returncode = language_server_api_process.poll()
    if returncode is None:
        kill_process_and_subprocesses(language_server_api_process.pid)

    if os.path.exists(log_file):
        print("--- %s contents:" % (log_file, ))
        with open(log_file, "r") as stream:
            print(stream.read())
def server_process(tmpdir, on_timeout, remote_fs_observer):
    from robocorp_ls_core.basic import kill_process_and_subprocesses
    from robotframework_ls.server_api.server__main__ import start_server_process

    log_file = str(tmpdir.join("robotframework_api_tests.log"))

    import robot

    env = {
        "PYTHONPATH":
        os.path.dirname(os.path.dirname(os.path.abspath(robot.__file__)))
    }

    language_server_api_process = start_server_process(
        args=[
            "-vv",
            "--log-file=%s" % log_file,
            f"--remote-fs-observer-port={remote_fs_observer.port}",
        ],
        env=env,
    )
    returncode = language_server_api_process.poll()
    assert returncode is None

    def write_on_finish():
        import sys

        dirname = os.path.dirname(log_file)
        for f in os.listdir(dirname):
            if f.startswith("robotframework_api_tests") and f.endswith(".log"):
                full = os.path.join(dirname, f)
                sys.stderr.write("\n--- %s contents:\n" % (full, ))
                with open(full, "r") as stream:
                    sys.stderr.write(stream.read())

    on_timeout.add(write_on_finish)

    yield language_server_api_process

    on_timeout.remove(write_on_finish)

    returncode = language_server_api_process.poll()
    if returncode is None:
        kill_process_and_subprocesses(language_server_api_process.pid)

    write_on_finish()
Exemple #3
0
    def get_robotframework_api_client(
            self) -> Optional[IRobotFrameworkApiClient]:
        self._check_in_main_thread()
        workspace = self.workspace
        assert (
            workspace
        ), "The workspace must be already set when getting the server api."

        server_process = self._server_process

        if server_process is not None:
            # If someone killed it, dispose of internal references
            # and create a new process.
            if not is_process_alive(server_process.pid):
                server_process = None
                self._dispose_server_process()

        if server_process is None:
            try:
                from robotframework_ls.options import Setup
                from robotframework_ls.server_api.client import RobotFrameworkApiClient
                from robotframework_ls.server_api.server__main__ import (
                    start_server_process, )
                from robocorp_ls_core.jsonrpc.streams import (
                    JsonRpcStreamWriter,
                    JsonRpcStreamReader,
                )

                args = []
                if Setup.options.verbose:
                    args.append("-" + "v" * int(Setup.options.verbose))
                if Setup.options.log_file:
                    log_id = _next_id()
                    # i.e.: use a log id in case we create more than one in the
                    # same session.
                    if log_id == 0:
                        args.append("--log-file=" + Setup.options.log_file +
                                    self._log_extension)
                    else:
                        args.append("--log-file=" + Setup.options.log_file +
                                    (".%s" % (log_id, )) + self._log_extension)

                python_exe = self._get_python_executable()
                environ = self._get_environ()

                self._used_python_executable = python_exe
                self._used_environ = environ

                server_process = start_server_process(args=args,
                                                      python_exe=python_exe,
                                                      env=environ)

                self._server_process = server_process

                write_to = server_process.stdin
                read_from = server_process.stdout
                w = JsonRpcStreamWriter(write_to, sort_keys=True)
                r = JsonRpcStreamReader(read_from)

                api = self._robotframework_api_client = RobotFrameworkApiClient(
                    w, r, server_process)

                log.debug(
                    "Initializing api... (this pid: %s, api pid: %s).",
                    os.getpid(),
                    server_process.pid,
                )
                api.initialize(
                    process_id=os.getpid(),
                    root_uri=workspace.root_uri,
                    workspace_folders=list({
                        "uri": folder.uri,
                        "name": folder.name
                    } for folder in workspace.iter_folders()),
                )

                config = self._config
                log.debug("Forwarding config to api...")
                if config is not None:
                    api.forward(
                        "workspace/didChangeConfiguration",
                        {"settings": config.get_full_settings()},
                    )

                # Open existing documents in the API.
                source: Optional[str]
                for document in workspace.iter_documents():
                    log.debug("Forwarding doc: %s to api...", document.uri)
                    try:
                        source = document.source
                    except Exception:
                        source = None

                    api.forward(
                        "textDocument/didOpen",
                        {
                            "textDocument": {
                                "uri": document.uri,
                                "version": document.version,
                                "text": source,
                            }
                        },
                    )

            except Exception as e:
                if server_process is None:
                    log.exception(
                        "Error starting robotframework server api (server_process=None)."
                    )
                else:
                    exitcode = server_process.poll()
                    if exitcode is not None:
                        # Note: only read() if the process exited.
                        log.exception(
                            "Error starting robotframework server api. Exit code: %s Base exception: %s. Stderr: %s",
                            exitcode,
                            e,
                            server_process.stderr.read(),
                        )
                    else:
                        log.exception(
                            "Error (%s) starting robotframework server api (still running). Base exception: %s.",
                            exitcode,
                            e,
                        )
                self._dispose_server_process()
            finally:
                if server_process is not None:
                    log.debug("Server api (%s) created pid: %s", self,
                              server_process.pid)
                else:
                    log.debug(
                        "server_process == None in get_robotframework_api_client()"
                    )

        return self._robotframework_api_client