Skip to content

Adopt new Python extensions non-blocking API for interpreter disocvery #7583

@karrtikr

Description

@karrtikr

Three discovery APIs are being added for Jupyter which is meant to replace existing getInterpreters() API: microsoft/vscode-python#17452

type PythonApiForJupyterExtension = {
     ...
    /**
     * IInterpreterService
     */
    readonly refreshPromise: Promise<void> | undefined;
    /**
     * IInterpreterService
     */
    readonly onDidChangeInterpreters: Event<PythonEnvironmentsChangedEvent>;
    /**
     * Equivalent to getInterpreters() in IInterpreterService
     */
    getKnownInterpreters(resource?: Uri): PythonEnvironment[];
    /**
     * Equivalent to getAllInterpreters() in IInterpreterService
     */
    getInterpreters(resource?: Uri): Promise<PythonEnvironment[]>;
    ...

Previous behavior:

Existing getInterpreters() is an asynchronus blocking API, so it waits until all of discovery is completed the first time it is called. Subsequent calls return instantaneously from cache if the same resource is queried again.

New behavior:

  • New getKnownInterpreters() simply returns whatever is currently in cache. It is useful when we do not need all of the interpreters at once, which is usually the case. In the Python extension we are able to replace all instances of getInterpreters() with getKnownInterpreters(). Do note that the kind info returned by this API may change as refresh progresses.
  • onDidChangeInterpreters fires when an environment gets added/removed/updated in cache. Event properties tracks the old and new environments accordingly.
  • Python extension triggers a refresh in background when the extension loads for the first time, which is when refreshPromise is set. It can be used to implement now deprecated getInterpreters() in the following way:
    /** Gets all interpreters **/
    public async getInterpreters(resource?: Uri): Promise<PythonEnvironment[]> {
        await this.refreshPromise; // Wait for the refresh to finish so that the cache contains all environments.
        return getKnownInterpreters(resource); // Return from cache.
    }
  • getInterpreterDetails() is still available as before, and can be used to get complete and reliable information on environments. As it is a blocking call, it's recommend to only use it if complete information is needed, which is generally only the case for selected interpreters.

You can the see the new API in action here in our dynamic quickpick microsoft/vscode-python#17043 (comment).

Note: Any internal interpreter list caching that was recently added should go away once onDidChangeInterpreters events are available.

Changes regarding quickpick API

We also used to expose getSuggestions API for the quickpick, which has the same problem as getInterpreters(). The following non-blocking API is being added to replace it:

getKnownSuggestions(resource: Resource): Promise<IInterpreterQuickPickItem[]>;

It can be used in combination of refreshPromise to get all suggestions. Let me know if you have any questions! 😄

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions