From bd1ce022fef327134f4cf20f3de4f5b157058c80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kry=C5=A1tof=20Korb?= Date: Thu, 4 Jan 2024 00:33:23 +0100 Subject: [PATCH] Enhance reading from .python-version --- __tests__/utils.test.ts | 26 ++++++++++++++++++++++++-- src/setup-python.ts | 4 ++-- src/utils.ts | 29 ++++++++++++++++++++++------- 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/__tests__/utils.test.ts b/__tests__/utils.test.ts index f5e36478..122c7534 100644 --- a/__tests__/utils.test.ts +++ b/__tests__/utils.test.ts @@ -10,7 +10,7 @@ import { validatePythonVersionFormatForPyPy, isCacheFeatureAvailable, getVersionInputFromFile, - getVersionInputFromPlainFile, + getVersionsInputFromPlainFile, getVersionInputFromTomlFile, getNextPageUrl } from '../src/utils'; @@ -91,7 +91,7 @@ const tempDir = path.join( ); describe('Version from file test', () => { - it.each([getVersionInputFromPlainFile, getVersionInputFromFile])( + it.each([getVersionsInputFromPlainFile, getVersionInputFromFile])( 'Version from plain file test', async _fn => { await io.mkdirP(tempDir); @@ -102,6 +102,28 @@ describe('Version from file test', () => { expect(_fn(pythonVersionFilePath)).toEqual([pythonVersionFileContent]); } ); + it.each([getVersionsInputFromPlainFile, getVersionInputFromFile])( + 'Versions from multiline plain file test', + async _fn => { + await io.mkdirP(tempDir); + const pythonVersionFileName = 'python-version.file'; + const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName); + const pythonVersionFileContent = '3.8\r\n3.7'; + fs.writeFileSync(pythonVersionFilePath, pythonVersionFileContent); + expect(_fn(pythonVersionFilePath)).toEqual(['3.8', '3.7']); + } + ); + it.each([getVersionsInputFromPlainFile, getVersionInputFromFile])( + 'Version from complex plain file test', + async _fn => { + await io.mkdirP(tempDir); + const pythonVersionFileName = 'python-version.file'; + const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName); + const pythonVersionFileContent = '3.10/envs/virtualenv\r# 3.9\n3.8\r\n3.7\r\n 3.6 \r\n'; + fs.writeFileSync(pythonVersionFilePath, pythonVersionFileContent); + expect(_fn(pythonVersionFilePath)).toEqual(['3.10', '3.8', '3.7', '3.6']); + } + ); it.each([getVersionInputFromTomlFile, getVersionInputFromFile])( 'Version from standard pyproject.toml test', async _fn => { diff --git a/src/setup-python.ts b/src/setup-python.ts index 0dd45f0c..329fe9e7 100644 --- a/src/setup-python.ts +++ b/src/setup-python.ts @@ -11,7 +11,7 @@ import { logWarning, IS_MAC, getVersionInputFromFile, - getVersionInputFromPlainFile + getVersionsInputFromPlainFile } from './utils'; function isPyPyVersion(versionSpec: string) { @@ -35,7 +35,7 @@ async function cacheDependencies(cache: string, pythonVersion: string) { function resolveVersionInputFromDefaultFile(): string[] { const couples: [string, (versionFile: string) => string[]][] = [ - ['.python-version', getVersionInputFromPlainFile] + ['.python-version', getVersionsInputFromPlainFile] ]; for (const [versionFile, _fn] of couples) { logWarning( diff --git a/src/utils.ts b/src/utils.ts index 644b4af5..157dd201 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -260,13 +260,28 @@ export function getVersionInputFromTomlFile(versionFile: string): string[] { } /** - * Python version extracted from a plain text file. + * Python versions extracted from a plain text file. + * - Resolves multiple versions from multiple lines. + * - Handles pyenv-virtualenv pointers (e.g. `3.10/envs/virtualenv`). + * - Ignores empty lines and lines starting with `#` + * - Trims whitespace. */ -export function getVersionInputFromPlainFile(versionFile: string): string[] { - core.debug(`Trying to resolve version form ${versionFile}`); - const version = fs.readFileSync(versionFile, 'utf8').trim(); - core.info(`Resolved ${versionFile} as ${version}`); - return [version]; +export function getVersionsInputFromPlainFile(versionFile: string): string[] { + core.debug(`Trying to resolve versions form ${versionFile}`); + const content = fs.readFileSync(versionFile, 'utf8').trim(); + const lines = content.split(/\r\n|\r|\n/); + const versions = lines + .map(line => { + if (line.startsWith('#') || line.trim() === '') { + return undefined; + } + let version: string = line.trim(); + version = version.split('/')[0]; + return version; + }) + .filter(version => version !== undefined) as string[]; + core.info(`Resolved ${versionFile} as ${versions.join(', ')}`); + return versions; } /** @@ -276,7 +291,7 @@ export function getVersionInputFromFile(versionFile: string): string[] { if (versionFile.endsWith('.toml')) { return getVersionInputFromTomlFile(versionFile); } else { - return getVersionInputFromPlainFile(versionFile); + return getVersionsInputFromPlainFile(versionFile); } }