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.
Files changed (137) hide show
  1. ham/__init__.py +10 -0
  2. {hammad_python-0.0.30.dist-info → hammad_python-0.0.31.dist-info}/METADATA +6 -32
  3. hammad_python-0.0.31.dist-info/RECORD +6 -0
  4. hammad/__init__.py +0 -84
  5. hammad/_internal.py +0 -256
  6. hammad/_main.py +0 -226
  7. hammad/cache/__init__.py +0 -40
  8. hammad/cache/base_cache.py +0 -181
  9. hammad/cache/cache.py +0 -169
  10. hammad/cache/decorators.py +0 -261
  11. hammad/cache/file_cache.py +0 -80
  12. hammad/cache/ttl_cache.py +0 -74
  13. hammad/cli/__init__.py +0 -33
  14. hammad/cli/animations.py +0 -573
  15. hammad/cli/plugins.py +0 -867
  16. hammad/cli/styles/__init__.py +0 -55
  17. hammad/cli/styles/settings.py +0 -139
  18. hammad/cli/styles/types.py +0 -358
  19. hammad/cli/styles/utils.py +0 -634
  20. hammad/data/__init__.py +0 -90
  21. hammad/data/collections/__init__.py +0 -49
  22. hammad/data/collections/collection.py +0 -326
  23. hammad/data/collections/indexes/__init__.py +0 -37
  24. hammad/data/collections/indexes/qdrant/__init__.py +0 -1
  25. hammad/data/collections/indexes/qdrant/index.py +0 -723
  26. hammad/data/collections/indexes/qdrant/settings.py +0 -94
  27. hammad/data/collections/indexes/qdrant/utils.py +0 -210
  28. hammad/data/collections/indexes/tantivy/__init__.py +0 -1
  29. hammad/data/collections/indexes/tantivy/index.py +0 -426
  30. hammad/data/collections/indexes/tantivy/settings.py +0 -40
  31. hammad/data/collections/indexes/tantivy/utils.py +0 -176
  32. hammad/data/configurations/__init__.py +0 -35
  33. hammad/data/configurations/configuration.py +0 -564
  34. hammad/data/models/__init__.py +0 -50
  35. hammad/data/models/extensions/__init__.py +0 -4
  36. hammad/data/models/extensions/pydantic/__init__.py +0 -42
  37. hammad/data/models/extensions/pydantic/converters.py +0 -759
  38. hammad/data/models/fields.py +0 -546
  39. hammad/data/models/model.py +0 -1078
  40. hammad/data/models/utils.py +0 -280
  41. hammad/data/sql/__init__.py +0 -24
  42. hammad/data/sql/database.py +0 -576
  43. hammad/data/sql/types.py +0 -127
  44. hammad/data/types/__init__.py +0 -75
  45. hammad/data/types/file.py +0 -431
  46. hammad/data/types/multimodal/__init__.py +0 -36
  47. hammad/data/types/multimodal/audio.py +0 -200
  48. hammad/data/types/multimodal/image.py +0 -182
  49. hammad/data/types/text.py +0 -1308
  50. hammad/formatting/__init__.py +0 -33
  51. hammad/formatting/json/__init__.py +0 -27
  52. hammad/formatting/json/converters.py +0 -158
  53. hammad/formatting/text/__init__.py +0 -63
  54. hammad/formatting/text/converters.py +0 -723
  55. hammad/formatting/text/markdown.py +0 -131
  56. hammad/formatting/yaml/__init__.py +0 -26
  57. hammad/formatting/yaml/converters.py +0 -5
  58. hammad/genai/__init__.py +0 -217
  59. hammad/genai/a2a/__init__.py +0 -32
  60. hammad/genai/a2a/workers.py +0 -552
  61. hammad/genai/agents/__init__.py +0 -59
  62. hammad/genai/agents/agent.py +0 -1973
  63. hammad/genai/agents/run.py +0 -1024
  64. hammad/genai/agents/types/__init__.py +0 -42
  65. hammad/genai/agents/types/agent_context.py +0 -13
  66. hammad/genai/agents/types/agent_event.py +0 -128
  67. hammad/genai/agents/types/agent_hooks.py +0 -220
  68. hammad/genai/agents/types/agent_messages.py +0 -31
  69. hammad/genai/agents/types/agent_response.py +0 -125
  70. hammad/genai/agents/types/agent_stream.py +0 -327
  71. hammad/genai/graphs/__init__.py +0 -125
  72. hammad/genai/graphs/_utils.py +0 -190
  73. hammad/genai/graphs/base.py +0 -1828
  74. hammad/genai/graphs/plugins.py +0 -316
  75. hammad/genai/graphs/types.py +0 -638
  76. hammad/genai/models/__init__.py +0 -1
  77. hammad/genai/models/embeddings/__init__.py +0 -43
  78. hammad/genai/models/embeddings/model.py +0 -226
  79. hammad/genai/models/embeddings/run.py +0 -163
  80. hammad/genai/models/embeddings/types/__init__.py +0 -37
  81. hammad/genai/models/embeddings/types/embedding_model_name.py +0 -75
  82. hammad/genai/models/embeddings/types/embedding_model_response.py +0 -76
  83. hammad/genai/models/embeddings/types/embedding_model_run_params.py +0 -66
  84. hammad/genai/models/embeddings/types/embedding_model_settings.py +0 -47
  85. hammad/genai/models/language/__init__.py +0 -57
  86. hammad/genai/models/language/model.py +0 -1098
  87. hammad/genai/models/language/run.py +0 -878
  88. hammad/genai/models/language/types/__init__.py +0 -40
  89. hammad/genai/models/language/types/language_model_instructor_mode.py +0 -47
  90. hammad/genai/models/language/types/language_model_messages.py +0 -28
  91. hammad/genai/models/language/types/language_model_name.py +0 -239
  92. hammad/genai/models/language/types/language_model_request.py +0 -127
  93. hammad/genai/models/language/types/language_model_response.py +0 -217
  94. hammad/genai/models/language/types/language_model_response_chunk.py +0 -56
  95. hammad/genai/models/language/types/language_model_settings.py +0 -89
  96. hammad/genai/models/language/types/language_model_stream.py +0 -600
  97. hammad/genai/models/language/utils/__init__.py +0 -28
  98. hammad/genai/models/language/utils/requests.py +0 -421
  99. hammad/genai/models/language/utils/structured_outputs.py +0 -135
  100. hammad/genai/models/model_provider.py +0 -4
  101. hammad/genai/models/multimodal.py +0 -47
  102. hammad/genai/models/reranking.py +0 -26
  103. hammad/genai/types/__init__.py +0 -1
  104. hammad/genai/types/base.py +0 -215
  105. hammad/genai/types/history.py +0 -290
  106. hammad/genai/types/tools.py +0 -507
  107. hammad/logging/__init__.py +0 -35
  108. hammad/logging/decorators.py +0 -834
  109. hammad/logging/logger.py +0 -1018
  110. hammad/mcp/__init__.py +0 -53
  111. hammad/mcp/client/__init__.py +0 -35
  112. hammad/mcp/client/client.py +0 -624
  113. hammad/mcp/client/client_service.py +0 -400
  114. hammad/mcp/client/settings.py +0 -178
  115. hammad/mcp/servers/__init__.py +0 -26
  116. hammad/mcp/servers/launcher.py +0 -1161
  117. hammad/runtime/__init__.py +0 -32
  118. hammad/runtime/decorators.py +0 -142
  119. hammad/runtime/run.py +0 -299
  120. hammad/service/__init__.py +0 -49
  121. hammad/service/create.py +0 -527
  122. hammad/service/decorators.py +0 -283
  123. hammad/types.py +0 -288
  124. hammad/typing/__init__.py +0 -435
  125. hammad/web/__init__.py +0 -43
  126. hammad/web/http/__init__.py +0 -1
  127. hammad/web/http/client.py +0 -944
  128. hammad/web/models.py +0 -275
  129. hammad/web/openapi/__init__.py +0 -1
  130. hammad/web/openapi/client.py +0 -740
  131. hammad/web/search/__init__.py +0 -1
  132. hammad/web/search/client.py +0 -1023
  133. hammad/web/utils.py +0 -472
  134. hammad_python-0.0.30.dist-info/RECORD +0 -135
  135. {hammad → ham}/py.typed +0 -0
  136. {hammad_python-0.0.30.dist-info → hammad_python-0.0.31.dist-info}/WHEEL +0 -0
  137. {hammad_python-0.0.30.dist-info → hammad_python-0.0.31.dist-info}/licenses/LICENSE +0 -0
@@ -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__)