From d68a8bd6d9b4eafdc460ba9fad32c7ee203288bf Mon Sep 17 00:00:00 2001 From: apoorva-01 Date: Wed, 15 Jul 2026 18:55:09 +0530 Subject: [PATCH] fix: split pip show output on the exact package separator `\n---` also matches dashed lines inside a package's License (pytest-django), so the block got shredded and indexing died. --- .../src/virtualenv/PythonPackage.test.ts | 78 +++++++++++++++++++ .../src/virtualenv/PythonPackage.ts | 8 ++ .../src/virtualenv/environment.ts | 2 +- 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 packages/pyright-scip/src/virtualenv/PythonPackage.test.ts diff --git a/packages/pyright-scip/src/virtualenv/PythonPackage.test.ts b/packages/pyright-scip/src/virtualenv/PythonPackage.test.ts new file mode 100644 index 000000000..2d8c79f81 --- /dev/null +++ b/packages/pyright-scip/src/virtualenv/PythonPackage.test.ts @@ -0,0 +1,78 @@ +import assert from 'assert'; +import PythonPackage from './PythonPackage'; + +// Real `pip show -f` output for two packages, taken from issue #173. pytest-django +// puts its full license into the `License:` metadata field, so the block contains +// dashed rule lines (`----...`). Those start with `\n---`, which is what the old +// split matched, shattering pytest-django across several blocks and making +// PythonPackage.fromPipShow throw "Unexpected. Thought I should be getting files now". +const pipShowOutput = `Name: pytest-django +Version: 4.11.1 +Summary: A Django plugin for pytest. +Home-page: +Author: +Author-email: Andreas Pelme +License: pytest-django is released under the BSD (3-clause) license +---------------------------------------------------------- +Copyright (c) 2015-2018, pytest-django authors (see AUTHORS file) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED. + + +This version of pytest-django is a fork of pytest_django created by Ben Firshman. +--------------------------------------------------------------------------------- +Copyright (c) 2009, Ben Firshman +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met. + +Location: /home/leni/.cache/pypoetry/virtualenvs/test-infra-back-lSRTar0T-py3.12/lib/python3.12/site-packages +Requires: pytest +Required-by: +Files: + pytest_django-4.11.1.dist-info/INSTALLER + pytest_django-4.11.1.dist-info/METADATA + pytest_django-4.11.1.dist-info/RECORD + pytest_django/__init__.py + pytest_django/fixtures.py + pytest_django/plugin.py + pytest_django/py.typed +--- +Name: attrs +Version: 25.3.0 +Summary: Classes Without Boilerplate +Location: /home/leni/.cache/pypoetry/virtualenvs/test-infra-back-lSRTar0T-py3.12/lib/python3.12/site-packages +Requires: +Required-by: pytest-django +Files: + attr/__init__.py + attrs/__init__.py +`; + +test('splitPipShowBlocks keeps a package whose License contains dashed rules in one block', () => { + const blocks = PythonPackage.splitPipShowBlocks(pipShowOutput); + assert.strictEqual(blocks.length, 2); + + const packages = blocks.map((block) => PythonPackage.fromPipShow(block)); + assert.deepStrictEqual( + packages.map((pkg) => pkg.name), + ['pytest-django', 'attrs'] + ); + + assert.strictEqual(packages[0].version, '4.11.1'); + assert.ok(packages[0].files.includes('pytest_django/__init__.py')); + assert.ok(packages[0].files.includes('pytest_django/plugin.py')); + assert.ok(!packages[0].files.some((file) => file.includes('.dist-info'))); + + assert.strictEqual(packages[1].version, '25.3.0'); + assert.deepStrictEqual(packages[1].files, ['attr/__init__.py', 'attrs/__init__.py']); +}); diff --git a/packages/pyright-scip/src/virtualenv/PythonPackage.ts b/packages/pyright-scip/src/virtualenv/PythonPackage.ts index ec11ea445..c2c0c1185 100644 --- a/packages/pyright-scip/src/virtualenv/PythonPackage.ts +++ b/packages/pyright-scip/src/virtualenv/PythonPackage.ts @@ -49,4 +49,12 @@ export default class PythonPackage { return new PythonPackage(name, version, files); } + + // pip separates each `pip show` block with a line containing only `---`. + // Match that exact separator rather than a bare `\n---`, which also shows up + // inside a package's License text (e.g. pytest-django's dashed rule lines) and + // would split a single package across several blocks. + static splitPipShowBlocks(output: string): string[] { + return output.split(/\r?\n---\r?\n/).filter((block) => block.trim()); + } } diff --git a/packages/pyright-scip/src/virtualenv/environment.ts b/packages/pyright-scip/src/virtualenv/environment.ts index 8843c8bc4..624ffc574 100644 --- a/packages/pyright-scip/src/virtualenv/environment.ts +++ b/packages/pyright-scip/src/virtualenv/environment.ts @@ -180,7 +180,7 @@ function pipBulkShow(names: string[]): PipBulkShowResult { return { success: true, - data: result.stdout.split('\n---').filter((pkg) => pkg.trim()), + data: PythonPackage.splitPipShowBlocks(result.stdout), }; }