Skip to content
Snippets Groups Projects
Commit e5f3c4dd authored by Vincent Texier's avatar Vincent Texier
Browse files

issue #52 Fix circular import migrating BlockUID class in new module (break BC)

Fix mypy check
Fix tests
parent bb07b1f7
No related branches found
No related tags found
No related merge requests found
......@@ -33,3 +33,4 @@ WS2PID_REGEX = "[0-9a-f]{8}"
WS2P_PRIVATE_PREFIX_REGEX = "O[CT][SAM]"
WS2P_PUBLIC_PREFIX_REGEX = "I[CT]"
WS2P_HEAD_REGEX = "HEAD:?(?:[0-9]+)?"
EMPTY_HASH = "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855"
from .block import Block, BlockUID, block_uid
from .block import Block
from .block_uid import BlockUID, block_uid
from .certification import Identity, Certification, Revocation
from .membership import Membership
from .transaction import SimpleTransaction, Transaction, InputSource, OutputSource, \
......
import base64
import hashlib
import re
from typing import Union, TypeVar, Type, Optional, List, Sequence
from typing import TypeVar, Type, Optional, List, Sequence
from .block_uid import BlockUID
from .certification import Identity, Certification, Revocation
from .document import Document, MalformedDocumentError
from .membership import Membership
from .transaction import Transaction
from ..constants import PUBKEY_REGEX, BLOCK_ID_REGEX, BLOCK_HASH_REGEX
# required to type hint cls in classmethod
BlockUIDType = TypeVar('BlockUIDType', bound='BlockUID')
class BlockUID:
"""
A simple block id
"""
re_block_uid = re.compile("({block_id_regex})-({block_hash_regex})".format(block_id_regex=BLOCK_ID_REGEX,
block_hash_regex=BLOCK_HASH_REGEX))
re_hash = re.compile("({block_hash_regex})".format(block_hash_regex=BLOCK_HASH_REGEX))
def __init__(self, number: int, sha_hash: str) -> None:
assert (type(number) is int)
assert (BlockUID.re_hash.match(sha_hash) is not None)
self.number = number
self.sha_hash = sha_hash
@classmethod
def empty(cls: Type[BlockUIDType]) -> BlockUIDType:
return cls(0, Block.Empty_Hash)
@classmethod
def from_str(cls: Type[BlockUIDType], blockid: str) -> BlockUIDType:
"""
:param blockid: The block id
"""
data = BlockUID.re_block_uid.match(blockid)
if data is None:
raise MalformedDocumentError("BlockUID")
try:
number = int(data.group(1))
except AttributeError:
raise MalformedDocumentError("BlockUID")
try:
sha_hash = data.group(2)
except AttributeError:
raise MalformedDocumentError("BlockHash")
return cls(number, sha_hash)
def __str__(self) -> str:
return "{0}-{1}".format(self.number, self.sha_hash)
def __eq__(self, other: object) -> bool:
if not isinstance(other, BlockUID):
return False
return self.number == other.number and self.sha_hash == other.sha_hash
def __lt__(self, other: object) -> bool:
if not isinstance(other, BlockUID):
return False
return self.number < other.number
def __gt__(self, other: object) -> bool:
if not isinstance(other, BlockUID):
return False
return self.number > other.number
def __le__(self, other: object) -> bool:
if not isinstance(other, BlockUID):
return False
return self.number <= other.number
def __ge__(self, other: object) -> bool:
if not isinstance(other, BlockUID):
return False
return self.number >= other.number
def __hash__(self) -> int:
return hash((self.number, self.sha_hash))
def __bool__(self) -> bool:
return self != BlockUID.empty()
def block_uid(value: Union[str, BlockUID, None]) -> BlockUID:
"""
Convert value to BlockUID instance
:param value: Value to convert
:return:
"""
if isinstance(value, BlockUID):
return value
elif isinstance(value, str):
return BlockUID.from_str(value)
elif value is None:
return BlockUID.empty()
else:
raise TypeError("Cannot convert {0} to BlockUID".format(type(value)))
from ..constants import PUBKEY_REGEX, BLOCK_HASH_REGEX
# required to type hint cls in classmethod
......@@ -212,8 +119,6 @@ The class Block handles Block documents.
}
}
Empty_Hash = "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855"
def __init__(self,
version: int,
currency: str,
......
import re
from typing import Union, TypeVar, Type
from .document import MalformedDocumentError
from ..constants import EMPTY_HASH, BLOCK_ID_REGEX, BLOCK_HASH_REGEX
# required to type hint cls in classmethod
BlockUIDType = TypeVar('BlockUIDType', bound='BlockUID')
class BlockUID:
"""
A simple block id
"""
re_block_uid = re.compile("({block_id_regex})-({block_hash_regex})".format(block_id_regex=BLOCK_ID_REGEX,
block_hash_regex=BLOCK_HASH_REGEX))
re_hash = re.compile("({block_hash_regex})".format(block_hash_regex=BLOCK_HASH_REGEX))
def __init__(self, number: int, sha_hash: str) -> None:
assert (type(number) is int)
assert (BlockUID.re_hash.match(sha_hash) is not None)
self.number = number
self.sha_hash = sha_hash
@classmethod
def empty(cls: Type[BlockUIDType]) -> BlockUIDType:
return cls(0, EMPTY_HASH)
@classmethod
def from_str(cls: Type[BlockUIDType], blockid: str) -> BlockUIDType:
"""
:param blockid: The block id
"""
data = BlockUID.re_block_uid.match(blockid)
if data is None:
raise MalformedDocumentError("BlockUID")
try:
number = int(data.group(1))
except AttributeError:
raise MalformedDocumentError("BlockUID")
try:
sha_hash = data.group(2)
except AttributeError:
raise MalformedDocumentError("BlockHash")
return cls(number, sha_hash)
def __str__(self) -> str:
return "{0}-{1}".format(self.number, self.sha_hash)
def __eq__(self, other: object) -> bool:
if not isinstance(other, BlockUID):
return False
return self.number == other.number and self.sha_hash == other.sha_hash
def __lt__(self, other: object) -> bool:
if not isinstance(other, BlockUID):
return False
return self.number < other.number
def __gt__(self, other: object) -> bool:
if not isinstance(other, BlockUID):
return False
return self.number > other.number
def __le__(self, other: object) -> bool:
if not isinstance(other, BlockUID):
return False
return self.number <= other.number
def __ge__(self, other: object) -> bool:
if not isinstance(other, BlockUID):
return False
return self.number >= other.number
def __hash__(self) -> int:
return hash((self.number, self.sha_hash))
def __bool__(self) -> bool:
return self != BlockUID.empty()
def block_uid(value: Union[str, BlockUID, None]) -> BlockUID:
"""
Convert value to BlockUID instance
:param value: Value to convert
:return:
"""
if isinstance(value, BlockUID):
return value
elif isinstance(value, str):
return BlockUID.from_str(value)
elif value is None:
return BlockUID.empty()
else:
raise TypeError("Cannot convert {0} to BlockUID".format(type(value)))
import base64
import logging
import re
from typing import Optional, TypeVar, Type, List
from duniterpy.documents import BlockUID
from typing import Optional, TypeVar, Type
from .block_uid import BlockUID
from ..constants import PUBKEY_REGEX, SIGNATURE_REGEX, BLOCK_ID_REGEX, BLOCK_UID_REGEX, UID_REGEX
from .document import Document, MalformedDocumentError
......@@ -63,8 +62,6 @@ class Identity(Document):
:param inline: Inline string of the Identity
:return:
"""
from .block import BlockUID
selfcert_data = Identity.re_inline.match(inline)
if selfcert_data is None:
raise MalformedDocumentError("Inline self certification")
......@@ -82,8 +79,6 @@ class Identity(Document):
:param signed_raw: Signed raw document
:return:
"""
from .block import BlockUID
n = 0
lines = signed_raw.splitlines(True)
......@@ -141,6 +136,8 @@ Timestamp: {timestamp}
# required to type hint cls in classmethod
CertificationType = TypeVar('CertificationType', bound='Certification')
# todo: certification document should be created with the certified Identity document in arguments
class Certification(Document):
"""
......@@ -197,8 +194,6 @@ class Certification(Document):
:param signed_raw: Signed raw document
:return:
"""
from .block import BlockUID
n = 0
lines = signed_raw.splitlines(True)
......@@ -245,7 +240,6 @@ class Certification(Document):
:param inline: Inline document
:return:
"""
from .block import BlockUID
cert_data = Certification.re_inline.match(inline)
if cert_data is None:
raise MalformedDocumentError("Certification ({0})".format(inline))
......@@ -325,6 +319,8 @@ CertTimestamp: {timestamp}
# required to type hint cls in classmethod
RevocationType = TypeVar('RevocationType', bound='Revocation')
# todo: Revocation document should be created with the revoked Identity document in arguments
class Revocation(Document):
"""
......
......@@ -4,7 +4,7 @@ Created on 2 déc. 2014
@author: inso
"""
import re
from .block_uid import BlockUID
from .document import Document, MalformedDocumentError
from ..constants import BLOCK_UID_REGEX, SIGNATURE_REGEX, PUBKEY_REGEX
......@@ -69,7 +69,6 @@ class Membership(Document):
@classmethod
def from_inline(cls, version, currency, membership_type, inline):
from .block import BlockUID
data = Membership.re_inline.match(inline)
if data is None:
raise MalformedDocumentError("Inline membership ({0})".format(inline))
......@@ -82,7 +81,6 @@ class Membership(Document):
@classmethod
def from_signed_raw(cls, signed_raw):
from .block import BlockUID
lines = signed_raw.splitlines(True)
n = 0
......
......@@ -2,7 +2,7 @@ import re
from duniterpy.api.endpoint import endpoint
from .document import Document
from . import BlockUID
from .block_uid import BlockUID
from ..constants import BLOCK_HASH_REGEX, PUBKEY_REGEX
......
import re
import pypeg2
from .block_uid import BlockUID
from .document import Document, MalformedDocumentError
from ..constants import PUBKEY_REGEX, TRANSACTION_HASH_REGEX, BLOCK_ID_REGEX, BLOCK_UID_REGEX
from ..grammars import output
......@@ -165,7 +165,6 @@ Comment: {comment}
@classmethod
def from_compact(cls, currency, compact):
from .block import BlockUID
lines = compact.splitlines(True)
n = 0
......@@ -231,7 +230,6 @@ Comment: {comment}
@classmethod
def from_signed_raw(cls, raw):
from .block import BlockUID
lines = raw.splitlines(True)
n = 0
......
......@@ -2,7 +2,7 @@ import re
import attr
from ..block import BlockUID
from ..block_uid import BlockUID
from ..document import MalformedDocumentError
from ...constants import WS2P_PUBLIC_PREFIX_REGEX, WS2P_PRIVATE_PREFIX_REGEX, WS2P_HEAD_REGEX, \
PUBKEY_REGEX, SIGNATURE_REGEX, WS2PID_REGEX, BLOCK_UID_REGEX
......
......@@ -5,7 +5,8 @@ Created on 12 déc. 2014
"""
import unittest
from duniterpy.documents.block import Block, BlockUID, block_uid
from duniterpy.documents.block import Block
from duniterpy.documents.block_uid import BlockUID, block_uid
raw_block = """Version: 2
Type: Block
......
......@@ -6,7 +6,8 @@ Created on 6 déc. 2014
import unittest
from duniterpy.documents.certification import Identity, Certification, Revocation
from duniterpy.documents import Block, BlockUID
from duniterpy.documents.block import Block, BlockUID
from duniterpy.constants import EMPTY_HASH
selfcert_inlines = ["HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk:\
h/H8tDIEbfA4yxMQcvfOXVDQhi1sUa9qYtPKrM59Bulv97ouwbAvAsEkC1Uyit1IOpeAV+CQQs4IaAyjE8F1Cw==:\
......@@ -73,7 +74,7 @@ J3G9oM5AKYZNLAB5Wx499w61NuUoS57JVccTShUbGpCMjCqj9yXXqNq7dyZpDWA6BxipsiaMZhujMeBf
self.assertEqual(cert.pubkey_from, "8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU")
self.assertEqual(cert.pubkey_to, "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk")
self.assertEqual(cert.timestamp.number, 0)
self.assertEqual(cert.timestamp.sha_hash, Block.Empty_Hash)
self.assertEqual(cert.timestamp.sha_hash, EMPTY_HASH)
self.assertEqual(cert.signatures[0], "TgmDuMxZdyutroj9jiLJA8tQp/389JIzDKuxW5+h7GIfjDu1ZbwI7HNm5rlUDhR2KreaV/QJjEaItT4Cf75rCQ==")
cert = Certification.from_inline(version, currency, "DB30D958EE5CB75186972286ED3F4686B8A1C2CD", cert_inlines[1])
......
......@@ -47,7 +47,7 @@ class Test_Membership(unittest.TestCase):
def test_fromraw_toraw(self):
membership = Membership.from_signed_raw(membership_raw)
rendered_membership = membership.signed_raw_for_certified()
rendered_membership = membership.signed_raw()
from_rendered_membership = Membership.from_signed_raw(rendered_membership)
self.assertEqual(from_rendered_membership.issuer, "HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk")
self.assertEqual(from_rendered_membership.membership_ts.number, 0)
......
......@@ -59,7 +59,7 @@ class TestPeer(unittest.TestCase):
def test_fromraw_toraw(self):
peer = Peer.from_signed_raw(rawpeer)
rendered_peer = peer.signed_raw_for_certified()
rendered_peer = peer.signed_raw()
from_rendered_peer = Peer.from_signed_raw(rendered_peer)
self.assertEqual(from_rendered_peer.currency, "beta_brousouf")
......@@ -87,9 +87,9 @@ class TestPeer(unittest.TestCase):
self.assertEqual(from_rendered_peer.signatures[0],
"dkaXIiCYUJtCg8Feh/BKvPYf4uFH9CJ/zY6J4MlA9BsjmcMe4YAblvNt/gJy31b1aGq3ue3h14mLMCu84rraDg==")
self.assertEqual(rawpeer, from_rendered_peer.signed_raw_for_certified())
self.assertEqual(rawpeer, from_rendered_peer.signed_raw())
def test_incorrect(self):
peer = Peer.from_signed_raw(test_weird_ipv6_peer)
rendered_peer = peer.signed_raw_for_certified()
rendered_peer = peer.signed_raw()
Peer.from_signed_raw(rendered_peer)
......@@ -299,7 +299,7 @@ class Test_Transaction(unittest.TestCase):
def test_fromraw_toraw(self):
tx = Transaction.from_signed_raw(tx_raw)
rendered_tx = tx.signed_raw_for_certified()
rendered_tx = tx.signed_raw()
from_rendered_tx = Transaction.from_signed_raw(rendered_tx)
self.assertEqual(tx.version, 2)
......@@ -366,7 +366,7 @@ class Test_Transaction(unittest.TestCase):
def test_fromraw_toraw_v3(self):
tx = Transaction.from_signed_raw(tx_raw_v3)
rendered_tx = tx.signed_raw_for_certified()
rendered_tx = tx.signed_raw()
from_rendered_tx = Transaction.from_signed_raw(rendered_tx)
self.assertEqual(tx.version, 3)
......@@ -435,7 +435,7 @@ class Test_Transaction(unittest.TestCase):
def test_compact_change(self):
tx = Transaction.from_compact("gtest", compact_change)
rendered_tx = tx.signed_raw_for_certified()
rendered_tx = tx.signed_raw()
from_rendered_tx = Transaction.from_signed_raw(rendered_tx)
def test_reduce_base(self):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment