From a9e32196da56eabc0d584ea8b87d2a2f4c78f640 Mon Sep 17 00:00:00 2001 From: DeeDeeG Date: Mon, 15 Feb 2021 12:57:12 -0500 Subject: [PATCH 01/15] lib: drop Python 2 support in find-python.js Python 2 isn't supported in gyp-next anymore, so we should stop finding/trying to use Python 2. --- lib/find-python.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/lib/find-python.js b/lib/find-python.js index af269de2fc..86f9c86653 100644 --- a/lib/find-python.js +++ b/lib/find-python.js @@ -18,7 +18,7 @@ PythonFinder.prototype = { log: logWithPrefix(log, 'find Python'), argsExecutable: ['-c', 'import sys; print(sys.executable);'], argsVersion: ['-c', 'import sys; print("%s.%s.%s" % sys.version_info[:3]);'], - semverRange: '2.7.x || >=3.5.0', + semverRange: '>=3.5.0', // These can be overridden for testing: execFile: cp.execFile, @@ -26,8 +26,7 @@ PythonFinder.prototype = { win: win, pyLauncher: 'py.exe', winDefaultLocations: [ - path.join(process.env.SystemDrive || 'C:', 'Python37', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Python27', 'python.exe') + path.join(process.env.SystemDrive || 'C:', 'Python37', 'python.exe') ], // Logs a message at verbose level, but also saves it to be displayed later @@ -96,11 +95,6 @@ PythonFinder.prototype = { before: () => { this.addLog('checking if "python" can be used') }, check: this.checkCommand, arg: 'python' - }, - { - before: () => { this.addLog('checking if "python2" can be used') }, - check: this.checkCommand, - arg: 'python2' } ] From 83bf0411f788e1d036d0d91d691f9f042bb04e55 Mon Sep 17 00:00:00 2001 From: DeeDeeG Date: Mon, 15 Feb 2021 14:19:20 -0500 Subject: [PATCH 02/15] test: test find-python against supported Python 3 Note: This commit is required for the previous commit to pass tests. I have left it separate for clarity during review of this PR. But it should be squashed with the previous commit if/when merging. --- test/test-find-python.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test-find-python.js b/test/test-find-python.js index 6be887f7eb..e958fd3ed4 100644 --- a/test/test-find-python.js +++ b/test/test-find-python.js @@ -66,7 +66,7 @@ test('find python - python', function (t) { poison(f, 'execFile') t.strictEqual(program, '/path/python') t.ok(/sys\.version_info/.test(args[1])) - cb(null, '2.7.15') + cb(null, '3.9.1') } t.strictEqual(program, process.platform === 'win32' ? '"python"' : 'python') @@ -162,7 +162,7 @@ test('find python - no python, use python launcher', function (t) { cb(new Error('not found')) } else if (/sys\.version_info/.test(args[args.length - 1])) { if (program === 'Z:\\snake.exe') { - cb(null, '2.7.14') + cb(null, '3.9.0') } else { t.fail() } From 39403a8e480bea5b8a6d34998968ed86659c6995 Mon Sep 17 00:00:00 2001 From: DeeDeeG Date: Mon, 15 Feb 2021 12:59:45 -0500 Subject: [PATCH 03/15] Revert "lib: drop "-2" flag for "py.exe" launcher" This reverts commit c255ffbf6adc6b60cb39fa1aa40bfc8eb45f80ac. Note: My intent here is not to actually restore any Python 2 support, just to make it clearer where the comment text originally came from. It would be fair to squash this with the next commit if/when merging. --- lib/find-python.js | 11 ++++++++--- test/test-find-python.js | 3 ++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/find-python.js b/lib/find-python.js index 86f9c86653..12aabe7203 100644 --- a/lib/find-python.js +++ b/lib/find-python.js @@ -113,7 +113,7 @@ PythonFinder.prototype = { checks.push({ before: () => { this.addLog( - 'checking if the py launcher can be used to find Python') + 'checking if the py launcher can be used to find Python 2') }, check: this.checkPyLauncher }) @@ -182,10 +182,15 @@ PythonFinder.prototype = { // Distributions of Python on Windows by default install with the "py.exe" // Python launcher which is more likely to exist than the Python executable // being in the $PATH. + // Because the Python launcher supports all versions of Python, we have to + // explicitly request a Python 2 version. This is done by supplying "-2" as + // the first command line argument. Since "py.exe -2" would be an invalid + // executable for "execFile", we have to use the launcher to figure out + // where the actual "python.exe" executable is located. checkPyLauncher: function checkPyLauncher (errorCallback) { this.log.verbose( - `- executing "${this.pyLauncher}" to get Python executable path`) - this.run(this.pyLauncher, this.argsExecutable, false, + `- executing "${this.pyLauncher}" to get Python 2 executable path`) + this.run(this.pyLauncher, ['-2', ...this.argsExecutable], false, function (err, execPath) { // Possible outcomes: same as checkCommand if (err) { diff --git a/test/test-find-python.js b/test/test-find-python.js index e958fd3ed4..bbb1015a0c 100644 --- a/test/test-find-python.js +++ b/test/test-find-python.js @@ -146,13 +146,14 @@ test('find python - no python2, no python, unix', function (t) { }) test('find python - no python, use python launcher', function (t) { - t.plan(3) + t.plan(4) var f = new TestPythonFinder(null, done) f.win = true f.execFile = function (program, args, opts, cb) { if (program === 'py.exe') { + t.notEqual(args.indexOf('-2'), -1) t.notEqual(args.indexOf('-c'), -1) return cb(null, 'Z:\\snake.exe') } From 9c0d980176b40028a033021ce94672e59234d962 Mon Sep 17 00:00:00 2001 From: DeeDeeG Date: Mon, 15 Feb 2021 13:05:19 -0500 Subject: [PATCH 04/15] lib: use "-3" flag with py.exe launcher Ensures the py.exe launcher only finds Python 3. (Only applies to Windows users.) --- lib/find-python.js | 12 ++++++------ test/test-find-python.js | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/find-python.js b/lib/find-python.js index 12aabe7203..f65edc3043 100644 --- a/lib/find-python.js +++ b/lib/find-python.js @@ -113,7 +113,7 @@ PythonFinder.prototype = { checks.push({ before: () => { this.addLog( - 'checking if the py launcher can be used to find Python 2') + 'checking if the py launcher can be used to find Python 3') }, check: this.checkPyLauncher }) @@ -182,15 +182,15 @@ PythonFinder.prototype = { // Distributions of Python on Windows by default install with the "py.exe" // Python launcher which is more likely to exist than the Python executable // being in the $PATH. - // Because the Python launcher supports all versions of Python, we have to - // explicitly request a Python 2 version. This is done by supplying "-2" as - // the first command line argument. Since "py.exe -2" would be an invalid + // Because the Python launcher supports Python 2 and Python 3, we should + // explicitly request a Python 3 version. This is done by supplying "-3" as + // the first command line argument. Since "py.exe -3" would be an invalid // executable for "execFile", we have to use the launcher to figure out // where the actual "python.exe" executable is located. checkPyLauncher: function checkPyLauncher (errorCallback) { this.log.verbose( - `- executing "${this.pyLauncher}" to get Python 2 executable path`) - this.run(this.pyLauncher, ['-2', ...this.argsExecutable], false, + `- executing "${this.pyLauncher}" to get Python 3 executable path`) + this.run(this.pyLauncher, ['-3', ...this.argsExecutable], false, function (err, execPath) { // Possible outcomes: same as checkCommand if (err) { diff --git a/test/test-find-python.js b/test/test-find-python.js index bbb1015a0c..e2d39c67cd 100644 --- a/test/test-find-python.js +++ b/test/test-find-python.js @@ -153,7 +153,7 @@ test('find python - no python, use python launcher', function (t) { f.execFile = function (program, args, opts, cb) { if (program === 'py.exe') { - t.notEqual(args.indexOf('-2'), -1) + t.notEqual(args.indexOf('-3'), -1) t.notEqual(args.indexOf('-c'), -1) return cb(null, 'Z:\\snake.exe') } From 3c48f7072cd06f8f6ef6b72c7e78a38c3a747ca9 Mon Sep 17 00:00:00 2001 From: DeeDeeG Date: Mon, 15 Feb 2021 15:36:14 -0500 Subject: [PATCH 05/15] test: reject Python 2 in test-find-python --- test/test-find-python.js | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/test/test-find-python.js b/test/test-find-python.js index e2d39c67cd..18a364fdfb 100644 --- a/test/test-find-python.js +++ b/test/test-find-python.js @@ -10,19 +10,15 @@ const PythonFinder = findPython.test.PythonFinder require('npmlog').level = 'warn' test('find python', function (t) { - t.plan(4) + t.plan(5) findPython.test.findPython(null, function (err, found) { t.strictEqual(err, null) var proc = execFile(found, ['-V'], function (err, stdout, stderr) { t.strictEqual(err, null) - if (/Python 2/.test(stderr)) { - t.strictEqual(stdout, '') - t.ok(/Python 2/.test(stderr)) - } else { - t.ok(/Python 3/.test(stdout)) - t.strictEqual(stderr, '') - } + t.notOk(/Python 2/.test(stderr)) + t.ok(/Python 3/.test(stdout)) + t.strictEqual(stderr, '') }) proc.stdout.setEncoding('utf-8') proc.stderr.setEncoding('utf-8') From f13747daea3ec8c75be62f9ebc1fae458b425319 Mon Sep 17 00:00:00 2001 From: DeeDeeG Date: Tue, 16 Feb 2021 12:57:06 -0500 Subject: [PATCH 06/15] lib: accept python '>=3.6.0' in find-python.js Co-authored-by: Christian Clauss --- lib/find-python.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/find-python.js b/lib/find-python.js index f65edc3043..1f1599eb29 100644 --- a/lib/find-python.js +++ b/lib/find-python.js @@ -18,7 +18,7 @@ PythonFinder.prototype = { log: logWithPrefix(log, 'find Python'), argsExecutable: ['-c', 'import sys; print(sys.executable);'], argsVersion: ['-c', 'import sys; print("%s.%s.%s" % sys.version_info[:3]);'], - semverRange: '>=3.5.0', + semverRange: '>=3.6.0', // These can be overridden for testing: execFile: cp.execFile, From d1f2aec578bb9715e93d2cd2f5c7f70683bfeeb9 Mon Sep 17 00:00:00 2001 From: DeeDeeG Date: Tue, 16 Feb 2021 14:57:55 -0500 Subject: [PATCH 07/15] lib: use real Python 3 default install paths --- lib/find-python.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/find-python.js b/lib/find-python.js index 1f1599eb29..58ed92deec 100644 --- a/lib/find-python.js +++ b/lib/find-python.js @@ -26,7 +26,22 @@ PythonFinder.prototype = { win: win, pyLauncher: 'py.exe', winDefaultLocations: [ - path.join(process.env.SystemDrive || 'C:', 'Python37', 'python.exe') + path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python39', 'python.exe'), + path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python39', 'python.exe'), + path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python39-32', 'python.exe'), + path.join(process.env.SystemDrive || 'C:', 'Program Files (x86)', 'Python39', 'python.exe'), + path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python38', 'python.exe'), + path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python38', 'python.exe'), + path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python38-32', 'python.exe'), + path.join(process.env.SystemDrive || 'C:', 'Program Files (x86)', 'Python38', 'python.exe'), + path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python37', 'python.exe'), + path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python37', 'python.exe'), + path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python37-32', 'python.exe'), + path.join(process.env.SystemDrive || 'C:', 'Program Files (x86)', 'Python37', 'python.exe'), + path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python36', 'python.exe'), + path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python36', 'python.exe'), + path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python36-32', 'python.exe'), + path.join(process.env.SystemDrive || 'C:', 'Program Files (x86)', 'Python36', 'python.exe') ], // Logs a message at verbose level, but also saves it to be displayed later From 2562153451a8d26ee81b7b6a1b2eba4d4112462f Mon Sep 17 00:00:00 2001 From: DeeDeeG Date: Tue, 16 Feb 2021 17:09:58 -0500 Subject: [PATCH 08/15] test: update Python path for "good guess" test Note: This is required for the previous commit to pass tests. Please squash this with the previous commit if/when merging. --- test/test-find-python.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test-find-python.js b/test/test-find-python.js index 18a364fdfb..4931a48646 100644 --- a/test/test-find-python.js +++ b/test/test-find-python.js @@ -178,9 +178,9 @@ test('find python - no python, use python launcher', function (t) { test('find python - no python, no python launcher, good guess', function (t) { t.plan(2) - var re = /C:[\\/]Python37[\\/]python[.]exe/ var f = new TestPythonFinder(null, done) f.win = true + const expectedProgram = f.winDefaultLocations[0] f.execFile = function (program, args, opts, cb) { if (program === 'py.exe') { @@ -188,7 +188,7 @@ test('find python - no python, no python launcher, good guess', function (t) { } if (/sys\.executable/.test(args[args.length - 1])) { cb(new Error('not found')) - } else if (re.test(program) && + } else if (program === expectedProgram && /sys\.version_info/.test(args[args.length - 1])) { cb(null, '3.7.3') } else { @@ -199,7 +199,7 @@ test('find python - no python, no python launcher, good guess', function (t) { function done (err, python) { t.strictEqual(err, null) - t.ok(re.test(python)) + t.ok(python === expectedProgram) } }) From d20f929974872258c9c230bc30b79cdeb69335e5 Mon Sep 17 00:00:00 2001 From: DeeDeeG Date: Wed, 17 Feb 2021 19:47:45 -0500 Subject: [PATCH 09/15] lib: use correct paths for 32-bit system-wide Python Paths are installed with a "-32" suffix: "Python[version]-32" I forgot to add the "-32" in previous commits. Note: It would be good to squash this with the previous two commits. --- lib/find-python.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/find-python.js b/lib/find-python.js index 58ed92deec..24efa4a8b9 100644 --- a/lib/find-python.js +++ b/lib/find-python.js @@ -29,19 +29,19 @@ PythonFinder.prototype = { path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python39', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python39', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python39-32', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Program Files (x86)', 'Python39', 'python.exe'), + path.join(process.env.SystemDrive || 'C:', 'Program Files (x86)', 'Python39-32', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python38', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python38', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python38-32', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Program Files (x86)', 'Python38', 'python.exe'), + path.join(process.env.SystemDrive || 'C:', 'Program Files (x86)', 'Python38-32', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python37', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python37', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python37-32', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Program Files (x86)', 'Python37', 'python.exe'), + path.join(process.env.SystemDrive || 'C:', 'Program Files (x86)', 'Python37-32', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python36', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python36', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python36-32', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Program Files (x86)', 'Python36', 'python.exe') + path.join(process.env.SystemDrive || 'C:', 'Program Files (x86)', 'Python36-32', 'python.exe') ], // Logs a message at verbose level, but also saves it to be displayed later From 54041d88411a600217f0fe8a5e3f1887f3062469 Mon Sep 17 00:00:00 2001 From: DeeDeeG Date: Thu, 18 Feb 2021 16:51:06 -0500 Subject: [PATCH 10/15] lib: add system-wide Python path for 32-bit Windows 32-bit Windows doesn't have a "Program Files (x86)" folder, only "Program Files". --- lib/find-python.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/find-python.js b/lib/find-python.js index 24efa4a8b9..8a04c492a9 100644 --- a/lib/find-python.js +++ b/lib/find-python.js @@ -29,18 +29,22 @@ PythonFinder.prototype = { path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python39', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python39', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python39-32', 'python.exe'), + path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python39-32', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Program Files (x86)', 'Python39-32', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python38', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python38', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python38-32', 'python.exe'), + path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python38-32', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Program Files (x86)', 'Python38-32', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python37', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python37', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python37-32', 'python.exe'), + path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python37-32', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Program Files (x86)', 'Python37-32', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python36', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python36', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python36-32', 'python.exe'), + path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python36-32', 'python.exe'), path.join(process.env.SystemDrive || 'C:', 'Program Files (x86)', 'Python36-32', 'python.exe') ], From d0bcb5c4494dfe747fe5d771f982c91b201bbae5 Mon Sep 17 00:00:00 2001 From: DeeDeeG Date: Thu, 18 Feb 2021 18:18:11 -0500 Subject: [PATCH 11/15] lib: construct winDefaultLocations programatically Reduces boilerplate code. Also, refactored to drop the dependency on the 'path' module. --- lib/find-python.js | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/lib/find-python.js b/lib/find-python.js index 8a04c492a9..e79698e321 100644 --- a/lib/find-python.js +++ b/lib/find-python.js @@ -1,6 +1,5 @@ 'use strict' -const path = require('path') const log = require('npmlog') const semver = require('semver') const cp = require('child_process') @@ -8,6 +7,20 @@ const extend = require('util')._extend // eslint-disable-line const win = process.platform === 'win32' const logWithPrefix = require('./util').logWithPrefix +const systemDrive = process.env.SystemDrive || 'C:' +const username = process.env.USERNAME || process.env.USER +const winDefaultLocationsArray = [] + +for (const majorMinor of ['39', '38', '37', '36']) { + winDefaultLocationsArray.push( + `${systemDrive}\\Users\\${username}\\AppData\\Local\\Programs\\Python\\Python${majorMinor}\\python.exe`, + `${systemDrive}\\Program Files\\Python${majorMinor}\\python.exe`, + `${systemDrive}\\Users\\${username}\\AppData\\Local\\Programs\\Python\\Python${majorMinor}-32\\python.exe`, + `${systemDrive}\\Program Files\\Python${majorMinor}-32\\python.exe`, + `${systemDrive}\\Program Files (x86)\\Python${majorMinor}-32\\python.exe` + ) +} + function PythonFinder (configPython, callback) { this.callback = callback this.configPython = configPython @@ -25,28 +38,7 @@ PythonFinder.prototype = { env: process.env, win: win, pyLauncher: 'py.exe', - winDefaultLocations: [ - path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python39', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python39', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python39-32', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python39-32', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Program Files (x86)', 'Python39-32', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python38', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python38', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python38-32', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python38-32', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Program Files (x86)', 'Python38-32', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python37', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python37', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python37-32', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python37-32', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Program Files (x86)', 'Python37-32', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python36', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python36', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Users', process.env.USERNAME || process.env.USER, 'AppData', 'Local', 'Programs', 'Python', 'Python36-32', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Program Files', 'Python36-32', 'python.exe'), - path.join(process.env.SystemDrive || 'C:', 'Program Files (x86)', 'Python36-32', 'python.exe') - ], + winDefaultLocations: winDefaultLocationsArray, // Logs a message at verbose level, but also saves it to be displayed later // at error level if an error occurs. This should help diagnose the problem. From a7b43aa984e6fc78aa424c7e9d30fc89038b5cc6 Mon Sep 17 00:00:00 2001 From: DeeDeeG Date: Fri, 19 Feb 2021 23:26:53 -0500 Subject: [PATCH 12/15] lib: assign localAppData and programFiles from env These paths may be localized to other languages, or placed on another drive. (These paths appear to be mostly standardized on Windows 10, but they can apparently be relocated on Windows Server, and may be localized on some older version(s) of Windows.) --- lib/find-python.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/find-python.js b/lib/find-python.js index e79698e321..667e6ec89e 100644 --- a/lib/find-python.js +++ b/lib/find-python.js @@ -9,15 +9,18 @@ const logWithPrefix = require('./util').logWithPrefix const systemDrive = process.env.SystemDrive || 'C:' const username = process.env.USERNAME || process.env.USER -const winDefaultLocationsArray = [] +const localAppData = process.env.LOCALAPPDATA || `${systemDrive}\\${username}\\AppData\\Local` +const programFiles = process.env.ProgramW6432 || process.env.ProgramFiles || `${systemDrive}\\Program Files` +const programFilesX86 = process.env['ProgramFiles(x86)'] || `${programFiles} (x86)` +const winDefaultLocationsArray = [] for (const majorMinor of ['39', '38', '37', '36']) { winDefaultLocationsArray.push( - `${systemDrive}\\Users\\${username}\\AppData\\Local\\Programs\\Python\\Python${majorMinor}\\python.exe`, - `${systemDrive}\\Program Files\\Python${majorMinor}\\python.exe`, - `${systemDrive}\\Users\\${username}\\AppData\\Local\\Programs\\Python\\Python${majorMinor}-32\\python.exe`, - `${systemDrive}\\Program Files\\Python${majorMinor}-32\\python.exe`, - `${systemDrive}\\Program Files (x86)\\Python${majorMinor}-32\\python.exe` + `${localAppData}\\Programs\\Python\\Python${majorMinor}\\python.exe`, + `${programFiles}\\Python${majorMinor}\\python.exe`, + `${localAppData}\\Programs\\Python\\Python${majorMinor}-32\\python.exe`, + `${programFiles}\\Python${majorMinor}-32\\python.exe`, + `${programFilesX86}\\Python${majorMinor}-32\\python.exe` ) } From 432447d5e51315fa2d307f0116364366eaa2edf5 Mon Sep 17 00:00:00 2001 From: DeeDeeG Date: Mon, 22 Feb 2021 14:06:56 -0500 Subject: [PATCH 13/15] lib: fall back to os.userInfo() to get username This should be a reliable fallback in case the environment variables have been deleted or unset. --- lib/find-python.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/find-python.js b/lib/find-python.js index 667e6ec89e..47a9aa6dd4 100644 --- a/lib/find-python.js +++ b/lib/find-python.js @@ -8,7 +8,7 @@ const win = process.platform === 'win32' const logWithPrefix = require('./util').logWithPrefix const systemDrive = process.env.SystemDrive || 'C:' -const username = process.env.USERNAME || process.env.USER +const username = process.env.USERNAME || process.env.USER || require('os').userInfo().username const localAppData = process.env.LOCALAPPDATA || `${systemDrive}\\${username}\\AppData\\Local` const programFiles = process.env.ProgramW6432 || process.env.ProgramFiles || `${systemDrive}\\Program Files` const programFilesX86 = process.env['ProgramFiles(x86)'] || `${programFiles} (x86)` From 171104691eaa51e82d7dd457aa0ec11950aceb51 Mon Sep 17 00:00:00 2001 From: DeeDeeG Date: Mon, 22 Feb 2021 14:16:54 -0500 Subject: [PATCH 14/15] test: delete redundant Python 2 check --- test/test-find-python.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/test-find-python.js b/test/test-find-python.js index 4931a48646..ba21af7364 100644 --- a/test/test-find-python.js +++ b/test/test-find-python.js @@ -16,7 +16,6 @@ test('find python', function (t) { t.strictEqual(err, null) var proc = execFile(found, ['-V'], function (err, stdout, stderr) { t.strictEqual(err, null) - t.notOk(/Python 2/.test(stderr)) t.ok(/Python 3/.test(stdout)) t.strictEqual(stderr, '') }) From ec64f91cfa3d3debbe1f975c8cf75ada426f110d Mon Sep 17 00:00:00 2001 From: DeeDeeG Date: Mon, 22 Feb 2021 14:33:46 -0500 Subject: [PATCH 15/15] test: adjust expected number of tests Note: This fixes an oversight in the previous commit, and is required for the previous commit to pass tests. Please squash this with the previous commit if/when merging. --- test/test-find-python.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-find-python.js b/test/test-find-python.js index ba21af7364..67d0b2664f 100644 --- a/test/test-find-python.js +++ b/test/test-find-python.js @@ -10,7 +10,7 @@ const PythonFinder = findPython.test.PythonFinder require('npmlog').level = 'warn' test('find python', function (t) { - t.plan(5) + t.plan(4) findPython.test.findPython(null, function (err, found) { t.strictEqual(err, null)