diff --git a/duniterpy/documents/ws2p/heads.py b/duniterpy/documents/ws2p/heads.py index 97a7a82f5614f9977614201b1afdf2cc46e3bbac..b5b028e1daf01879a3daa7ee68defaedcf8ace9b 100644 --- a/duniterpy/documents/ws2p/heads.py +++ b/duniterpy/documents/ws2p/heads.py @@ -1,5 +1,4 @@ import re - import attr from ..block_uid import BlockUID @@ -46,7 +45,7 @@ class Head: re_inline = re.compile(WS2P_HEAD_REGEX) @classmethod - def from_inline(cls, inline: str): + def from_inline(cls, inline: str, signature: str): try: data = Head.re_inline.match(inline) if data is None: @@ -62,11 +61,7 @@ class Head: @attr.s() -class HeadV0: - """ - A document describing a self certification. - """ - +class HeadV0(Head): signature = attr.ib(type=str) api = attr.ib(type=API) head = attr.ib(type=Head) @@ -92,11 +87,11 @@ class HeadV0: if data is None: raise MalformedDocumentError("HeadV0") api = API.from_inline(data.group(1)) - head = Head.from_inline(data.group(2)) + head = Head.from_inline(data.group(2), "") pubkey = data.group(3) blockstamp = BlockUID.from_str(data.group(4)) offload = data.group(5) - return cls(signature, api, head, pubkey, blockstamp), offload + return cls(head.version, signature, api, head, pubkey, blockstamp), offload except AttributeError: raise MalformedDocumentError("HeadV0") @@ -106,15 +101,18 @@ class HeadV0: for v in attr.astuple( self, recurse=False, - filter=attr.filters.exclude(attr.fields(HeadV0).signature), + filter=attr.filters.exclude( + attr.fields(HeadV0).version, + attr.fields(HeadV0).signature, + attr.fields(HeadV0).api, + ), ) ) - return ":".join(values) + return "{0}:{1}".format(str(self.api), ":".join(values)) @attr.s() -class HeadV1: - v0 = attr.ib(type=HeadV0) +class HeadV1(HeadV0): ws2pid = attr.ib(type=str) software = attr.ib(type=str) software_version = attr.ib(type=str) @@ -141,35 +139,27 @@ class HeadV1: software_version = data.group(3) pow_prefix = int(data.group(4)) offload = data.group(5) - return cls(v0, ws2pid, software, software_version, pow_prefix), offload + return ( + cls( + v0.version, + v0.signature, + v0.api, + v0.head, + v0.pubkey, + v0.blockstamp, + ws2pid, + software, + software_version, + pow_prefix, + ), + offload, + ) except AttributeError: raise MalformedDocumentError("HeadV1") - def inline(self) -> str: - values = [ - str(v) - for v in attr.astuple( - self, True, filter=attr.filters.exclude(attr.fields(HeadV1).v0) - ) - ] - return self.v0.inline() + ":" + ":".join(values) - - @property - def pubkey(self) -> str: - return self.v0.pubkey - - @property - def signature(self) -> str: - return self.v0.signature - - @property - def blockstamp(self) -> BlockUID: - return self.v0.blockstamp - @attr.s -class HeadV2: - v1 = attr.ib(type=HeadV1) +class HeadV2(HeadV1): free_member_room = attr.ib(type=int) free_mirror_room = attr.ib(type=int) @@ -188,27 +178,22 @@ class HeadV2: raise MalformedDocumentError("HeadV2") free_member_room = int(data.group(1)) free_mirror_room = int(data.group(2)) - return cls(v1, free_member_room, free_mirror_room), "" + return ( + cls( + v1.version, + v1.signature, + v1.api, + v1.head, + v1.pubkey, + v1.blockstamp, + v1.ws2pid, + v1.software, + v1.software_version, + v1.pow_prefix, + free_member_room, + free_mirror_room, + ), + "", + ) except AttributeError: raise MalformedDocumentError("HeadV2") - - def inline(self) -> str: - values = ( - str(v) - for v in attr.astuple( - self, True, filter=attr.filters.exclude(attr.fields(HeadV2).v1) - ) - ) - return self.v1.inline() + ":" + ":".join(values) - - @property - def pubkey(self) -> str: - return self.v1.pubkey - - @property - def signature(self) -> str: - return self.v1.signature - - @property - def blockstamp(self) -> BlockUID: - return self.v1.blockstamp diff --git a/tests/documents/test_ws2p_heads.py b/tests/documents/test_ws2p_heads.py index 7dae1ea71f643050618a764b753a3f61e7af1234..fec0c0047514671256f33f05ec71fbdb3bf6b2f5 100644 --- a/tests/documents/test_ws2p_heads.py +++ b/tests/documents/test_ws2p_heads.py @@ -9,11 +9,11 @@ headv1_tor = "" class TestWS2PHeads(unittest.TestCase): def test_headv0(self): - headv0, _ = HeadV0.from_inline( - "WS2P:HEAD:3dnbnYY9i2bHMQUGyFp5GVvJ2wBkVpus31cDJA5cfRpj:" - "54813-00000A24802B33B71A91B6E990038C145A4815A45C71E57B2F2EF393183C7E2C", - "a1vAAM666kPsMCFTbkgkcCsqHf8nmXR+Lh3D3u+BaXzmArj7kwlItbdGUs4fc9QUG5Lp4TwPS7nhOM5t1Kt6CA==", - ) + + inline = "WS2P:HEAD:3dnbnYY9i2bHMQUGyFp5GVvJ2wBkVpus31cDJA5cfRpj:54813-00000A24802B33B71A91B6E990038C145A4815A45C71E57B2F2EF393183C7E2C" + signature = "a1vAAM666kPsMCFTbkgkcCsqHf8nmXR+Lh3D3u+BaXzmArj7kwlItbdGUs4fc9QUG5Lp4TwPS7nhOM5t1Kt6CA==" + + headv0, _ = HeadV0.from_inline(inline, signature) self.assertEqual(headv0.api.public, "") self.assertEqual(headv0.api.private, "") @@ -26,28 +26,48 @@ class TestWS2PHeads(unittest.TestCase): ), ) + new_inline = headv0.inline() + + assert inline == new_inline + def test_ws2p_headv1(self): - headv1, _ = HeadV1.from_inline( - "WS2POCAIC:HEAD:1:HbTqJ1Ts3RhJ8Rx4XkNyh1oSKmoZL1kY5U7t9mKTSjAB:" - "102131-0000066028B991BDFE3FF6DBA84EF519F76B62EA3787BC29D9A05557675B1F16:1152e46e:" - "duniter:1.6.21-beta:1", - "ZGpT8HG4uX5Hc96gqhzIkkELVjGQKDp2/L+7BTFG5ODxGYWd2VX/H+hdZRqf0iUWRNuhxlequ68kkwMaE6ymBw==", - ) + inline = "WS2P:HEAD:1:HbTqJ1Ts3RhJ8Rx4XkNyh1oSKmoZL1kY5U7t9mKTSjAB:102131-0000066028B991BDFE3FF6DBA84EF519F76B62EA3787BC29D9A05557675B1F16:1152e46e:duniter:1.6.21-beta:1" + signature = "ZGpT8HG4uX5Hc96gqhzIkkELVjGQKDp2/L+7BTFG5ODxGYWd2VX/H+hdZRqf0iUWRNuhxlequ68kkwMaE6ymBw==" + headv1, _ = HeadV1.from_inline(inline, signature) - self.assertEqual(headv1.v0.api.public, "IC") - self.assertEqual(headv1.v0.api.private, "OCA") - self.assertEqual(headv1.v0.head.version, 1) + self.assertEqual(headv1.head.version, 1) self.assertEqual(headv1.software, "duniter") self.assertEqual(headv1.software_version, "1.6.21-beta") self.assertEqual(headv1.pow_prefix, 1) + new_inline = headv1.inline() + + assert inline == new_inline + def test_ws2p_headv2(self): - headv2, _ = HeadV2.from_inline( - "WS2POCA:HEAD:2:D3krfq6J9AmfpKnS3gQVYoy7NzGCc61vokteTS8LJ4YH:" - "99393-0000017256006BFA979565F1280488D5831DD66054069E46A3EDEB1AECDBBF13:cb36b021:" - "duniter:1.6.21:1:20:19", - "CgD1vaImPWZUCDFt5HDHUdjCTFcIwW5ndiCx6kXioFLZoz1a4WhCFYXvjI2N8+jEwQdWtf5+yNoHonqBSqirAQ==", - ) + inline = "WS2POCA:HEAD:2:D3krfq6J9AmfpKnS3gQVYoy7NzGCc61vokteTS8LJ4YH:99393-0000017256006BFA979565F1280488D5831DD66054069E46A3EDEB1AECDBBF13:cb36b021:duniter:1.6.21:1:20:19" + signature = "CgD1vaImPWZUCDFt5HDHUdjCTFcIwW5ndiCx6kXioFLZoz1a4WhCFYXvjI2N8+jEwQdWtf5+yNoHonqBSqirAQ==" + headv2, _ = HeadV2.from_inline(inline, signature) + self.assertEqual(headv2.api.public, "") + self.assertEqual(headv2.api.private, "OCA") self.assertEqual(headv2.free_member_room, 20) self.assertEqual(headv2.free_mirror_room, 19) - self.assertEqual(headv2.v1.v0.head.version, 2) + self.assertEqual(headv2.head.version, 2) + + new_inline = headv2.inline() + + assert inline == new_inline + + inline = "WS2POCAIC:HEAD:2:D3krfq6J9AmfpKnS3gQVYoy7NzGCc61vokteTS8LJ4YH:99393-0000017256006BFA979565F1280488D5831DD66054069E46A3EDEB1AECDBBF13:cb36b021:duniter:1.6.21:1:20:19" + signature = "CgD1vaImPWZUCDFt5HDHUdjCTFcIwW5ndiCx6kXioFLZoz1a4WhCFYXvjI2N8+jEwQdWtf5+yNoHonqBSqirAQ==" + + headv2, _ = HeadV2.from_inline(inline, signature) + self.assertEqual(headv2.api.public, "IC") + self.assertEqual(headv2.api.private, "OCA") + self.assertEqual(headv2.free_member_room, 20) + self.assertEqual(headv2.free_mirror_room, 19) + self.assertEqual(headv2.head.version, 2) + + new_inline = headv2.inline() + + assert inline == new_inline