Skip to content

Commit ebde048

Browse files
zekeclaude
andcommitted
feat: add get_path_url() function support for migration compatibility
Add support for get_path_url() function to maintain compatibility with old replicate-python client. This function extracts remote URLs from file output objects, enabling users to reuse URLs in model inputs. Key changes: - Export get_path_url from main module (__init__.py) - Add module-level function proxy in _module_client.py - Enhance FileOutput classes with __url__ attribute for compatibility - Add comprehensive test coverage for all supported object types - Maintain backward compatibility with same API as old client 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent b726483 commit ebde048

File tree

4 files changed

+121
-0
lines changed

4 files changed

+121
-0
lines changed

src/replicate/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
"Model",
9090
"Version",
9191
"ModelVersionIdentifier",
92+
"get_path_url",
9293
]
9394

9495
if not _t.TYPE_CHECKING:
@@ -104,6 +105,9 @@
104105
for __name in __all__:
105106
if not __name.startswith("__"):
106107
try:
108+
# Skip get_path_url as it's imported later
109+
if __name == "get_path_url":
110+
continue
107111
__locals[__name].__module__ = "replicate"
108112
except (TypeError, AttributeError):
109113
# Some of our exported symbols are builtins which we can't set attributes for.
@@ -253,4 +257,5 @@ def _reset_client() -> None: # type: ignore[reportUnusedFunction]
253257
collections as collections,
254258
deployments as deployments,
255259
predictions as predictions,
260+
get_path_url as get_path_url,
256261
)

src/replicate/_module_client.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ def __load__(self) -> PredictionsResource:
8282
__client: Replicate = cast(Replicate, {})
8383
run = __client.run
8484
use = __client.use
85+
86+
# Import get_path_url for type checking
87+
from .lib._predictions_use import get_path_url
8588
else:
8689

8790
def _run(*args, **kwargs):
@@ -100,8 +103,14 @@ def _use(ref, *, hint=None, streaming=False, use_async=False, **kwargs):
100103

101104
return use(Replicate, ref, hint=hint, streaming=streaming, **kwargs)
102105

106+
def _get_path_url(path):
107+
from .lib._predictions_use import get_path_url
108+
109+
return get_path_url(path)
110+
103111
run = _run
104112
use = _use
113+
get_path_url = _get_path_url
105114

106115
files: FilesResource = FilesResourceProxy().__as_proxied__()
107116
models: ModelsResource = ModelsResourceProxy().__as_proxied__()

src/replicate/lib/_files.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ class FileOutput(httpx.SyncByteStream):
139139
def __init__(self, url: str, client: Replicate) -> None:
140140
self.url = url
141141
self._client = client
142+
# Add __url__ attribute for compatibility with get_path_url()
143+
self.__url__ = url
142144

143145
def read(self) -> bytes:
144146
if self.url.startswith("data:"):
@@ -184,6 +186,8 @@ class AsyncFileOutput(httpx.AsyncByteStream):
184186
def __init__(self, url: str, client: AsyncReplicate) -> None:
185187
self.url = url
186188
self._client = client
189+
# Add __url__ attribute for compatibility with get_path_url()
190+
self.__url__ = url
187191

188192
async def read(self) -> bytes:
189193
if self.url.startswith("data:"):

tests/lib/test_get_path_url.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
from pathlib import Path
2+
3+
import replicate
4+
from replicate.lib._files import FileOutput, AsyncFileOutput
5+
from replicate.lib._predictions_use import URLPath, get_path_url
6+
7+
8+
def test_get_path_url_with_urlpath():
9+
"""Test get_path_url returns the URL for URLPath instances."""
10+
url = "https://example.com/test.jpg"
11+
path_proxy = URLPath(url)
12+
13+
result = get_path_url(path_proxy)
14+
assert result == url
15+
16+
17+
def test_get_path_url_with_fileoutput():
18+
"""Test get_path_url returns the URL for FileOutput instances."""
19+
url = "https://example.com/test.jpg"
20+
file_output = FileOutput(url, replicate.Replicate())
21+
22+
result = get_path_url(file_output)
23+
assert result == url
24+
25+
26+
def test_get_path_url_with_async_fileoutput():
27+
"""Test get_path_url returns the URL for AsyncFileOutput instances."""
28+
url = "https://example.com/test.jpg"
29+
async_file_output = AsyncFileOutput(url, replicate.AsyncReplicate())
30+
31+
result = get_path_url(async_file_output)
32+
assert result == url
33+
34+
35+
def test_get_path_url_with_regular_path():
36+
"""Test get_path_url returns None for regular Path instances."""
37+
regular_path = Path("test.txt")
38+
39+
result = get_path_url(regular_path)
40+
assert result is None
41+
42+
43+
def test_get_path_url_with_object_without_target():
44+
"""Test get_path_url returns None for objects without __url__."""
45+
46+
# Test with a string
47+
result = get_path_url("not a path")
48+
assert result is None
49+
50+
# Test with a dict
51+
result = get_path_url({"key": "value"})
52+
assert result is None
53+
54+
# Test with None
55+
result = get_path_url(None)
56+
assert result is None
57+
58+
59+
def test_get_path_url_module_level_import():
60+
"""Test that get_path_url can be imported at module level."""
61+
from replicate import get_path_url as module_get_path_url
62+
63+
url = "https://example.com/test.jpg"
64+
file_output = FileOutput(url, replicate.Replicate())
65+
66+
result = module_get_path_url(file_output)
67+
assert result == url
68+
69+
70+
def test_get_path_url_direct_module_access():
71+
"""Test that get_path_url can be accessed directly from replicate module."""
72+
url = "https://example.com/test.jpg"
73+
file_output = FileOutput(url, replicate.Replicate())
74+
75+
result = replicate.get_path_url(file_output)
76+
assert result == url
77+
78+
79+
def test_fileoutput_has_url_attribute():
80+
"""Test that FileOutput instances have __url__ attribute."""
81+
url = "https://example.com/test.jpg"
82+
file_output = FileOutput(url, replicate.Replicate())
83+
84+
assert hasattr(file_output, "__url__")
85+
assert file_output.__url__ == url
86+
87+
88+
def test_async_fileoutput_has_url_attribute():
89+
"""Test that AsyncFileOutput instances have __url__ attribute."""
90+
url = "https://example.com/test.jpg"
91+
async_file_output = AsyncFileOutput(url, replicate.AsyncReplicate())
92+
93+
assert hasattr(async_file_output, "__url__")
94+
assert async_file_output.__url__ == url
95+
96+
97+
def test_urlpath_has_url_attribute():
98+
"""Test that URLPath instances have __url__ attribute."""
99+
url = "https://example.com/test.jpg"
100+
url_path = URLPath(url)
101+
102+
assert hasattr(url_path, "__url__")
103+
assert url_path.__url__ == url

0 commit comments

Comments
 (0)