mindtrace-database 0.10.0__tar.gz → 0.11.0__tar.gz

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 (18) hide show
  1. {mindtrace_database-0.10.0 → mindtrace_database-0.11.0}/PKG-INFO +3 -3
  2. {mindtrace_database-0.10.0 → mindtrace_database-0.11.0}/mindtrace/database/backends/mongo_odm.py +293 -7
  3. {mindtrace_database-0.10.0 → mindtrace_database-0.11.0}/mindtrace/database/backends/unified_odm.py +22 -0
  4. {mindtrace_database-0.10.0 → mindtrace_database-0.11.0}/mindtrace_database.egg-info/PKG-INFO +3 -3
  5. {mindtrace_database-0.10.0 → mindtrace_database-0.11.0}/mindtrace_database.egg-info/requires.txt +2 -2
  6. {mindtrace_database-0.10.0 → mindtrace_database-0.11.0}/pyproject.toml +3 -3
  7. {mindtrace_database-0.10.0 → mindtrace_database-0.11.0}/LICENSE +0 -0
  8. {mindtrace_database-0.10.0 → mindtrace_database-0.11.0}/README.md +0 -0
  9. {mindtrace_database-0.10.0 → mindtrace_database-0.11.0}/mindtrace/database/__init__.py +0 -0
  10. {mindtrace_database-0.10.0 → mindtrace_database-0.11.0}/mindtrace/database/backends/mindtrace_odm.py +0 -0
  11. {mindtrace_database-0.10.0 → mindtrace_database-0.11.0}/mindtrace/database/backends/redis_odm.py +0 -0
  12. {mindtrace_database-0.10.0 → mindtrace_database-0.11.0}/mindtrace/database/backends/registry_odm.py +0 -0
  13. {mindtrace_database-0.10.0 → mindtrace_database-0.11.0}/mindtrace/database/core/exceptions.py +0 -0
  14. {mindtrace_database-0.10.0 → mindtrace_database-0.11.0}/mindtrace/database/sample/user.py +0 -0
  15. {mindtrace_database-0.10.0 → mindtrace_database-0.11.0}/mindtrace_database.egg-info/SOURCES.txt +0 -0
  16. {mindtrace_database-0.10.0 → mindtrace_database-0.11.0}/mindtrace_database.egg-info/dependency_links.txt +0 -0
  17. {mindtrace_database-0.10.0 → mindtrace_database-0.11.0}/mindtrace_database.egg-info/top_level.txt +0 -0
  18. {mindtrace_database-0.10.0 → mindtrace_database-0.11.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mindtrace-database
3
- Version: 0.10.0
3
+ Version: 0.11.0
4
4
  Summary: Database functionality for Mindtrace
5
5
  Author: Mindtrace Team
6
6
  License-Expression: Apache-2.0
@@ -11,13 +11,13 @@ Classifier: Programming Language :: Python :: 3.12
11
11
  Description-Content-Type: text/markdown
12
12
  License-File: LICENSE
13
13
  Requires-Dist: beanie<2,>=1.29.0
14
- Requires-Dist: mindtrace-core>=0.10.0
14
+ Requires-Dist: mindtrace-core>=0.11.0
15
15
  Requires-Dist: pydantic>=2.11.1
16
16
  Requires-Dist: redis>=4.0.0
17
17
  Requires-Dist: redis-om>=0.3.5
18
18
  Requires-Dist: motor>=3.3.0
19
19
  Requires-Dist: pymongo>=4.14.0
20
- Requires-Dist: mindtrace-registry>=0.10.0
20
+ Requires-Dist: mindtrace-registry>=0.11.0
21
21
  Dynamic: license-file
22
22
 
23
23
  [![PyPI version](https://img.shields.io/pypi/v/mindtrace-database)](https://pypi.org/project/mindtrace-database/)
@@ -1,9 +1,14 @@
1
1
  import asyncio
2
- from typing import Dict, List, Optional, Type, TypeVar
2
+ from collections.abc import AsyncIterator, Iterator
3
+ from typing import Any, Dict, List, Optional, Type, TypeVar
3
4
 
4
5
  from beanie import Document, PydanticObjectId, init_beanie
6
+ from beanie.odm.utils.dump import get_dict
7
+ from bson import ObjectId
8
+ from bson.errors import InvalidId
5
9
  from motor.motor_asyncio import AsyncIOMotorClient
6
10
  from pydantic import BaseModel
11
+ from pymongo import MongoClient
7
12
  from pymongo.errors import DuplicateKeyError
8
13
 
9
14
  from mindtrace.database.backends.mindtrace_odm import InitMode, MindtraceODM
@@ -44,6 +49,12 @@ class MindtraceDocument(Document):
44
49
 
45
50
  ModelType = TypeVar("ModelType", bound=MindtraceDocument)
46
51
 
52
+ # Beanie binds each Document class to one database *process-wide*. A second ``init_beanie`` for the same
53
+ # ``model_cls`` (whether another ``db_name``, another URI, or another ``MongoMindtraceODM`` instance)
54
+ # would re-bind that class and break earlier lakes. Only the first ODM per ``model_cls`` runs
55
+ # ``init_beanie``; subsequent backends set ``_motor_routing`` and use Motor on ``self.client[self.db_name]``.
56
+ _BEANIE_INITIALIZED_MODEL_CLASSES: set[Type[Any]] = set()
57
+
47
58
 
48
59
  class MongoMindtraceODM[T: MindtraceDocument](MindtraceODM):
49
60
  """
@@ -87,6 +98,8 @@ class MongoMindtraceODM[T: MindtraceDocument](MindtraceODM):
87
98
  allow_index_dropping: bool = False,
88
99
  auto_init: bool = False,
89
100
  init_mode: InitMode | None = None,
101
+ *,
102
+ client: AsyncIOMotorClient | None = None,
90
103
  ):
91
104
  """
92
105
  Initialize the MongoDB ODM backend.
@@ -127,8 +140,17 @@ class MongoMindtraceODM[T: MindtraceDocument](MindtraceODM):
127
140
  if not db_uri or not db_name:
128
141
  raise ValueError("db_uri and db_name are required")
129
142
 
130
- self.client = AsyncIOMotorClient(db_uri)
143
+ self.db_uri = db_uri
144
+ if client is not None:
145
+ self.client = client
146
+ self._owns_client = False
147
+ else:
148
+ self.client = AsyncIOMotorClient(db_uri)
149
+ self._owns_client = True
150
+ self._sync_client: MongoClient | None = None
151
+ self._closed = False
131
152
  self.db_name = db_name
153
+ self._motor_routing = False
132
154
  self._allow_index_dropping = allow_index_dropping
133
155
  self._is_initialized = False
134
156
  self._model_odms: Dict[str, "MongoMindtraceODM"] = {}
@@ -152,9 +174,8 @@ class MongoMindtraceODM[T: MindtraceDocument](MindtraceODM):
152
174
  allow_index_dropping=allow_index_dropping,
153
175
  auto_init=False, # We'll initialize all together
154
176
  init_mode=init_mode,
177
+ client=self.client,
155
178
  )
156
- # Share the same client instance
157
- odm.client = self.client
158
179
  # Store parent reference for initialization delegation
159
180
  odm._parent_odm = self
160
181
  self._model_odms[name] = odm
@@ -192,6 +213,56 @@ class MongoMindtraceODM[T: MindtraceDocument](MindtraceODM):
192
213
  # Defer initialization - operations will auto-init on first use
193
214
  self._needs_init = True
194
215
 
216
+ def _collection_name(self) -> str:
217
+ if self.model_cls is None:
218
+ raise ValueError("model_cls is required for collection name resolution")
219
+ return getattr(self.model_cls.Settings, "name")
220
+
221
+ def _motor_collection(self):
222
+ return self.client[self.db_name][self._collection_name()]
223
+
224
+ def _sync_collection(self):
225
+ if self._sync_client is None:
226
+ self._sync_client = MongoClient(self.db_uri)
227
+ return self._sync_client[self.db_name][self._collection_name()]
228
+
229
+ def _mongo_doc_to_model(self, doc: dict | None) -> T | None:
230
+ if doc is None:
231
+ return None
232
+ payload = dict(doc)
233
+ if "_id" in payload and "id" not in payload:
234
+ payload["id"] = payload["_id"]
235
+ return self.model_cls.model_validate(payload)
236
+
237
+ def _motor_model_dump(self, doc: BaseModel) -> dict[str, Any]:
238
+ """Serialize a model for raw Motor insert/replace.
239
+
240
+ Pydantic v2 ``model_dump`` on Beanie ``Document`` can fail (class-level
241
+ descriptors such as ``ExpressionField``). Beanie's BSON ``get_dict`` matches
242
+ ``Document.insert`` and avoids that serializer path.
243
+ """
244
+ if isinstance(doc, Document):
245
+ return get_dict(doc, to_db=True, keep_nulls=doc.get_settings().keep_nulls)
246
+ return doc.model_dump(mode="python", by_alias=True, serialize_as_any=True)
247
+
248
+ def _motor_patch_fields(self, obj: BaseModel) -> dict[str, Any]:
249
+ """Shallow field map from ``obj`` for merge-into-document updates (Motor mode)."""
250
+ if isinstance(obj, Document):
251
+ return {name: getattr(obj, name) for name in obj.model_fields if name != "id"}
252
+ return obj.model_dump(exclude={"id"}, serialize_as_any=True)
253
+
254
+ @staticmethod
255
+ def _to_object_id(id: str | PydanticObjectId | ObjectId) -> ObjectId:
256
+ # ``PydanticObjectId`` subclasses ``ObjectId``; check it first so we normalize via ``str``.
257
+ if isinstance(id, PydanticObjectId):
258
+ return ObjectId(str(id))
259
+ if isinstance(id, ObjectId):
260
+ return id
261
+ try:
262
+ return ObjectId(str(id))
263
+ except InvalidId as exc:
264
+ raise DocumentNotFoundError(f"Invalid document id {id!r}") from exc
265
+
195
266
  async def _do_initialize(self):
196
267
  """Internal method to perform the actual initialization."""
197
268
  if not self._is_initialized:
@@ -199,7 +270,12 @@ class MongoMindtraceODM[T: MindtraceDocument](MindtraceODM):
199
270
  # Multi-model mode: initialize all models together
200
271
  document_models = list(self._models.values())
201
272
  else:
202
- # Single model mode
273
+ # Single model mode: at most one init_beanie per Document subclass in this process.
274
+ if self.model_cls in _BEANIE_INITIALIZED_MODEL_CLASSES:
275
+ self._motor_routing = True
276
+ self._is_initialized = True
277
+ return
278
+ _BEANIE_INITIALIZED_MODEL_CLASSES.add(self.model_cls)
203
279
  document_models = [self.model_cls]
204
280
 
205
281
  await init_beanie(
@@ -253,6 +329,31 @@ class MongoMindtraceODM[T: MindtraceDocument](MindtraceODM):
253
329
  self._allow_index_dropping = allow_index_dropping
254
330
  await self._do_initialize()
255
331
 
332
+ def close(self) -> None:
333
+ """Release resources held by this ODM.
334
+
335
+ Closes the lazily-created synchronous client if present, and closes
336
+ the owning motor client if this ODM created it. ODMs constructed with
337
+ an injected ``client=`` hold a non-owning reference and do not close
338
+ it on shutdown — responsibility stays with whoever created the client.
339
+
340
+ Idempotent: safe to call multiple times.
341
+ """
342
+ if self._closed:
343
+ return
344
+ if self._sync_client is not None:
345
+ try:
346
+ self._sync_client.close()
347
+ except Exception:
348
+ pass
349
+ self._sync_client = None
350
+ if self._owns_client and self.client is not None:
351
+ try:
352
+ self.client.close()
353
+ except Exception:
354
+ pass
355
+ self._closed = True
356
+
256
357
  def __getattr__(self, name: str):
257
358
  """Support attribute-based access to model-specific ODMs in multi-model mode.
258
359
 
@@ -340,11 +441,22 @@ class MongoMindtraceODM[T: MindtraceDocument](MindtraceODM):
340
441
  doc.id = None
341
442
 
342
443
  try:
444
+ if self._motor_routing:
445
+ raw = self._motor_model_dump(doc)
446
+ raw.pop("_id", None)
447
+ if raw.get("id") is None:
448
+ raw.pop("id", None)
449
+ result = await self._motor_collection().insert_one(raw)
450
+ inserted = await self._motor_collection().find_one({"_id": result.inserted_id})
451
+ if inserted is None:
452
+ raise DuplicateInsertError("insert_one did not persist a readable document")
453
+ out = self._mongo_doc_to_model(inserted)
454
+ if out is None:
455
+ raise DuplicateInsertError("Could not deserialize inserted document")
456
+ return out
343
457
  return await doc.insert()
344
458
  except DuplicateKeyError as e:
345
459
  raise DuplicateInsertError(f"Duplicate key error: {str(e)}")
346
- except Exception as e:
347
- raise DuplicateInsertError(str(e))
348
460
 
349
461
  async def get(self, id: str | PydanticObjectId, fetch_links: bool = False) -> T:
350
462
  """
@@ -381,6 +493,18 @@ class MongoMindtraceODM[T: MindtraceDocument](MindtraceODM):
381
493
  if not self._is_initialized:
382
494
  await self.initialize()
383
495
 
496
+ if self._motor_routing:
497
+ if fetch_links:
498
+ raise NotImplementedError("fetch_links is not supported for this database routing mode")
499
+ oid = self._to_object_id(id)
500
+ doc = await self._motor_collection().find_one({"_id": oid})
501
+ if not doc:
502
+ raise DocumentNotFoundError(f"Object with id {id} not found")
503
+ out = self._mongo_doc_to_model(doc)
504
+ if out is None:
505
+ raise DocumentNotFoundError(f"Object with id {id} not found")
506
+ return out
507
+
384
508
  doc = await self.model_cls.get(id, fetch_links=fetch_links)
385
509
  if not doc:
386
510
  raise DocumentNotFoundError(f"Object with id {id} not found")
@@ -421,6 +545,29 @@ class MongoMindtraceODM[T: MindtraceDocument](MindtraceODM):
421
545
  if not self._is_initialized:
422
546
  await self.initialize()
423
547
 
548
+ if self._motor_routing:
549
+ if isinstance(obj, self.model_cls):
550
+ if not obj.id:
551
+ raise DocumentNotFoundError("Document must have an id to be updated")
552
+ oid = self._to_object_id(obj.id)
553
+ raw = self._motor_model_dump(obj)
554
+ await self._motor_collection().replace_one({"_id": oid}, raw)
555
+ return obj
556
+ if not hasattr(obj, "id") or not obj.id:
557
+ raise DocumentNotFoundError("Document must have an id to be updated")
558
+ oid = self._to_object_id(obj.id)
559
+ existing = await self._motor_collection().find_one({"_id": oid})
560
+ if not existing:
561
+ raise DocumentNotFoundError(f"Object with id {obj.id} not found")
562
+ doc = self._mongo_doc_to_model(existing)
563
+ if doc is None:
564
+ raise DocumentNotFoundError(f"Object with id {obj.id} not found")
565
+ for key, value in self._motor_patch_fields(obj).items():
566
+ setattr(doc, key, value)
567
+ raw = self._motor_model_dump(doc)
568
+ await self._motor_collection().replace_one({"_id": oid}, raw)
569
+ return doc
570
+
424
571
  # Check if obj is already a document instance
425
572
  if isinstance(obj, self.model_cls):
426
573
  # If it's already a document instance, just save it
@@ -471,6 +618,13 @@ class MongoMindtraceODM[T: MindtraceDocument](MindtraceODM):
471
618
  if not self._is_initialized:
472
619
  await self.initialize()
473
620
 
621
+ if self._motor_routing:
622
+ oid = self._to_object_id(id)
623
+ result = await self._motor_collection().delete_one({"_id": oid})
624
+ if result.deleted_count == 0:
625
+ raise DocumentNotFoundError(f"Object with id {id} not found")
626
+ return
627
+
474
628
  doc = await self.model_cls.get(id)
475
629
  if doc:
476
630
  await doc.delete()
@@ -502,6 +656,10 @@ class MongoMindtraceODM[T: MindtraceDocument](MindtraceODM):
502
656
  if not self._is_initialized:
503
657
  await self.initialize()
504
658
 
659
+ if self._motor_routing:
660
+ raw = await self._motor_collection().find({}).to_list(length=None)
661
+ return [m for m in (self._mongo_doc_to_model(d) for d in raw) if m is not None]
662
+
505
663
  return await self.model_cls.find_all().to_list()
506
664
 
507
665
  async def find(self, *args, fetch_links: bool = False, **kwargs) -> List[T]:
@@ -541,10 +699,136 @@ class MongoMindtraceODM[T: MindtraceDocument](MindtraceODM):
541
699
  # Remove fetch_links from kwargs if present (it's a parameter, not a query field)
542
700
  kwargs_without_fetch_links = {k: v for k, v in kwargs.items() if k != "fetch_links"}
543
701
 
702
+ if self._motor_routing:
703
+ if fetch_links:
704
+ raise NotImplementedError("fetch_links is not supported for this database routing mode")
705
+ if len(args) != 1 or not isinstance(args[0], dict) or kwargs_without_fetch_links:
706
+ raise NotImplementedError(
707
+ "Only a single dict filter is supported for find() in this database routing mode"
708
+ )
709
+ raw = await self._motor_collection().find(args[0]).to_list(length=None)
710
+ return [m for m in (self._mongo_doc_to_model(d) for d in raw) if m is not None]
711
+
544
712
  # In Beanie, fetch_links is passed as a parameter to find(), not called as a method
545
713
  query = self.model_cls.find(*args, fetch_links=fetch_links, **kwargs_without_fetch_links)
546
714
  return await query.to_list()
547
715
 
716
+ async def find_iter(
717
+ self,
718
+ query: dict[str, Any] | None = None,
719
+ *,
720
+ sort: list[tuple[str, int]] | None = None,
721
+ batch_size: int | None = None,
722
+ limit: int | None = None,
723
+ ) -> AsyncIterator[T]:
724
+ """
725
+ Lazily iterate over matching documents using a Mongo cursor.
726
+
727
+ This is intended for large scans where materializing the full result set
728
+ would be wasteful.
729
+ """
730
+ if self._models is not None:
731
+ raise ValueError("Cannot use find_iter() in multi-model mode. Use db.model_name.find_iter() instead.")
732
+
733
+ if not self._is_initialized:
734
+ await self.initialize()
735
+
736
+ cursor = self._motor_collection().find(query or {})
737
+ if sort:
738
+ cursor = cursor.sort(sort)
739
+ if batch_size is not None:
740
+ cursor = cursor.batch_size(batch_size)
741
+ if limit is not None:
742
+ cursor = cursor.limit(limit)
743
+
744
+ try:
745
+ async for raw in cursor:
746
+ model = self._mongo_doc_to_model(raw)
747
+ if model is not None:
748
+ yield model
749
+ finally:
750
+ await cursor.close()
751
+
752
+ async def find_window(
753
+ self,
754
+ query: dict[str, Any] | None = None,
755
+ *,
756
+ sort: list[tuple[str, int]] | None = None,
757
+ limit: int | None = None,
758
+ ) -> List[T]:
759
+ """
760
+ Return a bounded, sorted window of matching documents.
761
+
762
+ This is useful for page-oriented callers that need ``limit + 1`` rows to
763
+ determine whether another page exists without loading the full collection.
764
+ """
765
+ if self._models is not None:
766
+ raise ValueError("Cannot use find_window() in multi-model mode. Use db.model_name.find_window() instead.")
767
+
768
+ if not self._is_initialized:
769
+ await self.initialize()
770
+
771
+ cursor = self._motor_collection().find(query or {})
772
+ if sort:
773
+ cursor = cursor.sort(sort)
774
+ raw = await cursor.to_list(length=limit)
775
+ return [m for m in (self._mongo_doc_to_model(d) for d in raw) if m is not None]
776
+
777
+ def find_iter_sync(
778
+ self,
779
+ query: dict[str, Any] | None = None,
780
+ *,
781
+ sort: list[tuple[str, int]] | None = None,
782
+ batch_size: int | None = None,
783
+ limit: int | None = None,
784
+ ) -> Iterator[T]:
785
+ """Lazily iterate over matching documents using a synchronous Mongo cursor."""
786
+ if self._models is not None:
787
+ raise ValueError(
788
+ "Cannot use find_iter_sync() in multi-model mode. Use db.model_name.find_iter_sync() instead."
789
+ )
790
+
791
+ try:
792
+ asyncio.get_running_loop()
793
+ raise RuntimeError("find_iter_sync() called from async context. Use async for item in find_iter() instead.")
794
+ except RuntimeError as exc:
795
+ if "no running event loop" not in str(exc).lower():
796
+ raise
797
+
798
+ if not self._is_initialized:
799
+ self.initialize_sync()
800
+
801
+ cursor = self._sync_collection().find(query or {})
802
+ if sort:
803
+ cursor = cursor.sort(sort)
804
+ if batch_size is not None:
805
+ cursor = cursor.batch_size(batch_size)
806
+ if limit is not None:
807
+ cursor = cursor.limit(limit)
808
+
809
+ def _generator() -> Iterator[T]:
810
+ try:
811
+ for raw in cursor:
812
+ model = self._mongo_doc_to_model(raw)
813
+ if model is not None:
814
+ yield model
815
+ finally:
816
+ cursor.close()
817
+
818
+ return _generator()
819
+
820
+ async def count_documents(self, query: dict[str, Any] | None = None) -> int:
821
+ """Return the number of documents matching ``query`` without loading them."""
822
+ if self._models is not None:
823
+ raise ValueError(
824
+ "Cannot use count_documents() in multi-model mode. Use db.model_name.count_documents() instead."
825
+ )
826
+
827
+ if not self._is_initialized:
828
+ await self.initialize()
829
+
830
+ return await self._motor_collection().count_documents(query or {})
831
+
548
832
  async def aggregate(self, pipeline: list) -> List[T]:
549
833
  """
550
834
  Execute a MongoDB aggregation pipeline.
@@ -568,6 +852,8 @@ class MongoMindtraceODM[T: MindtraceDocument](MindtraceODM):
568
852
  # Auto-initialize if needed (backward compatible)
569
853
  if not self._is_initialized:
570
854
  await self.initialize()
855
+ if self._motor_routing:
856
+ return await self._motor_collection().aggregate(pipeline).to_list(None)
571
857
  return await self.model_cls.get_motor_collection().aggregate(pipeline).to_list(None)
572
858
 
573
859
  def get_raw_model(self) -> Type[T]:
@@ -532,6 +532,7 @@ class UnifiedMindtraceODM(MindtraceODM):
532
532
  self.unified_model_cls = unified_model_cls
533
533
  self._unified_models = unified_models
534
534
  self._model_odms: Dict[str, "UnifiedMindtraceODM"] = {}
535
+ self._closed = False
535
536
 
536
537
  # Support multi-model mode with unified models
537
538
  if unified_models is not None:
@@ -634,6 +635,27 @@ class UnifiedMindtraceODM(MindtraceODM):
634
635
  return self._model_odms[name]
635
636
  raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{name}'")
636
637
 
638
+ def close(self) -> None:
639
+ """Release resources held by the underlying backends.
640
+
641
+ Closes any child UnifiedMindtraceODM instances (multi-model mode)
642
+ and each backend that exposes a ``close`` method. Idempotent.
643
+ """
644
+ if self._closed:
645
+ return
646
+ for odm in self._model_odms.values():
647
+ try:
648
+ odm.close()
649
+ except Exception:
650
+ pass
651
+ for backend in (self.mongo_backend, self.redis_backend):
652
+ if backend is not None and hasattr(backend, "close"):
653
+ try:
654
+ backend.close()
655
+ except Exception:
656
+ pass
657
+ self._closed = True
658
+
637
659
  def _get_active_backend(self):
638
660
  """
639
661
  Get the currently active backend based on preference and availability.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mindtrace-database
3
- Version: 0.10.0
3
+ Version: 0.11.0
4
4
  Summary: Database functionality for Mindtrace
5
5
  Author: Mindtrace Team
6
6
  License-Expression: Apache-2.0
@@ -11,13 +11,13 @@ Classifier: Programming Language :: Python :: 3.12
11
11
  Description-Content-Type: text/markdown
12
12
  License-File: LICENSE
13
13
  Requires-Dist: beanie<2,>=1.29.0
14
- Requires-Dist: mindtrace-core>=0.10.0
14
+ Requires-Dist: mindtrace-core>=0.11.0
15
15
  Requires-Dist: pydantic>=2.11.1
16
16
  Requires-Dist: redis>=4.0.0
17
17
  Requires-Dist: redis-om>=0.3.5
18
18
  Requires-Dist: motor>=3.3.0
19
19
  Requires-Dist: pymongo>=4.14.0
20
- Requires-Dist: mindtrace-registry>=0.10.0
20
+ Requires-Dist: mindtrace-registry>=0.11.0
21
21
  Dynamic: license-file
22
22
 
23
23
  [![PyPI version](https://img.shields.io/pypi/v/mindtrace-database)](https://pypi.org/project/mindtrace-database/)
@@ -1,8 +1,8 @@
1
1
  beanie<2,>=1.29.0
2
- mindtrace-core>=0.10.0
2
+ mindtrace-core>=0.11.0
3
3
  pydantic>=2.11.1
4
4
  redis>=4.0.0
5
5
  redis-om>=0.3.5
6
6
  motor>=3.3.0
7
7
  pymongo>=4.14.0
8
- mindtrace-registry>=0.10.0
8
+ mindtrace-registry>=0.11.0
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mindtrace-database"
3
- version = "0.10.0"
3
+ version = "0.11.0"
4
4
  description = "Database functionality for Mindtrace"
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -13,13 +13,13 @@ classifiers = [
13
13
  ]
14
14
  dependencies = [
15
15
  "beanie>=1.29.0, <2",
16
- "mindtrace-core>=0.10.0",
16
+ "mindtrace-core>=0.11.0",
17
17
  "pydantic>=2.11.1",
18
18
  "redis>=4.0.0",
19
19
  "redis-om>=0.3.5",
20
20
  "motor>=3.3.0",
21
21
  "pymongo>=4.14.0",
22
- "mindtrace-registry>=0.10.0",
22
+ "mindtrace-registry>=0.11.0",
23
23
  ]
24
24
 
25
25
  [project.urls]