diff --git a/lib/datasource/pypi/__snapshots__/index.spec.ts.snap b/lib/datasource/pypi/__snapshots__/index.spec.ts.snap index 6508370bd093c5e2f07bc4d7b890b99831ad0a2a..dfbb337cebd3c5d7e3694435c38dace330acf092 100644 --- a/lib/datasource/pypi/__snapshots__/index.spec.ts.snap +++ b/lib/datasource/pypi/__snapshots__/index.spec.ts.snap @@ -60,7 +60,7 @@ Array [ "user-agent": "https://github.com/renovatebot/renovate", }, "method": "GET", - "url": "https://custom.pypi.net/foo/dj-database-url", + "url": "https://custom.pypi.net/foo/dj-database-url/", }, ] `; @@ -114,7 +114,7 @@ Array [ "user-agent": "https://github.com/renovatebot/renovate", }, "method": "GET", - "url": "https://pypi.org/simple/dj-database-url", + "url": "https://pypi.org/simple/dj-database-url/", }, ] `; @@ -169,7 +169,7 @@ Array [ "user-agent": "https://github.com/renovatebot/renovate", }, "method": "GET", - "url": "https://some.registry.org/+simple/dj-database-url", + "url": "https://some.registry.org/+simple/dj-database-url/", }, ] `; @@ -224,7 +224,7 @@ Array [ "user-agent": "https://github.com/renovatebot/renovate", }, "method": "GET", - "url": "https://pypi.org/simple/dj-database-url", + "url": "https://pypi.org/simple/dj-database-url/", }, ] `; @@ -248,7 +248,7 @@ Array [ "user-agent": "https://github.com/renovatebot/renovate", }, "method": "GET", - "url": "https://pypi.org/simple/image-collector", + "url": "https://pypi.org/simple/image-collector/", }, ] `; @@ -435,7 +435,7 @@ Array [ "user-agent": "https://github.com/renovatebot/renovate", }, "method": "GET", - "url": "https://pypi.org/pypi/something", + "url": "https://pypi.org/pypi/something/", }, ] `; @@ -449,7 +449,7 @@ Array [ "user-agent": "https://github.com/renovatebot/renovate", }, "method": "GET", - "url": "https://pypi.org/simple/dj-database-url", + "url": "https://pypi.org/simple/dj-database-url/", }, ] `; @@ -463,7 +463,7 @@ Array [ "user-agent": "https://github.com/renovatebot/renovate", }, "method": "GET", - "url": "https://pypi.org/simple/dj-database-url", + "url": "https://pypi.org/simple/dj-database-url/", }, ] `; diff --git a/lib/datasource/pypi/index.spec.ts b/lib/datasource/pypi/index.spec.ts index 1640af18e8eafe7c00b274900ec276ae6a1db376..42588b4e32e5ff085f831054348afa57db0f549d 100644 --- a/lib/datasource/pypi/index.spec.ts +++ b/lib/datasource/pypi/index.spec.ts @@ -53,7 +53,7 @@ describe('datasource/pypi', () => { }); it('returns null for 404', async () => { httpMock.scope(baseUrl).get('/something/json').reply(404); - httpMock.scope(baseUrl).get('/something').reply(404); + httpMock.scope(baseUrl).get('/something/').reply(404); expect( await getPkgReleases({ datasource, @@ -233,7 +233,7 @@ describe('datasource/pypi', () => { it('process data from simple endpoint', async () => { httpMock .scope('https://pypi.org/simple/') - .get('/dj-database-url') + .get('/dj-database-url/') .reply(200, htmlResponse); const config = { registryUrls: ['https://pypi.org/simple/'], @@ -251,7 +251,7 @@ describe('datasource/pypi', () => { it('process data from +simple endpoint', async () => { httpMock .scope('https://some.registry.org/+simple/') - .get('/dj-database-url') + .get('/dj-database-url/') .reply(200, htmlResponse); const config = { registryUrls: ['https://some.registry.org/+simple/'], @@ -270,7 +270,7 @@ describe('datasource/pypi', () => { hostRules.add({ hostName: 'some.private.registry.org', token: 'abc123' }); httpMock .scope('https://some.private.registry.org/+simple/') - .get('/dj-database-url') + .get('/dj-database-url/') .reply(200, htmlResponse); const config = { registryUrls: ['https://some.private.registry.org/+simple/'], @@ -286,7 +286,7 @@ describe('datasource/pypi', () => { it('process data from simple endpoint with hyphens replaced with underscores', async () => { httpMock .scope('https://pypi.org/simple/') - .get('/image-collector') + .get('/image-collector/') .reply(200, mixedHyphensResponse); const config = { registryUrls: ['https://pypi.org/simple/'], @@ -304,7 +304,7 @@ describe('datasource/pypi', () => { it('returns null for empty response', async () => { httpMock .scope('https://pypi.org/simple/') - .get('/dj-database-url') + .get('/dj-database-url/') .reply(200); const config = { registryUrls: ['https://pypi.org/simple/'], @@ -322,7 +322,7 @@ describe('datasource/pypi', () => { it('returns null for 404 response from simple endpoint', async () => { httpMock .scope('https://pypi.org/simple/') - .get('/dj-database-url') + .get('/dj-database-url/') .replyWithError('error'); const config = { registryUrls: ['https://pypi.org/simple/'], @@ -340,7 +340,7 @@ describe('datasource/pypi', () => { it('returns null for response with no versions', async () => { httpMock .scope('https://pypi.org/simple/') - .get('/dj-database-url') + .get('/dj-database-url/') .reply(200, badResponse); const config = { registryUrls: ['https://pypi.org/simple/'], @@ -361,7 +361,7 @@ describe('datasource/pypi', () => { .reply(404); httpMock .scope('https://custom.pypi.net/foo') - .get('/dj-database-url') + .get('/dj-database-url/') .reply(200, htmlResponse); const config = { registryUrls: ['https://custom.pypi.net/foo'], @@ -377,7 +377,7 @@ describe('datasource/pypi', () => { it('parses data-requires-python and respects constraints from simple endpoint', async () => { httpMock .scope('https://pypi.org/simple/') - .get('/dj-database-url') + .get('/dj-database-url/') .reply(200, dataRequiresPythonResponse); const config = { registryUrls: ['https://pypi.org/simple/'], diff --git a/lib/datasource/pypi/index.ts b/lib/datasource/pypi/index.ts index b588d6d0ac46e82f276f511851239ffad3ac94e0..5699398e9ae85e54666a37140707751bf2133770 100644 --- a/lib/datasource/pypi/index.ts +++ b/lib/datasource/pypi/index.ts @@ -175,7 +175,7 @@ async function getSimpleDependency( packageName: string, hostUrl: string ): Promise<ReleaseResult | null> { - const lookupUrl = url.resolve(hostUrl, `${packageName}`); + const lookupUrl = url.resolve(hostUrl, ensureTrailingSlash(packageName)); const dependency: ReleaseResult = { releases: null }; const response = await http.get(lookupUrl); const dep = response?.body;