Cleanup and document fixes from #31.
The PR was broken through fixed in ``next_minor()`` / ``next_major()``.
This commit is contained in:
@@ -32,6 +32,7 @@ ChangeLog
|
||||
* ``Spec('<=1.3.0')`` now matches ``Version('1.3.0+abde24fe883')``
|
||||
|
||||
* `#24 <https://github.com/rbarrois/python-semanticversion/issues/24>`_: Fix handling of bumping pre-release versions, thanks to @minchinweb.
|
||||
* `#30 <https://github.com/rbarrois/python-semanticversion/issues/30>`_: Add support for NPM-style ``^1.2.3`` and ``~2.3.4`` specs, thanks to @skwashd
|
||||
|
||||
2.4.2 (2015-07-02)
|
||||
------------------
|
||||
|
||||
@@ -277,6 +277,11 @@ This means that::
|
||||
.. note:: python-semanticversion also accepts ``"*"`` as a version spec,
|
||||
that matches all (valid) version strings.
|
||||
|
||||
.. note:: python-semanticversion includes support for NPM-style specs:
|
||||
|
||||
* ``~1.2.3`` means "Any release between 1.2.3 and 1.3.0"
|
||||
* ``^1.3.4`` means "Any release between 1.3.4 and 2.0.0"
|
||||
|
||||
In order to force matches to *strictly* compare version numbers, these additional
|
||||
rules apply:
|
||||
|
||||
@@ -307,6 +312,7 @@ rules apply:
|
||||
* ``<1.1.1+b1`` is invalid
|
||||
|
||||
|
||||
|
||||
.. class:: Spec(spec_string[, spec_string[, ...]])
|
||||
|
||||
Stores a list of :class:`SpecItem` and matches any :class:`Version` against all
|
||||
|
||||
@@ -406,7 +406,13 @@ class SpecItem(object):
|
||||
KIND_CARET = '^'
|
||||
KIND_TILDE = '~'
|
||||
|
||||
re_spec = re.compile(r'^(<|<=|={,2}|>=|>|!=|\^|~)(\d.*)$')
|
||||
# Map a kind alias to its full version
|
||||
KIND_ALIASES = {
|
||||
KIND_SHORTEQ: KIND_EQUAL,
|
||||
KIND_EMPTY: KIND_EQUAL,
|
||||
}
|
||||
|
||||
re_spec = re.compile(r'^(<|<=||=|==|>=|>|!=|\^|~)(\d.*)$')
|
||||
|
||||
def __init__(self, requirement_string):
|
||||
kind, spec = self.parse(requirement_string)
|
||||
@@ -427,6 +433,9 @@ class SpecItem(object):
|
||||
raise ValueError("Invalid requirement specification: %r" % requirement_string)
|
||||
|
||||
kind, version = match.groups()
|
||||
if kind in cls.KIND_ALIASES:
|
||||
kind = cls.KIND_ALIASES[kind]
|
||||
|
||||
spec = Version(version, partial=True)
|
||||
if spec.build is not None and kind not in (cls.KIND_EQUAL, cls.KIND_NEQ):
|
||||
raise ValueError(
|
||||
@@ -441,7 +450,7 @@ class SpecItem(object):
|
||||
return version < self.spec
|
||||
elif self.kind == self.KIND_LTE:
|
||||
return version <= self.spec
|
||||
elif self.kind in [self.KIND_EQUAL, self.KIND_SHORTEQ, self.KIND_EMPTY]:
|
||||
elif self.kind == self.KIND_EQUAL:
|
||||
return version == self.spec
|
||||
elif self.kind == self.KIND_GTE:
|
||||
return version >= self.spec
|
||||
@@ -450,20 +459,13 @@ class SpecItem(object):
|
||||
elif self.kind == self.KIND_NEQ:
|
||||
return version != self.spec
|
||||
elif self.kind == self.KIND_CARET:
|
||||
return self.caretCompare(version)
|
||||
return self.spec <= version < self.spec.next_major()
|
||||
return self.caret_compare(version)
|
||||
elif self.kind == self.KIND_TILDE:
|
||||
return self.tildeCompare(version)
|
||||
return self.spec <= version < self.spec.next_minor()
|
||||
else: # pragma: no cover
|
||||
raise ValueError('Unexpected match kind: %r' % self.kind)
|
||||
|
||||
def caretCompare(self, version):
|
||||
max_version = version.next_major()
|
||||
return version >= self.spec and version < max_version
|
||||
|
||||
def tildeCompare(self, version):
|
||||
max_version = version.next_minor()
|
||||
return version >= self.spec and version < max_version
|
||||
|
||||
def __str__(self):
|
||||
return '%s%s' % (self.kind, self.spec)
|
||||
|
||||
|
||||
@@ -419,6 +419,10 @@ class SpecItemTestCase(unittest.TestCase):
|
||||
'>=2.0.0': (base.SpecItem.KIND_GTE, 2, 0, 0, None, None),
|
||||
'!=0.1.1+rc3': (base.SpecItem.KIND_NEQ, 0, 1, 1, (), ('rc3',)),
|
||||
'!=0.3.0': (base.SpecItem.KIND_NEQ, 0, 3, 0, None, None),
|
||||
'=0.3.0': (base.SpecItem.KIND_EQUAL, 0, 3, 0, None, None),
|
||||
'0.3.0': (base.SpecItem.KIND_EQUAL, 0, 3, 0, None, None),
|
||||
'~0.1.2': (base.SpecItem.KIND_TILDE, 0, 1, 2, None, None),
|
||||
'^0.1.3': (base.SpecItem.KIND_CARET, 0, 1, 3, None, None),
|
||||
}
|
||||
|
||||
def test_components(self):
|
||||
@@ -433,14 +437,19 @@ class SpecItemTestCase(unittest.TestCase):
|
||||
self.assertEqual(prerelease, spec.spec.prerelease)
|
||||
self.assertEqual(build, spec.spec.build)
|
||||
|
||||
self.assertNotEqual(spec, spec_text)
|
||||
self.assertEqual(spec_text, str(spec))
|
||||
|
||||
matches = {
|
||||
'==0.1.0': (
|
||||
['0.1.0', '0.1.0-rc1', '0.1.0+build1', '0.1.0-rc1+build2'],
|
||||
['0.0.1', '0.2.0', '0.1.1'],
|
||||
),
|
||||
'=0.1.0': (
|
||||
['0.1.0', '0.1.0-rc1', '0.1.0+build1', '0.1.0-rc1+build2'],
|
||||
['0.0.1', '0.2.0', '0.1.1'],
|
||||
),
|
||||
'0.1.0': (
|
||||
['0.1.0', '0.1.0-rc1', '0.1.0+build1', '0.1.0-rc1+build2'],
|
||||
['0.0.1', '0.2.0', '0.1.1'],
|
||||
),
|
||||
'==0.1.2-rc3': (
|
||||
['0.1.2-rc3+build1', '0.1.2-rc3+build4.5'],
|
||||
['0.1.2-rc4', '0.1.2', '0.1.3'],
|
||||
@@ -489,6 +498,14 @@ class SpecItemTestCase(unittest.TestCase):
|
||||
['0.4.0', '1.3.0', '0.3.4-alpha', '0.3.4-alpha+b1'],
|
||||
['0.3.4', '0.3.4+b1'],
|
||||
),
|
||||
'~1.1.2': (
|
||||
['1.1.3', '1.1.2-alpha', '1.1.2-alpha+b1'],
|
||||
['1.1.1', '1.2.1', '2.1.0'],
|
||||
),
|
||||
'^1.1.2': (
|
||||
['1.1.3', '1.2.1', '1.1.2-alpha', '1.1.2-alpha+b1'],
|
||||
['1.1.1', '2.1.0'],
|
||||
),
|
||||
}
|
||||
|
||||
def test_matches(self):
|
||||
|
||||
@@ -122,8 +122,9 @@ class MatchTestCase(unittest.TestCase):
|
||||
|
||||
def test_simple(self):
|
||||
for valid in self.valid_specs:
|
||||
version = semantic_version.Spec(valid)
|
||||
self.assertEqual(valid, str(version))
|
||||
spec = semantic_version.SpecItem(valid)
|
||||
normalized = str(spec)
|
||||
self.assertEqual(spec, semantic_version.SpecItem(normalized))
|
||||
|
||||
def test_match(self):
|
||||
for spec_txt, versions in self.matches.items():
|
||||
|
||||
Reference in New Issue
Block a user