mindtrace-database 0.11.0__tar.gz → 0.13.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 (31) hide show
  1. mindtrace_database-0.13.0/PKG-INFO +486 -0
  2. mindtrace_database-0.13.0/README.md +464 -0
  3. {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/mindtrace/database/__init__.py +2 -1
  4. {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/mindtrace/database/backends/mongo_odm.py +61 -9
  5. {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/mindtrace/database/backends/redis_odm.py +26 -20
  6. {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/mindtrace/database/core/exceptions.py +7 -0
  7. mindtrace_database-0.13.0/mindtrace/database/sample/user.py +12 -0
  8. mindtrace_database-0.13.0/mindtrace/database/testing/__init__.py +29 -0
  9. mindtrace_database-0.13.0/mindtrace/database/testing/suites/__init__.py +1 -0
  10. mindtrace_database-0.13.0/mindtrace/database/testing/suites/_models.py +21 -0
  11. mindtrace_database-0.13.0/mindtrace/database/testing/suites/_mongo.py +28 -0
  12. mindtrace_database-0.13.0/mindtrace/database/testing/suites/mongo_crud.py +106 -0
  13. mindtrace_database-0.13.0/mindtrace/database/testing/suites/mongo_insert.py +113 -0
  14. mindtrace_database-0.13.0/mindtrace/database/testing/suites/mongo_read.py +133 -0
  15. mindtrace_database-0.13.0/mindtrace/database/testing/suites/mongo_update.py +124 -0
  16. mindtrace_database-0.13.0/mindtrace_database.egg-info/PKG-INFO +486 -0
  17. {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/mindtrace_database.egg-info/SOURCES.txt +9 -0
  18. mindtrace_database-0.13.0/mindtrace_database.egg-info/entry_points.txt +2 -0
  19. {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/mindtrace_database.egg-info/requires.txt +2 -2
  20. {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/pyproject.toml +6 -3
  21. mindtrace_database-0.11.0/PKG-INFO +0 -1084
  22. mindtrace_database-0.11.0/README.md +0 -1062
  23. mindtrace_database-0.11.0/mindtrace/database/sample/user.py +0 -10
  24. mindtrace_database-0.11.0/mindtrace_database.egg-info/PKG-INFO +0 -1084
  25. {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/LICENSE +0 -0
  26. {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/mindtrace/database/backends/mindtrace_odm.py +0 -0
  27. {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/mindtrace/database/backends/registry_odm.py +0 -0
  28. {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/mindtrace/database/backends/unified_odm.py +0 -0
  29. {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/mindtrace_database.egg-info/dependency_links.txt +0 -0
  30. {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/mindtrace_database.egg-info/top_level.txt +0 -0
  31. {mindtrace_database-0.11.0 → mindtrace_database-0.13.0}/setup.cfg +0 -0
@@ -0,0 +1,486 @@
1
+ Metadata-Version: 2.4
2
+ Name: mindtrace-database
3
+ Version: 0.13.0
4
+ Summary: Database functionality for Mindtrace
5
+ Author: Mindtrace Team
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://mindtrace.ai
8
+ Project-URL: Repository, https://github.com/mindtrace/mindtrace/blob/main/mindtrace/database
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: beanie<2,>=1.29.0
14
+ Requires-Dist: mindtrace-core>=0.13.0
15
+ Requires-Dist: pydantic>=2.11.1
16
+ Requires-Dist: redis>=4.0.0
17
+ Requires-Dist: redis-om>=0.3.5
18
+ Requires-Dist: motor>=3.3.0
19
+ Requires-Dist: pymongo>=4.14.0
20
+ Requires-Dist: mindtrace-registry>=0.13.0
21
+ Dynamic: license-file
22
+
23
+ [![PyPI version](https://img.shields.io/pypi/v/mindtrace-database)](https://pypi.org/project/mindtrace-database/)
24
+ [![License](https://img.shields.io/pypi/l/mindtrace-database)](https://github.com/mindtrace/mindtrace/blob/main/mindtrace/database/LICENSE)
25
+ [![Downloads](https://static.pepy.tech/badge/mindtrace-database)](https://pepy.tech/projects/mindtrace-database)
26
+
27
+ # Mindtrace Database
28
+
29
+ The `Database` module provides Mindtrace’s object-document mapping layer for MongoDB, Redis, Registry-backed storage, and unified multi-backend workflows.
30
+
31
+ ## Features
32
+
33
+ - **Unified ODM interface** through `UnifiedMindtraceODM`
34
+ - **Backend-specific ODMs** for MongoDB, Redis, and Registry-backed storage
35
+ - **Single-model and multi-model operation** in the same API style
36
+ - **Sync and async access patterns** across all supported backends
37
+ - **Unified document models** that can target both MongoDB and Redis
38
+ - **Consistent exceptions** such as `DocumentNotFoundError` and `DuplicateInsertError`
39
+
40
+ ## Quick Start
41
+
42
+ ```python
43
+ import asyncio
44
+
45
+ from pydantic import Field
46
+
47
+ from mindtrace.database import BackendType, UnifiedMindtraceDocument, UnifiedMindtraceODM
48
+
49
+
50
+ class User(UnifiedMindtraceDocument):
51
+ name: str = Field(description="User name")
52
+ email: str = Field(description="Email address")
53
+ age: int = Field(ge=0)
54
+
55
+ class Meta:
56
+ collection_name = "users"
57
+ global_key_prefix = "myapp"
58
+ indexed_fields = ["email", "name"]
59
+ unique_fields = ["email"]
60
+
61
+
62
+ async def main():
63
+ db = UnifiedMindtraceODM(
64
+ unified_model_cls=User,
65
+ mongo_db_uri="mongodb://localhost:27017",
66
+ mongo_db_name="myapp",
67
+ redis_url="redis://localhost:6379",
68
+ preferred_backend=BackendType.MONGO,
69
+ )
70
+
71
+ user = User(name="Alice", email="alice@example.com", age=30)
72
+ inserted = await db.insert_async(user)
73
+ fetched = await db.get_async(inserted.id)
74
+ print(fetched)
75
+
76
+
77
+ asyncio.run(main())
78
+ ```
79
+
80
+ In practice, the database module gives you a common way to define document models and CRUD workflows while choosing the backend that best fits your application.
81
+
82
+ ## Core Concepts
83
+
84
+ The package revolves around four main ODM styles:
85
+
86
+ - **`UnifiedMindtraceODM`** — one API over MongoDB and/or Redis
87
+ - **`MongoMindtraceODM`** — MongoDB-specific ODM built on Beanie
88
+ - **`RedisMindtraceODM`** — Redis-specific ODM built on redis-om
89
+ - **`RegistryMindtraceODM`** — Registry-backed ODM for simpler local or storage-backed document persistence
90
+
91
+ The package also provides matching document model bases:
92
+
93
+ - `UnifiedMindtraceDocument`
94
+ - `MindtraceDocument`
95
+ - `MindtraceRedisDocument`
96
+
97
+ ## UnifiedMindtraceODM
98
+
99
+ `UnifiedMindtraceODM` is the recommended starting point when you want one API that can work across MongoDB and Redis.
100
+
101
+ ### Unified document model
102
+
103
+ ```python
104
+ from pydantic import Field
105
+
106
+ from mindtrace.database import UnifiedMindtraceDocument
107
+
108
+
109
+ class User(UnifiedMindtraceDocument):
110
+ name: str = Field(description="User name")
111
+ email: str = Field(description="Email")
112
+ age: int = Field(ge=0)
113
+
114
+ class Meta:
115
+ collection_name = "users"
116
+ global_key_prefix = "myapp"
117
+ indexed_fields = ["email", "name"]
118
+ unique_fields = ["email"]
119
+ ```
120
+
121
+ ### Unified ODM setup
122
+
123
+ ```python
124
+ from mindtrace.database import BackendType, UnifiedMindtraceODM
125
+
126
+
127
+ db = UnifiedMindtraceODM(
128
+ unified_model_cls=User,
129
+ mongo_db_uri="mongodb://localhost:27017",
130
+ mongo_db_name="myapp",
131
+ redis_url="redis://localhost:6379",
132
+ preferred_backend=BackendType.MONGO,
133
+ )
134
+ ```
135
+
136
+ ### Common operations
137
+
138
+ ```python
139
+ # Async operations
140
+ inserted_user = await db.insert_async(User(name="Alice", email="alice@example.com", age=30))
141
+ retrieved_user = await db.get_async(inserted_user.id)
142
+ retrieved_user.age = 31
143
+ updated_user = await db.update_async(retrieved_user)
144
+ all_users = await db.all_async()
145
+ python_users = await db.find_async({"name": "Alice"})
146
+ ```
147
+
148
+ ```python
149
+ # Sync operations
150
+ inserted_user = db.insert(User(name="Bob", email="bob@example.com", age=25))
151
+ retrieved_user = db.get(inserted_user.id)
152
+ retrieved_user.age = 26
153
+ updated_user = db.update(retrieved_user)
154
+ all_users = db.all()
155
+ ```
156
+
157
+ ### Switching backends
158
+
159
+ ```python
160
+ db.switch_backend(BackendType.REDIS)
161
+ redis_user = db.insert(User(name="Carol", email="carol@example.com", age=28))
162
+
163
+ current_backend = db.get_current_backend_type()
164
+ print(current_backend)
165
+ ```
166
+
167
+ ### Multi-model mode
168
+
169
+ All ODMs in this package support multi-model mode.
170
+
171
+ ```python
172
+ class Address(UnifiedMindtraceDocument):
173
+ street: str
174
+ city: str
175
+
176
+ class Meta:
177
+ collection_name = "addresses"
178
+ global_key_prefix = "myapp"
179
+
180
+
181
+ db = UnifiedMindtraceODM(
182
+ unified_models={"user": User, "address": Address},
183
+ mongo_db_uri="mongodb://localhost:27017",
184
+ mongo_db_name="myapp",
185
+ redis_url="redis://localhost:6379",
186
+ )
187
+
188
+ address = await db.address.insert_async(Address(street="123 Main St", city="NYC"))
189
+ user = await db.user.insert_async(User(name="Alice", email="alice@example.com", age=30))
190
+ users = await db.user.all_async()
191
+ ```
192
+
193
+ In multi-model mode, use attribute-based access like `db.user.insert_async(...)` rather than `db.insert_async(...)`.
194
+
195
+ ## MongoMindtraceODM
196
+
197
+ Use `MongoMindtraceODM` when you want MongoDB-specific document models and Beanie features.
198
+
199
+ ### Mongo document model
200
+
201
+ ```python
202
+ from typing import Annotated
203
+
204
+ from beanie import Indexed
205
+
206
+ from mindtrace.database import MindtraceDocument
207
+
208
+
209
+ class MongoUser(MindtraceDocument):
210
+ name: str
211
+ email: Annotated[str, Indexed(unique=True)]
212
+ age: int
213
+
214
+ class Settings:
215
+ name = "users"
216
+ use_cache = False
217
+ ```
218
+
219
+ ### Mongo ODM setup
220
+
221
+ ```python
222
+ from mindtrace.database import MongoMindtraceODM
223
+
224
+
225
+ db = MongoMindtraceODM(
226
+ model_cls=MongoUser,
227
+ db_uri="mongodb://localhost:27017",
228
+ db_name="myapp",
229
+ )
230
+ ```
231
+
232
+ ### Async-first behavior
233
+
234
+ MongoDB is natively async in this package.
235
+
236
+ ```python
237
+ inserted = await db.insert(MongoUser(name="Alice", email="alice@example.com", age=30))
238
+ fetched = await db.get(inserted.id)
239
+ results = await db.find(MongoUser.name == "Alice")
240
+ ```
241
+
242
+ ### Sync wrappers
243
+
244
+ ```python
245
+ inserted = db.insert_sync(MongoUser(name="Bob", email="bob@example.com", age=25))
246
+ fetched = db.get_sync(inserted.id)
247
+ all_users = db.all_sync()
248
+ ```
249
+
250
+ ### Linked documents
251
+
252
+ MongoDB supports Beanie `Link` fields.
253
+
254
+ ```python
255
+ from typing import Optional
256
+
257
+ from mindtrace.database import Link, MindtraceDocument, MongoMindtraceODM
258
+
259
+
260
+ class Address(MindtraceDocument):
261
+ street: str
262
+ city: str
263
+
264
+ class Settings:
265
+ name = "addresses"
266
+ use_cache = False
267
+
268
+
269
+ class UserWithAddress(MindtraceDocument):
270
+ name: str
271
+ address: Optional[Link[Address]] = None
272
+
273
+ class Settings:
274
+ name = "users"
275
+ use_cache = False
276
+
277
+
278
+ db = MongoMindtraceODM(
279
+ models={"user": UserWithAddress, "address": Address},
280
+ db_uri="mongodb://localhost:27017",
281
+ db_name="myapp",
282
+ )
283
+
284
+ address = await db.address.insert(Address(street="123 Main St", city="NYC"))
285
+ user = await db.user.insert(UserWithAddress(name="Alice", address=address))
286
+ user_with_links = await db.user.get(user.id, fetch_links=True)
287
+ ```
288
+
289
+ ### Aggregation
290
+
291
+ ```python
292
+ pipeline = [
293
+ {"$match": {"age": {"$gte": 18}}},
294
+ {"$group": {"_id": "$age", "count": {"$sum": 1}}},
295
+ ]
296
+ results = await db.aggregate(pipeline)
297
+ ```
298
+
299
+ ## RedisMindtraceODM
300
+
301
+ Use `RedisMindtraceODM` when you want Redis-backed JSON documents and indexed Redis OM queries.
302
+
303
+ ### Redis document model
304
+
305
+ ```python
306
+ from redis_om import Field
307
+
308
+ from mindtrace.database import MindtraceRedisDocument
309
+
310
+
311
+ class RedisUser(MindtraceRedisDocument):
312
+ name: str = Field(index=True)
313
+ email: str = Field(index=True)
314
+ age: int = Field(index=True)
315
+
316
+ class Meta:
317
+ global_key_prefix = "myapp"
318
+ ```
319
+
320
+ ### Redis ODM setup
321
+
322
+ ```python
323
+ from mindtrace.database import RedisMindtraceODM
324
+
325
+
326
+ db = RedisMindtraceODM(
327
+ model_cls=RedisUser,
328
+ redis_url="redis://localhost:6379",
329
+ )
330
+ ```
331
+
332
+ ### Sync-first behavior
333
+
334
+ Redis is natively sync in this package.
335
+
336
+ ```python
337
+ inserted = db.insert(RedisUser(name="Alice", email="alice@example.com", age=30))
338
+ fetched = db.get(inserted.id)
339
+ results = db.find(RedisUser.age >= 18)
340
+ all_users = db.all()
341
+ ```
342
+
343
+ ### Async wrappers
344
+
345
+ ```python
346
+ inserted = await db.insert_async(RedisUser(name="Bob", email="bob@example.com", age=25))
347
+ fetched = await db.get_async(inserted.id)
348
+ all_users = await db.all_async()
349
+ ```
350
+
351
+ ### Notes on Redis IDs
352
+
353
+ Redis OM uses `pk` internally, but `MindtraceRedisDocument` exposes a consistent `id` property so code can treat MongoDB and Redis documents more similarly.
354
+
355
+ ## RegistryMindtraceODM
356
+
357
+ Use `RegistryMindtraceODM` when you want a simpler registry-backed ODM using Mindtrace’s Registry layer instead of a database server.
358
+
359
+ ```python
360
+ from pydantic import BaseModel
361
+
362
+ from mindtrace.database import RegistryMindtraceODM
363
+
364
+
365
+ class User(BaseModel):
366
+ name: str
367
+ email: str
368
+
369
+
370
+ db = RegistryMindtraceODM(model_cls=User)
371
+ inserted = db.insert(User(name="John Doe", email="john@example.com"))
372
+ retrieved = db.get(inserted.id)
373
+ retrieved.name = "John Smith"
374
+ updated = db.update(retrieved)
375
+ all_users = db.all()
376
+ ```
377
+
378
+ This backend is useful when you want the ODM interface but prefer Registry-backed storage semantics.
379
+
380
+ ## Sync and Async Interfaces
381
+
382
+ All ODMs expose the same broad CRUD shape, but their native execution mode differs.
383
+
384
+ - **MongoMindtraceODM** — native async, with sync wrappers
385
+ - **RedisMindtraceODM** — native sync, with async wrappers
386
+ - **UnifiedMindtraceODM** — routes to the active backend and adapts accordingly
387
+ - **RegistryMindtraceODM** — sync-oriented
388
+
389
+ That means you can often keep the same mental model while fitting your application’s execution style.
390
+
391
+ ## Initialization
392
+
393
+ ODMs support automatic or explicit initialization.
394
+
395
+ ```python
396
+ from mindtrace.database import BackendType, InitMode, UnifiedMindtraceDocument, UnifiedMindtraceODM
397
+
398
+
399
+ db = UnifiedMindtraceODM(
400
+ unified_model_cls=User,
401
+ mongo_db_uri="mongodb://localhost:27017",
402
+ mongo_db_name="myapp",
403
+ redis_url="redis://localhost:6379",
404
+ preferred_backend=BackendType.MONGO,
405
+ auto_init=True,
406
+ init_mode=InitMode.SYNC,
407
+ )
408
+ ```
409
+
410
+ ### Init modes
411
+
412
+ - `InitMode.SYNC`
413
+ - `InitMode.ASYNC`
414
+
415
+ Defaults differ by backend:
416
+
417
+ - MongoDB defaults to `ASYNC`
418
+ - Redis defaults to `SYNC`
419
+ - Registry is sync-oriented
420
+
421
+ ## Error Handling
422
+
423
+ The package provides a consistent exception surface across backends.
424
+
425
+ ```python
426
+ from mindtrace.database import DocumentNotFoundError, DuplicateInsertError
427
+
428
+
429
+ try:
430
+ user = await db.get_async("missing-id")
431
+ except DocumentNotFoundError as e:
432
+ print(f"Not found: {e}")
433
+
434
+ try:
435
+ await db.insert_async(User(name="Alice", email="alice@example.com", age=30))
436
+ except DuplicateInsertError as e:
437
+ print(f"Duplicate insert: {e}")
438
+ ```
439
+
440
+ In multi-model mode, calling direct methods like `db.insert(...)` instead of `db.user.insert(...)` raises a `ValueError` to prevent ambiguity.
441
+
442
+ ## Installation
443
+
444
+ If you are working from the full Mindtrace repo:
445
+
446
+ ```bash
447
+ $ git clone https://github.com/Mindtrace/mindtrace.git && cd mindtrace
448
+ $ uv sync --dev --all-extras
449
+ ```
450
+
451
+ The database package depends on backend libraries such as Beanie, Motor, PyMongo, and Redis OM.
452
+
453
+ ## Examples
454
+
455
+ Related examples in the repo:
456
+
457
+ - [Unified ODM example](../../samples/database/unified_example.py)
458
+ - [MongoDB example](../../samples/database/mongo_example.py)
459
+ - [Redis example](../../samples/database/redis_example.py)
460
+ - [Registry example](../../samples/database/registry_example.py)
461
+ - [Database samples README](../../samples/database/README.md)
462
+
463
+ ## Testing
464
+
465
+ If you are working in the full Mindtrace repo, run tests for this module specifically:
466
+
467
+ ```bash
468
+ $ git clone https://github.com/Mindtrace/mindtrace.git && cd mindtrace
469
+ $ uv sync --dev --all-extras
470
+ $ ds test: database
471
+ $ ds test: --unit database
472
+ ```
473
+
474
+ If you want backend-specific integration coverage as well:
475
+
476
+ ```bash
477
+ $ ds test: database --integration
478
+ ```
479
+
480
+ ## Practical Notes and Caveats
481
+
482
+ - `UnifiedMindtraceODM` only exposes the overlap of capabilities that make sense across MongoDB and Redis; backend-specific features still live on the backend-specific ODMs.
483
+ - Multi-model mode changes the calling style: use attribute-based access like `db.user.get(...)`.
484
+ - MongoDB supports linked documents and aggregation; Redis does not provide the same feature set.
485
+ - Redis and MongoDB differ in native execution style, so some methods are wrappers around the backend’s natural sync/async mode.
486
+ - `RegistryMindtraceODM` is useful for simpler or storage-backed workflows, but its query capabilities are intentionally simpler than MongoDB or Redis.