Skip to content

Commit

Permalink
Add diff method to AwesomeVersion to list out changes between 2 objec…
Browse files Browse the repository at this point in the history
…ts (#185)

* Add diff method to AwesomeVersion to list out changes between 2 objects

* Make it an object

* lint

* Add substraction
  • Loading branch information
ludeeus authored Sep 15, 2022
1 parent 729cfe1 commit e7dce59
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 3 deletions.
3 changes: 2 additions & 1 deletion awesomeversion/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Initialize the AwesomeVersion package."""
from .awesomeversion import AwesomeVersion
from .awesomeversion import AwesomeVersion, AwesomeVersionDiff
from .exceptions import (
AwesomeVersionCompareException,
AwesomeVersionException,
Expand All @@ -10,6 +10,7 @@
__all__ = [
"AwesomeVersion",
"AwesomeVersionCompareException",
"AwesomeVersionDiff",
"AwesomeVersionException",
"AwesomeVersionStrategy",
"AwesomeVersionStrategyException",
Expand Down
64 changes: 62 additions & 2 deletions awesomeversion/awesomeversion.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""AwesomeVersion."""
from __future__ import annotations

from typing import Any
from typing import TYPE_CHECKING, Any, Dict
from warnings import warn

from .comparehandlers.container import compare_handler_container
Expand All @@ -15,7 +15,6 @@
AwesomeVersionStrategy,
AwesomeVersionStrategyDescription,
)
from .typing import EnsureStrategyIterableType, EnsureStrategyType, VersionType
from .utils.regex import (
RE_DIGIT,
RE_MODIFIER,
Expand All @@ -24,6 +23,9 @@
generate_full_string_regex,
)

if TYPE_CHECKING:
from .typing import EnsureStrategyIterableType, EnsureStrategyType, VersionType


class _AwesomeVersionBase(str):
"""Base class for AwesomeVersion to allow the usage of the default JSON encoder."""
Expand Down Expand Up @@ -202,6 +204,25 @@ def __le__(self, compareto: object) -> bool:
def __ge__(self, compareto: object) -> bool:
return self.__eq__(compareto) or self.__gt__(compareto)

def __sub__(self, compareto: object) -> AwesomeVersionDiff:
return self.diff(compareto)

def diff(self, compareto: VersionType) -> AwesomeVersionDiff:
"""Return a dictionary with differences between 2 AwesomeVersion objects."""
if isinstance(compareto, (str, float, int)):
compareto = AwesomeVersion(compareto)
if not isinstance(compareto, AwesomeVersion):
raise AwesomeVersionCompareException("Not a valid AwesomeVersion object")
return AwesomeVersionDiff(
{
"major": self.major != compareto.major,
"minor": self.minor != compareto.minor,
"patch": self.patch != compareto.patch,
"modifier": self.modifier != compareto.modifier,
"strategy": self.strategy != compareto.strategy,
}
)

def section(self, idx: int) -> int:
"""Return the value of the specified section of the version."""
if self.sections >= (idx + 1):
Expand Down Expand Up @@ -430,3 +451,42 @@ def simple(self) -> bool:
generate_full_string_regex(RE_SIMPLE).match(self.string) is not None
)
return self._simple


class AwesomeVersionDiff:
"""Structured output of AwesomeVersion.diff"""

def __init__(self, changes: Dict[str, bool]) -> None:
"""Initialize the AwesomeVersionDiff."""
self._changes = changes

def __repr__(self) -> str:
return (
f"AwesomeVersionDiff(major={self.major}, minor={self.minor}, "
f"patch={self.patch}, modifier={self.modifier}, strategy={self.strategy})"
)

@property
def major(self) -> bool:
"""Return True if the major version has changed."""
return self._changes["major"]

@property
def minor(self) -> bool:
"""Return True if the minor version has changed."""
return self._changes["minor"]

@property
def patch(self) -> bool:
"""Return True if the patch version has changed."""
return self._changes["patch"]

@property
def modifier(self) -> bool:
"""Return True if the modifier version has changed."""
return self._changes["modifier"]

@property
def strategy(self) -> bool:
"""Return True if the strategy has changed."""
return self._changes["strategy"]
24 changes: 24 additions & 0 deletions tests/test_awesomeversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
AwesomeVersionStrategy,
AwesomeVersionStrategyException,
)
from awesomeversion.exceptions import AwesomeVersionException
from awesomeversion.strategy import COMPARABLE_STRATEGIES
from awesomeversion.typing import VersionType

Expand Down Expand Up @@ -222,3 +223,26 @@ def test_find_first_match_exception() -> None:
assert "Can not use find_first_match without ensure_strategy" in str(
warning_list[-1].message
)


def test_diff() -> None:
"""Test .diff"""
version = AwesomeVersion("2020.12.1")

assert version.diff("2021.12.1").major
assert not version.diff("2021.12.1").minor
assert not version.diff("2021.12.1").patch
assert not version.diff("2021.12.1").modifier
assert not version.diff("2021.12.1").strategy

assert version.diff("2021.11.1").minor
assert version.diff("2021.12.2").patch
assert version.diff("2021.12.1dev2").modifier
assert version.diff("2.11.1").strategy

diff = version - "2021.12.1"
assert diff.major
assert diff.__repr__().startswith("AwesomeVersionDiff(")

with pytest.raises(AwesomeVersionException):
version.diff(None)

0 comments on commit e7dce59

Please sign in to comment.