Skip to content

Commit 9485ba7

Browse files
committed
feature: add version parsing from Pipfile
1 parent 1264885 commit 9485ba7

File tree

5 files changed

+222
-3
lines changed

5 files changed

+222
-3
lines changed

.github/workflows/test-python.yml

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,108 @@ 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-20.04,
298+
ubuntu-22.04,
299+
ubuntu-22.04-arm,
300+
macos-13,
301+
ubuntu-latest,
302+
ubuntu-24.04-arm
303+
]
304+
python: [3.9.13, 3.10.11, 3.11.9, 3.13.2]
305+
steps:
306+
- name: Checkout
307+
uses: actions/checkout@v4
308+
309+
- name: build-version-file ${{ matrix.python }}
310+
run: |
311+
echo '[requires]
312+
python_version = "${{ matrix.python }}"
313+
' > Pipfile
314+
315+
- name: setup-python ${{ matrix.python }}
316+
id: setup-python
317+
uses: ./
318+
with:
319+
python-version-file: Pipfile
320+
321+
- name: Check python-path
322+
run: ./__tests__/check-python-path.sh '${{ steps.setup-python.outputs.python-path }}'
323+
shell: bash
324+
325+
- name: Validate version
326+
run: |
327+
$pythonVersion = (python --version)
328+
if ("Python ${{ matrix.python }}".replace("==", "") -ne "$pythonVersion"){
329+
Write-Host "The current version is $pythonVersion; expected version is ${{ matrix.python }}"
330+
exit 1
331+
}
332+
$pythonVersion
333+
shell: pwsh
334+
335+
- name: Run simple code
336+
run: python -c 'import math; print(math.factorial(5))'
337+
338+
setup-versions-from-pipfile-with-python_full_version:
339+
name: Setup ${{ matrix.python }} ${{ matrix.os }} Pipfile with python_full_version
340+
runs-on: ${{ matrix.os }}
341+
strategy:
342+
fail-fast: false
343+
matrix:
344+
os:
345+
[
346+
macos-latest,
347+
windows-latest,
348+
ubuntu-20.04,
349+
ubuntu-22.04,
350+
ubuntu-22.04-arm,
351+
macos-13,
352+
ubuntu-latest,
353+
ubuntu-24.04-arm
354+
]
355+
python: [3.9.13, 3.10.11, 3.11.9, 3.13.2]
356+
steps:
357+
- name: Checkout
358+
uses: actions/checkout@v4
359+
360+
- name: build-version-file ${{ matrix.python }}
361+
run: |
362+
echo '[requires]
363+
python_full_version = "${{ matrix.python }}"
364+
' > Pipfile
365+
366+
- name: setup-python ${{ matrix.python }}
367+
id: setup-python
368+
uses: ./
369+
with:
370+
python-version-file: Pipfile
371+
372+
- name: Check python-path
373+
run: ./__tests__/check-python-path.sh '${{ steps.setup-python.outputs.python-path }}'
374+
shell: bash
375+
376+
- name: Validate version
377+
run: |
378+
$pythonVersion = (python --version)
379+
if ("Python ${{ matrix.python }}".replace("==", "") -ne "$pythonVersion"){
380+
Write-Host "The current version is $pythonVersion; expected version is ${{ matrix.python }}"
381+
exit 1
382+
}
383+
$pythonVersion
384+
shell: pwsh
385+
386+
- name: Run simple code
387+
run: python -c 'import math; print(math.factorial(5))'
388+
287389
setup-pre-release-version-from-manifest:
288390
name: Setup 3.14.0-alpha.6 ${{ matrix.os }}
289391
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: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97046,7 +97046,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
9704697046
return (mod && mod.__esModule) ? mod : { "default": mod };
9704797047
};
9704897048
Object.defineProperty(exports, "__esModule", ({ value: true }));
97049-
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;
97049+
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;
9705097050
/* eslint no-unsafe-finally: "off" */
9705197051
const cache = __importStar(__nccwpck_require__(5116));
9705297052
const core = __importStar(__nccwpck_require__(7484));
@@ -97316,7 +97316,37 @@ function getVersionInputFromToolVersions(versionFile) {
9731697316
}
9731797317
exports.getVersionInputFromToolVersions = getVersionInputFromToolVersions;
9731897318
/**
97319-
* Python version extracted from a plain, .tool-versions or TOML file.
97319+
* Python version extracted from the Pipfile file.
97320+
*/
97321+
function getVersionInputFromPipfileFile(versionFile) {
97322+
core.debug(`Trying to resolve version form ${versionFile}`);
97323+
let pipfileFile = fs_1.default.readFileSync(versionFile, 'utf8');
97324+
// Normalize the line endings in the pipfileFile
97325+
pipfileFile = pipfileFile.replace(/\r\n/g, '\n');
97326+
const pipfileConfig = toml.parse(pipfileFile);
97327+
const keys = ['requires'];
97328+
if (!('requires' in pipfileConfig)) {
97329+
core.warning(`No Python version found in ${versionFile}`);
97330+
return [];
97331+
}
97332+
if ('python_full_version' in pipfileConfig['requires']) {
97333+
// specifies a full python version
97334+
keys.push('python_full_version');
97335+
}
97336+
else {
97337+
keys.push('python_version');
97338+
}
97339+
const versions = [];
97340+
const version = extractValue(pipfileConfig, keys);
97341+
if (version !== undefined) {
97342+
versions.push(version);
97343+
}
97344+
core.info(`Extracted ${versions} from ${versionFile}`);
97345+
return [extractValue(pipfileConfig, keys)];
97346+
}
97347+
exports.getVersionInputFromPipfileFile = getVersionInputFromPipfileFile;
97348+
/**
97349+
* Python version extracted from a plain, .tool-versions, Pipfile or TOML file.
9732097350
*/
9732197351
function getVersionInputFromFile(versionFile) {
9732297352
if (versionFile.endsWith('.toml')) {
@@ -97325,6 +97355,9 @@ function getVersionInputFromFile(versionFile) {
9732597355
else if (versionFile.match('.tool-versions')) {
9732697356
return getVersionInputFromToolVersions(versionFile);
9732797357
}
97358+
else if (versionFile.match('Pipfile')) {
97359+
return getVersionInputFromPipfileFile(versionFile);
97360+
}
9732897361
else {
9732997362
return getVersionsInputFromPlainFile(versionFile);
9733097363
}

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: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,14 +325,50 @@ 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 form ${versionFile}`);
334+
335+
let pipfileFile = fs.readFileSync(versionFile, 'utf8');
336+
// Normalize the line endings in the pipfileFile
337+
pipfileFile = pipfileFile.replace(/\r\n/g, '\n');
338+
339+
const pipfileConfig = toml.parse(pipfileFile);
340+
const keys = ['requires'];
341+
342+
if (!('requires' in pipfileConfig)) {
343+
core.warning(`No Python version found in ${versionFile}`);
344+
return [];
345+
}
346+
if ('python_full_version' in (pipfileConfig['requires'] as toml.JsonMap)) {
347+
// specifies a full python version
348+
keys.push('python_full_version');
349+
} else {
350+
keys.push('python_version');
351+
}
352+
const versions = [];
353+
const version = extractValue(pipfileConfig, keys);
354+
if (version !== undefined) {
355+
versions.push(version);
356+
}
357+
358+
core.info(`Extracted ${versions} from ${versionFile}`);
359+
return [extractValue(pipfileConfig, keys)] as string[];
360+
}
361+
328362
/**
329-
* Python version extracted from a plain, .tool-versions or TOML file.
363+
* Python version extracted from a plain, .tool-versions, Pipfile or TOML file.
330364
*/
331365
export function getVersionInputFromFile(versionFile: string): string[] {
332366
if (versionFile.endsWith('.toml')) {
333367
return getVersionInputFromTomlFile(versionFile);
334368
} else if (versionFile.match('.tool-versions')) {
335369
return getVersionInputFromToolVersions(versionFile);
370+
} else if (versionFile.match('Pipfile')) {
371+
return getVersionInputFromPipfileFile(versionFile);
336372
} else {
337373
return getVersionsInputFromPlainFile(versionFile);
338374
}

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