File: test_symbols.py

package info (click to toggle)
python-lsp-server 1.13.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 868 kB
  • sloc: python: 8,250; sh: 12; makefile: 4
file content (132 lines) | stat: -rw-r--r-- 4,062 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# Copyright 2017-2020 Palantir Technologies, Inc.
# Copyright 2021- Python Language Server Contributors.

import os
import sys

import pytest

from pylsp import uris
from pylsp.lsp import SymbolKind
from pylsp.plugins.symbols import pylsp_document_symbols
from pylsp.workspace import Document

PY2 = sys.version[0] == "2"
LINUX = sys.platform.startswith("linux")
CI = os.environ.get("CI")
DOC_URI = uris.from_fs_path(__file__)
DOC = """import sys

a = 'hello'

class B:
    def __init__(self):
        x = 2
        self.y = x

def main(x):
    y = 2 * x
    return y

"""

DOC_IMPORTS = """from . import something
from ..module import something
from module import (a, b)

def main():
    # import ignored
    print("from module import x")  # string with import
    return something

"""


def helper_check_symbols_all_scope(symbols):
    # All eight symbols (import sys, a, B, __init__, x, y, main, y)
    assert len(symbols) == 8

    def sym(name):
        return [s for s in symbols if s["name"] == name][0]

    # Check we have some sane mappings to VSCode constants
    assert sym("a")["kind"] == SymbolKind.Variable
    assert sym("B")["kind"] == SymbolKind.Class
    assert sym("__init__")["kind"] == SymbolKind.Method
    assert sym("main")["kind"] == SymbolKind.Function

    # Not going to get too in-depth here else we're just testing Jedi
    assert sym("a")["location"]["range"]["start"] == {"line": 2, "character": 0}


def test_symbols(config, workspace):
    doc = Document(DOC_URI, workspace, DOC)
    config.update({"plugins": {"jedi_symbols": {"all_scopes": False}}})
    symbols = pylsp_document_symbols(config, doc)

    # All four symbols (import sys, a, B, main)
    # y is not in the root scope, it shouldn't be returned
    assert len(symbols) == 5

    def sym(name):
        return [s for s in symbols if s["name"] == name][0]

    # Check we have some sane mappings to VSCode constants
    assert sym("a")["kind"] == SymbolKind.Variable
    assert sym("B")["kind"] == SymbolKind.Class
    assert sym("main")["kind"] == SymbolKind.Function

    # Not going to get too in-depth here else we're just testing Jedi
    assert sym("a")["location"]["range"]["start"] == {"line": 2, "character": 0}

    # Ensure that the symbol range spans the whole definition
    assert sym("main")["location"]["range"]["start"] == {"line": 9, "character": 0}
    assert sym("main")["location"]["range"]["end"] == {"line": 12, "character": 0}


def test_symbols_complex_imports(config, workspace):
    doc = Document(DOC_URI, workspace, DOC_IMPORTS)
    config.update({"plugins": {"jedi_symbols": {"all_scopes": False}}})
    symbols = pylsp_document_symbols(config, doc)

    import_symbols = [s for s in symbols if s["kind"] == SymbolKind.Module]

    assert len(import_symbols) == 4

    names = [s["name"] for s in import_symbols]
    assert "something" in names
    assert "a" in names or "b" in names

    assert any(
        s["name"] == "main" and s["kind"] == SymbolKind.Function for s in symbols
    )


def test_symbols_all_scopes(config, workspace) -> None:
    doc = Document(DOC_URI, workspace, DOC)
    symbols = pylsp_document_symbols(config, doc)
    helper_check_symbols_all_scope(symbols)


def test_symbols_non_existing_file(config, workspace, tmpdir) -> None:
    path = tmpdir.join("foo.py")
    # Check pre-condition: file must not exist
    assert not path.check(exists=1)

    doc = Document(uris.from_fs_path(str(path)), workspace, DOC)
    symbols = pylsp_document_symbols(config, doc)
    helper_check_symbols_all_scope(symbols)


@pytest.mark.skipif(
    PY2 or not LINUX or not CI, reason="tested on linux and python 3 only"
)
def test_symbols_all_scopes_with_jedi_environment(workspace) -> None:
    doc = Document(DOC_URI, workspace, DOC)

    # Update config extra environment
    env_path = "/tmp/pyenv/bin/python"
    settings = {"pylsp": {"plugins": {"jedi": {"environment": env_path}}}}
    doc.update_config(settings)
    symbols = pylsp_document_symbols(doc._config, doc)
    helper_check_symbols_all_scope(symbols)