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
@@ -1,623 +0,0 @@
1
- """hammad.utils.pydantic.converters
2
-
3
- Contains various converters for converting various objects into
4
- a Pydantic model. These converters are used to convert
5
- various objects into a Pydantic model, such as types,
6
- docstrings, and other objects."""
7
-
8
- import inspect
9
- import logging
10
- from dataclasses import is_dataclass, fields as dataclass_fields, MISSING
11
- from docstring_parser import parse
12
- from typing import (
13
- Any,
14
- Dict,
15
- Literal,
16
- Optional,
17
- Type,
18
- Union,
19
- Mapping,
20
- get_type_hints,
21
- Callable,
22
- Sequence,
23
- TypeVar,
24
- Tuple,
25
- List,
26
- overload,
27
- cast,
28
- )
29
- from pydantic import BaseModel, Field, create_model
30
-
31
- from ..cache.decorators import cached
32
-
33
- logger = logging.getLogger(__name__)
34
-
35
- __all__ = [
36
- "is_pydantic_model_class",
37
- "get_pydantic_fields_from_function",
38
- "convert_to_pydantic_field",
39
- "convert_to_pydantic_model",
40
- "create_selection_pydantic_model",
41
- "create_confirmation_pydantic_model",
42
- "convert_dataclass_to_pydantic_model",
43
- "convert_type_to_pydantic_model",
44
- "convert_function_to_pydantic_model",
45
- "convert_sequence_to_pydantic_model",
46
- "convert_dict_to_pydantic_model",
47
- ]
48
-
49
-
50
- # -----------------------------------------------------------------------------
51
- # Types & Constants
52
- # -----------------------------------------------------------------------------
53
-
54
- BaseModelType = TypeVar("BaseModelType", bound=BaseModel)
55
- """Helper type for Pydantic model classes."""
56
-
57
-
58
- JSON_TYPE_MAPPING: Mapping[Any, Tuple[str, Any]] = {
59
- int: ("int", int),
60
- float: ("float", float),
61
- bool: ("bool", bool),
62
- str: ("str", str),
63
- bytes: ("bytes", bytes),
64
- list: ("list", list),
65
- tuple: ("tuple", tuple),
66
- dict: ("dict", dict),
67
- set: ("set", set),
68
- frozenset: ("frozenset", frozenset),
69
- Any: ("any", Any),
70
- None: ("none", None),
71
- Union: ("union", Union),
72
- Optional: ("optional", Optional),
73
- }
74
- """
75
- A mapping of types to their string representations. Used for hinting & JSON schema
76
- generation.
77
- """
78
-
79
-
80
- # -----------------------------------------------------------------------------
81
- # Pydantic Model Utils
82
- # -----------------------------------------------------------------------------
83
-
84
-
85
- def is_pydantic_model_class(obj: Any) -> bool:
86
- """
87
- Checks if an object is a Pydantic model class.
88
- """
89
- return isinstance(obj, type) and issubclass(obj, BaseModel)
90
-
91
-
92
- def get_pydantic_fields_from_function(func: Callable) -> Dict[str, Tuple[Type, Field]]:
93
- """
94
- Extracts Pydantic fields from a function's signature and docstring.
95
- Returns a dictionary mapping field names to (type, Pydantic Field) tuples.
96
-
97
- Args:
98
- func: The function to extract Pydantic fields from.
99
-
100
- Returns:
101
- A dictionary mapping field names to (type, Pydantic Field) tuples.
102
- """
103
- try:
104
- hints = get_type_hints(func)
105
- fields_dict: Dict[str, Tuple[Type, Field]] = {}
106
- doc_info = parse(func.__doc__ or "")
107
-
108
- for param_name, param_type in hints.items():
109
- if param_name == "return":
110
- continue
111
-
112
- description = ""
113
- if doc_info.params:
114
- description = (
115
- next(
116
- (
117
- p.description
118
- for p in doc_info.params
119
- if p.arg_name == param_name
120
- ),
121
- "",
122
- )
123
- or ""
124
- )
125
-
126
- default_value = ...
127
- param = inspect.signature(func).parameters.get(param_name)
128
- if param and param.default is not inspect.Parameter.empty:
129
- default_value = param.default
130
-
131
- fields_dict[param_name] = (
132
- param_type,
133
- Field(default=default_value, description=description),
134
- )
135
- return fields_dict
136
- except Exception as e:
137
- logger.error(
138
- f"Error extracting function fields for {getattr(func, '__name__', 'unknown function')}: {e}"
139
- )
140
- return {}
141
-
142
-
143
- @cached
144
- def convert_to_pydantic_field(
145
- type_hint: Type,
146
- index: Optional[int] = None,
147
- description: Optional[str] = None,
148
- default: Any = ...,
149
- ) -> Dict[str, Tuple[Type, Field]]:
150
- """
151
- Creates a Pydantic field definition from a type hint.
152
- Returns a dictionary mapping a generated field name to its (type, Field) tuple.
153
- """
154
- try:
155
- base_name, _ = JSON_TYPE_MAPPING.get(type_hint, ("value", type_hint))
156
- field_name = f"value_{index}" if index is not None else "value"
157
- return {
158
- field_name: (
159
- type_hint,
160
- Field(default=default, description=description or ""),
161
- )
162
- }
163
- except Exception as e:
164
- logger.error(f"Error creating Pydantic field mapping for type {type_hint}: {e}")
165
- raise
166
-
167
-
168
- # -----------------------------------------------------------------------------
169
- # Simplified Model Creation
170
- # -----------------------------------------------------------------------------
171
-
172
-
173
- # -----------------------------------------------------------------------------
174
- # Helpers (Private)
175
- # -----------------------------------------------------------------------------
176
-
177
-
178
- @cached
179
- def convert_dataclass_to_pydantic_model(
180
- target: Union[Type, Any], # NOTE: DATACLASS TYPE OR INSTANCE
181
- init: bool,
182
- name: Optional[str],
183
- description: Optional[str],
184
- ) -> Union[Type[BaseModel], BaseModel]:
185
- # Determine if we're dealing with a type or instance
186
- is_instance = not isinstance(target, type)
187
- dataclass_type = type(target) if is_instance else target
188
-
189
- model_name = name or dataclass_type.__name__
190
- doc_info = parse(dataclass_type.__doc__ or "")
191
- model_doc = description or doc_info.short_description
192
-
193
- pydantic_fields: Dict[str, Tuple[Type, Field]] = {}
194
- for dc_field in dataclass_fields(dataclass_type):
195
- field_type = dc_field.type
196
- field_default = dc_field.default if dc_field.default is not MISSING else ... # type: ignore
197
- if dc_field.default_factory is not MISSING: # type: ignore
198
- field_default = Field(default_factory=dc_field.default_factory)
199
-
200
- field_description = ""
201
- if doc_info.params:
202
- field_description = (
203
- next(
204
- (
205
- p.description
206
- for p in doc_info.params
207
- if p.arg_name == dc_field.name
208
- ),
209
- "",
210
- )
211
- or ""
212
- )
213
-
214
- pydantic_fields[dc_field.name] = (
215
- field_type,
216
- Field(default=field_default, description=field_description),
217
- )
218
-
219
- model_class = create_model(model_name, __doc__=model_doc, **pydantic_fields)
220
-
221
- if init and is_instance:
222
- instance_data = {
223
- f.name: getattr(target, f.name) for f in dataclass_fields(dataclass_type)
224
- }
225
- return model_class(**instance_data)
226
- return model_class
227
-
228
-
229
- @cached
230
- def convert_type_to_pydantic_model(
231
- target: Type,
232
- name: Optional[str],
233
- description: Optional[str],
234
- field_name: Optional[str],
235
- default: Any,
236
- ) -> Type[BaseModel]:
237
- model_name = name or "GeneratedModel"
238
- field_mapping = convert_to_pydantic_field(
239
- target, description=description, default=default
240
- )
241
-
242
- if field_name: # Override default field name "value"
243
- current_field_def = list(field_mapping.values())[0]
244
- field_mapping = {field_name: current_field_def}
245
-
246
- return create_model(model_name, __doc__=(description or ""), **field_mapping)
247
-
248
-
249
- @cached
250
- def convert_function_to_pydantic_model(
251
- target: Callable,
252
- name: Optional[str],
253
- description: Optional[str],
254
- ) -> Type[BaseModel]:
255
- model_name = name or target.__name__
256
- doc_info = parse(target.__doc__ or "")
257
- model_doc = description or doc_info.short_description
258
-
259
- fields = get_pydantic_fields_from_function(target)
260
- return create_model(model_name, __doc__=model_doc, **fields)
261
-
262
-
263
- @cached
264
- def convert_sequence_to_pydantic_model(
265
- target: Sequence[Type],
266
- name: Optional[str],
267
- description: Optional[str],
268
- field_name: Optional[str],
269
- default: Any,
270
- ) -> Type[BaseModel]:
271
- if not target:
272
- raise ValueError("Cannot create Pydantic model from empty sequence")
273
-
274
- model_name = name or "GeneratedModel"
275
- pydantic_fields: Dict[str, Tuple[Type, Field]] = {}
276
-
277
- for i, type_hint in enumerate(target):
278
- if not isinstance(type_hint, type):
279
- raise ValueError(
280
- f"Sequence elements must be types, got {type_hint} at index {i}"
281
- )
282
-
283
- field_desc = description if i == 0 and field_name else None
284
- field_def_default = default if i == 0 and field_name else ...
285
-
286
- # Use provided field_name for the first element if specified
287
- current_field_name_override = field_name if i == 0 else None
288
-
289
- # Generate field(s) from type_hint
290
- temp_field_def = convert_to_pydantic_field(
291
- type_hint,
292
- index=None if current_field_name_override else i,
293
- description=field_desc,
294
- default=field_def_default,
295
- )
296
-
297
- actual_field_name = list(temp_field_def.keys())[0]
298
- actual_type_info = list(temp_field_def.values())[0]
299
-
300
- if current_field_name_override:
301
- pydantic_fields[current_field_name_override] = actual_type_info
302
- else:
303
- pydantic_fields[actual_field_name] = actual_type_info
304
-
305
- return create_model(model_name, __doc__=(description or ""), **pydantic_fields)
306
-
307
-
308
- @cached
309
- def convert_dict_to_pydantic_model(
310
- target: Dict[str, Any],
311
- init: bool,
312
- name: Optional[str],
313
- description: Optional[str],
314
- ) -> Union[Type[BaseModel], BaseModel]:
315
- model_name = name or "GeneratedModel"
316
-
317
- pydantic_fields: Dict[str, Tuple[Type, Field]] = {}
318
- for k, v in target.items():
319
- pydantic_fields[k] = (type(v), Field(default=v if init else ...))
320
-
321
- model_class = create_model(
322
- model_name, __doc__=(description or ""), **pydantic_fields
323
- )
324
-
325
- if init:
326
- return model_class(**target)
327
- return model_class
328
-
329
-
330
- @cached
331
- def _reconvert_to_pydantic_model_from_basemodel_instance(
332
- target: BaseModel,
333
- name: Optional[str],
334
- description: Optional[str],
335
- ) -> BaseModel:
336
- model_name = name or target.__class__.__name__
337
- doc_info = parse(target.__class__.__doc__ or "")
338
- model_doc = description or doc_info.short_description
339
-
340
- instance_data = target.model_dump()
341
- pydantic_fields: Dict[str, Tuple[Type, Field]] = {}
342
- for k, v_instance in instance_data.items():
343
- original_field_info = target.__class__.model_fields.get(k)
344
- field_desc = original_field_info.description if original_field_info else ""
345
- pydantic_fields[k] = (
346
- type(v_instance),
347
- Field(default=v_instance, description=field_desc),
348
- )
349
-
350
- new_model_class = create_model(model_name, __doc__=model_doc, **pydantic_fields)
351
- return new_model_class(**instance_data)
352
-
353
-
354
- # ITS OVER 9000
355
-
356
-
357
- @overload
358
- def convert_to_pydantic_model(
359
- target: Type[BaseModelType],
360
- init: Literal[False] = False,
361
- name: Optional[str] = None,
362
- description: Optional[str] = None,
363
- field_name: Optional[str] = None,
364
- default: Any = ...,
365
- ) -> Type[BaseModelType]: ...
366
- @overload
367
- def convert_to_pydantic_model(
368
- target: Type[BaseModelType],
369
- init: Literal[True],
370
- name: Optional[str] = None,
371
- description: Optional[str] = None,
372
- field_name: Optional[str] = None,
373
- default: Any = ...,
374
- ) -> BaseModelType: ...
375
- @overload
376
- def convert_to_pydantic_model(
377
- target: BaseModelType,
378
- init: Literal[False] = False,
379
- name: Optional[str] = None,
380
- description: Optional[str] = None,
381
- field_name: Optional[str] = None,
382
- default: Any = ...,
383
- ) -> Type[BaseModelType]: ...
384
- @overload
385
- def convert_to_pydantic_model(
386
- target: BaseModelType,
387
- init: Literal[True],
388
- name: Optional[str] = None,
389
- description: Optional[str] = None,
390
- field_name: Optional[str] = None,
391
- default: Any = ...,
392
- ) -> BaseModelType: ...
393
- @overload
394
- def convert_to_pydantic_model(
395
- target: Type,
396
- init: Literal[False] = False,
397
- name: Optional[str] = None,
398
- description: Optional[str] = None,
399
- field_name: Optional[str] = None,
400
- default: Any = ...,
401
- ) -> Type[BaseModel]: ...
402
- @overload
403
- def convert_to_pydantic_model(
404
- target: Type,
405
- init: Literal[True],
406
- name: Optional[str] = None,
407
- description: Optional[str] = None,
408
- field_name: Optional[str] = None,
409
- default: Any = ...,
410
- ) -> BaseModel: # For dataclass instances from type
411
- ...
412
- @overload
413
- def convert_to_pydantic_model(
414
- target: Callable,
415
- init: Literal[False] = False,
416
- name: Optional[str] = None,
417
- description: Optional[str] = None,
418
- field_name: Optional[str] = None,
419
- default: Any = ...,
420
- ) -> Type[BaseModel]: ...
421
- @overload
422
- def convert_to_pydantic_model(
423
- target: Sequence[Type],
424
- init: Literal[False] = False,
425
- name: Optional[str] = None,
426
- description: Optional[str] = None,
427
- field_name: Optional[str] = None,
428
- default: Any = ...,
429
- ) -> Type[BaseModel]: ...
430
- @overload
431
- def convert_to_pydantic_model(
432
- target: Dict[str, Any],
433
- init: Literal[False] = False,
434
- name: Optional[str] = None,
435
- description: Optional[str] = None,
436
- field_name: Optional[str] = None,
437
- default: Any = ...,
438
- ) -> Type[BaseModel]: ...
439
- @overload
440
- def convert_to_pydantic_model(
441
- target: Dict[str, Any],
442
- init: Literal[True],
443
- name: Optional[str] = None,
444
- description: Optional[str] = None,
445
- field_name: Optional[str] = None,
446
- default: Any = ...,
447
- ) -> BaseModel: ...
448
-
449
-
450
- def convert_to_pydantic_model(
451
- target: Union[Type, Sequence[Type], Dict[str, Any], BaseModel, Callable],
452
- init: bool = False,
453
- name: Optional[str] = None,
454
- description: Optional[str] = None,
455
- field_name: Optional[str] = None,
456
- default: Any = ...,
457
- ) -> Union[Type[BaseModel], BaseModel]:
458
- """
459
- Converts various input types into a Pydantic model class or instance.
460
-
461
- Args:
462
- target: The target to convert (Python type, Pydantic BaseModel class/instance,
463
- dataclass type/instance, function, sequence of types, or dict).
464
- init: If True, returns an initialized Pydantic model instance where applicable
465
- (e.g., from a dict, dataclass instance, or BaseModel instance).
466
- If False (default), returns a Pydantic model class.
467
- name: Optional name for the generated Pydantic model.
468
- description: Optional description for the model (used as its docstring).
469
- field_name: Optional name for the primary field if `target` is a single type
470
- or for the first field if `target` is a sequence of types.
471
- default: Optional default value if `target` is a single type, used with `field_name`.
472
-
473
- Returns:
474
- A Pydantic model class, or an instance of one if `init` is True and applicable.
475
- """
476
- # Handle existing Pydantic model classes
477
- if is_pydantic_model_class(target):
478
- target_cls = cast(Type[BaseModel], target)
479
- if init:
480
- try:
481
- return target_cls()
482
- except Exception as e:
483
- logger.warning(
484
- f"Cannot auto-initialize {target_cls.__name__} due to missing required fields: {e}"
485
- )
486
- # Cannot create instance without required fields, return the class instead
487
- return target_cls
488
- if name and name != target_cls.__name__ or description:
489
- return _reconvert_to_pydantic_model_from_basemodel_instance(
490
- target_cls(), name=name, description=description
491
- )
492
- return target_cls
493
-
494
- # Handle Pydantic model instances
495
- if isinstance(target, BaseModel):
496
- if init:
497
- return _reconvert_to_pydantic_model_from_basemodel_instance(
498
- target, name=name, description=description
499
- )
500
- return target.__class__
501
-
502
- # Handle dataclasses (types or instances)
503
- if is_dataclass(target):
504
- if isinstance(target, type):
505
- # target is a dataclass type
506
- return convert_dataclass_to_pydantic_model(
507
- cast(Type, target),
508
- init=init,
509
- name=name,
510
- description=description,
511
- )
512
- else:
513
- # target is a dataclass instance
514
- return convert_dataclass_to_pydantic_model(
515
- target, # Pass the instance directly
516
- init=init,
517
- name=name,
518
- description=description,
519
- )
520
-
521
- # Handle standard Python types (int, str, etc.)
522
- if isinstance(target, type):
523
- return convert_type_to_pydantic_model(
524
- target, name, description, field_name, default
525
- )
526
-
527
- # Handle callables (functions)
528
- if callable(target):
529
- return convert_function_to_pydantic_model(target, name, description)
530
-
531
- # Handle sequences of types
532
- if isinstance(target, Sequence) and not isinstance(target, str):
533
- if not all(isinstance(t, type) for t in target):
534
- raise TypeError("If target is a sequence, all its elements must be types.")
535
- return convert_sequence_to_pydantic_model(
536
- cast(Sequence[Type], target), name, description, field_name, default
537
- )
538
-
539
- # Handle dictionaries
540
- if isinstance(target, dict):
541
- return convert_dict_to_pydantic_model(target, init, name, description)
542
-
543
- else:
544
- logger.error(
545
- f"Unsupported target type for Pydantic model creation: {type(target)} | how did you get here?"
546
- )
547
- raise TypeError(
548
- f"Cannot create Pydantic model from target of type {type(target)}"
549
- )
550
-
551
-
552
- # -----------------------------------------------------------------------------
553
- # Specialized Model Creation Utils
554
- # -----------------------------------------------------------------------------
555
-
556
-
557
- @cached
558
- def create_selection_pydantic_model(
559
- fields: List[str],
560
- name: str = "Selection",
561
- description: Optional[str] = None,
562
- ) -> Type[BaseModel]:
563
- """
564
- Creates a Pydantic model for making a selection from a list of string options.
565
- The model will have a single field named `selection` of type `Literal[*fields]`.
566
-
567
- Args:
568
- fields: A list of strings representing the allowed choices. Must not be empty.
569
- name: The name for the created Pydantic model.
570
- description: Optional description for the model (becomes its docstring).
571
-
572
- Returns:
573
- A new Pydantic BaseModel class with a 'selection' field.
574
- Raises:
575
- ValueError: If `fields` is empty.
576
- """
577
- if not fields:
578
- raise ValueError(
579
- "`fields` list cannot be empty for `create_selection_pydantic_model`."
580
- )
581
-
582
- literal_args_str = ", ".join(repr(str(f)) for f in fields)
583
- selection_type = eval(f"Literal[{literal_args_str}]")
584
-
585
- model_fields_definitions = {
586
- "selection": (
587
- selection_type,
588
- Field(..., description="The selected value from the available options."),
589
- )
590
- }
591
- model_docstring = (
592
- description or f"A model for selecting one option from: {', '.join(fields)}."
593
- )
594
- return create_model(
595
- name, __base__=BaseModel, __doc__=model_docstring, **model_fields_definitions
596
- )
597
-
598
-
599
- @cached
600
- def create_confirmation_pydantic_model(
601
- name: str = "Confirmation",
602
- description: Optional[str] = None,
603
- field_name: str = "confirmed",
604
- ) -> Type[BaseModel]:
605
- """
606
- Creates a Pydantic model for a boolean confirmation.
607
- The model will have a single boolean field.
608
-
609
- Args:
610
- name: The name for the created Pydantic model.
611
- description: Optional description for the model.
612
- field_name: Name of the boolean field in the model.
613
-
614
- Returns:
615
- A new Pydantic BaseModel class.
616
- """
617
- model_fields_definitions = {
618
- field_name: (bool, Field(..., description="The boolean confirmation value."))
619
- }
620
- model_docstring = description or "A model for boolean confirmation."
621
- return create_model(
622
- name, __base__=BaseModel, __doc__=model_docstring, **model_fields_definitions
623
- )
@@ -1,28 +0,0 @@
1
- """hammad.pydantic.models"""
2
-
3
- from typing import TYPE_CHECKING
4
- from ..._core._utils._import_utils import _auto_create_getattr_loader
5
-
6
- if TYPE_CHECKING:
7
- from .arbitrary_model import ArbitraryModel
8
- from .cacheable_model import CacheableModel
9
- from .fast_model import FastModel
10
- from .function_model import FunctionModel
11
- from .subscriptable_model import SubscriptableModel
12
-
13
-
14
- __all__ = (
15
- "ArbitraryModel",
16
- "CacheableModel",
17
- "FastModel",
18
- "FunctionModel",
19
- "SubscriptableModel",
20
- )
21
-
22
-
23
- __getattr__ = _auto_create_getattr_loader(__all__)
24
-
25
-
26
- def __dir__() -> list[str]:
27
- """Get the attributes of the models module."""
28
- return list(__all__)
@@ -1,46 +0,0 @@
1
- """hammad.pydantic.models.arbitrary_model"""
2
-
3
- from typing import Any, Dict
4
- from pydantic import ConfigDict
5
-
6
- from .subscriptable_model import SubscriptableModel
7
-
8
- __all__ = ("ArbitraryModel",)
9
-
10
-
11
- class ArbitraryModel(SubscriptableModel):
12
- """
13
- A model that allows dynamic field assignment and access.
14
- Perfect for handling arbitrary JSON data or when schema is unknown at compile time.
15
-
16
- Usage:
17
- >>> data = ArbitraryModel()
18
- >>> data.name = "John"
19
- >>> data.age = 30
20
- >>> data.metadata = {"key": "value"}
21
- >>> print(data.name) # John
22
- >>> print(data["age"]) # 30
23
- """
24
-
25
- model_config = ConfigDict(extra="allow", arbitrary_types_allowed=True)
26
-
27
- def __init__(self, **data: Any):
28
- super().__init__(**data)
29
- # Store extra fields for easy access
30
- self._arbitrary_fields: Dict[str, Any] = {}
31
-
32
- def __setattr__(self, name: str, value: Any) -> None:
33
- if name.startswith("_") or name in self.__class__.model_fields:
34
- super().__setattr__(name, value)
35
- else:
36
- # Store in dynamic fields and set normally
37
- if hasattr(self, "_arbitrary_fields"):
38
- self._arbitrary_fields[name] = value
39
- super().__setattr__(name, value)
40
-
41
- def to_dict(self) -> Dict[str, Any]:
42
- """Convert to dictionary including all dynamic fields."""
43
- result = self.model_dump()
44
- if hasattr(self, "_arbitrary_fields"):
45
- result.update(self._arbitrary_fields)
46
- return result