diff --git a/lib/versioning/pep440/index.spec.ts b/lib/versioning/pep440/index.spec.ts index 50407d8e165ee6cd7476dc6b98784a2e13a2bcb4..7e40db69c7cfabe433cadc725512c27e217d5302 100644 --- a/lib/versioning/pep440/index.spec.ts +++ b/lib/versioning/pep440/index.spec.ts @@ -178,3 +178,38 @@ describe('pep440.getNewValue()', () => { expect(invalid).toEqual('==1.2.3'); }); }); + +describe('pep.isLessThanRange()', () => { + test.each([ + ['>= 1.0.0, < 2.0.0', '0.9.9.9', true], + ['>= 1.0.0, < 2.0.0', '1.0.0a0', true], + + ['> 1.0.0, < 2.0.0', '1.0.0.0', true], + ['> 1.0.0, < 2.0.0', '2.0.1.0', false], + ['> 1.0.0, < 2.0.0', '2.0.0.0', false], + ['> 1.0.0, < 2.0.0', '2.0.0a0', false], + + ['== 1.2.3', '1.2.2.9', true], + ['== 1.2.3', '1.2.3a0', true], + ['== 1.2.3', '1.2.3.0', false], + ['== 1.2.3', '1.2.3.1', false], + ['== 1.2.3', '1.2.4a0', false], + + ['!= 1.2.3', '1.2.2.9', false], + ['!= 1.2.3', '1.2.3.0', false], + ['!= 1.2.3', '1.2.3.1', false], + + ['< 1.0.0', '0.0.1', false], + ['< 1.0.0', '1.0.0', false], + ['< 1.0.0', '2.0.0', false], + + ['<= 1.0.0', '0.0.1', false], + ['<= 1.0.0', '1.0.0', false], + ['<= 1.0.0', '2.0.0', false], + + ['< 1.0.0, > 2.0.0', '0.0.1', true], // fixme (maybe) + ['< 1.0.0, > 2.0.0', '3.0.0', false], + ])(`%s\t%s\t%s`, (range, version, expected) => { + expect(pep440.isLessThanRange(version, range)).toBe(expected); + }); +}); diff --git a/lib/versioning/pep440/index.ts b/lib/versioning/pep440/index.ts index 27962b2875e51d4c822bd32234be9cac231c4e21..464abc75d9091fa38ec42b01fda912e390f70888 100644 --- a/lib/versioning/pep440/index.ts +++ b/lib/versioning/pep440/index.ts @@ -1,7 +1,7 @@ import * as pep440 from '@renovate/pep440'; import { filter } from '@renovate/pep440/lib/specifier'; import type { VersioningApi } from '../types'; -import { getNewValue } from './range'; +import { getNewValue, isLessThanRange } from './range'; export const id = 'pep440'; export const displayName = 'PEP440'; @@ -69,6 +69,7 @@ export const api: VersioningApi = { minSatisfyingVersion, getNewValue, sortVersions, + isLessThanRange, }; export default api; diff --git a/lib/versioning/pep440/range.ts b/lib/versioning/pep440/range.ts index f08bf0f6f0b40cf40cd2d63ce1c961af5c406aae..c2c9d85627927aeca67b88fd2bac5cf33b98a422 100644 --- a/lib/versioning/pep440/range.ts +++ b/lib/versioning/pep440/range.ts @@ -1,4 +1,4 @@ -import { gte, lte, satisfies } from '@renovate/pep440'; +import { gte, lt, lte, satisfies } from '@renovate/pep440'; import { parse as parseRange } from '@renovate/pep440/lib/specifier'; import { parse as parseVersion } from '@renovate/pep440/lib/version'; import { logger } from '../../logger'; @@ -154,3 +154,38 @@ export function getNewValue({ return result; } + +export function isLessThanRange(input: string, range: string): boolean { + try { + let invertResult = true; + + const results = range + .split(',') + .map((x) => + x + .replace(/\s*/g, '') + .split(/(~=|==|!=|<=|>=|<|>|===)/) + .slice(1) + ) + .map(([op, version]) => { + if (['!=', '<=', '<'].includes(op)) { + return true; + } + invertResult = false; + if (['~=', '==', '>=', '==='].includes(op)) { + return lt(input, version); + } + if (op === '>') { + return lte(input, version); + } + // istanbul ignore next + return false; + }); + + const result = results.every((res) => res === true); + + return invertResult ? !result : result; + } catch (err) /* istanbul ignore next */ { + return false; + } +}