From 152bdecc78bb2541ce52c47c2ad7afd091900a6e Mon Sep 17 00:00:00 2001 From: Bas Schoenmaeckers Date: Tue, 26 Nov 2024 23:18:30 +0100 Subject: [PATCH 1/9] feat: support uv index pinning & index authentication --- lib/modules/manager/pep621/processors/uv.ts | 116 +++++++++++++++----- lib/modules/manager/pep621/schema.ts | 15 +++ 2 files changed, 106 insertions(+), 25 deletions(-) diff --git a/lib/modules/manager/pep621/processors/uv.ts b/lib/modules/manager/pep621/processors/uv.ts index 5de57d565e5c52..e603035bfd01c0 100644 --- a/lib/modules/manager/pep621/processors/uv.ts +++ b/lib/modules/manager/pep621/processors/uv.ts @@ -53,13 +53,14 @@ export class UvProcessor implements PyProjectProcessor { const depSource = uv.sources[dep.packageName]; if (depSource) { dep.depType = depTypes.uvSources; - if ('url' in depSource) { - dep.skipReason = 'unsupported-url'; - } else if ('path' in depSource) { - dep.skipReason = 'path-dependency'; - } else if ('workspace' in depSource) { - dep.skipReason = 'inherited-dependency'; - } else { + if ('index' in depSource) { + const index = uv.index?.find( + ({ name }) => name === depSource.index, + ); + if (index) { + dep.registryUrls = [index.url]; + } + } else if ('git' in depSource) { applyGitSource( dep, depSource.git, @@ -67,6 +68,14 @@ export class UvProcessor implements PyProjectProcessor { depSource.tag, depSource.branch, ); + } else if ('url' in depSource) { + dep.skipReason = 'unsupported-url'; + } else if ('path' in depSource) { + dep.skipReason = 'path-dependency'; + } else if ('workspace' in depSource) { + dep.skipReason = 'inherited-dependency'; + } else { + dep.skipReason = 'unknown-registry'; } } } @@ -132,7 +141,8 @@ export class UvProcessor implements PyProjectProcessor { const extraEnv = { ...getGitEnvironmentVariables(['pep621']), - ...(await getUvExtraIndexUrl(updateArtifact.updatedDeps)), + ...(await getUvExtraIndexUrl(project, updateArtifact.updatedDeps)), + ...(await getUvIndexCredentials(project)), }; const execOptions: ExecOptions = { cwdFile: packageFileName, @@ -217,11 +227,41 @@ function getMatchingHostRule(url: string | undefined): HostRule { return find({ hostType: PypiDatasource.id, url }); } -async function getUvExtraIndexUrl(deps: Upgrade[]): Promise { +async function getUsernamePassword( + url: URL, +): Promise<{ username?: string; password?: string }> { + const rule = getMatchingHostRule(url.toString()); + if (rule.username || rule.password) { + return rule; + } + + if (url.hostname.endsWith('.pkg.dev')) { + const accessToken = await getGoogleAuthTokenRaw(); + if (accessToken) { + return { + username: 'oauth2accesstoken', + password: accessToken, + }; + } else { + logger.once.debug({ url }, 'Could not get Google access token'); + } + } + + return {}; +} + +async function getUvExtraIndexUrl( + project: PyProject, + deps: Upgrade[], +): Promise { const pyPiRegistryUrls = deps .filter((dep) => dep.datasource === PypiDatasource.id) - .map((dep) => dep.registryUrls) - .flat(); + .filter((dep) => { + // Remove dependencies that are pinned to a specific index + const sources = project.tool?.uv?.sources; + return !sources || !(dep.packageName! in sources); + }) + .flatMap((dep) => dep.registryUrls); const registryUrls = new Set(pyPiRegistryUrls); const extraIndexUrls: string[] = []; @@ -231,21 +271,13 @@ async function getUvExtraIndexUrl(deps: Upgrade[]): Promise { continue; } - const rule = getMatchingHostRule(parsedUrl.toString()); - if (rule.username || rule.password) { - if (rule.username) { - parsedUrl.username = rule.username; - } - if (rule.password) { - parsedUrl.password = rule.password; + const { username, password } = await getUsernamePassword(parsedUrl); + if (username || password) { + if (username) { + parsedUrl.username = username; } - } else if (parsedUrl.hostname.endsWith('.pkg.dev')) { - const accessToken = await getGoogleAuthTokenRaw(); - if (accessToken) { - parsedUrl.username = 'oauth2accesstoken'; - parsedUrl.password = accessToken; - } else { - logger.once.debug({ registryUrl }, 'Could not get Google access token'); + if (password) { + parsedUrl.password = password; } } @@ -256,3 +288,37 @@ async function getUvExtraIndexUrl(deps: Upgrade[]): Promise { UV_EXTRA_INDEX_URL: extraIndexUrls.join(' '), }; } + +async function getUvIndexCredentials( + project: PyProject, +): Promise { + const uv_indexes = project.tool?.uv?.index; + + if (is.nullOrUndefined(uv_indexes)) { + return {}; + } + + const entries = []; + + for (const { name, url } of uv_indexes) { + const parsedUrl = parseUrl(url); + // istanbul ignore if + if (!parsedUrl) { + continue; + } + + const { username, password } = await getUsernamePassword(parsedUrl); + + const NAME = name.toUpperCase().replace(/[^A-Z0-9]/g, '_'); + + if (username) { + entries.push([`UV_INDEX_${NAME}_USERNAME`, username]); + } + + if (password) { + entries.push([`UV_INDEX_${NAME}_PASSWORD`, password]); + } + } + + return Object.fromEntries(entries); +} diff --git a/lib/modules/manager/pep621/schema.ts b/lib/modules/manager/pep621/schema.ts index 0c31b241a497c3..8188ec6258d407 100644 --- a/lib/modules/manager/pep621/schema.ts +++ b/lib/modules/manager/pep621/schema.ts @@ -36,6 +36,10 @@ const HatchSchema = z.object({ .optional(), }); +const UvIndexSource = z.object({ + index: z.string(), +}); + const UvGitSource = z.object({ git: z.string(), rev: z.string().optional(), @@ -58,6 +62,7 @@ const UvWorkspaceSource = z.object({ // https://docs.astral.sh/uv/concepts/dependencies/#dependency-sources const UvSource = z.union([ + UvIndexSource, UvGitSource, UvUrlSource, UvPathSource, @@ -71,6 +76,16 @@ const UvSchema = z.object({ z.string().transform((source) => normalizePythonDepName(source)), UvSource, ).optional(), + index: z + .array( + z.object({ + name: z.string(), + url: z.string(), + default: z.boolean().default(false), + explicit: z.boolean().default(false), + }), + ) + .optional(), }); export const PyProjectSchema = z.object({ From c4ede69870980b65cac4d5b7cef55f4b9cb4fcb2 Mon Sep 17 00:00:00 2001 From: Bas Schoenmaeckers Date: Wed, 27 Nov 2024 11:15:12 +0100 Subject: [PATCH 2/9] Add support for implicit and default indexes --- lib/modules/manager/pep621/processors/uv.ts | 29 +++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/lib/modules/manager/pep621/processors/uv.ts b/lib/modules/manager/pep621/processors/uv.ts index e603035bfd01c0..eea261730cd885 100644 --- a/lib/modules/manager/pep621/processors/uv.ts +++ b/lib/modules/manager/pep621/processors/uv.ts @@ -32,6 +32,12 @@ export class UvProcessor implements PyProjectProcessor { return deps; } + const hasExplicitDefault = uv.index?.some((index) => index.default && index.explicit); + const defaultIndex = uv.index?.find((index) => index.default && !index.explicit); + const implicitIndexes = uv.index + ?.filter((index) => !index.explicit && index.name !== defaultIndex?.name) + ?.map(({ url }) => url); + deps.push( ...parseDependencyList( depTypes.uvDevDependencies, @@ -41,7 +47,7 @@ export class UvProcessor implements PyProjectProcessor { // https://docs.astral.sh/uv/concepts/dependencies/#dependency-sources // Skip sources that do not make sense to handle (e.g. path). - if (uv.sources) { + if (uv.sources || defaultIndex || implicitIndexes) { for (const dep of deps) { // istanbul ignore if if (!dep.packageName) { @@ -50,8 +56,9 @@ export class UvProcessor implements PyProjectProcessor { // Using `packageName` as it applies PEP 508 normalization, which is // also applied by uv when matching a source to a dependency. - const depSource = uv.sources[dep.packageName]; + const depSource = uv.sources?.[dep.packageName]; if (depSource) { + // Dependency is pinned to a specific source. dep.depType = depTypes.uvSources; if ('index' in depSource) { const index = uv.index?.find( @@ -77,6 +84,24 @@ export class UvProcessor implements PyProjectProcessor { } else { dep.skipReason = 'unknown-registry'; } + } else { + // Dependency is not pinned to a specific source, so we need to + // determine the source based on the index configuration. + if (hasExplicitDefault) { + // don't fall back to pypi if there is an explicit default index + dep.registryUrls = []; + } else if (defaultIndex) { + // There is a default index configured, so use it. + dep.registryUrls = [defaultIndex.url]; + } + + if (implicitIndexes) { + // If there are implicit indexes, check them first and fall back + // to the default. + dep.registryUrls = implicitIndexes.concat( + dep.registryUrls ?? 'https://pypi.org/pypi/' + ); + } } } } From 470a41c2a11317a38eb0c6b22a37a1c65a497e76 Mon Sep 17 00:00:00 2001 From: Bas Schoenmaeckers Date: Wed, 27 Nov 2024 12:01:43 +0100 Subject: [PATCH 3/9] Add test --- .../manager/pep621/processors/uv.spec.ts | 205 +++++++++++++++++- 1 file changed, 202 insertions(+), 3 deletions(-) diff --git a/lib/modules/manager/pep621/processors/uv.spec.ts b/lib/modules/manager/pep621/processors/uv.spec.ts index 772a3050644d1d..47a64ac2b27f33 100644 --- a/lib/modules/manager/pep621/processors/uv.spec.ts +++ b/lib/modules/manager/pep621/processors/uv.spec.ts @@ -150,6 +150,176 @@ describe('modules/manager/pep621/processors/uv', () => { ]); }); + it('pinned to non-default index', () => { + const pyproject = { + tool: { + uv: { + sources: { + dep1: { index: 'foo' }, + dep2: { index: 'bar' }, + }, + index: [ + { + name: 'foo', + url: 'https://foo.com/simple', + default: false, + explicit: true, + }, + { + name: 'bar', + url: 'https://bar.com/simple', + default: false, + explicit: true, + }, + { + name: 'baz', + url: 'https://baz.com/simple', + default: false, + explicit: false, + }, + ], + }, + }, + }; + + const dependencies = [ + { + depName: 'dep1', + packageName: 'dep1', + }, + { + depName: 'dep2', + packageName: 'dep2', + }, + { + depName: 'dep3', + packageName: 'dep3', + }, + ]; + + const result = processor.process(pyproject, dependencies); + + expect(result).toEqual([ + { + depName: 'dep1', + depType: depTypes.uvSources, + registryUrls: ['https://foo.com/simple'], + packageName: 'dep1', + }, + { + depName: 'dep2', + depType: depTypes.uvSources, + registryUrls: ['https://bar.com/simple'], + packageName: 'dep2', + }, + { + depName: 'dep3', + registryUrls: [ + 'https://baz.com/simple', + 'https://pypi.org/pypi/' + ], + packageName: 'dep3', + }, + ]); + }); + + +it('override implicit default index', () => { + const pyproject = { + tool: { + uv: { + index: [ + { + name: 'foo', + url: 'https://foo.com/simple', + default: true, + explicit: false, + }, + ], + }, + }, + }; + + const dependencies = [ + { + depName: 'dep1', + packageName: 'dep1', + }, + { + depName: 'dep2', + packageName: 'dep2', + }, + ]; + + const result = processor.process(pyproject, dependencies); + + expect(result).toEqual([ + { + depName: 'dep1', + registryUrls: [ + 'https://foo.com/simple', + ], + packageName: 'dep1', + }, + { + depName: 'dep2', + registryUrls: [ + 'https://foo.com/simple', + ], + packageName: 'dep2', + }, + ]); + }); + +it('override explicit default index', () => { + const pyproject = { + tool: { + uv: { + sources: { + dep1: { index: 'foo' }, + }, + index: [ + { + name: 'foo', + url: 'https://foo.com/simple', + default: true, + explicit: true, + }, + ], + }, + }, + }; + + const dependencies = [ + { + depName: 'dep1', + packageName: 'dep1', + }, + { + depName: 'dep2', + packageName: 'dep2', + }, + ]; + + const result = processor.process(pyproject, dependencies); + + expect(result).toEqual([ + { + depName: 'dep1', + depType: depTypes.uvSources, + registryUrls: [ + 'https://foo.com/simple', + ], + packageName: 'dep1', + }, + { + depName: 'dep2', + registryUrls: [], + packageName: 'dep2', + }, + ]); + }); + describe('updateArtifacts()', () => { it('returns null if there is no lock file', async () => { fs.getSiblingFileName.mockReturnValueOnce('uv.lock'); @@ -303,6 +473,11 @@ describe('modules/manager/pep621/processors/uv', () => { username: 'user', password: 'pass', }); + hostRules.add({ + matchHost: 'https://pinned.com/simple', + username: 'user', + password: 'pass', + }); googleAuth.mockImplementationOnce( jest.fn().mockImplementationOnce(() => ({ getAccessToken: jest.fn().mockResolvedValue('some-token'), @@ -353,6 +528,14 @@ describe('modules/manager/pep621/processors/uv', () => { 'https://someregion-python.pkg.dev/some-project/some-repo/', ], }, + { + packageName: 'dep6', + depType: depTypes.dependencies, + datasource: PypiDatasource.id, + registryUrls: [ + 'https://pinned.com/simple', + ], + }, ]; const result = await processor.updateArtifacts( { @@ -361,7 +544,21 @@ describe('modules/manager/pep621/processors/uv', () => { config: {}, updatedDeps, }, - {}, + { + tool: { + uv: { + sources: { + dep6: {index : 'pinned-index'}, + }, + index: [{ + name: 'pinned-index', + url: 'https://pinned.com/simple', + default: false, + explicit: true, + }] + } + } + }, ); expect(result).toEqual([ { @@ -374,10 +571,10 @@ describe('modules/manager/pep621/processors/uv', () => { ]); expect(execSnapshots).toMatchObject([ { - cmd: 'uv lock --upgrade-package dep1 --upgrade-package dep2 --upgrade-package dep3 --upgrade-package dep4 --upgrade-package dep5', + cmd: 'uv lock --upgrade-package dep1 --upgrade-package dep2 --upgrade-package dep3 --upgrade-package dep4 --upgrade-package dep5 --upgrade-package dep6', options: { env: { - GIT_CONFIG_COUNT: '3', + GIT_CONFIG_COUNT: '6', GIT_CONFIG_KEY_0: 'url.https://user:pass@example.com/.insteadOf', GIT_CONFIG_KEY_1: 'url.https://user:pass@example.com/.insteadOf', GIT_CONFIG_KEY_2: 'url.https://user:pass@example.com/.insteadOf', @@ -386,6 +583,8 @@ describe('modules/manager/pep621/processors/uv', () => { GIT_CONFIG_VALUE_2: 'https://example.com/', UV_EXTRA_INDEX_URL: 'https://foobar.com/ https://user:pass@example.com/ https://oauth2accesstoken:some-token@someregion-python.pkg.dev/some-project/some-repo/', + UV_INDEX_PINNED_INDEX_USERNAME: "user", + UV_INDEX_PINNED_INDEX_PASSWORD: "pass", }, }, }, From d40a1f9d7d5b5d9ea59d996e93826e72ce44a62b Mon Sep 17 00:00:00 2001 From: Bas Schoenmaeckers Date: Wed, 27 Nov 2024 16:30:01 +0100 Subject: [PATCH 4/9] Fix linting --- .../manager/pep621/processors/uv.spec.ts | 50 ++++++++----------- lib/modules/manager/pep621/processors/uv.ts | 10 ++-- 2 files changed, 27 insertions(+), 33 deletions(-) diff --git a/lib/modules/manager/pep621/processors/uv.spec.ts b/lib/modules/manager/pep621/processors/uv.spec.ts index 47a64ac2b27f33..6bb6a09f01439a 100644 --- a/lib/modules/manager/pep621/processors/uv.spec.ts +++ b/lib/modules/manager/pep621/processors/uv.spec.ts @@ -214,17 +214,13 @@ describe('modules/manager/pep621/processors/uv', () => { }, { depName: 'dep3', - registryUrls: [ - 'https://baz.com/simple', - 'https://pypi.org/pypi/' - ], + registryUrls: ['https://baz.com/simple', 'https://pypi.org/pypi/'], packageName: 'dep3', }, ]); }); - -it('override implicit default index', () => { + it('override implicit default index', () => { const pyproject = { tool: { uv: { @@ -256,22 +252,18 @@ it('override implicit default index', () => { expect(result).toEqual([ { depName: 'dep1', - registryUrls: [ - 'https://foo.com/simple', - ], + registryUrls: ['https://foo.com/simple'], packageName: 'dep1', }, { depName: 'dep2', - registryUrls: [ - 'https://foo.com/simple', - ], + registryUrls: ['https://foo.com/simple'], packageName: 'dep2', }, ]); }); -it('override explicit default index', () => { + it('override explicit default index', () => { const pyproject = { tool: { uv: { @@ -307,9 +299,7 @@ it('override explicit default index', () => { { depName: 'dep1', depType: depTypes.uvSources, - registryUrls: [ - 'https://foo.com/simple', - ], + registryUrls: ['https://foo.com/simple'], packageName: 'dep1', }, { @@ -532,9 +522,7 @@ it('override explicit default index', () => { packageName: 'dep6', depType: depTypes.dependencies, datasource: PypiDatasource.id, - registryUrls: [ - 'https://pinned.com/simple', - ], + registryUrls: ['https://pinned.com/simple'], }, ]; const result = await processor.updateArtifacts( @@ -548,16 +536,18 @@ it('override explicit default index', () => { tool: { uv: { sources: { - dep6: {index : 'pinned-index'}, + dep6: { index: 'pinned-index' }, }, - index: [{ - name: 'pinned-index', - url: 'https://pinned.com/simple', - default: false, - explicit: true, - }] - } - } + index: [ + { + name: 'pinned-index', + url: 'https://pinned.com/simple', + default: false, + explicit: true, + }, + ], + }, + }, }, ); expect(result).toEqual([ @@ -583,8 +573,8 @@ it('override explicit default index', () => { GIT_CONFIG_VALUE_2: 'https://example.com/', UV_EXTRA_INDEX_URL: 'https://foobar.com/ https://user:pass@example.com/ https://oauth2accesstoken:some-token@someregion-python.pkg.dev/some-project/some-repo/', - UV_INDEX_PINNED_INDEX_USERNAME: "user", - UV_INDEX_PINNED_INDEX_PASSWORD: "pass", + UV_INDEX_PINNED_INDEX_USERNAME: 'user', + UV_INDEX_PINNED_INDEX_PASSWORD: 'pass', }, }, }, diff --git a/lib/modules/manager/pep621/processors/uv.ts b/lib/modules/manager/pep621/processors/uv.ts index eea261730cd885..87b96ee5a8578f 100644 --- a/lib/modules/manager/pep621/processors/uv.ts +++ b/lib/modules/manager/pep621/processors/uv.ts @@ -32,8 +32,12 @@ export class UvProcessor implements PyProjectProcessor { return deps; } - const hasExplicitDefault = uv.index?.some((index) => index.default && index.explicit); - const defaultIndex = uv.index?.find((index) => index.default && !index.explicit); + const hasExplicitDefault = uv.index?.some( + (index) => index.default && index.explicit, + ); + const defaultIndex = uv.index?.find( + (index) => index.default && !index.explicit, + ); const implicitIndexes = uv.index ?.filter((index) => !index.explicit && index.name !== defaultIndex?.name) ?.map(({ url }) => url); @@ -99,7 +103,7 @@ export class UvProcessor implements PyProjectProcessor { // If there are implicit indexes, check them first and fall back // to the default. dep.registryUrls = implicitIndexes.concat( - dep.registryUrls ?? 'https://pypi.org/pypi/' + dep.registryUrls ?? 'https://pypi.org/pypi/', ); } } From fd501e6967161a7818c917a86334016242a3c7ec Mon Sep 17 00:00:00 2001 From: Bas Schoenmaeckers Date: Wed, 27 Nov 2024 16:44:29 +0100 Subject: [PATCH 5/9] Ignore coverage for non-existent source type --- lib/modules/manager/pep621/processors/uv.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/modules/manager/pep621/processors/uv.ts b/lib/modules/manager/pep621/processors/uv.ts index 87b96ee5a8578f..0e2a128d905526 100644 --- a/lib/modules/manager/pep621/processors/uv.ts +++ b/lib/modules/manager/pep621/processors/uv.ts @@ -64,6 +64,7 @@ export class UvProcessor implements PyProjectProcessor { if (depSource) { // Dependency is pinned to a specific source. dep.depType = depTypes.uvSources; + /* istanbul ignore else */ if ('index' in depSource) { const index = uv.index?.find( ({ name }) => name === depSource.index, From 83c0fca18f366564f1fabd605a4cde5a7bc4f532 Mon Sep 17 00:00:00 2001 From: Bas Schoenmaeckers Date: Thu, 28 Nov 2024 08:41:07 +0100 Subject: [PATCH 6/9] Test unknown uv source type --- lib/modules/manager/pep621/processors/uv.spec.ts | 13 ++++++++++++- lib/modules/manager/pep621/processors/uv.ts | 1 - 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/modules/manager/pep621/processors/uv.spec.ts b/lib/modules/manager/pep621/processors/uv.spec.ts index 6bb6a09f01439a..b5df6e51226c70 100644 --- a/lib/modules/manager/pep621/processors/uv.spec.ts +++ b/lib/modules/manager/pep621/processors/uv.spec.ts @@ -157,6 +157,7 @@ describe('modules/manager/pep621/processors/uv', () => { sources: { dep1: { index: 'foo' }, dep2: { index: 'bar' }, + dep3: { non_existent_future_source: {} }, }, index: [ { @@ -195,6 +196,10 @@ describe('modules/manager/pep621/processors/uv', () => { depName: 'dep3', packageName: 'dep3', }, + { + depName: 'dep4', + packageName: 'dep4', + }, ]; const result = processor.process(pyproject, dependencies); @@ -214,8 +219,14 @@ describe('modules/manager/pep621/processors/uv', () => { }, { depName: 'dep3', - registryUrls: ['https://baz.com/simple', 'https://pypi.org/pypi/'], + depType: depTypes.uvSources, packageName: 'dep3', + skipReason: 'unknown-registry', + }, + { + depName: 'dep4', + registryUrls: ['https://baz.com/simple', 'https://pypi.org/pypi/'], + packageName: 'dep4', }, ]); }); diff --git a/lib/modules/manager/pep621/processors/uv.ts b/lib/modules/manager/pep621/processors/uv.ts index 0e2a128d905526..87b96ee5a8578f 100644 --- a/lib/modules/manager/pep621/processors/uv.ts +++ b/lib/modules/manager/pep621/processors/uv.ts @@ -64,7 +64,6 @@ export class UvProcessor implements PyProjectProcessor { if (depSource) { // Dependency is pinned to a specific source. dep.depType = depTypes.uvSources; - /* istanbul ignore else */ if ('index' in depSource) { const index = uv.index?.find( ({ name }) => name === depSource.index, From 36ed153b106fbef904313a331c157b709be7ebc1 Mon Sep 17 00:00:00 2001 From: Bas Schoenmaeckers Date: Thu, 28 Nov 2024 10:02:13 +0100 Subject: [PATCH 7/9] Make typescript happy again --- lib/modules/manager/pep621/processors/uv.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/modules/manager/pep621/processors/uv.spec.ts b/lib/modules/manager/pep621/processors/uv.spec.ts index b5df6e51226c70..a2df90cff6eda8 100644 --- a/lib/modules/manager/pep621/processors/uv.spec.ts +++ b/lib/modules/manager/pep621/processors/uv.spec.ts @@ -157,7 +157,7 @@ describe('modules/manager/pep621/processors/uv', () => { sources: { dep1: { index: 'foo' }, dep2: { index: 'bar' }, - dep3: { non_existent_future_source: {} }, + dep3: { non_existent_future_source: {} } as any, }, index: [ { From a2853bb7a0bc05690af937ce3ca96cef40b8f0ce Mon Sep 17 00:00:00 2001 From: Bas Schoenmaeckers Date: Thu, 28 Nov 2024 13:49:33 +0100 Subject: [PATCH 8/9] Apply comments --- lib/modules/manager/pep621/processors/uv.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/modules/manager/pep621/processors/uv.ts b/lib/modules/manager/pep621/processors/uv.ts index 87b96ee5a8578f..982a82dfa7b398 100644 --- a/lib/modules/manager/pep621/processors/uv.ts +++ b/lib/modules/manager/pep621/processors/uv.ts @@ -38,7 +38,7 @@ export class UvProcessor implements PyProjectProcessor { const defaultIndex = uv.index?.find( (index) => index.default && !index.explicit, ); - const implicitIndexes = uv.index + const implicitIndexUrls = uv.index ?.filter((index) => !index.explicit && index.name !== defaultIndex?.name) ?.map(({ url }) => url); @@ -51,7 +51,7 @@ export class UvProcessor implements PyProjectProcessor { // https://docs.astral.sh/uv/concepts/dependencies/#dependency-sources // Skip sources that do not make sense to handle (e.g. path). - if (uv.sources || defaultIndex || implicitIndexes) { + if (uv.sources || defaultIndex || implicitIndexUrls) { for (const dep of deps) { // istanbul ignore if if (!dep.packageName) { @@ -99,11 +99,11 @@ export class UvProcessor implements PyProjectProcessor { dep.registryUrls = [defaultIndex.url]; } - if (implicitIndexes) { + if (implicitIndexUrls) { // If there are implicit indexes, check them first and fall back // to the default. - dep.registryUrls = implicitIndexes.concat( - dep.registryUrls ?? 'https://pypi.org/pypi/', + dep.registryUrls = implicitIndexUrls.concat( + dep.registryUrls ?? new PypiDatasource().defaultRegistryUrls, ); } } From c0750e1e52cfbf0fe0303e3abb7d97d980102fda Mon Sep 17 00:00:00 2001 From: Bas Schoenmaeckers Date: Thu, 28 Nov 2024 15:04:34 +0100 Subject: [PATCH 9/9] Use `PypiDatasource.defaultURL` --- lib/modules/manager/pep621/processors/uv.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/modules/manager/pep621/processors/uv.ts b/lib/modules/manager/pep621/processors/uv.ts index 982a82dfa7b398..87f8024e46c5fc 100644 --- a/lib/modules/manager/pep621/processors/uv.ts +++ b/lib/modules/manager/pep621/processors/uv.ts @@ -103,7 +103,7 @@ export class UvProcessor implements PyProjectProcessor { // If there are implicit indexes, check them first and fall back // to the default. dep.registryUrls = implicitIndexUrls.concat( - dep.registryUrls ?? new PypiDatasource().defaultRegistryUrls, + dep.registryUrls ?? PypiDatasource.defaultURL, ); } }