コード例 #1
0
def test_complete_from_context(rf_server_api, libspec_manager, tmpdir):
    from robotframework_ls.impl.completion_context import CompletionContext
    from robotframework_ls.impl.robot_workspace import RobotDocument
    from robotframework_ls.impl.robot_workspace import RobotWorkspace
    from robocorp_ls_core.watchdog_wrapper import create_observer

    api = rf_server_api

    text = """*** Task ***
Some task
    Log    Something     console=True
    Lo"""

    doc = RobotDocument("", text)

    line, col = doc.get_last_line_col()
    workspace = RobotWorkspace(
        str(tmpdir),
        fs_observer=create_observer("dummy", []),
        libspec_manager=libspec_manager,
    )
    completion_context = CompletionContext(doc, line, col, workspace=workspace)

    for completion in api._complete_from_completion_context(completion_context):
        if completion["label"] == "Log":
            break
    else:
        raise AssertionError('Did not find "Log" entry in completions.')
コード例 #2
0
    def _obtain_fs_observer(self) -> IFSObserver:
        """
        The FSObserver is needed to keep the list of files updated in the
        Workspace (_VirtualFS).
        """
        try:
            return self._observer
        except AttributeError:
            from robocorp_ls_core import watchdog_wrapper

            self._observer = watchdog_wrapper.create_observer("dummy", None)
            return self._observer
コード例 #3
0
def test_watchdog_all(tmpdir):
    from robocorp_ls_core import watchdog_wrapper
    from robocorp_ls_core.watchdog_wrapper import PathInfo
    from robocorp_ls_core.unittest_tools.fixtures import wait_for_test_condition

    tmpdir.join("dir_not_rec").mkdir()
    tmpdir.join("dir_rec").mkdir()

    found = []

    def on_change(filepath, *args):
        found.append(filepath)
        assert args == ("foo", "bar")

    notifier = watchdog_wrapper.create_notifier(on_change, timeout=0.1)
    observer = watchdog_wrapper.create_observer()

    watch = observer.notify_on_any_change(
        [
            PathInfo(tmpdir.join("dir_not_rec"), False),
            PathInfo(tmpdir.join("dir_rec"), True),
        ],
        notifier.on_change,
        call_args=("foo", "bar"),
    )

    try:
        tmpdir.join("dir_not_rec").join("mya.txt").write("foo")
        tmpdir.join("dir_not_rec").join("mya.libspec").write("foo")

        tmpdir.join("dir_rec").join("myb.txt").write("foo")
        tmpdir.join("dir_rec").join("myb.libspec").write("foo")

        def collect_basenames():
            import os.path

            basenames = [os.path.basename(x) for x in found]
            return set(basenames)

        def check1():
            expected = {"myb.txt", "mya.libspec", "myb.libspec", "mya.txt"}
            return collect_basenames().issuperset(expected)

        wait_for_test_condition(
            check1, msg=lambda: f"Basenames found: {collect_basenames()}")

    finally:
        watch.stop_tracking()
        notifier.dispose()
        observer.dispose()
コード例 #4
0
    def __init__(self, builtin_libspec_dir=None, user_libspec_dir=None):
        """
        :param __internal_libspec_dir__:
            Only to be used in tests (to regenerate the builtins)!
        """
        from robocorp_ls_core import watchdog_wrapper

        self._libspec_failures_cache: Dict[tuple, bool] = {}

        self._main_thread = threading.current_thread()

        watch_impl = os.environ.get("ROBOTFRAMEWORK_LS_WATCH_IMPL", "watchdog")
        if watch_impl not in ("watchdog", "fsnotify"):
            log.info(
                f"ROBOTFRAMEWORK_LS_WATCH_IMPL should be 'watchdog' or 'fsnotify'. Found: {watch_impl} (falling back to fsnotify)"
            )
            # i.e.: the default is watchdog, so, if a different one is set,
            # presumably the default is not ok, so, fall back to watchdog.
            watch_impl = "fsnotify"

        self._observer = watchdog_wrapper.create_observer(
            watch_impl, (".py", ".libspec")
        )

        self._file_changes_notifier = watchdog_wrapper.create_notifier(
            self._on_file_changed, timeout=0.5
        )

        self._libspec_dir = self.get_internal_libspec_dir()

        self._user_libspec_dir = user_libspec_dir or os.path.join(
            self._libspec_dir, "user"
        )
        self._builtins_libspec_dir = (
            builtin_libspec_dir
            or self.get_internal_builtins_libspec_dir(self._libspec_dir)
        )
        log.debug("User libspec dir: %s", self._user_libspec_dir)
        log.debug("Builtins libspec dir: %s", self._builtins_libspec_dir)

        try:
            os.makedirs(self._user_libspec_dir)
        except:
            # Ignore exception if it's already created.
            pass
        try:
            os.makedirs(self._builtins_libspec_dir)
        except:
            # Ignore exception if it's already created.
            pass

        # Spec info found in the workspace
        self._workspace_folder_uri_to_folder_info = {}
        self._additional_pythonpath_folder_to_folder_info = {}

        # Spec info found in the pythonpath
        pythonpath_folder_to_folder_info = {}
        for path in sys.path:
            if path and os.path.isdir(path):
                pythonpath_folder_to_folder_info[path] = _FolderInfo(
                    path, recursive=False
                )
        self._pythonpath_folder_to_folder_info = pythonpath_folder_to_folder_info

        # Spec info found in internal dirs (autogenerated)
        self._internal_folder_to_folder_info = {
            self._user_libspec_dir: _FolderInfo(
                self._user_libspec_dir, recursive=False
            ),
            self._builtins_libspec_dir: _FolderInfo(
                self._builtins_libspec_dir, recursive=False
            ),
        }

        # Must be set from the outside world when needed.
        self.config = None

        log.debug("Generating builtin libraries.")
        self._gen_builtin_libraries()
        log.debug("Synchronizing internal caches.")
        self._synchronize()
        log.debug("Finished initializing LibspecManager.")
コード例 #5
0
def test_watchdog_extensions(tmpdir):
    from robocorp_ls_core import watchdog_wrapper
    from robocorp_ls_core.watchdog_wrapper import PathInfo
    from robocorp_ls_core.unittest_tools.fixtures import wait_for_test_condition

    tmpdir.join("dir_not_rec").mkdir()
    tmpdir.join("dir_rec").mkdir()

    found = []

    def on_change(filepath, *args):
        found.append(filepath)
        assert args == ("foo", "bar")

    notifier = watchdog_wrapper.create_notifier(on_change, timeout=0.1)
    observer = watchdog_wrapper.create_observer()

    watch = observer.notify_on_extensions_change(
        [
            PathInfo(tmpdir.join("dir_not_rec"), False),
            PathInfo(tmpdir.join("dir_rec"), True),
        ],
        ["libspec"],
        notifier.on_change,
        call_args=("foo", "bar"),
    )

    try:
        tmpdir.join("my.txt").write("foo")
        tmpdir.join("my.libspec").write("foo")

        tmpdir.join("dir_not_rec").join("mya.txt").write("foo")
        tmpdir.join("dir_not_rec").join("mya.libspec").write("foo")

        tmpdir.join("dir_rec").join("myb.txt").write("foo")
        tmpdir.join("dir_rec").join("myb.libspec").write("foo")

        def check1():
            found_my_a = False
            found_my_b = False
            for filepath in found:
                if not filepath.endswith(".libspec"):
                    raise AssertionError(
                        "Expected only libspec files to be tracked.")
                if filepath.endswith("my.libspec"):
                    raise AssertionError("Wrong folder tracked.")
                found_my_a = found_my_a or "mya.libspec" in filepath
                found_my_b = found_my_b or "myb.libspec" in filepath

            return found_my_a and found_my_b

        wait_for_test_condition(
            check1,
            msg=lambda:
            "Expected to find mya.libspec and myb.libspec. Found:\n%s" %
            ("\n".join(found), ),
        )

        # not listened
        tmpdir.join("dir_not_rec").join("another").mkdir()
        tmpdir.join("dir_not_rec").join("another").join("myc.txt").write("foo")
        tmpdir.join("dir_not_rec").join("another").join("myc.libspec").write(
            "foo")

        # listened
        tmpdir.join("dir_rec").join("another").mkdir()
        tmpdir.join("dir_rec").join("another").join("myd.txt").write("foo")
        tmpdir.join("dir_rec").join("another").join("myd.libspec").write("foo")

        del found[:]

        def check2():
            found_my_d = False
            for filepath in found:
                if not filepath.endswith(".libspec"):
                    raise AssertionError(
                        "Expected only libspec files to be tracked.")
                if filepath.endswith("myc.libspec"):
                    raise AssertionError("Wrong folder tracked.")
                found_my_d = found_my_d or "myd.libspec" in filepath

            return found_my_d

        wait_for_test_condition(
            check2,
            msg=lambda: "Expected to find myd.libspec. Found:\n%s" %
            ("\n".join(found), ),
        )

        watch.stop_tracking()
        del found[:]
        tmpdir.join("dir_rec").join("mye.txt").write("foo")
        tmpdir.join("dir_rec").join("mye.libspec").write("foo")

        # Give time to check if some change arrives.
        time.sleep(1)
        assert not found

    finally:
        notifier.dispose()
        observer.dispose()
コード例 #6
0
    def __init__(self, builtin_libspec_dir=None, user_libspec_dir=None):
        """
        :param __internal_libspec_dir__:
            Only to be used in tests (to regenerate the builtins)!
        """

        from robocorp_ls_core import watchdog_wrapper

        self._libspec_failures_cache: Dict[tuple, bool] = {}

        self._main_thread = threading.current_thread()

        self._observer = watchdog_wrapper.create_observer()

        self._file_changes_notifier = watchdog_wrapper.create_notifier(
            self._on_file_changed, timeout=0.5)

        self._root_uri = None

        self._libspec_dir = self.get_internal_libspec_dir()

        self._user_libspec_dir = user_libspec_dir or os.path.join(
            self._libspec_dir, "user")
        self._builtins_libspec_dir = (
            builtin_libspec_dir
            or self.get_internal_builtins_libspec_dir(self._libspec_dir))
        log.debug("User libspec dir: %s", self._user_libspec_dir)
        log.debug("Builtins libspec dir: %s", self._builtins_libspec_dir)

        try:
            os.makedirs(self._user_libspec_dir)
        except BaseException:
            # Ignore exception if it's already created.
            pass
        try:
            os.makedirs(self._builtins_libspec_dir)
        except BaseException:
            # Ignore exception if it's already created.
            pass

        self.libspec_errors: Dict[LibspecErrorEntry, str] = {}
        self.libspec_warnings: Dict[LibspecErrorEntry, str] = {}

        # Spec info found in the workspace
        self._workspace_folder_uri_to_folder_info = {}
        self._additional_pythonpath_folder_to_folder_info = {}

        # Spec info found in the pythonpath
        pythonpath_folder_to_folder_info = {}
        for path in sys.path:
            if path and os.path.isdir(path):
                pythonpath_folder_to_folder_info[path] = _FolderInfo(
                    path, recursive=False)
        self._pythonpath_folder_to_folder_info = pythonpath_folder_to_folder_info

        # Spec info found in internal dirs (autogenerated)
        self._internal_folder_to_folder_info = {
            self._user_libspec_dir:
            _FolderInfo(self._user_libspec_dir, recursive=False),
            self._builtins_libspec_dir:
            _FolderInfo(self._builtins_libspec_dir, recursive=False),
        }

        # Must be set from the outside world when needed.
        self.config = None

        self.process_pool = ProcessPoolExecutor()

        # we have to submit a dummy process to start the process pool,
        # because it does not start correctly if we do it from another
        # thread
        self.process_pool.submit(dummy_process).result()

        self.thread_pool = ThreadPoolExecutor(
            thread_name_prefix="libspec_manager_")

        log.debug("Generating builtin libraries.")
        self._gen_builtin_libraries()
        log.debug("Synchronizing internal caches.")
        self._synchronize()
        log.debug("Finished initializing LibspecManager.")
コード例 #7
0
def test_workspace_memory_cache(tmpdir, small_vs_sleep):
    from robocorp_ls_core.workspace import Workspace
    from robocorp_ls_core import uris
    from robocorp_ls_core.lsp import WorkspaceFolder
    import os
    from typing import List
    from robocorp_ls_core.protocols import IWorkspaceFolder
    import typing
    from robocorp_ls_core.workspace import _WorkspaceFolderWithVirtualFS
    from robocorp_ls_core import watchdog_wrapper
    from robocorp_ls_core.basic import wait_for_condition

    root_uri = uris.from_fs_path(str(tmpdir))
    workspace_folders: List[IWorkspaceFolder] = [
        WorkspaceFolder(root_uri, os.path.basename(str(tmpdir)))
    ]
    fs_observer = watchdog_wrapper.create_observer("watchdog",
                                                   extensions=(".py", ".txt"))
    ws = Workspace(root_uri,
                   fs_observer,
                   workspace_folders,
                   track_file_extensions=(".py", ".txt"))

    folders = list(ws.iter_folders())
    assert len(folders) == 1
    folder = typing.cast(_WorkspaceFolderWithVirtualFS, folders[0])
    vs = folder._vs

    wait_for_condition(
        lambda: list(ws.iter_all_doc_uris_in_workspace((".py", ".txt"))) == [])
    # If the change is too fast the mtime may end up being the same...

    f = tmpdir.join("my.txt")
    f.write_text("foo", "utf-8")

    wait_for_condition(
        lambda: list(ws.iter_all_doc_uris_in_workspace(
            (".py", ".txt"))) == [uris.from_fs_path(str(f))])

    dir1 = tmpdir.join("dir1")
    dir1.mkdir()

    f2 = dir1.join("my.py")
    f2.write_text("foo", "utf-8")

    wait_for_condition(
        lambda: set(ws.iter_all_doc_uris_in_workspace((".py", ".txt"))) ==
        {uris.from_fs_path(str(f)),
         uris.from_fs_path(str(f2))})

    wait_for_condition(
        lambda: set(ws.iter_all_doc_uris_in_workspace((".py", ".txt"))) ==
        {uris.from_fs_path(str(f)),
         uris.from_fs_path(str(f2))})

    # If the change is too fast the mtime may end up being the same...
    f2.remove()

    wait_for_condition(
        lambda: set(ws.iter_all_doc_uris_in_workspace(
            (".py", ".txt"))) == {uris.from_fs_path(str(f))})

    wait_for_condition(
        lambda: set(ws.iter_all_doc_uris_in_workspace(
            (".py", ".txt"))) == {uris.from_fs_path(str(f))})

    ws.remove_folder(root_uri)
    assert set(ws.iter_all_doc_uris_in_workspace((".py", ".txt"))) == set()
    vs._virtual_fsthread.join(0.5)
    assert not vs._virtual_fsthread.is_alive()
コード例 #8
0
    def __init__(self, builtin_libspec_dir=None, user_libspec_dir=None):
        """
        :param __internal_libspec_dir__:
            Only to be used in tests (to regenerate the builtins)!
        """
        from robocorp_ls_core import watchdog_wrapper

        self._main_thread = threading.current_thread()

        self._observer = watchdog_wrapper.create_observer()

        self._spec_changes_notifier = watchdog_wrapper.create_notifier(
            self._on_spec_file_changed, timeout=0.5)

        self._libspec_dir = self.get_internal_libspec_dir()

        self._user_libspec_dir = user_libspec_dir or os.path.join(
            self._libspec_dir, "user")
        self._builtins_libspec_dir = (
            builtin_libspec_dir
            or self.get_internal_builtins_libspec_dir(self._libspec_dir))
        log.debug("User libspec dir: %s", self._user_libspec_dir)
        log.debug("Builtins libspec dir: %s", self._builtins_libspec_dir)

        try:
            os.makedirs(self._user_libspec_dir)
        except:
            # Ignore exception if it's already created.
            pass
        try:
            os.makedirs(self._builtins_libspec_dir)
        except:
            # Ignore exception if it's already created.
            pass

        # Spec info found in the workspace
        self._workspace_folder_uri_to_folder_info = {}
        self._additional_pythonpath_folder_to_folder_info = {}

        # Spec info found in the pythonpath
        pythonpath_folder_to_folder_info = {}
        for path in sys.path:
            if path and os.path.isdir(path):
                pythonpath_folder_to_folder_info[path] = _FolderInfo(
                    path, recursive=False)
        self._pythonpath_folder_to_folder_info = pythonpath_folder_to_folder_info

        # Spec info found in internal dirs (autogenerated)
        self._internal_folder_to_folder_info = {
            self._user_libspec_dir:
            _FolderInfo(self._user_libspec_dir, recursive=False),
            self._builtins_libspec_dir:
            _FolderInfo(self._builtins_libspec_dir, recursive=False),
        }

        # Must be set from the outside world when needed.
        self.config = None

        log.debug("Generating builtin libraries.")
        self._gen_builtin_libraries()
        log.debug("Synchronizing internal caches.")
        self._synchronize()
        log.debug("Finished initializing LibspecManager.")
コード例 #9
0
    def __init__(self, builtin_libspec_dir=None, user_libspec_dir=None):
        """
        :param __internal_libspec_dir__:
            Only to be used in tests (to regenerate the builtins)!
        """
        from robocorp_ls_core import watchdog_wrapper

        self._libspec_failures_cache: Dict[tuple, bool] = {}

        self._main_thread = threading.current_thread()

        watch_impl = os.environ.get("ROBOTFRAMEWORK_LS_WATCH_IMPL", "auto")
        if watch_impl not in ("watchdog", "fsnotify", "auto"):
            log.info(
                f"ROBOTFRAMEWORK_LS_WATCH_IMPL should be 'auto', 'watchdog' or 'fsnotify'. Found: {watch_impl} (falling back to auto)"
            )
            watch_impl = "auto"

        if watch_impl == "auto":
            # In auto mode we use watchdog for windows and fsnotify (polling)
            # for Linux and Mac. The reason for that is that on Linux and Mac
            # if big folders are watched the system may complain due to the
            # lack of resources, which may prevent the extension from working
            # properly.
            #
            # If users want to opt-in, they can change to watchdog (and
            # ideally install it to their env to get native extensions).
            if sys.platform == "win32":
                watch_impl = "watchdog"
            else:
                watch_impl = "fsnotify"

        self._observer = watchdog_wrapper.create_observer(
            watch_impl, (".py", ".libspec")
        )

        self._file_changes_notifier = watchdog_wrapper.create_notifier(
            self._on_file_changed, timeout=0.5
        )

        self._libspec_dir = self.get_internal_libspec_dir()

        self._user_libspec_dir = user_libspec_dir or os.path.join(
            self._libspec_dir, "user"
        )
        self._builtins_libspec_dir = (
            builtin_libspec_dir
            or self.get_internal_builtins_libspec_dir(self._libspec_dir)
        )
        log.debug("User libspec dir: %s", self._user_libspec_dir)
        log.debug("Builtins libspec dir: %s", self._builtins_libspec_dir)

        try:
            os.makedirs(self._user_libspec_dir)
        except:
            # Ignore exception if it's already created.
            pass
        try:
            os.makedirs(self._builtins_libspec_dir)
        except:
            # Ignore exception if it's already created.
            pass

        # Spec info found in the workspace
        self._workspace_folder_uri_to_folder_info = {}
        self._additional_pythonpath_folder_to_folder_info = {}

        # Spec info found in the pythonpath
        pythonpath_folder_to_folder_info = {}
        for path in sys.path:
            if path and os.path.isdir(path):
                pythonpath_folder_to_folder_info[path] = _FolderInfo(
                    path, recursive=False
                )
        self._pythonpath_folder_to_folder_info = pythonpath_folder_to_folder_info

        # Spec info found in internal dirs (autogenerated)
        self._internal_folder_to_folder_info = {
            self._user_libspec_dir: _FolderInfo(
                self._user_libspec_dir, recursive=False
            ),
            self._builtins_libspec_dir: _FolderInfo(
                self._builtins_libspec_dir, recursive=False
            ),
        }

        # Must be set from the outside world when needed.
        self.config = None

        log.debug("Generating builtin libraries.")
        self._gen_builtin_libraries()
        log.debug("Synchronizing internal caches.")
        self._synchronize()
        log.debug("Finished initializing LibspecManager.")