@@ -15,6 +15,7 @@ const {
1515} = require ( 'fs-extra' ) ;
1616const { quote } = require ( 'shell-quote' ) ;
1717const { sep, delimiter } = require ( 'path' ) ;
18+ const { _ } = require ( 'lodash' ) ;
1819
1920const { getUserCachePath, sha256Path } = require ( './lib/shared' ) ;
2021
@@ -94,39 +95,55 @@ const test = (desc, func, opts = {}) =>
9495 }
9596 } ) ;
9697
97- const executableExtension = process . platform === 'win32' ? '.exe' : '' ;
98- const executableSearch = process . env . PATH . split ( delimiter ) ;
99- const whichCache = { } ;
100-
101- const which = ( name , extra ) => {
102- const found = whichCache [ name ] ;
103- if ( found !== undefined ) {
104- return found ;
98+ const availablePythons = ( ( ) => {
99+ const versions = [ ] ;
100+ const mapping = { } ;
101+ if ( process . env . USE_PYTHON ) {
102+ versions . push (
103+ ...process . env . USE_PYTHON . split ( ',' ) . map ( v => v . toString ( ) . trim ( ) )
104+ ) ;
105+ } else {
106+ versions . push ( '3.8' , '3.7' , '3.6' , '2.7' ) ;
105107 }
106- const fullName = `${ name } ${ executableExtension } ` ;
107- for ( const path of ( extra || [ ] ) . concat ( executableSearch ) ) {
108- const fullPath = `${ path } ${ sep } ${ fullName } ` ;
109- if ( pathExistsSync ( fullPath ) ) {
110- whichCache [ name ] = fullPath ;
111- return fullPath ;
108+ const exe = process . platform === 'win32' ? '.exe' : '' ;
109+ for ( const ver of _ . uniq (
110+ _ . concat (
111+ versions ,
112+ versions . map ( v => v [ 0 ] ) ,
113+ [ '' ]
114+ )
115+ ) ) {
116+ const python = `python${ ver } ${ exe } ` ;
117+ const { stdout, stderr, status } = crossSpawn . sync ( python , [
118+ '-c' ,
119+ 'import sys; sys.stdout.write(".".join(map(str, sys.version_info[:2])))'
120+ ] ) ;
121+ const realVer = stdout && stdout . toString ( ) . trim ( ) ;
122+ if ( ! status && realVer && _ . includes ( versions , realVer ) ) {
123+ for ( const recommend of [ realVer , realVer [ 0 ] ] ) {
124+ if ( ! mapping [ recommend ] ) {
125+ mapping [ recommend ] = python ;
126+ }
127+ }
112128 }
113129 }
114- whichCache [ name ] = null ;
115- return null ;
116- } ;
130+ if ( _ . isEmpty ( mapping ) ) {
131+ throw new Error ( `No pythons available meeting ${ versions } ` ) ;
132+ }
133+ return mapping ;
134+ } ) ( ) ;
117135
118136const getPythonBin = ( version = 3 ) => {
119- if ( ! [ 2 , 3 ] . includes ( version ) ) throw new Error ( 'version must be 2 or 3' ) ;
120- const extra = [ ] ;
121- /* if (process.platform === 'win32')
122- * extra.push(...glob.sync(`c:/python${version}*`)); */
123- const bin = which ( `python${ version } ` , extra ) ;
124- if ( bin === null ) throw new Error ( `Can't find python${ version } on PATH` ) ;
137+ const bin = availablePythons [ String ( version ) ] ;
138+ if ( ! bin )
139+ throw new Error (
140+ `No python version ${ version } available, only ${ availablePythons } `
141+ ) ;
125142 return bin ;
126143} ;
127144
128145const hasPython = version => {
129- return getPythonBin ( version ) !== null ;
146+ return Boolean ( availablePythons [ String ( version ) ] ) ;
130147} ;
131148
132149const listZipFiles = filename =>
0 commit comments