mirror of
https://github.com/actions/setup-python.git
synced 2025-04-19 19:33:29 +00:00
Add utils to extract python version from files
This commit is contained in:
parent
3e4f08959a
commit
5fe4cfd090
@ -1,9 +1,17 @@
|
||||
import * as cache from '@actions/cache';
|
||||
import * as core from '@actions/core';
|
||||
import * as io from '@actions/io';
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
import {
|
||||
validateVersion,
|
||||
validatePythonVersionFormatForPyPy,
|
||||
isCacheFeatureAvailable
|
||||
isCacheFeatureAvailable,
|
||||
getVersionInputFromFile,
|
||||
getVersionInputFromPlainFile,
|
||||
getVersionInputFromTomlFile
|
||||
} from '../src/utils';
|
||||
|
||||
jest.mock('@actions/cache');
|
||||
@ -73,3 +81,48 @@ describe('isCacheFeatureAvailable', () => {
|
||||
expect(isCacheFeatureAvailable()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
const tempDir = path.join(
|
||||
__dirname,
|
||||
'runner',
|
||||
path.join(Math.random().toString(36).substring(7)),
|
||||
'temp'
|
||||
);
|
||||
|
||||
describe('Version from file test', () => {
|
||||
it.each([getVersionInputFromPlainFile, getVersionInputFromFile])(
|
||||
'Version from plain file test',
|
||||
async _fn => {
|
||||
await io.mkdirP(tempDir);
|
||||
const pythonVersionFileName = 'python-version.file';
|
||||
const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName);
|
||||
const pythonVersionFileContent = '3.7';
|
||||
fs.writeFileSync(pythonVersionFilePath, pythonVersionFileContent);
|
||||
expect(_fn(pythonVersionFilePath)).toEqual([pythonVersionFileContent]);
|
||||
}
|
||||
);
|
||||
it.each([getVersionInputFromTomlFile, getVersionInputFromFile])(
|
||||
'Version from standard pyproject.toml test',
|
||||
async _fn => {
|
||||
await io.mkdirP(tempDir);
|
||||
const pythonVersionFileName = 'pyproject.toml';
|
||||
const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName);
|
||||
const pythonVersion = '>=3.7';
|
||||
const pythonVersionFileContent = `[project]\nrequires-python = "${pythonVersion}"`;
|
||||
fs.writeFileSync(pythonVersionFilePath, pythonVersionFileContent);
|
||||
expect(_fn(pythonVersionFilePath)).toEqual([pythonVersion]);
|
||||
}
|
||||
);
|
||||
it.each([getVersionInputFromTomlFile, getVersionInputFromFile])(
|
||||
'Version from poetry pyproject.toml test',
|
||||
async _fn => {
|
||||
await io.mkdirP(tempDir);
|
||||
const pythonVersionFileName = 'pyproject.toml';
|
||||
const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName);
|
||||
const pythonVersion = '>=3.7';
|
||||
const pythonVersionFileContent = `[tool.poetry.dependencies]\npython = "${pythonVersion}"`;
|
||||
fs.writeFileSync(pythonVersionFilePath, pythonVersionFileContent);
|
||||
expect(_fn(pythonVersionFilePath)).toEqual([pythonVersion]);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -5,7 +5,14 @@ import * as path from 'path';
|
||||
import * as os from 'os';
|
||||
import fs from 'fs';
|
||||
import {getCacheDistributor} from './cache-distributions/cache-factory';
|
||||
import {isCacheFeatureAvailable, logWarning, IS_MAC} from './utils';
|
||||
import {
|
||||
isCacheFeatureAvailable,
|
||||
logWarning,
|
||||
IS_MAC,
|
||||
getVersionInputFromFile,
|
||||
getVersionInputFromPlainFile,
|
||||
getVersionInputFromTomlFile
|
||||
} from './utils';
|
||||
|
||||
function isPyPyVersion(versionSpec: string) {
|
||||
return versionSpec.startsWith('pypy');
|
||||
@ -22,43 +29,48 @@ async function cacheDependencies(cache: string, pythonVersion: string) {
|
||||
await cacheDistributor.restoreCache();
|
||||
}
|
||||
|
||||
function resolveVersionInput() {
|
||||
const versions = core.getMultilineInput('python-version');
|
||||
let versionFile = core.getInput('python-version-file');
|
||||
function resolveVersionInputFromDefaultFile(): string[] {
|
||||
const couples: [string, (versionFile: string) => string[]][] = [
|
||||
['.python-version', getVersionInputFromPlainFile],
|
||||
['pyproject.toml', getVersionInputFromTomlFile]
|
||||
];
|
||||
for (const [versionFile, _fn] of couples) {
|
||||
logWarning(
|
||||
`Neither 'python-version' nor 'python-version-file' inputs were supplied. Attempting to find '${versionFile}' file.`
|
||||
);
|
||||
if (fs.existsSync(versionFile)) {
|
||||
return _fn(versionFile);
|
||||
} else {
|
||||
logWarning(`${versionFile} doesn't exist.`);
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
if (versions.length && versionFile) {
|
||||
function resolveVersionInput() {
|
||||
let versions = core.getMultilineInput('python-version');
|
||||
const versionFile = core.getInput('python-version-file');
|
||||
|
||||
if (versions.length) {
|
||||
if (versionFile) {
|
||||
core.warning(
|
||||
'Both python-version and python-version-file inputs are specified, only python-version will be used.'
|
||||
);
|
||||
}
|
||||
|
||||
if (versions.length) {
|
||||
return versions;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (versionFile) {
|
||||
if (!fs.existsSync(versionFile)) {
|
||||
throw new Error(
|
||||
`The specified python version file at: ${versionFile} doesn't exist.`
|
||||
);
|
||||
}
|
||||
const version = fs.readFileSync(versionFile, 'utf8');
|
||||
core.info(`Resolved ${versionFile} as ${version}`);
|
||||
return [version];
|
||||
versions = getVersionInputFromFile(versionFile);
|
||||
} else {
|
||||
versions = resolveVersionInputFromDefaultFile();
|
||||
}
|
||||
}
|
||||
|
||||
logWarning(
|
||||
"Neither 'python-version' nor 'python-version-file' inputs were supplied. Attempting to find '.python-version' file."
|
||||
);
|
||||
versionFile = '.python-version';
|
||||
if (fs.existsSync(versionFile)) {
|
||||
const version = fs.readFileSync(versionFile, 'utf8');
|
||||
core.info(`Resolved ${versionFile} as ${version}`);
|
||||
return [version];
|
||||
}
|
||||
|
||||
logWarning(`${versionFile} doesn't exist.`);
|
||||
|
||||
versions = Array.from(versions, version => version.split(',').join(' '));
|
||||
return versions;
|
||||
}
|
||||
|
||||
|
63
src/utils.ts
63
src/utils.ts
@ -4,6 +4,7 @@ import * as core from '@actions/core';
|
||||
import fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as semver from 'semver';
|
||||
import * as toml from 'toml';
|
||||
import * as exec from '@actions/exec';
|
||||
|
||||
export const IS_WINDOWS = process.platform === 'win32';
|
||||
@ -181,3 +182,65 @@ export async function getOSInfo() {
|
||||
return osInfo;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Python version extracted from the TOML file.
|
||||
* If the `project` key is present at the root level, the version is assumed to
|
||||
* be specified according to PEP 621 in `project.requires-python`.
|
||||
* Otherwise, if the `tool` key is present at the root level, the version is
|
||||
* assumed to be specified using poetry under `tool.poetry.dependencies.python`.
|
||||
* If none is present, returns an empty list.
|
||||
*/
|
||||
export function getVersionInputFromTomlFile(versionFile: string): string[] {
|
||||
core.debug(`Trying to resolve version form ${versionFile}`);
|
||||
|
||||
const pyprojectFile = fs.readFileSync(versionFile, 'utf8');
|
||||
const pyprojectConfig = toml.parse(pyprojectFile);
|
||||
const versions = [];
|
||||
|
||||
if ('project' in pyprojectConfig) {
|
||||
// standard project metadata (PEP 621)
|
||||
const projectMetadata = pyprojectConfig['project'];
|
||||
if ('requires-python' in projectMetadata) {
|
||||
versions.push(projectMetadata['requires-python']);
|
||||
}
|
||||
} else {
|
||||
// python poetry
|
||||
if ('tool' in pyprojectConfig) {
|
||||
const toolMetadata = pyprojectConfig['tool'];
|
||||
if ('poetry' in toolMetadata) {
|
||||
const poetryMetadata = toolMetadata['poetry'];
|
||||
if ('dependencies' in poetryMetadata) {
|
||||
const dependenciesMetadata = poetryMetadata['dependencies'];
|
||||
if ('python' in dependenciesMetadata) {
|
||||
versions.push(dependenciesMetadata['python']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
core.info(`Extracted ${versions} from ${versionFile}`);
|
||||
return versions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Python version extracted from a plain text file.
|
||||
*/
|
||||
export function getVersionInputFromPlainFile(versionFile: string): string[] {
|
||||
core.debug(`Trying to resolve version form ${versionFile}`);
|
||||
const version = fs.readFileSync(versionFile, 'utf8');
|
||||
core.info(`Resolved ${versionFile} as ${version}`);
|
||||
return [version];
|
||||
}
|
||||
|
||||
/**
|
||||
* Python version extracted from a plain or TOML file.
|
||||
*/
|
||||
export function getVersionInputFromFile(versionFile: string): string[] {
|
||||
if (versionFile.endsWith('.toml')) {
|
||||
return getVersionInputFromTomlFile(versionFile);
|
||||
} else {
|
||||
return getVersionInputFromPlainFile(versionFile);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user