openframe-adapters-db-mongo 1.0.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.
@@ -0,0 +1,218 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ # Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ # poetry.lock
109
+ # poetry.toml
110
+
111
+ # pdm
112
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
114
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
115
+ # pdm.lock
116
+ # pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # pixi
121
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
122
+ # pixi.lock
123
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
124
+ # in the .venv directory. It is recommended not to include this directory in version control.
125
+ .pixi
126
+
127
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
128
+ __pypackages__/
129
+
130
+ # Celery stuff
131
+ celerybeat-schedule
132
+ celerybeat.pid
133
+
134
+ # Redis
135
+ *.rdb
136
+ *.aof
137
+ *.pid
138
+
139
+ # RabbitMQ
140
+ mnesia/
141
+ rabbitmq/
142
+ rabbitmq-data/
143
+
144
+ # ActiveMQ
145
+ activemq-data/
146
+
147
+ # SageMath parsed files
148
+ *.sage.py
149
+
150
+ # Environments
151
+ .env
152
+ .envrc
153
+ .venv
154
+ env/
155
+ venv/
156
+ ENV/
157
+ env.bak/
158
+ venv.bak/
159
+
160
+ # Spyder project settings
161
+ .spyderproject
162
+ .spyproject
163
+
164
+ # Rope project settings
165
+ .ropeproject
166
+
167
+ # mkdocs documentation
168
+ /site
169
+
170
+ # mypy
171
+ .mypy_cache/
172
+ .dmypy.json
173
+ dmypy.json
174
+
175
+ # Pyre type checker
176
+ .pyre/
177
+
178
+ # pytype static type analyzer
179
+ .pytype/
180
+
181
+ # Cython debug symbols
182
+ cython_debug/
183
+
184
+ # PyCharm
185
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
186
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
187
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
188
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
189
+ # .idea/
190
+
191
+ # Abstra
192
+ # Abstra is an AI-powered process automation framework.
193
+ # Ignore directories containing user credentials, local state, and settings.
194
+ # Learn more at https://abstra.io/docs
195
+ .abstra/
196
+
197
+ # Visual Studio Code
198
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
199
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
200
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
201
+ # you could uncomment the following to ignore the entire vscode folder
202
+ # .vscode/
203
+ # Temporary file for partial code execution
204
+ tempCodeRunnerFile.py
205
+
206
+ # Ruff stuff:
207
+ .ruff_cache/
208
+
209
+ # PyPI configuration file
210
+ .pypirc
211
+
212
+ # Marimo
213
+ marimo/_static/
214
+ marimo/_lsp/
215
+ __marimo__/
216
+
217
+ # Streamlit
218
+ .streamlit/secrets.toml
@@ -0,0 +1,198 @@
1
+ Metadata-Version: 2.4
2
+ Name: openframe-adapters-db-mongo
3
+ Version: 1.0.0
4
+ Summary: OpenFrame Microservice Suite — MongoDB document store adapter.
5
+ License: MIT
6
+ Keywords: document-store,hexagonal,microservice,mongodb,motor,openframe
7
+ Requires-Python: >=3.11
8
+ Requires-Dist: motor>=3.3
9
+ Requires-Dist: openframe-core<2,>=1.0
10
+ Requires-Dist: pymongo>=4.6
11
+ Provides-Extra: dev
12
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
13
+ Requires-Dist: pytest-mock>=3.14; extra == 'dev'
14
+ Requires-Dist: pytest>=8.0; extra == 'dev'
15
+ Description-Content-Type: text/markdown
16
+
17
+ # openframe-adapters-db-mongo
18
+
19
+ MongoDB document store adapter for the **OpenFrame Microservice Suite**.
20
+
21
+ Part of the `openframe-adapters` monorepo. Implements `BaseRepository[T]` and
22
+ `HealthCheck` from `openframe-core` using `motor` (`AsyncIOMotorClient`).
23
+
24
+ ---
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ pip install openframe-adapters-db-mongo
30
+ ```
31
+
32
+ Required env vars:
33
+
34
+ ```
35
+ MONGO_URL=mongodb://user:password@host:27017
36
+ MONGO_DATABASE=mydb
37
+ ```
38
+
39
+ Atlas SRV URIs work too:
40
+
41
+ ```
42
+ MONGO_URL=mongodb+srv://user:password@cluster.mongodb.net
43
+ ```
44
+
45
+ ---
46
+
47
+ ## Quick start
48
+
49
+ ### Raw dict mode
50
+
51
+ ```python
52
+ from openframe.adapters.db.mongo import MongoSettings, MongoRepository
53
+
54
+ settings = MongoSettings() # reads MONGO_URL and MONGO_DATABASE from env
55
+ repo = MongoRepository(settings, collection="artifacts")
56
+
57
+ doc = await repo.get("507f1f77bcf86cd799439011") # dict | None
58
+ docs, total = await repo.list(10, 0) # ([dict, ...], int)
59
+ created = await repo.create({"title": "paper"})
60
+ updated = await repo.update({"_id": "...", "title": "updated"})
61
+ deleted = await repo.delete("507f1f77bcf86cd799439011") # bool
62
+ ```
63
+
64
+ ### Typed domain mode
65
+
66
+ ```python
67
+ from dataclasses import dataclass
68
+ from openframe.adapters.db.mongo import MongoSettings, MongoRepository
69
+
70
+ @dataclass
71
+ class Artifact:
72
+ id: str
73
+ title: str
74
+ artifact_type: str
75
+
76
+ class ArtifactRepository(MongoRepository[Artifact]):
77
+ _collection = "artifacts"
78
+
79
+ def _doc_to_entity(self, doc: dict) -> Artifact:
80
+ return Artifact(
81
+ id=doc["_id"],
82
+ title=doc["title"],
83
+ artifact_type=doc["artifact_type"],
84
+ )
85
+
86
+ def _entity_to_doc(self, entity: Artifact) -> dict:
87
+ return {
88
+ "_id": entity.id,
89
+ "title": entity.title,
90
+ "artifact_type": entity.artifact_type,
91
+ }
92
+
93
+ settings = MongoSettings()
94
+ repo = ArtifactRepository(settings)
95
+ artifact: Artifact | None = await repo.get("507f1f77bcf86cd799439011")
96
+ ```
97
+
98
+ ---
99
+
100
+ ## `_id` handling
101
+
102
+ MongoDB uses `_id` as the document identifier; `BaseRepository` uses
103
+ `entity_id: str`. The adapter bridges this transparently:
104
+
105
+ - **Reading:** `_id` is always returned as `str` — `ObjectId` is never
106
+ exposed to callers. A convenience `id` key is also added mirroring `_id`.
107
+ - **Writing:** If an entity dict has an `id` key but no `_id` key, the
108
+ adapter maps `id` → `_id` before insertion.
109
+ - **Filtering:** String entity IDs that are valid 24-char hex are parsed
110
+ as `ObjectId` for indexed lookups; other strings are used as plain string
111
+ `_id` values.
112
+
113
+ ---
114
+
115
+ ## Configuration
116
+
117
+ All settings are read from environment variables.
118
+
119
+ | Env var | Type | Default | Description |
120
+ |---|---|---|---|
121
+ | `MONGO_URL` | `str` | **required** | Motor/pymongo connection string |
122
+ | `MONGO_DATABASE` | `str` | **required** | Database name |
123
+ | `MONGO_MIN_POOL_SIZE` | `int` | `5` | Minimum pool connections |
124
+ | `MONGO_MAX_POOL_SIZE` | `int` | `20` | Maximum pool connections |
125
+ | `MONGO_SERVER_SELECTION_TIMEOUT_MS` | `int` | `5000` | Server selection timeout (ms) |
126
+ | `MONGO_TLS` | `bool` | `False` | Enable TLS/SSL |
127
+ | `MONGO_TLS_ALLOW_INVALID_CERTS` | `bool` | `False` | Skip cert validation (dev only) |
128
+ | `CONNECTION_TIMEOUT` | `float` | `30.0` | Pool creation timeout (s) |
129
+ | `OPERATION_TIMEOUT` | `float` | `10.0` | Per-operation timeout (s) |
130
+ | `MAX_RETRIES` | `int` | `3` | Max retry attempts |
131
+
132
+ ---
133
+
134
+ ## Timeout strategy
135
+
136
+ Two layers of timeout on every operation:
137
+
138
+ 1. `asyncio.timeout(settings.operation_timeout)` — cancels the Python coroutine.
139
+ 2. `max_time_ms=int(settings.operation_timeout * 1000)` passed to motor query
140
+ methods — instructs the MongoDB server to abort the query.
141
+
142
+ ---
143
+
144
+ ## Health checks
145
+
146
+ `MongoRepository` implements the `HealthCheck` protocol from `openframe-core`.
147
+
148
+ ```python
149
+ alive = await repo.ping() # admin.command("ping") — fast liveness check
150
+ ready = await repo.is_ready() # list_collection_names() — full readiness check
151
+ ```
152
+
153
+ Both methods return `False` on any failure and never raise.
154
+
155
+ ---
156
+
157
+ ## Exception hierarchy
158
+
159
+ All exceptions are `AdapterError` subclasses from `openframe.core.exceptions`.
160
+ Raw motor/pymongo exceptions never escape the adapter.
161
+
162
+ | Situation | Exception |
163
+ |---|---|
164
+ | Cannot connect to MongoDB | `AdapterConnectionError` |
165
+ | Invalid `MONGO_URL` syntax | `AdapterConfigurationError` |
166
+ | Query failed (constraint, auth, etc.) | `AdapterQueryError` |
167
+ | Operation exceeded timeout | `AdapterTimeoutError` |
168
+
169
+ ---
170
+
171
+ ## Development
172
+
173
+ ```bash
174
+ # from the package directory
175
+ pip install -e ".[dev]"
176
+ pytest tests/ -v
177
+ ```
178
+
179
+ ---
180
+
181
+ ## Protocol conformance
182
+
183
+ ```python
184
+ from openframe.core.ports import BaseRepository
185
+ from openframe.core.health import HealthCheck
186
+
187
+ repo = MongoRepository(settings, collection="artifacts")
188
+ assert isinstance(repo, BaseRepository) # True — structural check
189
+ assert isinstance(repo, HealthCheck) # True — structural check
190
+ ```
191
+
192
+ No inheritance from either Protocol is required or used.
193
+
194
+ ---
195
+
196
+ ## License
197
+
198
+ MIT
@@ -0,0 +1,182 @@
1
+ # openframe-adapters-db-mongo
2
+
3
+ MongoDB document store adapter for the **OpenFrame Microservice Suite**.
4
+
5
+ Part of the `openframe-adapters` monorepo. Implements `BaseRepository[T]` and
6
+ `HealthCheck` from `openframe-core` using `motor` (`AsyncIOMotorClient`).
7
+
8
+ ---
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ pip install openframe-adapters-db-mongo
14
+ ```
15
+
16
+ Required env vars:
17
+
18
+ ```
19
+ MONGO_URL=mongodb://user:password@host:27017
20
+ MONGO_DATABASE=mydb
21
+ ```
22
+
23
+ Atlas SRV URIs work too:
24
+
25
+ ```
26
+ MONGO_URL=mongodb+srv://user:password@cluster.mongodb.net
27
+ ```
28
+
29
+ ---
30
+
31
+ ## Quick start
32
+
33
+ ### Raw dict mode
34
+
35
+ ```python
36
+ from openframe.adapters.db.mongo import MongoSettings, MongoRepository
37
+
38
+ settings = MongoSettings() # reads MONGO_URL and MONGO_DATABASE from env
39
+ repo = MongoRepository(settings, collection="artifacts")
40
+
41
+ doc = await repo.get("507f1f77bcf86cd799439011") # dict | None
42
+ docs, total = await repo.list(10, 0) # ([dict, ...], int)
43
+ created = await repo.create({"title": "paper"})
44
+ updated = await repo.update({"_id": "...", "title": "updated"})
45
+ deleted = await repo.delete("507f1f77bcf86cd799439011") # bool
46
+ ```
47
+
48
+ ### Typed domain mode
49
+
50
+ ```python
51
+ from dataclasses import dataclass
52
+ from openframe.adapters.db.mongo import MongoSettings, MongoRepository
53
+
54
+ @dataclass
55
+ class Artifact:
56
+ id: str
57
+ title: str
58
+ artifact_type: str
59
+
60
+ class ArtifactRepository(MongoRepository[Artifact]):
61
+ _collection = "artifacts"
62
+
63
+ def _doc_to_entity(self, doc: dict) -> Artifact:
64
+ return Artifact(
65
+ id=doc["_id"],
66
+ title=doc["title"],
67
+ artifact_type=doc["artifact_type"],
68
+ )
69
+
70
+ def _entity_to_doc(self, entity: Artifact) -> dict:
71
+ return {
72
+ "_id": entity.id,
73
+ "title": entity.title,
74
+ "artifact_type": entity.artifact_type,
75
+ }
76
+
77
+ settings = MongoSettings()
78
+ repo = ArtifactRepository(settings)
79
+ artifact: Artifact | None = await repo.get("507f1f77bcf86cd799439011")
80
+ ```
81
+
82
+ ---
83
+
84
+ ## `_id` handling
85
+
86
+ MongoDB uses `_id` as the document identifier; `BaseRepository` uses
87
+ `entity_id: str`. The adapter bridges this transparently:
88
+
89
+ - **Reading:** `_id` is always returned as `str` — `ObjectId` is never
90
+ exposed to callers. A convenience `id` key is also added mirroring `_id`.
91
+ - **Writing:** If an entity dict has an `id` key but no `_id` key, the
92
+ adapter maps `id` → `_id` before insertion.
93
+ - **Filtering:** String entity IDs that are valid 24-char hex are parsed
94
+ as `ObjectId` for indexed lookups; other strings are used as plain string
95
+ `_id` values.
96
+
97
+ ---
98
+
99
+ ## Configuration
100
+
101
+ All settings are read from environment variables.
102
+
103
+ | Env var | Type | Default | Description |
104
+ |---|---|---|---|
105
+ | `MONGO_URL` | `str` | **required** | Motor/pymongo connection string |
106
+ | `MONGO_DATABASE` | `str` | **required** | Database name |
107
+ | `MONGO_MIN_POOL_SIZE` | `int` | `5` | Minimum pool connections |
108
+ | `MONGO_MAX_POOL_SIZE` | `int` | `20` | Maximum pool connections |
109
+ | `MONGO_SERVER_SELECTION_TIMEOUT_MS` | `int` | `5000` | Server selection timeout (ms) |
110
+ | `MONGO_TLS` | `bool` | `False` | Enable TLS/SSL |
111
+ | `MONGO_TLS_ALLOW_INVALID_CERTS` | `bool` | `False` | Skip cert validation (dev only) |
112
+ | `CONNECTION_TIMEOUT` | `float` | `30.0` | Pool creation timeout (s) |
113
+ | `OPERATION_TIMEOUT` | `float` | `10.0` | Per-operation timeout (s) |
114
+ | `MAX_RETRIES` | `int` | `3` | Max retry attempts |
115
+
116
+ ---
117
+
118
+ ## Timeout strategy
119
+
120
+ Two layers of timeout on every operation:
121
+
122
+ 1. `asyncio.timeout(settings.operation_timeout)` — cancels the Python coroutine.
123
+ 2. `max_time_ms=int(settings.operation_timeout * 1000)` passed to motor query
124
+ methods — instructs the MongoDB server to abort the query.
125
+
126
+ ---
127
+
128
+ ## Health checks
129
+
130
+ `MongoRepository` implements the `HealthCheck` protocol from `openframe-core`.
131
+
132
+ ```python
133
+ alive = await repo.ping() # admin.command("ping") — fast liveness check
134
+ ready = await repo.is_ready() # list_collection_names() — full readiness check
135
+ ```
136
+
137
+ Both methods return `False` on any failure and never raise.
138
+
139
+ ---
140
+
141
+ ## Exception hierarchy
142
+
143
+ All exceptions are `AdapterError` subclasses from `openframe.core.exceptions`.
144
+ Raw motor/pymongo exceptions never escape the adapter.
145
+
146
+ | Situation | Exception |
147
+ |---|---|
148
+ | Cannot connect to MongoDB | `AdapterConnectionError` |
149
+ | Invalid `MONGO_URL` syntax | `AdapterConfigurationError` |
150
+ | Query failed (constraint, auth, etc.) | `AdapterQueryError` |
151
+ | Operation exceeded timeout | `AdapterTimeoutError` |
152
+
153
+ ---
154
+
155
+ ## Development
156
+
157
+ ```bash
158
+ # from the package directory
159
+ pip install -e ".[dev]"
160
+ pytest tests/ -v
161
+ ```
162
+
163
+ ---
164
+
165
+ ## Protocol conformance
166
+
167
+ ```python
168
+ from openframe.core.ports import BaseRepository
169
+ from openframe.core.health import HealthCheck
170
+
171
+ repo = MongoRepository(settings, collection="artifacts")
172
+ assert isinstance(repo, BaseRepository) # True — structural check
173
+ assert isinstance(repo, HealthCheck) # True — structural check
174
+ ```
175
+
176
+ No inheritance from either Protocol is required or used.
177
+
178
+ ---
179
+
180
+ ## License
181
+
182
+ MIT
@@ -0,0 +1,49 @@
1
+ """
2
+ openframe.adapters.db.mongo
3
+ =============================
4
+ MongoDB document store adapter for the OpenFrame Microservice Suite.
5
+
6
+ Public API:
7
+
8
+ MongoSettings — Pydantic Settings subclass for connection config.
9
+ MongoRepository — Generic async repository (BaseRepository + HealthCheck).
10
+ get_mongo_client — Synchronous factory that creates / returns the cached client.
11
+
12
+ Quick start::
13
+
14
+ from openframe.adapters.db.mongo import (
15
+ MongoSettings,
16
+ MongoRepository,
17
+ get_mongo_client,
18
+ )
19
+
20
+ settings = MongoSettings(
21
+ mongo_url="mongodb://user:pw@localhost:27017",
22
+ mongo_database="mydb",
23
+ )
24
+
25
+ # Raw dict mode
26
+ repo = MongoRepository(settings, collection="artifacts")
27
+ doc = await repo.get("507f1f77bcf86cd799439011") # dict | None
28
+
29
+ # Typed mode — subclass and override mapping methods
30
+ class ArtifactRepository(MongoRepository[Artifact]):
31
+ _collection = "artifacts"
32
+
33
+ def _doc_to_entity(self, doc):
34
+ return Artifact(**doc)
35
+
36
+ def _entity_to_doc(self, entity):
37
+ return entity.model_dump()
38
+ """
39
+ from __future__ import annotations
40
+
41
+ from .config import MongoSettings
42
+ from .connection import get_mongo_client
43
+ from .repository import MongoRepository
44
+
45
+ __all__ = [
46
+ "MongoSettings",
47
+ "MongoRepository",
48
+ "get_mongo_client",
49
+ ]
@@ -0,0 +1,69 @@
1
+ """
2
+ openframe/adapters/db/mongo/config.py
3
+ =======================================
4
+ MongoDB adapter settings.
5
+
6
+ Reads all connection configuration from environment variables via Pydantic
7
+ Settings. Every field is validated at instantiation — missing required fields
8
+ raise ``pydantic_core.ValidationError`` immediately so misconfigured
9
+ deployments fail fast on startup.
10
+
11
+ Required env vars:
12
+ MONGO_URL: Full motor/pymongo connection string.
13
+ Standard: mongodb://user:pass@host:port
14
+ Atlas: mongodb+srv://user:pass@cluster.mongodb.net
15
+ Atlas SRV URIs require dnspython, which motor resolves
16
+ automatically — no extra dependency needed.
17
+ MONGO_DATABASE: Database name to operate on.
18
+
19
+ Optional env vars (all have defaults):
20
+ MONGO_MIN_POOL_SIZE: int = 5
21
+ MONGO_MAX_POOL_SIZE: int = 20
22
+ MONGO_SERVER_SELECTION_TIMEOUT_MS: int = 5000
23
+ MONGO_TLS: bool = False
24
+ MONGO_TLS_ALLOW_INVALID_CERTS: bool = False
25
+ ADAPTER_NAME: str = "mongo"
26
+ """
27
+ from __future__ import annotations
28
+
29
+ from openframe.core.config import BaseAdapterSettings
30
+
31
+ __all__ = ["MongoSettings"]
32
+
33
+
34
+ class MongoSettings(BaseAdapterSettings):
35
+ """
36
+ Settings for the MongoDB adapter.
37
+
38
+ All fields read from environment variables. Missing required fields raise
39
+ ``pydantic_core.ValidationError`` at instantiation time.
40
+
41
+ Inherits from ``BaseAdapterSettings``:
42
+ adapter_name: str = "mongo" (overrides base default)
43
+ connection_timeout: float = 30.0
44
+ operation_timeout: float = 10.0
45
+ max_retries: int = 3
46
+
47
+ Attributes:
48
+ mongo_url: Motor/pymongo connection string
49
+ (required). Standard or Atlas SRV.
50
+ mongo_database: Database name (required).
51
+ mongo_min_pool_size: Minimum connections in the pool.
52
+ Default 5.
53
+ mongo_max_pool_size: Maximum connections in the pool.
54
+ Default 20.
55
+ mongo_server_selection_timeout_ms: Milliseconds to wait for a suitable
56
+ server. Default 5000.
57
+ mongo_tls: Enable TLS/SSL. Default False.
58
+ mongo_tls_allow_invalid_certs: Skip certificate validation — for
59
+ development only. Default False.
60
+ """
61
+
62
+ mongo_url: str
63
+ mongo_database: str
64
+ mongo_min_pool_size: int = 5
65
+ mongo_max_pool_size: int = 20
66
+ mongo_server_selection_timeout_ms: int = 5000
67
+ mongo_tls: bool = False
68
+ mongo_tls_allow_invalid_certs: bool = False
69
+ adapter_name: str = "mongo"