Skip to content

Commit 8afb007

Browse files
authored
bug fix: Stricter pip list Package Parsing (#698)
Addressing bug #697. When parsing the output of pip list for packages, two checks were added. First, does the line contain exactly two space-separated keywords? The assumption being we will exactly see "[package name] [package version]" in a valid package list. Secondly, it uses the [regex in the PEP 440 docs](https://peps.python.org/pep-0440/#appendix-b-parsing-version-strings-with-regular-expressions) to verify a valid pip version. Adding these checks will help ensure we only parse valid packages and don't pick up any other information, such as warning messages. Lastly, added a unit test for the situation described in the bug.
1 parent 6173146 commit 8afb007

File tree

4 files changed

+34
-4
lines changed

4 files changed

+34
-4
lines changed

src/managers/builtin/pipListUtils.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ export interface PipPackage {
44
displayName: string;
55
description: string;
66
}
7+
export function isValidVersion(version: string): boolean {
8+
return /^([1-9][0-9]*!)?(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))*((a|b|rc)(0|[1-9][0-9]*))?(\.post(0|[1-9][0-9]*))?(\.dev(0|[1-9][0-9]*))?$/.test(
9+
version,
10+
);
11+
}
712
export function parsePipList(data: string): PipPackage[] {
813
const collection: PipPackage[] = [];
914

@@ -13,9 +18,12 @@ export function parsePipList(data: string): PipPackage[] {
1318
continue;
1419
}
1520
const parts = line.split(' ').filter((e) => e);
16-
if (parts.length > 1) {
21+
if (parts.length === 2) {
1722
const name = parts[0].trim();
1823
const version = parts[1].trim();
24+
if (!isValidVersion(version)) {
25+
continue;
26+
}
1927
const pkg = {
2028
name,
2129
version,

src/test/managers/builtin/pipListUtils.unit.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1+
import assert from 'assert';
12
import * as fs from 'fs-extra';
23
import * as path from 'path';
3-
import { EXTENSION_TEST_ROOT } from '../../constants';
44
import { parsePipList } from '../../../managers/builtin/pipListUtils';
5-
import assert from 'assert';
5+
import { EXTENSION_TEST_ROOT } from '../../constants';
66

77
const TEST_DATA_ROOT = path.join(EXTENSION_TEST_ROOT, 'managers', 'builtin');
88

99
suite('Pip List Parser tests', () => {
10-
const testNames = ['piplist1', 'piplist2'];
10+
const testNames = ['piplist1', 'piplist2', 'piplist3'];
1111

1212
testNames.forEach((testName) => {
1313
test(`Test parsing pip list output ${testName}`, async () => {
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Package Version
2+
---------- -------
3+
altgraph 0.17.2
4+
future 0.18.2
5+
macholib 1.15.2
6+
pip 21.2.4
7+
setuptools 58.0.4
8+
six 1.15.0
9+
wheel 0.37.0
10+
WARNING: You are using pip version 21.2.4; however, version 25.2 is available.
11+
You should consider upgrading via the '/Library/Developer/CommandLineTools/usr/bin/python3 -m pip install --upgrade pip' command.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"packages": [
3+
{ "name": "altgraph", "version": "0.17.2" },
4+
{ "name": "future", "version": "0.18.2" },
5+
{ "name": "macholib", "version": "1.15.2" },
6+
{ "name": "pip", "version": "21.2.4" },
7+
{ "name": "setuptools", "version": "58.0.4" },
8+
{ "name": "six", "version": "1.15.0" },
9+
{ "name": "wheel", "version": "0.37.0" }
10+
]
11+
}

0 commit comments

Comments
 (0)