hammad-python 0.0.30__py3-none-any.whl → 0.0.31__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ham/__init__.py +10 -0
- {hammad_python-0.0.30.dist-info → hammad_python-0.0.31.dist-info}/METADATA +6 -32
- hammad_python-0.0.31.dist-info/RECORD +6 -0
- hammad/__init__.py +0 -84
- hammad/_internal.py +0 -256
- hammad/_main.py +0 -226
- hammad/cache/__init__.py +0 -40
- hammad/cache/base_cache.py +0 -181
- hammad/cache/cache.py +0 -169
- hammad/cache/decorators.py +0 -261
- hammad/cache/file_cache.py +0 -80
- hammad/cache/ttl_cache.py +0 -74
- hammad/cli/__init__.py +0 -33
- hammad/cli/animations.py +0 -573
- hammad/cli/plugins.py +0 -867
- hammad/cli/styles/__init__.py +0 -55
- hammad/cli/styles/settings.py +0 -139
- hammad/cli/styles/types.py +0 -358
- hammad/cli/styles/utils.py +0 -634
- hammad/data/__init__.py +0 -90
- hammad/data/collections/__init__.py +0 -49
- hammad/data/collections/collection.py +0 -326
- hammad/data/collections/indexes/__init__.py +0 -37
- hammad/data/collections/indexes/qdrant/__init__.py +0 -1
- hammad/data/collections/indexes/qdrant/index.py +0 -723
- hammad/data/collections/indexes/qdrant/settings.py +0 -94
- hammad/data/collections/indexes/qdrant/utils.py +0 -210
- hammad/data/collections/indexes/tantivy/__init__.py +0 -1
- hammad/data/collections/indexes/tantivy/index.py +0 -426
- hammad/data/collections/indexes/tantivy/settings.py +0 -40
- hammad/data/collections/indexes/tantivy/utils.py +0 -176
- hammad/data/configurations/__init__.py +0 -35
- hammad/data/configurations/configuration.py +0 -564
- hammad/data/models/__init__.py +0 -50
- hammad/data/models/extensions/__init__.py +0 -4
- hammad/data/models/extensions/pydantic/__init__.py +0 -42
- hammad/data/models/extensions/pydantic/converters.py +0 -759
- hammad/data/models/fields.py +0 -546
- hammad/data/models/model.py +0 -1078
- hammad/data/models/utils.py +0 -280
- hammad/data/sql/__init__.py +0 -24
- hammad/data/sql/database.py +0 -576
- hammad/data/sql/types.py +0 -127
- hammad/data/types/__init__.py +0 -75
- hammad/data/types/file.py +0 -431
- hammad/data/types/multimodal/__init__.py +0 -36
- hammad/data/types/multimodal/audio.py +0 -200
- hammad/data/types/multimodal/image.py +0 -182
- hammad/data/types/text.py +0 -1308
- hammad/formatting/__init__.py +0 -33
- hammad/formatting/json/__init__.py +0 -27
- hammad/formatting/json/converters.py +0 -158
- hammad/formatting/text/__init__.py +0 -63
- hammad/formatting/text/converters.py +0 -723
- hammad/formatting/text/markdown.py +0 -131
- hammad/formatting/yaml/__init__.py +0 -26
- hammad/formatting/yaml/converters.py +0 -5
- hammad/genai/__init__.py +0 -217
- hammad/genai/a2a/__init__.py +0 -32
- hammad/genai/a2a/workers.py +0 -552
- hammad/genai/agents/__init__.py +0 -59
- hammad/genai/agents/agent.py +0 -1973
- hammad/genai/agents/run.py +0 -1024
- hammad/genai/agents/types/__init__.py +0 -42
- hammad/genai/agents/types/agent_context.py +0 -13
- hammad/genai/agents/types/agent_event.py +0 -128
- hammad/genai/agents/types/agent_hooks.py +0 -220
- hammad/genai/agents/types/agent_messages.py +0 -31
- hammad/genai/agents/types/agent_response.py +0 -125
- hammad/genai/agents/types/agent_stream.py +0 -327
- hammad/genai/graphs/__init__.py +0 -125
- hammad/genai/graphs/_utils.py +0 -190
- hammad/genai/graphs/base.py +0 -1828
- hammad/genai/graphs/plugins.py +0 -316
- hammad/genai/graphs/types.py +0 -638
- hammad/genai/models/__init__.py +0 -1
- hammad/genai/models/embeddings/__init__.py +0 -43
- hammad/genai/models/embeddings/model.py +0 -226
- hammad/genai/models/embeddings/run.py +0 -163
- hammad/genai/models/embeddings/types/__init__.py +0 -37
- hammad/genai/models/embeddings/types/embedding_model_name.py +0 -75
- hammad/genai/models/embeddings/types/embedding_model_response.py +0 -76
- hammad/genai/models/embeddings/types/embedding_model_run_params.py +0 -66
- hammad/genai/models/embeddings/types/embedding_model_settings.py +0 -47
- hammad/genai/models/language/__init__.py +0 -57
- hammad/genai/models/language/model.py +0 -1098
- hammad/genai/models/language/run.py +0 -878
- hammad/genai/models/language/types/__init__.py +0 -40
- hammad/genai/models/language/types/language_model_instructor_mode.py +0 -47
- hammad/genai/models/language/types/language_model_messages.py +0 -28
- hammad/genai/models/language/types/language_model_name.py +0 -239
- hammad/genai/models/language/types/language_model_request.py +0 -127
- hammad/genai/models/language/types/language_model_response.py +0 -217
- hammad/genai/models/language/types/language_model_response_chunk.py +0 -56
- hammad/genai/models/language/types/language_model_settings.py +0 -89
- hammad/genai/models/language/types/language_model_stream.py +0 -600
- hammad/genai/models/language/utils/__init__.py +0 -28
- hammad/genai/models/language/utils/requests.py +0 -421
- hammad/genai/models/language/utils/structured_outputs.py +0 -135
- hammad/genai/models/model_provider.py +0 -4
- hammad/genai/models/multimodal.py +0 -47
- hammad/genai/models/reranking.py +0 -26
- hammad/genai/types/__init__.py +0 -1
- hammad/genai/types/base.py +0 -215
- hammad/genai/types/history.py +0 -290
- hammad/genai/types/tools.py +0 -507
- hammad/logging/__init__.py +0 -35
- hammad/logging/decorators.py +0 -834
- hammad/logging/logger.py +0 -1018
- hammad/mcp/__init__.py +0 -53
- hammad/mcp/client/__init__.py +0 -35
- hammad/mcp/client/client.py +0 -624
- hammad/mcp/client/client_service.py +0 -400
- hammad/mcp/client/settings.py +0 -178
- hammad/mcp/servers/__init__.py +0 -26
- hammad/mcp/servers/launcher.py +0 -1161
- hammad/runtime/__init__.py +0 -32
- hammad/runtime/decorators.py +0 -142
- hammad/runtime/run.py +0 -299
- hammad/service/__init__.py +0 -49
- hammad/service/create.py +0 -527
- hammad/service/decorators.py +0 -283
- hammad/types.py +0 -288
- hammad/typing/__init__.py +0 -435
- hammad/web/__init__.py +0 -43
- hammad/web/http/__init__.py +0 -1
- hammad/web/http/client.py +0 -944
- hammad/web/models.py +0 -275
- hammad/web/openapi/__init__.py +0 -1
- hammad/web/openapi/client.py +0 -740
- hammad/web/search/__init__.py +0 -1
- hammad/web/search/client.py +0 -1023
- hammad/web/utils.py +0 -472
- hammad_python-0.0.30.dist-info/RECORD +0 -135
- {hammad → ham}/py.typed +0 -0
- {hammad_python-0.0.30.dist-info → hammad_python-0.0.31.dist-info}/WHEEL +0 -0
- {hammad_python-0.0.30.dist-info → hammad_python-0.0.31.dist-info}/licenses/LICENSE +0 -0
hammad/data/types/__init__.py
DELETED
@@ -1,75 +0,0 @@
|
|
1
|
-
"""hammad.data.types
|
2
|
-
|
3
|
-
Contains functional alias, or model-like objects that are meant to be used
|
4
|
-
by users as bases as well as for type hints. These objects define simple
|
5
|
-
interfaces for various types of common objects."""
|
6
|
-
|
7
|
-
from typing import TYPE_CHECKING
|
8
|
-
from ..._internal import create_getattr_importer
|
9
|
-
|
10
|
-
|
11
|
-
if TYPE_CHECKING:
|
12
|
-
from .text import (
|
13
|
-
BaseText,
|
14
|
-
Text,
|
15
|
-
SimpleText,
|
16
|
-
CodeSection,
|
17
|
-
SchemaSection,
|
18
|
-
OutputText,
|
19
|
-
convert_to_simple_text,
|
20
|
-
convert_to_output_text,
|
21
|
-
convert_to_output_instructions,
|
22
|
-
convert_to_code_section,
|
23
|
-
convert_to_schema_section,
|
24
|
-
convert_to_base_text,
|
25
|
-
)
|
26
|
-
from .file import (
|
27
|
-
File,
|
28
|
-
read_file_from_bytes,
|
29
|
-
read_file_from_path,
|
30
|
-
read_file_from_url,
|
31
|
-
)
|
32
|
-
from .multimodal import (
|
33
|
-
Audio,
|
34
|
-
Image,
|
35
|
-
read_audio_from_path,
|
36
|
-
read_audio_from_url,
|
37
|
-
read_image_from_path,
|
38
|
-
read_image_from_url,
|
39
|
-
)
|
40
|
-
|
41
|
-
|
42
|
-
__all__ = (
|
43
|
-
# hammad.data.types.text
|
44
|
-
"BaseText",
|
45
|
-
"Text",
|
46
|
-
"SimpleText",
|
47
|
-
"CodeSection",
|
48
|
-
"SchemaSection",
|
49
|
-
"OutputText",
|
50
|
-
"convert_to_simple_text",
|
51
|
-
"convert_to_output_text",
|
52
|
-
"convert_to_output_instructions",
|
53
|
-
"convert_to_code_section",
|
54
|
-
"convert_to_schema_section",
|
55
|
-
"convert_to_base_text",
|
56
|
-
# hammad.data.types.file
|
57
|
-
"File",
|
58
|
-
"read_file_from_bytes",
|
59
|
-
"read_file_from_path",
|
60
|
-
"read_file_from_url",
|
61
|
-
# hammad.data.types.multimodal
|
62
|
-
"Audio",
|
63
|
-
"Image",
|
64
|
-
"read_audio_from_path",
|
65
|
-
"read_audio_from_url",
|
66
|
-
"read_image_from_path",
|
67
|
-
"read_image_from_url",
|
68
|
-
)
|
69
|
-
|
70
|
-
|
71
|
-
__getattr__ = create_getattr_importer(__all__)
|
72
|
-
|
73
|
-
|
74
|
-
def __dir__() -> list[str]:
|
75
|
-
return list(__all__)
|
hammad/data/types/file.py
DELETED
@@ -1,431 +0,0 @@
|
|
1
|
-
"""hammad.data.types.file"""
|
2
|
-
|
3
|
-
from pathlib import Path
|
4
|
-
import httpx
|
5
|
-
from typing import Any, Self
|
6
|
-
import mimetypes
|
7
|
-
from urllib.parse import urlparse
|
8
|
-
|
9
|
-
from ..models.model import Model
|
10
|
-
from ..models.fields import field
|
11
|
-
|
12
|
-
__all__ = (
|
13
|
-
"File",
|
14
|
-
"FileSource",
|
15
|
-
"read_file_from_path",
|
16
|
-
"read_file_from_url",
|
17
|
-
"read_file_from_bytes",
|
18
|
-
)
|
19
|
-
|
20
|
-
|
21
|
-
_FILE_SIGNATURES = {
|
22
|
-
b"\x89PNG": "image/png",
|
23
|
-
b"\xff\xd8\xff": "image/jpeg",
|
24
|
-
b"GIF87a": "image/gif",
|
25
|
-
b"GIF89a": "image/gif",
|
26
|
-
b"%PDF": "application/pdf",
|
27
|
-
b"PK": "application/zip",
|
28
|
-
}
|
29
|
-
|
30
|
-
|
31
|
-
_mime_cache: dict[str, str] = {}
|
32
|
-
"""Cache for MIME types."""
|
33
|
-
|
34
|
-
|
35
|
-
class FileSource(Model, kw_only=True, dict=True, frozen=True):
|
36
|
-
"""Represents the source of a `File` object."""
|
37
|
-
|
38
|
-
is_file: bool = field(default=False)
|
39
|
-
"""Whether this data represents a file."""
|
40
|
-
is_dir: bool = field(default=False)
|
41
|
-
"""Whether this data represents a directory."""
|
42
|
-
is_url: bool = field(default=False)
|
43
|
-
"""Whether this data originates from a URL."""
|
44
|
-
path: Path | None = field(default=None)
|
45
|
-
"""The file path if this is file-based data."""
|
46
|
-
url: str | None = field(default=None)
|
47
|
-
"""The URL if this is URL-based data."""
|
48
|
-
size: int | None = field(default=None)
|
49
|
-
"""Size in bytes if available."""
|
50
|
-
encoding: str | None = field(default=None)
|
51
|
-
"""Text encoding if applicable."""
|
52
|
-
|
53
|
-
|
54
|
-
class File(Model, kw_only=True, dict=True):
|
55
|
-
"""Base object for all file-like structure types within
|
56
|
-
the `hammad` ecosystem."""
|
57
|
-
|
58
|
-
data: Any | None = field(default=None)
|
59
|
-
"""The actual data content (bytes, string, path object, etc.)"""
|
60
|
-
type: str | None = field(default=None)
|
61
|
-
"""The MIME type or identifier for the data."""
|
62
|
-
|
63
|
-
source: FileSource = field(default_factory=FileSource)
|
64
|
-
"""The source of the data. Contains metadata as well."""
|
65
|
-
|
66
|
-
# Private cached attributes
|
67
|
-
_name: str | None = field(default=None)
|
68
|
-
_extension: str | None = field(default=None)
|
69
|
-
_repr: str | None = field(default=None)
|
70
|
-
|
71
|
-
@property
|
72
|
-
def name(self) -> str | None:
|
73
|
-
"""Returns the name of this data object."""
|
74
|
-
if self._name is not None:
|
75
|
-
return self._name
|
76
|
-
|
77
|
-
if self.source.path:
|
78
|
-
self._name = self.source.path.name
|
79
|
-
elif self.source.url:
|
80
|
-
parsed = urlparse(self.source.url)
|
81
|
-
self._name = parsed.path.split("/")[-1] or parsed.netloc
|
82
|
-
else:
|
83
|
-
self._name = "" # Cache empty result
|
84
|
-
|
85
|
-
return self._name if self._name else None
|
86
|
-
|
87
|
-
@property
|
88
|
-
def extension(self) -> str | None:
|
89
|
-
"""Returns the extension of this data object."""
|
90
|
-
if self._extension is not None:
|
91
|
-
return self._extension
|
92
|
-
|
93
|
-
if self.source.path:
|
94
|
-
self._extension = self.source.path.suffix
|
95
|
-
elif name := self.name:
|
96
|
-
if "." in name:
|
97
|
-
self._extension = f".{name.rsplit('.', 1)[-1]}"
|
98
|
-
else:
|
99
|
-
self._extension = "" # Cache empty result
|
100
|
-
else:
|
101
|
-
self._extension = "" # Cache empty result
|
102
|
-
|
103
|
-
return self._extension if self._extension else None
|
104
|
-
|
105
|
-
@property
|
106
|
-
def exists(self) -> bool:
|
107
|
-
"""Returns whether this data object exists."""
|
108
|
-
if self.data is not None:
|
109
|
-
return True
|
110
|
-
if self.source.path and (self.source.is_file or self.source.is_dir):
|
111
|
-
return self.source.path.exists()
|
112
|
-
return False
|
113
|
-
|
114
|
-
def read(self) -> bytes | str:
|
115
|
-
"""Reads the data content.
|
116
|
-
|
117
|
-
Returns:
|
118
|
-
The data content as bytes or string depending on the source.
|
119
|
-
|
120
|
-
Raises:
|
121
|
-
ValueError: If the data cannot be read.
|
122
|
-
"""
|
123
|
-
if self.data is not None:
|
124
|
-
return self.data
|
125
|
-
|
126
|
-
if self.source.path and self.source.is_file and self.source.path.exists():
|
127
|
-
if self.source.encoding:
|
128
|
-
return self.source.path.read_text(encoding=self.source.encoding)
|
129
|
-
return self.source.path.read_bytes()
|
130
|
-
|
131
|
-
raise ValueError(f"Cannot read data from {self.name or 'unknown source'}")
|
132
|
-
|
133
|
-
def to_file(self, path: str | Path, *, overwrite: bool = False) -> Path:
|
134
|
-
"""Save the data to a file.
|
135
|
-
|
136
|
-
Args:
|
137
|
-
path: The path to save to.
|
138
|
-
overwrite: If True, overwrite existing files.
|
139
|
-
|
140
|
-
Returns:
|
141
|
-
The path where the file was saved.
|
142
|
-
|
143
|
-
Raises:
|
144
|
-
FileExistsError: If file exists and overwrite is False.
|
145
|
-
ValueError: If data cannot be saved.
|
146
|
-
"""
|
147
|
-
save_path = Path(path)
|
148
|
-
|
149
|
-
if save_path.exists() and not overwrite:
|
150
|
-
raise FileExistsError(f"File already exists: {save_path}")
|
151
|
-
|
152
|
-
# Ensure parent directory exists
|
153
|
-
save_path.parent.mkdir(parents=True, exist_ok=True)
|
154
|
-
|
155
|
-
data = self.read()
|
156
|
-
if isinstance(data, str):
|
157
|
-
save_path.write_text(data, encoding=self.source.encoding or "utf-8")
|
158
|
-
else:
|
159
|
-
save_path.write_bytes(data)
|
160
|
-
|
161
|
-
return save_path
|
162
|
-
|
163
|
-
def __repr__(self) -> str:
|
164
|
-
"""Returns a string representation of the data object."""
|
165
|
-
if self._repr is not None:
|
166
|
-
return self._repr
|
167
|
-
|
168
|
-
parts = []
|
169
|
-
|
170
|
-
if self.source.path:
|
171
|
-
parts.append(f"path={self.source.path!r}")
|
172
|
-
elif self.source.url:
|
173
|
-
parts.append(f"url={self.source.url!r}")
|
174
|
-
elif self.data is not None:
|
175
|
-
parts.append(f"data={self.data!r}")
|
176
|
-
|
177
|
-
if self.source.is_file:
|
178
|
-
parts.append("is_file=True")
|
179
|
-
elif self.source.is_dir:
|
180
|
-
parts.append("is_dir=True")
|
181
|
-
elif self.source.is_url:
|
182
|
-
parts.append("is_url=True")
|
183
|
-
|
184
|
-
if (size := self.source.size) is not None:
|
185
|
-
if size < 1024:
|
186
|
-
size_str = f"{size}B"
|
187
|
-
elif size < 1048576: # 1024 * 1024
|
188
|
-
size_str = f"{size / 1024:.1f}KB"
|
189
|
-
elif size < 1073741824: # 1024 * 1024 * 1024
|
190
|
-
size_str = f"{size / 1048576:.1f}MB"
|
191
|
-
else:
|
192
|
-
size_str = f"{size / 1073741824:.1f}GB"
|
193
|
-
parts.append(f"size={size_str}")
|
194
|
-
|
195
|
-
if self.source.encoding:
|
196
|
-
parts.append(f"encoding={self.source.encoding!r}")
|
197
|
-
|
198
|
-
self._repr = f"<{', '.join(parts)}>"
|
199
|
-
return self._repr
|
200
|
-
|
201
|
-
def __eq__(self, other: Any) -> bool:
|
202
|
-
"""Returns whether this data object is equal to another."""
|
203
|
-
return isinstance(other, File) and self.data == other.data
|
204
|
-
|
205
|
-
@classmethod
|
206
|
-
def from_path(
|
207
|
-
cls,
|
208
|
-
path: str | Path,
|
209
|
-
*,
|
210
|
-
encoding: str | None = None,
|
211
|
-
lazy: bool = True,
|
212
|
-
) -> Self:
|
213
|
-
"""Creates a data object from a filepath and
|
214
|
-
assigns the appropriate type and flags.
|
215
|
-
|
216
|
-
Args:
|
217
|
-
path: The file or directory path.
|
218
|
-
encoding: Text encoding for reading text files.
|
219
|
-
lazy: If True, defer loading content until needed.
|
220
|
-
|
221
|
-
Returns:
|
222
|
-
A new Data instance representing the file or directory.
|
223
|
-
"""
|
224
|
-
path = Path(path)
|
225
|
-
|
226
|
-
# Use cached stat call
|
227
|
-
try:
|
228
|
-
stat = path.stat()
|
229
|
-
is_file = stat.st_mode & 0o170000 == 0o100000 # S_IFREG
|
230
|
-
is_dir = stat.st_mode & 0o170000 == 0o040000 # S_IFDIR
|
231
|
-
size = stat.st_size if is_file else None
|
232
|
-
except OSError:
|
233
|
-
is_file = is_dir = False
|
234
|
-
size = None
|
235
|
-
|
236
|
-
# Get MIME type for files using cache
|
237
|
-
mime_type = None
|
238
|
-
if is_file:
|
239
|
-
path_str = str(path)
|
240
|
-
if path_str in _mime_cache:
|
241
|
-
mime_type = _mime_cache[path_str]
|
242
|
-
else:
|
243
|
-
mime_type, _ = mimetypes.guess_type(path_str)
|
244
|
-
_mime_cache[path_str] = mime_type
|
245
|
-
|
246
|
-
# Load data if not lazy and it's a file
|
247
|
-
data = None
|
248
|
-
if not lazy and is_file and size is not None:
|
249
|
-
if encoding or (mime_type and mime_type.startswith("text/")):
|
250
|
-
data = path.read_text(encoding=encoding or "utf-8")
|
251
|
-
else:
|
252
|
-
data = path.read_bytes()
|
253
|
-
|
254
|
-
return cls(
|
255
|
-
data=data,
|
256
|
-
type=mime_type,
|
257
|
-
source=FileSource(
|
258
|
-
is_file=is_file,
|
259
|
-
is_dir=is_dir,
|
260
|
-
is_url=False,
|
261
|
-
path=path,
|
262
|
-
size=size,
|
263
|
-
encoding=encoding,
|
264
|
-
),
|
265
|
-
)
|
266
|
-
|
267
|
-
@classmethod
|
268
|
-
def from_url(
|
269
|
-
cls,
|
270
|
-
url: str,
|
271
|
-
*,
|
272
|
-
type: str | None = None,
|
273
|
-
lazy: bool = True,
|
274
|
-
) -> Self:
|
275
|
-
"""Creates a data object from either a downloadable
|
276
|
-
URL (treated as a file), or a web page itself treated as a
|
277
|
-
document.
|
278
|
-
|
279
|
-
Args:
|
280
|
-
url: The URL to create data from.
|
281
|
-
type: Optional MIME type override.
|
282
|
-
lazy: If True, defer loading content until needed.
|
283
|
-
|
284
|
-
Returns:
|
285
|
-
A new Data instance representing the URL.
|
286
|
-
"""
|
287
|
-
data = None
|
288
|
-
size = None
|
289
|
-
encoding = None
|
290
|
-
|
291
|
-
# Load data if not lazy
|
292
|
-
if not lazy:
|
293
|
-
try:
|
294
|
-
with httpx.Client() as client:
|
295
|
-
response = client.get(url)
|
296
|
-
response.raise_for_status()
|
297
|
-
|
298
|
-
data = response.content
|
299
|
-
size = len(data)
|
300
|
-
|
301
|
-
# Get content type from response headers if not provided
|
302
|
-
if not type:
|
303
|
-
content_type = response.headers.get("content-type", "")
|
304
|
-
type = content_type.split(";")[0] if content_type else None
|
305
|
-
|
306
|
-
# Get encoding from response if it's text content
|
307
|
-
if response.headers.get("content-type", "").startswith("text/"):
|
308
|
-
encoding = response.encoding
|
309
|
-
data = response.text
|
310
|
-
|
311
|
-
except Exception:
|
312
|
-
# If download fails, still create the object but without data
|
313
|
-
pass
|
314
|
-
|
315
|
-
return cls(
|
316
|
-
data=data,
|
317
|
-
type=type,
|
318
|
-
source=FileSource(
|
319
|
-
is_url=True,
|
320
|
-
is_file=False,
|
321
|
-
is_dir=False,
|
322
|
-
url=url,
|
323
|
-
size=size,
|
324
|
-
encoding=encoding,
|
325
|
-
),
|
326
|
-
)
|
327
|
-
|
328
|
-
@classmethod
|
329
|
-
def from_bytes(
|
330
|
-
cls,
|
331
|
-
data: bytes,
|
332
|
-
*,
|
333
|
-
type: str | None = None,
|
334
|
-
name: str | None = None,
|
335
|
-
) -> Self:
|
336
|
-
"""Creates a data object from a bytes object.
|
337
|
-
|
338
|
-
Args:
|
339
|
-
data: The bytes data.
|
340
|
-
type: Optional MIME type.
|
341
|
-
name: Optional name for the data.
|
342
|
-
|
343
|
-
Returns:
|
344
|
-
A new Data instance containing the bytes data.
|
345
|
-
"""
|
346
|
-
# Try to detect type from content if not provided
|
347
|
-
if not type and data:
|
348
|
-
# Check against pre-compiled signatures
|
349
|
-
for sig, mime in _FILE_SIGNATURES.items():
|
350
|
-
if data.startswith(sig):
|
351
|
-
type = mime
|
352
|
-
break
|
353
|
-
|
354
|
-
return cls(
|
355
|
-
data=data,
|
356
|
-
type=type,
|
357
|
-
source=FileSource(
|
358
|
-
is_file=True,
|
359
|
-
is_dir=False,
|
360
|
-
is_url=False,
|
361
|
-
size=len(data),
|
362
|
-
path=Path(name) if name else None,
|
363
|
-
),
|
364
|
-
)
|
365
|
-
|
366
|
-
|
367
|
-
def read_file_from_path(
|
368
|
-
path: str | Path,
|
369
|
-
*,
|
370
|
-
encoding: str | None = None,
|
371
|
-
) -> File:
|
372
|
-
"""Read a file from a filesystem path.
|
373
|
-
|
374
|
-
Args:
|
375
|
-
path: The path to the file to read.
|
376
|
-
encoding: Optional text encoding to use when reading the file.
|
377
|
-
If not provided, will attempt to detect automatically.
|
378
|
-
|
379
|
-
Returns:
|
380
|
-
A File instance containing the file data.
|
381
|
-
|
382
|
-
Raises:
|
383
|
-
FileNotFoundError: If the file does not exist.
|
384
|
-
PermissionError: If the file cannot be read due to permissions.
|
385
|
-
IsADirectoryError: If the path points to a directory.
|
386
|
-
"""
|
387
|
-
return File.from_path(path, encoding=encoding)
|
388
|
-
|
389
|
-
|
390
|
-
def read_file_from_url(
|
391
|
-
url: str,
|
392
|
-
*,
|
393
|
-
encoding: str | None = None,
|
394
|
-
timeout: float = 30.0,
|
395
|
-
) -> File:
|
396
|
-
"""Read a file from a URL.
|
397
|
-
|
398
|
-
Args:
|
399
|
-
url: The URL to fetch the file from.
|
400
|
-
encoding: Optional text encoding to use when reading the response.
|
401
|
-
If not provided, will attempt to detect automatically.
|
402
|
-
timeout: Request timeout in seconds. Defaults to 30.0.
|
403
|
-
|
404
|
-
Returns:
|
405
|
-
A File instance containing the downloaded data.
|
406
|
-
|
407
|
-
Raises:
|
408
|
-
httpx.RequestError: If the request fails.
|
409
|
-
httpx.HTTPStatusError: If the response has an error status code.
|
410
|
-
"""
|
411
|
-
return File.from_url(url, encoding=encoding, timeout=timeout)
|
412
|
-
|
413
|
-
|
414
|
-
def read_file_from_bytes(
|
415
|
-
data: bytes,
|
416
|
-
*,
|
417
|
-
type: str | None = None,
|
418
|
-
name: str | None = None,
|
419
|
-
) -> File:
|
420
|
-
"""Create a file from raw bytes data.
|
421
|
-
|
422
|
-
Args:
|
423
|
-
data: The bytes data to create the file from.
|
424
|
-
type: Optional MIME type of the data. If not provided,
|
425
|
-
will attempt to detect from content signatures.
|
426
|
-
name: Optional name for the file data.
|
427
|
-
|
428
|
-
Returns:
|
429
|
-
A File instance containing the bytes data.
|
430
|
-
"""
|
431
|
-
return File.from_bytes(data, type=type, name=name)
|
@@ -1,36 +0,0 @@
|
|
1
|
-
"""hammad.types.multimodal
|
2
|
-
|
3
|
-
Contains types and model like objects for working with various
|
4
|
-
types of multimodal data."""
|
5
|
-
|
6
|
-
from typing import TYPE_CHECKING
|
7
|
-
from ...._internal import create_getattr_importer
|
8
|
-
|
9
|
-
if TYPE_CHECKING:
|
10
|
-
from .image import (
|
11
|
-
Image,
|
12
|
-
read_image_from_path,
|
13
|
-
read_image_from_url,
|
14
|
-
)
|
15
|
-
from .audio import (
|
16
|
-
Audio,
|
17
|
-
read_audio_from_path,
|
18
|
-
read_audio_from_url,
|
19
|
-
)
|
20
|
-
|
21
|
-
|
22
|
-
__all__ = (
|
23
|
-
"Image",
|
24
|
-
"Audio",
|
25
|
-
"read_audio_from_path",
|
26
|
-
"read_audio_from_url",
|
27
|
-
"read_image_from_path",
|
28
|
-
"read_image_from_url",
|
29
|
-
)
|
30
|
-
|
31
|
-
|
32
|
-
__getattr__ = create_getattr_importer(__all__)
|
33
|
-
|
34
|
-
|
35
|
-
def __dir__() -> list[str]:
|
36
|
-
return list(__all__)
|