Example #1
0
def test_hash_and_range_key_success(model, index, range_condition_lambda):
    """AND(hash, range) + AND(range, hash) for valid hash and range key conditions"""
    hash_condition = (index or model.Meta).hash_key == "value"
    range_condition = range_condition_lambda(
        column=(index or model.Meta).range_key)
    validate_key_condition(model, index,
                           AndCondition(hash_condition, range_condition))
    validate_key_condition(model, index,
                           AndCondition(range_condition, hash_condition))
Example #2
0
def test_and_bad_range_key(model, index, range_condition_lambda):
    """AND with valid hash range condition but bad hash key condition"""
    hash_condition = (index or model.Meta).hash_key == "value"
    range_condition = range_condition_lambda(column=(index or model.Meta).range_key)

    with pytest.raises(InvalidKeyCondition):
        validate_key_condition(model, index, AndCondition(hash_condition, range_condition))
    with pytest.raises(InvalidKeyCondition):
        validate_key_condition(model, index, AndCondition(range_condition, hash_condition))
Example #3
0
def test_and_bad_hash_key(model, index, range_condition_lambda):
    """AND with valid range key condition but bad hash key condition"""
    hash_condition = (index or model.Meta).hash_key.between("bad", "condition")
    range_condition = range_condition_lambda(column=(index or model.Meta).range_key)

    with pytest.raises(InvalidKeyCondition):
        validate_key_condition(model, index, AndCondition(hash_condition, range_condition))
    with pytest.raises(InvalidKeyCondition):
        validate_key_condition(model, index, AndCondition(range_condition, hash_condition))
Example #4
0
def test_and_both_and():
    """(a & b) & (c & d) -> (a & b & c & d)"""
    a, b, c, d = [condition_for(">") for _ in range(4)]
    left = AndCondition(a, b)
    right = AndCondition(c, d)

    assert (left & right).operation == "and"

    assert (left & right).values == [a, b, c, d]
    assert (right & left).values == [c, d, a, b]
Example #5
0
def test_iand_both_and():
    """other's conditions are appended to self's conditions"""
    a, b, c, d = [condition_for(">") for _ in range(4)]
    left = AndCondition(a, b)
    right = AndCondition(c, d)

    original_left = left
    left &= right
    assert left is original_left
    assert left.values == [a, b, c, d]
    assert right.values == [c, d]
Example #6
0
def test_and_both_same_key(model, index, key_name):
    """AND with 2 conditions, but both conditions are on the same key"""
    key_column = getattr(index or model.Meta, key_name)
    condition = key_column == "value"
    key = AndCondition(condition, condition)
    with pytest.raises(InvalidSearch):
        validate_key_condition(model, index, key)
Example #7
0
def conditions_for(classes, include=None, exclude=None):
    """Returns lambdas that take column"""
    value = "value"
    values = ["0", "1", "2"]
    condition_lambdas = []
    if BeginsWithCondition in classes:
        condition_lambdas.append(
            lambda column: BeginsWithCondition(column, value))
    if BetweenCondition in classes:
        condition_lambdas.append(
            lambda column: BetweenCondition(column, values[0], values[1]))
    if ComparisonCondition in classes:
        condition_lambdas.extend(
            comparisons_for(include=include, exclude=exclude))
    if Condition in classes:
        condition_lambdas.append(lambda column: Condition())
    if ContainsCondition in classes:
        condition_lambdas.append(
            lambda column: ContainsCondition(column, value))
    if InCondition in classes:
        condition_lambdas.append(lambda column: InCondition(column, values))

    # Meta Conditions
    if AndCondition in classes:
        condition_lambdas.append(
            lambda column: AndCondition(column == value, column != value))
    if OrCondition in classes:
        condition_lambdas.append(
            lambda column: OrCondition(column == value, column != value))
    if NotCondition in classes:
        condition_lambdas.append(lambda column: NotCondition(column == value))

    return condition_lambdas
Example #8
0
def conditions_for(*operations, column=None):
    column = column or MockColumn("c")
    value = 0
    values = [1, 2]
    conditions = []
    if None in operations:
        conditions.append(Condition())
    if "and" in operations:
        left = ComparisonCondition("==", column, value)
        right = ComparisonCondition("!=", column, value)
        conditions.append(AndCondition(left, right))
    if "or" in operations:
        left = ComparisonCondition("==", column, value)
        right = ComparisonCondition("!=", column, value)
        conditions.append(OrCondition(left, right))
    if "not" in operations:
        inner = ComparisonCondition("==", column, value)
        conditions.append(NotCondition(inner))
    if "begins_with" in operations:
        conditions.append(BeginsWithCondition(column, value))
    if "between" in operations:
        conditions.append(BetweenCondition(column, *values))
    if "contains" in operations:
        conditions.append(ContainsCondition(column, value))
    if "in" in operations:
        conditions.append(InCondition(column, values))
    for operation in ("<", "<=", ">", ">=", "!=", "=="):
        if operation in operations:
            conditions.append(ComparisonCondition(operation, column, value))
    return conditions
Example #9
0
def empty_conditions():
    return [
        Condition(),
        AndCondition(),
        OrCondition(),
        NotCondition(Condition())
    ]
Example #10
0
def test_len_unpack_not():
    """Even though not(not(x)) -> x shouldn't exist, its length should be the inner length"""
    lt, gt = conditions_for("<", ">")
    outer = NotCondition(lt)
    condition = NotCondition(outer)
    assert len(condition) == len(outer) == 1

    # Swap inner for an AND with length 2
    and_ = AndCondition(lt, gt)
    outer.values[0] = and_
    assert len(condition) == len(outer) == len(and_) == 2
Example #11
0
def test_and_simplifies(other):
    """When only one condition is an and, the other is put in a new and, in the correct place
    (a & b) & (c > 2) -> (a & b & (c > 2))
    (a > 2) & (b & c) -> ((a > 2) & b & c)
    """
    a, b, = [condition_for(">"), condition_for("<")]
    and_condition = AndCondition(a, b)

    assert (and_condition & other).operation == "and"

    assert (and_condition & other).values == [a, b, other]
    assert (other & and_condition).values == [other, a, b]
Example #12
0
def test_iand_simplifies(other):
    """Similar to and, other value is pushed into the and (on LHS) or front of a new and (on RHS)"""
    a, b, = [condition_for(">"), condition_for("<")]
    and_condition = AndCondition(a, b)

    original_other = other
    other &= and_condition
    assert other is not original_other
    assert other.values == [original_other, a, b]

    original_and_condition = and_condition
    and_condition &= original_other
    assert and_condition is original_and_condition
    assert and_condition.values == [a, b, original_other]
Example #13
0
def test_len_cyclic():
    """Cyclic conditions count the cyclic reference"""
    # Here's the structure to create:
    #   root
    #  /    \
    # a      b
    #      /   \
    #     c   root
    root = AndCondition()
    a = ComparisonCondition("<", MockColumn("a"), 3)
    b = OrCondition()
    c = ComparisonCondition(">", MockColumn("c"), 3)
    root.values.extend([a, b])
    b.values.extend([c, root])

    assert len(root) == 4
Example #14
0
def test_iter_conditions_cyclic():
    """Cyclic conditions can be iterated safely"""
    # Here's the structure to create:
    #   root
    #  /    \
    # a      b
    #      /   \
    #     c   root
    root = AndCondition()
    a = ComparisonCondition("<", MockColumn("a"), 3)
    b = OrCondition()
    c = ComparisonCondition(">", MockColumn("c"), 3)
    root.values.extend([a, b])
    b.values.extend([c, root])

    expected = {root, a, b, c}
    actual = set(iter_conditions(root))
    assert actual == expected
Example #15
0
def test_and_not_two(model, index, count):
    """AND on hash+range fails if there aren't exactly 2 key conditions"""
    hash_key_column = (index or model.Meta).hash_key
    key = AndCondition(*[hash_key_column == "value"] * count)
    with pytest.raises(InvalidSearch):
        validate_key_condition(model, index, key)
Example #16
0
    assert a.values == [original_a, original_b]

    b |= original_a
    assert b is not original_b
    assert b.operation == "or"
    assert b.values == [original_b, original_a]


# CONDITIONS REPR ==================================================================================== CONDITIONS REPR


@pytest.mark.parametrize(
    "condition, expected",
    [
        # and
        (AndCondition(), "( & )"),
        (AndCondition("foo"), "('foo' &)"),
        (AndCondition("a", "b", "c"), "('a' & 'b' & 'c')"),

        # or
        (OrCondition(), "( | )"),
        (OrCondition("foo"), "('foo' |)"),
        (OrCondition("a", "b", "c"), "('a' | 'b' | 'c')"),

        # not
        (NotCondition("a"), "(~'a')"),

        # comparisons
        (ComparisonCondition("<", column=c, value=3), "(M.c < 3)"),
        (ComparisonCondition(">", column=c, value=3), "(M.c > 3)"),
        (ComparisonCondition("<=", column=c, value=3), "(M.c <= 3)"),