diff --git a/quasardb/numpy/__init__.py b/quasardb/numpy/__init__.py index cab194cc..32479995 100644 --- a/quasardb/numpy/__init__.py +++ b/quasardb/numpy/__init__.py @@ -863,6 +863,12 @@ def write_arrays( assert len(dtype) is len(cinfos) if index is None and isinstance(data_, dict) and "$timestamp" in data_: + # Create shallow copy of `data_` so that we don't modify the reference, i.e. + # delete keys. + # + # This ensures that the user can call the same function multiple times without + # side-effects. + data_ = data_.copy() index_ = data_.pop("$timestamp") assert "$timestamp" not in data_ elif index is not None: diff --git a/scripts/teamcity/20.test.sh b/scripts/teamcity/20.test.sh index a3b052f2..c3d5d2aa 100644 --- a/scripts/teamcity/20.test.sh +++ b/scripts/teamcity/20.test.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash SCRIPT_DIR="$(cd "$(dirname -- "${BASH_SOURCE[0]}")" >/dev/null && pwd)" diff --git a/tests/test_numpy.py b/tests/test_numpy.py index c3c2f761..86dda992 100644 --- a/tests/test_numpy.py +++ b/tests/test_numpy.py @@ -141,6 +141,60 @@ def test_arrays_read_write_data_as_dict(array_with_index_and_table, qdbd_connect assert_indexed_arrays_equal((index, data), res) +@conftest.override_cdtypes("native") +def test_provide_index_as_dict(array_with_index_and_table, qdbd_connection): + """ + For convenience, we allow the `$timestamp` index also to provided as a dict + key. + """ + (ctype, dtype, data, index, table) = array_with_index_and_table + + col = table.column_id_by_index(0) + dict_ = {"$timestamp": index, col: data} + + qdbnp.write_arrays( + dict_, + qdbd_connection, + table, + dtype=dtype, + infer_types=False, + truncate=True, + ) + + res = qdbnp.read_array(table, col) + + assert_indexed_arrays_equal((index, data), res) + + +@conftest.override_cdtypes("native") +def test_provide_index_as_dict_has_no_side_effects_sc16279( + array_with_index_and_table, qdbd_connection +): + """ + In earlier versions of the API, we `pop`'ed the $timestamp from the provided dict without making a + shallow copy of the dict. This would cause re-invocations of the same function (e.g. in case of an + error) to not work, as the original dict had been modified. + + The test below has been confirmed to trigger the original bug described in QDB-16279, and was fixed + afterwards. + """ + (ctype, dtype, data, index, table) = array_with_index_and_table + + col = table.column_id_by_index(0) + + dict_ = {"$timestamp": index, col: data} + qdbnp.write_arrays( + dict_, + qdbd_connection, + table, + dtype=dtype, + infer_types=False, + truncate=True, + ) + + assert "$timestamp" in dict_ + + ###### # # Arrays tests