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,79 +0,0 @@
1
- """hammad.pydantic.models.cacheable_model"""
2
-
3
- from typing import Any, Callable, Dict, Optional
4
- from functools import wraps
5
-
6
- from .subscriptable_model import SubscriptableModel
7
-
8
- __all__ = ("CacheableModel",)
9
-
10
-
11
- class CacheableModel(SubscriptableModel):
12
- """
13
- A model with built-in caching for computed properties.
14
- Automatically caches expensive computations and invalidates when dependencies change.
15
-
16
- Usage:
17
- >>> class MyModel(CacheableModel):
18
- ... value: int
19
- ... @CacheableModel.cached_property(dependencies=["value"])
20
- ... def expensive_computation(self) -> int:
21
- ... return self.value ** 2
22
- >>> model = MyModel(value=10)
23
- >>> model.expensive_computation # Computed once
24
- >>> model.expensive_computation # Returns cached value
25
- """
26
-
27
- def __init__(self, **data: Any):
28
- super().__init__(**data)
29
- self._cache: Dict[str, Any] = {}
30
- self._cache_dependencies: Dict[str, list] = {}
31
-
32
- @classmethod
33
- def cached_property(cls, dependencies: Optional[list] = None):
34
- """Decorator for creating cached properties with optional dependencies."""
35
-
36
- def decorator(func: Callable) -> property:
37
- prop_name = func.__name__
38
- deps = dependencies or []
39
-
40
- @wraps(func)
41
- def wrapper(self) -> Any:
42
- # Check if cached and dependencies haven't changed
43
- if prop_name in self._cache:
44
- if not deps or all(
45
- getattr(self, dep) == self._cache.get(f"_{dep}_snapshot")
46
- for dep in deps
47
- ):
48
- return self._cache[prop_name]
49
-
50
- # Compute and cache
51
- result = func(self)
52
- self._cache[prop_name] = result
53
-
54
- # Store dependency snapshots
55
- for dep in deps:
56
- self._cache[f"_{dep}_snapshot"] = getattr(self, dep)
57
-
58
- return result
59
-
60
- return property(wrapper)
61
-
62
- return decorator
63
-
64
- def clear_cache(self, property_name: Optional[str] = None) -> None:
65
- """Clear cache for specific property or all cached properties."""
66
- if property_name:
67
- self._cache.pop(property_name, None)
68
- else:
69
- self._cache.clear()
70
-
71
- def __setattr__(self, name: str, value: Any) -> None:
72
- # Invalidate cache when dependencies change
73
- if hasattr(self, "_cache") and name in self.__class__.model_fields:
74
- # Clear cache for properties that depend on this field
75
- for prop_name, deps in getattr(self, "_cache_dependencies", {}).items():
76
- if name in deps:
77
- self._cache.pop(prop_name, None)
78
-
79
- super().__setattr__(name, value)
@@ -1,318 +0,0 @@
1
- """hammad.pydantic.models.fast_model"""
2
-
3
- from typing import Any, Callable, Dict, List, Optional, Set, Tuple, TypeVar, Generic
4
- from pydantic import BaseModel, ConfigDict
5
- from dataclasses import dataclass
6
- import copy
7
-
8
- T = TypeVar("T")
9
-
10
- __all__ = ("FastModel",)
11
-
12
-
13
- class FastModel(BaseModel, Generic[T]):
14
- """
15
- FastModel = Pydantic BaseModel with IDE friendly(auto code completion),
16
- dot-accessible attributes with extended type hints & utilizing the
17
- Pydantic style `model_..` method naming convention to avoid conflicts.
18
-
19
- Combines the power of Pydantic BaseModel with dictionary-like access patterns.
20
-
21
- Examples:
22
-
23
- ```python
24
- model = FastModel(name="John", age=30)
25
-
26
- print(model.name)
27
- print(model.age)
28
-
29
- model.name = "Jane"
30
- print(model.name)
31
-
32
- model.age = 25
33
-
34
- # Dictionary-like access
35
- print(model["name"])
36
- model["age"] = 30
37
- ```
38
- """
39
-
40
- model_config = ConfigDict(extra="allow", arbitrary_types_allowed=True)
41
-
42
- def __init__(self: "FastModel[T]", *args: Any, **kwargs: Any) -> None:
43
- # Handle dictionary-like initialization
44
- if args and len(args) == 1 and isinstance(args[0], dict):
45
- kwargs.update(args[0])
46
- args = ()
47
-
48
- super().__init__(**kwargs)
49
-
50
- # Set all properties to None for annotated attributes not provided
51
- for k, v in self.model_attr_types().items():
52
- if k not in kwargs:
53
- setattr(self, k, None)
54
-
55
- # Set default values of annotated attributes
56
- self.init()
57
-
58
- def init(self: "FastModel[T]") -> None:
59
- """Override this method to set default values."""
60
- ...
61
-
62
- def __getstate__(self: "FastModel[T]") -> dict[str, Any]:
63
- return self.model_dump()
64
-
65
- def __setstate__(self: "FastModel[T]", state: dict[str, Any]) -> "FastModel[T]":
66
- return FastModel.model_from_dict(state)
67
-
68
- def __deepcopy__(
69
- self: "FastModel[T]", memo: Optional[dict[int, Any]] = None
70
- ) -> "FastModel[T]":
71
- # Get current field values
72
- current_data = {}
73
- for key in self.keys():
74
- current_data[key] = getattr(self, key)
75
-
76
- new = self.model_from_dict(current_data)
77
- for key in self.__class__.model_fields.keys():
78
- new.model_set_attribute(key, copy.deepcopy(getattr(self, key), memo=memo))
79
- return new
80
-
81
- # Dictionary-like access methods
82
- def __getitem__(self: "FastModel[T]", key: str) -> Any:
83
- """Get field value using dict-like access."""
84
- if hasattr(self, key):
85
- return getattr(self, key)
86
- raise KeyError(key)
87
-
88
- def __setitem__(self: "FastModel[T]", key: str, value: Any) -> None:
89
- """Set field value using dict-like access."""
90
- setattr(self, key, value)
91
-
92
- def __contains__(self: "FastModel[T]", key: str) -> bool:
93
- """Check if field exists using 'in' operator."""
94
- return hasattr(self, key) or key in self.__class__.model_fields
95
-
96
- def get(self: "FastModel[T]", key: str, default: Any = None) -> Any:
97
- """Get field value with optional default."""
98
- return getattr(self, key, default)
99
-
100
- def keys(self: "FastModel[T]"):
101
- """Return all field names."""
102
- return list(self.__class__.model_fields.keys()) + [
103
- k for k in self.__dict__.keys() if not k.startswith("_")
104
- ]
105
-
106
- def items(self: "FastModel[T]"):
107
- """Return all field (name, value) pairs."""
108
- for key in self.keys():
109
- yield key, getattr(self, key)
110
-
111
- def values(self: "FastModel[T]"):
112
- """Return all field values."""
113
- for key in self.keys():
114
- yield getattr(self, key)
115
-
116
- def update(self: "FastModel[T]", other: dict) -> None:
117
- """Update multiple fields at once."""
118
- for key, value in other.items():
119
- setattr(self, key, value)
120
-
121
- @classmethod
122
- def model_from_dict(cls: type["FastModel[T]"], d: dict[str, Any]) -> "FastModel[T]":
123
- return cls(**d)
124
-
125
- @classmethod
126
- def model_attr_has_default_value(cls: type["FastModel[T]"], attr_name: str) -> bool:
127
- return hasattr(cls, attr_name) and not callable(getattr(cls, attr_name))
128
-
129
- @classmethod
130
- def model_get_attr_default_value(cls: type["FastModel[T]"], attr_name: str) -> Any:
131
- if cls.model_attr_has_default_value(attr_name):
132
- return getattr(cls, attr_name)
133
- else:
134
- return None
135
-
136
- @classmethod
137
- def model_attr_type(cls: type["FastModel[T]"], attr_name: str) -> type:
138
- return cls.model_attr_types()[attr_name]
139
-
140
- @classmethod
141
- def model_attr_types(cls: type["FastModel[T]"]) -> dict[str, type]:
142
- return cls.__annotations__ if hasattr(cls, "__annotations__") else {}
143
-
144
- @classmethod
145
- def model_attr_names(cls: type["FastModel[T]"]) -> List[str]:
146
- """
147
- Returns annotated attribute names
148
- :return: List[str]
149
- """
150
- return [k for k, v in cls.model_attr_types().items()]
151
-
152
- @classmethod
153
- def model_has_attr(cls: type["FastModel[T]"], attr_name: str) -> bool:
154
- """
155
- Returns True if class have an annotated attribute
156
- :param attr_name: Attribute name
157
- :return: bool
158
- """
159
- return bool(cls.model_attr_types().get(attr_name))
160
-
161
- def model_set_default(self: "FastModel[T]", attr_name: str) -> None:
162
- if self.model_attr_has_default_value(attr_name):
163
- attr_default_value: Any = self.model_get_attr_default_value(attr_name)
164
- setattr(self, attr_name, attr_default_value)
165
-
166
- def model_get_constructor(
167
- self: "FastModel[T]", attr_name: str, value: Any
168
- ) -> Tuple[Optional[Callable[..., Any]], Optional[type]]:
169
- """
170
- This method is used for type conversion.
171
- FastModel uses this method to get the type of a value, then based on the
172
- value, it return a constructor. If the type of a value is 'float' then
173
- it returns 'float' since 'float' is also a constructor to build a float
174
- value.
175
- """
176
- attr_type1: type = self.model_attr_type(attr_name)
177
- constructor: Optional[Callable[..., Any]] = None
178
- element_type: Optional[type] = None
179
-
180
- if attr_type1 == float:
181
- constructor = float
182
- elif attr_type1 == str:
183
- constructor = str
184
- elif attr_type1 == int:
185
- constructor = int
186
- elif attr_type1 == list:
187
- constructor = list
188
- elif isinstance(value, FastModel):
189
- constructor = attr_type1.model_from_dict
190
- elif attr_type1 is Any:
191
- constructor = None
192
- elif isinstance(value, dict):
193
- if attr_type1 == dict:
194
- constructor = FastModel.model_from_dict
195
- elif issubclass(attr_type1, FastModel):
196
- constructor = self.model_attr_type(attr_name).model_from_dict
197
- elif attr_type1 is List:
198
- constructor = list
199
- elif hasattr(attr_type1, "__origin__"):
200
- if attr_type1.__dict__["__origin__"] is list:
201
- # if the type is 'List[something]'
202
- if len(attr_type1.__args__) == 0:
203
- constructor = list
204
- elif len(attr_type1.__args__) == 1:
205
- constructor = List
206
- element_type = attr_type1.__args__[0]
207
- elif len(attr_type1.__args__) > 1:
208
- raise TypeError("Only one dimensional List is supported")
209
- elif attr_type1.__dict__["__origin__"] is tuple:
210
- # if the type is 'Tuple[something]'
211
- constructor = tuple
212
-
213
- return constructor, element_type
214
-
215
- def model_set_attribute(self: "FastModel[T]", attr_name: str, value: Any) -> None:
216
- element_type: Optional[type] = None
217
-
218
- # Check for reserved dict keys (restored from original FastModel)
219
- dict_reserved_keys = vars(dict).keys()
220
- if attr_name in dict_reserved_keys:
221
- raise TypeError("You cannot set a reserved name as attribute")
222
-
223
- if self.model_has_attr(attr_name):
224
- if value is None:
225
- setattr(self, attr_name, None)
226
- elif self.model_attr_type(attr_name) == Any:
227
- setattr(self, attr_name, value)
228
- else:
229
- constructor, element_type = self.model_get_constructor(attr_name, value)
230
- if constructor is None:
231
- setattr(self, attr_name, value)
232
- elif constructor == List:
233
- # NOTE: fix typing
234
- value_list: List[Any] = value
235
- new_list: List[Any] = []
236
-
237
- if element_type and issubclass(element_type, FastModel):
238
- element_constructor: Callable[[Any], Any] = (
239
- element_type.model_from_dict
240
- )
241
- else:
242
- element_constructor = (
243
- element_type if element_type else lambda x: x
244
- )
245
-
246
- for v in value_list:
247
- new_list.append(element_constructor(v))
248
- setattr(self, attr_name, new_list)
249
- elif constructor == list:
250
- setattr(self, attr_name, list(value))
251
- else:
252
- setattr(self, attr_name, constructor(value))
253
- else:
254
- if isinstance(value, dict):
255
- if isinstance(value, FastModel):
256
- constructor: Callable[[Any], Any] = value.model_from_dict
257
- else:
258
- constructor = FastModel.model_from_dict
259
- setattr(self, attr_name, constructor(value))
260
- else:
261
- setattr(self, attr_name, value)
262
-
263
- def model_set_attributes(self: "FastModel[T]", **d: Any) -> None:
264
- for k, v in d.items():
265
- self.model_set_attribute(k, v)
266
-
267
- def __getattr__(self: "FastModel[T]", item: str) -> T:
268
- """Handle missing attribute access like the original FastModel."""
269
- # Avoid infinite recursion by checking the actual object dict and model fields
270
- if item in self.__class__.model_fields or item in self.__dict__:
271
- return getattr(self, item)
272
-
273
- raise AttributeError(
274
- f"{type(self).__name__!r} object has no attribute {item!r}"
275
- )
276
-
277
- def to_dict(
278
- self: "FastModel[T]",
279
- *args: Any,
280
- exclude: Optional[List[str]] = None,
281
- is_recursive: bool = False,
282
- exclude_none: bool = False,
283
- exclude_none_in_lists: bool = False,
284
- **kwargs: Any,
285
- ) -> dict[str, T]:
286
- """Convert to dictionary with various options."""
287
- exclude_set: Set[str] = set(exclude) if exclude is not None else set()
288
- ret: dict[str, T] = {}
289
-
290
- for k in self.keys():
291
- if k in exclude_set:
292
- continue
293
-
294
- v = getattr(self, k)
295
-
296
- if exclude_none and v is None:
297
- continue
298
-
299
- if is_recursive and isinstance(v, FastModel):
300
- ret[k] = v.to_dict(
301
- is_recursive=is_recursive,
302
- exclude_none=exclude_none,
303
- exclude_none_in_lists=exclude_none_in_lists,
304
- )
305
- elif exclude_none_in_lists and isinstance(v, list):
306
- ret[k] = [
307
- item.to_dict(exclude_none=True, is_recursive=is_recursive)
308
- if isinstance(item, FastModel)
309
- else item
310
- for item in v
311
- ]
312
- else:
313
- ret[k] = v
314
-
315
- return ret
316
-
317
- def model_to_dataclass(self) -> dataclass:
318
- return dataclass(**self.model_dump())
@@ -1,176 +0,0 @@
1
- """hammad.pydantic.models.function_model"""
2
-
3
- from typing import Any, Callable, Dict, List, Optional, TypeVar, Generic, cast
4
- from pydantic import BaseModel
5
- import inspect
6
- from typing import get_type_hints
7
-
8
- try:
9
- from typing import ParamSpec
10
- except ImportError:
11
- from typing_extensions import ParamSpec
12
-
13
- __all__ = ("FunctionModel",)
14
-
15
- P = ParamSpec("P")
16
- R = TypeVar("R")
17
-
18
-
19
- class FunctionModel(BaseModel, Generic[P, R]):
20
- """
21
- A specialized pydantic model that acts as a "passthrough" for functions,
22
- allowing for partial function application.
23
-
24
- ```python
25
- from cursives.pydantic.models import FunctionModel
26
-
27
- @FunctionModel(exclude = ["y"])
28
- def some_function(x: int, y: str = "1") -> int:
29
- return x + len(y)
30
-
31
- print(some_function.call(x=1))
32
- >>> 2
33
-
34
- print(some_function.function_schema())
35
- # Create OpenAI compatible function schema easily!
36
- >>> {
37
- ... "name": "some_function",
38
- ... "parameters": {
39
- ... "x": {"type": "integer"},
40
- ... "y": {"type": "string", "default": "1"}
41
- ... }
42
- ... }
43
-
44
- print(some_function.call_from_dict(...))
45
- """
46
-
47
- def __init__(self, exclude: Optional[List[str]] = None, **kwargs):
48
- super().__init__(**kwargs)
49
- self._exclude = exclude or []
50
- self._original_function: Optional[Callable[P, R]] = None
51
- self._function_name: Optional[str] = None
52
- self._signature: Optional[inspect.Signature] = None
53
- self._type_hints: Optional[Dict[str, Any]] = None
54
-
55
- def __call__(
56
- self, func: Callable[P, R], exclude: Optional[List[str]] = None
57
- ) -> "FunctionModel[P, R]":
58
- """Make this work as a decorator."""
59
- self._original_function = func
60
- self._function_name = func.__name__
61
- self._signature = inspect.signature(func)
62
- self._type_hints = get_type_hints(func)
63
-
64
- # Create a new instance that wraps the function
65
- # Use exclude parameter if provided, otherwise use self._exclude
66
- final_exclude = exclude if exclude is not None else self._exclude
67
- wrapped: FunctionModel[P, R] = FunctionModel(exclude=final_exclude)
68
- wrapped._original_function = func
69
- wrapped._function_name = func.__name__
70
- wrapped._signature = self._signature
71
- wrapped._type_hints = self._type_hints
72
-
73
- return wrapped
74
-
75
- def call(self, **kwargs) -> R:
76
- """Call the wrapped function with provided arguments."""
77
- if not self._original_function:
78
- raise ValueError("No function wrapped. Use as decorator first.")
79
-
80
- # Get all parameters from signature
81
- sig_params = self._signature.parameters
82
- final_kwargs = {}
83
-
84
- # Add provided kwargs (but not excluded ones)
85
- for key, value in kwargs.items():
86
- if key in sig_params and key not in self._exclude:
87
- final_kwargs[key] = value
88
-
89
- # Add defaults for missing parameters (except excluded ones)
90
- for param_name, param in sig_params.items():
91
- if param_name not in final_kwargs and param_name not in self._exclude:
92
- if param.default is not inspect.Parameter.empty:
93
- final_kwargs[param_name] = param.default
94
-
95
- return self._original_function(**final_kwargs)
96
-
97
- def call_from_dict(self, data: Dict[str, Any]) -> R:
98
- """Call the function using a dictionary of arguments."""
99
- return self.call(**data)
100
-
101
- def function_schema(self) -> Dict[str, Any]:
102
- """Generate OpenAI-compatible function schema."""
103
- if not self._original_function:
104
- raise ValueError("No function wrapped. Use as decorator first.")
105
-
106
- schema = {
107
- "name": self._function_name,
108
- "description": self._original_function.__doc__ or "",
109
- "parameters": {"type": "object", "properties": {}, "required": []},
110
- }
111
-
112
- # Process each parameter
113
- for param_name, param in self._signature.parameters.items():
114
- if param_name in self._exclude:
115
- continue
116
-
117
- param_type = self._type_hints.get(param_name, Any)
118
-
119
- # Convert Python types to JSON schema types
120
- json_type = self._python_type_to_json_schema(param_type)
121
-
122
- param_schema = {"type": json_type}
123
-
124
- # Add default if present
125
- if param.default is not inspect.Parameter.empty:
126
- param_schema["default"] = param.default
127
- else:
128
- schema["parameters"]["required"].append(param_name)
129
-
130
- schema["parameters"]["properties"][param_name] = param_schema
131
-
132
- return schema
133
-
134
- def _python_type_to_json_schema(self, python_type: Any) -> str:
135
- """Convert Python type to JSON schema type string."""
136
- if python_type is int:
137
- return "integer"
138
- elif python_type is float:
139
- return "number"
140
- elif python_type is str:
141
- return "string"
142
- elif python_type is bool:
143
- return "boolean"
144
- elif python_type is list or python_type is List:
145
- return "array"
146
- elif python_type is dict or python_type is Dict:
147
- return "object"
148
- else:
149
- return "string" # Default fallback
150
-
151
- def partial(self, **kwargs) -> "FunctionModel":
152
- """Create a new FunctionModel with some arguments pre-filled."""
153
- if not self._original_function:
154
- raise ValueError("No function wrapped. Use as decorator first.")
155
-
156
- def partial_func(**additional_kwargs):
157
- combined_kwargs = {**kwargs, **additional_kwargs}
158
- return self.call(**combined_kwargs)
159
-
160
- # Create new wrapped function
161
- new_wrapped = FunctionModel(exclude=self._exclude)
162
- new_wrapped._original_function = partial_func
163
- new_wrapped._function_name = f"{self._function_name}_partial"
164
-
165
- # Update signature to remove pre-filled parameters
166
- new_params = []
167
- for param_name, param in self._signature.parameters.items():
168
- if param_name not in kwargs:
169
- new_params.append(param)
170
-
171
- new_wrapped._signature = inspect.Signature(new_params)
172
- new_wrapped._type_hints = {
173
- k: v for k, v in self._type_hints.items() if k not in kwargs
174
- }
175
-
176
- return new_wrapped
@@ -1,63 +0,0 @@
1
- """hammad.pydantic.models.subscriptable_model"""
2
-
3
- from pydantic import BaseModel
4
- from typing import Any
5
-
6
- __all__ = ("SubscriptableModel",)
7
-
8
-
9
- class SubscriptableModel(BaseModel):
10
- """
11
- A pydantic model that allows for dict-like access to its fields.
12
- """
13
-
14
- def __getitem__(self, key: str) -> Any:
15
- """Get field value using dict-like access.
16
-
17
- Usage:
18
- >>> msg = Message(role='user')
19
- >>> msg['role']
20
- 'user'
21
- """
22
- if hasattr(self, key):
23
- return getattr(self, key)
24
- raise KeyError(key)
25
-
26
- def __setitem__(self, key: str, value: Any) -> None:
27
- """Set field value using dict-like access.
28
-
29
- Usage:
30
- >>> msg = Message(role='user')
31
- >>> msg['role'] = 'assistant'
32
- >>> msg['role']
33
- 'assistant'
34
- """
35
- setattr(self, key, value)
36
-
37
- def __contains__(self, key: str) -> bool:
38
- """Check if field exists using 'in' operator.
39
-
40
- Usage:
41
- >>> msg = Message(role='user')
42
- >>> 'role' in msg
43
- True
44
- >>> 'nonexistent' in msg
45
- False
46
- """
47
- if hasattr(self, key):
48
- return True
49
- if value := self.__class__.model_fields.get(key):
50
- return value.default is not None
51
- return False
52
-
53
- def get(self, key: str, default: Any = None) -> Any:
54
- """Get field value with optional default.
55
-
56
- Usage:
57
- >>> msg = Message(role='user')
58
- >>> msg.get('role')
59
- 'user'
60
- >>> msg.get('nonexistent', 'default')
61
- 'default'
62
- """
63
- return getattr(self, key) if hasattr(self, key) else default