test-find-python.js 5.6 KB

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