Example #1
0
def test_ExpressionAttributeNames_appends_references():

    mock_request = immutable(attributes=immutable({
        'keys': [],
        'values': [],
        'conditions': []
    }),
                             conditions=immutable({'references': ['state']}))

    result = args.ExpressionAttributeNames(mock_request)

    assert result == {'#state': 'state'}
Example #2
0
def test_AttributeDefinitions_does_not_duplicate_keys():
    mock_request = immutable(
        hash_key={
            'name': 'id',
            'type': 'S'
        },
        range_key={
            'name': 'contry',
            'type': 'S'
        },
        lsi=[dict(name='gs_index', range_key={
            'name': 'type',
            'type': 'S'
        })],
        gsi=[
            dict(name='gs_index',
                 hash_key={
                     'name': 'country',
                     'type': 'S'
                 },
                 range_key={
                     'name': 'status',
                     'type': 'S'
                 })
        ])

    result = [
        item.get('AttributeName')
        for item in args.AttributeDefinitions(mock_request)
    ]

    assert len([1 for key in result if key == 'country']) == 1
Example #3
0
def test_LocalSecondaryIndexes_result():
    mock_request = immutable(
        hash_key={
            'name': 'main_hash_key',
            'type': 'S'
        },
        lsi=[dict(
            name='gs_index',
            range_key={
                'name': 'type',
                'type': 'S'
            },
        )])

    expected = [{
        'IndexName':
        'gs_index',
        'KeySchema': [{
            'AttributeName': 'main_hash_key',
            'KeyType': 'HASH'
        }, {
            'AttributeName': 'type',
            'KeyType': 'RANGE'
        }],
        'Projection': {
            'ProjectionType': 'ALL'
        }
    }]

    result = args.LocalSecondaryIndexes(mock_request)

    assertObjectsEqual(result, expected)
Example #4
0
def Condition(expression, attributes, references=None):
    references = references or []
    return immutable({
        'expression': expression,
        'attributes': attributes,
        'references': references
    })
Example #5
0
def test_update_handles_deep_objects():

    original = immutable({'alpha': {'color': 23}, 'beta': 2, 'dalet': 4})

    result = update(original, alpha={'color': 10})

    assert original is not result
    assert result.get('alpha').get('color') == 10
Example #6
0
def test_update_returns_with_updates():

    original = immutable({'alpha': 1, 'beta': 2, 'dalet': 4})

    result = update(original, alpha=10)

    assert original is not result
    assert result.get('alpha') == 10
Example #7
0
def test_update_returns_new_instance():

    original = immutable({'alpha': 1, 'beta': 2, 'dalet': 4})

    result = update(original)

    assert original == result
    assert original is not result
Example #8
0
def test_db_passes_args():

    mock_client = {}
    mock_runner = lambda r, x: r
    mock_operation = immutable(name='mock', description={}, runner=mock_runner)

    db = dynofunc.db(mock_client)

    db(mock_operation)
Example #9
0
def test_condition_composition():

    cond = cand(
        attr('username').equals('sunshie'),
        cor(cand(attr('rank').gt(12),
                 attr('rank').lt(20)),
            cand(attr('kills').gt_or_eq(100),
                 attr('kills').lt_or_eq(1000))))

    mock_attributes = [
        immutable({
            'original': 'rank',
            'key': ':rank',
            'value': {
                "N": 12
            },
            'alias': 'rank',
            'func': None
        }),
        immutable({
            'original': 'kills',
            'key': ':kills',
            'value': {
                "N": 300
            },
            'alias': 'kills',
            'func': None
        }),
        immutable({
            'original': 'username',
            'key': ':username',
            'value': {
                "S": "sunshie"
            },
            'alias': 'username',
            'func': None
        })
    ]

    expected = '(username = :username) AND (((rank > :rank) AND (rank < :rank)) OR ((kills >= :kills) AND (kills <= :kills)))'

    result = cond.expression(mock_attributes)

    assert result == expected
Example #10
0
def Attr(equals, gt, lt, lt_or_eq, gt_or_eq, between, begins_with):
    return immutable({
        'equals': equals,
        'gt': gt,
        'lt': lt,
        'lt_or_eq': lt_or_eq,
        'gt_or_eq': gt_or_eq,
        'between': between,
        'begins_with': begins_with
    })
Example #11
0
def RequestTree(attributes, table_name, index_name, hash_key, range_key,
                conditions, gsi, lsi):
    return immutable({
        'attributes': attributes,
        'table_name': table_name,
        'index_name': index_name,
        'hash_key': hash_key,
        'range_key': range_key,
        'conditions': conditions,
        'gsi': gsi,
        'lsi': lsi
    })
Example #12
0
def test_immutable_raises_when_set():
    obj = immutable(x=2, y=23)

    with pytest.raises(TypeError):
        obj['x'] = 5

    with pytest.raises(TypeError):
        obj.x = 5

    with pytest.raises(TypeError):
        del obj['x']

    with pytest.raises(TypeError):
        del obj.x
Example #13
0
def table(db, table_name):

    def wrap_op(op):
        def call_op(*args, **kwargs):
            return db(op(table_name, *args, **kwargs))
        return call_op

    return immutable(
        add=wrap_op(add),
        create=wrap_op(create),
        delete=wrap_op(delete),
        describe=wrap_op(describe),
        find=wrap_op(find),
        query=wrap_op(query),
        update=wrap_op(update),
        scan=wrap_op(scan))
Example #14
0
def ExpressionAttributeNames(request: RequestTree):
    all_attributes = [
        *request.attributes.keys,
        *request.attributes.values,
        *request.attributes.conditions
    ]

    aliased_attributes = [attr for attr in all_attributes if attr.alias[0] == '#']

    if request.conditions is not None and request.conditions.references is not None:
        for ref in request.conditions.references:
            aliased_attributes.append(immutable({
                'alias': get_safe_alias(ref),
                'original': ref
            }))

    return { attr.alias: attr.original for attr in aliased_attributes }
Example #15
0
def test_condition_begins_with():
    cond = attr('state').begins_with('Ca')
    mock_attributes = [
        immutable({
            'original': 'state',
            'key': ':state',
            'value': {
                "S": 'California'
            },
            'alias': 'state',
            'func': None
        })
    ]

    result = cond.expression(mock_attributes)

    assert result == 'begins_with(state, :state)'
Example #16
0
def test_attribute_equals_condition():
    cond = attr('username').equals('sunshie')
    mock_attributes = [
        immutable({
            'original': 'username',
            'key': ':username',
            'value': {
                "S": "sunshie"
            },
            'alias': 'username',
            'func': None
        })
    ]

    result = cond.expression(mock_attributes)

    # username = :username
    # { ":username": { "S": "sunshie" } }
    assert result == 'username = :username'
Example #17
0
def Attribute(original, key, value, alias, func):
    """
    Parameters
    ----------
    original : str
        The orignial name the client passed us for the attribute.
        Should never change for later references

        Ex. { 'item': 'a' } => 'item'


    key : str
        The key we should use in expressions to refer to the value
        of this attribute

        Ex. { 'item': 'a' } => ':item'

    value : dict
        The typed value of the attribute. NOTE: The attribute name should
        be stripped out so only the object defining the value/type is stored
        here. Different operations will use this and some will need to set a
        custom key so here were only storing the value of the value/type tree

        Ex. { 'item': 'a' } => { 'S': 'a' }

    alias : str
        The name we should use when refering to the dynamodb _column_. Typically
        this will be the same as `original`. However, in the case of reserved attr
        names it will be updated to something dynamodb friendly

        Ex. { 'item': 'a' } => '#item'

    func : Function
        A func from `dynofunc.funcs` that should be called to modify the attr
    """
    return immutable({
        'original': original,
        'key': key,
        'value': value,
        'alias': alias,
        'func': func
    })
Example #18
0
def test_KeySchema_uses_hash_and_range():
    mock_request = immutable(hash_key={
        'name': 'id',
        'type': 'S'
    },
                             range_key={
                                 'name': 'type',
                                 'type': 'S'
                             })

    expected = [{
        'AttributeName': 'id',
        'KeyType': 'HASH'
    }, {
        'AttributeName': 'type',
        'KeyType': 'RANGE'
    }]

    result = args.KeySchema(mock_request)

    assertObjectsEqual(result, expected)
Example #19
0
def test_AttributeDefinitions_gets_all_keys():
    mock_request = immutable(
        hash_key={
            'name': 'id',
            'type': 'S'
        },
        range_key={
            'name': 'country',
            'type': 'S'
        },
        lsi=[dict(
            name='gs_index',
            range_key={
                'name': 'type',
                'type': 'S'
            },
        )],
        gsi=[
            dict(name='gs_index',
                 hash_key={
                     'name': 'username',
                     'type': 'S'
                 },
                 range_key={
                     'name': 'status',
                     'type': 'S'
                 })
        ])

    expected = ['id', 'type', 'username', 'status', 'country']

    result = [
        item.get('AttributeName')
        for item in args.AttributeDefinitions(mock_request)
    ]

    assert set(expected) == set(result)
Example #20
0
def test_GlobalSecondaryIndexes_result():
    mock_request = immutable(gsi=[
        dict(
            name='gs_index',
            hash_key={
                'name': 'other',
                'type': 'S'
            },
            range_key={
                'name': 'type',
                'type': 'S'
            },
        )
    ])

    expected = [{
        'IndexName':
        'gs_index',
        'KeySchema': [{
            'AttributeName': 'other',
            'KeyType': 'HASH'
        }, {
            'AttributeName': 'type',
            'KeyType': 'RANGE'
        }],
        'Projection': {
            'ProjectionType': 'ALL'
        },
        'ProvisionedThroughput': {
            'ReadCapacityUnits': 10,
            'WriteCapacityUnits': 10
        }
    }]

    result = args.GlobalSecondaryIndexes(mock_request)

    assertObjectsEqual(result, expected)
Example #21
0
def response(res):
    def get_items():
        items = res.get('Items', None)
        if items is not None and len(items) > 0:
            return [destructure_type_tree(item) for item in items]
        return None

    return immutable({
        'retries':
        lambda: res.get('ResponseMetadata', {}).get('RetryAttempts', None),
        'success':
        lambda: res.get('ResponseMetadata', {}).get('HTTPStatusCode', 0) ==
        200,
        'item':
        lambda: destructure_type_tree(res.get('Item', None)),
        'items':
        get_items,
        'count':
        lambda: res.get('Count', None),
        'scanned_count':
        lambda: res.get('ScannedCount', None),
        'raw':
        lambda: res
    })
Example #22
0
def Operation(description, runner):
    return immutable({'description': description, 'runner': runner})
Example #23
0
def test_immutable_none_comparison():
    obj = immutable(x=2, y=23)
    isEqual = obj == None
    assert isEqual is not True
Example #24
0
def test_immutable_repr_dumps_json():
    obj = immutable(x=2, y=23)
    r = repr(obj)
    json.loads(r)
Example #25
0
def test_immutable_str_dumps_json():
    obj = immutable(x=2, y=23)
    s = str(obj)
    json.loads(s)
Example #26
0
def Function(expression, value):
    return immutable({'expression': expression, 'value': value})
Example #27
0
def AttributeGroup(keys, values, conditions):
    return immutable({
        'keys': keys,
        'values': values,
        'conditions': conditions
    })