Skip to content

Commit 249aec7

Browse files
authored
Interfaces rewrite (#55)
* Replaces Protocols with Abstract Base Classes in the `sqlalchemy_bind_manager.repository` module * The `SortDirection` enum has been replaced by literal `"asc"` or `"desc"` * Remove `SQLAlchemyAsyncConfig ` and use `SQLAlchemyConfig` for async engines * Documentation update
1 parent 974c491 commit 249aec7

File tree

17 files changed

+445
-164
lines changed

17 files changed

+445
-164
lines changed

docs/api_reference/bind_manager.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,3 @@
33
members:
44
- SQLAlchemyBindManager
55
- SQLAlchemyConfig
6-
- SQLAlchemyAsyncConfig

docs/api_reference/repository.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
::: sqlalchemy_bind_manager.protocols
1+
::: sqlalchemy_bind_manager.repository
22
options:
33
members:
4-
- SQLAlchemyRepositoryInterface
5-
- SQLAlchemyAsyncRepositoryInterface
6-
- SortDirection
4+
- SQLAlchemyRepository
5+
- SQLAlchemyAsyncRepository
76
- PaginatedResult
7+
- PageInfo
88
- CursorPaginatedResult
9-
- CursorReference
9+
- CursorPageInfo

docs/manager/alembic/env.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
from sqlalchemy import Column, Integer, String
77
from sqlalchemy.ext.asyncio import AsyncEngine
88

9-
from sqlalchemy_bind_manager import SQLAlchemyAsyncConfig, SQLAlchemyBindManager
9+
from sqlalchemy_bind_manager import SQLAlchemyConfig, SQLAlchemyBindManager
1010

1111
################################################################
1212
## Note: The bind_config, sa_manager and models are normally ##
1313
## implemented in an application. This is only an example! ##
1414
################################################################
1515
bind_config = {
16-
"default": SQLAlchemyAsyncConfig(
16+
"default": SQLAlchemyConfig(
1717
engine_url=f"sqlite+aiosqlite:///{os.path.dirname(os.path.abspath(__file__))}/sqlite.db",
1818
engine_options=dict(
1919
connect_args={
@@ -22,6 +22,7 @@
2222
echo=False,
2323
future=True,
2424
),
25+
async_engine=True,
2526
),
2627
}
2728

docs/manager/config.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,14 @@ All the `SQLAlchemyBindManager` helper methods accept the `bind_name` optional p
6363

6464
## Asynchronous database engines
6565

66-
Is it possible to supply configurations for asyncio supported engines using `SQLAlchemyAsyncConfig` objects.
66+
Is it possible to supply configurations for asyncio supported engines using the `async_engine` config property.
6767

6868
```python
69-
from sqlalchemy_bind_manager import SQLAlchemyAsyncConfig, SQLAlchemyBindManager
69+
from sqlalchemy_bind_manager import SQLAlchemyConfig, SQLAlchemyBindManager
7070

71-
config = SQLAlchemyAsyncConfig(
71+
config = SQLAlchemyConfig(
7272
engine_url="postgresql+asyncpg://scott:tiger@localhost/test",
73+
async_engine=True,
7374
)
7475

7576
sa_manager = SQLAlchemyBindManager(config)

docs/repository/usage.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,27 +35,29 @@ The classes provide some common use methods:
3535
* `paginated_find`: Search for a list of models, with pagination support
3636
* `cursor_paginated_find`: Search for a list of models, with cursor based pagination support
3737

38-
/// details | Typing and Protocols
38+
/// details | Typing and Interfaces
3939
type: tip
4040

41-
The repository classes are fully typed (as the rest of this package), but
42-
protocols classes are provided as addition to allow more decoupled type checking
41+
The repository classes are fully typed (as the rest of this package). The repositories
42+
implement interface classes that are available to allow better code decoupling
4343
and inversion of control patterns such as
4444
[dependency injection](https://en.wikipedia.org/wiki/Dependency_injection).
4545

4646
```python
47-
from sqlalchemy_bind_manager.protocols import SQLAlchemyRepositoryInterface, SQLAlchemyAsyncRepositoryInterface
47+
from sqlalchemy_bind_manager.repository import SQLAlchemyRepositoryInterface, SQLAlchemyAsyncRepositoryInterface
48+
4849

4950
def some_function(repository: SQLAlchemyRepositoryInterface[MyModel]):
5051
model = repository.get(123)
5152
...
5253

54+
5355
async def some_async_function(repository: SQLAlchemyAsyncRepositoryInterface[MyModel]):
5456
model = await repository.get(123)
5557
...
5658
```
5759

58-
Both repository and related protocols are Generic, accepting the model class as argument.
60+
Both repository and related interface are Generic, accepting the model class as a typing argument.
5961
///
6062

6163
### Maximum query limit

sqlalchemy_bind_manager/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
# DEALINGS IN THE SOFTWARE.
2020

2121
from ._bind_manager import (
22-
SQLAlchemyAsyncConfig,
2322
SQLAlchemyBindManager,
2423
SQLAlchemyConfig,
2524
)

sqlalchemy_bind_manager/_bind_manager.py

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
from typing import Mapping, MutableMapping, Union
2222

23-
from pydantic import BaseModel, ConfigDict
23+
from pydantic import BaseModel, ConfigDict, StrictBool
2424
from sqlalchemy import MetaData, create_engine
2525
from sqlalchemy.engine import Engine
2626
from sqlalchemy.ext.asyncio import (
@@ -40,22 +40,13 @@
4040

4141
class SQLAlchemyConfig(BaseModel):
4242
"""
43-
Configuration for synchronous engines
44-
"""
45-
46-
engine_url: str
47-
engine_options: Union[dict, None] = None
48-
session_options: Union[dict, None] = None
49-
50-
51-
class SQLAlchemyAsyncConfig(BaseModel):
52-
"""
53-
Configuration for asynchronous engines
43+
Configuration for engines
5444
"""
5545

5646
engine_url: str
5747
engine_options: Union[dict, None] = None
5848
session_options: Union[dict, None] = None
49+
async_engine: StrictBool = False
5950

6051

6152
class SQLAlchemyBind(BaseModel):
@@ -85,9 +76,8 @@ class SQLAlchemyBindManager:
8576
def __init__(
8677
self,
8778
config: Union[
88-
Mapping[str, Union[SQLAlchemyConfig, SQLAlchemyAsyncConfig]],
79+
Mapping[str, SQLAlchemyConfig],
8980
SQLAlchemyConfig,
90-
SQLAlchemyAsyncConfig,
9181
],
9282
) -> None:
9383
self.__binds = {}
@@ -97,18 +87,10 @@ def __init__(
9787
else:
9888
self.__init_bind(DEFAULT_BIND_NAME, config)
9989

100-
def __init_bind(
101-
self, name: str, config: Union[SQLAlchemyConfig, SQLAlchemyAsyncConfig]
102-
):
103-
if not any(
104-
[
105-
isinstance(config, SQLAlchemyConfig),
106-
isinstance(config, SQLAlchemyAsyncConfig),
107-
]
108-
):
90+
def __init_bind(self, name: str, config: SQLAlchemyConfig):
91+
if not isinstance(config, SQLAlchemyConfig):
10992
raise InvalidConfigError(
110-
f"Config for bind `{name}` is not a SQLAlchemyConfig"
111-
f" or SQLAlchemyAsyncConfig object"
93+
f"Config for bind `{name}` is not a SQLAlchemyConfig" f"object"
11294
)
11395

11496
engine_options: dict = config.engine_options or {}
@@ -119,7 +101,7 @@ def __init_bind(
119101
session_options.setdefault("expire_on_commit", False)
120102
session_options.setdefault("autobegin", False)
121103

122-
if isinstance(config, SQLAlchemyAsyncConfig):
104+
if config.async_engine:
123105
self.__binds[name] = self.__build_async_bind(
124106
engine_url=config.engine_url,
125107
engine_options=engine_options,

sqlalchemy_bind_manager/_repository/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@
1818
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1919
# DEALINGS IN THE SOFTWARE.
2020

21+
from .abstract import SQLAlchemyAsyncRepositoryInterface, SQLAlchemyRepositoryInterface
2122
from .async_ import SQLAlchemyAsyncRepository
2223
from .common import (
24+
CursorPageInfo,
2325
CursorPaginatedResult,
2426
CursorReference,
27+
PageInfo,
2528
PaginatedResult,
26-
SortDirection,
2729
)
2830
from .sync import SQLAlchemyRepository

0 commit comments

Comments
 (0)