Ejemplo n.º 1
0
 def __init__(self):
     super(GetNewAddressesRequestFilter, self).__init__(
         {
             # Everything except ``seed`` is optional.
             'checksum':
             f.Type(bool) | f.Optional(default=False),
             'count':
             f.Type(int) | f.Min(1),
             'index':
             f.Type(int) | f.Min(0) | f.Optional(default=0),
             'securityLevel':
             f.Type(int)
             | f.Min(1)
             | f.Max(self.MAX_SECURITY_LEVEL)
             | f.Optional(default=AddressGenerator.DEFAULT_SECURITY_LEVEL),
             'seed':
             f.Required | Trytes(result_type=Seed),
         },
         allow_missing_keys={
             'checksum',
             'count',
             'index',
             'securityLevel',
         },
     )
Ejemplo n.º 2
0
    def __init__(self):
        super(GetPrivateKeysRequestFilter, self).__init__(
            {
                # Optional Parameters
                'count':
                    f.Type(int) | f.Min(1) | f.Optional(default=1),

                'index':
                    f.Type(int) | f.Min(0) | f.Optional(default=0),

                'securityLevel':
                    f.Type(int)
                    | f.Min(1)
                    | f.Optional(default=AddressGenerator.DEFAULT_SECURITY_LEVEL),

                # Required Parameters
                'seed':
                    f.Required | Trytes(result_type=Seed),
            },

            allow_missing_keys={
                'count',
                'index',
                'securityLevel',
            },
        )
Ejemplo n.º 3
0
    def __init__(self):
        super(SendTransferRequestFilter, self).__init__(
            {
                # Required parameters.
                'depth':
                f.Required | f.Type(int) | f.Min(1),
                'seed':
                f.Required | Trytes(result_type=Seed),

                # Loosely-validated; testnet nodes require a different value
                # than mainnet.
                'minWeightMagnitude':
                f.Required | f.Type(int) | f.Min(1),
                'transfers':
                (f.Required
                 | f.Array
                 | f.FilterRepeater(f.Required | f.Type(ProposedTransaction))),

                # Optional parameters.
                'changeAddress':
                Trytes(result_type=Address),

                # Note that ``inputs`` is allowed to be an empty array.
                'inputs':
                f.Array
                | f.FilterRepeater(f.Required | Trytes(result_type=Address)),
            },
            allow_missing_keys={
                'changeAddress',
                'inputs',
            },
        )
Ejemplo n.º 4
0
  def __init__(self):
    super(ReplayBundleRequestFilter, self).__init__({
      'depth':        f.Required | f.Type(int) | f.Min(1),
      'transaction':  f.Required | Trytes(result_type=TransactionHash),

      # Loosely-validated; testnet nodes require a different value than
      # mainnet.
      'minWeightMagnitude': f.Required | f.Type(int) | f.Min(1),
    })
    def __init__(self):
        super(PromoteTransactionRequestFilter, self).__init__({
            'depth': f.Required | f.Type(int) | f.Min(1),
            'transaction': f.Required | Trytes(TransactionHash),

            # Loosely-validated; testnet nodes require a different value
            # than mainnet.
            'minWeightMagnitude': f.Required | f.Type(int) | f.Min(1),
        })
Ejemplo n.º 6
0
 def __init__(self):
     super(GetNewAddressesRequestFilter, self).__init__(
         {
             # ``count`` and ``index`` are optional.
             'count': f.Type(int) | f.Min(1),
             'index': f.Type(int) | f.Min(0) | f.Optional(default=0),
             'seed': f.Required | Trytes(result_type=Seed),
         },
         allow_missing_keys={
             'count',
             'index',
         },
     )
Ejemplo n.º 7
0
    def __init__(self):
        super(SendTrytesRequestFilter, self).__init__({
            'depth': f.Required | f.Type(int) | f.Min(1),

            'trytes':
                f.Required
                | f.Array
                | f.FilterRepeater(f.Required | Trytes(result_type=TransactionTrytes)),

            # Loosely-validated; testnet nodes require a different value than
            # mainnet.
            'minWeightMagnitude': f.Required | f.Type(int) | f.Min(1),
        })
Ejemplo n.º 8
0
    def test_extra_keys_disallowed(self):
        """
        FilterMappers can be configured to treat any extra key as an
        invalid value.
        """
        self.filter_type = lambda: f.FilterMapper(
            {
                'id':       f.Required | f.Int | f.Min(1),
                'subject':  f.NotEmpty | f.MaxLength(16),
            },

            # Treat all extra keys as invalid values.s
            allow_extra_keys = False,
        )

        self.assertFilterErrors(
            {
                'id':       '42',
                'subject':  'Hello, world!',
                'extra':    'ignored',
            },

            {
                'extra': [f.FilterMapper.CODE_EXTRA_KEY],
            },

            # The valid fields were still included in the return value,
            # but the invalid field was removed.
            expected_value = {
                'id':       42,
                'subject':  'Hello, world!',
            }
        )
Ejemplo n.º 9
0
    def test_pass_ordered_mapping(self):
        """
        Configuring the FilterRepeater to return an OrderedDict.
        """
        # Note that we pass an OrderedDict to the filter initializer.
        self.filter_type = lambda: f.FilterMapper(OrderedDict((
            ('subject', f.NotEmpty | f.MaxLength(16)),
            ('id', f.Required | f.Int | f.Min(1)),
        )))

        filter_ = self._filter({
            'id':       '42',
            'subject':  'Hello, world!',
        })

        self.assertFilterPasses(
            filter_,

            OrderedDict((
                ('subject', 'Hello, world!'),
                ('id', 42),
            )),
        )

        # The result is an OrderedDict, to match the type of the filter
        # map.
        self.assertIs(type(filter_.cleaned_data), OrderedDict)
Ejemplo n.º 10
0
    def test_missing_keys_specified(self):
        """
        FilterMappers can be configured to allow some missing keys but
        not others.
        """
        self.filter_type = lambda: f.FilterMapper(
            {
                'id': f.Required | f.Int | f.Min(1),
                'subject': f.NotEmpty | f.MaxLength(16),
            },
            allow_missing_keys={'subject'},
        )

        # The FilterMapper is configured to treat missing 'subject' as
        # if it were set to `None`.
        self.assertFilterPasses(
            {'id': '42'},
            {
                'id': 42,
                'subject': None,
            },
        )

        # However, 'id' is still required.
        self.assertFilterErrors({
            'subject': 'Hello, world!',
        }, {
            'id': [f.FilterMapper.CODE_MISSING_KEY],
        },
                                expected_value={
                                    'id': None,
                                    'subject': 'Hello, world!',
                                })
Ejemplo n.º 11
0
    def test_missing_keys_allowed(self):
        """
        By default, FilterMappers treat missing keys as `None`.
        """
        self.filter_type = lambda: f.FilterMapper(
            {
                'id': f.Required | f.Int | f.Min(1),
                'subject': f.NotEmpty | f.MaxLength(16),
            })

        # 'subject' allows null values, so no errors are generated.
        self.assertFilterPasses(
            {
                'id': '42',
            },
            {
                'id': 42,
                'subject': None,
            },
        )

        # However, 'id' has Required in its FilterChain, so a missing
        # 'id' is still an error.
        self.assertFilterErrors(
            {
                'subject': 'Hello, world!',
            },
            {
                'id': [f.Required.CODE_EMPTY],
            },
            expected_value={
                'id': None,
                'subject': 'Hello, world!',
            },
        )
Ejemplo n.º 12
0
    def test_fail_match_case(self):
        """
        The incoming value matches one of the switch cases, but it is
        not valid, according to the corresponding filter.
        """
        self.assertFilterErrors(
            self._filter(
                {
                    'name': 'positive',
                    'value': -1
                },
                getter=lambda value: value['name'],
                cases={
                    'positive': f.FilterMapper({'value': f.Int | f.Min(0)}),
                },
            ),
            {'value': [f.Min.CODE_TOO_SMALL]},

            # The result is the exact same as if the value were passed
            # directly to the corresponding filter.
            expected_value={
                'name': 'positive',
                'value': None
            },
        )
Ejemplo n.º 13
0
    def test_missing_keys_disallowed(self):
        """
        FilterMappers can be configured to treat missing keys as
        invalid values.
        """
        self.filter_type = lambda: f.FilterMapper(
            {
                'id':       f.Required | f.Int | f.Min(1),
                'subject':  f.NotEmpty | f.MaxLength(16),
            },

            # Treat missing keys as invalid values.
            allow_missing_keys = False,
        )

        self.assertFilterErrors(
            {},

            {
                'id':       [f.FilterMapper.CODE_MISSING_KEY],
                'subject':  [f.FilterMapper.CODE_MISSING_KEY],
            },

            expected_value = {
                'id':       None,
                'subject':  None,
            },
        )
Ejemplo n.º 14
0
    def test_pass_mapping(self):
        """
        A FilterRepeater is applied to a dict containing valid values.
        """
        self.filter_type = lambda: f.FilterMapper({
            'id':       f.Required | f.Int | f.Min(1),
            'subject':  f.NotEmpty | f.MaxLength(16),
        })

        filter_ = self._filter({
            'id':       '42',
            'subject':  'Hello, world!',
        })

        self.assertFilterPasses(
            filter_,

            {
                'id':       42,
                'subject':  'Hello, world!',
            },
        )

        # The result is a dict, to match the type of the filter map.
        self.assertIs(type(filter_.cleaned_data), dict)
Ejemplo n.º 15
0
    def __init__(self):
        super(GetInputsRequestFilter, self).__init__(
            {
                # These arguments are optional.
                'stop': f.Type(int) | f.Min(0),
                'start': f.Type(int) | f.Min(0) | f.Optional(0),
                'threshold': f.Type(int) | f.Min(0),

                # These arguments are required.
                'seed': f.Required | Trytes(result_type=Seed),
            },
            allow_missing_keys={
                'stop',
                'start',
                'threshold',
            })
Ejemplo n.º 16
0
    def test_fail_mapping(self):
        """
        A FilterRepeater is applied to a dict containing invalid
        values.
        """
        self.filter_type = lambda: f.FilterMapper({
            'id':       f.Required | f.Int | f.Min(1),
            'subject':  f.NotEmpty | f.MaxLength(16),
        })

        self.assertFilterErrors(
            {
                'id':       None,
                'subject':  'Antidisestablishmentarianism',
            },

            {
                'id':       [f.Required.CODE_EMPTY],
                'subject':  [f.MaxLength.CODE_TOO_LONG],
            },

            expected_value = {
                'id':       None,
                'subject':  None,
            }
        )
Ejemplo n.º 17
0
    def __init__(self) -> None:
        super(GetAccountDataRequestFilter, self).__init__(
            {
                # Required parameters.
                'seed': f.Required | Trytes(Seed),

                # Optional parameters.
                'stop': f.Type(int) | f.Min(0),
                'start': f.Type(int) | f.Min(0) | f.Optional(0),
                'inclusionStates': f.Type(bool) | f.Optional(False),
                'security_level': SecurityLevel
            },
            allow_missing_keys={
                'stop', 'start', 'inclusionStates', 'security_level'
            },
        )
Ejemplo n.º 18
0
    def test_extra_keys_ordered(self):
        """
        When the filter map is an OrderedDict, extra keys are
        alphabetized.
        """
        # Note that we pass an OrderedDict to the filter initializer.
        self.filter_type = lambda: f.FilterMapper(OrderedDict((
            ('subject', f.NotEmpty | f.MaxLength(16)),
            ('id', f.Required | f.Int | f.Min(1)),
        )))

        filter_ = self._filter({
            'id':       '42',
            'subject':  'Hello, world!',
            'cat':      'felix',
            'bird':     'phoenix',
            'fox':      'fennecs',
        })

        self.assertFilterPasses(
            filter_,

            OrderedDict((
                # The filtered keys are always listed first.
                ('subject', 'Hello, world!'),
                ('id', 42),

                # Extra keys are listed afterward, in alphabetical
                # order.
                ('bird', 'phoenix'),
                ('cat', 'felix'),
                ('fox', 'fennecs'),
            )),
        )
Ejemplo n.º 19
0
    def test_mapper_chained_with_mapper(self):
        """
        Chaining two FilterMappers together has basically the same
        effect as combining their Filters.

        Generally, combining two FilterMappers into a single instance
        is much easier to read/maintain than chaining them, but in
        a few cases it may be unavoidable (for example, if you need
        each FilterMapper to handle extra and/or missing keys
        differently).
        """
        fm1 = f.FilterMapper(
            {
                'id': f.Int | f.Min(1),
            },
            allow_missing_keys=True,
            allow_extra_keys=True,
        )

        fm2 = f.FilterMapper(
            {
                'id': f.Required | f.Max(256),
                'subject': f.NotEmpty | f.MaxLength(16),
            },
            allow_missing_keys=False,
            allow_extra_keys=False,
        )

        self.filter_type = lambda: fm1 | fm2

        self.assertFilterPasses(
            {
                'id': '42',
                'subject': 'Hello, world!',
            },
            {
                'id': 42,
                'subject': 'Hello, world!',
            },
        )

        self.assertFilterErrors(
            {},
            {
                # ``fm1`` allows missing keys, so it sets 'id' to
                # ``None``.
                # However, ``fm2`` does not allow ``None`` for 'id'
                # (because of the ``Required`` filter).
                'id': [f.Required.CODE_EMPTY],

                # `fm1` does not care about `subject`, but `fm2`
                # expects it to be there.
                'subject': [f.FilterMapper.CODE_MISSING_KEY],
            },
            expected_value={
                'id': None,
                'subject': None,
            },
        )
Ejemplo n.º 20
0
 def __init__(self):
     super(GetNewAddressesRequestFilter, self).__init__(
         {
             # Everything except ``seed`` is optional.
             'checksum': f.Type(bool) | f.Optional(default=False),
             'count': f.Type(int) | f.Min(1),
             'index': f.Type(int) | f.Min(0) | f.Optional(default=0),
             'securityLevel': SecurityLevel,
             'seed': f.Required | Trytes(Seed),
         },
         allow_missing_keys={
             'checksum',
             'count',
             'index',
             'securityLevel',
         },
     )
Ejemplo n.º 21
0
    def test_success_filter_map(self):
        """
        Applying a :py:class:`f.FilterMap` to the values in a namedtuple
        after converting (success case).
        """
        self.filter_type = lambda: f.NamedTuple(
            Color,
            {
                # For whatever reason, we decide not to filter ``r``.
                'g': f.Required | f.Int | f.Min(0) | f.Max(255),
                'b': f.Required | f.Int | f.Min(0) | f.Max(255),
            })

        self.assertFilterPasses(
            ('64.0', '128', 192.0),
            Color('64.0', 128, 192),
        )
Ejemplo n.º 22
0
    def __init__(self):
        super(GetAccountDataRequestFilter, self).__init__(
            {
                # Required parameters.
                'seed': f.Required | Trytes(result_type=Seed),

                # Optional parameters.
                'stop': f.Type(int) | f.Min(0),
                'start': f.Type(int) | f.Min(0) | f.Optional(0),
                'inclusionStates': f.Type(bool) | f.Optional(False),
            },
            allow_missing_keys={
                'stop',
                'inclusionStates',
                'start',
            },
        )
Ejemplo n.º 23
0
    def __init__(self) -> None:
        super(GetDigestsRequestFilter, self).__init__(
            {
                # Optional Parameters
                'count': f.Type(int) | f.Min(1) | f.Optional(default=1),
                'index': f.Type(int) | f.Min(0) | f.Optional(default=0),
                'securityLevel': SecurityLevel,

                # Required Parameters
                'seed': f.Required | Trytes(Seed),
            },
            allow_missing_keys={
                'count',
                'index',
                'securityLevel',
            },
        )
Ejemplo n.º 24
0
    def __init__(self) -> None:
        super(GetTransfersRequestFilter, self).__init__(
            {
                # Required parameters.
                'seed': f.Required | Trytes(Seed),

                # Optional parameters.
                'stop': f.Type(int) | f.Min(0),
                'start': f.Type(int) | f.Min(0) | f.Optional(0),
                'inclusionStates': f.Type(bool) | f.Optional(False),
            },
            allow_missing_keys={
                'stop',
                'inclusionStates',
                'start',
            },
        )
Ejemplo n.º 25
0
 def __init__(self):
     super(GetTransactionsToApproveRequestFilter, self).__init__(
         {
             'depth': f.Required | f.Type(int) | f.Min(1),
             'reference': Trytes(result_type=TransactionHash),
         },
         allow_missing_keys={
             'reference',
         })
Ejemplo n.º 26
0
def SecurityLevel():
    """
    Generates a filter chain for validating a security level.

    :return:
        :py:class:`filters.FilterChain` object.
    """
    return (f.Type(int) | f.Min(1) | f.Max(3)
            | f.Optional(default=AddressGenerator.DEFAULT_SECURITY_LEVEL))
Ejemplo n.º 27
0
    def __init__(self) -> None:
        super(SendTrytesRequestFilter, self).__init__(
            {
                'depth':
                f.Required | f.Type(int) | f.Min(1),
                'trytes':
                f.Required | f.Array
                | f.FilterRepeater(f.Required | Trytes(TransactionTrytes), ),

                # Loosely-validated; devnet nodes require a different value
                # than mainnet.
                'minWeightMagnitude':
                f.Required | f.Type(int) | f.Min(1),
                'reference':
                Trytes(TransactionHash),
            },
            allow_missing_keys={
                'reference',
            })
Ejemplo n.º 28
0
    def test_passthru_key(self):
        """
        If you want to make a key required but do not want to run any
        Filters on it, set its FilterChain to `None`.
        """
        self.filter_type = lambda: f.FilterMapper(
            {
                'id':       f.Required | f.Int | f.Min(1),
                'subject':  None,
            },

            # If you configure a FilterMapper with passthru keys(s),
            # you generally also want to disallow missing keys.
            allow_missing_keys = False,
        )

        self.assertFilterPasses(
            {
                'id':       '42',
                'subject':  'Hello, world!',
            },

            {
                'id':       42,
                'subject':  'Hello, world!',
            },
        )

        self.assertFilterPasses(
            {
                'id':       '42',
                'subject':  None,
            },

            {
                'id':       42,
                'subject':  None,
            },
        )

        self.assertFilterErrors(
            {
                'id': '42',
            },

            {
                'subject': [f.FilterMapper.CODE_MISSING_KEY],
            },

            expected_value = {
                'id':       42,
                'subject':  None,
            },
        )
Ejemplo n.º 29
0
    def test_fail_filter_map(self):
        """
        Applying a :py:class:`f.FilterMap` to the values in a namedtuple
        after converting (failure case).
        """
        self.filter_type = lambda: f.NamedTuple(
            Color,
            {
                # For whatever reason, we decide not to filter ``r``.
                'g': f.Required | f.Int | f.Min(0) | f.Max(255),
                'b': f.Required | f.Int | f.Min(0) | f.Max(255),
            })

        self.assertFilterErrors(
            ['NaN', None, (42, )],
            {
                'g': [f.Required.CODE_EMPTY],
                'b': [f.Decimal.CODE_INVALID],
            },
        )
Ejemplo n.º 30
0
    def test_fail_non_mapping(self):
        """The incoming value is not a mapping."""
        self.filter_type = lambda: f.FilterMapper({
            'id':       f.Required | f.Int | f.Min(1),
            'subject':  f.NotEmpty | f.MaxLength(16),
        })

        self.assertFilterErrors(
            # Nope; it's gotta be an explicit mapping.
            (('id', '42'), ('subject', 'Hello, world!')),
            [f.Type.CODE_WRONG_TYPE],
        )