From aa48916377791e52d0f39a4e67d747cdb236cf00 Mon Sep 17 00:00:00 2001 From: Phoenix Zerin Date: Wed, 9 Oct 2019 10:18:53 +1300 Subject: [PATCH 1/2] Refactored repeated filter logic into macro. --- iota/commands/core/broadcast_transactions.py | 11 ++----- iota/commands/core/find_transactions.py | 25 +++------------ iota/commands/core/get_balances.py | 9 ++---- iota/commands/core/get_inclusion_states.py | 14 ++------- iota/commands/core/get_trytes.py | 8 ++--- iota/commands/core/store_transactions.py | 8 ++--- iota/commands/extended/is_reattachable.py | 9 ++---- iota/filters.py | 33 ++++++++++++++++++++ 8 files changed, 50 insertions(+), 67 deletions(-) diff --git a/iota/commands/core/broadcast_transactions.py b/iota/commands/core/broadcast_transactions.py index 77625c75..a8227b51 100644 --- a/iota/commands/core/broadcast_transactions.py +++ b/iota/commands/core/broadcast_transactions.py @@ -6,7 +6,7 @@ from iota import TransactionTrytes from iota.commands import FilterCommand, RequestFilter -from iota.filters import Trytes +from iota.filters import StringifiedTrytesArray __all__ = [ 'BroadcastTransactionsCommand', @@ -31,12 +31,5 @@ def get_response_filter(self): class BroadcastTransactionsRequestFilter(RequestFilter): def __init__(self): super(BroadcastTransactionsRequestFilter, self).__init__({ - 'trytes': - f.Required | - f.Array | - f.FilterRepeater( - f.Required | - Trytes(TransactionTrytes) | - f.Unicode(encoding='ascii', normalize=False), - ), + 'trytes': StringifiedTrytesArray(TransactionTrytes) | f.Required, }) diff --git a/iota/commands/core/find_transactions.py b/iota/commands/core/find_transactions.py index 7193cd24..8c531148 100644 --- a/iota/commands/core/find_transactions.py +++ b/iota/commands/core/find_transactions.py @@ -7,7 +7,7 @@ from iota import BundleHash, Tag, TransactionHash from iota.commands import FilterCommand, RequestFilter, ResponseFilter -from iota.filters import AddressNoChecksum, Trytes +from iota.filters import AddressNoChecksum, StringifiedTrytesArray, Trytes __all__ = [ 'FindTransactionsCommand', @@ -46,26 +46,9 @@ def __init__(self): f.Unicode(encoding='ascii', normalize=False), ), - 'approvees': - f.Array | f.FilterRepeater( - f.Required | - Trytes(TransactionHash) | - f.Unicode(encoding='ascii', normalize=False), - ), - - 'bundles': - f.Array | f.FilterRepeater( - f.Required | - Trytes(BundleHash) | - f.Unicode(encoding='ascii', normalize=False), - ), - - 'tags': - f.Array | f.FilterRepeater( - f.Required | - Trytes(Tag) | - f.Unicode(encoding='ascii', normalize=False), - ), + 'approvees': StringifiedTrytesArray(TransactionHash), + 'bundles': StringifiedTrytesArray(BundleHash), + 'tags': StringifiedTrytesArray(Tag), }, # Technically, all of the parameters for this command are diff --git a/iota/commands/core/get_balances.py b/iota/commands/core/get_balances.py index f4caef89..5d55fd35 100644 --- a/iota/commands/core/get_balances.py +++ b/iota/commands/core/get_balances.py @@ -7,7 +7,7 @@ from iota import TransactionHash from iota.commands import FilterCommand, RequestFilter, ResponseFilter -from iota.filters import AddressNoChecksum, Trytes +from iota.filters import AddressNoChecksum, StringifiedTrytesArray, Trytes __all__ = [ 'GetBalancesCommand', @@ -46,12 +46,7 @@ def __init__(self): f.Max(100) | f.Optional(default=100), - 'tips': - f.Array | f.FilterRepeater( - f.Required | - Trytes(TransactionHash) | - f.Unicode(encoding='ascii', normalize=False), - ) + 'tips': StringifiedTrytesArray(TransactionHash), }, allow_missing_keys={ diff --git a/iota/commands/core/get_inclusion_states.py b/iota/commands/core/get_inclusion_states.py index bc3066e2..cfcd6024 100644 --- a/iota/commands/core/get_inclusion_states.py +++ b/iota/commands/core/get_inclusion_states.py @@ -6,7 +6,7 @@ from iota import TransactionHash from iota.commands import FilterCommand, RequestFilter -from iota.filters import Trytes +from iota.filters import StringifiedTrytesArray __all__ = [ 'GetInclusionStatesCommand', @@ -34,19 +34,11 @@ def __init__(self): { # Required parameters. 'transactions': - f.Required | f.Array | f.FilterRepeater( - f.Required | - Trytes(TransactionHash) | - f.Unicode(encoding='ascii', normalize=False), - ), + StringifiedTrytesArray(TransactionHash) | f.Required, # Optional parameters. 'tips': - f.Array | f.FilterRepeater( - f.Required | - Trytes(TransactionHash) | - f.Unicode(encoding='ascii', normalize=False), - ) | + StringifiedTrytesArray(TransactionHash) | f.Optional(default=[]), }, diff --git a/iota/commands/core/get_trytes.py b/iota/commands/core/get_trytes.py index 3915b59a..f1a1851b 100644 --- a/iota/commands/core/get_trytes.py +++ b/iota/commands/core/get_trytes.py @@ -6,7 +6,7 @@ from iota import TransactionHash from iota.commands import FilterCommand, RequestFilter, ResponseFilter -from iota.filters import Trytes +from iota.filters import StringifiedTrytesArray, Trytes __all__ = [ 'GetTrytesCommand', @@ -32,11 +32,7 @@ class GetTrytesRequestFilter(RequestFilter): def __init__(self): super(GetTrytesRequestFilter, self).__init__({ 'hashes': - f.Required | f.Array | f.FilterRepeater( - f.Required | - Trytes(TransactionHash) | - f.Unicode(encoding='ascii', normalize=False), - ), + StringifiedTrytesArray(TransactionHash) | f.Required, }) diff --git a/iota/commands/core/store_transactions.py b/iota/commands/core/store_transactions.py index 0412eeca..31715846 100644 --- a/iota/commands/core/store_transactions.py +++ b/iota/commands/core/store_transactions.py @@ -6,7 +6,7 @@ from iota import TransactionTrytes from iota.commands import FilterCommand, RequestFilter -from iota.filters import Trytes +from iota.filters import StringifiedTrytesArray __all__ = [ 'StoreTransactionsCommand', @@ -32,9 +32,5 @@ class StoreTransactionsRequestFilter(RequestFilter): def __init__(self): super(StoreTransactionsRequestFilter, self).__init__({ 'trytes': - f.Required | f.Array | f.FilterRepeater( - f.Required | - Trytes(TransactionTrytes) | - f.Unicode(encoding='ascii', normalize=False), - ), + StringifiedTrytesArray(TransactionTrytes) | f.Required, }) diff --git a/iota/commands/extended/is_reattachable.py b/iota/commands/extended/is_reattachable.py index f136a194..3b5e83a6 100644 --- a/iota/commands/extended/is_reattachable.py +++ b/iota/commands/extended/is_reattachable.py @@ -10,7 +10,7 @@ from iota.commands import FilterCommand, RequestFilter, ResponseFilter from iota.commands.extended import FindTransactionObjectsCommand, \ GetLatestInclusionCommand -from iota.filters import Trytes +from iota.filters import Trytes, StringifiedTrytesArray __all__ = [ 'IsReattachableCommand', @@ -69,12 +69,7 @@ class IsReattachableRequestFilter(RequestFilter): def __init__(self): super(IsReattachableRequestFilter, self).__init__( { - 'addresses': - f.Required | f.Array | f.FilterRepeater( - f.Required | - Trytes(Address) | - f.Unicode(encoding='ascii', normalize=False), - ), + 'addresses': StringifiedTrytesArray(Address) | f.Required, }, ) diff --git a/iota/filters.py b/iota/filters.py index 2c980678..5e920224 100644 --- a/iota/filters.py +++ b/iota/filters.py @@ -11,6 +11,15 @@ from iota import Address, TryteString, TrytesCompatible from iota.crypto.addresses import AddressGenerator +__all__ = [ + 'AddressNoChecksum', + 'GeneratedAddress', + 'NodeUri', + 'SecurityLevel', + 'StringifiedTrytesArray', + 'Trytes', +] + class GeneratedAddress(f.BaseFilter): """ @@ -172,6 +181,30 @@ def _apply(self, value): ) +@filter_macro +def StringifiedTrytesArray(trytes_type=TryteString): + """ + Validates that the incoming value is an array containing tryte + strings corresponding to the specified type (e.g., + ``TransactionHash``). + + .. important:: + This filter will return string values, suitable for inclusion in + an API request. If you are expecting objects (e.g., + :py:class:`Address`), then this is not the filter to use! + + .. note:: + This filter will allow empty arrays and `None`. If this is not + desirable, chain this filter with ``f.NotEmpty`` or + ``f.Required``, respectively. + """ + return f.Array | f.FilterRepeater( + f.Required | + Trytes(trytes_type) | + f.Unicode(encoding='ascii', normalize=False), + ) + + class AddressNoChecksum(Trytes): """ Validates a sequence as an Address, then chops off the checksum if From 31f8707c3219bef2dbfae6f30d76c0bed3bd7909 Mon Sep 17 00:00:00 2001 From: Phoenix Zerin Date: Wed, 9 Oct 2019 10:24:36 +1300 Subject: [PATCH 2/2] Added type hint. --- iota/filters.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/iota/filters.py b/iota/filters.py index 5e920224..88f3cbff 100644 --- a/iota/filters.py +++ b/iota/filters.py @@ -2,7 +2,7 @@ from __future__ import absolute_import, division, print_function, \ unicode_literals -from typing import Text +from typing import Text, Type import filters as f from filters.macros import filter_macro @@ -181,8 +181,10 @@ def _apply(self, value): ) +# noinspection PyPep8Naming @filter_macro def StringifiedTrytesArray(trytes_type=TryteString): + # type: (Type[TryteString]) -> f.FilterChain """ Validates that the incoming value is an array containing tryte strings corresponding to the specified type (e.g.,