Skip to content

Sort environments by assumed usefulness

Kim-Adeline Miguel edited this page Jun 18, 2021 · 5 revisions

This is a design document for the new environment sorting logic we will implement (#16520).

Motivation

Currently, environments are sorted by Python version > architecture (if any) > company name (if any). This hampers discoverability, and we believe that sorting them with the most useful ones at the top will improve the environment selection experience.

"Usefulness" would be determined by environment type:

  • Local environments (e.g. venv) will be closest to the top of the quickpick;
  • Globally-installed environments (e.g. $WORK_ON or conda) will follow;
  • Global installs (e.g. /usr/bin/python3.9) will be last.

And then within each category, sort with the most recent Python versions first.

Scope

The work done here covers the quickpick that appears when the Python: Select Interpreter command is triggered. This new sorting logic will also impact the auto-selection process, which we will discuss once the sorting logic is implemented.

Alternative Considered

An option could be to still sort by Python version, but by descending order instead of the current ascending logic. Even though it is simpler that the logic we decided on, it doesn't differentiate between environment types, and doesn't suggest that local environments would be more preferable to the user.

Architecture

The quickpick gets populated by IInterpreterSelector.getSuggestions:

    public async getSuggestions(resource: Resource, ignoreCache?: boolean): Promise<IInterpreterQuickPickItem[]> {
        const interpreters = await this.interpreterManager.getInterpreters(resource, {
            onSuggestion: true,
            ignoreCache,
        });
        interpreters.sort(this.interpreterComparer.compare.bind(this.interpreterComparer));
        return Promise.all(interpreters.map((item) => this.suggestionToQuickPickItem(item, resource)));
    }

Environments are retrieved from interpreterManager.getInterpreters, but the real sorting magic happens in interpreters.sort(this.interpreterComparer.compare.bind(this.interpreterComparer)), which is an instance of the InterpreterComparer class implementing the IInterpreterComparer interface:

export interface IInterpreterComparer {
    compare(a: PythonEnvironment, b: PythonEnvironment): number;
}

Since the comparison is stateless, the new logic can live in its own function (instead of a class), following this sorting algorithm:

  • Check the environment type: local > global environment > global install;
  • Then, compare by descending Python version;
  • Finally, compare with the rest of the environment info: architecture, company name, and environment name.

APIs

No externally-facing APIs will be exposed.

Telemetry and Experimentation

This sorting algorithm will be gated behind an experiment, so we can see how it impacts our current metrics. Since it's a change we want to roll out to all users (instead of just testing hypotheses), the experiment will have a quick progression.

Testing Strategy

Unit tests will be written for the comparison function. Tests should also be added to interpreterManager.getInterpreters to make sure that the sorting logic works for both experiment groups.

Clone this wiki locally