Skip to content

Commit

Permalink
Merge pull request #425 from mbektas/conda_activate_using_root_env
Browse files Browse the repository at this point in the history
activate conda env using base conda env
  • Loading branch information
mbektas authored Mar 17, 2022
2 parents f0ea251 + 2fa6101 commit fc85f68
Show file tree
Hide file tree
Showing 6 changed files with 244 additions and 95 deletions.
20 changes: 19 additions & 1 deletion src/main/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ export interface IApplication {
saveState: (service: IStatefulService, data: JSONValue) => Promise<void>;

getPythonEnvironment(): Promise<IPythonEnvironment>;

setCondaRootPath(condaRootPath: string): void;

getCondaRootPath(): Promise<string>;
}

/**
Expand Down Expand Up @@ -127,7 +131,8 @@ export class JupyterApplication implements IApplication, IStatefulService {

this._applicationState = {
checkForUpdatesAutomatically: true,
pythonPath: ''
pythonPath: '',
condaRootPath: ''
};

this.registerStatefulService(this).then(
Expand Down Expand Up @@ -168,6 +173,18 @@ export class JupyterApplication implements IApplication, IStatefulService {
});
}

setCondaRootPath(condaRootPath: string): void {
this._applicationState.condaRootPath = condaRootPath;
}

getCondaRootPath(): Promise<string> {
return new Promise<string>((resolve, _reject) => {
this._appState.then((state: JSONObject) => {
resolve(this._applicationState.condaRootPath);
});
});
}

registerStatefulService(service: IStatefulService): Promise<JSONValue> {
this._services.push(service);

Expand Down Expand Up @@ -630,6 +647,7 @@ export namespace JupyterApplication {
export interface IState extends JSONObject {
checkForUpdatesAutomatically?: boolean;
pythonPath?: string;
condaRootPath?: string;
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/main/env_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
env_type = 'venv'

if env_type != 'venv' and os.path.exists(os.path.join(sys.prefix, "conda-meta")):
env_type = 'conda'
is_root = os.path.exists(os.path.join(sys.prefix, "condabin"))
env_type = 'conda-root' if is_root else 'conda-env'

if env_type != 'system':
env_name = os.path.basename(sys.prefix)
Expand Down
46 changes: 41 additions & 5 deletions src/main/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { ArrayExt } from '@lumino/algorithm';
import * as fs from 'fs';
import log from 'electron-log';
import {
EnvironmentTypeName,
IEnvironmentType,
IPythonEnvironment,
IVersionContainer
Expand All @@ -38,6 +39,8 @@ export interface IRegistry {

getEnvironmentList: () => Promise<IPythonEnvironment[]>;

getCondaEnvironments(): Promise<IPythonEnvironment[]>;

addEnvironment: (path: string) => Promise<IPythonEnvironment>;

getUserJupyterPath: () => Promise<IPythonEnvironment>;
Expand All @@ -46,6 +49,8 @@ export interface IRegistry {

validatePythonEnvironmentAtPath: (path: string) => boolean;

validateCondaBaseEnvironmentAtPath: (envPath: string) => boolean;

setDefaultPythonPath: (path: string) => void;

getCurrentPythonEnvironment: () => IPythonEnvironment;
Expand Down Expand Up @@ -130,6 +135,7 @@ export class Registry implements IRegistry {
this._setDefaultEnvironment(undefined);
});
} else {
this._condaEnvironments = this._loadCondaEnvironments();
this._registryBuilt = Promise.resolve();
}
}
Expand Down Expand Up @@ -256,6 +262,14 @@ export class Registry implements IRegistry {
});
}

/**
* Retrieve the list of conda environments, once they have been resolved
* @returns a promise that resolves to a list of conda environments
*/
getCondaEnvironments(): Promise<IPythonEnvironment[]> {
return this._condaEnvironments;
}

/**
* Create a new environment from a python executable, without waiting for the
* entire registry to be resolved first.
Expand Down Expand Up @@ -317,6 +331,16 @@ export class Registry implements IRegistry {
return true;
}

validateCondaBaseEnvironmentAtPath(envPath: string): boolean {
const isWin = process.platform === 'win32';
const condaBinPath = path.join(
envPath,
'condabin',
isWin ? 'conda.bat' : 'conda'
);
return fs.existsSync(condaBinPath) && fs.lstatSync(condaBinPath).isFile();
}

getEnvironmentInfo(pythonPath: string): IPythonEnvironment {
const runOptions = {
env: { PATH: this.getAdditionalPathIncludesForPythonPath(pythonPath) }
Expand All @@ -339,13 +363,16 @@ export class Registry implements IRegistry {
);
const envInfoOut = this._runCommandSync(pythonPath, ['-c', envInfoPyCode]);
const envInfo = JSON.parse(envInfoOut.trim());
const envName = `${envInfo.type}: ${envInfo.name}`;
const envType =
envInfo.type === 'conda-root'
? IEnvironmentType.CondaRoot
: envInfo.type === 'conda-env'
? IEnvironmentType.CondaEnv
: IEnvironmentType.VirtualEnv;
const envName = `${EnvironmentTypeName[envType]}: ${envInfo.name}`;

return {
type:
envInfo.type === 'conda'
? IEnvironmentType.CondaEnv
: IEnvironmentType.VirtualEnv,
type: envType,
name: envName,
path: pythonPath,
versions: { python: pythonVersion, jupyterlab: jlabVersion },
Expand Down Expand Up @@ -486,6 +513,13 @@ export class Registry implements IRegistry {
);

let allCondas = [pathCondas, commonCondas];

// add bundled conda env to the list of base conda envs
const bundledEnvPath = path.join(dirname(app.getAppPath()), 'jlab_server');
if (fs.existsSync(path.join(bundledEnvPath, 'condabin'))) {
allCondas.unshift(Promise.resolve([bundledEnvPath]));
}

if (process.platform === 'win32') {
allCondas.push(this._getWindowsRegistryCondas());
}
Expand Down Expand Up @@ -1101,6 +1135,8 @@ export class Registry implements IRegistry {

private _environments: IPythonEnvironment[] = [];

private _condaEnvironments: Promise<IPythonEnvironment[]>;

private _default: IPythonEnvironment;

private _registryBuilt: Promise<void>;
Expand Down
Loading

0 comments on commit fc85f68

Please sign in to comment.