mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
Added docstrings and tests to new methods
This commit is contained in:
parent
8c0dbeb281
commit
aacba571f8
@ -108,8 +108,8 @@ def create_votes_secondary_index(conn, dbname):
|
||||
def create_assets_secondary_index(conn, dbname):
|
||||
logger.info('Create `assets` secondary index.')
|
||||
|
||||
# is the first index redundant then?
|
||||
# compound index to order votes by block id and node
|
||||
# unique index on the id of the asset.
|
||||
# the id is the txid of the transaction that created the asset
|
||||
conn.conn[dbname]['assets'].create_index('id',
|
||||
name='asset_id',
|
||||
unique=True)
|
||||
|
@ -213,13 +213,28 @@ def get_block(connection, block_id):
|
||||
|
||||
@singledispatch
|
||||
def write_assets(connection, assets):
|
||||
# TODO: write docstring
|
||||
"""Write a list of assets to the assets table.
|
||||
|
||||
Args:
|
||||
assets (list): a list of assets to write.
|
||||
|
||||
Returns:
|
||||
The database response.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
@singledispatch
|
||||
def get_assets(connection, assets):
|
||||
# TODO: write docstring
|
||||
def get_assets(connection, asset_ids):
|
||||
"""Get a list of assets from the assets table.
|
||||
|
||||
Args:
|
||||
asset_ids (list): a of list of ids for the assets to be retrieved from
|
||||
the database.
|
||||
|
||||
Returns:
|
||||
assets (list): the list of returned assets.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
|
@ -315,13 +315,33 @@ class Block(object):
|
||||
|
||||
@classmethod
|
||||
def from_db(cls, bigchain, block_dict):
|
||||
"""
|
||||
Helper method that reconstructs a block_dict that was returned from
|
||||
the database. If checks what asset_ids to retrieve, retrieves the
|
||||
assets from the assets table and reconstructs the block.
|
||||
|
||||
Args:
|
||||
bigchain (:class:`~bigchaindb.Bigchain`): An instance of Bigchain
|
||||
used to perform database queries.
|
||||
|
||||
Returns:
|
||||
:class:`~Block`
|
||||
|
||||
"""
|
||||
asset_ids = cls.get_asset_ids(block_dict)
|
||||
assets = bigchain.get_assets(asset_ids)
|
||||
block_dict = cls.couple_assets(block_dict, assets)
|
||||
return cls.from_dict(block_dict)
|
||||
|
||||
def decouple_assets(self):
|
||||
# TODO: Write documentation
|
||||
"""
|
||||
Extracts the assets from the `CREATE` transactions in the block.
|
||||
|
||||
Returns:
|
||||
tuple: (assets, block) with the assets being a list of dicts and
|
||||
the block being the dict of the block with no assets in the CREATE
|
||||
transactions.
|
||||
"""
|
||||
block_dict = deepcopy(self.to_dict())
|
||||
assets = []
|
||||
for transaction in block_dict['block']['transactions']:
|
||||
@ -335,7 +355,20 @@ class Block(object):
|
||||
|
||||
@staticmethod
|
||||
def couple_assets(block_dict, assets):
|
||||
# TODO: Write docstring
|
||||
"""
|
||||
Give a block_dict with not assets (as returned from a database call)
|
||||
and a list of assets, reconstruct the original block by puting the
|
||||
assets back into the `CREATE` transactions in the block.
|
||||
|
||||
Args:
|
||||
block_dict (:obj:`dict`): The block dict as returned from a
|
||||
database call.
|
||||
assets (:obj:`list` of :obj:`dict`): A list of assets returned from
|
||||
a database call.
|
||||
|
||||
Returns:
|
||||
dict: The dict of the reconstructed block.
|
||||
"""
|
||||
# create a dict with {'<txid>': asset}
|
||||
assets = {asset.pop('id'): asset for asset in assets}
|
||||
# add the assets to the block transactions
|
||||
@ -348,7 +381,19 @@ class Block(object):
|
||||
|
||||
@staticmethod
|
||||
def get_asset_ids(block_dict):
|
||||
# TODO: Write docstring
|
||||
"""
|
||||
Given a block_dict return all the asset_ids for that block (the txid
|
||||
of CREATE transactions). Usefull to know which assets to retrieve
|
||||
from the database to reconstruct the block.
|
||||
|
||||
Args:
|
||||
block_dict (:obj:`dict`): The block dict as returned from a
|
||||
database call.
|
||||
|
||||
Returns:
|
||||
list: The list of asset_ids in the block.
|
||||
|
||||
"""
|
||||
asset_ids = []
|
||||
for transaction in block_dict['block']['transactions']:
|
||||
if transaction['operation'] in [Transaction.CREATE,
|
||||
|
@ -1,4 +1,7 @@
|
||||
from copy import deepcopy
|
||||
|
||||
import pytest
|
||||
import pymongo
|
||||
|
||||
pytestmark = pytest.mark.bdb
|
||||
|
||||
@ -418,3 +421,46 @@ def test_get_txids_filtered(signed_create_tx, signed_transfer_tx):
|
||||
# Test get by asset and TRANSFER
|
||||
txids = set(query.get_txids_filtered(conn, asset_id, Transaction.TRANSFER))
|
||||
assert txids == {signed_transfer_tx.id}
|
||||
|
||||
|
||||
def test_write_assets():
|
||||
from bigchaindb.backend import connect, query
|
||||
conn = connect()
|
||||
|
||||
assets = [
|
||||
{'id': 1, 'data': '1'},
|
||||
{'id': 2, 'data': '2'},
|
||||
{'id': 3, 'data': '3'},
|
||||
# Duplicated id. Should not be written to the database
|
||||
{'id': 1, 'data': '1'},
|
||||
]
|
||||
|
||||
# write the assets
|
||||
query.write_assets(conn, deepcopy(assets))
|
||||
|
||||
# check that 3 assets were written to the database
|
||||
cursor = conn.db.assets.find({}, projection={'_id': False})\
|
||||
.sort('id', pymongo.ASCENDING)
|
||||
|
||||
assert cursor.count() == 3
|
||||
assert list(cursor) == assets[:-1]
|
||||
|
||||
|
||||
def test_get_assets():
|
||||
from bigchaindb.backend import connect, query
|
||||
conn = connect()
|
||||
|
||||
assets = [
|
||||
{'id': 1, 'data': '1'},
|
||||
{'id': 2, 'data': '2'},
|
||||
{'id': 3, 'data': '3'},
|
||||
]
|
||||
|
||||
# write the assets
|
||||
conn.db.assets.insert_many(deepcopy(assets), ordered=False)
|
||||
|
||||
# read only 2 assets
|
||||
cursor = query.get_assets(conn, [1, 3])
|
||||
|
||||
assert cursor.count() == 2
|
||||
assert list(cursor.sort('id', pymongo.ASCENDING)) == assets[::2]
|
||||
|
@ -153,3 +153,136 @@ class TestBlockModel(object):
|
||||
block = b.create_block([tx, tx])
|
||||
with raises(DuplicateTransaction):
|
||||
block._validate_block(b)
|
||||
|
||||
def test_decouple_assets(self, b):
|
||||
from bigchaindb.models import Block, Transaction
|
||||
|
||||
assets = [
|
||||
{'msg': '1'},
|
||||
{'msg': '2'},
|
||||
{'msg': '3'},
|
||||
]
|
||||
|
||||
txs = []
|
||||
# create 3 assets
|
||||
for asset in assets:
|
||||
tx = Transaction.create([b.me], [([b.me], 1)], asset=asset)
|
||||
txs.append(tx)
|
||||
|
||||
# create a `TRANSFER` transaction.
|
||||
# the asset in `TRANSFER` transactions is not extracted
|
||||
tx = Transaction.transfer(txs[0].to_inputs(), [([b.me], 1)],
|
||||
asset_id=txs[0].id)
|
||||
txs.append(tx)
|
||||
|
||||
# create the block
|
||||
block = Block(txs)
|
||||
# decouple assets
|
||||
assets_from_block, block_dict = block.decouple_assets()
|
||||
|
||||
assert len(assets_from_block) == 3
|
||||
for i in range(3):
|
||||
assert assets_from_block[i]['data'] == assets[i]
|
||||
assert assets_from_block[i]['id'] == txs[i].id
|
||||
|
||||
# check the `TRANSFER` transaction was not changed
|
||||
assert block.transactions[3].to_dict() == \
|
||||
block_dict['block']['transactions'][3]
|
||||
|
||||
def test_couple_assets(self, b):
|
||||
from bigchaindb.models import Block, Transaction
|
||||
|
||||
assets = [
|
||||
{'msg': '1'},
|
||||
{'msg': '2'},
|
||||
{'msg': '3'},
|
||||
]
|
||||
|
||||
txs = []
|
||||
# create 3 assets
|
||||
for asset in assets:
|
||||
tx = Transaction.create([b.me], [([b.me], 1)], asset=asset)
|
||||
txs.append(tx)
|
||||
|
||||
# create a `TRANSFER` transaction.
|
||||
# the asset in `TRANSFER` transactions is not extracted
|
||||
tx = Transaction.transfer(txs[0].to_inputs(), [([b.me], 1)],
|
||||
asset_id=txs[0].id)
|
||||
txs.append(tx)
|
||||
|
||||
# create the block
|
||||
block = Block(txs)
|
||||
# decouple assets
|
||||
assets_from_block, block_dict = block.decouple_assets()
|
||||
|
||||
# reconstruct the block
|
||||
block_dict_reconstructed = Block.couple_assets(block_dict,
|
||||
assets_from_block)
|
||||
|
||||
# check that the reconstructed block is the as the original block
|
||||
assert block == Block.from_dict(block_dict_reconstructed)
|
||||
|
||||
def test_get_asset_ids(self, b):
|
||||
from bigchaindb.models import Block, Transaction
|
||||
|
||||
assets = [
|
||||
{'msg': '1'},
|
||||
{'msg': '2'},
|
||||
{'msg': '3'},
|
||||
]
|
||||
|
||||
txs = []
|
||||
# create 3 assets
|
||||
for asset in assets:
|
||||
tx = Transaction.create([b.me], [([b.me], 1)], asset=asset)
|
||||
txs.append(tx)
|
||||
|
||||
# create a `TRANSFER` transaction.
|
||||
# the asset in `TRANSFER` transactions is not extracted
|
||||
tx = Transaction.transfer(txs[0].to_inputs(), [([b.me], 1)],
|
||||
asset_id=txs[0].id)
|
||||
txs.append(tx)
|
||||
|
||||
# create the block
|
||||
block = Block(txs)
|
||||
# decouple assets
|
||||
assets_from_block, block_dict = block.decouple_assets()
|
||||
|
||||
# get the asset_ids and check that they are the same as the `CREATE`
|
||||
# transactions
|
||||
asset_ids = Block.get_asset_ids(block_dict)
|
||||
assert asset_ids == [tx.id for tx in txs[:-1]]
|
||||
|
||||
def test_from_db(self, b):
|
||||
from bigchaindb.models import Block, Transaction
|
||||
|
||||
assets = [
|
||||
{'msg': '1'},
|
||||
{'msg': '2'},
|
||||
{'msg': '3'},
|
||||
]
|
||||
|
||||
txs = []
|
||||
# create 3 assets
|
||||
for asset in assets:
|
||||
tx = Transaction.create([b.me], [([b.me], 1)], asset=asset)
|
||||
txs.append(tx)
|
||||
|
||||
# create a `TRANSFER` transaction.
|
||||
# the asset in `TRANSFER` transactions is not extracted
|
||||
tx = Transaction.transfer(txs[0].to_inputs(), [([b.me], 1)],
|
||||
asset_id=txs[0].id)
|
||||
txs.append(tx)
|
||||
|
||||
# create the block
|
||||
block = Block(txs)
|
||||
# decouple assets
|
||||
assets_from_block, block_dict = block.decouple_assets()
|
||||
|
||||
# write the assets and block separatedly
|
||||
b.write_assets(assets_from_block)
|
||||
b.write_block(block)
|
||||
|
||||
# check the reconstructed block is the same as the original block
|
||||
block_from_db = Block.from_db(b, block_dict)
|
||||
assert block == block_from_db
|
||||
|
Loading…
x
Reference in New Issue
Block a user