-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- boolean check for a sem-ver string - filter and sort a sequence of sem-ver strings
- Loading branch information
Darren Weber
committed
Sep 13, 2019
1 parent
0a5a70d
commit 5bffc45
Showing
2 changed files
with
117 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
""" | ||
Strict SEM-VER utilities | ||
The focus of this module is only on sem-ver support and not | ||
full PEP-0440 support, which is not compatible with all the | ||
SEM-VER specs. | ||
https://legacy.python.org/dev/peps/pep-0440/#semantic-versioning | ||
> Semantic versions containing a hyphen (pre-releases - clause 10) or | ||
> a plus sign (builds - clause 11) are not compatible with this PEP | ||
> and are not permitted in the public version field. | ||
""" | ||
|
||
from typing import List | ||
from typing import Optional | ||
|
||
import semver | ||
|
||
|
||
def is_semver(value): # type: (str) -> bool | ||
"""Check that a string is a single SEM-VER identifier | ||
:param value: a single SEM-VER identifier | ||
:return: True if value is a single SEM-VER identifier | ||
""" | ||
try: | ||
semver.VersionInfo.parse(value) | ||
return True | ||
except (TypeError, ValueError): | ||
return False | ||
|
||
|
||
def sorted_semver( | ||
values, reverse=False | ||
): # type: (List[str], Optional[bool]) -> List[str] | ||
"""Sort a list of single SEM-VER constraints (string); | ||
discards any string that is not a SEM-VER identifier. | ||
:param values: a list of single SEM-VER identifiers (strings) | ||
:param reverse: sort descending (reverse=True) or ascending (reverse=False) | ||
:return: sorted values based on SEM-VER sort criteria | ||
""" | ||
unsorted = [ver for ver in values if is_semver(ver)] | ||
return sorted(unsorted, key=semver.VersionInfo.parse, reverse=reverse) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import random | ||
|
||
import pytest | ||
import semver | ||
|
||
from poetry.semver.semver_utils import is_semver | ||
from poetry.semver.semver_utils import sorted_semver | ||
|
||
# semver sorted values, from | ||
# https://github.com/k-bx/python-semver/blob/master/test_semver.py | ||
SORTED = [ | ||
"1.0.0-alpha", | ||
"1.0.0-alpha.1", | ||
"1.0.0-alpha.beta", | ||
"1.0.0-beta", | ||
"1.0.0-beta.2", | ||
"1.0.0-beta.11", | ||
"1.0.0-rc.1", | ||
"1.0.0", | ||
"1.0.0", | ||
"2.0.0", | ||
] | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"version,result", | ||
[ | ||
("1.2.3-alpha.1.2+build.11.e0f985a", True), | ||
("2.0.0", True), | ||
("1.0.0", True), | ||
("1.0.0-alpha.1", True), | ||
("1.0.0-alpha", True), | ||
("1.0.0-alpha.beta", True), | ||
("1.0.0-rc.1", True), | ||
("1.0.0-beta.11", True), | ||
("1.0.0-beta.2", True), | ||
("1.0.0-beta", True), | ||
("1.0.0.2", False), | ||
("1.0.0.0rc2", False), | ||
("n.a.n", False), | ||
("hot-fix-666", False), | ||
], | ||
) | ||
def test_is_semver(mocker, version, result): | ||
# The semver library is responsible for testing all variants, so this | ||
# test simply passes some examples and checks that semver.parse is called; | ||
# See also https://github.com/k-bx/python-semver/blob/master/test_semver.py | ||
parser = mocker.spy(semver.VersionInfo, name="parse") | ||
assert is_semver(version) == result | ||
assert parser.call_count == 1 | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"unsorted, sorted_", | ||
[ | ||
(random.sample(SORTED, k=len(SORTED)), SORTED), | ||
(["1.0.3", "1.0.2", "1.0.1"], ["1.0.1", "1.0.2", "1.0.3"]), | ||
( | ||
["1.0.3", "1.0.2", "1.0.1", "n.a.n", "hot-fix-666"], | ||
["1.0.1", "1.0.2", "1.0.3"], | ||
), | ||
(["10.0.3", "1.0.3", "n.a.n", "hot-fix-666"], ["1.0.3", "10.0.3"]), | ||
], | ||
) | ||
def test_sem_ver_sorted(mocker, unsorted, sorted_): | ||
parser = mocker.spy(semver.VersionInfo, name="parse") | ||
assert sorted_semver(unsorted) == sorted_ | ||
# parse is called to (a) check is_semver and (b) instantiate semver.VersionInfo for sort key | ||
assert parser.call_count == (len(unsorted) + len(sorted_)) | ||
# test the reverse order | ||
parser.reset_mock() | ||
assert sorted_semver(unsorted, reverse=True) == list(reversed(sorted_)) | ||
assert parser.call_count == (len(unsorted) + len(sorted_)) |