Skip to content

Commit 8217e8d

Browse files
fix: overwrite mode now deletes existing dataset before re-creating
Previously, on_exist="overwrite" called create_dataset directly, which returned a 409 Conflict (DatasetUploadError) when the dataset already existed. The code incorrectly assumed Phoenix would create a new version. The fix looks up the existing dataset, deletes it via the REST API (DELETE /v1/datasets/{id}), then creates a fresh dataset.
1 parent 36b9534 commit 8217e8d

2 files changed

Lines changed: 29 additions & 6 deletions

File tree

src/evalwire/uploader.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import logging
66
from pathlib import Path
77
from typing import TYPE_CHECKING, Any, Literal, cast
8+
from urllib.parse import quote
89

910
import pandas as pd
1011

@@ -145,9 +146,12 @@ def _upload_one(
145146
)
146147

147148
elif on_exist == "overwrite":
148-
# Phoenix datasets are versioned; create_dataset with an existing name
149-
# adds a new version rather than replacing the dataset object, so a
150-
# delete step is not needed (and no delete API exists in Phoenix >=13).
149+
try:
150+
existing = self.client.datasets.get_dataset(dataset=name)
151+
self._delete_dataset(existing.id)
152+
logger.info("Deleted existing dataset %r; re-creating.", name)
153+
except ValueError:
154+
logger.debug("Dataset %r not found; creating it.", name)
151155
return self.client.datasets.create_dataset(
152156
dataframe=df,
153157
name=name,
@@ -176,3 +180,15 @@ def _upload_one(
176180
input_keys=self.input_keys,
177181
output_keys=self.output_keys,
178182
)
183+
184+
def _delete_dataset(self, dataset_id: str) -> None:
185+
"""Delete a dataset via the Phoenix REST API.
186+
187+
The Phoenix Python client does not expose a delete method, but the
188+
server supports ``DELETE /v1/datasets/{id}``.
189+
"""
190+
response = self.client.datasets._client.delete(
191+
url=f"v1/datasets/{quote(dataset_id)}",
192+
headers={"accept": "application/json"},
193+
)
194+
response.raise_for_status()

tests/test_uploader.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,19 +107,26 @@ def test_non_not_found_error_propagates(
107107

108108

109109
class TestUploadOverwrite:
110-
def test_always_calls_upload_dataset(
110+
def test_deletes_existing_then_creates(
111111
self, sample_csv: Path, mock_phoenix_client: MagicMock
112112
):
113+
existing = MagicMock()
114+
existing.id = "ds-123"
115+
mock_phoenix_client.datasets.get_dataset.return_value = existing
116+
mock_response = MagicMock()
117+
mock_phoenix_client.datasets._client.delete.return_value = mock_response
113118
uploader = _make_uploader(sample_csv, mock_phoenix_client)
114119
uploader.upload(on_exist="overwrite")
115-
assert mock_phoenix_client.datasets.create_dataset.called
120+
mock_phoenix_client.datasets._client.delete.assert_called()
121+
mock_phoenix_client.datasets.create_dataset.assert_called()
116122

117-
def test_overwrite_when_dataset_missing_still_creates(
123+
def test_creates_directly_when_dataset_missing(
118124
self, sample_csv: Path, mock_phoenix_client: MagicMock
119125
):
120126
mock_phoenix_client.datasets.get_dataset.side_effect = ValueError("not found")
121127
uploader = _make_uploader(sample_csv, mock_phoenix_client)
122128
result = uploader.upload(on_exist="overwrite")
129+
mock_phoenix_client.datasets._client.delete.assert_not_called()
123130
assert mock_phoenix_client.datasets.create_dataset.called
124131
assert len(result) == 2
125132

0 commit comments

Comments
 (0)