|
2 | 2 |
|
3 | 3 | // eslint-disable-next-line camelcase
|
4 | 4 | import * as path from 'path';
|
| 5 | +import * as fs from 'fs'; |
5 | 6 | import {
|
6 | 7 | ConfigurationChangeEvent,
|
7 | 8 | ConfigurationTarget,
|
@@ -35,6 +36,8 @@ import {
|
35 | 36 | } from './types';
|
36 | 37 | import { debounceSync } from './utils/decorators';
|
37 | 38 | import { SystemVariables } from './variables/systemVariables';
|
| 39 | +import { getOSType, OSType } from './utils/platform'; |
| 40 | +import { isWindows } from './platform/platformService'; |
38 | 41 |
|
39 | 42 | const untildify = require('untildify');
|
40 | 43 |
|
@@ -391,7 +394,7 @@ export class PythonSettings implements IPythonSettings {
|
391 | 394 |
|
392 | 395 | // eslint-disable-next-line class-methods-use-this
|
393 | 396 | protected getPythonExecutable(pythonPath: string): string {
|
394 |
| - return untildify(pythonPath); |
| 397 | + return getPythonExecutable(pythonPath); |
395 | 398 | }
|
396 | 399 |
|
397 | 400 | protected onWorkspaceFoldersChanged(): void {
|
@@ -490,3 +493,63 @@ function getAbsolutePath(pathToCheck: string, rootDir: string | undefined): stri
|
490 | 493 | }
|
491 | 494 | return path.isAbsolute(pathToCheck) ? pathToCheck : path.resolve(rootDir, pathToCheck);
|
492 | 495 | }
|
| 496 | + |
| 497 | +function getPythonExecutable(pythonPath: string): string { |
| 498 | + pythonPath = untildify(pythonPath) as string; |
| 499 | + |
| 500 | + // If only 'python'. |
| 501 | + if ( |
| 502 | + pythonPath === 'python' || |
| 503 | + pythonPath.indexOf(path.sep) === -1 || |
| 504 | + path.basename(pythonPath) === path.dirname(pythonPath) |
| 505 | + ) { |
| 506 | + return pythonPath; |
| 507 | + } |
| 508 | + |
| 509 | + if (isValidPythonPath(pythonPath)) { |
| 510 | + return pythonPath; |
| 511 | + } |
| 512 | + // Keep python right on top, for backwards compatibility. |
| 513 | + |
| 514 | + const KnownPythonExecutables = [ |
| 515 | + 'python', |
| 516 | + 'python4', |
| 517 | + 'python3.6', |
| 518 | + 'python3.5', |
| 519 | + 'python3', |
| 520 | + 'python2.7', |
| 521 | + 'python2', |
| 522 | + 'python3.7', |
| 523 | + 'python3.8', |
| 524 | + 'python3.9', |
| 525 | + ]; |
| 526 | + |
| 527 | + for (let executableName of KnownPythonExecutables) { |
| 528 | + // Suffix with 'python' for linux and 'osx', and 'python.exe' for 'windows'. |
| 529 | + if (isWindows()) { |
| 530 | + executableName = `${executableName}.exe`; |
| 531 | + if (isValidPythonPath(path.join(pythonPath, executableName))) { |
| 532 | + return path.join(pythonPath, executableName); |
| 533 | + } |
| 534 | + if (isValidPythonPath(path.join(pythonPath, 'Scripts', executableName))) { |
| 535 | + return path.join(pythonPath, 'Scripts', executableName); |
| 536 | + } |
| 537 | + } else { |
| 538 | + if (isValidPythonPath(path.join(pythonPath, executableName))) { |
| 539 | + return path.join(pythonPath, executableName); |
| 540 | + } |
| 541 | + if (isValidPythonPath(path.join(pythonPath, 'bin', executableName))) { |
| 542 | + return path.join(pythonPath, 'bin', executableName); |
| 543 | + } |
| 544 | + } |
| 545 | + } |
| 546 | + |
| 547 | + return pythonPath; |
| 548 | +} |
| 549 | + |
| 550 | +function isValidPythonPath(pythonPath: string): boolean { |
| 551 | + return ( |
| 552 | + fs.existsSync(pythonPath) && |
| 553 | + path.basename(getOSType() === OSType.Windows ? pythonPath.toLowerCase() : pythonPath).startsWith('python') |
| 554 | + ); |
| 555 | +} |
0 commit comments