class MagicString(Annotable): foo = Argument(str) bar = Argument(bool) baz = Argument(int) def __eq__(self, other): return self.args == other.args
def test_argument(validator, expected): arg = Argument(validator) # test coercion assert arg.validate(3) == expected # syntactic sugar assert arg(3) == expected
def test_argument_raise_on_missing_value(): validator = Argument(lambda x: x) expected_msg = "missing 1 required positional argument" with pytest.raises(TypeError, match=expected_msg): validator() expected_msg = "got an unexpected keyword argument 'name'" with pytest.raises(TypeError, match=expected_msg): validator(name='mandatory')
def test_argument_raise_on_missing_value(): arg = Argument(lambda x: x) expected_msg = 'Missing required value for argument' with pytest.raises(TypeError, message=expected_msg): arg.validate() expected_msg = 'Missing required value for argument `mandatory`' with pytest.raises(TypeError, message=expected_msg): arg.validate(name='mandatory')
class StringJoin(StringOp): __slots__ = ('_memoize', ) # new slot sep = Argument(str) # new overridden slot
class IntBinop(Annotable): left = Argument(int) right = Argument(int)
def test_invalid_arity_validator(): arg = Argument(lambda x, y: x + y) with pytest.raises(TypeError): arg('value')
class MagicString(StringOp): foo = Argument(str) bar = Argument(bool) baz = Argument(int)
class ValueOp(Op): arg = Argument(object)
class B(Annotable): b = Argument(int)
class UDAF(UDF, Reduction): arity = Argument(int)
class StringSplit(StringOp): sep = Argument(str) # inherit
class StringJoin(StringOp): __slots__ = '_memoize', # override sep = Argument(str)
class StringOp(Op): arg = Argument(str) # inherit
class FloatAddClip(FloatAddRhs): left = Argument(float) clip_lower = Argument(int, default=0) clip_upper = Argument(int, default=10)
class FloatAddRhs(IntBinop): right = Argument(float)
class ValueOp(Annotable): arg = Argument(object)
def test_optional_argument(default, expected): arg = Argument(lambda x: x, default=default) assert arg.validate() == expected assert arg() == expected
class UDF(ValueOp): func = Argument(lambda fn, this: fn)
validator(name='mandatory') @pytest.mark.parametrize( ('default', 'expected'), [(None, None), (0, 0), ('default', 'default'), (lambda: 3, 3)], ) def test_optional_argument(default, expected): validator = Optional(lambda x: x, default=default) assert validator(None) == expected @pytest.mark.parametrize( ('validator', 'value', 'expected'), [ (Argument(identity, default=None), None, None), (Argument(identity, default=None), 'three', 'three'), (Argument(identity, default=1), None, 1), (Argument(identity, default=lambda: 8), 'cat', 'cat'), (Argument(identity, default=lambda: 8), None, 8), (Argument(int, default=11), None, 11), (Argument(int, default=None), None, None), (Argument(int, default=None), 18, 18), (Argument(str, default=None), 'caracal', 'caracal'), ], ) def test_valid_optional(validator, value, expected): assert validator(value) == expected @pytest.mark.parametrize(
class A(Annotable): a = Argument(int)
class Between(Annotable): value = Argument(int) lower = Argument(int, default=0) upper = Argument(int, default=None)
class AB(A, B): ab = Argument(int)
class Op(Annotable): __slots__ = ('_cache', ) # first definition arg = Argument(lambda x: x)
class StringOp(ValueOp): arg = Argument(str)
def test_signature_equals(): s1 = TypeSignature([ ('left', Argument(int)), ('right', Argument(int)) ]) s2 = TypeSignature([ ('left', Argument(int)), ('right', Argument(int)) ]) s3 = TypeSignature([ ('left', Argument(int)), ('right', Argument(float)) ]) s4 = TypeSignature([ ('left', Argument(int)), ('right', Argument(float)) ]) s5 = TypeSignature([ ('left_one', Argument(int)), ('right', Argument(float)) ]) s6 = TypeSignature([ ('left_one', Argument(int)), ('right', Argument(int)) ]) assert s1 == s2 assert s3 == s4 assert s1 != s3 assert s2 != s4 assert s1 != s5 assert s2 != s6 assert s5 != s6
def test_invalid_validator(validator): with pytest.raises(TypeError): Argument(validator)
class StringSplit(StringOp): sep = Argument(str) # new slot
class StringOp(Op): arg = Argument(str) # new overridden slot
def test_signature_inheritance(): class IntBinop(Annotable): left = Argument(int) right = Argument(int) class FloatAddRhs(IntBinop): right = Argument(float) class FloatAddClip(FloatAddRhs): left = Argument(float) clip_lower = Argument(int, default=0) clip_upper = Argument(int, default=10) class IntAddClip(FloatAddClip, IntBinop): pass assert IntBinop.signature == TypeSignature([ ('left', Argument(int)), ('right', Argument(int)) ]) assert FloatAddRhs.signature == TypeSignature([ ('left', Argument(int)), ('right', Argument(float)) ]) assert FloatAddClip.signature == TypeSignature([ ('left', Argument(float)), ('right', Argument(float)), ('clip_lower', Argument(int, default=0)), ('clip_upper', Argument(int, default=10)) ]) assert IntAddClip.signature == TypeSignature([ ('left', Argument(int)), ('right', Argument(int)), ('clip_lower', Argument(int, default=0)), ('clip_upper', Argument(int, default=10)) ])