Repository navigation
Expand file tree
/
Copy pathtest_hover.py
More file actions
177 lines (142 loc) · 5.63 KB
/
Copy pathtest_hover.py
File metadata and controls
177 lines (142 loc) · 5.63 KB
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# Copyright 2017-2020 Palantir Technologies, Inc.
# Copyright 2021- Python Language Server Contributors.
import os
from pylsp import uris
from pylsp.plugins.hover import pylsp_hover
from pylsp.workspace import Document
DOC_URI = uris.from_fs_path(__file__)
DOC = """
def main(a: float, b: float):
\"\"\"hello world\"\"\"
pass
"""
NUMPY_DOC = """
import numpy as np
np.sin
"""
def test_numpy_hover(workspace) -> None:
# Over the blank line
no_hov_position = {"line": 1, "character": 0}
# Over 'numpy' in import numpy as np
numpy_hov_position_1 = {"line": 2, "character": 8}
# Over 'np' in import numpy as np
numpy_hov_position_2 = {"line": 2, "character": 17}
# Over 'np' in np.sin
numpy_hov_position_3 = {"line": 3, "character": 1}
# Over 'sin' in np.sin
numpy_sin_hov_position = {"line": 3, "character": 4}
doc = Document(DOC_URI, workspace, NUMPY_DOC)
contents = ""
assert contents in pylsp_hover(doc._config, doc, no_hov_position)["contents"]
# For module hovers, the format is a list with just the docstring (no signature)
def get_hover_text(result):
contents = result["contents"]
if isinstance(contents, list) and len(contents) > 0:
# Return the last item which is the docstring
return contents[-1]
return contents
contents = "NumPy\n=====\n\nProvides\n"
assert contents in get_hover_text(
pylsp_hover(doc._config, doc, numpy_hov_position_1)
)
contents = "NumPy\n=====\n\nProvides\n"
assert contents in get_hover_text(
pylsp_hover(doc._config, doc, numpy_hov_position_2)
)
contents = "NumPy\n=====\n\nProvides\n"
assert contents in get_hover_text(
pylsp_hover(doc._config, doc, numpy_hov_position_3)
)
# https://github.com/davidhalter/jedi/issues/1746
import numpy as np
if np.lib.NumpyVersion(np.__version__) < "1.20.0":
contents = "Trigonometric sine, element-wise.\n\n"
assert contents in get_hover_text(
pylsp_hover(doc._config, doc, numpy_sin_hov_position)
)
def test_hover(workspace) -> None:
# Over 'main' in def main():
hov_position = {"line": 2, "character": 6}
doc = Document(DOC_URI, workspace, DOC)
result = pylsp_hover(doc._config, doc, hov_position)
assert "contents" in result
contents = result["contents"]
if isinstance(contents, list):
assert len(contents) == 2
assert contents[0] == {
"language": "python",
"value": "main(a: float, b: float)",
}
assert "hello world" in contents[1]
else:
assert isinstance(contents, dict) and "value" in contents
assert "hello world" in contents["value"]
def test_hover_signature_formatting(workspace) -> None:
# Over 'main' in def main():
hov_position = {"line": 2, "character": 6}
doc = Document(DOC_URI, workspace, DOC)
# setting low line length should trigger reflow to multiple lines
doc._config.update({"signature": {"line_length": 10}})
result = pylsp_hover(doc._config, doc, hov_position)
assert "contents" in result
contents = result["contents"]
if isinstance(contents, list):
assert len(contents) == 2
assert contents[0] == {
"language": "python",
"value": "main(a: float, b: float)",
}
assert "hello world" in contents[1]
else:
assert isinstance(contents, dict) and "value" in contents
assert "hello world" in contents["value"]
def test_hover_signature_formatting_opt_out(workspace) -> None:
# Over 'main' in def main():
hov_position = {"line": 2, "character": 6}
doc = Document(DOC_URI, workspace, DOC)
doc._config.update({"signature": {"line_length": 10, "formatter": None}})
result = pylsp_hover(doc._config, doc, hov_position)
assert "contents" in result
contents = result["contents"]
if isinstance(contents, list):
assert len(contents) == 2
assert contents[0] == {
"language": "python",
"value": "main(a: float, b: float)",
}
assert "hello world" in contents[1]
else:
assert isinstance(contents, dict) and "value" in contents
assert "hello world" in contents["value"]
def test_document_path_hover(workspace_other_root_path, tmpdir) -> None:
# Create a dummy module out of the workspace's root_path and try to get
# a definition on it in another file placed next to it.
module_content = '''
def foo():
"""A docstring for foo."""
pass
'''
p = tmpdir.join("mymodule.py")
p.write(module_content)
# Content of doc to test definition
doc_content = """from mymodule import foo
foo"""
doc_path = str(tmpdir) + os.path.sep + "myfile.py"
doc_uri = uris.from_fs_path(doc_path)
doc = Document(doc_uri, workspace_other_root_path, doc_content)
cursor_pos = {"line": 1, "character": 3}
result = pylsp_hover(doc._config, doc, cursor_pos)
contents = result["contents"]
# contents is now a list after cc0efee commit
# The result should be either a list with signature and/or docstring, or empty string
if isinstance(contents, list) and len(contents) > 0:
# Convert list to string for checking
contents_str = " ".join(
str(item) if not isinstance(item, dict) else item.get("value", "")
for item in contents
)
assert "A docstring for foo." in contents_str
else:
# If Jedi can't resolve the definition (e.g., in test environment), the hover may be empty
# This is acceptable behavior - just verify we got a valid response structure
assert contents == "" or contents == []