Skip to content

Commit

Permalink
More changes (broken ) state
Browse files Browse the repository at this point in the history
  • Loading branch information
karthiknadig committed Jul 18, 2024
1 parent 26834d7 commit a414a65
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 118 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import { Disposable, EventEmitter, Event, Uri, LogOutputChannel } from 'vscode';
import { Disposable, EventEmitter, Event, Uri } from 'vscode';
import * as ch from 'child_process';
import * as path from 'path';
import * as rpc from 'vscode-jsonrpc/node';
Expand All @@ -17,7 +17,7 @@ import { VENVFOLDERS_SETTING_KEY, VENVPATH_SETTING_KEY } from '../lowLevel/custo
import { getUserHomeDir } from '../../../../common/utils/platform';
import { createLogOutputChannel } from '../../../../common/vscodeApis/windowApis';
import { sendNativeTelemetry, NativePythonTelemetry } from './nativePythonTelemetry';
import { traceError } from '../../../../logging';
import { NativePythonEnvironmentKind } from './nativePythonUtils';

const untildify = require('untildify');

Expand All @@ -29,7 +29,7 @@ export interface NativeEnvInfo {
displayName?: string;
name?: string;
executable?: string;
kind?: PythonEnvironmentKind;
kind?: NativePythonEnvironmentKind;
version?: string;
prefix?: string;
manager?: NativeEnvManagerInfo;
Expand All @@ -41,32 +41,13 @@ export interface NativeEnvInfo {
symlinks?: string[];
}

export enum PythonEnvironmentKind {
Conda = 'Conda',
Homebrew = 'Homebrew',
Pyenv = 'Pyenv',
GlobalPaths = 'GlobalPaths',
PyenvVirtualEnv = 'PyenvVirtualEnv',
Pipenv = 'Pipenv',
Poetry = 'Poetry',
MacPythonOrg = 'MacPythonOrg',
MacCommandLineTools = 'MacCommandLineTools',
LinuxGlobal = 'LinuxGlobal',
MacXCode = 'MacXCode',
Venv = 'Venv',
VirtualEnv = 'VirtualEnv',
VirtualEnvWrapper = 'VirtualEnvWrapper',
WindowsStore = 'WindowsStore',
WindowsRegistry = 'WindowsRegistry',
}

export interface NativeEnvManagerInfo {
tool: string;
executable: string;
version?: string;
}

export function isNativeInfoEnvironment(info: NativeEnvInfo | NativeEnvManagerInfo): info is NativeEnvInfo {
export function isNativeEnvInfo(info: NativeEnvInfo | NativeEnvManagerInfo): info is NativeEnvInfo {
if ((info as NativeEnvManagerInfo).tool) {
return false;
}
Expand All @@ -91,9 +72,9 @@ export interface NativePythonFinder extends Disposable {
*
* If a Uri is provided, then it will search for python environments in that location (ignoring workspaces).
* Uri can be a file or a folder.
* If a PythonEnvironmentKind is provided, then it will search for python environments of that kind (ignoring workspaces).
* If a NativePythonEnvironmentKind is provided, then it will search for python environments of that kind (ignoring workspaces).
*/
refresh(options?: PythonEnvironmentKind | Uri[]): AsyncIterable<NativeEnvInfo | NativeEnvManagerInfo>;
refresh(options?: NativePythonEnvironmentKind | Uri[]): AsyncIterable<NativeEnvInfo | NativeEnvManagerInfo>;
/**
* Will spawn the provided Python executable and return information about the environment.
* @param executable
Expand All @@ -105,48 +86,12 @@ export interface NativePythonFinder extends Disposable {
getCondaInfo(): Promise<NativeCondaInfo>;
}

const mapping = new Map<PythonEnvironmentKind, PythonEnvKind>([
[PythonEnvironmentKind.Conda, PythonEnvKind.Conda],
[PythonEnvironmentKind.GlobalPaths, PythonEnvKind.OtherGlobal],
[PythonEnvironmentKind.Pyenv, PythonEnvKind.Pyenv],
[PythonEnvironmentKind.PyenvVirtualEnv, PythonEnvKind.Pyenv],
[PythonEnvironmentKind.Pipenv, PythonEnvKind.Pipenv],
[PythonEnvironmentKind.Poetry, PythonEnvKind.Poetry],
[PythonEnvironmentKind.VirtualEnv, PythonEnvKind.VirtualEnv],
[PythonEnvironmentKind.VirtualEnvWrapper, PythonEnvKind.VirtualEnvWrapper],
[PythonEnvironmentKind.Venv, PythonEnvKind.Venv],
[PythonEnvironmentKind.WindowsRegistry, PythonEnvKind.System],
[PythonEnvironmentKind.WindowsStore, PythonEnvKind.MicrosoftStore],
[PythonEnvironmentKind.Homebrew, PythonEnvKind.System],
[PythonEnvironmentKind.LinuxGlobal, PythonEnvKind.System],
[PythonEnvironmentKind.MacCommandLineTools, PythonEnvKind.System],
[PythonEnvironmentKind.MacPythonOrg, PythonEnvKind.System],
[PythonEnvironmentKind.MacXCode, PythonEnvKind.System],
]);

export function categoryToKind(category?: PythonEnvironmentKind, logger?: LogOutputChannel): PythonEnvKind {
if (!category) {
return PythonEnvKind.Unknown;
}
const kind = mapping.get(category);
if (kind) {
return kind;
}

if (logger) {
logger.error(`Unknown Python Environment category '${category}' from Native Locator.`);
} else {
traceError(`Unknown Python Environment category '${category}' from Native Locator.`);
}
return PythonEnvKind.Unknown;
}

interface NativeLog {
level: string;
message: string;
}

class NativeGlobalPythonFinderImpl extends DisposableBase implements NativePythonFinder {
class NativePythonFinderImpl extends DisposableBase implements NativePythonFinder {
private readonly connection: rpc.MessageConnection;

private firstRefreshResults: undefined | (() => AsyncGenerator<NativeEnvInfo, void, unknown>);
Expand All @@ -169,7 +114,7 @@ class NativeGlobalPythonFinderImpl extends DisposableBase implements NativePytho
return environment;
}

async *refresh(options?: PythonEnvironmentKind | Uri[]): AsyncIterable<NativeEnvInfo> {
async *refresh(options?: NativePythonEnvironmentKind | Uri[]): AsyncIterable<NativeEnvInfo> {
if (this.firstRefreshResults) {
// If this is the first time we are refreshing,
// Then get the results from the first refresh.
Expand Down Expand Up @@ -315,7 +260,7 @@ class NativeGlobalPythonFinderImpl extends DisposableBase implements NativePytho
}

private doRefresh(
options?: PythonEnvironmentKind | Uri[],
options?: NativePythonEnvironmentKind | Uri[],
): { completed: Promise<void>; discovered: Event<NativeEnvInfo | NativeEnvManagerInfo> } {
const disposable = this._register(new DisposableStore());
const discovered = disposable.add(new EventEmitter<NativeEnvInfo | NativeEnvManagerInfo>());
Expand Down Expand Up @@ -377,7 +322,7 @@ class NativeGlobalPythonFinderImpl extends DisposableBase implements NativePytho
);

type RefreshOptions = {
searchKind?: PythonEnvironmentKind;
searchKind?: NativePythonEnvironmentKind;
searchPaths?: string[];
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,42 +1,61 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import { LogOutputChannel } from 'vscode';
import { PythonEnvKind } from '../../info';
import { traceError } from '../../../../logging';

export function categoryToKind(category?: string): PythonEnvKind {
export enum NativePythonEnvironmentKind {
Conda = 'Conda',
Homebrew = 'Homebrew',
Pyenv = 'Pyenv',
GlobalPaths = 'GlobalPaths',
PyenvVirtualEnv = 'PyenvVirtualEnv',
Pipenv = 'Pipenv',
Poetry = 'Poetry',
MacPythonOrg = 'MacPythonOrg',
MacCommandLineTools = 'MacCommandLineTools',
LinuxGlobal = 'LinuxGlobal',
MacXCode = 'MacXCode',
Venv = 'Venv',
VirtualEnv = 'VirtualEnv',
VirtualEnvWrapper = 'VirtualEnvWrapper',
WindowsStore = 'WindowsStore',
WindowsRegistry = 'WindowsRegistry',
}

const mapping = new Map<NativePythonEnvironmentKind, PythonEnvKind>([
[NativePythonEnvironmentKind.Conda, PythonEnvKind.Conda],
[NativePythonEnvironmentKind.GlobalPaths, PythonEnvKind.OtherGlobal],
[NativePythonEnvironmentKind.Pyenv, PythonEnvKind.Pyenv],
[NativePythonEnvironmentKind.PyenvVirtualEnv, PythonEnvKind.Pyenv],
[NativePythonEnvironmentKind.Pipenv, PythonEnvKind.Pipenv],
[NativePythonEnvironmentKind.Poetry, PythonEnvKind.Poetry],
[NativePythonEnvironmentKind.VirtualEnv, PythonEnvKind.VirtualEnv],
[NativePythonEnvironmentKind.VirtualEnvWrapper, PythonEnvKind.VirtualEnvWrapper],
[NativePythonEnvironmentKind.Venv, PythonEnvKind.Venv],
[NativePythonEnvironmentKind.WindowsRegistry, PythonEnvKind.System],
[NativePythonEnvironmentKind.WindowsStore, PythonEnvKind.MicrosoftStore],
[NativePythonEnvironmentKind.Homebrew, PythonEnvKind.System],
[NativePythonEnvironmentKind.LinuxGlobal, PythonEnvKind.System],
[NativePythonEnvironmentKind.MacCommandLineTools, PythonEnvKind.System],
[NativePythonEnvironmentKind.MacPythonOrg, PythonEnvKind.System],
[NativePythonEnvironmentKind.MacXCode, PythonEnvKind.System],
]);

export function categoryToKind(category?: NativePythonEnvironmentKind, logger?: LogOutputChannel): PythonEnvKind {
if (!category) {
return PythonEnvKind.Unknown;
}
switch (category.toLowerCase()) {
case 'conda':
return PythonEnvKind.Conda;
case 'system':
case 'homebrew':
case 'macpythonorg':
case 'maccommandlinetools':
case 'macxcode':
case 'windowsregistry':
case 'linuxglobal':
return PythonEnvKind.System;
case 'globalpaths':
return PythonEnvKind.OtherGlobal;
case 'pyenv':
return PythonEnvKind.Pyenv;
case 'poetry':
return PythonEnvKind.Poetry;
case 'pipenv':
return PythonEnvKind.Pipenv;
case 'pyenvvirtualenv':
return PythonEnvKind.VirtualEnv;
case 'venv':
return PythonEnvKind.Venv;
case 'virtualenv':
return PythonEnvKind.VirtualEnv;
case 'virtualenvwrapper':
return PythonEnvKind.VirtualEnvWrapper;
case 'windowsstore':
return PythonEnvKind.MicrosoftStore;
default:
return PythonEnvKind.Unknown;
const kind = mapping.get(category);
if (kind) {
return kind;
}

if (logger) {
logger.error(`Unknown Python Environment category '${category}' from Native Locator.`);
} else {
traceError(`Unknown Python Environment category '${category}' from Native Locator.`);
}
return PythonEnvKind.Unknown;
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { PythonEnvCollectionChangedEvent, PythonEnvsWatcher } from '../../watche
import { IEnvsCollectionCache } from './envsCollectionCache';
import {
getNativePythonFinder,
isNativeInfoEnvironment,
isNativeEnvInfo,
NativeEnvInfo,
NativePythonFinder,
} from '../common/nativePythonFinder';
Expand Down Expand Up @@ -300,7 +300,7 @@ export class EnvsCollectionService extends PythonEnvsWatcher<PythonEnvCollection
const executablesFoundByNativeLocator = new Set<string>();
const nativeStopWatch = new StopWatch();
for await (const data of this.nativeFinder.refresh()) {
if (isNativeInfoEnvironment(data)) {
if (isNativeEnvInfo(data)) {
nativeEnvs.push(data);
if (data.executable) {
// Lowercase for purposes of comparison (safe).
Expand Down Expand Up @@ -973,7 +973,7 @@ async function getCondaTelemetry(
const rootPrefixEnvs = await flattenIterable(nativeFinder.refresh([Uri.file(rootPrefix)]));
// Did we find an env with the same prefix?
const rootPrefixEnv = rootPrefixEnvs
.filter(isNativeInfoEnvironment)
.filter(isNativeEnvInfo)
.find((e) => fsPath.normalize(e.prefix || '').toLowerCase() === rootPrefix.toLowerCase());
condaTelemetry.condaRootPrefixEnvsAfterFind = rootPrefixEnvs.length;
condaTelemetry.condaRootPrefixFoundInInfoAfterFind = !!rootPrefixEnv;
Expand Down Expand Up @@ -1012,7 +1012,7 @@ async function getCondaTelemetry(
const defaultPrefixEnvs = await flattenIterable(nativeFinder.refresh([Uri.file(defaultPrefix)]));
// Did we find an env with the same prefix?
const defaultPrefixEnv = defaultPrefixEnvs
.filter(isNativeInfoEnvironment)
.filter(isNativeEnvInfo)
.find((e) => fsPath.normalize(e.prefix || '').toLowerCase() === defaultPrefix.toLowerCase());
condaTelemetry.condaDefaultPrefixEnvsAfterFind = defaultPrefixEnvs.length;
condaTelemetry.condaDefaultPrefixFoundInInfoAfterFind = !!defaultPrefixEnv;
Expand Down
10 changes: 5 additions & 5 deletions src/client/pythonEnvironments/nativeAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
TriggerRefreshOptions,
} from './base/locator';
import { PythonEnvCollectionChangedEvent } from './base/watcher';
import { isNativeInfoEnvironment, NativeEnvInfo, NativePythonFinder } from './base/locators/common/nativePythonFinder';
import { isNativeEnvInfo, NativeEnvInfo, NativePythonFinder } from './base/locators/common/nativePythonFinder';
import { createDeferred, Deferred } from '../common/utils/async';
import { Architecture } from '../common/utils/platform';
import { parseVersion } from './base/info/pythonVersion';
Expand Down Expand Up @@ -150,7 +150,7 @@ function getName(nativeEnv: NativeEnvInfo, kind: PythonEnvKind): string {
return '';
}

function toPythonEnvInfo(finder: NativePythonFinder, nativeEnv: NativeEnvInfo): PythonEnvInfo | undefined {
function toPythonEnvInfo(nativeEnv: NativeEnvInfo): PythonEnvInfo | undefined {
if (!validEnv(nativeEnv)) {
return undefined;
}
Expand Down Expand Up @@ -230,7 +230,7 @@ class NativePythonEnvironments implements IDiscoveryAPI, Disposable {
setImmediate(async () => {
try {
for await (const native of this.finder.refresh()) {
if (!isNativeInfoEnvironment(native) || !validEnv(native)) {
if (!isNativeEnvInfo(native) || !validEnv(native)) {
// eslint-disable-next-line no-continue
continue;
}
Expand Down Expand Up @@ -289,7 +289,7 @@ class NativePythonEnvironments implements IDiscoveryAPI, Disposable {
}

addEnv(native: NativeEnvInfo): void {
const info = toPythonEnvInfo(this.finder, native);
const info = toPythonEnvInfo(native);
if (!info) {
return;
}
Expand All @@ -311,7 +311,7 @@ class NativePythonEnvironments implements IDiscoveryAPI, Disposable {
}
const native = await this.finder.resolve(envPath);
if (native) {
const env = toPythonEnvInfo(this.finder, native);
const env = toPythonEnvInfo(native);
if (env) {
const old = this._envs.find((item) => item.executable.filename === env.executable.filename);
if (old) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@ class MockNativePythonFinder implements nativeFinder.NativePythonFinder {
throw new Error('Method not implemented.');
}

categoryToKind(_category: nativeFinder.PythonEnvironmentKind): PythonEnvKind {
throw new Error('Method not implemented.');
}

resolve(_executable: string): Promise<nativeFinder.NativeEnvInfo> {
throw new Error('Method not implemented.');
}
Expand Down
13 changes: 6 additions & 7 deletions src/test/pythonEnvironments/nativeAPI.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@ import * as sinon from 'sinon';
import * as nativeAPI from '../../client/pythonEnvironments/nativeAPI';
import { IDiscoveryAPI } from '../../client/pythonEnvironments/base/locator';
import {
categoryToKind,
NativeEnvInfo,
NativePythonFinder,
PythonEnvironmentKind,
} from '../../client/pythonEnvironments/base/locators/common/nativePythonFinder';
import { Architecture } from '../../client/common/utils/platform';
import { PythonEnvInfo, PythonEnvKind, PythonEnvType } from '../../client/pythonEnvironments/base/info';
import { isWindows } from '../../client/common/platform/platformService';
import { NativePythonEnvironmentKind } from '../../client/pythonEnvironments/base/locators/common/nativePythonUtils';

suite('Native Python API', () => {
let api: IDiscoveryAPI;
Expand All @@ -26,7 +25,7 @@ suite('Native Python API', () => {
displayName: 'Basic Python',
name: 'basic_python',
executable: '/usr/bin/python',
kind: PythonEnvironmentKind.LinuxGlobal,
kind: NativePythonEnvironmentKind.LinuxGlobal,
version: `3.12.0`,
prefix: '/usr/bin',
};
Expand All @@ -35,7 +34,7 @@ suite('Native Python API', () => {
displayName: 'Basic Python',
name: 'basic_python',
executable: '/usr/bin/python',
kind: PythonEnvironmentKind.LinuxGlobal,
kind: NativePythonEnvironmentKind.LinuxGlobal,
version: undefined, // this is intentionally set to trigger resolve
prefix: '/usr/bin',
};
Expand All @@ -58,7 +57,7 @@ suite('Native Python API', () => {
displayName: 'Conda Python',
name: 'conda_python',
executable: '/home/user/.conda/envs/conda_python/python',
kind: PythonEnvironmentKind.Conda,
kind: NativePythonEnvironmentKind.Conda,
version: `3.12.0`,
prefix: '/home/user/.conda/envs/conda_python',
};
Expand All @@ -67,7 +66,7 @@ suite('Native Python API', () => {
displayName: 'Conda Python',
name: 'conda_python',
executable: '/home/user/.conda/envs/conda_python/python',
kind: PythonEnvironmentKind.Conda,
kind: NativePythonEnvironmentKind.Conda,
version: undefined, // this is intentionally set to test conda without python
prefix: '/home/user/.conda/envs/conda_python',
};
Expand All @@ -76,7 +75,7 @@ suite('Native Python API', () => {
displayName: 'Conda Python',
name: 'conda_python',
executable: undefined, // this is intentionally set to test env with no executable
kind: PythonEnvironmentKind.Conda,
kind: NativePythonEnvironmentKind.Conda,
version: undefined, // this is intentionally set to test conda without python
prefix: '/home/user/.conda/envs/conda_python',
};
Expand Down
Loading

0 comments on commit a414a65

Please sign in to comment.