From 4ad3aa6b74a6120f94e408ce2f138feed42dd260 Mon Sep 17 00:00:00 2001 From: Luke Murphy Date: Wed, 7 Aug 2019 07:58:26 +0200 Subject: [PATCH] Finalise on naming and module imports --- README.rst | 13 +++++++ documentation/source/modules-api.rst | 5 ++- merkle_tree_stream/__init__.py | 6 +-- merkle_tree_stream/node.py | 31 +++++++++++++++ merkle_tree_stream/{generate.py => tree.py} | 43 +++++++-------------- test/{test_generate.py => test_tree.py} | 2 +- 6 files changed, 65 insertions(+), 35 deletions(-) create mode 100644 merkle_tree_stream/node.py rename merkle_tree_stream/{generate.py => tree.py} (75%) rename test/{test_generate.py => test_tree.py} (97%) diff --git a/README.rst b/README.rst index d08b8c8..01ec01b 100644 --- a/README.rst +++ b/README.rst @@ -48,6 +48,19 @@ See the following for more: .. _Merkle Tree: https://datprotocol.github.io/book/ch01-02-merkle-tree.html .. _Merkle Tree Stream: https://datprotocol.github.io/book/ch02-02-merkle-tree-stream.html +A note on naming +================ + +For the purposes of uniformity and easy of discovery alongside the reference +implementation, we use the same module name as `merkle-tree-stream`_. This may +cause confusion since it is not clear what exactly is referred to when using +the term "stream" in the context of Python. To be clear, this module provides a +`Python iterator`_ which appears to match the implementation and meaning of the +reference implementation. + +.. _merkle-tree-stream: https://github.com/mafintosh/merkle-tree-stream +.. _a Python Iterator: https://docs.python.org/3/c-api/iter.html + .. _documentation: Documentation diff --git a/documentation/source/modules-api.rst b/documentation/source/modules-api.rst index a3bffee..1f080e5 100644 --- a/documentation/source/modules-api.rst +++ b/documentation/source/modules-api.rst @@ -4,5 +4,8 @@ Modules API *********** -.. automodule:: merkle_tree_stream.generate +.. automodule:: merkle_tree_stream.iter + :members: + +.. automodule:: merkle_tree_stream.node :members: diff --git a/merkle_tree_stream/__init__.py b/merkle_tree_stream/__init__.py index 57b5331..a23b817 100644 --- a/merkle_tree_stream/__init__.py +++ b/merkle_tree_stream/__init__.py @@ -1,9 +1,7 @@ """merkle-tree-stream module.""" -from merkle_tree_stream.generate import ( # noqa - MerkleTreeIterator, - MerkleTreeNode, -) +from merkle_tree_stream.node import MerkleTreeNode # noqa +from merkle_tree_stream.tree import MerkleTreeIterator # noqa try: import pkg_resources diff --git a/merkle_tree_stream/node.py b/merkle_tree_stream/node.py new file mode 100644 index 0000000..192c92f --- /dev/null +++ b/merkle_tree_stream/node.py @@ -0,0 +1,31 @@ +"""A merkle tree node.""" + +from typing import Any, Optional + +import attr +from flat_tree import FlatTreeAccessor + +__all__ = ['MerkleTreeNode'] + + +@attr.s(auto_attribs=True) +class MerkleTreeNode: + """A node in a merkle tree. + + :param index: The index of node + :param parent: The parent of the node + :param size: The size of the data + :param data: The data of the node + :param hash: The hash of the data + """ + + index: int + parent: int + size: int + data: bytes + hash: Optional[str] = attr.Factory(str) + + def __attrs_post_init__(self) -> Any: + """Initialise the parent index.""" + flat_tree = FlatTreeAccessor() + self.parent = flat_tree.parent(self.index) diff --git a/merkle_tree_stream/generate.py b/merkle_tree_stream/tree.py similarity index 75% rename from merkle_tree_stream/generate.py rename to merkle_tree_stream/tree.py index 8a489cf..547d49e 100644 --- a/merkle_tree_stream/generate.py +++ b/merkle_tree_stream/tree.py @@ -1,42 +1,25 @@ -"""The merkle tree stream generator.""" +"""A merkle tree iterator.""" -from typing import Any, Callable, Iterator, List, Optional +from typing import Any, Callable, Iterator, List import attr from flat_tree import FlatTreeAccessor +from merkle_tree_stream.node import MerkleTreeNode + Hash = str -__all__ = ['MerkleTreeIterator', 'MerkleTreeNode'] +EMPTY_DATA = b'' +EMPTY_HASH = None + +__all__ = ['MerkleTreeIterator'] flat_tree = FlatTreeAccessor() -@attr.s(auto_attribs=True) -class MerkleTreeNode: - """A node in a merkle tree. - - :param index: The index of node - :param parent: The parent of the node - :param size: The size of the data - :param data: The data of the node - :param hash: The hash of the data - """ - - index: int - parent: int - size: int - data: bytes - hash: Optional[str] = None - - def __attrs_post_init__(self) -> Any: - """Initialise the parent index.""" - self.parent = flat_tree.parent(self.index) - - @attr.s(auto_attribs=True) class MerkleTreeIterator: - """A merkle tree iterator based on incoming data. + """A merkle tree iterator. :param leaf: The leaf hash generation function :param parent: The parent hash generation function @@ -83,8 +66,10 @@ class MerkleTreeIterator: """The number of nodes stored in the tree.""" return len(self._nodes) + # TODO(decentral1se): we need to take pass on async capability. Please see + # https://datprotocol.github.io/book/ch02-02-merkle-tree-stream.html#async def write(self, data: bytes): - """Write a new node to the tree. + """Write a new node to the tree and compute the new hashes. :param data: The new tree data """ @@ -95,7 +80,7 @@ class MerkleTreeIterator: leaf_node = MerkleTreeNode( index=index, parent=flat_tree.parent(index), - hash=None, + hash=EMPTY_HASH, data=data, size=len(data), ) @@ -118,7 +103,7 @@ class MerkleTreeIterator: parent=flat_tree.parent(left.parent), hash=self.parent(left, right), size=left.size + right.size, - data=b'', + data=EMPTY_DATA, ) self.roots[len(self.roots) - 1] = new_node diff --git a/test/test_generate.py b/test/test_tree.py similarity index 97% rename from test/test_generate.py rename to test/test_tree.py index e916bae..07cb231 100644 --- a/test/test_generate.py +++ b/test/test_tree.py @@ -1,4 +1,4 @@ -"""Merkle tree generation test module.""" +"""Merkle tree test module.""" import hashlib