-
Notifications
You must be signed in to change notification settings - Fork 338
Support remote commands in the kernel picker #10602
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This can be merged after endgame. |
export const mementoKeyToIndicateIfConnectingToLocalKernelsOnly = 'connectToLocalKernelsOnly'; | ||
|
||
@injectable() | ||
export class ServerConnectionType { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I deleted this class and moved its functionality to the JupyterServerUriStorage class.
The reason for this is that this class was essentially exposing the internal state of the JupyterServerUriStorage class and they had to be in sync. And they weren't always.
To make this impossible, I just removed this class altogether and added a new interface to the JupyterServerUriStorage class. Most of the changes for this is simply using an interface instead of a class.
Good use case for why we should expose interfaces to the DI container and not classes.
) { | ||
// Remember if local only |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
THis is the code that was originally in the serverConnectionType.ts file.
title: allowLocal | ||
? DataScience.jupyterSelectURIQuickPickTitle() | ||
: DataScience.jupyterSelectURIQuickPickTitleRemoteOnly(), | ||
acceptFilterBoxTextAsSelection: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since URI entering happens on the quick pick, we can't use input box validation. So I added this to allow a modal dialog to appear.
@@ -183,10 +180,6 @@ export class ControllerLoader implements IControllerLoader, IExtensionSyncActiva | |||
|
|||
private async loadControllersImpl(cancelToken: vscode.CancellationToken) { | |||
let cachedConnections = await this.listKernels(cancelToken, 'useCache'); | |||
// Remove all remove kernels if we're no longer interested in them. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All filtering is done in the controllerRegistration.
if (message) { | ||
resolvable = false; | ||
// No validation allowed on a quick pick. Have to put up a dialog instead | ||
await this.shell.showErrorMessage(message, { modal: true }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I need to change this to support markdown. For remote there's a URL the user can click on and it doesn't seem to be clickable at the moment. Maybe dialogs don't support this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think they don't sadly. Our "Install Python" popup tries to link to Python.org, but it's not clickable. Pretty sure when we talked about it in v-team that's just how it is.
// Activate all activation services together. Don't fail them all if one fails. | ||
await Promise.all([ | ||
this.singleActivationServices.map(async (item) => { | ||
const promise = item.activate(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had a bug in my activate and it made the extension not start. Figured this was better.
|
||
assert.equal(showInputBox.firstCall.args[0].value, expectedDefaultUri); | ||
} | ||
|
||
test('Display default uri', async () => { | ||
await testDefaultUri(defaultUri); | ||
}); | ||
test('Display default uri if clipboard is empty', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not supporting the clipboard anymore. Fixes the problem with web where the user may not have clipboard permissions.
New workflow doesn't really need clipboard as the user can also filter in the same entry so defaulting to the url in the clipboard doesn't really make sense.
@@ -955,5 +955,10 @@ | |||
"Installer.dataScienceInstallPrompt": "Data Science library {0} is not installed. Install?", | |||
"Products.installingModule": "Installing {0}", | |||
"DataScience.webNotSupported": "Operation not supported in web version of Jupyter Extension.", | |||
"DataScience.outputSizeExceedLimit": "Output exceeds the <a href={0}>size limit</a>. Open the full output data <a href={1}>in a text editor</a>" | |||
"DataScience.outputSizeExceedLimit": "Output exceeds the <a href={0}>size limit</a>. Open the full output data <a href={1}>in a text editor</a>", | |||
"DataScience.installPythonTitle": "Install Python", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@IanMatthewHuff looks like this will need to be reviewed closly as you're also working in the similar area (installing python when its missing). I.e. you might want to review the workflow & the changes.
Feels like this stuff related to no python might require its own folder/set of classes & its been worked on for months if not years (i.e. workflow keeps changing, hence better to keep it isolated & easier to manage)
Agai, I haven't reviewed anything yet, but just a thought about this (prompting to install python - getting started) part of the exetnsion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DonJayamanne I think Rich was just adding on the Command localization that I missed in my addition. The only real conflict to consider here is just the fact that we won't have only one command anymore in the new user scenario. Means that we don't get that nice "just hit the run button" launch, but we can tweak that as we move forward. Maybe prioritization for commands in the kernel picker somehow.
Codecov Report
@@ Coverage Diff @@
## main #10602 +/- ##
=======================================
- Coverage 71% 70% -1%
=======================================
Files 475 475
Lines 28056 28205 +149
Branches 4706 4736 +30
=======================================
- Hits 19990 19977 -13
- Misses 6187 6348 +161
- Partials 1879 1880 +1
|
await this.addToUriList(uri, Date.now(), displayName); | ||
await this.setUri(uri); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like addToUriList is happening in two spots? Both here and in setUri, do we need both?
@@ -188,17 +157,17 @@ export class JupyterServerSelector { | |||
); | |||
items.splice(items.indexOf(e.item), 1); | |||
onDidChangeItems.fire(items.concat([])); | |||
} else if (e.button) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry a bit lost on this bit. Maybe there are just more buttons added and I'm not there in the review yet? I thought there was only the remove button. So having this case seems odd since it's not scoped to a specific button. Just any button that doesn't match the remove button goes back?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah there's only two buttons for the server selector. Back and the 'delete' this URI.
|
||
// Then group them by kind | ||
const kernelsPerCategory = groupBy(picks, (a, b) => | ||
compareIgnoreCase(a.controller.controller.kind || 'z', b.controller.controller.kind || 'z') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the 'z' for alphabetizing? Doesn't seem like that would work for non-en.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I copied this from the core, but it does seem wrong. 'z' only works in ascii.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll enter an issue to relook at this in both the core and here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
||
public get onCreated(): Event<IVSCodeNotebookController> { | ||
return this.creationEmitter.event; | ||
} | ||
public get values(): IVSCodeNotebookController[] { | ||
return [...this.registeredControllers.values()]; | ||
} | ||
private get connections(): KernelConnectionMetadata[] { | ||
return [...this.registeredConnections.values()]; | ||
private get metadatas(): KernelConnectionMetadata[] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a naming opinion here. But to me this takes it the wrong direction. Metadata is super generic. Can mean anything. Before a 'connection' kinda represented a possible connection. It's wordier, but 'connectionMetadata' if we wanted to be clearer.
if (message) { | ||
resolvable = false; | ||
// No validation allowed on a quick pick. Have to put up a dialog instead | ||
await this.shell.showErrorMessage(message, { modal: true }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think they don't sadly. Our "Install Python" popup tries to link to Python.org, but it's not clickable. Pretty sure when we talked about it in v-team that's just how it is.
Seems good to me. This is going to be a big improvement. Honestly the hardest part of this PR was that I find the MultiStep input control flow really wacky and hard to read. But that's not anything on you or this PR, I think I just need to play with that myself a bit versus looking at the PR. |
I agree about the multistep input. It's really a state machine. I think it would be better with an iterator type pattern instead of a promise type pattern. Took me a long time to get the promises to work out correctly. |
@@ -54,11 +51,7 @@ export type SelectJupyterUriCommandSource = | |||
| 'prompt'; | |||
@injectable() | |||
export class JupyterServerSelector { | |||
private readonly localLabel = `$(zap) ${DataScience.jupyterSelectURINoneLabel()}`; | |||
private readonly newLabel = `$(server) ${DataScience.jupyterSelectURINewLabel()}`; | |||
private readonly remoteLabel = `$(server) ${DataScience.jupyterSelectURIRemoteLabel()}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these not needed anymore?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No they shouldn't be. Maybe. I think we might need the 'None' label.
} | ||
} | ||
return result; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohh fancy! Would it make sense to have a common place for functional utilities like this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe. Not sure where that would be. It's only used in this class at the moment.
@@ -118,7 +118,7 @@ suite('VSCode Notebook - Run By Line', function () { | |||
); | |||
|
|||
// Give the files a quick chance to clean up | |||
await sleep(1000); | |||
await sleep(3000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test was failing attempting to see if files were cleaned up. Stopped failing after I did this, so yeah probably.
There's likely another way to accomplish this but I wasn't working on this code so I just wanted the test to pass
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok that makes sense! Thanks for the context
Fixes #10435
Fixes #10363
Fixes #10191
Refactor remote support such that:
Telemetry for these new modes is already handled. Commands send telemetry on their own and remote/local mode is already sent in telemetry.
package-lock.json
has been regenerated by runningnpm install
(if dependencies have changed).