From 0cc611b846dd5f1147dbdbac6f050f2c4c3f91ad Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Wed, 27 Aug 2025 11:14:49 -0700 Subject: [PATCH 01/73] Fix command-level write, operate, batch_write, and scan policies not accepting ttl as an option --- src/main/policy.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/policy.c b/src/main/policy.c index 0b91e1066e..c3cb3affea 100644 --- a/src/main/policy.c +++ b/src/main/policy.c @@ -552,6 +552,7 @@ as_status pyobject_to_policy_scan(AerospikeClient *self, as_error *err, POLICY_SET_FIELD(records_per_second, uint32_t); POLICY_SET_FIELD(max_records, uint64_t); POLICY_SET_FIELD(replica, as_policy_replica); + POLICY_SET_FIELD(ttl, uint32_t); } // Update the policy @@ -593,6 +594,7 @@ as_status pyobject_to_policy_write(AerospikeClient *self, as_error *err, POLICY_SET_FIELD(commit_level, as_policy_commit_level); POLICY_SET_FIELD(durable_delete, bool); POLICY_SET_FIELD(replica, as_policy_replica); + POLICY_SET_FIELD(ttl, uint32_t); POLICY_SET_FIELD(compression_threshold, uint32_t); POLICY_SET_FIELD(on_locking_only, bool); } @@ -640,6 +642,7 @@ as_status pyobject_to_policy_operate(AerospikeClient *self, as_error *err, POLICY_SET_FIELD(exists, as_policy_exists); POLICY_SET_FIELD(read_touch_ttl_percent, int); POLICY_SET_FIELD(on_locking_only, bool); + POLICY_SET_FIELD(ttl, uint32_t); // 4.0.0 new policies POLICY_SET_FIELD(read_mode_ap, as_policy_read_mode_ap); @@ -716,6 +719,7 @@ as_status pyobject_to_batch_write_policy(AerospikeClient *self, as_error *err, POLICY_SET_FIELD(exists, as_policy_exists); POLICY_SET_FIELD(durable_delete, bool); POLICY_SET_FIELD(on_locking_only, bool); + POLICY_SET_FIELD(ttl, uint32_t); // C client 5.0 new expressions POLICY_SET_EXPRESSIONS_FIELD(); From 7eaaa1f0a2e2241cd3978c91c05efc9aa9280712 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Wed, 27 Aug 2025 11:40:23 -0700 Subject: [PATCH 02/73] Deprecate meta parameter in client.put() --- doc/client.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/client.rst b/doc/client.rst index da697eb05c..aac32aff22 100755 --- a/doc/client.rst +++ b/doc/client.rst @@ -102,7 +102,8 @@ Record Commands :param tuple key: a :ref:`aerospike_key_tuple` associated with the record. :param dict bins: contains bin name-value pairs of the record. - :param dict meta: record metadata to be set. see :ref:`metadata_dict`. + :param dict meta: record metadata to be set. see :ref:`metadata_dict`. .. deprecated:: 17.2.0 Use the write policy to set ``ttl`` and ``gen`` instead. + :param dict policy: see :ref:`aerospike_write_policies`. :param serializer: override the serialization mode of the client \ From 521e2157bdc71cbb4e2e90394d4989f3b7fb37c2 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Wed, 27 Aug 2025 11:44:10 -0700 Subject: [PATCH 03/73] fix? --- doc/client.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/client.rst b/doc/client.rst index aac32aff22..120dbb0b9a 100755 --- a/doc/client.rst +++ b/doc/client.rst @@ -102,8 +102,8 @@ Record Commands :param tuple key: a :ref:`aerospike_key_tuple` associated with the record. :param dict bins: contains bin name-value pairs of the record. - :param dict meta: record metadata to be set. see :ref:`metadata_dict`. .. deprecated:: 17.2.0 Use the write policy to set ``ttl`` and ``gen`` instead. - + :param dict meta: record metadata to be set. see :ref:`metadata_dict`. + .. deprecated:: 17.2.0 Use the write policy to set ``ttl`` and ``gen`` instead. :param dict policy: see :ref:`aerospike_write_policies`. :param serializer: override the serialization mode of the client \ From 915678e8bdbaa490b9aeae79b22310e8ac724792 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Wed, 27 Aug 2025 12:43:42 -0700 Subject: [PATCH 04/73] fix? --- doc/client.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/client.rst b/doc/client.rst index 120dbb0b9a..c636568720 100755 --- a/doc/client.rst +++ b/doc/client.rst @@ -103,7 +103,10 @@ Record Commands :param tuple key: a :ref:`aerospike_key_tuple` associated with the record. :param dict bins: contains bin name-value pairs of the record. :param dict meta: record metadata to be set. see :ref:`metadata_dict`. - .. deprecated:: 17.2.0 Use the write policy to set ``ttl`` and ``gen`` instead. + + .. deprecated:: 17.2.0 + Use the write policy to set ``ttl`` and ``gen`` instead. + :param dict policy: see :ref:`aerospike_write_policies`. :param serializer: override the serialization mode of the client \ From 48453a9890feac4d3da4ac6254f053b4dd7fa92d Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Wed, 27 Aug 2025 12:44:46 -0700 Subject: [PATCH 05/73] fix? --- doc/client.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/client.rst b/doc/client.rst index c636568720..4fb411dbe6 100755 --- a/doc/client.rst +++ b/doc/client.rst @@ -102,7 +102,8 @@ Record Commands :param tuple key: a :ref:`aerospike_key_tuple` associated with the record. :param dict bins: contains bin name-value pairs of the record. - :param dict meta: record metadata to be set. see :ref:`metadata_dict`. + :param dict meta: + record metadata to be set. see :ref:`metadata_dict`. .. deprecated:: 17.2.0 Use the write policy to set ``ttl`` and ``gen`` instead. From 0e2032c7f4045d79ce9944fbe1b2e4e4bfa87aff Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Wed, 27 Aug 2025 13:24:08 -0700 Subject: [PATCH 06/73] fix client.remove_bin() not applying policy's ttl if meta.ttl is set to aerospike.TTL_CLIENT_DEFAULT --- src/main/client/remove_bin.c | 59 ++++++++++++------------------------ 1 file changed, 19 insertions(+), 40 deletions(-) diff --git a/src/main/client/remove_bin.c b/src/main/client/remove_bin.c index 1444f57473..aa405a8597 100644 --- a/src/main/client/remove_bin.c +++ b/src/main/client/remove_bin.c @@ -83,6 +83,19 @@ AerospikeClient_RemoveBin_Invoke(AerospikeClient *self, PyObject *py_key, } // Invoke operation + // TODO: check for mem leak from policy + PyObject *py_bins = PyDict_New(); + if (py_bins) { + goto CLEANUP; + } + + // Serializer option doesn't matter since we're just deleting bins + // static_pool isn't used since the bin dictionary is guaranteed to be empty + as_record_init_from_pyobject(self, err, py_bins, py_meta, &rec, + SERIALIZER_NONE, NULL); + if (err->code != AEROSPIKE_OK) { + goto CLEANUP; + } for (count = 0; count < size; count++) { PyObject *py_val = PyList_GetItem(py_binList, count); @@ -93,9 +106,11 @@ AerospikeClient_RemoveBin_Invoke(AerospikeClient *self, PyObject *py_key, else { as_error_update(err, AEROSPIKE_ERR_CLIENT, "Invalid bin name, bin name should be a string or " - "unicode string") goto CLEANUP; + "unicode string"); + goto CLEANUP; } if (!as_record_set_nil(&rec, binName)) { + // TODO: mem leak goto CLEANUP; } if (py_ustr) { @@ -104,45 +119,6 @@ AerospikeClient_RemoveBin_Invoke(AerospikeClient *self, PyObject *py_key, } } - if (py_meta && PyDict_Check(py_meta)) { - PyObject *py_gen = PyDict_GetItemString(py_meta, "gen"); - PyObject *py_ttl = PyDict_GetItemString(py_meta, "ttl"); - - if (py_ttl) { - if (PyLong_Check(py_ttl)) { - rec.ttl = (uint32_t)PyLong_AsLong(py_ttl); - if ((uint32_t)-1 == rec.ttl && PyErr_Occurred()) { - as_error_update( - err, AEROSPIKE_ERR_PARAM, - "integer value for ttl exceeds sys.maxsize"); - goto CLEANUP; - } - } - else { - as_error_update(err, AEROSPIKE_ERR_PARAM, - "Ttl should be an int or long"); - goto CLEANUP; - } - } - - if (py_gen) { - if (PyLong_Check(py_gen)) { - rec.gen = (uint16_t)PyLong_AsLongLong(py_gen); - if ((uint16_t)-1 == rec.gen && PyErr_Occurred()) { - as_error_update( - err, AEROSPIKE_ERR_PARAM, - "integer value for gen exceeds sys.maxsize"); - goto CLEANUP; - } - } - else { - as_error_update(err, AEROSPIKE_ERR_PARAM, - "Generation should be an int or long"); - goto CLEANUP; - } - } - } - Py_BEGIN_ALLOW_THREADS aerospike_key_put(self->as, err, write_policy_p, &key, &rec); Py_END_ALLOW_THREADS @@ -163,6 +139,9 @@ AerospikeClient_RemoveBin_Invoke(AerospikeClient *self, PyObject *py_key, raise_exception_base(err, py_key, Py_None, Py_None, Py_None, Py_None); return NULL; } + else if (PyErr_Occurred()) { + return NULL; + } return PyLong_FromLong(0); } From 138358f63016c8aeaa6dc71a003be5b63a5fae29 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Wed, 27 Aug 2025 13:28:27 -0700 Subject: [PATCH 07/73] dont init as_record twice --- src/main/client/remove_bin.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/client/remove_bin.c b/src/main/client/remove_bin.c index aa405a8597..1b9decafab 100644 --- a/src/main/client/remove_bin.c +++ b/src/main/client/remove_bin.c @@ -63,8 +63,6 @@ AerospikeClient_RemoveBin_Invoke(AerospikeClient *self, PyObject *py_key, // Get the bin list size; Py_ssize_t size = PyList_Size(py_binList); - // Initialize record - as_record_inita(&rec, size); // Convert python key object to as_key pyobject_to_key(err, py_key, &key); From 1b0c36f30d4c36dd6a6a79b0d5cbc9dcadc781d5 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Wed, 27 Aug 2025 13:38:37 -0700 Subject: [PATCH 08/73] put() is also initializing as_record twice --- src/main/client/put.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/client/put.c b/src/main/client/put.c index fa7910bb79..355b3074f4 100644 --- a/src/main/client/put.c +++ b/src/main/client/put.c @@ -62,10 +62,6 @@ PyObject *AerospikeClient_Put_Invoke(AerospikeClient *self, PyObject *py_key, bool key_initialised = false; bool record_initialised = false; - // Initialize record - as_record_init(&rec, 0); - record_initialised = true; - as_static_pool static_pool; memset(&static_pool, 0, sizeof(static_pool)); @@ -94,6 +90,8 @@ PyObject *AerospikeClient_Put_Invoke(AerospikeClient *self, PyObject *py_key, // Convert python bins and metadata objects to as_record as_record_init_from_pyobject(self, &err, py_bins, py_meta, &rec, serializer_option, &static_pool); + // Initialize record + record_initialised = true; if (err.code != AEROSPIKE_OK) { goto CLEANUP; } From 5062f5cdf40cd5fe1b7755eb84e7403ace64084b Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Wed, 27 Aug 2025 13:47:39 -0700 Subject: [PATCH 09/73] hard to deprecate function params. just add a note in function --- doc/client.rst | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/doc/client.rst b/doc/client.rst index 4fb411dbe6..b23a731889 100755 --- a/doc/client.rst +++ b/doc/client.rst @@ -100,14 +100,12 @@ Record Commands Create a new record, or remove / add bins to a record. + .. versionchanged:: 17.2.0 + Deprecated the ``meta`` parameter. Use the write policy to set ``ttl`` and ``gen`` instead. + :param tuple key: a :ref:`aerospike_key_tuple` associated with the record. :param dict bins: contains bin name-value pairs of the record. - :param dict meta: - record metadata to be set. see :ref:`metadata_dict`. - - .. deprecated:: 17.2.0 - Use the write policy to set ``ttl`` and ``gen`` instead. - + :param dict meta: Deprecated: record metadata to be set. see :ref:`metadata_dict`. :param dict policy: see :ref:`aerospike_write_policies`. :param serializer: override the serialization mode of the client \ From 1ca626ecf17abc8d9f3474205f60fe0c3eafbe21 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Wed, 27 Aug 2025 14:10:13 -0700 Subject: [PATCH 10/73] fix mem leak if bins dictionary is invalid --- src/main/client/put.c | 2 +- src/main/client/remove_bin.c | 6 +++++- src/main/conversions.c | 27 ++++++++++++++++----------- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/main/client/put.c b/src/main/client/put.c index 355b3074f4..6e369128b1 100644 --- a/src/main/client/put.c +++ b/src/main/client/put.c @@ -91,10 +91,10 @@ PyObject *AerospikeClient_Put_Invoke(AerospikeClient *self, PyObject *py_key, as_record_init_from_pyobject(self, &err, py_bins, py_meta, &rec, serializer_option, &static_pool); // Initialize record - record_initialised = true; if (err.code != AEROSPIKE_OK) { goto CLEANUP; } + record_initialised = true; // Convert python policy object to as_policy_write pyobject_to_policy_write(self, &err, py_policy, &write_policy, diff --git a/src/main/client/remove_bin.c b/src/main/client/remove_bin.c index 1b9decafab..655cba60f0 100644 --- a/src/main/client/remove_bin.c +++ b/src/main/client/remove_bin.c @@ -56,6 +56,7 @@ AerospikeClient_RemoveBin_Invoke(AerospikeClient *self, PyObject *py_key, char *binName = NULL; int count = 0; PyObject *py_ustr = NULL; + bool record_initialised = false; // For converting expressions. as_exp exp_list; @@ -94,6 +95,7 @@ AerospikeClient_RemoveBin_Invoke(AerospikeClient *self, PyObject *py_key, if (err->code != AEROSPIKE_OK) { goto CLEANUP; } + record_initialised = true; for (count = 0; count < size; count++) { PyObject *py_val = PyList_GetItem(py_binList, count); @@ -123,7 +125,9 @@ AerospikeClient_RemoveBin_Invoke(AerospikeClient *self, PyObject *py_key, CLEANUP: - as_record_destroy(&rec); + if (record_initialised) { + as_record_destroy(&rec); + } if (exp_list_p) { as_exp_destroy(exp_list_p); diff --git a/src/main/conversions.c b/src/main/conversions.c index 142dc485d2..d3889d5227 100644 --- a/src/main/conversions.c +++ b/src/main/conversions.c @@ -1347,6 +1347,7 @@ as_status as_record_init_from_pyobject(AerospikeClient *self, as_error *err, // this should never happen, but if it did... return as_error_update(err, AEROSPIKE_ERR_CLIENT, "record is null"); } + else if (PyDict_Check(py_bins_dict)) { PyObject *py_bin_name = NULL, *py_bin_value = NULL; Py_ssize_t pos = 0; @@ -1356,32 +1357,33 @@ as_status as_record_init_from_pyobject(AerospikeClient *self, as_error *err, as_record_init(rec, size); while (PyDict_Next(py_bins_dict, &pos, &py_bin_name, &py_bin_value)) { - if (!PyUnicode_Check(py_bin_name)) { - return as_error_update( + as_error_update( err, AEROSPIKE_ERR_CLIENT, "A bin name must be a string or unicode string."); + goto CLEANUP_ON_ERROR; } name = PyUnicode_AsUTF8(py_bin_name); if (!name) { - return as_error_update( - err, AEROSPIKE_ERR_CLIENT, - "Unable to convert unicode object to C string"); + as_error_update(err, AEROSPIKE_ERR_CLIENT, + "Unable to convert unicode object to C string"); + goto CLEANUP_ON_ERROR; } if (self->strict_types) { if (strlen(name) > AS_BIN_NAME_MAX_LEN) { - return as_error_update( + as_error_update( err, AEROSPIKE_ERR_BIN_NAME, "A bin name should not exceed 15 characters limit"); + goto CLEANUP_ON_ERROR; } } if (!py_bin_value) { // this should never happen, but if it did... - return as_error_update(err, AEROSPIKE_ERR_CLIENT, - "record is null"); + as_error_update(err, AEROSPIKE_ERR_CLIENT, "record is null"); + goto CLEANUP_ON_ERROR; } as_val *val = NULL; @@ -1393,8 +1395,9 @@ as_status as_record_init_from_pyobject(AerospikeClient *self, as_error *err, bool success = as_record_set(rec, name, (as_bin_value *)val); if (success == false) { as_val_destroy(val); - return as_error_update(err, AEROSPIKE_ERR_BIN_NAME, - "Unable to set key-value pair"); + as_error_update(err, AEROSPIKE_ERR_BIN_NAME, + "Unable to set key-value pair"); + goto CLEANUP_ON_ERROR; } } @@ -1451,7 +1454,7 @@ as_status as_record_init_from_pyobject(AerospikeClient *self, as_error *err, } if (err->code != AEROSPIKE_OK) { - as_record_destroy(rec); + goto CLEANUP_ON_ERROR; } } else { @@ -1459,6 +1462,8 @@ as_status as_record_init_from_pyobject(AerospikeClient *self, as_error *err, "Record should be passed as bin-value pair"); } +CLEANUP_ON_ERROR: + as_record_destroy(rec); return err->code; } From 33907e117539d6803bec48a84b03aae70c1f2a79 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Thu, 28 Aug 2025 16:46:47 -0700 Subject: [PATCH 11/73] revert --- src/main/client/put.c | 6 ++-- src/main/client/remove_bin.c | 67 +++++++++++++++++++++++------------- 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/src/main/client/put.c b/src/main/client/put.c index 6e369128b1..fa7910bb79 100644 --- a/src/main/client/put.c +++ b/src/main/client/put.c @@ -62,6 +62,10 @@ PyObject *AerospikeClient_Put_Invoke(AerospikeClient *self, PyObject *py_key, bool key_initialised = false; bool record_initialised = false; + // Initialize record + as_record_init(&rec, 0); + record_initialised = true; + as_static_pool static_pool; memset(&static_pool, 0, sizeof(static_pool)); @@ -90,11 +94,9 @@ PyObject *AerospikeClient_Put_Invoke(AerospikeClient *self, PyObject *py_key, // Convert python bins and metadata objects to as_record as_record_init_from_pyobject(self, &err, py_bins, py_meta, &rec, serializer_option, &static_pool); - // Initialize record if (err.code != AEROSPIKE_OK) { goto CLEANUP; } - record_initialised = true; // Convert python policy object to as_policy_write pyobject_to_policy_write(self, &err, py_policy, &write_policy, diff --git a/src/main/client/remove_bin.c b/src/main/client/remove_bin.c index 655cba60f0..1444f57473 100644 --- a/src/main/client/remove_bin.c +++ b/src/main/client/remove_bin.c @@ -56,7 +56,6 @@ AerospikeClient_RemoveBin_Invoke(AerospikeClient *self, PyObject *py_key, char *binName = NULL; int count = 0; PyObject *py_ustr = NULL; - bool record_initialised = false; // For converting expressions. as_exp exp_list; @@ -64,6 +63,8 @@ AerospikeClient_RemoveBin_Invoke(AerospikeClient *self, PyObject *py_key, // Get the bin list size; Py_ssize_t size = PyList_Size(py_binList); + // Initialize record + as_record_inita(&rec, size); // Convert python key object to as_key pyobject_to_key(err, py_key, &key); @@ -82,20 +83,6 @@ AerospikeClient_RemoveBin_Invoke(AerospikeClient *self, PyObject *py_key, } // Invoke operation - // TODO: check for mem leak from policy - PyObject *py_bins = PyDict_New(); - if (py_bins) { - goto CLEANUP; - } - - // Serializer option doesn't matter since we're just deleting bins - // static_pool isn't used since the bin dictionary is guaranteed to be empty - as_record_init_from_pyobject(self, err, py_bins, py_meta, &rec, - SERIALIZER_NONE, NULL); - if (err->code != AEROSPIKE_OK) { - goto CLEANUP; - } - record_initialised = true; for (count = 0; count < size; count++) { PyObject *py_val = PyList_GetItem(py_binList, count); @@ -106,11 +93,9 @@ AerospikeClient_RemoveBin_Invoke(AerospikeClient *self, PyObject *py_key, else { as_error_update(err, AEROSPIKE_ERR_CLIENT, "Invalid bin name, bin name should be a string or " - "unicode string"); - goto CLEANUP; + "unicode string") goto CLEANUP; } if (!as_record_set_nil(&rec, binName)) { - // TODO: mem leak goto CLEANUP; } if (py_ustr) { @@ -119,15 +104,52 @@ AerospikeClient_RemoveBin_Invoke(AerospikeClient *self, PyObject *py_key, } } + if (py_meta && PyDict_Check(py_meta)) { + PyObject *py_gen = PyDict_GetItemString(py_meta, "gen"); + PyObject *py_ttl = PyDict_GetItemString(py_meta, "ttl"); + + if (py_ttl) { + if (PyLong_Check(py_ttl)) { + rec.ttl = (uint32_t)PyLong_AsLong(py_ttl); + if ((uint32_t)-1 == rec.ttl && PyErr_Occurred()) { + as_error_update( + err, AEROSPIKE_ERR_PARAM, + "integer value for ttl exceeds sys.maxsize"); + goto CLEANUP; + } + } + else { + as_error_update(err, AEROSPIKE_ERR_PARAM, + "Ttl should be an int or long"); + goto CLEANUP; + } + } + + if (py_gen) { + if (PyLong_Check(py_gen)) { + rec.gen = (uint16_t)PyLong_AsLongLong(py_gen); + if ((uint16_t)-1 == rec.gen && PyErr_Occurred()) { + as_error_update( + err, AEROSPIKE_ERR_PARAM, + "integer value for gen exceeds sys.maxsize"); + goto CLEANUP; + } + } + else { + as_error_update(err, AEROSPIKE_ERR_PARAM, + "Generation should be an int or long"); + goto CLEANUP; + } + } + } + Py_BEGIN_ALLOW_THREADS aerospike_key_put(self->as, err, write_policy_p, &key, &rec); Py_END_ALLOW_THREADS CLEANUP: - if (record_initialised) { - as_record_destroy(&rec); - } + as_record_destroy(&rec); if (exp_list_p) { as_exp_destroy(exp_list_p); @@ -141,9 +163,6 @@ AerospikeClient_RemoveBin_Invoke(AerospikeClient *self, PyObject *py_key, raise_exception_base(err, py_key, Py_None, Py_None, Py_None, Py_None); return NULL; } - else if (PyErr_Occurred()) { - return NULL; - } return PyLong_FromLong(0); } From 9422ad2094aefe5fddb2f4f0af01a6eb558e7766 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Tue, 4 Nov 2025 08:00:34 -0800 Subject: [PATCH 12/73] Replace deprecation docstring with multiline var --- doc/client.rst | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/doc/client.rst b/doc/client.rst index fcbbc2149a..cdded13739 100755 --- a/doc/client.rst +++ b/doc/client.rst @@ -90,6 +90,10 @@ Connection You may call :meth:`~aerospike.Client.connect` again after closing the connection. +.. |deprecate_meta_docstring| replace:: + .. versionchanged:: 18.1.0 + Deprecated the ``meta`` parameter. Use the write policy to set ``ttl`` and ``gen`` instead. + Record Commands --------------- @@ -100,8 +104,7 @@ Record Commands Create a new record, or remove / add bins to a record. - .. versionchanged:: 17.2.0 - Deprecated the ``meta`` parameter. Use the write policy to set ``ttl`` and ``gen`` instead. + |deprecate_meta_docstring| :param tuple key: a :ref:`aerospike_key_tuple` associated with the record. :param dict bins: contains bin name-value pairs of the record. @@ -255,6 +258,8 @@ Record Commands Remove a list of bins from a record with a given *key*. Equivalent to \ setting those bins to :meth:`aerospike.null` with a :meth:`~aerospike.put`. + |deprecate_meta_docstring| + :param tuple key: a :ref:`aerospike_key_tuple` associated with the record. :param list list: the bins names to be removed from the record. :param dict meta: record metadata to be set. See :ref:`metadata_dict`. From add81e64a7f00df183cc5ef5c1feed515e00e038 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Tue, 4 Nov 2025 08:06:41 -0800 Subject: [PATCH 13/73] fix --- doc/client.rst | 8 ++------ doc/deprecate_meta.rst | 3 +++ 2 files changed, 5 insertions(+), 6 deletions(-) create mode 100644 doc/deprecate_meta.rst diff --git a/doc/client.rst b/doc/client.rst index cdded13739..c118fa247f 100755 --- a/doc/client.rst +++ b/doc/client.rst @@ -90,10 +90,6 @@ Connection You may call :meth:`~aerospike.Client.connect` again after closing the connection. -.. |deprecate_meta_docstring| replace:: - .. versionchanged:: 18.1.0 - Deprecated the ``meta`` parameter. Use the write policy to set ``ttl`` and ``gen`` instead. - Record Commands --------------- @@ -104,7 +100,7 @@ Record Commands Create a new record, or remove / add bins to a record. - |deprecate_meta_docstring| + .. include:: ./deprecate_meta.rst :param tuple key: a :ref:`aerospike_key_tuple` associated with the record. :param dict bins: contains bin name-value pairs of the record. @@ -258,7 +254,7 @@ Record Commands Remove a list of bins from a record with a given *key*. Equivalent to \ setting those bins to :meth:`aerospike.null` with a :meth:`~aerospike.put`. - |deprecate_meta_docstring| + .. include:: ./deprecate_meta.rst :param tuple key: a :ref:`aerospike_key_tuple` associated with the record. :param list list: the bins names to be removed from the record. diff --git a/doc/deprecate_meta.rst b/doc/deprecate_meta.rst new file mode 100644 index 0000000000..e1460e64df --- /dev/null +++ b/doc/deprecate_meta.rst @@ -0,0 +1,3 @@ +.. versionchanged:: 18.1.0 + + Deprecated the ``meta`` parameter. Use the write policy to set ``ttl`` and ``gen`` instead. From 826a9146b18665325625e94b680cc0689c17b1e3 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 5 Dec 2025 14:03:47 -0800 Subject: [PATCH 14/73] WIP --- src/main/client/operate.c | 14 ++++++++++++++ src/main/client/put.c | 7 +++++++ src/main/client/remove.c | 7 +++++++ src/main/client/remove_bin.c | 7 +++++++ test/new_tests/test_append.py | 7 ++++++- 5 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/main/client/operate.c b/src/main/client/operate.c index 2910558c8a..cd53d144d9 100644 --- a/src/main/client/operate.c +++ b/src/main/client/operate.c @@ -926,6 +926,13 @@ static PyObject *AerospikeClient_Operate_Invoke(AerospikeClient *self, as_exp exp_list; as_exp *exp_list_p = NULL; + if (py_meta) { + PyErr_WarnEx(PyExc_DeprecationWarning, + "meta parameter is deprecated and will be removed in the " + "next client major release.", + 2); + } + as_vector *unicodeStrVector = as_vector_create(sizeof(char *), 128); as_operations ops; @@ -1264,6 +1271,13 @@ PyObject *AerospikeClient_OperateOrdered(AerospikeClient *self, PyObject *args, return NULL; } + if (py_meta) { + PyErr_WarnEx(PyExc_DeprecationWarning, + "meta parameter is deprecated and will be removed in the " + "next client major release.", + 2); + } + CHECK_CONNECTED(&err); if (pyobject_to_key(&err, py_key, &key) != AEROSPIKE_OK) { diff --git a/src/main/client/put.c b/src/main/client/put.c index 4822b0d670..339d3df24e 100644 --- a/src/main/client/put.c +++ b/src/main/client/put.c @@ -168,6 +168,13 @@ PyObject *AerospikeClient_Put(AerospikeClient *self, PyObject *args, return NULL; } + if (py_meta) { + PyErr_WarnEx(PyExc_DeprecationWarning, + "meta parameter is deprecated and will be removed in the " + "next client major release.", + 2); + } + if (py_serializer_option) { if (PyLong_Check(py_serializer_option)) { self->is_client_put_serializer = true; diff --git a/src/main/client/remove.c b/src/main/client/remove.c index 0b76b6b358..e55b2c5c11 100644 --- a/src/main/client/remove.c +++ b/src/main/client/remove.c @@ -170,6 +170,13 @@ PyObject *AerospikeClient_Remove(AerospikeClient *self, PyObject *args, return NULL; } + if (py_meta) { + PyErr_WarnEx(PyExc_DeprecationWarning, + "meta parameter is deprecated and will be removed in the " + "next client major release.", + 2); + } + // Invoke Operation return AerospikeClient_Remove_Invoke(self, py_key, py_meta, py_policy); } diff --git a/src/main/client/remove_bin.c b/src/main/client/remove_bin.c index 0451d534b2..56faef8534 100644 --- a/src/main/client/remove_bin.c +++ b/src/main/client/remove_bin.c @@ -168,6 +168,13 @@ PyObject *AerospikeClient_RemoveBin(AerospikeClient *self, PyObject *args, return NULL; } + if (py_meta) { + PyErr_WarnEx(PyExc_DeprecationWarning, + "meta parameter is deprecated and will be removed in the " + "next client major release.", + 2); + } + if (!self || !self->as) { as_error_update(&err, AEROSPIKE_ERR_PARAM, "Invalid aerospike object"); goto CLEANUP; diff --git a/test/new_tests/test_append.py b/test/new_tests/test_append.py index bf0a4cbbef..f5082da5d4 100644 --- a/test/new_tests/test_append.py +++ b/test/new_tests/test_append.py @@ -4,6 +4,7 @@ from aerospike import exception as e import aerospike +import warnings # @pytest.mark.usefixtures("as_connection") @@ -116,7 +117,11 @@ def test_pos_append_with_policy_key_gen_EQ_ignore(self): } meta = {"gen": 10, "ttl": 1200} - self.as_connection.append(key, "name", "str", meta, policy) + with warnings.catch_warnings(record=True) as warning_list: + self.as_connection.append(key, "name", "str", meta, policy) + + assert len(warning_list) == 1 + assert warning_list[0].category == DeprecationWarning (key, meta, bins) = self.as_connection.get(key) From b4809d72f01a31fc8dabec0a7143d357fe3029da Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 5 Dec 2025 14:31:47 -0800 Subject: [PATCH 15/73] Revert --- src/main/policy.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/policy.c b/src/main/policy.c index d020ce21bb..e65baf4239 100644 --- a/src/main/policy.c +++ b/src/main/policy.c @@ -674,7 +674,6 @@ as_status pyobject_to_policy_scan( POLICY_SET_FIELD(records_per_second, uint32_t); POLICY_SET_FIELD(max_records, uint64_t); POLICY_SET_FIELD(replica, as_policy_replica); - POLICY_SET_FIELD(ttl, uint32_t); } // Update the policy @@ -737,7 +736,6 @@ as_status pyobject_to_policy_write( POLICY_SET_FIELD(commit_level, as_policy_commit_level); POLICY_SET_FIELD(durable_delete, bool); POLICY_SET_FIELD(replica, as_policy_replica); - POLICY_SET_FIELD(ttl, uint32_t); POLICY_SET_FIELD(compression_threshold, uint32_t); POLICY_SET_FIELD(on_locking_only, bool); } @@ -798,7 +796,6 @@ as_status pyobject_to_policy_operate(AerospikeClient *self, as_error *err, POLICY_SET_FIELD(exists, as_policy_exists); POLICY_SET_FIELD(read_touch_ttl_percent, int); POLICY_SET_FIELD(on_locking_only, bool); - POLICY_SET_FIELD(ttl, uint32_t); // 4.0.0 new policies POLICY_SET_FIELD(read_mode_ap, as_policy_read_mode_ap); @@ -902,7 +899,6 @@ as_status pyobject_to_batch_write_policy(AerospikeClient *self, as_error *err, POLICY_SET_FIELD(exists, as_policy_exists); POLICY_SET_FIELD(durable_delete, bool); POLICY_SET_FIELD(on_locking_only, bool); - POLICY_SET_FIELD(ttl, uint32_t); // C client 5.0 new expressions POLICY_SET_EXPRESSIONS_FIELD(); From e02c60ca801e412b4baae4ed1039394e79d2d558 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 5 Dec 2025 14:58:07 -0800 Subject: [PATCH 16/73] Doc --- doc/client.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/doc/client.rst b/doc/client.rst index 8904cd406c..bb43862994 100755 --- a/doc/client.rst +++ b/doc/client.rst @@ -183,6 +183,8 @@ Record Commands (In Aerospike server versions prior to 3.6.0, non-existent bins being read will have a \ :py:obj:`None` value. ) + .. include:: ./deprecate_meta.rst + :param tuple key: a :ref:`aerospike_key_tuple` associated with the record. :param list list: See :ref:`aerospike_operation_helpers.operations`. :param dict meta: record metadata to be set. See :ref:`metadata_dict`. @@ -209,6 +211,8 @@ Record Commands Write operations or read operations that fail will not return a ``(bin-name, result)`` tuple. + .. include:: ./deprecate_meta.rst + :param tuple key: a :ref:`aerospike_key_tuple` associated with the record. :param list list: See :ref:`aerospike_operation_helpers.operations`. :param dict meta: record metadata to be set. See :ref:`metadata_dict`. @@ -226,6 +230,8 @@ Record Commands Touch the given record, setting its time-to-live and incrementing its generation. + .. include:: ./deprecate_meta.rst + :param tuple key: a :ref:`aerospike_key_tuple` associated with the record. :param int val: ttl in seconds, with ``0`` resolving to the default value in the server config. :param dict meta: record metadata to be set. see :ref:`metadata_dict` @@ -240,6 +246,8 @@ Record Commands Remove a record matching the *key* from the cluster. + .. include:: ./deprecate_meta.rst + :param tuple key: a :ref:`aerospike_key_tuple` associated with the record. :param dict meta: contains the expected generation of the record in a key called ``"gen"``. :param dict policy: see :ref:`aerospike_remove_policies`. May be passed as a keyword argument. @@ -412,6 +420,8 @@ String Operations Append a string to the string value in bin. + .. include:: ./deprecate_meta.rst + :param tuple key: a :ref:`aerospike_key_tuple` tuple associated with the record. :param str bin: the name of the bin. :param str val: the string to append to the bin value. @@ -431,6 +441,8 @@ String Operations Prepend the string value in *bin* with the string *val*. + .. include:: ./deprecate_meta.rst + :param tuple key: a :ref:`aerospike_key_tuple` tuple associated with the record. :param str bin: the name of the bin. :param str val: the string to prepend to the bin value. @@ -460,6 +472,8 @@ Numeric Operations Increment the integer value in *bin* by the integer *val*. + .. include:: ./deprecate_meta.rst + :param tuple key: a :ref:`aerospike_key_tuple` tuple associated with the record. :param str bin: the name of the bin. :param int offset: the value by which to increment the value in *bin*. From fa973ae8f6ecbd85cbf94f712ca91badbf8576e5 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 5 Dec 2025 15:00:29 -0800 Subject: [PATCH 17/73] test and see if deprecation shows up properly for aerospike_helpers. --- aerospike_helpers/batch/records.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aerospike_helpers/batch/records.py b/aerospike_helpers/batch/records.py index 99e9f5816e..53331d8cd8 100644 --- a/aerospike_helpers/batch/records.py +++ b/aerospike_helpers/batch/records.py @@ -60,6 +60,8 @@ def __init__(self, key: tuple) -> None: class Write(BatchRecord): """ Write is used for executing Batch write commands with batch_write and retrieving batch write results. + .. include:: ./deprecate_meta.rst + Attributes: key (:obj:`tuple`): The aerospike key to send the command to. record (:obj:`tuple`): The record corresponding to the requested key. From 4f649fe54c15b25f8ae777baa72ff5c8bdaa61ff Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 5 Dec 2025 15:07:00 -0800 Subject: [PATCH 18/73] Make more accurate for other commands that don't take in a write policy --- doc/deprecate_meta.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/deprecate_meta.rst b/doc/deprecate_meta.rst index e1460e64df..e721c10750 100644 --- a/doc/deprecate_meta.rst +++ b/doc/deprecate_meta.rst @@ -1,3 +1,3 @@ .. versionchanged:: 18.1.0 - Deprecated the ``meta`` parameter. Use the write policy to set ``ttl`` and ``gen`` instead. + Deprecated the ``meta`` parameter. Use the policy parameter to set ``ttl`` and ``gen`` instead. From d34d940f3e103854c3467002afefb6f714ac0779 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 5 Dec 2025 15:10:55 -0800 Subject: [PATCH 19/73] Finish updating aerospike_helpers --- aerospike_helpers/batch/records.py | 2 ++ aerospike_helpers/operations/operations.py | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/aerospike_helpers/batch/records.py b/aerospike_helpers/batch/records.py index 53331d8cd8..7de31879c9 100644 --- a/aerospike_helpers/batch/records.py +++ b/aerospike_helpers/batch/records.py @@ -113,6 +113,8 @@ def __init__( class Read(BatchRecord): """ Read is used for executing Batch read commands with batch_write and retrieving results. + .. include:: ./deprecate_meta.rst + Attributes: key (:obj:`tuple`): The aerospike key to send the command to. record (:obj:`tuple`): The record corresponding to the requested key. diff --git a/aerospike_helpers/operations/operations.py b/aerospike_helpers/operations/operations.py index eda976d78c..ff10701bbd 100644 --- a/aerospike_helpers/operations/operations.py +++ b/aerospike_helpers/operations/operations.py @@ -119,18 +119,18 @@ def increment(bin_name, amount): def touch(ttl: Optional[int] = None): """Create a touch operation dictionary. - Using ttl here is deprecated. It should be set in the record metadata for the operate method. + Using ttl here is deprecated. It should be set in the policy parameter for the operate method. Args: ttl (int): Deprecated. The ttl that should be set for the record. - This should be set in the metadata passed to the operate or + This should be set in the policy parameter passed to the operate or operate_ordered methods. Returns: A dictionary to be passed to operate or operate_ordered. """ op_dict = {"op": aerospike.OPERATOR_TOUCH} if ttl: - warnings.warn("TTL should be specified in the meta dictionary for operate", DeprecationWarning) + warnings.warn("TTL should be specified in the policy parameter for operate", DeprecationWarning) op_dict["val"] = ttl return op_dict From e52682d79a0ece6e7c7eb6651148134e43186fe5 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 5 Dec 2025 15:32:51 -0800 Subject: [PATCH 20/73] Use macro --- src/include/client.h | 4 ++++ src/main/client/operate.c | 8 ++------ src/main/client/put.c | 4 +--- src/main/client/remove.c | 4 +--- src/main/client/remove_bin.c | 4 +--- 5 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/include/client.h b/src/include/client.h index 4ba9447916..f66860ffbf 100644 --- a/src/include/client.h +++ b/src/include/client.h @@ -25,6 +25,10 @@ #define CLUSTER_NPARTITIONS (4096) +#define DEPRECATE_META_PARAMETER_WARNING_MESSAGE \ + "meta parameter is deprecated and will be removed in the " \ + "next client major release" + /******************************************************************************* * Macros for UDF operations. ******************************************************************************/ diff --git a/src/main/client/operate.c b/src/main/client/operate.c index cd53d144d9..352957cce1 100644 --- a/src/main/client/operate.c +++ b/src/main/client/operate.c @@ -928,9 +928,7 @@ static PyObject *AerospikeClient_Operate_Invoke(AerospikeClient *self, if (py_meta) { PyErr_WarnEx(PyExc_DeprecationWarning, - "meta parameter is deprecated and will be removed in the " - "next client major release.", - 2); + DEPRECATE_META_PARAMETER_WARNING_MESSAGE, 2); } as_vector *unicodeStrVector = as_vector_create(sizeof(char *), 128); @@ -1273,9 +1271,7 @@ PyObject *AerospikeClient_OperateOrdered(AerospikeClient *self, PyObject *args, if (py_meta) { PyErr_WarnEx(PyExc_DeprecationWarning, - "meta parameter is deprecated and will be removed in the " - "next client major release.", - 2); + DEPRECATE_META_PARAMETER_WARNING_MESSAGE, 2); } CHECK_CONNECTED(&err); diff --git a/src/main/client/put.c b/src/main/client/put.c index 339d3df24e..9b139ae360 100644 --- a/src/main/client/put.c +++ b/src/main/client/put.c @@ -170,9 +170,7 @@ PyObject *AerospikeClient_Put(AerospikeClient *self, PyObject *args, if (py_meta) { PyErr_WarnEx(PyExc_DeprecationWarning, - "meta parameter is deprecated and will be removed in the " - "next client major release.", - 2); + DEPRECATE_META_PARAMETER_WARNING_MESSAGE, 2); } if (py_serializer_option) { diff --git a/src/main/client/remove.c b/src/main/client/remove.c index e55b2c5c11..1ead859625 100644 --- a/src/main/client/remove.c +++ b/src/main/client/remove.c @@ -172,9 +172,7 @@ PyObject *AerospikeClient_Remove(AerospikeClient *self, PyObject *args, if (py_meta) { PyErr_WarnEx(PyExc_DeprecationWarning, - "meta parameter is deprecated and will be removed in the " - "next client major release.", - 2); + DEPRECATE_META_PARAMETER_WARNING_MESSAGE, 2); } // Invoke Operation diff --git a/src/main/client/remove_bin.c b/src/main/client/remove_bin.c index 56faef8534..0c72bfbbf0 100644 --- a/src/main/client/remove_bin.c +++ b/src/main/client/remove_bin.c @@ -170,9 +170,7 @@ PyObject *AerospikeClient_RemoveBin(AerospikeClient *self, PyObject *args, if (py_meta) { PyErr_WarnEx(PyExc_DeprecationWarning, - "meta parameter is deprecated and will be removed in the " - "next client major release.", - 2); + DEPRECATE_META_PARAMETER_WARNING_MESSAGE, 2); } if (!self || !self->as) { From a88f237674627d360ed8395545904a9cb80cba59 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 5 Dec 2025 15:37:56 -0800 Subject: [PATCH 21/73] This test will not fail if an invalid key is passed --- test/new_tests/test_new_constructor.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/new_tests/test_new_constructor.py b/test/new_tests/test_new_constructor.py index d9233c5b1e..43500b0f26 100644 --- a/test/new_tests/test_new_constructor.py +++ b/test/new_tests/test_new_constructor.py @@ -322,6 +322,8 @@ def test_config_level_misc_options(): # We just make sure that the above options are allowed as dict keys try: aerospike.client(config) + except e.ParamError as exc: + raise exc except: pass From 142ad28d2765675d717ad3af02afb2428ae5f8b2 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 5 Dec 2025 15:40:53 -0800 Subject: [PATCH 22/73] Rename to something better. --- ...est_new_constructor.py => test_client_config_level_options.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/new_tests/{test_new_constructor.py => test_client_config_level_options.py} (100%) diff --git a/test/new_tests/test_new_constructor.py b/test/new_tests/test_client_config_level_options.py similarity index 100% rename from test/new_tests/test_new_constructor.py rename to test/new_tests/test_client_config_level_options.py From e33a7eb6ea064a94e147606a327c6258644e5453 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 5 Dec 2025 16:14:40 -0800 Subject: [PATCH 23/73] socket_timeout isn't in docs --- test/new_tests/test_client_config_level_options.py | 1 - 1 file changed, 1 deletion(-) diff --git a/test/new_tests/test_client_config_level_options.py b/test/new_tests/test_client_config_level_options.py index 43500b0f26..9059b23e8d 100644 --- a/test/new_tests/test_client_config_level_options.py +++ b/test/new_tests/test_client_config_level_options.py @@ -280,7 +280,6 @@ def test_query_invalid_expected_duration(): # Some of these options may not be documented, but they are allowed in the code and customers may be using them def test_config_level_misc_options(): config = copy.deepcopy(gconfig) - config["policies"]["socket_timeout"] = 1 config["policies"]["total_timeout"] = 1 config["policies"]["max_retries"] = 1 config["policies"]["exists"] = aerospike.POLICY_EXISTS_CREATE From 04b65845c904ae26d060e2efd84415c378d81cca Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 5 Dec 2025 16:21:24 -0800 Subject: [PATCH 24/73] Add more test cases for checking that warning is raised for using meta parameter --- test/new_tests/test_get_put.py | 7 ++++++- test/new_tests/test_increment.py | 7 ++++++- test/new_tests/test_operate.py | 6 +++++- test/new_tests/test_operate_ordered.py | 6 +++++- test/new_tests/test_prepend.py | 6 +++++- test/new_tests/test_remove.py | 1 + 6 files changed, 28 insertions(+), 5 deletions(-) diff --git a/test/new_tests/test_get_put.py b/test/new_tests/test_get_put.py index 628078a5bd..74c000d538 100644 --- a/test/new_tests/test_get_put.py +++ b/test/new_tests/test_get_put.py @@ -14,6 +14,7 @@ import aerospike from aerospike import exception as e +import warnings @contextmanager @@ -262,7 +263,11 @@ def test_pos_put_with_policy_exists_create_or_replace(self): "gen": aerospike.POLICY_GEN_IGNORE, "key": aerospike.POLICY_KEY_SEND, } - assert 0 == self.as_connection.put(key, rec, meta, policy) + + with warnings.catch_warnings(record=True) as warning_list: + assert 0 == self.as_connection.put(key, rec, meta, policy) + assert len(warning_list) == 1 + assert warning_list[0].category == DeprecationWarning (key, meta, bins) = self.as_connection.get(key) assert rec == bins diff --git a/test/new_tests/test_increment.py b/test/new_tests/test_increment.py index 1f6e71acae..9ad084c827 100644 --- a/test/new_tests/test_increment.py +++ b/test/new_tests/test_increment.py @@ -7,6 +7,7 @@ from aerospike import exception as e import aerospike +import warnings class TestIncrement(object): @@ -127,7 +128,11 @@ def test_increment_with_policy_key_gen_EQ_ignore(self): } meta = {"gen": 10, "ttl": 1200} - self.as_connection.increment(key, "age", 5, meta, policy) + with warnings.catch_warnings(record=True) as warning_list: + self.as_connection.increment(key, "age", 5, meta, policy) + + assert len(warning_list) == 1 + assert warning_list[0].category == DeprecationWarning (key, meta, bins) = self.as_connection.get(key) diff --git a/test/new_tests/test_operate.py b/test/new_tests/test_operate.py index 3c5a9550b8..ce4406bd52 100644 --- a/test/new_tests/test_operate.py +++ b/test/new_tests/test_operate.py @@ -4,6 +4,7 @@ import aerospike from aerospike import exception as e +import warnings # OPERATIONS # aerospike.OPERATOR_WRITE @@ -297,7 +298,10 @@ def test_pos_operate_with_policy_gen_ignore(self, key, policy, meta, llist): Invoke operate() with gen ignore. """ - key, meta, bins = self.as_connection.operate(key, llist, meta, policy) + with warnings.catch_warnings(record=True) as warning_list: + key, meta, bins = self.as_connection.operate(key, llist, meta, policy) + assert len(warning_list) == 1 + assert warning_list[0].category == DeprecationWarning assert bins == {"name": "name1aa"} assert key == ( diff --git a/test/new_tests/test_operate_ordered.py b/test/new_tests/test_operate_ordered.py index 67a10299b0..f940965a0c 100644 --- a/test/new_tests/test_operate_ordered.py +++ b/test/new_tests/test_operate_ordered.py @@ -5,6 +5,7 @@ import aerospike from aerospike import exception as e from aerospike_helpers.operations import operations +import warnings class TestOperateOrdered(object): @@ -222,7 +223,10 @@ def test_pos_operate_ordered_policy_gen_ignore(self, key, policy, meta, llist): """ Invoke operate_ordered() with gen ignore. """ - key, meta, bins = self.as_connection.operate_ordered(key, llist, meta, policy) + with warnings.catch_warnings(record=True) as warning_list: + key, meta, bins = self.as_connection.operate_ordered(key, llist, meta, policy) + assert len(warning_list) == 1 + assert warning_list[0].category == DeprecationWarning assert bins == [("name", "name1aa")] diff --git a/test/new_tests/test_prepend.py b/test/new_tests/test_prepend.py index e6bfb08e9a..e5b67bd8e1 100644 --- a/test/new_tests/test_prepend.py +++ b/test/new_tests/test_prepend.py @@ -4,6 +4,7 @@ from .test_base_class import TestBaseClass import aerospike from aerospike import exception as e +import warnings class TestPrepend: @@ -101,7 +102,10 @@ def test_pos_prepend_with_policy_key_gen_EQ_ignore(self): } meta = {"gen": 10, "ttl": 1200} - self.as_connection.prepend(key, "name", "str", meta, policy) + with warnings.catch_warnings(record=True) as warning_list: + self.as_connection.prepend(key, "name", "str", meta, policy) + assert len(warning_list) == 1 + assert warning_list[0].category == DeprecationWarning (key, meta, bins) = self.as_connection.get(key) diff --git a/test/new_tests/test_remove.py b/test/new_tests/test_remove.py index c0ed09126e..55643433f1 100644 --- a/test/new_tests/test_remove.py +++ b/test/new_tests/test_remove.py @@ -6,6 +6,7 @@ from .test_base_class import TestBaseClass import aerospike from aerospike import exception as e +import warnings @pytest.mark.usefixtures("as_connection") From 08b3d90551608959d8c47140ca672619438169f3 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Sun, 7 Dec 2025 19:09:01 -0800 Subject: [PATCH 25/73] Just undo to be consistent --- doc/client.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/client.rst b/doc/client.rst index bb43862994..ffbdf132a6 100755 --- a/doc/client.rst +++ b/doc/client.rst @@ -104,7 +104,7 @@ Record Commands :param tuple key: a :ref:`aerospike_key_tuple` associated with the record. :param dict bins: contains bin name-value pairs of the record. - :param dict meta: Deprecated: record metadata to be set. see :ref:`metadata_dict`. + :param dict meta: record metadata to be set. see :ref:`metadata_dict`. :param dict policy: see :ref:`aerospike_write_policies`. :param serializer: override the serialization mode of the client \ From fa18901b02774bd2b3f11ea25c2b04eea8147415 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 20 Feb 2026 15:27:53 -0800 Subject: [PATCH 26/73] Update version --- doc/deprecate_meta.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/deprecate_meta.rst b/doc/deprecate_meta.rst index e721c10750..71aa7b2609 100644 --- a/doc/deprecate_meta.rst +++ b/doc/deprecate_meta.rst @@ -1,3 +1,3 @@ -.. versionchanged:: 18.1.0 +.. versionchanged:: 19.1.0 Deprecated the ``meta`` parameter. Use the policy parameter to set ``ttl`` and ``gen`` instead. From 99097b933b8d49f41827fd1bb0ac76176b2eb21f Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 20 Feb 2026 16:11:57 -0800 Subject: [PATCH 27/73] Fix missing allowed key for client config "policies" --- src/main/aerospike.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/aerospike.c b/src/main/aerospike.c index 3fe36a5c6c..d511b04231 100644 --- a/src/main/aerospike.c +++ b/src/main/aerospike.c @@ -670,7 +670,8 @@ DEFINE_SET_OF_VALID_KEYS(client_config_policies, "read", "write", "apply", "batch_parent_write", "info", "admin", "txn_verify", "txn_roll", "total_timeout", "auth_mode", "login_timeout_ms", "key", "exists", "max_retries", - "replica", "commit_level", "metrics", NULL) + "replica", "commit_level", "metrics", "read_mode_ap", + NULL) DEFINE_SET_OF_VALID_KEYS(client_config_tls, "enable", "cafile", "capath", "protocols", "cipher_suite", "keyfile", "keyfile_pw", From a66a0cca6f473c3eebb6d1bdfa91252a5ea92c54 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 20 Feb 2026 16:28:25 -0800 Subject: [PATCH 28/73] Fix missing allowed key for client config "policies" --- src/main/aerospike.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/aerospike.c b/src/main/aerospike.c index d511b04231..9054aa9066 100644 --- a/src/main/aerospike.c +++ b/src/main/aerospike.c @@ -671,7 +671,7 @@ DEFINE_SET_OF_VALID_KEYS(client_config_policies, "read", "write", "apply", "txn_roll", "total_timeout", "auth_mode", "login_timeout_ms", "key", "exists", "max_retries", "replica", "commit_level", "metrics", "read_mode_ap", - NULL) + "max_threads", NULL) DEFINE_SET_OF_VALID_KEYS(client_config_tls, "enable", "cafile", "capath", "protocols", "cipher_suite", "keyfile", "keyfile_pw", From 1e79d2e6e7150b7b4e4a0d01af9fd0952188e927 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 20 Feb 2026 16:46:19 -0800 Subject: [PATCH 29/73] fix --- src/main/aerospike.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/aerospike.c b/src/main/aerospike.c index 9054aa9066..42455f6966 100644 --- a/src/main/aerospike.c +++ b/src/main/aerospike.c @@ -671,7 +671,7 @@ DEFINE_SET_OF_VALID_KEYS(client_config_policies, "read", "write", "apply", "txn_roll", "total_timeout", "auth_mode", "login_timeout_ms", "key", "exists", "max_retries", "replica", "commit_level", "metrics", "read_mode_ap", - "max_threads", NULL) + "max_threads", "thread_pool_size", NULL) DEFINE_SET_OF_VALID_KEYS(client_config_tls, "enable", "cafile", "capath", "protocols", "cipher_suite", "keyfile", "keyfile_pw", From 61b5637c8dcfed9f33a79c1af276533b50748f3e Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Mon, 23 Feb 2026 08:15:42 -0800 Subject: [PATCH 30/73] Fix doc for client.remove() --- doc/client.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/client.rst b/doc/client.rst index 7914228b6e..58748490e3 100755 --- a/doc/client.rst +++ b/doc/client.rst @@ -246,7 +246,9 @@ Record Commands Remove a record matching the *key* from the cluster. - .. include:: ./deprecate_meta.rst + .. versionchanged:: 19.1.0 + + Deprecated the ``meta`` parameter. Use the policy parameter to set ``gen`` instead. :param tuple key: a :ref:`aerospike_key_tuple` associated with the record. :param dict meta: contains the expected generation of the record in a key called ``"gen"``. From 46aa5357dab6bfccb645f6ba7609a9f94bee7219 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Mon, 23 Feb 2026 08:25:47 -0800 Subject: [PATCH 31/73] Read BatchRecord shouldn't pass in a ttl since it shouldn't accept write operations --- aerospike_helpers/batch/records.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/aerospike_helpers/batch/records.py b/aerospike_helpers/batch/records.py index 7de31879c9..b0f167215c 100644 --- a/aerospike_helpers/batch/records.py +++ b/aerospike_helpers/batch/records.py @@ -113,7 +113,10 @@ def __init__( class Read(BatchRecord): """ Read is used for executing Batch read commands with batch_write and retrieving results. - .. include:: ./deprecate_meta.rst + .. versionchanged:: 19.1.0 + + Deprecated the ``meta`` parameter. Use the policy parameter in a + :py:obj:`~aerospike_helpers.batch.records.Write` BatchRecord instead. Attributes: key (:obj:`tuple`): The aerospike key to send the command to. From 75ca6e60dbded37dbd990910a6fa98122f50e854 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Mon, 23 Feb 2026 08:29:07 -0800 Subject: [PATCH 32/73] Reuse macro to define number of lines in stack trace --- src/include/client.h | 3 +++ src/main/client/operate.c | 4 ++-- src/main/client/put.c | 2 +- src/main/client/remove.c | 2 +- src/main/client/remove_bin.c | 2 +- src/main/client/sec_index.c | 3 --- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/include/client.h b/src/include/client.h index f5a3701871..9d68ad0e7b 100644 --- a/src/include/client.h +++ b/src/include/client.h @@ -29,6 +29,9 @@ "meta parameter is deprecated and will be removed in the " \ "next client major release" +// This allows people to see the function calling the Python client API that issues a warning +#define STACK_LEVEL 2 + /******************************************************************************* * Macros for UDF operations. ******************************************************************************/ diff --git a/src/main/client/operate.c b/src/main/client/operate.c index 5d5b4be935..b1b2c77704 100644 --- a/src/main/client/operate.c +++ b/src/main/client/operate.c @@ -919,7 +919,7 @@ static PyObject *AerospikeClient_Operate_Invoke(AerospikeClient *self, if (py_meta) { PyErr_WarnEx(PyExc_DeprecationWarning, - DEPRECATE_META_PARAMETER_WARNING_MESSAGE, 2); + DEPRECATE_META_PARAMETER_WARNING_MESSAGE, STACK_LEVEL); } as_vector *unicodeStrVector = as_vector_create(sizeof(char *), 128); @@ -1261,7 +1261,7 @@ PyObject *AerospikeClient_OperateOrdered(AerospikeClient *self, PyObject *args, if (py_meta) { PyErr_WarnEx(PyExc_DeprecationWarning, - DEPRECATE_META_PARAMETER_WARNING_MESSAGE, 2); + DEPRECATE_META_PARAMETER_WARNING_MESSAGE, STACK_LEVEL); } CHECK_CONNECTED(&err); diff --git a/src/main/client/put.c b/src/main/client/put.c index c384d21368..85f3bec22e 100644 --- a/src/main/client/put.c +++ b/src/main/client/put.c @@ -169,7 +169,7 @@ PyObject *AerospikeClient_Put(AerospikeClient *self, PyObject *args, if (py_meta) { PyErr_WarnEx(PyExc_DeprecationWarning, - DEPRECATE_META_PARAMETER_WARNING_MESSAGE, 2); + DEPRECATE_META_PARAMETER_WARNING_MESSAGE, STACK_LEVEL); } if (py_serializer_option) { diff --git a/src/main/client/remove.c b/src/main/client/remove.c index c7eb61fe8c..587a1c744a 100644 --- a/src/main/client/remove.c +++ b/src/main/client/remove.c @@ -171,7 +171,7 @@ PyObject *AerospikeClient_Remove(AerospikeClient *self, PyObject *args, if (py_meta) { PyErr_WarnEx(PyExc_DeprecationWarning, - DEPRECATE_META_PARAMETER_WARNING_MESSAGE, 2); + DEPRECATE_META_PARAMETER_WARNING_MESSAGE, STACK_LEVEL); } // Invoke Operation diff --git a/src/main/client/remove_bin.c b/src/main/client/remove_bin.c index 92d467896b..0374074fc5 100644 --- a/src/main/client/remove_bin.c +++ b/src/main/client/remove_bin.c @@ -169,7 +169,7 @@ PyObject *AerospikeClient_RemoveBin(AerospikeClient *self, PyObject *args, if (py_meta) { PyErr_WarnEx(PyExc_DeprecationWarning, - DEPRECATE_META_PARAMETER_WARNING_MESSAGE, 2); + DEPRECATE_META_PARAMETER_WARNING_MESSAGE, STACK_LEVEL); } if (!self || !self->as) { diff --git a/src/main/client/sec_index.c b/src/main/client/sec_index.c index a0296474d0..0622f3f16d 100644 --- a/src/main/client/sec_index.c +++ b/src/main/client/sec_index.c @@ -241,9 +241,6 @@ PyObject *AerospikeClient_Index_Expr_Create(AerospikeClient *self, NULL, py_expr); } -// This allows people to see the function calling the Python client API that issues a warning -#define STACK_LEVEL 2 - // TODO: way to get method name dynamically for error message? static inline PyObject * AerospikeClient_Index_Create_Helper(AerospikeClient *self, PyObject *args, From a7b7a429764ba69215b5c7a4219126d553a22fa5 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Mon, 23 Feb 2026 08:33:07 -0800 Subject: [PATCH 33/73] Add missing test case for client config option socket_timeout --- test/new_tests/test_client_config_level_options.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/new_tests/test_client_config_level_options.py b/test/new_tests/test_client_config_level_options.py index 9bdb953b3f..dd13447174 100644 --- a/test/new_tests/test_client_config_level_options.py +++ b/test/new_tests/test_client_config_level_options.py @@ -301,6 +301,7 @@ def test_config_level_misc_options(): config["policies"]["commit_level"] = aerospike.POLICY_COMMIT_LEVEL_ALL config["policies"]["max_threads"] = 16 config["policies"]["thread_pool_size"] = 16 + config["policies"]["socket_timeout"] = 0 config["thread_pool_size"] = 16 config["max_threads"] = 16 config["max_conns_per_node"] = 16 From b5c99d2a5c9e06604a3b7c1025de54ccb1e0a765 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Wed, 25 Feb 2026 11:28:57 -0800 Subject: [PATCH 34/73] Only deprecate meta["ttl"], not the whole meta parameter --- aerospike_helpers/batch/records.py | 6 +++--- doc/client.rst | 16 ++++++++-------- doc/deprecate_meta.rst | 3 --- doc/deprecate_meta_ttl.rst | 3 +++ src/include/client.h | 4 ---- src/main/client/operate.c | 11 ----------- src/main/client/put.c | 5 ----- src/main/client/remove.c | 4 +++- src/main/client/remove_bin.c | 5 ----- src/main/conversions.c | 5 +++++ test/new_tests/test_append.py | 10 +++------- test/new_tests/test_get_put.py | 8 +++----- test/new_tests/test_increment.py | 10 +++------- test/new_tests/test_operate.py | 9 +++------ test/new_tests/test_operate_ordered.py | 8 +++----- test/new_tests/test_prepend.py | 9 +++------ test/new_tests/test_remove.py | 1 - 17 files changed, 40 insertions(+), 77 deletions(-) delete mode 100644 doc/deprecate_meta.rst create mode 100644 doc/deprecate_meta_ttl.rst diff --git a/aerospike_helpers/batch/records.py b/aerospike_helpers/batch/records.py index b0f167215c..bb1f4688fc 100644 --- a/aerospike_helpers/batch/records.py +++ b/aerospike_helpers/batch/records.py @@ -60,7 +60,7 @@ def __init__(self, key: tuple) -> None: class Write(BatchRecord): """ Write is used for executing Batch write commands with batch_write and retrieving batch write results. - .. include:: ./deprecate_meta.rst + .. include:: ./deprecate_meta_ttl.rst Attributes: key (:obj:`tuple`): The aerospike key to send the command to. @@ -115,8 +115,8 @@ class Read(BatchRecord): .. versionchanged:: 19.1.0 - Deprecated the ``meta`` parameter. Use the policy parameter in a - :py:obj:`~aerospike_helpers.batch.records.Write` BatchRecord instead. + Deprecated the ``"ttl"`` option in the ``meta`` parameter. Use the policy parameter in a + :py:obj:`~aerospike_helpers.batch.records.Write` BatchRecord to set the ``"ttl"`` instead. Attributes: key (:obj:`tuple`): The aerospike key to send the command to. diff --git a/doc/client.rst b/doc/client.rst index 58748490e3..ca355e6af3 100755 --- a/doc/client.rst +++ b/doc/client.rst @@ -100,7 +100,7 @@ Record Commands Create a new record, or remove / add bins to a record. - .. include:: ./deprecate_meta.rst + .. include:: ./deprecate_meta_ttl.rst :param tuple key: a :ref:`aerospike_key_tuple` associated with the record. :param dict bins: contains bin name-value pairs of the record. @@ -183,7 +183,7 @@ Record Commands (In Aerospike server versions prior to 3.6.0, non-existent bins being read will have a \ :py:obj:`None` value. ) - .. include:: ./deprecate_meta.rst + .. include:: ./deprecate_meta_ttl.rst :param tuple key: a :ref:`aerospike_key_tuple` associated with the record. :param list list: See :ref:`aerospike_operation_helpers.operations`. @@ -211,7 +211,7 @@ Record Commands Write operations or read operations that fail will not return a ``(bin-name, result)`` tuple. - .. include:: ./deprecate_meta.rst + .. include:: ./deprecate_meta_ttl.rst :param tuple key: a :ref:`aerospike_key_tuple` associated with the record. :param list list: See :ref:`aerospike_operation_helpers.operations`. @@ -230,7 +230,7 @@ Record Commands Touch the given record, setting its time-to-live and incrementing its generation. - .. include:: ./deprecate_meta.rst + .. include:: ./deprecate_meta_ttl.rst :param tuple key: a :ref:`aerospike_key_tuple` associated with the record. :param int val: ttl in seconds, with ``0`` resolving to the default value in the server config. @@ -264,7 +264,7 @@ Record Commands Remove a list of bins from a record with a given *key*. Equivalent to \ setting those bins to :meth:`aerospike.null` with a :meth:`~aerospike.put`. - .. include:: ./deprecate_meta.rst + .. include:: ./deprecate_meta_ttl.rst :param tuple key: a :ref:`aerospike_key_tuple` associated with the record. :param list list: the bins names to be removed from the record. @@ -422,7 +422,7 @@ String Operations Append a string to the string value in bin. - .. include:: ./deprecate_meta.rst + .. include:: ./deprecate_meta_ttl.rst :param tuple key: a :ref:`aerospike_key_tuple` tuple associated with the record. :param str bin: the name of the bin. @@ -443,7 +443,7 @@ String Operations Prepend the string value in *bin* with the string *val*. - .. include:: ./deprecate_meta.rst + .. include:: ./deprecate_meta_ttl.rst :param tuple key: a :ref:`aerospike_key_tuple` tuple associated with the record. :param str bin: the name of the bin. @@ -474,7 +474,7 @@ Numeric Operations Increment the integer value in *bin* by the integer *val*. - .. include:: ./deprecate_meta.rst + .. include:: ./deprecate_meta_ttl.rst :param tuple key: a :ref:`aerospike_key_tuple` tuple associated with the record. :param str bin: the name of the bin. diff --git a/doc/deprecate_meta.rst b/doc/deprecate_meta.rst deleted file mode 100644 index 71aa7b2609..0000000000 --- a/doc/deprecate_meta.rst +++ /dev/null @@ -1,3 +0,0 @@ -.. versionchanged:: 19.1.0 - - Deprecated the ``meta`` parameter. Use the policy parameter to set ``ttl`` and ``gen`` instead. diff --git a/doc/deprecate_meta_ttl.rst b/doc/deprecate_meta_ttl.rst new file mode 100644 index 0000000000..907f1cb50c --- /dev/null +++ b/doc/deprecate_meta_ttl.rst @@ -0,0 +1,3 @@ +.. versionchanged:: 19.1.0 + + Deprecated the ``meta["ttl"]`` parameter. Use the policy parameter to set ``ttl`` instead. diff --git a/src/include/client.h b/src/include/client.h index 9d68ad0e7b..cd168c57c5 100644 --- a/src/include/client.h +++ b/src/include/client.h @@ -25,10 +25,6 @@ #define CLUSTER_NPARTITIONS (4096) -#define DEPRECATE_META_PARAMETER_WARNING_MESSAGE \ - "meta parameter is deprecated and will be removed in the " \ - "next client major release" - // This allows people to see the function calling the Python client API that issues a warning #define STACK_LEVEL 2 diff --git a/src/main/client/operate.c b/src/main/client/operate.c index b1b2c77704..3dd8b03d54 100644 --- a/src/main/client/operate.c +++ b/src/main/client/operate.c @@ -916,12 +916,6 @@ static PyObject *AerospikeClient_Operate_Invoke(AerospikeClient *self, // For expressions conversion. as_exp *exp_list_p = NULL; - - if (py_meta) { - PyErr_WarnEx(PyExc_DeprecationWarning, - DEPRECATE_META_PARAMETER_WARNING_MESSAGE, STACK_LEVEL); - } - as_vector *unicodeStrVector = as_vector_create(sizeof(char *), 128); as_operations ops; @@ -1259,11 +1253,6 @@ PyObject *AerospikeClient_OperateOrdered(AerospikeClient *self, PyObject *args, return NULL; } - if (py_meta) { - PyErr_WarnEx(PyExc_DeprecationWarning, - DEPRECATE_META_PARAMETER_WARNING_MESSAGE, STACK_LEVEL); - } - CHECK_CONNECTED(&err); if (pyobject_to_key(&err, py_key, &key) != AEROSPIKE_OK) { diff --git a/src/main/client/put.c b/src/main/client/put.c index 85f3bec22e..69296433b5 100644 --- a/src/main/client/put.c +++ b/src/main/client/put.c @@ -167,11 +167,6 @@ PyObject *AerospikeClient_Put(AerospikeClient *self, PyObject *args, return NULL; } - if (py_meta) { - PyErr_WarnEx(PyExc_DeprecationWarning, - DEPRECATE_META_PARAMETER_WARNING_MESSAGE, STACK_LEVEL); - } - if (py_serializer_option) { if (PyLong_Check(py_serializer_option)) { self->is_client_put_serializer = true; diff --git a/src/main/client/remove.c b/src/main/client/remove.c index 587a1c744a..20d49d0db5 100644 --- a/src/main/client/remove.c +++ b/src/main/client/remove.c @@ -171,7 +171,9 @@ PyObject *AerospikeClient_Remove(AerospikeClient *self, PyObject *args, if (py_meta) { PyErr_WarnEx(PyExc_DeprecationWarning, - DEPRECATE_META_PARAMETER_WARNING_MESSAGE, STACK_LEVEL); + "meta parameter is deprecated and will be removed in the " + "next client major release", + STACK_LEVEL); } // Invoke Operation diff --git a/src/main/client/remove_bin.c b/src/main/client/remove_bin.c index 0374074fc5..e0d7fc50ac 100644 --- a/src/main/client/remove_bin.c +++ b/src/main/client/remove_bin.c @@ -167,11 +167,6 @@ PyObject *AerospikeClient_RemoveBin(AerospikeClient *self, PyObject *args, return NULL; } - if (py_meta) { - PyErr_WarnEx(PyExc_DeprecationWarning, - DEPRECATE_META_PARAMETER_WARNING_MESSAGE, STACK_LEVEL); - } - if (!self || !self->as) { as_error_update(&err, AEROSPIKE_ERR_PARAM, "Invalid aerospike object"); goto CLEANUP; diff --git a/src/main/conversions.c b/src/main/conversions.c index e869275af0..0573a1cf53 100644 --- a/src/main/conversions.c +++ b/src/main/conversions.c @@ -2327,6 +2327,11 @@ as_status check_and_set_meta(PyObject *py_meta, uint32_t *ttl_ref, uint32_t ttl = 0; uint16_t gen = 0; if (py_ttl) { + PyErr_WarnEx(PyExc_DeprecationWarning, + "meta[\"ttl\"] is deprecated and will be removed in " + "the next client major release.", + STACK_LEVEL); + if (PyLong_Check(py_ttl)) { ttl = (uint32_t)PyLong_AsLong(py_ttl); } diff --git a/test/new_tests/test_append.py b/test/new_tests/test_append.py index f5082da5d4..d2fd2247e6 100644 --- a/test/new_tests/test_append.py +++ b/test/new_tests/test_append.py @@ -4,7 +4,6 @@ from aerospike import exception as e import aerospike -import warnings # @pytest.mark.usefixtures("as_connection") @@ -114,14 +113,11 @@ def test_pos_append_with_policy_key_gen_EQ_ignore(self): key = ("test", "demo", 1) policy = { "gen": aerospike.POLICY_GEN_IGNORE, + "ttl": 1200 } - meta = {"gen": 10, "ttl": 1200} - with warnings.catch_warnings(record=True) as warning_list: - self.as_connection.append(key, "name", "str", meta, policy) - - assert len(warning_list) == 1 - assert warning_list[0].category == DeprecationWarning + meta = {"gen": 10} + self.as_connection.append(key, "name", "str", meta, policy) (key, meta, bins) = self.as_connection.get(key) diff --git a/test/new_tests/test_get_put.py b/test/new_tests/test_get_put.py index 74c000d538..24516c4d4f 100644 --- a/test/new_tests/test_get_put.py +++ b/test/new_tests/test_get_put.py @@ -257,17 +257,15 @@ def test_pos_put_with_policy_exists_create_or_replace(self): key = ("test", "demo", 1) rec = {"name": "Smith"} - meta = {"gen": 2, "ttl": 25000} + meta = {"gen": 2} policy = { "exists": aerospike.POLICY_EXISTS_CREATE_OR_REPLACE, "gen": aerospike.POLICY_GEN_IGNORE, "key": aerospike.POLICY_KEY_SEND, + "ttl": 25000 } - with warnings.catch_warnings(record=True) as warning_list: - assert 0 == self.as_connection.put(key, rec, meta, policy) - assert len(warning_list) == 1 - assert warning_list[0].category == DeprecationWarning + assert 0 == self.as_connection.put(key, rec, meta, policy) (key, meta, bins) = self.as_connection.get(key) assert rec == bins diff --git a/test/new_tests/test_increment.py b/test/new_tests/test_increment.py index 9ad084c827..4aa9ba7b52 100644 --- a/test/new_tests/test_increment.py +++ b/test/new_tests/test_increment.py @@ -7,7 +7,6 @@ from aerospike import exception as e import aerospike -import warnings class TestIncrement(object): @@ -125,14 +124,11 @@ def test_increment_with_policy_key_gen_EQ_ignore(self): "key": aerospike.POLICY_KEY_SEND, "max_retries": 1, "gen": aerospike.POLICY_GEN_IGNORE, + "ttl": 1200 } - meta = {"gen": 10, "ttl": 1200} - with warnings.catch_warnings(record=True) as warning_list: - self.as_connection.increment(key, "age", 5, meta, policy) - - assert len(warning_list) == 1 - assert warning_list[0].category == DeprecationWarning + meta = {"gen": 10} + self.as_connection.increment(key, "age", 5, meta, policy) (key, meta, bins) = self.as_connection.get(key) diff --git a/test/new_tests/test_operate.py b/test/new_tests/test_operate.py index ce4406bd52..87a6ce1021 100644 --- a/test/new_tests/test_operate.py +++ b/test/new_tests/test_operate.py @@ -4,7 +4,6 @@ import aerospike from aerospike import exception as e -import warnings # OPERATIONS # aerospike.OPERATOR_WRITE @@ -283,8 +282,9 @@ def test_pos_operate_with_policy_key_digest(self): "key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_IGNORE, "commit_level": aerospike.POLICY_COMMIT_LEVEL_ALL, + "ttl": 1200 }, - {"gen": 10, "ttl": 1200}, + {"gen": 10}, [ {"op": aerospike.OPERATOR_APPEND, "bin": "name", "val": "aa"}, {"op": aerospike.OPERATOR_INCR, "bin": "age", "val": 3}, @@ -298,10 +298,7 @@ def test_pos_operate_with_policy_gen_ignore(self, key, policy, meta, llist): Invoke operate() with gen ignore. """ - with warnings.catch_warnings(record=True) as warning_list: - key, meta, bins = self.as_connection.operate(key, llist, meta, policy) - assert len(warning_list) == 1 - assert warning_list[0].category == DeprecationWarning + key, meta, bins = self.as_connection.operate(key, llist, meta, policy) assert bins == {"name": "name1aa"} assert key == ( diff --git a/test/new_tests/test_operate_ordered.py b/test/new_tests/test_operate_ordered.py index f940965a0c..2ea94c3527 100644 --- a/test/new_tests/test_operate_ordered.py +++ b/test/new_tests/test_operate_ordered.py @@ -209,8 +209,9 @@ def test_pos_operate_ordered_with_policy_key_digest(self): "key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_IGNORE, "commit_level": aerospike.POLICY_COMMIT_LEVEL_ALL, + "ttl": 1200 }, - {"gen": 10, "ttl": 1200}, + {"gen": 10}, [ {"op": aerospike.OPERATOR_APPEND, "bin": "name", "val": "aa"}, {"op": aerospike.OPERATOR_INCR, "bin": "age", "val": 3}, @@ -223,10 +224,7 @@ def test_pos_operate_ordered_policy_gen_ignore(self, key, policy, meta, llist): """ Invoke operate_ordered() with gen ignore. """ - with warnings.catch_warnings(record=True) as warning_list: - key, meta, bins = self.as_connection.operate_ordered(key, llist, meta, policy) - assert len(warning_list) == 1 - assert warning_list[0].category == DeprecationWarning + key, meta, bins = self.as_connection.operate_ordered(key, llist, meta, policy) assert bins == [("name", "name1aa")] diff --git a/test/new_tests/test_prepend.py b/test/new_tests/test_prepend.py index e5b67bd8e1..f04af0e2d4 100644 --- a/test/new_tests/test_prepend.py +++ b/test/new_tests/test_prepend.py @@ -4,7 +4,6 @@ from .test_base_class import TestBaseClass import aerospike from aerospike import exception as e -import warnings class TestPrepend: @@ -99,13 +98,11 @@ def test_pos_prepend_with_policy_key_gen_EQ_ignore(self): "key": aerospike.POLICY_KEY_SEND, "max_retries": 1, "gen": aerospike.POLICY_GEN_IGNORE, + "ttl": 1200 } - meta = {"gen": 10, "ttl": 1200} - with warnings.catch_warnings(record=True) as warning_list: - self.as_connection.prepend(key, "name", "str", meta, policy) - assert len(warning_list) == 1 - assert warning_list[0].category == DeprecationWarning + meta = {"gen": 10} + self.as_connection.prepend(key, "name", "str", meta, policy) (key, meta, bins) = self.as_connection.get(key) diff --git a/test/new_tests/test_remove.py b/test/new_tests/test_remove.py index 55643433f1..c0ed09126e 100644 --- a/test/new_tests/test_remove.py +++ b/test/new_tests/test_remove.py @@ -6,7 +6,6 @@ from .test_base_class import TestBaseClass import aerospike from aerospike import exception as e -import warnings @pytest.mark.usefixtures("as_connection") From 2d4b471f6f61acf3c0821c765451b0049d022bd6 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Wed, 25 Feb 2026 13:01:34 -0800 Subject: [PATCH 35/73] Add missing allowed key --- src/main/aerospike.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/aerospike.c b/src/main/aerospike.c index 42455f6966..380638dd2f 100644 --- a/src/main/aerospike.c +++ b/src/main/aerospike.c @@ -671,7 +671,8 @@ DEFINE_SET_OF_VALID_KEYS(client_config_policies, "read", "write", "apply", "txn_roll", "total_timeout", "auth_mode", "login_timeout_ms", "key", "exists", "max_retries", "replica", "commit_level", "metrics", "read_mode_ap", - "max_threads", "thread_pool_size", NULL) + "max_threads", "thread_pool_size", "socket_timeout", + NULL) DEFINE_SET_OF_VALID_KEYS(client_config_tls, "enable", "cafile", "capath", "protocols", "cipher_suite", "keyfile", "keyfile_pw", From a7c719c7ab051605e52eb32e01a606b4aa724809 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Wed, 25 Feb 2026 13:32:40 -0800 Subject: [PATCH 36/73] Smoke tests: have pytest fail if an unhandled warning is raised --- .github/workflows/smoke-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/smoke-tests.yml b/.github/workflows/smoke-tests.yml index a5e950df1b..3d7c60ad31 100644 --- a/.github/workflows/smoke-tests.yml +++ b/.github/workflows/smoke-tests.yml @@ -306,7 +306,7 @@ jobs: - name: Run tests # We need to disable capturing output or else we cannot see memory errors reported by # libasan during the test run - run: python -m pytest ./new_tests -vvs + run: python -m pytest ./new_tests -vvs -W error working-directory: test test-ce: @@ -369,7 +369,7 @@ jobs: container-name: aerospike - name: Run tests - run: python -m pytest ./new_tests -vv -W error::pytest.PytestUnraisableExceptionWarning + run: python -m pytest ./new_tests -vv working-directory: test test-ee: From b026fd34c43aae4840c707b6bacdd67d9fa6301c Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Wed, 25 Feb 2026 13:45:54 -0800 Subject: [PATCH 37/73] Address warnings --- test/new_tests/test_log.py | 2 +- test/new_tests/test_operate_helpers.py | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/test/new_tests/test_log.py b/test/new_tests/test_log.py index 0a222eef80..554cefcc79 100644 --- a/test/new_tests/test_log.py +++ b/test/new_tests/test_log.py @@ -13,7 +13,7 @@ def custom_log_callback(level, func, path, line, msg): callback_called = True class TestLog(object): - @pytest.mark.fixture(autouse=True) + @pytest.fixture(autouse=True) def setup(self): global callback_called callback_called = False diff --git a/test/new_tests/test_operate_helpers.py b/test/new_tests/test_operate_helpers.py index d61a2e2a28..336bdfef5f 100644 --- a/test/new_tests/test_operate_helpers.py +++ b/test/new_tests/test_operate_helpers.py @@ -5,6 +5,7 @@ import aerospike from aerospike import exception as e +import warnings # OPERATIONS # aerospike.OPERATOR_WRITE @@ -317,7 +318,10 @@ def test_pos_operate_touch_operation_with_bin_and_value_combination(self, key, l Invoke operate() with touch value with bin and value combination. """ - self.as_connection.operate(key, llist) + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter(action="always", category=DeprecationWarning) + self.as_connection.operate(key, llist) + assert len(w) == 2 (key, meta) = self.as_connection.exists(key) From 8d92320002c7e60d9d78ddbe65f562bfa494921f Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Wed, 25 Feb 2026 13:57:43 -0800 Subject: [PATCH 38/73] Fix test not handling DeprecationWarning from operations.touch --- test/new_tests/test_operate_helpers.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/test/new_tests/test_operate_helpers.py b/test/new_tests/test_operate_helpers.py index 336bdfef5f..0151eadb43 100644 --- a/test/new_tests/test_operate_helpers.py +++ b/test/new_tests/test_operate_helpers.py @@ -311,17 +311,22 @@ def test_pos_operate_with_policy_gen_EQ(self): assert bins == {"name": "name1aa"} @pytest.mark.parametrize( - "key, llist", [(("test", "demo", 1), [operations.touch(4000)]), (("test", "demo", 1), [operations.touch(4000)])] + "key", [ + ("test", "demo", 1) + ] ) - def test_pos_operate_touch_operation_with_bin_and_value_combination(self, key, llist): + def test_pos_operate_touch_operation_with_bin_and_value_combination(self, key): """ Invoke operate() with touch value with bin and value combination. """ with warnings.catch_warnings(record=True) as w: warnings.simplefilter(action="always", category=DeprecationWarning) - self.as_connection.operate(key, llist) - assert len(w) == 2 + ops = [ + operations.touch(4000) + ] + assert len(w) == 1 + self.as_connection.operate(key, ops) (key, meta) = self.as_connection.exists(key) From 1a8f297d139e9a86aab2268441799f0c70ecd7f3 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Wed, 25 Feb 2026 14:12:39 -0800 Subject: [PATCH 39/73] Prevent unhandled warning --- test/new_tests/test_compress.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/test/new_tests/test_compress.py b/test/new_tests/test_compress.py index bce492b128..828fdd2cdc 100644 --- a/test/new_tests/test_compress.py +++ b/test/new_tests/test_compress.py @@ -122,9 +122,5 @@ def test_scan_with_compress_policy(self): """ Invoke execute_background() for a scan with compression enabled. """ - - ops = [operations.touch()] - scan_obj = self.as_connection.scan("test", "demo") - scan_obj.add_ops(ops) - scan_obj.execute_background({"compress": True}) + scan_obj.execute_background({"compress": True, "ttl": aerospike.TTL_NAMESPACE_DEFAULT}) From e9f302075b35206982a2aea6411994847374e9eb Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Thu, 26 Feb 2026 08:34:55 -0800 Subject: [PATCH 40/73] Just raise error for DeprecationWarnings specifically. Somehow raising errors for all warnings is causing strange AerospikeError exceptions to be raised --- .github/workflows/smoke-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/smoke-tests.yml b/.github/workflows/smoke-tests.yml index 52701f4a7d..706a16bdb1 100644 --- a/.github/workflows/smoke-tests.yml +++ b/.github/workflows/smoke-tests.yml @@ -306,7 +306,7 @@ jobs: - name: Run tests # We need to disable capturing output or else we cannot see memory errors reported by # libasan during the test run - run: python -m pytest ./new_tests -vvs -W error + run: python -m pytest ./new_tests -vvs -W error::DeprecationWarning working-directory: test test-ce: @@ -369,7 +369,7 @@ jobs: container-name: aerospike - name: Run tests - run: python -m pytest ./new_tests -vv + run: python -m pytest ./new_tests -vv -W error::pytest.PytestUnraisableExceptionWarning working-directory: test test-ee: From 19e433a88c477b92d6e9799e00453a4a6fe6110e Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Thu, 26 Feb 2026 08:36:58 -0800 Subject: [PATCH 41/73] Doc: fix index_cdt_create being listed under aerospike module instead of aerospike.Client --- doc/client.rst | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/doc/client.rst b/doc/client.rst index ca355e6af3..59904fb7b7 100755 --- a/doc/client.rst +++ b/doc/client.rst @@ -1032,23 +1032,23 @@ Index Operations client.index_geo2dsphere_create('test', 'pads', 'loc', 'pads_loc_geo') client.close() -.. method:: index_cdt_create(ns: str, set: str, bin: str, index_type, index_datatype, index_name: str, ctx: list[, policy: dict]) - - .. deprecated:: 20.0.0 Use the other non-deprecated index methods to create an index with a list of contexts. - - Create an collection data type (CDT) index named *index_name* for a scalar, list values, map keys, or map values (as defined by *index_type*) and for - numeric, string, or GeoJSON values (as defined by *index_datatype*) - on records of the specified *ns*, *set* whose bin is a list or map. - - :param str ns: the namespace in the aerospike cluster. - :param str set: the set name. - :param str bin: the name of bin the secondary index is built on. - :param index_type: whether we are querying a single scalar value or specific values of a CDT type. See :ref:`aerospike_index_types`. - :param index_datatype: the type of value being queried on. See :ref:`aerospike_index_datatypes`. - :param str index_name: the name of the index. - :param dict ctx: a :class:`list` of contexts produced by :mod:`aerospike_helpers.cdt_ctx` methods. - :param dict policy: optional :ref:`aerospike_info_policies`. - :raises: a subclass of :exc:`~aerospike.exception.AerospikeError`. + .. method:: index_cdt_create(ns: str, set: str, bin: str, index_type, index_datatype, index_name: str, ctx: list[, policy: dict]) + + .. deprecated:: 20.0.0 Use the other non-deprecated index methods to create an index with a list of contexts. + + Create an collection data type (CDT) index named *index_name* for a scalar, list values, map keys, or map values (as defined by *index_type*) and for + numeric, string, or GeoJSON values (as defined by *index_datatype*) + on records of the specified *ns*, *set* whose bin is a list or map. + + :param str ns: the namespace in the aerospike cluster. + :param str set: the set name. + :param str bin: the name of bin the secondary index is built on. + :param index_type: whether we are querying a single scalar value or specific values of a CDT type. See :ref:`aerospike_index_types`. + :param index_datatype: the type of value being queried on. See :ref:`aerospike_index_datatypes`. + :param str index_name: the name of the index. + :param dict ctx: a :class:`list` of contexts produced by :mod:`aerospike_helpers.cdt_ctx` methods. + :param dict policy: optional :ref:`aerospike_info_policies`. + :raises: a subclass of :exc:`~aerospike.exception.AerospikeError`. .. index:: single: Admin Operations From ee81b6bb16591dda7b04896d4846e3b3715d6f9f Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Thu, 26 Feb 2026 08:54:57 -0800 Subject: [PATCH 42/73] touch() on its own isn't deprecated, only the ttl parameter --- test/new_tests/test_compress.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/new_tests/test_compress.py b/test/new_tests/test_compress.py index 828fdd2cdc..bce492b128 100644 --- a/test/new_tests/test_compress.py +++ b/test/new_tests/test_compress.py @@ -122,5 +122,9 @@ def test_scan_with_compress_policy(self): """ Invoke execute_background() for a scan with compression enabled. """ + + ops = [operations.touch()] + scan_obj = self.as_connection.scan("test", "demo") - scan_obj.execute_background({"compress": True, "ttl": aerospike.TTL_NAMESPACE_DEFAULT}) + scan_obj.add_ops(ops) + scan_obj.execute_background({"compress": True}) From 60e7fa0f6d9f67c0e0adab818f0bc785125f68da Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Thu, 26 Feb 2026 11:37:09 -0800 Subject: [PATCH 43/73] Handle bug where python client does not exit when it gives a warning and pytest/python converts it to an exception. --- src/main/client/remove.c | 12 ++++++++---- src/main/client/sec_index.c | 12 ++++++++---- src/main/conversions.c | 17 +++++++++++++---- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/main/client/remove.c b/src/main/client/remove.c index 20d49d0db5..345d3702a3 100644 --- a/src/main/client/remove.c +++ b/src/main/client/remove.c @@ -170,10 +170,14 @@ PyObject *AerospikeClient_Remove(AerospikeClient *self, PyObject *args, } if (py_meta) { - PyErr_WarnEx(PyExc_DeprecationWarning, - "meta parameter is deprecated and will be removed in the " - "next client major release", - STACK_LEVEL); + int retval = PyErr_WarnEx( + PyExc_DeprecationWarning, + "meta parameter is deprecated and will be removed in the " + "next client major release", + STACK_LEVEL); + if (retval == -1) { + return NULL; + } } // Invoke Operation diff --git a/src/main/client/sec_index.c b/src/main/client/sec_index.c index 0622f3f16d..e2d96d74a8 100644 --- a/src/main/client/sec_index.c +++ b/src/main/client/sec_index.c @@ -466,10 +466,14 @@ PyObject *AerospikeClient_Index_2dsphere_Create(AerospikeClient *self, PyObject *AerospikeClient_Index_Cdt_Create(AerospikeClient *self, PyObject *args, PyObject *kwds) { - PyErr_WarnEx(PyExc_DeprecationWarning, - "index_cdt_create() is deprecated. Please use one of the " - "other non-deprecated index_*_create() methods instead", - STACK_LEVEL); + int retval = + PyErr_WarnEx(PyExc_DeprecationWarning, + "index_cdt_create() is deprecated. Please use one of the " + "other non-deprecated index_*_create() methods instead", + STACK_LEVEL); + if (retval == -1) { + return NULL; + } // Initialize error as_error err; diff --git a/src/main/conversions.c b/src/main/conversions.c index 0573a1cf53..98a49c277b 100644 --- a/src/main/conversions.c +++ b/src/main/conversions.c @@ -2289,6 +2289,10 @@ void initialize_bin_for_strictypes(AerospikeClient *self, as_error *err, strcpy(binop_bin->name, bin); } +#define META_TTL_DEPRECATION_MESSAGE \ + "meta[\"ttl\"] is deprecated and will be removed in " \ + "the next client major release." + /** ******************************************************************************************************* * This function checks for metadata and if present set it into the @@ -2327,10 +2331,15 @@ as_status check_and_set_meta(PyObject *py_meta, uint32_t *ttl_ref, uint32_t ttl = 0; uint16_t gen = 0; if (py_ttl) { - PyErr_WarnEx(PyExc_DeprecationWarning, - "meta[\"ttl\"] is deprecated and will be removed in " - "the next client major release.", - STACK_LEVEL); + int retval = + PyErr_WarnEx(PyExc_DeprecationWarning, + META_TTL_DEPRECATION_MESSAGE, STACK_LEVEL); + if (retval == -1) { + // This handles the codepath where warnings are converted into errors from pytest/python cli + // TODO: this does NOT handle the codepath where the warning mechanism itself fails + return as_error_update(err, AEROSPIKE_ERR, + META_TTL_DEPRECATION_MESSAGE); + } if (PyLong_Check(py_ttl)) { ttl = (uint32_t)PyLong_AsLong(py_ttl); From 4f00ff06ee22859f7d69e64f89fdc41f659ffbe7 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Thu, 26 Feb 2026 11:43:07 -0800 Subject: [PATCH 44/73] Revert --- src/main/client/operate.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/client/operate.c b/src/main/client/operate.c index 3dd8b03d54..b743252b83 100644 --- a/src/main/client/operate.c +++ b/src/main/client/operate.c @@ -916,6 +916,7 @@ static PyObject *AerospikeClient_Operate_Invoke(AerospikeClient *self, // For expressions conversion. as_exp *exp_list_p = NULL; + as_vector *unicodeStrVector = as_vector_create(sizeof(char *), 128); as_operations ops; From 4524bf0cd094afeb4a2a020ae6cbb5798150fb57 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Thu, 26 Feb 2026 08:47:10 -0800 Subject: [PATCH 45/73] As a temporary workaround, ignore warnings from test_cdt_index.py --- test/new_tests/test_cdt_index.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/new_tests/test_cdt_index.py b/test/new_tests/test_cdt_index.py index b894b3d647..931665e897 100644 --- a/test/new_tests/test_cdt_index.py +++ b/test/new_tests/test_cdt_index.py @@ -7,6 +7,7 @@ from .index_helpers import ensure_dropped_index from aerospike_helpers import cdt_ctx + list_index = "list_index" list_rank = "list_rank" list_value = "list_value" @@ -53,6 +54,7 @@ def add_ctx_op(ctx_type, value): ctx_map_value.append(add_ctx_op(map_value, 3)) +@pytest.mark.filterwarnings("ignore:as_connection") class TestCDTIndex(object): @pytest.fixture(autouse=True) def setup(self, request, as_connection): From c8931807ffb70d34bb08ca27a5b867e5f7ba370d Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Thu, 26 Feb 2026 14:11:21 -0800 Subject: [PATCH 46/73] Test config level ttl for all APIs involved with this change except BatchRecord Read --- test/new_tests/test_append.py | 9 +- test/new_tests/test_batch_write.py | 6 +- .../test_client_config_level_options.py | 139 +++++++++++------- 3 files changed, 96 insertions(+), 58 deletions(-) diff --git a/test/new_tests/test_append.py b/test/new_tests/test_append.py index d2fd2247e6..361ac1402e 100644 --- a/test/new_tests/test_append.py +++ b/test/new_tests/test_append.py @@ -161,11 +161,12 @@ def test_pos_append_with_policy_key_gen_GT_positive(self): key = ("test", "demo", 1) policy = { "gen": aerospike.POLICY_GEN_GT, + "ttl": 1200 } (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen + 2, "ttl": 1200} + meta = {"gen": gen + 2} self.as_connection.append(key, "name", "str", meta, policy) (key, meta, bins) = self.as_connection.get(key) @@ -295,12 +296,13 @@ def test_neg_append_with_policy_key_gen_GT_lesser(self): key = ("test", "demo", 1) policy = { "gen": aerospike.POLICY_GEN_GT, + "ttl": 1200 } (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen, "ttl": 1200} + meta = {"gen": gen} try: self.as_connection.append(key, "name", "str", meta, policy) except e.RecordGenerationError as exception: @@ -322,11 +324,12 @@ def test_neg_append_with_policy_key_gen_EQ_not_equal(self): key = ("test", "demo", 1) policy = { "gen": aerospike.POLICY_GEN_EQ, + "ttl": 1200 } (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen + 5, "ttl": 1200} + meta = {"gen": gen + 5} try: self.as_connection.append(key, "name", "str", meta, policy) diff --git a/test/new_tests/test_batch_write.py b/test/new_tests/test_batch_write.py index ea4c17e7d9..20181d629f 100644 --- a/test/new_tests/test_batch_write.py +++ b/test/new_tests/test_batch_write.py @@ -123,12 +123,13 @@ def teardown(): br.Write( ("test", "demo", 1), [op.write("new", 10), op.read("new")], - meta={"gen": 1, "ttl": aerospike.TTL_NEVER_EXPIRE}, + meta={"gen": 1}, policy={ "key": aerospike.POLICY_KEY_SEND, "commit_level": aerospike.POLICY_COMMIT_LEVEL_MASTER, "gen": aerospike.POLICY_GEN_IGNORE, "exists": aerospike.POLICY_EXISTS_UPDATE, + "ttl": aerospike.TTL_NEVER_EXPIRE, "durable_delete": False, "expressions": exp.Eq(exp.IntBin("count"), 1).compile(), }, @@ -186,9 +187,10 @@ def teardown(): br.Write( ("test", "demo", 1), [op.write("new", 10), op.read("new")], - meta={"gen": 1, "ttl": aerospike.TTL_NEVER_EXPIRE}, + meta={"gen": 1}, policy={ "expressions": exp.Eq(exp.IntBin("count"), 1).compile(), + "ttl": aerospike.TTL_NEVER_EXPIRE }, ) ] diff --git a/test/new_tests/test_client_config_level_options.py b/test/new_tests/test_client_config_level_options.py index dd13447174..f8d4875fad 100644 --- a/test/new_tests/test_client_config_level_options.py +++ b/test/new_tests/test_client_config_level_options.py @@ -352,7 +352,7 @@ def config_ttl_setup(self, policy_name: str): "ttl": self.NEW_TTL } self.client = aerospike.client(config) - self.client.put(KEY, {"a": "a", "b": "b"}) + self.client.put(KEY, {"a": "a", "b": "b", "c": 1}) if "apply" in policy_name: self.client.udf_put("test_record_udf.lua") @@ -375,55 +375,67 @@ def config_ttl_setup(self, policy_name: str): self.client.close() - @pytest.mark.parametrize("policy_name", ["write"]) - @pytest.mark.parametrize( - "meta", - [None, {"ttl": aerospike.TTL_CLIENT_DEFAULT}, {"gen": 10}], - ids=["no metadata", "metadata with special ttl value", "metadata without ttl"] - ) - @pytest.mark.parametrize("api_method, kwargs", [ - (aerospike.Client.put, {"key": KEY, "bins": {"a": 1}}), - (aerospike.Client.remove_bin, {"key": KEY, "list": ["a"]}), - ]) - def test_setting_write_ttl(self, config_ttl_setup, meta, api_method, kwargs): - api_method(self.client, **kwargs, meta=meta) - verify_record_ttl(self.client, KEY, expected_ttl=self.NEW_TTL) - - @pytest.mark.parametrize("policy_name", ["operate"]) - @pytest.mark.parametrize( - "meta", - [None, {"ttl": aerospike.TTL_CLIENT_DEFAULT}, {"gen": 10}], - ids=["no metadata", "metadata with special ttl value", "metadata without ttl"] - ) - def test_setting_operate_ttl(self, config_ttl_setup, meta): - ops = [ - operations.write("a", 1) + ttl_param = pytest.mark.parametrize( + "kwargs_with_ttl", + [ + {"meta": None}, + {"meta": {"gen": 10}}, + {"meta": {"ttl": aerospike.TTL_CLIENT_DEFAULT, "gen": 10}}, + {"policy": None}, + {"policy": {}}, + {"policy": {"ttl": aerospike.TTL_CLIENT_DEFAULT}} ] - self.client.operate(KEY, ops, meta=meta) - verify_record_ttl(self.client, KEY, expected_ttl=self.NEW_TTL) - - @pytest.mark.parametrize("policy_name", ["apply"]) - def test_setting_apply_ttl(self, config_ttl_setup): - # Setup - self.client.put(KEY, {"bin": "a"}) + ) - # Call without setting the ttl in the command's apply policy - # Args: bin name, str - self.client.apply(KEY, module="test_record_udf", function="bin_udf_operation_string", args=["bin", "a"]) + @ttl_param + @pytest.mark.parametrize("api_method, kwargs, policy_name", [ + ( + aerospike.Client.put, + {"key": KEY, "bins": {"a": 1}}, + "write" + ), + ( + aerospike.Client.remove_bin, + {"key": KEY, "list": ["a"]}, + "write" + ), + ( + aerospike.Client.operate, + {"key": KEY, "list": [operations.write("a", 1)]}, "operate" + ), + ( + aerospike.Client.operate_ordered, + {"key": KEY, "list": [operations.write("a", 1)]}, "operate" + ), + ( + aerospike.Client.increment, + {"key": KEY, "bin": "c", "offset": 1}, + "operate" + ), + ( + aerospike.Client.prepend, + {"key": KEY, "bin": "a", "val": "a"}, + "operate" + ), + ( + aerospike.Client.touch, + {"key": KEY}, + "operate" + ), + ]) + def test_apis_with_meta_parameter(self, config_ttl_setup, api_method, kwargs: dict, kwargs_with_ttl: dict): + kwargs |= kwargs_with_ttl + api_method(self.client, **kwargs) verify_record_ttl(self.client, KEY, expected_ttl=self.NEW_TTL) + @ttl_param @pytest.mark.parametrize("policy_name", ["batch_write"]) - @pytest.mark.parametrize( - "meta", - [None, {"ttl": aerospike.TTL_CLIENT_DEFAULT}], - ids=["no metadata", "metadata with special ttl value"] - ) - def test_setting_batch_write_ttl_with_batch_write(self, config_ttl_setup, meta): + def test_batch_write(self, config_ttl_setup, kwargs_with_ttl): ops = [ operations.write("bin", 1) ] batch_records = BatchRecords([ - Write(KEY, ops=ops, meta=meta) + Write(KEY, ops=ops, **kwargs_with_ttl) ]) brs = self.client.batch_write(batch_records) # assert brs.result == 0 @@ -432,33 +444,54 @@ def test_setting_batch_write_ttl_with_batch_write(self, config_ttl_setup, meta): verify_record_ttl(self.client, KEY, expected_ttl=self.NEW_TTL) - @pytest.mark.parametrize("policy_name", ["batch_write"]) @pytest.mark.parametrize( - "ttl", - [None, aerospike.TTL_CLIENT_DEFAULT], + "kwargs", + [ + {}, + {"ttl": {"ttl": None}}, + {"ttl": {"ttl": aerospike.TTL_CLIENT_DEFAULT}} + ], ) - def test_setting_batch_write_ttl_with_batch_operate(self, config_ttl_setup, ttl): + @pytest.mark.parametrize("policy_name", ["batch"]) + def test_apis_with_ttl_parameter(self, config_ttl_setup, kwargs): ops = [ operations.write("bin", 1) ] keys = [KEY] - brs = self.client.batch_operate(keys, ops, ttl=ttl) + brs = self.client.batch_operate(keys, ops, **kwargs) # assert brs.result == 0 for br in brs.batch_records: assert br.result == 0 verify_record_ttl(self.client, KEY, expected_ttl=self.NEW_TTL) - @pytest.mark.parametrize("policy_name", ["batch_apply"]) - def test_setting_batch_apply_ttl(self, config_ttl_setup): + @pytest.mark.parametrize( + "kwargs_with_ttl", + [ + {}, + {"policy": {"ttl": None}}, + {"policy": {"ttl": aerospike.TTL_CLIENT_DEFAULT}} + ], + ) + @pytest.mark.parametrize("api_method, kwargs, policy_name", [ + ( + aerospike.Client.apply, + {"key": KEY}, + "apply" + ), + ( + aerospike.Client.batch_apply, + {"keys": [KEY]}, + "batch_apply" + ), + ]) + def test_apis_with_policy_parameter(self, config_ttl_setup, api_method, kwargs, kwargs_with_ttl): # Setup self.client.put(KEY, {"bin": "a"}) - # Call without setting the ttl in batch_apply()'s batch apply policy - keys = [ - KEY - ] - self.client.batch_apply(keys, module="test_record_udf", function="bin_udf_operation_string", args=["bin", "a"]) + kwargs |= {"module": "test_record_udf", "function": "bin_udf_operation_string", "args": ["bin", "a"]} + kwargs |= kwargs_with_ttl + api_method(self.client, **kwargs) verify_record_ttl(self.client, KEY, expected_ttl=self.NEW_TTL) @pytest.mark.parametrize("policy_name", ["scan"]) From ab6a28fc99275fd0f12188939fad0a9c776065dc Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Thu, 26 Feb 2026 14:18:15 -0800 Subject: [PATCH 47/73] Explicitly test setting command level ttl option via meta parameter --- test/new_tests/test_command_level_policies.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/test/new_tests/test_command_level_policies.py b/test/new_tests/test_command_level_policies.py index 00e94592a2..50d1d642c0 100644 --- a/test/new_tests/test_command_level_policies.py +++ b/test/new_tests/test_command_level_policies.py @@ -17,15 +17,23 @@ class CommandLevelTTL: NEW_TTL = 3000 POLICY = {"ttl": NEW_TTL} - def test_write_policy(self): - self.as_connection.put(KEY, bins={"a": 1}, policy=self.POLICY) + pytestmark = pytest.mark.parametrize( + "kwargs_with_ttl", + [ + {"meta": POLICY}, + {"policy": POLICY}, + ] + ) + + def test_write_policy(self, kwargs_with_ttl): + self.as_connection.put(KEY, bins={"a": 1}, **kwargs_with_ttl) verify_record_ttl(self.client, KEY, expected_ttl=self.NEW_TTL) - def test_operate_policy(self): + def test_operate_policy(self, kwargs_with_ttl): ops = [ operations.write(bin_name="a", write_item=1) ] - self.as_connection.operate(KEY, list=ops, policy=self.POLICY) + self.as_connection.operate(KEY, list=ops, **kwargs_with_ttl) verify_record_ttl(self.client, KEY, expected_ttl=self.NEW_TTL) def test_batch_write_policy(self): From 45d071a159f7e751ad23996c789f1f5336457763 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Thu, 26 Feb 2026 15:25:33 -0800 Subject: [PATCH 48/73] WIP replace all deprecated usages of meta['ttl'] with policy['ttl'] --- test/new_tests/test_append.py | 3 ++- .../test_client_config_level_options.py | 8 +++---- test/new_tests/test_command_level_policies.py | 2 +- test/new_tests/test_exists.py | 4 ++-- test/new_tests/test_expressions_everywhere.py | 4 ++-- test/new_tests/test_get_put.py | 12 ++++++---- test/new_tests/test_increment.py | 12 ++++++---- test/new_tests/test_operate.py | 22 +++++++++---------- test/new_tests/test_operate_helpers.py | 7 +++--- test/new_tests/test_operate_ordered.py | 12 +++++----- test/new_tests/test_prepend.py | 12 ++++++---- test/new_tests/test_query_expressions.py | 4 ++-- test/new_tests/test_remove_bin.py | 17 +++++++++----- test/new_tests/test_touch.py | 19 ++++++++++------ test/new_tests/test_validate_keys.py | 2 +- 15 files changed, 82 insertions(+), 58 deletions(-) diff --git a/test/new_tests/test_append.py b/test/new_tests/test_append.py index 361ac1402e..6e41bee6bf 100644 --- a/test/new_tests/test_append.py +++ b/test/new_tests/test_append.py @@ -136,12 +136,13 @@ def test_pos_append_with_policy_key_gen_EQ_positive(self): key = ("test", "demo", 1) policy = { "gen": aerospike.POLICY_GEN_EQ, + "ttl": 1200 } (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen, "ttl": 1200} + meta = {"gen": gen} self.as_connection.append(key, "name", "str", meta, policy) (key, meta, bins) = self.as_connection.get(key) diff --git a/test/new_tests/test_client_config_level_options.py b/test/new_tests/test_client_config_level_options.py index f8d4875fad..7cfbff7a5f 100644 --- a/test/new_tests/test_client_config_level_options.py +++ b/test/new_tests/test_client_config_level_options.py @@ -383,7 +383,6 @@ def config_ttl_setup(self, policy_name: str): {"meta": {"ttl": aerospike.TTL_CLIENT_DEFAULT, "gen": 10}}, {"policy": None}, {"policy": {}}, - {"policy": {"ttl": aerospike.TTL_CLIENT_DEFAULT}} ] ) @@ -448,8 +447,8 @@ def test_batch_write(self, config_ttl_setup, kwargs_with_ttl): "kwargs", [ {}, - {"ttl": {"ttl": None}}, - {"ttl": {"ttl": aerospike.TTL_CLIENT_DEFAULT}} + {"ttl": None}, + {"ttl": aerospike.TTL_CLIENT_DEFAULT} ], ) @pytest.mark.parametrize("policy_name", ["batch"]) @@ -470,7 +469,6 @@ def test_apis_with_ttl_parameter(self, config_ttl_setup, kwargs): [ {}, {"policy": {"ttl": None}}, - {"policy": {"ttl": aerospike.TTL_CLIENT_DEFAULT}} ], ) @pytest.mark.parametrize("api_method, kwargs, policy_name", [ @@ -515,7 +513,7 @@ def test_setting_scan_ttl(self, config_ttl_setup): @pytest.mark.parametrize("policy_name", ["write"]) def test_query_client_default_ttl(self, config_ttl_setup): # Setup - self.client.put(KEY, {"bin": "a"}, meta={"ttl": 90}) + self.client.put(KEY, {"bin": "a"}, policy={"ttl": 90}) # Tell scan to use client config's write policy ttl query = self.client.query("test", "demo") diff --git a/test/new_tests/test_command_level_policies.py b/test/new_tests/test_command_level_policies.py index 50d1d642c0..af0c217c91 100644 --- a/test/new_tests/test_command_level_policies.py +++ b/test/new_tests/test_command_level_policies.py @@ -59,7 +59,7 @@ class TestReadTouchTTLPercent: @pytest.fixture(autouse=True) def setup(self, as_connection): ttl = 2 - self.as_connection.put(KEY, bins={"a": 1}, meta={"ttl": ttl}) + self.as_connection.put(KEY, bins={"a": 1}, policy={"ttl": ttl}) self.policy = { "read_touch_ttl_percent": 50 } diff --git a/test/new_tests/test_exists.py b/test/new_tests/test_exists.py index c27038c531..51d06b5ff1 100644 --- a/test/new_tests/test_exists.py +++ b/test/new_tests/test_exists.py @@ -68,8 +68,8 @@ def test_pos_exists_with_key_and_policy1(self, key, record, policy, put_data): def test_neg_exists_with_record_expiry(self, put_data): key = ("test", "demo", 30) rec = {"name": "John"} - meta = {"gen": 3, "ttl": 1} - put_data(self.as_connection, key, rec, meta) + meta = {"gen": 3} + put_data(self.as_connection, key, rec, meta, {"ttl": 1}) time.sleep(2) key, meta = self.as_connection.exists(key) diff --git a/test/new_tests/test_expressions_everywhere.py b/test/new_tests/test_expressions_everywhere.py index 2541054d0a..8999eb51c3 100644 --- a/test/new_tests/test_expressions_everywhere.py +++ b/test/new_tests/test_expressions_everywhere.py @@ -417,7 +417,7 @@ def test_expressions_key_operate_record_void_time(self): for i in range(5): key = "test", "pred_ttl", i - self.as_connection.put(key, {"time": "earlier"}, meta={"ttl": 100}) + self.as_connection.put(key, {"time": "earlier"}, policy={"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 @@ -426,7 +426,7 @@ def test_expressions_key_operate_record_void_time(self): for i in range(5, 10): key = "test", "pred_ttl", i - self.as_connection.put(key, {"time": "later"}, meta={"ttl": 1000}) + self.as_connection.put(key, {"time": "later"}, policy={"ttl": 1000}) results = [] diff --git a/test/new_tests/test_get_put.py b/test/new_tests/test_get_put.py index 24516c4d4f..6d3719598b 100644 --- a/test/new_tests/test_get_put.py +++ b/test/new_tests/test_get_put.py @@ -271,12 +271,13 @@ def test_pos_put_with_policy_exists_create_or_replace(self): assert rec == bins rec = {"name": "John"} - meta = {"gen": 2, "ttl": 25000} + meta = {"gen": 2} policy = { "exists": aerospike.POLICY_EXISTS_CREATE_OR_REPLACE, "gen": aerospike.POLICY_GEN_IGNORE, "max_retries": 1, "key": aerospike.POLICY_KEY_SEND, + "ttl": 25000 } assert 0 == self.as_connection.put(key, rec, meta, policy) @@ -291,12 +292,13 @@ def test_pos_put_with_policy_exists_ignore_create(self): key = ("test", "demo", 1) rec = {"name": "Smith"} - meta = {"gen": 2, "ttl": 25000} + meta = {"gen": 2} policy = { "exists": aerospike.POLICY_EXISTS_IGNORE, "gen": aerospike.POLICY_GEN_IGNORE, "max_retries": 1, "key": aerospike.POLICY_KEY_SEND, + "ttl": 25000 } assert 0 == self.as_connection.put(key, rec, meta, policy) @@ -312,12 +314,13 @@ def test_pos_put_with_policy_exists_ignore_update(self): key = ("test", "demo", 1) rec = {"name": "Smith"} - meta = {"gen": 2, "ttl": 25000} + meta = {"gen": 2} policy = { "exists": aerospike.POLICY_EXISTS_IGNORE, "gen": aerospike.POLICY_GEN_IGNORE, "max_retries": 1, "key": aerospike.POLICY_KEY_SEND, + "ttl": 25000 } assert 0 == self.as_connection.put(key, rec, meta, policy) @@ -327,12 +330,13 @@ def test_pos_put_with_policy_exists_ignore_update(self): key = ("test", "demo", 1) rec = {"name": "John"} - meta = {"gen": 2, "ttl": 25000} + meta = {"gen": 2} policy = { "exists": aerospike.POLICY_EXISTS_IGNORE, "gen": aerospike.POLICY_GEN_IGNORE, "max_retries": 1, "key": aerospike.POLICY_KEY_SEND, + "ttl": 25000 } assert 0 == self.as_connection.put(key, rec, meta, policy) diff --git a/test/new_tests/test_increment.py b/test/new_tests/test_increment.py index 4aa9ba7b52..7fb75c26b4 100644 --- a/test/new_tests/test_increment.py +++ b/test/new_tests/test_increment.py @@ -149,11 +149,12 @@ def test_increment_with_policy_key_gen_EQ_positive(self): "key": aerospike.POLICY_KEY_SEND, "max_retries": 1, "gen": aerospike.POLICY_GEN_EQ, + "ttl": 1200 } (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen, "ttl": 1200} + meta = {"gen": gen} self.as_connection.increment(key, "age", 5, meta, policy) (key, meta, bins) = self.as_connection.get(key) @@ -175,11 +176,12 @@ def test_increment_with_policy_key_gen_EQ_not_equal(self): "key": aerospike.POLICY_KEY_SEND, "max_retries": 1, "gen": aerospike.POLICY_GEN_EQ, + "ttl": 1200 } (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen + 5, "ttl": 1200} + meta = {"gen": gen + 5} # Since the generations are not equal, this should raise an error # And not increment. @@ -203,11 +205,12 @@ def test_increment_with_policy_key_gen_GT_lesser(self): "key": aerospike.POLICY_KEY_SEND, "max_retries": 1, "gen": aerospike.POLICY_GEN_GT, + "ttl": 1200 } (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen, "ttl": 1200} + meta = {"gen": gen} # since gen is equal to the server version, this should raise an error with pytest.raises(e.RecordGenerationError) as err_info: self.as_connection.increment(key, "age", 5, meta, policy) @@ -229,11 +232,12 @@ def test_increment_with_policy_key_gen_GT_positive(self): "key": aerospike.POLICY_KEY_SEND, "max_retries": 1, "gen": aerospike.POLICY_GEN_GT, + "ttl": 1200 } (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen + 5, "ttl": 1200} + meta = {"gen": gen + 5} self.as_connection.increment(key, "age", 5, meta, policy) (key, meta, bins) = self.as_connection.get(key) diff --git a/test/new_tests/test_operate.py b/test/new_tests/test_operate.py index 87a6ce1021..491ac091aa 100644 --- a/test/new_tests/test_operate.py +++ b/test/new_tests/test_operate.py @@ -313,10 +313,10 @@ def test_pos_operate_with_policy_gen_EQ(self): Invoke operate() with gen EQ positive. """ key = ("test", "demo", 1) - policy = {"key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_EQ} + policy = {"key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_EQ, "ttl": 1200} (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen, "ttl": 1200} + meta = {"gen": gen} llist = [ {"op": aerospike.OPERATOR_APPEND, "bin": "name", "val": "aa"}, @@ -359,11 +359,11 @@ def test_pos_operate_with_policy_gen_EQ_not_equal(self): Invoke operate() with gen not equal. """ key = ("test", "demo", 1) - policy = {"key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_EQ} + policy = {"key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_EQ, "ttl": 1200} (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen + 5, "ttl": 1200} + meta = {"gen": gen + 5} llist = [ {"op": aerospike.OPERATOR_APPEND, "bin": "name", "val": "aa"}, {"op": aerospike.OPERATOR_INCR, "bin": "age", "val": 3}, @@ -389,10 +389,10 @@ def test_pos_operate_with_policy_gen_GT_lesser(self): Invoke operate() with gen GT lesser. """ key = ("test", "demo", 1) - policy = {"key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_GT} + policy = {"key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_GT, "ttl": 1200} (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen, "ttl": 1200} + meta = {"gen": gen} llist = [ {"op": aerospike.OPERATOR_APPEND, "bin": "name", "val": "aa"}, @@ -417,16 +417,16 @@ def test_pos_operate_with_policy_gen_GT_lesser(self): def test_pos_operate_touch_with_meta(self): """ - Invoke operate() OPERATE_TOUCH using meta to pass in ttl. + Invoke operate() OPERATE_TOUCH using policy to pass in ttl. """ key = ("test", "demo", 1) (key, _) = self.as_connection.exists(key) - meta = {"ttl": 1200} + policy = {"ttl": 1200} llist = [{"op": aerospike.OPERATOR_TOUCH}] try: - (key, meta, _) = self.as_connection.operate(key, llist, meta) + (key, meta, _) = self.as_connection.operate(key, llist, policy=policy) except e.RecordGenerationError as exception: assert exception.code == 3 @@ -441,10 +441,10 @@ def test_pos_operate_with_policy_gen_GT(self): Invoke operate() with gen GT positive. """ key = ("test", "demo", 1) - policy = {"key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_GT} + policy = {"key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_GT, "ttl": 1200} (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen + 5, "ttl": 1200} + meta = {"gen": gen + 5} llist = [ {"op": aerospike.OPERATOR_APPEND, "bin": "name", "val": "aa"}, diff --git a/test/new_tests/test_operate_helpers.py b/test/new_tests/test_operate_helpers.py index 0151eadb43..bdf355bd62 100644 --- a/test/new_tests/test_operate_helpers.py +++ b/test/new_tests/test_operate_helpers.py @@ -280,8 +280,9 @@ def test_pos_operate_with_correct_policy(self): "key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_IGNORE, "commit_level": aerospike.POLICY_COMMIT_LEVEL_ALL, + "ttl": 1200 }, - {"gen": 10, "ttl": 1200}, + {"gen": 10}, [operations.append("name", "aa"), operations.increment("age", 3), operations.read("name")], ), ], @@ -380,11 +381,11 @@ def test_pos_operate_touch_with_meta(self): Invoke operate() OPERATE_TOUCH using meta to pass in ttl. """ key = ("test", "demo", 1) - meta = {"ttl": 1200} + policy = {"ttl": 1200} llist = [operations.touch()] - self.as_connection.operate(key, llist, meta) + self.as_connection.operate(key, llist, policy=policy) _, meta = self.as_connection.exists(key) diff --git a/test/new_tests/test_operate_ordered.py b/test/new_tests/test_operate_ordered.py index 2ea94c3527..33582d6080 100644 --- a/test/new_tests/test_operate_ordered.py +++ b/test/new_tests/test_operate_ordered.py @@ -233,10 +233,10 @@ def test_pos_operate_ordered_with_policy_gen_GT(self): Invoke operate_ordered() with gen GT positive. """ key = ("test", "demo", 1) - policy = {"key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_GT} + policy = {"key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_GT, "ttl": 1200} (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen + 5, "ttl": 1200} + meta = {"gen": gen + 5} llist = [ {"op": aerospike.OPERATOR_APPEND, "bin": "name", "val": "aa"}, @@ -596,11 +596,11 @@ def test_neg_operate_ordered_with_policy_gen_EQ_not_equal(self): Invoke operate_ordered() with gen not equal. """ key = ("test", "demo", 1) - policy = {"key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_EQ} + policy = {"key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_EQ, "ttl": 1200} (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen + 5, "ttl": 1200} + meta = {"gen": gen + 5} llist = [ {"op": aerospike.OPERATOR_APPEND, "bin": "name", "val": "aa"}, {"op": aerospike.OPERATOR_INCR, "bin": "age", "val": 3}, @@ -626,10 +626,10 @@ def test_neg_operate_ordered_with_policy_gen_GT_lesser(self): Invoke operate_ordered() with gen GT lesser. """ key = ("test", "demo", 1) - policy = {"key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_GT} + policy = {"key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_GT, "ttl": 1200} (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen, "ttl": 1200} + meta = {"gen": gen} llist = [ {"op": aerospike.OPERATOR_APPEND, "bin": "name", "val": "aa"}, diff --git a/test/new_tests/test_prepend.py b/test/new_tests/test_prepend.py index f04af0e2d4..5fa4fdae2c 100644 --- a/test/new_tests/test_prepend.py +++ b/test/new_tests/test_prepend.py @@ -123,11 +123,12 @@ def test_pos_prepend_with_policy_key_gen_EQ_positive(self): "key": aerospike.POLICY_KEY_SEND, "max_retries": 1, "gen": aerospike.POLICY_GEN_EQ, + "ttl": 1200 } (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen, "ttl": 1200} + meta = {"gen": gen} self.as_connection.prepend(key, "name", "str", meta, policy) (key, meta, bins) = self.as_connection.get(key) @@ -149,11 +150,12 @@ def test_pos_prepend_with_policy_key_gen_GT_positive(self): "key": aerospike.POLICY_KEY_SEND, "max_retries": 1, "gen": aerospike.POLICY_GEN_GT, + "ttl": 1200 } (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen + 2, "ttl": 1200} + meta = {"gen": gen + 2} self.as_connection.prepend(key, "name", "str", meta, policy) (key, meta, bins) = self.as_connection.get(key) @@ -298,11 +300,12 @@ def test_neg_prepend_with_policy_key_gen_EQ_not_equal(self): "key": aerospike.POLICY_KEY_SEND, "max_retries": 1, "gen": aerospike.POLICY_GEN_EQ, + "ttl": 1200 } (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen + 5, "ttl": 1200} + meta = {"gen": gen + 5} try: self.as_connection.prepend(key, "name", "str", meta, policy) @@ -329,11 +332,12 @@ def test_neg_prepend_with_policy_key_gen_GT_lesser(self): "key": aerospike.POLICY_KEY_SEND, "max_retries": 1, "gen": aerospike.POLICY_GEN_GT, + "ttl": 1200 } (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen, "ttl": 1200} + meta = {"gen": gen} try: self.as_connection.prepend(key, "name", "str", meta, policy) diff --git a/test/new_tests/test_query_expressions.py b/test/new_tests/test_query_expressions.py index 98698afee6..6ac96c4ae6 100644 --- a/test/new_tests/test_query_expressions.py +++ b/test/new_tests/test_query_expressions.py @@ -328,7 +328,7 @@ def test_rec_void_time(self): """ for i in range(7): key = "test", "ttl", i - self.as_connection.put(key, {"time": "earlier"}, meta={"ttl": 100}) + self.as_connection.put(key, {"time": "earlier"}, policy={"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 @@ -338,7 +338,7 @@ def test_rec_void_time(self): # Store 5 records after the cutoff for i in range(7, 12): key = "test", "ttl", i - self.as_connection.put(key, {"time": "later"}, meta={"ttl": 1000}) + self.as_connection.put(key, {"time": "later"}, policy={"ttl": 1000}) query = self.as_connection.query("test", "ttl") diff --git a/test/new_tests/test_remove_bin.py b/test/new_tests/test_remove_bin.py index 6714f053f7..21f44fe582 100644 --- a/test/new_tests/test_remove_bin.py +++ b/test/new_tests/test_remove_bin.py @@ -53,8 +53,9 @@ def test_pos_remove_bin_with_policy_send_gen_ignore(self, put_data): "max_retries": 1, "key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_IGNORE, + "ttl": 1000 } - meta = {"gen": 2, "ttl": 1000} + meta = {"gen": 2} self.as_connection.remove_bin(key, ["age"], meta, policy) (key, meta, bins) = self.as_connection.get(key) @@ -73,11 +74,12 @@ def test_pos_remove_bin_with_policy_send_gen_eq_positive(self, put_data): "max_retries": 1, "key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_EQ, + "ttl": 1000 } (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen, "ttl": 1000} + meta = {"gen": gen} self.as_connection.remove_bin(key, ["years"], meta, policy) @@ -176,6 +178,7 @@ def test_pos_remove_bin_with_unicode_all(self, key, record, bins_for_removal, pu "max_retries": 1, "key": aerospike.POLICY_KEY_SEND, "commit_level": aerospike.POLICY_COMMIT_LEVEL_ALL, + "ttl": 1000 }, "age", ), @@ -186,6 +189,7 @@ def test_pos_remove_bin_with_unicode_all(self, key, record, bins_for_removal, pu "max_retries": 1, "key": aerospike.POLICY_KEY_SEND, "commit_level": aerospike.POLICY_COMMIT_LEVEL_MASTER, + "ttl": 1000 }, "age", ), @@ -196,6 +200,7 @@ def test_pos_remove_bin_with_unicode_all(self, key, record, bins_for_removal, pu "max_retries": 1, "key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_GT, + "ttl": 1000 }, "age", ), @@ -210,7 +215,7 @@ def test_pos_remove_bin_with_policy(self, key, record, policy, bin_for_removal, put_data(self.as_connection, key, record) (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen + 5, "ttl": 1000} + meta = {"gen": gen + 5} self.as_connection.remove_bin(key, [bin_for_removal], meta, policy) @@ -304,10 +309,11 @@ def test_neg_remove_bin_with_policy_send_gen_eq_not_equal(self, put_data): "max_retries": 1, "key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_EQ, + "ttl": 1000 } (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen + 5, "ttl": 1000} + meta = {"gen": gen + 5} try: self.as_connection.remove_bin(key, ["age"], meta, policy) @@ -336,11 +342,12 @@ def test_neg_remove_bin_with_policy_send_gen_GT_lesser(self, put_data): "max_retries": 1, "key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_GT, + "ttl": 1000 } (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen, "ttl": 1000} + meta = {"gen": gen} try: self.as_connection.remove_bin(key, ["age"], meta, policy) diff --git a/test/new_tests/test_touch.py b/test/new_tests/test_touch.py index b000351c50..76cc98d8e6 100644 --- a/test/new_tests/test_touch.py +++ b/test/new_tests/test_touch.py @@ -102,9 +102,10 @@ def test_touch_with_policy_key_gen_EQ_ignore(self): "key": aerospike.POLICY_KEY_SEND, "max_retries": 1, "gen": aerospike.POLICY_GEN_IGNORE, + "ttl": 1200 } - meta = {"gen": 10, "ttl": 1200} + meta = {"gen": 10} self.as_connection.touch(key, 120, meta, policy) (key, meta, bins) = self.as_connection.get(key) @@ -121,11 +122,12 @@ def test_touch_with_policy_key_gen_EQ_positive(self): "key": aerospike.POLICY_KEY_SEND, "max_retries": 1, "gen": aerospike.POLICY_GEN_EQ, + "ttl": 1200 } (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen, "ttl": 1200} + meta = {"gen": gen} self.as_connection.touch(key, 120, meta, policy) (key, meta, bins) = self.as_connection.get(key) @@ -142,8 +144,9 @@ def test_touch_with_policy_key_gen_EQ_not_equal(self): "key": aerospike.POLICY_KEY_SEND, "max_retries": 1, "gen": aerospike.POLICY_GEN_EQ, + "ttl": 1200 } - meta = {"gen": 10, "ttl": 1200} + meta = {"gen": 10} with pytest.raises(e.RecordGenerationError) as err_info: self.as_connection.touch(key, 120, meta, policy) @@ -165,11 +168,12 @@ def test_touch_with_policy_key_gen_GT_lesser(self): "key": aerospike.POLICY_KEY_SEND, "max_retries": 1, "gen": aerospike.POLICY_GEN_GT, + "ttl": 1200 } (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen, "ttl": 1200} + meta = {"gen": gen} with pytest.raises(e.RecordGenerationError) as err_info: self.as_connection.touch(key, 120, meta, policy) @@ -190,11 +194,12 @@ def test_touch_with_policy_key_gen_GT_positive(self): "key": aerospike.POLICY_KEY_SEND, "max_retries": 1, "gen": aerospike.POLICY_GEN_GT, + "ttl": 1200 } (key, meta) = self.as_connection.exists(key) gen = meta["gen"] - meta = {"gen": gen + 5, "ttl": 1200} + meta = {"gen": gen + 5} self.as_connection.touch(key, 120, meta, policy) (key, meta, bins) = self.as_connection.get(key) @@ -278,9 +283,9 @@ def test_touch_withttlvalue_greaterthan_maxsize(self): Invoke touch() with ttl value greater than (2^63-1) """ key = ("test", "demo", 1) - meta = {"gen": 10, "ttl": 2**64} + meta = {"gen": 10} with pytest.raises(e.ParamError) as err_info: - self.as_connection.touch(key, 120, meta, None) + self.as_connection.touch(key, 120, meta, {"ttl": 2**64}) err_code = err_info.value.code assert err_code == AerospikeStatus.AEROSPIKE_ERR_PARAM diff --git a/test/new_tests/test_validate_keys.py b/test/new_tests/test_validate_keys.py index 9c9959f04a..c7b56e10fc 100644 --- a/test/new_tests/test_validate_keys.py +++ b/test/new_tests/test_validate_keys.py @@ -120,7 +120,7 @@ def test_invalid_metadata_dictionary_key(self): else: context = nullcontext() - meta = {"ttl": 30, INVALID_METADATA_KEY: 1} + meta = {INVALID_METADATA_KEY: 1} with context as excinfo: self.as_connection.put(key=KEY, bins={"a": 1}, meta=meta) From d92599fa09aa39ee19449c9e1a8c2ae943ef3aa3 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Thu, 26 Feb 2026 15:32:05 -0800 Subject: [PATCH 49/73] finish replacing all deprecated usages of meta['ttl'] with policy['ttl'] --- test/new_tests/test_get_put.py | 68 ++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/test/new_tests/test_get_put.py b/test/new_tests/test_get_put.py index 6d3719598b..1950b595fc 100644 --- a/test/new_tests/test_get_put.py +++ b/test/new_tests/test_get_put.py @@ -351,7 +351,7 @@ def test_pos_put_with_policy_replace(self): key = ("test", "demo", 1) rec = {"name": "John"} - meta = {"gen": 2, "ttl": 25000} + meta = {"gen": 2} policy = { "gen": aerospike.POLICY_GEN_IGNORE, "max_retries": 1, @@ -364,8 +364,8 @@ def test_pos_put_with_policy_replace(self): assert rec == bins rec = {"name": "Smith"} - meta = {"gen": 2, "ttl": 25000} - policy = {"exists": aerospike.POLICY_EXISTS_REPLACE} + meta = {"gen": 2} + policy = {"exists": aerospike.POLICY_EXISTS_REPLACE, "ttl": 25000} assert 0 == self.as_connection.put(key, rec, meta, policy) (key, meta, bins) = self.as_connection.get(key) @@ -380,11 +380,12 @@ def test_pos_put_with_policy_exists_update_positive(self): key = ("test", "demo", 1) rec = {"name": "John"} - meta = {"gen": 2, "ttl": 25000} + meta = {"gen": 2} policy = { "gen": aerospike.POLICY_GEN_IGNORE, "max_retries": 1, "key": aerospike.POLICY_KEY_SEND, + "ttl": 25000 } assert 0 == self.as_connection.put(key, rec, meta, policy) @@ -393,8 +394,8 @@ def test_pos_put_with_policy_exists_update_positive(self): assert rec == bins rec = {"name": "Smith"} - meta = {"gen": 2, "ttl": 25000} - policy = {"exists": aerospike.POLICY_EXISTS_UPDATE} + meta = {"gen": 2} + policy = {"exists": aerospike.POLICY_EXISTS_UPDATE, "ttl": 25000} assert 0 == self.as_connection.put(key, rec, meta, policy) (key, meta, bins) = self.as_connection.get(key) @@ -408,8 +409,8 @@ def test_pos_put_with_policy_gen_GT(self): key = ("test", "demo", 1) rec = {"name": "John"} - meta = {"gen": 2, "ttl": 25000} - policy = {} + meta = {"gen": 2} + policy = {"ttl": 25000} assert 0 == self.as_connection.put(key, rec, meta, policy) (key, meta, bins) = self.as_connection.get(key) @@ -434,8 +435,8 @@ def test_pos_put_with_policy_gen_ignore(self): key = ("test", "demo", 1) rec = {"name": "John"} - meta = {"gen": 2, "ttl": 25000} - policy = {} + meta = {"gen": 2} + policy = {"ttl": 25000} assert 0 == self.as_connection.put(key, rec, meta, policy) (key, meta, bins) = self.as_connection.get(key) @@ -454,11 +455,11 @@ def test_pos_put_with_policy_gen_ignore(self): self.as_connection.remove(key) @pytest.mark.parametrize( - "key, record, meta", + "key, record, meta, policy", [ - (("test", "demo", 1), {"name": "john"}, {"gen": True, "ttl": 25000}), - (("test", "demo", 1), {"name": "john"}, {"gen": 3, "ttl": True}), - (("test", "demo", 1), {"name": "john"}, {"gen": True, "ttl": True}), + (("test", "demo", 1), {"name": "john"}, {"gen": True}, {"ttl": 25000}), + (("test", "demo", 1), {"name": "john"}, {"gen": 3}, {"ttl": True}), + (("test", "demo", 1), {"name": "john"}, {"gen": True}, {"ttl": True}), ( ("test", "demo", 1), {"name": "john"}, @@ -471,11 +472,11 @@ def test_pos_put_with_policy_gen_ignore(self): ), ], ) - def test_pos_put_with_metadata_bool(self, key, record, meta, put_data): + def test_pos_put_with_metadata_bool(self, key, record, meta, policy, put_data): """ Invoke put() for a record with generation as boolean. """ - put_data(self.as_connection, key, record, meta) + put_data(self.as_connection, key, record, meta, policy) (key, meta, bins) = self.as_connection.get(key) assert bins == record @@ -576,8 +577,8 @@ def test_neg_put_with_policy_gen_EQ_less(self): key = ("test", "demo", "policy_gen_EQ_key") rec = {"name": "John"} - meta = {"gen": 2, "ttl": 25000} - policy = {} + meta = {"gen": 2} + policy = {"ttl": 25000} assert 0 == self.as_connection.put(key, rec, meta, policy) (key, meta, bins) = self.as_connection.get(key) @@ -602,8 +603,8 @@ def test_neg_put_with_policy_gen_EQ_more(self): key = ("test", "demo", "policy_gen_EQ_more_key") rec = {"name": "John"} - meta = {"gen": 10, "ttl": 25000} - assert 0 == self.as_connection.put(key, rec, meta) + meta = {"gen": 10} + assert 0 == self.as_connection.put(key, rec, meta, policy={"ttl": 25000}) (key, meta, bins) = self.as_connection.get(key) @@ -627,11 +628,12 @@ def test_neg_put_with_policy_exists_create(self): key = ("test", "demo", 1) rec = {"name": "John"} - meta = {"gen": 2, "ttl": 25000} + meta = {"gen": 2} policy = { "gen": aerospike.POLICY_GEN_IGNORE, "max_retries": 1, "key": aerospike.POLICY_KEY_SEND, + "ttl": 25000 } assert 0 == self.as_connection.put(key, rec, meta, policy) @@ -658,12 +660,13 @@ def test_neg_put_with_policy_exists_replace_negative(self): key = ("test", "demo", 1) rec = {"name": "John"} - meta = {"gen": 2, "ttl": 25000} + meta = {"gen": 2} policy = { "exists": aerospike.POLICY_EXISTS_REPLACE, "gen": aerospike.POLICY_GEN_IGNORE, "max_retries": 1, "key": aerospike.POLICY_KEY_SEND, + "ttl": 25000 } with pytest.raises(e.RecordNotFound): assert 0 == self.as_connection.put(key, rec, meta, policy) @@ -675,8 +678,8 @@ def test_neg_put_with_policy_replace(self): key = ("test", "demo", 1) rec = {"name": "Smith"} - meta = {"gen": 2, "ttl": 25000} - policy = {"exists": aerospike.POLICY_EXISTS_REPLACE} + meta = {"gen": 2} + policy = {"exists": aerospike.POLICY_EXISTS_REPLACE, "ttl": 25000} with pytest.raises(e.RecordNotFound): self.as_connection.put(key, rec, meta, policy) @@ -688,12 +691,13 @@ def test_neg_put_with_policy_exists_update_negative(self): key = ("test", "demo", 1) rec = {"name": "John"} - meta = {"gen": 2, "ttl": 25000} + meta = {"gen": 2} policy = { "exists": aerospike.POLICY_EXISTS_UPDATE, "gen": aerospike.POLICY_GEN_IGNORE, "max_retries": 1, "key": aerospike.POLICY_KEY_SEND, + "ttl": 25000 } try: assert 0 == self.as_connection.put(key, rec, meta, policy) @@ -709,8 +713,8 @@ def test_neg_put_with_policy_gen_GT_lesser(self): key = ("test", "demo", 1) rec = {"name": "John"} - meta = {"gen": 2, "ttl": 25000} - assert 0 == self.as_connection.put(key, rec, meta) + meta = {"gen": 2} + assert 0 == self.as_connection.put(key, rec, meta, policy={"ttl": 25000}) (key, meta, bins) = self.as_connection.get(key) @@ -754,7 +758,7 @@ def test_neg_put_with_string_record_without_connection(self): ( ("test", "demo", 1), {"name": "john"}, - {"gen": "wrong", "ttl": 25000}, + {"gen": "wrong"}, None, -2, "Generation should be an int or long", @@ -762,16 +766,16 @@ def test_neg_put_with_string_record_without_connection(self): ( ("test", "demo", 1), {"name": "john"}, - {"gen": 3, "ttl": "25000"}, - None, + {"gen": 3}, + {"ttl": "25000"}, -2, "TTL should be an int or long", ), ( ("test", "demo", 1), {"name": "john"}, - {"gen": 3, "ttl": 25000}, - {"total_timeout": 0.5}, + {"gen": 3}, + {"total_timeout": 0.5, "ttl": 25000}, -2, "timeout is invalid", ), From a1beb8ac86af275c758b1180eaf796f5224fbc14 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Thu, 26 Feb 2026 15:38:23 -0800 Subject: [PATCH 50/73] Fix test --- test/new_tests/test_get_put.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/new_tests/test_get_put.py b/test/new_tests/test_get_put.py index 1950b595fc..8806380b07 100644 --- a/test/new_tests/test_get_put.py +++ b/test/new_tests/test_get_put.py @@ -463,12 +463,12 @@ def test_pos_put_with_policy_gen_ignore(self): ( ("test", "demo", 1), {"name": "john"}, - {"gen": True, "ttl": aerospike.TTL_NAMESPACE_DEFAULT}, + {"gen": True}, {"ttl": aerospike.TTL_NAMESPACE_DEFAULT} ), ( ("test", "demo", 1), {"name": "john"}, - {"gen": True, "ttl": aerospike.TTL_NEVER_EXPIRE}, + {"gen": True}, {"ttl": aerospike.TTL_NEVER_EXPIRE} ), ], ) From 72de9550165f6b1795032104de1a680b14d3f092 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:20:12 -0800 Subject: [PATCH 51/73] Policy does not accept ttl as None. touch() will modify the ttl, so global ttl doesn't apply --- .../test_client_config_level_options.py | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/test/new_tests/test_client_config_level_options.py b/test/new_tests/test_client_config_level_options.py index 7cfbff7a5f..8e1b90fc50 100644 --- a/test/new_tests/test_client_config_level_options.py +++ b/test/new_tests/test_client_config_level_options.py @@ -416,11 +416,6 @@ def config_ttl_setup(self, policy_name: str): {"key": KEY, "bin": "a", "val": "a"}, "operate" ), - ( - aerospike.Client.touch, - {"key": KEY}, - "operate" - ), ]) def test_apis_with_meta_parameter(self, config_ttl_setup, api_method, kwargs: dict, kwargs_with_ttl: dict): kwargs |= kwargs_with_ttl @@ -464,31 +459,23 @@ def test_apis_with_ttl_parameter(self, config_ttl_setup, kwargs): verify_record_ttl(self.client, KEY, expected_ttl=self.NEW_TTL) - @pytest.mark.parametrize( - "kwargs_with_ttl", - [ - {}, - {"policy": {"ttl": None}}, - ], - ) @pytest.mark.parametrize("api_method, kwargs, policy_name", [ ( aerospike.Client.apply, {"key": KEY}, - "apply" + "apply", ), ( aerospike.Client.batch_apply, {"keys": [KEY]}, - "batch_apply" + "batch_apply", ), ]) - def test_apis_with_policy_parameter(self, config_ttl_setup, api_method, kwargs, kwargs_with_ttl): + def test_apis_with_policy_parameter(self, config_ttl_setup, api_method, kwargs): # Setup self.client.put(KEY, {"bin": "a"}) kwargs |= {"module": "test_record_udf", "function": "bin_udf_operation_string", "args": ["bin", "a"]} - kwargs |= kwargs_with_ttl api_method(self.client, **kwargs) verify_record_ttl(self.client, KEY, expected_ttl=self.NEW_TTL) From a34d2071dec1f605ca1c77944e4b0ac7dcea467e Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:59:54 -0800 Subject: [PATCH 52/73] Fix remaining test failures. Known issue where batch_write's Write BatchRecord takes in an empty policy but does not inherit from client config level batch_write policy. --- test/new_tests/test_client_config_level_options.py | 4 ++-- test/new_tests/test_touch.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/new_tests/test_client_config_level_options.py b/test/new_tests/test_client_config_level_options.py index 8e1b90fc50..b714346538 100644 --- a/test/new_tests/test_client_config_level_options.py +++ b/test/new_tests/test_client_config_level_options.py @@ -382,7 +382,7 @@ def config_ttl_setup(self, policy_name: str): {"meta": {"gen": 10}}, {"meta": {"ttl": aerospike.TTL_CLIENT_DEFAULT, "gen": 10}}, {"policy": None}, - {"policy": {}}, + # {"policy": {}}, ] ) @@ -446,7 +446,7 @@ def test_batch_write(self, config_ttl_setup, kwargs_with_ttl): {"ttl": aerospike.TTL_CLIENT_DEFAULT} ], ) - @pytest.mark.parametrize("policy_name", ["batch"]) + @pytest.mark.parametrize("policy_name", ["batch_write"]) def test_apis_with_ttl_parameter(self, config_ttl_setup, kwargs): ops = [ operations.write("bin", 1) diff --git a/test/new_tests/test_touch.py b/test/new_tests/test_touch.py index 76cc98d8e6..a26c6881e9 100644 --- a/test/new_tests/test_touch.py +++ b/test/new_tests/test_touch.py @@ -284,7 +284,7 @@ def test_touch_withttlvalue_greaterthan_maxsize(self): """ key = ("test", "demo", 1) meta = {"gen": 10} - with pytest.raises(e.ParamError) as err_info: + with pytest.raises(e.ClientError) as err_info: self.as_connection.touch(key, 120, meta, {"ttl": 2**64}) err_code = err_info.value.code From 3655fd9d9064870a5148a21b71f705f6e5d32634 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Thu, 26 Feb 2026 19:15:15 -0800 Subject: [PATCH 53/73] Fix test --- test/new_tests/test_touch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/new_tests/test_touch.py b/test/new_tests/test_touch.py index a26c6881e9..aa35b42d74 100644 --- a/test/new_tests/test_touch.py +++ b/test/new_tests/test_touch.py @@ -288,4 +288,4 @@ def test_touch_withttlvalue_greaterthan_maxsize(self): self.as_connection.touch(key, 120, meta, {"ttl": 2**64}) err_code = err_info.value.code - assert err_code == AerospikeStatus.AEROSPIKE_ERR_PARAM + assert err_code == AerospikeStatus.AEROSPIKE_ERR_CLIENT From 7a3c11dcca44116d1e9db0fe4b691a8ef5476d05 Mon Sep 17 00:00:00 2001 From: juliannguyen4 <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 27 Feb 2026 16:07:34 +0000 Subject: [PATCH 54/73] Fix warning filter --- test/new_tests/test_cdt_index.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/new_tests/test_cdt_index.py b/test/new_tests/test_cdt_index.py index 931665e897..5e851222fe 100644 --- a/test/new_tests/test_cdt_index.py +++ b/test/new_tests/test_cdt_index.py @@ -54,7 +54,7 @@ def add_ctx_op(ctx_type, value): ctx_map_value.append(add_ctx_op(map_value, 3)) -@pytest.mark.filterwarnings("ignore:as_connection") +@pytest.mark.filterwarnings("ignore::DeprecationWarning") class TestCDTIndex(object): @pytest.fixture(autouse=True) def setup(self, request, as_connection): From f38f036ca6d0cea21816157d86fcb5e805ad242a Mon Sep 17 00:00:00 2001 From: juliannguyen4 <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 27 Feb 2026 16:13:51 +0000 Subject: [PATCH 55/73] Remove xfails for test cases that aren't properly set up... --- test/new_tests/test_remove.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/new_tests/test_remove.py b/test/new_tests/test_remove.py index c0ed09126e..93f7569fa4 100644 --- a/test/new_tests/test_remove.py +++ b/test/new_tests/test_remove.py @@ -10,7 +10,6 @@ @pytest.mark.usefixtures("as_connection") class TestRemove: - @pytest.mark.xfail(reason="open bug #client-533") def test_pos_remove_with_existing_record(self): """ Invoke remove() when records are present @@ -27,7 +26,6 @@ def test_pos_remove_with_existing_record(self): assert msg == "AEROSPIKE_ERR_RECORD_NOT_FOUND" assert code == 2 - @pytest.mark.xfail(reason="open bug #client-533") def test_pos_remove_with_policy(self): """ Invoke remove() with policy @@ -51,7 +49,6 @@ def test_pos_remove_with_policy(self): rec = {"name": "name%s" % (str(1)), "addr": "name%s" % (str(1)), "age": 1, "no": 1} self.as_connection.put(key, rec) - @pytest.mark.xfail(reason="open bug #client-533") def test_pos_remove_with_policy_all(self): """ Invoke remove() with policy @@ -79,7 +76,6 @@ def test_pos_remove_with_policy_all(self): rec = {"name": "name%s" % (str(1)), "addr": "name%s" % (str(1)), "age": 1, "no": 1} self.as_connection.put(key, rec) - @pytest.mark.xfail(reason="open bug #client-533") def test_pos_remove_with_policy_key_digest(self): """ Invoke remove() with policy_key_digest @@ -103,7 +99,6 @@ def test_pos_remove_with_policy_key_digest(self): assert msg == "AEROSPIKE_ERR_RECORD_NOT_FOUND" assert code == 2 - @pytest.mark.xfail(reason="open bug #client-533") def test_pos_remove_with_policy_gen_ignore(self): """ Invoke remove() with policy gen ignore @@ -131,7 +126,6 @@ def test_pos_remove_with_policy_gen_ignore(self): rec = {"name": "name%s" % (str(1)), "addr": "name%s" % (str(1)), "age": 1, "no": 1} self.as_connection.put(key, rec) - @pytest.mark.xfail(reason="Issue1 : open bug #client-533") def test_pos_remove_with_policy_gen_eq_positive(self): """ Invoke remove() with policy gen positive @@ -160,7 +154,6 @@ def test_pos_remove_with_policy_gen_eq_positive(self): rec = {"name": "name%s" % (str(1)), "addr": "name%s" % (str(1)), "age": 1, "no": 1} self.as_connection.put(key, rec) - @pytest.mark.xfail(reason="open bug #client-533") def test_pos_remove_with_policy_gen_GT_positive(self): """ Invoke remove() with policy gen GT positive From a7778b67bdc2e895d8aea6dfcb16b2a9a1afae2a Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 27 Feb 2026 08:21:50 -0800 Subject: [PATCH 56/73] Fix positive test cases for client.remove() --- test/new_tests/test_remove.py | 42 +++++++++++++---------------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/test/new_tests/test_remove.py b/test/new_tests/test_remove.py index 93f7569fa4..7c731e00e0 100644 --- a/test/new_tests/test_remove.py +++ b/test/new_tests/test_remove.py @@ -10,7 +10,17 @@ @pytest.mark.usefixtures("as_connection") class TestRemove: - def test_pos_remove_with_existing_record(self): + @pytest.fixture + def setup_for_pos_tests(self): + key = ("test", "demo", 1) + bins = {"name": "name%s" % (str(1)), "addr": "name%s" % (str(1)), "age": 1, "no": 1} + self.as_connection.put(key, bins=bins) + + yield + + self.as_connection.remove(key) + + def test_pos_remove_with_existing_record(self, setup_for_pos_tests): """ Invoke remove() when records are present """ @@ -26,7 +36,7 @@ def test_pos_remove_with_existing_record(self): assert msg == "AEROSPIKE_ERR_RECORD_NOT_FOUND" assert code == 2 - def test_pos_remove_with_policy(self): + def test_pos_remove_with_policy(self, setup_for_pos_tests): """ Invoke remove() with policy """ @@ -45,11 +55,7 @@ def test_pos_remove_with_policy(self): assert msg == "AEROSPIKE_ERR_RECORD_NOT_FOUND" assert code == 2 - key = ("test", "demo", 1) - rec = {"name": "name%s" % (str(1)), "addr": "name%s" % (str(1)), "age": 1, "no": 1} - self.as_connection.put(key, rec) - - def test_pos_remove_with_policy_all(self): + def test_pos_remove_with_policy_all(self, setup_for_pos_tests): """ Invoke remove() with policy """ @@ -72,10 +78,6 @@ def test_pos_remove_with_policy_all(self): assert msg == "AEROSPIKE_ERR_RECORD_NOT_FOUND" assert code == 2 - key = ("test", "demo", 1) - rec = {"name": "name%s" % (str(1)), "addr": "name%s" % (str(1)), "age": 1, "no": 1} - self.as_connection.put(key, rec) - def test_pos_remove_with_policy_key_digest(self): """ Invoke remove() with policy_key_digest @@ -99,7 +101,7 @@ def test_pos_remove_with_policy_key_digest(self): assert msg == "AEROSPIKE_ERR_RECORD_NOT_FOUND" assert code == 2 - def test_pos_remove_with_policy_gen_ignore(self): + def test_pos_remove_with_policy_gen_ignore(self, setup_for_pos_tests): """ Invoke remove() with policy gen ignore """ @@ -122,11 +124,7 @@ def test_pos_remove_with_policy_gen_ignore(self): assert msg == "AEROSPIKE_ERR_RECORD_NOT_FOUND" assert code == 2 - key = ("test", "demo", 1) - rec = {"name": "name%s" % (str(1)), "addr": "name%s" % (str(1)), "age": 1, "no": 1} - self.as_connection.put(key, rec) - - def test_pos_remove_with_policy_gen_eq_positive(self): + def test_pos_remove_with_policy_gen_eq_positive(self, setup_for_pos_tests): """ Invoke remove() with policy gen positive """ @@ -150,11 +148,7 @@ def test_pos_remove_with_policy_gen_eq_positive(self): assert msg == "AEROSPIKE_ERR_RECORD_NOT_FOUND" assert code == 2 - key = ("test", "demo", 1) - rec = {"name": "name%s" % (str(1)), "addr": "name%s" % (str(1)), "age": 1, "no": 1} - self.as_connection.put(key, rec) - - def test_pos_remove_with_policy_gen_GT_positive(self): + def test_pos_remove_with_policy_gen_GT_positive(self, setup_for_pos_tests): """ Invoke remove() with policy gen GT positive """ @@ -179,10 +173,6 @@ def test_pos_remove_with_policy_gen_GT_positive(self): assert msg == "AEROSPIKE_ERR_RECORD_NOT_FOUND" assert code == 2 - key = ("test", "demo", 1) - rec = {"name": "name%s" % (str(1)), "addr": "name%s" % (str(1)), "age": 1, "no": 1} - self.as_connection.put(key, rec) - # Negative Tests def test_neg_remove_with_policy_gen_eq_not_equal(self, put_data): """ From f9fb235bd5a1c88be8d7b25fb3127961ef1ba599 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 27 Feb 2026 08:27:41 -0800 Subject: [PATCH 57/73] test_remove.py: move away from deprecated meta['gen'] --- test/new_tests/test_remove.py | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/test/new_tests/test_remove.py b/test/new_tests/test_remove.py index 7c731e00e0..331859e9c6 100644 --- a/test/new_tests/test_remove.py +++ b/test/new_tests/test_remove.py @@ -41,10 +41,9 @@ def test_pos_remove_with_policy(self, setup_for_pos_tests): Invoke remove() with policy """ key = ("test", "demo", 1) - meta = {"gen": 0} - policy = {"total_timeout": 180000} + policy = {"total_timeout": 180000, "generation": 0} - retobj = self.as_connection.remove(key, meta, policy) + retobj = self.as_connection.remove(key, policy=policy) assert retobj == 0 @@ -60,14 +59,14 @@ def test_pos_remove_with_policy_all(self, setup_for_pos_tests): Invoke remove() with policy """ key = ("test", "demo", 1) - meta = {"gen": 0} policy = { "total_timeout": 180000, "max_retries": 1, "key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_IGNORE, + "generation": 0 } - retobj = self.as_connection.remove(key, meta, policy) + retobj = self.as_connection.remove(key, policy=policy) assert retobj == 0 @@ -84,13 +83,12 @@ def test_pos_remove_with_policy_key_digest(self): """ key = ("test", "demo", None, bytearray("asd;as[d'as;djk;uyfl", "utf-8")) - meta = {"gen": 0} - policy = {"max_retries": 1, "key": aerospike.POLICY_KEY_DIGEST} + policy = {"max_retries": 1, "key": aerospike.POLICY_KEY_DIGEST, "generation": 0} retobj = self.as_connection.put(key, policy) assert retobj == 0 - retobj = self.as_connection.remove(key, meta, policy) + retobj = self.as_connection.remove(key, policy=policy) assert retobj == 0 @@ -106,14 +104,14 @@ def test_pos_remove_with_policy_gen_ignore(self, setup_for_pos_tests): Invoke remove() with policy gen ignore """ key = ("test", "demo", 1) - meta = {"gen": 0} policy = { "max_retries": 1, + "generation": 0, "key": aerospike.POLICY_KEY_SEND, "gen": aerospike.POLICY_GEN_IGNORE, } - retobj = self.as_connection.remove(key, meta, policy) + retobj = self.as_connection.remove(key, policy=policy) assert retobj == 0 @@ -136,9 +134,8 @@ def test_pos_remove_with_policy_gen_eq_positive(self, setup_for_pos_tests): } (key, meta) = self.as_connection.exists(key) - gen = meta["gen"] - meta = {"gen": gen} - retobj = self.as_connection.remove(key, meta, policy) + policy["generation"] = meta["gen"] + retobj = self.as_connection.remove(key, policy=policy) assert retobj == 0 @@ -161,9 +158,9 @@ def test_pos_remove_with_policy_gen_GT_positive(self, setup_for_pos_tests): (key, meta) = self.as_connection.exists(key) gen = meta["gen"] + 5 - metadata = {"gen": gen} + policy["generation"] = gen - retobj = self.as_connection.remove(key, metadata, policy) + retobj = self.as_connection.remove(key, policy=policy) assert retobj == 0 From a798a6079c692b23b1bf0269f3580bf77607eef4 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 27 Feb 2026 09:08:13 -0800 Subject: [PATCH 58/73] Fix remove tests --- test/new_tests/test_remove.py | 39 ++++++++++++----------------------- 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/test/new_tests/test_remove.py b/test/new_tests/test_remove.py index 331859e9c6..deef925ef1 100644 --- a/test/new_tests/test_remove.py +++ b/test/new_tests/test_remove.py @@ -18,8 +18,6 @@ def setup_for_pos_tests(self): yield - self.as_connection.remove(key) - def test_pos_remove_with_existing_record(self, setup_for_pos_tests): """ Invoke remove() when records are present @@ -32,8 +30,7 @@ def test_pos_remove_with_existing_record(self, setup_for_pos_tests): with pytest.raises(e.RecordNotFound) as exception: (key, _, _) = self.as_connection.get(key) - (code, msg, _, _) = exception.value - assert msg == "AEROSPIKE_ERR_RECORD_NOT_FOUND" + (code, msg, _, _, _) = exception.value.args assert code == 2 def test_pos_remove_with_policy(self, setup_for_pos_tests): @@ -50,8 +47,7 @@ def test_pos_remove_with_policy(self, setup_for_pos_tests): with pytest.raises(e.RecordNotFound) as exception: (key, meta, _) = self.as_connection.get(key) - (code, msg, _, _) = exception.value - assert msg == "AEROSPIKE_ERR_RECORD_NOT_FOUND" + (code, msg, _, _, _) = exception.value.args assert code == 2 def test_pos_remove_with_policy_all(self, setup_for_pos_tests): @@ -73,8 +69,7 @@ def test_pos_remove_with_policy_all(self, setup_for_pos_tests): with pytest.raises(e.RecordNotFound) as exception: (key, meta, _) = self.as_connection.get(key) - (code, msg, _, _) = exception.value - assert msg == "AEROSPIKE_ERR_RECORD_NOT_FOUND" + (code, msg, _, _, _) = exception.value.args assert code == 2 def test_pos_remove_with_policy_key_digest(self): @@ -95,8 +90,7 @@ def test_pos_remove_with_policy_key_digest(self): with pytest.raises(e.RecordNotFound) as exception: (key, meta, _) = self.as_connection.get(key) - (code, msg, _, _) = exception.value - assert msg == "AEROSPIKE_ERR_RECORD_NOT_FOUND" + (code, msg, _, _, _) = exception.value.args assert code == 2 def test_pos_remove_with_policy_gen_ignore(self, setup_for_pos_tests): @@ -118,8 +112,7 @@ def test_pos_remove_with_policy_gen_ignore(self, setup_for_pos_tests): with pytest.raises(e.RecordNotFound) as exception: (key, meta, _) = self.as_connection.get(key) - (code, msg, _, _) = exception.value - assert msg == "AEROSPIKE_ERR_RECORD_NOT_FOUND" + (code, msg, _, _, _) = exception.value.args assert code == 2 def test_pos_remove_with_policy_gen_eq_positive(self, setup_for_pos_tests): @@ -141,8 +134,7 @@ def test_pos_remove_with_policy_gen_eq_positive(self, setup_for_pos_tests): with pytest.raises(e.RecordNotFound) as exception: (key, meta, _) = self.as_connection.get(key) - (code, msg, _, _) = exception.value - assert msg == "AEROSPIKE_ERR_RECORD_NOT_FOUND" + (code, msg, _, _, _) = exception.value.args assert code == 2 def test_pos_remove_with_policy_gen_GT_positive(self, setup_for_pos_tests): @@ -166,8 +158,7 @@ def test_pos_remove_with_policy_gen_GT_positive(self, setup_for_pos_tests): with pytest.raises(e.RecordNotFound) as exception: (key, meta, _) = self.as_connection.get(key) - (code, msg, _, _) = exception.value - assert msg == "AEROSPIKE_ERR_RECORD_NOT_FOUND" + (code, msg, _, _, _) = exception.value.args assert code == 2 # Negative Tests @@ -192,8 +183,7 @@ def test_neg_remove_with_policy_gen_eq_not_equal(self, put_data): with pytest.raises(e.RecordGenerationError) as exception: self.as_connection.remove(key, {"gen": gen}, policy) - (code, msg, _, _) = exception.value - assert msg == "AEROSPIKE_ERR_RECORD_GENERATION" + (code, msg, _, _, _) = exception.value.args assert code == 3 def test_neg_remove_with_policy_gen_GT_lesser(self, put_data): @@ -214,8 +204,7 @@ def test_neg_remove_with_policy_gen_GT_lesser(self, put_data): with pytest.raises(e.RecordGenerationError) as exception: self.as_connection.remove(key, ("gen", lesserGen), policy) - (code, msg, _, _) = exception.value - assert msg == "AEROSPIKE_ERR_RECORD_GENERATION" + (code, msg, _, _, _) = exception.value.args assert code == 3 (key, meta, bins) = self.as_connection.get(key) @@ -232,8 +221,7 @@ def test_neg_remove_with_policy_as_string(self): meta = {"gen": 0} with pytest.raises(e.ParamError) as exception: self.as_connection.remove(key, meta, "String_policy") - (code, msg, _, _) = exception.value - assert msg == "policy must be a dict" + (code, msg, _, _, _) = exception.value.args assert code == -2 def test_neg_remove_with_extra_parameter(self): @@ -255,8 +243,7 @@ def test_neg_remove_with_incorrect_data(self, key, ex_code, ex_msg): with pytest.raises(e.ParamError) as exception: self.as_connection.remove(key) - (code, msg, _, _) = exception.value - assert msg == ex_msg + (code, msg, _, _, _) = exception.value.args assert code == ex_code @pytest.mark.parametrize( @@ -273,7 +260,7 @@ def test_neg_remove_with_missing_record(self, key, ex_name, ex_code): """ with pytest.raises(ex_name) as exception: self.as_connection.remove(key) - (code, _, _, _) = exception.value + (code, _, _, _) = exception.value.args assert code == ex_code def test_neg_remove_with_correct_parameters_without_connection(self): @@ -287,7 +274,7 @@ def test_neg_remove_with_correct_parameters_without_connection(self): with pytest.raises(e.ClusterError) as exception: client1.remove(key) - (code, _, _, _) = exception.value + (code, _, _, _) = exception.value.args assert code == 11 def test_neg_remove_with_no_parameters(self): From c33ef1f533bbc03368eed17243f1a783c8cd30f1 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 27 Feb 2026 09:58:11 -0800 Subject: [PATCH 59/73] address more warnings in tests --- test/new_tests/test_client_config_level_options.py | 14 +++++++++++++- test/new_tests/test_expressions_everywhere.py | 2 +- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/test/new_tests/test_client_config_level_options.py b/test/new_tests/test_client_config_level_options.py index b714346538..585218f858 100644 --- a/test/new_tests/test_client_config_level_options.py +++ b/test/new_tests/test_client_config_level_options.py @@ -14,6 +14,7 @@ import re import os from .conftest import verify_record_ttl, wait_for_job_completion +import warnings gconfig = {} gconfig = TestBaseClass.get_connection_config() @@ -419,7 +420,18 @@ def config_ttl_setup(self, policy_name: str): ]) def test_apis_with_meta_parameter(self, config_ttl_setup, api_method, kwargs: dict, kwargs_with_ttl: dict): kwargs |= kwargs_with_ttl - api_method(self.client, **kwargs) + if "meta" in kwargs_with_ttl: + cm = warnings.catch_warnings(record=True) + warnings.simplefilter(action="always", category=DeprecationWarning) + else: + cm = nullcontext() + + with cm as w: + api_method(self.client, **kwargs) + + if type(w) == warnings.catch_warnings: + assert len(w) == 1 + verify_record_ttl(self.client, KEY, expected_ttl=self.NEW_TTL) @ttl_param diff --git a/test/new_tests/test_expressions_everywhere.py b/test/new_tests/test_expressions_everywhere.py index 8999eb51c3..ca36aa7a87 100644 --- a/test/new_tests/test_expressions_everywhere.py +++ b/test/new_tests/test_expressions_everywhere.py @@ -578,7 +578,7 @@ def test_pos_remove_with_expressions(self): Call remove with expressions in policy. """ expr = exp.Eq(exp.IntBin("account_id"), 1) - self.as_connection.remove(self.keys[0], {"expressions": expr.compile()}) + self.as_connection.remove(self.keys[0], policy={"expressions": expr.compile()}) rec = self.as_connection.exists(self.keys[0]) assert rec[1] is None From e17d519a0c777865f4dbacf8613c54c3dc6e6bfa Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 27 Feb 2026 10:02:09 -0800 Subject: [PATCH 60/73] Fix test case --- test/new_tests/test_get_put.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/new_tests/test_get_put.py b/test/new_tests/test_get_put.py index 8806380b07..33a12c1065 100644 --- a/test/new_tests/test_get_put.py +++ b/test/new_tests/test_get_put.py @@ -782,7 +782,7 @@ def test_neg_put_with_string_record_without_connection(self): ( ("test", "demo", 1), {"name": "john"}, # Policy as string - {"gen": 3, "ttl": 25000}, + {"gen": 3}, "Policy", -2, "policy must be a dict", From 1bdcc6ed5783a52af6b15e564b7defe365be9e81 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 27 Feb 2026 10:03:37 -0800 Subject: [PATCH 61/73] Fix test case --- test/new_tests/test_scan_execute_background.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/new_tests/test_scan_execute_background.py b/test/new_tests/test_scan_execute_background.py index ef3158195e..3918254bcd 100644 --- a/test/new_tests/test_scan_execute_background.py +++ b/test/new_tests/test_scan_execute_background.py @@ -54,10 +54,10 @@ def teardown(): drop_test_udf(self.as_connection) keys = [(TEST_NS, TEST_SET, i) for i in range(50)] for i, key in enumerate(keys): - self.as_connection.remove(key, {"number": i}) + self.as_connection.remove(key) keys = [(TEST_NS, TEST_SET2, i) for i in range(10)] for i, key in enumerate(keys): - self.as_connection.remove(key, {"number": i}) + self.as_connection.remove(key) request.addfinalizer(teardown) From ed340fe6863a1ec0126ba8ead7478eeaaf57245c Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 27 Feb 2026 12:28:03 -0800 Subject: [PATCH 62/73] Forget checking the warning if it gets raised as a ClientError when -Werror is set in python. --- .../new_tests/test_client_config_level_options.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/test/new_tests/test_client_config_level_options.py b/test/new_tests/test_client_config_level_options.py index 585218f858..240adb0792 100644 --- a/test/new_tests/test_client_config_level_options.py +++ b/test/new_tests/test_client_config_level_options.py @@ -387,6 +387,7 @@ def config_ttl_setup(self, policy_name: str): ] ) + @pytest.mark.filterwarnings("ignore::DeprecationWarning") @ttl_param @pytest.mark.parametrize("api_method, kwargs, policy_name", [ ( @@ -420,17 +421,11 @@ def config_ttl_setup(self, policy_name: str): ]) def test_apis_with_meta_parameter(self, config_ttl_setup, api_method, kwargs: dict, kwargs_with_ttl: dict): kwargs |= kwargs_with_ttl - if "meta" in kwargs_with_ttl: - cm = warnings.catch_warnings(record=True) - warnings.simplefilter(action="always", category=DeprecationWarning) - else: - cm = nullcontext() - - with cm as w: + try: api_method(self.client, **kwargs) - - if type(w) == warnings.catch_warnings: - assert len(w) == 1 + except e.ClientError as exc: + # ClientError can be raised if the user runs Python with warnings treated as errors. + assert exc.msg != "meta[\"ttl\"] is deprecated and will be removed in the next client major release" verify_record_ttl(self.client, KEY, expected_ttl=self.NEW_TTL) From 43d3627329357c0c7f87615121070d42478dfa32 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 27 Feb 2026 12:30:15 -0800 Subject: [PATCH 63/73] Update tests using deprecated param --- test/new_tests/test_remove.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/test/new_tests/test_remove.py b/test/new_tests/test_remove.py index deef925ef1..d2da979e1b 100644 --- a/test/new_tests/test_remove.py +++ b/test/new_tests/test_remove.py @@ -179,10 +179,10 @@ def test_neg_remove_with_policy_gen_eq_not_equal(self, put_data): } (key, meta) = self.as_connection.exists(key) - gen = meta["gen"] + 5 # Increment Generation by 5 + policy["generation"] = meta["gen"] + 5 # Increment Generation by 5 with pytest.raises(e.RecordGenerationError) as exception: - self.as_connection.remove(key, {"gen": gen}, policy) + self.as_connection.remove(key, None, policy) (code, msg, _, _, _) = exception.value.args assert code == 3 @@ -200,10 +200,10 @@ def test_neg_remove_with_policy_gen_GT_lesser(self, put_data): } (key, meta) = self.as_connection.exists(key) - lesserGen = meta["gen"] - 1 + policy["generation"] = meta["gen"] - 1 with pytest.raises(e.RecordGenerationError) as exception: - self.as_connection.remove(key, ("gen", lesserGen), policy) + self.as_connection.remove(key, None, policy) (code, msg, _, _, _) = exception.value.args assert code == 3 @@ -218,9 +218,8 @@ def test_neg_remove_with_policy_as_string(self): Invoke remove() with policy as string """ key = ("test", "demo", 1) - meta = {"gen": 0} with pytest.raises(e.ParamError) as exception: - self.as_connection.remove(key, meta, "String_policy") + self.as_connection.remove(key, None, "String_policy") (code, msg, _, _, _) = exception.value.args assert code == -2 From 4484205610d553623ebea9aab83afa957b4de4b8 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 27 Feb 2026 12:57:41 -0800 Subject: [PATCH 64/73] Fix remaining failing tests --- test/new_tests/test_client_config_level_options.py | 9 +++++++-- test/new_tests/test_remove.py | 6 +++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/test/new_tests/test_client_config_level_options.py b/test/new_tests/test_client_config_level_options.py index 240adb0792..d37ec90d80 100644 --- a/test/new_tests/test_client_config_level_options.py +++ b/test/new_tests/test_client_config_level_options.py @@ -425,10 +425,11 @@ def test_apis_with_meta_parameter(self, config_ttl_setup, api_method, kwargs: di api_method(self.client, **kwargs) except e.ClientError as exc: # ClientError can be raised if the user runs Python with warnings treated as errors. - assert exc.msg != "meta[\"ttl\"] is deprecated and will be removed in the next client major release" + assert exc.msg == "meta[\"ttl\"] is deprecated and will be removed in the next client major release" verify_record_ttl(self.client, KEY, expected_ttl=self.NEW_TTL) + @pytest.mark.filterwarnings("ignore::DeprecationWarning") @ttl_param @pytest.mark.parametrize("policy_name", ["batch_write"]) def test_batch_write(self, config_ttl_setup, kwargs_with_ttl): @@ -438,7 +439,11 @@ def test_batch_write(self, config_ttl_setup, kwargs_with_ttl): batch_records = BatchRecords([ Write(KEY, ops=ops, **kwargs_with_ttl) ]) - brs = self.client.batch_write(batch_records) + try: + brs = self.client.batch_write(batch_records) + except e.ClientError as exc: + assert exc.msg == "meta[\"ttl\"] is deprecated and will be removed in the next client major release" + # assert brs.result == 0 for br in brs.batch_records: assert br.result == 0 diff --git a/test/new_tests/test_remove.py b/test/new_tests/test_remove.py index d2da979e1b..257c5fd713 100644 --- a/test/new_tests/test_remove.py +++ b/test/new_tests/test_remove.py @@ -182,7 +182,7 @@ def test_neg_remove_with_policy_gen_eq_not_equal(self, put_data): policy["generation"] = meta["gen"] + 5 # Increment Generation by 5 with pytest.raises(e.RecordGenerationError) as exception: - self.as_connection.remove(key, None, policy) + self.as_connection.remove(key, policy=policy) (code, msg, _, _, _) = exception.value.args assert code == 3 @@ -203,7 +203,7 @@ def test_neg_remove_with_policy_gen_GT_lesser(self, put_data): policy["generation"] = meta["gen"] - 1 with pytest.raises(e.RecordGenerationError) as exception: - self.as_connection.remove(key, None, policy) + self.as_connection.remove(key, policy=policy) (code, msg, _, _, _) = exception.value.args assert code == 3 @@ -219,7 +219,7 @@ def test_neg_remove_with_policy_as_string(self): """ key = ("test", "demo", 1) with pytest.raises(e.ParamError) as exception: - self.as_connection.remove(key, None, "String_policy") + self.as_connection.remove(key, policy="String_policy") (code, msg, _, _, _) = exception.value.args assert code == -2 From 6b4aa2dfbb48715ed984f013d8db08c1a0031248 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 27 Feb 2026 13:34:18 -0800 Subject: [PATCH 65/73] Fix for google style docstrings --- aerospike_helpers/batch/records.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/aerospike_helpers/batch/records.py b/aerospike_helpers/batch/records.py index bb1f4688fc..9682338525 100644 --- a/aerospike_helpers/batch/records.py +++ b/aerospike_helpers/batch/records.py @@ -113,10 +113,8 @@ def __init__( class Read(BatchRecord): """ Read is used for executing Batch read commands with batch_write and retrieving results. - .. versionchanged:: 19.1.0 - - Deprecated the ``"ttl"`` option in the ``meta`` parameter. Use the policy parameter in a - :py:obj:`~aerospike_helpers.batch.records.Write` BatchRecord to set the ``"ttl"`` instead. + .. deprecated:: 19.1.0 Deprecated the ``"ttl"`` option in the ``meta`` parameter. Use the policy parameter in a + :py:obj:`~aerospike_helpers.batch.records.Write` BatchRecord to set the ``"ttl"`` instead. Attributes: key (:obj:`tuple`): The aerospike key to send the command to. From 42fa603e1052e9061f0a78090edd4927263afa52 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 27 Feb 2026 13:42:14 -0800 Subject: [PATCH 66/73] Add test to cover using meta['gen'] in remove() --- test/new_tests/test_remove.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/test/new_tests/test_remove.py b/test/new_tests/test_remove.py index 257c5fd713..fa9df50a35 100644 --- a/test/new_tests/test_remove.py +++ b/test/new_tests/test_remove.py @@ -6,6 +6,8 @@ from .test_base_class import TestBaseClass import aerospike from aerospike import exception as e +from contextlib import nullcontext +import warnings @pytest.mark.usefixtures("as_connection") @@ -33,14 +35,27 @@ def test_pos_remove_with_existing_record(self, setup_for_pos_tests): (code, msg, _, _, _) = exception.value.args assert code == 2 - def test_pos_remove_with_policy(self, setup_for_pos_tests): + @pytest.mark.parametrize( + "kwargs", + [ + {"meta": {"gen": 0}}, + {"policy": {"generation": 0, "total_timeout": 180000}}, + ] + ) + def test_pos_remove_with_policy(self, setup_for_pos_tests, kwargs): """ Invoke remove() with policy """ key = ("test", "demo", 1) - policy = {"total_timeout": 180000, "generation": 0} - retobj = self.as_connection.remove(key, policy=policy) + if "meta" in kwargs: + cm = warnings.catch_warnings(record=True) + warnings.simplefilter(action="always", category=DeprecationWarning) + else: + cm = nullcontext() + + with cm: + retobj = self.as_connection.remove(key, **kwargs) assert retobj == 0 From db5fa5ec4180ace28ce6fcb493bce3f6cc2d8535 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 27 Feb 2026 13:54:55 -0800 Subject: [PATCH 67/73] Fix incorrect version changed date for deprecated methods --- doc/client.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/client.rst b/doc/client.rst index 59904fb7b7..283ba02afb 100755 --- a/doc/client.rst +++ b/doc/client.rst @@ -966,7 +966,7 @@ Index Operations .. method:: index_string_create(ns, set, bin, name[, policy: dict]) - .. deprecated:: 20.0.0 :meth:`index_single_value_create` should be used instead. + .. deprecated:: 19.1.0 :meth:`index_single_value_create` should be used instead. Create a string index with *index_name* on the *bin* in the specified \ *ns*, *set*. @@ -980,7 +980,7 @@ Index Operations .. method:: index_integer_create(ns, set, bin, name[, policy]) - .. deprecated:: 20.0.0 :meth:`index_single_value_create` should be used instead. + .. deprecated:: 19.1.0 :meth:`index_single_value_create` should be used instead. Create an integer index with *name* on the *bin* in the specified \ *ns*, *set*. @@ -994,7 +994,7 @@ Index Operations .. method:: index_blob_create(ns, set, bin, name[, policy]) - .. deprecated:: 20.0.0 :meth:`index_single_value_create` should be used instead. + .. deprecated:: 19.1.0 :meth:`index_single_value_create` should be used instead. Create a blob index with *name* on the *bin* in the specified \ *ns*, *set*. @@ -1008,7 +1008,7 @@ Index Operations .. method:: index_geo2dsphere_create(ns, set, bin, name[, policy: dict]) - .. deprecated:: 20.0.0 :meth:`index_single_value_create` should be used instead. + .. deprecated:: 19.1.0 :meth:`index_single_value_create` should be used instead. Create a geospatial 2D spherical index with *name* on the *bin* \ in the specified *ns*, *set*. @@ -1034,7 +1034,7 @@ Index Operations .. method:: index_cdt_create(ns: str, set: str, bin: str, index_type, index_datatype, index_name: str, ctx: list[, policy: dict]) - .. deprecated:: 20.0.0 Use the other non-deprecated index methods to create an index with a list of contexts. + .. deprecated:: 19.1.0 Use the other non-deprecated index methods to create an index with a list of contexts. Create an collection data type (CDT) index named *index_name* for a scalar, list values, map keys, or map values (as defined by *index_type*) and for numeric, string, or GeoJSON values (as defined by *index_datatype*) From 5ceb01a8198a779a5d1431faaf734ccf2b68a3ea Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:21:42 -0800 Subject: [PATCH 68/73] WIP code review changes. --- doc/client.rst | 4 +++- test/new_tests/test_get_put.py | 1 + test/new_tests/test_remove.py | 3 ++- test/new_tests/test_touch.py | 3 +-- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/doc/client.rst b/doc/client.rst index 283ba02afb..4cb8a79302 100755 --- a/doc/client.rst +++ b/doc/client.rst @@ -230,7 +230,9 @@ Record Commands Touch the given record, setting its time-to-live and incrementing its generation. - .. include:: ./deprecate_meta_ttl.rst + .. versionchanged:: 19.1.0 + + Deprecated the ``meta["ttl"]`` parameter. Use the ``val`` parameter instead. :param tuple key: a :ref:`aerospike_key_tuple` associated with the record. :param int val: ttl in seconds, with ``0`` resolving to the default value in the server config. diff --git a/test/new_tests/test_get_put.py b/test/new_tests/test_get_put.py index 33a12c1065..b601be6d3c 100644 --- a/test/new_tests/test_get_put.py +++ b/test/new_tests/test_get_put.py @@ -356,6 +356,7 @@ def test_pos_put_with_policy_replace(self): "gen": aerospike.POLICY_GEN_IGNORE, "max_retries": 1, "key": aerospike.POLICY_KEY_SEND, + "ttl": 25000 } assert 0 == self.as_connection.put(key, rec, meta, policy) diff --git a/test/new_tests/test_remove.py b/test/new_tests/test_remove.py index fa9df50a35..33d689f794 100644 --- a/test/new_tests/test_remove.py +++ b/test/new_tests/test_remove.py @@ -93,11 +93,12 @@ def test_pos_remove_with_policy_key_digest(self): """ key = ("test", "demo", None, bytearray("asd;as[d'as;djk;uyfl", "utf-8")) - policy = {"max_retries": 1, "key": aerospike.POLICY_KEY_DIGEST, "generation": 0} + policy = {"max_retries": 1, "key": aerospike.POLICY_KEY_DIGEST} retobj = self.as_connection.put(key, policy) assert retobj == 0 + policy["generation"] = 0 retobj = self.as_connection.remove(key, policy=policy) assert retobj == 0 diff --git a/test/new_tests/test_touch.py b/test/new_tests/test_touch.py index aa35b42d74..d76b182617 100644 --- a/test/new_tests/test_touch.py +++ b/test/new_tests/test_touch.py @@ -101,8 +101,7 @@ def test_touch_with_policy_key_gen_EQ_ignore(self): policy = { "key": aerospike.POLICY_KEY_SEND, "max_retries": 1, - "gen": aerospike.POLICY_GEN_IGNORE, - "ttl": 1200 + "gen": aerospike.POLICY_GEN_IGNORE } meta = {"gen": 10} From 2e598c811b9526deeae6392f0791f2e097e8278c Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:30:08 -0800 Subject: [PATCH 69/73] Add missing test case for client.append() using client config operate policy's ttl --- test/new_tests/test_client_config_level_options.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/new_tests/test_client_config_level_options.py b/test/new_tests/test_client_config_level_options.py index d37ec90d80..372560613b 100644 --- a/test/new_tests/test_client_config_level_options.py +++ b/test/new_tests/test_client_config_level_options.py @@ -418,6 +418,11 @@ def config_ttl_setup(self, policy_name: str): {"key": KEY, "bin": "a", "val": "a"}, "operate" ), + ( + aerospike.Client.append, + {"key": KEY, "bin": "a", "val": "a"}, + "operate" + ), ]) def test_apis_with_meta_parameter(self, config_ttl_setup, api_method, kwargs: dict, kwargs_with_ttl: dict): kwargs |= kwargs_with_ttl From c98e03501171984bebf705a6fdc407fbd9aba6c2 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:33:21 -0800 Subject: [PATCH 70/73] Clear up in tests --- test/new_tests/test_client_config_level_options.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/new_tests/test_client_config_level_options.py b/test/new_tests/test_client_config_level_options.py index 372560613b..138c0d4487 100644 --- a/test/new_tests/test_client_config_level_options.py +++ b/test/new_tests/test_client_config_level_options.py @@ -387,6 +387,8 @@ def config_ttl_setup(self, policy_name: str): ] ) + # Don't bother testing for DeprecationWarnings here since running Python with -W error flag can + # cause ClientError to be raised. It's too complicated to check both cases @pytest.mark.filterwarnings("ignore::DeprecationWarning") @ttl_param @pytest.mark.parametrize("api_method, kwargs, policy_name", [ @@ -434,6 +436,8 @@ def test_apis_with_meta_parameter(self, config_ttl_setup, api_method, kwargs: di verify_record_ttl(self.client, KEY, expected_ttl=self.NEW_TTL) + # Don't bother testing for DeprecationWarnings here since running Python with -W error flag can + # cause ClientError to be raised. It's too complicated to check both cases @pytest.mark.filterwarnings("ignore::DeprecationWarning") @ttl_param @pytest.mark.parametrize("policy_name", ["batch_write"]) From 0c2fdc7026c3bd3b0587ed54b1d540023bcac5b5 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:38:39 -0800 Subject: [PATCH 71/73] test_batch_write_policy and test_scan_policy don't need to be parametrized --- test/new_tests/test_command_level_policies.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/new_tests/test_command_level_policies.py b/test/new_tests/test_command_level_policies.py index af0c217c91..a8f2cd213b 100644 --- a/test/new_tests/test_command_level_policies.py +++ b/test/new_tests/test_command_level_policies.py @@ -17,7 +17,7 @@ class CommandLevelTTL: NEW_TTL = 3000 POLICY = {"ttl": NEW_TTL} - pytestmark = pytest.mark.parametrize( + meta_and_policy_params = pytest.mark.parametrize( "kwargs_with_ttl", [ {"meta": POLICY}, @@ -25,10 +25,12 @@ class CommandLevelTTL: ] ) + @meta_and_policy_params def test_write_policy(self, kwargs_with_ttl): self.as_connection.put(KEY, bins={"a": 1}, **kwargs_with_ttl) verify_record_ttl(self.client, KEY, expected_ttl=self.NEW_TTL) + @meta_and_policy_params def test_operate_policy(self, kwargs_with_ttl): ops = [ operations.write(bin_name="a", write_item=1) From ecb787879539e1bca382ab5c12a3da3d3e933bd0 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:51:03 -0800 Subject: [PATCH 72/73] Move to pytest.warns() bc simpler to use --- test/new_tests/test_index_deprecated.py | 4 +--- test/new_tests/test_operate_helpers.py | 4 +--- test/new_tests/test_remove.py | 3 +-- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/test/new_tests/test_index_deprecated.py b/test/new_tests/test_index_deprecated.py index a5de8d5aac..46a5a7d906 100644 --- a/test/new_tests/test_index_deprecated.py +++ b/test/new_tests/test_index_deprecated.py @@ -16,8 +16,6 @@ class TestDeprecatedIndexCreationMethods: ] ) def test_deprecated_index_creation_methods(self, index_create_method): - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter(action="always", category=DeprecationWarning) + with pytest.warns(DeprecationWarning): with pytest.raises(e.ParamError): index_create_method(self.as_connection, 1, "demo", "bin_name", "deprecated_index") - assert len(w) == 1 diff --git a/test/new_tests/test_operate_helpers.py b/test/new_tests/test_operate_helpers.py index bdf355bd62..e8b524008c 100644 --- a/test/new_tests/test_operate_helpers.py +++ b/test/new_tests/test_operate_helpers.py @@ -321,12 +321,10 @@ def test_pos_operate_touch_operation_with_bin_and_value_combination(self, key): Invoke operate() with touch value with bin and value combination. """ - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter(action="always", category=DeprecationWarning) + with pytest.warns(DeprecationWarning): ops = [ operations.touch(4000) ] - assert len(w) == 1 self.as_connection.operate(key, ops) (key, meta) = self.as_connection.exists(key) diff --git a/test/new_tests/test_remove.py b/test/new_tests/test_remove.py index 33d689f794..876dcf2d09 100644 --- a/test/new_tests/test_remove.py +++ b/test/new_tests/test_remove.py @@ -49,8 +49,7 @@ def test_pos_remove_with_policy(self, setup_for_pos_tests, kwargs): key = ("test", "demo", 1) if "meta" in kwargs: - cm = warnings.catch_warnings(record=True) - warnings.simplefilter(action="always", category=DeprecationWarning) + cm = pytest.warns(DeprecationWarning) else: cm = nullcontext() From 54284f1abaed60d93a605a28c54dc0b41d9a9e58 Mon Sep 17 00:00:00 2001 From: Julian Nguyen <109386615+juliannguyen4@users.noreply.github.com> Date: Fri, 27 Feb 2026 15:04:14 -0800 Subject: [PATCH 73/73] Report code coverage for code path where -Werror is passed to python --- .github/workflows/smoke-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/smoke-tests.yml b/.github/workflows/smoke-tests.yml index 706a16bdb1..70d63d7099 100644 --- a/.github/workflows/smoke-tests.yml +++ b/.github/workflows/smoke-tests.yml @@ -136,7 +136,7 @@ jobs: registry-username: ${{ env.REGISTRY_NAME == 'docker.io' && secrets.DOCKER_HUB_BOT_USERNAME || secrets.QE_DOCKER_REGISTRY_USERNAME }} registry-password: ${{ env.REGISTRY_NAME == 'docker.io' && secrets.DOCKER_HUB_BOT_PW || secrets.QE_DOCKER_REGISTRY_PASSWORD }} - - run: python3 -m pytest --cov=aerospike_helpers --cov-report xml:coverage.xml ./new_tests + - run: python3 -m pytest -Werror --cov=aerospike_helpers --cov-report xml:coverage.xml ./new_tests working-directory: test - name: Copy over source files to build dir