Skip to content

Commit 2ab6e8f

Browse files
authored
Merge pull request #190 from aminya/pipx [skip ci]
2 parents e0bca0a + 20531c3 commit 2ab6e8f

File tree

10 files changed

+122
-61
lines changed

10 files changed

+122
-61
lines changed

cspell.config.yaml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ words:
3232
- DCMAKE
3333
- deps
3434
- devel
35+
- DVCPKG
3536
- dyld
3637
- eabi
3738
- esmodule
@@ -67,13 +68,15 @@ words:
6768
- OSSDK
6869
- papm
6970
- patha
71+
- pipx
7072
- pnpm
7173
- pwsh
7274
- pygments
7375
- pypy
7476
- Sccache
7577
- setupcpp
7678
- setx
79+
- SYSROOT
7780
- Syuu
7881
- terserrc
7982
- Trofimovich
@@ -83,16 +86,15 @@ words:
8386
- upleveled
8487
- vbatts
8588
- vcpkg
89+
- VCPKG
8690
- vcvarsall
91+
- venv
8792
- visualc
8893
- visualcpp
8994
- vsversion
9095
- whatwg
9196
- xcrun
9297
- Yahyaabadi
93-
- VCPKG
94-
- DVCPKG
95-
- SYSROOT
9698
ignoreWords: []
9799
import: []
98100
dictionaryDefinitions: []

dist/actions/setup-cpp.js

Lines changed: 16 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/actions/setup-cpp.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/legacy/setup-cpp.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/legacy/setup-cpp.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/modern/setup-cpp.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/modern/setup-cpp.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/conan/conan.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { setupPipPack } from "../utils/setup/setupPipPack"
22

33
// eslint-disable-next-line @typescript-eslint/no-unused-vars
4-
export async function setupConan(version: string | undefined, _setupDir: string, _arch: string) {
5-
await setupPipPack("setuptools", "")
4+
export function setupConan(version: string | undefined, _setupDir: string, _arch: string) {
65
return setupPipPack("conan", version)
76
}

src/python/python.ts

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { isBinUptoDate } from "../utils/setup/version"
2121
import { unique } from "../utils/std"
2222
import { MinVersions } from "../versions/default_versions"
2323
import { pathExists } from "path-exists"
24-
import { setupPipPackWithPython } from "../utils/setup/setupPipPack"
24+
import { hasPipx, setupPipPackSystem, setupPipPackWithPython } from "../utils/setup/setupPipPack"
2525

2626
export async function setupPython(version: string, setupDir: string, arch: string): Promise<InstallationInfo> {
2727
const installInfo = await findOrSetupPython(version, setupDir, arch)
@@ -34,15 +34,37 @@ export async function setupPython(version: string, setupDir: string, arch: strin
3434
throw new Error("pip was not installed correctly")
3535
}
3636

37-
// setup wheel and setuptools
37+
await setupPipx(foundPython)
38+
39+
await setupWheel(foundPython)
40+
41+
return installInfo
42+
}
43+
44+
async function setupPipx(foundPython: string) {
3845
try {
39-
await setupPipPackWithPython(foundPython, "setuptools", undefined, true)
40-
await setupPipPackWithPython(foundPython, "wheel", undefined, true)
46+
if (!(await hasPipx(foundPython))) {
47+
await setupPipPackWithPython(foundPython, "pipx", undefined, { upgrade: true, usePipx: false })
48+
}
49+
await execa(foundPython, ["-m", "pipx", "ensurepath"], { stdio: "inherit" })
50+
await setupPipPackWithPython(foundPython, "venv", undefined, { upgrade: false, usePipx: false })
4151
} catch (err) {
42-
warning(`Failed to install setuptools or wheel: ${(err as Error).toString()}. Ignoring...`)
52+
warning(`Failed to install pipx: ${(err as Error).toString()}. Ignoring...`)
4353
}
54+
}
4455

45-
return installInfo
56+
/** Setup wheel and setuptools */
57+
async function setupWheel(foundPython: string) {
58+
try {
59+
await setupPipPackWithPython(foundPython, "setuptools", undefined, {
60+
upgrade: true,
61+
isLibrary: true,
62+
usePipx: false,
63+
})
64+
await setupPipPackWithPython(foundPython, "wheel", undefined, { upgrade: true, isLibrary: true, usePipx: false })
65+
} catch (err) {
66+
warning(`Failed to install setuptools or wheel: ${(err as Error).toString()}. Ignoring...`)
67+
}
4668
}
4769

4870
async function findOrSetupPython(version: string, setupDir: string, arch: string) {
@@ -203,7 +225,9 @@ async function isPipUptoDate(pip: string) {
203225
async function setupPip(foundPython: string) {
204226
const upgraded = await ensurePipUpgrade(foundPython)
205227
if (!upgraded) {
206-
await setupPipSystem()
228+
// ensure that pip is installed on Linux (happens when python is found but pip not installed)
229+
await setupPipPackSystem("pip")
230+
207231
// upgrade pip
208232
await ensurePipUpgrade(foundPython)
209233
}
@@ -228,20 +252,6 @@ async function ensurePipUpgrade(foundPython: string) {
228252
return false
229253
}
230254

231-
function setupPipSystem() {
232-
if (process.platform === "linux") {
233-
// ensure that pip is installed on Linux (happens when python is found but pip not installed)
234-
if (isArch()) {
235-
return setupPacmanPack("python-pip")
236-
} else if (hasDnf()) {
237-
return setupDnfPack([{ name: "python3-pip" }])
238-
} else if (isUbuntu()) {
239-
return setupAptPack([{ name: "python3-pip" }])
240-
}
241-
}
242-
throw new Error(`Could not install pip on ${process.platform}`)
243-
}
244-
245255
async function addPythonBaseExecPrefix_raw(python: string) {
246256
const dirs: string[] = []
247257

src/utils/setup/setupPipPack.ts

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { info } from "@actions/core"
2-
import { execaSync } from "execa"
2+
import { execa, execaSync } from "execa"
33
import { pathExists } from "path-exists"
44
import { addExeExt, dirname, join } from "patha"
55
import which from "which"
@@ -9,26 +9,59 @@ import { InstallationInfo } from "./setupBin"
99
import { getVersion } from "../../versions/versions"
1010
import { ubuntuVersion } from "../env/ubuntu_version"
1111
import memoize from "micro-memoize"
12+
import { isArch } from "../env/isArch"
13+
import { setupPacmanPack } from "./setupPacmanPack"
14+
import { hasDnf } from "../env/hasDnf"
15+
import { setupDnfPack } from "./setupDnfPack"
16+
import { isUbuntu } from "../env/isUbuntu"
17+
import { setupAptPack } from "./setupAptPack"
18+
19+
export type SetupPipPackOptions = {
20+
/** Whether to use pipx instead of pip */
21+
usePipx?: boolean
22+
/** Whether to install the package as a user */
23+
user?: boolean
24+
/** Whether to upgrade the package */
25+
upgrade?: boolean
26+
/** Whether the package is a library */
27+
isLibrary?: boolean
28+
}
1229

1330
/** A function that installs a package using pip */
14-
export async function setupPipPack(name: string, version?: string, upgrade = false): Promise<InstallationInfo> {
15-
return setupPipPackWithPython(await getPython(), name, version, upgrade)
31+
export async function setupPipPack(
32+
name: string,
33+
version?: string,
34+
options: SetupPipPackOptions = {},
35+
): Promise<InstallationInfo> {
36+
return setupPipPackWithPython(await getPython(), name, version, options)
1637
}
1738

1839
export async function setupPipPackWithPython(
1940
givenPython: string,
2041
name: string,
2142
version?: string,
22-
upgrade = false,
43+
options: SetupPipPackOptions = {},
2344
): Promise<InstallationInfo> {
24-
info(`Installing ${name} ${version ?? ""} via pip`)
45+
const { usePipx = true, user = true, upgrade = false, isLibrary = false } = options
46+
47+
const isPipx = usePipx && !isLibrary && (await hasPipx(givenPython))
48+
const pip = isPipx ? "pipx" : "pip"
2549

26-
const nameAndVersion = version !== undefined && version !== "" ? `${name}==${version}` : name
27-
const upgradeFlag = upgrade === true ? ["--upgrade"] : []
50+
info(`Installing ${name} ${version ?? ""} via ${pip}`)
2851

29-
execaSync(givenPython, ["-m", "pip", "install", ...upgradeFlag, nameAndVersion], {
30-
stdio: "inherit",
31-
})
52+
try {
53+
const nameAndVersion = version !== undefined && version !== "" ? `${name}==${version}` : name
54+
const upgradeFlag = upgrade ? (isPipx ? ["upgrade"] : ["install", "--upgrade"]) : ["install"]
55+
const userFlag = !isPipx && user ? ["--user"] : []
56+
57+
execaSync(givenPython, ["-m", pip, ...upgradeFlag, ...userFlag, nameAndVersion], {
58+
stdio: "inherit",
59+
})
60+
} catch (err) {
61+
if ((await setupPipPackSystem(name)) === null) {
62+
throw new Error(`Failed to install ${name} via ${pip} ${err}`)
63+
}
64+
}
3265

3366
const execPaths = await addPythonBaseExecPrefix(givenPython)
3467
const binDir = await findBinDir(execPaths, name)
@@ -38,6 +71,10 @@ export async function setupPipPackWithPython(
3871
return { binDir }
3972
}
4073

74+
export async function hasPipx(givenPython: string) {
75+
return (await execa(givenPython, ["-m", "pipx", "--help"], { stdio: "ignore", reject: false })).exitCode === 0
76+
}
77+
4178
async function getPython_raw(): Promise<string> {
4279
const pythonBin = (await setupPython(getVersion("python", undefined, await ubuntuVersion()), "", process.arch)).bin
4380
if (pythonBin === undefined) {
@@ -62,3 +99,16 @@ async function findBinDir(dirs: string[], name: string) {
6299

63100
return dirs[dirs.length - 1]
64101
}
102+
103+
export function setupPipPackSystem(name: string) {
104+
if (process.platform === "linux") {
105+
if (isArch()) {
106+
return setupPacmanPack(`python-${name}`)
107+
} else if (hasDnf()) {
108+
return setupDnfPack([{ name: `python3-${name}` }])
109+
} else if (isUbuntu()) {
110+
return setupAptPack([{ name: `python3-${name}` }])
111+
}
112+
}
113+
return null
114+
}

0 commit comments

Comments
 (0)