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,596 +0,0 @@
1
- """hammad.data.collections.vector_collection"""
2
-
3
- import uuid
4
- from typing import Any, Dict, Optional, List, Generic, Union, Callable
5
- from datetime import datetime, timezone, timedelta
6
-
7
- try:
8
- from qdrant_client import QdrantClient
9
- from qdrant_client.models import (
10
- Distance,
11
- VectorParams,
12
- PointStruct,
13
- Filter,
14
- FieldCondition,
15
- MatchValue,
16
- SearchRequest,
17
- QueryResponse,
18
- )
19
- import numpy as np
20
- except ImportError as e:
21
- raise ImportError(
22
- "qdrant-client is required for VectorCollection. "
23
- "Install with: pip install qdrant-client"
24
- "Or install the the `ai` extra: `pip install hammad-python[ai]`"
25
- ) from e
26
-
27
- from .base_collection import BaseCollection, Object, Filters, Schema
28
- from ...ai.embeddings.create import (
29
- create_embeddings,
30
- )
31
-
32
- __all__ = ("VectorCollection",)
33
-
34
-
35
- class VectorCollection(BaseCollection, Generic[Object]):
36
- """
37
- Vector collection class that uses Qdrant for vector storage and similarity search.
38
-
39
- This provides vector-based functionality for storing embeddings and performing
40
- semantic similarity searches.
41
- """
42
-
43
- # Namespace UUID for generating deterministic UUIDs from string IDs
44
- _NAMESPACE_UUID = uuid.UUID("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
45
-
46
- def __init__(
47
- self,
48
- name: str,
49
- vector_size: int,
50
- schema: Optional[Schema] = None,
51
- default_ttl: Optional[int] = None,
52
- storage_backend: Optional[Any] = None,
53
- distance_metric: Distance = Distance.DOT,
54
- qdrant_config: Optional[Dict[str, Any]] = None,
55
- embedding_function: Optional[Callable[[Any], List[float]]] = None,
56
- model: Optional[str] = None,
57
- # Common embedding parameters
58
- format: bool = False,
59
- # LiteLLM parameters
60
- dimensions: Optional[int] = None,
61
- encoding_format: Optional[str] = None,
62
- timeout: Optional[int] = None,
63
- api_base: Optional[str] = None,
64
- api_version: Optional[str] = None,
65
- api_key: Optional[str] = None,
66
- api_type: Optional[str] = None,
67
- caching: bool = False,
68
- user: Optional[str] = None,
69
- # FastEmbed parameters
70
- parallel: Optional[int] = None,
71
- batch_size: Optional[int] = None,
72
- ):
73
- """
74
- Initialize a vector collection.
75
-
76
- Args:
77
- name: The name of the collection
78
- vector_size: Size/dimension of the vectors to store
79
- schema: Optional schema for type validation
80
- default_ttl: Default TTL for items in seconds
81
- storage_backend: Optional storage backend (Database instance or custom)
82
- distance_metric: Distance metric for similarity search (COSINE, DOT, EUCLID, MANHATTAN)
83
- qdrant_config: Optional Qdrant configuration
84
- Example: {
85
- "path": "/path/to/db", # For persistent storage
86
- "host": "localhost", # For remote Qdrant
87
- "port": 6333,
88
- "grpc_port": 6334,
89
- "prefer_grpc": True,
90
- "api_key": "your-api-key"
91
- }
92
- embedding_function: Optional function to convert objects to vectors
93
- model: Optional model name (e.g., 'fastembed/BAAI/bge-small-en-v1.5', 'openai/text-embedding-3-small')
94
- format: Whether to format each non-string input as a markdown string
95
-
96
- # LiteLLM-specific parameters:
97
- dimensions: The dimensions of the embedding
98
- encoding_format: The encoding format of the embedding (e.g. "float", "base64")
99
- timeout: The timeout for the embedding request
100
- api_base: The base URL for the embedding API
101
- api_version: The version of the embedding API
102
- api_key: The API key for the embedding API
103
- api_type: The type of the embedding API
104
- caching: Whether to cache the embedding
105
- user: The user for the embedding
106
-
107
- # FastEmbed-specific parameters:
108
- parallel: The number of parallel processes to use for the embedding
109
- batch_size: The batch size to use for the embedding
110
- """
111
- self.name = name
112
- self.vector_size = vector_size
113
- self.schema = schema
114
- self.default_ttl = default_ttl
115
- self.distance_metric = distance_metric
116
- self._storage_backend = storage_backend
117
- self._embedding_function = embedding_function
118
- self._model = model
119
-
120
- # Store embedding parameters
121
- self._embedding_params = {
122
- "format": format,
123
- # LiteLLM parameters
124
- "dimensions": dimensions,
125
- "encoding_format": encoding_format,
126
- "timeout": timeout,
127
- "api_base": api_base,
128
- "api_version": api_version,
129
- "api_key": api_key,
130
- "api_type": api_type,
131
- "caching": caching,
132
- "user": user,
133
- # FastEmbed parameters
134
- "parallel": parallel,
135
- "batch_size": batch_size,
136
- }
137
-
138
- # If model is provided, create embedding function
139
- if model:
140
- self._embedding_function = self._create_embedding_function(model)
141
-
142
- # Store qdrant configuration
143
- self._qdrant_config = qdrant_config or {}
144
-
145
- # In-memory storage when used independently
146
- self._items: Dict[str, Dict[str, Any]] = {}
147
-
148
- # Mapping from original IDs to UUIDs
149
- self._id_mapping: Dict[str, str] = {}
150
-
151
- # Initialize Qdrant client
152
- self._init_qdrant_client()
153
-
154
- def _create_embedding_function(
155
- self,
156
- model_name: str,
157
- ) -> Callable[[Any], List[float]]:
158
- """Create an embedding function from a model name."""
159
-
160
- def embedding_function(text: Any) -> List[float]:
161
- if not isinstance(text, str):
162
- text = str(text)
163
-
164
- # Filter out None values from embedding parameters
165
- embedding_kwargs = {
166
- k: v for k, v in self._embedding_params.items() if v is not None
167
- }
168
- embedding_kwargs["model"] = model_name
169
- embedding_kwargs["input"] = text
170
-
171
- response = create_embeddings(**embedding_kwargs)
172
- return response.data[0].embedding
173
-
174
- return embedding_function
175
-
176
- def _init_qdrant_client(self):
177
- """Initialize the Qdrant client and collection."""
178
- config = self._qdrant_config
179
-
180
- if "path" in config:
181
- # Persistent local storage
182
- self._client = QdrantClient(path=config["path"])
183
- elif "host" in config:
184
- # Remote Qdrant server
185
- self._client = QdrantClient(
186
- host=config.get("host", "localhost"),
187
- port=config.get("port", 6333),
188
- grpc_port=config.get("grpc_port", 6334),
189
- prefer_grpc=config.get("prefer_grpc", False),
190
- api_key=config.get("api_key"),
191
- timeout=config.get("timeout"),
192
- )
193
- else:
194
- # In-memory database (default)
195
- self._client = QdrantClient(":memory:")
196
-
197
- # Create collection if it doesn't exist
198
- try:
199
- collections = self._client.get_collections()
200
- collection_names = [col.name for col in collections.collections]
201
-
202
- if self.name not in collection_names:
203
- self._client.create_collection(
204
- collection_name=self.name,
205
- vectors_config=VectorParams(
206
- size=self.vector_size, distance=self.distance_metric
207
- ),
208
- )
209
- except Exception as e:
210
- # Collection might already exist or other issue
211
- pass
212
-
213
- def _ensure_uuid(self, id_str: str) -> str:
214
- """Convert a string ID to a UUID string, or validate if already a UUID."""
215
- # Check if it's already a valid UUID
216
- try:
217
- uuid.UUID(id_str)
218
- return id_str
219
- except ValueError:
220
- # Not a valid UUID, create a deterministic one
221
- new_uuid = str(uuid.uuid5(self._NAMESPACE_UUID, id_str))
222
- self._id_mapping[id_str] = new_uuid
223
- return new_uuid
224
-
225
- def __repr__(self) -> str:
226
- item_count = len(self._items) if self._storage_backend is None else "managed"
227
- return f"<{self.__class__.__name__} name='{self.name}' vector_size={self.vector_size} items={item_count}>"
228
-
229
- def _calculate_expires_at(self, ttl: Optional[int]) -> Optional[datetime]:
230
- """Calculate expiry time based on TTL."""
231
- if ttl is None:
232
- ttl = self.default_ttl
233
- if ttl and ttl > 0:
234
- return datetime.now(timezone.utc) + timedelta(seconds=ttl)
235
- return None
236
-
237
- def _is_expired(self, expires_at: Optional[datetime]) -> bool:
238
- """Check if an item has expired."""
239
- if expires_at is None:
240
- return False
241
- now = datetime.now(timezone.utc)
242
- if expires_at.tzinfo is None:
243
- expires_at = expires_at.replace(tzinfo=timezone.utc)
244
- return now >= expires_at
245
-
246
- def _match_filters(
247
- self, stored: Optional[Filters], query: Optional[Filters]
248
- ) -> bool:
249
- """Check if stored filters match query filters."""
250
- if query is None:
251
- return True
252
- if stored is None:
253
- return False
254
- return all(stored.get(k) == v for k, v in query.items())
255
-
256
- def _prepare_vector(self, entry: Any) -> List[float]:
257
- """Prepare vector from entry using embedding function or direct vector."""
258
- if self._embedding_function:
259
- return self._embedding_function(entry)
260
- elif isinstance(entry, dict) and "vector" in entry:
261
- vector = entry["vector"]
262
- if isinstance(vector, np.ndarray):
263
- return vector.tolist()
264
- elif isinstance(vector, list):
265
- return vector
266
- else:
267
- raise ValueError("Vector must be a list or numpy array")
268
- elif isinstance(entry, (list, np.ndarray)):
269
- if isinstance(entry, np.ndarray):
270
- return entry.tolist()
271
- return entry
272
- else:
273
- raise ValueError(
274
- "Entry must contain 'vector' key, be a vector itself, "
275
- "or embedding_function must be provided"
276
- )
277
-
278
- def _build_qdrant_filter(self, filters: Optional[Filters]) -> Optional[Filter]:
279
- """Build Qdrant filter from filters dict."""
280
- if not filters:
281
- return None
282
-
283
- conditions = []
284
- for key, value in filters.items():
285
- conditions.append(FieldCondition(key=key, match=MatchValue(value=value)))
286
-
287
- if len(conditions) == 1:
288
- return Filter(must=[conditions[0]])
289
- else:
290
- return Filter(must=conditions)
291
-
292
- def get(self, id: str, *, filters: Optional[Filters] = None) -> Optional[Object]:
293
- """Get an item by ID."""
294
- if self._storage_backend is not None:
295
- # Delegate to storage backend (Database instance)
296
- return self._storage_backend.get(id, collection=self.name, filters=filters)
297
-
298
- # Convert ID to UUID if needed
299
- uuid_id = self._ensure_uuid(id)
300
-
301
- # Independent operation
302
- try:
303
- points = self._client.retrieve(
304
- collection_name=self.name,
305
- ids=[uuid_id],
306
- with_payload=True,
307
- with_vectors=False,
308
- )
309
-
310
- if not points:
311
- return None
312
-
313
- point = points[0]
314
- payload = point.payload or {}
315
-
316
- # Check expiration
317
- expires_at_str = payload.get("expires_at")
318
- if expires_at_str:
319
- expires_at = datetime.fromisoformat(expires_at_str)
320
- if self._is_expired(expires_at):
321
- # Delete expired item
322
- self._client.delete(
323
- collection_name=self.name, points_selector=[uuid_id]
324
- )
325
- return None
326
-
327
- # Check filters - they are stored as top-level fields in payload
328
- if filters:
329
- for key, value in filters.items():
330
- if payload.get(key) != value:
331
- return None
332
-
333
- return payload.get("value")
334
-
335
- except Exception:
336
- return None
337
-
338
- def add(
339
- self,
340
- entry: Object,
341
- id: Optional[str] = None,
342
- *,
343
- filters: Optional[Filters] = None,
344
- ttl: Optional[int] = None,
345
- ) -> str:
346
- """Add an item to the collection.
347
-
348
- Args:
349
- entry: The object/data to store
350
- id: Optional ID for the item (will generate UUID if not provided)
351
- filters: Optional metadata filters
352
- ttl: Time-to-live in seconds
353
-
354
- Returns:
355
- The ID of the added item
356
- """
357
- if self._storage_backend is not None:
358
- # Delegate to storage backend
359
- self._storage_backend.add(
360
- entry, id=id, collection=self.name, filters=filters, ttl=ttl
361
- )
362
- return id or str(uuid.uuid4())
363
-
364
- # Independent operation
365
- item_id = id or str(uuid.uuid4())
366
- # Convert to UUID if needed
367
- uuid_id = self._ensure_uuid(item_id)
368
-
369
- expires_at = self._calculate_expires_at(ttl)
370
- created_at = datetime.now(timezone.utc)
371
-
372
- # Prepare vector
373
- vector = self._prepare_vector(entry)
374
-
375
- if len(vector) != self.vector_size:
376
- raise ValueError(
377
- f"Vector size {len(vector)} doesn't match collection size {self.vector_size}"
378
- )
379
-
380
- # Prepare payload - store original ID if converted
381
- payload = {
382
- "value": entry,
383
- "created_at": created_at.isoformat(),
384
- "updated_at": created_at.isoformat(),
385
- }
386
-
387
- # Add filter fields as top-level payload fields
388
- if filters:
389
- for key, value in filters.items():
390
- payload[key] = value
391
-
392
- # Store original ID if it was converted
393
- if item_id != uuid_id:
394
- payload["original_id"] = item_id
395
-
396
- if expires_at:
397
- payload["expires_at"] = expires_at.isoformat()
398
-
399
- # Store in memory with UUID
400
- self._items[uuid_id] = payload
401
-
402
- # Create point and upsert to Qdrant
403
- point = PointStruct(id=uuid_id, vector=vector, payload=payload)
404
-
405
- self._client.upsert(collection_name=self.name, points=[point])
406
-
407
- return item_id
408
-
409
- def query(
410
- self,
411
- query: Optional[str] = None,
412
- *,
413
- filters: Optional[Filters] = None,
414
- limit: Optional[int] = None,
415
- ) -> List[Object]:
416
- """Query items from the collection.
417
-
418
- Args:
419
- query: Search query string. If provided, performs semantic similarity search.
420
- filters: Optional filters to apply
421
- limit: Maximum number of results to return
422
- """
423
- if self._storage_backend is not None:
424
- return self._storage_backend.query(
425
- collection=self.name,
426
- filters=filters,
427
- search=query,
428
- limit=limit,
429
- )
430
-
431
- # For basic query without vector search, just return all items with filters
432
- if query is None:
433
- return self._query_all(filters=filters, limit=limit)
434
-
435
- # If search is provided but no embedding function, treat as error
436
- if self._embedding_function is None:
437
- raise ValueError(
438
- "Search query provided but no embedding_function configured. "
439
- "Use vector_search() for direct vector similarity search."
440
- )
441
-
442
- # Convert search to vector and perform similarity search
443
- query_vector = self._embedding_function(query)
444
- return self.vector_search(
445
- query_vector=query_vector, filters=filters, limit=limit
446
- )
447
-
448
- def _query_all(
449
- self,
450
- *,
451
- filters: Optional[Filters] = None,
452
- limit: Optional[int] = None,
453
- ) -> List[Object]:
454
- """Query all items with optional filters (no vector search)."""
455
- try:
456
- # Scroll through all points
457
- points, _ = self._client.scroll(
458
- collection_name=self.name,
459
- scroll_filter=self._build_qdrant_filter(filters),
460
- limit=limit or 100,
461
- with_payload=True,
462
- with_vectors=False,
463
- )
464
-
465
- results = []
466
- for point in points:
467
- payload = point.payload or {}
468
-
469
- # Check expiration
470
- expires_at_str = payload.get("expires_at")
471
- if expires_at_str:
472
- expires_at = datetime.fromisoformat(expires_at_str)
473
- if self._is_expired(expires_at):
474
- continue
475
-
476
- results.append(payload.get("value"))
477
-
478
- return results
479
-
480
- except Exception:
481
- return []
482
-
483
- def vector_search(
484
- self,
485
- query_vector: Union[List[float], np.ndarray],
486
- *,
487
- filters: Optional[Filters] = None,
488
- limit: int = 10,
489
- score_threshold: Optional[float] = None,
490
- ) -> List[Object]:
491
- """
492
- Perform vector similarity search.
493
-
494
- Args:
495
- query_vector: Query vector for similarity search
496
- filters: Optional filters to apply
497
- limit: Maximum number of results to return (default: 10)
498
- score_threshold: Minimum similarity score threshold
499
-
500
- Returns:
501
- List of matching objects sorted by similarity score
502
- """
503
- if isinstance(query_vector, np.ndarray):
504
- query_vector = query_vector.tolist()
505
-
506
- if len(query_vector) != self.vector_size:
507
- raise ValueError(
508
- f"Query vector size {len(query_vector)} doesn't match collection size {self.vector_size}"
509
- )
510
-
511
- try:
512
- results = self._client.query_points(
513
- collection_name=self.name,
514
- query=query_vector,
515
- query_filter=self._build_qdrant_filter(filters),
516
- limit=limit,
517
- score_threshold=score_threshold,
518
- with_payload=True,
519
- with_vectors=False,
520
- )
521
-
522
- matches = []
523
- for result in results.points:
524
- payload = result.payload or {}
525
-
526
- # Check expiration
527
- expires_at_str = payload.get("expires_at")
528
- if expires_at_str:
529
- expires_at = datetime.fromisoformat(expires_at_str)
530
- if self._is_expired(expires_at):
531
- continue
532
-
533
- matches.append(payload.get("value"))
534
-
535
- return matches
536
-
537
- except Exception:
538
- return []
539
-
540
- def get_vector(self, id: str) -> Optional[List[float]]:
541
- """Get the vector for a specific item by ID."""
542
- # Convert ID to UUID if needed
543
- uuid_id = self._ensure_uuid(id)
544
-
545
- try:
546
- points = self._client.retrieve(
547
- collection_name=self.name,
548
- ids=[uuid_id],
549
- with_payload=False,
550
- with_vectors=True,
551
- )
552
-
553
- if not points:
554
- return None
555
-
556
- vector = points[0].vector
557
- if isinstance(vector, dict):
558
- # Handle named vectors if used
559
- return list(vector.values())[0] if vector else None
560
- return vector
561
-
562
- except Exception:
563
- return None
564
-
565
- def delete(self, id: str) -> bool:
566
- """Delete an item by ID."""
567
- # Convert ID to UUID if needed
568
- uuid_id = self._ensure_uuid(id)
569
-
570
- try:
571
- self._client.delete(collection_name=self.name, points_selector=[uuid_id])
572
- # Remove from in-memory storage if exists
573
- self._items.pop(uuid_id, None)
574
- return True
575
- except Exception:
576
- return False
577
-
578
- def count(self, *, filters: Optional[Filters] = None) -> int:
579
- """Count items in the collection."""
580
- try:
581
- info = self._client.count(
582
- collection_name=self.name,
583
- count_filter=self._build_qdrant_filter(filters),
584
- exact=True,
585
- )
586
- return info.count
587
- except Exception:
588
- return 0
589
-
590
- def attach_to_database(self, database: Any) -> None:
591
- """Attach this collection to a database instance."""
592
- self._storage_backend = database
593
- # Ensure the collection exists in the database
594
- database.create_collection(
595
- self.name, schema=self.schema, default_ttl=self.default_ttl
596
- )
@@ -1,35 +0,0 @@
1
- """hammad.configuration
2
-
3
- Contains the `Configuration` class and related functions for parsing configurations
4
- from various sources.
5
- """
6
-
7
- from typing import TYPE_CHECKING
8
- from ...performance.imports import create_getattr_importer
9
-
10
- if TYPE_CHECKING:
11
- from .configuration import (
12
- Configuration,
13
- read_configuration_from_file,
14
- read_configuration_from_url,
15
- read_configuration_from_os_vars,
16
- read_configuration_from_os_prefix,
17
- read_configuration_from_dotenv,
18
- )
19
-
20
-
21
- __all__ = (
22
- "Configuration",
23
- "read_configuration_from_file",
24
- "read_configuration_from_url",
25
- "read_configuration_from_os_vars",
26
- "read_configuration_from_os_prefix",
27
- "read_configuration_from_dotenv",
28
- )
29
-
30
-
31
- __getattr__ = create_getattr_importer(__all__)
32
-
33
-
34
- def __dir__() -> list[str]:
35
- return list(__all__)