From 1324a446ed4335df44edc8c400d0181794338b89 Mon Sep 17 00:00:00 2001 From: Rafael Weingartner-Ortner Date: Fri, 27 Dec 2024 12:39:12 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Make=20versions=20comparible?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement comparison functions for version objects `PythonVersion` and `PythonRelease`. --- pirel/_utils.py | 39 +++++++++++++++++++++++++++++++++++++++ pirel/python_cli.py | 8 +++++++- pirel/releases.py | 8 ++++++-- 3 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 pirel/_utils.py diff --git a/pirel/_utils.py b/pirel/_utils.py new file mode 100644 index 0000000..eed69f4 --- /dev/null +++ b/pirel/_utils.py @@ -0,0 +1,39 @@ +from __future__ import annotations + +import abc + + +class VersionLike(abc.ABC): + """Abstract class for objects that hold a version (`tuple` of `int`s) and + should be comparible based on their version. + """ + + @property + @abc.abstractmethod + def version_tuple(self) -> tuple[int, ...]: + pass + + def __eq__(self, other: object) -> bool: + if not isinstance(other, VersionLike): + return NotImplemented + return self.version_tuple == other.version_tuple + + def __lt__(self, other: object) -> bool: + if not isinstance(other, VersionLike): + return NotImplemented + return self.version_tuple < other.version_tuple + + def __le__(self, other: object) -> bool: + if not isinstance(other, VersionLike): + return NotImplemented + return self.version_tuple <= other.version_tuple + + def __gt__(self, other: object) -> bool: + if not isinstance(other, VersionLike): + return NotImplemented + return self.version_tuple > other.version_tuple + + def __ge__(self, other: object) -> bool: + if not isinstance(other, VersionLike): + return NotImplemented + return self.version_tuple >= other.version_tuple diff --git a/pirel/python_cli.py b/pirel/python_cli.py index e93da3a..a828eb7 100644 --- a/pirel/python_cli.py +++ b/pirel/python_cli.py @@ -6,12 +6,14 @@ import sys from dataclasses import dataclass +from . import _utils + PYTHON_VERSION_RE = re.compile(r"Python ([23])\.(\d+)\.(\d+)") logger = logging.getLogger("pirel") @dataclass(frozen=True) -class PythonVersion: +class PythonVersion(_utils.VersionLike): major: int minor: int patch: int @@ -34,6 +36,10 @@ def this(cls) -> PythonVersion: def as_release(self) -> str: return f"{self.major}.{self.minor}" + @property + def version_tuple(self) -> tuple[int, int, int]: + return (self.major, self.minor, self.patch) + def __str__(self) -> str: return f"{self.major}.{self.minor}.{self.patch}" diff --git a/pirel/releases.py b/pirel/releases.py index 3bccb1e..dbdece6 100644 --- a/pirel/releases.py +++ b/pirel/releases.py @@ -11,7 +11,7 @@ import typer from rich.table import Table -from . import _cache, python_cli +from . import _cache, _utils, python_cli DATE_NOW = datetime.date.today() RELEASE_CYCLE_URL = "https://raw.githubusercontent.com/python/devguide/refs/heads/main/include/release-cycle.json" @@ -82,7 +82,7 @@ def wrap_style(text: str, style: str) -> str: return f"[{style.strip()}]{text}[/{style.strip()}]" -class PythonRelease: +class PythonRelease(_utils.VersionLike): def __init__(self, version: str, data: dict[str, Any]): self._version = version self._status: str = data["status"] @@ -105,6 +105,10 @@ def __str__(self) -> str: def version(self) -> str: return self._version + @property + def version_tuple(self) -> tuple[int, ...]: + return tuple(map(int, self._version.split("."))) + @property def status(self) -> str: return wrap_style(self._status, status_style(self._status))