From 45c1b7100f896df5aaec6b25670d70367231b57f Mon Sep 17 00:00:00 2001 From: Dan Callaghan Date: May 01 2018 03:06:55 +0000 Subject: [PATCH 1/2] unit tests for nodejs.req The commented out assertions are ones which we are currently producing incorrect requirements for and need fixing. --- diff --git a/.gitignore b/.gitignore index 1f19bdd..96ae363 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ /node-v0.10.3.tar.gz /node-v0.10.4.tar.gz /node-v0.10.5.tar.gz +/.cache/ diff --git a/test_nodejs_req.py b/test_nodejs_req.py new file mode 100644 index 0000000..c5b1f75 --- /dev/null +++ b/test_nodejs_req.py @@ -0,0 +1,107 @@ + +# Hackery to import nodejs.req as a module (Python 3.4+) +# https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly +import importlib.util, importlib.machinery +loader = importlib.machinery.SourceFileLoader('nodejs_req', 'nodejs.req') +spec = importlib.machinery.ModuleSpec('nodejs_req', loader) +nodejs_req = importlib.util.module_from_spec(spec) +spec.loader.exec_module(nodejs_req) + +process_dep = nodejs_req.process_dep + +def test_process_dep(): + # Single version + assert process_dep('npm(a)', '1') == '(npm(a) >= 1 with npm(a) < 2)' + assert process_dep('npm(a)', '=1') == 'npm(a) = 1' + assert process_dep('npm(a)', 'v1') == '(npm(a) >= 1 with npm(a) < 2)' + #assert process_dep('npm(a)', '=v1') == 'npm(a) = 1' + assert process_dep('npm(a)', '1.2') == '(npm(a) >= 1.2 with npm(a) < 1.3)' + assert process_dep('npm(a)', '=1.2') == 'npm(a) = 1.2' + assert process_dep('npm(a)', 'v1.2') == '(npm(a) >= 1.2 with npm(a) < 1.3)' + #assert process_dep('npm(a)', '=v1.2') == 'npm(a) = 1.2' + assert process_dep('npm(a)', '1.2.3') == 'npm(a) = 1.2.3' + assert process_dep('npm(a)', '=1.2.3') == 'npm(a) = 1.2.3' + assert process_dep('npm(a)', 'v1.2.3') == 'npm(a) = 1.2.3' + #assert process_dep('npm(a)', '=v1.2.3') == 'npm(a) = 1.2.3' + + # Ranges with one comparator + assert process_dep('npm(a)', '>1') == 'npm(a) > 1' + assert process_dep('npm(a)', '>1.2') == 'npm(a) > 1.2' + assert process_dep('npm(a)', '>1.2.3') == 'npm(a) > 1.2.3' + assert process_dep('npm(a)', '>=1') == 'npm(a) >= 1' + assert process_dep('npm(a)', '>=1.2') == 'npm(a) >= 1.2' + assert process_dep('npm(a)', '>=1.2.3') == 'npm(a) >= 1.2.3' + assert process_dep('npm(a)', '<2') == 'npm(a) < 2' + assert process_dep('npm(a)', '<2.3') == 'npm(a) < 2.3' + assert process_dep('npm(a)', '<2.3.4') == 'npm(a) < 2.3.4' + assert process_dep('npm(a)', '<=2') == 'npm(a) <= 2' + assert process_dep('npm(a)', '<=2.3') == 'npm(a) <= 2.3' + assert process_dep('npm(a)', '<=2.3.4') == 'npm(a) <= 2.3.4' + + # Ranges with two comparators + assert process_dep('npm(a)', '>1 <2') == '(npm(a) > 1 with npm(a) < 2)' + assert process_dep('npm(a)', '>1.2 <2.3') == '(npm(a) > 1.2 with npm(a) < 2.3)' + assert process_dep('npm(a)', '>1.2.3 <2.3.4') == '(npm(a) > 1.2.3 with npm(a) < 2.3.4)' + assert process_dep('npm(a)', '>=1 <=2') == '(npm(a) >= 1 with npm(a) <= 2)' + assert process_dep('npm(a)', '>=1.2 <=2.3') == '(npm(a) >= 1.2 with npm(a) <= 2.3)' + assert process_dep('npm(a)', '>=1.2.3 <=2.3.4') == '(npm(a) >= 1.2.3 with npm(a) <= 2.3.4)' + assert process_dep('npm(a)', '<2 >1') == '(npm(a) < 2 with npm(a) > 1)' + assert process_dep('npm(a)', '<2.3 >1.2') == '(npm(a) < 2.3 with npm(a) > 1.2)' + assert process_dep('npm(a)', '<2.3.4 >1.2.3') == '(npm(a) < 2.3.4 with npm(a) > 1.2.3)' + assert process_dep('npm(a)', '<=2 >=1') == '(npm(a) <= 2 with npm(a) >= 1)' + assert process_dep('npm(a)', '<=2.3 >=1.2') == '(npm(a) <= 2.3 with npm(a) >= 1.2)' + assert process_dep('npm(a)', '<=2.3.4 >=1.2.3') == '(npm(a) <= 2.3.4 with npm(a) >= 1.2.3)' + + # Hyphen ranges + assert process_dep('npm(a)', '1.2.3 - 2.3.4') == '(npm(a) >= 1.2.3 with npm(a) <= 2.3.4)' + #assert process_dep('npm(a)', '1.2.3 - 2.3') == '(npm(a) >= 1.2.3 with npm(a) < 2.4)' + #assert process_dep('npm(a)', '1.2.3 - 2') == '(npm(a) >= 1.2.3 with npm(a) < 3)' + assert process_dep('npm(a)', '1.2 - 2.3.4') == '(npm(a) >= 1.2 with npm(a) <= 2.3.4)' + assert process_dep('npm(a)', '1 - 2.3.4') == '(npm(a) >= 1 with npm(a) <= 2.3.4)' + #assert process_dep('npm(a)', '1.2 - 2.3') == '(npm(a) >= 1.2 with npm(a) < 2.4)' + #assert process_dep('npm(a)', '1.2 - 2') == '(npm(a) >= 1.2 with npm(a) < 3)' + #assert process_dep('npm(a)', '1 - 2.3') == '(npm(a) >= 1 with npm(a) < 2.4)' + #assert process_dep('npm(a)', '1 - 2') == '(npm(a) >= 1 with npm(a) < 3)' + + # X-Ranges + assert process_dep('npm(a)', '1.2.x') == '(npm(a) >= 1.2 with npm(a) < 1.3)' + assert process_dep('npm(a)', '1.2.*') == '(npm(a) >= 1.2 with npm(a) < 1.3)' + assert process_dep('npm(a)', '1.x') == '(npm(a) >= 1 with npm(a) < 2)' + assert process_dep('npm(a)', '1.*') == '(npm(a) >= 1 with npm(a) < 2)' + assert process_dep('npm(a)', '*') == 'npm(a)' + assert process_dep('npm(a)', '') == 'npm(a)' + + # Tilde ranges + assert process_dep('npm(a)', '~1.2.3') == '(npm(a) >= 1.2.3 with npm(a) < 1.3)' + assert process_dep('npm(a)', '~1.2.x') == '(npm(a) >= 1.2 with npm(a) < 1.3)' + #assert process_dep('npm(a)', '~1.2') == '(npm(a) >= 1.2 with npm(a) < 1.3)' + assert process_dep('npm(a)', '~1.x') == '(npm(a) >= 1 with npm(a) < 2)' + assert process_dep('npm(a)', '~1') == '(npm(a) >= 1 with npm(a) < 2)' + + # Caret ranges + assert process_dep('npm(a)', '^1.2.3') == '(npm(a) >= 1.2.3 with npm(a) < 2)' + assert process_dep('npm(a)', '^0.2.3') == '(npm(a) >= 0.2.3 with npm(a) < 0.3)' + #assert process_dep('npm(a)', '^0.0.3') == '(npm(a) >= 0.0.3 with npm(a) < 0.0.4)' + #assert process_dep('npm(a)', '^1.2.x') == '(npm(a) >= 1.2 with npm(a) < 2)' + assert process_dep('npm(a)', '^1.2') == '(npm(a) >= 1.2 with npm(a) < 2)' + assert process_dep('npm(a)', '^0.1.x') == '(npm(a) >= 0.1 with npm(a) < 0.2)' + #assert process_dep('npm(a)', '^0.1') == '(npm(a) >= 0.1 with npm(a) < 0.2)' + assert process_dep('npm(a)', '^1.x') == '(npm(a) >= 1 with npm(a) < 2)' + assert process_dep('npm(a)', '^1') == '(npm(a) >= 1 with npm(a) < 2)' + assert process_dep('npm(a)', '^0.0.x') == '(npm(a) >= 0.0 with npm(a) < 0.1)' + #assert process_dep('npm(a)', '^0.0') == '(npm(a) >= 0.0 with npm(a) < 0.1)' + assert process_dep('npm(a)', '^0.x') == 'npm(a) < 1' + assert process_dep('npm(a)', '^0') == 'npm(a) < 1' + + # The following cases are not implemented currently... + + # Multiple comparator sets separated by || + assert process_dep('npm(a)', '^1.2 || ^2.2') == 'npm(a)' + + # More than two comparators in a set + # (no reason for this to ever appear, but it is permitted) + #assert process_dep('npm(a)', '>1.2 <2.0 <1.9') == '(npm(a) > 1.2 with npm(a) < 2.0 with npm(a) < 1.9)' + assert process_dep('npm(a)', '>1.2 <2.0 <1.9') == '(npm(a) > 1.2 with npm(a) < 2.0)' + + # The whole pre-release stuff: https://docs.npmjs.com/misc/semver#prerelease-tags + # which is not even enumerated here because it is so complex. From e5f7762e3c8438e27d8351046936afab4b6678c7 Mon Sep 17 00:00:00 2001 From: Dan Callaghan Date: May 01 2018 22:41:38 +0000 Subject: [PATCH 2/2] properly fix nodejs.req version handling Rewrote the version handling logic to more closely match the grammar defined in: https://docs.npmjs.com/misc/semver It now passes all tests, including some outstanding broken ones. --- diff --git a/nodejs.req b/nodejs.req index f09dd87..04e1365 100755 --- a/nodejs.req +++ b/nodejs.req @@ -32,8 +32,6 @@ import os import re import sys -RE_VERSION = re.compile(r'\s*v?([<>=~^]{0,2})\s*([0-9][0-9\.\-]*)\s*') - def has_all_bundled(path): # remove 'package.json' path = os.path.dirname(path) @@ -100,34 +98,17 @@ def main(): def process_dep(req, version): """Converts an individual npm dependency into RPM dependencies""" - deps = [] - #there's no way RPM can do anything like an OR dependency if '||' in version: sys.stderr.write("WARNING: The {0} dependency contains an ".format(req) + "OR (||) dependency: '{0}.\nPlease manually include ".format(version) + "a versioned dependency in your spec file if necessary") - deps.append(req) - - elif ' - ' in version: - gt, lt = version.split(' - ') - deps.append(req + ' >= ' + gt) - deps.append(req + ' <= ' + lt) - - else: - m = re.match(RE_VERSION, version) - - if m: - deps += convert_dep(req, m.group(1), m.group(2)) + return req - #There could be up to two versions here (e.g.">1.0 <3.1") - if len(version) > m.end(): - m = re.match(RE_VERSION, version[m.end():]) + if ' - ' in version: + version = expand_hyphen_range(version) - if m: - deps += convert_dep(req, m.group(1), m.group(2)) - else: - deps.append(req) + deps = convert_dep(req, version) if len(deps) > 1: dep = "(" + " with ".join(deps) + ")" @@ -136,61 +117,179 @@ def process_dep(req, version): return dep -def convert_dep(req, operator, version): - """Converts one of the two possibly listed versions into an RPM dependency""" - - deps = [] +def parse_version(v): + """ + Parse an individual version number like 1.2.3 into a tuple. + '1.2.3' -> (1, 2, 3) + '1.2' -> (1, 2) + '1' -> (1,) + '*' -> () + This is the "partial" production in the grammar: + https://docs.npmjs.com/misc/semver#range-grammar + """ + # Ignore leading 'v' + v = v.lstrip('v') + parts = v.split('.', 3) + if parts[0] in ['', 'x', 'X', '*']: + return () + if len(parts) < 2 or parts[1] in ['', 'x', 'X', '*']: + return (int(parts[0]),) + if len(parts) < 3 or parts[2] in ['', 'x', 'X', '*']: + return (int(parts[0]), int(parts[1])) + # Strip off and discard any pre-release or build qualifiers at the end. + # We can get away with this, because there is no sane way to represent + # these kinds of version requirements in RPM, and we generally expect + # the distro will only carry proper releases anyway. + return (int(parts[0]), + int(parts[1]), + int(''.join(c for c in parts[2] if c.isdigit()))) + +def incremented(v): + """ + Returns the given version tuple with the last part incremented. + (1, 2, 3) -> (1, 2, 4) + (1, 2) -> (1, 3) + (1,) -> (2,) + () -> () + """ + if len(v) == 3: + return (v[0], v[1], v[2] + 1) + if len(v) == 2: + return (v[0], v[1] + 1) + if len(v) == 1: + return (v[0] + 1,) + if len(v) == 0: + return () + +def expand_hyphen_range(version): + """ + Converts a hyphen range into its equivalent comparator set. + '1.2.3 - 2.3.4' -> '>=1.2.3 <=2.3.4' + + https://docs.npmjs.com/misc/semver#hyphen-ranges-xyz---abc + """ + lower, upper = version.split(' - ', 1) + upper_parts = parse_version(upper) + if len(upper_parts) == 3: + return '>={} <={}'.format(lower, upper) + # Special behaviour if the upper bound is partial: + if len(upper_parts) == 2: + return '>={} <{}.{}'.format(lower, upper_parts[0], upper_parts[1] + 1) + if len(upper_parts) == 1: + return '>={} <{}'.format(lower, upper_parts[0] + 1) + if len(upper_parts) == 0: + return '>={}'.format(lower) + +def convert_dep(req, version): + """ + Converts an NPM requirement to an equivalent list of RPM requirements. + """ + # The version is a space-separated set of one or more comparators. + # There can be any number of comparators (even more than two) using all the + # various shortcut operators, but ultimately the comparator set is + # equivalent to a continuous range of version numbers, with an upper and + # lower bound (possibly inclusive or exclusive at each end). + + # Start by defining the range as infinite. + lower_bound = () + lower_bound_inclusive = True + upper_bound = () + upper_bound_inclusive = False + + # Helper function to narrow the lower bound to the given version, if it's + # *higher* than what we have now. + def narrow_lower(parts, inclusive): + nonlocal lower_bound, lower_bound_inclusive + if parts > lower_bound: + lower_bound = parts + lower_bound_inclusive = inclusive + elif parts == lower_bound: + if not inclusive and lower_bound_inclusive: + lower_bound_inclusive = False + # Same for the upper bound. + def narrow_upper(parts, inclusive): + nonlocal upper_bound, upper_bound_inclusive + if parts == (): + return + if upper_bound == () or parts < upper_bound: + upper_bound = parts + upper_bound_inclusive = inclusive + elif parts == upper_bound: + if not inclusive and upper_bound_inclusive: + upper_bound_inclusive = False + + # For each comparator in the set, narrow the range to match it, + # using the two helper functions. + for comparator in version.split(): + operator, v = re.match(r'(<=|>=|<|>|=|\^|~)?(.*)', comparator).groups() + if operator is None: + operator = '=' + parts = parse_version(v) + + if operator == '>': + narrow_lower(parts, False) + + elif operator == '>=': + narrow_lower(parts, True) + + elif operator == '<': + narrow_upper(parts, False) + + elif operator == '<=': + narrow_upper(parts, True) + + elif operator == '=': + narrow_lower(parts, True) + narrow_upper(incremented(parts), False) - #any version will do - if not version or version == '*': - deps.append(req) - - #any prefix but ~ makes things dead simple - elif operator in ['>', '<', '<=', '>=', '=']: - deps.append(' '.join([req, operator, version])) - - #oh boy, here we go... - else: - #split the dotted portions into a list (handling trailing dots properly) - parts = [part if part else 'x' for part in version.split('.')] - parts = [int(part) if part != 'x' and not '-' in part - else part for part in parts] - - # 1 or 1.x or 1.x.x or ~1 or ^1 - if len(parts) == 1 or parts[1] == 'x': - if parts[0] != 0: - deps.append('{0} >= {1}'.format(req, parts[0])) - deps.append('{0} < {1}'.format(req, parts[0]+1)) - - # 1.2.3 or 1.2.3-4 or 1.2.x or ~1.2.3 or ^1.2.3 or 1.2 - elif len(parts) == 3 or not operator: - # 1.2.x or 1.2 - if len(parts) == 2 or parts[2] == 'x': - deps.append('{0} >= {1}.{2}'.format(req, parts[0], parts[1])) - deps.append('{0} < {1}.{2}'.format(req, parts[0], parts[1]+1)) - # ~1.2.3 or ^0.1.2 (zero is special with the caret operator) - elif operator == '~' or (operator == '^' and parts[0] == 0 and parts[1] > 0): - deps.append('{0} >= {1}'.format(req, version)) - deps.append('{0} < {1}.{2}'.format(req, parts[0], parts[1]+1)) - #^1.2.3 - elif operator == '^' and parts[0:1] != [0,0]: - deps.append('{0} >= {1}'.format(req, version)) - deps.append('{0} < {1}'.format(req, parts[0]+1)) - # 1.2.3 or 1.2.3-4 or ^0.0.3 - else: - deps.append('{0} = {1}'.format(req, version)) - - # ~1.2 elif operator == '~': - deps.append('{0} >= {1}'.format(req, version)) - deps.append('{0} < {1}'.format(req, parts[0]+1)) + narrow_lower(parts, True) + if len(parts) == 0: + pass + elif len(parts) == 1: + narrow_upper((parts[0] + 1,), False) + else: + narrow_upper((parts[0], parts[1] + 1), False) - #^1.2 elif operator == '^': - deps.append('{0} >= {1}'.format(req, version)) - deps.append('{0} < {1}'.format(req, parts[0]+1)) - - + narrow_lower(parts, True) + if len(parts) == 0: + pass + elif len(parts) == 1: + narrow_upper((parts[0] + 1,), False) + elif len(parts) == 2: + if parts[0] == 0: + narrow_upper((0, parts[1] + 1), False) + else: + narrow_upper((parts[0] + 1,), False) + elif len(parts) == 3: + if parts[0] == 0 and parts[1] == 0: + narrow_upper((0, 0, parts[2] + 1), False) + elif parts[0] == 0: + narrow_upper((0, parts[1] + 1), False) + else: + narrow_upper((parts[0] + 1,), False) + + # At the end, we have an upper and lower bound which satisfies all the + # comparators in the set. This is what will become our RPM version + # requirements. + + # Special case: no effective bounds. + if not lower_bound and not upper_bound: + return [req] + + # Otherwise, produce RPM requirements for the upper and lower bounds. + deps = [] + if lower_bound not in [(), (0,), (0, 0), (0, 0, 0)]: + deps.append('{} {} {}'.format( + req, + '>=' if lower_bound_inclusive else '>', + '.'.join(str(part) for part in lower_bound))) + if upper_bound != (): + deps.append('{} {} {}'.format( + req, + '<=' if upper_bound_inclusive else '<', + '.'.join(str(part) for part in upper_bound))) return deps if __name__ == '__main__': diff --git a/test_nodejs_req.py b/test_nodejs_req.py index c5b1f75..c1a1965 100644 --- a/test_nodejs_req.py +++ b/test_nodejs_req.py @@ -12,17 +12,17 @@ process_dep = nodejs_req.process_dep def test_process_dep(): # Single version assert process_dep('npm(a)', '1') == '(npm(a) >= 1 with npm(a) < 2)' - assert process_dep('npm(a)', '=1') == 'npm(a) = 1' + assert process_dep('npm(a)', '=1') == '(npm(a) >= 1 with npm(a) < 2)' assert process_dep('npm(a)', 'v1') == '(npm(a) >= 1 with npm(a) < 2)' - #assert process_dep('npm(a)', '=v1') == 'npm(a) = 1' + assert process_dep('npm(a)', '=v1') == '(npm(a) >= 1 with npm(a) < 2)' assert process_dep('npm(a)', '1.2') == '(npm(a) >= 1.2 with npm(a) < 1.3)' - assert process_dep('npm(a)', '=1.2') == 'npm(a) = 1.2' + assert process_dep('npm(a)', '=1.2') == '(npm(a) >= 1.2 with npm(a) < 1.3)' assert process_dep('npm(a)', 'v1.2') == '(npm(a) >= 1.2 with npm(a) < 1.3)' - #assert process_dep('npm(a)', '=v1.2') == 'npm(a) = 1.2' - assert process_dep('npm(a)', '1.2.3') == 'npm(a) = 1.2.3' - assert process_dep('npm(a)', '=1.2.3') == 'npm(a) = 1.2.3' - assert process_dep('npm(a)', 'v1.2.3') == 'npm(a) = 1.2.3' - #assert process_dep('npm(a)', '=v1.2.3') == 'npm(a) = 1.2.3' + assert process_dep('npm(a)', '=v1.2') == '(npm(a) >= 1.2 with npm(a) < 1.3)' + assert process_dep('npm(a)', '1.2.3') == '(npm(a) >= 1.2.3 with npm(a) < 1.2.4)' + assert process_dep('npm(a)', '=1.2.3') == '(npm(a) >= 1.2.3 with npm(a) < 1.2.4)' + assert process_dep('npm(a)', 'v1.2.3') == '(npm(a) >= 1.2.3 with npm(a) < 1.2.4)' + assert process_dep('npm(a)', '=v1.2.3') == '(npm(a) >= 1.2.3 with npm(a) < 1.2.4)' # Ranges with one comparator assert process_dep('npm(a)', '>1') == 'npm(a) > 1' @@ -45,23 +45,23 @@ def test_process_dep(): assert process_dep('npm(a)', '>=1 <=2') == '(npm(a) >= 1 with npm(a) <= 2)' assert process_dep('npm(a)', '>=1.2 <=2.3') == '(npm(a) >= 1.2 with npm(a) <= 2.3)' assert process_dep('npm(a)', '>=1.2.3 <=2.3.4') == '(npm(a) >= 1.2.3 with npm(a) <= 2.3.4)' - assert process_dep('npm(a)', '<2 >1') == '(npm(a) < 2 with npm(a) > 1)' - assert process_dep('npm(a)', '<2.3 >1.2') == '(npm(a) < 2.3 with npm(a) > 1.2)' - assert process_dep('npm(a)', '<2.3.4 >1.2.3') == '(npm(a) < 2.3.4 with npm(a) > 1.2.3)' - assert process_dep('npm(a)', '<=2 >=1') == '(npm(a) <= 2 with npm(a) >= 1)' - assert process_dep('npm(a)', '<=2.3 >=1.2') == '(npm(a) <= 2.3 with npm(a) >= 1.2)' - assert process_dep('npm(a)', '<=2.3.4 >=1.2.3') == '(npm(a) <= 2.3.4 with npm(a) >= 1.2.3)' + assert process_dep('npm(a)', '<2 >1') == '(npm(a) > 1 with npm(a) < 2)' + assert process_dep('npm(a)', '<2.3 >1.2') == '(npm(a) > 1.2 with npm(a) < 2.3)' + assert process_dep('npm(a)', '<2.3.4 >1.2.3') == '(npm(a) > 1.2.3 with npm(a) < 2.3.4)' + assert process_dep('npm(a)', '<=2 >=1') == '(npm(a) >= 1 with npm(a) <= 2)' + assert process_dep('npm(a)', '<=2.3 >=1.2') == '(npm(a) >= 1.2 with npm(a) <= 2.3)' + assert process_dep('npm(a)', '<=2.3.4 >=1.2.3') == '(npm(a) >= 1.2.3 with npm(a) <= 2.3.4)' # Hyphen ranges assert process_dep('npm(a)', '1.2.3 - 2.3.4') == '(npm(a) >= 1.2.3 with npm(a) <= 2.3.4)' - #assert process_dep('npm(a)', '1.2.3 - 2.3') == '(npm(a) >= 1.2.3 with npm(a) < 2.4)' - #assert process_dep('npm(a)', '1.2.3 - 2') == '(npm(a) >= 1.2.3 with npm(a) < 3)' + assert process_dep('npm(a)', '1.2.3 - 2.3') == '(npm(a) >= 1.2.3 with npm(a) < 2.4)' + assert process_dep('npm(a)', '1.2.3 - 2') == '(npm(a) >= 1.2.3 with npm(a) < 3)' assert process_dep('npm(a)', '1.2 - 2.3.4') == '(npm(a) >= 1.2 with npm(a) <= 2.3.4)' assert process_dep('npm(a)', '1 - 2.3.4') == '(npm(a) >= 1 with npm(a) <= 2.3.4)' - #assert process_dep('npm(a)', '1.2 - 2.3') == '(npm(a) >= 1.2 with npm(a) < 2.4)' - #assert process_dep('npm(a)', '1.2 - 2') == '(npm(a) >= 1.2 with npm(a) < 3)' - #assert process_dep('npm(a)', '1 - 2.3') == '(npm(a) >= 1 with npm(a) < 2.4)' - #assert process_dep('npm(a)', '1 - 2') == '(npm(a) >= 1 with npm(a) < 3)' + assert process_dep('npm(a)', '1.2 - 2.3') == '(npm(a) >= 1.2 with npm(a) < 2.4)' + assert process_dep('npm(a)', '1.2 - 2') == '(npm(a) >= 1.2 with npm(a) < 3)' + assert process_dep('npm(a)', '1 - 2.3') == '(npm(a) >= 1 with npm(a) < 2.4)' + assert process_dep('npm(a)', '1 - 2') == '(npm(a) >= 1 with npm(a) < 3)' # X-Ranges assert process_dep('npm(a)', '1.2.x') == '(npm(a) >= 1.2 with npm(a) < 1.3)' @@ -74,34 +74,33 @@ def test_process_dep(): # Tilde ranges assert process_dep('npm(a)', '~1.2.3') == '(npm(a) >= 1.2.3 with npm(a) < 1.3)' assert process_dep('npm(a)', '~1.2.x') == '(npm(a) >= 1.2 with npm(a) < 1.3)' - #assert process_dep('npm(a)', '~1.2') == '(npm(a) >= 1.2 with npm(a) < 1.3)' + assert process_dep('npm(a)', '~1.2') == '(npm(a) >= 1.2 with npm(a) < 1.3)' assert process_dep('npm(a)', '~1.x') == '(npm(a) >= 1 with npm(a) < 2)' assert process_dep('npm(a)', '~1') == '(npm(a) >= 1 with npm(a) < 2)' # Caret ranges assert process_dep('npm(a)', '^1.2.3') == '(npm(a) >= 1.2.3 with npm(a) < 2)' assert process_dep('npm(a)', '^0.2.3') == '(npm(a) >= 0.2.3 with npm(a) < 0.3)' - #assert process_dep('npm(a)', '^0.0.3') == '(npm(a) >= 0.0.3 with npm(a) < 0.0.4)' - #assert process_dep('npm(a)', '^1.2.x') == '(npm(a) >= 1.2 with npm(a) < 2)' + assert process_dep('npm(a)', '^0.0.3') == '(npm(a) >= 0.0.3 with npm(a) < 0.0.4)' + assert process_dep('npm(a)', '^1.2.x') == '(npm(a) >= 1.2 with npm(a) < 2)' assert process_dep('npm(a)', '^1.2') == '(npm(a) >= 1.2 with npm(a) < 2)' assert process_dep('npm(a)', '^0.1.x') == '(npm(a) >= 0.1 with npm(a) < 0.2)' - #assert process_dep('npm(a)', '^0.1') == '(npm(a) >= 0.1 with npm(a) < 0.2)' + assert process_dep('npm(a)', '^0.1') == '(npm(a) >= 0.1 with npm(a) < 0.2)' assert process_dep('npm(a)', '^1.x') == '(npm(a) >= 1 with npm(a) < 2)' assert process_dep('npm(a)', '^1') == '(npm(a) >= 1 with npm(a) < 2)' - assert process_dep('npm(a)', '^0.0.x') == '(npm(a) >= 0.0 with npm(a) < 0.1)' - #assert process_dep('npm(a)', '^0.0') == '(npm(a) >= 0.0 with npm(a) < 0.1)' + assert process_dep('npm(a)', '^0.0.x') == 'npm(a) < 0.1' + assert process_dep('npm(a)', '^0.0') == 'npm(a) < 0.1' assert process_dep('npm(a)', '^0.x') == 'npm(a) < 1' assert process_dep('npm(a)', '^0') == 'npm(a) < 1' + # More than two comparators in a set + # (no reason for this to ever appear, but it is permitted) + assert process_dep('npm(a)', '>1.2 <2.0 <1.9') == '(npm(a) > 1.2 with npm(a) < 1.9)' + # The following cases are not implemented currently... # Multiple comparator sets separated by || assert process_dep('npm(a)', '^1.2 || ^2.2') == 'npm(a)' - # More than two comparators in a set - # (no reason for this to ever appear, but it is permitted) - #assert process_dep('npm(a)', '>1.2 <2.0 <1.9') == '(npm(a) > 1.2 with npm(a) < 2.0 with npm(a) < 1.9)' - assert process_dep('npm(a)', '>1.2 <2.0 <1.9') == '(npm(a) > 1.2 with npm(a) < 2.0)' - # The whole pre-release stuff: https://docs.npmjs.com/misc/semver#prerelease-tags # which is not even enumerated here because it is so complex.