From 783237bdd25b82a62627aa347a93d27661c1fa4c Mon Sep 17 00:00:00 2001
From: Moul <moul@moul.re>
Date: Wed, 10 Nov 2021 18:11:33 +0100
Subject: [PATCH] =?UTF-8?q?[enh]=20#187:=20Implement=20=5F=5Feq=5F=5F=20an?=
 =?UTF-8?q?d=20=5F=5Fhash=5F=5F=20Membership=E2=80=99s=20methods?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 duniterpy/documents/membership.py  | 31 +++++++++++++++++++++++++++-
 tests/documents/test_membership.py | 33 ++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+), 1 deletion(-)

diff --git a/duniterpy/documents/membership.py b/duniterpy/documents/membership.py
index 592858af..86e4056b 100644
--- a/duniterpy/documents/membership.py
+++ b/duniterpy/documents/membership.py
@@ -14,7 +14,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import re
-from typing import Type, TypeVar
+from typing import Any, Type, TypeVar
 
 from ..constants import (
     BLOCK_ID_REGEX,
@@ -105,6 +105,35 @@ class Membership(Document):
         if signing_key is not None:
             self.sign(signing_key)
 
+    def __eq__(self, other: Any) -> bool:
+        """
+        Check Membership instances equality
+        """
+        if not isinstance(other, Membership):
+            return NotImplemented
+        return (
+            super().__eq__(other)
+            and self.issuer == other.issuer
+            and self.membership_block_id == other.membership_block_id
+            and self.uid == other.uid
+            and self.identity_block_id == other.identity_block_id
+            and self.membership_type == other.membership_type
+        )
+
+    def __hash__(self) -> int:
+        return hash(
+            (
+                self.issuer,
+                self.membership_block_id,
+                self.uid,
+                self.identity_block_id,
+                self.membership_type,
+                self.version,
+                self.currency,
+                self.signature,
+            )
+        )
+
     @classmethod
     def from_inline(
         cls: Type[MembershipType],
diff --git a/tests/documents/test_membership.py b/tests/documents/test_membership.py
index edadb065..bc49de15 100644
--- a/tests/documents/test_membership.py
+++ b/tests/documents/test_membership.py
@@ -15,6 +15,9 @@
 
 import unittest
 
+import pytest
+
+from duniterpy.constants import G1_TEST_CURRENCY_CODENAME
 from duniterpy.documents.membership import Membership
 
 membership_inline = "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:\
@@ -104,3 +107,33 @@ class TestMembership(unittest.TestCase):
             "dkaXIiCYUJtCg8Feh/BKvPYf4uFH9CJ/zY6J4MlA9BsjmcMe4YAblvNt/gJy31b1aGq3ue3h14mLMCu84rraDg==",
         )
         self.assertEqual(from_rendered_membership.membership_type, "IN")
+
+
+ISSUER = "issuer"
+MEMB_BLOCK_ID = "2-MEMB"
+UID = "uid"
+IDTY_BLOCK_ID = "0-IDTY"
+MEMBERSHIP_KWARGS = [ISSUER, MEMB_BLOCK_ID, UID, IDTY_BLOCK_ID]
+
+
+def test_membership_equality():
+    memb1 = Membership(*MEMBERSHIP_KWARGS)
+    memb2 = Membership(*MEMBERSHIP_KWARGS)
+    assert memb1 == memb2
+
+
+@pytest.mark.parametrize(
+    "issuer, memb_block_id, uid, idty_block_id, currency",
+    [
+        (ISSUER, MEMB_BLOCK_ID, "test", IDTY_BLOCK_ID, None),
+        (ISSUER, MEMB_BLOCK_ID, UID, "1-TEST", None),
+        ("test", MEMB_BLOCK_ID, UID, IDTY_BLOCK_ID, None),
+        MEMBERSHIP_KWARGS + [G1_TEST_CURRENCY_CODENAME],
+    ],
+)
+def test_membership_inequality(issuer, memb_block_id, uid, idty_block_id, currency):
+    memb1 = Membership(*MEMBERSHIP_KWARGS)
+    memb2 = Membership(issuer, memb_block_id, uid, idty_block_id)
+    if currency:
+        memb2.currency = currency
+    assert not memb1 == memb2
-- 
GitLab