def test_default_allows_update_and_create(self):
        key = 'test', 'write_mode', 1
        self.keys.append(key)
        self.as_connection.put(key, {'map': {'existing': 'old'}})

        map_policy = {'map_write_mode': aerospike.MAP_UPDATE}
        ops = [
            map_ops.map_put('map', 'existing', 'new', map_policy=map_policy),
            map_ops.map_put('map', 'new', 'new', map_policy=map_policy),
        ]
        self.as_connection.operate(key, ops)

        _, _, bins = self.as_connection.get(key)

        map_bin = bins['map']
        assert map_bin['existing'] == 'new'
        assert map_bin['new'] == 'new'
    def test_default_allows_update_and_create(self):
        key = 'test', 'write_mode', 1
        self.keys.append(key)
        self.as_connection.put(key, {'map': {'existing': 'old'}})

        map_policy = {
            'map_write_mode': aerospike.MAP_UPDATE
        }
        ops = [
            map_ops.map_put('map', 'existing', 'new', map_policy=map_policy),
            map_ops.map_put('map', 'new', 'new', map_policy=map_policy),
        ]
        self.as_connection.operate(key, ops)

        _, _, bins = self.as_connection.get(key)

        map_bin = bins['map']
        assert map_bin['existing'] == 'new'
        assert map_bin['new'] == 'new'
    def test_default_allows_update_and_create(self):
        skip_less_than_430(self.server_version)
        key = 'test', 'write_flags', 1
        self.keys.append(key)
        self.as_connection.put(key, {'map': {'existing': 'old'}})

        map_policy = {
            'map_write_flags': aerospike.MAP_WRITE_FLAGS_DEFAULT
        }
        ops = [
            map_ops.map_put('map', 'existing', 'new', map_policy=map_policy),
            map_ops.map_put('map', 'new', 'new', map_policy=map_policy),
        ]
        self.as_connection.operate(key, ops)

        _, _, bins = self.as_connection.get(key)

        map_bin = bins['map']
        assert map_bin['existing'] == 'new'
        assert map_bin['new'] == 'new'
    def test_nofail_allows_an_op_to_fail_silently(self):
        skip_less_than_430(self.server_version)
        key = 'test', 'write_flags', 1
        self.keys.append(key)
        self.as_connection.put(key, {'map': {'existing': 'old'}})

        map_policy = {
            'map_write_flags': aerospike.MAP_WRITE_FLAGS_UPDATE_ONLY | aerospike.MAP_WRITE_FLAGS_NO_FAIL
        }
        ops = [
            map_ops.map_put('map', 'existing', 'new', map_policy=map_policy),
            map_ops.map_put('map', 'new', 'new', map_policy=map_policy),
        ]

        self.as_connection.operate(key, ops)

        _, _, bins = self.as_connection.get(key)

        map_bin = bins['map']
        assert map_bin['existing'] == 'new'
        assert 'new' not in map_bin
    def test_create_only_does_not_allow_update(self):
        key = 'test', 'write_mode', 1
        self.keys.append(key)
        self.as_connection.put(key, {'map': {'existing': 'old'}})

        map_policy = {'map_write_mode': aerospike.MAP_CREATE_ONLY}
        ops = [
            map_ops.map_put('map', 'existing', 'new', map_policy=map_policy),
        ]
        with pytest.raises(e.ElementExistsError):
            self.as_connection.operate(key, ops)

        _, _, bins = self.as_connection.get(key)

        map_bin = bins['map']
        assert map_bin['existing'] == 'old'
    def test_create_only_does_not_allow_update(self):
        key = 'test', 'write_mode', 1
        self.keys.append(key)
        self.as_connection.put(key, {'map': {'existing': 'old'}})

        map_policy = {
            'map_write_mode': aerospike.MAP_CREATE_ONLY
        }
        ops = [
            map_ops.map_put('map', 'existing', 'new', map_policy=map_policy),
        ]
        with pytest.raises(e.ElementExistsError):
            self.as_connection.operate(key, ops)

        _, _, bins = self.as_connection.get(key)

        map_bin = bins['map']
        assert map_bin['existing'] == 'old'
    def test_create_only_does_not_allow_update(self):
        skip_less_than_430(self.server_version)
        key = 'test', 'write_flags', 1
        self.keys.append(key)
        self.as_connection.put(key, {'map': {'existing': 'old'}})

        map_policy = {
            'map_write_flags': aerospike.MAP_WRITE_FLAGS_CREATE_ONLY
        }
        ops = [
            map_ops.map_put('map', 'existing', 'new', map_policy=map_policy),
        ]
        with pytest.raises(e.AerospikeError):
            self.as_connection.operate(key, ops)

        _, _, bins = self.as_connection.get(key)

        map_bin = bins['map']
        assert map_bin['existing'] == 'old'
 def test_map_put(self):
     operations =[map_ops.map_put(self.test_bin, "new", "map_put")]
     self.as_connection.operate(self.test_key, operations)
     res_map = self.as_connection.get(self.test_key)[2][self.test_bin]
     assert res_map["new"] == "map_put"
class TestPredEveryWhere(object):
    @pytest.fixture(autouse=True)
    def setup(self, request, as_connection):
        """
        Setup Method
        """
        self.keys = []
        self.test_data = [{
            'account_id': j,
            'user_name': 'user' + str(j),
            'acct_balance': j * 10,
            'charges': [j + 5, j + 10],
            'meta': {
                'date': '11/4/2019'
            }
        } for j in range(1, 5)]
        self.test_data.append({'string_list': ['s1', 's2', 's3', 's4']})
        self.test_data.append(
            {'map_bin': {
                'k1': 1,
                'k2': 2,
                'k3': 3,
                'k4': 4
            }})

        georec = {
            'id': 1,
            'point': geo_point,
            'region': geo_circle,
            'geolist': [geo_point]
        }

        self.test_data.append(georec)
        self.test_data_bin = 'test_data'
        self.keys = [('test', 'pred_evry', i + 1)
                     for i, _ in enumerate(self.test_data)]
        # print('self keys is: ', self.keys)

        for key, data in zip(self.keys, self.test_data):
            self.as_connection.put(key, data)

        # cleanup
        yield

        for key in self.keys:
            try:
                self.as_connection.remove(key)
            except e.AerospikeError:
                pass

    @pytest.mark.parametrize(
        "ops, predexp, expected_bins, expected_res, key_num",
        [
            (  # test integer equal
                [operations.increment("account_id", 1)], [
                    as_predexp.integer_bin('account_id'),
                    as_predexp.integer_value(3),
                    as_predexp.integer_equal()
                ], {
                    'account_id': 4,
                    'user_name': 'user3',
                    'acct_balance': 30,
                    'charges': [8, 13],
                    'meta': {
                        'date': '11/4/2019'
                    }
                }, {}, 3),
            (  # test string equal
                [operations.increment("account_id", 1)], [
                    as_predexp.string_bin('user_name'),
                    as_predexp.string_value('user3'),
                    as_predexp.string_equal()
                ], {
                    'account_id': 4,
                    'user_name': 'user3',
                    'acct_balance': 30,
                    'charges': [8, 13],
                    'meta': {
                        'date': '11/4/2019'
                    }
                }, {}, 3),
            (  # test and
                [
                    list_operations.list_remove_by_index_range(
                        'charges', 0, 3, aerospike.LIST_RETURN_COUNT),
                    operations.increment("acct_balance", -23)
                ], [
                    as_predexp.integer_bin('acct_balance'),
                    as_predexp.integer_value(10),
                    as_predexp.integer_greatereq(),
                    as_predexp.integer_bin('acct_balance'),
                    as_predexp.integer_value(50),
                    as_predexp.integer_lesseq(),
                    as_predexp.predexp_and(2)
                ], {
                    'account_id': 4,
                    'user_name': 'user4',
                    'acct_balance': 17,
                    'charges': [],
                    'meta': {
                        'date': '11/4/2019'
                    }
                }, {
                    'charges': [0, 1]
                }, 4),
            (  # test or
                [map_operations.map_put('meta', 'lupdated', 'now')], [
                    as_predexp.string_bin('user_name'),
                    as_predexp.string_value('user2'),
                    as_predexp.string_equal(),
                    as_predexp.integer_bin('acct_balance'),
                    as_predexp.integer_value(50),
                    as_predexp.integer_greatereq(),
                    as_predexp.predexp_or(2)
                ], {
                    'account_id': 2,
                    'user_name': 'user2',
                    'acct_balance': 20,
                    'charges': [7, 12],
                    'meta': {
                        'date': '11/4/2019',
                        'lupdated': 'now'
                    }
                }, {
                    'meta': 2
                }, 2),
            (  # test integer greater
                [map_operations.map_clear('meta')], [
                    as_predexp.integer_bin('account_id'),
                    as_predexp.integer_value(2),
                    as_predexp.integer_greater()
                ], {
                    'account_id': 3,
                    'user_name': 'user3',
                    'acct_balance': 30,
                    'charges': [8, 13],
                    'meta': {}
                }, {
                    'meta': None
                }, 3),
            (  # test integer greatereq
                [map_operations.map_clear('meta')], [
                    as_predexp.integer_bin('account_id'),
                    as_predexp.integer_value(2),
                    as_predexp.integer_greatereq()
                ], {
                    'account_id': 3,
                    'user_name': 'user3',
                    'acct_balance': 30,
                    'charges': [8, 13],
                    'meta': {}
                }, {
                    'meta': None
                }, 3),
            (  # test integer less
                [list_operations.list_clear('charges')], [
                    as_predexp.integer_bin('account_id'),
                    as_predexp.integer_value(5),
                    as_predexp.integer_less()
                ], {
                    'account_id': 4,
                    'user_name': 'user4',
                    'acct_balance': 40,
                    'charges': [],
                    'meta': {
                        'date': '11/4/2019'
                    }
                }, {}, 4),
            (  # test integer lesseq
                [list_operations.list_clear('charges')], [
                    as_predexp.integer_bin('account_id'),
                    as_predexp.integer_value(4),
                    as_predexp.integer_lesseq()
                ], {
                    'account_id': 4,
                    'user_name': 'user4',
                    'acct_balance': 40,
                    'charges': [],
                    'meta': {
                        'date': '11/4/2019'
                    }
                }, {}, 4),
            (  # test string unequal
                [list_operations.list_append('charges', 2)], [
                    as_predexp.string_bin('user_name'),
                    as_predexp.string_value('user2'),
                    as_predexp.string_unequal()
                ], {
                    'account_id': 4,
                    'user_name': 'user4',
                    'acct_balance': 40,
                    'charges': [9, 14, 2],
                    'meta': {
                        'date': '11/4/2019'
                    }
                }, {
                    'charges': 3
                }, 4),
            (  # test not
                [list_operations.list_append('charges', 2)], [
                    as_predexp.string_bin('user_name'),
                    as_predexp.string_value('user4'),
                    as_predexp.string_unequal(),
                    as_predexp.predexp_not()
                ], {
                    'account_id': 4,
                    'user_name': 'user4',
                    'acct_balance': 40,
                    'charges': [9, 14, 2],
                    'meta': {
                        'date': '11/4/2019'
                    }
                }, {
                    'charges': 3
                }, 4),
            (  # test string regex
                [list_operations.list_append('charges', 2)], [
                    as_predexp.string_bin('user_name'),
                    as_predexp.string_value('.*4.*'),
                    as_predexp.string_regex(aerospike.REGEX_ICASE)
                ], {
                    'account_id': 4,
                    'user_name': 'user4',
                    'acct_balance': 40,
                    'charges': [9, 14, 2],
                    'meta': {
                        'date': '11/4/2019'
                    }
                }, {
                    'charges': 3
                }, 4),
            (  # test list or int
                [list_operations.list_append('charges', 2)], [
                    as_predexp.integer_var('list_val'),
                    as_predexp.integer_value(14),
                    as_predexp.integer_equal(),
                    as_predexp.list_bin('charges'),
                    as_predexp.list_iterate_or('list_val')
                ], {
                    'account_id': 4,
                    'user_name': 'user4',
                    'acct_balance': 40,
                    'charges': [9, 14, 2],
                    'meta': {
                        'date': '11/4/2019'
                    }
                }, {
                    'charges': 3
                }, 4),
            (  # test list and int
                [list_operations.list_append('charges', 2)], [
                    as_predexp.integer_var('list_val'),
                    as_predexp.integer_value(120),
                    as_predexp.integer_less(),
                    as_predexp.list_bin('charges'),
                    as_predexp.list_iterate_or('list_val')
                ], {
                    'account_id': 4,
                    'user_name': 'user4',
                    'acct_balance': 40,
                    'charges': [9, 14, 2],
                    'meta': {
                        'date': '11/4/2019'
                    }
                }, {
                    'charges': 3
                }, 4),
            (  # test list or str
                [list_operations.list_append('string_list', 's5')], [
                    as_predexp.string_var('list_val'),
                    as_predexp.string_value('s2'),
                    as_predexp.string_equal(),
                    as_predexp.list_bin('string_list'),
                    as_predexp.list_iterate_or('list_val')
                ], {
                    'string_list': ['s1', 's2', 's3', 's4', 's5']
                }, {
                    'string_list': 5
                }, 5),
            (  # test list and str
                [
                    list_operations.list_remove_by_index_range(
                        'string_list', 0, aerospike.LIST_RETURN_VALUE, 2)
                ], [
                    as_predexp.string_var('list_val'),
                    as_predexp.string_value('.*s.*'),
                    as_predexp.string_regex(aerospike.REGEX_ICASE),
                    as_predexp.list_bin('string_list'),
                    as_predexp.list_iterate_and('list_val')
                ], {
                    'string_list': ['s3', 's4']
                }, {
                    'string_list': ['s1', 's2']
                }, 5),
            (  # test map_key_iterate_or
                [map_operations.map_put('map_bin', 'k5', 5)], [
                    as_predexp.string_var('map_key'),
                    as_predexp.string_value('k3'),
                    as_predexp.string_equal(),
                    as_predexp.map_bin('map_bin'),
                    as_predexp.mapkey_iterate_or('map_key')
                ], {
                    'map_bin': {
                        'k1': 1,
                        'k2': 2,
                        'k3': 3,
                        'k4': 4,
                        'k5': 5
                    }
                }, {
                    'map_bin': 5
                }, 6),
            (  # test map_key_iterate_and
                [map_operations.map_put('map_bin', 'k5', 5)], [
                    as_predexp.string_var('map_key'),
                    as_predexp.string_value('k7'),
                    as_predexp.string_unequal(),
                    as_predexp.map_bin('map_bin'),
                    as_predexp.mapkey_iterate_and('map_key')
                ], {
                    'map_bin': {
                        'k1': 1,
                        'k2': 2,
                        'k3': 3,
                        'k4': 4,
                        'k5': 5
                    }
                }, {
                    'map_bin': 5
                }, 6),
            (  # test mapkey_iterate_and
                [map_operations.map_put('map_bin', 'k5', 5)], [
                    as_predexp.string_var('map_key'),
                    as_predexp.string_value('k7'),
                    as_predexp.string_unequal(),
                    as_predexp.map_bin('map_bin'),
                    as_predexp.mapkey_iterate_and('map_key')
                ], {
                    'map_bin': {
                        'k1': 1,
                        'k2': 2,
                        'k3': 3,
                        'k4': 4,
                        'k5': 5
                    }
                }, {
                    'map_bin': 5
                }, 6),
            (  # test mapval_iterate_and
                [map_operations.map_put('map_bin', 'k5', 5)], [
                    as_predexp.integer_var('map_val'),
                    as_predexp.integer_value(7),
                    as_predexp.integer_unequal(),
                    as_predexp.map_bin('map_bin'),
                    as_predexp.mapval_iterate_and('map_val')
                ], {
                    'map_bin': {
                        'k1': 1,
                        'k2': 2,
                        'k3': 3,
                        'k4': 4,
                        'k5': 5
                    }
                }, {
                    'map_bin': 5
                }, 6),
            (  # test mapval_iterate_or
                [
                    map_operations.map_get_by_key('map_bin', 'k1',
                                                  aerospike.MAP_RETURN_VALUE)
                ], [
                    as_predexp.integer_var('map_val'),
                    as_predexp.integer_value(3),
                    as_predexp.integer_less(),
                    as_predexp.map_bin('map_bin'),
                    as_predexp.mapval_iterate_or('map_val')
                ], {
                    'map_bin': {
                        'k1': 1,
                        'k2': 2,
                        'k3': 3,
                        'k4': 4
                    }
                }, {
                    'map_bin': 1
                }, 6)
        ])
    def test_predexp_key_operate(self, ops, predexp, expected_bins,
                                 expected_res, key_num):
        """
        Invoke the C client aerospike_key_operate with predexp.
        """
        key = ('test', 'pred_evry', key_num)

        _, _, res = self.as_connection.operate(key,
                                               ops,
                                               policy={'predexp': predexp})
        assert res == expected_res

        _, _, bins = self.as_connection.get(key)
        assert bins == expected_bins

    @pytest.mark.parametrize(
        "ops, predexp, expected_bins, expected_res, key_num",
        [(  # test mapval_iterate_or
            [
                map_operations.map_put_items('map_bin', {
                    'k5': 5,
                    'k6': 6
                }),
                map_operations.map_get_by_key('map_bin', 'k1',
                                              aerospike.MAP_RETURN_VALUE)
            ], [
                as_predexp.integer_var('map_val'),
                as_predexp.integer_value(3),
                as_predexp.integer_less(),
                as_predexp.map_bin('map_bin'),
                as_predexp.mapval_iterate_or('map_val')
            ], {
                'map_bin': {
                    'k1': 1,
                    'k2': 2,
                    'k3': 3,
                    'k4': 4,
                    'k5': 5,
                    'k6': 6
                }
            }, [('map_bin', 6), ('map_bin', 1)], 6)])
    def test_predexp_key_operate_ordered(self, ops, predexp, expected_bins,
                                         expected_res, key_num):
        """
        Invoke the C client aerospike_key_operate with predexp using operate_ordered.
        """
        key = ('test', 'pred_evry', key_num)

        _, _, res = self.as_connection.operate_ordered(
            key, ops, policy={'predexp': predexp})
        assert res == expected_res

        _, _, bins = self.as_connection.get(key)
        assert bins == expected_bins

    @pytest.mark.parametrize(
        "ops, predexp, expected, key_num",
        [(  # test mapval_iterate_or
            [
                map_operations.map_get_by_key('map_bin', 'k1',
                                              aerospike.MAP_RETURN_VALUE)
            ], [
                as_predexp.integer_var('map_val'),
                as_predexp.integer_value(3),
                as_predexp.integer_less(),
                as_predexp.map_bin('map_bin'),
                as_predexp.mapval_iterate_or('map_val'),
                as_predexp.predexp_not()
            ], e.FilteredOut, 6)])
    def test_predexp_key_operate_ordered_negative(self, ops, predexp, expected,
                                                  key_num):
        """
        Invoke the C client aerospike_key_operate with predexp using operate_ordered with expected failures.
        """
        key = ('test', 'pred_evry', key_num)

        with pytest.raises(expected):
            _, _, res = self.as_connection.operate_ordered(
                key, ops, policy={'predexp': predexp})

    @pytest.mark.parametrize(
        "ops, predexp, key_num, bin",
        [
            (  # test geojson_within
                [operations.increment('id', 1)], [
                    as_predexp.geojson_bin('point'),
                    as_predexp.geojson_value(geo_circle.dumps()),
                    as_predexp.geojson_within()
                ], 7, 'point'),
            (  # test geojson_contains
                [operations.increment('id', 1)], [
                    as_predexp.geojson_bin('region'),
                    as_predexp.geojson_value(geo_point.dumps()),
                    as_predexp.geojson_contains()
                ], 7, 'point'),
        ])
    def test_predexp_key_operate_geojson(self, ops, predexp, key_num, bin):
        """
        Invoke the C client aerospike_key_operate with predexp.
        """
        key = ('test', 'pred_evry', key_num)

        _, _, _ = self.as_connection.operate(key,
                                             ops,
                                             policy={'predexp': predexp})

        _, _, bins = self.as_connection.get(key)
        assert bins['id'] == 2

    # NOTE: may fail due to clock skew
    def test_predexp_key_operate_record_last_updated(self):
        """
        Invoke the C client aerospike_key_operate with a record_last_updated predexp.
        """

        for i in range(5):
            key = 'test', 'pred_lut', i
            self.as_connection.put(key, {'time': 'earlier'})

        cutoff_nanos = (10**9) * int(time.time() + 2)
        time.sleep(5)

        for i in range(5, 10):
            key = 'test', 'pred_lut', i
            self.as_connection.put(key, {'time': 'later'})

        results = []

        predexp = [
            as_predexp.rec_last_update(),
            as_predexp.integer_value(cutoff_nanos),
            as_predexp.integer_less()
        ]

        ops = [operations.read('time')]

        for i in range(10):
            try:
                key = 'test', 'pred_lut', i
                _, _, res = self.as_connection.operate(
                    key, ops, policy={'predexp': predexp})
                results.append(res)
            except:
                pass
            self.as_connection.remove(key)

        assert len(results) == 5
        for res in results:
            assert res['time'] == 'earlier'

    # NOTE: may fail due to clock skew
    def test_predexp_key_operate_record_void_time(self):
        """
        Invoke the C client aerospike_key_operate with a rec_void_time predexp.
        """

        for i in range(5):
            key = 'test', 'pred_ttl', i
            self.as_connection.put(key, {'time': 'earlier'}, meta={'ttl': 100})

        # 150 second range for record TTLs should be enough, we are storing with
        # Current time + 100s and current time +5000s, so only one of the group should be found
        void_time_range_start = (10**9) * int(time.time() + 50)
        void_time_range_end = (10**9) * int(time.time() + 150)

        for i in range(5, 10):
            key = 'test', 'pred_ttl', i
            self.as_connection.put(key, {'time': 'later'}, meta={'ttl': 1000})

        results = []

        predexp = [
            as_predexp.rec_void_time(),
            as_predexp.integer_value(void_time_range_start),
            as_predexp.integer_greater(),
            as_predexp.rec_void_time(),
            as_predexp.integer_value(void_time_range_end),
            as_predexp.integer_less(),
            as_predexp.predexp_and(2)
        ]

        ops = [operations.read('time')]

        for i in range(10):
            try:
                key = 'test', 'pred_ttl', i
                _, _, res = self.as_connection.operate(
                    key, ops, policy={'predexp': predexp})
                results.append(res)
            except:
                pass
            self.as_connection.remove(key)

        assert len(results) == 5
        for res in results:
            assert res['time'] == 'earlier'

    def test_predexp_key_operate_record_digest_modulo(self):
        """
        Invoke the C client aerospike_key_operate with a rec_digest_modulo predexp.
        """

        less_than_128 = 0
        for i in range(100):
            key = 'test', 'demo', i
            if aerospike.calc_digest(*key)[-1] < 128:
                less_than_128 += 1
            self.as_connection.put(key, {'dig_id': i})

        results = []

        predexp = [
            as_predexp.rec_digest_modulo(256),
            as_predexp.integer_value(128),
            as_predexp.integer_less()
        ]

        ops = [operations.read('dig_id')]

        for i in range(100):
            try:
                key = 'test', 'demo', i
                _, _, res = self.as_connection.operate(
                    key, ops, policy={'predexp': predexp})
                results.append(res)
            except:
                pass
            self.as_connection.remove(key)

        assert len(results) == less_than_128

    @pytest.mark.parametrize(
        "ops, predexp, expected, key_num",
        [
            (  # filtered out
                [operations.increment("account_id", 1)], [
                    as_predexp.integer_bin('account_id'),
                    as_predexp.integer_value(5),
                    as_predexp.integer_equal()
                ], e.FilteredOut, 3),
            (  # incorrect bin type
                [
                    list_operations.list_remove_by_index_range(
                        'charges', 0, 3, aerospike.LIST_RETURN_COUNT),
                    operations.increment("acct_balance", -23)
                ],
                [
                    as_predexp.integer_bin('acct_balance'),
                    as_predexp.string_value(10),  #incorrect bin type
                    as_predexp.integer_greatereq(),
                    as_predexp.integer_bin('acct_balance'),
                    as_predexp.integer_value(50),
                    as_predexp.integer_lesseq(),
                    as_predexp.predexp_and(2)
                ],
                e.ParamError,
                4),
            (  # filtered out
                [map_operations.map_put('meta', 'lupdated', 'now')], [
                    as_predexp.string_bin('user_name'),
                    as_predexp.string_value('user2'),
                    as_predexp.string_equal(),
                    as_predexp.integer_bin('acct_balance'),
                    as_predexp.integer_value(50),
                    as_predexp.integer_greatereq(),
                    as_predexp.predexp_or(2),
                    as_predexp.predexp_not()
                ], e.FilteredOut, 2),
            (  # empty predexp list
                [map_operations.map_put('meta', 'lupdated', 'now')
                 ], [], e.InvalidRequest, 2),
            (  # predexp not in list
                [map_operations.map_put('meta', 'lupdated', 'now')
                 ], 'bad predexp', e.ParamError, 2),
        ])
    def test_predexp_key_operate_negative(self, ops, predexp, expected,
                                          key_num):
        """
        Invoke the C client aerospike_key_operate with predexp. Expecting failures.
        """
        key = ('test', 'pred_evry', key_num)

        with pytest.raises(expected):
            self.as_connection.operate(key, ops, policy={'predexp': predexp})

    @pytest.mark.parametrize("predexp, rec_place, rec_bin, expected",
                             [([
                                 as_predexp.integer_bin('account_id'),
                                 as_predexp.integer_value(2),
                                 as_predexp.integer_equal()
                             ], 1, 'account_id', 2),
                              ([
                                  as_predexp.string_bin('user_name'),
                                  as_predexp.string_value('user2'),
                                  as_predexp.string_equal(),
                              ], 1, 'account_id', 2),
                              ([
                                  as_predexp.string_bin('user_name'),
                                  as_predexp.string_value('user2'),
                                  as_predexp.string_equal(),
                                  as_predexp.integer_bin('acct_balance'),
                                  as_predexp.integer_value(30),
                                  as_predexp.integer_greatereq(),
                                  as_predexp.predexp_or(2)
                              ], 2, 'account_id', 3)])
    def test_pos_get_many_with_predexp(self, predexp, rec_place, rec_bin,
                                       expected):
        '''
        Proper call to get_many with predexp in policy
        '''
        records = self.as_connection.get_many(self.keys, {'predexp': predexp})

        #assert isinstance(records, list)
        # assert records[2][2]['age'] == 2
        assert records[rec_place][2][rec_bin] == expected

    def test_pos_get_many_with_large_predexp(self):
        '''
        Proper call to get_many with predexp in policy.
        '''
        predexp = [
            as_predexp.integer_bin('account_id'),
            as_predexp.integer_value(4),
            as_predexp.integer_equal(),
            as_predexp.string_bin('user_name'),
            as_predexp.string_value('user3'),
            as_predexp.string_equal(),
            as_predexp.integer_var('list_val'),
            as_predexp.integer_value(12),
            as_predexp.integer_less(),
            as_predexp.list_bin('charges'),
            as_predexp.list_iterate_and('list_val'),
            as_predexp.predexp_or(3)
        ]

        matched_recs = []
        records = self.as_connection.get_many(self.keys, {'predexp': predexp})
        for rec in records:
            if rec[2] is not None:
                matched_recs.append(rec[2])

        assert len(matched_recs) == 3
        for rec in matched_recs:
            assert rec['account_id'] == 1 or rec['account_id'] == 3 or rec[
                'account_id'] == 4

    def test_pos_select_many_with_large_predexp(self):
        '''
        Proper call to select_many with predexp in policy.
        '''
        predexp = [
            as_predexp.integer_bin('account_id'),
            as_predexp.integer_value(4),
            as_predexp.integer_equal(),
            as_predexp.string_bin('user_name'),
            as_predexp.string_value('user3'),
            as_predexp.string_equal(),
            as_predexp.integer_var('list_val'),
            as_predexp.integer_value(12),
            as_predexp.integer_less(),
            as_predexp.list_bin('charges'),
            as_predexp.list_iterate_and('list_val'),
            as_predexp.predexp_or(3)
        ]

        matched_recs = []
        records = self.as_connection.select_many(self.keys, ['account_id'],
                                                 {'predexp': predexp})
        for rec in records:
            if rec[2] is not None:
                matched_recs.append(rec[2])

        assert len(matched_recs) == 3
        for rec in matched_recs:
            assert rec['account_id'] == 1 or rec['account_id'] == 3 or rec[
                'account_id'] == 4

    def test_pos_remove_with_predexp(self):
        '''
        Call remove with predexp in policy.
        '''
        predexp = [
            as_predexp.integer_bin('account_id'),
            as_predexp.integer_value(1),
            as_predexp.integer_equal()
        ]
        records = self.as_connection.remove(self.keys[0])

        rec = self.as_connection.exists(self.keys[0])
        assert rec[1] is None

    def test_remove_with_predexp_filtered_out(self):
        '''
        Call remove with predexp in policy with expected failure.
        '''
        predexp = [
            as_predexp.integer_bin('account_id'),
            as_predexp.integer_value(3),
            as_predexp.integer_equal()
        ]
        with pytest.raises(e.FilteredOut):
            self.as_connection.remove(self.keys[0],
                                      policy={'predexp': predexp})

    def test_remove_bin_with_predexp(self):
        '''
        Call remove_bin with predexp in policy.
        '''
        predexp = [
            as_predexp.integer_bin('account_id'),
            as_predexp.integer_value(1),
            as_predexp.integer_equal()
        ]
        self.as_connection.remove_bin(self.keys[0],
                                      ['account_id', 'user_name'],
                                      policy={'predexp': predexp})

        rec = self.as_connection.get(self.keys[0])
        assert rec[2].get('account_id') is None and rec[2].get(
            'user_name') is None

    def test_remove_bin_with_predexp_filtered_out(self):
        '''
        Call remove_bin with predexp in policy with expected failure.
        '''
        predexp = [
            as_predexp.integer_bin('account_id'),
            as_predexp.integer_value(4),
            as_predexp.integer_equal()
        ]
        with pytest.raises(e.FilteredOut):
            self.as_connection.remove_bin(self.keys[0],
                                          ['account_id', 'user_name'],
                                          policy={'predexp': predexp})

    def test_put_with_predexp(self):
        '''
        Call put with predexp in policy.
        '''
        predexp = [
            as_predexp.integer_bin('account_id'),
            as_predexp.integer_value(1),
            as_predexp.integer_equal()
        ]
        self.as_connection.put(self.keys[0], {'newkey': 'newval'},
                               policy={'predexp': predexp})

        rec = self.as_connection.get(self.keys[0])
        assert rec[2]['newkey'] == 'newval'

    def test_put_new_record_with_predexp(self):  # should this fail?
        '''
        Call put a new record with predexp in policy.
        '''
        predexp = [
            as_predexp.integer_bin('account_id'),
            as_predexp.integer_value(1),
            as_predexp.integer_equal()
        ]
        key = ("test", "demo", 10)
        self.as_connection.put(key, {'newkey': 'newval'},
                               policy={'predexp': predexp})

        rec = self.as_connection.get(key)
        self.as_connection.remove(key)
        assert rec[2]['newkey'] == 'newval'

    def test_put_with_predexp_filtered_out(self):
        '''
        Call put with predexp in policy with expected failure.
        '''
        predexp = [
            as_predexp.integer_bin('account_id'),
            as_predexp.integer_value(4),
            as_predexp.integer_equal()
        ]
        with pytest.raises(e.FilteredOut):
            self.as_connection.put(self.keys[0], {'newkey': 'newval'},
                                   policy={'predexp': predexp})

    def test_get_with_predexp(self):
        '''
        Call to get with predexp in policy.
        '''
        predexp = [
            as_predexp.integer_bin('account_id'),
            as_predexp.integer_value(1),
            as_predexp.integer_equal()
        ]
        record = self.as_connection.get(self.keys[0], {'predexp': predexp})

        assert record[2]['account_id'] == 1

    def test_get_with_predexp_filtered_out(self):
        '''
        Call to get with predexp in policy with expected failures.
        '''
        predexp = [
            as_predexp.integer_bin('account_id'),
            as_predexp.integer_value(3),
            as_predexp.integer_equal()
        ]
        with pytest.raises(e.FilteredOut):
            self.as_connection.get(self.keys[0], {'predexp': predexp})

    def test_select_with_predexp(self):
        '''
        Call to select with predexp in policy.
        '''
        predexp = [
            as_predexp.integer_bin('acct_balance'),
            as_predexp.integer_value(20),
            as_predexp.integer_equal(),
            as_predexp.integer_var('charge'),
            as_predexp.integer_value(20),
            as_predexp.integer_less(),
            as_predexp.list_bin('charges'),
            as_predexp.list_iterate_and('charge'),
            as_predexp.predexp_and(2)
        ]

        result = self.as_connection.select(self.keys[1],
                                           ['account_id', 'acct_balance'],
                                           {'predexp': predexp})
        assert result[2]['account_id'] == 2 and result[2]['acct_balance'] == 20

    def test_select_with_predexp_filtered_out(self):
        '''
        Call to select with predexp in policy with expected failures.
        '''
        predexp = [
            as_predexp.integer_bin('acct_balance'),
            as_predexp.integer_value(20),
            as_predexp.integer_equal(),
            as_predexp.integer_var('charge'),
            as_predexp.integer_value(
                10),  # charge should trigger a filtered_out
            as_predexp.integer_less(),
            as_predexp.list_bin('charges'),
            as_predexp.list_iterate_and('charge'),
            as_predexp.predexp_and(2)
        ]

        with pytest.raises(e.FilteredOut):
            self.as_connection.select(self.keys[1],
                                      ['account_id', 'acct_balance'],
                                      {'predexp': predexp})

    def test_exists_many_with_large_predexp(self):
        '''
        Proper call to exists_many with predexp in policy.
        '''
        predexp = [
            as_predexp.integer_bin('account_id'),
            as_predexp.integer_value(4),
            as_predexp.integer_equal(),
            as_predexp.string_bin('user_name'),
            as_predexp.string_value('user3'),
            as_predexp.string_equal(),
            as_predexp.integer_var('list_val'),
            as_predexp.integer_value(12),
            as_predexp.integer_less(),
            as_predexp.list_bin('charges'),
            as_predexp.list_iterate_and('list_val'),
            as_predexp.predexp_or(3)
        ]

        matched_recs = []
        records = self.as_connection.exists_many(self.keys,
                                                 {'predexp': predexp})
        for rec in records:
            if rec[1] is not None:
                matched_recs.append(rec[1])

        assert len(matched_recs) == 3
    )
    sys.exit(3)

pp = pprint.PrettyPrinter(indent=2)
spacer = "=" * 30
epoch = datetime.datetime(2019, 1, 1)
now = datetime.datetime.now()
try:
    # Upsert a single segment in the user profile
    key = (namespace, set, "u1")
    segment_id = random.randint(0, 81999)
    ttl_dt = now + datetime.timedelta(days=30)
    segment_ttl = int((ttl_dt - epoch).total_seconds() / 3600)
    ops = [
        mh.map_get_by_key("u", segment_id, aerospike.MAP_RETURN_KEY_VALUE),
        mh.map_put("u", segment_id, [segment_ttl, {}]),
        mh.map_get_by_key("u", segment_id, aerospike.MAP_RETURN_KEY_VALUE),
    ]
    print("\nUpsert segment {} => [{}] to user u1".format(segment_id, segment_ttl))
    if options.interactive:
        pause()
    _, _, b = client.operate_ordered(key, ops)
    segment_check, segment_count, new_segment = b
    print("Segment value before: {}".format(segment_check[1]))
    print("Number of segments after upsert: {}".format(segment_count[1]))
    print("Segment value after: {}".format(new_segment[1]))
    print(spacer)

    # Update multiple segments of a user profile
    segments = {}
    ttl_dt = now + datetime.timedelta(days=30)
key = (options.namespace, options.set, "map-put")
try:
    client.remove(key)
except ex.RecordError as e:
    pass

try:
    print("\nput(bin, key, value[, writeFlags, createType, context])\n")
    # create a new record with one element by upsert
    # by default a newly created map is unordered, so declare the map order to
    # be  K_ORDERED
    # the map order policy is only used when creating a new map bin
    policy = {
        "map_order": aerospike.MAP_KEY_ORDERED,
    }
    _, _, bins = client.operate(key, [mapops.map_put("m", "a", 1, policy)])
    print(
        "put('m','a', 1, createType=K_ORDERED). Number of elements in the map: {}"
        .format(bins["m"]))
    # put('m','a', 1, createType=K_ORDERED). Number of elements in the map: 1
    key, metadata, bins = client.get(key)
    print("{}".format(bins["m"]))
    # {'a': 1}

    # put the same element with the CREATE_ONLY and NO_FAIL write flags
    # this should fail gracefully
    policy = {
        "map_write_flags":
        aerospike.MAP_WRITE_FLAGS_CREATE_ONLY
        | aerospike.MAP_WRITE_FLAGS_NO_FAIL,
    }
 def test_map_put(self):
     operations = [map_ops.map_put(self.test_bin, "new", "map_put")]
     self.as_connection.operate(self.test_key, operations)
     res_map = self.as_connection.get(self.test_key)[2][self.test_bin]
     assert res_map["new"] == "map_put"
Exemplo n.º 13
0
    by_rank = client.map_get_by_rank_range(key, "scores", 0, 5,
                                           aerospike.MAP_RETURN_KEY_VALUE)
    pp.pprint(by_rank)
    print("\nSize of the top scores map is", client.map_size(key, "scores"))

    print(spacer)
    print(
        "\nInject a new top score, keep map capped to 100 elements,",
        "in a single operation",
    )
    ts, score, name, dt = random_score()
    print("New score to add will be")
    new_score = [score, {"name": name, "dt": dt}]
    pp.pprint(new_score)
    ops = [
        map_operations.map_put("scores", ts, new_score),
        map_operations.map_remove_by_rank_range("scores", 1, 100,
                                                aerospike.MAP_RETURN_NONE,
                                                True),
    ]
    client.operate(key, ops, meta)
    print("\nSize of the top scores map is now",
          client.map_size(key, "scores"))
    print("\nBottom 5 Pac-Man top scores, sorted by score (rank)")
    by_rank = client.map_get_by_rank_range(key, "scores", 0, 5,
                                           aerospike.MAP_RETURN_KEY_VALUE)
    pp.pprint(by_rank)
    print("New lowest score is:")
    pp.pprint(
        client.map_get_by_rank(key, "scores", 0,
                               aerospike.MAP_RETURN_KEY_VALUE))
    _, _, bins = client.operate(key, [
        listops.list_append("l", {'c': 3}, aerospike.MAP_RETURN_NONE, ctx=ctx)
    ])
    print("{}".format(bins["l"]))
    _, _, bins = client.get(key)
    print("{}".format(bins["l"]))
    sys.exit(18)

    # put the same element with the CREATE_ONLY and NO_FAIL write flags
    # this should fail gracefully
    policy = {
        "map_write_flags":
        aerospike.MAP_WRITE_FLAGS_CREATE_ONLY
        | aerospike.MAP_WRITE_FLAGS_NO_FAIL,
    }
    _, _, bins = client.operate(key, [mapops.map_put("l", "a", 11, policy)])
    print(
        "\nput('l','a', 11, CREATE_ONLY|NO_FAIL. Number of elements in the map: {}"
        .format(bins["l"]))
    # put('l','a', 1, CREATE_ONLY|NO_FAIL). Number of elements in the map: 1
    key, metadata, bins = client.get(key)
    print("{}".format(bins["l"]))
    # {'a': 1}

    # put a different element with the UPDATE_ONLY and NO_FAIL write flags
    # this should fail gracefully
    policy = {
        "map_write_flags":
        aerospike.MAP_WRITE_FLAGS_UPDATE_ONLY
        | aerospike.MAP_WRITE_FLAGS_NO_FAIL,
    }
for i in range(0, 20, 1):
    try:
        ad = ads[random.randrange(0, 4, 1)]
        val = client.map_get_by_key(key, "ads", ad, aerospike.MAP_RETURN_VALUE)
        print("Ad", ad, "has value", val)
        if not val:
            val = 0
        if val < AD_LIMIT:
            # continue and attempt to serve the ad
            print("Ad", ad, "is under the cap, incrementing its counter")
            client.map_increment(
                key, "ads", ad, 1, {},
                {"ttl": aerospike.TTL_DONT_UPDATE})  # aka ttl -2
    except ex.RecordNotFound as e:
        ttl = aerospike.TTL_NAMESPACE_DEFAULT  # AKA ttl 0, inherit the default-ttl
        try:
            ops = [
                map_operations.map_put("ads", ad, 1, {}),
                map_operations.map_get_by_key("ads", ad,
                                              aerospike.MAP_RETURN_VALUE),
            ]
            print("Ad", ad, "does not exist yet, initializing it to 1")
            (key, meta, bins) = client.operate(key, ops, {"ttl": ttl})
        except ex.AerospikeError as e:
            print("Error: {0} [{1}]".format(e.msg, e.code))

print("\nState of the consolidated counters at this key")
k, m, b = client.get(key)
pp.pprint(b)
client.close()
    by_rank = b["scores"]
    pp.pprint(by_rank)
    print("==============================")

    # add an award icon to a specific player ("CFO") where awards have a type
    # and a count, some awards can be given once, and some more than once
    ctx = [
        ctxh.cdt_ctx_map_key("CFO"),
        # the attribute map is the second element of the tuple
        ctxh.cdt_ctx_list_index(1),
    ]
    ops = [
        # give the unicorn award exactly once
        mh.map_put("scores", "awards", {"🦄": 1}, {
            "map_write_flags":
            aerospike.MAP_WRITE_FLAGS_CREATE_ONLY
            | aerospike.MAP_WRITE_FLAGS_NO_FAIL
        }, ctx)
    ]
    k, m, b = client.operate(key, ops)

    # assuming it's given once a day, grant the 'top score' award to the
    # current top score
    ctx = [
        ctxh.cdt_ctx_map_rank(-1),
        # the attribute map is the second element of the tuple
        ctxh.cdt_ctx_list_index(1),
    ]
    ctx2 = ctx + [ctxh.cdt_ctx_map_key("awards")]
    ops = [
        # create the top score award if it doesn't exist