openframe-adapters-db-postgres 1.1.0__tar.gz → 1.2.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.
- {openframe_adapters_db_postgres-1.1.0 → openframe_adapters_db_postgres-1.2.0}/PKG-INFO +1 -1
- {openframe_adapters_db_postgres-1.1.0 → openframe_adapters_db_postgres-1.2.0}/openframe/adapters/db/postgres/plugin.py +40 -3
- {openframe_adapters_db_postgres-1.1.0 → openframe_adapters_db_postgres-1.2.0}/pyproject.toml +1 -1
- {openframe_adapters_db_postgres-1.1.0 → openframe_adapters_db_postgres-1.2.0}/tests/test_plugin.py +67 -2
- {openframe_adapters_db_postgres-1.1.0 → openframe_adapters_db_postgres-1.2.0}/.gitignore +0 -0
- {openframe_adapters_db_postgres-1.1.0 → openframe_adapters_db_postgres-1.2.0}/README.md +0 -0
- {openframe_adapters_db_postgres-1.1.0 → openframe_adapters_db_postgres-1.2.0}/openframe/adapters/db/postgres/__init__.py +0 -0
- {openframe_adapters_db_postgres-1.1.0 → openframe_adapters_db_postgres-1.2.0}/openframe/adapters/db/postgres/config.py +0 -0
- {openframe_adapters_db_postgres-1.1.0 → openframe_adapters_db_postgres-1.2.0}/openframe/adapters/db/postgres/connection.py +0 -0
- {openframe_adapters_db_postgres-1.1.0 → openframe_adapters_db_postgres-1.2.0}/openframe/adapters/db/postgres/repository.py +0 -0
- {openframe_adapters_db_postgres-1.1.0 → openframe_adapters_db_postgres-1.2.0}/tests/conftest.py +0 -0
- {openframe_adapters_db_postgres-1.1.0 → openframe_adapters_db_postgres-1.2.0}/tests/test_config.py +0 -0
- {openframe_adapters_db_postgres-1.1.0 → openframe_adapters_db_postgres-1.2.0}/tests/test_connection.py +0 -0
- {openframe_adapters_db_postgres-1.1.0 → openframe_adapters_db_postgres-1.2.0}/tests/test_health.py +0 -0
- {openframe_adapters_db_postgres-1.1.0 → openframe_adapters_db_postgres-1.2.0}/tests/test_repository.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openframe-adapters-db-postgres
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary: OpenFrame Microservice Suite — PostgreSQL database adapter.
|
|
5
5
|
Project-URL: Homepage, https://github.com/Furious-Meteors/openframe-adapters
|
|
6
6
|
Project-URL: Documentation, https://furious-meteors.github.io/openframe-adapters/
|
|
@@ -22,6 +22,9 @@ Usage via deps.py (unchanged, no plugin needed)::
|
|
|
22
22
|
repo = PostgresRepository(PostgresSettings())
|
|
23
23
|
traced = TracingProxy(repo, prefix="repository.item")
|
|
24
24
|
"""
|
|
25
|
+
# Capability: "persistence"
|
|
26
|
+
# See capability taxonomy:
|
|
27
|
+
# https://furious-meteors.github.io/openframe-core/developer-guide/composition-root/
|
|
25
28
|
from __future__ import annotations
|
|
26
29
|
|
|
27
30
|
import logging
|
|
@@ -44,6 +47,8 @@ class PostgresPlugin:
|
|
|
44
47
|
|
|
45
48
|
Capability: "persistence"
|
|
46
49
|
|
|
50
|
+
Stability: beta
|
|
51
|
+
|
|
47
52
|
Lifecycle:
|
|
48
53
|
initialize() — creates the asyncpg connection pool and verifies
|
|
49
54
|
connectivity via ping(). Raises AdapterConnectionError
|
|
@@ -53,10 +58,20 @@ class PostgresPlugin:
|
|
|
53
58
|
|
|
54
59
|
The plugin exposes get_repository() after initialization for use
|
|
55
60
|
in the composition root or ApplicationBootstrap.
|
|
61
|
+
|
|
62
|
+
By default constructs a plain PostgresRepository. To use a domain-specific
|
|
63
|
+
subclass, pass it via repository_class::
|
|
64
|
+
|
|
65
|
+
registry.register(PostgresPlugin(
|
|
66
|
+
PostgresSettings(),
|
|
67
|
+
table="items",
|
|
68
|
+
id_column="id",
|
|
69
|
+
repository_class=ItemPostgresRepository,
|
|
70
|
+
))
|
|
56
71
|
"""
|
|
57
72
|
|
|
58
73
|
name: str = "openframe-postgres"
|
|
59
|
-
version: str = "1.
|
|
74
|
+
version: str = "1.2.0"
|
|
60
75
|
capability: str = "persistence"
|
|
61
76
|
|
|
62
77
|
def __init__(
|
|
@@ -64,10 +79,31 @@ class PostgresPlugin:
|
|
|
64
79
|
settings: PostgresSettings,
|
|
65
80
|
table: str = "",
|
|
66
81
|
id_column: str = "id",
|
|
82
|
+
repository_class: type[PostgresRepository] = PostgresRepository,
|
|
67
83
|
) -> None:
|
|
84
|
+
"""
|
|
85
|
+
Args:
|
|
86
|
+
settings: PostgresSettings instance.
|
|
87
|
+
table: Table name. If omitted the plugin acts as a
|
|
88
|
+
connection manager only (no get_repository()).
|
|
89
|
+
id_column: Primary key column name. Defaults to "id".
|
|
90
|
+
repository_class: The PostgresRepository subclass to construct.
|
|
91
|
+
Defaults to the base PostgresRepository. Pass a
|
|
92
|
+
domain-specific subclass here to get proper
|
|
93
|
+
entity mapping through get_repository().
|
|
94
|
+
|
|
95
|
+
Raises:
|
|
96
|
+
TypeError: repository_class is not a subclass of PostgresRepository.
|
|
97
|
+
"""
|
|
98
|
+
if not (isinstance(repository_class, type) and issubclass(repository_class, PostgresRepository)):
|
|
99
|
+
raise TypeError(
|
|
100
|
+
f"repository_class must be a subclass of PostgresRepository, "
|
|
101
|
+
f"got {repository_class!r}"
|
|
102
|
+
)
|
|
68
103
|
self._settings = settings
|
|
69
104
|
self._table = table
|
|
70
105
|
self._id_column = id_column
|
|
106
|
+
self._repository_class = repository_class
|
|
71
107
|
self._repo: PostgresRepository | None = None
|
|
72
108
|
self._status = PluginStatus.REGISTERED
|
|
73
109
|
|
|
@@ -94,7 +130,7 @@ class PostgresPlugin:
|
|
|
94
130
|
try:
|
|
95
131
|
pool = await get_postgres_pool(self._settings)
|
|
96
132
|
if self._table:
|
|
97
|
-
self._repo =
|
|
133
|
+
self._repo = self._repository_class(
|
|
98
134
|
self._settings,
|
|
99
135
|
table=self._table,
|
|
100
136
|
id_column=self._id_column,
|
|
@@ -117,8 +153,9 @@ class PostgresPlugin:
|
|
|
117
153
|
) from exc
|
|
118
154
|
self._status = PluginStatus.READY
|
|
119
155
|
_logger.info(
|
|
120
|
-
"PostgresPlugin initialized — %s",
|
|
156
|
+
"PostgresPlugin initialized — %s (repository_class=%s)",
|
|
121
157
|
self._settings.database_url.split("@")[-1],
|
|
158
|
+
self._repository_class.__name__,
|
|
122
159
|
)
|
|
123
160
|
except Exception:
|
|
124
161
|
self._status = PluginStatus.FAILED
|
{openframe_adapters_db_postgres-1.1.0 → openframe_adapters_db_postgres-1.2.0}/tests/test_plugin.py
RENAMED
|
@@ -7,7 +7,7 @@ from __future__ import annotations
|
|
|
7
7
|
|
|
8
8
|
import pytest
|
|
9
9
|
|
|
10
|
-
from openframe.adapters.db.postgres import PostgresPlugin, PostgresSettings
|
|
10
|
+
from openframe.adapters.db.postgres import PostgresPlugin, PostgresRepository, PostgresSettings
|
|
11
11
|
from openframe.core.plugins import OpenFramePlugin, PluginContext, PluginStatus
|
|
12
12
|
|
|
13
13
|
|
|
@@ -46,7 +46,7 @@ def test_postgres_plugin_name(plugin):
|
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
def test_postgres_plugin_version(plugin):
|
|
49
|
-
assert plugin.version == "1.
|
|
49
|
+
assert plugin.version == "1.2.0"
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
def test_postgres_plugin_capability(plugin):
|
|
@@ -177,3 +177,68 @@ async def test_health_returns_failed_when_ping_fails(
|
|
|
177
177
|
assert result is not None
|
|
178
178
|
assert result.status == PluginStatus.FAILED
|
|
179
179
|
conn_module._pool_cache.clear()
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
# ── repository_class parameter ─────────────────────────────────────────────
|
|
183
|
+
|
|
184
|
+
def test_plugin_defaults_to_base_repository_class(settings):
|
|
185
|
+
"""Backwards compatibility — no repository_class passed."""
|
|
186
|
+
plugin = PostgresPlugin(settings, table="items")
|
|
187
|
+
assert plugin._repository_class is PostgresRepository
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def test_plugin_accepts_custom_repository_class(settings):
|
|
191
|
+
class CustomRepo(PostgresRepository):
|
|
192
|
+
pass
|
|
193
|
+
|
|
194
|
+
plugin = PostgresPlugin(settings, table="items", repository_class=CustomRepo)
|
|
195
|
+
assert plugin._repository_class is CustomRepo
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def test_plugin_rejects_non_repository_class(settings):
|
|
199
|
+
"""repository_class must be a subclass of PostgresRepository — TypeError if not."""
|
|
200
|
+
with pytest.raises(TypeError, match="subclass of PostgresRepository"):
|
|
201
|
+
PostgresPlugin(settings, table="items", repository_class=object) # type: ignore[arg-type]
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
async def test_initialize_constructs_custom_repository_class(
|
|
205
|
+
settings, plugin_context, mock_pool, mock_settings
|
|
206
|
+
):
|
|
207
|
+
"""
|
|
208
|
+
REGRESSION: plugin always constructed the base class, silently discarding
|
|
209
|
+
domain subclass overrides of entity mapping methods.
|
|
210
|
+
"""
|
|
211
|
+
import openframe.adapters.db.postgres.connection as conn_module
|
|
212
|
+
|
|
213
|
+
class CustomRepo(PostgresRepository):
|
|
214
|
+
marker = True
|
|
215
|
+
|
|
216
|
+
conn_module._pool_cache[mock_settings.database_url] = mock_pool
|
|
217
|
+
mock_pool.fetchval.return_value = 1
|
|
218
|
+
|
|
219
|
+
plugin = PostgresPlugin(mock_settings, table="items", repository_class=CustomRepo)
|
|
220
|
+
await plugin.initialize(plugin_context)
|
|
221
|
+
|
|
222
|
+
repo = plugin.get_repository()
|
|
223
|
+
assert isinstance(repo, CustomRepo)
|
|
224
|
+
assert hasattr(repo, "marker")
|
|
225
|
+
conn_module._pool_cache.clear()
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
async def test_get_repository_returns_subclass_not_base_class(
|
|
229
|
+
settings, plugin_context, mock_pool, mock_settings
|
|
230
|
+
):
|
|
231
|
+
"""type(repo) must be the subclass, not just isinstance-compatible."""
|
|
232
|
+
import openframe.adapters.db.postgres.connection as conn_module
|
|
233
|
+
|
|
234
|
+
class CustomRepo(PostgresRepository):
|
|
235
|
+
pass
|
|
236
|
+
|
|
237
|
+
conn_module._pool_cache[mock_settings.database_url] = mock_pool
|
|
238
|
+
mock_pool.fetchval.return_value = 1
|
|
239
|
+
|
|
240
|
+
plugin = PostgresPlugin(mock_settings, table="items", repository_class=CustomRepo)
|
|
241
|
+
await plugin.initialize(plugin_context)
|
|
242
|
+
|
|
243
|
+
assert type(plugin.get_repository()) is CustomRepo
|
|
244
|
+
conn_module._pool_cache.clear()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openframe_adapters_db_postgres-1.1.0 → openframe_adapters_db_postgres-1.2.0}/tests/conftest.py
RENAMED
|
File without changes
|
{openframe_adapters_db_postgres-1.1.0 → openframe_adapters_db_postgres-1.2.0}/tests/test_config.py
RENAMED
|
File without changes
|
|
File without changes
|
{openframe_adapters_db_postgres-1.1.0 → openframe_adapters_db_postgres-1.2.0}/tests/test_health.py
RENAMED
|
File without changes
|
|
File without changes
|