src/executables/python.js
import { execFile } from '../executive'
import Executable from './executable'
export default class PythonExecutable extends Executable {
setExtras () {
return Promise.all([
this.detectInstaller(),
this.setSysPath()
])
.catch(error => {
this.addError(error)
return this
})
}
cleanVersion () {
return this.rawVersion.trim().match(/python ([\d.\-a-zA-Z]+)/i)[1]
}
setSysPath () {
return new Promise((resolve, reject) => {
let exportCmd = "import sys; print(':::'.join([path for path in sys.path if path]))"
let params = ['-c', exportCmd]
execFile(this.path, params, (error, stdout, stderr) => {
if (error) {
this.addError(error)
} else {
this.sysPath = stdout.trim().split(':::')
}
resolve(this)
})
})
}
pathContains (str) {
return this.realpath.toLowerCase().indexOf(str.toLowerCase()) !== -1
}
isActivePython () {
return new Promise((resolve, reject) => {
let params = ['-c', 'import activestate']
execFile(this.path, params, (error, stdout) => {
resolve(!error)
})
})
}
isWinPython () {
return new Promise((resolve, reject) => {
let params = ['-c', 'import winpython']
execFile(this.path, params, (error, stdout) => {
resolve(!error)
})
})
}
isXyPython () {
return new Promise((resolve, reject) => {
let params = ['-m', 'pip', '--version']
execFile(this.path, params, (error, stdout) => {
if (error) {
resolve(false)
}
resolve(stdout.indexOf('xy') !== -1)
})
})
}
detectInstaller () {
return new Promise((resolve, reject) => {
if (this.rawVersion && this.rawVersion.indexOf('Anaconda') !== -1) {
this.installer = 'anaconda'
}
/* NB: The Miniconda one also says Continuum, but Anaconda is probably more popular */
if (this.rawVersion && this.rawVersion.indexOf('Continuum') !== -1) {
this.installer = 'anaconda'
}
if (this.realpath) {
/* Custom Distributions */
if (this.pathContains('Enthought')) { this.installer = 'canopy' }
if (this.pathContains('Canopy')) { this.installer = 'canopy' }
if (this.pathContains('anaconda')) { this.installer = 'anaconda' }
if (this.pathContains('miniconda')) { this.installer = 'miniconda' }
/* OS X */
if (this.pathContains('Cellar')) { this.installer = 'homebrew' }
/* Note the order on these! */
/* Honestly though I guess we don't know, anything can install here */
// if (this.pathContains('/Library/Frameworks/Python.framework')) { this.installer = 'Python.org' }
// if (this.pathContains('/System/Library/Frameworks/Python.framework')) { this.installer = 'Default-OSX' }
/* Windows */
if (this.pathContains('APPDATA\\LOCAL\\PROGRAMS\\PYTHON')) { this.installer = 'pythonorg' }
/* if nothing else, test for ActivePython/ActiveState since it isn't in --version */
if (!this.installer) {
return Promise.all([
this.isActivePython(),
this.isXyPython(),
this.isWinPython()
]).then((values) => {
if (values[0]) {
this.installer = 'activepython'
}
if (values[1]) {
this.installer = 'xy'
}
if (values[2]) {
this.installer = 'winpython'
}
resolve(this)
})
} else {
resolve(this)
}
}
})
}
assureMergeable () {
/* Need to set the version */
return this.setVersion()
.then(() => this.setSysPath())
.catch(err => this.addError(err))
}
get mergeField () {
// previously just .realpath
return JSON.stringify({
rawVersion: this.rawVersion,
sysPath: this.sysPath
})
}
}