def test_traverse_changed(self): calls = [] op = (lambda dt: calls.append(dt) or str) mapping = Mapping(ANY) transformed = mapping.traverse(op) self.assertIsNot(transformed, mapping) self.assertEqual(transformed, Mapping(str)) self.assertEqual(calls, [ str, ANY, ])
def test_normalize_datatype(self): class Spam: @classmethod def normalize(cls): return OKAY OKAY = object() NOOP = object() param = SimpleParameter(str) tests = [ # explicitly handled (REF, TYPE_REFERENCE), (TYPE_REFERENCE, NOOP), (ANY, NOOP), (None, NOOP), (int, NOOP), (str, NOOP), (bool, NOOP), (Enum(str, ('spam', )), NOOP), (Union(str, int), NOOP), ({str, int}, Union(str, int)), (frozenset([str, int]), Union(str, int)), (Array(str), NOOP), ([str], Array(str)), ((str, ), Array(str)), (Mapping(str), NOOP), ({ str: str }, Mapping(str)), # others (Field('spam'), NOOP), (Fields(Field('spam')), NOOP), (param, NOOP), (DatatypeHandler(str), NOOP), (Arg(param, 'spam'), NOOP), (SimpleParameter(str), NOOP), (UnionParameter(Union(str)), NOOP), (ArrayParameter(Array(str)), NOOP), (ComplexParameter(Fields()), NOOP), (NOT_SET, NOOP), (object(), NOOP), (object, NOOP), (type, NOOP), (Spam, OKAY), ] for datatype, expected in tests: if expected is NOOP: expected = datatype with self.subTest(datatype): datatype = _normalize_datatype(datatype) self.assertEqual(datatype, expected)
def test_as_data_simple(self): raw = {'a': 1, 'b': 2, 'c': 3} param = MappingParameter(Mapping(int)) handler = param.match_type(raw) data = handler.as_data(raw) self.assertEqual(data, raw)
def test_match_type_match(self): param = MappingParameter(Mapping(int)) expected = MappingParameter.HANDLER(Mapping(int)) values = [ { 'a': 1, 'b': 2, 'c': 3 }, {}, ] for value in values: with self.subTest(value): handler = param.match_type(value) self.assertEqual(handler, expected)
def test_normalized(self): tests = [ (REF, TYPE_REFERENCE), ({str, int}, Union(str, int)), (frozenset([str, int]), Union(str, int)), ([str], Array(str)), ((str, ), Array(str)), ({ str: str }, Mapping(str)), (None, None), ] for datatype, expected in tests: with self.subTest(datatype): mapping = Mapping(datatype) self.assertEqual(mapping, Mapping(expected))
def test_traverse_noop(self): calls = [] op = (lambda dt: calls.append(dt) or dt) mapping = Mapping(Union(str, int)) transformed = mapping.traverse(op) self.assertIs(transformed, mapping) self.assertCountEqual( calls, [ str, # Note that it did not recurse into Union(str, int). Union(str, int), ])
def test_normalized_transformed(self): calls = 0 class Spam: @classmethod def traverse(cls, op): nonlocal calls calls += 1 return cls mapping = Mapping(Spam) self.assertIs(mapping.keytype, str) self.assertIs(mapping.valuetype, Spam) self.assertEqual(calls, 1)
def test_as_data_complicated(self): param = MappingParameter(Mapping(Union(int, Basic))) value = { 'a': 1, 'b': BASIC_FULL, 'c': 3, } handler = param.match_type(value) data = handler.as_data({ 'a': 1, 'b': Basic(name='spam', value='eggs'), 'c': 3, }) self.assertEqual(data, value)
def test_coerce_complicated(self): param = MappingParameter(Mapping(Union(int, Basic))) value = { 'a': 1, 'b': BASIC_FULL, 'c': 3, } handler = param.match_type(value) coerced = handler.coerce(value) self.assertEqual(coerced, { 'a': 1, 'b': Basic(name='spam', value='eggs'), 'c': 3, })
def test_coerce_simple(self): param = MappingParameter(Mapping(int)) values = [ { 'a': 1, 'b': 2, 'c': 3 }, {}, ] for value in values: with self.subTest(value): handler = param.match_type(value) coerced = handler.coerce(value) self.assertEqual(coerced, value)
def test_match_type_no_match(self): param = MappingParameter(Mapping(int)) values = [ { 'a': 1, 'b': '2', 'c': 3 }, [('a', 1), ('b', 2), ('c', 3)], 'spam', ] for value in values: with self.subTest(value): handler = param.match_type(value) self.assertIs(handler, None)
def test_normalized(self): tests = [ (REF, TYPE_REFERENCE), ({str, int}, Union(*{str, int})), (frozenset([str, int]), Union(*frozenset([str, int]))), ([str], Array(str)), ((str, ), Array(str)), ({ str: str }, Mapping(str)), (None, None), ] for datatype, expected in tests: with self.subTest(datatype): union = Union(int, datatype, str) self.assertEqual(union, Union(int, expected, str))
def test_normalized(self): tests = [ (REF, TYPE_REFERENCE), ({str, int}, Union(str, int)), (frozenset([str, int]), Union(str, int)), ([str], Array(str)), ((str, ), Array(str)), ({ str: str }, Mapping(str)), (None, None), ] for datatype, expected in tests: with self.subTest(datatype): fields = Fields(Field('spam', datatype), ) self.assertEqual(fields, [ Field('spam', expected), ])
def test_transform_datatype_container(self): class Spam(FieldsNamespace): FIELDS = [Field('a'), Field('b', {str: str})] fields = Fields(Field('...')) field_spam = Field('spam', ANY) field_ham = Field('ham', Union(Array(Spam), )) field_eggs = Field('eggs', Array(TYPE_REFERENCE)) nested = Fields( Field('???', fields), field_spam, field_ham, field_eggs, ) tests = { Array(str): [ Array(str), str, ], Field('...'): [ Field('...'), str, ], fields: [ fields, Field('...'), str, ], nested: [ nested, # ... Field('???', fields), fields, Field('...'), str, # ... Field('spam', ANY), ANY, # ... field_ham, Union(Array(Spam)), Array(Spam), Spam, Field('a'), str, Field('b', Mapping(str)), Mapping(str), str, str, # ... field_eggs, Array(TYPE_REFERENCE), TYPE_REFERENCE, ], } self.maxDiff = None for datatype, expected in tests.items(): calls = [] op = (lambda dt: calls.append(dt) or dt) with self.subTest(datatype): transformed = _transform_datatype(datatype, op) self.assertIs(transformed, datatype) self.assertEqual(calls, expected) # Check Union separately due to set iteration order. calls = [] op = (lambda dt: calls.append(dt) or dt) datatype = Union(str, int) transformed = _transform_datatype(datatype, op) self.assertIs(transformed, datatype) self.assertEqual(calls[0], Union(str, int)) self.assertEqual(set(calls[1:]), {str, int})
def test_validate(self): raw = {'a': 1, 'b': 2, 'c': 3} param = MappingParameter(Mapping(int)) handler = param.match_type(raw) handler.validate(raw)