Skip to content

Commit 6463113

Browse files
authored
Merge branch 'master' into FixTruncatedJediResponses
2 parents b9c08c5 + e9b115d commit 6463113

File tree

14 files changed

+402
-116
lines changed

14 files changed

+402
-116
lines changed

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
## CHANGELOG
22

3+
### `@krassowski/jupyterlab-lsp 3.3.0` (unreleased)
4+
5+
- features:
6+
7+
- added a timeout for kernel completion, with the default of 600ms ([#496])
8+
- added an option to skip waiting for kernel completions if busy, off by default ([#496])
9+
10+
- bug fixes:
11+
12+
- delayed completion suggestions will no longer show up if cursor moved to another line ([#496])
13+
- changes in notebooks after kernel restart or file rename will now be recorded by the language server again ([#496])
14+
- when either of kernel providers: kernel or LSP server fails, the completion from the other will still be shown ([#496])
15+
16+
[#496]: https://github.com/krassowski/jupyterlab-lsp/pull/496
17+
318
### `@krassowski/jupyterlab-lsp 3.2.0` (2021-01-24)
419

520
- features:

README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,14 @@ Advanced static-analysis autocompletion without a running kernel
5454

5555
![autocompletion](https://raw.githubusercontent.com/krassowski/jupyterlab-lsp/master/examples/screenshots/autocompletion.png)
5656

57-
> When a kernel is available the suggestions from the kernel (such as keys of a
58-
> dict and columns of a DataFrame autocompletion) are merged with the suggestions
59-
> from the Language Server (currently only in notebook).
57+
#### The runtime kernel suggestions are still there
58+
59+
When a kernel is available the suggestions from the kernel (such as keys of a
60+
dict and columns of a DataFrame autocompletion) are merged with the suggestions
61+
from the Language Server (currently only in notebook).
62+
63+
If the kernel is too slow to respond promptly only the LSP static analysis suggestions will be shown (default threshold: 0.6s).
64+
You can configure the completer to not attempt to fetch the kernel completions if the kernel is busy (skipping the 0.6s timeout).
6065

6166
### Rename
6267

atest/03_Notebook.robot

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,41 @@ Foreign Extractors
6666
Code Overrides
6767
${file} = Set Variable Code overrides.ipynb
6868
Setup Notebook Python ${file}
69-
${virtual_path} = Set Variable ${VIRTUALDOCS DIR}${/}Code overrides.ipynb
69+
${virtual_path} = Set Variable ${VIRTUALDOCS DIR}${/}${file}
7070
Wait Until Created ${virtual_path}
7171
Wait Until Keyword Succeeds 10x 1s File Should Not Be Empty ${virtual_path}
7272
${document} = Get File ${virtual_path}
7373
Should Be Equal ${document} get_ipython().run_line_magic("ls", "")\n\n\nget_ipython().run_line_magic("pip", " freeze")\n
74+
[Teardown] Clean Up After Working With File Code overrides.ipynb
75+
76+
Adding Text To Cells Is Reflected In Virtual Document
77+
${file} = Set Variable Empty.ipynb
78+
Setup Notebook Python ${file}
79+
${virtual_path} = Set Variable ${VIRTUALDOCS DIR}${/}${file}
80+
Wait Until Created ${virtual_path}
81+
Enter Cell Editor 1
82+
Press Keys None cell_1
83+
Lab Command Insert Cell Below
84+
Enter Cell Editor 2
85+
Press Keys None cell_2
86+
Wait Until Keyword Succeeds 3x 1s File Content Should Be Equal ${virtual_path} cell_1\n\n\ncell_2\n
87+
[Teardown] Clean Up After Working With File Empty.ipynb
88+
89+
Adding Text To Cells After Kernel Restart
90+
${file} = Set Variable Empty.ipynb
91+
Setup Notebook Python ${file}
92+
${virtual_path} = Set Variable ${VIRTUALDOCS DIR}${/}${file}
93+
Wait Until Created ${virtual_path}
94+
Enter Cell Editor 1
95+
Lab Command Insert Cell Below
96+
Enter Cell Editor 2 line=1
97+
Press Keys None text
98+
Wait Until Keyword Succeeds 3x 1s File Content Should Be Equal ${virtual_path} \n\n\ntext\n
99+
[Teardown] Clean Up After Working With File Empty.ipynb
100+
101+
*** Keywords ***
102+
File Content Should Be Equal
103+
[Arguments] ${file} ${text}
104+
Wait Until Keyword Succeeds 5x 1s File Should Not Be Empty ${file}
105+
${document} = Get File ${file}
106+
Should Be Equal ${document} ${text}

atest/04_Interface/Statusbar.robot

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,7 @@ Statusbar Popup Opens
2222
Status Changes Between Notebooks
2323
Setup Notebook Python Python.ipynb
2424
Wait Until Fully Initialized
25-
Lab Command New Notebook
26-
Wait For Dialog
27-
# Kernel selection dialog shows up, accept Python as default kernel
28-
Accept Default Dialog Option
25+
Open New Notebook
2926
Element Should Contain ${STATUSBAR} Waiting...
3027
Wait Until Fully Initialized
3128
Switch To Tab Python.ipynb

atest/05_Features/Completion.robot

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ Resource ../Keywords.robot
88
*** Variables ***
99
${COMPLETER_BOX} css:.jp-Completer.jp-HoverBox
1010
${DOCUMENTATION_PANEL} css:.jp-Completer-docpanel
11+
${KERNEL_BUSY_INDICATOR} css:.jp-NotebookPanel-toolbar div[title="Kernel Busy"]
1112

1213
*** Test Cases ***
13-
Works With Kernel Running
14+
Works When Kernel Is Idle
15+
Configure JupyterLab Plugin {"kernelResponseTimeout": -1, "waitForBusyKernel": false} plugin id=${COMPLETION PLUGIN ID}
1416
[Documentation] The suggestions from kernel and LSP should get integrated.
1517
Enter Cell Editor 1 line=2
1618
Capture Page Screenshot 01-entered-cell.png
@@ -27,6 +29,15 @@ Works With Kernel Running
2729
${content} = Get Cell Editor Content 1
2830
Should Contain ${content} TabError
2931

32+
Uses LSP Completions When Kernel Resoponse Times Out
33+
Configure JupyterLab Plugin {"kernelResponseTimeout": 1, "waitForBusyKernel": true} plugin id=${COMPLETION PLUGIN ID}
34+
Should Complete While Kernel Is Busy
35+
36+
Uses LSP Completions When Kernel Is Busy
37+
[Documentation] When kernel is not available the best thing is to show some suggestions (LSP) rather than none.
38+
Configure JupyterLab Plugin {"kernelResponseTimeout": -1, "waitForBusyKernel": false} plugin id=${COMPLETION PLUGIN ID}
39+
Should Complete While Kernel Is Busy
40+
3041
Works When Kernel Is Shut Down
3142
Lab Command Shut Down All Kernels…
3243
Wait For Dialog
@@ -42,9 +53,7 @@ Works When Kernel Is Shut Down
4253
Completer Should Not Suggest %%timeit
4354

4455
Works After Kernel Restart In New Cells
45-
Lab Command Restart Kernel…
46-
Wait For Dialog
47-
Accept Default Dialog Option
56+
Restart Kernel
4857
Enter Cell Editor 1 line=2
4958
# works in old cells
5059
Trigger Completer
@@ -134,6 +143,7 @@ Completion Works For Tokens Separated By Space
134143

135144
Kernel And LSP Completions Merge Prefix Conflicts Are Resolved
136145
[Documentation] Reconciliate Python kernel returning prefixed completions and LSP (pyls) not-prefixed ones
146+
Configure JupyterLab Plugin {"kernelResponseTimeout": -1, "waitForBusyKernel": false} plugin id=${COMPLETION PLUGIN ID}
137147
# For more details see: https://github.com/krassowski/jupyterlab-lsp/issues/30#issuecomment-576003987
138148
# `import os.pat<tab>` → `import os.pathsep`
139149
Enter Cell Editor 15 line=1
@@ -290,3 +300,30 @@ Completer Should Include Documentation
290300
[Arguments] ${text}
291301
Wait Until Page Contains Element ${DOCUMENTATION_PANEL} timeout=10s
292302
Wait Until Keyword Succeeds 10 x 1 s Element Should Contain ${DOCUMENTATION_PANEL} ${text}
303+
Element Should Contain ${DOCUMENTATION_PANEL} ${text}
304+
305+
Restart Kernel
306+
Lab Command Restart Kernel…
307+
Wait For Dialog
308+
Accept Default Dialog Option
309+
310+
Count Completer Hints
311+
${count} = Get Element Count css:.jp-Completer-item
312+
[Return] ${count}
313+
314+
Should Complete While Kernel Is Busy
315+
# Run the cell with sleep(20)
316+
Enter Cell Editor 17
317+
# for some reason the lab command selects another cell along the way...
318+
# Lab Command Run Selected Cells And Don't Advance
319+
Press Keys None CTRL+ENTER
320+
# Confirm that the kernel is busy
321+
Wait Until Page Contains Element ${KERNEL_BUSY_INDICATOR} timeout=5s
322+
# Enter a cell with "t"
323+
Enter Cell Editor 18
324+
# Check if completion worked
325+
Enter Cell Editor 1 line=2
326+
Trigger Completer timeout=10s
327+
Completer Should Suggest test
328+
# Confirm that the kernel indicator was busy all along
329+
Page Should Contain Element ${KERNEL_BUSY_INDICATOR}

atest/Keywords.robot

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,3 +413,9 @@ Measure Cursor Position
413413
Switch To Tab
414414
[Arguments] ${file}
415415
Click Element ${JLAB XP DOCK TAB}\[contains(., '${file}')]
416+
417+
Open New Notebook
418+
Lab Command New Notebook
419+
Wait For Dialog
420+
# Kernel selection dialog shows up, accept Python as default kernel
421+
Accept Default Dialog Option

atest/examples/Completion.ipynb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,32 @@
124124
"source": [
125125
"import os.pat"
126126
]
127+
},
128+
{
129+
"cell_type": "markdown",
130+
"metadata": {},
131+
"source": [
132+
"LSP completion works when kernel is busy:"
133+
]
134+
},
135+
{
136+
"cell_type": "code",
137+
"execution_count": null,
138+
"metadata": {},
139+
"outputs": [],
140+
"source": [
141+
"from time import sleep\n",
142+
"sleep(20)"
143+
]
144+
},
145+
{
146+
"cell_type": "code",
147+
"execution_count": null,
148+
"metadata": {},
149+
"outputs": [],
150+
"source": [
151+
"t"
152+
]
127153
}
128154
],
129155
"metadata": {

atest/examples/Empty.ipynb

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": null,
6+
"metadata": {},
7+
"outputs": [],
8+
"source": []
9+
}
10+
],
11+
"metadata": {
12+
"kernelspec": {
13+
"display_name": "Python 3",
14+
"language": "python",
15+
"name": "python3"
16+
},
17+
"language_info": {
18+
"codemirror_mode": {
19+
"name": "ipython",
20+
"version": 3
21+
},
22+
"file_extension": ".py",
23+
"mimetype": "text/x-python",
24+
"name": "python",
25+
"nbconvert_exporter": "python",
26+
"pygments_lexer": "ipython3",
27+
"version": "3.7.9"
28+
}
29+
},
30+
"nbformat": 4,
31+
"nbformat_minor": 4
32+
}

packages/jupyterlab-lsp/schema/completion.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,19 @@
2424
"type": "string"
2525
},
2626
"default": ["comment", "string"],
27-
"description": "An array of CodeMirror tokens for which the auto-invoke should be suppressed. The token names vary between languages (modes)."
27+
"description": "An array of CodeMirror tokens for which the auto-invoke should be suppressed. Adding 'def' will prevent continuous hinting when writing a function name in Python, Julia, JavaScript and other languages. The token names vary between languages (modes)."
28+
},
29+
"kernelResponseTimeout": {
30+
"title": "Kernel completion response timeout",
31+
"default": 600,
32+
"type": "number",
33+
"description": "The time to wait for the kernel completions suggestions in milliseconds. Set to 0 to disable kernel completions, or to -1 to wait indefinitely (not recommended)."
34+
},
35+
"waitForBusyKernel": {
36+
"title": "Wait for kernel if busy",
37+
"default": true,
38+
"type": "boolean",
39+
"description": "Should an attempt to get the kernel response (with timeout as specified by kernelResponseTimeout) be made if kernel is busy? If you often write code in notebook while computations are running for long time (e.g. training models), turning this off might give you faster response times."
2840
},
2941
"theme": {
3042
"title": "Completer theme",

packages/jupyterlab-lsp/src/adapters/adapter.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,14 @@ export abstract class WidgetAdapter<T extends IDocumentWidget> {
221221
this
222222
);
223223

224+
// pretend that all editors were removed to trigger the disconnection of even handlers
225+
// they will be connected again on new connection
226+
for (let editor of this.editors) {
227+
this.editorRemoved.emit({
228+
editor: editor
229+
});
230+
}
231+
224232
for (let adapter of this.adapters.values()) {
225233
adapter.dispose();
226234
}
@@ -392,6 +400,7 @@ export abstract class WidgetAdapter<T extends IDocumentWidget> {
392400
return;
393401
}
394402
this.virtual_editor = virtual_editor;
403+
this.connect_contentChanged_signal();
395404
}
396405

397406
/**
@@ -538,7 +547,7 @@ export abstract class WidgetAdapter<T extends IDocumentWidget> {
538547
* (range) updates this can be still implemented by comparison of before/after states of the
539548
* virtual documents, which is even more resilient and -obviously - editor-independent.
540549
*/
541-
connect_contentChanged_signal() {
550+
private connect_contentChanged_signal() {
542551
this.widget.context.model.contentChanged.connect(
543552
this.onContentChanged,
544553
this

0 commit comments

Comments
 (0)