diff --git a/docs/commands.rst b/docs/commands.rst
new file mode 100644
index 00000000..a860a441
--- /dev/null
+++ b/docs/commands.rst
@@ -0,0 +1,217 @@
+Advanced: PyOTA Commands
+========================
+
+.. note::
+ **This page contains information about how PyOTA works under the hood.**
+
+ It is absolutely not necessary to be familiar with the content described
+ below if you just want to use the library.
+
+ However, if you are a curious mind or happen to do development on the
+ library, the following information might be useful.
+
+PyOTA provides the API interface (:ref:`Core API Methods` and
+:ref:`Extended API Methods`) for users of the library. These handle
+constructing and sending HTTP requests to the specified node through adapters,
+furthermore creating, transforming and translating between PyOTA-specific types
+and (JSON-encoded) raw data. They also filter outgoing requests and incoming
+responses to ensure that only appropriate data is communicated with the node.
+
+PyOTA implements the `Command Design Pattern`_. High level API interface
+methods (:ref:`Core API Methods` and :ref:`Extended API Methods`)
+internally call PyOTA commands to get the job done.
+
+Most PyOTA commands are sub-classed from :py:class:`FilterCommand` class, which
+is in turn sub-classed from :py:class:`BaseCommand` class. The reason for the
+2-level inheritance is simple: separating functionality. As the name implies,
+:py:class:`FilterCommand` adds filtering capabilities to
+:py:class:`BaseCommand`, that contains the logic of constructing the request
+and using its adapter to send it and receive a response.
+
+Command Flow
+------------
+As mentioned earlier, API methods rely on PyOTA commands to carry out
+specific operations. It is important to understand what happens during command
+execution so you are able to implement new methods that extend the current
+capabilities of PyOTA.
+
+.. py:currentmodule:: iota
+
+Let's investigate the process through an example of a core API method, for
+instance :py:meth:`~Iota.find_transactions`, that calls
+:py:class:`FindTransactionCommand` PyOTA command internally.
+
+.. note::
+ :py:class:`FindTransactionCommand` is sub-classed from :py:class:`FilterCommand`.
+
+To illustrate what the happens inside the API method, take a look at the
+following figure
+
+
+.. figure:: images/command_execution.svg
+ :scale: 100 %
+ :alt: Inner workings of a PyOTA Command.
+
+ Inner workings of a PyOTA Command.
+
+- When you call :py:meth:`~Iota.find_transactions` core API method, it
+ initializes a :py:class:`FindTransactionCommand` object with the adapter of the
+ API instance it belongs to.
+
+- Then calls this command with the keyword arguments it was provided with.
+
+- The command prepares the request by applying a ``RequestFilter`` on the
+ payload. The command specific ``RequestFilter`` validates that the payload
+ has correct types, in some cases it is even able to convert the payload to
+ the required type and format.
+
+- Command execution injects the name of the API command (see `IRI API Reference`_
+ for command names) in the request and sends it to the adapter.
+
+- The adapter communicates with the node and returns its response.
+
+- The response is prepared by going through a command-specific
+ ``ResponseFilter``.
+
+- The response is returned to the high level API method as a ``dict``, ready
+ to be returned to the main application.
+
+.. note::
+ A command object can only be called once without resetting it. When you
+ use the high level API methods, you don't need to worry about resetting
+ commands as each call to an API method will initialize a new command object.
+
+Filters
+-------
+
+If you take a look at the actual implementation of
+:py:class:`FindTransactionsCommand`, you notice that you have to define your
+own request and response filter classes.
+
+Filters in PyOTA are based on the `Filters library`_. Read more about how
+they work at the `filters documentation site`_.
+
+In short, you can create filter chains through which the filtered value passes,
+and generates errors if something failed validation. Filter chains are specified
+in the custom filter class's :py:meth:`__init__` function. If you also want to
+modify the filtered value before returning it, override the :py:meth:`_apply`
+method of its base class. Read more about how to `create custom filters`_.
+
+PyOTA offers you some custom filters for PyOTA-specific types:
+
+**Trytes**
+~~~~~~~~~~
+.. autoclass:: iota.filters.Trytes
+
+**StringifiedTrytesArray**
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+.. automethod:: iota.filters.StringifiedTrytesArray
+
+**AddressNoChecksum**
+~~~~~~~~~~~~~~~~~~~~~
+.. autoclass:: iota.filters.AddressNoChecksum
+
+**GeneratedAddress**
+~~~~~~~~~~~~~~~~~~~~
+.. autoclass:: iota.filters.GeneratedAddress
+
+**NodeUri**
+~~~~~~~~~~~
+.. autoclass:: iota.filters.NodeUri
+ :members: SCHEMES
+
+**SecurityLevel**
+~~~~~~~~~~~~~~~~~~~~
+.. automethod:: iota.filters.SecurityLevel
+
+.. important::
+ The general rule in PyOTA is that all requests going to a node are
+ validated, but only responses that contain transaction/bundle trytes or
+ hashes are checked.
+
+ Also note, that for extended commands, ``ResponseFilter`` is usually
+ implemented with just a "pass" statement. The reason being that these
+ commands do not directly receive their result a node, but rather from
+ core commands that do have their ``ResponseFilter`` implemented.
+ More about this topic in the next section.
+
+
+Extended Commands
+-----------------
+
+Core commands, like :py:meth:`~Iota.find_transactions` in the example above,
+are for direct communication with the node for simple tasks such
+as finding a transaction on the Tangle or getting info about the node.
+Extended commands (that serve :ref:`Extended API Methods`) on the other hand
+carry out more complex operations such as combining core commands, building
+objects, etc...
+
+As a consequence, extended commands override the default execution phase of their
+base class.
+
+Observe for example :py:class:`FindTransactionObjectsCommand` extended command
+that is called in :py:meth:`~Iota.find_transaction_objects` extended API
+method. It overrides the :py:meth:`_execute` method of its base class.
+
+Let's take a closer look at the implementation::
+
+ ...
+ def _execute(self, request):
+ bundles = request\
+ .get('bundles') # type: Optional[Iterable[BundleHash]]
+ addresses = request\
+ .get('addresses') # type: Optional[Iterable[Address]]
+ tags = request\
+ .get('tags') # type: Optional[Iterable[Tag]]
+ approvees = request\
+ .get('approvees') # type: Optional[Iterable[TransactionHash]]
+
+ ft_response = FindTransactionsCommand(adapter=self.adapter)(
+ bundles=bundles,
+ addresses=addresses,
+ tags=tags,
+ approvees=approvees,
+ )
+
+ hashes = ft_response['hashes']
+ transactions = []
+ if hashes:
+ gt_response = GetTrytesCommand(adapter=self.adapter)(hashes=hashes)
+
+ transactions = list(map(
+ Transaction.from_tryte_string,
+ gt_response.get('trytes') or [],
+ )) # type: List[Transaction]
+
+ return {
+ 'transactions': transactions,
+ }
+ ...
+
+Instead of sending the request to the adapter,
+:py:meth:`FindTransactionObjectsCommand._execute` calls
+:py:class:`FindTransactionsCommand` core command, gathers the transaction hashes
+that it found, and collects the trytes of those transactions by calling
+:py:class:`GetTrytesCommand` core command. Finally, using the obtained trytes,
+it constructs a list of transaction objects that are returned to
+:py:meth:`~Iota.find_transaction_objects`.
+
+.. important::
+ If you come up with a new functionality for the PyOTA API, please raise
+ an issue in the `PyOTA Bug Tracker`_ to facilitate discussion.
+
+ Once the community agrees on your proposal, you may start implementing
+ a new extended API method and the corresponding extended PyOTA command.
+
+ Contributions are always welcome! :)
+
+ Visit the `Contributing to PyOTA`_ page to find out how you can make a
+ difference!
+
+.. _Command Design Pattern: https://en.wikipedia.org/wiki/Command_pattern
+.. _IRI API Reference: https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference
+.. _Filters library: https://pypi.org/project/phx-filters/
+.. _filters documentation site: https://filters.readthedocs.io/en/latest/
+.. _create custom filters: https://filters.readthedocs.io/en/latest/writing_filters.html
+.. _PyOTA Bug Tracker: https://github.com/iotaledger/iota.py/issues
+.. _Contributing to PyOTA: https://github.com/iotaledger/iota.py/blob/master/CONTRIBUTING.rst
\ No newline at end of file
diff --git a/docs/images/command_execution.svg b/docs/images/command_execution.svg
new file mode 100644
index 00000000..5f1b4b8d
--- /dev/null
+++ b/docs/images/command_execution.svg
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/docs/index.rst b/docs/index.rst
index a8432a97..5c654c0f 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -11,5 +11,6 @@
extended_api
addresses
multisig
+ commands
.. include:: ../README.rst
diff --git a/iota/api.py b/iota/api.py
index 7c43c9f5..d0d40b30 100644
--- a/iota/api.py
+++ b/iota/api.py
@@ -4,13 +4,10 @@
from typing import Dict, Iterable, Optional, Text
-from six import add_metaclass
-
from iota import AdapterSpec, Address, BundleHash, ProposedTransaction, Tag, \
TransactionHash, TransactionTrytes, TryteString, TrytesCompatible
from iota.adapter import BaseAdapter, resolve_adapter
-from iota.commands import BaseCommand, CustomCommand, core, \
- discover_commands, extended
+from iota.commands import BaseCommand, CustomCommand, core, extended
from iota.commands.extended.helpers import Helpers
from iota.crypto.addresses import AddressGenerator
from iota.crypto.types import Seed
@@ -28,32 +25,6 @@ class InvalidCommand(ValueError):
"""
pass
-
-class ApiMeta(type):
- """
- Manages command registries for IOTA API base classes.
- """
-
- def __init__(cls, name, bases=None, attrs=None):
- super(ApiMeta, cls).__init__(name, bases, attrs)
-
- if not hasattr(cls, 'commands'):
- cls.commands = {}
-
- # Copy command registry from base class to derived class, but
- # in the event of a conflict, preserve the derived class'
- # commands.
- commands = {}
- for base in bases:
- if isinstance(base, ApiMeta):
- commands.update(base.commands)
-
- if commands:
- commands.update(cls.commands)
- cls.commands = commands
-
-
-@add_metaclass(ApiMeta)
class StrictIota(object):
"""
API to send HTTP requests for communicating with an IOTA node.
@@ -82,7 +53,6 @@ class StrictIota(object):
:ref:`find out` how to use it.
"""
- commands = discover_commands('iota.commands.core')
def __init__(self, adapter, testnet=False, local_pow=False):
# type: (AdapterSpec, bool, bool) -> None
@@ -123,48 +93,6 @@ def __init__(self, adapter, testnet=False, local_pow=False):
self.adapter.set_local_pow(local_pow)
self.testnet = testnet
- def __getattr__(self, command):
- # type: (Text) -> BaseCommand
- """
- Creates a pre-configured command instance.
-
- This method will only return commands supported by the API
- class.
-
- If you want to execute an arbitrary API command, use
- :py:meth:`create_command`.
-
- :param Text command:
- The name of the command to create.
-
- References:
-
- - 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.py/issues/41
- if command == '__name__':
- # noinspection PyTypeChecker
- return None
-
- # Fix an error when invoking dunder methods.
- # https://github.com/iotaledger/iota.py/issues/206
- if command.startswith("__"):
- # noinspection PyUnresolvedReferences
- return super(StrictIota, self).__getattr__(command)
-
- try:
- command_class = self.commands[command]
- except KeyError:
- raise InvalidCommand(
- '{cls} does not support {command!r} command.'.format(
- cls=type(self).__name__,
- command=command,
- ),
- )
-
- return command_class(self.adapter)
-
def create_command(self, command):
# type: (Text) -> CustomCommand
"""
@@ -862,7 +790,6 @@ class Iota(StrictIota):
- 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')
def __init__(self, adapter, seed=None, testnet=False, local_pow=False):
# type: (AdapterSpec, Optional[TrytesCompatible], bool, bool) -> None
diff --git a/iota/commands/__init__.py b/iota/commands/__init__.py
index acfefa36..39695bc8 100644
--- a/iota/commands/__init__.py
+++ b/iota/commands/__init__.py
@@ -18,76 +18,13 @@
__all__ = [
'BaseCommand',
- 'command_registry',
- 'discover_commands',
'CustomCommand',
'FilterCommand',
'RequestFilter',
'ResponseFilter',
]
-command_registry = {} # type: Dict[Text, CommandMeta]
-"""
-Registry of commands, indexed by command name.
-"""
-
-
-def discover_commands(package, recursively=True):
- # type: (Union[ModuleType, Text], bool) -> Dict[Text, 'CommandMeta']
- """
- Automatically discover commands in the specified package.
-
- :param package:
- Package path or reference.
-
- :param recursively:
- If True, will descend recursively into sub-packages.
-
- :return:
- All commands discovered in the specified package, indexed by
- command name (note: not class name).
- """
- # http://stackoverflow.com/a/25562415/
- if isinstance(package, six.string_types):
- package = import_module(package) # type: ModuleType
-
- commands = {}
-
- for _, name, is_package in walk_packages(package.__path__, package.__name__ + '.'):
- # Loading the module is good enough; the CommandMeta metaclass will
- # ensure that any commands in the module get registered.
-
- # Prefix in name module move to function "walk_packages" for fix
- # conflict with names importing packages
- # Bug https://github.com/iotaledger/iota.py/issues/63
- sub_package = import_module(name)
-
- # Index any command classes that we find.
- for (_, obj) in get_members(sub_package):
- if is_class(obj) and isinstance(obj, CommandMeta):
- command_name = getattr(obj, 'command')
- if command_name:
- commands[command_name] = obj
-
- if recursively and is_package:
- commands.update(discover_commands(sub_package))
-
- return commands
-
-class CommandMeta(ABCMeta):
- """
- Automatically register new commands.
- """
- # noinspection PyShadowingBuiltins
- def __init__(cls, what, bases=None, dict=None):
- super(CommandMeta, cls).__init__(what, bases, dict)
-
- if not is_abstract(cls):
- command = getattr(cls, 'command')
- if command:
- command_registry[command] = cls
-
-@six.add_metaclass(CommandMeta)
+@six.add_metaclass(ABCMeta)
class BaseCommand(object):
"""
An API command ready to send to the node.
@@ -265,6 +202,7 @@ class FilterCommand(BaseCommand):
"""
Uses filters to manipulate request/response values.
"""
+
@abstract_method
def get_request_filter(self):
# type: () -> Optional[RequestFilter]
@@ -336,8 +274,4 @@ def _apply_filter(value, filter_, failure_message):
},
)
- return value
-
-
-# Autodiscover commands in this package.
-discover_commands(__name__)
+ return value
\ No newline at end of file
diff --git a/iota/filters.py b/iota/filters.py
index 88f3cbff..9025a817 100644
--- a/iota/filters.py
+++ b/iota/filters.py
@@ -24,7 +24,13 @@
class GeneratedAddress(f.BaseFilter):
"""
Validates an incoming value as a generated :py:class:`Address` (must
- have ``key_index`` set).
+ have ``key_index`` and ``security_level`` set).
+
+ When a value doesn't pass the filter, a ``ValueError`` is raised with lots
+ of contextual info attached to it.
+
+ :return:
+ :py:class:`GeneratedAddress` object.
"""
CODE_NO_KEY_INDEX = 'no_key_index'
CODE_NO_SECURITY_LEVEL = 'no_security_level'
@@ -55,6 +61,12 @@ def _apply(self, value):
class NodeUri(f.BaseFilter):
"""
Validates a string as a node URI.
+
+ When a value doesn't pass the filter, a ``ValueError`` is raised with lots
+ of contextual info attached to it.
+
+ :return:
+ :py:class:`NodeUri` object.
"""
SCHEMES = {'tcp', 'udp'}
"""
@@ -87,6 +99,9 @@ def _apply(self, value):
def SecurityLevel():
"""
Generates a filter chain for validating a security level.
+
+ :return:
+ :py:class:`filters.FilterChain` object.
"""
return (
f.Type(int) |
@@ -99,6 +114,21 @@ def SecurityLevel():
class Trytes(f.BaseFilter):
"""
Validates a sequence as a sequence of trytes.
+
+ When a value doesn't pass the filter, a ``ValueError`` is raised with lots
+ of contextual info attached to it.
+
+ :param TryteString result_type:
+ Any subclass of :py:class:`~iota.TryteString` that you want the filter
+ to validate.
+
+ :raises TypeError: if value is not of ``result_type``.
+ :raises ValueError:
+ if ``result_type`` is not of :py:class:`~iota.TryteString` type.
+
+ :return:
+ :py:class:`Trytes` object.
+
"""
CODE_NOT_TRYTES = 'not_trytes'
CODE_WRONG_FORMAT = 'wrong_format'
@@ -190,6 +220,16 @@ def StringifiedTrytesArray(trytes_type=TryteString):
strings corresponding to the specified type (e.g.,
``TransactionHash``).
+ When a value doesn't pass the filter, a ``ValueError`` is raised with lots
+ of contextual info attached to it.
+
+ :param TryteString result_type:
+ Any subclass of :py:class:`~iota.TryteString` that you want the filter
+ to validate.
+
+ :return:
+ :py:class:`filters.FilterChain` object.
+
.. important::
This filter will return string values, suitable for inclusion in
an API request. If you are expecting objects (e.g.,
@@ -209,8 +249,14 @@ def StringifiedTrytesArray(trytes_type=TryteString):
class AddressNoChecksum(Trytes):
"""
- Validates a sequence as an Address, then chops off the checksum if
- present.
+ Validates a sequence as an :py:class:`Address`, then chops off the checksum
+ if present.
+
+ When a value doesn't pass the filter, a ``ValueError`` is raised with lots
+ of contextual info attached to it.
+
+ :return:
+ :py:class:`AddressNoChecksum` object.
"""
ADDRESS_BAD_CHECKSUM = 'address_bad_checksum'
diff --git a/iota/multisig/api.py b/iota/multisig/api.py
index 563f7ca1..0ad14b8d 100644
--- a/iota/multisig/api.py
+++ b/iota/multisig/api.py
@@ -5,7 +5,6 @@
from typing import Iterable, Optional
from iota import Address, Iota, ProposedTransaction
-from iota.commands import discover_commands
from iota.crypto.addresses import AddressGenerator
from iota.crypto.types import Digest
from iota.multisig import commands
@@ -31,7 +30,6 @@ class MultisigIota(Iota):
- https://github.com/iotaledger/wiki/blob/master/multisigs.md
"""
- commands = discover_commands('iota.multisig.commands')
def create_multisig_address(self, digests):
# type: (Iterable[Digest]) -> dict
diff --git a/test/__init__.py b/test/__init__.py
index 83fdaa2f..0b9065db 100644
--- a/test/__init__.py
+++ b/test/__init__.py
@@ -8,7 +8,9 @@
# In Python 3 the ``mock`` library was moved into the stdlib.
# noinspection PyUnresolvedReferences
from unittest import mock
+ from unittest.mock import MagicMock, patch
else:
# In Python 2, the ``mock`` library is included as a dependency.
# noinspection PyUnresolvedReferences
import mock
+ from mock import MagicMock, patch
diff --git a/test/api_test.py b/test/api_test.py
index 7a60e550..95084f4b 100644
--- a/test/api_test.py
+++ b/test/api_test.py
@@ -107,27 +107,6 @@ def test_init_with_uri(self):
api = StrictIota('mock://')
self.assertIsInstance(api.adapter, MockAdapter)
- def test_registered_command(self):
- """
- Preparing a documented command.
- """
- api = StrictIota(MockAdapter())
-
- # We just need to make sure the correct command type is
- # instantiated; individual commands have their own unit tests.
- command = api.getNodeInfo
- self.assertIsInstance(command, GetNodeInfoCommand)
-
- def test_unregistered_command(self):
- """
- Attempting to create an unsupported command.
- """
- api = StrictIota(MockAdapter())
-
- with self.assertRaises(InvalidCommand):
- # noinspection PyStatementEffect
- api.helloWorld
-
def test_create_command(self):
"""
Preparing an experimental/undocumented command.
diff --git a/test/commands/core/add_neighbors_test.py b/test/commands/core/add_neighbors_test.py
index 367f8780..985c3acb 100644
--- a/test/commands/core/add_neighbors_test.py
+++ b/test/commands/core/add_neighbors_test.py
@@ -6,10 +6,11 @@
import filters as f
from filters.test import BaseFilterTestCase
-from iota import Iota
+from iota import StrictIota
from iota.adapter import MockAdapter
from iota.commands.core.add_neighbors import AddNeighborsCommand
from iota.filters import NodeUri
+from test import patch, MagicMock
class AddNeighborsRequestFilterTestCase(BaseFilterTestCase):
@@ -151,8 +152,20 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).addNeighbors,
- AddNeighborsCommand,
- )
+ with patch('iota.commands.core.add_neighbors.AddNeighborsCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = StrictIota(self.adapter)
+
+ response = api.add_neighbors('test_uri')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
\ No newline at end of file
diff --git a/test/commands/core/attach_to_tangle_test.py b/test/commands/core/attach_to_tangle_test.py
index 787a0ed0..604057e9 100644
--- a/test/commands/core/attach_to_tangle_test.py
+++ b/test/commands/core/attach_to_tangle_test.py
@@ -11,6 +11,7 @@
from iota.commands.core.attach_to_tangle import AttachToTangleCommand
from iota.filters import Trytes
from six import binary_type, text_type
+from test import patch, MagicMock
class AttachToTangleRequestFilterTestCase(BaseFilterTestCase):
@@ -423,7 +424,6 @@ def test_pass_happy_path(self):
},
)
-
class AttachToTangleCommandTestCase(TestCase):
def setUp(self):
super(AttachToTangleCommandTestCase, self).setUp()
@@ -433,8 +433,21 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).attachToTangle,
- AttachToTangleCommand,
- )
+ with patch('iota.commands.core.attach_to_tangle.AttachToTangleCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.attach_to_tangle('trunk', 'branch', 'trytes')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
diff --git a/test/commands/core/broadcast_transactions_test.py b/test/commands/core/broadcast_transactions_test.py
index 17c104d9..e5c3b73e 100644
--- a/test/commands/core/broadcast_transactions_test.py
+++ b/test/commands/core/broadcast_transactions_test.py
@@ -13,7 +13,7 @@
from iota.commands.core.broadcast_transactions import \
BroadcastTransactionsCommand
from iota.filters import Trytes
-
+from test import patch, MagicMock
class BroadcastTransactionsRequestFilterTestCase(BaseFilterTestCase):
filter_type = BroadcastTransactionsCommand(MockAdapter()).get_request_filter
@@ -187,8 +187,21 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).broadcastTransactions,
- BroadcastTransactionsCommand,
- )
+ with patch('iota.commands.core.broadcast_transactions.BroadcastTransactionsCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.broadcast_transactions('trytes')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
diff --git a/test/commands/core/check_consistency_test.py b/test/commands/core/check_consistency_test.py
index 028f39cd..57517df0 100644
--- a/test/commands/core/check_consistency_test.py
+++ b/test/commands/core/check_consistency_test.py
@@ -11,6 +11,7 @@
from iota.adapter import MockAdapter
from iota.commands.core.check_consistency import CheckConsistencyCommand
from iota.filters import Trytes
+from test import patch, MagicMock
class CheckConsistencyRequestFilterTestCase(BaseFilterTestCase):
@@ -200,11 +201,24 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).checkConsistency,
- CheckConsistencyCommand,
- )
+ with patch('iota.commands.core.check_consistency.CheckConsistencyCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.check_consistency('tails')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
def test_happy_path(self):
"""
diff --git a/test/commands/core/find_transactions_test.py b/test/commands/core/find_transactions_test.py
index cad20fff..3d5a72cb 100644
--- a/test/commands/core/find_transactions_test.py
+++ b/test/commands/core/find_transactions_test.py
@@ -13,6 +13,7 @@
from iota.commands.core.find_transactions import FindTransactionsCommand, \
FindTransactionsRequestFilter
from iota.filters import Trytes
+from test import patch, MagicMock
class FindTransactionsRequestFilterTestCase(BaseFilterTestCase):
@@ -561,8 +562,21 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).findTransactions,
- FindTransactionsCommand,
- )
+ with patch('iota.commands.core.check_consistency.CheckConsistencyCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.check_consistency('tails')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
\ No newline at end of file
diff --git a/test/commands/core/get_balances_test.py b/test/commands/core/get_balances_test.py
index 4f9ecc8b..bfd1450d 100644
--- a/test/commands/core/get_balances_test.py
+++ b/test/commands/core/get_balances_test.py
@@ -11,6 +11,7 @@
from iota.adapter import MockAdapter
from iota.commands.core.get_balances import GetBalancesCommand
from iota.filters import Trytes
+from test import patch, MagicMock
class GetBalancesRequestFilterTestCase(BaseFilterTestCase):
@@ -351,8 +352,21 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).getBalances,
- GetBalancesCommand,
- )
+ with patch('iota.commands.core.get_balances.GetBalancesCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.get_balances('addresses')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
diff --git a/test/commands/core/get_inclusion_states_test.py b/test/commands/core/get_inclusion_states_test.py
index 3a63c754..873a49a1 100644
--- a/test/commands/core/get_inclusion_states_test.py
+++ b/test/commands/core/get_inclusion_states_test.py
@@ -11,6 +11,7 @@
from iota.commands.core.get_inclusion_states import GetInclusionStatesCommand
from iota.filters import Trytes
from six import binary_type, text_type
+from test import patch, MagicMock
class GetInclusionStatesRequestFilterTestCase(BaseFilterTestCase):
@@ -259,8 +260,21 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).getInclusionStates,
- GetInclusionStatesCommand,
- )
+ with patch('iota.commands.core.get_inclusion_states.GetInclusionStatesCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.get_inclusion_states('transactions', 'tips')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
diff --git a/test/commands/core/get_missing_transactions_test.py b/test/commands/core/get_missing_transactions_test.py
index cb6de746..0c5adb00 100644
--- a/test/commands/core/get_missing_transactions_test.py
+++ b/test/commands/core/get_missing_transactions_test.py
@@ -10,6 +10,7 @@
from iota import Iota, TransactionHash
from iota.adapter import MockAdapter
from iota.commands.core import GetMissingTransactionsCommand
+from test import patch, MagicMock
class GetMissingTransactionsRequestFilterTestCase(BaseFilterTestCase):
@@ -109,8 +110,21 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).getMissingTransactions,
- GetMissingTransactionsCommand,
- )
+ with patch('iota.commands.core.get_missing_transactions.GetMissingTransactionsCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.get_missing_transactions()
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
diff --git a/test/commands/core/get_neighbors_test.py b/test/commands/core/get_neighbors_test.py
index be7888f5..83e71172 100644
--- a/test/commands/core/get_neighbors_test.py
+++ b/test/commands/core/get_neighbors_test.py
@@ -9,6 +9,7 @@
from iota import Iota
from iota.adapter import MockAdapter
from iota.commands.core.get_neighbors import GetNeighborsCommand
+from test import patch, MagicMock
class GetNeighborsRequestFilterTestCase(BaseFilterTestCase):
@@ -49,8 +50,21 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).getNeighbors,
- GetNeighborsCommand,
- )
+ with patch('iota.commands.core.get_neighbors.GetNeighborsCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.get_neighbors()
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
diff --git a/test/commands/core/get_node_api_configuration_test.py b/test/commands/core/get_node_api_configuration_test.py
index bee9e7a7..9f154873 100644
--- a/test/commands/core/get_node_api_configuration_test.py
+++ b/test/commands/core/get_node_api_configuration_test.py
@@ -10,6 +10,7 @@
from iota import Iota
from iota.adapter import MockAdapter
from iota.commands.core import GetNodeAPIConfigurationCommand
+from test import patch, MagicMock
class GetNodeAPIConfigurationRequestFilterTestCase(BaseFilterTestCase):
@@ -53,8 +54,21 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).getNodeAPIConfiguration,
- GetNodeAPIConfigurationCommand,
- )
+ with patch('iota.commands.core.get_node_api_configuration.GetNodeAPIConfigurationCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.get_node_api_configuration()
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
diff --git a/test/commands/core/get_node_info_test.py b/test/commands/core/get_node_info_test.py
index 00a34021..9927ed74 100644
--- a/test/commands/core/get_node_info_test.py
+++ b/test/commands/core/get_node_info_test.py
@@ -9,6 +9,7 @@
from iota import Iota, TransactionHash
from iota.adapter import MockAdapter
from iota.commands.core.get_node_info import GetNodeInfoCommand
+from test import patch, MagicMock
class GetNodeInfoRequestFilterTestCase(BaseFilterTestCase):
@@ -122,8 +123,21 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).getNodeInfo,
- GetNodeInfoCommand,
- )
+ with patch('iota.commands.core.get_node_info.GetNodeInfoCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.get_node_info()
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
diff --git a/test/commands/core/get_tips_test.py b/test/commands/core/get_tips_test.py
index 03cc9a89..5dfb191d 100644
--- a/test/commands/core/get_tips_test.py
+++ b/test/commands/core/get_tips_test.py
@@ -11,6 +11,7 @@
from iota.adapter import MockAdapter
from iota.commands.core.get_tips import GetTipsCommand
from iota.transaction.types import TransactionHash
+from test import patch, MagicMock
class GetTipsRequestFilterTestCase(BaseFilterTestCase):
@@ -120,11 +121,24 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).getTips,
- GetTipsCommand,
- )
+ with patch('iota.commands.core.get_tips.GetTipsCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.get_tips()
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
def test_type_coercion(self):
"""
diff --git a/test/commands/core/get_transactions_to_approve_test.py b/test/commands/core/get_transactions_to_approve_test.py
index 89559bf0..b5158000 100644
--- a/test/commands/core/get_transactions_to_approve_test.py
+++ b/test/commands/core/get_transactions_to_approve_test.py
@@ -11,6 +11,7 @@
from iota.commands.core.get_transactions_to_approve import \
GetTransactionsToApproveCommand
from iota.filters import Trytes
+from test import patch, MagicMock
class GetTransactionsToApproveRequestFilterTestCase(BaseFilterTestCase):
@@ -218,17 +219,30 @@ def test_pass_happy_path(self):
)
-class GetTransactionsToApproveTestCase(TestCase):
+class GetTransactionsToApproveCommandTestCase(TestCase):
def setUp(self):
- super(GetTransactionsToApproveTestCase, self).setUp()
+ super(GetTransactionsToApproveCommandTestCase, self).setUp()
self.adapter = MockAdapter()
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).getTransactionsToApprove,
- GetTransactionsToApproveCommand,
- )
+ with patch('iota.commands.core.get_transactions_to_approve.GetTransactionsToApproveCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.get_transactions_to_approve('depth')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
diff --git a/test/commands/core/get_trytes_test.py b/test/commands/core/get_trytes_test.py
index 7d6c2844..2cf36bb0 100644
--- a/test/commands/core/get_trytes_test.py
+++ b/test/commands/core/get_trytes_test.py
@@ -11,6 +11,7 @@
from iota.adapter import MockAdapter
from iota.commands.core.get_trytes import GetTrytesCommand
from iota.filters import Trytes
+from test import patch, MagicMock
class GetTrytesRequestFilterTestCase(BaseFilterTestCase):
@@ -242,8 +243,21 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).getTrytes,
- GetTrytesCommand,
- )
+ with patch('iota.commands.core.get_trytes.GetTrytesCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.get_trytes('hashes')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
diff --git a/test/commands/core/interrupt_attaching_to_tangle_test.py b/test/commands/core/interrupt_attaching_to_tangle_test.py
index 4580b867..3bcb8c76 100644
--- a/test/commands/core/interrupt_attaching_to_tangle_test.py
+++ b/test/commands/core/interrupt_attaching_to_tangle_test.py
@@ -10,6 +10,7 @@
from iota.adapter import MockAdapter
from iota.commands.core.interrupt_attaching_to_tangle import \
InterruptAttachingToTangleCommand
+from test import patch, MagicMock
class InterruptAttachingToTangleRequestFilterTestCase(BaseFilterTestCase):
@@ -48,8 +49,21 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).interruptAttachingToTangle,
- InterruptAttachingToTangleCommand,
- )
+ with patch('iota.commands.core.interrupt_attaching_to_tangle.InterruptAttachingToTangleCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.interrupt_attaching_to_tangle()
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
diff --git a/test/commands/core/remove_neighbors_test.py b/test/commands/core/remove_neighbors_test.py
index b05c532f..32ca749e 100644
--- a/test/commands/core/remove_neighbors_test.py
+++ b/test/commands/core/remove_neighbors_test.py
@@ -10,6 +10,7 @@
from iota.adapter import MockAdapter
from iota.commands.core.remove_neighbors import RemoveNeighborsCommand
from iota.filters import NodeUri
+from test import patch, MagicMock
class RemoveNeighborsRequestFilterTestCase(BaseFilterTestCase):
@@ -153,8 +154,21 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).removeNeighbors,
- RemoveNeighborsCommand,
- )
+ with patch('iota.commands.core.remove_neighbors.RemoveNeighborsCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.remove_neighbors('uris')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
diff --git a/test/commands/core/store_transactions_test.py b/test/commands/core/store_transactions_test.py
index 57e20457..b1a87d1f 100644
--- a/test/commands/core/store_transactions_test.py
+++ b/test/commands/core/store_transactions_test.py
@@ -12,6 +12,7 @@
from iota.adapter import MockAdapter
from iota.commands.core.store_transactions import StoreTransactionsCommand
from iota.filters import Trytes
+from test import patch, MagicMock
class StoreTransactionsRequestFilterTestCase(BaseFilterTestCase):
@@ -187,8 +188,21 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).storeTransactions,
- StoreTransactionsCommand,
- )
+ with patch('iota.commands.core.store_transactions.StoreTransactionsCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.store_transactions('trytes')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
diff --git a/test/commands/core/were_addresses_spent_from_test.py b/test/commands/core/were_addresses_spent_from_test.py
index 4fd482e1..399a197b 100644
--- a/test/commands/core/were_addresses_spent_from_test.py
+++ b/test/commands/core/were_addresses_spent_from_test.py
@@ -11,6 +11,7 @@
from iota.adapter import MockAdapter
from iota.commands.core import WereAddressesSpentFromCommand
from iota.filters import Trytes
+from test import patch, MagicMock
class WereAddressesSpentFromRequestFilterTestCase(BaseFilterTestCase):
@@ -169,8 +170,21 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).wereAddressesSpentFrom,
- WereAddressesSpentFromCommand,
- )
+ with patch('iota.commands.core.were_addresses_spent_from.WereAddressesSpentFromCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.were_addresses_spent_from('addresses')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
diff --git a/test/commands/extended/broadcast_and_store_test.py b/test/commands/extended/broadcast_and_store_test.py
index 6e02dd27..9354784e 100644
--- a/test/commands/extended/broadcast_and_store_test.py
+++ b/test/commands/extended/broadcast_and_store_test.py
@@ -9,6 +9,7 @@
from iota import Iota, TransactionTrytes
from iota.adapter import MockAdapter
from iota.commands.extended.broadcast_and_store import BroadcastAndStoreCommand
+from test import patch, MagicMock
class BroadcastAndStoreCommandTestCase(TestCase):
@@ -27,11 +28,24 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).broadcastAndStore,
- BroadcastAndStoreCommand,
- )
+ with patch('iota.commands.extended.broadcast_and_store.BroadcastAndStoreCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.broadcast_and_store('trytes')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
def test_happy_path(self):
"""
diff --git a/test/commands/extended/broadcast_bundle_test.py b/test/commands/extended/broadcast_bundle_test.py
index b6014ac7..3d047801 100644
--- a/test/commands/extended/broadcast_bundle_test.py
+++ b/test/commands/extended/broadcast_bundle_test.py
@@ -12,13 +12,8 @@
from iota.adapter import MockAdapter
from iota.commands.extended.broadcast_bundle import BroadcastBundleCommand
from iota.filters import Trytes
+from test import patch, MagicMock
-from six import PY2
-
-if PY2:
- from mock import MagicMock, patch
-else:
- from unittest.mock import MagicMock, patch
# RequestFilterTestCase code reused from get_bundles_test.py
class BroadcastBundleRequestFilterTestCase(BaseFilterTestCase):
@@ -148,11 +143,24 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).broadcastBundle,
- BroadcastBundleCommand,
- )
+ with patch('iota.commands.extended.broadcast_bundle.BroadcastBundleCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.broadcast_bundle('trytes')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
def test_happy_path(self):
"""
diff --git a/test/commands/extended/find_transaction_objects.py b/test/commands/extended/find_transaction_objects.py
index a98b97c7..e87b3805 100644
--- a/test/commands/extended/find_transaction_objects.py
+++ b/test/commands/extended/find_transaction_objects.py
@@ -4,10 +4,9 @@
from unittest import TestCase
-import mock
-
from iota import Iota, MockAdapter, Transaction
from iota.commands.extended import FindTransactionObjectsCommand
+from test import patch, MagicMock, mock
class FindTransactionObjectsCommandTestCase(TestCase):
@@ -72,11 +71,24 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).findTransactionObjects,
- FindTransactionObjectsCommand,
- )
+ with patch('iota.commands.extended.find_transaction_objects.FindTransactionObjectsCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.find_transaction_objects('bundle')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
def test_transaction_found(self):
"""
diff --git a/test/commands/extended/get_account_data_test.py b/test/commands/extended/get_account_data_test.py
index 649ac39f..1a0e524a 100644
--- a/test/commands/extended/get_account_data_test.py
+++ b/test/commands/extended/get_account_data_test.py
@@ -15,6 +15,7 @@
from iota.crypto.types import Seed
from iota.filters import Trytes
from test import mock
+from test import patch, MagicMock
class GetAccountDataRequestFilterTestCase(BaseFilterTestCase):
@@ -362,11 +363,24 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).getAccountData,
- GetAccountDataCommand,
- )
+ with patch('iota.commands.extended.get_account_data.GetAccountDataCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.get_account_data()
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
def test_happy_path(self):
"""
diff --git a/test/commands/extended/get_bundles_test.py b/test/commands/extended/get_bundles_test.py
index 2a1de500..4d596fb4 100644
--- a/test/commands/extended/get_bundles_test.py
+++ b/test/commands/extended/get_bundles_test.py
@@ -12,6 +12,7 @@
from iota.adapter import MockAdapter
from iota.commands.extended.get_bundles import GetBundlesCommand
from iota.filters import Trytes
+from test import patch, MagicMock
class GetBundlesRequestFilterTestCase(BaseFilterTestCase):
@@ -274,12 +275,25 @@ def setUp(self):
def test_wireup(self):
"""
- Verifies that the command is wired up correctly.
+ Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).getBundles,
- GetBundlesCommand,
- )
+ with patch('iota.commands.extended.get_bundles.GetBundlesCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.get_bundles('transaction')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
def test_happy_path(self):
"""
diff --git a/test/commands/extended/get_inputs_test.py b/test/commands/extended/get_inputs_test.py
index ee3594ab..439a687f 100644
--- a/test/commands/extended/get_inputs_test.py
+++ b/test/commands/extended/get_inputs_test.py
@@ -14,6 +14,7 @@
from iota.crypto.types import Seed
from iota.filters import Trytes
from test import mock
+from test import patch, MagicMock
class GetInputsRequestFilterTestCase(BaseFilterTestCase):
@@ -441,11 +442,24 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).getInputs,
- GetInputsCommand,
- )
+ with patch('iota.commands.extended.get_inputs.GetInputsCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.get_inputs()
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
def test_stop_threshold_met(self):
"""
diff --git a/test/commands/extended/get_latest_inclusion_test.py b/test/commands/extended/get_latest_inclusion_test.py
index 375f631e..4680693d 100644
--- a/test/commands/extended/get_latest_inclusion_test.py
+++ b/test/commands/extended/get_latest_inclusion_test.py
@@ -12,6 +12,7 @@
from iota.commands.extended.get_latest_inclusion import \
GetLatestInclusionCommand
from iota.filters import Trytes
+from test import patch, MagicMock
class GetLatestInclusionRequestFilterTestCase(BaseFilterTestCase):
@@ -204,11 +205,24 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).getLatestInclusion,
- GetLatestInclusionCommand,
- )
+ with patch('iota.commands.extended.get_latest_inclusion.GetLatestInclusionCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.get_latest_inclusion('hashes')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
def test_happy_path(self):
"""
diff --git a/test/commands/extended/get_new_addresses_test.py b/test/commands/extended/get_new_addresses_test.py
index 53730e78..bf14b0a1 100644
--- a/test/commands/extended/get_new_addresses_test.py
+++ b/test/commands/extended/get_new_addresses_test.py
@@ -13,6 +13,7 @@
from iota.crypto.addresses import AddressGenerator
from iota.crypto.types import Seed
from iota.filters import Trytes
+from test import patch, MagicMock
class GetNewAddressesRequestFilterTestCase(BaseFilterTestCase):
@@ -365,11 +366,24 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).getNewAddresses,
- GetNewAddressesCommand,
- )
+ with patch('iota.commands.extended.get_new_addresses.GetNewAddressesCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.get_new_addresses('hashes')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
def test_get_addresses_offline(self):
"""
diff --git a/test/commands/extended/get_transaction_objects_test.py b/test/commands/extended/get_transaction_objects_test.py
index 16fddbce..552889a4 100644
--- a/test/commands/extended/get_transaction_objects_test.py
+++ b/test/commands/extended/get_transaction_objects_test.py
@@ -4,10 +4,9 @@
from unittest import TestCase
-import mock
-
from iota import Iota, MockAdapter, Transaction
from iota.commands.extended import GetTransactionObjectsCommand
+from test import patch, MagicMock, mock
class GetTransactionObjectsCommandTestCase(TestCase):
@@ -71,11 +70,24 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).getTransactionObjects,
- GetTransactionObjectsCommand,
- )
+ with patch('iota.commands.extended.get_transaction_objects.GetTransactionObjectsCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.get_transaction_objects('hashes')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
def test_transaction_found(self):
"""
diff --git a/test/commands/extended/get_transfers_test.py b/test/commands/extended/get_transfers_test.py
index 4b64d707..7373daf4 100644
--- a/test/commands/extended/get_transfers_test.py
+++ b/test/commands/extended/get_transfers_test.py
@@ -15,6 +15,7 @@
from iota.crypto.types import Seed
from iota.filters import Trytes
from test import mock
+from test import patch, MagicMock
class GetTransfersRequestFilterTestCase(BaseFilterTestCase):
@@ -339,12 +340,24 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).getTransfers,
- GetTransfersCommand,
- )
+ with patch('iota.commands.extended.get_transfers.GetTransfersCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+ # Don't need to call with proper args here.
+ response = api.get_transfers()
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
def test_full_scan(self):
"""
Scanning the Tangle for all transfers.
diff --git a/test/commands/extended/is_promotable_test.py b/test/commands/extended/is_promotable_test.py
index ad991789..cc1506a3 100644
--- a/test/commands/extended/is_promotable_test.py
+++ b/test/commands/extended/is_promotable_test.py
@@ -14,6 +14,7 @@
get_current_ms, is_within_depth, MILESTONE_INTERVAL, ONE_WAY_DELAY
from iota.filters import Trytes
from test import mock
+from test import patch, MagicMock
class IsPromotableRequestFilterTestCase(BaseFilterTestCase):
filter_type = IsPromotableCommand(MockAdapter()).get_request_filter
@@ -290,11 +291,24 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).isPromotable,
- IsPromotableCommand,
- )
+ with patch('iota.commands.extended.is_promotable.IsPromotableCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.is_promotable('tails')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
def test_happy_path(self):
"""
diff --git a/test/commands/extended/is_reattachable_test.py b/test/commands/extended/is_reattachable_test.py
index edef5fd5..2800b069 100644
--- a/test/commands/extended/is_reattachable_test.py
+++ b/test/commands/extended/is_reattachable_test.py
@@ -11,6 +11,7 @@
from iota import Address, Iota
from iota.adapter import MockAdapter
from iota.commands.extended.is_reattachable import IsReattachableCommand
+from test import patch, MagicMock
class IsReattachableRequestFilterTestCase(BaseFilterTestCase):
@@ -199,8 +200,21 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).isReattachable,
- IsReattachableCommand,
- )
+ with patch('iota.commands.extended.is_reattachable.IsReattachableCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.is_reattachable('addresses')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
diff --git a/test/commands/extended/prepare_transfer_test.py b/test/commands/extended/prepare_transfer_test.py
index 35e0f9df..0a6c46b6 100644
--- a/test/commands/extended/prepare_transfer_test.py
+++ b/test/commands/extended/prepare_transfer_test.py
@@ -16,6 +16,7 @@
from iota.crypto.types import Seed
from iota.filters import GeneratedAddress, Trytes
from test import mock
+from test import patch, MagicMock
class PrepareTransferRequestFilterTestCase(BaseFilterTestCase):
@@ -576,11 +577,24 @@ def get_current_timestamp():
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).prepareTransfer,
- PrepareTransferCommand,
- )
+ with patch('iota.commands.extended.prepare_transfer.PrepareTransferCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.prepare_transfer('transfers')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
def test_pass_inputs_not_needed(self):
"""
diff --git a/test/commands/extended/promote_transaction_test.py b/test/commands/extended/promote_transaction_test.py
index 21f5b815..e732ae4f 100644
--- a/test/commands/extended/promote_transaction_test.py
+++ b/test/commands/extended/promote_transaction_test.py
@@ -13,6 +13,7 @@
from iota.commands.extended.promote_transaction import PromoteTransactionCommand
from iota.filters import Trytes
from test import mock
+from test import patch, MagicMock
class PromoteTransactionRequestFilterTestCase(BaseFilterTestCase):
@@ -311,12 +312,25 @@ def setUp(self):
def test_wireup(self):
"""
- Verifies that the command is wired-up correctly.
+ Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).promoteTransaction,
- PromoteTransactionCommand,
- )
+ with patch('iota.commands.extended.promote_transaction.PromoteTransactionCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.promote_transaction('transaction')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
def test_happy_path(self):
"""
diff --git a/test/commands/extended/replay_bundle_test.py b/test/commands/extended/replay_bundle_test.py
index b6079bfd..858e038b 100644
--- a/test/commands/extended/replay_bundle_test.py
+++ b/test/commands/extended/replay_bundle_test.py
@@ -14,6 +14,7 @@
from iota.commands.extended.replay_bundle import ReplayBundleCommand
from iota.filters import Trytes
from test import mock
+from test import patch, MagicMock
class ReplayBundleRequestFilterTestCase(BaseFilterTestCase):
@@ -303,12 +304,25 @@ def setUp(self):
def test_wireup(self):
"""
- Verifies that the command is wired-up correctly.
+ Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).replayBundle,
- ReplayBundleCommand,
- )
+ with patch('iota.commands.extended.replay_bundle.ReplayBundleCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.replay_bundle('transaction')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
def test_happy_path(self):
"""
diff --git a/test/commands/extended/send_transfer_test.py b/test/commands/extended/send_transfer_test.py
index aaedac8d..8a277c0e 100644
--- a/test/commands/extended/send_transfer_test.py
+++ b/test/commands/extended/send_transfer_test.py
@@ -16,6 +16,7 @@
from iota.crypto.types import Seed
from iota.filters import Trytes
from test import mock
+from test import patch, MagicMock
class SendTransferRequestFilterTestCase(BaseFilterTestCase):
@@ -671,12 +672,25 @@ def setUp(self):
def test_wireup(self):
"""
- Verifies that the command is wired up correctly.
+ Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).sendTransfer,
- SendTransferCommand,
- )
+ with patch('iota.commands.extended.send_transfer.SendTransferCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.send_transfer('transfers')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
def test_happy_path(self):
"""
diff --git a/test/commands/extended/send_trytes_test.py b/test/commands/extended/send_trytes_test.py
index b2d4d02e..70301806 100644
--- a/test/commands/extended/send_trytes_test.py
+++ b/test/commands/extended/send_trytes_test.py
@@ -12,6 +12,7 @@
from iota.adapter import MockAdapter
from iota.commands.extended.send_trytes import SendTrytesCommand
from iota.filters import Trytes
+from test import patch, MagicMock
class SendTrytesRequestFilterTestCase(BaseFilterTestCase):
@@ -371,11 +372,24 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).sendTrytes,
- SendTrytesCommand,
- )
+ with patch('iota.commands.extended.send_trytes.SendTrytesCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.send_trytes('trytes')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
def test_happy_path(self):
"""
diff --git a/test/commands/extended/traverse_bundle_test.py b/test/commands/extended/traverse_bundle_test.py
index e700c776..f28066fd 100644
--- a/test/commands/extended/traverse_bundle_test.py
+++ b/test/commands/extended/traverse_bundle_test.py
@@ -12,7 +12,7 @@
from iota.adapter import MockAdapter
from iota.commands.extended.traverse_bundle import TraverseBundleCommand
from iota.filters import Trytes
-
+from test import patch, MagicMock
# Same tests as for GetBundlesRequestFilter (it is the same filter)
class TraverseBundleRequestFilterTestCase(BaseFilterTestCase):
@@ -129,12 +129,25 @@ def setUp(self):
def test_wireup(self):
"""
- Verifies that the command is wired up correctly.
+ Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- Iota(self.adapter).traverseBundle,
- TraverseBundleCommand,
- )
+ with patch('iota.commands.extended.traverse_bundle.TraverseBundleCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = Iota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.traverse_bundle('tail')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
def test_single_transaction(self):
"""
diff --git a/test/multisig/commands/create_multisig_address_test.py b/test/multisig/commands/create_multisig_address_test.py
index 301fd9eb..be7f3adc 100644
--- a/test/multisig/commands/create_multisig_address_test.py
+++ b/test/multisig/commands/create_multisig_address_test.py
@@ -15,6 +15,7 @@
from iota.multisig import MultisigIota
from iota.multisig.commands import CreateMultisigAddressCommand
from iota.multisig.types import MultisigAddress
+from test import patch, MagicMock
class CreateMultisigAddressCommandTestCase(TestCase):
@@ -49,11 +50,24 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- MultisigIota(self.adapter).createMultisigAddress,
- CreateMultisigAddressCommand,
- )
+ with patch('iota.multisig.commands.create_multisig_address.CreateMultisigAddressCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = MultisigIota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.create_multisig_address('digests')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
def test_happy_path(self):
"""
diff --git a/test/multisig/commands/get_digests_test.py b/test/multisig/commands/get_digests_test.py
index fa96c477..daa88c20 100644
--- a/test/multisig/commands/get_digests_test.py
+++ b/test/multisig/commands/get_digests_test.py
@@ -16,7 +16,7 @@
from iota.filters import Trytes
from iota.multisig import MultisigIota
from iota.multisig.commands import GetDigestsCommand
-from test import mock
+from test import mock, patch, MagicMock
class GetDigestsCommandTestCase(TestCase):
@@ -37,11 +37,24 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- MultisigIota(self.adapter).getDigests,
- GetDigestsCommand,
- )
+ with patch('iota.multisig.commands.get_digests.GetDigestsCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = MultisigIota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.get_digests()
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
def test_generate_single_digest(self):
"""
diff --git a/test/multisig/commands/get_private_keys_test.py b/test/multisig/commands/get_private_keys_test.py
index c68d5fb4..a6dc7d54 100644
--- a/test/multisig/commands/get_private_keys_test.py
+++ b/test/multisig/commands/get_private_keys_test.py
@@ -16,7 +16,7 @@
from iota.filters import Trytes
from iota.multisig import MultisigIota
from iota.multisig.commands import GetPrivateKeysCommand
-from test import mock
+from test import mock, patch, MagicMock
class GetPrivateKeysCommandTestCase(TestCase):
@@ -41,11 +41,24 @@ def setUp(self):
def test_wireup(self):
"""
Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- MultisigIota(self.adapter).getPrivateKeys,
- GetPrivateKeysCommand,
- )
+ with patch('iota.multisig.commands.get_private_keys.GetPrivateKeysCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = MultisigIota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.get_private_keys()
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
def test_generate_single_key(self):
"""
diff --git a/test/multisig/commands/prepare_multisig_transfer_test.py b/test/multisig/commands/prepare_multisig_transfer_test.py
index 9cb01990..bbf4ac6b 100644
--- a/test/multisig/commands/prepare_multisig_transfer_test.py
+++ b/test/multisig/commands/prepare_multisig_transfer_test.py
@@ -14,6 +14,7 @@
from iota.multisig import MultisigIota
from iota.multisig.commands import PrepareMultisigTransferCommand
from iota.multisig.types import MultisigAddress
+from test import patch, MagicMock
class PrepareMultisigTransferRequestFilterTestCase(BaseFilterTestCase):
@@ -526,12 +527,25 @@ def setUp(self):
def test_wireup(self):
"""
- Verifies the command is wired up correctly.
+ Verify that the command is wired up correctly.
+
+ The API method indeed calls the appropiate command.
"""
- self.assertIsInstance(
- MultisigIota(self.adapter).prepareMultisigTransfer,
- PrepareMultisigTransferCommand,
- )
+ with patch('iota.multisig.commands.prepare_multisig_transfer.PrepareMultisigTransferCommand.__call__',
+ MagicMock(return_value='You found me!')
+ ) as mocked_command:
+
+ api = MultisigIota(self.adapter)
+
+ # Don't need to call with proper args here.
+ response = api.prepare_multisig_transfer('transfer', 'multisig_input')
+
+ self.assertTrue(mocked_command.called)
+
+ self.assertEqual(
+ response,
+ 'You found me!'
+ )
def test_happy_path(self):
"""