diff --git a/docs/api.rst b/docs/api.rst
index 778db6a..d6eceac 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -9,7 +9,8 @@ These methods are "low level" and generally do not need to be called
directly.
For the full documentation of all the Core API calls, please refer
-to the `official documentation `__.
+to the `official documentation `__.
Extended API
============
diff --git a/docs/getting_started.rst b/docs/getting_started.rst
index 6da3a62..da254bc 100644
--- a/docs/getting_started.rst
+++ b/docs/getting_started.rst
@@ -1,6 +1,6 @@
Installation
============
-PyOTA is compatible with Python 3.6, 3.5 and 2.7.
+PyOTA is compatible with Python 3.7, 3.6, 3.5 and 2.7.
Install PyOTA using `pip`:
@@ -76,7 +76,7 @@ your API requests so that they contain the necessary authentication metadata.
)
.. _forum: https://forum.iota.org/
-.. _official api: https://iota.readme.io/
+.. _official api: https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference
.. _pyota-ccurl extension: https://pypi.python.org/pypi/PyOTA-CCurl
.. _run your own node.: http://iotasupport.com/headlessnode.shtml
.. _slack: http://slack.iota.org/
diff --git a/iota/api.py b/iota/api.py
index 7a31609..83aebb5 100644
--- a/iota/api.py
+++ b/iota/api.py
@@ -63,7 +63,7 @@ class StrictIota(object):
References:
- - https://iota.readme.io/docs/getting-started
+ - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference
"""
commands = discover_commands('iota.commands.core')
@@ -100,7 +100,7 @@ def __getattr__(self, command):
References:
- - https://iota.readme.io/docs/making-requests
+ - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference
"""
# Fix an error when invoking :py:func:`help`.
# https://github.com/iotaledger/iota.lib.py/issues/41
@@ -165,7 +165,7 @@ def add_neighbors(self, uris):
References:
- - https://iota.readme.io/docs/addneighors
+ - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#addneighbors
"""
return core.AddNeighborsCommand(self.adapter)(uris=uris)
@@ -190,7 +190,7 @@ def attach_to_tangle(
References:
- - https://iota.readme.io/docs/attachtotangle
+ - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#attachtotangle
"""
if min_weight_magnitude is None:
min_weight_magnitude = self.default_min_weight_magnitude
@@ -212,7 +212,7 @@ def broadcast_transactions(self, trytes):
References:
- - https://iota.readme.io/docs/broadcasttransactions
+ - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#broadcasttransactions
"""
return core.BroadcastTransactionsCommand(self.adapter)(trytes=trytes)
@@ -242,6 +242,10 @@ def check_consistency(self, tails):
This field will only exist set if ``state`` is
``False``.
}
+
+ References:
+
+ - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#checkconsistency
"""
return core.CheckConsistencyCommand(self.adapter)(
tails=tails,
@@ -280,7 +284,7 @@ def find_transactions(
References:
- - https://iota.readme.io/docs/findtransactions
+ - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#findtransactions
"""
return core.FindTransactionsCommand(self.adapter)(
bundles=bundles,
@@ -289,8 +293,13 @@ def find_transactions(
approvees=approvees,
)
- def get_balances(self, addresses, threshold=100):
- # type: (Iterable[Address], int) -> dict
+ def get_balances(
+ self,
+ addresses, # type: Iterable[Address]
+ threshold=100, # type: int
+ tips=None, # type: Optional[Iterable[TransactionHash]]
+ ):
+ # type: (...) -> dict
"""
Similar to :py:meth:`get_inclusion_states`. Returns the
confirmed balance which a list of addresses have at the latest
@@ -305,15 +314,19 @@ def get_balances(self, addresses, threshold=100):
List of addresses to get the confirmed balance for.
:param threshold:
- Confirmation threshold.
+ Confirmation threshold between 0 and 100.
+
+ :param tips:
+ Tips whose history of transactions to traverse to find the balance.
References:
- - https://iota.readme.io/docs/getbalances
+ - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#getbalances
"""
return core.GetBalancesCommand(self.adapter)(
addresses=addresses,
threshold=threshold,
+ tips=tips,
)
def get_inclusion_states(self, transactions, tips):
@@ -334,13 +347,25 @@ def get_inclusion_states(self, transactions, tips):
References:
- - https://iota.readme.io/docs/getinclusionstates
+ - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#getinclusionstates
"""
return core.GetInclusionStatesCommand(self.adapter)(
transactions=transactions,
tips=tips,
)
+ def get_missing_transactions(self):
+ # type: () -> dict
+ """
+ Returns all transaction hashes that a node is currently requesting
+ from its neighbors.
+
+ References:
+
+ - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#getmissingtransactions
+ """
+ return core.GetMissingTransactionsCommand(self.adapter)()
+
def get_neighbors(self):
# type: () -> dict
"""
@@ -351,10 +376,21 @@ def get_neighbors(self):
References:
- - https://iota.readme.io/docs/getneighborsactivity
+ - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#getneighbors
"""
return core.GetNeighborsCommand(self.adapter)()
+ def get_node_api_configuration(self):
+ # type: () -> dict
+ """
+ Returns a node's API configuration settings.
+
+ References:
+
+ - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#getnodeapiconfiguration
+ """
+ return core.GetNodeAPIConfigurationCommand(self.adapter)()
+
def get_node_info(self):
# type: () -> dict
"""
@@ -362,7 +398,7 @@ def get_node_info(self):
References:
- - https://iota.readme.io/docs/getnodeinfo
+ - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#getnodeinfo
"""
return core.GetNodeInfoCommand(self.adapter)()
@@ -374,13 +410,13 @@ def get_tips(self):
References:
- - https://iota.readme.io/docs/gettips
- - https://iota.readme.io/docs/glossary#iota-terms
+ - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#gettips
+ - https://docs.iota.org/docs/dev-essentials/0.1/references/glossary
"""
return core.GetTipsCommand(self.adapter)()
- def get_transactions_to_approve(self, depth):
- # type: (int) -> dict
+ def get_transactions_to_approve(self, depth, reference=None):
+ # type: (int, Optional[TransactionHash]) -> dict
"""
Tip selection which returns ``trunkTransaction`` and
``branchTransaction``.
@@ -393,11 +429,19 @@ def get_transactions_to_approve(self, depth):
will perform for the network (as it will confirm more
transactions that way).
+ :param reference:
+ Transaction hash from which to start the weighted random walk.
+ Use this parameter to make sure the returned tip transaction hashes
+ approve a given reference transaction.
+
References:
- - https://iota.readme.io/docs/gettransactionstoapprove
+ - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#gettransactionstoapprove
"""
- return core.GetTransactionsToApproveCommand(self.adapter)(depth=depth)
+ return core.GetTransactionsToApproveCommand(self.adapter)(
+ depth=depth,
+ reference=reference,
+ )
def get_trytes(self, hashes):
# type: (Iterable[TransactionHash]) -> dict
@@ -407,7 +451,7 @@ def get_trytes(self, hashes):
References:
- - https://iota.readme.io/docs/gettrytes
+ - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#gettrytes
"""
return core.GetTrytesCommand(self.adapter)(hashes=hashes)
@@ -419,7 +463,7 @@ def interrupt_attaching_to_tangle(self):
References:
- - https://iota.readme.io/docs/interruptattachingtotangle
+ - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#interruptattachingtotangle
"""
return core.InterruptAttachingToTangleCommand(self.adapter)()
@@ -435,7 +479,7 @@ def remove_neighbors(self, uris):
References:
- - https://iota.readme.io/docs/removeneighors
+ - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#removeneighbors
"""
return core.RemoveNeighborsCommand(self.adapter)(uris=uris)
@@ -449,7 +493,7 @@ def store_transactions(self, trytes):
References:
- - https://iota.readme.io/docs/storetransactions
+ - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#storetransactions
"""
return core.StoreTransactionsCommand(self.adapter)(trytes=trytes)
@@ -464,7 +508,7 @@ def were_addresses_spent_from(self, addresses):
References:
- - https://iota.readme.io/docs/wereaddressesspentfrom
+ - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#wereaddressesspentfrom
"""
return core.WereAddressesSpentFromCommand(self.adapter)(
addresses=addresses,
@@ -478,7 +522,7 @@ class Iota(StrictIota):
References:
- - https://iota.readme.io/docs/getting-started
+ - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference
- https://github.com/iotaledger/wiki/blob/master/api-proposal.md
"""
commands = discover_commands('iota.commands.extended')
diff --git a/iota/commands/core/__init__.py b/iota/commands/core/__init__.py
index 81f120a..64a9874 100644
--- a/iota/commands/core/__init__.py
+++ b/iota/commands/core/__init__.py
@@ -4,7 +4,7 @@
References:
-- https://iota.readme.io/docs/getting-started
+- https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference
"""
from __future__ import absolute_import, division, print_function, \
@@ -17,7 +17,9 @@
from .find_transactions import *
from .get_balances import *
from .get_inclusion_states import *
+from .get_missing_transactions import *
from .get_neighbors import *
+from .get_node_api_configuration import *
from .get_node_info import *
from .get_tips import *
from .get_transactions_to_approve import *
diff --git a/iota/commands/core/get_balances.py b/iota/commands/core/get_balances.py
index 423e9ca..f4caef8 100644
--- a/iota/commands/core/get_balances.py
+++ b/iota/commands/core/get_balances.py
@@ -3,8 +3,9 @@
unicode_literals
import filters as f
+from six import iteritems
-from iota import Address
+from iota import TransactionHash
from iota.commands import FilterCommand, RequestFilter, ResponseFilter
from iota.filters import AddressNoChecksum, Trytes
@@ -44,19 +45,47 @@ def __init__(self):
f.Min(0) |
f.Max(100) |
f.Optional(default=100),
+
+ 'tips':
+ f.Array | f.FilterRepeater(
+ f.Required |
+ Trytes(TransactionHash) |
+ f.Unicode(encoding='ascii', normalize=False),
+ )
},
allow_missing_keys={
- 'threshold',
+ 'threshold', 'tips',
},
)
+ def _apply(self, value):
+ value = super(GetBalancesRequestFilter, self)._apply(
+ value
+ ) # type: dict
+
+ if self._has_errors:
+ return value
+
+ # Remove null search terms.
+ # Note: We will assume that empty lists are intentional.
+ search_terms = {
+ term: query
+ for term, query in iteritems(value)
+ if query is not None
+ }
+
+ return search_terms
+
class GetBalancesResponseFilter(ResponseFilter):
def __init__(self):
super(GetBalancesResponseFilter, self).__init__({
'balances': f.Array | f.FilterRepeater(f.Int),
- 'milestone':
- f.ByteString(encoding='ascii') | Trytes(Address),
+ 'references':
+ f.Array | f.FilterRepeater(
+ f.ByteString(encoding='ascii') |
+ Trytes(TransactionHash)
+ ),
})
diff --git a/iota/commands/core/get_missing_transactions.py b/iota/commands/core/get_missing_transactions.py
new file mode 100644
index 0000000..c0d3ee4
--- /dev/null
+++ b/iota/commands/core/get_missing_transactions.py
@@ -0,0 +1,47 @@
+# coding=utf-8
+from __future__ import absolute_import, division, print_function, \
+ unicode_literals
+
+import filters as f
+
+from iota import TransactionHash
+from iota.commands import FilterCommand, RequestFilter, ResponseFilter
+from iota.filters import Trytes
+
+__all__ = [
+ 'GetMissingTransactionsCommand',
+]
+
+
+class GetMissingTransactionsCommand(FilterCommand):
+ """
+ Executes `getMissingTransactions` command.
+
+ See :py:meth:`iota.api.StrictIota.get_missing_transactions`.
+ """
+ command = 'getMissingTransactions'
+
+ def get_request_filter(self):
+ return GetMissingTransactionsRequestFilter()
+
+ def get_response_filter(self):
+ return GetMissingTransactionsResponseFilter()
+
+
+class GetMissingTransactionsRequestFilter(RequestFilter):
+ def __init__(self):
+ # ``getMissingTransactions`` does not accept any parameters.
+ # Using a filter here just to enforce that the request is empty.
+ super(GetMissingTransactionsRequestFilter, self).__init__({})
+
+
+class GetMissingTransactionsResponseFilter(ResponseFilter):
+ def __init__(self):
+ super(GetMissingTransactionsResponseFilter, self).__init__({
+ 'hashes':
+ f.FilterRepeater(
+ f.ByteString(encoding='ascii') |
+ Trytes(TransactionHash)
+ ) |
+ f.Optional(default=[]),
+ })
diff --git a/iota/commands/core/get_node_api_configuration.py b/iota/commands/core/get_node_api_configuration.py
new file mode 100644
index 0000000..acaf9a0
--- /dev/null
+++ b/iota/commands/core/get_node_api_configuration.py
@@ -0,0 +1,31 @@
+# coding=utf-8
+from __future__ import absolute_import, division, print_function, \
+ unicode_literals
+
+from iota.commands import FilterCommand, RequestFilter
+
+__all__ = [
+ 'GetNodeAPIConfigurationCommand',
+]
+
+
+class GetNodeAPIConfigurationCommand(FilterCommand):
+ """
+ Executes `getNodeAPIConfiguration` command.
+
+ See :py:meth:`iota.api.StrictIota.get_node_api_configuration`.
+ """
+ command = 'getNodeAPIConfiguration'
+
+ def get_request_filter(self):
+ return GetNodeAPIConfigurationRequestFilter()
+
+ def get_response_filter(self):
+ pass
+
+
+class GetNodeAPIConfigurationRequestFilter(RequestFilter):
+ def __init__(self):
+ # ``getNodeAPIConfiguration`` does not accept any parameters.
+ # Using a filter here just to enforce that the request is empty.
+ super(GetNodeAPIConfigurationRequestFilter, self).__init__({})
diff --git a/test/commands/core/check_consistency_test.py b/test/commands/core/check_consistency_test.py
index 3b684b5..028f39c 100644
--- a/test/commands/core/check_consistency_test.py
+++ b/test/commands/core/check_consistency_test.py
@@ -1,6 +1,6 @@
# coding=utf-8
from __future__ import absolute_import, division, print_function, \
- unicode_literals
+ unicode_literals
from unittest import TestCase
@@ -14,234 +14,234 @@
class CheckConsistencyRequestFilterTestCase(BaseFilterTestCase):
- filter_type = CheckConsistencyCommand(MockAdapter()).get_request_filter
- skip_value_check = True
-
- # noinspection SpellCheckingInspection
- def setUp(self):
- super(CheckConsistencyRequestFilterTestCase, self).setUp()
-
- self.hash1 = (
- 'TESTVALUE9DONTUSEINPRODUCTION99999DXSCAD'
- 'YBVDCTTBLHFYQATFZPYPCBG9FOUKIGMYIGLHM9NEZ'
- )
-
- self.hash2 = (
- 'TESTVALUE9DONTUSEINPRODUCTION99999EMFYSM'
- 'HWODIAPUTTFDLQRLYIDAUIPJXXEXZZSBVKZEBWGAN'
- )
-
- def test_pass_happy_path(self):
- """
- Request is valid.
- """
- request = {
- # Raw trytes are extracted to match the IRI's JSON protocol.
- 'tails': [self.hash1, self.hash2],
- }
-
- filter_ = self._filter(request)
-
- self.assertFilterPasses(filter_)
- self.assertDictEqual(filter_.cleaned_data, request)
-
- def test_pass_compatible_types(self):
- """
- Request contains values that can be converted to the expected
- types.
- """
- filter_ = self._filter({
- 'tails': [
- # Any TrytesCompatible value can be used here.
- TransactionHash(self.hash1),
- bytearray(self.hash2.encode('ascii')),
- ],
- })
-
- self.assertFilterPasses(filter_)
- self.assertDictEqual(
- filter_.cleaned_data,
-
- {
- # Raw trytes are extracted to match the IRI's JSON protocol.
- 'tails': [self.hash1, self.hash2],
- },
- )
-
- def test_fail_empty(self):
- """
- Request is empty.
- """
- self.assertFilterErrors(
- {},
-
- {
- 'tails': [f.FilterMapper.CODE_MISSING_KEY],
- },
- )
-
- def test_fail_unexpected_parameters(self):
- """
- Request contains unexpected parameters.
- """
- self.assertFilterErrors(
- {
- 'tails': [TransactionHash(self.hash1)],
- 'foo': 'bar',
- },
-
- {
- 'foo': [f.FilterMapper.CODE_EXTRA_KEY],
- },
- )
-
- def test_fail_tails_null(self):
- """
- ``tails`` is null.
- """
- self.assertFilterErrors(
- {
- 'tails': None,
- },
-
- {
- 'tails': [f.Required.CODE_EMPTY],
- },
- )
-
- def test_fail_tails_wrong_type(self):
- """
- ``tails`` is not an array.
- """
- self.assertFilterErrors(
- {
- # It's gotta be an array, even if there's only one hash.
- 'tails': TransactionHash(self.hash1),
- },
-
- {
- 'tails': [f.Type.CODE_WRONG_TYPE],
- },
- )
-
- def test_fail_tails_empty(self):
- """
- ``tails`` is an array, but it is empty.
- """
- self.assertFilterErrors(
- {
- 'tails': [],
- },
-
- {
- 'tails': [f.Required.CODE_EMPTY],
- },
- )
-
- def test_fail_tails_contents_invalid(self):
- """
- ``tails`` is a non-empty array, but it contains invalid values.
- """
- self.assertFilterErrors(
- {
- 'tails': [
- b'',
- True,
- None,
- b'not valid trytes',
-
- # This is actually valid; I just added it to make sure the
- # filter isn't cheating!
- TryteString(self.hash1),
-
- 2130706433,
- b'9' * 82,
- ],
- },
-
- {
- 'tails.0': [f.Required.CODE_EMPTY],
- 'tails.1': [f.Type.CODE_WRONG_TYPE],
- 'tails.2': [f.Required.CODE_EMPTY],
- 'tails.3': [Trytes.CODE_NOT_TRYTES],
- 'tails.5': [f.Type.CODE_WRONG_TYPE],
- 'tails.6': [Trytes.CODE_WRONG_FORMAT],
- },
- )
+ filter_type = CheckConsistencyCommand(MockAdapter()).get_request_filter
+ skip_value_check = True
+
+ # noinspection SpellCheckingInspection
+ def setUp(self):
+ super(CheckConsistencyRequestFilterTestCase, self).setUp()
+
+ self.hash1 = (
+ 'TESTVALUE9DONTUSEINPRODUCTION99999DXSCAD'
+ 'YBVDCTTBLHFYQATFZPYPCBG9FOUKIGMYIGLHM9NEZ'
+ )
+
+ self.hash2 = (
+ 'TESTVALUE9DONTUSEINPRODUCTION99999EMFYSM'
+ 'HWODIAPUTTFDLQRLYIDAUIPJXXEXZZSBVKZEBWGAN'
+ )
+
+ def test_pass_happy_path(self):
+ """
+ Request is valid.
+ """
+ request = {
+ # Raw trytes are extracted to match the IRI's JSON protocol.
+ 'tails': [self.hash1, self.hash2],
+ }
+
+ filter_ = self._filter(request)
+
+ self.assertFilterPasses(filter_)
+ self.assertDictEqual(filter_.cleaned_data, request)
+
+ def test_pass_compatible_types(self):
+ """
+ Request contains values that can be converted to the expected
+ types.
+ """
+ filter_ = self._filter({
+ 'tails': [
+ # Any TrytesCompatible value can be used here.
+ TransactionHash(self.hash1),
+ bytearray(self.hash2.encode('ascii')),
+ ],
+ })
+
+ self.assertFilterPasses(filter_)
+ self.assertDictEqual(
+ filter_.cleaned_data,
+
+ {
+ # Raw trytes are extracted to match the IRI's JSON protocol.
+ 'tails': [self.hash1, self.hash2],
+ },
+ )
+
+ def test_fail_empty(self):
+ """
+ Request is empty.
+ """
+ self.assertFilterErrors(
+ {},
+
+ {
+ 'tails': [f.FilterMapper.CODE_MISSING_KEY],
+ },
+ )
+
+ def test_fail_unexpected_parameters(self):
+ """
+ Request contains unexpected parameters.
+ """
+ self.assertFilterErrors(
+ {
+ 'tails': [TransactionHash(self.hash1)],
+ 'foo': 'bar',
+ },
+
+ {
+ 'foo': [f.FilterMapper.CODE_EXTRA_KEY],
+ },
+ )
+
+ def test_fail_tails_null(self):
+ """
+ ``tails`` is null.
+ """
+ self.assertFilterErrors(
+ {
+ 'tails': None,
+ },
+
+ {
+ 'tails': [f.Required.CODE_EMPTY],
+ },
+ )
+
+ def test_fail_tails_wrong_type(self):
+ """
+ ``tails`` is not an array.
+ """
+ self.assertFilterErrors(
+ {
+ # It's gotta be an array, even if there's only one hash.
+ 'tails': TransactionHash(self.hash1),
+ },
+
+ {
+ 'tails': [f.Type.CODE_WRONG_TYPE],
+ },
+ )
+
+ def test_fail_tails_empty(self):
+ """
+ ``tails`` is an array, but it is empty.
+ """
+ self.assertFilterErrors(
+ {
+ 'tails': [],
+ },
+
+ {
+ 'tails': [f.Required.CODE_EMPTY],
+ },
+ )
+
+ def test_fail_tails_contents_invalid(self):
+ """
+ ``tails`` is a non-empty array, but it contains invalid values.
+ """
+ self.assertFilterErrors(
+ {
+ 'tails': [
+ b'',
+ True,
+ None,
+ b'not valid trytes',
+
+ # This is actually valid; I just added it to make sure the
+ # filter isn't cheating!
+ TryteString(self.hash1),
+
+ 2130706433,
+ b'9' * 82,
+ ],
+ },
+
+ {
+ 'tails.0': [f.Required.CODE_EMPTY],
+ 'tails.1': [f.Type.CODE_WRONG_TYPE],
+ 'tails.2': [f.Required.CODE_EMPTY],
+ 'tails.3': [Trytes.CODE_NOT_TRYTES],
+ 'tails.5': [f.Type.CODE_WRONG_TYPE],
+ 'tails.6': [Trytes.CODE_WRONG_FORMAT],
+ },
+ )
class CheckConsistencyCommandTestCase(TestCase):
- # noinspection SpellCheckingInspection
- def setUp(self):
- super(CheckConsistencyCommandTestCase, self).setUp()
-
- self.adapter = MockAdapter()
- self.command = CheckConsistencyCommand(self.adapter)
-
- # Define some tryte sequences that we can re-use across tests.
- self.milestone =\
- TransactionHash(
- b'TESTVALUE9DONTUSEINPRODUCTION99999W9KDIH'
- b'BALAYAFCADIDU9HCXDKIXEYDNFRAKHN9IEIDZFWGJ'
- )
-
- self.hash1 =\
- TransactionHash(
- b'TESTVALUE9DONTUSEINPRODUCTION99999TBPDM9'
- b'ADFAWCKCSFUALFGETFIFG9UHIEFE9AYESEHDUBDDF'
- )
-
- self.hash2 =\
- TransactionHash(
- b'TESTVALUE9DONTUSEINPRODUCTION99999CIGCCF'
- b'KIUFZF9EP9YEYGQAIEXDTEAAUGAEWBBASHYCWBHDX'
- )
-
- def test_wireup(self):
- """
- Verify that the command is wired up correctly.
- """
- self.assertIsInstance(
- Iota(self.adapter).checkConsistency,
- CheckConsistencyCommand,
- )
-
- def test_happy_path(self):
- """
- Successfully checking consistency.
- """
-
- self.adapter.seed_response('checkConsistency', {
- 'state': True,
- })
-
- response = self.command(tails=[self.hash1, self.hash2])
-
- self.assertDictEqual(
- response,
-
- {
- 'state': True,
- }
- )
-
- def test_info_with_false_state(self):
- """
- `info` field exists when `state` is False.
- """
-
- self.adapter.seed_response('checkConsistency', {
- 'state': False,
- 'info': 'Additional information',
- })
-
- response = self.command(tails=[self.hash1, self.hash2])
-
- self.assertDictEqual(
- response,
-
- {
- 'state': False,
- 'info': 'Additional information',
- }
- )
+ # noinspection SpellCheckingInspection
+ def setUp(self):
+ super(CheckConsistencyCommandTestCase, self).setUp()
+
+ self.adapter = MockAdapter()
+ self.command = CheckConsistencyCommand(self.adapter)
+
+ # Define some tryte sequences that we can re-use across tests.
+ self.milestone = \
+ TransactionHash(
+ b'TESTVALUE9DONTUSEINPRODUCTION99999W9KDIH'
+ b'BALAYAFCADIDU9HCXDKIXEYDNFRAKHN9IEIDZFWGJ'
+ )
+
+ self.hash1 = \
+ TransactionHash(
+ b'TESTVALUE9DONTUSEINPRODUCTION99999TBPDM9'
+ b'ADFAWCKCSFUALFGETFIFG9UHIEFE9AYESEHDUBDDF'
+ )
+
+ self.hash2 = \
+ TransactionHash(
+ b'TESTVALUE9DONTUSEINPRODUCTION99999CIGCCF'
+ b'KIUFZF9EP9YEYGQAIEXDTEAAUGAEWBBASHYCWBHDX'
+ )
+
+ def test_wireup(self):
+ """
+ Verify that the command is wired up correctly.
+ """
+ self.assertIsInstance(
+ Iota(self.adapter).checkConsistency,
+ CheckConsistencyCommand,
+ )
+
+ def test_happy_path(self):
+ """
+ Successfully checking consistency.
+ """
+
+ self.adapter.seed_response('checkConsistency', {
+ 'state': True,
+ })
+
+ response = self.command(tails=[self.hash1, self.hash2])
+
+ self.assertDictEqual(
+ response,
+
+ {
+ 'state': True,
+ }
+ )
+
+ def test_info_with_false_state(self):
+ """
+ `info` field exists when `state` is False.
+ """
+
+ self.adapter.seed_response('checkConsistency', {
+ 'state': False,
+ 'info': 'Additional information',
+ })
+
+ response = self.command(tails=[self.hash1, self.hash2])
+
+ self.assertDictEqual(
+ response,
+
+ {
+ 'state': False,
+ 'info': 'Additional information',
+ }
+ )
diff --git a/test/commands/core/get_balances_test.py b/test/commands/core/get_balances_test.py
index 01245bd..4f9ecc8 100644
--- a/test/commands/core/get_balances_test.py
+++ b/test/commands/core/get_balances_test.py
@@ -1,6 +1,6 @@
# coding=utf-8
from __future__ import absolute_import, division, print_function, \
- unicode_literals
+ unicode_literals
from unittest import TestCase
@@ -14,290 +14,345 @@
class GetBalancesRequestFilterTestCase(BaseFilterTestCase):
- filter_type = GetBalancesCommand(MockAdapter()).get_request_filter
- skip_value_check = True
-
- # noinspection SpellCheckingInspection
- def setUp(self):
- super(GetBalancesRequestFilterTestCase, self).setUp()
-
- # Define a few valid values that we can reuse across tests.
- self.trytes1 = (
- 'TESTVALUE9DONTUSEINPRODUCTION99999EKJZZT'
- 'SOGJOUNVEWLDPKGTGAOIZIPMGBLHC9LMQNHLGXGYX'
- )
-
- self.trytes2 = (
- 'TESTVALUE9DONTUSEINPRODUCTION99999FDCDTZ'
- 'ZWLL9MYGUTLSYVSIFJ9NGALTRMCQVIIOVEQOITYTE'
- )
-
- def test_pass_happy_path(self):
- """
- Typical invocation of ``getBalances``.
- """
- request = {
- # Raw trytes are extracted to match the IRI's JSON protocol.
- 'addresses': [self.trytes1, self.trytes2],
-
- 'threshold': 80,
- }
-
- filter_ = self._filter(request)
-
- self.assertFilterPasses(filter_)
- self.assertDictEqual(filter_.cleaned_data, request)
-
- def test_pass_compatible_types(self):
- """
- The incoming request contains values that can be converted to the
- expected types.
- """
- request = {
- 'addresses': [
- Address(self.trytes1),
- bytearray(self.trytes2.encode('ascii')),
- ],
-
- 'threshold': 80,
- }
-
- filter_ = self._filter(request)
-
- self.assertFilterPasses(filter_)
- self.assertDictEqual(
- filter_.cleaned_data,
-
- {
- 'addresses': [self.trytes1, self.trytes2],
- 'threshold': 80,
- },
- )
-
- def test_pass_threshold_optional(self):
- """
- The incoming request does not contain a ``threshold`` value, so the
- default value is assumed.
- """
- request = {
- 'addresses': [Address(self.trytes1)],
- }
-
- filter_ = self._filter(request)
-
- self.assertFilterPasses(filter_)
- self.assertDictEqual(
- filter_.cleaned_data,
-
- {
- 'addresses': [Address(self.trytes1)],
- 'threshold': 100,
- },
- )
-
- def test_fail_empty(self):
- """
- The incoming request is empty.
- """
- self.assertFilterErrors(
- {},
-
- {
- 'addresses': [f.FilterMapper.CODE_MISSING_KEY],
- },
- )
-
- def test_fail_unexpected_parameters(self):
- """
- The incoming request contains unexpected parameters.
- """
- self.assertFilterErrors(
- {
- 'addresses': [Address(self.trytes1)],
-
- # I've had a perfectly wonderful evening.
- # But this wasn't it.
- 'foo': 'bar',
- },
-
- {
- 'foo': [f.FilterMapper.CODE_EXTRA_KEY],
- },
- )
-
- def test_fail_addresses_wrong_type(self):
- """
- ``addresses`` is not an array.
- """
- self.assertFilterErrors(
- {
- 'addresses': Address(self.trytes1),
- },
-
- {
- 'addresses': [f.Type.CODE_WRONG_TYPE],
- },
- )
-
- def test_fail_addresses_empty(self):
- """
- ``addresses`` is an array, but it's empty.
- """
- self.assertFilterErrors(
- {
- 'addresses': [],
- },
-
- {
- 'addresses': [f.Required.CODE_EMPTY],
- },
- )
-
- def test_fail_addresses_contents_invalid(self):
- """
- ``addresses`` is an array, but it contains invalid values.
- """
- self.assertFilterErrors(
- {
- 'addresses': [
- b'',
- True,
- None,
- b'not valid trytes',
-
- # This is actually valid; I just added it to make sure the
- # filter isn't cheating!
- TryteString(self.trytes2),
-
- 2130706433,
- b'9' * 82,
- ],
- },
-
- {
- 'addresses.0': [f.Required.CODE_EMPTY],
- 'addresses.1': [f.Type.CODE_WRONG_TYPE],
- 'addresses.2': [f.Required.CODE_EMPTY],
- 'addresses.3': [Trytes.CODE_NOT_TRYTES],
- 'addresses.5': [f.Type.CODE_WRONG_TYPE],
- 'addresses.6': [Trytes.CODE_WRONG_FORMAT],
- },
- )
-
- def test_fail_threshold_float(self):
- """
- `threshold` is a float.
- """
- self.assertFilterErrors(
- {
- # Even with an empty fpart, floats are not accepted.
- 'threshold': 86.0,
-
- 'addresses': [Address(self.trytes1)],
- },
-
- {
- 'threshold': [f.Type.CODE_WRONG_TYPE],
- },
- )
-
- def test_fail_threshold_string(self):
- """
- ``threshold`` is a string.
- """
- self.assertFilterErrors(
- {
- 'threshold': '86',
-
- 'addresses': [Address(self.trytes1)],
- },
-
- {
- 'threshold': [f.Type.CODE_WRONG_TYPE],
- },
- )
-
- def test_fail_threshold_too_small(self):
- """
- ``threshold`` is less than 0.
- """
- self.assertFilterErrors(
- {
- 'threshold': -1,
-
- 'addresses': [Address(self.trytes1)],
- },
-
- {
- 'threshold': [f.Min.CODE_TOO_SMALL],
- },
- )
-
- def test_fail_threshold_too_big(self):
- """
- ``threshold`` is greater than 100.
- """
- self.assertFilterErrors(
- {
- 'threshold': 101,
-
- 'addresses': [Address(self.trytes1)],
- },
-
- {
- 'threshold': [f.Max.CODE_TOO_BIG],
- },
- )
+ filter_type = GetBalancesCommand(MockAdapter()).get_request_filter
+ skip_value_check = True
+
+ # noinspection SpellCheckingInspection
+ def setUp(self):
+ super(GetBalancesRequestFilterTestCase, self).setUp()
+
+ # Define a few valid values that we can reuse across tests.
+ self.trytes1 = (
+ 'TESTVALUE9DONTUSEINPRODUCTION99999EKJZZT'
+ 'SOGJOUNVEWLDPKGTGAOIZIPMGBLHC9LMQNHLGXGYX'
+ )
+
+ self.trytes2 = (
+ 'TESTVALUE9DONTUSEINPRODUCTION99999FDCDTZ'
+ 'ZWLL9MYGUTLSYVSIFJ9NGALTRMCQVIIOVEQOITYTE'
+ )
+
+ self.trytes3 = (
+ 'TESTVALUE9DONTUSEINPRODUCTION99999FDCDTZ'
+ 'ASKDFJWOEFJSKLDJFWEIOFFJSKDJFWIOEFJSKDF9E'
+ )
+
+ def test_pass_happy_path(self):
+ """
+ Typical invocation of ``getBalances``.
+ """
+ request = {
+ # Raw trytes are extracted to match the IRI's JSON protocol.
+ 'addresses': [self.trytes1, self.trytes2],
+
+ 'threshold': 80,
+ }
+
+ filter_ = self._filter(request)
+
+ self.assertFilterPasses(filter_)
+ self.assertDictEqual(filter_.cleaned_data, request)
+
+ def test_pass_happy_path_with_tips(self):
+ """
+ Typical invocation of ``getBalances`` with tips.
+ """
+ request = {
+ 'addresses': [self.trytes1, self.trytes2],
+
+ 'threshold': 80,
+
+ 'tips': [self.trytes3],
+ }
+
+ filter_ = self._filter(request)
+
+ self.assertFilterPasses(filter_)
+ self.assertDictEqual(filter_.cleaned_data, request)
+
+ def test_pass_compatible_types(self):
+ """
+ The incoming request contains values that can be converted to the
+ expected types.
+ """
+ request = {
+ 'addresses': [
+ Address(self.trytes1),
+ bytearray(self.trytes2.encode('ascii')),
+ ],
+
+ 'threshold': 80,
+ }
+
+ filter_ = self._filter(request)
+
+ self.assertFilterPasses(filter_)
+ self.assertDictEqual(
+ filter_.cleaned_data,
+
+ {
+ 'addresses': [self.trytes1, self.trytes2],
+ 'threshold': 80,
+ },
+ )
+
+ def test_pass_threshold_optional(self):
+ """
+ The incoming request does not contain a ``threshold`` value, so the
+ default value is assumed.
+ """
+ request = {
+ 'addresses': [Address(self.trytes1)],
+ }
+
+ filter_ = self._filter(request)
+
+ self.assertFilterPasses(filter_)
+ self.assertDictEqual(
+ filter_.cleaned_data,
+
+ {
+ 'addresses': [Address(self.trytes1)],
+ 'threshold': 100,
+ },
+ )
+
+ def test_fail_empty(self):
+ """
+ The incoming request is empty.
+ """
+ self.assertFilterErrors(
+ {},
+
+ {
+ 'addresses': [f.FilterMapper.CODE_MISSING_KEY],
+ },
+ )
+
+ def test_fail_unexpected_parameters(self):
+ """
+ The incoming request contains unexpected parameters.
+ """
+ self.assertFilterErrors(
+ {
+ 'addresses': [Address(self.trytes1)],
+
+ # I've had a perfectly wonderful evening.
+ # But this wasn't it.
+ 'foo': 'bar',
+ },
+
+ {
+ 'foo': [f.FilterMapper.CODE_EXTRA_KEY],
+ },
+ )
+
+ def test_fail_addresses_wrong_type(self):
+ """
+ ``addresses`` is not an array.
+ """
+ self.assertFilterErrors(
+ {
+ 'addresses': Address(self.trytes1),
+ },
+
+ {
+ 'addresses': [f.Type.CODE_WRONG_TYPE],
+ },
+ )
+
+ def test_fail_addresses_empty(self):
+ """
+ ``addresses`` is an array, but it's empty.
+ """
+ self.assertFilterErrors(
+ {
+ 'addresses': [],
+ },
+
+ {
+ 'addresses': [f.Required.CODE_EMPTY],
+ },
+ )
+
+ def test_fail_addresses_contents_invalid(self):
+ """
+ ``addresses`` is an array, but it contains invalid values.
+ """
+ self.assertFilterErrors(
+ {
+ 'addresses': [
+ b'',
+ True,
+ None,
+ b'not valid trytes',
+
+ # This is actually valid; I just added it to make sure the
+ # filter isn't cheating!
+ TryteString(self.trytes2),
+
+ 2130706433,
+ b'9' * 82,
+ ],
+ },
+
+ {
+ 'addresses.0': [f.Required.CODE_EMPTY],
+ 'addresses.1': [f.Type.CODE_WRONG_TYPE],
+ 'addresses.2': [f.Required.CODE_EMPTY],
+ 'addresses.3': [Trytes.CODE_NOT_TRYTES],
+ 'addresses.5': [f.Type.CODE_WRONG_TYPE],
+ 'addresses.6': [Trytes.CODE_WRONG_FORMAT],
+ },
+ )
+
+ def test_fail_threshold_float(self):
+ """
+ `threshold` is a float.
+ """
+ self.assertFilterErrors(
+ {
+ # Even with an empty fpart, floats are not accepted.
+ 'threshold': 86.0,
+
+ 'addresses': [Address(self.trytes1)],
+ },
+
+ {
+ 'threshold': [f.Type.CODE_WRONG_TYPE],
+ },
+ )
+
+ def test_fail_threshold_string(self):
+ """
+ ``threshold`` is a string.
+ """
+ self.assertFilterErrors(
+ {
+ 'threshold': '86',
+
+ 'addresses': [Address(self.trytes1)],
+ },
+
+ {
+ 'threshold': [f.Type.CODE_WRONG_TYPE],
+ },
+ )
+
+ def test_fail_threshold_too_small(self):
+ """
+ ``threshold`` is less than 0.
+ """
+ self.assertFilterErrors(
+ {
+ 'threshold': -1,
+
+ 'addresses': [Address(self.trytes1)],
+ },
+
+ {
+ 'threshold': [f.Min.CODE_TOO_SMALL],
+ },
+ )
+
+ def test_fail_threshold_too_big(self):
+ """
+ ``threshold`` is greater than 100.
+ """
+ self.assertFilterErrors(
+ {
+ 'threshold': 101,
+
+ 'addresses': [Address(self.trytes1)],
+ },
+
+ {
+ 'threshold': [f.Max.CODE_TOO_BIG],
+ },
+ )
+
+ def test_fail_tips_contents_invalid(self):
+ """
+ ``tips`` is an array, but it contains invalid values.
+ """
+ self.assertFilterErrors(
+ {
+ 'addresses': [self.trytes1],
+ 'tips': [
+ b'',
+ True,
+ None,
+ b'not valid trytes',
+
+ # This is actually valid; I just added it to make sure the
+ # filter isn't cheating!
+ TryteString(self.trytes2),
+
+ 2130706433,
+ b'9' * 82,
+ ],
+ },
+
+ {
+ 'tips.0': [f.Required.CODE_EMPTY],
+ 'tips.1': [f.Type.CODE_WRONG_TYPE],
+ 'tips.2': [f.Required.CODE_EMPTY],
+ 'tips.3': [Trytes.CODE_NOT_TRYTES],
+ 'tips.5': [f.Type.CODE_WRONG_TYPE],
+ 'tips.6': [Trytes.CODE_WRONG_FORMAT],
+ },
+ )
# noinspection SpellCheckingInspection
class GetBalancesResponseFilterTestCase(BaseFilterTestCase):
- filter_type = GetBalancesCommand(MockAdapter()).get_response_filter
- skip_value_check = True
-
- def test_balances(self):
- """
- Typical ``getBalances`` response.
- """
- filter_ = self._filter({
- 'balances': ['114544444', '0', '8175737'],
- 'duration': 42,
- 'milestoneIndex': 128,
-
- 'milestone':
- 'INRTUYSZCWBHGFGGXXPWRWBZACYAFGVRRP9VYEQJ'
- 'OHYD9URMELKWAFYFMNTSP9MCHLXRGAFMBOZPZ9999',
- })
-
- self.assertFilterPasses(filter_)
- self.assertDictEqual(
- filter_.cleaned_data,
-
- {
- 'balances': [114544444, 0, 8175737],
- 'duration': 42,
- 'milestoneIndex': 128,
-
- 'milestone':
- Address(
- b'INRTUYSZCWBHGFGGXXPWRWBZACYAFGVRRP9VYEQJ'
- b'OHYD9URMELKWAFYFMNTSP9MCHLXRGAFMBOZPZ9999',
- ),
- },
- )
+ filter_type = GetBalancesCommand(MockAdapter()).get_response_filter
+ skip_value_check = True
+
+ def setUp(self):
+ super(GetBalancesResponseFilterTestCase, self).setUp()
+
+ # Define a few valid values that we can reuse across tests.
+ self.trytes1 = (
+ 'TESTVALUE9DONTUSEINPRODUCTION99999EKJZZT'
+ 'SOGJOUNVEWLDPKGTGAOIZIPMGBLHC9LMQNHLGXGYX'
+ )
+
+ def test_balances(self):
+ """
+ Typical ``getBalances`` response.
+ """
+ filter_ = self._filter({
+ 'balances': ['114544444', '0', '8175737'],
+ 'duration': 42,
+ 'milestoneIndex': 128,
+ 'references': [self.trytes1]
+ })
+
+ self.assertFilterPasses(filter_)
+ self.assertDictEqual(
+ filter_.cleaned_data,
+
+ {
+ 'balances': [114544444, 0, 8175737],
+ 'duration': 42,
+ 'milestoneIndex': 128,
+ 'references': [self.trytes1]
+ },
+ )
class GetBalancesCommandTestCase(TestCase):
- def setUp(self):
- super(GetBalancesCommandTestCase, self).setUp()
-
- self.adapter = MockAdapter()
-
- def test_wireup(self):
- """
- Verify that the command is wired up correctly.
- """
- self.assertIsInstance(
- Iota(self.adapter).getBalances,
- GetBalancesCommand,
- )
+ def setUp(self):
+ super(GetBalancesCommandTestCase, self).setUp()
+
+ self.adapter = MockAdapter()
+
+ def test_wireup(self):
+ """
+ Verify that the command is wired up correctly.
+ """
+ self.assertIsInstance(
+ Iota(self.adapter).getBalances,
+ GetBalancesCommand,
+ )
diff --git a/test/commands/core/get_missing_transactions_test.py b/test/commands/core/get_missing_transactions_test.py
new file mode 100644
index 0000000..cb6de74
--- /dev/null
+++ b/test/commands/core/get_missing_transactions_test.py
@@ -0,0 +1,116 @@
+# coding=utf-8
+from __future__ import absolute_import, division, print_function, \
+ unicode_literals
+
+from unittest import TestCase
+
+import filters as f
+from filters.test import BaseFilterTestCase
+
+from iota import Iota, TransactionHash
+from iota.adapter import MockAdapter
+from iota.commands.core import GetMissingTransactionsCommand
+
+
+class GetMissingTransactionsRequestFilterTestCase(BaseFilterTestCase):
+ filter_type = \
+ GetMissingTransactionsCommand(MockAdapter()).get_request_filter
+ skip_value_check = True
+
+ def test_pass_empty(self):
+ """
+ The incoming request is (correctly) empty.
+ """
+ request = {}
+
+ filter_ = self._filter(request)
+
+ self.assertFilterPasses(filter_)
+ self.assertDictEqual(filter_.cleaned_data, request)
+
+ def test_fail_unexpected_parameters(self):
+ """
+ The incoming request contains unexpected parameters.
+ """
+ self.assertFilterErrors(
+ {
+ # All you had to do was nothing! How did you screw that up?!
+ 'foo': 'bar',
+ },
+
+ {
+ 'foo': [f.FilterMapper.CODE_EXTRA_KEY],
+ },
+ )
+
+
+class GetMissingTransactionsResponseFilterTestCase(BaseFilterTestCase):
+ filter_type = \
+ GetMissingTransactionsCommand(MockAdapter()).get_response_filter
+ skip_value_check = True
+
+ # noinspection SpellCheckingInspection
+ def test_no_results(self):
+ """
+ The incoming response contains no hashes.
+ """
+ response = {
+ 'hashes': [],
+ }
+
+ filter_ = self._filter(response)
+
+ self.assertFilterPasses(filter_)
+ self.assertDictEqual(filter_.cleaned_data, response)
+
+ # noinspection SpellCheckingInspection
+ def test_search_results(self):
+ """
+ The incoming response contains lots of hashes.
+ """
+ filter_ = self._filter({
+ 'hashes': [
+ 'RVORZ9SIIP9RCYMREUIXXVPQIPHVCNPQ9HZWYKFW'
+ 'YWZRE9JQKG9REPKIASHUUECPSQO9JT9XNMVKWYGVA',
+
+ 'ZJVYUGTDRPDYFGFXMKOTV9ZWSGFK9CFPXTITQLQN'
+ 'LPPG9YNAARMKNKYQO9GSCSBIOTGMLJUFLZWSY9999',
+ ],
+
+ })
+
+ self.assertFilterPasses(filter_)
+ self.assertDictEqual(
+ filter_.cleaned_data,
+
+ {
+ 'hashes': [
+ TransactionHash(
+ b'RVORZ9SIIP9RCYMREUIXXVPQIPHVCNPQ9HZWYKFW'
+ b'YWZRE9JQKG9REPKIASHUUECPSQO9JT9XNMVKWYGVA',
+ ),
+
+ TransactionHash(
+ b'ZJVYUGTDRPDYFGFXMKOTV9ZWSGFK9CFPXTITQLQN'
+ b'LPPG9YNAARMKNKYQO9GSCSBIOTGMLJUFLZWSY9999',
+ ),
+ ],
+
+ },
+ )
+
+
+class GetMissingTransactionsCommandTestCase(TestCase):
+ def setUp(self):
+ super(GetMissingTransactionsCommandTestCase, self).setUp()
+
+ self.adapter = MockAdapter()
+
+ def test_wireup(self):
+ """
+ Verify that the command is wired up correctly.
+ """
+ self.assertIsInstance(
+ Iota(self.adapter).getMissingTransactions,
+ GetMissingTransactionsCommand,
+ )
diff --git a/test/commands/core/get_node_api_configuration_test.py b/test/commands/core/get_node_api_configuration_test.py
new file mode 100644
index 0000000..bee9e7a
--- /dev/null
+++ b/test/commands/core/get_node_api_configuration_test.py
@@ -0,0 +1,60 @@
+# coding=utf-8
+from __future__ import absolute_import, division, print_function, \
+ unicode_literals
+
+from unittest import TestCase
+
+import filters as f
+from filters.test import BaseFilterTestCase
+
+from iota import Iota
+from iota.adapter import MockAdapter
+from iota.commands.core import GetNodeAPIConfigurationCommand
+
+
+class GetNodeAPIConfigurationRequestFilterTestCase(BaseFilterTestCase):
+ filter_type = \
+ GetNodeAPIConfigurationCommand(MockAdapter()).get_request_filter
+ skip_value_check = True
+
+ def test_pass_empty(self):
+ """
+ The incoming request is (correctly) empty.
+ """
+ request = {}
+
+ filter_ = self._filter(request)
+
+ self.assertFilterPasses(filter_)
+ self.assertDictEqual(filter_.cleaned_data, request)
+
+ def test_fail_unexpected_parameters(self):
+ """
+ The incoming request contains unexpected parameters.
+ """
+ self.assertFilterErrors(
+ {
+ # All you had to do was nothing! How did you screw that up?!
+ 'foo': 'bar',
+ },
+
+ {
+ 'foo': [f.FilterMapper.CODE_EXTRA_KEY],
+ },
+ )
+
+
+class GetNodeAPIConfigurationCommandTestCase(TestCase):
+ def setUp(self):
+ super(GetNodeAPIConfigurationCommandTestCase, self).setUp()
+
+ self.adapter = MockAdapter()
+
+ def test_wireup(self):
+ """
+ Verify that the command is wired up correctly.
+ """
+ self.assertIsInstance(
+ Iota(self.adapter).getNodeAPIConfiguration,
+ GetNodeAPIConfigurationCommand,
+ )
diff --git a/test/commands/core/get_node_info_test.py b/test/commands/core/get_node_info_test.py
index 3c98afa..00a3402 100644
--- a/test/commands/core/get_node_info_test.py
+++ b/test/commands/core/get_node_info_test.py
@@ -17,7 +17,7 @@ class GetNodeInfoRequestFilterTestCase(BaseFilterTestCase):
def test_pass_empty(self):
"""
- The incoming response is (correctly) empty.
+ The incoming request is (correctly) empty.
"""
request = {}
@@ -28,7 +28,7 @@ def test_pass_empty(self):
def test_fail_unexpected_parameters(self):
"""
- The incoming response contains unexpected parameters.
+ The incoming request contains unexpected parameters.
"""
self.assertFilterErrors(
{
diff --git a/test/commands/core/get_tips_test.py b/test/commands/core/get_tips_test.py
index 0a2f1d1..410335d 100644
--- a/test/commands/core/get_tips_test.py
+++ b/test/commands/core/get_tips_test.py
@@ -19,7 +19,7 @@ class GetTipsRequestFilterTestCase(BaseFilterTestCase):
def test_pass_empty(self):
"""
- The incoming response is (correctly) empty.
+ The incoming request is (correctly) empty.
"""
request = {}
@@ -30,7 +30,7 @@ def test_pass_empty(self):
def test_fail_unexpected_parameters(self):
"""
- The incoming response contains unexpected parameters.
+ The incoming request contains unexpected parameters.
"""
self.assertFilterErrors(
{
diff --git a/test/commands/core/get_transactions_to_approve_test.py b/test/commands/core/get_transactions_to_approve_test.py
index 5875fdc..89559bf 100644
--- a/test/commands/core/get_transactions_to_approve_test.py
+++ b/test/commands/core/get_transactions_to_approve_test.py
@@ -1,6 +1,6 @@
# coding=utf-8
from __future__ import absolute_import, division, print_function, \
- unicode_literals
+ unicode_literals
from unittest import TestCase
@@ -9,226 +9,226 @@
from iota import Iota, TransactionHash
from iota.adapter import MockAdapter
from iota.commands.core.get_transactions_to_approve import \
- GetTransactionsToApproveCommand
+ GetTransactionsToApproveCommand
from iota.filters import Trytes
class GetTransactionsToApproveRequestFilterTestCase(BaseFilterTestCase):
- filter_type =\
- GetTransactionsToApproveCommand(MockAdapter()).get_request_filter
- skip_value_check = True
-
- def setUp(self):
- super(GetTransactionsToApproveRequestFilterTestCase, self).setUp()
-
- # Define some tryte sequences that we can reuse between tests.
- self.trytes1 = (
- b'TESTVALUEONE9DONTUSEINPRODUCTION99999JBW'
- b'GEC99GBXFFBCHAEJHLC9DX9EEPAI9ICVCKBX9FFII'
- )
-
- def test_pass_happy_path_without_reference(self):
- """
- Request is valid without reference.
- """
- request = {
- 'depth': 100,
- }
-
- filter_ = self._filter(request)
-
- self.assertFilterPasses(filter_)
- self.assertDictEqual(filter_.cleaned_data, request)
-
- def test_pass_happy_path_with_reference(self):
- """
- Request is valid with reference.
- """
- request = {
- 'depth': 100,
- 'reference': TransactionHash(self.trytes1),
- }
-
- filter_ = self._filter(request)
-
- self.assertFilterPasses(filter_)
- self.assertDictEqual(filter_.cleaned_data, request)
-
- def test_fail_empty(self):
- """
- Request is empty.
- """
- self.assertFilterErrors(
- {},
-
- {
- 'depth': [f.FilterMapper.CODE_MISSING_KEY],
- },
- )
-
- def test_fail_unexpected_parameters(self):
- """
- Request contains unexpected parameters.
- """
- self.assertFilterErrors(
- {
- 'depth': 100,
-
- # I knew I should have taken that left turn at Albuquerque.
- 'foo': 'bar',
- },
-
- {
- 'foo': [f.FilterMapper.CODE_EXTRA_KEY],
- },
- )
-
- def test_fail_depth_null(self):
- """
- ``depth`` is null.
- """
- self.assertFilterErrors(
- {
- 'depth': None,
- },
-
- {
- 'depth': [f.Required.CODE_EMPTY],
- },
- )
-
- def test_fail_depth_float(self):
- """
- ``depth`` is a float.
- """
- self.assertFilterErrors(
- {
- 'depth': 100.0,
- },
-
- {
- 'depth': [f.Type.CODE_WRONG_TYPE],
- },
- )
-
- def test_fail_depth_string(self):
- """
- ``depth`` is a string.
- """
- self.assertFilterErrors(
- {
- 'depth': '100',
- },
-
- {
- 'depth': [f.Type.CODE_WRONG_TYPE],
- },
- )
-
- def test_fail_depth_too_small(self):
- """
- ``depth`` is less than 1.
- """
- self.assertFilterErrors(
- {
- 'depth': 0,
- },
-
- {
- 'depth': [f.Min.CODE_TOO_SMALL],
- },
- )
-
- def test_fail_reference_wrong_type(self):
- """
- ``reference`` is not a TrytesCompatible value.
- """
- self.assertFilterErrors(
- {
- 'reference': 42,
-
- 'depth': 100,
- },
-
- {
- 'reference': [f.Type.CODE_WRONG_TYPE],
- },
- )
-
- def test_fail_reference_not_trytes(self):
- """
- ``reference`` contains invalid characters.
- """
- self.assertFilterErrors(
- {
- 'reference': b'not valid; must contain only uppercase and "9"',
-
- 'depth': 100,
- },
-
- {
- 'reference': [Trytes.CODE_NOT_TRYTES],
- },
- )
+ filter_type = \
+ GetTransactionsToApproveCommand(MockAdapter()).get_request_filter
+ skip_value_check = True
+
+ def setUp(self):
+ super(GetTransactionsToApproveRequestFilterTestCase, self).setUp()
+
+ # Define some tryte sequences that we can reuse between tests.
+ self.trytes1 = (
+ b'TESTVALUEONE9DONTUSEINPRODUCTION99999JBW'
+ b'GEC99GBXFFBCHAEJHLC9DX9EEPAI9ICVCKBX9FFII'
+ )
+
+ def test_pass_happy_path_without_reference(self):
+ """
+ Request is valid without reference.
+ """
+ request = {
+ 'depth': 100,
+ }
+
+ filter_ = self._filter(request)
+
+ self.assertFilterPasses(filter_)
+ self.assertDictEqual(filter_.cleaned_data, request)
+
+ def test_pass_happy_path_with_reference(self):
+ """
+ Request is valid with reference.
+ """
+ request = {
+ 'depth': 100,
+ 'reference': TransactionHash(self.trytes1),
+ }
+
+ filter_ = self._filter(request)
+
+ self.assertFilterPasses(filter_)
+ self.assertDictEqual(filter_.cleaned_data, request)
+
+ def test_fail_empty(self):
+ """
+ Request is empty.
+ """
+ self.assertFilterErrors(
+ {},
+
+ {
+ 'depth': [f.FilterMapper.CODE_MISSING_KEY],
+ },
+ )
+
+ def test_fail_unexpected_parameters(self):
+ """
+ Request contains unexpected parameters.
+ """
+ self.assertFilterErrors(
+ {
+ 'depth': 100,
+
+ # I knew I should have taken that left turn at Albuquerque.
+ 'foo': 'bar',
+ },
+
+ {
+ 'foo': [f.FilterMapper.CODE_EXTRA_KEY],
+ },
+ )
+
+ def test_fail_depth_null(self):
+ """
+ ``depth`` is null.
+ """
+ self.assertFilterErrors(
+ {
+ 'depth': None,
+ },
+
+ {
+ 'depth': [f.Required.CODE_EMPTY],
+ },
+ )
+
+ def test_fail_depth_float(self):
+ """
+ ``depth`` is a float.
+ """
+ self.assertFilterErrors(
+ {
+ 'depth': 100.0,
+ },
+
+ {
+ 'depth': [f.Type.CODE_WRONG_TYPE],
+ },
+ )
+
+ def test_fail_depth_string(self):
+ """
+ ``depth`` is a string.
+ """
+ self.assertFilterErrors(
+ {
+ 'depth': '100',
+ },
+
+ {
+ 'depth': [f.Type.CODE_WRONG_TYPE],
+ },
+ )
+
+ def test_fail_depth_too_small(self):
+ """
+ ``depth`` is less than 1.
+ """
+ self.assertFilterErrors(
+ {
+ 'depth': 0,
+ },
+
+ {
+ 'depth': [f.Min.CODE_TOO_SMALL],
+ },
+ )
+
+ def test_fail_reference_wrong_type(self):
+ """
+ ``reference`` is not a TrytesCompatible value.
+ """
+ self.assertFilterErrors(
+ {
+ 'reference': 42,
+
+ 'depth': 100,
+ },
+
+ {
+ 'reference': [f.Type.CODE_WRONG_TYPE],
+ },
+ )
+
+ def test_fail_reference_not_trytes(self):
+ """
+ ``reference`` contains invalid characters.
+ """
+ self.assertFilterErrors(
+ {
+ 'reference': b'not valid; must contain only uppercase and "9"',
+
+ 'depth': 100,
+ },
+
+ {
+ 'reference': [Trytes.CODE_NOT_TRYTES],
+ },
+ )
class GetTransactionsToApproveResponseFilterTestCase(BaseFilterTestCase):
- filter_type =\
- GetTransactionsToApproveCommand(MockAdapter()).get_response_filter
- skip_value_check = True
-
- # noinspection SpellCheckingInspection
- def test_pass_happy_path(self):
- """
- Typical ``getTransactionsToApprove`` response.
- """
- response = {
- 'trunkTransaction':
- 'TKGDZ9GEI9CPNQGHEATIISAKYPPPSXVCXBSR9EIW'
- 'CTHHSSEQCD9YLDPEXYERCNJVASRGWMAVKFQTC9999',
-
- 'branchTransaction':
- 'TKGDZ9GEI9CPNQGHEATIISAKYPPPSXVCXBSR9EIW'
- 'CTHHSSEQCD9YLDPEXYERCNJVASRGWMAVKFQTC9999',
-
- 'duration': 936,
- }
-
- filter_ = self._filter(response)
-
- self.assertFilterPasses(filter_)
- self.assertDictEqual(
- filter_.cleaned_data,
-
- {
- 'trunkTransaction':
- TransactionHash(
- b'TKGDZ9GEI9CPNQGHEATIISAKYPPPSXVCXBSR9EIW'
- b'CTHHSSEQCD9YLDPEXYERCNJVASRGWMAVKFQTC9999'
- ),
-
- 'branchTransaction':
- TransactionHash(
- b'TKGDZ9GEI9CPNQGHEATIISAKYPPPSXVCXBSR9EIW'
- b'CTHHSSEQCD9YLDPEXYERCNJVASRGWMAVKFQTC9999'
- ),
-
- 'duration': 936,
- },
- )
+ filter_type = \
+ GetTransactionsToApproveCommand(MockAdapter()).get_response_filter
+ skip_value_check = True
+
+ # noinspection SpellCheckingInspection
+ def test_pass_happy_path(self):
+ """
+ Typical ``getTransactionsToApprove`` response.
+ """
+ response = {
+ 'trunkTransaction':
+ 'TKGDZ9GEI9CPNQGHEATIISAKYPPPSXVCXBSR9EIW'
+ 'CTHHSSEQCD9YLDPEXYERCNJVASRGWMAVKFQTC9999',
+
+ 'branchTransaction':
+ 'TKGDZ9GEI9CPNQGHEATIISAKYPPPSXVCXBSR9EIW'
+ 'CTHHSSEQCD9YLDPEXYERCNJVASRGWMAVKFQTC9999',
+
+ 'duration': 936,
+ }
+
+ filter_ = self._filter(response)
+
+ self.assertFilterPasses(filter_)
+ self.assertDictEqual(
+ filter_.cleaned_data,
+
+ {
+ 'trunkTransaction':
+ TransactionHash(
+ b'TKGDZ9GEI9CPNQGHEATIISAKYPPPSXVCXBSR9EIW'
+ b'CTHHSSEQCD9YLDPEXYERCNJVASRGWMAVKFQTC9999'
+ ),
+
+ 'branchTransaction':
+ TransactionHash(
+ b'TKGDZ9GEI9CPNQGHEATIISAKYPPPSXVCXBSR9EIW'
+ b'CTHHSSEQCD9YLDPEXYERCNJVASRGWMAVKFQTC9999'
+ ),
+
+ 'duration': 936,
+ },
+ )
class GetTransactionsToApproveTestCase(TestCase):
- def setUp(self):
- super(GetTransactionsToApproveTestCase, self).setUp()
-
- self.adapter = MockAdapter()
-
- def test_wireup(self):
- """
- Verify that the command is wired up correctly.
- """
- self.assertIsInstance(
- Iota(self.adapter).getTransactionsToApprove,
- GetTransactionsToApproveCommand,
- )
+ def setUp(self):
+ super(GetTransactionsToApproveTestCase, self).setUp()
+
+ self.adapter = MockAdapter()
+
+ def test_wireup(self):
+ """
+ Verify that the command is wired up correctly.
+ """
+ self.assertIsInstance(
+ Iota(self.adapter).getTransactionsToApprove,
+ GetTransactionsToApproveCommand,
+ )
diff --git a/test/commands/core/were_addresses_spent_from_test.py b/test/commands/core/were_addresses_spent_from_test.py
index ba3053c..4fd482e 100644
--- a/test/commands/core/were_addresses_spent_from_test.py
+++ b/test/commands/core/were_addresses_spent_from_test.py
@@ -1,6 +1,6 @@
# coding=utf-8
from __future__ import absolute_import, division, print_function, \
- unicode_literals
+ unicode_literals
from unittest import TestCase
@@ -9,167 +9,168 @@
from iota import Address, Iota, TryteString
from iota.adapter import MockAdapter
-from iota.commands.core.were_addresses_spent_from import WereAddressesSpentFromCommand
+from iota.commands.core import WereAddressesSpentFromCommand
from iota.filters import Trytes
class WereAddressesSpentFromRequestFilterTestCase(BaseFilterTestCase):
- filter_type = WereAddressesSpentFromCommand(MockAdapter()).get_request_filter
- skip_value_check = True
-
- # noinspection SpellCheckingInspection
- def setUp(self):
- super(WereAddressesSpentFromRequestFilterTestCase, self).setUp()
-
- # Define a few valid values that we can reuse across tests.
- self.trytes1 = (
- 'TESTVALUE9DONTUSEINPRODUCTION99999EKJZZT'
- 'SOGJOUNVEWLDPKGTGAOIZIPMGBLHC9LMQNHLGXGYX'
- )
-
- self.trytes2 = (
- 'TESTVALUE9DONTUSEINPRODUCTION99999FDCDTZ'
- 'ZWLL9MYGUTLSYVSIFJ9NGALTRMCQVIIOVEQOITYTE'
- )
-
- def test_pass_happy_path(self):
- """
- Typical invocation of ``wereAddressesSpentFrom``.
- """
- request = {
- # Raw trytes are extracted to match the IRI's JSON protocol.
- 'addresses': [self.trytes1, self.trytes2],
- }
-
- filter_ = self._filter(request)
-
- self.assertFilterPasses(filter_)
- self.assertDictEqual(filter_.cleaned_data, request)
-
- def test_pass_compatible_types(self):
- """
- The incoming request contains values that can be converted to the
- expected types.
- """
- request = {
- 'addresses': [
- Address(self.trytes1),
- bytearray(self.trytes2.encode('ascii')),
- ],
- }
-
- filter_ = self._filter(request)
-
- self.assertFilterPasses(filter_)
- self.assertDictEqual(
- filter_.cleaned_data,
-
- {
- 'addresses': [self.trytes1, self.trytes2],
- },
- )
-
- def test_fail_empty(self):
- """
- The incoming request is empty.
- """
- self.assertFilterErrors(
- {},
-
- {
- 'addresses': [f.FilterMapper.CODE_MISSING_KEY],
- },
- )
-
- def test_fail_unexpected_parameters(self):
- """
- The incoming request contains unexpected parameters.
- """
- self.assertFilterErrors(
- {
- 'addresses': [Address(self.trytes1)],
-
- # I've had a perfectly wonderful evening.
- # But this wasn't it.
- 'foo': 'bar',
- },
-
- {
- 'foo': [f.FilterMapper.CODE_EXTRA_KEY],
- },
- )
-
- def test_fail_addresses_wrong_type(self):
- """
- ``addresses`` is not an array.
- """
- self.assertFilterErrors(
- {
- 'addresses': Address(self.trytes1),
- },
-
- {
- 'addresses': [f.Type.CODE_WRONG_TYPE],
- },
- )
-
- def test_fail_addresses_empty(self):
- """
- ``addresses`` is an array, but it's empty.
- """
- self.assertFilterErrors(
- {
- 'addresses': [],
- },
-
- {
- 'addresses': [f.Required.CODE_EMPTY],
- },
- )
-
- def test_fail_addresses_contents_invalid(self):
- """
- ``addresses`` is an array, but it contains invalid values.
- """
- self.assertFilterErrors(
- {
- 'addresses': [
- b'',
- True,
- None,
- b'not valid trytes',
-
- # This is actually valid; I just added it to make sure the
- # filter isn't cheating!
- TryteString(self.trytes2),
-
- 2130706433,
- b'9' * 82,
- ],
- },
-
- {
- 'addresses.0': [f.Required.CODE_EMPTY],
- 'addresses.1': [f.Type.CODE_WRONG_TYPE],
- 'addresses.2': [f.Required.CODE_EMPTY],
- 'addresses.3': [Trytes.CODE_NOT_TRYTES],
- 'addresses.5': [f.Type.CODE_WRONG_TYPE],
- 'addresses.6': [Trytes.CODE_WRONG_FORMAT],
- },
- )
+ filter_type = \
+ WereAddressesSpentFromCommand(MockAdapter()).get_request_filter
+ skip_value_check = True
+
+ # noinspection SpellCheckingInspection
+ def setUp(self):
+ super(WereAddressesSpentFromRequestFilterTestCase, self).setUp()
+
+ # Define a few valid values that we can reuse across tests.
+ self.trytes1 = (
+ 'TESTVALUE9DONTUSEINPRODUCTION99999EKJZZT'
+ 'SOGJOUNVEWLDPKGTGAOIZIPMGBLHC9LMQNHLGXGYX'
+ )
+
+ self.trytes2 = (
+ 'TESTVALUE9DONTUSEINPRODUCTION99999FDCDTZ'
+ 'ZWLL9MYGUTLSYVSIFJ9NGALTRMCQVIIOVEQOITYTE'
+ )
+
+ def test_pass_happy_path(self):
+ """
+ Typical invocation of ``wereAddressesSpentFrom``.
+ """
+ request = {
+ # Raw trytes are extracted to match the IRI's JSON protocol.
+ 'addresses': [self.trytes1, self.trytes2],
+ }
+
+ filter_ = self._filter(request)
+
+ self.assertFilterPasses(filter_)
+ self.assertDictEqual(filter_.cleaned_data, request)
+
+ def test_pass_compatible_types(self):
+ """
+ The incoming request contains values that can be converted to the
+ expected types.
+ """
+ request = {
+ 'addresses': [
+ Address(self.trytes1),
+ bytearray(self.trytes2.encode('ascii')),
+ ],
+ }
+
+ filter_ = self._filter(request)
+
+ self.assertFilterPasses(filter_)
+ self.assertDictEqual(
+ filter_.cleaned_data,
+
+ {
+ 'addresses': [self.trytes1, self.trytes2],
+ },
+ )
+
+ def test_fail_empty(self):
+ """
+ The incoming request is empty.
+ """
+ self.assertFilterErrors(
+ {},
+
+ {
+ 'addresses': [f.FilterMapper.CODE_MISSING_KEY],
+ },
+ )
+
+ def test_fail_unexpected_parameters(self):
+ """
+ The incoming request contains unexpected parameters.
+ """
+ self.assertFilterErrors(
+ {
+ 'addresses': [Address(self.trytes1)],
+
+ # I've had a perfectly wonderful evening.
+ # But this wasn't it.
+ 'foo': 'bar',
+ },
+
+ {
+ 'foo': [f.FilterMapper.CODE_EXTRA_KEY],
+ },
+ )
+
+ def test_fail_addresses_wrong_type(self):
+ """
+ ``addresses`` is not an array.
+ """
+ self.assertFilterErrors(
+ {
+ 'addresses': Address(self.trytes1),
+ },
+
+ {
+ 'addresses': [f.Type.CODE_WRONG_TYPE],
+ },
+ )
+
+ def test_fail_addresses_empty(self):
+ """
+ ``addresses`` is an array, but it's empty.
+ """
+ self.assertFilterErrors(
+ {
+ 'addresses': [],
+ },
+
+ {
+ 'addresses': [f.Required.CODE_EMPTY],
+ },
+ )
+
+ def test_fail_addresses_contents_invalid(self):
+ """
+ ``addresses`` is an array, but it contains invalid values.
+ """
+ self.assertFilterErrors(
+ {
+ 'addresses': [
+ b'',
+ True,
+ None,
+ b'not valid trytes',
+
+ # This is actually valid; I just added it to make sure the
+ # filter isn't cheating!
+ TryteString(self.trytes2),
+
+ 2130706433,
+ b'9' * 82,
+ ],
+ },
+
+ {
+ 'addresses.0': [f.Required.CODE_EMPTY],
+ 'addresses.1': [f.Type.CODE_WRONG_TYPE],
+ 'addresses.2': [f.Required.CODE_EMPTY],
+ 'addresses.3': [Trytes.CODE_NOT_TRYTES],
+ 'addresses.5': [f.Type.CODE_WRONG_TYPE],
+ 'addresses.6': [Trytes.CODE_WRONG_FORMAT],
+ },
+ )
class WereAddressesSpentFromCommandTestCase(TestCase):
- def setUp(self):
- super(WereAddressesSpentFromCommandTestCase, self).setUp()
-
- self.adapter = MockAdapter()
-
- def test_wireup(self):
- """
- Verify that the command is wired up correctly.
- """
- self.assertIsInstance(
- Iota(self.adapter).wereAddressesSpentFrom,
- WereAddressesSpentFromCommand,
- )
+ def setUp(self):
+ super(WereAddressesSpentFromCommandTestCase, self).setUp()
+
+ self.adapter = MockAdapter()
+
+ def test_wireup(self):
+ """
+ Verify that the command is wired up correctly.
+ """
+ self.assertIsInstance(
+ Iota(self.adapter).wereAddressesSpentFrom,
+ WereAddressesSpentFromCommand,
+ )