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', }, )
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, }, )
def test_implicit_chain(self): """ Chaining two filters together creates a FilterChain. """ self.filter_type = lambda: f.Int | f.Max(3) self.assertFilterPasses('1', 1) self.assertFilterErrors('4', [f.Max.CODE_TOO_BIG])
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), )
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))
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], }, )
def __init__(self): super(GetBalancesRequestFilter, self).__init__( { 'addresses': f.Required | f.Array | f.FilterRepeater( f.Required | AddressNoChecksum() | f.Unicode(encoding='ascii', normalize=False), ), 'threshold': f.Type(int) | f.Min(0) | f.Max(100) | f.Optional(default=100), }, allow_missing_keys={ 'threshold', }, )
def __init__(self): super(GetBalancesRequestFilter, self).__init__( { 'addresses': (f.Required | f.Array | f.FilterRepeater(f.Required | Trytes(result_type=Address))), 'threshold': (f.Type(int) | f.Min(0) | f.Max(100) | f.Optional(default=100)), }, allow_missing_keys={ 'threshold', }, )
def test_pass_default(self): """ The incoming value does not match any of the switch cases, but we defined a default filter. """ self.assertFilterPasses( self._filter( { 'name': 'negative', 'value': -42 }, getter=lambda value: value['name'], cases={ 'positive': f.FilterMapper({'value': f.Int | f.Min(0)}), }, default=f.FilterMapper({'value': f.Int | f.Max(0)}), ), )