hammad-python 0.0.13__py3-none-any.whl → 0.0.15__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 (87) hide show
  1. hammad_python-0.0.15.dist-info/METADATA +184 -0
  2. hammad_python-0.0.15.dist-info/RECORD +4 -0
  3. hammad/__init__.py +0 -180
  4. hammad/_core/__init__.py +0 -1
  5. hammad/_core/_utils/__init__.py +0 -4
  6. hammad/_core/_utils/_import_utils.py +0 -182
  7. hammad/ai/__init__.py +0 -59
  8. hammad/ai/_utils.py +0 -142
  9. hammad/ai/completions/__init__.py +0 -44
  10. hammad/ai/completions/client.py +0 -729
  11. hammad/ai/completions/create.py +0 -686
  12. hammad/ai/completions/types.py +0 -711
  13. hammad/ai/completions/utils.py +0 -374
  14. hammad/ai/embeddings/__init__.py +0 -35
  15. hammad/ai/embeddings/client/__init__.py +0 -1
  16. hammad/ai/embeddings/client/base_embeddings_client.py +0 -26
  17. hammad/ai/embeddings/client/fastembed_text_embeddings_client.py +0 -200
  18. hammad/ai/embeddings/client/litellm_embeddings_client.py +0 -288
  19. hammad/ai/embeddings/create.py +0 -159
  20. hammad/ai/embeddings/types.py +0 -69
  21. hammad/base/__init__.py +0 -35
  22. hammad/base/fields.py +0 -546
  23. hammad/base/model.py +0 -1078
  24. hammad/base/utils.py +0 -280
  25. hammad/cache/__init__.py +0 -48
  26. hammad/cache/base_cache.py +0 -181
  27. hammad/cache/cache.py +0 -169
  28. hammad/cache/decorators.py +0 -261
  29. hammad/cache/file_cache.py +0 -80
  30. hammad/cache/ttl_cache.py +0 -74
  31. hammad/cli/__init__.py +0 -33
  32. hammad/cli/animations.py +0 -604
  33. hammad/cli/plugins.py +0 -781
  34. hammad/cli/styles/__init__.py +0 -55
  35. hammad/cli/styles/settings.py +0 -139
  36. hammad/cli/styles/types.py +0 -358
  37. hammad/cli/styles/utils.py +0 -480
  38. hammad/configuration/__init__.py +0 -35
  39. hammad/configuration/configuration.py +0 -564
  40. hammad/data/__init__.py +0 -39
  41. hammad/data/collections/__init__.py +0 -34
  42. hammad/data/collections/base_collection.py +0 -58
  43. hammad/data/collections/collection.py +0 -452
  44. hammad/data/collections/searchable_collection.py +0 -556
  45. hammad/data/collections/vector_collection.py +0 -603
  46. hammad/data/databases/__init__.py +0 -21
  47. hammad/data/databases/database.py +0 -902
  48. hammad/json/__init__.py +0 -21
  49. hammad/json/converters.py +0 -152
  50. hammad/logging/__init__.py +0 -35
  51. hammad/logging/decorators.py +0 -834
  52. hammad/logging/logger.py +0 -954
  53. hammad/multimodal/__init__.py +0 -24
  54. hammad/multimodal/audio.py +0 -96
  55. hammad/multimodal/image.py +0 -80
  56. hammad/multithreading/__init__.py +0 -304
  57. hammad/py.typed +0 -0
  58. hammad/pydantic/__init__.py +0 -43
  59. hammad/pydantic/converters.py +0 -623
  60. hammad/pydantic/models/__init__.py +0 -28
  61. hammad/pydantic/models/arbitrary_model.py +0 -46
  62. hammad/pydantic/models/cacheable_model.py +0 -79
  63. hammad/pydantic/models/fast_model.py +0 -318
  64. hammad/pydantic/models/function_model.py +0 -176
  65. hammad/pydantic/models/subscriptable_model.py +0 -63
  66. hammad/text/__init__.py +0 -82
  67. hammad/text/converters.py +0 -723
  68. hammad/text/markdown.py +0 -131
  69. hammad/text/text.py +0 -1066
  70. hammad/types/__init__.py +0 -11
  71. hammad/types/file.py +0 -358
  72. hammad/typing/__init__.py +0 -407
  73. hammad/web/__init__.py +0 -43
  74. hammad/web/http/__init__.py +0 -1
  75. hammad/web/http/client.py +0 -944
  76. hammad/web/models.py +0 -245
  77. hammad/web/openapi/__init__.py +0 -0
  78. hammad/web/openapi/client.py +0 -740
  79. hammad/web/search/__init__.py +0 -1
  80. hammad/web/search/client.py +0 -988
  81. hammad/web/utils.py +0 -472
  82. hammad/yaml/__init__.py +0 -30
  83. hammad/yaml/converters.py +0 -19
  84. hammad_python-0.0.13.dist-info/METADATA +0 -38
  85. hammad_python-0.0.13.dist-info/RECORD +0 -85
  86. {hammad_python-0.0.13.dist-info → hammad_python-0.0.15.dist-info}/WHEEL +0 -0
  87. {hammad_python-0.0.13.dist-info → hammad_python-0.0.15.dist-info}/licenses/LICENSE +0 -0
hammad/base/fields.py DELETED
@@ -1,546 +0,0 @@
1
- """hammad.base.fields"""
2
-
3
- import re
4
- from dataclasses import dataclass
5
- from functools import lru_cache
6
- from typing import Any, Callable, Dict, List, Literal, Optional, Pattern, Set, Union
7
-
8
- import msgspec
9
- from msgspec import field as msgspec_field
10
-
11
- __all__ = (
12
- "FieldInfo",
13
- "field",
14
- "Field",
15
- "str_field",
16
- "int_field",
17
- "float_field",
18
- "list_field",
19
- )
20
-
21
-
22
- @dataclass(frozen=True, slots=True)
23
- class FieldInfo:
24
- """Immutable field information container optimized for performance.
25
-
26
- Uses frozen dataclass with slots for memory efficiency and faster attribute access.
27
- """
28
-
29
- # Core field configuration
30
- default: Any = msgspec.UNSET
31
- default_factory: Optional[Callable[[], Any]] = None
32
-
33
- # Naming and aliases
34
- alias: Optional[str] = None
35
- validation_alias: Optional[str] = None
36
- serialization_alias: Optional[str] = None
37
-
38
- # Documentation
39
- title: Optional[str] = None
40
- description: Optional[str] = None
41
- examples: Optional[List[Any]] = None
42
-
43
- # Serialization control
44
- exclude: bool = False
45
- include: bool = True
46
- repr: bool = True
47
-
48
- # Validation configuration
49
- strict: bool = False
50
- validate_default: bool = False
51
- frozen: bool = False
52
- allow_mutation: bool = True
53
-
54
- # Numeric constraints
55
- gt: Optional[Union[int, float]] = None
56
- ge: Optional[Union[int, float]] = None
57
- lt: Optional[Union[int, float]] = None
58
- le: Optional[Union[int, float]] = None
59
- multiple_of: Optional[Union[int, float]] = None
60
- allow_inf_nan: bool = True
61
-
62
- # String constraints
63
- pattern: Optional[Union[str, Pattern[str]]] = None
64
- strip_whitespace: bool = False
65
- to_lower: bool = False
66
- to_upper: bool = False
67
-
68
- # Collection constraints
69
- min_length: Optional[int] = None
70
- max_length: Optional[int] = None
71
- unique_items: bool = False
72
-
73
- # Advanced configuration
74
- discriminator: Optional[str] = None
75
- json_schema_extra: Optional[Dict[str, Any]] = None
76
- kw_only: bool = False
77
- init: bool = True
78
- init_var: bool = False
79
-
80
- # Union handling
81
- union_mode: Literal["smart", "left_to_right"] = "smart"
82
-
83
- # Custom validators (stored as tuples for immutability)
84
- validators: tuple[Callable[[Any], Any], ...] = ()
85
- pre_validators: tuple[Callable[[Any], Any], ...] = ()
86
- post_validators: tuple[Callable[[Any], Any], ...] = ()
87
-
88
- def __post_init__(self):
89
- """Validate field configuration after initialization."""
90
- # Validate numeric constraints
91
- if self.gt is not None and self.ge is not None:
92
- raise ValueError("Cannot specify both 'gt' and 'ge'")
93
- if self.lt is not None and self.le is not None:
94
- raise ValueError("Cannot specify both 'lt' and 'le'")
95
-
96
- # Validate string pattern
97
- if self.pattern is not None and isinstance(self.pattern, str):
98
- try:
99
- object.__setattr__(self, "pattern", re.compile(self.pattern))
100
- except re.error as e:
101
- raise ValueError(f"Invalid regex pattern: {e}")
102
-
103
- # Ensure validators are tuples
104
- for attr in ("validators", "pre_validators", "post_validators"):
105
- val = getattr(self, attr)
106
- if not isinstance(val, tuple):
107
- object.__setattr__(self, attr, tuple(val) if val else ())
108
-
109
- @lru_cache(maxsize=None)
110
- def get_effective_alias(
111
- self, mode: Literal["validation", "serialization", "general"] = "general"
112
- ) -> Optional[str]:
113
- """Get the effective alias for a given mode with caching."""
114
- if mode == "validation" and self.validation_alias:
115
- return self.validation_alias
116
- elif mode == "serialization" and self.serialization_alias:
117
- return self.serialization_alias
118
- return self.alias
119
-
120
- def apply_constraints(self, value: Any, field_name: str) -> Any:
121
- """Apply validation constraints to a value."""
122
- # Pre-validators
123
- for validator in self.pre_validators:
124
- value = validator(value)
125
-
126
- # Type-specific constraints
127
- if isinstance(value, (int, float)):
128
- value = self._validate_numeric(value, field_name)
129
- elif isinstance(value, str):
130
- value = self._validate_string(value, field_name)
131
- elif isinstance(value, (list, tuple, set, frozenset)):
132
- value = self._validate_collection(value, field_name)
133
-
134
- # General validators
135
- for validator in self.validators:
136
- value = validator(value)
137
-
138
- # Post-validators
139
- for validator in self.post_validators:
140
- value = validator(value)
141
-
142
- return value
143
-
144
- def _validate_numeric(
145
- self, value: Union[int, float], field_name: str
146
- ) -> Union[int, float]:
147
- """Apply numeric constraints."""
148
- if not self.allow_inf_nan and isinstance(value, float):
149
- if value != value: # NaN check
150
- raise ValueError(f"{field_name}: NaN values are not allowed")
151
- if value == float("inf") or value == float("-inf"):
152
- raise ValueError(f"{field_name}: Infinite values are not allowed")
153
-
154
- if self.gt is not None and value <= self.gt:
155
- raise ValueError(f"{field_name}: {value} is not greater than {self.gt}")
156
- if self.ge is not None and value < self.ge:
157
- raise ValueError(
158
- f"{field_name}: {value} is not greater than or equal to {self.ge}"
159
- )
160
- if self.lt is not None and value >= self.lt:
161
- raise ValueError(f"{field_name}: {value} is not less than {self.lt}")
162
- if self.le is not None and value > self.le:
163
- raise ValueError(
164
- f"{field_name}: {value} is not less than or equal to {self.le}"
165
- )
166
-
167
- if self.multiple_of is not None:
168
- if isinstance(value, float) or isinstance(self.multiple_of, float):
169
- # Use float comparison with small epsilon for floats
170
- remainder = value % self.multiple_of
171
- if abs(remainder) > 1e-9 and abs(remainder - self.multiple_of) > 1e-9:
172
- raise ValueError(
173
- f"{field_name}: {value} is not a multiple of {self.multiple_of}"
174
- )
175
- else:
176
- # Exact comparison for integers
177
- if value % self.multiple_of != 0:
178
- raise ValueError(
179
- f"{field_name}: {value} is not a multiple of {self.multiple_of}"
180
- )
181
-
182
- return value
183
-
184
- def _validate_string(self, value: str, field_name: str) -> str:
185
- """Apply string constraints and transformations."""
186
- # Transformations
187
- if self.strip_whitespace:
188
- value = value.strip()
189
- if self.to_lower:
190
- value = value.lower()
191
- if self.to_upper:
192
- value = value.upper()
193
-
194
- # Length validation
195
- if self.min_length is not None and len(value) < self.min_length:
196
- raise ValueError(
197
- f"{field_name}: String length {len(value)} is less than minimum {self.min_length}"
198
- )
199
- if self.max_length is not None and len(value) > self.max_length:
200
- raise ValueError(
201
- f"{field_name}: String length {len(value)} exceeds maximum {self.max_length}"
202
- )
203
-
204
- # Pattern validation
205
- if self.pattern is not None:
206
- pattern = (
207
- self.pattern
208
- if isinstance(self.pattern, Pattern)
209
- else re.compile(self.pattern)
210
- )
211
- if not pattern.match(value):
212
- raise ValueError(
213
- f"{field_name}: String does not match pattern {pattern.pattern}"
214
- )
215
-
216
- return value
217
-
218
- def _validate_collection(
219
- self, value: Union[List, Set, tuple, frozenset], field_name: str
220
- ) -> Any:
221
- """Apply collection constraints."""
222
- # Length validation
223
- if self.min_length is not None and len(value) < self.min_length:
224
- raise ValueError(
225
- f"{field_name}: Collection length {len(value)} is less than minimum {self.min_length}"
226
- )
227
- if self.max_length is not None and len(value) > self.max_length:
228
- raise ValueError(
229
- f"{field_name}: Collection length {len(value)} exceeds maximum {self.max_length}"
230
- )
231
-
232
- # Unique items validation for lists/tuples
233
- if self.unique_items and isinstance(value, (list, tuple)):
234
- seen = set()
235
- for item in value:
236
- # Handle unhashable types
237
- try:
238
- if item in seen:
239
- raise ValueError(
240
- f"{field_name}: Duplicate items are not allowed"
241
- )
242
- seen.add(item)
243
- except TypeError:
244
- # For unhashable types, fall back to linear search
245
- if value.count(item) > 1:
246
- raise ValueError(
247
- f"{field_name}: Duplicate items are not allowed"
248
- )
249
-
250
- return value
251
-
252
- def to_json_schema(self) -> Dict[str, Any]:
253
- """Generate JSON schema for this field."""
254
- schema = {}
255
-
256
- if self.title:
257
- schema["title"] = self.title
258
- if self.description:
259
- schema["description"] = self.description
260
- if self.examples:
261
- schema["examples"] = self.examples
262
-
263
- # Numeric constraints
264
- if self.gt is not None:
265
- schema["exclusiveMinimum"] = self.gt
266
- if self.ge is not None:
267
- schema["minimum"] = self.ge
268
- if self.lt is not None:
269
- schema["exclusiveMaximum"] = self.lt
270
- if self.le is not None:
271
- schema["maximum"] = self.le
272
- if self.multiple_of is not None:
273
- schema["multipleOf"] = self.multiple_of
274
-
275
- # String constraints
276
- if self.pattern is not None:
277
- pattern = (
278
- self.pattern if isinstance(self.pattern, str) else self.pattern.pattern
279
- )
280
- schema["pattern"] = pattern
281
- if self.min_length is not None:
282
- schema["minLength"] = self.min_length
283
- if self.max_length is not None:
284
- schema["maxLength"] = self.max_length
285
-
286
- # Collection constraints
287
- if self.unique_items:
288
- schema["uniqueItems"] = True
289
-
290
- # Extra schema properties
291
- if self.json_schema_extra:
292
- schema.update(self.json_schema_extra)
293
-
294
- return schema
295
-
296
-
297
- class Field:
298
- """Field descriptor that combines msgspec.field with FieldInfo metadata.
299
-
300
- This class wraps msgspec's field functionality while preserving our
301
- extended metadata for validation and serialization.
302
- """
303
-
304
- def __init__(self, field_info: FieldInfo):
305
- self.field_info = field_info
306
- self._msgspec_field = None
307
-
308
- def __set_name__(self, owner, name):
309
- """Called when the descriptor is assigned to a class attribute."""
310
- self.name = name
311
-
312
- def to_msgspec(self) -> Any:
313
- """Convert to a msgspec field."""
314
- kwargs = {}
315
-
316
- # Handle default value
317
- if self.field_info.default is not msgspec.UNSET:
318
- kwargs["default"] = self.field_info.default
319
- elif self.field_info.default_factory is not None:
320
- kwargs["default_factory"] = self.field_info.default_factory
321
-
322
- # Handle field naming
323
- if self.field_info.alias:
324
- # Use Annotated with Meta for field renaming
325
- return msgspec_field(**kwargs)
326
-
327
- return msgspec_field(**kwargs)
328
-
329
- def __repr__(self):
330
- return f"Field({self.field_info})"
331
-
332
-
333
- def field(
334
- default: Any = msgspec.UNSET,
335
- *,
336
- default_factory: Optional[Callable[[], Any]] = None,
337
- alias: Optional[str] = None,
338
- validation_alias: Optional[str] = None,
339
- serialization_alias: Optional[str] = None,
340
- title: Optional[str] = None,
341
- description: Optional[str] = None,
342
- examples: Optional[List[Any]] = None,
343
- exclude: bool = False,
344
- include: bool = True,
345
- repr: bool = True,
346
- strict: bool = False,
347
- validate_default: bool = False,
348
- frozen: bool = False,
349
- allow_mutation: bool = True,
350
- gt: Optional[Union[int, float]] = None,
351
- ge: Optional[Union[int, float]] = None,
352
- lt: Optional[Union[int, float]] = None,
353
- le: Optional[Union[int, float]] = None,
354
- multiple_of: Optional[Union[int, float]] = None,
355
- allow_inf_nan: bool = True,
356
- pattern: Optional[Union[str, Pattern[str]]] = None,
357
- strip_whitespace: bool = False,
358
- to_lower: bool = False,
359
- to_upper: bool = False,
360
- min_length: Optional[int] = None,
361
- max_length: Optional[int] = None,
362
- unique_items: bool = False,
363
- discriminator: Optional[str] = None,
364
- json_schema_extra: Optional[Dict[str, Any]] = None,
365
- kw_only: bool = False,
366
- init: bool = True,
367
- init_var: bool = False,
368
- union_mode: Literal["smart", "left_to_right"] = "smart",
369
- validators: Optional[List[Callable[[Any], Any]]] = None,
370
- pre_validators: Optional[List[Callable[[Any], Any]]] = None,
371
- post_validators: Optional[List[Callable[[Any], Any]]] = None,
372
- ) -> Any:
373
- """Create a field descriptor for Model with Pydantic-like configuration.
374
-
375
- This function creates a field with validation, serialization, and schema
376
- generation capabilities while maintaining msgspec's performance benefits.
377
-
378
- Args:
379
- default: Default value for the field
380
- default_factory: Factory function to generate default values
381
- alias: Alternative name for the field in serialization/deserialization
382
- validation_alias: Specific alias for validation (input) only
383
- serialization_alias: Specific alias for serialization (output) only
384
- title: Human-readable title for documentation
385
- description: Human-readable description for documentation
386
- examples: List of example valid values
387
- exclude: Whether to exclude this field from serialization
388
- include: Whether to include this field in serialization
389
- repr: Whether to include in string representation
390
- strict: Whether to use strict type validation
391
- validate_default: Whether to validate the default value
392
- frozen: Whether the field is immutable after creation
393
- allow_mutation: Whether the field can be modified
394
- gt: Value must be greater than this
395
- ge: Value must be greater than or equal to this
396
- lt: Value must be less than this
397
- le: Value must be less than or equal to this
398
- multiple_of: Value must be a multiple of this
399
- allow_inf_nan: Whether to allow infinity and NaN for floats
400
- pattern: Regex pattern for string validation
401
- strip_whitespace: Whether to strip whitespace from strings
402
- to_lower: Whether to convert strings to lowercase
403
- to_upper: Whether to convert strings to uppercase
404
- min_length: Minimum length for strings/collections
405
- max_length: Maximum length for strings/collections
406
- unique_items: Whether collection items must be unique
407
- discriminator: Field name for discriminating unions
408
- json_schema_extra: Additional JSON schema properties
409
- kw_only: Whether the field is keyword-only in __init__
410
- init: Whether to include in __init__
411
- init_var: Whether the field is init-only
412
- union_mode: How to validate union types
413
- validators: List of validation functions
414
- pre_validators: List of pre-processing validators
415
- post_validators: List of post-processing validators
416
-
417
- Returns:
418
- Field descriptor or Annotated type with metadata for use with Model
419
- """
420
- # Store field info for potential future use (validation, schema generation, etc.)
421
- info = FieldInfo(
422
- default=default,
423
- default_factory=default_factory,
424
- alias=alias,
425
- validation_alias=validation_alias,
426
- serialization_alias=serialization_alias,
427
- title=title,
428
- description=description,
429
- examples=examples,
430
- exclude=exclude,
431
- include=include,
432
- repr=repr,
433
- strict=strict,
434
- validate_default=validate_default,
435
- frozen=frozen,
436
- allow_mutation=allow_mutation,
437
- gt=gt,
438
- ge=ge,
439
- lt=lt,
440
- le=le,
441
- multiple_of=multiple_of,
442
- allow_inf_nan=allow_inf_nan,
443
- pattern=pattern,
444
- strip_whitespace=strip_whitespace,
445
- to_lower=to_lower,
446
- to_upper=to_upper,
447
- min_length=min_length,
448
- max_length=max_length,
449
- unique_items=unique_items,
450
- discriminator=discriminator,
451
- json_schema_extra=json_schema_extra,
452
- kw_only=kw_only,
453
- init=init,
454
- init_var=init_var,
455
- union_mode=union_mode,
456
- validators=tuple(validators or []),
457
- pre_validators=tuple(pre_validators or []),
458
- post_validators=tuple(post_validators or []),
459
- )
460
-
461
- # Build the kwargs for the msgspec field
462
- kwargs = {}
463
- if default is not msgspec.UNSET:
464
- kwargs["default"] = default
465
- elif default_factory is not None:
466
- kwargs["default_factory"] = default_factory
467
-
468
- # Create the msgspec field with validation info embedded
469
- msgspec_field_instance = msgspec_field(**kwargs)
470
-
471
- # For now, just return the msgspec field - let msgspec handle everything
472
- return msgspec_field_instance
473
-
474
-
475
- def str_field(
476
- *,
477
- min_length: Optional[int] = None,
478
- max_length: Optional[int] = None,
479
- pattern: Optional[Union[str, Pattern[str]]] = None,
480
- strip_whitespace: bool = False,
481
- to_lower: bool = False,
482
- to_upper: bool = False,
483
- **kwargs,
484
- ) -> Any:
485
- """Create a string field with common string-specific options."""
486
- return field(
487
- min_length=min_length,
488
- max_length=max_length,
489
- pattern=pattern,
490
- strip_whitespace=strip_whitespace,
491
- to_lower=to_lower,
492
- to_upper=to_upper,
493
- **kwargs,
494
- )
495
-
496
-
497
- def int_field(
498
- *,
499
- gt: Optional[int] = None,
500
- ge: Optional[int] = None,
501
- lt: Optional[int] = None,
502
- le: Optional[int] = None,
503
- multiple_of: Optional[int] = None,
504
- **kwargs,
505
- ) -> Any:
506
- """Create an integer field with numeric constraints."""
507
- return field(gt=gt, ge=ge, lt=lt, le=le, multiple_of=multiple_of, **kwargs)
508
-
509
-
510
- def float_field(
511
- *,
512
- gt: Optional[float] = None,
513
- ge: Optional[float] = None,
514
- lt: Optional[float] = None,
515
- le: Optional[float] = None,
516
- multiple_of: Optional[float] = None,
517
- allow_inf_nan: bool = True,
518
- **kwargs,
519
- ) -> Any:
520
- """Create a float field with numeric constraints."""
521
- return field(
522
- gt=gt,
523
- ge=ge,
524
- lt=lt,
525
- le=le,
526
- multiple_of=multiple_of,
527
- allow_inf_nan=allow_inf_nan,
528
- **kwargs,
529
- )
530
-
531
-
532
- def list_field(
533
- *,
534
- min_length: Optional[int] = None,
535
- max_length: Optional[int] = None,
536
- unique_items: bool = False,
537
- **kwargs,
538
- ) -> Any:
539
- """Create a list field with collection constraints."""
540
- return field(
541
- default_factory=list,
542
- min_length=min_length,
543
- max_length=max_length,
544
- unique_items=unique_items,
545
- **kwargs,
546
- )