Skip to content

Commit f26151a

Browse files
authored
Overide Image.hydrate to hide from docs and error better (#3333)
* Overide Image.hydrate to hide from docs and error better * Add .hydrate() call on hydrated image
1 parent f3237da commit f26151a

2 files changed

Lines changed: 18 additions & 2 deletions

File tree

modal/image.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
from google.protobuf.message import Message
2525
from grpclib.exceptions import GRPCError, StreamTerminatedError
26+
from typing_extensions import Self
2627

2728
from modal_proto import api_pb2
2829

@@ -42,7 +43,7 @@
4243
from .cloud_bucket_mount import _CloudBucketMount
4344
from .config import config, logger, user_config_path
4445
from .environments import _get_environment_cached
45-
from .exception import InvalidError, NotFoundError, RemoteError, VersionError
46+
from .exception import ExecutionError, InvalidError, NotFoundError, RemoteError, VersionError
4647
from .file_pattern_matcher import NON_PYTHON_FILES, FilePatternMatcher, _ignore_fn
4748
from .gpu import GPU_T, parse_gpu_config
4849
from .mount import _Mount, python_standalone_mount_name
@@ -2295,5 +2296,15 @@ async def _logs(self) -> typing.AsyncGenerator[str, None]:
22952296
if task_log.data:
22962297
yield task_log.data
22972298

2299+
async def hydrate(self, client: Optional[_Client] = None) -> Self:
2300+
"""mdmd:hidden"""
2301+
# Image inherits hydrate() from Object but can't be hydrated on demand
2302+
# Overriding the method lets us hide it from the docs and raise a better error message
2303+
if not self.is_hydrated:
2304+
raise ExecutionError(
2305+
"Images cannot currently be hydrated on demand; you can build an Image by running an App that uses it."
2306+
)
2307+
return self
2308+
22982309

22992310
Image = synchronize_api(_Image)

test/image_test.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from modal._serialization import serialize
1818
from modal._utils.async_utils import synchronizer
1919
from modal.client import Client
20-
from modal.exception import InvalidError, ModuleNotMountable, NotFoundError, VersionError
20+
from modal.exception import ExecutionError, InvalidError, ModuleNotMountable, NotFoundError, VersionError
2121
from modal.experimental import raw_dockerfile_image, raw_registry_image
2222
from modal.file_pattern_matcher import FilePatternMatcher
2323
from modal.image import (
@@ -2261,3 +2261,8 @@ def test_raw_registry_image(servicer, client):
22612261

22622262
with pytest.raises(InvalidError, match="whatever"):
22632263
raw_registry_image(tag, registry_secret=registry_secret, credential_type="whatever") # type: ignore
2264+
2265+
2266+
def test_hydration_refusal():
2267+
with pytest.raises(ExecutionError, match="Images cannot currently be hydrated on demand"):
2268+
Image.debian_slim().hydrate()

0 commit comments

Comments
 (0)