10
10
from pylsp .python_lsp import PythonLSPServer
11
11
from pylsp .lsp import NotebookCellKind
12
12
13
- CALL_TIMEOUT = 10
13
+ CALL_TIMEOUT_IN_SECONDS = 10
14
14
15
15
16
- def wait_for_condition (condition , timeout = CALL_TIMEOUT ):
16
+ def wait_for_condition (condition , timeout = CALL_TIMEOUT_IN_SECONDS ):
17
17
"""Wait for a condition to be true, or timeout."""
18
18
start_time = time .time ()
19
19
while not condition ():
@@ -51,9 +51,9 @@ def client_server_pair():
51
51
52
52
yield (client_server_pair_obj .client , client_server_pair_obj .server )
53
53
54
- shutdown_response = client_server_pair_obj .client ._endpoint .request ("shutdown" ). result (
55
- timeout = CALL_TIMEOUT
56
- )
54
+ shutdown_response = client_server_pair_obj .client ._endpoint .request (
55
+ "shutdown"
56
+ ). result ( timeout = CALL_TIMEOUT_IN_SECONDS )
57
57
assert shutdown_response is None
58
58
client_server_pair_obj .client ._endpoint .notify ("exit" )
59
59
@@ -67,13 +67,15 @@ def test_initialize(client_server_pair): # pylint: disable=redefined-outer-name
67
67
"rootPath" : os .path .dirname (__file__ ),
68
68
"initializationOptions" : {},
69
69
},
70
- ).result (timeout = CALL_TIMEOUT )
70
+ ).result (timeout = CALL_TIMEOUT_IN_SECONDS )
71
71
assert server .workspace is not None
72
72
assert "capabilities" in response
73
73
# TODO: assert that notebook capabilities are in response
74
74
75
75
76
- def test_notebook_document__did_open (client_server_pair ): # pylint: disable=redefined-outer-name
76
+ def test_notebook_document__did_open (
77
+ client_server_pair ,
78
+ ): # pylint: disable=redefined-outer-name
77
79
client , server = client_server_pair
78
80
client ._endpoint .request (
79
81
"initialize" ,
@@ -82,7 +84,7 @@ def test_notebook_document__did_open(client_server_pair): # pylint: disable=red
82
84
"rootPath" : os .path .dirname (__file__ ),
83
85
"initializationOptions" : {},
84
86
},
85
- ).result (timeout = CALL_TIMEOUT )
87
+ ).result (timeout = CALL_TIMEOUT_IN_SECONDS )
86
88
87
89
with patch .object (server ._endpoint , "notify" ) as mock_notify :
88
90
client ._endpoint .notify (
@@ -100,28 +102,70 @@ def test_notebook_document__did_open(client_server_pair): # pylint: disable=red
100
102
"kind" : NotebookCellKind .Code ,
101
103
"document" : "cell_2_uri" ,
102
104
},
105
+ {
106
+ "kind" : NotebookCellKind .Code ,
107
+ "document" : "cell_3_uri" ,
108
+ },
109
+ {
110
+ "kind" : NotebookCellKind .Code ,
111
+ "document" : "cell_4_uri" ,
112
+ },
113
+ {
114
+ "kind" : NotebookCellKind .Code ,
115
+ "document" : "cell_5_uri" ,
116
+ },
103
117
],
104
118
},
119
+ # Test as many edge cases as possible for the diagnostics message
105
120
"cellTextDocuments" : [
106
121
{
107
122
"uri" : "cell_1_uri" ,
108
123
"languageId" : "python" ,
109
- "text" : "import sys " ,
124
+ "text" : "" ,
110
125
},
111
126
{
112
127
"uri" : "cell_2_uri" ,
113
128
"languageId" : "python" ,
114
- "text" : "x = 1" ,
129
+ "text" : "\n " ,
130
+ },
131
+ {
132
+ "uri" : "cell_3_uri" ,
133
+ "languageId" : "python" ,
134
+ "text" : "\n import sys\n \n abc\n \n " ,
135
+ },
136
+ {
137
+ "uri" : "cell_4_uri" ,
138
+ "languageId" : "python" ,
139
+ "text" : "x" ,
140
+ },
141
+ {
142
+ "uri" : "cell_5_uri" ,
143
+ "languageId" : "python" ,
144
+ "text" : "y\n " ,
115
145
},
116
146
],
117
147
},
118
148
)
119
- wait_for_condition (lambda : mock_notify .call_count >= 2 )
149
+ wait_for_condition (lambda : mock_notify .call_count >= 5 )
120
150
expected_call_args = [
121
151
call (
122
152
"textDocument/publishDiagnostics" ,
123
153
params = {
124
154
"uri" : "cell_1_uri" ,
155
+ "diagnostics" : [],
156
+ },
157
+ ),
158
+ call (
159
+ "textDocument/publishDiagnostics" ,
160
+ params = {
161
+ "uri" : "cell_2_uri" ,
162
+ "diagnostics" : [],
163
+ },
164
+ ),
165
+ call (
166
+ "textDocument/publishDiagnostics" ,
167
+ params = {
168
+ "uri" : "cell_3_uri" ,
125
169
"diagnostics" : [
126
170
{
127
171
"source" : "pyflakes" ,
@@ -131,33 +175,70 @@ def test_notebook_document__did_open(client_server_pair): # pylint: disable=red
131
175
},
132
176
"message" : "'sys' imported but unused" ,
133
177
"severity" : 2 ,
134
- }
178
+ },
179
+ {
180
+ "source" : "pyflakes" ,
181
+ "range" : {
182
+ "start" : {"line" : 3 , "character" : 0 },
183
+ "end" : {"line" : 3 , "character" : 4 },
184
+ },
185
+ "message" : "undefined name 'abc'" ,
186
+ "severity" : 1 ,
187
+ },
188
+ {
189
+ "source" : "pycodestyle" ,
190
+ "range" : {
191
+ "start" : {"line" : 1 , "character" : 0 },
192
+ "end" : {"line" : 1 , "character" : 11 },
193
+ },
194
+ "message" : "E303 too many blank lines (3)" ,
195
+ "code" : "E303" ,
196
+ "severity" : 2 ,
197
+ },
135
198
],
136
199
},
137
200
),
138
201
call (
139
202
"textDocument/publishDiagnostics" ,
140
203
params = {
141
- "uri" : "cell_2_uri " ,
204
+ "uri" : "cell_4_uri " ,
142
205
"diagnostics" : [
143
206
{
144
- "source" : "pycodestyle " ,
207
+ "source" : "pyflakes " ,
145
208
"range" : {
146
- "start" : {"line" : 0 , "character" : 5 },
147
- "end" : {"line" : 0 , "character" : 5 },
209
+ "start" : {"line" : 0 , "character" : 0 },
210
+ "end" : {"line" : 0 , "character" : 2 },
148
211
},
149
- "message" : "W292 no newline at end of file" ,
150
- "code" : "W292" ,
151
- "severity" : 2 ,
152
- }
212
+ "message" : "undefined name 'x'" ,
213
+ "severity" : 1 ,
214
+ },
215
+ ],
216
+ },
217
+ ),
218
+ call (
219
+ "textDocument/publishDiagnostics" ,
220
+ params = {
221
+ "uri" : "cell_5_uri" ,
222
+ "diagnostics" : [
223
+ {
224
+ "source" : "pyflakes" ,
225
+ "range" : {
226
+ "start" : {"line" : 0 , "character" : 0 },
227
+ "end" : {"line" : 0 , "character" : 2 },
228
+ },
229
+ "message" : "undefined name 'y'" ,
230
+ "severity" : 1 ,
231
+ },
153
232
],
154
233
},
155
234
),
156
235
]
157
236
mock_notify .assert_has_calls (expected_call_args )
158
237
159
238
160
- def test_notebook_document__did_change (client_server_pair ): # pylint: disable=redefined-outer-name
239
+ def test_notebook_document__did_change (
240
+ client_server_pair ,
241
+ ): # pylint: disable=redefined-outer-name
161
242
client , server = client_server_pair
162
243
client ._endpoint .request (
163
244
"initialize" ,
@@ -166,7 +247,7 @@ def test_notebook_document__did_change(client_server_pair): # pylint: disable=r
166
247
"rootPath" : os .path .dirname (__file__ ),
167
248
"initializationOptions" : {},
168
249
},
169
- ).result (timeout = CALL_TIMEOUT )
250
+ ).result (timeout = CALL_TIMEOUT_IN_SECONDS )
170
251
171
252
# Open notebook
172
253
with patch .object (server ._endpoint , "notify" ) as mock_notify :
@@ -274,7 +355,17 @@ def test_notebook_document__did_change(client_server_pair): # pylint: disable=r
274
355
},
275
356
"message" : "'sys' imported but unused" ,
276
357
"severity" : 2 ,
277
- }
358
+ },
359
+ {
360
+ "source" : "pycodestyle" ,
361
+ "range" : {
362
+ "start" : {"line" : 0 , "character" : 10 },
363
+ "end" : {"line" : 0 , "character" : 10 },
364
+ },
365
+ "message" : "W292 no newline at end of file" ,
366
+ "code" : "W292" ,
367
+ "severity" : 2 ,
368
+ },
278
369
],
279
370
},
280
371
)
@@ -349,7 +440,17 @@ def test_notebook_document__did_change(client_server_pair): # pylint: disable=r
349
440
},
350
441
"message" : "undefined name 'x'" ,
351
442
"severity" : 1 ,
352
- }
443
+ },
444
+ {
445
+ "source" : "pycodestyle" ,
446
+ "range" : {
447
+ "start" : {"line" : 0 , "character" : 1 },
448
+ "end" : {"line" : 0 , "character" : 1 },
449
+ },
450
+ "message" : "W292 no newline at end of file" ,
451
+ "code" : "W292" ,
452
+ "severity" : 2 ,
453
+ },
353
454
],
354
455
},
355
456
),
@@ -406,7 +507,9 @@ def test_notebook_document__did_change(client_server_pair): # pylint: disable=r
406
507
mock_notify .assert_has_calls (expected_call_args )
407
508
408
509
409
- def test_notebook__did_close (client_server_pair ): # pylint: disable=redefined-outer-name
510
+ def test_notebook__did_close (
511
+ client_server_pair ,
512
+ ): # pylint: disable=redefined-outer-name
410
513
client , server = client_server_pair
411
514
client ._endpoint .request (
412
515
"initialize" ,
@@ -415,7 +518,7 @@ def test_notebook__did_close(client_server_pair): # pylint: disable=redefined-
415
518
"rootPath" : os .path .dirname (__file__ ),
416
519
"initializationOptions" : {},
417
520
},
418
- ).result (timeout = CALL_TIMEOUT )
521
+ ).result (timeout = CALL_TIMEOUT_IN_SECONDS )
419
522
420
523
# Open notebook
421
524
with patch .object (server ._endpoint , "notify" ) as mock_notify :
0 commit comments