summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaphaël Barrois <raphael.barrois@polytechnique.org>2019-08-28 21:09:50 +0200
committerRaphaël Barrois <raphael.barrois@polytechnique.org>2019-08-28 21:09:50 +0200
commit4bc0edd07fb3210dd382512d6485ef172fcbfb0a (patch)
treeb29b753e1c29beef2162e216bf48a07b30350e1c
parent1241c3470f65b7f680a4590b68b144dac97df89b (diff)
downloadsemantic-version-4bc0edd07fb3210dd382512d6485ef172fcbfb0a.tar.gz
Fix NPM-style caret matching.
-rw-r--r--ChangeLog4
-rw-r--r--semantic_version/base.py16
-rw-r--r--tests/test_npm.py12
3 files changed, 25 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index 15f81be..f156e28 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,7 +4,9 @@ ChangeLog
2.7.1 (unreleased)
------------------
-- Nothing changed yet.
+*Bugfix:*
+
+ * Fix parsing of npm-based caret expressions.
2.7.0 (2019-08-28)
diff --git a/semantic_version/base.py b/semantic_version/base.py
index fb8205c..1c4b01d 100644
--- a/semantic_version/base.py
+++ b/semantic_version/base.py
@@ -1186,7 +1186,7 @@ class NpmSpec(BaseSpec):
PART = r'[a-zA-Z0-9.-]*'
NPM_SPEC_BLOCK = re.compile(r"""
^(?:v)? # Strip optional initial v
- (?P<op><|<=|>=|>|=|^|~|) # Operator, can be empty
+ (?P<op><|<=|>=|>|=|\^|~|) # Operator, can be empty
(?P<major>{nb})(?:\.(?P<minor>{nb})(?:\.(?P<patch>{nb}))?)?
(?:-(?P<prerel>{part}))? # Optional re-release
(?:\+(?P<build>{part}))? # Optional build
@@ -1316,13 +1316,17 @@ class NpmSpec(BaseSpec):
raise ValueError("Invalid NPM spec: %r" % simple)
if prefix == cls.PREFIX_CARET:
- if target.major: # ^1.2.4 => >=1.2.4 <2.0.0
- high = target.next_major()
+ if target.major: # ^1.2.4 => >=1.2.4 <2.0.0 ; ^1.x => >=1.0.0 <2.0.0
+ high = target.truncate().next_major()
elif target.minor: # ^0.1.2 => >=0.1.2 <0.2.0
- high = target.next_minor()
+ high = target.truncate().next_minor()
+ elif minor is None: # ^0.x => >=0.0.0 <1.0.0
+ high = target.truncate().next_major()
+ elif patch is None: # ^0.2.x => >=0.2.0 <0.3.0
+ high = target.truncate().next_minor()
else: # ^0.0.1 => >=0.0.1 <0.0.2
- high = target.next_patch()
- return [cls.range(Range.OP_GTE, target), cls.Range(Range.OP_LT, high)]
+ high = target.truncate().next_patch()
+ return [cls.range(Range.OP_GTE, target), cls.range(Range.OP_LT, high)]
elif prefix == cls.PREFIX_TILDE:
assert major is not None
diff --git a/tests/test_npm.py b/tests/test_npm.py
index 76cb6e2..86cbc76 100644
--- a/tests/test_npm.py
+++ b/tests/test_npm.py
@@ -77,6 +77,18 @@ class NpmSpecTests(unittest.TestCase):
'~0.2': '>=0.2.0 <0.3.0',
'~0': '>=0.0.0 <1.0.0',
'~1.2.3-beta.2': '>=1.2.3-beta.2 <1.3.0',
+
+ # Caret ranges
+ '^1.2.3': '>=1.2.3 <2.0.0',
+ '^0.2.3': '>=0.2.3 <0.3.0',
+ '^0.0.3': '>=0.0.3 <0.0.4',
+ '^1.2.3-beta.2': '>=1.2.3-beta.2 <2.0.0',
+ '^0.0.3-beta': '>=0.0.3-beta <0.0.4',
+ '^1.2.x': '>=1.2.0 <2.0.0',
+ '^0.0.x': '>=0.0.0 <0.1.0',
+ '^0.0': '>=0.0.0 <0.1.0',
+ '^1.x': '>=1.0.0 <2.0.0',
+ '^0.x': '>=0.0.0 <1.0.0',
}
def test_expand(self):