def test_invalid(): @validate_inputs(a=2) def wrapper(a): return f(a) msg = "Validator must either be a shortcut, callable, or type" assert_raises(TypeError, msg, wrapper, 1)
def test_del_item(self): d = FrozenDict({1: 2}) del d[1] assert len(d) == 0 assert_raises(KeyError, None, d.__delitem__, 1)
def test_invalid_output_stack(): @validate_inputs(a=int) @validate_outputs(1, 1) def wrapper(a): return a - 1 msg = "Validator must either be a shortcut, callable, or type" assert_raises(TypeError, msg, wrapper, 1)
def test_callable(): @validate_outputs(None, lambda x: x == 1) def wrapper(a): return f(a) assert wrapper(1) == 1 msg = "Invalid value for variable" assert_raises(ValueError, msg, wrapper, 1.5)
def test_input_duplicate_variable(self): validator = ValidatedFunction(lambda x: x + 1) validator.update_input_validators(x=int) msg = "Validator\(s\) for input" assert_raises(ValueError, msg, validator.update_input_validators, x=float)
def test_number(self): @validate_inputs(a="number") def wrapper(a): return f(a) assert wrapper(1) == 0 msg = "Expected a number but got" assert_raises(TypeError, msg, wrapper, "foo") assert_raises(TypeError, msg, wrapper, [1, 2])
def test_negate(self): @validate_inputs(a="~number") def wrapper(a): return a assert wrapper("foo") == "foo" assert wrapper((1, 2, 3)) == (1, 2, 3) msg = "'number' passed when it shouldn't have" assert_raises(NegateFailure, msg, wrapper, 1)
def test_number(self): @validate_outputs(None, "number") def wrapper(a): return f(a) assert wrapper(1) == 1 assert wrapper(1.5) == 1.5 msg = "Expected a number but got" assert_raises(TypeError, msg, wrapper, "foo") assert_raises(TypeError, msg, wrapper, {1, 2})
def test_negate(self): @validate_outputs(-1, "~integer") def wrapper(a): return a assert wrapper(1.5) == 1.5 assert wrapper("foo") == "foo" assert wrapper((1, 2, 3)) == (1, 2, 3) msg = "'integer' passed when it shouldn't have" assert_raises(NegateFailure, msg, wrapper, 1)
def test_output_positive_count(self): @validate_outputs(2) def wrapper(a): if a == 1: return f(a), f(a) else: return f(a) assert wrapper(1) == (1, 1) msg = "items returned but got" assert_raises(ValueError, msg, wrapper, 2)
def test_multi_args(): @validate_inputs(a=int, b=lambda x: x == 1) def wrapper(a, b): return a + b assert wrapper(2, 1) == 3 msg = "Incorrect type for variable" assert_raises(TypeError, msg, wrapper, a="foo", b=1) msg = "Invalid value for variable" assert_raises(ValueError, msg, wrapper, a=1, b=2)
def test_no_match(): @validate_inputs(b=int) def wrapper(a): return f(a) assert wrapper(1) == 0 assert wrapper(1.5) == 0.5 # No argument matches, so raise whatever # error Python is raising natively. msg = "unsupported operand type" assert_raises(TypeError, msg, wrapper, "foo")
def test_set_item(self): d = FrozenDict() d[1] = 2 assert d[1] == 2 assert len(d) == 1 d[2] = 3 assert d[2] == 3 assert len(d) == 2 assert_raises(KeyError, None, d.__setitem__, 1, 3)
def test_output_negative_count_validators(self): @validate_outputs(-1, tuple) def wrapper(a): if a == 1: return f(a), f(a) else: return f(a) # Tuples are validated as is, and in this # case, we specifically check that we get # a tuple from the function. assert wrapper(1) == (1, 1) msg = "Incorrect type for variable" assert_raises(TypeError, msg, wrapper, 0)
def test_odd(self): @validate_inputs(a="odd") def wrapper(a): return f(a) assert wrapper(1) == 0 msg = "Expected an integer but got" assert_raises(TypeError, msg, wrapper, 1.0) assert_raises(TypeError, msg, wrapper, "foo") assert_raises(TypeError, msg, wrapper, (-1, 5)) msg = "Expected an odd integer" assert_raises(ValueError, msg, wrapper, 2) assert_raises(ValueError, msg, wrapper, 4)
def test_even(self): @validate_inputs(a="even") def wrapper(a): return f(a) assert wrapper(2) == 1 msg = "Expected an integer but got" assert_raises(TypeError, msg, wrapper, "foo") assert_raises(TypeError, msg, wrapper, (1,)) assert_raises(TypeError, msg, wrapper, 2.0) msg = "Expected an even integer" assert_raises(ValueError, msg, wrapper, 1) assert_raises(ValueError, msg, wrapper, 3)
def test_callable_exception(): msg = "input must be 1" def validate(a): if a != 1: raise ValueError(msg) @validate_inputs(a=validate) def wrapper(a): return f(a) assert wrapper(1) == 0 msg = "Failed validation for input 'a': " + msg assert_raises(ValueError, msg, wrapper, "foo") assert_raises(ValueError, msg, wrapper, 1.5)
def test_two_inputs(): @validate_inputs(a=int) @validate_inputs(b=int) def wrapper(a, b): return a + b assert wrapper(1, 2) == 3 assert wrapper(3, 14) == 17 assert wrapper(*(5, 17)) == 22 msg = "Incorrect type for variable" assert_raises(TypeError, msg, wrapper, "foo", 1) assert_raises(TypeError, msg, wrapper, 1, "foo") assert_raises(TypeError, msg, wrapper, "foo", "foo") assert_raises(TypeError, msg, wrapper, dict(), list()) assert_raises(TypeError, msg, wrapper, tuple([1, 3]), 4)
def test_two_outputs_append(): @validate_outputs(None, int) @validate_outputs(None, float) def wrapper(a): if a == 1: return float(a), a elif a == 0: return a, float(a) else: return float(a), float(a) assert wrapper(1) == (1.0, 1) msg = "Incorrect type for variable" assert_raises(TypeError, msg, wrapper, 0) assert_raises(TypeError, msg, wrapper, 2)
def test_numpy_dtypes(self): np = pytest.importorskip("numpy") dtypes = np.typecodes["AllInteger"] for dtype in dtypes: dtype = np.dtype(dtype).type shortcuts.check_integer(dtype(1)) # The integer check is strict. The # type must match, even if numerically # the number is an integer. msg = "Expected an integer but got" dtypes = (np.typecodes["AllFloat"] + np.typecodes["Complex"]) for dtype in dtypes: dtype = np.dtype(dtype).type assert_raises(TypeError, msg, shortcuts.check_integer, dtype(1))
def test_bad_arg_count(): @validate_inputs(a=int) def wrapper(a): return f(a) # We expect Python to handle incorrect # argument counts for us before validation. py3 = sys.version_info >= (3, 0) msg = ("takes 1 positional argument" if py3 else "takes exactly 1 argument") assert_raises(TypeError, msg, wrapper, 1, 1.5) msg = ("missing 1 required positional argument" if py3 else "takes exactly 1 argument") assert_raises(TypeError, msg, wrapper)
def test_even(self): @validate_outputs(None, "even") def wrapper(a): return f(a) assert wrapper(2) == 2 msg = "Expected an integer" assert_raises(TypeError, msg, wrapper, 1.5) assert_raises(TypeError, msg, wrapper, "foo") assert_raises(TypeError, msg, wrapper, [3, 4]) msg = "Expected an even integer" assert_raises(ValueError, msg, wrapper, 1)
def test_odd(self): @validate_outputs(None, "odd") def wrapper(a): return f(a) assert wrapper(1) == 1 msg = "Expected an integer" assert_raises(TypeError, msg, wrapper, 1.5) assert_raises(TypeError, msg, wrapper, "foo") assert_raises(TypeError, msg, wrapper, dict()) msg = "Expected an odd integer" assert_raises(ValueError, msg, wrapper, 2)
def test_negate_stack(): @validate_inputs(a="integer") @validate_inputs(b="~number") def wrapper(a, b): return a * b assert wrapper(2, "bar") == "barbar" assert wrapper(3, [1, 2]) == [1, 2, 1, 2, 1, 2] msg = "Expected an integer" assert_raises(TypeError, msg, wrapper, "foo", "bar") assert_raises(TypeError, msg, wrapper, [1, 2, 3], "bar") msg = "'number' passed when it shouldn't have" assert_raises(NegateFailure, msg, wrapper, 5, 5) assert_raises(NegateFailure, msg, wrapper, 5, 12.1)
def test_input_bad_exp_len(self): validator = ValidatedFunction(lambda x: x + 1) msg = "Expected an integer for expected output length" assert_raises(TypeError, msg, validator.update_exp_output_len, 1.0) assert_raises(TypeError, msg, validator.update_exp_output_len, "foo") validator = ValidatedFunction(lambda x: x + 1) msg = "Expected output length must be positive or -1" assert_raises(ValueError, msg, validator.update_exp_output_len, -2)
def test_kwargs(): @validate_inputs(a=int) def wrapper(a, **_): return f(a) assert wrapper(1) == 0 assert wrapper(1, b=5, c=2) == 0 msg = "Incorrect type for variable" assert_raises(TypeError, msg, wrapper, 1.5, b=2) assert_raises(TypeError, msg, wrapper, "foo", k="bar") assert_raises(TypeError, msg, wrapper, [], **dict(c=5, e="cat")) # We expect Python to handle duplicate # keyword arguments for us before validation. msg = "got multiple values for argument" assert_raises(TypeError, msg, wrapper, 1, a=1)
def test_callable_bool(): @validate_inputs(a=lambda x: x == 1) def wrapper(a): return f(a) assert wrapper(1) == 0 msg = "Invalid value for variable" assert_raises(ValueError, msg, wrapper, 1.5) assert_raises(ValueError, msg, wrapper, "foo") assert_raises(ValueError, msg, wrapper, dict())
def test_integer(self): @validate_inputs(a="integer") def wrapper(a): return f(a) assert wrapper(1) == 0 msg = "Expected an integer but got" assert_raises(TypeError, msg, wrapper, "foo") assert_raises(TypeError, msg, wrapper, 1.0) assert_raises(TypeError, msg, wrapper, (1,))
def test_integer(self): @validate_outputs(None, "integer") def wrapper(a): return f(a) assert wrapper(1) == 1 msg = "Expected an integer" assert_raises(TypeError, msg, wrapper, 1.5) assert_raises(TypeError, msg, wrapper, "foo") assert_raises(TypeError, msg, wrapper, [-1, -3])
def test_basic(): @validate_inputs(a=int) def wrapper(a): return f(a) assert wrapper(1) == 0 assert wrapper(9) == 8 msg = "Incorrect type for variable" assert_raises(TypeError, msg, wrapper, 1.5) assert_raises(TypeError, msg, wrapper, "foo") assert_raises(TypeError, msg, wrapper, [1, 2])