Skip to content

Commit

Permalink
🚧 Started with HTTPWorker and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
migduroli committed Apr 15, 2024
1 parent b9c20b8 commit 80ab42a
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 4 deletions.
20 changes: 19 additions & 1 deletion flama/ddd/repositories.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,16 @@
except Exception: # pragma: no cover
...

__all__ = ["AbstractRepository", "SQLAlchemyRepository", "SQLAlchemyTableRepository", "SQLAlchemyTableManager"]
from httpx import AsyncClient


__all__ = [
"AbstractRepository",
"SQLAlchemyRepository",
"SQLAlchemyTableRepository",
"SQLAlchemyTableManager",
"RestRepository",
]


class AbstractRepository(abc.ABC):
Expand Down Expand Up @@ -336,3 +345,12 @@ async def drop(self, *clauses, **filters) -> int:
:return: The number of elements dropped.
"""
return await self._table_manager.drop(*clauses, **filters)


class RestRepository(AbstractRepository):
def __init__(self, client: "AsyncClient", *args, **kwargs):
super().__init__(*args, **kwargs)
self._client = client

def __eq__(self, other):
return isinstance(other, RestRepository) and self._client == other._client
73 changes: 72 additions & 1 deletion flama/ddd/workers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import inspect
import typing as t

from httpx import AsyncClient

from flama.ddd import types
from flama.ddd.repositories import AbstractRepository
from flama.exceptions import ApplicationError
Expand All @@ -15,7 +17,7 @@
from flama import Flama


__all__ = ["WorkerType", "AbstractWorker", "SQLAlchemyWorker"]
__all__ = ["WorkerType", "AbstractWorker", "SQLAlchemyWorker", "HTTPWorker"]


class WorkerType(abc.ABCMeta):
Expand Down Expand Up @@ -201,3 +203,72 @@ async def commit(self):
async def rollback(self):
"""Rollback the unit of work."""
await self.connection.rollback()


class HTTPWorker(AbstractWorker):
"""Worker for HTTP client.
It will provide a flama Client and create the repositories for the corresponding resources.
"""

_client: "AsyncClient"
_url: str

@property
def client(self) -> "AsyncClient":
"""Client to interact with an HTTP resource
:return: Flama client.
:raises AttributeError: If the client is not initialized.
"""
try:
return self._client
except AttributeError:
raise AttributeError("Client not initialized")

@property
def url(self) -> str:
"""Base URL of the HTTP resource
:return: Base URL.
:raises AttributeError: If the url is not initialized.
"""
try:
return self._url
except AttributeError:
raise AttributeError("URL not initialized")

async def begin_transaction(self) -> None:
"""Initialize the client with the URL."""
self._client = await AsyncClient(base_url=self.url).__aenter__()

async def end_transaction(self) -> None:
"""Close and delete the client."""
await self.client.__aexit__()
del self._client

async def begin(self) -> None:
"""Start a unit of work.
Initialize the client, and create the repositories.
"""
await self.begin_transaction()

for repository, repository_class in self._repositories.items():
setattr(self, repository, repository_class(self._client))

async def end(self, *, rollback: bool = False) -> None:
"""End a unit of work.
Close the client, and delete the repositories.
"""
await self.end_transaction()

for repository in self._repositories.keys():
delattr(self, repository)

async def commit(self) -> None:
...

async def rollback(self) -> None:
...
35 changes: 33 additions & 2 deletions tests/ddd/test_workers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import pytest
from sqlalchemy.ext.asyncio import AsyncConnection

from flama.ddd.repositories import SQLAlchemyRepository
from flama.ddd.workers import SQLAlchemyWorker
from flama.ddd.repositories import RestRepository, SQLAlchemyRepository
from flama.ddd.workers import HTTPWorker, SQLAlchemyWorker
from flama.exceptions import ApplicationError


Expand Down Expand Up @@ -141,3 +141,34 @@ async def test_rollback(self, worker):
with patch.object(worker, "_connection", new=connection_mock, create=True):
await worker.rollback()
assert rollback_mock.await_args_list == [call()]


class TestCaseHTTPWorker:
@pytest.fixture(scope="function")
def worker(self, client):
class FooWorker(HTTPWorker):
bar: RestRepository

return FooWorker(client.app)

def test_init(self, app):
worker = HTTPWorker(app)

assert worker._app == app
assert not hasattr(worker, "_client")

def test_client(self, worker):
with pytest.raises(AttributeError, match="Client not initialized"):
worker.client

def test_url(self, worker):
with pytest.raises(AttributeError, match="URL not initialized"):
worker.url

async def test_begin_transaction(self, app, worker, client):
aenter_mock = AsyncMock()
worker._url = "foo"

with patch.multiple("httpx.AsyncClient", __aenter__=AsyncMock(return_value=aenter_mock)):
await worker.begin_transaction()
assert worker._client == aenter_mock

0 comments on commit 80ab42a

Please sign in to comment.