Merge pull request #139 from aminya/python-fix [skip ci]

This commit is contained in:
Amin Yahyaabadi 2022-11-04 20:16:57 -07:00 committed by GitHub
commit 9c8f057dbf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 106 additions and 78 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -12,6 +12,13 @@ import { dirname, join } from "patha"
import { hasDnf } from "../utils/env/hasDnf"
import { setupDnfPack } from "../utils/setup/setupDnfPack"
import { isUbuntu } from "../utils/env/isUbuntu"
import { getExecOutput } from "@actions/exec"
import { existsSync } from "fs"
import { isBinUptoDate } from "../utils/setup/version"
import { getVersion } from "../versions/versions"
import assert from "assert"
import execa from "execa"
import { unique } from "../utils/std"
export async function setupPython(version: string, setupDir: string, arch: string) {
if (ciDetect() !== "github-actions") {
@ -48,7 +55,7 @@ export async function setupPythonViaSystem(
join(setupDir, "python.exe")
const pythonSetupDir = dirname(pythonBinPath)
/** The directory which the tool is installed to */
await activateWinPython(pythonSetupDir)
await addPath(pythonSetupDir)
return { installDir: pythonSetupDir, binDir: pythonSetupDir }
}
case "darwin": {
@ -76,7 +83,67 @@ export async function setupPythonViaSystem(
}
}
async function activateWinPython(binDir: string) {
info(`Add ${binDir} to PATH`)
await addPath(binDir)
let setupPythonAndPipTried = false
/// setup python and pip if needed
export async function setupPythonAndPip(): Promise<string> {
let foundPython: string
// install python
if (which.sync("python3", { nothrow: true }) !== null) {
foundPython = "python3"
} else if (which.sync("python", { nothrow: true }) !== null && (await isBinUptoDate("python", "3.0.0"))) {
foundPython = "python"
} else {
info("python3 was not found. Installing python")
await setupPython(getVersion("python", undefined), "", process.arch)
// try again
if (setupPythonAndPipTried) {
throw new Error("Failed to install python")
}
setupPythonAndPipTried = true
return setupPythonAndPip() // recurse
}
assert(typeof foundPython === "string")
// install pip
if (process.platform === "win32") {
// downgrade pip on Windows
// https://github.com/pypa/pip/issues/10875#issuecomment-1030293005
execa.sync(foundPython, ["-m", "pip", "install", "-U", "pip==21.3.1"], { stdio: "inherit" })
} else if (process.platform === "linux") {
// ensure that pip is installed on Linux (happens when python is found but pip not installed)
if (isArch()) {
setupPacmanPack("python-pip")
} else if (hasDnf()) {
setupDnfPack("python3-pip")
} else if (isUbuntu()) {
await setupAptPack("python3-pip")
}
}
// install wheel (required for Conan, Meson, etc.)
execa.sync(foundPython, ["-m", "pip", "install", "-U", "wheel"], { stdio: "inherit" })
return foundPython
}
export async function addPythonBaseExecPrefix(python: string) {
const dirs: string[] = []
// detection based on the platform
if (process.platform === "linux") {
dirs.push("/home/runner/.local/bin/")
} else if (process.platform === "darwin") {
dirs.push("/usr/local/bin/")
}
// detection using python.sys
const base_exec_prefix = (await getExecOutput(`${python} -c "import sys;print(sys.base_exec_prefix);"`)).stdout.trim()
// any of these are possible depending on the operating system!
dirs.push(join(base_exec_prefix, "Scripts"), join(base_exec_prefix, "Scripts", "bin"), join(base_exec_prefix, "bin"))
// remove duplicates
return unique(dirs)
}

View File

@ -1,91 +1,49 @@
/* eslint-disable require-atomic-updates */
import { getExecOutput } from "@actions/exec"
import execa from "execa"
import which from "which"
import { info } from "@actions/core"
import { addPath } from "../env/addEnv"
import { setupPython } from "../../python/python"
import { isBinUptoDate } from "./version"
import { join } from "patha"
import { getVersion } from "../../versions/versions"
import { addPythonBaseExecPrefix, setupPythonAndPip } from "../../python/python"
import { InstallationInfo } from "./setupBin"
import { setupAptPack } from "./setupAptPack"
import { setupPacmanPack } from "./setupPacmanPack"
import { isArch } from "../env/isArch"
import { isUbuntu } from "../env/isUbuntu"
import { hasDnf } from "../env/hasDnf"
import { setupDnfPack } from "./setupDnfPack"
import { existsSync } from "fs"
import { addExeExt, dirname, join } from "patha"
import { addPath } from "../env/addEnv"
import which from "which"
let python: string | undefined
let binDir: string | undefined
let tried = false
let binDirs: string[] | undefined
/** A function that installs a package using pip */
export async function setupPipPack(name: string, version?: string): Promise<InstallationInfo> {
info(`Installing ${name} ${version ?? ""} via pip`)
// setup python and pip if needed
if (python === undefined) {
if (which.sync("python3", { nothrow: true }) !== null) {
python = "python3"
} else if (which.sync("python", { nothrow: true }) !== null && (await isBinUptoDate("python", "3.0.0"))) {
python = "python"
} else {
info("python3 was not found. Installing python")
await setupPython(getVersion("python", undefined), "", process.arch)
// try again
if (tried) {
throw new Error("Failed to install python")
}
tried = true
return setupPipPack(name, version)
}
if (process.platform === "win32") {
// downgrade pip on Windows
// https://github.com/pypa/pip/issues/10875#issuecomment-1030293005
execa.sync(python, ["-m", "pip", "install", "-U", "pip==21.3.1"], { stdio: "inherit" })
} else if (process.platform === "linux") {
// ensure that pip is installed on Linux (happens when python is found but pip not installed)
if (isArch()) {
setupPacmanPack("python-pip")
} else if (hasDnf()) {
setupDnfPack("python3-pip")
} else if (isUbuntu()) {
await setupAptPack("python3-pip")
}
}
// install wheel (required for Conan, Meson, etc.)
execa.sync(python, ["-m", "pip", "install", "-U", "wheel"], { stdio: "inherit" })
python = await setupPythonAndPip()
}
execa.sync(python, ["-m", "pip", "install", version !== undefined && version !== "" ? `${name}==${version}` : name], {
stdio: "inherit",
})
if (binDir === undefined) {
if (process.platform === "linux") {
binDir = "/home/runner/.local/bin/"
} else if (process.platform === "darwin") {
binDir = "/usr/local/bin/"
} else {
// windows or others
try {
binDir = join(
(await getExecOutput(`${python} -c "import sys;print(sys.base_exec_prefix);"`)).stdout.trim(),
"Scripts"
)
} catch {
binDir = join(
(await getExecOutput(`${python} -c "import sys;print(sys.base_exec_prefix);"`)).stdout.trim(),
"Scripts"
)
}
}
info(`${binDir} to PATH`)
await addPath(binDir)
if (binDirs === undefined) {
binDirs = await addPythonBaseExecPrefix(python)
}
const binDir = findBinDir(binDirs, name)
await addPath(binDir)
return { binDir }
}
function findBinDir(dirs: string[], name: string) {
const foundDir = dirs.find((dir) => existsSync(join(dir, addExeExt(name))))
if (foundDir !== undefined) {
return foundDir
}
const whichDir = which.sync(addExeExt(name), { nothrow: true })
if (whichDir !== null) {
return dirname(whichDir)
}
return dirs[dirs.length - 1]
}

3
src/utils/std/index.ts Normal file
View File

@ -0,0 +1,3 @@
export function unique(dirs: string[]) {
return [...new Set(dirs)]
}

View File

@ -14,7 +14,7 @@ export const DefaultVersions: Record<string, string> = {
meson: "0.63.3", // https://github.com/mesonbuild/meson/releases
kcov: "40", // https://github.com/SimonKagstrom/kcov/releases
task: "3.16.0", // https://github.com/go-task/task/releases
doxygen: isArch() ? "1.9.3-1" : "1.9.5", // https://www.doxygen.nl/download.html // https://packages.ubuntu.com/search?suite=all&arch=any&searchon=names&keywords=doxygen // https://formulae.brew.sh/formula/doxygen // https://archlinux.org/packages/extra/x86_64/doxygen/
doxygen: isArch() ? "1.9.5-1" : "1.9.5", // https://www.doxygen.nl/download.html // https://packages.ubuntu.com/search?suite=all&arch=any&searchon=names&keywords=doxygen // https://formulae.brew.sh/formula/doxygen // https://archlinux.org/packages/extra/x86_64/doxygen/
gcc: "11", // https://github.com/brechtsanders/winlibs_mingw/releases and // https://packages.ubuntu.com/search?suite=all&arch=any&searchon=names&keywords=gcc
}