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