From 230f763b0ab8023ee3a50a83443dd601d6f779fa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 4 Jun 2026 13:07:01 +0000 Subject: [PATCH 1/3] Initial plan From efc9a2f1e027f626b667a93b75a2095a62757028 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 4 Jun 2026 13:12:02 +0000 Subject: [PATCH 2/3] Handle pip package names case-insensitively for conda-installed skips --- packages/mambajs/src/solverpip.ts | 15 ++++++++++++--- unittests/tests/pip/test-solver.ts | 26 ++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/packages/mambajs/src/solverpip.ts b/packages/mambajs/src/solverpip.ts index 0424217..3755134 100644 --- a/packages/mambajs/src/solverpip.ts +++ b/packages/mambajs/src/solverpip.ts @@ -83,6 +83,10 @@ interface IWheelInfo { platformTags: string[]; } +function normalizePackageName(packageName: string): string { + return packageName.toLowerCase().replace(/[-_.]+/g, '-'); +} + function parseWheelFilename(filename: string): IWheelInfo { if (!filename.endsWith('.whl')) { throw new Error('Invalid wheel filename: must end with .whl'); @@ -590,7 +594,11 @@ export async function processRequirement(options: { // Don't pass down parent extras unless needed (PyPI handles it via markers) parsedRequirement.extras = undefined; - if (installedCondaPackagesNames.has(parsedRequirement.package)) { + if ( + installedCondaPackagesNames.has( + normalizePackageName(parsedRequirement.package) + ) + ) { if (!warnedPackages.has(parsedRequirement.package)) { logger?.log( `Requirement ${parsedRequirement.package} already satisfied.` @@ -657,7 +665,7 @@ export async function solvePip( const installedCondaPackagesNames = new Set(); for (const installedPackage of Object.values(installedCondaPackages)) { const pipPackageName = await getPipPackageName(installedPackage.name); - installedCondaPackagesNames.add(pipPackageName); + installedCondaPackagesNames.add(normalizePackageName(pipPackageName)); } // Create pip package lookup we can more easily use (index by package name, not wheel name) @@ -669,8 +677,9 @@ export async function solvePip( const warnedPackages = new Set(); const pipSolvedPackages: ISolvedPipPackages = { ...installedPipPackages }; for (const spec of specs) { + const normalizedSpecName = normalizePackageName(spec.package); // Ignoring already installed package via conda - if (installedCondaPackagesNames.has(spec.package)) { + if (installedCondaPackagesNames.has(normalizedSpecName)) { logger?.log( `Requirement ${spec.package} already handled by conda/micromamba/mamba.` ); diff --git a/unittests/tests/pip/test-solver.ts b/unittests/tests/pip/test-solver.ts index 85e57d5..f56fa3a 100644 --- a/unittests/tests/pip/test-solver.ts +++ b/unittests/tests/pip/test-solver.ts @@ -51,3 +51,29 @@ solvePip(ymlPrerelease, packages, {}, {}, [], logger, 'linux-64').then( expect(packageVersions['jupytergis-lab']).toEqual('0.16.0a0'); } ); + +const packagesWithMarkupSafe = { + ...packages, + 'markupsafe-3.0.2-pyhd8ed1ab_0.conda': { + name: 'markupsafe', + build: 'pyhd8ed1ab_0', + version: '3.0.2', + subdir: 'noarch', + channel: 'conda-forge' + } +}; + +const ymlCaseInsensitiveCondaName = ` +dependencies: + - pip: + - MarkupSafe +`; + +solvePip(ymlCaseInsensitiveCondaName, packagesWithMarkupSafe, {}, {}, [], logger).then( + result => { + expect(Object.values(result)).toBeEmpty(); + expect(logger.logs).toInclude( + 'Requirement MarkupSafe already handled by conda/micromamba/mamba.' + ); + } +); From 28b444a9f861f45812fffdee1a9f3464d05aa3f7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 4 Jun 2026 13:14:19 +0000 Subject: [PATCH 3/3] Improve new MarkupSafe solver test promise handling --- unittests/tests/pip/test-solver.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/unittests/tests/pip/test-solver.ts b/unittests/tests/pip/test-solver.ts index f56fa3a..602c5be 100644 --- a/unittests/tests/pip/test-solver.ts +++ b/unittests/tests/pip/test-solver.ts @@ -69,11 +69,20 @@ dependencies: - MarkupSafe `; -solvePip(ymlCaseInsensitiveCondaName, packagesWithMarkupSafe, {}, {}, [], logger).then( - result => { +solvePip( + ymlCaseInsensitiveCondaName, + packagesWithMarkupSafe, + {}, + {}, + [], + logger +) + .then(result => { expect(Object.values(result)).toBeEmpty(); expect(logger.logs).toInclude( 'Requirement MarkupSafe already handled by conda/micromamba/mamba.' ); - } -); + }) + .catch(err => { + throw err; + });