Skip to content

Commit

Permalink
meh
Browse files Browse the repository at this point in the history
  • Loading branch information
bartfeenstra committed Apr 9, 2024
1 parent fb8de81 commit c6c02ff
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 12 deletions.
19 changes: 14 additions & 5 deletions betty/service/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@


class CyclicDependency(RuntimeError):
def __init__(self, service_ids: Sequence[str]):
def __init__(self, service_ids: Sequence[ServiceId]):
assert len(service_ids) > 1
traceback = []
for index, service_id in enumerate(service_ids):
Expand All @@ -30,12 +30,19 @@ def __init__(self, service_ids: Sequence[str]):
''')


class _ServiceNotFound(RuntimeError):
pass
class ServiceNotFound(RuntimeError):
def __init__(self, service_id: ServiceId):
super().__init__(f'Unknown service "{service_id}".')


class _ServiceContainerNotStarted(RuntimeError):
pass
class ServiceContainerNotStarted(RuntimeError):
def __init__(self):
super().__init__('This service container has not yet started.')

Check warning on line 40 in betty/service/__init__.py

View check run for this annotation

Codecov / codecov/patch

betty/service/__init__.py#L40

Added line #L40 was not covered by tests


class ServiceContainerStarted(RuntimeError):
def __init__(self):
super().__init__('This service container has already started.')

Check warning on line 45 in betty/service/__init__.py

View check run for this annotation

Codecov / codecov/patch

betty/service/__init__.py#L45

Added line #L45 was not covered by tests


class ServiceContainer:
Expand All @@ -46,6 +53,7 @@ class ServiceContainer:
Implementations must be thread-safe.
"""

async def get(self, service_id: ServiceId) -> Service:
raise NotImplementedError(type(self))

Expand All @@ -69,6 +77,7 @@ class ServiceContainerBuilder:
A service container builder allows you to define the services to build a service container with.
"""

@overload
def define(self, service_id: ServiceId, *, service_factory: ServiceFactory) -> None:
pass
Expand Down
19 changes: 14 additions & 5 deletions betty/service/_default.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
from typing_extensions import override

from betty.concurrent import AsynchronizedLock, _Lock
from betty.service import ServiceContainer, ServiceId, ServiceFactory, Service, _ServiceNotFound, \
ServiceContainerBuilder, CyclicDependency
from betty.service import ServiceContainer, ServiceId, ServiceFactory, Service, ServiceNotFound, \
ServiceContainerBuilder, CyclicDependency, ServiceContainerNotStarted, ServiceContainerStarted


class _ServiceContainerBase(ServiceContainer):
Expand All @@ -29,16 +29,25 @@ async def _lock(self, service_id: ServiceId) -> _Lock:
async with self._locks_lock:
return self._locks[service_id]

def _assert_started(self) -> None:
if not self._started:
raise ServiceContainerNotStarted()

Check warning on line 34 in betty/service/_default.py

View check run for this annotation

Codecov / codecov/patch

betty/service/_default.py#L34

Added line #L34 was not covered by tests

def _assert_not_started(self) -> None:
if self._started:
raise ServiceContainerStarted()

Check warning on line 38 in betty/service/_default.py

View check run for this annotation

Codecov / codecov/patch

betty/service/_default.py#L38

Added line #L38 was not covered by tests

async def start(self) -> None:
self._assert_not_started()
assert not self._started
self._started = True

async def stop(self) -> None:
assert self._started
self._assert_started()

@override
async def get(self, service_id: ServiceId) -> Service:
assert self._started
self._assert_started()
async with await self._lock(service_id):
try:
return self._services[service_id]
Expand Down Expand Up @@ -108,7 +117,7 @@ async def _initialize(self, service_id: ServiceId) -> Service:
try:
service_factory = self._service_factories[service_id]
except KeyError:
raise _ServiceNotFound(f'Service "{service_id}" is unknown.')
raise ServiceNotFound(f'Service "{service_id}" is unknown.')
service_context = service_factory(self)
service = await service_context.__aenter__()
self._entered_service_contexts.append(service_context)
Expand Down
4 changes: 2 additions & 2 deletions betty/tests/service/test_default.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import pytest

from betty.service import _ServiceNotFound, ServiceContainer, CyclicDependency
from betty.service import ServiceNotFound, ServiceContainer, CyclicDependency
from betty.service._default import DefaultServiceContainerBuilder


Expand Down Expand Up @@ -36,7 +36,7 @@ async def test_without_services(self) -> None:
async def test_with_unknown_service(self) -> None:
builder = DefaultServiceContainerBuilder()
async with builder.build() as services:
with pytest.raises(_ServiceNotFound):
with pytest.raises(ServiceNotFound):
await services.get('UnknownServiceId')

async def test_with_as_is_service(self) -> None:
Expand Down

0 comments on commit c6c02ff

Please sign in to comment.