Skip to content

Commit 65ed4c1

Browse files
committed
Add support for files API endpoints
Signed-off-by: Mattt Zmuda <[email protected]>
1 parent cd09db0 commit 65ed4c1

File tree

1 file changed

+127
-1
lines changed

1 file changed

+127
-1
lines changed

replicate/files.py

Lines changed: 127 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,136 @@
22
import io
33
import mimetypes
44
import os
5-
from typing import Optional
5+
from typing import Any, Dict, List, Optional
66

77
import httpx
88

9+
from replicate.resource import Namespace, Resource
10+
11+
12+
class File(Resource):
13+
"""A file on the server."""
14+
15+
id: str
16+
"""The ID of the file."""
17+
18+
name: str
19+
"""The name of the file."""
20+
21+
content_type: str
22+
"""The content type of the file."""
23+
24+
size: int
25+
"""The size of the file in bytes."""
26+
27+
etag: str
28+
"""The ETag of the file."""
29+
30+
checksum: str
31+
"""The checksum of the file."""
32+
33+
metadata: Dict[str, Any]
34+
"""The metadata of the file."""
35+
36+
created_at: str
37+
"""The time the file was created."""
38+
39+
expires_at: Optional[str]
40+
"""The time the file will expire."""
41+
42+
urls: Dict[str, str]
43+
"""The URLs of the file."""
44+
45+
46+
class Files(Namespace):
47+
def create(
48+
self, file: io.IOBase, metadata: Optional[Dict[str, Any]] = None
49+
) -> File:
50+
"""Create a file on the server."""
51+
52+
file.seek(0)
53+
54+
resp = self._client._request(
55+
"POST",
56+
"/files",
57+
data={
58+
"content": _file_content(file),
59+
"metadata": metadata,
60+
},
61+
timeout=None,
62+
)
63+
64+
return _json_to_file(resp.json())
65+
66+
async def async_create(
67+
self, file: io.IOBase, metadata: Optional[Dict[str, Any]] = None
68+
) -> File:
69+
"""Create a file on the server."""
70+
71+
file.seek(0)
72+
73+
resp = await self._client._async_request(
74+
"POST",
75+
"/files",
76+
data={
77+
"content": _file_content(file),
78+
"metadata": metadata,
79+
},
80+
timeout=None,
81+
)
82+
83+
return _json_to_file(resp.json())
84+
85+
def get(self, file_id: str) -> File:
86+
"""Get a file from the server by its ID."""
87+
88+
resp = self._client._request("GET", f"/files/{file_id}")
89+
return _json_to_file(resp.json())
90+
91+
async def async_get(self, file_id: str) -> File:
92+
"""Get a file from the server by its ID."""
93+
94+
resp = await self._client._async_request("GET", f"/files/{file_id}")
95+
return _json_to_file(resp.json())
96+
97+
def list(self) -> List[File]:
98+
"""List all files on the server."""
99+
100+
resp = self._client._request("GET", "/files")
101+
return [_json_to_file(file_json) for file_json in resp.json()]
102+
103+
async def async_list(self) -> List[File]:
104+
"""List all files on the server."""
105+
106+
resp = await self._client._async_request("GET", "/files")
107+
return [_json_to_file(file_json) for file_json in resp.json()]
108+
109+
def delete(self, file_id: str) -> File:
110+
"""Delete a file from the server by its ID."""
111+
112+
resp = self._client._request("DELETE", f"/files/{file_id}")
113+
return _json_to_file(resp.json())
114+
115+
async def async_delete(self, file_id: str) -> File:
116+
"""Delete a file from the server by its ID."""
117+
118+
resp = await self._client._async_request("DELETE", f"/files/{file_id}")
119+
return _json_to_file(resp.json())
120+
121+
122+
def _file_content(file: io.IOBase) -> tuple[str, io.IOBase, str]:
123+
"""Get the file content details including name, file object and content type."""
124+
125+
name = getattr(file, "name", "output")
126+
content_type = (
127+
mimetypes.guess_type(getattr(file, "name", ""))[0] or "application/octet-stream"
128+
)
129+
return (os.path.basename(name), file, content_type)
130+
131+
132+
def _json_to_file(json: Dict[str, Any]) -> File:
133+
return File(**json)
134+
9135

10136
def upload_file(file: io.IOBase, output_file_prefix: Optional[str] = None) -> str:
11137
"""

0 commit comments

Comments
 (0)