Skip to content

Commit 85d9b2a

Browse files
authored
Implement models.versions.delete endpoint (#234)
In #173, @satellitebryn mentioned the [`models.versions.delete`](https://replicate.com/docs/reference/http#models.versions.delete) endpoint, which currently doesn't have a corresponding method in the Python client. This PR adds a `delete` and `async_delete` method to the `versions` namespace. ```python model = client.models.get("your-username/model-name") model.versions.delete(model.latest_version.id) ``` Signed-off-by: Mattt Zmuda <[email protected]>
1 parent a7f725c commit 85d9b2a

File tree

2 files changed

+127
-0
lines changed

2 files changed

+127
-0
lines changed

replicate/version.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,46 @@ async def async_list(self) -> Page[Version]:
113113

114114
return Page[Version](**obj)
115115

116+
def delete(self, id: str) -> bool:
117+
"""
118+
Delete a model version and all associated predictions, including all output files.
119+
120+
Model version deletion has some restrictions:
121+
122+
* You can only delete versions from models you own.
123+
* You can only delete versions from private models.
124+
* You cannot delete a version if someone other than you
125+
has run predictions with it.
126+
127+
Args:
128+
id: The version ID.
129+
"""
130+
131+
resp = self._client._request(
132+
"DELETE", f"/v1/models/{self.model[0]}/{self.model[1]}/versions/{id}"
133+
)
134+
return resp.status_code == 204
135+
136+
async def async_delete(self, id: str) -> bool:
137+
"""
138+
Delete a model version and all associated predictions, including all output files.
139+
140+
Model version deletion has some restrictions:
141+
142+
* You can only delete versions from models you own.
143+
* You can only delete versions from private models.
144+
* You cannot delete a version if someone other than you
145+
has run predictions with it.
146+
147+
Args:
148+
id: The version ID.
149+
"""
150+
151+
resp = await self._client._async_request(
152+
"DELETE", f"/v1/models/{self.model[0]}/{self.model[1]}/versions/{id}"
153+
)
154+
return resp.status_code == 204
155+
116156

117157
def _json_to_version(json: Dict[str, Any]) -> Version:
118158
return Version(**json)

tests/test_version.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import httpx
2+
import pytest
3+
import respx
4+
5+
from replicate.client import Client
6+
7+
router = respx.Router(base_url="https://api.replicate.com/v1")
8+
9+
router.route(
10+
method="GET",
11+
path="/models/replicate/hello-world",
12+
name="models.get",
13+
).mock(
14+
return_value=httpx.Response(
15+
200,
16+
json={
17+
"owner": "replicate",
18+
"name": "hello-world",
19+
"description": "A tiny model that says hello",
20+
"visibility": "public",
21+
"run_count": 1e10,
22+
"url": "https://replicate.com/replicate/hello-world",
23+
"created_at": "2022-04-26T19:13:45.911328Z",
24+
"latest_version": {
25+
"id": "5c7d5dc6dd8bf75c1acaa8565735e7986bc5b66206b55cca93cb72c9bf15ccaa",
26+
"cog_version": "0.3.0",
27+
"openapi_schema": {
28+
"openapi": "3.0.2",
29+
"info": {"title": "Cog", "version": "0.1.0"},
30+
"components": {
31+
"schemas": {
32+
"Input": {
33+
"type": "object",
34+
"title": "Input",
35+
"required": ["text"],
36+
"properties": {
37+
"text": {
38+
"type": "string",
39+
"title": "Text",
40+
"x-order": 0,
41+
"description": "Text to prefix with 'hello '",
42+
}
43+
},
44+
},
45+
"Output": {"type": "string", "title": "Output"},
46+
}
47+
},
48+
},
49+
"created_at": "2022-04-26T19:29:04.418669Z",
50+
},
51+
},
52+
)
53+
)
54+
55+
router.route(
56+
method="DELETE",
57+
path__regex=r"^/models/replicate/hello-world/versions/(?P<id>\w+)/?",
58+
name="models.versions.delete",
59+
).mock(
60+
return_value=httpx.Response(
61+
202,
62+
)
63+
)
64+
65+
66+
@pytest.mark.asyncio
67+
@pytest.mark.parametrize("async_flag", [True, False])
68+
async def test_version_delete(async_flag):
69+
client = Client(
70+
api_token="test-token", transport=httpx.MockTransport(router.handler)
71+
)
72+
73+
if async_flag:
74+
model = await client.models.async_get("replicate/hello-world")
75+
assert model is not None
76+
assert model.latest_version is not None
77+
78+
await model.versions.async_delete(model.latest_version.id)
79+
else:
80+
model = client.models.get("replicate/hello-world")
81+
assert model is not None
82+
assert model.latest_version is not None
83+
84+
model.versions.delete(model.latest_version.id)
85+
86+
assert router["models.get"].called
87+
assert router["models.versions.delete"].called

0 commit comments

Comments
 (0)