-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #92 from glyph/docs-and-repo
implement a "repository" convenience function for collecting a bunch of accessors and transaction management
- Loading branch information
Showing
7 changed files
with
176 additions
and
77 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
# -*- test-case-name: dbxs.test.test_access.AccessTestCase.test_repository -*- | ||
""" | ||
A repository combines a collection of accessors. | ||
""" | ||
|
||
from __future__ import annotations | ||
|
||
import sys | ||
from contextlib import asynccontextmanager | ||
from inspect import signature | ||
from typing import AsyncContextManager, AsyncIterator, Callable, TypeVar | ||
|
||
from ._access import accessor | ||
from .async_dbapi import AsyncConnectable, transaction | ||
|
||
|
||
T = TypeVar("T") | ||
|
||
|
||
def repository( | ||
repositoryType: type[T], | ||
) -> Callable[[AsyncConnectable], AsyncContextManager[T]]: | ||
""" | ||
A L{repository} combines management of a transaction with management of a | ||
"repository", which is a collection of L{accessor}s and a contextmanager | ||
that manages a transaction. This is easier to show with an example than a | ||
description:: | ||
class Users(Protocol): | ||
@query(sql="...", load=one(User)) | ||
def getUserByID(self, id: UserID) -> User: ... | ||
class Posts(Protocol): | ||
@query(sql="...", load=many(Post)) | ||
def getPostsFromUser(self, id: UserID) -> AsyncIterator[Posts]: ... | ||
@dataclass | ||
class BlogDB: | ||
users: Users | ||
posts: Posts | ||
blogRepository = repository(BlogDB) | ||
# ... | ||
async def userAndPosts(pool: AsyncConnectable, id: UserID) -> str: | ||
async with blogRepository(pool) as blog: | ||
user = await blog.users.getUserByID(id) | ||
posts = await blog.posts.getPostsFromUser(posts) | ||
# transaction commits here | ||
""" | ||
|
||
sig = signature(repositoryType) | ||
accessors = {} | ||
for name, parameter in sig.parameters.items(): # pragma: no branch | ||
annotation = parameter.annotation | ||
# It would be nicer to do this with signature(..., eval_str=True), but | ||
# that's not available until we require python>=3.10 | ||
if isinstance(annotation, str): # pragma: no branch | ||
annotation = eval( | ||
annotation, sys.modules[repositoryType.__module__].__dict__ | ||
) | ||
accessors[name] = accessor(annotation) | ||
|
||
@asynccontextmanager | ||
async def transactify(acxn: AsyncConnectable) -> AsyncIterator[T]: | ||
kw = {} | ||
async with transaction(acxn) as aconn: | ||
for name in accessors: # pragma: no branch | ||
kw[name] = accessors[name](aconn) | ||
yield repositoryType(**kw) | ||
|
||
return transactify |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters