Skip to content

Commit 893b23c

Browse files
committed
Raise error on providing absolute path to local files
1 parent a259335 commit 893b23c

File tree

4 files changed

+17
-7
lines changed

4 files changed

+17
-7
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ poetry.toml
55
.ruff_cache/
66
.vscode
77
.env
8-
.env.test
98
tests/assets/*.jsonl
109
tests/assets/*.parquet
10+
# Ignore humanloop directory which could mistakenly be committed when testing sync functionality as it's used as the default sync directory
1111
humanloop

src/humanloop/cli/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def load_api_key(env_file: Optional[str] = None) -> str:
6464
def get_client(
6565
api_key: Optional[str] = None, env_file: Optional[str] = None, base_url: Optional[str] = None
6666
) -> Humanloop:
67-
"""Get a Humanloop client instance.
67+
"""Instantiate a Humanloop client for the CLI.
6868
6969
Args:
7070
api_key: Optional API key provided directly

src/humanloop/overload.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ def _handle_local_files(
108108
)
109109

110110
file_type = _get_file_type_from_client(client)
111+
if file_type not in SyncClient.SERIALIZABLE_FILE_TYPES:
112+
raise HumanloopRuntimeError(f"Local files are not supported for `{file_type}` files.")
113+
111114
# If file_type is already specified in kwargs, it means user provided a PromptKernelRequestParams object
112115
if file_type in kwargs and not isinstance(kwargs[file_type], str):
113116
logger.warning(
@@ -117,7 +120,7 @@ def _handle_local_files(
117120
return kwargs
118121

119122
try:
120-
file_content = sync_client.get_file_content(normalized_path, file_type)
123+
file_content = sync_client.get_file_content(normalized_path, file_type) # type: ignore [arg-type] file_type was checked above
121124
kwargs[file_type] = file_content
122125
except HumanloopRuntimeError as e:
123126
raise HumanloopRuntimeError(f"Failed to use local file for `{normalized_path}`: {str(e)}")
@@ -186,7 +189,7 @@ def overload_client(
186189
use_local_files: bool = False,
187190
) -> Any:
188191
"""Overloads client methods to add tracing, local file handling, and evaluation context."""
189-
# Store original log method as _log for all clients. Used in flow decorator
192+
# Store original log method as _log for all clients. Used in flow decorator
190193
if hasattr(client, "log") and not hasattr(client, "_log"):
191194
client._log = client.log # type: ignore [attr-defined]
192195

src/humanloop/sync/sync_client.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from typing import List, Tuple, TYPE_CHECKING
44
from functools import lru_cache
55
import typing
6-
from humanloop.types import FileType
76
import time
87
from humanloop.error import HumanloopRuntimeError
98
import json
@@ -164,6 +163,14 @@ def _normalize_path(self, path: str) -> str:
164163
# Convert to Path object to handle platform-specific separators
165164
path_obj = Path(path)
166165

166+
# Paths are considered absolute on unix-like systems if they start with a forward slash.
167+
# This is because we want to ensure seamless toggling between the local and remote filesystems.
168+
if path_obj.is_absolute():
169+
raise HumanloopRuntimeError(
170+
f"Absolute paths are not supported: `{path}`. "
171+
f"Paths should be relative to the base directory (`{self.base_dir}`)."
172+
)
173+
167174
# Remove extension, convert to string with forward slashes, and remove leading/trailing slashes
168175
normalized = str(path_obj.with_suffix(""))
169176
# Replace all backslashes and normalize multiple forward slashes
@@ -208,7 +215,7 @@ def _pull_file(self, path: str | None = None, environment: str | None = None) ->
208215
environment=environment,
209216
include_raw_file_content=True,
210217
)
211-
218+
212219
if file.type not in self.SERIALIZABLE_FILE_TYPES:
213220
logger.error(f"Unsupported file type: {file.type}")
214221
return False
@@ -237,7 +244,7 @@ def _pull_directory(
237244
Returns:
238245
Tuple of two lists:
239246
- First list contains paths of successfully synced files
240-
- Second list contains paths of files that failed to sync.
247+
- Second list contains paths of files that failed to sync.
241248
Failures can occur due to missing content in the response or errors during local file writing.
242249
243250
Raises:

0 commit comments

Comments
 (0)