def test_match_type_mixed(self): datatype = Union( str, # XXX add dedicated enums Enum(int, (1, 2, 3)), Basic, Array(str), Array(int), Union(int, bool), ) param = UnionParameter(datatype) tests = [ ('spam', SimpleParameter.HANDLER(str)), (2, EnumParameter.HANDLER(int, (1, 2, 3))), (BASIC_FULL, ComplexParameter(Basic).match_type(BASIC_FULL)), (['spam'], ArrayParameter.HANDLER(Array(str))), ([], ArrayParameter.HANDLER(Array(str))), ([10], ArrayParameter.HANDLER(Array(int))), (10, SimpleParameter.HANDLER(int)), (True, SimpleParameter.HANDLER(bool)), # no match (Integer(2), None), ([True], None), ({}, None), ] for value, expected in tests: with self.subTest(value): handler = param.match_type(value) self.assertEqual(handler, expected)
def test_transform_datatype_simple(self): datatypes = [ REF, TYPE_REFERENCE, ANY, None, int, str, bool, {str, int}, frozenset([str, int]), [str], (str, ), Parameter(object()), DatatypeHandler(str), Arg(SimpleParameter(str), 'spam'), SimpleParameter(str), UnionParameter(Union(str, int)), ArrayParameter(Array(str)), ComplexParameter(Fields()), NOT_SET, object(), object, type, ] for expected in datatypes: transformed = [] op = (lambda dt: transformed.append(dt) or dt) with self.subTest(expected): datatype = _transform_datatype(expected, op) self.assertIs(datatype, expected) self.assertEqual(transformed, [expected])
def test_supported(self): handler = DatatypeHandler(str) tests = [ (Parameter(str), Parameter(str)), (handler, Parameter(str, handler)), (Fields(Field('spam')), ComplexParameter(Fields(Field('spam')))), (Field('spam'), SimpleParameter(str)), (Field('spam', str, enum={'a'}), EnumParameter(str, {'a'})), (ANY, NoopParameter()), (None, SingletonParameter(None)), (str, SimpleParameter(str)), (int, SimpleParameter(int)), (bool, SimpleParameter(bool)), (Enum(str, {'a'}), EnumParameter(str, {'a'})), (Union(str, int), UnionParameter(Union(str, int))), ({str, int}, UnionParameter(Union(str, int))), (frozenset([str, int]), UnionParameter(Union(str, int))), (Array(str), ArrayParameter(Array(str))), ([str], ArrayParameter(Array(str))), ((str, ), ArrayParameter(Array(str))), (Basic, ComplexParameter(Basic)), ] for datatype, expected in tests: with self.subTest(datatype): param = param_from_datatype(datatype) self.assertEqual(param, expected)
def test_match_type_strict_no_match(self): tests = { str: String('spam'), int: Integer(10), } for datatype, value in tests.items(): with self.subTest(datatype): param = SimpleParameter(datatype, strict=True) handler = param.match_type(value) self.assertIs(handler, None)
def test_match_type_strict_match(self): tests = { str: 'spam', int: 10, bool: True, } for datatype, value in tests.items(): with self.subTest(datatype): param = SimpleParameter(datatype, strict=True) handler = param.match_type(value) self.assertIs(handler.datatype, datatype)
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_match_type_match(self): tests = [ (str, 'spam'), (str, String('spam')), (int, 10), (bool, True), ] for datatype, value in tests: with self.subTest((datatype, value)): param = SimpleParameter(datatype, strict=False) handler = param.match_type(value) self.assertIs(handler.datatype, datatype)
def test_match_type_catchall(self): NOOP = DatatypeHandler(ANY) param = UnionParameter(Union(int, str, ANY)) tests = [ ('spam', SimpleParameter.HANDLER(str)), (10, SimpleParameter.HANDLER(int)), # catchall (BASIC_FULL, NOOP), (['spam'], NOOP), (True, NOOP), (Integer(2), NOOP), ([10], NOOP), ({}, NOOP), ] for value, expected in tests: with self.subTest(value): handler = param.match_type(value) self.assertEqual(handler, expected)
def test_validate_valid(self): tests = { str: 'spam', int: 10, bool: True, } for datatype, value in tests.items(): with self.subTest(datatype): handler = SimpleParameter.HANDLER(datatype) handler.validate(value)
def test_match_type_no_match(self): tests = [ (int, 'spam'), # coercible (str, 10), (int, 10.0), (int, '10'), (bool, 1), # semi-coercible (str, b'spam'), (int, 10 + 0j), (int, b'\10'), ] for datatype, value in tests: with self.subTest((datatype, value)): param = SimpleParameter(datatype, strict=False) handler = param.match_type(value) self.assertIs(handler, None)
def test_coerce(self): tests = [ (str, 'spam', 'spam'), (str, String('spam'), 'spam'), (int, 10, 10), (bool, True, True), # did not match, but still coercible (str, 10, '10'), (str, str, "<class 'str'>"), (int, 10.0, 10), (int, '10', 10), (bool, 1, True), ] for datatype, value, expected in tests: with self.subTest((datatype, value)): handler = SimpleParameter.HANDLER(datatype) coerced = handler.coerce(value) self.assertEqual(coerced, expected)
def test_validate_invalid(self): tests = [ (int, 'spam'), # coercible (str, String('spam')), (str, 10), (int, 10.0), (int, '10'), (bool, 1), # semi-coercible (str, b'spam'), (int, 10 + 0j), (int, b'\10'), ] for datatype, value in tests: with self.subTest((datatype, value)): handler = SimpleParameter.HANDLER(datatype) with self.assertRaises(ValueError): handler.validate(value)
def test_as_data(self): tests = [ (str, 'spam'), (int, 10), (bool, True), # did not match, but still coercible (str, String('spam')), (str, 10), (str, str), (int, 10.0), (int, '10'), (bool, 1), # semi-coercible (str, b'spam'), (int, 10 + 0j), (int, b'\10'), ] for datatype, value in tests: with self.subTest((datatype, value)): handler = SimpleParameter.HANDLER(datatype) data = handler.as_data(value) self.assertIs(data, value)