diff --git a/changelog.d/309.trivial.rst b/changelog.d/309.trivial.rst
new file mode 100644
index 00000000..97bbba1e
--- /dev/null
+++ b/changelog.d/309.trivial.rst
@@ -0,0 +1,17 @@
+Some (private) functions from the :mod:`semver.version`
+module has been changed.
+
+The following functions got renamed:
+
+* function ``semver.version.comparator`` got renamed to
+ :func:`semver.version._comparator` as it is only useful
+ inside the :class:`~semver.version.Version` class.
+* function ``semver.version.cmp`` got renamed to
+ :func:`semver.version._cmp` as it is only useful
+ inside the :class:`~semver.version.Version` class.
+
+The following functions got integrated into the
+:class:`~semver.version.Version` class:
+
+* function ``semver.version._nat_cmd`` as a classmethod
+* function ``semver.version.ensure_str``
diff --git a/docs/api.rst b/docs/api.rst
index d35c48fe..196e30a9 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -50,12 +50,6 @@ Version Handling :mod:`semver.version`
.. automodule:: semver.version
-.. autofunction:: semver.version.cmp
-
-.. autofunction:: semver.version.ensure_str
-
-.. autofunction:: semver.version.comparator
-
.. autoclass:: semver.version.VersionInfo
.. autoclass:: semver.version.Version
diff --git a/src/semver/version.py b/src/semver/version.py
index 4633f4bc..9e02544f 100644
--- a/src/semver/version.py
+++ b/src/semver/version.py
@@ -29,37 +29,7 @@
Comparator = Callable[["Version", Comparable], bool]
-def cmp(a, b): # TODO: type hints
- """Return negative if ab."""
- return (a > b) - (a < b)
-
-
-def ensure_str(s: String, encoding="utf-8", errors="strict") -> str:
- # Taken from six project
- """
- Coerce *s* to `str`.
-
- * `str` -> `str`
- * `bytes` -> decoded to `str`
-
- :param s: the string to convert
- :param encoding: the encoding to apply, defaults to "utf-8"
- :param errors: set a different error handling scheme,
- defaults to "strict".
- Other possible values are `ignore`, `replace`, and
- `xmlcharrefreplace` as well as any other name
- registered with :func:`codecs.register_error`.
- :raises TypeError: if ``s`` is not str or bytes type
- :return: the converted string
- """
- if isinstance(s, bytes):
- s = s.decode(encoding, errors)
- elif not isinstance(s, String.__args__): # type: ignore
- raise TypeError("not expecting type '%s'" % type(s))
- return s
-
-
-def comparator(operator: Comparator) -> Comparator:
+def _comparator(operator: Comparator) -> Comparator:
"""Wrap a Version binary op method in a type-check."""
@wraps(operator)
@@ -78,31 +48,9 @@ def wrapper(self: "Version", other: Comparable) -> bool:
return wrapper
-def _nat_cmp(a, b): # TODO: type hints
- def convert(text):
- return int(text) if re.match("^[0-9]+$", text) else text
-
- def split_key(key):
- return [convert(c) for c in key.split(".")]
-
- def cmp_prerelease_tag(a, b):
- if isinstance(a, int) and isinstance(b, int):
- return cmp(a, b)
- elif isinstance(a, int):
- return -1
- elif isinstance(b, int):
- return 1
- else:
- return cmp(a, b)
-
- a, b = a or "", b or ""
- a_parts, b_parts = split_key(a), split_key(b)
- for sub_a, sub_b in zip(a_parts, b_parts):
- cmp_result = cmp_prerelease_tag(sub_a, sub_b)
- if cmp_result != 0:
- return cmp_result
- else:
- return cmp(len(a), len(b))
+def _cmp(a, b): # TODO: type hints
+ """Return negative if ab."""
+ return (a > b) - (a < b)
class Version:
@@ -165,6 +113,29 @@ def __init__(
self._prerelease = None if prerelease is None else str(prerelease)
self._build = None if build is None else str(build)
+ @classmethod
+ def _nat_cmp(cls, a, b): # TODO: type hints
+ def cmp_prerelease_tag(a, b):
+ if isinstance(a, int) and isinstance(b, int):
+ return _cmp(a, b)
+ elif isinstance(a, int):
+ return -1
+ elif isinstance(b, int):
+ return 1
+ else:
+ return _cmp(a, b)
+
+ a, b = a or "", b or ""
+ a_parts, b_parts = a.split("."), b.split(".")
+ a_parts = [int(x) if re.match(r"^\d+$", x) else x for x in a_parts]
+ b_parts = [int(x) if re.match(r"^\d+$", x) else x for x in b_parts]
+ for sub_a, sub_b in zip(a_parts, b_parts):
+ cmp_result = cmp_prerelease_tag(sub_a, sub_b)
+ if cmp_result != 0:
+ return cmp_result
+ else:
+ return _cmp(len(a), len(b))
+
@property
def major(self) -> int:
"""The major part of a version (read-only)."""
@@ -381,12 +352,12 @@ def compare(self, other: Comparable) -> int:
v1 = self.to_tuple()[:3]
v2 = other.to_tuple()[:3]
- x = cmp(v1, v2)
+ x = _cmp(v1, v2)
if x:
return x
rc1, rc2 = self.prerelease, other.prerelease
- rccmp = _nat_cmp(rc1, rc2)
+ rccmp = self._nat_cmp(rc1, rc2)
if not rccmp:
return 0
@@ -444,27 +415,27 @@ def next_version(self, part: str, prerelease_token: str = "rc") -> "Version":
version = version.bump_patch()
return version.bump_prerelease(prerelease_token)
- @comparator
+ @_comparator
def __eq__(self, other: Comparable) -> bool: # type: ignore
return self.compare(other) == 0
- @comparator
+ @_comparator
def __ne__(self, other: Comparable) -> bool: # type: ignore
return self.compare(other) != 0
- @comparator
+ @_comparator
def __lt__(self, other: Comparable) -> bool:
return self.compare(other) < 0
- @comparator
+ @_comparator
def __le__(self, other: Comparable) -> bool:
return self.compare(other) <= 0
- @comparator
+ @_comparator
def __gt__(self, other: Comparable) -> bool:
return self.compare(other) > 0
- @comparator
+ @_comparator
def __ge__(self, other: Comparable) -> bool:
return self.compare(other) >= 0
@@ -593,15 +564,20 @@ def parse(cls, version: String) -> "Version":
:param version: version string
:return: a new :class:`Version` instance
:raises ValueError: if version is invalid
+ :raises TypeError: if version contains the wrong type
>>> semver.Version.parse('3.4.5-pre.2+build.4')
Version(major=3, minor=4, patch=5, \
prerelease='pre.2', build='build.4')
"""
- version_str = ensure_str(version)
- match = cls._REGEX.match(version_str)
+ if isinstance(version, bytes):
+ version = version.decode("UTF-8")
+ elif not isinstance(version, String.__args__): # type: ignore
+ raise TypeError("not expecting type '%s'" % type(version))
+
+ match = cls._REGEX.match(version)
if match is None:
- raise ValueError(f"{version_str} is not valid SemVer string")
+ raise ValueError(f"{version} is not valid SemVer string")
matched_version_parts: Dict[str, Any] = match.groupdict()
diff --git a/tests/test_typeerror-274.py b/tests/test_typeerror-274.py
index 61480bcf..326304b8 100644
--- a/tests/test_typeerror-274.py
+++ b/tests/test_typeerror-274.py
@@ -1,95 +1,14 @@
-import sys
-
import pytest
-
import semver
-import semver.version
-
-PY2 = sys.version_info[0] == 2
-PY3 = sys.version_info[0] == 3
-
-
-def ensure_binary(s, encoding="utf-8", errors="strict"):
- """
- Coerce ``s`` to bytes.
-
- * `str` -> encoded to `bytes`
- * `bytes` -> `bytes`
-
- :param s: the string to convert
- :type s: str | bytes
- :param encoding: the encoding to apply, defaults to "utf-8"
- :type encoding: str
- :param errors: set a different error handling scheme;
- other possible values are `ignore`, `replace`, and
- `xmlcharrefreplace` as well as any other name
- registered with :func:`codecs.register_error`.
- Defaults to "strict".
- :type errors: str
- :raises TypeError: if ``s`` is not str or bytes type
- :return: the converted string
- :rtype: str
- """
- if isinstance(s, str):
- return s.encode(encoding, errors)
- elif isinstance(s, bytes):
- return s
- else:
- raise TypeError("not expecting type '%s'" % type(s))
-def test_should_work_with_string_and_unicode():
+def test_should_work_with_string_and_bytes():
result = semver.compare("1.1.0", b"1.2.2")
assert result == -1
result = semver.compare(b"1.1.0", "1.2.2")
assert result == -1
-class TestEnsure:
- # From six project
- # grinning face emoji
- UNICODE_EMOJI = "\U0001F600"
- BINARY_EMOJI = b"\xf0\x9f\x98\x80"
-
- def test_ensure_binary_raise_type_error(self):
- with pytest.raises(TypeError):
- semver.version.ensure_str(8)
-
- def test_errors_and_encoding(self):
- ensure_binary(self.UNICODE_EMOJI, encoding="latin-1", errors="ignore")
- with pytest.raises(UnicodeEncodeError):
- ensure_binary(self.UNICODE_EMOJI, encoding="latin-1", errors="strict")
-
- def test_ensure_binary_raise(self):
- converted_unicode = ensure_binary(
- self.UNICODE_EMOJI, encoding="utf-8", errors="strict"
- )
- converted_binary = ensure_binary(
- self.BINARY_EMOJI, encoding="utf-8", errors="strict"
- )
-
- # PY3: str -> bytes
- assert converted_unicode == self.BINARY_EMOJI and isinstance(
- converted_unicode, bytes
- )
- # PY3: bytes -> bytes
- assert converted_binary == self.BINARY_EMOJI and isinstance(
- converted_binary, bytes
- )
-
- def test_ensure_str(self):
- converted_unicode = semver.version.ensure_str(
- self.UNICODE_EMOJI, encoding="utf-8", errors="strict"
- )
- converted_binary = semver.version.ensure_str(
- self.BINARY_EMOJI, encoding="utf-8", errors="strict"
- )
-
- # PY3: str -> str
- assert converted_unicode == self.UNICODE_EMOJI and isinstance(
- converted_unicode, str
- )
- # PY3: bytes -> str
- assert converted_binary == self.UNICODE_EMOJI and isinstance(
- converted_unicode, str
- )
+def test_should_not_work_with_invalid_args():
+ with pytest.raises(TypeError):
+ semver.version.Version.parse(8)
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: