Beispiel #1
0
    def on_setBreakpoints_request(self, request):
        from robocorp_ls_core.debug_adapter_core.dap.dap_schema import SourceBreakpoint
        from robocorp_ls_core.debug_adapter_core.dap.dap_schema import Breakpoint
        from robocorp_ls_core.debug_adapter_core.dap.dap_schema import (
            SetBreakpointsResponseBody, )
        from robocorp_ls_core.debug_adapter_core.dap import dap_base_schema
        from robotframework_debug_adapter import file_utils
        from robotframework_debug_adapter.debugger_impl import RobotBreakpoint
        from robocorp_ls_core.robotframework_log import get_logger

        log = get_logger("robotframework_debug_adapter.run_robot__main__.py")

        # Just acknowledge that no breakpoints are valid.

        breakpoints = []
        robot_breakpoints = []
        source = request.arguments.source
        path = source.path
        filename = file_utils.norm_file_to_server(path)
        log.info("Normalized %s to %s", path, filename)

        if request.arguments.breakpoints:

            for bp in request.arguments.breakpoints:
                source_breakpoint = SourceBreakpoint(**bp)
                breakpoints.append(
                    Breakpoint(verified=True,
                               line=source_breakpoint.line,
                               source=source).to_dict())
                hit_condition = None
                try:
                    if source_breakpoint.hitCondition:
                        hit_condition = int(source_breakpoint.hitCondition)
                except:
                    log.exception(
                        "Unable to evaluate hit condition (%s) to an int. Ignoring it.",
                        source_breakpoint.hitCondition,
                    )
                robot_breakpoints.append(
                    RobotBreakpoint(
                        source_breakpoint.line,
                        source_breakpoint.condition,
                        hit_condition,
                        source_breakpoint.logMessage,
                    ))

        if self._debugger_impl:
            self._debugger_impl.set_breakpoints(filename, robot_breakpoints)
        else:
            if robot_breakpoints:
                get_log().info("Unable to set breakpoints (no debug mode).")

        self.write_message(
            dap_base_schema.build_response(
                request,
                kwargs=dict(body=SetBreakpointsResponseBody(
                    breakpoints=breakpoints)),
            ))
Beispiel #2
0
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 robocorp_ls_core.robotframework_log import get_logger
    from robocorp_ls_core.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
    robotframework_ls.import_robocorp_ls_core()

    from robotframework_ls.options import Setup, Options
    from robocorp_ls_core.robotframework_log import (
        configure_logger,
        log_args_and_python,
        get_logger,
    )

    from robocorp_ls_core.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)
    if args.version:
        sys.stdout.write(robotframework_ls.__version__)
        sys.stdout.flush()
        return
    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, robotframework_ls.__version__)

    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)
Beispiel #4
0
def _stderr_reader(stream):
    from robocorp_ls_core.robotframework_log import get_logger

    log = get_logger(__name__)

    try:
        while True:
            line = stream.readline()
            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.")
Beispiel #5
0
def connect(port):
    from robotframework_ls.options import DEFAULT_TIMEOUT
    from robotframework_ls.impl.robot_lsp_constants import ENV_OPTION_ROBOT_DAP_TIMEOUT
    from robocorp_ls_core.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
Beispiel #6
0
def main():
    log = None
    try:
        src_folder = os.path.dirname(
            os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
        try:
            import robotframework_ls
        except ImportError:
            # Automatically add it to the path if __main__ is being executed.
            assert os.path.exists(
                src_folder), "Expected: %s to exist" % (src_folder, )
            sys.path.append(src_folder)
            import robotframework_ls  # @UnusedImport

        robotframework_ls.import_robocorp_ls_core()

        from robocorp_ls_core.robotframework_log import get_logger

        log = get_logger(__name__)

        log.info("Initializing RobotFramework Server api. Args: %s",
                 (sys.argv[1:], ))

        from robotframework_ls import __main__
        from robotframework_ls.server_api.server import RobotFrameworkServerApi

        __main__.main(language_server_class=RobotFrameworkServerApi)
    except:
        try:
            if log is not None:
                log.exception("Error initializing RobotFrameworkServerApi.")
        finally:
            # 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()
def main():
    log = None
    try:
        try:
            import robocorp_code
        except ImportError:
            # Automatically add it to the path if __main__ is being executed.
            sys.path.append(
                os.path.dirname(
                    os.path.dirname(os.path.dirname(
                        os.path.dirname(__file__)))))
            import robocorp_code  # @UnusedImport
        robocorp_code.import_robocorp_ls_core()

        from robocorp_ls_core.robotframework_log import get_logger

        log = get_logger(__name__)

        log.info("Initializing Locators Server api. Args: %s",
                 (sys.argv[1:], ))

        from robocorp_code import __main__
        from robocorp_code.locators.server.locator_server_api import LocatorServerApi

        __main__.main(language_server_class=LocatorServerApi)
    except:
        try:
            if log is not None:
                log.exception("Error initializing LocatorServerApi.")
        finally:
            # 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()
from robocorp_ls_core.workspace import Workspace, Document
from robocorp_ls_core.basic import overrides
from robocorp_ls_core.cache import instance_cache
from robotframework_ls.constants import NULL
from robocorp_ls_core.robotframework_log import get_logger
from robotframework_ls.impl.protocols import IRobotWorkspace, IRobotDocument
from robocorp_ls_core.protocols import check_implements, IWorkspaceFolder
from robocorp_ls_core.watchdog_wrapper import IFSObserver
from typing import Optional, Any

log = get_logger(__name__)


class RobotWorkspace(Workspace):
    def __init__(
        self,
        root_uri,
        fs_observer: IFSObserver,
        workspace_folders=None,
        libspec_manager=NULL,
        generate_ast=True,
    ):
        self.libspec_manager = libspec_manager

        Workspace.__init__(self,
                           root_uri,
                           fs_observer,
                           workspace_folders=workspace_folders)
        self._generate_ast = generate_ast

    @overrides(Workspace.add_folder)
def main():
    log = None
    try:
        src_folder = os.path.dirname(
            os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
        try:
            import robotframework_ls
        except ImportError:
            # Automatically add it to the path if __main__ is being executed.
            assert os.path.exists(
                src_folder), "Expected: %s to exist" % (src_folder, )
            sys.path.append(src_folder)
            import robotframework_ls  # @UnusedImport

        robotframework_ls.import_robocorp_ls_core()

        from robocorp_ls_core.robotframework_log import get_logger

        log = get_logger(__name__)

        log.info("Initializing RobotFramework Server api. Args: %s",
                 (sys.argv[1:], ))

        from robotframework_ls import __main__
        from robotframework_ls.server_api.server import RobotFrameworkServerApi

        args = sys.argv[1:]
        new_args = []

        found_remote_fs_obverver_port = False
        for arg in args:
            if arg.startswith("--remote-fs-observer-port="):
                # Now, in this process, we don't own the RemoteFSObserver, we
                # just expect to connect to an existing one.
                found_remote_fs_obverver_port = True
                port = int(arg.split("=")[1].strip())
                from robocorp_ls_core.remote_fs_observer_impl import RemoteFSObserver

                observer = RemoteFSObserver("<unused>", extensions=None)
                observer.connect_to_server(port)

                class RobotFrameworkServerApiWithObserver(
                        RobotFrameworkServerApi):
                    def __init__(self, *args, **kwargs):
                        kwargs["observer"] = observer
                        RobotFrameworkServerApi.__init__(self, *args, **kwargs)

            else:
                new_args.append(arg)

        if not found_remote_fs_obverver_port:
            raise RuntimeError(
                'Expected "--remote-fs-observer-port=" to be passed in the arguments.'
            )
        __main__.main(
            language_server_class=RobotFrameworkServerApiWithObserver,
            args=new_args)
    except:
        try:
            if log is not None:
                log.exception("Error initializing RobotFrameworkServerApi.")
        finally:
            # 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()
Beispiel #10
0
def main(args=None, language_server_class=None):
    original_args = args if args is not None else sys.argv[1:]

    parser = argparse.ArgumentParser()
    add_arguments(parser)

    args = parser.parse_args(args=original_args)
    verbose = args.verbose
    log_file = args.log_file or ""

    try:
        try:
            import robotframework_interactive
        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_interactive  # @UnusedImport
        robotframework_interactive.import_robocorp_ls_core()

        from robocorp_ls_core.robotframework_log import (
            configure_logger,
            log_args_and_python,
            get_logger,
        )
    except:
        # Failed before having setup the logger (but after reading args).
        log_file = os.path.expanduser(log_file)
        log_file = os.path.realpath(os.path.abspath(log_file))
        dirname = os.path.dirname(log_file)
        basename = os.path.basename(log_file)
        try:
            os.makedirs(dirname)
        except:
            pass  # Ignore error if it already exists.

        name, ext = os.path.splitext(basename)
        postfix = "rf_interactive.init"
        log_file = os.path.join(
            dirname, name + "." + postfix + "." + str(os.getpid()) + ext)
        with open(log_file, "a+") as stream:
            traceback.print_exc(file=stream)

        raise

    if args.version:
        sys.stdout.write(robotframework_interactive.__version__)
        sys.stdout.flush()
        return

    configure_logger("rfinteractive", verbose, log_file)
    log = get_logger("robotframework_interactive.__main__")
    log_args_and_python(log, original_args, robotframework_interactive)

    try:
        from robotframework_interactive.server.options import Setup, Options

        Setup.options = Options(args)

        # Ok, now that we have our options, let's connect back.

        from robocorp_ls_core.python_ls import (
            start_io_lang_server,
            start_tcp_lang_client,
            binary_stdio,
        )

        if args.tcp:
            start_tcp_lang_client(args.host, args.port, language_server_class)
        else:
            stdin, stdout = binary_stdio()
            start_io_lang_server(stdin, stdout, language_server_class)

    except:
        log.exception("Error initializing")
        raise
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

        if sys.version_info[0] <= 2:
            raise AssertionError(
                "Python 3+ is required for the RobotFramework Debug Adapter.\nCurrent executable: "
                + sys.executable)

        try:
            import robotframework_debug_adapter
            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_debug_adapter  # @UnusedImport
            import robotframework_ls

        robotframework_ls.import_robocorp_ls_core()

        from robocorp_ls_core.debug_adapter_core.debug_adapter_threads import (
            STOP_WRITER_THREAD, )
        from robocorp_ls_core.robotframework_log import (
            get_logger,
            configure_logger,
            log_args_and_python,
        )

        from robotframework_debug_adapter.constants import LOG_FILENAME
        from robotframework_debug_adapter.constants import LOG_LEVEL

        configure_logger("dap", LOG_LEVEL, LOG_FILENAME)
        log = get_logger("robotframework_debug_adapter.__main__")
        log_args_and_python(log, sys.argv, robotframework_ls.__version__)

        from robocorp_ls_core.debug_adapter_core.debug_adapter_threads import (
            reader_thread, )
        from robocorp_ls_core.debug_adapter_core.debug_adapter_threads import (
            writer_thread, )
        from robotframework_debug_adapter.debug_adapter_comm import DebugAdapterComm

        try:
            from queue import Queue
        except ImportError:
            from Queue import Queue

        to_client_queue = Queue()
        comm = DebugAdapterComm(to_client_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, to_client_queue, "write to client"),
            name="Write to client (dap __main__)",
        )
        reader = threading.Thread(
            target=reader_thread,
            args=(read_from, comm.from_client, to_client_queue,
                  b"read from client"),
            name="Read from client (dap __main__)",
        )

        reader.start()
        writer.start()

        reader.join()
        log.debug("Exited reader.\n")
        to_client_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")
Beispiel #12
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
    robotframework_ls.import_robocorp_ls_core()

    from robotframework_ls.options import Setup, Options
    from robocorp_ls_core.robotframework_log import (
        configure_logger,
        log_args_and_python,
        get_logger,
    )

    from robocorp_ls_core.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)
    if args.version:
        sys.stdout.write(robotframework_ls.__version__)
        sys.stdout.flush()
        return
    Setup.options = Options(args)
    verbose = args.verbose
    log_file = args.log_file or ""

    if not log_file:
        # If not specified in args, also check the environment variables.
        log_file = os.environ.get("ROBOTFRAMEWORK_LS_LOG_FILE", "")
        if log_file:
            # If the log file comes from the environment, make sure the log-level
            # also comes from it (with a log-level==2 by default).
            Setup.options.log_file = log_file
            try:
                verbose = int(
                    os.environ.get("ROBOTFRAMEWORK_LS_LOG_LEVEL", "2"))
            except:
                verbose = 2
            Setup.options.verbose = verbose

    configure_logger("lsp", verbose, log_file)
    log = get_logger("robotframework_ls.__main__")
    log_args_and_python(log, original_args, robotframework_ls)

    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 get_log():
    from robocorp_ls_core.robotframework_log import get_logger

    return get_logger("robotframework_debug_adapter.run_robot__main__.py")