8000 Enhance reading from .python-version (#787) · Bostt/setup-python@5db1cf9 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5db1cf9

Browse files
authored
Enhance reading from .python-version (actions#787)
* Enhance reading from .python-version * Fix typos * Fix lint * Add built files * Don't use EOL versions 10000 in `utils.test.ts` * Fix Prettier * Don't use unreleased versions in `utils.test.ts` * Update versions in `utils.test.ts` again
1 parent a26af69 commit 5db1cf9

File tree

4 files changed

+99
-41
lines changed

4 files changed

+99
-41
lines changed

__tests__/utils.test.ts

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
validatePythonVersionFormatForPyPy,
1111
isCacheFeatureAvailable,
1212
getVersionInputFromFile,
13-
getVersionInputFromPlainFile,
13+
getVersionsInputFromPlainFile,
1414
getVersionInputFromTomlFile,
1515
getNextPageUrl,
1616
isGhes,
@@ -24,10 +24,10 @@ jest.mock('@actions/core');
2424

2525
describe('validatePythonVersionFormatForPyPy', () => {
2626
it.each([
27-
['3.6', true],
28-
['3.7', true],
29-
['3.6.x', false],
30-
['3.7.x', false],
27+
['3.12', true],
28+
['3.13', true],
29+
['3.12.x', false],
30+
['3.13.x', false],
3131
['3.x', false],
3232
['3', false]
3333
])('%s -> %s', (input, expected) => {
@@ -95,24 +95,52 @@ const tempDir = path.join(
9595
);
9696

9797
describe('Version from file test', () => {
98-
it.each([getVersionInputFromPlainFile, getVersionInputFromFile])(
98+
it.each([getVersionsInputFromPlainFile, getVersionInputFromFile])(
9999
'Version from plain file test',
100100
async _fn => {
101101
await io.mkdirP(tempDir);
102102
const pythonVersionFileName = 'python-version.file';
103103
const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName);
104-
const pythonVersionFileContent = '3.7';
104+
const pythonVersionFileContent = '3.13';
105105
fs.writeFileSync(pythonVersionFilePath, pythonVersionFileContent);
106106
expect(_fn(pythonVersionFilePath)).toEqual([pythonVersionFileContent]);
107107
}
108108
);
109+
it.each([getVersionsInputFromPlainFile, getVersionInputFromFile])(
110+
'Versions from multiline plain file test',
111+
async _fn => {
112+
await io.mkdirP(tempDir);
113+
const pythonVersionFileName = 'python-version.file';
114+
const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName);
115+
const pythonVersionFileContent = '3.13\r\n3.12';
116+
fs.writeFileSync(pythonVersionFilePath, pythonVersionFileContent);
117+
expect(_fn(pythonVersionFilePath)).toEqual(['3.13', '3.12']);
118+
}
119+
);
120+
it.each([getVersionsInputFromPlainFile, getVersionInputFromFile])(
121+
'Version from complex plain file test',
122+
async _fn => {
123+
await io.mkdirP(tempDir);
124+
const pythonVersionFileName = 'python-version.file';
125+
const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName);
126+
const pythonVersionFileContent =
127+
'3.13/envs/virtualenv\r# 3.12\n3.11\r\n3.10\r\n 3.9 \r\n';
128+
fs.writeFileSync(pythonVersionFilePath, pythonVersionFileContent);
129+
expect(_fn(pythonVersionFilePath)).toEqual([
130+
'3.13',
131+
'3.11',
132+
'3.10',
133+
'3.9'
134+
]);
135+
}
136+
);
109137
it.each([getVersionInputFromTomlFile, getVersionInputFromFile])(
110138
'Version from standard pyproject.toml test',
111139
async _fn => {
112140
await io.mkdirP(tempDir);
113141
const pythonVersionFileName = 'pyproject.toml';
114142
const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName);
115-
const pythonVersion = '>=3.7.0';
143+
const pythonVersion = '>=3.13.0';
116144
const pythonVersionFileContent = `[project]\nrequires-python = "${pythonVersion}"`;
117145
fs.writeFileSync(pythonVersionFilePath, pythonVersionFileContent);
118146
expect(_fn(pythonVersionFilePath)).toEqual([pythonVersion]);
@@ -124,7 +152,7 @@ describe('Version from file test', () => {
124152
await io.mkdirP(tempDir);
125153
const pythonVersionFileName = 'pyproject.toml';
126154
const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName);
127-
const pythonVersion = '>=3.7.0';
155+
const pythonVersion = '>=3.13.0';
128156
const pythonVersionFileContent = `[tool.poetry.dependencies]\npython = "${pythonVersion}"`;
129157
fs.writeFileSync(pythonVersionFilePath, pythonVersionFileContent);
130158
expect(_fn(pythonVersionFilePath)).toEqual([pythonVersion]);
@@ -145,9 +173,9 @@ describe('Version from file test', () => {
145173
async _fn => {
146174
const toolVersionFileName = '.tool-versions';
147175
const toolVersionFilePath = path.join(tempDir, toolVersionFileName);
148-
const toolVersionContent = 'python 3.9.10\nnodejs 16';
176+
const toolVersionContent = 'python 3.13.2\nnodejs 16';
149177
fs.writeFileSync(toolVersionFilePath, toolVersionContent);
150-
expect(_fn(toolVersionFilePath)).toEqual(['3.9.10']);
178+
expect(_fn(toolVersionFilePath)).toEqual(['3.13.2']);
151179
}
152180
);
153181

@@ -156,9 +184,9 @@ describe('Version from file test', () => {
156184
async _fn => {
157185
const toolVersionFileName = '.tool-versions';
158186
const toolVersionFilePath = path.join(tempDir, toolVersionFileName);
159-
const toolVersionContent = '# python 3.8\npython 3.9';
187+
const toolVersionContent = '# python 3.13\npython 3.12';
160188
fs.writeFileSync(toolVersionFilePath, toolVersionContent);
161-
expect(_fn(toolVersionFilePath)).toEqual(['3.9']);
189+
expect(_fn(toolVersionFilePath)).toEqual(['3.12']);
162190
}
163191
);
164192

@@ -167,9 +195,9 @@ describe('Version from file test', () => {
167195
async _fn => {
168196
const toolVersionFileName = '.tool-versions';
169197
const toolVersionFilePath = path.join(tempDir, toolVersionFileName);
170-
const toolVersionContent = ' python 3.10 ';
198+
const toolVersionContent = ' python 3.13 ';
171199
fs.writeFileSync(toolVersionFilePath, toolVersionContent);
172-
expect(_fn(toolVersionFilePath)).toEqual(['3.10']);
200+
expect(_fn(toolVersionFilePath)).toEqual(['3.13']);
173201
}
174202
);
175203

@@ -178,9 +206,9 @@ describe('Version from file test', () => {
178206
async _fn => {
179207
const toolVersionFileName = '.tool-versions';
180208
const toolVersionFilePath = path.join(tempDir, toolVersionFileName);
181-
const toolVersionContent = 'python v3.9.10';
209+
const toolVersionContent = 'python v3.13.2';
182210
fs.writeFileSync(toolVersionFilePath, toolVersionContent);
183-
expect(_fn(toolVersionFilePath)).toEqual(['3.9.10']);
211+
expect(_fn(toolVersionFilePath)).toEqual(['3.13.2']);
184212
}
185213
);
186214

@@ -189,9 +217,9 @@ describe('Version from file test', () => {
189217
async _fn => {
190218
const toolVersionFileName = '.tool-versions';
191219
const toolVersionFilePath = path.join(tempDir, toolVersionFileName);
192-
const toolVersionContent = 'python pypy3.10-7.3.14';
220+
const toolVersionContent = 'python pypy3.10-7.3.19';
193221
fs.writeFileSync(toolVersionFilePath, toolVersionContent);
194-
expect(_fn(toolVersionFilePath)).toEqual(['pypy3.10-7.3.14']);
222+
expect(_fn(toolVersionFilePath)).toEqual(['pypy3.10-7.3.19']);
195223
}
196224
);
197225

dist/setup/index.js

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -96929,7 +96929,7 @@ function cacheDependencies(cache, pythonVersion) {
9692996929
}
9693096930
function resolveVersionInputFromDefaultFile() {
9693196931
const couples = [
96932-
['.python-version', utils_1.getVersionInputFromPlainFile]
96932+
['.python-version', utils_1.getVersionsInputFromPlainFile]
9693396933
];
9693496934
for (const [versionFile, _fn] of couples) {
9693596935
(0, utils_1.logWarning)(`Neither 'python-version' nor 'python-version-file' inputs were supplied. Attempting to find '${versionFile}' file.`);
@@ -97066,7 +97066,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
9706697066
return (mod && mod.__esModule) ? mod : { "default": mod };
9706797067
};
9706897068
Object.defineProperty(exports, "__esModule", ({ value: true }));
97069-
exports.getDownloadFileName = exports.getNextPageUrl = exports.getBinaryDirectory = exports.getVersionInputFromFile = exports.getVersionInputFromToolVersions = exports.getVersionInputFromPlainFile = exports.getVersionInputFromTomlFile = exports.getOSInfo = exports.getLinuxInfo = exports.logWarning = exports.isCacheFeatureAvailable = exports.isGhes = exports.validatePythonVersionFormatForPyPy = exports.writeExactPyPyVersionFile = exports.readExactPyPyVersionFile = exports.getPyPyVersionFromPath = exports.isNightlyKeyword = exports.validateVersion = exports.createSymlinkInFolder = exports.WINDOWS_PLATFORMS = exports.WINDOWS_ARCHS = exports.IS_MAC = exports.IS_LINUX = exports.IS_WINDOWS = void 0;
97069+
exports.getDownloadFileName = exports.getNextPageUrl = exports.getBinaryDirectory = exports.getVersionInputFromFile = exports.getVersionInputFromToolVersions = exports.getVersionsInputFromPlainFile = exports.getVersionInputFromTomlFile = exports.getOSInfo = exports.getLinuxInfo = exports.logWarning = exports.isCacheFeatureAvailable = exports.isGhes = exports.validatePythonVersionFormatForPyPy = exports.writeExactPyPyVersionFile = exports.readExactPyPyVersionFile = exports.getPyPyVersionFromPath = exports.isNightlyKeyword = exports.validateVersion = exports.createSymlinkInFolder = exports.WINDOWS_PLATFORMS = exports.WINDOWS_ARCHS = exports.IS_MAC = exports.IS_LINUX = exports.IS_WINDOWS = void 0;
9707097070
/* eslint no-unsafe-finally: "off" */
9707197071
const cache = __importStar(__nccwpck_require__(5116));
9707297072
const core = __importStar(__nccwpck_require__(7484));
@@ -97247,7 +97247,7 @@ function extractValue(obj, keys) {
9724797247
* If none is present, returns an empty list.
9724897248
*/
9724997249
function getVersionInputFromTomlFile(versionFile) {
97250-
core.debug(`Trying to resolve version form ${versionFile}`);
97250+
core.debug(`Trying to resolve version from ${versionFile}`);
9725197251
let pyprojectFile = fs_1.default.readFileSync(versionFile, 'utf8');
9725297252
// Normalize the line endings in the pyprojectFile
9725397253
pyprojectFile = pyprojectFile.replace(/\r\n/g, '\n');
@@ -97280,15 +97280,30 @@ function getVersionInputFromTomlFile(versionFile) {
9728097280
}
9728197281
exports.getVersionInputFromTomlFile = getVersionInputFromTomlFile;
9728297282
/**
97283-
* Python version extracted from a plain text file.
97284-
*/
97285-
function getVersionInputFromPlainFile(versionFile) {
97286-
core.debug(`Trying to resolve version form ${versionFile}`);
97287-
const version = fs_1.default.readFileSync(versionFile, 'utf8').trim();
97288-
core.info(`Resolved ${versionFile} as ${version}`);
97289-
return [version];
97283+
* Python versions extracted from a plain text file.
97284+
* - Resolves multiple versions from multiple lines.
97285+
* - Handles pyenv-virtualenv pointers (e.g. `3.10/envs/virtualenv`).
97286+
* - Ignores empty lines and lines starting with `#`
97287+
* - Trims whitespace.
97288+
*/
97289+
function getVersionsInputFromPlainFile(versionFile) {
97290+
core.debug(`Trying to resolve versions from ${versionFile}`);
97291+
const content = fs_1.default.readFileSync(versionFile, 'utf8').trim();
97292+
const lines = content.split(/\r\n|\r|\n/);
97293+
const versions = lines
97294+
.map(line => {
97295+
if (line.startsWith('#') || line.trim() === '') {
97296+
return undefined;
97297+
}
97298+
let version = line.trim();
97299+
version = version.split('/')[0];
97300+
return version;
97301+
})
97302+
.filter(version => version !== undefined);
97303+
core.info(`Resolved ${versionFile} as ${versions.join(', ')}`);
97304+
return versions;
9729097305
}
97291-
exports.getVersionInputFromPlainFile = getVersionInputFromPlainFile;
97306+
exports.getVersionsInputFromPlainFile = getVersionsInputFromPlainFile;
9729297307
/**
9729397308
* Python version extracted from a .tool-versions file.
9729497309
*/
@@ -97331,7 +97346,7 @@ function getVersionInputFromFile(versionFile) {
9733197346
return getVersionInputFromToolVersions(versionFile);
9733297347
}
9733397348
else {
97334-
return getVersionInputFromPlainFile(versionFile);
97349+
return getVersionsInputFromPlainFile(versionFile);
9733597350
}
9733697351
}
9733797352
exports.getVersionInputFromFile = getVersionInputFromFile;

src/setup-python.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
logWarning,
1212
IS_MAC,
1313
getVersionInputFromFile,
14-
getVersionInputFromPlainFile
14+
getVersionsInputFromPlainFile
1515
} from './utils';
1616

1717
function isPyPyVersion(versionSpec: string) {
@@ -35,7 +35,7 @@ async function cacheDependencies(cache: string, pythonVersion: string) {
3535

3636
function resolveVersionInputFromDefaultFile(): string[] {
3737
const couples: [string, (versionFile: string) => string[]][] = [
38-
['.python-version', getVersionInputFromPlainFile]
38+
['.python-version', getVersionsInputFromPlainFile]
3939
];
4040
for (const [versionFile, _fn] of couples) {
4141
logWarning(

src/utils.ts

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ function extractValue(obj: any, keys: string[]): string | undefined {
228228
* If none is present, returns an empty list.
229229
*/
230230
export function getVersionInputFromTomlFile(versionFile: string): string[] {
231-
core.debug(`Trying to resolve version form ${versionFile}`);
231+
core.debug(`Trying to resolve version from ${versionFile}`);
232232

233233
let pyprojectFile = fs.readFileSync(versionFile, 'utf8');
234234
// Normalize the line endings in the pyprojectFile
@@ -269,13 +269,28 @@ export function getVersionInputFromTomlFile(versionFile: string): string[] {
269269
}
270270

271271
/**
272-
* Python version extracted from a plain text file.
272+
* Python versions extracted from a plain text file.
273+
* - Resolves multiple versions from multiple lines.
274+
* - Handles pyenv-virtualenv pointers (e.g. `3.10/envs/virtualenv`).
275+
* - Ignores empty lines and lines starting with `#`
276+
* - Trims whitespace.
273277
*/
274-
export function getVersionInputFromPlainFile(versionFile: string): string[] {
275-
core.debug(`Trying to resolve version form ${versionFile}`);
276-
const version = fs.readFileSync(versionFile, 'utf8').trim();
277-
core.info(`Resolved ${versionFile} as ${version}`);
278-
return [version];
278+
export function getVersionsInputFromPlainFile(versionFile: string): string[] {
279+
core.debug(`Trying to resolve versions from ${versionFile}`);
280+
const content = fs.readFileSync(versionFile, 'utf8').trim();
281+
const lines = content.split(/\r\n|\r|\n/);
282+
const versions = lines
283+
.map(line => {
284+
if (line.startsWith('#') || line.trim() === '') {
285+
return undefined;
286+
}
287+
let version: string = line.trim();
288+
version = version.split('/')[0];
289+
return version;
290+
})
291+
.filter(version => version !== undefined) as string[];
292+
core.info(`Resolved ${versionFile} as ${versions.join(', ')}`);
293+
return versions;
279294
}
280295

281296
/**
@@ -319,7 +334,7 @@ export function getVersionInputFromFile(versionFile: string): string[] {
319334
} else if (versionFile.match('.tool-versions')) {
320335
return getVersionInputFromToolVersions(versionFile);
321336
} else {
322-
return getVersionInputFromPlainFile(versionFile);
337+
return getVersionsInputFromPlainFile(versionFile);
323338
}
324339
}
325340

0 commit comments

Comments
 (0)
0