Skip to content

Commit cbd209e

Browse files
yeldarbyclaude
andcommitted
trash: use "project" instead of "dataset" for the item-type vocabulary
Aligns the SDK with the rest of the public API. Diego flagged on the docs PR that DELETE responses use `type: "project"` but the trash list/restore payloads were using `type: "dataset"` — same item, two names. Fixing on `"project"` to match the rest of the public surface (`:project` URL params, DELETE responses, the `project:*` scope namespace). Backend ships the same change on the `soft-delete` branch; the docs PR covers the user-visible REST API and SDK pages. - `Project.restore()`: looks up `trash["sections"]["projects"]` and passes `"project"` to `rfapi.restore_trash_item`. Docstring updated to show `type: "project"` in the example response. - `Workspace.restore_from_trash()`: docstring lists the valid item types as `"project"`, `"version"`, `"workflow"` (was `"dataset"`/.../...). - `roboflow project restore` CLI: same lookup + restore call. - `rfapi.restore_trash_item` docstring: matching update. - Tests under `tests/cli/test_project_handler.py` and `tests/cli/test_trash_handler.py` now exercise the project vocabulary. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 3624bac commit cbd209e

6 files changed

Lines changed: 17 additions & 17 deletions

File tree

roboflow/adapters/rfapi.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -931,8 +931,8 @@ def list_trash(api_key, workspace_url):
931931
def restore_trash_item(api_key, workspace_url, item_type, item_id, parent_id=None):
932932
"""POST /{workspace}/trash/restore — restore an item from Trash.
933933
934-
`item_type` must be one of "dataset", "version", "workflow".
935-
`parent_id` is required when restoring a version (the dataset id).
934+
`item_type` must be one of "project", "version", "workflow".
935+
`parent_id` is required when restoring a version (the parent project id).
936936
"""
937937
url = f"{API_URL}/{workspace_url}/trash/restore?api_key={api_key}"
938938
payload = {"type": item_type, "id": item_id}

roboflow/cli/handlers/project.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,8 @@ def _restore_project(args): # noqa: ANN001
314314
)
315315
return
316316

317-
datasets = trash.get("sections", {}).get("datasets", [])
318-
match = next((d for d in datasets if d.get("url") == project_slug), None)
317+
projects = trash.get("sections", {}).get("projects", [])
318+
match = next((p for p in projects if p.get("url") == project_slug), None)
319319
if not match:
320320
output_error(
321321
args,
@@ -326,7 +326,7 @@ def _restore_project(args): # noqa: ANN001
326326
return
327327

328328
try:
329-
data = rfapi.restore_trash_item(api_key, workspace_url, "dataset", match["id"])
329+
data = rfapi.restore_trash_item(api_key, workspace_url, "project", match["id"])
330330
except rfapi.RoboflowError as exc:
331331
output_error(
332332
args,

roboflow/core/project.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,7 +1069,7 @@ def restore(self):
10691069
RuntimeError if the project isn't currently in Trash.
10701070
10711071
Returns:
1072-
dict: Server response with `{restored: True, type: "dataset", ...}`.
1072+
dict: Server response with `{restored: True, type: "project", ...}`.
10731073
10741074
Example:
10751075
>>> import roboflow
@@ -1079,8 +1079,8 @@ def restore(self):
10791079
>>> project.restore()
10801080
"""
10811081
trash = rfapi.list_trash(self.__api_key, self.__workspace)
1082-
datasets = trash.get("sections", {}).get("datasets", [])
1083-
match = next((d for d in datasets if d.get("url") == self.__project_name), None)
1082+
projects = trash.get("sections", {}).get("projects", [])
1083+
match = next((p for p in projects if p.get("url") == self.__project_name), None)
10841084
if not match:
10851085
raise RuntimeError(f"Project '{self.__project_name}' is not in Trash — nothing to restore.")
1086-
return rfapi.restore_trash_item(self.__api_key, self.__workspace, "dataset", match["id"])
1086+
return rfapi.restore_trash_item(self.__api_key, self.__workspace, "project", match["id"])

roboflow/core/workspace.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,7 +1339,7 @@ def trash(self) -> dict:
13391339
13401340
Returns a dict with:
13411341
- `items`: flat list of everything in Trash
1342-
- `sections`: grouped by `datasets`, `versions`, `workflows`
1342+
- `sections`: grouped by `projects`, `versions`, `workflows`
13431343
Each item includes `id`, `type`, `name`, `deletedAt`,
13441344
`scheduledCleanupAt`, and — for versions — `parentId` / `parentUrl`.
13451345
@@ -1358,9 +1358,9 @@ def restore_from_trash(self, item_type: str, item_id: str, parent_id: Optional[s
13581358
Restore an item from Trash.
13591359
13601360
Args:
1361-
item_type: one of "dataset", "version", "workflow"
1361+
item_type: one of "project", "version", "workflow"
13621362
item_id: the item's Firestore id (found via `trash()`)
1363-
parent_id: required when restoring a version — the parent dataset id
1363+
parent_id: required when restoring a version — the parent project id
13641364
13651365
Returns:
13661366
dict: Server response with `{restored: True, type, id}`.

tests/cli/test_project_handler.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,16 +94,16 @@ def test_restore_found(self) -> None:
9494

9595
from roboflow.cli.handlers.project import _restore_project
9696

97-
trash = {"sections": {"datasets": [{"id": "abc123", "url": "my-proj", "name": "My Project"}]}}
97+
trash = {"sections": {"projects": [{"id": "abc123", "url": "my-proj", "name": "My Project"}]}}
9898
with (
9999
patch("roboflow.adapters.rfapi.list_trash", return_value=trash),
100100
patch(
101101
"roboflow.adapters.rfapi.restore_trash_item",
102-
return_value={"restored": True, "type": "dataset", "id": "abc123"},
102+
return_value={"restored": True, "type": "project", "id": "abc123"},
103103
) as mock_restore,
104104
):
105105
_restore_project(self._args())
106-
mock_restore.assert_called_once_with("fake-key", "my-ws", "dataset", "abc123")
106+
mock_restore.assert_called_once_with("fake-key", "my-ws", "project", "abc123")
107107

108108
def test_restore_not_in_trash(self) -> None:
109109
from unittest.mock import patch
@@ -115,7 +115,7 @@ def test_restore_not_in_trash(self) -> None:
115115
with (
116116
patch(
117117
"roboflow.adapters.rfapi.list_trash",
118-
return_value={"sections": {"datasets": []}},
118+
return_value={"sections": {"projects": []}},
119119
),
120120
patch("roboflow.adapters.rfapi.restore_trash_item") as mock_restore,
121121
patch("sys.exit"),

tests/cli/test_trash_handler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def test_list_text_output(self) -> None:
5959
trash_response = {
6060
"items": [
6161
{
62-
"type": "dataset",
62+
"type": "project",
6363
"id": "d1",
6464
"name": "My Project",
6565
"deletedAt": "2026-04-01",

0 commit comments

Comments
 (0)