mirror of
https://github.com/astral-sh/setup-uv.git
synced 2026-09-04 14:39:28 +00:00
112 lines
3.7 KiB
TypeScript
112 lines
3.7 KiB
TypeScript
import { join } from "node:path";
|
|
import { promisify } from "node:util";
|
|
import { afterEach, beforeEach, expect, it, jest } from "@jest/globals";
|
|
import { createSetupInputs } from "../helpers/setup-inputs";
|
|
|
|
const mockExecFile =
|
|
jest.fn<
|
|
(...args: unknown[]) => Promise<{ stdout: string; stderr: string }>
|
|
>();
|
|
const mockDebug = jest.fn();
|
|
const originalPlatform = process.platform;
|
|
const inputs = createSetupInputs({
|
|
activateEnvironment: true,
|
|
pythonVersion: "3.15t",
|
|
});
|
|
|
|
jest.unstable_mockModule("@actions/core", () => ({ debug: mockDebug }));
|
|
jest.unstable_mockModule("node:child_process", () => ({
|
|
// execFile's custom promisifier returns both stdout and stderr.
|
|
execFile: Object.assign(mockExecFile, { [promisify.custom]: mockExecFile }),
|
|
}));
|
|
|
|
const { getPythonRuntimeId } = await import("../../src/utils/python-runtime");
|
|
|
|
function mockRuntime(overrides: Record<string, unknown> = {}) {
|
|
mockExecFile.mockResolvedValue({
|
|
stderr: "",
|
|
stdout: `${JSON.stringify({
|
|
freethreaded: false,
|
|
implementation: "cpython",
|
|
implementationVersion: [3, 13, 1, "final", 0],
|
|
pythonVersion: "3.13.1",
|
|
...overrides,
|
|
})}\r\n`,
|
|
});
|
|
}
|
|
|
|
beforeEach(() => {
|
|
mockExecFile.mockReset();
|
|
mockRuntime();
|
|
});
|
|
afterEach(() => {
|
|
Object.defineProperty(process, "platform", { value: originalPlatform });
|
|
});
|
|
|
|
it("does not query Python without environment activation", async () => {
|
|
expect(
|
|
await getPythonRuntimeId({ ...inputs, activateEnvironment: false }),
|
|
).toBe("");
|
|
expect(mockExecFile).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it.each([
|
|
["3.13.1", false, "cpython-3.13.1"],
|
|
["3.15.0a1", false, "cpython-3.15.0a1"],
|
|
["3.15.0b2", false, "cpython-3.15.0b2"],
|
|
["3.15.0rc1", false, "cpython-3.15.0rc1"],
|
|
["3.15.0rc1", true, "cpython-3.15.0rc1-freethreaded"],
|
|
["3.15.0rc2", true, "cpython-3.15.0rc2-freethreaded"],
|
|
["3.15.0", true, "cpython-3.15.0-freethreaded"],
|
|
])("formats CPython %s, free-threading=%s", async (version, free, expected) => {
|
|
mockRuntime({ freethreaded: free, pythonVersion: version });
|
|
expect(await getPythonRuntimeId(inputs)).toBe(expected);
|
|
});
|
|
|
|
it.each([
|
|
["pypy", [7, 3, 23, "final", 0], "pypy-7.3.23"],
|
|
["pypy", [7, 3, 24, "final", 0], "pypy-7.3.24"],
|
|
["pypy", [7, 3, 24, "alpha", 1], "pypy-7.3.24a1"],
|
|
["pypy", [7, 3, 24, "beta", 2], "pypy-7.3.24b2"],
|
|
["pypy", [7, 3, 24, "candidate", 3], "pypy-7.3.24rc3"],
|
|
["graalpy", [25, 0, 0, "final", 0], "graalpy-25.0.0"],
|
|
["pypy", [7, 3, 24, "unknown", 0], ""],
|
|
])("formats %s implementation version %j", async (name, version, expected) => {
|
|
mockRuntime({
|
|
implementation: name,
|
|
implementationVersion: version,
|
|
pythonVersion: "3.11.15",
|
|
});
|
|
expect(await getPythonRuntimeId(inputs)).toBe(
|
|
expected ? `${expected}-python-3.11.15` : "",
|
|
);
|
|
});
|
|
|
|
it.each([
|
|
["linux", 'a "quoted" venv', "bin/python"],
|
|
["darwin", "custom venv", "bin/python"],
|
|
["win32", "custom venv", "Scripts/python.exe"],
|
|
])("passes the venv executable directly on %s", async (platform, name, exe) => {
|
|
Object.defineProperty(process, "platform", { value: platform });
|
|
const venvPath = join("/runner temp", name);
|
|
await getPythonRuntimeId({ ...inputs, venvPath });
|
|
expect(mockExecFile).toHaveBeenCalledWith(
|
|
join(venvPath, exe),
|
|
["-I", "-c", expect.any(String)],
|
|
{ encoding: "utf8" },
|
|
);
|
|
});
|
|
|
|
it.each([new Error("interpreter missing"), "", "not JSON", "null", "{}"])(
|
|
"returns an empty ID for interpreter failure: %s",
|
|
async (result) => {
|
|
if (result instanceof Error) {
|
|
mockExecFile.mockRejectedValue(result);
|
|
} else {
|
|
mockExecFile.mockResolvedValue({ stderr: "", stdout: result });
|
|
}
|
|
expect(await getPythonRuntimeId(inputs)).toBe("");
|
|
expect(mockDebug).toHaveBeenCalled();
|
|
},
|
|
);
|