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