Skip to content

Commit

Permalink
Fix PyPy installation on Windows to adopt new parameters format (#201)
Browse files Browse the repository at this point in the history
* test for pypy new version notation

* formatting

* uncommented condition

* test

* added pypy to test matrix

* test

* test

* restored all tests

* removed logs, added multiarch support for toolcache

* reduced test matrix

* removed extra condition about arch
  • Loading branch information
AlenaSviridenko authored Apr 12, 2021
1 parent a112144 commit dc73133
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 21 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/test-pypy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-18.04, ubuntu-20.04]
os: [macos-latest, windows-latest, ubuntu-18.04, ubuntu-latest]
pypy:
- 'pypy-2.7'
- 'pypy-3.6'
Expand All @@ -28,7 +28,7 @@ jobs:
- 'pypy-3.7-v7.3.2'
- 'pypy-3.6-v7.3.x'
- 'pypy-3.7-v7.x'
- 'pypy-3.6-v7.3.3rc1'
- 'pypy-2.7-v7.3.4rc1'
- 'pypy-3.7-nightly'

steps:
Expand Down
39 changes: 39 additions & 0 deletions __tests__/data/pypy.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,45 @@
}
]
},
{
"pypy_version": "7.3.4rc1",
"python_version": "2.7.18",
"stable": false,
"latest_pypy": false,
"date": "2021-03-19",
"files": [
{
"filename": "pypy2.7-v7.3.4rc1-aarch64.tar.bz2",
"arch": "aarch64",
"platform": "linux",
"download_url": "https://test.downloads.python.org/pypy/pypy2.7-v7.3.4rc1-aarch64.tar.bz2"
},
{
"filename": "pypy2.7-v7.3.4rc1-linux32.tar.bz2",
"arch": "i686",
"platform": "linux",
"download_url": "https://test.downloads.python.org/pypy/pypy2.7-v7.3.4rc1-linux32.tar.bz2"
},
{
"filename": "pypy2.7-v7.3.4rc1-linux64.tar.bz2",
"arch": "x64",
"platform": "linux",
"download_url": "https://test.downloads.python.org/pypy/pypy2.7-v7.3.4rc1-linux64.tar.bz2"
},
{
"filename": "pypy2.7-v7.3.4rc1-osx64.tar.bz2",
"arch": "x64",
"platform": "darwin",
"download_url": "https://test.downloads.python.org/pypy/pypy2.7-v7.3.4rc1-osx64.tar.bz2"
},
{
"filename": "pypy2.7-v7.3.4rc1-win64.zip",
"arch": "x64",
"platform": "win64",
"download_url": "https://test.downloads.python.org/pypy/pypy2.7-v7.3.4rc1-win64.zip"
}
]
},
{
"pypy_version": "7.3.3rc2",
"python_version": "3.7.7",
Expand Down
42 changes: 35 additions & 7 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1108,10 +1108,6 @@ function findPyPyVersion(versionSpec, architecture) {
let resolvedPythonVersion = '';
let installDir;
const pypyVersionSpec = parsePyPyVersion(versionSpec);
// PyPy only precompiles binaries for x86, but the architecture parameter defaults to x64.
if (utils_1.IS_WINDOWS && architecture === 'x64') {
architecture = 'x86';
}
({ installDir, resolvedPythonVersion, resolvedPyPyVersion } = findPyPyToolCache(pypyVersionSpec.pythonVersion, pypyVersionSpec.pypyVersion, architecture));
if (!installDir) {
({
Expand All @@ -1133,7 +1129,9 @@ exports.findPyPyVersion = findPyPyVersion;
function findPyPyToolCache(pythonVersion, pypyVersion, architecture) {
let resolvedPyPyVersion = '';
let resolvedPythonVersion = '';
let installDir = tc.find('PyPy', pythonVersion, architecture);
let installDir = utils_1.IS_WINDOWS
? findPyPyInstallDirForWindows(pythonVersion)
: 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.
Expand Down Expand Up @@ -1177,6 +1175,12 @@ function parsePyPyVersion(versionSpec) {
};
}
exports.parsePyPyVersion = parsePyPyVersion;
function findPyPyInstallDirForWindows(pythonVersion) {
let installDir = '';
utils_1.WINDOWS_ARCHS.forEach(architecture => (installDir = installDir || tc.find('PyPy', pythonVersion, architecture)));
return installDir;
}
exports.findPyPyInstallDirForWindows = findPyPyInstallDirForWindows;


/***/ }),
Expand Down Expand Up @@ -2327,6 +2331,8 @@ const path = __importStar(__webpack_require__(622));
const semver = __importStar(__webpack_require__(876));
exports.IS_WINDOWS = process.platform === 'win32';
exports.IS_LINUX = process.platform === 'linux';
exports.WINDOWS_ARCHS = ['x86', 'x64'];
exports.WINDOWS_PLATFORMS = ['win32', 'win64'];
const PYPY_VERSION_FILE = 'PYPY_VERSION';
/** create Symlinks for downloaded PyPy
* It should be executed only for downloaded versions in runtime, because
Expand Down Expand Up @@ -2893,7 +2899,9 @@ function findRelease(releases, pythonVersion, pypyVersion, architecture) {
const isPyPyVersionSatisfied = isPyPyNightly ||
semver.satisfies(pypyVersionToSemantic(item.pypy_version), pypyVersion);
const isArchPresent = item.files &&
item.files.some(file => file.arch === architecture && file.platform === process.platform);
(utils_1.IS_WINDOWS
? isArchPresentForWindows(item)
: isArchPresentForMacOrLinux(item, architecture, process.platform));
return isPythonVersionSatisfied && isPyPyVersionSatisfied && isArchPresent;
});
if (filterReleases.length === 0) {
Expand All @@ -2904,7 +2912,9 @@ function findRelease(releases, pythonVersion, pypyVersion, architecture) {
semver.compare(semver.coerce(current.python_version), semver.coerce(previous.python_version)));
});
const foundRelease = sortedReleases[0];
const foundAsset = foundRelease.files.find(item => item.arch === architecture && item.platform === process.platform);
const foundAsset = utils_1.IS_WINDOWS
? findAssetForWindows(foundRelease)
: findAssetForMacOrLinux(foundRelease, architecture, process.platform);
return {
foundAsset,
resolvedPythonVersion: foundRelease.python_version,
Expand All @@ -2926,6 +2936,24 @@ function pypyVersionToSemantic(versionSpec) {
return versionSpec.replace(prereleaseVersion, '$1-$2.$3');
}
exports.pypyVersionToSemantic = pypyVersionToSemantic;
function isArchPresentForWindows(item) {
return item.files.some((file) => utils_1.WINDOWS_ARCHS.includes(file.arch) &&
utils_1.WINDOWS_PLATFORMS.includes(file.platform));
}
exports.isArchPresentForWindows = isArchPresentForWindows;
function isArchPresentForMacOrLinux(item, architecture, platform) {
return item.files.some((file) => file.arch === architecture && file.platform === platform);
}
exports.isArchPresentForMacOrLinux = isArchPresentForMacOrLinux;
function findAssetForWindows(releases) {
return releases.files.find((item) => utils_1.WINDOWS_ARCHS.includes(item.arch) &&
utils_1.WINDOWS_PLATFORMS.includes(item.platform));
}
exports.findAssetForWindows = findAssetForWindows;
function findAssetForMacOrLinux(releases, architecture, platform) {
return releases.files.find((item) => item.arch === architecture && item.platform === platform);
}
exports.findAssetForMacOrLinux = findAssetForMacOrLinux;


/***/ }),
Expand Down
21 changes: 15 additions & 6 deletions src/find-pypy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as path from 'path';
import * as pypyInstall from './install-pypy';
import {
IS_WINDOWS,
WINDOWS_ARCHS,
validateVersion,
getPyPyVersionFromPath,
readExactPyPyVersionFile,
Expand All @@ -27,11 +28,6 @@ export async function findPyPyVersion(

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,
Expand Down Expand Up @@ -67,7 +63,9 @@ export function findPyPyToolCache(
) {
let resolvedPyPyVersion = '';
let resolvedPythonVersion = '';
let installDir: string | null = tc.find('PyPy', pythonVersion, architecture);
let installDir: string | null = IS_WINDOWS
? findPyPyInstallDirForWindows(pythonVersion)
: tc.find('PyPy', pythonVersion, architecture);

if (installDir) {
// 'tc.find' finds tool based on Python version but we also need to check
Expand Down Expand Up @@ -129,3 +127,14 @@ export function parsePyPyVersion(versionSpec: string): IPyPyVersionSpec {
pythonVersion: pythonVersion
};
}

export function findPyPyInstallDirForWindows(pythonVersion: string): string {
let installDir = '';

WINDOWS_ARCHS.forEach(
architecture =>
(installDir = installDir || tc.find('PyPy', pythonVersion, architecture))
);

return installDir;
}
50 changes: 44 additions & 6 deletions src/install-pypy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import fs from 'fs';

import {
IS_WINDOWS,
WINDOWS_ARCHS,
WINDOWS_PLATFORMS,
IPyPyManifestRelease,
createSymlinkInFolder,
isNightlyKeyword,
Expand Down Expand Up @@ -143,9 +145,9 @@ export function findRelease(
semver.satisfies(pypyVersionToSemantic(item.pypy_version), pypyVersion);
const isArchPresent =
item.files &&
item.files.some(
file => file.arch === architecture && file.platform === process.platform
);
(IS_WINDOWS
? isArchPresentForWindows(item)
: isArchPresentForMacOrLinux(item, architecture, process.platform));
return isPythonVersionSatisfied && isPyPyVersionSatisfied && isArchPresent;
});

Expand All @@ -167,9 +169,9 @@ export function findRelease(
});

const foundRelease = sortedReleases[0];
const foundAsset = foundRelease.files.find(
item => item.arch === architecture && item.platform === process.platform
);
const foundAsset = IS_WINDOWS
? findAssetForWindows(foundRelease)
: findAssetForMacOrLinux(foundRelease, architecture, process.platform);

return {
foundAsset,
Expand All @@ -191,3 +193,39 @@ export function pypyVersionToSemantic(versionSpec: string) {
const prereleaseVersion = /(\d+\.\d+\.\d+)((?:a|b|rc))(\d*)/g;
return versionSpec.replace(prereleaseVersion, '$1-$2.$3');
}

export function isArchPresentForWindows(item: any) {
return item.files.some(
(file: any) =>
WINDOWS_ARCHS.includes(file.arch) &&
WINDOWS_PLATFORMS.includes(file.platform)
);
}

export function isArchPresentForMacOrLinux(
item: any,
architecture: string,
platform: string
) {
return item.files.some(
(file: any) => file.arch === architecture && file.platform === platform
);
}

export function findAssetForWindows(releases: any) {
return releases.files.find(
(item: any) =>
WINDOWS_ARCHS.includes(item.arch) &&
WINDOWS_PLATFORMS.includes(item.platform)
);
}

export function findAssetForMacOrLinux(
releases: any,
architecture: string,
platform: string
) {
return releases.files.find(
(item: any) => item.arch === architecture && item.platform === platform
);
}
2 changes: 2 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import * as semver from 'semver';

export const IS_WINDOWS = process.platform === 'win32';
export const IS_LINUX = process.platform === 'linux';
export const WINDOWS_ARCHS = ['x86', 'x64'];
export const WINDOWS_PLATFORMS = ['win32', 'win64'];
const PYPY_VERSION_FILE = 'PYPY_VERSION';

export interface IPyPyManifestAsset {
Expand Down

0 comments on commit dc73133

Please sign in to comment.