Coverage for haystack/dataclasses/byte_stream.py: 100%
39 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-21 13:53 +0000
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-21 13:53 +0000
1# SPDX-FileCopyrightText: 2022-present deepset GmbH <info@deepset.ai>
2#
3# SPDX-License-Identifier: Apache-2.0
5from dataclasses import dataclass, field
6from pathlib import Path
7from typing import Any
9from haystack.utils.dataclasses import _warn_on_inplace_mutation
10from haystack.utils.misc import _guess_mime_type
13@_warn_on_inplace_mutation
14@dataclass(repr=False)
15class ByteStream:
16 """
17 Base data class representing a binary object in the Haystack API.
19 :param data: The binary data stored in Bytestream.
20 :param meta: Additional metadata to be stored with the ByteStream.
21 :param mime_type: The mime type of the binary data.
22 """
24 data: bytes
25 meta: dict[str, Any] = field(default_factory=dict, hash=False)
26 mime_type: str | None = field(default=None)
28 def to_file(self, destination_path: Path) -> None:
29 """
30 Write the ByteStream to a file. Note: the metadata will be lost.
32 :param destination_path: The path to write the ByteStream to.
33 """
34 with open(destination_path, "wb") as fd:
35 fd.write(self.data)
37 @classmethod
38 def from_file_path(
39 cls,
40 filepath: Path,
41 mime_type: str | None = None,
42 meta: dict[str, Any] | None = None,
43 guess_mime_type: bool = False,
44 ) -> "ByteStream":
45 """
46 Create a ByteStream from the contents read from a file.
48 :param filepath: A valid path to a file.
49 :param mime_type: The mime type of the file.
50 :param meta: Additional metadata to be stored with the ByteStream.
51 :param guess_mime_type: Whether to guess the mime type from the file.
52 """
53 if not mime_type and guess_mime_type:
54 mime_type = _guess_mime_type(filepath)
55 with open(filepath, "rb") as fd:
56 return cls(data=fd.read(), mime_type=mime_type, meta=meta or {})
58 @classmethod
59 def from_string(
60 cls, text: str, encoding: str = "utf-8", mime_type: str | None = None, meta: dict[str, Any] | None = None
61 ) -> "ByteStream":
62 """
63 Create a ByteStream encoding a string.
65 :param text: The string to encode
66 :param encoding: The encoding used to convert the string into bytes
67 :param mime_type: The mime type of the file.
68 :param meta: Additional metadata to be stored with the ByteStream.
69 """
70 return cls(data=text.encode(encoding), mime_type=mime_type, meta=meta or {})
72 def to_string(self, encoding: str = "utf-8") -> str:
73 """
74 Convert the ByteStream to a string, metadata will not be included.
76 :param encoding: The encoding used to convert the bytes to a string. Defaults to "utf-8".
77 :returns: The string representation of the ByteStream.
78 :raises UnicodeDecodeError: If the ByteStream data cannot be decoded with the specified encoding.
79 """
80 return self.data.decode(encoding)
82 def __repr__(self) -> str:
83 """
84 Return a string representation of the ByteStream, truncating the data to 100 bytes.
85 """
86 fields = []
87 truncated_data = self.data[:100] + b"..." if len(self.data) > 100 else self.data
88 fields.append(f"data={truncated_data!r}")
89 fields.append(f"meta={self.meta!r}")
90 fields.append(f"mime_type={self.mime_type!r}")
91 fields_str = ", ".join(fields)
92 return f"{self.__class__.__name__}({fields_str})"
94 def to_dict(self) -> dict[str, Any]:
95 """
96 Convert the ByteStream to a dictionary representation.
98 :returns: A dictionary with keys 'data', 'meta', and 'mime_type'.
99 """
100 # Note: The data is converted to a list of integers for serialization since JSON does not support bytes
101 # directly.
102 return {"data": list(self.data), "meta": self.meta, "mime_type": self.mime_type}
104 def _to_trace_dict(self) -> dict[str, Any]:
105 """
106 Convert the ByteStream to a dictionary representation for tracing.
108 Binary data is replaced with a placeholder string to avoid sending large payloads to the tracing backend.
110 :returns:
111 Serialized version of the object only for tracing purposes.
112 """
113 return {"data": f"Binary data ({len(self.data)} bytes)", "meta": self.meta, "mime_type": self.mime_type}
115 @classmethod
116 def from_dict(cls, data: dict[str, Any]) -> "ByteStream":
117 """
118 Create a ByteStream from a dictionary representation.
120 :param data: A dictionary with keys 'data', 'meta', and 'mime_type'.
122 :returns: A ByteStream instance.
123 """
124 return ByteStream(data=bytes(data["data"]), meta=data.get("meta", {}), mime_type=data.get("mime_type"))