From 29e01ff9dee71f80a3d91b3cc6912a409b04a608 Mon Sep 17 00:00:00 2001 From: Levente Pap Date: Fri, 13 Mar 2020 13:05:17 +0100 Subject: [PATCH 1/3] Introduce Type Annotations - Remove type hints. - Follow PEP-484 and PEP-8. --- iota/__init__.py | 8 +- iota/adapter/__init__.py | 102 ++-- iota/adapter/wrappers.py | 27 +- iota/api.py | 475 +++++++++--------- iota/api_async.py | 394 ++++++++------- iota/bin/__init__.py | 30 +- iota/bin/repl.py | 11 +- iota/codecs.py | 18 +- iota/commands/__init__.py | 54 +- iota/commands/core/add_neighbors.py | 2 +- iota/commands/core/attach_to_tangle.py | 9 +- iota/commands/core/broadcast_transactions.py | 2 +- iota/commands/core/check_consistency.py | 2 +- iota/commands/core/find_transactions.py | 10 +- iota/commands/core/get_balances.py | 10 +- iota/commands/core/get_inclusion_states.py | 2 +- .../commands/core/get_missing_transactions.py | 4 +- iota/commands/core/get_neighbors.py | 2 +- .../core/get_node_api_configuration.py | 2 +- iota/commands/core/get_node_info.py | 4 +- iota/commands/core/get_tips.py | 4 +- .../core/get_transactions_to_approve.py | 10 +- iota/commands/core/get_trytes.py | 4 +- .../core/interrupt_attaching_to_tangle.py | 2 +- iota/commands/core/remove_neighbors.py | 2 +- iota/commands/core/store_transactions.py | 2 +- .../core/were_addresses_spent_from.py | 2 +- iota/commands/extended/broadcast_and_store.py | 4 +- iota/commands/extended/broadcast_bundle.py | 14 +- .../extended/find_transaction_objects.py | 24 +- iota/commands/extended/get_account_data.py | 20 +- iota/commands/extended/get_bundles.py | 9 +- iota/commands/extended/get_inputs.py | 16 +- .../commands/extended/get_latest_inclusion.py | 8 +- iota/commands/extended/get_new_addresses.py | 26 +- .../extended/get_transaction_objects.py | 17 +- iota/commands/extended/get_transfers.py | 14 +- iota/commands/extended/is_promotable.py | 32 +- iota/commands/extended/is_reattachable.py | 12 +- iota/commands/extended/prepare_transfer.py | 18 +- iota/commands/extended/promote_transaction.py | 12 +- iota/commands/extended/replay_bundle.py | 14 +- iota/commands/extended/send_transfer.py | 22 +- iota/commands/extended/send_trytes.py | 14 +- iota/commands/extended/traverse_bundle.py | 23 +- iota/commands/extended/utils.py | 32 +- iota/crypto/addresses.py | 40 +- iota/crypto/kerl/conv.py | 23 +- iota/crypto/kerl/pykerl.py | 22 +- iota/crypto/pycurl.py | 29 +- iota/crypto/signing.py | 160 +++--- iota/crypto/types.py | 41 +- iota/exceptions.py | 3 +- iota/filters.py | 20 +- iota/multisig/api.py | 68 ++- .../commands/create_multisig_address.py | 10 +- iota/multisig/commands/get_digests.py | 16 +- iota/multisig/commands/get_private_keys.py | 16 +- .../commands/prepare_multisig_transfer.py | 104 ++-- iota/multisig/crypto/addresses.py | 12 +- iota/multisig/transaction.py | 3 +- iota/multisig/types.py | 13 +- iota/transaction/base.py | 255 +++++----- iota/transaction/creation.py | 89 ++-- iota/transaction/types.py | 9 +- iota/transaction/utils.py | 6 +- iota/transaction/validator.py | 30 +- iota/trits.py | 21 +- iota/types.py | 170 +++---- 69 files changed, 1354 insertions(+), 1331 deletions(-) diff --git a/iota/__init__.py b/iota/__init__.py index 2d1c26e..e311054 100644 --- a/iota/__init__.py +++ b/iota/__init__.py @@ -1,12 +1,14 @@ # Define a few magic constants. -DEFAULT_PORT = 14265 +from typing import Dict, Text + +DEFAULT_PORT: int = 14265 """ Default port to use when configuring an adapter, if the port is not specified. """ -TRITS_PER_TRYTE = 3 +TRITS_PER_TRYTE: int = 3 """ Number of trits in a tryte. Changing this will probably break everything, but there's a chance it @@ -14,7 +16,7 @@ In that way, it's kind of like toxic waste in a superhero story. """ -STANDARD_UNITS = { +STANDARD_UNITS: Dict[Text, int] = { # Valid IOTA unit suffixes. Example value '-273.15 Ki' 'i': 1, 'Ki': 1000, diff --git a/iota/adapter/__init__.py b/iota/adapter/__init__.py index d6a7a32..f155310 100644 --- a/iota/adapter/__init__.py +++ b/iota/adapter/__init__.py @@ -1,11 +1,12 @@ import json from abc import ABCMeta, abstractmethod as abstract_method +from asyncio import Future from collections import deque from inspect import isabstract as is_abstract from logging import DEBUG, Logger from socket import getdefaulttimeout as get_default_timeout -from typing import Container, Dict, List, Optional, Text, Tuple, Union +from typing import Container, Dict, List, Optional, Text, Tuple, Union, Any from httpx import AsyncClient, Response, codes, auth import asyncio @@ -42,7 +43,8 @@ # Load SplitResult for IDE type hinting and autocompletion. from urllib.parse import SplitResult, urlsplit -def async_return(result): + +def async_return(result: Any) -> Future: """ Turns 'result' into a `Future` object with 'result' value. @@ -52,6 +54,7 @@ def async_return(result): f.set_result(result) return f + class BadApiResponse(ValueError): """ Indicates that a non-success response was received from the node. @@ -66,21 +69,20 @@ class InvalidUri(ValueError): pass -adapter_registry = {} # type: Dict[Text, AdapterMeta] +adapter_registry: Dict[Text, 'AdapterMeta'] = {} """ Keeps track of available adapters and their supported protocols. """ -def resolve_adapter(uri): - # type: (AdapterSpec) -> BaseAdapter +def resolve_adapter(uri: AdapterSpec) -> 'BaseAdapter': """ Given a URI, returns a properly-configured adapter instance. """ if isinstance(uri, BaseAdapter): return uri - parsed = urlsplit(uri) # type: SplitResult + parsed: SplitResult = urlsplit(uri) if not parsed.scheme: raise with_context( @@ -116,7 +118,7 @@ class AdapterMeta(ABCMeta): Automatically registers new adapter classes in ``adapter_registry``. """ - def __init__(cls, what, bases=None, dict=None): + def __init__(cls, what, bases=None, dict=None) -> None: super(AdapterMeta, cls).__init__(what, bases, dict) if not is_abstract(cls): @@ -125,8 +127,7 @@ def __init__(cls, what, bases=None, dict=None): # adapters. adapter_registry.setdefault(protocol, cls) - def configure(cls, parsed): - # type: (Union[Text, SplitResult]) -> HttpAdapter + def configure(cls, parsed: Union[Text, SplitResult]) -> 'HttpAdapter': """ Creates a new instance using the specified URI. @@ -143,21 +144,20 @@ class BaseAdapter(object, metaclass=AdapterMeta): Adapters make it easy to customize the way an API instance communicates with a node. """ - supported_protocols = () # type: Tuple[Text] + supported_protocols: Tuple[Text] = () """ Protocols that ``resolve_adapter`` can use to identify this adapter type. """ - def __init__(self): + def __init__(self) -> None: super(BaseAdapter, self).__init__() - self._logger = None # type: Logger - self.local_pow = False # type: boolean + self._logger: Logger = None + self.local_pow: bool = False @abstract_method - def get_uri(self): - # type: () -> Text + def get_uri(self) -> Text: """ Returns the URI that this adapter will use. """ @@ -166,8 +166,7 @@ def get_uri(self): ) @abstract_method - def send_request(self, payload, **kwargs): - # type: (dict, dict) -> dict + def send_request(self, payload: Dict, **kwargs: Dict) -> Dict: """ Sends an API request to the node. @@ -188,8 +187,7 @@ def send_request(self, payload, **kwargs): 'Not implemented in {cls}.'.format(cls=type(self).__name__), ) - def set_logger(self, logger): - # type: (Logger) -> BaseAdapter + def set_logger(self, logger: Logger) -> 'BaseAdapter': """ Attaches a logger instance to the adapter. The adapter will send information about API requests/responses @@ -198,16 +196,19 @@ def set_logger(self, logger): self._logger = logger return self - def _log(self, level, message, context=None): - # type: (int, Text, Optional[dict]) -> None + def _log( + self, + level: int, + message: Text, + context: Optional[int] = None + ) -> None: """ Sends a message to the instance's logger, if configured. """ if self._logger: self._logger.log(level, message, extra={'context': context or {}}) - def set_local_pow(self, local_pow): - # type: (bool) -> None + def set_local_pow(self, local_pow: bool) -> None: """ Sets the local_pow attribute of the adapter. If it is true, attach_to_tangle command calls external interface to perform @@ -216,6 +217,7 @@ def set_local_pow(self, local_pow): """ self.local_pow = local_pow + class HttpAdapter(BaseAdapter): """ Sends standard HTTP(S) requests to the node. @@ -257,8 +259,12 @@ class HttpAdapter(BaseAdapter): in the ``headers`` kwarg. """ - def __init__(self, uri, timeout=None, authentication=None): - # type: (Union[Text, SplitResult], Optional[int]) -> None + def __init__( + self, + uri: Union[Text, SplitResult], + timeout: Optional[int] = None, + authentication: Optional[Dict] = None + ) -> None: super(HttpAdapter, self).__init__() self.client = AsyncClient() @@ -266,7 +272,7 @@ def __init__(self, uri, timeout=None, authentication=None): self.authentication = authentication if isinstance(uri, str): - uri = urlsplit(uri) # type: SplitResult + uri: SplitResult = urlsplit(uri) if uri.scheme not in self.supported_protocols: raise with_context( @@ -310,19 +316,16 @@ def __init__(self, uri, timeout=None, authentication=None): self.uri = uri @property - def node_url(self): - # type: () -> Text + def node_url(self) -> Text: """ Returns the node URL. """ return self.uri.geturl() - def get_uri(self): - # type: () -> Text + def get_uri(self) -> Text: return self.uri.geturl() - async def send_request(self, payload, **kwargs): - # type: (dict, dict) -> dict + async def send_request(self, payload: Dict, **kwargs: Dict) -> Dict: kwargs.setdefault('headers', {}) for key, value in self.DEFAULT_HEADERS.items(): kwargs['headers'].setdefault(key, value) @@ -338,8 +341,13 @@ async def send_request(self, payload, **kwargs): return self._interpret_response(response, payload, {codes['OK']}) - async def _send_http_request(self, url, payload, method='post', **kwargs): - # type: (Text, Optional[Text], Text, dict) -> Response + async def _send_http_request( + self, + url: Text, + payload: Optional[Text], + method: Text = 'post', + **kwargs: Any + ) -> Response: """ Sends the actual HTTP request. @@ -352,7 +360,7 @@ async def _send_http_request(self, url, payload, method='post', **kwargs): ) if self.authentication: - kwargs.setdefault('auth', auth.HTTPBasicAuth(*self.authentication)) + kwargs.setdefault('auth', auth.BasicAuth(*self.authentication)) self._log( level=DEBUG, @@ -394,8 +402,12 @@ async def _send_http_request(self, url, payload, method='post', **kwargs): return response - def _interpret_response(self, response, payload, expected_status): - # type: (Response, dict, Container[int]) -> dict + def _interpret_response( + self, + response: Response, + payload: Dict, + expected_status: Container[Dict] + ) -> Dict: """ Interprets the HTTP response from the node. @@ -425,7 +437,7 @@ def _interpret_response(self, response, payload, expected_status): ) try: - decoded = json.loads(raw_content) # type: dict + decoded: Dict = json.loads(raw_content) # :bc: py2k doesn't have JSONDecodeError except ValueError: raise with_context( @@ -523,17 +535,16 @@ class MockAdapter(BaseAdapter): def configure(cls, uri): return cls() - def __init__(self): + def __init__(self) -> None: super(MockAdapter, self).__init__() - self.responses = {} # type: Dict[Text, deque] - self.requests = [] # type: List[dict] + self.responses: Dict[Text, deque] = {} + self.requests: List[dict] = [] - def get_uri(self): + def get_uri(self) -> Text: return 'mock://' - def seed_response(self, command, response): - # type: (Text, dict) -> MockAdapter + def seed_response(self, command: Text, response: Dict) -> 'MockAdapter': """ Sets the response that the adapter will return for the specified command. @@ -573,11 +584,10 @@ def seed_response(self, command, response): self.responses[command].append(response) return self - async def send_request(self, payload, **kwargs): + async def send_request(self, payload: Dict, **kwargs: Dict) -> Dict: """ Mimic asynchronous behavior of `HttpAdapter.send_request`. """ - # type: (dict, dict) -> dict # Store a snapshot so that we can inspect the request later. self.requests.append(dict(payload)) diff --git a/iota/adapter/wrappers.py b/iota/adapter/wrappers.py index d2a5f9b..c984373 100644 --- a/iota/adapter/wrappers.py +++ b/iota/adapter/wrappers.py @@ -14,22 +14,19 @@ class BaseWrapper(BaseAdapter, metaclass=ABCMeta): functionality of IOTA adapters. """ - def __init__(self, adapter): - # type: (AdapterSpec) -> None + def __init__(self, adapter: AdapterSpec) -> None: super(BaseWrapper, self).__init__() if not isinstance(adapter, BaseAdapter): adapter = resolve_adapter(adapter) - self.adapter = adapter # type: BaseAdapter + self.adapter: BaseAdapter = adapter - def get_uri(self): - # type: () -> Text + def get_uri(self) -> Text: return self.adapter.get_uri() @abstract_method - def send_request(self, payload, **kwargs): - # type: (dict, dict) -> dict + def send_request(self, payload: Dict, **kwargs: Dict) -> Dict: raise NotImplementedError( 'Not implemented in {cls}.'.format(cls=type(self).__name__), ) @@ -86,8 +83,7 @@ class RoutingWrapper(BaseWrapper): defined in :py:class:`RoutingWrapper`. """ - def __init__(self, default_adapter): - # type: (AdapterSpec) -> None + def __init__(self, default_adapter: AdapterSpec) -> None: """ :param default_adapter: Adapter to use for any routes not listed in ``routes``. @@ -96,12 +92,11 @@ def __init__(self, default_adapter): # Try to limit the number of distinct adapter instances we create # when resolving URIs. - self.adapter_aliases = {} # type: Dict[AdapterSpec, BaseAdapter] + self.adapter_aliases: Dict[AdapterSpec, BaseAdapter] = {} - self.routes = {} # type: Dict[Text, BaseAdapter] + self.routes: Dict[Text, BaseAdapter] = {} - def add_route(self, command, adapter): - # type: (Text, AdapterSpec) -> RoutingWrapper + def add_route(self, command: Text, adapter: AdapterSpec) -> 'RoutingWrapper': """ Adds a route to the wrapper. @@ -130,15 +125,13 @@ def add_route(self, command, adapter): return self - def get_adapter(self, command): - # type: (Text) -> BaseAdapter + def get_adapter(self, command: Text) -> BaseAdapter: """ Return the adapter for the specified command. """ return self.routes.get(command, self.adapter) - async def send_request(self, payload, **kwargs): - # type: (dict, dict) -> dict + async def send_request(self, payload: Dict, **kwargs: Dict) -> Dict: command = payload.get('command') return await self.get_adapter(command).send_request(payload, **kwargs) diff --git a/iota/api.py b/iota/api.py index 2c1a3e6..17ab405 100644 --- a/iota/api.py +++ b/iota/api.py @@ -1,7 +1,7 @@ from typing import Dict, Iterable, Optional, Text from iota import AdapterSpec, Address, BundleHash, ProposedTransaction, Tag, \ - TransactionHash, TransactionTrytes, TryteString + TransactionHash, TransactionTrytes, TryteString, TrytesCompatible from iota.crypto.addresses import AddressGenerator from iota.api_async import AsyncStrictIota, AsyncIota import asyncio @@ -19,6 +19,7 @@ class InvalidCommand(ValueError): """ pass + # There is a compact and easy way to create the synchronous version of the async # classes: @@ -72,8 +73,12 @@ class StrictIota(AsyncStrictIota): """ - def __init__(self, adapter, devnet=False, local_pow=False): - # type: (AdapterSpec, bool, bool) -> None + def __init__( + self, + adapter: AdapterSpec, + devnet: bool = False, + local_pow: bool = False + ) -> None: """ :param AdapterSpec adapter: URI string or BaseAdapter instance. @@ -93,8 +98,7 @@ def __init__(self, adapter, devnet=False, local_pow=False): """ super().__init__(adapter, devnet, local_pow) - def add_neighbors(self, uris): - # type: (Iterable[Text]) -> dict + def add_neighbors(self, uris: Iterable[Text]) -> Dict: """ Add one or more neighbors to the node. Lasts until the node is restarted. @@ -126,17 +130,16 @@ def add_neighbors(self, uris): # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().add_neighbors(uris) + super().add_neighbors(uris) ) def attach_to_tangle( self, - trunk_transaction, # type: TransactionHash - branch_transaction, # type: TransactionHash - trytes, # type: Iterable[TryteString] - min_weight_magnitude=None, # type: Optional[int] - ): - # type: (...) -> dict + trunk_transaction: TransactionHash, + branch_transaction: TransactionHash, + trytes: Iterable[TryteString], + min_weight_magnitude: Optional[int] = None, + ) -> Dict: """ Attaches the specified transactions (trytes) to the Tangle by doing Proof of Work. You need to supply branchTransaction as @@ -177,16 +180,15 @@ def attach_to_tangle( # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().attach_to_tangle( - trunk_transaction, - branch_transaction, - trytes, - min_weight_magnitude, - ) + super().attach_to_tangle( + trunk_transaction, + branch_transaction, + trytes, + min_weight_magnitude, + ) ) - def broadcast_transactions(self, trytes): - # type: (Iterable[TryteString]) -> dict + def broadcast_transactions(self, trytes: Iterable[TryteString]) -> Dict: """ Broadcast a list of transactions to all neighbors. @@ -212,13 +214,12 @@ def broadcast_transactions(self, trytes): # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().broadcast_transactions( - trytes, - ) + super().broadcast_transactions( + trytes, + ) ) - def check_consistency(self, tails): - # type: (Iterable[TransactionHash]) -> dict + def check_consistency(self, tails: Iterable[TransactionHash]) -> Dict: """ Used to ensure tail resolves to a consistent ledger which is necessary to validate before attempting promotion. Checks @@ -251,19 +252,18 @@ def check_consistency(self, tails): # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().check_consistency( - tails, - ) + super().check_consistency( + tails, + ) ) def find_transactions( self, - bundles=None, # type: Optional[Iterable[BundleHash]] - addresses=None, # type: Optional[Iterable[Address]] - tags=None, # type: Optional[Iterable[Tag]] - approvees=None, # type: Optional[Iterable[TransactionHash]] - ): - # type: (...) -> dict + bundles: Optional[Iterable[BundleHash]] = None, + addresses: Optional[Iterable[Address]] = None, + tags: Optional[Iterable[Tag]] = None, + approvees: Optional[Iterable[TransactionHash]] = None, + ) -> Dict: """ Find the transactions which match the specified input and return. @@ -303,21 +303,20 @@ def find_transactions( # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().find_transactions( - bundles, - addresses, - tags, - approvees, - ) + super().find_transactions( + bundles, + addresses, + tags, + approvees, + ) ) def get_balances( self, - addresses, # type: Iterable[Address] - threshold=100, # type: int - tips=None, # type: Optional[Iterable[TransactionHash]] - ): - # type: (...) -> dict + addresses: Iterable[Address], + threshold: int = 100, + tips: Optional[Iterable[TransactionHash]] = None, + ) -> Dict: """ Similar to :py:meth:`get_inclusion_states`. Returns the confirmed balance which a list of addresses have at the latest @@ -363,15 +362,18 @@ def get_balances( # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().get_balances( - addresses, - threshold, - tips, - ) + super().get_balances( + addresses, + threshold, + tips, + ) ) - def get_inclusion_states(self, transactions, tips): - # type: (Iterable[TransactionHash], Iterable[TransactionHash]) -> dict + def get_inclusion_states( + self, + transactions: Iterable[TransactionHash], + tips: Iterable[TransactionHash] + ) -> Dict: """ Get the inclusion states of a set of transactions. This is for determining if a transaction was accepted and confirmed by the @@ -406,14 +408,13 @@ def get_inclusion_states(self, transactions, tips): # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().get_inclusion_states( - transactions, - tips, - ) + super().get_inclusion_states( + transactions, + tips, + ) ) - def get_missing_transactions(self): - # type: () -> dict + def get_missing_transactions(self) -> Dict: """ Returns all transaction hashes that a node is currently requesting from its neighbors. @@ -436,11 +437,10 @@ def get_missing_transactions(self): # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().get_missing_transactions() + super().get_missing_transactions() ) - def get_neighbors(self): - # type: () -> dict + def get_neighbors(self) -> Dict: """ Returns the set of neighbors the node is connected with, as well as their activity count. @@ -474,11 +474,10 @@ def get_neighbors(self): # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().get_neighbors() + super().get_neighbors() ) - def get_node_api_configuration(self): - # type: () -> dict + def get_node_api_configuration(self) -> Dict: """ Returns a node's API configuration settings. @@ -503,11 +502,10 @@ def get_node_api_configuration(self): # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().get_node_api_configuration() + super().get_node_api_configuration() ) - def get_node_info(self): - # type: () -> dict + def get_node_info(self) -> Dict: """ Returns information about the node. @@ -567,11 +565,10 @@ def get_node_info(self): # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().get_node_info() + super().get_node_info() ) - def get_tips(self): - # type: () -> dict + def get_tips(self) -> Dict: """ Returns the list of tips (transactions which have no other transactions referencing them). @@ -595,11 +592,14 @@ def get_tips(self): # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().get_tips() + super().get_tips() ) - def get_transactions_to_approve(self, depth, reference=None): - # type: (int, Optional[TransactionHash]) -> dict + def get_transactions_to_approve( + self, + depth: int, + reference: Optional[TransactionHash] = None, + ) -> Dict: """ Tip selection which returns ``trunkTransaction`` and ``branchTransaction``. @@ -636,14 +636,13 @@ def get_transactions_to_approve(self, depth, reference=None): # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().get_transactions_to_approve( - depth, - reference, - ) + super().get_transactions_to_approve( + depth, + reference, + ) ) - def get_trytes(self, hashes): - # type: (Iterable[TransactionHash]) -> dict + def get_trytes(self, hashes: Iterable[TransactionHash]) -> Dict: """ Returns the raw transaction data (trytes) of one or more transactions. @@ -672,13 +671,12 @@ def get_trytes(self, hashes): # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().get_trytes( - hashes, - ) + super().get_trytes( + hashes, + ) ) - def interrupt_attaching_to_tangle(self): - # type: () -> dict + def interrupt_attaching_to_tangle(self) -> Dict: """ Interrupts and completely aborts the :py:meth:`attach_to_tangle` process. @@ -699,11 +697,10 @@ def interrupt_attaching_to_tangle(self): # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().interrupt_attaching_to_tangle() + super().interrupt_attaching_to_tangle() ) - def remove_neighbors(self, uris): - # type: (Iterable[Text]) -> dict + def remove_neighbors(self, uris: Iterable[Text]) -> Dict: """ Removes one or more neighbors from the node. Lasts until the node is restarted. @@ -730,11 +727,10 @@ def remove_neighbors(self, uris): # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().remove_neighbors(uris) + super().remove_neighbors(uris) ) - def store_transactions(self, trytes): - # type: (Iterable[TryteString]) -> dict + def store_transactions(self, trytes: Iterable[TryteString]) -> Dict: """ Store transactions into local storage of the node. @@ -762,11 +758,13 @@ def store_transactions(self, trytes): # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().store_transactions(trytes) + super().store_transactions(trytes) ) - def were_addresses_spent_from(self, addresses): - # type: (Iterable[Address]) -> dict + def were_addresses_spent_from( + self, + addresses: Iterable[Address] + ) -> Dict: """ Check if a list of addresses was ever spent from, in the current epoch, or in previous epochs. @@ -796,7 +794,7 @@ def were_addresses_spent_from(self, addresses): # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().were_addresses_spent_from(addresses) + super().were_addresses_spent_from(addresses) ) @@ -837,8 +835,13 @@ class Iota(StrictIota, AsyncIota): - https://github.com/iotaledger/wiki/blob/master/api-proposal.md """ - def __init__(self, adapter, seed=None, devnet=False, local_pow=False): - # type: (AdapterSpec, Optional[TrytesCompatible], bool, bool) -> None + def __init__( + self, + adapter: AdapterSpec, + seed: Optional[TrytesCompatible] = None, + devnet: bool = False, + local_pow: bool = False + ) -> None: """ :param seed: Seed used to generate new addresses. @@ -850,8 +853,10 @@ def __init__(self, adapter, seed=None, devnet=False, local_pow=False): # Explicitly call AsyncIota's init, as we need the seed AsyncIota.__init__(self, adapter, seed, devnet, local_pow) - def broadcast_and_store(self, trytes): - # type: (Iterable[TransactionTrytes]) -> dict + def broadcast_and_store( + self, + trytes: Iterable[TransactionTrytes] + ) -> Dict: """ Broadcasts and stores a set of transaction trytes. @@ -874,11 +879,13 @@ def broadcast_and_store(self, trytes): # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().broadcast_and_store(trytes) + super().broadcast_and_store(trytes) ) - def broadcast_bundle(self, tail_transaction_hash): - # type (TransactionHash) -> dict + def broadcast_bundle( + self, + tail_transaction_hash: TransactionHash + ) -> Dict: """ Re-broadcasts all transactions in a bundle given the tail transaction hash. It might be useful when transactions did not properly propagate, @@ -903,17 +910,16 @@ def broadcast_bundle(self, tail_transaction_hash): # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().broadcast_bundle(tail_transaction_hash) + super().broadcast_bundle(tail_transaction_hash) ) def find_transaction_objects( self, - bundles=None, # type: Optional[Iterable[BundleHash]] - addresses=None, # type: Optional[Iterable[Address]] - tags=None, # type: Optional[Iterable[Tag]] - approvees=None, # type: Optional[Iterable[TransactionHash]] - ): - # type: (...) -> dict + bundles: Optional[Iterable[BundleHash]] = None, + addresses: Optional[Iterable[Address]] = None, + tags: Optional[Iterable[Tag]] = None, + approvees: Optional[Iterable[TransactionHash]] = None, + ) -> Dict: """ A more extensive version of :py:meth:`find_transactions` that returns transaction objects instead of hashes. @@ -954,16 +960,21 @@ def find_transaction_objects( # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().find_transaction_objects( - bundles, - addresses, - tags, - approvees, - ) + super().find_transaction_objects( + bundles, + addresses, + tags, + approvees, + ) ) - def get_account_data(self, start=0, stop=None, inclusion_states=False, security_level=None): - # type: (int, Optional[int], bool, Optional[int]) -> dict + def get_account_data( + self, + start: int = 0, + stop: Optional[int] = None, + inclusion_states: bool = False, + security_level: Optional[int] = None + ) -> Dict: """ More comprehensive version of :py:meth:`get_transfers` that returns addresses and account balance in addition to bundles. @@ -1034,16 +1045,18 @@ def get_account_data(self, start=0, stop=None, inclusion_states=False, security_ # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().get_account_data( - start, - stop, - inclusion_states, - security_level, - ) + super().get_account_data( + start, + stop, + inclusion_states, + security_level, + ) ) - def get_bundles(self, transactions): - # type: (Iterable[TransactionHash]) -> dict + def get_bundles( + self, + transactions: Iterable[TransactionHash] + ) -> Dict: """ Returns the bundle(s) associated with the specified transaction hashes. @@ -1071,17 +1084,16 @@ def get_bundles(self, transactions): # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().get_bundles(transactions) + super().get_bundles(transactions) ) def get_inputs( self, - start=0, - stop=None, - threshold=None, - security_level=None, - ): - # type: (int, Optional[int], Optional[int], Optional[int]) -> dict + start: int = 0, + stop: Optional[int] = None, + threshold: Optional[int] = None, + security_level: Optional[int] = None, + ) -> Dict: """ Gets all possible inputs of a seed and returns them, along with the total balance. @@ -1181,16 +1193,18 @@ def get_inputs( # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().get_inputs( - start, - stop, - threshold, - security_level, - ) + super().get_inputs( + start, + stop, + threshold, + security_level, + ) ) - def get_latest_inclusion(self, hashes): - # type: (Iterable[TransactionHash]) -> Dict[TransactionHash, bool] + def get_latest_inclusion( + self, + hashes: Iterable[TransactionHash] + ) -> Dict[Text, Dict[TransactionHash, bool]]: """ Fetches the inclusion state for the specified transaction hashes, as of the latest milestone that the node has processed. @@ -1214,17 +1228,16 @@ def get_latest_inclusion(self, hashes): # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().get_latest_inclusion(hashes) + super().get_latest_inclusion(hashes) ) def get_new_addresses( self, - index=0, - count=1, - security_level=AddressGenerator.DEFAULT_SECURITY_LEVEL, - checksum=False, + index: int = 0, + count: int = 1, + security_level: int = AddressGenerator.DEFAULT_SECURITY_LEVEL, + checksum: bool = False, ): - # type: (int, int, int, bool) -> dict """ Generates one or more new addresses from the seed. @@ -1281,19 +1294,18 @@ def get_new_addresses( # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().get_new_addresses( - count=count, - index=index, - security_level=security_level, - checksum=checksum, - ) + super().get_new_addresses( + count=count, + index=index, + security_level=security_level, + checksum=checksum, + ) ) def get_transaction_objects( self, - hashes, # type: [Iterable[TransactionHash]] - ): - # type: (...) -> dict + hashes: [Iterable[TransactionHash]], + ) -> Dict: """ Fetches transaction objects from the Tangle given their transaction IDs (hashes). @@ -1318,11 +1330,15 @@ def get_transaction_objects( # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().get_transaction_objects(hashes) + super().get_transaction_objects(hashes) ) - def get_transfers(self, start=0, stop=None, inclusion_states=False): - # type: (int, Optional[int], bool) -> dict + def get_transfers( + self, + start: int = 0, + stop: Optional[int] = None, + inclusion_states: bool = False + ) -> Dict: """ Returns all transfers associated with the seed. @@ -1377,18 +1393,17 @@ def get_transfers(self, start=0, stop=None, inclusion_states=False): # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().get_transfers( - start, - stop, - inclusion_states, - ) + super().get_transfers( + start, + stop, + inclusion_states, + ) ) def is_promotable( self, - tails, # type: Iterable[TransactionHash] - ): - # type: (Iterable(TransactionHash)] -> dict + tails: Iterable[TransactionHash], + ) -> Dict: """ Checks if tail transaction(s) is promotable by calling :py:meth:`check_consistency` and verifying that ``attachmentTimestamp`` @@ -1422,17 +1437,16 @@ def is_promotable( # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().is_promotable(tails) + super().is_promotable(tails) ) def prepare_transfer( self, - transfers, # type: Iterable[ProposedTransaction] - inputs=None, # type: Optional[Iterable[Address]] - change_address=None, # type: Optional[Address] - security_level=None, # type: Optional[int] - ): - # type: (...) -> dict + transfers: Iterable[ProposedTransaction], + inputs: Optional[Iterable[Address]] = None, + change_address: Optional[Address] = None, + security_level: Optional[int] = None, + ) -> Dict: """ Prepares transactions to be broadcast to the Tangle, by generating the correct bundle, as well as choosing and signing @@ -1482,21 +1496,20 @@ def prepare_transfer( # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().prepare_transfer( - transfers, - inputs, - change_address, - security_level, - ) + super().prepare_transfer( + transfers, + inputs, + change_address, + security_level, + ) ) def promote_transaction( self, - transaction, - depth=3, - min_weight_magnitude=None, - ): - # type: (TransactionHash, int, Optional[int]) -> dict + transaction: TransactionHash, + depth: int = 3, + min_weight_magnitude: Optional[int] = None, + ) -> Dict: """ Promotes a transaction by adding spam on top of it. @@ -1524,20 +1537,19 @@ def promote_transaction( # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().promote_transaction( - transaction, - depth, - min_weight_magnitude, - ) + super().promote_transaction( + transaction, + depth, + min_weight_magnitude, + ) ) def replay_bundle( self, - transaction, - depth=3, - min_weight_magnitude=None, - ): - # type: (TransactionHash, int, Optional[int]) -> dict + transaction: TransactionHash, + depth: int = 3, + min_weight_magnitude: Optional[int] = None, + ) -> Dict: """ Takes a tail transaction hash as input, gets the bundle associated with the transaction and then replays the bundle by @@ -1571,23 +1583,22 @@ def replay_bundle( # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().replay_bundle( - transaction, - depth, - min_weight_magnitude, - ) + super().replay_bundle( + transaction, + depth, + min_weight_magnitude, + ) ) def send_transfer( self, - transfers, # type: Iterable[ProposedTransaction] - depth=3, # type: int - inputs=None, # type: Optional[Iterable[Address]] - change_address=None, # type: Optional[Address] - min_weight_magnitude=None, # type: Optional[int] - security_level=None, # type: Optional[int] - ): - # type: (...) -> dict + transfers: Iterable[ProposedTransaction], + depth: int = 3, + inputs: Optional[Iterable[Address]] = None, + change_address: Optional[Address] = None, + min_weight_magnitude: Optional[int] = None, + security_level: Optional[int] = None, + ) -> Dict: """ Prepares a set of transfers and creates the bundle, then attaches the bundle to the Tangle, and broadcasts and stores the @@ -1641,18 +1652,22 @@ def send_transfer( # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().send_transfer( - transfers, - depth, - inputs, - change_address, - min_weight_magnitude, - security_level, - ) + super().send_transfer( + transfers, + depth, + inputs, + change_address, + min_weight_magnitude, + security_level, + ) ) - def send_trytes(self, trytes, depth=3, min_weight_magnitude=None): - # type: (Iterable[TransactionTrytes], int, Optional[int]) -> dict + def send_trytes( + self, + trytes: Iterable[TransactionTrytes], + depth: int = 3, + min_weight_magnitude: Optional[int] = None + ) -> Dict: """ Attaches transaction trytes to the Tangle, then broadcasts and stores them. @@ -1685,15 +1700,14 @@ def send_trytes(self, trytes, depth=3, min_weight_magnitude=None): # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().send_trytes( - trytes, - depth, - min_weight_magnitude, - ) + super().send_trytes( + trytes, + depth, + min_weight_magnitude, + ) ) - def is_reattachable(self, addresses): - # type: (Iterable[Address]) -> dict + def is_reattachable(self, addresses: Iterable[Address]) -> Dict: """ This API function helps you to determine whether you should replay a transaction or make a new one (either with the same @@ -1722,13 +1736,12 @@ def is_reattachable(self, addresses): # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().is_reattachable( - addresses, - ) + super().is_reattachable( + addresses, + ) ) - def traverse_bundle(self, tail_hash): - # type: (TransactionHash) -> dict + def traverse_bundle(self, tail_hash: TransactionHash) -> Dict: """ Fetches and traverses a bundle from the Tangle given a tail transaction hash. @@ -1754,7 +1767,7 @@ def traverse_bundle(self, tail_hash): # Execute original coroutine inside an event loop to make this method # synchronous return asyncio.get_event_loop().run_until_complete( - super().traverse_bundle( - tail_hash, - ) + super().traverse_bundle( + tail_hash, + ) ) diff --git a/iota/api_async.py b/iota/api_async.py index c013cde..9098461 100644 --- a/iota/api_async.py +++ b/iota/api_async.py @@ -43,8 +43,12 @@ class AsyncStrictIota: """ - def __init__(self, adapter, devnet=False, local_pow=False): - # type: (AdapterSpec, bool, bool) -> None + def __init__( + self, + adapter: AdapterSpec, + devnet: bool = False, + local_pow: bool = False + ) -> None: """ :param AdapterSpec adapter: URI string or BaseAdapter instance. @@ -67,7 +71,7 @@ def __init__(self, adapter, devnet=False, local_pow=False): if not isinstance(adapter, BaseAdapter): adapter = resolve_adapter(adapter) - self.adapter = adapter # type: BaseAdapter + self.adapter: BaseAdapter = adapter # Note that the `local_pow` parameter is passed to adapter, # the api class has no notion about it. The reason being, # that this parameter is used in `AttachToTangeCommand` calls, @@ -81,8 +85,7 @@ def __init__(self, adapter, devnet=False, local_pow=False): self.adapter.set_local_pow(local_pow) self.devnet = devnet - def create_command(self, command): - # type: (Text) -> CustomCommand + def create_command(self, command: Text) -> CustomCommand: """ Creates a pre-configured CustomCommand instance. @@ -95,8 +98,7 @@ def create_command(self, command): """ return CustomCommand(self.adapter, command) - def set_local_pow(self, local_pow): - # type: (bool) -> None + def set_local_pow(self, local_pow: bool) -> None: """ Sets the :py:attr:`local_pow` attribute of the adapter of the api instance. If it is ``True``, :py:meth:`~Iota.attach_to_tangle` command calls @@ -116,16 +118,14 @@ def set_local_pow(self, local_pow): self.adapter.set_local_pow(local_pow) @property - def default_min_weight_magnitude(self): - # type: () -> int + def default_min_weight_magnitude(self) -> int: """ Returns the default ``min_weight_magnitude`` value to use for API requests. """ return 9 if self.devnet else 14 - async def add_neighbors(self, uris): - # type: (Iterable[Text]) -> dict + async def add_neighbors(self, uris: Iterable[Text]) -> Dict: """ Add one or more neighbors to the node. Lasts until the node is restarted. @@ -157,12 +157,11 @@ async def add_neighbors(self, uris): async def attach_to_tangle( self, - trunk_transaction, # type: TransactionHash - branch_transaction, # type: TransactionHash - trytes, # type: Iterable[TryteString] - min_weight_magnitude=None, # type: Optional[int] - ): - # type: (...) -> dict + trunk_transaction: TransactionHash, + branch_transaction: TransactionHash, + trytes: Iterable[TryteString], + min_weight_magnitude: Optional[int] = None, + ) -> Dict: """ Attaches the specified transactions (trytes) to the Tangle by doing Proof of Work. You need to supply branchTransaction as @@ -203,14 +202,13 @@ async def attach_to_tangle( min_weight_magnitude = self.default_min_weight_magnitude return await core.AttachToTangleCommand(self.adapter)( - trunkTransaction=trunk_transaction, - branchTransaction=branch_transaction, - minWeightMagnitude=min_weight_magnitude, - trytes=trytes, + trunkTransaction=trunk_transaction, + branchTransaction=branch_transaction, + minWeightMagnitude=min_weight_magnitude, + trytes=trytes, ) - async def broadcast_transactions(self, trytes): - # type: (Iterable[TryteString]) -> dict + async def broadcast_transactions(self, trytes: Iterable[TryteString]) -> Dict: """ Broadcast a list of transactions to all neighbors. @@ -234,8 +232,7 @@ async def broadcast_transactions(self, trytes): """ return await core.BroadcastTransactionsCommand(self.adapter)(trytes=trytes) - async def check_consistency(self, tails): - # type: (Iterable[TransactionHash]) -> dict + async def check_consistency(self, tails: Iterable[TransactionHash]) -> Dict: """ Used to ensure tail resolves to a consistent ledger which is necessary to validate before attempting promotion. Checks @@ -265,17 +262,16 @@ async def check_consistency(self, tails): - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#checkconsistency """ return await core.CheckConsistencyCommand(self.adapter)( - tails=tails, + tails=tails, ) async def find_transactions( self, - bundles=None, # type: Optional[Iterable[BundleHash]] - addresses=None, # type: Optional[Iterable[Address]] - tags=None, # type: Optional[Iterable[Tag]] - approvees=None, # type: Optional[Iterable[TransactionHash]] - ): - # type: (...) -> dict + bundles: Optional[Iterable[BundleHash]] = None, + addresses: Optional[Iterable[Address]] = None, + tags: Optional[Iterable[Tag]] = None, + approvees: Optional[Iterable[TransactionHash]] = None, + ) -> Dict: """ Find the transactions which match the specified input and return. @@ -312,19 +308,18 @@ async def find_transactions( - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#findtransactions """ return await core.FindTransactionsCommand(self.adapter)( - bundles=bundles, - addresses=addresses, - tags=tags, - approvees=approvees, + bundles=bundles, + addresses=addresses, + tags=tags, + approvees=approvees, ) async def get_balances( self, - addresses, # type: Iterable[Address] - threshold=100, # type: int - tips=None, # type: Optional[Iterable[TransactionHash]] - ): - # type: (...) -> dict + addresses: Iterable[Address], + threshold: int = 100, + tips: Optional[Iterable[TransactionHash]] = None, + ) -> Dict: """ Similar to :py:meth:`get_inclusion_states`. Returns the confirmed balance which a list of addresses have at the latest @@ -367,13 +362,16 @@ async def get_balances( - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#getbalances """ return await core.GetBalancesCommand(self.adapter)( - addresses=addresses, - threshold=threshold, - tips=tips, + addresses=addresses, + threshold=threshold, + tips=tips, ) - async def get_inclusion_states(self, transactions, tips): - # type: (Iterable[TransactionHash], Iterable[TransactionHash]) -> dict + async def get_inclusion_states( + self, + transactions: Iterable[TransactionHash], + tips: Iterable[TransactionHash] + ) -> Dict: """ Get the inclusion states of a set of transactions. This is for determining if a transaction was accepted and confirmed by the @@ -405,12 +403,11 @@ async def get_inclusion_states(self, transactions, tips): - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#getinclusionstates """ return await core.GetInclusionStatesCommand(self.adapter)( - transactions=transactions, - tips=tips, + transactions=transactions, + tips=tips, ) - async def get_missing_transactions(self): - # type: () -> dict + async def get_missing_transactions(self) -> Dict: """ Returns all transaction hashes that a node is currently requesting from its neighbors. @@ -431,8 +428,7 @@ async def get_missing_transactions(self): """ return await core.GetMissingTransactionsCommand(self.adapter)() - async def get_neighbors(self): - # type: () -> dict + async def get_neighbors(self) -> Dict: """ Returns the set of neighbors the node is connected with, as well as their activity count. @@ -464,8 +460,7 @@ async def get_neighbors(self): """ return await core.GetNeighborsCommand(self.adapter)() - async def get_node_api_configuration(self): - # type: () -> dict + async def get_node_api_configuration(self) -> Dict: """ Returns a node's API configuration settings. @@ -488,8 +483,7 @@ async def get_node_api_configuration(self): """ return await core.GetNodeAPIConfigurationCommand(self.adapter)() - async def get_node_info(self): - # type: () -> dict + async def get_node_info(self) -> Dict: """ Returns information about the node. @@ -547,8 +541,7 @@ async def get_node_info(self): """ return await core.GetNodeInfoCommand(self.adapter)() - async def get_tips(self): - # type: () -> dict + async def get_tips(self) -> Dict: """ Returns the list of tips (transactions which have no other transactions referencing them). @@ -570,8 +563,11 @@ async def get_tips(self): """ return await core.GetTipsCommand(self.adapter)() - async def get_transactions_to_approve(self, depth, reference=None): - # type: (int, Optional[TransactionHash]) -> dict + async def get_transactions_to_approve( + self, + depth: int, + reference: Optional[TransactionHash] = None, + ) -> Dict: """ Tip selection which returns ``trunkTransaction`` and ``branchTransaction``. @@ -605,12 +601,11 @@ async def get_transactions_to_approve(self, depth, reference=None): - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#gettransactionstoapprove """ return await core.GetTransactionsToApproveCommand(self.adapter)( - depth=depth, - reference=reference, + depth=depth, + reference=reference, ) - async def get_trytes(self, hashes): - # type: (Iterable[TransactionHash]) -> dict + async def get_trytes(self, hashes: Iterable[TransactionHash]) -> Dict: """ Returns the raw transaction data (trytes) of one or more transactions. @@ -637,8 +632,7 @@ async def get_trytes(self, hashes): """ return await core.GetTrytesCommand(self.adapter)(hashes=hashes) - async def interrupt_attaching_to_tangle(self): - # type: () -> dict + async def interrupt_attaching_to_tangle(self) -> Dict: """ Interrupts and completely aborts the :py:meth:`attach_to_tangle` process. @@ -657,8 +651,7 @@ async def interrupt_attaching_to_tangle(self): """ return await core.InterruptAttachingToTangleCommand(self.adapter)() - async def remove_neighbors(self, uris): - # type: (Iterable[Text]) -> dict + async def remove_neighbors(self, uris: Iterable[Text]) -> Dict: """ Removes one or more neighbors from the node. Lasts until the node is restarted. @@ -683,8 +676,7 @@ async def remove_neighbors(self, uris): """ return await core.RemoveNeighborsCommand(self.adapter)(uris=uris) - async def store_transactions(self, trytes): - # type: (Iterable[TryteString]) -> dict + async def store_transactions(self, trytes: Iterable[TryteString]) -> Dict: """ Store transactions into local storage of the node. @@ -710,8 +702,10 @@ async def store_transactions(self, trytes): """ return await core.StoreTransactionsCommand(self.adapter)(trytes=trytes) - async def were_addresses_spent_from(self, addresses): - # type: (Iterable[Address]) -> dict + async def were_addresses_spent_from( + self, + addresses: Iterable[Address] + ) -> Dict: """ Check if a list of addresses was ever spent from, in the current epoch, or in previous epochs. @@ -738,9 +732,10 @@ async def were_addresses_spent_from(self, addresses): - https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#wereaddressesspentfrom """ return await core.WereAddressesSpentFromCommand(self.adapter)( - addresses=addresses, + addresses=addresses, ) + class AsyncIota(AsyncStrictIota): """ Implements the async core API, plus additional async wrapper methods for @@ -778,8 +773,13 @@ class AsyncIota(AsyncStrictIota): - https://github.com/iotaledger/wiki/blob/master/api-proposal.md """ - def __init__(self, adapter, seed=None, devnet=False, local_pow=False): - # type: (AdapterSpec, Optional[TrytesCompatible], bool, bool) -> None + def __init__( + self, + adapter: AdapterSpec, + seed: Optional[TrytesCompatible] = None, + devnet: bool = False, + local_pow: bool = False + ) -> None: """ :param seed: Seed used to generate new addresses. @@ -792,8 +792,10 @@ def __init__(self, adapter, seed=None, devnet=False, local_pow=False): self.seed = Seed(seed) if seed else Seed.random() - async def broadcast_and_store(self, trytes): - # type: (Iterable[TransactionTrytes]) -> dict + async def broadcast_and_store( + self, + trytes: Iterable[TransactionTrytes] + ) -> Dict: """ Broadcasts and stores a set of transaction trytes. @@ -814,11 +816,13 @@ async def broadcast_and_store(self, trytes): - https://github.com/iotaledger/wiki/blob/master/api-proposal.md#broadcastandstore """ return await extended.BroadcastAndStoreCommand(self.adapter)( - trytes=trytes, + trytes=trytes, ) - async def broadcast_bundle(self, tail_transaction_hash): - # type (TransactionHash) -> dict + async def broadcast_bundle( + self, + tail_transaction_hash: TransactionHash + ) -> Dict: """ Re-broadcasts all transactions in a bundle given the tail transaction hash. It might be useful when transactions did not properly propagate, @@ -841,17 +845,16 @@ async def broadcast_bundle(self, tail_transaction_hash): """ return await extended.BroadcastBundleCommand(self.adapter)( - tail_hash=tail_transaction_hash, + tail_hash=tail_transaction_hash, ) async def find_transaction_objects( self, - bundles=None, # type: Optional[Iterable[BundleHash]] - addresses=None, # type: Optional[Iterable[Address]] - tags=None, # type: Optional[Iterable[Tag]] - approvees=None, # type: Optional[Iterable[TransactionHash]] - ): - # type: (...) -> dict + bundles: Optional[Iterable[BundleHash]] = None, + addresses: Optional[Iterable[Address]] = None, + tags: Optional[Iterable[Tag]] = None, + approvees: Optional[Iterable[TransactionHash]] = None, + ) -> Dict: """ A more extensive version of :py:meth:`find_transactions` that returns transaction objects instead of hashes. @@ -890,14 +893,19 @@ async def find_transaction_objects( """ return await extended.FindTransactionObjectsCommand(self.adapter)( - bundles=bundles, - addresses=addresses, - tags=tags, - approvees=approvees, + bundles=bundles, + addresses=addresses, + tags=tags, + approvees=approvees, ) - async def get_account_data(self, start=0, stop=None, inclusion_states=False, security_level=None): - # type: (int, Optional[int], bool, Optional[int]) -> dict + async def get_account_data( + self, + start: int = 0, + stop: Optional[int] = None, + inclusion_states: bool = False, + security_level: Optional[int] = None + ) -> Dict: """ More comprehensive version of :py:meth:`get_transfers` that returns addresses and account balance in addition to bundles. @@ -966,15 +974,17 @@ async def get_account_data(self, start=0, stop=None, inclusion_states=False, sec """ return await extended.GetAccountDataCommand(self.adapter)( - seed=self.seed, - start=start, - stop=stop, - inclusionStates=inclusion_states, - security_level=security_level + seed=self.seed, + start=start, + stop=stop, + inclusionStates=inclusion_states, + security_level=security_level ) - async def get_bundles(self, transactions): - # type: (Iterable[TransactionHash]) -> dict + async def get_bundles( + self, + transactions: Iterable[TransactionHash] + ) -> Dict: """ Returns the bundle(s) associated with the specified transaction hashes. @@ -1000,17 +1010,16 @@ async def get_bundles(self, transactions): - https://github.com/iotaledger/wiki/blob/master/api-proposal.md#getbundle """ return await extended.GetBundlesCommand(self.adapter)( - transactions=transactions, + transactions=transactions, ) async def get_inputs( self, - start=0, - stop=None, - threshold=None, - security_level=None, - ): - # type: (int, Optional[int], Optional[int], Optional[int]) -> dict + start: int = 0, + stop: Optional[int] = None, + threshold: Optional[int] = None, + security_level: Optional[int] = None, + ) -> Dict: """ Gets all possible inputs of a seed and returns them, along with the total balance. @@ -1108,15 +1117,17 @@ async def get_inputs( - https://github.com/iotaledger/wiki/blob/master/api-proposal.md#getinputs """ return await extended.GetInputsCommand(self.adapter)( - seed=self.seed, - start=start, - stop=stop, - threshold=threshold, - securityLevel=security_level + seed=self.seed, + start=start, + stop=stop, + threshold=threshold, + securityLevel=security_level ) - async def get_latest_inclusion(self, hashes): - # type: (Iterable[TransactionHash]) -> Dict[TransactionHash, bool] + async def get_latest_inclusion( + self, + hashes: Iterable[TransactionHash] + ) -> Dict[Text, Dict[TransactionHash, bool]]: """ Fetches the inclusion state for the specified transaction hashes, as of the latest milestone that the node has processed. @@ -1141,12 +1152,11 @@ async def get_latest_inclusion(self, hashes): async def get_new_addresses( self, - index=0, - count=1, - security_level=AddressGenerator.DEFAULT_SECURITY_LEVEL, - checksum=False, + index: int = 0, + count: int = 1, + security_level: int = AddressGenerator.DEFAULT_SECURITY_LEVEL, + checksum: bool = False, ): - # type: (int, int, int, bool) -> dict """ Generates one or more new addresses from the seed. @@ -1201,18 +1211,17 @@ async def get_new_addresses( - https://github.com/iotaledger/wiki/blob/master/api-proposal.md#getnewaddress """ return await extended.GetNewAddressesCommand(self.adapter)( - count=count, - index=index, - securityLevel=security_level, - checksum=checksum, - seed=self.seed, + count=count, + index=index, + securityLevel=security_level, + checksum=checksum, + seed=self.seed, ) async def get_transaction_objects( self, - hashes, # type: [Iterable[TransactionHash]] - ): - # type: (...) -> dict + hashes: [Iterable[TransactionHash]], + ) -> Dict: """ Fetches transaction objects from the Tangle given their transaction IDs (hashes). @@ -1235,11 +1244,15 @@ async def get_transaction_objects( } """ return await extended.GetTransactionObjectsCommand(self.adapter)( - hashes=hashes, + hashes=hashes, ) - async def get_transfers(self, start=0, stop=None, inclusion_states=False): - # type: (int, Optional[int], bool) -> dict + async def get_transfers( + self, + start: int = 0, + stop: Optional[int] = None, + inclusion_states: bool = False + ) -> Dict: """ Returns all transfers associated with the seed. @@ -1292,17 +1305,16 @@ async def get_transfers(self, start=0, stop=None, inclusion_states=False): - https://github.com/iotaledger/wiki/blob/master/api-proposal.md#gettransfers """ return await extended.GetTransfersCommand(self.adapter)( - seed=self.seed, - start=start, - stop=stop, - inclusionStates=inclusion_states, + seed=self.seed, + start=start, + stop=stop, + inclusionStates=inclusion_states, ) async def is_promotable( self, - tails, # type: Iterable[TransactionHash] - ): - # type: (Iterable(TransactionHash)] -> dict + tails: Iterable[TransactionHash], + ) -> Dict: """ Checks if tail transaction(s) is promotable by calling :py:meth:`check_consistency` and verifying that ``attachmentTimestamp`` @@ -1334,17 +1346,16 @@ async def is_promotable( - https://github.com/iotaledger/iota.js/blob/next/api_reference.md#module_core.isPromotable """ return await extended.IsPromotableCommand(self.adapter)( - tails=tails, + tails=tails, ) async def prepare_transfer( self, - transfers, # type: Iterable[ProposedTransaction] - inputs=None, # type: Optional[Iterable[Address]] - change_address=None, # type: Optional[Address] - security_level=None, # type: Optional[int] - ): - # type: (...) -> dict + transfers: Iterable[ProposedTransaction], + inputs: Optional[Iterable[Address]] = None, + change_address: Optional[Address] = None, + security_level: Optional[int] = None, + ) -> Dict: """ Prepares transactions to be broadcast to the Tangle, by generating the correct bundle, as well as choosing and signing @@ -1392,20 +1403,19 @@ async def prepare_transfer( - https://github.com/iotaledger/wiki/blob/master/api-proposal.md#preparetransfers """ return await extended.PrepareTransferCommand(self.adapter)( - seed=self.seed, - transfers=transfers, - inputs=inputs, - changeAddress=change_address, - securityLevel=security_level, + seed=self.seed, + transfers=transfers, + inputs=inputs, + changeAddress=change_address, + securityLevel=security_level, ) async def promote_transaction( self, - transaction, - depth=3, - min_weight_magnitude=None, - ): - # type: (TransactionHash, int, Optional[int]) -> dict + transaction: TransactionHash, + depth: int = 3, + min_weight_magnitude: Optional[int] = None, + ) -> Dict: """ Promotes a transaction by adding spam on top of it. @@ -1434,18 +1444,17 @@ async def promote_transaction( min_weight_magnitude = self.default_min_weight_magnitude return await extended.PromoteTransactionCommand(self.adapter)( - transaction=transaction, - depth=depth, - minWeightMagnitude=min_weight_magnitude, + transaction=transaction, + depth=depth, + minWeightMagnitude=min_weight_magnitude, ) async def replay_bundle( self, - transaction, - depth=3, - min_weight_magnitude=None, - ): - # type: (TransactionHash, int, Optional[int]) -> dict + transaction: TransactionHash, + depth: int = 3, + min_weight_magnitude: Optional[int] = None, + ) -> Dict: """ Takes a tail transaction hash as input, gets the bundle associated with the transaction and then replays the bundle by @@ -1480,21 +1489,20 @@ async def replay_bundle( min_weight_magnitude = self.default_min_weight_magnitude return await extended.ReplayBundleCommand(self.adapter)( - transaction=transaction, - depth=depth, - minWeightMagnitude=min_weight_magnitude, + transaction=transaction, + depth=depth, + minWeightMagnitude=min_weight_magnitude, ) async def send_transfer( self, - transfers, # type: Iterable[ProposedTransaction] - depth=3, # type: int - inputs=None, # type: Optional[Iterable[Address]] - change_address=None, # type: Optional[Address] - min_weight_magnitude=None, # type: Optional[int] - security_level=None, # type: Optional[int] - ): - # type: (...) -> dict + transfers: Iterable[ProposedTransaction], + depth: int = 3, + inputs: Optional[Iterable[Address]] = None, + change_address: Optional[Address] = None, + min_weight_magnitude: Optional[int] = None, + security_level: Optional[int] = None, + ) -> Dict: """ Prepares a set of transfers and creates the bundle, then attaches the bundle to the Tangle, and broadcasts and stores the @@ -1549,17 +1557,21 @@ async def send_transfer( min_weight_magnitude = self.default_min_weight_magnitude return await extended.SendTransferCommand(self.adapter)( - seed=self.seed, - depth=depth, - transfers=transfers, - inputs=inputs, - changeAddress=change_address, - minWeightMagnitude=min_weight_magnitude, - securityLevel=security_level, + seed=self.seed, + depth=depth, + transfers=transfers, + inputs=inputs, + changeAddress=change_address, + minWeightMagnitude=min_weight_magnitude, + securityLevel=security_level, ) - async def send_trytes(self, trytes, depth=3, min_weight_magnitude=None): - # type: (Iterable[TransactionTrytes], int, Optional[int]) -> dict + async def send_trytes( + self, + trytes: Iterable[TransactionTrytes], + depth: int = 3, + min_weight_magnitude: Optional[int] = None + ) -> Dict: """ Attaches transaction trytes to the Tangle, then broadcasts and stores them. @@ -1593,13 +1605,12 @@ async def send_trytes(self, trytes, depth=3, min_weight_magnitude=None): min_weight_magnitude = self.default_min_weight_magnitude return await extended.SendTrytesCommand(self.adapter)( - trytes=trytes, - depth=depth, - minWeightMagnitude=min_weight_magnitude, + trytes=trytes, + depth=depth, + minWeightMagnitude=min_weight_magnitude, ) - async def is_reattachable(self, addresses): - # type: (Iterable[Address]) -> dict + async def is_reattachable(self, addresses: Iterable[Address]) -> Dict: """ This API function helps you to determine whether you should replay a transaction or make a new one (either with the same @@ -1626,11 +1637,10 @@ async def is_reattachable(self, addresses): """ return await extended.IsReattachableCommand(self.adapter)( - addresses=addresses + addresses=addresses ) - async def traverse_bundle(self, tail_hash): - # type: (TransactionHash) -> dict + async def traverse_bundle(self, tail_hash: TransactionHash) -> Dict: """ Fetches and traverses a bundle from the Tangle given a tail transaction hash. @@ -1654,5 +1664,5 @@ async def traverse_bundle(self, tail_hash): """ return await extended.TraverseBundleCommand(self.adapter)( - transaction=tail_hash - ) \ No newline at end of file + transaction=tail_hash + ) diff --git a/iota/bin/__init__.py b/iota/bin/__init__.py index 5606d2e..917d2a7 100644 --- a/iota/bin/__init__.py +++ b/iota/bin/__init__.py @@ -4,7 +4,7 @@ from getpass import getpass as secure_input from io import StringIO from sys import exit -from typing import Any, Optional, Text +from typing import Any, Optional, Text, Dict from iota import Iota, __version__ from iota.crypto.types import Seed @@ -23,8 +23,12 @@ class IotaCommandLineApp(object, metaclass=ABCMeta): Whether the command requires the user to provide a seed. """ - def __init__(self, stdout=sys.stdout, stderr=sys.stderr, stdin=sys.stdin): - # type: (StringIO, StringIO, StringIO) -> None + def __init__( + self, + stdout: StringIO = sys.stdout, + stderr: StringIO = sys.stderr, + stdin: StringIO = sys.stdin + ) -> None: super(IotaCommandLineApp, self).__init__() self.stdout = stdout @@ -32,8 +36,7 @@ def __init__(self, stdout=sys.stdout, stderr=sys.stderr, stdin=sys.stdin): self.stdin = stdin @abstract_method - def execute(self, api, **arguments): - # type: (Iota, **Any) -> Optional[int] + def execute(self, api: Iota, **arguments: Any) -> Optional[int]: """ Executes the command and (optionally) returns an exit code (used by the shell to determine if the application exited cleanly). @@ -48,14 +51,13 @@ def execute(self, api, **arguments): 'Not implemented in {cls}.'.format(cls=type(self).__name__), ) - def main(self): + def main(self) -> None: """ Executes the command from :py:data:`sys.argv` and exits. """ exit(self.run_from_argv()) - def run_from_argv(self, argv=None): - # type: (Optional[tuple]) -> int + def run_from_argv(self, argv: Optional[tuple] = None) -> int: """ Executes the command from a collection of arguments (e.g., :py:data`sys.argv`) and returns the exit code. @@ -71,8 +73,7 @@ def run_from_argv(self, argv=None): return exit_code - def parse_argv(self, argv=None): - # type: (Optional[tuple]) -> dict + def parse_argv(self, argv: Optional[tuple] = None) -> Dict: """ Parses arguments for the command. @@ -100,8 +101,7 @@ def parse_argv(self, argv=None): return arguments - def create_argument_parser(self): - # type: () -> ArgumentParser + def create_argument_parser(self) -> ArgumentParser: """ Returns the argument parser that will be used to interpret arguments and options from argv. @@ -145,8 +145,7 @@ def create_argument_parser(self): return parser @staticmethod - def seed_from_filepath(filepath): - # type: (Text) -> Seed + def seed_from_filepath(filepath: Text) -> Seed: """ Reads a seed from the first line of a text file. @@ -156,8 +155,7 @@ def seed_from_filepath(filepath): return Seed(f_.readline().strip()) @staticmethod - def prompt_for_seed(): - # type: () -> Seed + def prompt_for_seed() -> Seed: """ Prompts the user to enter their seed via stdin. """ diff --git a/iota/bin/repl.py b/iota/bin/repl.py index 3fa8acf..25b36af 100755 --- a/iota/bin/repl.py +++ b/iota/bin/repl.py @@ -8,6 +8,8 @@ # Import all IOTA symbols into module scope, so that it's more # convenient for the user. +from typing import Any + from iota import * from iota.adapter import resolve_adapter from iota.adapter.wrappers import RoutingWrapper @@ -19,8 +21,7 @@ class IotaReplCommandLineApp(IotaCommandLineApp): Creates an IOTA API instance and drops the user into a REPL. """ - def execute(self, api, **arguments): - # type: (Iota, ...) -> int + def execute(self, api: Iota, **arguments: Any) -> int: debug_requests = arguments['debug_requests'] pow_uri = arguments['pow_uri'] @@ -51,8 +52,7 @@ def execute(self, api, **arguments): return 0 - def create_argument_parser(self): - # type: () -> ArgumentParser + def create_argument_parser(self) -> ArgumentParser: parser = super(IotaReplCommandLineApp, self).create_argument_parser() parser.add_argument( @@ -74,8 +74,7 @@ def create_argument_parser(self): return parser @staticmethod - def _start_repl(api): - # type: (Iota) -> None + def _start_repl(api: Iota) -> None: """ Starts the REPL. """ diff --git a/iota/codecs.py b/iota/codecs.py index 6a670ab..3d4a553 100644 --- a/iota/codecs.py +++ b/iota/codecs.py @@ -1,4 +1,5 @@ from codecs import Codec, CodecInfo, register as lookup_function +from typing import Union, Text, Tuple from warnings import warn from iota.exceptions import with_context @@ -51,25 +52,26 @@ class AsciiTrytesCodec(Codec): """ @classmethod - def get_codec_info(cls): + def get_codec_info(cls) -> CodecInfo: """ Returns information used by the codecs library to configure the codec for use. """ codec = cls() + # In Python 2, all codecs are made equal. + # In Python 3, some codecs are more equal than others codec_info = { 'encode': codec.encode, 'decode': codec.decode, + '_is_text_encoding': False } - # In Python 2, all codecs are made equal. - # In Python 3, some codecs are more equal than others - codec_info['_is_text_encoding'] = False - return CodecInfo(**codec_info) - def encode(self, input, errors='strict'): + def encode(self, + input: Union[memoryview, bytes, bytearray], + errors: Text = 'strict') -> Tuple[bytes, int]: """ Encodes a byte string into trytes. """ @@ -103,7 +105,9 @@ def encode(self, input, errors='strict'): return bytes(trytes), len(input) - def decode(self, input, errors='strict'): + def decode(self, + input: Union[memoryview, bytes, bytearray], + errors: Text = 'strict') -> Tuple[bytes, int]: """ Decodes a tryte string into bytes. """ diff --git a/iota/commands/__init__.py b/iota/commands/__init__.py index e789cd8..56f8036 100644 --- a/iota/commands/__init__.py +++ b/iota/commands/__init__.py @@ -24,22 +24,20 @@ class BaseCommand(object, metaclass=ABCMeta): """ An API command ready to send to the node. """ - command = None # Text + command: Text = None - def __init__(self, adapter): - # type: (BaseAdapter) -> None + def __init__(self, adapter: BaseAdapter) -> None: """ :param adapter: Adapter that will send request payloads to the node. """ - self.adapter = adapter + self.adapter = adapter - self.called = False - self.request = None # type: dict - self.response = None # type: dict + self.called: bool = False + self.request: Dict = None + self.response: Dict = None - async def __call__(self, **kwargs): - # type: (**Any) -> dict + async def __call__(self, **kwargs: Any) -> Dict: """ Sends the command to the node. """ @@ -69,17 +67,15 @@ async def __call__(self, **kwargs): return self.response - def reset(self): - # type: () -> None + def reset(self) -> None: """ Resets the command, allowing it to be called again. """ - self.called = False - self.request = None # type: dict - self.response = None # type: dict + self.called = False + self.request = None + self.response = None - async def _execute(self, request): - # type: (dict) -> dict + async def _execute(self, request: Dict) -> Dict: """ Sends the request object to the adapter and returns the response. @@ -90,8 +86,7 @@ async def _execute(self, request): return await self.adapter.send_request(request) @abstract_method - def _prepare_request(self, request): - # type: (dict) -> Optional[dict] + def _prepare_request(self, request: Dict) -> Optional[Dict]: """ Modifies the request before sending it to the node. @@ -109,8 +104,7 @@ def _prepare_request(self, request): ) @abstract_method - def _prepare_response(self, response): - # type: (dict) -> Optional[dict] + def _prepare_response(self, response: Dict) -> Optional[Dict]: """ Modifies the response from the node. @@ -132,8 +126,7 @@ class CustomCommand(BaseCommand): Useful for executing experimental/undocumented commands. """ - def __init__(self, adapter, command): - # type: (BaseAdapter, Text) -> None + def __init__(self, adapter: BaseAdapter, command: Text) -> None: super(CustomCommand, self).__init__(adapter) self.command = command @@ -198,8 +191,7 @@ class FilterCommand(BaseCommand, metaclass=ABCMeta): """ @abstract_method - def get_request_filter(self): - # type: () -> Optional[RequestFilter] + def get_request_filter(self) -> Optional[RequestFilter]: """ Returns the filter that should be applied to the request (if any). @@ -212,8 +204,7 @@ def get_request_filter(self): ) @abstract_method - def get_response_filter(self): - # type: () -> Optional[ResponseFilter] + def get_response_filter(self) -> Optional[ResponseFilter]: """ Returns the filter that should be applied to the response (if any). @@ -225,14 +216,14 @@ def get_response_filter(self): 'Not implemented in {cls}.'.format(cls=type(self).__name__), ) - def _prepare_request(self, request): + def _prepare_request(self, request: Dict) -> Dict: return self._apply_filter( value = request, filter_ = self.get_request_filter(), failure_message = 'Request failed validation', ) - def _prepare_response(self, response): + def _prepare_response(self, response: Dict) -> Dict: return self._apply_filter( value = response, filter_ = self.get_response_filter(), @@ -240,8 +231,11 @@ def _prepare_response(self, response): ) @staticmethod - def _apply_filter(value, filter_, failure_message): - # type: (dict, Optional[f.BaseFilter], Text) -> dict + def _apply_filter( + value: Dict, + filter_: Optional[f.BaseFilter], + failure_message: Text + ) -> Dict: """ Applies a filter to a value. If the value does not pass the filter, an exception will be raised with lots of contextual info diff --git a/iota/commands/core/add_neighbors.py b/iota/commands/core/add_neighbors.py index d7d418a..d9634c5 100644 --- a/iota/commands/core/add_neighbors.py +++ b/iota/commands/core/add_neighbors.py @@ -24,7 +24,7 @@ def get_response_filter(self): class AddNeighborsRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(AddNeighborsRequestFilter, self).__init__({ 'uris': f.Required | f.Array | f.FilterRepeater(f.Required | NodeUri), diff --git a/iota/commands/core/attach_to_tangle.py b/iota/commands/core/attach_to_tangle.py index 6ad7510..64715d0 100644 --- a/iota/commands/core/attach_to_tangle.py +++ b/iota/commands/core/attach_to_tangle.py @@ -1,3 +1,5 @@ +from typing import Dict + import filters as f from iota import TransactionHash, TransactionTrytes @@ -24,7 +26,7 @@ def get_request_filter(self): def get_response_filter(self): return AttachToTangleResponseFilter() - async def _execute(self, request): + async def _execute(self, request: Dict) -> Dict: if self.adapter.local_pow is True: from pow import ccurl_interface powed_trytes = ccurl_interface.attach_to_tangle( @@ -37,8 +39,9 @@ async def _execute(self, request): else: return await super(FilterCommand, self)._execute(request) + class AttachToTangleRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(AttachToTangleRequestFilter, self).__init__({ 'branchTransaction': f.Required | Trytes(TransactionHash), 'trunkTransaction': f.Required | Trytes(TransactionHash), @@ -57,7 +60,7 @@ def __init__(self): class AttachToTangleResponseFilter(ResponseFilter): - def __init__(self): + def __init__(self) -> None: super(AttachToTangleResponseFilter, self).__init__({ 'trytes': f.FilterRepeater( diff --git a/iota/commands/core/broadcast_transactions.py b/iota/commands/core/broadcast_transactions.py index 7bd9eae..fae4607 100644 --- a/iota/commands/core/broadcast_transactions.py +++ b/iota/commands/core/broadcast_transactions.py @@ -25,7 +25,7 @@ def get_response_filter(self): class BroadcastTransactionsRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(BroadcastTransactionsRequestFilter, self).__init__({ 'trytes': StringifiedTrytesArray(TransactionTrytes) | f.Required, }) diff --git a/iota/commands/core/check_consistency.py b/iota/commands/core/check_consistency.py index d835ec8..ca0da90 100644 --- a/iota/commands/core/check_consistency.py +++ b/iota/commands/core/check_consistency.py @@ -25,7 +25,7 @@ def get_response_filter(self): class CheckConsistencyRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(CheckConsistencyRequestFilter, self).__init__({ 'tails': f.Required | diff --git a/iota/commands/core/find_transactions.py b/iota/commands/core/find_transactions.py index 0476e38..6b2f701 100644 --- a/iota/commands/core/find_transactions.py +++ b/iota/commands/core/find_transactions.py @@ -1,3 +1,5 @@ +from typing import Dict + import filters as f from iota import BundleHash, Tag, TransactionHash @@ -31,7 +33,7 @@ class FindTransactionsRequestFilter(RequestFilter): CODE_NO_SEARCH_VALUES: 'No search values specified.', } - def __init__(self): + def __init__(self) -> None: super(FindTransactionsRequestFilter, self).__init__( { 'addresses': @@ -53,9 +55,9 @@ def __init__(self): ) def _apply(self, value): - value = super(FindTransactionsRequestFilter, self)._apply( + value: Dict = super(FindTransactionsRequestFilter, self)._apply( value - ) # type: dict + ) if self._has_errors: return value @@ -78,7 +80,7 @@ def _apply(self, value): class FindTransactionsResponseFilter(ResponseFilter): - def __init__(self): + def __init__(self) -> None: super(FindTransactionsResponseFilter, self).__init__({ 'hashes': f.FilterRepeater( diff --git a/iota/commands/core/get_balances.py b/iota/commands/core/get_balances.py index e75fc84..661776c 100644 --- a/iota/commands/core/get_balances.py +++ b/iota/commands/core/get_balances.py @@ -1,3 +1,5 @@ +from typing import Dict + import filters as f from iota import TransactionHash @@ -25,7 +27,7 @@ def get_response_filter(self): class GetBalancesRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(GetBalancesRequestFilter, self).__init__( { 'addresses': @@ -50,9 +52,9 @@ def __init__(self): ) def _apply(self, value): - value = super(GetBalancesRequestFilter, self)._apply( + value: Dict = super(GetBalancesRequestFilter, self)._apply( value - ) # type: dict + ) if self._has_errors: return value @@ -69,7 +71,7 @@ def _apply(self, value): class GetBalancesResponseFilter(ResponseFilter): - def __init__(self): + def __init__(self) -> None: super(GetBalancesResponseFilter, self).__init__({ 'balances': f.Array | f.FilterRepeater(f.Int), diff --git a/iota/commands/core/get_inclusion_states.py b/iota/commands/core/get_inclusion_states.py index 0983b9b..c7f70ea 100644 --- a/iota/commands/core/get_inclusion_states.py +++ b/iota/commands/core/get_inclusion_states.py @@ -25,7 +25,7 @@ def get_response_filter(self): class GetInclusionStatesRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(GetInclusionStatesRequestFilter, self).__init__( { # Required parameters. diff --git a/iota/commands/core/get_missing_transactions.py b/iota/commands/core/get_missing_transactions.py index a5409e7..820a0bf 100644 --- a/iota/commands/core/get_missing_transactions.py +++ b/iota/commands/core/get_missing_transactions.py @@ -25,14 +25,14 @@ def get_response_filter(self): class GetMissingTransactionsRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: # ``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): + def __init__(self) -> None: super(GetMissingTransactionsResponseFilter, self).__init__({ 'hashes': f.FilterRepeater( diff --git a/iota/commands/core/get_neighbors.py b/iota/commands/core/get_neighbors.py index 3ac6542..bda4172 100644 --- a/iota/commands/core/get_neighbors.py +++ b/iota/commands/core/get_neighbors.py @@ -21,7 +21,7 @@ def get_response_filter(self): class GetNeighborsRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: # ``getNeighbors`` does not accept any parameters. # Using a filter here just to enforce that the request is empty. super(GetNeighborsRequestFilter, self).__init__({}) diff --git a/iota/commands/core/get_node_api_configuration.py b/iota/commands/core/get_node_api_configuration.py index 0647a92..1b36e2d 100644 --- a/iota/commands/core/get_node_api_configuration.py +++ b/iota/commands/core/get_node_api_configuration.py @@ -21,7 +21,7 @@ def get_response_filter(self): class GetNodeAPIConfigurationRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: # ``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/iota/commands/core/get_node_info.py b/iota/commands/core/get_node_info.py index ca5c0d6..14f9471 100644 --- a/iota/commands/core/get_node_info.py +++ b/iota/commands/core/get_node_info.py @@ -25,14 +25,14 @@ def get_response_filter(self): class GetNodeInfoRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: # ``getNodeInfo`` does not accept any parameters. # Using a filter here just to enforce that the request is empty. super(GetNodeInfoRequestFilter, self).__init__({}) class GetNodeInfoResponseFilter(ResponseFilter): - def __init__(self): + def __init__(self) -> None: super(GetNodeInfoResponseFilter, self).__init__({ 'latestMilestone': f.ByteString(encoding='ascii') | Trytes(TransactionHash), diff --git a/iota/commands/core/get_tips.py b/iota/commands/core/get_tips.py index b77ddbb..77d7375 100644 --- a/iota/commands/core/get_tips.py +++ b/iota/commands/core/get_tips.py @@ -25,14 +25,14 @@ def get_response_filter(self): class GetTipsRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: # ``getTips`` doesn't accept any parameters. # Using a filter here just to enforce that the request is empty. super(GetTipsRequestFilter, self).__init__({}) class GetTipsResponseFilter(ResponseFilter): - def __init__(self): + def __init__(self) -> None: super(GetTipsResponseFilter, self).__init__({ 'hashes': f.Array | f.FilterRepeater( diff --git a/iota/commands/core/get_transactions_to_approve.py b/iota/commands/core/get_transactions_to_approve.py index 929249a..6533e9a 100644 --- a/iota/commands/core/get_transactions_to_approve.py +++ b/iota/commands/core/get_transactions_to_approve.py @@ -1,3 +1,5 @@ +from typing import Dict + import filters as f from iota import TransactionHash @@ -25,7 +27,7 @@ def get_response_filter(self): class GetTransactionsToApproveRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(GetTransactionsToApproveRequestFilter, self).__init__( { 'depth': f.Required | f.Type(int) | f.Min(1), @@ -38,9 +40,9 @@ def __init__(self): }) def _apply(self, value): - value = super(GetTransactionsToApproveRequestFilter, self)._apply( + value: Dict = super(GetTransactionsToApproveRequestFilter, self)._apply( value, - ) # type: dict + ) if self._has_errors: return value @@ -53,7 +55,7 @@ def _apply(self, value): class GetTransactionsToApproveResponseFilter(ResponseFilter): - def __init__(self): + def __init__(self) -> None: super(GetTransactionsToApproveResponseFilter, self).__init__({ 'branchTransaction': f.ByteString(encoding='ascii') | Trytes(TransactionHash), diff --git a/iota/commands/core/get_trytes.py b/iota/commands/core/get_trytes.py index 9c1bd0a..d714b2f 100644 --- a/iota/commands/core/get_trytes.py +++ b/iota/commands/core/get_trytes.py @@ -25,7 +25,7 @@ def get_response_filter(self): class GetTrytesRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(GetTrytesRequestFilter, self).__init__({ 'hashes': StringifiedTrytesArray(TransactionHash) | f.Required, @@ -33,7 +33,7 @@ def __init__(self): class GetTrytesResponseFilter(ResponseFilter): - def __init__(self): + def __init__(self) -> None: super(GetTrytesResponseFilter, self).__init__({ 'trytes': f.Array | f.FilterRepeater( diff --git a/iota/commands/core/interrupt_attaching_to_tangle.py b/iota/commands/core/interrupt_attaching_to_tangle.py index 9c63fde..e6cfb4f 100644 --- a/iota/commands/core/interrupt_attaching_to_tangle.py +++ b/iota/commands/core/interrupt_attaching_to_tangle.py @@ -21,7 +21,7 @@ def get_response_filter(self): class InterruptAttachingToTangleRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: # ``interruptAttachingToTangle`` takes no parameters. # Using a filter here just to enforce that the request is empty. super(InterruptAttachingToTangleRequestFilter, self).__init__({}) diff --git a/iota/commands/core/remove_neighbors.py b/iota/commands/core/remove_neighbors.py index 809cf94..ecd6e72 100644 --- a/iota/commands/core/remove_neighbors.py +++ b/iota/commands/core/remove_neighbors.py @@ -24,7 +24,7 @@ def get_response_filter(self): class RemoveNeighborsRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(RemoveNeighborsRequestFilter, self).__init__({ 'uris': f.Required | f.Array | f.FilterRepeater( f.Required | diff --git a/iota/commands/core/store_transactions.py b/iota/commands/core/store_transactions.py index adf705a..4bab99d 100644 --- a/iota/commands/core/store_transactions.py +++ b/iota/commands/core/store_transactions.py @@ -25,7 +25,7 @@ def get_response_filter(self): class StoreTransactionsRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(StoreTransactionsRequestFilter, self).__init__({ 'trytes': StringifiedTrytesArray(TransactionTrytes) | f.Required, diff --git a/iota/commands/core/were_addresses_spent_from.py b/iota/commands/core/were_addresses_spent_from.py index 8827bda..618ae0d 100644 --- a/iota/commands/core/were_addresses_spent_from.py +++ b/iota/commands/core/were_addresses_spent_from.py @@ -24,7 +24,7 @@ def get_response_filter(self): class WereAddressesSpentFromRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(WereAddressesSpentFromRequestFilter, self).__init__({ 'addresses': f.Required | f.Array | f.FilterRepeater( diff --git a/iota/commands/extended/broadcast_and_store.py b/iota/commands/extended/broadcast_and_store.py index 7054859..07b4bce 100644 --- a/iota/commands/extended/broadcast_and_store.py +++ b/iota/commands/extended/broadcast_and_store.py @@ -1,3 +1,5 @@ +from typing import Dict + from iota.commands import FilterCommand from iota.commands.core.broadcast_transactions import \ BroadcastTransactionsCommand @@ -23,7 +25,7 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request): + async def _execute(self, request: Dict) -> Dict: # Submit the two coroutines to the already running event loop await asyncio.gather( BroadcastTransactionsCommand(self.adapter)(**request), diff --git a/iota/commands/extended/broadcast_bundle.py b/iota/commands/extended/broadcast_bundle.py index c2934b7..e4de3d1 100644 --- a/iota/commands/extended/broadcast_bundle.py +++ b/iota/commands/extended/broadcast_bundle.py @@ -1,3 +1,5 @@ +from typing import Dict + import filters as f from iota.filters import Trytes @@ -27,19 +29,19 @@ def get_response_filter(self): # Return value is filtered before hitting us. pass - async def _execute(self, request): + async def _execute(self, request: Dict) -> Dict: # Given tail hash, fetches the bundle from the tangle # and validates it. - # Returns List[List[TransactionTrytes]] - # (outer list has one item in current implementation) - bundle = await GetBundlesCommand(self.adapter)(transactions=[request['tail_hash']]) + tail_hash: TransactionHash = request['tail_hash'] + bundle = await GetBundlesCommand(self.adapter)(transactions=[tail_hash]) await BroadcastTransactionsCommand(self.adapter)(trytes=bundle[0]) return { 'trytes': bundle[0], } + class BroadcastBundleRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(BroadcastBundleRequestFilter, self).__init__({ 'tail_hash': f.Required | Trytes(TransactionHash), - }) \ No newline at end of file + }) diff --git a/iota/commands/extended/find_transaction_objects.py b/iota/commands/extended/find_transaction_objects.py index 64d8359..24af87d 100644 --- a/iota/commands/extended/find_transaction_objects.py +++ b/iota/commands/extended/find_transaction_objects.py @@ -1,4 +1,4 @@ -from typing import Iterable, List, Optional +from typing import Iterable, List, Optional, Dict from iota import Address, BundleHash, Tag, Transaction, TransactionHash from iota.commands.core import GetTrytesCommand, FindTransactionsCommand @@ -19,15 +19,15 @@ class FindTransactionObjectsCommand(FindTransactionsCommand): def get_response_filter(self): pass - async 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]] + async def _execute(self, request: Dict) -> Dict: + bundles: Optional[Iterable[BundleHash]] = request\ + .get('bundles') + addresses: Optional[Iterable[Address]] = request\ + .get('addresses') + tags: Optional[Iterable[Tag]] = request\ + .get('tags') + approvees: Optional[Iterable[TransactionHash]] = request\ + .get('approvees') ft_response = await FindTransactionsCommand(adapter=self.adapter)( bundles=bundles, @@ -41,10 +41,10 @@ async def _execute(self, request): if hashes: gt_response = await GetTrytesCommand(adapter=self.adapter)(hashes=hashes) - transactions = list(map( + transactions: List[Transaction] = list(map( Transaction.from_tryte_string, gt_response.get('trytes') or [], - )) # type: List[Transaction] + )) return { 'transactions': transactions, diff --git a/iota/commands/extended/get_account_data.py b/iota/commands/extended/get_account_data.py index 0ee277a..9aa07c7 100644 --- a/iota/commands/extended/get_account_data.py +++ b/iota/commands/extended/get_account_data.py @@ -1,5 +1,5 @@ from operator import attrgetter -from typing import List, Optional +from typing import List, Optional, Dict import filters as f @@ -32,16 +32,16 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request): - inclusion_states = request['inclusionStates'] # type: bool - seed = request['seed'] # type: Seed - start = request['start'] # type: int - stop = request['stop'] # type: Optional[int] - security_level = request['security_level'] # type: Optional[int] + async def _execute(self, request: Dict) -> Dict: + inclusion_states: bool = request['inclusionStates'] + seed: Seed = request['seed'] + start: int = request['start'] + stop: Optional[int] = request['stop'] + security_level: Optional[int] = request['security_level'] if stop is None: - my_addresses = [] # type: List[Address] - my_hashes = [] # type: List[TransactionHash] + my_addresses: List[Address] = [] + my_hashes: List[TransactionHash] = [] async for addy, hashes in iter_used_addresses(self.adapter, seed, start, security_level): my_addresses.append(addy) @@ -91,7 +91,7 @@ class GetAccountDataRequestFilter(RequestFilter): CODE_INTERVAL_TOO_BIG: '``stop`` - ``start`` must be <= {max_interval}', } - def __init__(self): + def __init__(self) -> None: super(GetAccountDataRequestFilter, self).__init__( { # Required parameters. diff --git a/iota/commands/extended/get_bundles.py b/iota/commands/extended/get_bundles.py index 76bb402..e1e65bc 100644 --- a/iota/commands/extended/get_bundles.py +++ b/iota/commands/extended/get_bundles.py @@ -1,3 +1,5 @@ +from typing import Dict, Iterable + import filters as f from iota import BadApiResponse, TransactionHash @@ -27,8 +29,8 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request): - transaction_hashes = request['transactions'] # type: Iterable[TransactionHash] + async def _execute(self, request: Dict) -> Dict: + transaction_hashes: Iterable[TransactionHash] = request['transactions'] async def fetch_and_validate(tx_hash): bundle = (await TraverseBundleCommand(self.adapter)( @@ -60,8 +62,9 @@ async def fetch_and_validate(tx_hash): 'bundles': bundles, } + class GetBundlesRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(GetBundlesRequestFilter, self).__init__({ 'transactions': f.Required | f.Array | f.FilterRepeater( diff --git a/iota/commands/extended/get_inputs.py b/iota/commands/extended/get_inputs.py index 0945c95..f36d785 100644 --- a/iota/commands/extended/get_inputs.py +++ b/iota/commands/extended/get_inputs.py @@ -1,4 +1,4 @@ -from typing import Optional +from typing import Optional, Dict import filters as f @@ -30,12 +30,12 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request): - stop = request['stop'] # type: Optional[int] - seed = request['seed'] # type: Seed - start = request['start'] # type: int - threshold = request['threshold'] # type: Optional[int] - security_level = request['securityLevel'] # int + async def _execute(self, request: Dict) -> Dict: + stop: Optional[int] = request['stop'] + seed: Seed = request['seed'] + start: int = request['start'] + threshold: Optional[int] = request['threshold'] + security_level: int = request['securityLevel'] # Determine the addresses we will be scanning. if stop is None: @@ -115,7 +115,7 @@ class GetInputsRequestFilter(RequestFilter): CODE_INTERVAL_TOO_BIG: '``stop`` - ``start`` must be <= {max_interval}', } - def __init__(self): + def __init__(self) -> None: super(GetInputsRequestFilter, self).__init__( { # These arguments are optional. diff --git a/iota/commands/extended/get_latest_inclusion.py b/iota/commands/extended/get_latest_inclusion.py index 65b7b1a..1e5db6f 100644 --- a/iota/commands/extended/get_latest_inclusion.py +++ b/iota/commands/extended/get_latest_inclusion.py @@ -1,4 +1,4 @@ -from typing import List +from typing import List, Dict import filters as f @@ -27,8 +27,8 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request): - hashes = request['hashes'] # type: List[TransactionHash] + async def _execute(self, request: Dict) -> Dict: + hashes: List[TransactionHash] = request['hashes'] gni_response = await GetNodeInfoCommand(self.adapter)() @@ -43,7 +43,7 @@ async def _execute(self, request): class GetLatestInclusionRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(GetLatestInclusionRequestFilter, self).__init__({ 'hashes': f.Required | f.Array | f.FilterRepeater( diff --git a/iota/commands/extended/get_new_addresses.py b/iota/commands/extended/get_new_addresses.py index efba67f..5b926a0 100644 --- a/iota/commands/extended/get_new_addresses.py +++ b/iota/commands/extended/get_new_addresses.py @@ -1,4 +1,4 @@ -from typing import List, Optional +from typing import List, Optional, Dict import filters as f @@ -31,12 +31,12 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request): - checksum = request['checksum'] # type: bool - count = request['count'] # type: Optional[int] - index = request['index'] # type: int - security_level = request['securityLevel'] # type: int - seed = request['seed'] # type: Seed + async def _execute(self, request: Dict) -> Dict: + checksum: bool = request['checksum'] + count: Optional[int] = request['count'] + index: int = request['index'] + security_level: int = request['securityLevel'] + seed: Seed = request['seed'] return { 'addresses': @@ -49,8 +49,14 @@ async def _execute(self, request): ), } - async def _find_addresses(self, seed, index, count, security_level, checksum): - # type: (Seed, int, Optional[int], int, bool) -> List[Address] + async def _find_addresses( + self, + seed: Seed, + index: int, + count: Optional[int], + security_level: int, + checksum: bool + ) -> List[Address]: """ Find addresses matching the command parameters. """ @@ -81,7 +87,7 @@ async def _find_addresses(self, seed, index, count, security_level, checksum): class GetNewAddressesRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(GetNewAddressesRequestFilter, self).__init__( { # Everything except ``seed`` is optional. diff --git a/iota/commands/extended/get_transaction_objects.py b/iota/commands/extended/get_transaction_objects.py index be53542..be8412e 100644 --- a/iota/commands/extended/get_transaction_objects.py +++ b/iota/commands/extended/get_transaction_objects.py @@ -1,4 +1,4 @@ -from typing import Iterable, List, Optional +from typing import Iterable, List, Dict import filters as f @@ -26,26 +26,27 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request): - hashes = request\ - .get('hashes') # type: Iterable[TransactionHash] + async def _execute(self, request: Dict) -> Dict: + hashes: Iterable[TransactionHash] = request\ + .get('hashes') transactions = [] if hashes: gt_response = await GetTrytesCommand(adapter=self.adapter)(hashes=hashes) - transactions = list(map( + transactions: List[Transaction] = list(map( Transaction.from_tryte_string, gt_response.get('trytes') or [], - )) # type: List[Transaction] + )) return { 'transactions': transactions, } + class GetTransactionObjectsRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(GetTransactionObjectsRequestFilter, self).__init__({ 'hashes': StringifiedTrytesArray(TransactionHash) | f.Required - }) \ No newline at end of file + }) diff --git a/iota/commands/extended/get_transfers.py b/iota/commands/extended/get_transfers.py index 565fac6..ae36c04 100644 --- a/iota/commands/extended/get_transfers.py +++ b/iota/commands/extended/get_transfers.py @@ -1,5 +1,5 @@ from itertools import chain -from typing import Optional +from typing import Optional, Dict import filters as f @@ -30,11 +30,11 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request): - inclusion_states = request['inclusionStates'] # type: bool - seed = request['seed'] # type: Seed - start = request['start'] # type: int - stop = request['stop'] # type: Optional[int] + async def _execute(self, request: Dict) -> Dict: + inclusion_states: bool = request['inclusionStates'] + seed: Seed = request['seed'] + start: int = request['start'] + stop: Optional[int] = request['stop'] # Determine the addresses we will be scanning, and pull their # transaction hashes. @@ -75,7 +75,7 @@ class GetTransfersRequestFilter(RequestFilter): CODE_INTERVAL_TOO_BIG: '``stop`` - ``start`` must be <= {max_interval}', } - def __init__(self): + def __init__(self) -> None: super(GetTransfersRequestFilter, self).__init__( { # Required parameters. diff --git a/iota/commands/extended/is_promotable.py b/iota/commands/extended/is_promotable.py index 0ff0e41..e401a66 100644 --- a/iota/commands/extended/is_promotable.py +++ b/iota/commands/extended/is_promotable.py @@ -1,3 +1,5 @@ +from typing import Dict, Optional + from iota.commands import FilterCommand, RequestFilter from iota.commands.core import CheckConsistencyCommand, GetTrytesCommand from iota.transaction import Transaction @@ -33,6 +35,7 @@ Calculate current time in milliseconds. """ + class IsPromotableCommand(FilterCommand): """ Determines if a tail transaction is promotable. @@ -47,8 +50,8 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request): - tails = request['tails'] + async def _execute(self, request: Dict) -> Dict: + tails: TransactionHash = request['tails'] # First, check consistency # A transaction is consistent, if: @@ -62,18 +65,18 @@ async def _execute(self, request): if not cc_response['state']: # One or more transactions are inconsistent return { - 'promotable' : False, - 'info' : cc_response['info'], + 'promotable': False, + 'info': cc_response['info'], } transactions = [ Transaction.from_tryte_string(x) for x in - (await GetTrytesCommand(self.adapter)(hashes=tails))['trytes'] + (await GetTrytesCommand(self.adapter)(hashes=tails))['trytes'] ] response = { - 'promotable' : True, - 'info' : [], + 'promotable': True, + 'info': [], } # Check timestamps @@ -89,14 +92,15 @@ async def _execute(self, request): response['promotable'] = response['promotable'] and is_within # If there are no problems, we don't need 'info' field - # Delete info field to make it consistent with check_consistency repsonse. + # Delete info field to make it consistent with check_consistency response. if response['promotable']: del response['info'] return response + class IsPromotableRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(IsPromotableRequestFilter, self).__init__({ 'tails': f.Required | @@ -104,10 +108,14 @@ def __init__(self): f.FilterRepeater(f.Required | Trytes(TransactionHash)), }) -def is_within_depth(attachment_timestamp, now, depth=DEPTH): - # type (int, int, Optiona(int)) -> bool + +def is_within_depth( + attachment_timestamp: int, + now: int, + depth: Optional[int] = DEPTH +): """ Checks if `attachment_timestamp` is within limits of `depth`. """ return attachment_timestamp < now and \ - now - attachment_timestamp < depth * MILESTONE_INTERVAL - ONE_WAY_DELAY \ No newline at end of file + now - attachment_timestamp < depth * MILESTONE_INTERVAL - ONE_WAY_DELAY diff --git a/iota/commands/extended/is_reattachable.py b/iota/commands/extended/is_reattachable.py index 8654b49..95af4a5 100644 --- a/iota/commands/extended/is_reattachable.py +++ b/iota/commands/extended/is_reattachable.py @@ -1,4 +1,4 @@ -from typing import List +from typing import List, Dict import filters as f @@ -6,7 +6,7 @@ from iota.commands import FilterCommand, RequestFilter, ResponseFilter from iota.commands.extended import FindTransactionObjectsCommand, \ GetLatestInclusionCommand -from iota.filters import Trytes, StringifiedTrytesArray +from iota.filters import StringifiedTrytesArray __all__ = [ 'IsReattachableCommand', @@ -25,8 +25,8 @@ def get_request_filter(self): def get_response_filter(self): return IsReattachableResponseFilter() - async def _execute(self, request): - addresses = request['addresses'] # type: List[Address] + async def _execute(self, request: Dict) -> Dict: + addresses: List[Address] = request['addresses'] # fetch full transaction objects transactions = (await FindTransactionObjectsCommand(adapter=self.adapter)( @@ -62,7 +62,7 @@ async def _execute(self, request): class IsReattachableRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(IsReattachableRequestFilter, self).__init__( { 'addresses': StringifiedTrytesArray(Address) | f.Required, @@ -71,7 +71,7 @@ def __init__(self): class IsReattachableResponseFilter(ResponseFilter): - def __init__(self): + def __init__(self) -> None: super(IsReattachableResponseFilter, self).__init__({ 'reattachable': f.Required | f.Array | f.FilterRepeater(f.Type(bool)), diff --git a/iota/commands/extended/prepare_transfer.py b/iota/commands/extended/prepare_transfer.py index ce25330..d694712 100644 --- a/iota/commands/extended/prepare_transfer.py +++ b/iota/commands/extended/prepare_transfer.py @@ -1,4 +1,4 @@ -from typing import List, Optional +from typing import List, Optional, Dict import filters as f @@ -32,15 +32,15 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request): + async def _execute(self, request: Dict) -> Dict: # Required parameters. - seed = request['seed'] # type: Seed - bundle = ProposedBundle(request['transfers']) + seed: Seed = request['seed'] + bundle: ProposedBundle = ProposedBundle(request['transfers']) # Optional parameters. - change_address = request.get('changeAddress') # type: Optional[Address] - proposed_inputs = request.get('inputs') # type: Optional[List[Address]] - security_level = request['securityLevel'] # type: int + change_address: Optional[Address] = request.get('changeAddress') + proposed_inputs: Optional[List[Address]] = request.get('inputs') + security_level: int = request['securityLevel'] want_to_spend = bundle.balance if want_to_spend > 0: @@ -60,7 +60,7 @@ async def _execute(self, request): # Inputs provided. Check to make sure we have # sufficient balance. available_to_spend = 0 - confirmed_inputs = [] # type: List[Address] + confirmed_inputs: List[Address] = [] gb_response = await GetBalancesCommand(self.adapter)( addresses=[i.address for i in proposed_inputs], @@ -121,7 +121,7 @@ async def _execute(self, request): class PrepareTransferRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(PrepareTransferRequestFilter, self).__init__( { # Required parameters. diff --git a/iota/commands/extended/promote_transaction.py b/iota/commands/extended/promote_transaction.py index dcdbf72..210d3e7 100644 --- a/iota/commands/extended/promote_transaction.py +++ b/iota/commands/extended/promote_transaction.py @@ -1,3 +1,5 @@ +from typing import Dict + import filters as f from iota import Address, BadApiResponse, ProposedTransaction, TransactionHash @@ -26,10 +28,10 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request): - depth = request['depth'] # type: int - min_weight_magnitude = request['minWeightMagnitude'] # type: int - transaction = request['transaction'] # type: TransactionHash + async def _execute(self, request: Dict) -> Dict: + depth: int = request['depth'] + min_weight_magnitude: int = request['minWeightMagnitude'] + transaction: TransactionHash = request['transaction'] cc_response = await CheckConsistencyCommand(self.adapter)(tails=[transaction]) if cc_response['state'] is False: @@ -53,7 +55,7 @@ async def _execute(self, request): class PromoteTransactionRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(PromoteTransactionRequestFilter, self).__init__({ 'depth': f.Required | f.Type(int) | f.Min(1), 'transaction': f.Required | Trytes(TransactionHash), diff --git a/iota/commands/extended/replay_bundle.py b/iota/commands/extended/replay_bundle.py index 5c1f204..254d22c 100644 --- a/iota/commands/extended/replay_bundle.py +++ b/iota/commands/extended/replay_bundle.py @@ -1,3 +1,5 @@ +from typing import Dict + import filters as f from iota import Bundle, TransactionHash @@ -25,16 +27,16 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request): - depth = request['depth'] # type: int - min_weight_magnitude = request['minWeightMagnitude'] # type: int - transaction = request['transaction'] # type: TransactionHash + async def _execute(self, request: Dict) -> Dict: + depth: int = request['depth'] + min_weight_magnitude: int = request['minWeightMagnitude'] + transaction: TransactionHash = request['transaction'] gb_response = await GetBundlesCommand(self.adapter)(transactions=[transaction]) # Note that we only replay the first bundle returned by # ``getBundles``. - bundle = gb_response['bundles'][0] # type: Bundle + bundle: Bundle = gb_response['bundles'][0] return await SendTrytesCommand(self.adapter)( depth=depth, @@ -44,7 +46,7 @@ async def _execute(self, request): class ReplayBundleRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(ReplayBundleRequestFilter, self).__init__({ 'depth': f.Required | f.Type(int) | f.Min(1), 'transaction': f.Required | Trytes(TransactionHash), diff --git a/iota/commands/extended/send_transfer.py b/iota/commands/extended/send_transfer.py index 347148d..1d36fc7 100644 --- a/iota/commands/extended/send_transfer.py +++ b/iota/commands/extended/send_transfer.py @@ -1,4 +1,4 @@ -from typing import List, Optional +from typing import List, Optional, Dict import filters as f @@ -28,15 +28,15 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request): - change_address = request['changeAddress'] # type: Optional[Address] - depth = request['depth'] # type: int - inputs = request['inputs'] # type: Optional[List[Address]] - min_weight_magnitude = request['minWeightMagnitude'] # type: int - seed = request['seed'] # type: Seed - transfers = request['transfers'] # type: List[ProposedTransaction] - reference = request['reference'] # type: Optional[TransactionHash] - security_level = request['securityLevel'] # int + async def _execute(self, request: Dict) -> Dict: + change_address: Optional[Address] = request['changeAddress'] + depth: int = request['depth'] + inputs: Optional[List[Address]] = request['inputs'] + min_weight_magnitude: int = request['minWeightMagnitude'] + seed: Seed = request['seed'] + transfers: List[ProposedTransaction] = request['transfers'] + reference: Optional[TransactionHash] = request['reference'] + security_level: int = request['securityLevel'] pt_response = await PrepareTransferCommand(self.adapter)( changeAddress=change_address, @@ -59,7 +59,7 @@ async def _execute(self, request): class SendTransferRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(SendTransferRequestFilter, self).__init__( { # Required parameters. diff --git a/iota/commands/extended/send_trytes.py b/iota/commands/extended/send_trytes.py index 0c2bbea..9783eab 100644 --- a/iota/commands/extended/send_trytes.py +++ b/iota/commands/extended/send_trytes.py @@ -1,4 +1,4 @@ -from typing import List, Optional +from typing import List, Optional, Dict import filters as f @@ -29,11 +29,11 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request): - depth = request['depth'] # type: int - min_weight_magnitude = request['minWeightMagnitude'] # type: int - trytes = request['trytes'] # type: List[TryteString] - reference = request['reference'] # type: Optional[TransactionHash] + async def _execute(self, request: Dict) -> Dict: + depth: int = request['depth'] + min_weight_magnitude: int = request['minWeightMagnitude'] + trytes: List[TryteString] = request['trytes'] + reference: Optional[TransactionHash] = request['reference'] # Call ``getTransactionsToApprove`` to locate trunk and branch # transactions so that we can attach the bundle to the Tangle. @@ -61,7 +61,7 @@ async def _execute(self, request): class SendTrytesRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(SendTrytesRequestFilter, self).__init__({ 'depth': f.Required | f.Type(int) | f.Min(1), diff --git a/iota/commands/extended/traverse_bundle.py b/iota/commands/extended/traverse_bundle.py index 12f43d9..69ad9e5 100644 --- a/iota/commands/extended/traverse_bundle.py +++ b/iota/commands/extended/traverse_bundle.py @@ -1,8 +1,8 @@ -from typing import List, Optional +from typing import List, Optional, Dict import filters as f -from iota import BadApiResponse, BundleHash, Transaction, \ +from iota import BadApiResponse, Transaction, \ TransactionHash, TryteString, Bundle, TransactionTrytes from iota.commands import FilterCommand, RequestFilter from iota.commands.core.get_trytes import GetTrytesCommand @@ -28,18 +28,22 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request): - txn_hash = request['transaction'] # type: TransactionHash + async def _execute(self, request: Dict) -> Dict: + txn_hash: TransactionHash = request['transaction'] bundle = Bundle(await self._traverse_bundle(txn_hash, None)) # No bundle validation return { - 'bundles' : [bundle] + 'bundles': [bundle] } - async def _traverse_bundle(self, txn_hash, target_bundle_hash): + async def _traverse_bundle( + self, + txn_hash: TransactionHash, + target_bundle_hash: Optional[TransactionHash] + ) -> List[Transaction]: """ Recursively traverse the Tangle, collecting transactions until we hit a new bundle. @@ -47,9 +51,9 @@ async def _traverse_bundle(self, txn_hash, target_bundle_hash): This method is (usually) faster than ``findTransactions``, and it ensures we don't collect transactions from replayed bundles. """ - trytes =(await GetTrytesCommand(self.adapter)( + trytes: List[TryteString] = (await GetTrytesCommand(self.adapter)( hashes=[txn_hash]) - )['trytes'] # type: List[TryteString] + )['trytes'] # If no tx was found by the node for txn_hash, it returns 9s, # so we check here if it returned all 9s trytes. @@ -100,8 +104,9 @@ async def _traverse_bundle(self, txn_hash, target_bundle_hash): target_bundle_hash ) + class TraverseBundleRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(TraverseBundleRequestFilter, self).__init__({ 'transaction': f.Required | Trytes(TransactionHash), }) diff --git a/iota/commands/extended/utils.py b/iota/commands/extended/utils.py index 0380e7a..e68353b 100644 --- a/iota/commands/extended/utils.py +++ b/iota/commands/extended/utils.py @@ -1,4 +1,4 @@ -from typing import Generator, Iterable, List, Optional, Tuple +from typing import Iterable, List, Optional, Tuple from iota import Address, Bundle, Transaction, \ TransactionHash, TransactionTrytes, BadApiResponse @@ -17,12 +17,13 @@ async def iter_used_addresses( - adapter, # type: BaseAdapter - seed, # type: Seed - start, # type: int - security_level=None, # type: Optional[int] -): - # type: (...) -> Generator[Tuple[Address, List[TransactionHash]], None, None] + adapter: BaseAdapter, + seed: Seed, + start: int, + security_level: Optional[int] = None, + # 'typing' only supports AsyncGenerator from python 3.6.1, so put it + # as string literal here. +) -> 'AsyncGenerator[Tuple[Address, List[TransactionHash]], None]': """ Scans the Tangle for used addresses. A used address is an address that was spent from or has a transaction. @@ -58,11 +59,10 @@ async def iter_used_addresses( async def get_bundles_from_transaction_hashes( - adapter, - transaction_hashes, - inclusion_states, -): - # type: (BaseAdapter, Iterable[TransactionHash], bool) -> List[Bundle] + adapter: BaseAdapter, + transaction_hashes: Iterable[TransactionHash], + inclusion_states: bool, +) -> List[Bundle]: """ Given a set of transaction hashes, returns the corresponding bundles, sorted by tail transaction timestamp. @@ -91,10 +91,10 @@ async def get_bundles_from_transaction_hashes( 'returned_transaction_trytes': tx_trytes, }, ) - all_transactions = list(map( + all_transactions: List[Transaction] = list(map( Transaction.from_tryte_string, gt_response['trytes'], - )) # type: List[Transaction] + )) for txn in all_transactions: if txn.is_tail: @@ -131,9 +131,9 @@ async def get_bundles_from_transaction_hashes( txn.is_confirmed = gli_response['states'].get(txn.hash) # Find the bundles for each transaction. - txn_bundles = (await GetBundlesCommand(adapter)( + txn_bundles: List[Bundle] = (await GetBundlesCommand(adapter)( transactions=[txn.hash for txn in tail_transactions] - ))['bundles'] # type: List[Bundle] + ))['bundles'] if inclusion_states: for bundle, txn in zip(txn_bundles, tail_transactions): diff --git a/iota/crypto/addresses.py b/iota/crypto/addresses.py index e3703cd..f7bbf12 100644 --- a/iota/crypto/addresses.py +++ b/iota/crypto/addresses.py @@ -60,27 +60,29 @@ class AddressGenerator(Iterable[Address]): def __init__( self, - seed, - security_level=DEFAULT_SECURITY_LEVEL, - checksum=False, - ): - # type: (TrytesCompatible, int, bool) -> None + seed: TrytesCompatible, + security_level: int = DEFAULT_SECURITY_LEVEL, + checksum: bool = False, + ) -> None: super(AddressGenerator, self).__init__() self.security_level = security_level self.checksum = checksum self.seed = Seed(seed) - def __iter__(self): - # type: () -> Generator[Address, None, None] + def __iter__(self) -> Generator[Address, None, None]: """ Returns a generator for creating new addresses, starting at index 0 and potentially continuing on forever. """ return self.create_iterator() - def get_addresses(self, start, count=1, step=1): - # type: (int, int, int) -> List[Address] + def get_addresses( + self, + start: int, + count: int = 1, + step: int = 1 + ) -> List[Address]: """ Generates and returns one or more addresses at the specified index(es). @@ -154,8 +156,11 @@ def get_addresses(self, start, count=1, step=1): return addresses - def create_iterator(self, start=0, step=1): - # type: (int, int) -> Generator[Address, None, None] + def create_iterator( + self, + start: int = 0, + step: int = 1 + ) -> Generator[Address, None, None]: """ Creates an iterator that can be used to progressively generate new addresses. @@ -194,12 +199,11 @@ def create_iterator(self, start=0, step=1): yield self._generate_address(key_iterator) @staticmethod - def address_from_digest(digest): - # type: (Digest) -> Address + def address_from_digest(digest: Digest) -> Address: """ Generates an address from a private key digest. """ - address_trits = [0] * (Address.LEN * TRITS_PER_TRYTE) # type: List[int] + address_trits: List[int] = [0] * (Address.LEN * TRITS_PER_TRYTE) sponge = Kerl() sponge.absorb(digest.as_trits()) @@ -212,8 +216,7 @@ def address_from_digest(digest): security_level=digest.security_level, ) - def _generate_address(self, key_iterator): - # type: (KeyIterator) -> Address + def _generate_address(self, key_iterator: KeyIterator) -> Address: """ Generates a new address. @@ -229,13 +232,12 @@ def _generate_address(self, key_iterator): return self.address_from_digest(self._get_digest(key_iterator)) @staticmethod - def _get_digest(key_iterator): - # type: (KeyIterator) -> Digest + def _get_digest(key_iterator: KeyIterator) -> Digest: """ Extracts parameters for :py:meth:`address_from_digest`. Split into a separate method so that it can be mocked during unit tests. """ - private_key = next(key_iterator) # type: PrivateKey + private_key: PrivateKey = next(key_iterator) return private_key.get_digest() diff --git a/iota/crypto/kerl/conv.py b/iota/crypto/kerl/conv.py index 109969b..20d0a0c 100644 --- a/iota/crypto/kerl/conv.py +++ b/iota/crypto/kerl/conv.py @@ -1,7 +1,10 @@ +from typing import Dict, Text, List + + BYTE_HASH_LENGTH = 48 TRIT_HASH_LENGTH = 243 -tryte_table = { +tryte_table: Dict[Text, List[int]] = { '9': [0, 0, 0], # 0 'A': [1, 0, 0], # 1 'B': [-1, 1, 0], # 2 @@ -35,7 +38,7 @@ trit_table = {tuple(v): k for k, v in tryte_table.items()} -def trytes_to_trits(trytes): +def trytes_to_trits(trytes: Text) -> List[int]: trits = [] for tryte in trytes: trits.extend(tryte_table[tryte]) @@ -43,7 +46,7 @@ def trytes_to_trits(trytes): return trits -def trits_to_trytes(trits): +def trits_to_trytes(trits: List[int]) -> Text: trytes = [] trits_chunks = [trits[i:i + 3] for i in range(0, len(trits), 3)] @@ -53,19 +56,19 @@ def trits_to_trytes(trits): return ''.join(trytes) -def convertToTrits(bytes_k): +def convertToTrits(bytes_k: List[int]) -> List[int]: bigInt = convertBytesToBigInt(bytes_k) trits = convertBigintToBase(bigInt, 3, TRIT_HASH_LENGTH) return trits -def convertToBytes(trits): +def convertToBytes(trits: List[int]) -> List[int]: bigInt = convertBaseToBigint(trits, 3) bytes_k = convertBigintToBytes(bigInt) return bytes_k -def convertBytesToBigInt(ba): +def convertBytesToBigInt(ba: List[int]) -> int: # copy of array bytesArray = list(map(lambda x: x, ba)) @@ -88,7 +91,7 @@ def convertBytesToBigInt(ba): enumerate(reversed(bytesArray))) * signum -def convertBigintToBytes(big): +def convertBigintToBytes(big: int) -> List[int]: bytesArrayTemp = [(abs(big) >> pos * 8) % (1 << 8) for pos in range(48)] @@ -112,7 +115,7 @@ def convertBigintToBytes(big): return bytesArray -def convertBaseToBigint(array, base): +def convertBaseToBigint(array: List[int], base: int) -> int: bigint = 0 for i in range(len(array)): @@ -121,7 +124,7 @@ def convertBaseToBigint(array, base): return bigint -def convertBigintToBase(bigInt, base, length): +def convertBigintToBase(bigInt: int, base: int, length: int) -> List[int]: result = [] is_negative = bigInt < 0 @@ -147,7 +150,7 @@ def convertBigintToBase(bigInt, base, length): return result -def convert_sign(byte): +def convert_sign(byte: int) -> int: """ Convert between signed and unsigned bytes. """ diff --git a/iota/crypto/kerl/pykerl.py b/iota/crypto/kerl/pykerl.py index 365e022..d4bb8f1 100644 --- a/iota/crypto/kerl/pykerl.py +++ b/iota/crypto/kerl/pykerl.py @@ -14,13 +14,17 @@ class Kerl(object): - k = None # type: keccak_384 + k: keccak_384 = None - def __init__(self): + def __init__(self) -> None: self.reset() - def absorb(self, trits, offset=0, length=None): - # type: (MutableSequence[int], int, Optional[int]) -> None + def absorb( + self, + trits: MutableSequence[int], + offset: int = 0, + length: Optional[int] = None + ) -> None: """ Absorb trits into the sponge from a buffer. @@ -74,8 +78,12 @@ def absorb(self, trits, offset=0, length=None): offset += TRIT_HASH_LENGTH - def squeeze(self, trits, offset=0, length=None): - # type: (MutableSequence[int], int, Optional[int]) -> None + def squeeze( + self, + trits: MutableSequence[int], + offset: int = 0, + length: Optional[int] = None + ) -> None: """ Squeeze trits from the sponge into a buffer. @@ -135,5 +143,5 @@ def squeeze(self, trits, offset=0, length=None): offset += TRIT_HASH_LENGTH - def reset(self): + def reset(self) -> None: self.k = keccak_384() diff --git a/iota/crypto/pycurl.py b/iota/crypto/pycurl.py index 639f7c2..0c301b2 100644 --- a/iota/crypto/pycurl.py +++ b/iota/crypto/pycurl.py @@ -45,19 +45,21 @@ class Curl(object): **IMPORTANT: Not thread-safe!** """ - def __init__(self): - # type: (Optional[Sequence[int]]) -> None + def __init__(self) -> None: self.reset() - def reset(self): - # type: () -> None + def reset(self) -> None: """ Resets internal state. """ - self._state = [0] * STATE_LENGTH # type: List[int] - - def absorb(self, trits, offset=0, length=None): - # type: (Sequence[int], Optional[int], Optional[int]) -> None + self._state: List[int] = [0] * STATE_LENGTH + + def absorb( + self, + trits: Sequence[int], + offset: Optional[int] = 0, + length: Optional[int] = None + ) -> None: """ Absorb trits into the sponge. @@ -107,8 +109,12 @@ def absorb(self, trits, offset=0, length=None): # Move on to the next hash. offset += HASH_LENGTH - def squeeze(self, trits, offset=0, length=HASH_LENGTH): - # type: (MutableSequence[int], Optional[int], Optional[int]) -> None + def squeeze( + self, + trits: MutableSequence[int], + offset: Optional[int] = 0, + length: Optional[int] = HASH_LENGTH + ) -> None: """ Squeeze trits from the sponge. @@ -166,8 +172,7 @@ def squeeze(self, trits, offset=0, length=HASH_LENGTH): offset += HASH_LENGTH length -= HASH_LENGTH - def _transform(self): - # type: () -> None + def _transform(self) -> None: """ Transforms internal state. """ diff --git a/iota/crypto/signing.py b/iota/crypto/signing.py index f735047..0edbe5b 100644 --- a/iota/crypto/signing.py +++ b/iota/crypto/signing.py @@ -1,6 +1,6 @@ from typing import Iterator, List, Sequence -from iota import Hash, TRITS_PER_TRYTE, TryteString, TrytesCompatible +from iota import Hash, TRITS_PER_TRYTE, TryteString, TrytesCompatible, Address from iota.crypto import FRAGMENT_LENGTH, HASH_LENGTH from iota.crypto.kerl import Kerl from iota.crypto.types import PrivateKey, Seed @@ -16,8 +16,7 @@ ] -def normalize(hash_): - # type: (Hash) -> List[List[int]] +def normalize(hash_: Hash) -> List[List[int]]: """ "Normalizes" a hash, converting it into a sequence of integers (not trits!) suitable for use in signature generation/validation. @@ -61,14 +60,12 @@ class KeyGenerator(object): Generates signing keys for messages. """ - def __init__(self, seed): - # type: (TrytesCompatible) -> None + def __init__(self, seed: TrytesCompatible) -> None: super(KeyGenerator, self).__init__() self.seed = Seed(seed) - def get_key(self, index, iterations): - # type: (int, int) -> PrivateKey + def get_key(self, index: int, iterations: int) -> PrivateKey: """ Generates a single key. @@ -85,14 +82,14 @@ def get_key(self, index, iterations): """ return ( self.get_keys( - start=index, - count=1, - step=1, - iterations=iterations, + start=index, + count=1, + step=1, + iterations=iterations, )[0] ) - def get_key_for(self, address): + def get_key_for(self, address: Address): """ Generates the key associated with the specified address. @@ -100,12 +97,17 @@ def get_key_for(self, address): address was generated from a different key! """ return self.get_key( - index=address.key_index, - iterations=address.security_level, + index=address.key_index, + iterations=address.security_level, ) - def get_keys(self, start, count=1, step=1, iterations=1): - # type: (int, int, int, int) -> List[PrivateKey] + def get_keys( + self, + start: int, + count: int = 1, + step: int = 1, + iterations: int = 1 + ) -> List[PrivateKey]: """ Generates and returns one or more keys at the specified index(es). @@ -147,26 +149,26 @@ def get_keys(self, start, count=1, step=1, iterations=1): """ if count < 1: raise with_context( - exc=ValueError('``count`` must be positive.'), - - context={ - 'start': start, - 'count': count, - 'step': step, - 'iterations': iterations, - }, + exc=ValueError('``count`` must be positive.'), + + context={ + 'start': start, + 'count': count, + 'step': step, + 'iterations': iterations, + }, ) if not step: raise with_context( - exc=ValueError('``step`` must not be zero.'), - - context={ - 'start': start, - 'count': count, - 'step': step, - 'iterations': iterations, - }, + exc=ValueError('``step`` must not be zero.'), + + context={ + 'start': start, + 'count': count, + 'step': step, + 'iterations': iterations, + }, ) iterator = self.create_iterator(start, step, iterations) @@ -182,8 +184,12 @@ def get_keys(self, start, count=1, step=1, iterations=1): return keys - def create_iterator(self, start=0, step=1, security_level=1): - # type: (int, int, int) -> KeyIterator + def create_iterator( + self, + start: int = 0, + step: int = 1, + security_level: int = 1 + ) -> 'KeyIterator': """ Creates a generator that can be used to progressively generate new keys. @@ -218,34 +224,39 @@ class KeyIterator(Iterator[PrivateKey]): Creates PrivateKeys from a set of iteration parameters. """ - def __init__(self, seed, start, step, security_level): - # type: (Seed, int, int, int) -> None + def __init__( + self, + seed: Seed, + start: int, + step: int, + security_level: int + ) -> None: super(KeyIterator, self).__init__() if start < 0: raise with_context( - exc=ValueError('``start`` cannot be negative.'), + exc=ValueError('``start`` cannot be negative.'), - context={ - 'start': start, - 'step': step, - 'security_level': security_level, - }, + context={ + 'start': start, + 'step': step, + 'security_level': security_level, + }, ) if security_level < 1: raise with_context( - exc=ValueError('``security_level`` must be >= 1.'), + exc=ValueError('``security_level`` must be >= 1.'), - context={ - 'start': start, - 'step': step, - 'security_level': security_level, - }, + context={ + 'start': start, + 'step': step, + 'security_level': security_level, + }, ) # In order to work correctly, the seed must be padded so that it - # is a multiple of 81 trytes. + # is a multiple of 81 trytes. seed += b'9' * (Hash.LEN - ((len(seed) % Hash.LEN) or Hash.LEN)) self.security_level = security_level @@ -258,12 +269,10 @@ def __init__(self, seed, start, step, security_level): self.fragment_length = FRAGMENT_LENGTH * TRITS_PER_TRYTE self.hashes_per_fragment = FRAGMENT_LENGTH // Hash.LEN - def __iter__(self): - # type: () -> KeyIterator + def __iter__(self) -> 'KeyIterator': return self - def __next__(self): - # type: () -> PrivateKey + def __next__(self) -> PrivateKey: while self.current >= 0: sponge = self._create_sponge(self.current) @@ -277,8 +286,8 @@ def __next__(self): sponge.squeeze(buffer) key_start = ( - (fragment_seq * self.fragment_length) + - (hash_seq * HASH_LENGTH) + (fragment_seq * self.fragment_length) + + (hash_seq * HASH_LENGTH) ) key_stop = key_start + HASH_LENGTH @@ -289,23 +298,22 @@ def __next__(self): key[key_start:key_stop] = buffer[0:HASH_LENGTH] private_key = PrivateKey.from_trits( - key_index=self.current, - security_level=self.security_level, - trits=key, + key_index=self.current, + security_level=self.security_level, + trits=key, ) self.advance() return private_key - def advance(self): + def advance(self) -> None: """ Advances the generator without creating a key. """ self.current += self.step - def _create_sponge(self, index): - # type: (int) -> Kerl + def _create_sponge(self, index: int) -> Kerl: """ Prepares the hash sponge for the generator. """ @@ -333,8 +341,7 @@ class SignatureFragmentGenerator(Iterator[TryteString]): key. """ - def __init__(self, private_key, hash_): - # type: (PrivateKey, Hash) -> None + def __init__(self, private_key: PrivateKey, hash_: Hash) -> None: super(SignatureFragmentGenerator, self).__init__() self._key_chunks = private_key.iter_chunks(FRAGMENT_LENGTH) @@ -342,12 +349,10 @@ def __init__(self, private_key, hash_): self._normalized_hash = normalize(hash_) self._sponge = Kerl() - def __iter__(self): - # type: () -> SignatureFragmentGenerator + def __iter__(self) -> 'SignatureFragmentGenerator': return self - def __len__(self): - # type: () -> int + def __len__(self) -> int: """ Returns the number of fragments this generator can create. @@ -356,12 +361,11 @@ def __len__(self): """ return len(self._key_chunks) - def __next__(self): - # type: () -> TryteString + def __next__(self) -> TryteString: """ Returns the next signature fragment. """ - key_trytes = next(self._key_chunks) # type: TryteString + key_trytes: TryteString = next(self._key_chunks) self._iteration += 1 # If the key is long enough, loop back around to the start. @@ -376,7 +380,7 @@ def __next__(self): hash_start = i * HASH_LENGTH hash_end = hash_start + HASH_LENGTH - buffer = signature_fragment[hash_start:hash_end] # type: List[int] + buffer: List[int] = signature_fragment[hash_start:hash_end] for _ in range(13 - normalized_chunk[i]): self._sponge.reset() @@ -387,13 +391,13 @@ def __next__(self): return TryteString.from_trits(signature_fragment) + def validate_signature_fragments( - fragments, - hash_, - public_key, - sponge_type=Kerl, -): - # type: (Sequence[TryteString], Hash, TryteString, type) -> bool + fragments: Sequence[TryteString], + hash_: Hash, + public_key: TryteString, + sponge_type: type = Kerl, +) -> bool: """ Returns whether a sequence of signature fragments is valid. @@ -424,7 +428,7 @@ def validate_signature_fragments( buffer = [] for j, hash_trytes in enumerate(fragment.iter_chunks(Hash.LEN)): - buffer = hash_trytes.as_trits() # type: List[int] + buffer: List[int] = hash_trytes.as_trits() inner_sponge = sponge_type() # Note the sign flip compared to diff --git a/iota/crypto/types.py b/iota/crypto/types.py index 64e9963..99b4869 100644 --- a/iota/crypto/types.py +++ b/iota/crypto/types.py @@ -1,5 +1,5 @@ import warnings -from typing import Optional +from typing import Optional, Dict from iota.crypto import FRAGMENT_LENGTH, HASH_LENGTH, SeedWarning from iota.crypto.kerl import Kerl @@ -33,8 +33,11 @@ class Digest(TryteString): if length of ``trytes`` is not multiple of :py:attr:`iota.Hash.LEN`. """ - def __init__(self, trytes, key_index=None): - # type: (TrytesCompatible, Optional[int]) -> None + def __init__( + self, + trytes: TrytesCompatible, + key_index: Optional[int] = None + ) -> None: super(Digest, self).__init__(trytes) # A digest is a series of hashes; its length should reflect @@ -57,8 +60,7 @@ def __init__(self, trytes, key_index=None): self.key_index = key_index @property - def security_level(self): - # type: () -> int + def security_level(self) -> int: """ Returns the number of iterations that were used to generate this digest (also known as "security level"). @@ -68,8 +70,7 @@ def security_level(self): """ return len(self) // Hash.LEN - def as_json_compatible(self): - # type: () -> dict + def as_json_compatible(self) -> Dict: """ Returns a JSON-compatible representation of the digest. @@ -113,8 +114,7 @@ class Seed(TryteString): Length of a Seed. """ - def __init__(self, trytes=None): - # type: (Optional[TrytesCompatible]) -> None + def __init__(self, trytes: Optional[TrytesCompatible] = None) -> None: if trytes and len(trytes) > Hash.LEN: warnings.warn( message=( @@ -128,7 +128,7 @@ def __init__(self, trytes=None): super(Seed, self).__init__(trytes) @classmethod - def random(cls, length=Hash.LEN): + def random(cls, length: int = Hash.LEN) -> 'Seed': """ Generates a random seed using a CSPRNG. @@ -175,8 +175,12 @@ class PrivateKey(TryteString): :py:attr:`iota.transaction.Fragement.LEN`. """ - def __init__(self, trytes, key_index=None, security_level=None): - # type: (TrytesCompatible, Optional[int], Optional[int]) -> None + def __init__( + self, + trytes: TrytesCompatible, + key_index: Optional[int] = None, + security_level: Optional[int] = None + ) -> None: super(PrivateKey, self).__init__(trytes) if len(self._trytes) % FRAGMENT_LENGTH: @@ -197,8 +201,7 @@ def __init__(self, trytes, key_index=None, security_level=None): self.key_index = key_index self.security_level = security_level - def as_json_compatible(self): - # type: () -> dict + def as_json_compatible(self) -> Dict: """ Returns a JSON-compatible representation of the private key. @@ -218,8 +221,7 @@ def as_json_compatible(self): 'security_level': self.security_level, } - def get_digest(self): - # type: () -> Digest + def get_digest(self) -> Digest: """ Generates the digest used to do the actual signing. @@ -276,8 +278,11 @@ def get_digest(self): return Digest(TryteString.from_trits(digest), self.key_index) - def sign_input_transactions(self, bundle, start_index): - # type: (Bundle, int) -> None + def sign_input_transactions( + self, + bundle: Bundle, + start_index: int + ) -> None: """ Signs the inputs starting at the specified index. diff --git a/iota/exceptions.py b/iota/exceptions.py index c10e106..dbc5348 100644 --- a/iota/exceptions.py +++ b/iota/exceptions.py @@ -4,8 +4,7 @@ ] -def with_context(exc, context): - # type: (Exception, dict) -> Exception +def with_context(exc: Exception, context: dict) -> Exception: """ Attaches a ``context`` value to an Exception. diff --git a/iota/filters.py b/iota/filters.py index 66c4f72..80d0684 100644 --- a/iota/filters.py +++ b/iota/filters.py @@ -40,7 +40,7 @@ class GeneratedAddress(f.BaseFilter): } def _apply(self, value): - value = self._filter(value, f.Type(Address)) # type: Address + value: Address = self._filter(value, f.Type(Address)) if self._has_errors: return None @@ -77,7 +77,7 @@ class NodeUri(f.BaseFilter): } def _apply(self, value): - value = self._filter(value, f.Type(str)) # type: Text + value: Text = self._filter(value, f.Type(str)) if self._has_errors: return None @@ -91,7 +91,7 @@ def _apply(self, value): @filter_macro -def SecurityLevel(): +def SecurityLevel() -> f.FilterChain: """ Generates a filter chain for validating a security level. @@ -133,8 +133,7 @@ class Trytes(f.BaseFilter): CODE_WRONG_FORMAT: 'This value is not a valid {result_type}.', } - def __init__(self, result_type=TryteString): - # type: (type) -> None + def __init__(self, result_type: type = TryteString) -> None: super(Trytes, self).__init__() if not isinstance(result_type, type): @@ -159,13 +158,13 @@ def __init__(self, result_type=TryteString): self.result_type = result_type def _apply(self, value): - value = self._filter( + value: TrytesCompatible = self._filter( filter_chain=f.Type( (bytes, bytearray, str, TryteString) ), value=value, - ) # type: TrytesCompatible + ) if self._has_errors: return None @@ -206,8 +205,7 @@ def _apply(self, value): @filter_macro -def StringifiedTrytesArray(trytes_type=TryteString): - # type: (Type[TryteString]) -> f.FilterChain +def StringifiedTrytesArray(trytes_type: Type = TryteString) -> f.FilterChain: """ Validates that the incoming value is an array containing tryte strings corresponding to the specified type (e.g., @@ -216,7 +214,7 @@ def StringifiedTrytesArray(trytes_type=TryteString): When a value doesn't pass the filter, a ``ValueError`` is raised with lots of contextual info attached to it. - :param TryteString result_type: + :param TryteString trytes_type: Any subclass of :py:class:`~iota.TryteString` that you want the filter to validate. @@ -258,7 +256,7 @@ class AddressNoChecksum(Trytes): 'Checksum is {supplied_checksum}, should be {expected_checksum}?', } - def __init__(self): + def __init__(self) -> None: super(AddressNoChecksum, self).__init__(result_type=Address) def _apply(self, value): diff --git a/iota/multisig/api.py b/iota/multisig/api.py index a337973..d0abdd8 100644 --- a/iota/multisig/api.py +++ b/iota/multisig/api.py @@ -1,4 +1,4 @@ -from typing import Iterable, Optional +from typing import Iterable, Optional, Dict from iota import Address, Iota, AsyncIota, ProposedTransaction from iota.crypto.addresses import AddressGenerator @@ -47,8 +47,10 @@ class AsyncMultisigIota(AsyncIota): - https://github.com/iotaledger/wiki/blob/master/multisigs.md """ - async def create_multisig_address(self, digests): - # type: (Iterable[Digest]) -> dict + async def create_multisig_address( + self, + digests: Iterable[Digest] + ) -> Dict: """ Generates a multisig address from a collection of digests. @@ -74,11 +76,10 @@ async def create_multisig_address(self, digests): async def get_digests( self, - index=0, - count=1, - security_level=AddressGenerator.DEFAULT_SECURITY_LEVEL, - ): - # type: (int, int, int) -> dict + index: int = 0, + count: int = 1, + security_level: int = AddressGenerator.DEFAULT_SECURITY_LEVEL, + ) -> Dict: """ Generates one or more key digests from the seed. @@ -117,11 +118,10 @@ async def get_digests( async def get_private_keys( self, - index=0, - count=1, - security_level=AddressGenerator.DEFAULT_SECURITY_LEVEL, - ): - # type: (int, int, int) -> dict + index: int = 0, + count: int = 1, + security_level: int = AddressGenerator.DEFAULT_SECURITY_LEVEL, + ) -> Dict: """ Generates one or more private keys from the seed. @@ -166,11 +166,10 @@ async def get_private_keys( async def prepare_multisig_transfer( self, - transfers, # type: Iterable[ProposedTransaction] - multisig_input, # type: MultisigAddress - change_address=None, # type: Optional[Address] - ): - # type: (...) -> dict + transfers: Iterable[ProposedTransaction], + multisig_input: MultisigAddress, + change_address: Optional[Address] = None, + ) -> Dict: """ Prepares a bundle that authorizes the spending of IOTAs from a multisig address. @@ -291,8 +290,10 @@ class MultisigIota(Iota, AsyncMultisigIota): - https://github.com/iotaledger/wiki/blob/master/multisigs.md """ - def create_multisig_address(self, digests): - # type: (Iterable[Digest]) -> dict + def create_multisig_address( + self, + digests: Iterable[Digest] + ) -> Dict: """ Generates a multisig address from a collection of digests. @@ -318,11 +319,10 @@ def create_multisig_address(self, digests): def get_digests( self, - index=0, - count=1, - security_level=AddressGenerator.DEFAULT_SECURITY_LEVEL, - ): - # type: (int, int, int) -> dict + index: int = 0, + count: int = 1, + security_level: int = AddressGenerator.DEFAULT_SECURITY_LEVEL, + ) -> Dict: """ Generates one or more key digests from the seed. @@ -362,11 +362,10 @@ def get_digests( def get_private_keys( self, - index=0, - count=1, - security_level=AddressGenerator.DEFAULT_SECURITY_LEVEL, - ): - # type: (int, int, int) -> dict + index: int = 0, + count: int = 1, + security_level: int = AddressGenerator.DEFAULT_SECURITY_LEVEL, + ) -> Dict: """ Generates one or more private keys from the seed. @@ -412,11 +411,10 @@ def get_private_keys( def prepare_multisig_transfer( self, - transfers, # type: Iterable[ProposedTransaction] - multisig_input, # type: MultisigAddress - change_address=None, # type: Optional[Address] - ): - # type: (...) -> dict + transfers: Iterable[ProposedTransaction], + multisig_input: MultisigAddress, + change_address: Optional[Address] = None, + ) -> Dict: """ Prepares a bundle that authorizes the spending of IOTAs from a multisig address. diff --git a/iota/multisig/commands/create_multisig_address.py b/iota/multisig/commands/create_multisig_address.py index 91fbb5a..142160f 100644 --- a/iota/multisig/commands/create_multisig_address.py +++ b/iota/multisig/commands/create_multisig_address.py @@ -1,4 +1,4 @@ -from typing import List +from typing import List, Dict import filters as f @@ -22,7 +22,7 @@ class CreateMultisigAddressCommand(FilterCommand): """ command = 'createMultisigAddress' - def get_request_filter(self): + def get_request_filter(self) -> 'CreateMultisigAddressRequestFilter': return CreateMultisigAddressRequestFilter() def get_response_filter(self): @@ -30,8 +30,8 @@ def get_response_filter(self): # There is no async operation going on here, but the base class is async, # so from the outside, we have to act like we are doing async. - async def _execute(self, request): - digests = request['digests'] # type: List[Digest] + async def _execute(self, request: Dict): + digests: List[Digest] = request['digests'] builder = MultisigAddressBuilder() @@ -44,7 +44,7 @@ async def _execute(self, request): class CreateMultisigAddressRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(CreateMultisigAddressRequestFilter, self).__init__({ 'digests': f.Required | f.Array | f.FilterRepeater( diff --git a/iota/multisig/commands/get_digests.py b/iota/multisig/commands/get_digests.py index ff3bc49..9ced79a 100644 --- a/iota/multisig/commands/get_digests.py +++ b/iota/multisig/commands/get_digests.py @@ -1,4 +1,4 @@ -from typing import Optional +from typing import Optional, Dict import filters as f @@ -22,7 +22,7 @@ class GetDigestsCommand(FilterCommand): """ command = 'getDigests' - def get_request_filter(self): + def get_request_filter(self) -> 'GetDigestsRequestFilter': return GetDigestsRequestFilter() def get_response_filter(self): @@ -30,11 +30,11 @@ def get_response_filter(self): # There is no async operation going on here, but the base class is async, # so from the outside, we have to act like we are doing async. - async def _execute(self, request): - count = request['count'] # type: Optional[int] - index = request['index'] # type: int - seed = request['seed'] # type: Seed - security_level = request['securityLevel'] # type: int + async def _execute(self, request: Dict): + count: Optional[int] = request['count'] + index: int = request['index'] + seed: Seed = request['seed'] + security_level: int = request['securityLevel'] gpk_result = await GetPrivateKeysCommand(self.adapter)( seed=seed, @@ -49,7 +49,7 @@ async def _execute(self, request): class GetDigestsRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(GetDigestsRequestFilter, self).__init__( { # Optional Parameters diff --git a/iota/multisig/commands/get_private_keys.py b/iota/multisig/commands/get_private_keys.py index d1affc9..0dcfadf 100644 --- a/iota/multisig/commands/get_private_keys.py +++ b/iota/multisig/commands/get_private_keys.py @@ -1,4 +1,4 @@ -from typing import Optional +from typing import Optional, Dict import filters as f @@ -23,7 +23,7 @@ class GetPrivateKeysCommand(FilterCommand): """ command = 'getPrivateKeys' - def get_request_filter(self): + def get_request_filter(self) -> 'GetPrivateKeysRequestFilter': return GetPrivateKeysRequestFilter() def get_response_filter(self): @@ -31,11 +31,11 @@ def get_response_filter(self): # There is no async operation going on here, but the base class is async, # so from the outside, we have to act like we are doing async. - async def _execute(self, request): - count = request['count'] # type: Optional[int] - index = request['index'] # type: int - seed = request['seed'] # type: Seed - security_level = request['securityLevel'] # type: int + async def _execute(self, request: Dict): + count: Optional[int] = request['count'] + index: int = request['index'] + seed: Seed = request['seed'] + security_level: int = request['securityLevel'] generator = KeyGenerator(seed) @@ -49,7 +49,7 @@ async def _execute(self, request): class GetPrivateKeysRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(GetPrivateKeysRequestFilter, self).__init__( { # Optional Parameters diff --git a/iota/multisig/commands/prepare_multisig_transfer.py b/iota/multisig/commands/prepare_multisig_transfer.py index b7dd663..7ae2453 100644 --- a/iota/multisig/commands/prepare_multisig_transfer.py +++ b/iota/multisig/commands/prepare_multisig_transfer.py @@ -1,4 +1,4 @@ -from typing import List, Optional +from typing import List, Optional, Dict import filters as f @@ -25,45 +25,45 @@ class PrepareMultisigTransferCommand(FilterCommand): """ command = 'prepareMultisigTransfer' - def get_request_filter(self): + def get_request_filter(self) -> 'PrepareMultisigTransferRequestFilter': return PrepareMultisigTransferRequestFilter() def get_response_filter(self): pass - async def _execute(self, request): - change_address = request['changeAddress'] # type: Optional[Address] - multisig_input = request['multisigInput'] # type: MultisigAddress - transfers = request['transfers'] # type: List[ProposedTransaction] + async def _execute(self, request: Dict): + change_address: Optional[Address] = request['changeAddress'] + multisig_input: MultisigAddress = request['multisigInput'] + transfers: List[ProposedTransaction] = request['transfers'] bundle = ProposedMultisigBundle(transfers) want_to_spend = bundle.balance if want_to_spend > 0: gb_response = await GetBalancesCommand(self.adapter)( - addresses=[multisig_input], + addresses=[multisig_input], ) multisig_input.balance = gb_response['balances'][0] if multisig_input.balance < want_to_spend: raise with_context( - exc=ValueError( - 'Insufficient balance; found {found}, need {need} ' - '(``exc.context`` has more info).'.format( - found=multisig_input.balance, - need=want_to_spend, + exc=ValueError( + 'Insufficient balance; found {found}, need {need} ' + '(``exc.context`` has more info).'.format( + found=multisig_input.balance, + need=want_to_spend, + ), ), - ), - # The structure of this context object is intended - # to match the one from ``PrepareTransferCommand``. - context={ - 'available_to_spend': multisig_input.balance, - 'confirmed_inputs': [multisig_input], - 'request': request, - 'want_to_spend': want_to_spend, - }, + # The structure of this context object is intended + # to match the one from ``PrepareTransferCommand``. + context={ + 'available_to_spend': multisig_input.balance, + 'confirmed_inputs': [multisig_input], + 'request': request, + 'want_to_spend': want_to_spend, + }, ) bundle.add_inputs([multisig_input]) @@ -86,29 +86,29 @@ async def _execute(self, request): # method! # raise with_context( - exc=ValueError( - 'Bundle has unspent inputs, ' - 'but no change address specified.', - ), - - context={ - 'available_to_spend': multisig_input.balance, - 'balance': bundle.balance, - 'confirmed_inputs': [multisig_input], - 'request': request, - 'want_to_spend': want_to_spend, - }, + exc=ValueError( + 'Bundle has unspent inputs, ' + 'but no change address specified.', + ), + + context={ + 'available_to_spend': multisig_input.balance, + 'balance': bundle.balance, + 'confirmed_inputs': [multisig_input], + 'request': request, + 'want_to_spend': want_to_spend, + }, ) else: raise with_context( - exc=ValueError( - 'Use ``prepare_transfer`` ' - 'to create a bundle without spending IOTAs.', - ), + exc=ValueError( + 'Use ``prepare_transfer`` ' + 'to create a bundle without spending IOTAs.', + ), - context={ - 'request': request, - }, + context={ + 'request': request, + }, ) bundle.finalize() @@ -120,19 +120,19 @@ async def _execute(self, request): class PrepareMultisigTransferRequestFilter(RequestFilter): - def __init__(self): + def __init__(self) -> None: super(PrepareMultisigTransferRequestFilter, self).__init__( - { - 'changeAddress': Trytes(Address), - 'multisigInput': f.Required | f.Type(MultisigAddress), + { + 'changeAddress': Trytes(Address), + 'multisigInput': f.Required | f.Type(MultisigAddress), - 'transfers': - f.Required | f.Array | f.FilterRepeater( - f.Required | f.Type(ProposedTransaction), - ), - }, + 'transfers': + f.Required | f.Array | f.FilterRepeater( + f.Required | f.Type(ProposedTransaction), + ), + }, - allow_missing_keys={ - 'changeAddress', - }, + allow_missing_keys={ + 'changeAddress', + }, ) diff --git a/iota/multisig/crypto/addresses.py b/iota/multisig/crypto/addresses.py index 24fb1ce..abf5473 100644 --- a/iota/multisig/crypto/addresses.py +++ b/iota/multisig/crypto/addresses.py @@ -20,16 +20,16 @@ class MultisigAddressBuilder(object): multiple addresses from a single input (seed). """ - def __init__(self): + def __init__(self) -> None: super(MultisigAddressBuilder, self).__init__() - self._digests = [] # type: List[Digest] + self._digests: List[Digest] = [] """ Keeps track of digests that were added, so that we can attach them to the final :py:class:`MultisigAddress` object. """ - self._address = None # type: Optional[MultisigAddress] + self._address: Optional[MultisigAddress] = None """ Caches the generated address. @@ -40,8 +40,7 @@ def __init__(self): self._sponge = Kerl() - def add_digest(self, digest): - # type: (Digest) -> None + def add_digest(self, digest: Digest) -> None: """ Absorbs a digest into the sponge. @@ -61,8 +60,7 @@ def add_digest(self, digest): self._sponge.absorb(digest.as_trits()) self._digests.append(digest) - def get_address(self): - # type: () -> MultisigAddress + def get_address(self) -> MultisigAddress: """ Returns the new multisig address. diff --git a/iota/multisig/transaction.py b/iota/multisig/transaction.py index 53ba855..cce6ca3 100644 --- a/iota/multisig/transaction.py +++ b/iota/multisig/transaction.py @@ -36,8 +36,7 @@ class ProposedMultisigBundle(ProposedBundle): :return: :py:class:`ProposedMultisigBundle` object. """ - def add_inputs(self, inputs): - # type: (Iterable[MultisigAddress]) -> None + def add_inputs(self, inputs: Iterable[MultisigAddress]) -> None: """ Adds inputs to spend in the bundle. diff --git a/iota/multisig/types.py b/iota/multisig/types.py index e9623aa..c0691b5 100644 --- a/iota/multisig/types.py +++ b/iota/multisig/types.py @@ -1,5 +1,5 @@ from operator import attrgetter -from typing import Iterable, Optional +from typing import Iterable, Optional, Dict from iota import Address, TrytesCompatible from iota.crypto.types import Digest @@ -42,8 +42,12 @@ class MultisigAddress(Address): :py:class:`MultisigAddress` object. """ - def __init__(self, trytes, digests, balance=None): - # type: (TrytesCompatible, Iterable[Digest], Optional[int]) -> None + def __init__( + self, + trytes: TrytesCompatible, + digests: Iterable[Digest], + balance: Optional[int] = None + ) -> None: # Key index is meaningless for multisig addresses. super(MultisigAddress, self).__init__(trytes, balance, key_index=None) @@ -53,7 +57,7 @@ def __init__(self, trytes, digests, balance=None): map(attrgetter('security_level'), self.digests) ) - def as_json_compatible(self): + def as_json_compatible(self) -> Dict: """ Get a JSON represenation of the :py:class:`MultisigAddress` object. @@ -70,7 +74,6 @@ def as_json_compatible(self): } """ - # type: () -> dict return { 'trytes': self._trytes.decode('ascii'), 'balance': self.balance, diff --git a/iota/transaction/base.py b/iota/transaction/base.py index b46fe3a..b971352 100644 --- a/iota/transaction/base.py +++ b/iota/transaction/base.py @@ -1,6 +1,6 @@ from operator import attrgetter from typing import Iterable, Iterator, List, MutableSequence, \ - Optional, Sequence, Text + Optional, Sequence, Text, TypeVar, Type, Dict from iota.codecs import TrytesDecodeError from iota.crypto import Curl, HASH_LENGTH @@ -15,6 +15,8 @@ 'Transaction', ] +T = TypeVar('T', bound='Transaction') + class Transaction(JsonSerializable): """ @@ -76,8 +78,11 @@ class Transaction(JsonSerializable): """ @classmethod - def from_tryte_string(cls, trytes, hash_=None): - # type: (TrytesCompatible, Optional[TransactionHash]) -> Transaction + def from_tryte_string( + cls: Type[T], + trytes: TrytesCompatible, + hash_: Optional[TransactionHash] = None + ) -> T: """ Creates a Transaction object from a sequence of trytes. @@ -146,7 +151,7 @@ def from_tryte_string(cls, trytes, hash_=None): tryte_string = TransactionTrytes(trytes) if not hash_: - hash_trits = [0] * HASH_LENGTH # type: MutableSequence[int] + hash_trits: MutableSequence[int] = [0] * HASH_LENGTH sponge = Curl() sponge.absorb(tryte_string.as_trits()) @@ -155,51 +160,51 @@ def from_tryte_string(cls, trytes, hash_=None): hash_ = TransactionHash.from_trits(hash_trits) return cls( - hash_=hash_, - signature_message_fragment=Fragment(tryte_string[0:2187]), - address=Address(tryte_string[2187:2268]), - value=int_from_trits(tryte_string[2268:2295].as_trits()), - legacy_tag=Tag(tryte_string[2295:2322]), - timestamp=int_from_trits(tryte_string[2322:2331].as_trits()), - current_index=int_from_trits(tryte_string[2331:2340].as_trits()), - last_index=int_from_trits(tryte_string[2340:2349].as_trits()), - bundle_hash=BundleHash(tryte_string[2349:2430]), - trunk_transaction_hash=TransactionHash(tryte_string[2430:2511]), - branch_transaction_hash=TransactionHash(tryte_string[2511:2592]), - tag=Tag(tryte_string[2592:2619]), - - attachment_timestamp=int_from_trits( - tryte_string[2619:2628].as_trits()), - - attachment_timestamp_lower_bound=int_from_trits( - tryte_string[2628:2637].as_trits()), - - attachment_timestamp_upper_bound=int_from_trits( - tryte_string[2637:2646].as_trits()), - - nonce=Nonce(tryte_string[2646:2673]), + hash_=hash_, + signature_message_fragment=Fragment(tryte_string[0:2187]), + address=Address(tryte_string[2187:2268]), + value=int_from_trits(tryte_string[2268:2295].as_trits()), + legacy_tag=Tag(tryte_string[2295:2322]), + timestamp=int_from_trits(tryte_string[2322:2331].as_trits()), + current_index=int_from_trits(tryte_string[2331:2340].as_trits()), + last_index=int_from_trits(tryte_string[2340:2349].as_trits()), + bundle_hash=BundleHash(tryte_string[2349:2430]), + trunk_transaction_hash=TransactionHash(tryte_string[2430:2511]), + branch_transaction_hash=TransactionHash(tryte_string[2511:2592]), + tag=Tag(tryte_string[2592:2619]), + + attachment_timestamp=int_from_trits( + tryte_string[2619:2628].as_trits()), + + attachment_timestamp_lower_bound=int_from_trits( + tryte_string[2628:2637].as_trits()), + + attachment_timestamp_upper_bound=int_from_trits( + tryte_string[2637:2646].as_trits()), + + nonce=Nonce(tryte_string[2646:2673]), ) def __init__( self, - hash_, # type: Optional[TransactionHash] - signature_message_fragment, # type: Optional[Fragment] - address, # type: Address - value, # type: int - timestamp, # type: int - current_index, # type: Optional[int] - last_index, # type: Optional[int] - bundle_hash, # type: Optional[BundleHash] - trunk_transaction_hash, # type: Optional[TransactionHash] - branch_transaction_hash, # type: Optional[TransactionHash] - tag, # type: Optional[Tag] - attachment_timestamp, # type: Optional[int] - attachment_timestamp_lower_bound, # type: Optional[int] - attachment_timestamp_upper_bound, # type: Optional[int] - nonce, # type: Optional[Nonce] - legacy_tag=None # type: Optional[Tag] - ): - self.hash = hash_ + hash_: Optional[TransactionHash], + signature_message_fragment: Optional[Fragment], + address: Address, + value: int, + timestamp: int, + current_index: Optional[int], + last_index: Optional[int], + bundle_hash: Optional[BundleHash], + trunk_transaction_hash: Optional[TransactionHash], + branch_transaction_hash: Optional[TransactionHash], + tag: Optional[Tag], + attachment_timestamp: Optional[int], + attachment_timestamp_lower_bound: Optional[int], + attachment_timestamp_upper_bound: Optional[int], + nonce: Optional[Nonce], + legacy_tag: Optional[Tag] = None + ) -> None: + self.hash: TransactionHash = hash_ """ The transaction hash, used to uniquely identify the transaction on the Tangle. @@ -209,7 +214,7 @@ def __init__( :type: :py:class:`TransactionHash` """ - self.bundle_hash = bundle_hash + self.bundle_hash: BundleHash = bundle_hash """ The bundle hash, used to identify transactions that are part of the same bundle. @@ -220,7 +225,7 @@ def __init__( :type: :py:class:`BundleHash` """ - self.address = address + self.address: Address = address """ The address associated with this transaction. @@ -231,7 +236,7 @@ def __init__( :type: :py:class:`Address` """ - self.value = value + self.value: int = value """ The number of iotas being transferred in this transaction: @@ -244,7 +249,7 @@ def __init__( :type: ``int`` """ - self._legacy_tag = legacy_tag + self._legacy_tag: Tag = legacy_tag """ A short message attached to the transaction. @@ -254,7 +259,7 @@ def __init__( :type: :py:class:`Tag` """ - self.nonce = nonce + self.nonce: Nonce = nonce """ Unique value used to increase security of the transaction hash. @@ -263,7 +268,7 @@ def __init__( :type: :py:class:`Nonce` """ - self.timestamp = timestamp + self.timestamp: int = timestamp """ Timestamp used to increase the security of the transaction hash. @@ -276,7 +281,7 @@ def __init__( :type: ``int``, unix timestamp in seconds. """ - self.current_index = current_index + self.current_index: int = current_index """ The position of the transaction inside the bundle. @@ -290,7 +295,7 @@ def __init__( :type: ``int`` """ - self.last_index = last_index + self.last_index: int = last_index """ The index of the final transaction in the bundle. @@ -300,7 +305,7 @@ def __init__( :type: ``int`` """ - self.trunk_transaction_hash = trunk_transaction_hash + self.trunk_transaction_hash: TransactionHash = trunk_transaction_hash """ The transaction hash of the next transaction in the bundle. @@ -314,7 +319,7 @@ def __init__( :type: :py:class:`TransactionHash` """ - self.branch_transaction_hash = branch_transaction_hash + self.branch_transaction_hash: TransactionHash = branch_transaction_hash """ An unrelated transaction that this transaction "approves". @@ -329,7 +334,7 @@ def __init__( :type: :py:class:`TransactionHash` """ - self.tag = tag + self.tag: Tag = tag """ Optional classification tag applied to this transaction. @@ -338,7 +343,7 @@ def __init__( :type: :py:class:`Tag` """ - self.attachment_timestamp = attachment_timestamp + self.attachment_timestamp: int = attachment_timestamp """ Estimated epoch time of the attachment to the tangle. @@ -347,21 +352,21 @@ def __init__( :type: ``int``, unix timestamp in milliseconds, """ - self.attachment_timestamp_lower_bound = attachment_timestamp_lower_bound + self.attachment_timestamp_lower_bound: int = attachment_timestamp_lower_bound """ The lowest possible epoch time of the attachment to the tangle. :type: ``int``, unix timestamp in milliseconds. """ - self.attachment_timestamp_upper_bound = attachment_timestamp_upper_bound + self.attachment_timestamp_upper_bound: int = attachment_timestamp_upper_bound """ The highest possible epoch time of the attachment to the tangle. :type: ``int``, unix timestamp in milliseconds. """ - self.signature_message_fragment = signature_message_fragment + self.signature_message_fragment: Fragment = signature_message_fragment """ "Signature/Message Fragment" (note the slash): @@ -381,7 +386,7 @@ def __init__( :type: :py:class:`Fragment` """ - self.is_confirmed = None # type: Optional[bool] + self.is_confirmed: bool = None """ Whether this transaction has been confirmed by neighbor nodes. Must be set manually via the ``getInclusionStates`` API command. @@ -395,8 +400,7 @@ def __init__( """ @property - def is_tail(self): - # type: () -> bool + def is_tail(self) -> bool: """ Returns whether this transaction is a tail (first one in the bundle). @@ -408,8 +412,7 @@ def is_tail(self): return self.current_index == 0 @property - def value_as_trytes(self): - # type: () -> TryteString + def value_as_trytes(self) -> TryteString: """ Returns a TryteString representation of the transaction's :py:attr:`value`. @@ -418,8 +421,7 @@ def value_as_trytes(self): return TryteString.from_trits(trits_from_int(self.value, pad=81)) @property - def timestamp_as_trytes(self): - # type: () -> TryteString + def timestamp_as_trytes(self) -> TryteString: """ Returns a TryteString representation of the transaction's :py:attr:`timestamp`. @@ -428,20 +430,18 @@ def timestamp_as_trytes(self): return TryteString.from_trits(trits_from_int(self.timestamp, pad=27)) @property - def current_index_as_trytes(self): - # type: () -> TryteString + def current_index_as_trytes(self) -> TryteString: """ Returns a TryteString representation of the transaction's :py:attr:`current_index`. """ # Note that we are padding to 27 *trits*. return TryteString.from_trits( - trits_from_int(self.current_index, pad=27), + trits_from_int(self.current_index, pad=27), ) @property - def last_index_as_trytes(self): - # type: () -> TryteString + def last_index_as_trytes(self) -> TryteString: """ Returns a TryteString representation of the transaction's :py:attr:`last_index`. @@ -450,43 +450,39 @@ def last_index_as_trytes(self): return TryteString.from_trits(trits_from_int(self.last_index, pad=27)) @property - def attachment_timestamp_as_trytes(self): - # type: () -> TryteString + def attachment_timestamp_as_trytes(self) -> TryteString: """ Returns a TryteString representation of the transaction's :py:attr:`attachment_timestamp`. """ # Note that we are padding to 27 *trits*. return TryteString.from_trits( - trits_from_int(self.attachment_timestamp, pad=27), + trits_from_int(self.attachment_timestamp, pad=27), ) @property - def attachment_timestamp_lower_bound_as_trytes(self): - # type: () -> TryteString + def attachment_timestamp_lower_bound_as_trytes(self) -> TryteString: """ Returns a TryteString representation of the transaction's :py:attr:`attachment_timestamp_lower_bound`. """ # Note that we are padding to 27 *trits*. return TryteString.from_trits( - trits_from_int(self.attachment_timestamp_lower_bound, pad=27), + trits_from_int(self.attachment_timestamp_lower_bound, pad=27), ) @property - def attachment_timestamp_upper_bound_as_trytes(self): - # type: () -> TryteString + def attachment_timestamp_upper_bound_as_trytes(self) -> TryteString: """ Returns a TryteString representation of the transaction's :py:attr:`attachment_timestamp_upper_bound`. """ # Note that we are padding to 27 *trits*. return TryteString.from_trits( - trits_from_int(self.attachment_timestamp_upper_bound, pad=27), + trits_from_int(self.attachment_timestamp_upper_bound, pad=27), ) - def as_json_compatible(self): - # type: () -> dict + def as_json_compatible(self) -> Dict: """ Returns a JSON-compatible representation of the object. @@ -540,8 +536,7 @@ def as_json_compatible(self): 'nonce': self.nonce, } - def as_tryte_string(self): - # type: () -> TransactionTrytes + def as_tryte_string(self) -> TransactionTrytes: """ Returns a TryteString representation of the transaction. @@ -549,25 +544,24 @@ def as_tryte_string(self): :py:class:`TryteString` object. """ return TransactionTrytes( - self.signature_message_fragment - + self.address.address - + self.value_as_trytes - + self.legacy_tag - + self.timestamp_as_trytes - + self.current_index_as_trytes - + self.last_index_as_trytes - + self.bundle_hash - + self.trunk_transaction_hash - + self.branch_transaction_hash - + self.tag - + self.attachment_timestamp_as_trytes - + self.attachment_timestamp_lower_bound_as_trytes - + self.attachment_timestamp_upper_bound_as_trytes - + self.nonce + self.signature_message_fragment + + self.address.address + + self.value_as_trytes + + self.legacy_tag + + self.timestamp_as_trytes + + self.current_index_as_trytes + + self.last_index_as_trytes + + self.bundle_hash + + self.trunk_transaction_hash + + self.branch_transaction_hash + + self.tag + + self.attachment_timestamp_as_trytes + + self.attachment_timestamp_lower_bound_as_trytes + + self.attachment_timestamp_upper_bound_as_trytes + + self.nonce ) - def get_bundle_essence_trytes(self): - # type: () -> TryteString + def get_bundle_essence_trytes(self) -> TryteString: """ Returns the values needed for calculating bundle hash. The bundle hash is the hash of the bundle essence, which is itself @@ -597,8 +591,7 @@ def get_bundle_essence_trytes(self): ) @property - def legacy_tag(self): - # type: () -> Tag + def legacy_tag(self) -> Tag: """ Return the legacy tag of the transaction. If no legacy tag was set, returns the tag instead. @@ -606,6 +599,9 @@ def legacy_tag(self): return self._legacy_tag or self.tag +B = TypeVar('B', bound='Bundle') + + class Bundle(JsonSerializable, Sequence[Transaction]): """ A collection of transactions, treated as an atomic unit when @@ -630,8 +626,7 @@ class Bundle(JsonSerializable, Sequence[Transaction]): """ @classmethod - def from_tryte_strings(cls, trytes): - # type: (Iterable[TryteString]) -> Bundle + def from_tryte_strings(cls: Type[B], trytes: Iterable[TryteString]) -> B: """ Creates a Bundle object from a list of tryte values. @@ -657,20 +652,22 @@ def from_tryte_strings(cls, trytes): """ return cls(map(Transaction.from_tryte_string, trytes)) - def __init__(self, transactions=None): - # type: (Optional[Iterable[Transaction]]) -> None + def __init__( + self, + transactions: Optional[Iterable[Transaction]] = None + ) -> None: super(Bundle, self).__init__() - self.transactions = [] # type: List[Transaction] + self.transactions: List[Transaction] = [] """ List of :py:class:`Transaction` objects that are in the bundle. """ if transactions: self.transactions.extend( - sorted(transactions, key=attrgetter('current_index')), + sorted(transactions, key=attrgetter('current_index')), ) - self._is_confirmed = None # type: Optional[bool] + self._is_confirmed: Optional[bool] = None """ Whether this bundle has been confirmed by neighbor nodes. Must be set manually. @@ -680,25 +677,20 @@ def __init__(self, transactions=None): - :py:class:`Iota.get_transfers` """ - def __contains__(self, transaction): - # type: (Transaction) -> bool + def __contains__(self, transaction: Transaction) -> bool: return transaction in self.transactions - def __getitem__(self, index): - # type: (int) -> Transaction + def __getitem__(self, index: int) -> Transaction: return self.transactions[index] - def __iter__(self): - # type: () -> Iterator[Transaction] + def __iter__(self) -> Iterator[Transaction]: return iter(self.transactions) - def __len__(self): - # type: () -> int + def __len__(self) -> int: return len(self.transactions) @property - def is_confirmed(self): - # type: () -> Optional[bool] + def is_confirmed(self) -> Optional[bool]: """ Returns whether this bundle has been confirmed by neighbor nodes. @@ -714,8 +706,7 @@ def is_confirmed(self): return self._is_confirmed @is_confirmed.setter - def is_confirmed(self, new_is_confirmed): - # type: (bool) -> None + def is_confirmed(self, new_is_confirmed: bool) -> None: """ Sets the ``is_confirmed`` for the bundle. """ @@ -725,8 +716,7 @@ def is_confirmed(self, new_is_confirmed): txn.is_confirmed = new_is_confirmed @property - def hash(self): - # type: () -> Optional[BundleHash] + def hash(self) -> Optional[BundleHash]: """ Returns the hash of the bundle. @@ -743,8 +733,7 @@ def hash(self): return None @property - def tail_transaction(self): - # type: () -> Transaction + def tail_transaction(self) -> Transaction: """ Returns the tail transaction of the bundle. @@ -752,8 +741,7 @@ def tail_transaction(self): """ return self[0] - def get_messages(self, errors='drop'): - # type: (Text) -> List[Text] + def get_messages(self, errors: Text = 'drop') -> List[Text]: """ Attempts to decipher encoded messages from the transactions in the bundle. @@ -798,8 +786,7 @@ def get_messages(self, errors='drop'): return messages - def as_tryte_strings(self, head_to_tail=False): - # type: (bool) -> List[TransactionTrytes] + def as_tryte_strings(self, head_to_tail: bool = False) -> List[TransactionTrytes]: """ Returns TryteString representations of the transactions in this bundle. @@ -818,8 +805,7 @@ def as_tryte_strings(self, head_to_tail=False): transactions = self if head_to_tail else reversed(self) return [t.as_tryte_string() for t in transactions] - def as_json_compatible(self): - # type: () -> List[dict] + def as_json_compatible(self) -> List[Dict]: """ Returns a JSON-compatible representation of the object. @@ -833,8 +819,7 @@ def as_json_compatible(self): """ return [txn.as_json_compatible() for txn in self] - def group_transactions(self): - # type: () -> List[List[Transaction]] + def group_transactions(self) -> List[List[Transaction]]: """ Groups transactions in the bundle by address. diff --git a/iota/transaction/creation.py b/iota/transaction/creation.py index b798b2e..cb57286 100644 --- a/iota/transaction/creation.py +++ b/iota/transaction/creation.py @@ -1,4 +1,4 @@ -from typing import Iterable, Iterator, List, Optional, Sequence +from typing import Iterable, Iterator, List, Optional, Sequence, Dict from iota.crypto import HASH_LENGTH from iota.crypto.kerl import Kerl @@ -72,12 +72,12 @@ class ProposedTransaction(Transaction): def __init__( self, - address, # type: Address - value, # type: int - tag=None, # type: Optional[Tag] - message=None, # type: Optional[TryteString] - timestamp=None, # type: Optional[int] - ): + address: Address, + value: int, + tag: Optional[Tag] = None, + message: Optional[TryteString] = None, + timestamp: Optional[int] = None, + ) -> None: if not timestamp: timestamp = get_current_timestamp() @@ -107,8 +107,7 @@ def __init__( self.message = TryteString(b'') if message is None else message - def as_tryte_string(self): - # type: () -> TryteString + def as_tryte_string(self) -> TryteString: """ Returns a TryteString representation of the transaction. @@ -136,7 +135,7 @@ def as_tryte_string(self): return super(ProposedTransaction, self).as_tryte_string() - def increment_legacy_tag(self): + def increment_legacy_tag(self) -> None: """ Increments the transaction's legacy tag, used to fix insecure bundle hashes when finalizing a bundle. @@ -184,13 +183,13 @@ class ProposedBundle(Bundle, Sequence[ProposedTransaction]): def __init__( self, - transactions=None, # type: Optional[Iterable[ProposedTransaction]] - inputs=None, # type: Optional[Iterable[Address]] - change_address=None, # type: Optional[Address] - ): + transactions: Optional[Iterable[ProposedTransaction]] = None, + inputs: Optional[Iterable[Address]] = None, + change_address: Optional[Address] = None, + ) -> None: super(ProposedBundle, self).__init__() - self._transactions = [] # type: List[ProposedTransaction] + self._transactions: List[ProposedTransaction] = [] if transactions: for t in transactions: @@ -201,8 +200,7 @@ def __init__( self.change_address = change_address - def __bool__(self): - # type: () -> bool + def __bool__(self) -> bool: """ Returns whether this bundle has any transactions. @@ -210,34 +208,29 @@ def __bool__(self): """ return bool(self._transactions) - def __contains__(self, transaction): - # type: (ProposedTransaction) -> bool + def __contains__(self, transaction: ProposedTransaction) -> bool: return transaction in self._transactions - def __getitem__(self, index): - # type: (int) -> ProposedTransaction + def __getitem__(self, index: int) -> ProposedTransaction: """ Returns the transaction at the specified index. """ return self._transactions[index] - def __iter__(self): - # type: () -> Iterator[ProposedTransaction] + def __iter__(self) -> Iterator[ProposedTransaction]: """ Iterates over transactions in the bundle. """ return iter(self._transactions) - def __len__(self): - # type: () -> int + def __len__(self) -> int: """ Returns te number of transactions in the bundle. """ return len(self._transactions) @property - def balance(self): - # type: () -> int + def balance(self) -> int: """ Returns the bundle balance. In order for a bundle to be valid, its balance must be 0: @@ -255,8 +248,7 @@ def balance(self): return sum(t.value for t in self._transactions) @property - def tag(self): - # type: () -> Tag + def tag(self) -> Tag: """ Determines the most relevant tag for the bundle. @@ -268,8 +260,7 @@ def tag(self): return Tag(b'') - def as_json_compatible(self): - # type: () -> List[dict] + def as_json_compatible(self) -> List[Dict]: """ Returns a JSON-compatible representation of the object. @@ -283,8 +274,7 @@ def as_json_compatible(self): """ return [txn.as_json_compatible() for txn in self] - def add_transaction(self, transaction): - # type: (ProposedTransaction) -> None + def add_transaction(self, transaction: ProposedTransaction) -> None: """ Adds a transaction to the bundle. @@ -328,8 +318,7 @@ def add_transaction(self, transaction): fragment = fragment[Fragment.LEN:] - def add_inputs(self, inputs): - # type: (Iterable[Address]) -> None + def add_inputs(self, inputs: Iterable[Address]) -> None: """ Specifies inputs that can be used to fund transactions that spend iotas. @@ -386,8 +375,7 @@ def add_inputs(self, inputs): self._create_input_transactions(addy) - def send_unspent_inputs_to(self, address): - # type: (Address) -> None + def send_unspent_inputs_to(self, address: Address) -> None: """ Specifies the address that will receive unspent iotas. @@ -406,8 +394,7 @@ def send_unspent_inputs_to(self, address): self.change_address = address - def finalize(self): - # type: () -> None + def finalize(self) -> None: """ Finalizes the bundle, preparing it to be attached to the Tangle. @@ -477,9 +464,9 @@ def finalize(self): # https://github.com/iotaledger/iota.py/issues/84 if any(13 in part for part in normalize(bundle_hash)): # Increment the legacy tag and try again. - tail_transaction = ( + tail_transaction: ProposedTransaction = ( self.tail_transaction - ) # type: ProposedTransaction + ) tail_transaction.increment_legacy_tag() else: break @@ -491,8 +478,7 @@ def finalize(self): # Initialize signature/message fragment. txn.signature_message_fragment = Fragment(txn.message or b'') - def sign_inputs(self, key_generator): - # type: (KeyGenerator) -> None + def sign_inputs(self, key_generator: KeyGenerator) -> None: """ Sign inputs in a finalized bundle. @@ -562,8 +548,11 @@ def sign_inputs(self, key_generator): # cases); skip this transaction. i += 1 - def sign_input_at(self, start_index, private_key): - # type: (int, PrivateKey) -> None + def sign_input_at( + self, + start_index: int, + private_key: PrivateKey + ) -> None: """ Signs the input at the specified index. @@ -590,8 +579,7 @@ def sign_input_at(self, start_index, private_key): private_key.sign_input_transactions(self, start_index) - def _create_input_transactions(self, addy): - # type: (Address) -> None + def _create_input_transactions(self, addy: Address) -> None: """ Creates transactions for the specified input address. @@ -621,10 +609,9 @@ def _create_input_transactions(self, addy): def add_signature_or_message( self, - fragments, # type: Iterable[Fragment] - start_index=0 # type: Optional[int] - ): - # type: (...) -> None + fragments: Iterable[Fragment], + start_index: Optional[int] = 0 + ) -> None: """ Adds signature/message fragments to transactions in the bundle starting at start_index. If a transaction already has a fragment, diff --git a/iota/transaction/types.py b/iota/transaction/types.py index c888c3d..7e8f468 100644 --- a/iota/transaction/types.py +++ b/iota/transaction/types.py @@ -37,8 +37,7 @@ class Fragment(TryteString): Length of a fragment in trytes. """ - def __init__(self, trytes): - # type: (TrytesCompatible) -> None + def __init__(self, trytes: TrytesCompatible) -> None: super(Fragment, self).__init__(trytes, pad=self.LEN) if len(self._trytes) > self.LEN: @@ -65,8 +64,7 @@ class TransactionTrytes(TryteString): Length of a transaction in trytes. """ - def __init__(self, trytes): - # type: (TrytesCompatible) -> None + def __init__(self, trytes: TrytesCompatible) -> None: super(TransactionTrytes, self).__init__(trytes, pad=self.LEN) if len(self._trytes) > self.LEN: @@ -93,8 +91,7 @@ class Nonce(TryteString): Length of a nonce in trytes. """ - def __init__(self, trytes): - # type: (TrytesCompatible) -> None + def __init__(self, trytes: TrytesCompatible) -> None: super(Nonce, self).__init__(trytes, pad=self.LEN) if len(self._trytes) > self.LEN: diff --git a/iota/transaction/utils.py b/iota/transaction/utils.py index 8eacc3f..38e1617 100644 --- a/iota/transaction/utils.py +++ b/iota/transaction/utils.py @@ -11,8 +11,7 @@ ] -def convert_value_to_standard_unit(value, symbol='i'): - # type: (Text, Text) -> float +def convert_value_to_standard_unit(value: Text, symbol: Text = 'i') -> float: """ Converts between any two standard units of iota. @@ -57,8 +56,7 @@ def convert_value_to_standard_unit(value, symbol='i'): return amount * (unit_factor_from / unit_factor_to) -def get_current_timestamp(): - # type: () -> int +def get_current_timestamp() -> int: """ Returns the current timestamp, used to set ``timestamp`` for new :py:class:`ProposedTransaction` objects. diff --git a/iota/transaction/validator.py b/iota/transaction/validator.py index 77710dc..25b009b 100644 --- a/iota/transaction/validator.py +++ b/iota/transaction/validator.py @@ -1,4 +1,4 @@ -from typing import Generator, List, Optional, Text +from typing import Generator, List, Optional, Text, Type from iota.crypto.kerl import Kerl from iota.crypto.signing import validate_signature_fragments @@ -24,18 +24,16 @@ class BundleValidator(object): Checks a bundle and its transactions for problems. """ - def __init__(self, bundle): - # type: (Bundle) -> None + def __init__(self, bundle: Bundle) -> None: super(BundleValidator, self).__init__() self.bundle = bundle - self._errors = [] # type: Optional[List[Text]] + self._errors: Optional[List[Text]] = [] self._validator = self._create_validator() @property - def errors(self): - # type: () -> List[Text] + def errors(self) -> List[Text]: """ Returns all errors found with the bundle. """ @@ -46,8 +44,7 @@ def errors(self): return self._errors - def is_valid(self): - # type: () -> bool + def is_valid(self) -> bool: """ Returns whether the bundle is valid. """ @@ -61,8 +58,7 @@ def is_valid(self): return not self._errors - def _create_validator(self): - # type: () -> Generator[Text, None, None] + def _create_validator(self) -> Generator[Text, None, None]: """ Creates a generator that does all the work. """ @@ -124,7 +120,7 @@ def _create_validator(self): # Signature validation is only meaningful if the transactions # are otherwise valid. if not self._errors: - signature_validation_queue = [] # type: List[List[Transaction]] + signature_validation_queue: List[List[Transaction]] = [] for group in grouped_transactions: # Signature validation only applies to inputs. @@ -181,8 +177,10 @@ def _create_validator(self): ): yield error - def _get_bundle_signature_errors(self, groups): - # type: (List[List[Transaction]]) -> List[Text] + def _get_bundle_signature_errors( + self, + groups: List[List[Transaction]] + ) -> List[Text]: """ Validates the signature fragments in the bundle. @@ -230,8 +228,10 @@ def _get_bundle_signature_errors(self, groups): return current_errors @staticmethod - def _get_group_signature_error(group, sponge_type): - # type: (List[Transaction], type) -> Optional[Text] + def _get_group_signature_error( + group: List[Transaction], + sponge_type: Type + ) -> Optional[Text]: """ Validates the signature fragments for a group of transactions using the specified sponge type. diff --git a/iota/trits.py b/iota/trits.py index 6f45029..6f2fe60 100644 --- a/iota/trits.py +++ b/iota/trits.py @@ -14,8 +14,7 @@ ] -def add_trits(left, right): - # type: (Sequence[int], Sequence[int]) -> List[int] +def add_trits(left: Sequence[int], right: Sequence[int]) -> List[int]: """ Adds two sequences of trits together. @@ -40,8 +39,7 @@ def add_trits(left, right): return res -def int_from_trits(trits): - # type: (Iterable[int]) -> int +def int_from_trits(trits: Iterable[int]) -> int: """ Converts a sequence of trits into an integer value. """ @@ -50,8 +48,7 @@ def int_from_trits(trits): return sum(base * (3 ** power) for power, base in enumerate(trits)) -def trits_from_int(n, pad=1): - # type: (int, Optional[int]) -> List[int] +def trits_from_int(n: int, pad: Optional[int] = 1) -> List[int]: """ Returns a trit representation of an integer value. @@ -86,8 +83,7 @@ def trits_from_int(n, pad=1): return trits -def _cons_trits(left, right): - # type: (int, int) -> int +def _cons_trits(left: int, right: int) -> int: """ Compares two trits. If they have the same value, returns that value. Otherwise, returns 0. @@ -95,8 +91,7 @@ def _cons_trits(left, right): return left if left == right else 0 -def _add_trits(left, right): - # type: (int, int) -> int +def _add_trits(left: int, right: int) -> int: """ Adds two individual trits together. @@ -106,8 +101,7 @@ def _add_trits(left, right): return res if -2 < res < 2 else (res < 0) - (res > 0) -def _any_trits(left, right): - # type: (int, int) -> int +def _any_trits(left: int, right: int) -> int: """ Adds two individual trits together and returns a single trit indicating whether the result is positive or negative. @@ -116,8 +110,7 @@ def _any_trits(left, right): return (res > 0) - (res < 0) -def _full_add_trits(left, right, carry): - # type: (int, int, int) -> Tuple[int, int] +def _full_add_trits(left: int, right: int, carry: int) -> Tuple[int, int]: """ Adds two trits together, with support for a carry trit. """ diff --git a/iota/types.py b/iota/types.py index c01c12b..ac9abd0 100644 --- a/iota/types.py +++ b/iota/types.py @@ -4,7 +4,7 @@ from math import ceil from random import SystemRandom from typing import Any, AnyStr, Generator, Iterable, Iterator, List, \ - MutableSequence, Optional, Text, Type, TypeVar, Union + MutableSequence, Optional, Text, Type, TypeVar, Union, Dict from warnings import warn from iota import AsciiTrytesCodec, TRITS_PER_TRYTE @@ -61,8 +61,7 @@ class TryteString(JsonSerializable): """ @classmethod - def random(cls, length=None): - # type: (Optional[int]) -> TryteString + def random(cls: Type[T], length: Optional[int] = None) -> T: """ Generates a random sequence of trytes. @@ -95,8 +94,11 @@ def random(cls, length=None): ) @classmethod - def from_bytes(cls, bytes_, codec=AsciiTrytesCodec.name, *args, **kwargs): - # type: (Type[T], Union[bytes, bytearray], Text, *Any, **Any) -> T + def from_bytes(cls: Type[T], + bytes_: Union[bytes, bytearray], + codec: Text = AsciiTrytesCodec.name, + *args: Any, + **kwargs: Any) -> T: """ Creates a TryteString from a sequence of bytes. @@ -128,8 +130,10 @@ def from_bytes(cls, bytes_, codec=AsciiTrytesCodec.name, *args, **kwargs): return cls(encode(bytes_, codec), *args, **kwargs) @classmethod - def from_unicode(cls, string, *args, **kwargs): - # type: (Type[T], Text, *Any, **Any) -> T + def from_unicode(cls: Type[T], + string: Text, + *args: Any, + **kwargs: Any) -> T: """ Creates a TryteString from a Unicode string. @@ -159,7 +163,7 @@ def from_unicode(cls, string, *args, **kwargs): ) @classmethod - def from_string(cls, *args, **kwargs): + def from_string(cls: Type[T], *args: Any, **kwargs: Any) -> T: """ Deprecated; use :py:meth:`from_unicode` instead. @@ -175,8 +179,10 @@ def from_string(cls, *args, **kwargs): return cls.from_unicode(*args, **kwargs) @classmethod - def from_trytes(cls, trytes, *args, **kwargs): - # type: (Type[T], Iterable[Iterable[int]], *Any, **Any) -> T + def from_trytes(cls: Type[T], + trytes: Iterable[Iterable[int]], + *args: Any, + **kwargs: Any) -> T: """ Creates a TryteString from a sequence of trytes. @@ -229,8 +235,10 @@ def from_trytes(cls, trytes, *args, **kwargs): return cls(chars, *args, **kwargs) @classmethod - def from_trits(cls, trits, *args, **kwargs): - # type: (Type[T], Iterable[int], *Any, **Any) -> T + def from_trits(cls: Type[T], + trits: Iterable[int], + *args: Any, + **kwargs: Any) -> T: """ Creates a TryteString from a sequence of trits. @@ -274,8 +282,7 @@ def from_trits(cls, trits, *args, **kwargs): **kwargs ) - def __init__(self, trytes, pad=None): - # type: (TrytesCompatible, Optional[int]) -> None + def __init__(self, trytes: TrytesCompatible, pad: Optional[int] = None) -> None: """ :param TrytesCompatible trytes: Byte string or bytearray. @@ -358,20 +365,18 @@ def __init__(self, trytes, pad=None): if pad: trytes += b'9' * max(0, pad - len(trytes)) - self._trytes = trytes # type: bytearray + self._trytes: bytearray = trytes - def __hash__(self): - # type: () -> int + def __hash__(self) -> int: return hash(bytes(self._trytes)) - def __repr__(self): - # type: () -> Text + def __repr__(self) -> Text: return '{cls}({trytes!r})'.format( cls=type(self).__name__, trytes=bytes(self._trytes), ) - def __bytes__(self): + def __bytes__(self) -> bytes: """ Converts the TryteString into an ASCII representation. @@ -387,7 +392,7 @@ def __bytes__(self): """ return bytes(self._trytes) - def __str__(self): + def __str__(self) -> str: """ Same as :py:meth:`__bytes__`, except this method returns a unicode string. @@ -397,21 +402,17 @@ def __str__(self): return bytes(self._trytes).decode('ascii') - def __bool__(self): - # type: () -> bool + def __bool__(self) -> bool: return bool(self._trytes) and any(t != b'9' for t in self) - def __len__(self): - # type: () -> int + def __len__(self) -> int: return len(self._trytes) - def __iter__(self): - # type: () -> Generator[bytes, None, None] + def __iter__(self) -> Generator[bytes, None, None]: # :see: http://stackoverflow.com/a/14267935/ return (bytes(self._trytes[i:i + 1]) for i in range(len(self))) - def __contains__(self, other): - # type: (TrytesCompatible) -> bool + def __contains__(self, other: TrytesCompatible) -> bool: if isinstance(other, TryteString): return other._trytes in self._trytes elif isinstance(other, str): @@ -434,8 +435,7 @@ def __contains__(self, other): }, ) - def __getitem__(self, item): - # type: (Union[int, slice]) -> TryteString + def __getitem__(self, item: Union[int, slice]) -> T: new_trytes = bytearray() sliced = self._trytes[item] @@ -447,8 +447,9 @@ def __getitem__(self, item): return TryteString(new_trytes) - def __setitem__(self, item, trytes): - # type: (Union[int, slice], TrytesCompatible) -> None + def __setitem__(self, + item: Union[int, slice], + trytes: TrytesCompatible) -> None: new_trytes = TryteString(trytes) if isinstance(item, slice): @@ -469,8 +470,7 @@ def __setitem__(self, item, trytes): else: self._trytes[item] = new_trytes._trytes[0] - def __add__(self, other): - # type: (TrytesCompatible) -> TryteString + def __add__(self, other: TrytesCompatible) -> T: if isinstance(other, TryteString): return TryteString(self._trytes + other._trytes) elif isinstance(other, str): @@ -493,8 +493,7 @@ def __add__(self, other): }, ) - def __eq__(self, other): - # type: (TrytesCompatible) -> bool + def __eq__(self, other: TrytesCompatible) -> bool: if isinstance(other, TryteString): return self._trytes == other._trytes elif isinstance(other, str): @@ -517,13 +516,7 @@ def __eq__(self, other): }, ) - # :bc: In Python 2 this must be defined explicitly. - def __ne__(self, other): - # type: (TrytesCompatible) -> bool - return not (self == other) - - def count_chunks(self, chunk_size): - # type: (int) -> int + def count_chunks(self, chunk_size: int) -> int: """ Returns the number of constant-size chunks the TryteString can be divided into (rounded up). @@ -533,8 +526,9 @@ def count_chunks(self, chunk_size): """ return len(self.iter_chunks(chunk_size)) - def iter_chunks(self, chunk_size): - # type: (int) -> ChunkIterator + # Declare forward reference as string until + # https://www.python.org/dev/peps/pep-0563/ + def iter_chunks(self, chunk_size: int) -> 'ChunkIterator': """ Iterates over the TryteString, in chunks of constant size. @@ -545,8 +539,9 @@ def iter_chunks(self, chunk_size): """ return ChunkIterator(self, chunk_size) - def encode(self, errors='strict', codec=AsciiTrytesCodec.name): - # type: (Text, Text) -> bytes + def encode(self, + errors: Text = 'strict', + codec: Text = AsciiTrytesCodec.name) -> bytes: """ Encodes the TryteString into a lower-level primitive (usually bytes). @@ -619,8 +614,8 @@ def as_bytes(self, *args, **kwargs): ) return self.encode(*args, **kwargs) - def decode(self, errors='strict', strip_padding=True): - # type: (Text, bool) -> Text + def decode(self, errors: Text = 'strict', + strip_padding: bool = True) -> Text: """ Decodes the TryteString into a higher-level abstraction (usually Unicode characters). @@ -682,8 +677,7 @@ def as_string(self, *args, **kwargs): ) return self.decode(*args, **kwargs) - def as_json_compatible(self): - # type: () -> Text + def as_json_compatible(self) -> Text: """ Returns a JSON-compatible representation of the object. @@ -705,8 +699,7 @@ def as_json_compatible(self): """ return self._trytes.decode('ascii') - def as_integers(self): - # type: () -> List[int] + def as_integers(self) -> List[int]: """ Converts the TryteString into a sequence of integers. @@ -733,8 +726,7 @@ def as_integers(self): for c in self._trytes ] - def as_trytes(self): - # type: () -> List[List[int]] + def as_trytes(self) -> List[List[int]]: """ Converts the TryteString into a sequence of trytes. @@ -763,8 +755,7 @@ def as_trytes(self): for n in self.as_integers() ] - def as_trits(self): - # type: () -> List[int] + def as_trits(self) -> List[int]: """ Converts the TryteString into a sequence of trit values. @@ -810,8 +801,7 @@ def _repr_pretty_(self, p, cycle): return p.text(repr(self)) @staticmethod - def _normalize(n): - # type: (int) -> int + def _normalize(n: int) -> int: if n > 26: raise ValueError( '{n} cannot be represented by a single tryte.'.format( @@ -828,8 +818,7 @@ class ChunkIterator(Iterator[TryteString]): Iterates over a TryteString, in chunks of constant size. """ - def __init__(self, trytes, chunk_size): - # type: (TryteString, int) -> None + def __init__(self, trytes: TryteString, chunk_size: int) -> None: """ :param trytes: :py:class:`TryteString` to iterate over. @@ -846,12 +835,12 @@ def __init__(self, trytes, chunk_size): self._offset = 0 - def __iter__(self): - # type: () -> ChunkIterator + # ChunkIterator class is not defined yet here, so we can't use + # it as a type... Forward ref type annotation as available from PY3.7 + def __iter__(self) -> 'ChunkIterator': return self - def __len__(self): - # type: () -> int + def __len__(self) -> int: """ Returns how many chunks this iterator will return. @@ -861,8 +850,7 @@ def __len__(self): """ return int(ceil(len(self.trytes) / self.chunk_size)) - def __next__(self): - # type: () -> TryteString + def __next__(self) -> TryteString: """ Returns the next chunk in the iterator. @@ -897,8 +885,7 @@ class Hash(TryteString): Length is always 81 trytes long. """ - def __init__(self, trytes): - # type: (TrytesCompatible) -> None + def __init__(self, trytes: TrytesCompatible) -> None: super(Hash, self).__init__(trytes, pad=self.LEN) if len(self._trytes) > self.LEN: @@ -944,19 +931,17 @@ class Address(TryteString): def __init__( self, - trytes, # type: TrytesCompatible - balance=None, # type: Optional[int] - key_index=None, # type: Optional[int] - security_level=None, # type: Optional[int] - ): - # type: (...) -> None + trytes: TrytesCompatible, + balance: Optional[int] = None, + key_index: Optional[int] = None, + security_level: Optional[int] = None,) -> None: super(Address, self).__init__(trytes, pad=self.LEN) self.checksum = None if len(self._trytes) == (self.LEN + AddressChecksum.LEN): - self.checksum = AddressChecksum( + self.checksum: Optional[AddressChecksum] = AddressChecksum( self[self.LEN:] - ) # type: Optional[AddressChecksum] + ) elif len(self._trytes) > self.LEN: raise with_context( @@ -975,7 +960,7 @@ def __init__( ) # Make the address sans checksum accessible. - self.address = self[:self.LEN] # type: TryteString + self.address: TryteString = self[:self.LEN] """ Address trytes without the checksum. """ @@ -1007,7 +992,7 @@ def __init__( address. """ - def as_json_compatible(self): + def as_json_compatible(self) -> Dict[Text, Union[Text, int]]: """ Returns a JSON-compatible representation of the Address. @@ -1034,7 +1019,6 @@ def as_json_compatible(self): print(addy.as_json_compatible()) """ - # type: () -> dict return { 'trytes': self._trytes.decode('ascii'), 'balance': self.balance, @@ -1042,8 +1026,7 @@ def as_json_compatible(self): 'security_level': self.security_level, } - def is_checksum_valid(self): - # type: () -> bool + def is_checksum_valid(self) -> bool: """ Returns whether this address has a valid checksum. @@ -1074,8 +1057,7 @@ def is_checksum_valid(self): return False - def with_valid_checksum(self): - # type: () -> Address + def with_valid_checksum(self) -> 'Address': """ Returns the address with a valid checksum attached. @@ -1109,12 +1091,11 @@ def with_valid_checksum(self): security_level=self.security_level, ) - def _generate_checksum(self): - # type: () -> AddressChecksum + def _generate_checksum(self) -> 'AddressChecksum': """ Generates the correct checksum for this address. """ - checksum_trits = [] # type: MutableSequence[int] + checksum_trits: MutableSequence[int] = [] sponge = Kerl() sponge.absorb(self.address.as_trits()) @@ -1124,8 +1105,7 @@ def _generate_checksum(self): return AddressChecksum.from_trits(checksum_trits[-checksum_length:]) - def add_checksum(self): - # type: () -> None + def add_checksum(self) -> None: """ Adds checksum to :py:class:`Address` object. @@ -1164,8 +1144,7 @@ def add_checksum(self): # Add generated checksum to internal buffer. self._trytes = self._trytes + self.checksum._trytes - def remove_checksum(self): - # type: () -> None + def remove_checksum(self) -> None: """ Removes checksum from :py:class:`Address` object. @@ -1198,6 +1177,7 @@ def remove_checksum(self): self.checksum = None self._trytes = self._trytes[:self.LEN] + class AddressChecksum(TryteString): """ A :py:class:`TryteString` that acts as an address checksum. @@ -1212,8 +1192,7 @@ class AddressChecksum(TryteString): Length of an address checksum. """ - def __init__(self, trytes): - # type: (TrytesCompatible) -> None + def __init__(self, trytes: TrytesCompatible) -> None: super(AddressChecksum, self).__init__(trytes, pad=None) if len(self._trytes) != self.LEN: @@ -1245,8 +1224,7 @@ class Tag(TryteString): Length of a tag. """ - def __init__(self, trytes): - # type: (TrytesCompatible) -> None + def __init__(self, trytes: TrytesCompatible) -> None: super(Tag, self).__init__(trytes, pad=self.LEN) if len(self._trytes) > self.LEN: From 9c95b9cd47baadbb40e99d7ba1eb521de735a584 Mon Sep 17 00:00:00 2001 From: Levente Pap Date: Fri, 20 Mar 2020 11:18:52 +0100 Subject: [PATCH 2/3] Apply suggestions from code review Co-Authored-By: Phoenix --- iota/adapter/__init__.py | 14 +++++------ iota/adapter/wrappers.py | 4 ++-- iota/codecs.py | 5 ++-- iota/commands/__init__.py | 6 ++--- iota/crypto/kerl/conv.py | 2 +- iota/crypto/signing.py | 2 +- iota/multisig/commands/get_digests.py | 2 +- iota/multisig/commands/get_private_keys.py | 2 +- .../commands/prepare_multisig_transfer.py | 2 +- iota/transaction/base.py | 24 +++++++++---------- 10 files changed, 32 insertions(+), 31 deletions(-) diff --git a/iota/adapter/__init__.py b/iota/adapter/__init__.py index f155310..78c5680 100644 --- a/iota/adapter/__init__.py +++ b/iota/adapter/__init__.py @@ -153,7 +153,7 @@ class BaseAdapter(object, metaclass=AdapterMeta): def __init__(self) -> None: super(BaseAdapter, self).__init__() - self._logger: Logger = None + self._logger: Optional[Logger] = None self.local_pow: bool = False @abstract_method @@ -166,7 +166,7 @@ def get_uri(self) -> Text: ) @abstract_method - def send_request(self, payload: Dict, **kwargs: Dict) -> Dict: + def send_request(self, payload: Dict, **kwargs: Any) -> Dict: """ Sends an API request to the node. @@ -200,7 +200,7 @@ def _log( self, level: int, message: Text, - context: Optional[int] = None + context: Optional[dict] = None ) -> None: """ Sends a message to the instance's logger, if configured. @@ -263,7 +263,7 @@ def __init__( self, uri: Union[Text, SplitResult], timeout: Optional[int] = None, - authentication: Optional[Dict] = None + authentication: Optional[Tuple[Text, Text]] = None ) -> None: super(HttpAdapter, self).__init__() @@ -325,7 +325,7 @@ def node_url(self) -> Text: def get_uri(self) -> Text: return self.uri.geturl() - async def send_request(self, payload: Dict, **kwargs: Dict) -> Dict: + async def send_request(self, payload: Dict, **kwargs: Any) -> Dict: kwargs.setdefault('headers', {}) for key, value in self.DEFAULT_HEADERS.items(): kwargs['headers'].setdefault(key, value) @@ -406,7 +406,7 @@ def _interpret_response( self, response: Response, payload: Dict, - expected_status: Container[Dict] + expected_status: Container[int] ) -> Dict: """ Interprets the HTTP response from the node. @@ -584,7 +584,7 @@ def seed_response(self, command: Text, response: Dict) -> 'MockAdapter': self.responses[command].append(response) return self - async def send_request(self, payload: Dict, **kwargs: Dict) -> Dict: + async def send_request(self, payload: Dict, **kwargs: Any) -> Dict: """ Mimic asynchronous behavior of `HttpAdapter.send_request`. """ diff --git a/iota/adapter/wrappers.py b/iota/adapter/wrappers.py index c984373..c8c06c9 100644 --- a/iota/adapter/wrappers.py +++ b/iota/adapter/wrappers.py @@ -26,7 +26,7 @@ def get_uri(self) -> Text: return self.adapter.get_uri() @abstract_method - def send_request(self, payload: Dict, **kwargs: Dict) -> Dict: + def send_request(self, payload: Dict, **kwargs: Any) -> Dict: raise NotImplementedError( 'Not implemented in {cls}.'.format(cls=type(self).__name__), ) @@ -131,7 +131,7 @@ def get_adapter(self, command: Text) -> BaseAdapter: """ return self.routes.get(command, self.adapter) - async def send_request(self, payload: Dict, **kwargs: Dict) -> Dict: + async def send_request(self, payload: Dict, **kwargs: Any) -> Dict: command = payload.get('command') return await self.get_adapter(command).send_request(payload, **kwargs) diff --git a/iota/codecs.py b/iota/codecs.py index 3d4a553..f54f785 100644 --- a/iota/codecs.py +++ b/iota/codecs.py @@ -59,11 +59,12 @@ def get_codec_info(cls) -> CodecInfo: """ codec = cls() - # In Python 2, all codecs are made equal. - # In Python 3, some codecs are more equal than others codec_info = { 'encode': codec.encode, 'decode': codec.decode, + + # In Python 2, all codecs are made equal. + # In Python 3, some codecs are more equal than others. '_is_text_encoding': False } diff --git a/iota/commands/__init__.py b/iota/commands/__init__.py index 56f8036..a9071cd 100644 --- a/iota/commands/__init__.py +++ b/iota/commands/__init__.py @@ -34,8 +34,8 @@ def __init__(self, adapter: BaseAdapter) -> None: self.adapter = adapter self.called: bool = False - self.request: Dict = None - self.response: Dict = None + self.request: Optional[Dict] = None + self.response: Optional[Dict] = None async def __call__(self, **kwargs: Any) -> Dict: """ @@ -262,4 +262,4 @@ def _apply_filter( }, ) - return value \ No newline at end of file + return value diff --git a/iota/crypto/kerl/conv.py b/iota/crypto/kerl/conv.py index 20d0a0c..6807f3c 100644 --- a/iota/crypto/kerl/conv.py +++ b/iota/crypto/kerl/conv.py @@ -91,7 +91,7 @@ def convertBytesToBigInt(ba: List[int]) -> int: enumerate(reversed(bytesArray))) * signum -def convertBigintToBytes(big: int) -> List[int]: +def convertBigIntToBytes(big: int) -> List[int]: bytesArrayTemp = [(abs(big) >> pos * 8) % (1 << 8) for pos in range(48)] diff --git a/iota/crypto/signing.py b/iota/crypto/signing.py index 0edbe5b..8649dc8 100644 --- a/iota/crypto/signing.py +++ b/iota/crypto/signing.py @@ -256,7 +256,7 @@ def __init__( ) # In order to work correctly, the seed must be padded so that it - # is a multiple of 81 trytes. + # is a multiple of 81 trytes. seed += b'9' * (Hash.LEN - ((len(seed) % Hash.LEN) or Hash.LEN)) self.security_level = security_level diff --git a/iota/multisig/commands/get_digests.py b/iota/multisig/commands/get_digests.py index 9ced79a..3d01841 100644 --- a/iota/multisig/commands/get_digests.py +++ b/iota/multisig/commands/get_digests.py @@ -30,7 +30,7 @@ def get_response_filter(self): # There is no async operation going on here, but the base class is async, # so from the outside, we have to act like we are doing async. - async def _execute(self, request: Dict): + async def _execute(self, request: Dict) -> Dict: count: Optional[int] = request['count'] index: int = request['index'] seed: Seed = request['seed'] diff --git a/iota/multisig/commands/get_private_keys.py b/iota/multisig/commands/get_private_keys.py index 0dcfadf..bb392b6 100644 --- a/iota/multisig/commands/get_private_keys.py +++ b/iota/multisig/commands/get_private_keys.py @@ -31,7 +31,7 @@ def get_response_filter(self): # There is no async operation going on here, but the base class is async, # so from the outside, we have to act like we are doing async. - async def _execute(self, request: Dict): + async def _execute(self, request: Dict) -> Dict: count: Optional[int] = request['count'] index: int = request['index'] seed: Seed = request['seed'] diff --git a/iota/multisig/commands/prepare_multisig_transfer.py b/iota/multisig/commands/prepare_multisig_transfer.py index 7ae2453..1585632 100644 --- a/iota/multisig/commands/prepare_multisig_transfer.py +++ b/iota/multisig/commands/prepare_multisig_transfer.py @@ -31,7 +31,7 @@ def get_request_filter(self) -> 'PrepareMultisigTransferRequestFilter': def get_response_filter(self): pass - async def _execute(self, request: Dict): + async def _execute(self, request: Dict) -> Dict: change_address: Optional[Address] = request['changeAddress'] multisig_input: MultisigAddress = request['multisigInput'] transfers: List[ProposedTransaction] = request['transfers'] diff --git a/iota/transaction/base.py b/iota/transaction/base.py index b971352..00d8965 100644 --- a/iota/transaction/base.py +++ b/iota/transaction/base.py @@ -214,7 +214,7 @@ def __init__( :type: :py:class:`TransactionHash` """ - self.bundle_hash: BundleHash = bundle_hash + self.bundle_hash: Optional[BundleHash] = bundle_hash """ The bundle hash, used to identify transactions that are part of the same bundle. @@ -249,7 +249,7 @@ def __init__( :type: ``int`` """ - self._legacy_tag: Tag = legacy_tag + self._legacy_tag: Optional[Tag] = legacy_tag """ A short message attached to the transaction. @@ -259,7 +259,7 @@ def __init__( :type: :py:class:`Tag` """ - self.nonce: Nonce = nonce + self.nonce: Optional[Nonce] = nonce """ Unique value used to increase security of the transaction hash. @@ -281,7 +281,7 @@ def __init__( :type: ``int``, unix timestamp in seconds. """ - self.current_index: int = current_index + self.current_index: Optional[int] = current_index """ The position of the transaction inside the bundle. @@ -295,7 +295,7 @@ def __init__( :type: ``int`` """ - self.last_index: int = last_index + self.last_index: Optional[int] = last_index """ The index of the final transaction in the bundle. @@ -305,7 +305,7 @@ def __init__( :type: ``int`` """ - self.trunk_transaction_hash: TransactionHash = trunk_transaction_hash + self.trunk_transaction_hash: Optional[TransactionHash] = trunk_transaction_hash """ The transaction hash of the next transaction in the bundle. @@ -319,7 +319,7 @@ def __init__( :type: :py:class:`TransactionHash` """ - self.branch_transaction_hash: TransactionHash = branch_transaction_hash + self.branch_transaction_hash: Optional[TransactionHash] = branch_transaction_hash """ An unrelated transaction that this transaction "approves". @@ -334,7 +334,7 @@ def __init__( :type: :py:class:`TransactionHash` """ - self.tag: Tag = tag + self.tag: Optional[Tag] = tag """ Optional classification tag applied to this transaction. @@ -343,7 +343,7 @@ def __init__( :type: :py:class:`Tag` """ - self.attachment_timestamp: int = attachment_timestamp + self.attachment_timestamp: Optional[int] = attachment_timestamp """ Estimated epoch time of the attachment to the tangle. @@ -352,21 +352,21 @@ def __init__( :type: ``int``, unix timestamp in milliseconds, """ - self.attachment_timestamp_lower_bound: int = attachment_timestamp_lower_bound + self.attachment_timestamp_lower_bound: Optional[int] = attachment_timestamp_lower_bound """ The lowest possible epoch time of the attachment to the tangle. :type: ``int``, unix timestamp in milliseconds. """ - self.attachment_timestamp_upper_bound: int = attachment_timestamp_upper_bound + self.attachment_timestamp_upper_bound: Optional[int] = attachment_timestamp_upper_bound """ The highest possible epoch time of the attachment to the tangle. :type: ``int``, unix timestamp in milliseconds. """ - self.signature_message_fragment: Fragment = signature_message_fragment + self.signature_message_fragment: Optional[Fragment] = signature_message_fragment """ "Signature/Message Fragment" (note the slash): From 0e609ad110a85a8901e5dee9d224bd44ff0983be Mon Sep 17 00:00:00 2001 From: Levente Pap Date: Fri, 20 Mar 2020 11:23:26 +0100 Subject: [PATCH 3/3] PR review changes --- examples/send_transfer.py | 2 +- iota/__init__.py | 5 +- iota/adapter/__init__.py | 54 +++++------ iota/adapter/wrappers.py | 16 ++-- iota/api.py | 88 ++++++++--------- iota/api_async.py | 95 +++++++++---------- iota/bin/__init__.py | 6 +- iota/bin/repl.py | 3 +- iota/codecs.py | 6 +- iota/commands/__init__.py | 33 +++---- iota/commands/core/attach_to_tangle.py | 4 +- iota/commands/core/find_transactions.py | 4 +- iota/commands/core/get_balances.py | 4 +- .../core/get_transactions_to_approve.py | 4 +- iota/commands/extended/broadcast_and_store.py | 4 +- iota/commands/extended/broadcast_bundle.py | 4 +- .../extended/find_transaction_objects.py | 4 +- iota/commands/extended/get_account_data.py | 4 +- iota/commands/extended/get_bundles.py | 4 +- iota/commands/extended/get_inputs.py | 4 +- .../commands/extended/get_latest_inclusion.py | 4 +- iota/commands/extended/get_new_addresses.py | 4 +- .../extended/get_transaction_objects.py | 4 +- iota/commands/extended/get_transfers.py | 4 +- iota/commands/extended/is_promotable.py | 4 +- iota/commands/extended/is_reattachable.py | 4 +- iota/commands/extended/prepare_transfer.py | 4 +- iota/commands/extended/promote_transaction.py | 4 +- iota/commands/extended/replay_bundle.py | 4 +- iota/commands/extended/send_transfer.py | 4 +- iota/commands/extended/send_trytes.py | 4 +- iota/commands/extended/traverse_bundle.py | 4 +- iota/crypto/kerl/conv.py | 10 +- iota/crypto/types.py | 10 +- iota/filters.py | 4 +- iota/multisig/api.py | 34 +++---- .../commands/create_multisig_address.py | 4 +- iota/multisig/commands/get_digests.py | 4 +- iota/multisig/commands/get_private_keys.py | 4 +- .../commands/prepare_multisig_transfer.py | 4 +- iota/multisig/types.py | 6 +- iota/transaction/base.py | 12 +-- iota/transaction/creation.py | 4 +- iota/transaction/utils.py | 3 +- iota/transaction/validator.py | 16 ++-- iota/types.py | 32 +++---- 46 files changed, 259 insertions(+), 284 deletions(-) diff --git a/examples/send_transfer.py b/examples/send_transfer.py index ab8b372..34c0045 100644 --- a/examples/send_transfer.py +++ b/examples/send_transfer.py @@ -12,7 +12,7 @@ Tag, TryteString, ) -from address_generator import get_seed, output_seed +from .address_generator import get_seed, output_seed def main(address, depth, message, tag, uri, value): diff --git a/iota/__init__.py b/iota/__init__.py index e311054..970c1d6 100644 --- a/iota/__init__.py +++ b/iota/__init__.py @@ -1,7 +1,6 @@ +from typing import Dict # Define a few magic constants. -from typing import Dict, Text - DEFAULT_PORT: int = 14265 """ Default port to use when configuring an adapter, if the port is not @@ -16,7 +15,7 @@ In that way, it's kind of like toxic waste in a superhero story. """ -STANDARD_UNITS: Dict[Text, int] = { +STANDARD_UNITS: Dict[str, int] = { # Valid IOTA unit suffixes. Example value '-273.15 Ki' 'i': 1, 'Ki': 1000, diff --git a/iota/adapter/__init__.py b/iota/adapter/__init__.py index 78c5680..36fadc2 100644 --- a/iota/adapter/__init__.py +++ b/iota/adapter/__init__.py @@ -6,8 +6,8 @@ from inspect import isabstract as is_abstract from logging import DEBUG, Logger from socket import getdefaulttimeout as get_default_timeout -from typing import Container, Dict, List, Optional, Text, Tuple, Union, Any -from httpx import AsyncClient, Response, codes, auth +from typing import Container, List, Optional, Tuple, Union, Any, Dict +from httpx import AsyncClient, Response, codes, BasicAuth import asyncio from iota.exceptions import with_context @@ -32,7 +32,7 @@ """ # Custom types for type hints and docstrings. -AdapterSpec = Union[Text, 'BaseAdapter'] +AdapterSpec = Union[str, 'BaseAdapter'] """ Placeholder that means “URI or adapter instance”. @@ -69,7 +69,7 @@ class InvalidUri(ValueError): pass -adapter_registry: Dict[Text, 'AdapterMeta'] = {} +adapter_registry: Dict[str, 'AdapterMeta'] = {} """ Keeps track of available adapters and their supported protocols. """ @@ -127,7 +127,7 @@ def __init__(cls, what, bases=None, dict=None) -> None: # adapters. adapter_registry.setdefault(protocol, cls) - def configure(cls, parsed: Union[Text, SplitResult]) -> 'HttpAdapter': + def configure(cls, parsed: Union[str, SplitResult]) -> 'HttpAdapter': """ Creates a new instance using the specified URI. @@ -144,7 +144,7 @@ class BaseAdapter(object, metaclass=AdapterMeta): Adapters make it easy to customize the way an API instance communicates with a node. """ - supported_protocols: Tuple[Text] = () + supported_protocols: Tuple[str] = () """ Protocols that ``resolve_adapter`` can use to identify this adapter type. @@ -157,7 +157,7 @@ def __init__(self) -> None: self.local_pow: bool = False @abstract_method - def get_uri(self) -> Text: + def get_uri(self) -> str: """ Returns the URI that this adapter will use. """ @@ -166,7 +166,7 @@ def get_uri(self) -> Text: ) @abstract_method - def send_request(self, payload: Dict, **kwargs: Any) -> Dict: + def send_request(self, payload: dict, **kwargs: Any) -> dict: """ Sends an API request to the node. @@ -199,7 +199,7 @@ def set_logger(self, logger: Logger) -> 'BaseAdapter': def _log( self, level: int, - message: Text, + message: str, context: Optional[dict] = None ) -> None: """ @@ -231,7 +231,7 @@ class HttpAdapter(BaseAdapter): :param Optional[int] timeout: Connection timeout in seconds. - :param Optional[Tuple(Text,Text)] authentication: + :param Optional[Tuple(str,str)] authentication: Credetentials for basic authentication with the node. :return: @@ -261,9 +261,9 @@ class HttpAdapter(BaseAdapter): def __init__( self, - uri: Union[Text, SplitResult], + uri: Union[str, SplitResult], timeout: Optional[int] = None, - authentication: Optional[Tuple[Text, Text]] = None + authentication: Optional[Tuple[str, str]] = None ) -> None: super(HttpAdapter, self).__init__() @@ -316,16 +316,16 @@ def __init__( self.uri = uri @property - def node_url(self) -> Text: + def node_url(self) -> str: """ Returns the node URL. """ return self.uri.geturl() - def get_uri(self) -> Text: + def get_uri(self) -> str: return self.uri.geturl() - async def send_request(self, payload: Dict, **kwargs: Any) -> Dict: + async def send_request(self, payload: dict, **kwargs: Any) -> dict: kwargs.setdefault('headers', {}) for key, value in self.DEFAULT_HEADERS.items(): kwargs['headers'].setdefault(key, value) @@ -343,9 +343,9 @@ async def send_request(self, payload: Dict, **kwargs: Any) -> Dict: async def _send_http_request( self, - url: Text, - payload: Optional[Text], - method: Text = 'post', + url: str, + payload: Optional[str], + method: str = 'post', **kwargs: Any ) -> Response: """ @@ -360,7 +360,7 @@ async def _send_http_request( ) if self.authentication: - kwargs.setdefault('auth', auth.BasicAuth(*self.authentication)) + kwargs.setdefault('auth', BasicAuth(*self.authentication)) self._log( level=DEBUG, @@ -405,9 +405,9 @@ async def _send_http_request( def _interpret_response( self, response: Response, - payload: Dict, + payload: dict, expected_status: Container[int] - ) -> Dict: + ) -> dict: """ Interprets the HTTP response from the node. @@ -437,7 +437,7 @@ def _interpret_response( ) try: - decoded: Dict = json.loads(raw_content) + decoded: dict = json.loads(raw_content) # :bc: py2k doesn't have JSONDecodeError except ValueError: raise with_context( @@ -538,13 +538,13 @@ def configure(cls, uri): def __init__(self) -> None: super(MockAdapter, self).__init__() - self.responses: Dict[Text, deque] = {} + self.responses: Dict[str, deque] = {} self.requests: List[dict] = [] - def get_uri(self) -> Text: + def get_uri(self) -> str: return 'mock://' - def seed_response(self, command: Text, response: Dict) -> 'MockAdapter': + def seed_response(self, command: str, response: dict) -> 'MockAdapter': """ Sets the response that the adapter will return for the specified command. @@ -558,7 +558,7 @@ def seed_response(self, command: Text, response: Dict) -> 'MockAdapter': have a seeded response for a particular command, it will raise a ``BadApiResponse`` exception (simulates a 404 response). - :param Text command: + :param str command: The name of the command. Note that this is the camelCase version of the command name (e.g., ``getNodeInfo``, not ``get_node_info``). @@ -584,7 +584,7 @@ def seed_response(self, command: Text, response: Dict) -> 'MockAdapter': self.responses[command].append(response) return self - async def send_request(self, payload: Dict, **kwargs: Any) -> Dict: + async def send_request(self, payload: Dict, **kwargs: Any) -> dict: """ Mimic asynchronous behavior of `HttpAdapter.send_request`. """ diff --git a/iota/adapter/wrappers.py b/iota/adapter/wrappers.py index c8c06c9..3beb0b0 100644 --- a/iota/adapter/wrappers.py +++ b/iota/adapter/wrappers.py @@ -1,5 +1,5 @@ from abc import ABCMeta, abstractmethod as abstract_method -from typing import Dict, Text +from typing import Dict, Any from iota.adapter import AdapterSpec, BaseAdapter, resolve_adapter @@ -22,11 +22,11 @@ def __init__(self, adapter: AdapterSpec) -> None: self.adapter: BaseAdapter = adapter - def get_uri(self) -> Text: + def get_uri(self) -> str: return self.adapter.get_uri() @abstract_method - def send_request(self, payload: Dict, **kwargs: Any) -> Dict: + def send_request(self, payload: dict, **kwargs: Any) -> dict: raise NotImplementedError( 'Not implemented in {cls}.'.format(cls=type(self).__name__), ) @@ -94,13 +94,13 @@ def __init__(self, default_adapter: AdapterSpec) -> None: # when resolving URIs. self.adapter_aliases: Dict[AdapterSpec, BaseAdapter] = {} - self.routes: Dict[Text, BaseAdapter] = {} + self.routes: Dict[str, BaseAdapter] = {} - def add_route(self, command: Text, adapter: AdapterSpec) -> 'RoutingWrapper': + def add_route(self, command: str, adapter: AdapterSpec) -> 'RoutingWrapper': """ Adds a route to the wrapper. - :param Text command: + :param str command: The name of the command. Note that this is the camelCase version of the command name (e.g., ``attachToTangle``, not ``attach_to_tangle``). @@ -125,13 +125,13 @@ def add_route(self, command: Text, adapter: AdapterSpec) -> 'RoutingWrapper': return self - def get_adapter(self, command: Text) -> BaseAdapter: + def get_adapter(self, command: str) -> BaseAdapter: """ Return the adapter for the specified command. """ return self.routes.get(command, self.adapter) - async def send_request(self, payload: Dict, **kwargs: Any) -> Dict: + async def send_request(self, payload: dict, **kwargs: Any) -> dict: command = payload.get('command') return await self.get_adapter(command).send_request(payload, **kwargs) diff --git a/iota/api.py b/iota/api.py index 17ab405..1f42cec 100644 --- a/iota/api.py +++ b/iota/api.py @@ -1,4 +1,4 @@ -from typing import Dict, Iterable, Optional, Text +from typing import Dict, Iterable, Optional from iota import AdapterSpec, Address, BundleHash, ProposedTransaction, Tag, \ TransactionHash, TransactionTrytes, TryteString, TrytesCompatible @@ -98,12 +98,12 @@ def __init__( """ super().__init__(adapter, devnet, local_pow) - def add_neighbors(self, uris: Iterable[Text]) -> Dict: + def add_neighbors(self, uris: Iterable[str]) -> dict: """ Add one or more neighbors to the node. Lasts until the node is restarted. - :param Iterable[Text] uris: + :param Iterable[str] uris: Use format ``://:``. Example: ``add_neighbors(['udp://example.com:14265'])`` @@ -139,7 +139,7 @@ def attach_to_tangle( branch_transaction: TransactionHash, trytes: Iterable[TryteString], min_weight_magnitude: Optional[int] = None, - ) -> Dict: + ) -> dict: """ Attaches the specified transactions (trytes) to the Tangle by doing Proof of Work. You need to supply branchTransaction as @@ -188,7 +188,7 @@ def attach_to_tangle( ) ) - def broadcast_transactions(self, trytes: Iterable[TryteString]) -> Dict: + def broadcast_transactions(self, trytes: Iterable[TryteString]) -> dict: """ Broadcast a list of transactions to all neighbors. @@ -219,7 +219,7 @@ def broadcast_transactions(self, trytes: Iterable[TryteString]) -> Dict: ) ) - def check_consistency(self, tails: Iterable[TransactionHash]) -> Dict: + def check_consistency(self, tails: Iterable[TransactionHash]) -> dict: """ Used to ensure tail resolves to a consistent ledger which is necessary to validate before attempting promotion. Checks @@ -240,7 +240,7 @@ def check_consistency(self, tails: Iterable[TransactionHash]) -> Dict: { 'state': bool, Whether tails resolve to consistent ledger. - 'info': Text, + 'info': str, This field will only exist if 'state' is ``False``. } @@ -263,7 +263,7 @@ def find_transactions( addresses: Optional[Iterable[Address]] = None, tags: Optional[Iterable[Tag]] = None, approvees: Optional[Iterable[TransactionHash]] = None, - ) -> Dict: + ) -> dict: """ Find the transactions which match the specified input and return. @@ -316,7 +316,7 @@ def get_balances( addresses: Iterable[Address], threshold: int = 100, tips: Optional[Iterable[TransactionHash]] = None, - ) -> Dict: + ) -> dict: """ Similar to :py:meth:`get_inclusion_states`. Returns the confirmed balance which a list of addresses have at the latest @@ -373,7 +373,7 @@ def get_inclusion_states( self, transactions: Iterable[TransactionHash], tips: Iterable[TransactionHash] - ) -> Dict: + ) -> dict: """ Get the inclusion states of a set of transactions. This is for determining if a transaction was accepted and confirmed by the @@ -414,7 +414,7 @@ def get_inclusion_states( ) ) - def get_missing_transactions(self) -> Dict: + def get_missing_transactions(self) -> dict: """ Returns all transaction hashes that a node is currently requesting from its neighbors. @@ -440,7 +440,7 @@ def get_missing_transactions(self) -> Dict: super().get_missing_transactions() ) - def get_neighbors(self) -> Dict: + def get_neighbors(self) -> dict: """ Returns the set of neighbors the node is connected with, as well as their activity count. @@ -477,7 +477,7 @@ def get_neighbors(self) -> Dict: super().get_neighbors() ) - def get_node_api_configuration(self) -> Dict: + def get_node_api_configuration(self) -> dict: """ Returns a node's API configuration settings. @@ -505,7 +505,7 @@ def get_node_api_configuration(self) -> Dict: super().get_node_api_configuration() ) - def get_node_info(self) -> Dict: + def get_node_info(self) -> dict: """ Returns information about the node. @@ -513,9 +513,9 @@ def get_node_info(self) -> Dict: ``dict`` with the following structure:: { - 'appName': Text, + 'appName': str, Name of the IRI network. - 'appVersion': Text, + 'appVersion': str, Version of the IRI. 'jreAvailableProcessors': int, Available CPU cores on the node. @@ -526,7 +526,7 @@ def get_node_info(self) -> Dict: can use, 'jreTotalMemory': int, Total amount of memory in the Java virtual machine. - 'jreVersion': Text, + 'jreVersion': str, The version of the Java runtime environment. 'latestMilestone': TransactionHash Transaction hash of the latest milestone. @@ -549,7 +549,7 @@ def get_node_info(self) -> Dict: 'transactionsToRequest': int, Total number of transactions that the node is missing in its ledger. - 'features': List[Text], + 'features': List[str], Enabled configuration options. 'coordinatorAddress': Address, Address (Merkle root) of the Coordinator. @@ -568,7 +568,7 @@ def get_node_info(self) -> Dict: super().get_node_info() ) - def get_tips(self) -> Dict: + def get_tips(self) -> dict: """ Returns the list of tips (transactions which have no other transactions referencing them). @@ -599,7 +599,7 @@ def get_transactions_to_approve( self, depth: int, reference: Optional[TransactionHash] = None, - ) -> Dict: + ) -> dict: """ Tip selection which returns ``trunkTransaction`` and ``branchTransaction``. @@ -642,7 +642,7 @@ def get_transactions_to_approve( ) ) - def get_trytes(self, hashes: Iterable[TransactionHash]) -> Dict: + def get_trytes(self, hashes: Iterable[TransactionHash]) -> dict: """ Returns the raw transaction data (trytes) of one or more transactions. @@ -676,7 +676,7 @@ def get_trytes(self, hashes: Iterable[TransactionHash]) -> Dict: ) ) - def interrupt_attaching_to_tangle(self) -> Dict: + def interrupt_attaching_to_tangle(self) -> dict: """ Interrupts and completely aborts the :py:meth:`attach_to_tangle` process. @@ -700,12 +700,12 @@ def interrupt_attaching_to_tangle(self) -> Dict: super().interrupt_attaching_to_tangle() ) - def remove_neighbors(self, uris: Iterable[Text]) -> Dict: + def remove_neighbors(self, uris: Iterable[str]) -> dict: """ Removes one or more neighbors from the node. Lasts until the node is restarted. - :param Text uris: + :param str uris: Use format ``://:``. Example: `remove_neighbors(['udp://example.com:14265'])` @@ -730,7 +730,7 @@ def remove_neighbors(self, uris: Iterable[Text]) -> Dict: super().remove_neighbors(uris) ) - def store_transactions(self, trytes: Iterable[TryteString]) -> Dict: + def store_transactions(self, trytes: Iterable[TryteString]) -> dict: """ Store transactions into local storage of the node. @@ -764,7 +764,7 @@ def store_transactions(self, trytes: Iterable[TryteString]) -> Dict: def were_addresses_spent_from( self, addresses: Iterable[Address] - ) -> Dict: + ) -> dict: """ Check if a list of addresses was ever spent from, in the current epoch, or in previous epochs. @@ -856,7 +856,7 @@ def __init__( def broadcast_and_store( self, trytes: Iterable[TransactionTrytes] - ) -> Dict: + ) -> dict: """ Broadcasts and stores a set of transaction trytes. @@ -885,7 +885,7 @@ def broadcast_and_store( def broadcast_bundle( self, tail_transaction_hash: TransactionHash - ) -> Dict: + ) -> dict: """ Re-broadcasts all transactions in a bundle given the tail transaction hash. It might be useful when transactions did not properly propagate, @@ -919,7 +919,7 @@ def find_transaction_objects( addresses: Optional[Iterable[Address]] = None, tags: Optional[Iterable[Tag]] = None, approvees: Optional[Iterable[TransactionHash]] = None, - ) -> Dict: + ) -> dict: """ A more extensive version of :py:meth:`find_transactions` that returns transaction objects instead of hashes. @@ -974,7 +974,7 @@ def get_account_data( stop: Optional[int] = None, inclusion_states: bool = False, security_level: Optional[int] = None - ) -> Dict: + ) -> dict: """ More comprehensive version of :py:meth:`get_transfers` that returns addresses and account balance in addition to bundles. @@ -1056,7 +1056,7 @@ def get_account_data( def get_bundles( self, transactions: Iterable[TransactionHash] - ) -> Dict: + ) -> dict: """ Returns the bundle(s) associated with the specified transaction hashes. @@ -1093,7 +1093,7 @@ def get_inputs( stop: Optional[int] = None, threshold: Optional[int] = None, security_level: Optional[int] = None, - ) -> Dict: + ) -> dict: """ Gets all possible inputs of a seed and returns them, along with the total balance. @@ -1204,7 +1204,7 @@ def get_inputs( def get_latest_inclusion( self, hashes: Iterable[TransactionHash] - ) -> Dict[Text, Dict[TransactionHash, bool]]: + ) -> Dict[str, Dict[TransactionHash, bool]]: """ Fetches the inclusion state for the specified transaction hashes, as of the latest milestone that the node has processed. @@ -1305,7 +1305,7 @@ def get_new_addresses( def get_transaction_objects( self, hashes: [Iterable[TransactionHash]], - ) -> Dict: + ) -> dict: """ Fetches transaction objects from the Tangle given their transaction IDs (hashes). @@ -1338,7 +1338,7 @@ def get_transfers( start: int = 0, stop: Optional[int] = None, inclusion_states: bool = False - ) -> Dict: + ) -> dict: """ Returns all transfers associated with the seed. @@ -1403,7 +1403,7 @@ def get_transfers( def is_promotable( self, tails: Iterable[TransactionHash], - ) -> Dict: + ) -> dict: """ Checks if tail transaction(s) is promotable by calling :py:meth:`check_consistency` and verifying that ``attachmentTimestamp`` @@ -1423,7 +1423,7 @@ def is_promotable( If ``True``, all tails are promotable. If ``False``, see `info` field. - 'info': Optional(List[Text]) + 'info': Optional(List[str]) If `promotable` is ``False``, this contains info about what went wrong. Note that when 'promotable' is ``True``, 'info' does not @@ -1446,7 +1446,7 @@ def prepare_transfer( inputs: Optional[Iterable[Address]] = None, change_address: Optional[Address] = None, security_level: Optional[int] = None, - ) -> Dict: + ) -> dict: """ Prepares transactions to be broadcast to the Tangle, by generating the correct bundle, as well as choosing and signing @@ -1509,7 +1509,7 @@ def promote_transaction( transaction: TransactionHash, depth: int = 3, min_weight_magnitude: Optional[int] = None, - ) -> Dict: + ) -> dict: """ Promotes a transaction by adding spam on top of it. @@ -1549,7 +1549,7 @@ def replay_bundle( transaction: TransactionHash, depth: int = 3, min_weight_magnitude: Optional[int] = None, - ) -> Dict: + ) -> dict: """ Takes a tail transaction hash as input, gets the bundle associated with the transaction and then replays the bundle by @@ -1598,7 +1598,7 @@ def send_transfer( change_address: Optional[Address] = None, min_weight_magnitude: Optional[int] = None, security_level: Optional[int] = None, - ) -> Dict: + ) -> dict: """ Prepares a set of transfers and creates the bundle, then attaches the bundle to the Tangle, and broadcasts and stores the @@ -1667,7 +1667,7 @@ def send_trytes( trytes: Iterable[TransactionTrytes], depth: int = 3, min_weight_magnitude: Optional[int] = None - ) -> Dict: + ) -> dict: """ Attaches transaction trytes to the Tangle, then broadcasts and stores them. @@ -1707,7 +1707,7 @@ def send_trytes( ) ) - def is_reattachable(self, addresses: Iterable[Address]) -> Dict: + def is_reattachable(self, addresses: Iterable[Address]) -> dict: """ This API function helps you to determine whether you should replay a transaction or make a new one (either with the same @@ -1741,7 +1741,7 @@ def is_reattachable(self, addresses: Iterable[Address]) -> Dict: ) ) - def traverse_bundle(self, tail_hash: TransactionHash) -> Dict: + def traverse_bundle(self, tail_hash: TransactionHash) -> dict: """ Fetches and traverses a bundle from the Tangle given a tail transaction hash. diff --git a/iota/api_async.py b/iota/api_async.py index 9098461..7a85003 100644 --- a/iota/api_async.py +++ b/iota/api_async.py @@ -1,12 +1,11 @@ -from typing import Dict, Iterable, Optional, Text +from typing import Dict, Iterable, Optional 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, extended +from iota.commands import CustomCommand, core, extended from iota.crypto.addresses import AddressGenerator from iota.crypto.types import Seed -import asyncio __all__ = [ 'AsyncIota', @@ -85,14 +84,14 @@ def __init__( self.adapter.set_local_pow(local_pow) self.devnet = devnet - def create_command(self, command: Text) -> CustomCommand: + def create_command(self, command: str) -> CustomCommand: """ Creates a pre-configured CustomCommand instance. This method is useful for invoking undocumented or experimental methods, or if you just want to troll your node for awhile. - :param Text command: + :param str command: The name of the command to create. """ @@ -125,12 +124,12 @@ def default_min_weight_magnitude(self) -> int: """ return 9 if self.devnet else 14 - async def add_neighbors(self, uris: Iterable[Text]) -> Dict: + async def add_neighbors(self, uris: Iterable[str]) -> dict: """ Add one or more neighbors to the node. Lasts until the node is restarted. - :param Iterable[Text] uris: + :param Iterable[str] uris: Use format ``://:``. Example: ``add_neighbors(['udp://example.com:14265'])`` @@ -161,7 +160,7 @@ async def attach_to_tangle( branch_transaction: TransactionHash, trytes: Iterable[TryteString], min_weight_magnitude: Optional[int] = None, - ) -> Dict: + ) -> dict: """ Attaches the specified transactions (trytes) to the Tangle by doing Proof of Work. You need to supply branchTransaction as @@ -208,7 +207,7 @@ async def attach_to_tangle( trytes=trytes, ) - async def broadcast_transactions(self, trytes: Iterable[TryteString]) -> Dict: + async def broadcast_transactions(self, trytes: Iterable[TryteString]) -> dict: """ Broadcast a list of transactions to all neighbors. @@ -232,7 +231,7 @@ async def broadcast_transactions(self, trytes: Iterable[TryteString]) -> Dict: """ return await core.BroadcastTransactionsCommand(self.adapter)(trytes=trytes) - async def check_consistency(self, tails: Iterable[TransactionHash]) -> Dict: + async def check_consistency(self, tails: Iterable[TransactionHash]) -> dict: """ Used to ensure tail resolves to a consistent ledger which is necessary to validate before attempting promotion. Checks @@ -253,7 +252,7 @@ async def check_consistency(self, tails: Iterable[TransactionHash]) -> Dict: { 'state': bool, Whether tails resolve to consistent ledger. - 'info': Text, + 'info': str, This field will only exist if 'state' is ``False``. } @@ -271,7 +270,7 @@ async def find_transactions( addresses: Optional[Iterable[Address]] = None, tags: Optional[Iterable[Tag]] = None, approvees: Optional[Iterable[TransactionHash]] = None, - ) -> Dict: + ) -> dict: """ Find the transactions which match the specified input and return. @@ -319,7 +318,7 @@ async def get_balances( addresses: Iterable[Address], threshold: int = 100, tips: Optional[Iterable[TransactionHash]] = None, - ) -> Dict: + ) -> dict: """ Similar to :py:meth:`get_inclusion_states`. Returns the confirmed balance which a list of addresses have at the latest @@ -371,7 +370,7 @@ async def get_inclusion_states( self, transactions: Iterable[TransactionHash], tips: Iterable[TransactionHash] - ) -> Dict: + ) -> dict: """ Get the inclusion states of a set of transactions. This is for determining if a transaction was accepted and confirmed by the @@ -407,7 +406,7 @@ async def get_inclusion_states( tips=tips, ) - async def get_missing_transactions(self) -> Dict: + async def get_missing_transactions(self) -> dict: """ Returns all transaction hashes that a node is currently requesting from its neighbors. @@ -428,7 +427,7 @@ async def get_missing_transactions(self) -> Dict: """ return await core.GetMissingTransactionsCommand(self.adapter)() - async def get_neighbors(self) -> Dict: + async def get_neighbors(self) -> dict: """ Returns the set of neighbors the node is connected with, as well as their activity count. @@ -460,7 +459,7 @@ async def get_neighbors(self) -> Dict: """ return await core.GetNeighborsCommand(self.adapter)() - async def get_node_api_configuration(self) -> Dict: + async def get_node_api_configuration(self) -> dict: """ Returns a node's API configuration settings. @@ -483,7 +482,7 @@ async def get_node_api_configuration(self) -> Dict: """ return await core.GetNodeAPIConfigurationCommand(self.adapter)() - async def get_node_info(self) -> Dict: + async def get_node_info(self) -> dict: """ Returns information about the node. @@ -491,9 +490,9 @@ async def get_node_info(self) -> Dict: ``dict`` with the following structure:: { - 'appName': Text, + 'appName': str, Name of the IRI network. - 'appVersion': Text, + 'appVersion': str, Version of the IRI. 'jreAvailableProcessors': int, Available CPU cores on the node. @@ -504,7 +503,7 @@ async def get_node_info(self) -> Dict: can use, 'jreTotalMemory': int, Total amount of memory in the Java virtual machine. - 'jreVersion': Text, + 'jreVersion': str, The version of the Java runtime environment. 'latestMilestone': TransactionHash Transaction hash of the latest milestone. @@ -527,7 +526,7 @@ async def get_node_info(self) -> Dict: 'transactionsToRequest': int, Total number of transactions that the node is missing in its ledger. - 'features': List[Text], + 'features': List[str], Enabled configuration options. 'coordinatorAddress': Address, Address (Merkle root) of the Coordinator. @@ -541,7 +540,7 @@ async def get_node_info(self) -> Dict: """ return await core.GetNodeInfoCommand(self.adapter)() - async def get_tips(self) -> Dict: + async def get_tips(self) -> dict: """ Returns the list of tips (transactions which have no other transactions referencing them). @@ -567,7 +566,7 @@ async def get_transactions_to_approve( self, depth: int, reference: Optional[TransactionHash] = None, - ) -> Dict: + ) -> dict: """ Tip selection which returns ``trunkTransaction`` and ``branchTransaction``. @@ -605,7 +604,7 @@ async def get_transactions_to_approve( reference=reference, ) - async def get_trytes(self, hashes: Iterable[TransactionHash]) -> Dict: + async def get_trytes(self, hashes: Iterable[TransactionHash]) -> dict: """ Returns the raw transaction data (trytes) of one or more transactions. @@ -632,7 +631,7 @@ async def get_trytes(self, hashes: Iterable[TransactionHash]) -> Dict: """ return await core.GetTrytesCommand(self.adapter)(hashes=hashes) - async def interrupt_attaching_to_tangle(self) -> Dict: + async def interrupt_attaching_to_tangle(self) -> dict: """ Interrupts and completely aborts the :py:meth:`attach_to_tangle` process. @@ -651,12 +650,12 @@ async def interrupt_attaching_to_tangle(self) -> Dict: """ return await core.InterruptAttachingToTangleCommand(self.adapter)() - async def remove_neighbors(self, uris: Iterable[Text]) -> Dict: + async def remove_neighbors(self, uris: Iterable[str]) -> dict: """ Removes one or more neighbors from the node. Lasts until the node is restarted. - :param Text uris: + :param str uris: Use format ``://:``. Example: `remove_neighbors(['udp://example.com:14265'])` @@ -676,7 +675,7 @@ async def remove_neighbors(self, uris: Iterable[Text]) -> Dict: """ return await core.RemoveNeighborsCommand(self.adapter)(uris=uris) - async def store_transactions(self, trytes: Iterable[TryteString]) -> Dict: + async def store_transactions(self, trytes: Iterable[TryteString]) -> dict: """ Store transactions into local storage of the node. @@ -705,7 +704,7 @@ async def store_transactions(self, trytes: Iterable[TryteString]) -> Dict: async def were_addresses_spent_from( self, addresses: Iterable[Address] - ) -> Dict: + ) -> dict: """ Check if a list of addresses was ever spent from, in the current epoch, or in previous epochs. @@ -795,7 +794,7 @@ def __init__( async def broadcast_and_store( self, trytes: Iterable[TransactionTrytes] - ) -> Dict: + ) -> dict: """ Broadcasts and stores a set of transaction trytes. @@ -822,7 +821,7 @@ async def broadcast_and_store( async def broadcast_bundle( self, tail_transaction_hash: TransactionHash - ) -> Dict: + ) -> dict: """ Re-broadcasts all transactions in a bundle given the tail transaction hash. It might be useful when transactions did not properly propagate, @@ -854,7 +853,7 @@ async def find_transaction_objects( addresses: Optional[Iterable[Address]] = None, tags: Optional[Iterable[Tag]] = None, approvees: Optional[Iterable[TransactionHash]] = None, - ) -> Dict: + ) -> dict: """ A more extensive version of :py:meth:`find_transactions` that returns transaction objects instead of hashes. @@ -905,7 +904,7 @@ async def get_account_data( stop: Optional[int] = None, inclusion_states: bool = False, security_level: Optional[int] = None - ) -> Dict: + ) -> dict: """ More comprehensive version of :py:meth:`get_transfers` that returns addresses and account balance in addition to bundles. @@ -984,7 +983,7 @@ async def get_account_data( async def get_bundles( self, transactions: Iterable[TransactionHash] - ) -> Dict: + ) -> dict: """ Returns the bundle(s) associated with the specified transaction hashes. @@ -1019,7 +1018,7 @@ async def get_inputs( stop: Optional[int] = None, threshold: Optional[int] = None, security_level: Optional[int] = None, - ) -> Dict: + ) -> dict: """ Gets all possible inputs of a seed and returns them, along with the total balance. @@ -1127,7 +1126,7 @@ async def get_inputs( async def get_latest_inclusion( self, hashes: Iterable[TransactionHash] - ) -> Dict[Text, Dict[TransactionHash, bool]]: + ) -> Dict[str, Dict[TransactionHash, bool]]: """ Fetches the inclusion state for the specified transaction hashes, as of the latest milestone that the node has processed. @@ -1221,7 +1220,7 @@ async def get_new_addresses( async def get_transaction_objects( self, hashes: [Iterable[TransactionHash]], - ) -> Dict: + ) -> dict: """ Fetches transaction objects from the Tangle given their transaction IDs (hashes). @@ -1252,7 +1251,7 @@ async def get_transfers( start: int = 0, stop: Optional[int] = None, inclusion_states: bool = False - ) -> Dict: + ) -> dict: """ Returns all transfers associated with the seed. @@ -1314,7 +1313,7 @@ async def get_transfers( async def is_promotable( self, tails: Iterable[TransactionHash], - ) -> Dict: + ) -> dict: """ Checks if tail transaction(s) is promotable by calling :py:meth:`check_consistency` and verifying that ``attachmentTimestamp`` @@ -1334,7 +1333,7 @@ async def is_promotable( If ``True``, all tails are promotable. If ``False``, see `info` field. - 'info': Optional(List[Text]) + 'info': Optional(List[str]) If `promotable` is ``False``, this contains info about what went wrong. Note that when 'promotable' is ``True``, 'info' does not @@ -1355,7 +1354,7 @@ async def prepare_transfer( inputs: Optional[Iterable[Address]] = None, change_address: Optional[Address] = None, security_level: Optional[int] = None, - ) -> Dict: + ) -> dict: """ Prepares transactions to be broadcast to the Tangle, by generating the correct bundle, as well as choosing and signing @@ -1415,7 +1414,7 @@ async def promote_transaction( transaction: TransactionHash, depth: int = 3, min_weight_magnitude: Optional[int] = None, - ) -> Dict: + ) -> dict: """ Promotes a transaction by adding spam on top of it. @@ -1454,7 +1453,7 @@ async def replay_bundle( transaction: TransactionHash, depth: int = 3, min_weight_magnitude: Optional[int] = None, - ) -> Dict: + ) -> dict: """ Takes a tail transaction hash as input, gets the bundle associated with the transaction and then replays the bundle by @@ -1502,7 +1501,7 @@ async def send_transfer( change_address: Optional[Address] = None, min_weight_magnitude: Optional[int] = None, security_level: Optional[int] = None, - ) -> Dict: + ) -> dict: """ Prepares a set of transfers and creates the bundle, then attaches the bundle to the Tangle, and broadcasts and stores the @@ -1571,7 +1570,7 @@ async def send_trytes( trytes: Iterable[TransactionTrytes], depth: int = 3, min_weight_magnitude: Optional[int] = None - ) -> Dict: + ) -> dict: """ Attaches transaction trytes to the Tangle, then broadcasts and stores them. @@ -1610,7 +1609,7 @@ async def send_trytes( minWeightMagnitude=min_weight_magnitude, ) - async def is_reattachable(self, addresses: Iterable[Address]) -> Dict: + async def is_reattachable(self, addresses: Iterable[Address]) -> dict: """ This API function helps you to determine whether you should replay a transaction or make a new one (either with the same @@ -1640,7 +1639,7 @@ async def is_reattachable(self, addresses: Iterable[Address]) -> Dict: addresses=addresses ) - async def traverse_bundle(self, tail_hash: TransactionHash) -> Dict: + async def traverse_bundle(self, tail_hash: TransactionHash) -> dict: """ Fetches and traverses a bundle from the Tangle given a tail transaction hash. diff --git a/iota/bin/__init__.py b/iota/bin/__init__.py index 917d2a7..4c035a6 100644 --- a/iota/bin/__init__.py +++ b/iota/bin/__init__.py @@ -4,7 +4,7 @@ from getpass import getpass as secure_input from io import StringIO from sys import exit -from typing import Any, Optional, Text, Dict +from typing import Any, Optional from iota import Iota, __version__ from iota.crypto.types import Seed @@ -73,7 +73,7 @@ def run_from_argv(self, argv: Optional[tuple] = None) -> int: return exit_code - def parse_argv(self, argv: Optional[tuple] = None) -> Dict: + def parse_argv(self, argv: Optional[tuple] = None) -> dict: """ Parses arguments for the command. @@ -145,7 +145,7 @@ def create_argument_parser(self) -> ArgumentParser: return parser @staticmethod - def seed_from_filepath(filepath: Text) -> Seed: + def seed_from_filepath(filepath: str) -> Seed: """ Reads a seed from the first line of a text file. diff --git a/iota/bin/repl.py b/iota/bin/repl.py index 25b36af..5e16163 100755 --- a/iota/bin/repl.py +++ b/iota/bin/repl.py @@ -6,10 +6,9 @@ from logging import basicConfig, getLogger, DEBUG from sys import stderr +from typing import Any # Import all IOTA symbols into module scope, so that it's more # convenient for the user. -from typing import Any - from iota import * from iota.adapter import resolve_adapter from iota.adapter.wrappers import RoutingWrapper diff --git a/iota/codecs.py b/iota/codecs.py index f54f785..cb3b533 100644 --- a/iota/codecs.py +++ b/iota/codecs.py @@ -1,5 +1,5 @@ from codecs import Codec, CodecInfo, register as lookup_function -from typing import Union, Text, Tuple +from typing import Union, Tuple from warnings import warn from iota.exceptions import with_context @@ -72,7 +72,7 @@ def get_codec_info(cls) -> CodecInfo: def encode(self, input: Union[memoryview, bytes, bytearray], - errors: Text = 'strict') -> Tuple[bytes, int]: + errors: str = 'strict') -> Tuple[bytes, int]: """ Encodes a byte string into trytes. """ @@ -108,7 +108,7 @@ def encode(self, def decode(self, input: Union[memoryview, bytes, bytearray], - errors: Text = 'strict') -> Tuple[bytes, int]: + errors: str = 'strict') -> Tuple[bytes, int]: """ Decodes a tryte string into bytes. """ diff --git a/iota/commands/__init__.py b/iota/commands/__init__.py index a9071cd..0f4c99a 100644 --- a/iota/commands/__init__.py +++ b/iota/commands/__init__.py @@ -1,10 +1,5 @@ from abc import ABCMeta, abstractmethod as abstract_method -from importlib import import_module -from inspect import getmembers as get_members, isabstract as is_abstract, \ - isclass as is_class -from pkgutil import walk_packages -from types import ModuleType -from typing import Any, Dict, Mapping, Optional, Text, Union +from typing import Any, Mapping, Optional import filters as f @@ -24,7 +19,7 @@ class BaseCommand(object, metaclass=ABCMeta): """ An API command ready to send to the node. """ - command: Text = None + command: str = None def __init__(self, adapter: BaseAdapter) -> None: """ @@ -34,10 +29,10 @@ def __init__(self, adapter: BaseAdapter) -> None: self.adapter = adapter self.called: bool = False - self.request: Optional[Dict] = None - self.response: Optional[Dict] = None + self.request: Optional[dict] = None + self.response: Optional[dict] = None - async def __call__(self, **kwargs: Any) -> Dict: + async def __call__(self, **kwargs: Any) -> dict: """ Sends the command to the node. """ @@ -75,7 +70,7 @@ def reset(self) -> None: self.request = None self.response = None - async def _execute(self, request: Dict) -> Dict: + async def _execute(self, request: dict) -> dict: """ Sends the request object to the adapter and returns the response. @@ -86,7 +81,7 @@ async def _execute(self, request: Dict) -> Dict: return await self.adapter.send_request(request) @abstract_method - def _prepare_request(self, request: Dict) -> Optional[Dict]: + def _prepare_request(self, request: dict) -> Optional[dict]: """ Modifies the request before sending it to the node. @@ -104,7 +99,7 @@ def _prepare_request(self, request: Dict) -> Optional[Dict]: ) @abstract_method - def _prepare_response(self, response: Dict) -> Optional[Dict]: + def _prepare_response(self, response: dict) -> Optional[dict]: """ Modifies the response from the node. @@ -126,7 +121,7 @@ class CustomCommand(BaseCommand): Useful for executing experimental/undocumented commands. """ - def __init__(self, adapter: BaseAdapter, command: Text) -> None: + def __init__(self, adapter: BaseAdapter, command: str) -> None: super(CustomCommand, self).__init__(adapter) self.command = command @@ -216,14 +211,14 @@ def get_response_filter(self) -> Optional[ResponseFilter]: 'Not implemented in {cls}.'.format(cls=type(self).__name__), ) - def _prepare_request(self, request: Dict) -> Dict: + def _prepare_request(self, request: dict) -> dict: return self._apply_filter( value = request, filter_ = self.get_request_filter(), failure_message = 'Request failed validation', ) - def _prepare_response(self, response: Dict) -> Dict: + def _prepare_response(self, response: dict) -> dict: return self._apply_filter( value = response, filter_ = self.get_response_filter(), @@ -232,10 +227,10 @@ def _prepare_response(self, response: Dict) -> Dict: @staticmethod def _apply_filter( - value: Dict, + value: dict, filter_: Optional[f.BaseFilter], - failure_message: Text - ) -> Dict: + failure_message: str + ) -> dict: """ Applies a filter to a value. If the value does not pass the filter, an exception will be raised with lots of contextual info diff --git a/iota/commands/core/attach_to_tangle.py b/iota/commands/core/attach_to_tangle.py index 64715d0..a0f9749 100644 --- a/iota/commands/core/attach_to_tangle.py +++ b/iota/commands/core/attach_to_tangle.py @@ -1,5 +1,3 @@ -from typing import Dict - import filters as f from iota import TransactionHash, TransactionTrytes @@ -26,7 +24,7 @@ def get_request_filter(self): def get_response_filter(self): return AttachToTangleResponseFilter() - async def _execute(self, request: Dict) -> Dict: + async def _execute(self, request: dict) -> dict: if self.adapter.local_pow is True: from pow import ccurl_interface powed_trytes = ccurl_interface.attach_to_tangle( diff --git a/iota/commands/core/find_transactions.py b/iota/commands/core/find_transactions.py index 6b2f701..5f70a49 100644 --- a/iota/commands/core/find_transactions.py +++ b/iota/commands/core/find_transactions.py @@ -1,5 +1,3 @@ -from typing import Dict - import filters as f from iota import BundleHash, Tag, TransactionHash @@ -55,7 +53,7 @@ def __init__(self) -> None: ) def _apply(self, value): - value: Dict = super(FindTransactionsRequestFilter, self)._apply( + value: dict = super(FindTransactionsRequestFilter, self)._apply( value ) diff --git a/iota/commands/core/get_balances.py b/iota/commands/core/get_balances.py index 661776c..5c54751 100644 --- a/iota/commands/core/get_balances.py +++ b/iota/commands/core/get_balances.py @@ -1,5 +1,3 @@ -from typing import Dict - import filters as f from iota import TransactionHash @@ -52,7 +50,7 @@ def __init__(self) -> None: ) def _apply(self, value): - value: Dict = super(GetBalancesRequestFilter, self)._apply( + value: dict = super(GetBalancesRequestFilter, self)._apply( value ) diff --git a/iota/commands/core/get_transactions_to_approve.py b/iota/commands/core/get_transactions_to_approve.py index 6533e9a..11a26d4 100644 --- a/iota/commands/core/get_transactions_to_approve.py +++ b/iota/commands/core/get_transactions_to_approve.py @@ -1,5 +1,3 @@ -from typing import Dict - import filters as f from iota import TransactionHash @@ -40,7 +38,7 @@ def __init__(self) -> None: }) def _apply(self, value): - value: Dict = super(GetTransactionsToApproveRequestFilter, self)._apply( + value: dict = super(GetTransactionsToApproveRequestFilter, self)._apply( value, ) diff --git a/iota/commands/extended/broadcast_and_store.py b/iota/commands/extended/broadcast_and_store.py index 07b4bce..7b58607 100644 --- a/iota/commands/extended/broadcast_and_store.py +++ b/iota/commands/extended/broadcast_and_store.py @@ -1,5 +1,3 @@ -from typing import Dict - from iota.commands import FilterCommand from iota.commands.core.broadcast_transactions import \ BroadcastTransactionsCommand @@ -25,7 +23,7 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request: Dict) -> Dict: + async def _execute(self, request: dict) -> dict: # Submit the two coroutines to the already running event loop await asyncio.gather( BroadcastTransactionsCommand(self.adapter)(**request), diff --git a/iota/commands/extended/broadcast_bundle.py b/iota/commands/extended/broadcast_bundle.py index e4de3d1..a17c0fa 100644 --- a/iota/commands/extended/broadcast_bundle.py +++ b/iota/commands/extended/broadcast_bundle.py @@ -1,5 +1,3 @@ -from typing import Dict - import filters as f from iota.filters import Trytes @@ -29,7 +27,7 @@ def get_response_filter(self): # Return value is filtered before hitting us. pass - async def _execute(self, request: Dict) -> Dict: + async def _execute(self, request: dict) -> dict: # Given tail hash, fetches the bundle from the tangle # and validates it. tail_hash: TransactionHash = request['tail_hash'] diff --git a/iota/commands/extended/find_transaction_objects.py b/iota/commands/extended/find_transaction_objects.py index 24af87d..fbc3ef4 100644 --- a/iota/commands/extended/find_transaction_objects.py +++ b/iota/commands/extended/find_transaction_objects.py @@ -1,4 +1,4 @@ -from typing import Iterable, List, Optional, Dict +from typing import Iterable, List, Optional from iota import Address, BundleHash, Tag, Transaction, TransactionHash from iota.commands.core import GetTrytesCommand, FindTransactionsCommand @@ -19,7 +19,7 @@ class FindTransactionObjectsCommand(FindTransactionsCommand): def get_response_filter(self): pass - async def _execute(self, request: Dict) -> Dict: + async def _execute(self, request: dict) -> dict: bundles: Optional[Iterable[BundleHash]] = request\ .get('bundles') addresses: Optional[Iterable[Address]] = request\ diff --git a/iota/commands/extended/get_account_data.py b/iota/commands/extended/get_account_data.py index 9aa07c7..ac97399 100644 --- a/iota/commands/extended/get_account_data.py +++ b/iota/commands/extended/get_account_data.py @@ -1,5 +1,5 @@ from operator import attrgetter -from typing import List, Optional, Dict +from typing import List, Optional import filters as f @@ -32,7 +32,7 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request: Dict) -> Dict: + async def _execute(self, request: dict) -> dict: inclusion_states: bool = request['inclusionStates'] seed: Seed = request['seed'] start: int = request['start'] diff --git a/iota/commands/extended/get_bundles.py b/iota/commands/extended/get_bundles.py index e1e65bc..5da2845 100644 --- a/iota/commands/extended/get_bundles.py +++ b/iota/commands/extended/get_bundles.py @@ -1,4 +1,4 @@ -from typing import Dict, Iterable +from typing import Iterable import filters as f @@ -29,7 +29,7 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request: Dict) -> Dict: + async def _execute(self, request: dict) -> dict: transaction_hashes: Iterable[TransactionHash] = request['transactions'] async def fetch_and_validate(tx_hash): diff --git a/iota/commands/extended/get_inputs.py b/iota/commands/extended/get_inputs.py index f36d785..4b50e3f 100644 --- a/iota/commands/extended/get_inputs.py +++ b/iota/commands/extended/get_inputs.py @@ -1,4 +1,4 @@ -from typing import Optional, Dict +from typing import Optional import filters as f @@ -30,7 +30,7 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request: Dict) -> Dict: + async def _execute(self, request: dict) -> dict: stop: Optional[int] = request['stop'] seed: Seed = request['seed'] start: int = request['start'] diff --git a/iota/commands/extended/get_latest_inclusion.py b/iota/commands/extended/get_latest_inclusion.py index 1e5db6f..afd5e3e 100644 --- a/iota/commands/extended/get_latest_inclusion.py +++ b/iota/commands/extended/get_latest_inclusion.py @@ -1,4 +1,4 @@ -from typing import List, Dict +from typing import List import filters as f @@ -27,7 +27,7 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request: Dict) -> Dict: + async def _execute(self, request: dict) -> dict: hashes: List[TransactionHash] = request['hashes'] gni_response = await GetNodeInfoCommand(self.adapter)() diff --git a/iota/commands/extended/get_new_addresses.py b/iota/commands/extended/get_new_addresses.py index 5b926a0..bc6a156 100644 --- a/iota/commands/extended/get_new_addresses.py +++ b/iota/commands/extended/get_new_addresses.py @@ -1,4 +1,4 @@ -from typing import List, Optional, Dict +from typing import List, Optional import filters as f @@ -31,7 +31,7 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request: Dict) -> Dict: + async def _execute(self, request: dict) -> dict: checksum: bool = request['checksum'] count: Optional[int] = request['count'] index: int = request['index'] diff --git a/iota/commands/extended/get_transaction_objects.py b/iota/commands/extended/get_transaction_objects.py index be8412e..632aacf 100644 --- a/iota/commands/extended/get_transaction_objects.py +++ b/iota/commands/extended/get_transaction_objects.py @@ -1,4 +1,4 @@ -from typing import Iterable, List, Dict +from typing import Iterable, List import filters as f @@ -26,7 +26,7 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request: Dict) -> Dict: + async def _execute(self, request: dict) -> dict: hashes: Iterable[TransactionHash] = request\ .get('hashes') diff --git a/iota/commands/extended/get_transfers.py b/iota/commands/extended/get_transfers.py index ae36c04..a96bd7c 100644 --- a/iota/commands/extended/get_transfers.py +++ b/iota/commands/extended/get_transfers.py @@ -1,5 +1,5 @@ from itertools import chain -from typing import Optional, Dict +from typing import Optional import filters as f @@ -30,7 +30,7 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request: Dict) -> Dict: + async def _execute(self, request: dict) -> dict: inclusion_states: bool = request['inclusionStates'] seed: Seed = request['seed'] start: int = request['start'] diff --git a/iota/commands/extended/is_promotable.py b/iota/commands/extended/is_promotable.py index e401a66..d3f6da4 100644 --- a/iota/commands/extended/is_promotable.py +++ b/iota/commands/extended/is_promotable.py @@ -1,4 +1,4 @@ -from typing import Dict, Optional +from typing import Optional from iota.commands import FilterCommand, RequestFilter from iota.commands.core import CheckConsistencyCommand, GetTrytesCommand @@ -50,7 +50,7 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request: Dict) -> Dict: + async def _execute(self, request: dict) -> dict: tails: TransactionHash = request['tails'] # First, check consistency diff --git a/iota/commands/extended/is_reattachable.py b/iota/commands/extended/is_reattachable.py index 95af4a5..97b3dea 100644 --- a/iota/commands/extended/is_reattachable.py +++ b/iota/commands/extended/is_reattachable.py @@ -1,4 +1,4 @@ -from typing import List, Dict +from typing import List import filters as f @@ -25,7 +25,7 @@ def get_request_filter(self): def get_response_filter(self): return IsReattachableResponseFilter() - async def _execute(self, request: Dict) -> Dict: + async def _execute(self, request: dict) -> dict: addresses: List[Address] = request['addresses'] # fetch full transaction objects diff --git a/iota/commands/extended/prepare_transfer.py b/iota/commands/extended/prepare_transfer.py index d694712..259869e 100644 --- a/iota/commands/extended/prepare_transfer.py +++ b/iota/commands/extended/prepare_transfer.py @@ -1,4 +1,4 @@ -from typing import List, Optional, Dict +from typing import List, Optional import filters as f @@ -32,7 +32,7 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request: Dict) -> Dict: + async def _execute(self, request: dict) -> dict: # Required parameters. seed: Seed = request['seed'] bundle: ProposedBundle = ProposedBundle(request['transfers']) diff --git a/iota/commands/extended/promote_transaction.py b/iota/commands/extended/promote_transaction.py index 210d3e7..26805b8 100644 --- a/iota/commands/extended/promote_transaction.py +++ b/iota/commands/extended/promote_transaction.py @@ -1,5 +1,3 @@ -from typing import Dict - import filters as f from iota import Address, BadApiResponse, ProposedTransaction, TransactionHash @@ -28,7 +26,7 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request: Dict) -> Dict: + async def _execute(self, request: dict) -> dict: depth: int = request['depth'] min_weight_magnitude: int = request['minWeightMagnitude'] transaction: TransactionHash = request['transaction'] diff --git a/iota/commands/extended/replay_bundle.py b/iota/commands/extended/replay_bundle.py index 254d22c..2f9a46b 100644 --- a/iota/commands/extended/replay_bundle.py +++ b/iota/commands/extended/replay_bundle.py @@ -1,5 +1,3 @@ -from typing import Dict - import filters as f from iota import Bundle, TransactionHash @@ -27,7 +25,7 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request: Dict) -> Dict: + async def _execute(self, request: dict) -> dict: depth: int = request['depth'] min_weight_magnitude: int = request['minWeightMagnitude'] transaction: TransactionHash = request['transaction'] diff --git a/iota/commands/extended/send_transfer.py b/iota/commands/extended/send_transfer.py index 1d36fc7..be1122e 100644 --- a/iota/commands/extended/send_transfer.py +++ b/iota/commands/extended/send_transfer.py @@ -1,4 +1,4 @@ -from typing import List, Optional, Dict +from typing import List, Optional import filters as f @@ -28,7 +28,7 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request: Dict) -> Dict: + async def _execute(self, request: dict) -> dict: change_address: Optional[Address] = request['changeAddress'] depth: int = request['depth'] inputs: Optional[List[Address]] = request['inputs'] diff --git a/iota/commands/extended/send_trytes.py b/iota/commands/extended/send_trytes.py index 9783eab..40bfd51 100644 --- a/iota/commands/extended/send_trytes.py +++ b/iota/commands/extended/send_trytes.py @@ -1,4 +1,4 @@ -from typing import List, Optional, Dict +from typing import List, Optional import filters as f @@ -29,7 +29,7 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request: Dict) -> Dict: + async def _execute(self, request: dict) -> dict: depth: int = request['depth'] min_weight_magnitude: int = request['minWeightMagnitude'] trytes: List[TryteString] = request['trytes'] diff --git a/iota/commands/extended/traverse_bundle.py b/iota/commands/extended/traverse_bundle.py index 69ad9e5..f819d11 100644 --- a/iota/commands/extended/traverse_bundle.py +++ b/iota/commands/extended/traverse_bundle.py @@ -1,4 +1,4 @@ -from typing import List, Optional, Dict +from typing import List, Optional import filters as f @@ -28,7 +28,7 @@ def get_request_filter(self): def get_response_filter(self): pass - async def _execute(self, request: Dict) -> Dict: + async def _execute(self, request: dict) -> dict: txn_hash: TransactionHash = request['transaction'] bundle = Bundle(await self._traverse_bundle(txn_hash, None)) diff --git a/iota/crypto/kerl/conv.py b/iota/crypto/kerl/conv.py index 6807f3c..8ba58e1 100644 --- a/iota/crypto/kerl/conv.py +++ b/iota/crypto/kerl/conv.py @@ -1,10 +1,10 @@ -from typing import Dict, Text, List +from typing import List, Dict BYTE_HASH_LENGTH = 48 TRIT_HASH_LENGTH = 243 -tryte_table: Dict[Text, List[int]] = { +tryte_table: Dict[str, List[int]] = { '9': [0, 0, 0], # 0 'A': [1, 0, 0], # 1 'B': [-1, 1, 0], # 2 @@ -38,7 +38,7 @@ trit_table = {tuple(v): k for k, v in tryte_table.items()} -def trytes_to_trits(trytes: Text) -> List[int]: +def trytes_to_trits(trytes: str) -> List[int]: trits = [] for tryte in trytes: trits.extend(tryte_table[tryte]) @@ -46,7 +46,7 @@ def trytes_to_trits(trytes: Text) -> List[int]: return trits -def trits_to_trytes(trits: List[int]) -> Text: +def trits_to_trytes(trits: List[int]) -> str: trytes = [] trits_chunks = [trits[i:i + 3] for i in range(0, len(trits), 3)] @@ -64,7 +64,7 @@ def convertToTrits(bytes_k: List[int]) -> List[int]: def convertToBytes(trits: List[int]) -> List[int]: bigInt = convertBaseToBigint(trits, 3) - bytes_k = convertBigintToBytes(bigInt) + bytes_k = convertBigIntToBytes(bigInt) return bytes_k diff --git a/iota/crypto/types.py b/iota/crypto/types.py index 99b4869..a33ab0c 100644 --- a/iota/crypto/types.py +++ b/iota/crypto/types.py @@ -1,5 +1,5 @@ import warnings -from typing import Optional, Dict +from typing import Optional from iota.crypto import FRAGMENT_LENGTH, HASH_LENGTH, SeedWarning from iota.crypto.kerl import Kerl @@ -70,7 +70,7 @@ def security_level(self) -> int: """ return len(self) // Hash.LEN - def as_json_compatible(self) -> Dict: + def as_json_compatible(self) -> dict: """ Returns a JSON-compatible representation of the digest. @@ -78,7 +78,7 @@ def as_json_compatible(self) -> Dict: ``dict`` with the following structure:: { - trytes': Text, + trytes': str, 'key_index': int, } @@ -201,7 +201,7 @@ def __init__( self.key_index = key_index self.security_level = security_level - def as_json_compatible(self) -> Dict: + def as_json_compatible(self) -> dict: """ Returns a JSON-compatible representation of the private key. @@ -209,7 +209,7 @@ def as_json_compatible(self) -> Dict: ``dict`` with the following structure:: { - trytes': Text, + trytes': str, 'key_index': int, 'security_level': int, } diff --git a/iota/filters.py b/iota/filters.py index 80d0684..d88b15b 100644 --- a/iota/filters.py +++ b/iota/filters.py @@ -1,4 +1,4 @@ -from typing import Text, Type +from typing import Type import filters as f from filters.macros import filter_macro @@ -77,7 +77,7 @@ class NodeUri(f.BaseFilter): } def _apply(self, value): - value: Text = self._filter(value, f.Type(str)) + value: str = self._filter(value, f.Type(str)) if self._has_errors: return None diff --git a/iota/multisig/api.py b/iota/multisig/api.py index d0abdd8..37695f6 100644 --- a/iota/multisig/api.py +++ b/iota/multisig/api.py @@ -1,4 +1,4 @@ -from typing import Iterable, Optional, Dict +from typing import Iterable, Optional from iota import Address, Iota, AsyncIota, ProposedTransaction from iota.crypto.addresses import AddressGenerator @@ -50,7 +50,7 @@ class AsyncMultisigIota(AsyncIota): async def create_multisig_address( self, digests: Iterable[Digest] - ) -> Dict: + ) -> dict: """ Generates a multisig address from a collection of digests. @@ -63,7 +63,7 @@ async def create_multisig_address( keys in the exact same order. :return: - Dict with the following items:: + ``dict`` with the following items:: { 'address': MultisigAddress, @@ -79,7 +79,7 @@ async def get_digests( index: int = 0, count: int = 1, security_level: int = AddressGenerator.DEFAULT_SECURITY_LEVEL, - ) -> Dict: + ) -> dict: """ Generates one or more key digests from the seed. @@ -101,7 +101,7 @@ async def get_digests( This value must be between 1 and 3, inclusive. :return: - Dict with the following items:: + ``dict`` with the following items:: { 'digests': List[Digest], @@ -121,7 +121,7 @@ async def get_private_keys( index: int = 0, count: int = 1, security_level: int = AddressGenerator.DEFAULT_SECURITY_LEVEL, - ) -> Dict: + ) -> dict: """ Generates one or more private keys from the seed. @@ -144,7 +144,7 @@ async def get_private_keys( This value must be between 1 and 3, inclusive. :return: - Dict with the following items:: + ``dict`` with the following items:: { 'keys': List[PrivateKey], @@ -169,7 +169,7 @@ async def prepare_multisig_transfer( transfers: Iterable[ProposedTransaction], multisig_input: MultisigAddress, change_address: Optional[Address] = None, - ) -> Dict: + ) -> dict: """ Prepares a bundle that authorizes the spending of IOTAs from a multisig address. @@ -233,7 +233,7 @@ async def prepare_multisig_transfer( signing the input(s)! :return: - Dict containing the following values:: + ``dict`` wontaining the following values:: { 'trytes': List[TransactionTrytes], @@ -293,7 +293,7 @@ class MultisigIota(Iota, AsyncMultisigIota): def create_multisig_address( self, digests: Iterable[Digest] - ) -> Dict: + ) -> dict: """ Generates a multisig address from a collection of digests. @@ -306,7 +306,7 @@ def create_multisig_address( keys in the exact same order. :return: - Dict with the following items:: + ``dict`` with the following items:: { 'address': MultisigAddress, @@ -322,7 +322,7 @@ def get_digests( index: int = 0, count: int = 1, security_level: int = AddressGenerator.DEFAULT_SECURITY_LEVEL, - ) -> Dict: + ) -> dict: """ Generates one or more key digests from the seed. @@ -344,7 +344,7 @@ def get_digests( This value must be between 1 and 3, inclusive. :return: - Dict with the following items:: + ``dict`` with the following items:: { 'digests': List[Digest], @@ -365,7 +365,7 @@ def get_private_keys( index: int = 0, count: int = 1, security_level: int = AddressGenerator.DEFAULT_SECURITY_LEVEL, - ) -> Dict: + ) -> dict: """ Generates one or more private keys from the seed. @@ -388,7 +388,7 @@ def get_private_keys( This value must be between 1 and 3, inclusive. :return: - Dict with the following items:: + ``dict`` with the following items:: { 'keys': List[PrivateKey], @@ -414,7 +414,7 @@ def prepare_multisig_transfer( transfers: Iterable[ProposedTransaction], multisig_input: MultisigAddress, change_address: Optional[Address] = None, - ) -> Dict: + ) -> dict: """ Prepares a bundle that authorizes the spending of IOTAs from a multisig address. @@ -478,7 +478,7 @@ def prepare_multisig_transfer( signing the input(s)! :return: - Dict containing the following values:: + ``dict`` containing the following values:: { 'trytes': List[TransactionTrytes], diff --git a/iota/multisig/commands/create_multisig_address.py b/iota/multisig/commands/create_multisig_address.py index 142160f..55c6ed4 100644 --- a/iota/multisig/commands/create_multisig_address.py +++ b/iota/multisig/commands/create_multisig_address.py @@ -1,4 +1,4 @@ -from typing import List, Dict +from typing import List import filters as f @@ -30,7 +30,7 @@ def get_response_filter(self): # There is no async operation going on here, but the base class is async, # so from the outside, we have to act like we are doing async. - async def _execute(self, request: Dict): + async def _execute(self, request: dict) -> dict: digests: List[Digest] = request['digests'] builder = MultisigAddressBuilder() diff --git a/iota/multisig/commands/get_digests.py b/iota/multisig/commands/get_digests.py index 3d01841..bb35125 100644 --- a/iota/multisig/commands/get_digests.py +++ b/iota/multisig/commands/get_digests.py @@ -1,4 +1,4 @@ -from typing import Optional, Dict +from typing import Optional import filters as f @@ -30,7 +30,7 @@ def get_response_filter(self): # There is no async operation going on here, but the base class is async, # so from the outside, we have to act like we are doing async. - async def _execute(self, request: Dict) -> Dict: + async def _execute(self, request: dict) -> dict: count: Optional[int] = request['count'] index: int = request['index'] seed: Seed = request['seed'] diff --git a/iota/multisig/commands/get_private_keys.py b/iota/multisig/commands/get_private_keys.py index bb392b6..8e82476 100644 --- a/iota/multisig/commands/get_private_keys.py +++ b/iota/multisig/commands/get_private_keys.py @@ -1,4 +1,4 @@ -from typing import Optional, Dict +from typing import Optional import filters as f @@ -31,7 +31,7 @@ def get_response_filter(self): # There is no async operation going on here, but the base class is async, # so from the outside, we have to act like we are doing async. - async def _execute(self, request: Dict) -> Dict: + async def _execute(self, request: dict) -> dict: count: Optional[int] = request['count'] index: int = request['index'] seed: Seed = request['seed'] diff --git a/iota/multisig/commands/prepare_multisig_transfer.py b/iota/multisig/commands/prepare_multisig_transfer.py index 1585632..cafa296 100644 --- a/iota/multisig/commands/prepare_multisig_transfer.py +++ b/iota/multisig/commands/prepare_multisig_transfer.py @@ -1,4 +1,4 @@ -from typing import List, Optional, Dict +from typing import List, Optional import filters as f @@ -31,7 +31,7 @@ def get_request_filter(self) -> 'PrepareMultisigTransferRequestFilter': def get_response_filter(self): pass - async def _execute(self, request: Dict) -> Dict: + async def _execute(self, request: dict) -> dict: change_address: Optional[Address] = request['changeAddress'] multisig_input: MultisigAddress = request['multisigInput'] transfers: List[ProposedTransaction] = request['transfers'] diff --git a/iota/multisig/types.py b/iota/multisig/types.py index c0691b5..f8fdb33 100644 --- a/iota/multisig/types.py +++ b/iota/multisig/types.py @@ -1,5 +1,5 @@ from operator import attrgetter -from typing import Iterable, Optional, Dict +from typing import Iterable, Optional from iota import Address, TrytesCompatible from iota.crypto.types import Digest @@ -57,7 +57,7 @@ def __init__( map(attrgetter('security_level'), self.digests) ) - def as_json_compatible(self) -> Dict: + def as_json_compatible(self) -> dict: """ Get a JSON represenation of the :py:class:`MultisigAddress` object. @@ -65,7 +65,7 @@ def as_json_compatible(self) -> Dict: ``dict`` with the following structure:: { - 'trytes': Text, + 'trytes': str, String representation of the address trytes. 'balance': int, Balance of the address. diff --git a/iota/transaction/base.py b/iota/transaction/base.py index 00d8965..b1a3a5a 100644 --- a/iota/transaction/base.py +++ b/iota/transaction/base.py @@ -1,6 +1,6 @@ from operator import attrgetter from typing import Iterable, Iterator, List, MutableSequence, \ - Optional, Sequence, Text, TypeVar, Type, Dict + Optional, Sequence, TypeVar, Type from iota.codecs import TrytesDecodeError from iota.crypto import Curl, HASH_LENGTH @@ -482,7 +482,7 @@ def attachment_timestamp_upper_bound_as_trytes(self) -> TryteString: trits_from_int(self.attachment_timestamp_upper_bound, pad=27), ) - def as_json_compatible(self) -> Dict: + def as_json_compatible(self) -> dict: """ Returns a JSON-compatible representation of the object. @@ -741,12 +741,12 @@ def tail_transaction(self) -> Transaction: """ return self[0] - def get_messages(self, errors: Text = 'drop') -> List[Text]: + def get_messages(self, errors: str = 'drop') -> List[str]: """ Attempts to decipher encoded messages from the transactions in the bundle. - :param Text errors: + :param str errors: How to handle trytes that can't be converted, or bytes that can't be decoded using UTF-8: @@ -762,7 +762,7 @@ def get_messages(self, errors: Text = 'drop') -> List[Text]: 'ignore' Omit the invalid tryte/byte sequence. - :return: ``List[Text]`` + :return: ``List[str]`` """ decode_errors = 'strict' if errors == 'drop' else errors @@ -805,7 +805,7 @@ def as_tryte_strings(self, head_to_tail: bool = False) -> List[TransactionTrytes transactions = self if head_to_tail else reversed(self) return [t.as_tryte_string() for t in transactions] - def as_json_compatible(self) -> List[Dict]: + def as_json_compatible(self) -> List[dict]: """ Returns a JSON-compatible representation of the object. diff --git a/iota/transaction/creation.py b/iota/transaction/creation.py index cb57286..dcc69a4 100644 --- a/iota/transaction/creation.py +++ b/iota/transaction/creation.py @@ -1,4 +1,4 @@ -from typing import Iterable, Iterator, List, Optional, Sequence, Dict +from typing import Iterable, Iterator, List, Optional, Sequence from iota.crypto import HASH_LENGTH from iota.crypto.kerl import Kerl @@ -260,7 +260,7 @@ def tag(self) -> Tag: return Tag(b'') - def as_json_compatible(self) -> List[Dict]: + def as_json_compatible(self) -> List[dict]: """ Returns a JSON-compatible representation of the object. diff --git a/iota/transaction/utils.py b/iota/transaction/utils.py index 38e1617..1e1cee2 100644 --- a/iota/transaction/utils.py +++ b/iota/transaction/utils.py @@ -1,6 +1,5 @@ from calendar import timegm as unix_timestamp from datetime import datetime -from typing import Text from iota import STANDARD_UNITS from iota.exceptions import with_context @@ -11,7 +10,7 @@ ] -def convert_value_to_standard_unit(value: Text, symbol: Text = 'i') -> float: +def convert_value_to_standard_unit(value: str, symbol: str = 'i') -> float: """ Converts between any two standard units of iota. diff --git a/iota/transaction/validator.py b/iota/transaction/validator.py index 25b009b..6b64261 100644 --- a/iota/transaction/validator.py +++ b/iota/transaction/validator.py @@ -1,4 +1,4 @@ -from typing import Generator, List, Optional, Text, Type +from typing import Generator, List, Optional, Type from iota.crypto.kerl import Kerl from iota.crypto.signing import validate_signature_fragments @@ -29,16 +29,16 @@ def __init__(self, bundle: Bundle) -> None: self.bundle = bundle - self._errors: Optional[List[Text]] = [] + self._errors: Optional[List[str]] = [] self._validator = self._create_validator() @property - def errors(self) -> List[Text]: + def errors(self) -> List[str]: """ Returns all errors found with the bundle. """ try: - self._errors.extend(self._validator) # type: List[Text] + self._errors.extend(self._validator) # type: List[str] except StopIteration: pass @@ -58,7 +58,7 @@ def is_valid(self) -> bool: return not self._errors - def _create_validator(self) -> Generator[Text, None, None]: + def _create_validator(self) -> Generator[str, None, None]: """ Creates a generator that does all the work. """ @@ -180,7 +180,7 @@ def _create_validator(self) -> Generator[Text, None, None]: def _get_bundle_signature_errors( self, groups: List[List[Transaction]] - ) -> List[Text]: + ) -> List[str]: """ Validates the signature fragments in the bundle. @@ -231,7 +231,7 @@ def _get_bundle_signature_errors( def _get_group_signature_error( group: List[Transaction], sponge_type: Type - ) -> Optional[Text]: + ) -> Optional[str]: """ Validates the signature fragments for a group of transactions using the specified sponge type. @@ -242,7 +242,7 @@ def _get_group_signature_error( :return: - ``None``: Indicates that the signature fragments are valid. - - ``Text``: Error message indicating the fragments are invalid. + - ``str``: Error message indicating the fragments are invalid. """ validate_group_signature = validate_signature_fragments( fragments=[txn.signature_message_fragment for txn in group], diff --git a/iota/types.py b/iota/types.py index ac9abd0..a4c3cf1 100644 --- a/iota/types.py +++ b/iota/types.py @@ -4,7 +4,7 @@ from math import ceil from random import SystemRandom from typing import Any, AnyStr, Generator, Iterable, Iterator, List, \ - MutableSequence, Optional, Text, Type, TypeVar, Union, Dict + MutableSequence, Optional, Type, TypeVar, Union, Dict from warnings import warn from iota import AsciiTrytesCodec, TRITS_PER_TRYTE @@ -96,7 +96,7 @@ def random(cls: Type[T], length: Optional[int] = None) -> T: @classmethod def from_bytes(cls: Type[T], bytes_: Union[bytes, bytearray], - codec: Text = AsciiTrytesCodec.name, + codec: str = AsciiTrytesCodec.name, *args: Any, **kwargs: Any) -> T: """ @@ -106,7 +106,7 @@ def from_bytes(cls: Type[T], Source bytes. ASCII representation of a sequence of bytes. Note that only tryte alphabet supported! - :param Text codec: + :param str codec: Reserved for future use. Currently supports only the 'trytes_ascii' codec. See https://github.com/iotaledger/iota.py/issues/62 for @@ -131,13 +131,13 @@ def from_bytes(cls: Type[T], @classmethod def from_unicode(cls: Type[T], - string: Text, + string: str, *args: Any, **kwargs: Any) -> T: """ Creates a TryteString from a Unicode string. - :param Text string: + :param str string: Source Unicode string. :param args: @@ -370,7 +370,7 @@ def __init__(self, trytes: TrytesCompatible, pad: Optional[int] = None) -> None: def __hash__(self) -> int: return hash(bytes(self._trytes)) - def __repr__(self) -> Text: + def __repr__(self) -> str: return '{cls}({trytes!r})'.format( cls=type(self).__name__, trytes=bytes(self._trytes), @@ -540,13 +540,13 @@ def iter_chunks(self, chunk_size: int) -> 'ChunkIterator': return ChunkIterator(self, chunk_size) def encode(self, - errors: Text = 'strict', - codec: Text = AsciiTrytesCodec.name) -> bytes: + errors: str = 'strict', + codec: str = AsciiTrytesCodec.name) -> bytes: """ Encodes the TryteString into a lower-level primitive (usually bytes). - :param Text errors: + :param str errors: How to handle trytes that can't be converted: 'strict' @@ -558,7 +558,7 @@ def encode(self, 'ignore' omit the tryte from the result. - :param Text codec: + :param str codec: Reserved for future use. See https://github.com/iotaledger/iota.py/issues/62 for @@ -614,13 +614,13 @@ def as_bytes(self, *args, **kwargs): ) return self.encode(*args, **kwargs) - def decode(self, errors: Text = 'strict', - strip_padding: bool = True) -> Text: + def decode(self, errors: str = 'strict', + strip_padding: bool = True) -> str: """ Decodes the TryteString into a higher-level abstraction (usually Unicode characters). - :param Text errors: + :param str errors: How to handle trytes that can't be converted, or bytes that can't be decoded using UTF-8: @@ -677,7 +677,7 @@ def as_string(self, *args, **kwargs): ) return self.decode(*args, **kwargs) - def as_json_compatible(self) -> Text: + def as_json_compatible(self) -> str: """ Returns a JSON-compatible representation of the object. @@ -992,7 +992,7 @@ def __init__( address. """ - def as_json_compatible(self) -> Dict[Text, Union[Text, int]]: + def as_json_compatible(self) -> Dict[str, Union[str, int]]: """ Returns a JSON-compatible representation of the Address. @@ -1000,7 +1000,7 @@ def as_json_compatible(self) -> Dict[Text, Union[Text, int]]: ``dict`` with the following structure:: { - 'trytes': Text, + 'trytes': str, 'balance': int, 'key_index': int, 'security_level': int,