mirror of
https://code.forgejo.org/actions/setup-python
synced 2025-06-09 04:42:20 +02:00
Adding support for more PyPy versions and installing them on-flight (#168)
* add support to install pypy * resolved comments, update readme, add e2e tests. * resolve throw error * Add pypy unit tests to cover code * add tests * Update test-pypy.yml * Update test-python.yml * Update test-python.yml * Update README.md * fixing tests * change order Co-authored-by: Maxim Lobanov <v-malob@microsoft.com> * add pypy tests and fix issue with pypy-3-nightly Co-authored-by: Maxim Lobanov <v-malob@microsoft.com>
This commit is contained in:
parent
2831efe49a
commit
8c5ea631b2
14 changed files with 1896 additions and 34 deletions
131
src/find-pypy.ts
Normal file
131
src/find-pypy.ts
Normal file
|
@ -0,0 +1,131 @@
|
|||
import * as path from 'path';
|
||||
import * as pypyInstall from './install-pypy';
|
||||
import {
|
||||
IS_WINDOWS,
|
||||
validateVersion,
|
||||
getPyPyVersionFromPath,
|
||||
readExactPyPyVersionFile,
|
||||
validatePythonVersionFormatForPyPy
|
||||
} from './utils';
|
||||
|
||||
import * as semver from 'semver';
|
||||
import * as core from '@actions/core';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
|
||||
interface IPyPyVersionSpec {
|
||||
pypyVersion: string;
|
||||
pythonVersion: string;
|
||||
}
|
||||
|
||||
export async function findPyPyVersion(
|
||||
versionSpec: string,
|
||||
architecture: string
|
||||
): Promise<{resolvedPyPyVersion: string; resolvedPythonVersion: string}> {
|
||||
let resolvedPyPyVersion = '';
|
||||
let resolvedPythonVersion = '';
|
||||
let installDir: string | null;
|
||||
|
||||
const pypyVersionSpec = parsePyPyVersion(versionSpec);
|
||||
|
||||
// PyPy only precompiles binaries for x86, but the architecture parameter defaults to x64.
|
||||
if (IS_WINDOWS && architecture === 'x64') {
|
||||
architecture = 'x86';
|
||||
}
|
||||
|
||||
({installDir, resolvedPythonVersion, resolvedPyPyVersion} = findPyPyToolCache(
|
||||
pypyVersionSpec.pythonVersion,
|
||||
pypyVersionSpec.pypyVersion,
|
||||
architecture
|
||||
));
|
||||
|
||||
if (!installDir) {
|
||||
({
|
||||
installDir,
|
||||
resolvedPythonVersion,
|
||||
resolvedPyPyVersion
|
||||
} = await pypyInstall.installPyPy(
|
||||
pypyVersionSpec.pypyVersion,
|
||||
pypyVersionSpec.pythonVersion,
|
||||
architecture
|
||||
));
|
||||
}
|
||||
|
||||
const pipDir = IS_WINDOWS ? 'Scripts' : 'bin';
|
||||
const _binDir = path.join(installDir, pipDir);
|
||||
const pythonLocation = pypyInstall.getPyPyBinaryPath(installDir);
|
||||
core.exportVariable('pythonLocation', pythonLocation);
|
||||
core.addPath(pythonLocation);
|
||||
core.addPath(_binDir);
|
||||
|
||||
return {resolvedPyPyVersion, resolvedPythonVersion};
|
||||
}
|
||||
|
||||
export function findPyPyToolCache(
|
||||
pythonVersion: string,
|
||||
pypyVersion: string,
|
||||
architecture: string
|
||||
) {
|
||||
let resolvedPyPyVersion = '';
|
||||
let resolvedPythonVersion = '';
|
||||
let installDir: string | null = tc.find('PyPy', pythonVersion, architecture);
|
||||
|
||||
if (installDir) {
|
||||
// 'tc.find' finds tool based on Python version but we also need to check
|
||||
// whether PyPy version satisfies requested version.
|
||||
resolvedPythonVersion = getPyPyVersionFromPath(installDir);
|
||||
resolvedPyPyVersion = readExactPyPyVersionFile(installDir);
|
||||
|
||||
const isPyPyVersionSatisfies = semver.satisfies(
|
||||
resolvedPyPyVersion,
|
||||
pypyVersion
|
||||
);
|
||||
if (!isPyPyVersionSatisfies) {
|
||||
installDir = null;
|
||||
resolvedPyPyVersion = '';
|
||||
resolvedPythonVersion = '';
|
||||
}
|
||||
}
|
||||
|
||||
if (!installDir) {
|
||||
core.info(
|
||||
`PyPy version ${pythonVersion} (${pypyVersion}) was not found in the local cache`
|
||||
);
|
||||
}
|
||||
|
||||
return {installDir, resolvedPythonVersion, resolvedPyPyVersion};
|
||||
}
|
||||
|
||||
export function parsePyPyVersion(versionSpec: string): IPyPyVersionSpec {
|
||||
const versions = versionSpec.split('-').filter(item => !!item);
|
||||
|
||||
if (versions.length < 2 || versions[0] != 'pypy') {
|
||||
throw new Error(
|
||||
"Invalid 'version' property for PyPy. PyPy version should be specified as 'pypy-<python-version>'. See README for examples and documentation."
|
||||
);
|
||||
}
|
||||
|
||||
const pythonVersion = versions[1];
|
||||
let pypyVersion: string;
|
||||
if (versions.length > 2) {
|
||||
pypyVersion = pypyInstall.pypyVersionToSemantic(versions[2]);
|
||||
} else {
|
||||
pypyVersion = 'x';
|
||||
}
|
||||
|
||||
if (!validateVersion(pythonVersion) || !validateVersion(pypyVersion)) {
|
||||
throw new Error(
|
||||
"Invalid 'version' property for PyPy. Both Python version and PyPy versions should satisfy SemVer notation. See README for examples and documentation."
|
||||
);
|
||||
}
|
||||
|
||||
if (!validatePythonVersionFormatForPyPy(pythonVersion)) {
|
||||
throw new Error(
|
||||
"Invalid format of Python version for PyPy. Python version should be specified in format 'x.y'. See README for examples and documentation."
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
pypyVersion: pypyVersion,
|
||||
pythonVersion: pythonVersion
|
||||
};
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue