change bucketname

This commit is contained in:
mubashir1osmani 2026-06-08 15:59:18 -07:00
parent 794ace360b
commit 8a44f64b47
No known key found for this signature in database
GPG key ID: AB055FF67D0B4D9A
5 changed files with 53 additions and 21 deletions

View file

@ -14,7 +14,7 @@ _OPTIONAL_KWARGS_KEYS = frozenset(
"azure_password",
"azure_scope",
"timeout",
"bucket_name",
"gcs_bucket_name",
"vertex_credentials",
"vertex_project",
"vertex_location",

View file

@ -785,10 +785,10 @@ def extract_file_metadata(file_data: FileTypes) -> Tuple[Optional[str], Optional
if filename is None:
if isinstance(file_content, PathLike):
filename = Path(file_content).name
elif isinstance(file_content, io.IOBase) and isinstance(
getattr(file_content, "name", None), str
):
filename = Path(file_content.name).name
elif isinstance(file_content, io.IOBase):
name_attr = getattr(file_content, "name", None)
if isinstance(name_attr, str):
filename = Path(name_attr).name
if not content_type:
guessed = mimetypes.guess_type(filename)[0] if filename else None

View file

@ -231,13 +231,23 @@ def _iter_openai_jsonl_lines(openai_file_content: FileTypes) -> Iterator[str]:
return
if hasattr(content, "read"):
# Rewind seekable handles (BytesIO, temp files) so the body can be
# replayed on a retry; a non-seekable stream cannot be re-read.
if hasattr(content, "seek"):
try:
content.seek(0)
except (OSError, ValueError):
pass
# The handle is read twice per upload (first-row probe for the GCS
# object name, then the body stream), so it must rewind to 0. A
# non-seekable handle would silently resume mid-stream and drop the
# already-consumed first row, so reject it loudly instead.
seek = getattr(content, "seek", None)
if seek is None:
raise ValueError(
"Batch upload file handle must be seekable; got a non-seekable "
"stream. Pass bytes, a path, or a seekable handle."
)
try:
seek(0)
except (OSError, ValueError) as e:
raise ValueError(
"Batch upload file handle must be seekable so it can be re-read "
"for the GCS object name and the upload body."
) from e
for raw in content:
line = raw.decode("utf-8") if isinstance(raw, bytes) else raw
line = line.strip()
@ -396,7 +406,7 @@ class VertexAIFilesConfig(VertexBase, BaseFilesConfig):
)
def _get_configured_bucket_name(self, litellm_params: Dict) -> str:
bucket_name = litellm_params.get("bucket_name") or os.getenv("GCS_BUCKET_NAME")
bucket_name = litellm_params.get("gcs_bucket_name") or os.getenv("GCS_BUCKET_NAME")
if not bucket_name:
raise ValueError("GCS bucket_name is required")
return bucket_name

View file

@ -174,7 +174,7 @@ class CredentialLiteLLMParams(BaseModel):
region_name: Optional[str] = None
## OBJECT STORAGE (files / batches) ##
bucket_name: Optional[str] = None
gcs_bucket_name: Optional[str] = None
## AWS BEDROCK / SAGEMAKER ##
aws_access_key_id: Optional[str] = None

View file

@ -152,7 +152,7 @@ class TestFileLikeInputNotPartiallyConsumed:
api_key=None,
model="",
optional_params={},
litellm_params={"bucket_name": "test-bucket"},
litellm_params={"gcs_bucket_name": "test-bucket"},
data=create_file_data,
)
out = cfg.transform_create_file_request(
@ -206,6 +206,29 @@ class TestStreamingLineIterator:
with pytest.raises(ValueError, match="Unsupported file content type"):
list(_iter_openai_jsonl_lines(12345)) # type: ignore[arg-type]
def test_non_seekable_handle_raises_instead_of_dropping_first_row(self):
# The handle is read twice (object-name probe, then body). A non-seekable
# handle can't rewind, so it must fail loudly rather than silently resume
# mid-stream and omit the opening batch request.
class _NonSeekable:
def __init__(self, raw: bytes):
self._buf = io.BytesIO(raw)
def read(self, *args):
return self._buf.read(*args)
def __iter__(self):
return iter(self._buf)
def seek(self, *args):
raise io.UnsupportedOperation("not seekable")
handle = _NonSeekable(
b'{"custom_id": "request-0"}\n{"custom_id": "request-1"}\n'
)
with pytest.raises(ValueError, match="seekable"):
list(_iter_openai_jsonl_lines(handle))
def test_is_lazy_does_not_parse_past_first_entry(self):
# Second row is invalid JSON; pulling only the first entry must not raise.
content = b'{"custom_id": "first"}\nnot-json-at-all\n'
@ -337,7 +360,7 @@ class TestPathSourcedStreaming:
api_key=None,
model="",
optional_params={},
litellm_params={"bucket_name": "test-bucket"},
litellm_params={"gcs_bucket_name": "test-bucket"},
data=data,
)
assert "uploadType=resumable" in url
@ -364,7 +387,7 @@ class TestPathSourcedStreaming:
api_key=None,
model="",
optional_params={},
litellm_params={"bucket_name": "test-bucket"},
litellm_params={"gcs_bucket_name": "test-bucket"},
data=data,
)
out = cfg.transform_create_file_request(
@ -476,7 +499,7 @@ class TestResumableUploadUrl:
api_key=None,
model="",
optional_params={},
litellm_params={"bucket_name": "test-bucket"},
litellm_params={"gcs_bucket_name": "test-bucket"},
data=request,
)
assert "uploadType=resumable" in url
@ -493,7 +516,7 @@ class TestResumableUploadUrl:
api_key=None,
model="",
optional_params={},
litellm_params={"bucket_name": "test-bucket"},
litellm_params={"gcs_bucket_name": "test-bucket"},
data=request,
)
assert "uploadType=media" in url
@ -581,7 +604,7 @@ class TestResumableUploadProtocol:
api_key=None,
model="",
optional_params={},
litellm_params={"bucket_name": "test-bucket"},
litellm_params={"gcs_bucket_name": "test-bucket"},
data=request,
)
transformed = cfg.transform_create_file_request(
@ -642,7 +665,6 @@ class TestResumableUploadProtocol:
async def test_exact_multiple_finalizes_with_empty_chunk(self):
# Build a body that is an exact multiple of the chunk size so the stream
# ends on a chunk boundary; the upload must still finalize (bytes */TOTAL).
cfg = VertexAIFilesConfig()
chunk_size = 256
stream = _FixedBytesStream(b"a" * (chunk_size * 3))
config = {"body_stream": stream, "chunk_size": chunk_size}