mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-12 06:56:24 +00:00
fix(pipenv): detect 'any-version' packages (#3544)
This commit is contained in:
parent
a6e8ea41de
commit
55fb2de89e
3 changed files with 55 additions and 4 deletions
|
@ -1,4 +1,5 @@
|
||||||
const toml = require('toml');
|
const toml = require('toml');
|
||||||
|
const is = require('@sindresorhus/is');
|
||||||
|
|
||||||
// based on https://www.python.org/dev/peps/pep-0508/#names
|
// based on https://www.python.org/dev/peps/pep-0508/#names
|
||||||
const packageRegex = /^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$/i;
|
const packageRegex = /^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$/i;
|
||||||
|
@ -43,7 +44,14 @@ function extractFromSection(pipfile, section, registryUrls) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const specifierRegex = new RegExp(`^${specifierPattern}$`);
|
const specifierRegex = new RegExp(`^${specifierPattern}$`);
|
||||||
const deps = Object.entries(pipfile[section])
|
const pipfileSection = pipfile[section];
|
||||||
|
|
||||||
|
Object.keys(pipfileSection).forEach(key => {
|
||||||
|
if (is.object(pipfileSection[key]))
|
||||||
|
pipfileSection[key].version = pipfileSection[key].version || '*';
|
||||||
|
});
|
||||||
|
|
||||||
|
const deps = Object.entries(pipfileSection)
|
||||||
.map(x => {
|
.map(x => {
|
||||||
const [depName, requirements] = x;
|
const [depName, requirements] = x;
|
||||||
let currentValue;
|
let currentValue;
|
||||||
|
@ -63,13 +71,16 @@ function extractFromSection(pipfile, section, registryUrls) {
|
||||||
}
|
}
|
||||||
const packageMatches = packageRegex.exec(depName);
|
const packageMatches = packageRegex.exec(depName);
|
||||||
const specifierMatches = specifierRegex.exec(currentValue);
|
const specifierMatches = specifierRegex.exec(currentValue);
|
||||||
|
let skipReason;
|
||||||
if (!packageMatches) {
|
if (!packageMatches) {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`Skipping dependency with malformed package name "${depName}".`
|
`Skipping dependency with malformed package name "${depName}".`
|
||||||
);
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!specifierMatches) {
|
if (currentValue === '*') {
|
||||||
|
skipReason = 'any-version';
|
||||||
|
} else if (!specifierMatches) {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`Skipping dependency with malformed version specifier "${currentValue}".`
|
`Skipping dependency with malformed version specifier "${currentValue}".`
|
||||||
);
|
);
|
||||||
|
@ -82,6 +93,9 @@ function extractFromSection(pipfile, section, registryUrls) {
|
||||||
datasource: 'pypi',
|
datasource: 'pypi',
|
||||||
depType: section,
|
depType: section,
|
||||||
};
|
};
|
||||||
|
if (skipReason) {
|
||||||
|
dep.skipReason = skipReason;
|
||||||
|
}
|
||||||
if (registryUrls) {
|
if (registryUrls) {
|
||||||
dep.registryUrls = registryUrls;
|
dep.registryUrls = registryUrls;
|
||||||
}
|
}
|
||||||
|
|
23
test/manager/pipenv/_fixtures/Pipfile3
Normal file
23
test/manager/pipenv/_fixtures/Pipfile3
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
[[source]]
|
||||||
|
url = "https://pypi.org/simple"
|
||||||
|
verify_ssl = true
|
||||||
|
name = "pypi"
|
||||||
|
|
||||||
|
[[source]]
|
||||||
|
url = "http://example.com/private-pypi/"
|
||||||
|
verify_ssl = false
|
||||||
|
name = "private-pypi"
|
||||||
|
|
||||||
|
[packages]
|
||||||
|
# all of these version specifiers make pipenv use the same version as "*"
|
||||||
|
raven = {extras = ['flask']}
|
||||||
|
Flask = "*"
|
||||||
|
Flask-Caching = '*'
|
||||||
|
flask-mako = {}
|
||||||
|
Flask-SQLAlchemy = {version = "*"}
|
||||||
|
Flask-Login = {editable = true}
|
||||||
|
|
||||||
|
[dev-packages]
|
||||||
|
|
||||||
|
[requires]
|
||||||
|
python_version = "3.6"
|
|
@ -9,6 +9,10 @@ const pipfile2 = fs.readFileSync(
|
||||||
'test/manager/pipenv/_fixtures/Pipfile2',
|
'test/manager/pipenv/_fixtures/Pipfile2',
|
||||||
'utf8'
|
'utf8'
|
||||||
);
|
);
|
||||||
|
const pipfile3 = fs.readFileSync(
|
||||||
|
'test/manager/pipenv/_fixtures/Pipfile3',
|
||||||
|
'utf8'
|
||||||
|
);
|
||||||
|
|
||||||
describe('lib/manager/pipenv/extract', () => {
|
describe('lib/manager/pipenv/extract', () => {
|
||||||
describe('extractPackageFile()', () => {
|
describe('extractPackageFile()', () => {
|
||||||
|
@ -27,6 +31,16 @@ describe('lib/manager/pipenv/extract', () => {
|
||||||
expect(res).toMatchSnapshot();
|
expect(res).toMatchSnapshot();
|
||||||
expect(res).toHaveLength(4);
|
expect(res).toHaveLength(4);
|
||||||
});
|
});
|
||||||
|
it('marks packages with "extras" as skipReason === any-version', () => {
|
||||||
|
const res = extractPackageFile(pipfile3, {
|
||||||
|
extends: ['config:base'],
|
||||||
|
pipenv: { enabled: true },
|
||||||
|
pip_setup: { enabled: true },
|
||||||
|
labels: ['dependencies'],
|
||||||
|
}).deps;
|
||||||
|
expect(res.filter(r => !r.skipReason)).toHaveLength(0);
|
||||||
|
expect(res.filter(r => r.skipReason)).toHaveLength(6);
|
||||||
|
});
|
||||||
it('extracts multiple dependencies', () => {
|
it('extracts multiple dependencies', () => {
|
||||||
const res = extractPackageFile(pipfile2, config).deps;
|
const res = extractPackageFile(pipfile2, config).deps;
|
||||||
expect(res).toMatchSnapshot();
|
expect(res).toMatchSnapshot();
|
||||||
|
@ -36,7 +50,7 @@ describe('lib/manager/pipenv/extract', () => {
|
||||||
const content =
|
const content =
|
||||||
'[packages]\r\nflask = {git = "https://github.com/pallets/flask.git"}\r\nwerkzeug = ">=0.14"';
|
'[packages]\r\nflask = {git = "https://github.com/pallets/flask.git"}\r\nwerkzeug = ">=0.14"';
|
||||||
const res = extractPackageFile(content, config).deps;
|
const res = extractPackageFile(content, config).deps;
|
||||||
expect(res).toHaveLength(1);
|
expect(res.filter(r => !r.skipReason)).toHaveLength(1);
|
||||||
});
|
});
|
||||||
it('ignores invalid package names', () => {
|
it('ignores invalid package names', () => {
|
||||||
const content = '[packages]\r\nfoo = "==1.0.0"\r\n_invalid = "==1.0.0"';
|
const content = '[packages]\r\nfoo = "==1.0.0"\r\n_invalid = "==1.0.0"';
|
||||||
|
@ -46,7 +60,7 @@ describe('lib/manager/pipenv/extract', () => {
|
||||||
it('ignores relative path dependencies', () => {
|
it('ignores relative path dependencies', () => {
|
||||||
const content = '[packages]\r\nfoo = "==1.0.0"\r\ntest = {path = "."}';
|
const content = '[packages]\r\nfoo = "==1.0.0"\r\ntest = {path = "."}';
|
||||||
const res = extractPackageFile(content, config).deps;
|
const res = extractPackageFile(content, config).deps;
|
||||||
expect(res).toHaveLength(1);
|
expect(res.filter(r => !r.skipReason)).toHaveLength(1);
|
||||||
});
|
});
|
||||||
it('ignores invalid versions', () => {
|
it('ignores invalid versions', () => {
|
||||||
const content = '[packages]\r\nfoo = "==1.0.0"\r\nsome-package = "==0 0"';
|
const content = '[packages]\r\nfoo = "==1.0.0"\r\nsome-package = "==0 0"';
|
||||||
|
|
Loading…
Reference in a new issue