From c6963868250936824ff1e0510a0fcc458b964158 Mon Sep 17 00:00:00 2001 From: Reinier Criel Date: Wed, 1 Apr 2026 15:38:42 -0700 Subject: [PATCH] Some more cleanup --- .../interceptors/pip/modifyPipJsonResponse.js | 12 ++++++++++-- .../interceptors/pip/parsePipPackageUrl.js | 17 ++++++++++++++++- .../interceptors/pip/parsePipPackageUrl.spec.js | 7 +++++++ 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/packages/safe-chain/src/registryProxy/interceptors/pip/modifyPipJsonResponse.js b/packages/safe-chain/src/registryProxy/interceptors/pip/modifyPipJsonResponse.js index 869a516..e005237 100644 --- a/packages/safe-chain/src/registryProxy/interceptors/pip/modifyPipJsonResponse.js +++ b/packages/safe-chain/src/registryProxy/interceptors/pip/modifyPipJsonResponse.js @@ -58,12 +58,16 @@ function filterJsonMetadataFiles( } let modified = false; + const loggedVersions = new Set(); json.files = json.files.filter((/** @type {any} */ file) => { const version = getPackageVersionFromMetadataFile(file, metadataUrl); if (version && isNewlyReleasedPackage(packageName, version)) { modified = true; - logSuppressedVersion(packageName, version); + if (!loggedVersions.has(version)) { + logSuppressedVersion(packageName, version); + loggedVersions.add(version); + } return false; } @@ -118,12 +122,16 @@ function filterJsonMetadataUrls( } let modified = false; + const loggedVersions = new Set(); json.urls = json.urls.filter((/** @type {any} */ file) => { const version = getPackageVersionFromMetadataFile(file, metadataUrl); if (version && isNewlyReleasedPackage(packageName, version)) { modified = true; - logSuppressedVersion(packageName, version); + if (!loggedVersions.has(version)) { + logSuppressedVersion(packageName, version); + loggedVersions.add(version); + } return false; } diff --git a/packages/safe-chain/src/registryProxy/interceptors/pip/parsePipPackageUrl.js b/packages/safe-chain/src/registryProxy/interceptors/pip/parsePipPackageUrl.js index 56f03f8..5a89e81 100644 --- a/packages/safe-chain/src/registryProxy/interceptors/pip/parsePipPackageUrl.js +++ b/packages/safe-chain/src/registryProxy/interceptors/pip/parsePipPackageUrl.js @@ -1,4 +1,19 @@ /** + * Parses a PyPI metadata URL and returns the package name and API type. + * + * @example + * parsePipMetadataUrl("https://pypi.org/simple/requests/") + * // => { packageName: "requests", type: "simple" } + * + * parsePipMetadataUrl("https://pypi.org/pypi/requests/json") + * // => { packageName: "requests", type: "json" } + * + * parsePipMetadataUrl("https://pypi.org/pypi/requests/2.28.1/json") + * // => { packageName: "requests", type: "json" } + * + * parsePipMetadataUrl("https://files.pythonhosted.org/packages/requests-2.28.1.tar.gz") + * // => { packageName: undefined, type: undefined } + * * @param {string} url * @returns {{ packageName: string | undefined, type: "simple" | "json" | undefined }} */ @@ -29,7 +44,7 @@ export function parsePipMetadataUrl(url) { if ( pathSegments.length >= 3 && pathSegments[0] === "pypi" && - pathSegments[2] === "json" && + pathSegments[pathSegments.length - 1] === "json" && pathSegments[1] ) { return { diff --git a/packages/safe-chain/src/registryProxy/interceptors/pip/parsePipPackageUrl.spec.js b/packages/safe-chain/src/registryProxy/interceptors/pip/parsePipPackageUrl.spec.js index 3d6eecd..1345dd4 100644 --- a/packages/safe-chain/src/registryProxy/interceptors/pip/parsePipPackageUrl.spec.js +++ b/packages/safe-chain/src/registryProxy/interceptors/pip/parsePipPackageUrl.spec.js @@ -21,6 +21,13 @@ describe("parsePipPackageUrl", () => { }); }); + it("parses per-version json metadata URLs", () => { + assert.deepEqual( + parsePipMetadataUrl("https://pypi.org/pypi/requests/2.28.1/json"), + { packageName: "requests", type: "json" } + ); + }); + it("decodes encoded metadata package names", () => { assert.deepEqual( parsePipMetadataUrl("https://pypi.org/simple/foo-bar%5Fbaz/"),