Skip to content

Commit 36da51d

Browse files
aradkdjCopilot
andauthored
Add version parsing from Pipfile (actions#1067)
* feature: add version parsing from Pipfile * Update utils.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/utils.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/utils.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * chore: update dist/setup/index.js --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 3c6f142 commit 36da51d

File tree

6 files changed

+308
-3
lines changed

6 files changed

+308
-3
lines changed

.github/workflows/test-python-freethreaded.yml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,86 @@ jobs:
242242
with:
243243
python-version-file: .tool-versions
244244

245+
setup-versions-from-pipfile-with-python_version:
246+
name: Setup ${{ matrix.python }} ${{ matrix.os }} Pipfile
247+
runs-on: ${{ matrix.os }}
248+
strategy:
249+
fail-fast: false
250+
matrix:
251+
os:
252+
[
253+
macos-latest,
254+
windows-latest,
255+
ubuntu-22.04,
256+
ubuntu-22.04-arm,
257+
macos-13,
258+
ubuntu-latest,
259+
ubuntu-24.04-arm
260+
]
261+
python: [3.13t, 3.14t-dev]
262+
steps:
263+
- name: Checkout
264+
uses: actions/checkout@v4
265+
266+
- name: build-version-file ${{ matrix.python }}
267+
run: |
268+
echo '[requires]
269+
python_version = "${{ matrix.python }}"
270+
' > Pipfile
271+
272+
- name: setup-python ${{ matrix.python }}
273+
id: setup-python
274+
uses: ./
275+
with:
276+
python-version-file: Pipfile
277+
278+
- name: Check python-path
279+
run: ./__tests__/check-python-path.sh '${{ steps.setup-python.outputs.python-path }}'
280+
shell: bash
281+
282+
- name: Run simple code
283+
run: python -c 'import math; print(math.factorial(5))'
284+
285+
setup-versions-from-pipfile-with-python_full_version:
286+
name: Setup ${{ matrix.python }} ${{ matrix.os }} .tool-versions file
287+
runs-on: ${{ matrix.os }}
288+
strategy:
289+
fail-fast: false
290+
matrix:
291+
os:
292+
[
293+
macos-latest,
294+
windows-latest,
295+
ubuntu-22.04,
296+
ubuntu-22.04-arm,
297+
macos-13,
298+
ubuntu-latest,
299+
ubuntu-24.04-arm
300+
]
301+
python: [3.13.0t, 3.13.1t, 3.13.2t, 3.14t-dev]
302+
steps:
303+
- name: Checkout
304+
uses: actions/checkout@v4
305+
306+
- name: build-version-file ${{ matrix.python }}
307+
run: |
308+
echo '[requires]
309+
python_full_version = "${{ matrix.python }}"
310+
' > Pipfile
311+
312+
- name: setup-python ${{ matrix.python }}
313+
id: setup-python
314+
uses: ./
315+
with:
316+
python-version-file: Pipfile
317+
318+
- name: Check python-path
319+
run: ./__tests__/check-python-path.sh '${{ steps.setup-python.outputs.python-path }}'
320+
shell: bash
321+
322+
- name: Run simple code
323+
run: python -c 'import math; print(math.factorial(5))'
324+
245325
setup-pre-release-version-from-manifest:
246326
name: Setup 3.14.0-alpha.6 ${{ matrix.os }}
247327
runs-on: ${{ matrix.os }}

.github/workflows/test-python.yml

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,106 @@ jobs:
284284
with:
285285
python-version-file: .tool-versions
286286

287+
setup-versions-from-pipfile-with-python_version:
288+
name: Setup ${{ matrix.python }} ${{ matrix.os }} Pipfile with python_version
289+
runs-on: ${{ matrix.os }}
290+
strategy:
291+
fail-fast: false
292+
matrix:
293+
os:
294+
[
295+
macos-latest,
296+
windows-latest,
297+
ubuntu-22.04,
298+
ubuntu-22.04-arm,
299+
macos-13,
300+
ubuntu-latest,
301+
ubuntu-24.04-arm
302+
]
303+
python: [3.9.13, 3.10.11, 3.11.9, 3.13.2]
304+
steps:
305+
- name: Checkout
306+
uses: actions/checkout@v4
307+
308+
- name: build-version-file ${{ matrix.python }}
309+
run: |
310+
echo '[requires]
311+
python_version = "${{ matrix.python }}"
312+
' > Pipfile
313+
314+
- name: setup-python ${{ matrix.python }}
315+
id: setup-python
316+
uses: ./
317+
with:
318+
python-version-file: Pipfile
319+
320+
- name: Check python-path
321+
run: ./__tests__/check-python-path.sh '${{ steps.setup-python.outputs.python-path }}'
322+
shell: bash
323+
324+
- name: Validate version
325+
run: |
326+
$pythonVersion = (python --version)
327+
if ("Python ${{ matrix.python }}".replace("==", "") -ne "$pythonVersion"){
328+
Write-Host "The current version is $pythonVersion; expected version is ${{ matrix.python }}"
329+
exit 1
330+
}
331+
$pythonVersion
332+
shell: pwsh
333+
334+
- name: Run simple code
335+
run: python -c 'import math; print(math.factorial(5))'
336+
337+
setup-versions-from-pipfile-with-python_full_version:
338+
name: Setup ${{ matrix.python }} ${{ matrix.os }} Pipfile with python_full_version
339+
runs-on: ${{ matrix.os }}
340+
strategy:
341+
fail-fast: false
342+
matrix:
343+
os:
344+
[
345+
macos-latest,
346+
windows-latest,
347+
ubuntu-22.04,
348+
ubuntu-22.04-arm,
349+
macos-13,
350+
ubuntu-latest,
351+
ubuntu-24.04-arm
352+
]
353+
python: [3.9.13, 3.10.11, 3.11.9, 3.13.2]
354+
steps:
355+
- name: Checkout
356+
uses: actions/checkout@v4
357+
358+
- name: build-version-file ${{ matrix.python }}
359+
run: |
360+
echo '[requires]
361+
python_full_version = "${{ matrix.python }}"
362+
' > Pipfile
363+
364+
- name: setup-python ${{ matrix.python }}
365+
id: setup-python
366+
uses: ./
367+
with:
368+
python-version-file: Pipfile
369+
370+
- name: Check python-path
371+
run: ./__tests__/check-python-path.sh '${{ steps.setup-python.outputs.python-path }}'
372+
shell: bash
373+
374+
- name: Validate version
375+
run: |
376+
$pythonVersion = (python --version)
377+
if ("Python ${{ matrix.python }}".replace("==", "") -ne "$pythonVersion"){
378+
Write-Host "The current version is $pythonVersion; expected version is ${{ matrix.python }}"
379+
exit 1
380+
}
381+
$pythonVersion
382+
shell: pwsh
383+
384+
- name: Run simple code
385+
run: python -c 'import math; print(math.factorial(5))'
386+
287387
setup-pre-release-version-from-manifest:
288388
name: Setup 3.14.0-alpha.6 ${{ matrix.os }}
289389
runs-on: ${{ matrix.os }}

__tests__/utils.test.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
getVersionInputFromFile,
1313
getVersionsInputFromPlainFile,
1414
getVersionInputFromTomlFile,
15+
getVersionInputFromPipfileFile,
1516
getNextPageUrl,
1617
isGhes,
1718
IS_WINDOWS,
@@ -244,6 +245,44 @@ describe('Version from file test', () => {
244245
expect(_fn(toolVersionFilePath)).toEqual(['3.14t-dev']);
245246
}
246247
);
248+
249+
it.each([getVersionInputFromPipfileFile, getVersionInputFromFile])(
250+
'Version from python_version in Pipfile',
251+
async _fn => {
252+
await io.mkdirP(tempDir);
253+
const pythonVersionFileName = 'Pipfile';
254+
const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName);
255+
const pythonVersion = '3.13';
256+
const pythonVersionFileContent = `[requires]\npython_version = "${pythonVersion}"`;
257+
fs.writeFileSync(pythonVersionFilePath, pythonVersionFileContent);
258+
expect(_fn(pythonVersionFilePath)).toEqual([pythonVersion]);
259+
}
260+
);
261+
262+
it.each([getVersionInputFromPipfileFile, getVersionInputFromFile])(
263+
'Version from python_full_version in Pipfile',
264+
async _fn => {
265+
await io.mkdirP(tempDir);
266+
const pythonVersionFileName = 'Pipfile';
267+
const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName);
268+
const pythonVersion = '3.13.0';
269+
const pythonVersionFileContent = `[requires]\npython_full_version = "${pythonVersion}"`;
270+
fs.writeFileSync(pythonVersionFilePath, pythonVersionFileContent);
271+
expect(_fn(pythonVersionFilePath)).toEqual([pythonVersion]);
272+
}
273+
);
274+
275+
it.each([getVersionInputFromPipfileFile, getVersionInputFromFile])(
276+
'Pipfile undefined version',
277+
async _fn => {
278+
await io.mkdirP(tempDir);
279+
const pythonVersionFileName = 'Pipfile';
280+
const pythonVersionFilePath = path.join(tempDir, pythonVersionFileName);
281+
const pythonVersionFileContent = ``;
282+
fs.writeFileSync(pythonVersionFilePath, pythonVersionFileContent);
283+
expect(_fn(pythonVersionFilePath)).toEqual([]);
284+
}
285+
);
247286
});
248287

249288
describe('getNextPageUrl', () => {

dist/setup/index.js

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97067,7 +97067,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
9706797067
return (mod && mod.__esModule) ? mod : { "default": mod };
9706897068
};
9706997069
Object.defineProperty(exports, "__esModule", ({ value: true }));
97070-
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;
97070+
exports.getDownloadFileName = exports.getNextPageUrl = exports.getBinaryDirectory = exports.getVersionInputFromFile = exports.getVersionInputFromPipfileFile = 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;
9707197071
/* eslint no-unsafe-finally: "off" */
9707297072
const cache = __importStar(__nccwpck_require__(5116));
9707397073
const core = __importStar(__nccwpck_require__(7484));
@@ -97337,7 +97337,41 @@ function getVersionInputFromToolVersions(versionFile) {
9733797337
}
9733897338
exports.getVersionInputFromToolVersions = getVersionInputFromToolVersions;
9733997339
/**
97340-
* Python version extracted from a plain, .tool-versions or TOML file.
97340+
* Python version extracted from the Pipfile file.
97341+
*/
97342+
function getVersionInputFromPipfileFile(versionFile) {
97343+
core.debug(`Trying to resolve version from ${versionFile}`);
97344+
if (!fs_1.default.existsSync(versionFile)) {
97345+
core.warning(`File ${versionFile} does not exist.`);
97346+
return [];
97347+
}
97348+
let pipfileFile = fs_1.default.readFileSync(versionFile, 'utf8');
97349+
// Normalize the line endings in the pipfileFile
97350+
pipfileFile = pipfileFile.replace(/\r\n/g, '\n');
97351+
const pipfileConfig = toml.parse(pipfileFile);
97352+
const keys = ['requires'];
97353+
if (!('requires' in pipfileConfig)) {
97354+
core.warning(`No Python version found in ${versionFile}`);
97355+
return [];
97356+
}
97357+
if ('python_full_version' in pipfileConfig['requires']) {
97358+
// specifies a full python version
97359+
keys.push('python_full_version');
97360+
}
97361+
else {
97362+
keys.push('python_version');
97363+
}
97364+
const versions = [];
97365+
const version = extractValue(pipfileConfig, keys);
97366+
if (version !== undefined) {
97367+
versions.push(version);
97368+
}
97369+
core.info(`Extracted ${versions} from ${versionFile}`);
97370+
return versions;
97371+
}
97372+
exports.getVersionInputFromPipfileFile = getVersionInputFromPipfileFile;
97373+
/**
97374+
* Python version extracted from a plain, .tool-versions, Pipfile or TOML file.
9734197375
*/
9734297376
function getVersionInputFromFile(versionFile) {
9734397377
if (versionFile.endsWith('.toml')) {
@@ -97346,6 +97380,9 @@ function getVersionInputFromFile(versionFile) {
9734697380
else if (versionFile.match('.tool-versions')) {
9734797381
return getVersionInputFromToolVersions(versionFile);
9734897382
}
97383+
else if (versionFile.match('Pipfile')) {
97384+
return getVersionInputFromPipfileFile(versionFile);
97385+
}
9734997386
else {
9735097387
return getVersionsInputFromPlainFile(versionFile);
9735197388
}

docs/advanced-usage.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,15 @@ steps:
310310
- run: python my_script.py
311311
```
312312

313+
```yaml
314+
steps:
315+
- uses: actions/checkout@v4
316+
- uses: actions/setup-python@v5
317+
with:
318+
python-version-file: 'Pipfile' # Read python version from a file Pipfile
319+
- run: python my_script.py
320+
```
321+
313322
## Check latest version
314323

315324
The `check-latest` flag defaults to `false`. Use the default or set `check-latest` to `false` if you prefer stability and if you want to ensure a specific `Python or PyPy` version is always used.

src/utils.ts

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,14 +325,54 @@ export function getVersionInputFromToolVersions(versionFile: string): string[] {
325325
return [];
326326
}
327327
}
328+
329+
/**
330+
* Python version extracted from the Pipfile file.
331+
*/
332+
export function getVersionInputFromPipfileFile(versionFile: string): string[] {
333+
core.debug(`Trying to resolve version from ${versionFile}`);
334+
335+
if (!fs.existsSync(versionFile)) {
336+
core.warning(`File ${versionFile} does not exist.`);
337+
return [];
338+
}
339+
let pipfileFile = fs.readFileSync(versionFile, 'utf8');
340+
// Normalize the line endings in the pipfileFile
341+
pipfileFile = pipfileFile.replace(/\r\n/g, '\n');
342+
343+
const pipfileConfig = toml.parse(pipfileFile);
344+
const keys = ['requires'];
345+
346+
if (!('requires' in pipfileConfig)) {
347+
core.warning(`No Python version found in ${versionFile}`);
348+
return [];
349+
}
350+
if ('python_full_version' in (pipfileConfig['requires'] as toml.JsonMap)) {
351+
// specifies a full python version
352+
keys.push('python_full_version');
353+
} else {
354+
keys.push('python_version');
355+
}
356+
const versions = [];
357+
const version = extractValue(pipfileConfig, keys);
358+
if (version !== undefined) {
359+
versions.push(version);
360+
}
361+
362+
core.info(`Extracted ${versions} from ${versionFile}`);
363+
return versions;
364+
}
365+
328366
/**
329-
* Python version extracted from a plain, .tool-versions or TOML file.
367+
* Python version extracted from a plain, .tool-versions, Pipfile or TOML file.
330368
*/
331369
export function getVersionInputFromFile(versionFile: string): string[] {
332370
if (versionFile.endsWith('.toml')) {
333371
return getVersionInputFromTomlFile(versionFile);
334372
} else if (versionFile.match('.tool-versions')) {
335373
return getVersionInputFromToolVersions(versionFile);
374+
} else if (versionFile.match('Pipfile')) {
375+
return getVersionInputFromPipfileFile(versionFile);
336376
} else {
337377
return getVersionsInputFromPlainFile(versionFile);
338378
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy