Skip to content

Commit 41b0c30

Browse files
authored
[SYNPY-1667]Update Error Messaging when Attempting to Delete Rows that do not exist from Tables (#1257)
* add test for raised exceptions * update how discrepant rows are identified and formatted * update discrepant rows in test case * raise lookuperror instead of valueerror * re escape string * separate failure tests and properly escape characters * update var name * add comment
1 parent 5d21697 commit 41b0c30

File tree

3 files changed

+78
-6
lines changed

3 files changed

+78
-6
lines changed

synapseclient/models/mixins/table_components.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4184,9 +4184,16 @@ async def main():
41844184
existing_rows, on=["ROW_ID", "ROW_VERSION"], how="left", indicator=True
41854185
)
41864186
if not all(merged["_merge"] == "both"):
4187-
discrepant_idx = merged.loc[merged["_merge"] != "both"].index
4188-
raise ValueError(
4189-
f"Rows with the following ROW_ID and ROW_VERSION pairs were not found in table {self.id}: {', '.join(map(str, discrepant_idx))}."
4187+
discrepant_rows = (
4188+
merged.loc[merged["_merge"] != "both"][["ROW_ID", "ROW_VERSION"]]
4189+
.astype(str)
4190+
.values
4191+
)
4192+
discrepant_tuples = [
4193+
f"({', '.join(tuple)})" for tuple in discrepant_rows
4194+
]
4195+
raise LookupError(
4196+
f"Rows with the following ROW_ID and ROW_VERSION pairs were not found in table {self.id}: {', '.join(discrepant_tuples)}."
41904197
)
41914198
client.logger.info(
41924199
f"Received {len(rows_to_delete)} rows to delete for given dataframe."

tests/integration/synapseclient/models/async/test_table_async.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import json
22
import os
33
import random
4+
import re
45
import string
56
import tempfile
67
import uuid
@@ -1849,6 +1850,43 @@ async def test_delete_multiple_rows_via_dataframe(
18491850
# AND only 1 row should exist on the table
18501851
assert len(results) == 1
18511852

1853+
async def test_delete_multiple_rows_via_dataframe_exception(
1854+
self, project_model: Project
1855+
) -> None:
1856+
# GIVEN a table in Synapse
1857+
table_name = str(uuid.uuid4())
1858+
table = Table(
1859+
name=table_name,
1860+
parent_id=project_model.id,
1861+
columns=[Column(name="column_string", column_type=ColumnType.STRING)],
1862+
)
1863+
table = await table.store_async(synapse_client=self.syn)
1864+
self.schedule_for_cleanup(table.id)
1865+
1866+
# AND data for a column already stored in Synapse
1867+
data_for_table = pd.DataFrame({"column_string": ["value1", "value2", "value3"]})
1868+
await table.store_rows_async(
1869+
values=data_for_table, schema_storage_strategy=None, synapse_client=self.syn
1870+
)
1871+
1872+
# AND row ids and versions that do not exist in the table
1873+
row_ids = [4, 5]
1874+
row_versions = [1, 1]
1875+
1876+
# And an excpeted error message that should be displayed
1877+
row_id_version_tuples = ", ".join(
1878+
[f"({id}, {version})" for id, version in zip(row_ids, row_versions)]
1879+
)
1880+
exception_message = f"Rows with the following ROW_ID and ROW_VERSION pairs were not found in table {re.escape(table.id)}: {re.escape(row_id_version_tuples)}."
1881+
1882+
# WHEN the rows that do not exist are attempted to be deleted
1883+
# THEN a value error should be raised and the appropriate message should be displayed
1884+
with pytest.raises(LookupError, match=exception_message):
1885+
await table.delete_rows_async(
1886+
df=pd.DataFrame({"ROW_ID": row_ids, "ROW_VERSION": row_versions}),
1887+
synapse_client=self.syn,
1888+
)
1889+
18521890

18531891
class TestColumnModifications:
18541892
@pytest.fixture(autouse=True, scope="function")

tests/unit/synapseclient/mixins/unit_test_table_components.py

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1902,15 +1902,42 @@ async def test_delete_rows_async_via_dataframe_pass(self):
19021902
pd.DataFrame(columns=["INVALID_COL1", "INVALID_COL2"]), # Both invalid
19031903
"The dataframe must contain the 'ROW_ID' and 'ROW_VERSION' columns.",
19041904
),
1905+
],
1906+
)
1907+
async def test_delete_rows_via_dataframe_fail_missing_columns(self, df, error_msg):
1908+
# GIVEN a TestClass instance
1909+
test_instance = self.ClassForTest()
1910+
1911+
# WHEN I call delete_rows_async
1912+
with (
1913+
patch(
1914+
"synapseclient.models.mixins.table_components.QueryMixin.query_async",
1915+
return_value=pd.DataFrame(
1916+
{"ROW_ID": ["A", "B"], "ROW_VERSION": [1, 2]}
1917+
),
1918+
) as mock_query_async,
1919+
patch.object(self.syn.logger, "info") as mock_logger_info,
1920+
):
1921+
with pytest.raises(ValueError, match=error_msg):
1922+
result = await test_instance.delete_rows_async(
1923+
df=df, synapse_client=self.syn
1924+
)
1925+
1926+
# THEN mock_logger_info should not be called
1927+
mock_logger_info.assert_not_called()
1928+
1929+
@pytest.mark.parametrize(
1930+
"df, error_msg",
1931+
[
19051932
(
19061933
pd.DataFrame(
19071934
{"ROW_ID": ["C", "D"], "ROW_VERSION": [2, 2]}
19081935
), # Both invalid
1909-
"Rows with the following ROW_ID and ROW_VERSION pairs were not found in table syn123: 0, 1.",
1936+
"Rows with the following ROW_ID and ROW_VERSION pairs were not found in table syn123: \\(C, 2\\), \\(D, 2\\).", # Special characters must be escaped due to use with regex in test
19101937
),
19111938
],
19121939
)
1913-
async def test_delete_rows_via_dataframe_fail(self, df, error_msg):
1940+
async def test_delete_rows_via_dataframe_fail_missing_rows(self, df, error_msg):
19141941
# GIVEN a TestClass instance
19151942
test_instance = self.ClassForTest()
19161943

@@ -1924,7 +1951,7 @@ async def test_delete_rows_via_dataframe_fail(self, df, error_msg):
19241951
) as mock_query_async,
19251952
patch.object(self.syn.logger, "info") as mock_logger_info,
19261953
):
1927-
with pytest.raises(ValueError, match=error_msg):
1954+
with pytest.raises(LookupError, match=error_msg):
19281955
result = await test_instance.delete_rows_async(
19291956
df=df, synapse_client=self.syn
19301957
)

0 commit comments

Comments
 (0)