1'use strict' 2 3delete process.env.PYTHON 4 5const { describe, it } = require('mocha') 6const assert = require('assert') 7const findPython = require('../lib/find-python') 8const execFile = require('child_process').execFile 9const PythonFinder = findPython.test.PythonFinder 10 11require('npmlog').level = 'warn' 12 13describe('find-python', function () { 14 it('find python', function () { 15 findPython.test.findPython(null, function (err, found) { 16 assert.strictEqual(err, null) 17 var proc = execFile(found, ['-V'], function (err, stdout, stderr) { 18 assert.strictEqual(err, null) 19 assert.ok(/Python 3/.test(stdout)) 20 assert.strictEqual(stderr, '') 21 }) 22 proc.stdout.setEncoding('utf-8') 23 proc.stderr.setEncoding('utf-8') 24 }) 25 }) 26 27 function poison (object, property) { 28 function fail () { 29 console.error(Error(`Property ${property} should not have been accessed.`)) 30 process.abort() 31 } 32 var descriptor = { 33 configurable: false, 34 enumerable: false, 35 get: fail, 36 set: fail 37 } 38 Object.defineProperty(object, property, descriptor) 39 } 40 41 function TestPythonFinder () { 42 PythonFinder.apply(this, arguments) 43 } 44 TestPythonFinder.prototype = Object.create(PythonFinder.prototype) 45 // Silence npmlog - remove for debugging 46 TestPythonFinder.prototype.log = { 47 silly: () => {}, 48 verbose: () => {}, 49 info: () => {}, 50 warn: () => {}, 51 error: () => {} 52 } 53 delete TestPythonFinder.prototype.env.NODE_GYP_FORCE_PYTHON 54 55 it('find python - python', function () { 56 var f = new TestPythonFinder('python', done) 57 f.execFile = function (program, args, opts, cb) { 58 f.execFile = function (program, args, opts, cb) { 59 poison(f, 'execFile') 60 assert.strictEqual(program, '/path/python') 61 assert.ok(/sys\.version_info/.test(args[1])) 62 cb(null, '3.9.1') 63 } 64 assert.strictEqual(program, 65 process.platform === 'win32' ? '"python"' : 'python') 66 assert.ok(/sys\.executable/.test(args[1])) 67 cb(null, '/path/python') 68 } 69 f.findPython() 70 71 function done (err, python) { 72 assert.strictEqual(err, null) 73 assert.strictEqual(python, '/path/python') 74 } 75 }) 76 77 it('find python - python too old', function () { 78 var f = new TestPythonFinder(null, done) 79 f.execFile = function (program, args, opts, cb) { 80 if (/sys\.executable/.test(args[args.length - 1])) { 81 cb(null, '/path/python') 82 } else if (/sys\.version_info/.test(args[args.length - 1])) { 83 cb(null, '2.3.4') 84 } else { 85 assert.fail() 86 } 87 } 88 f.findPython() 89 90 function done (err) { 91 assert.ok(/Could not find any Python/.test(err)) 92 assert.ok(/not supported/i.test(f.errorLog)) 93 } 94 }) 95 96 it('find python - no python', function () { 97 var f = new TestPythonFinder(null, done) 98 f.execFile = function (program, args, opts, cb) { 99 if (/sys\.executable/.test(args[args.length - 1])) { 100 cb(new Error('not found')) 101 } else if (/sys\.version_info/.test(args[args.length - 1])) { 102 cb(new Error('not a Python executable')) 103 } else { 104 assert.fail() 105 } 106 } 107 f.findPython() 108 109 function done (err) { 110 assert.ok(/Could not find any Python/.test(err)) 111 assert.ok(/not in PATH/.test(f.errorLog)) 112 } 113 }) 114 115 it('find python - no python2, no python, unix', function () { 116 var f = new TestPythonFinder(null, done) 117 f.checkPyLauncher = assert.fail 118 f.win = false 119 120 f.execFile = function (program, args, opts, cb) { 121 if (/sys\.executable/.test(args[args.length - 1])) { 122 cb(new Error('not found')) 123 } else { 124 assert.fail() 125 } 126 } 127 f.findPython() 128 129 function done (err) { 130 assert.ok(/Could not find any Python/.test(err)) 131 assert.ok(/not in PATH/.test(f.errorLog)) 132 } 133 }) 134 135 it('find python - no python, use python launcher', function () { 136 var f = new TestPythonFinder(null, done) 137 f.win = true 138 139 f.execFile = function (program, args, opts, cb) { 140 if (program === 'py.exe') { 141 assert.notStrictEqual(args.indexOf('-3'), -1) 142 assert.notStrictEqual(args.indexOf('-c'), -1) 143 return cb(null, 'Z:\\snake.exe') 144 } 145 if (/sys\.executable/.test(args[args.length - 1])) { 146 cb(new Error('not found')) 147 } else if (f.winDefaultLocations.includes(program)) { 148 cb(new Error('not found')) 149 } else if (/sys\.version_info/.test(args[args.length - 1])) { 150 if (program === 'Z:\\snake.exe') { 151 cb(null, '3.9.0') 152 } else { 153 assert.fail() 154 } 155 } else { 156 assert.fail() 157 } 158 } 159 f.findPython() 160 161 function done (err, python) { 162 assert.strictEqual(err, null) 163 assert.strictEqual(python, 'Z:\\snake.exe') 164 } 165 }) 166 167 it('find python - no python, no python launcher, good guess', function () { 168 var f = new TestPythonFinder(null, done) 169 f.win = true 170 const expectedProgram = f.winDefaultLocations[0] 171 172 f.execFile = function (program, args, opts, cb) { 173 if (program === 'py.exe') { 174 return cb(new Error('not found')) 175 } 176 if (/sys\.executable/.test(args[args.length - 1])) { 177 cb(new Error('not found')) 178 } else if (program === expectedProgram && 179 /sys\.version_info/.test(args[args.length - 1])) { 180 cb(null, '3.7.3') 181 } else { 182 assert.fail() 183 } 184 } 185 f.findPython() 186 187 function done (err, python) { 188 assert.strictEqual(err, null) 189 assert.ok(python === expectedProgram) 190 } 191 }) 192 193 it('find python - no python, no python launcher, bad guess', function () { 194 var f = new TestPythonFinder(null, done) 195 f.win = true 196 197 f.execFile = function (program, args, opts, cb) { 198 if (/sys\.executable/.test(args[args.length - 1])) { 199 cb(new Error('not found')) 200 } else if (/sys\.version_info/.test(args[args.length - 1])) { 201 cb(new Error('not a Python executable')) 202 } else { 203 assert.fail() 204 } 205 } 206 f.findPython() 207 208 function done (err) { 209 assert.ok(/Could not find any Python/.test(err)) 210 assert.ok(/not in PATH/.test(f.errorLog)) 211 } 212 }) 213}) 214