-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Fixes #22 to Detect anaconda from known locations #221
Changes from 8 commits
ecc1ca9
7c5778c
9d1bf82
ffba179
905c713
acc2109
c25d364
5e962a9
d470523
d392e8b
bf0e8e1
d25d8a7
4a1dc58
92f775f
32a6e53
ff00734
a4efe1e
d22be97
3cc3e3b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
'use strict'; | ||
import * as child_process from 'child_process'; | ||
import * as fs from 'fs-extra'; | ||
import * as path from 'path'; | ||
import { VersionUtils } from '../../../common/versionUtils'; | ||
import { ICondaLocatorService, IInterpreterLocatorService, PythonInterpreter } from '../../contracts'; | ||
// tslint:disable-next-line:no-require-imports no-var-requires | ||
const untildify: (value: string) => string = require('untildify'); | ||
|
||
const KNOWN_CONDA_LOCATIONS = ['~/anaconda3/bin/conda', '~/miniconda3/bin/conda']; | ||
|
||
export class CondaLocatorService implements ICondaLocatorService { | ||
constructor(private registryLookupForConda?: IInterpreterLocatorService) { | ||
} | ||
// tslint:disable-next-line:no-empty | ||
public dispose() { } | ||
public async getCondaFile(): Promise<string> { | ||
const isAvailable = await this.isCondaInCurrentPath(); | ||
if (isAvailable) { | ||
return 'conda'; | ||
} | ||
if (this.registryLookupForConda) { | ||
return this.registryLookupForConda.getInterpreters() | ||
.then(interpreters => interpreters.filter(this.isCondaEnvironment)) | ||
.then(condaInterpreters => this.getLatestVersion(condaInterpreters)) | ||
.then(condaInterpreter => { | ||
return condaInterpreter ? path.join(path.dirname(condaInterpreter.path), 'conda.exe') : 'conda'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't assuming There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should probably change the condition. Currently its implied with the existence of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed |
||
}) | ||
.then(async condaPath => { | ||
return fs.pathExists(condaPath).then(exists => exists ? condaPath : 'conda'); | ||
}); | ||
} | ||
return this.getCondaFileFromKnownLocations(); | ||
} | ||
public isCondaEnvironment(interpreter: PythonInterpreter) { | ||
return (interpreter.displayName ? interpreter.displayName : '').toUpperCase().indexOf('ANACONDA') >= 0 || | ||
(interpreter.companyDisplayName ? interpreter.companyDisplayName : '').toUpperCase().indexOf('CONTINUUM') >= 0; | ||
} | ||
public getLatestVersion(interpreters: PythonInterpreter[]) { | ||
const sortedInterpreters = interpreters.filter(interpreter => interpreter.version && interpreter.version.length > 0); | ||
// tslint:disable-next-line:no-non-null-assertion | ||
sortedInterpreters.sort((a, b) => VersionUtils.compareVersion(a.version!, b.version!)); | ||
if (sortedInterpreters.length > 0) { | ||
return sortedInterpreters[sortedInterpreters.length - 1]; | ||
} | ||
} | ||
public async isCondaInCurrentPath() { | ||
return new Promise<boolean>((resolve, reject) => { | ||
child_process.execFile('conda', ['--version'], (_, stdout) => { | ||
if (stdout && stdout.length > 0) { | ||
resolve(true); | ||
} else { | ||
resolve(false); | ||
} | ||
}); | ||
}); | ||
} | ||
private async getCondaFileFromKnownLocations(): Promise<string> { | ||
const condaFiles = await Promise.all(KNOWN_CONDA_LOCATIONS | ||
.map(untildify) | ||
.map(async (condaPath: string) => fs.pathExists(condaPath).then(exists => exists ? condaPath : ''))); | ||
|
||
const validCondaFiles = condaFiles.filter(condaPath => condaPath.length > 0); | ||
return validCondaFiles.length === 0 ? 'conda' : validCondaFiles[0]; | ||
} | ||
} |
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.
@brettcannon the more I look at the code, I feel its just not future proof.
What happens when Anaconda4 comes out? Do we add anaconda4, and so on?
Making it dynamic could be slow as well, i.e. looking for directories '~/anaconda*`
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.
Over the time I've installed different versions of miniconda on my home and work computer, and now I have all these directories:
.miniconda2
,miniconda
,miniconda3
.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 agree about the brittleness going forward. I say just do the glob match; the number of matches for that should be rather small and the number of stat calls to resolve this won't be that high.
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.
Will go with the hacky approach for now, created an issue to be resolve separately (as I'd need to add an npm package).
#256