Skip to content

Commit

Permalink
meh
Browse files Browse the repository at this point in the history
  • Loading branch information
bartfeenstra committed Apr 7, 2024
1 parent 4082797 commit c3187f3
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 10 deletions.
30 changes: 29 additions & 1 deletion betty/service.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""
Provide a service container.
"""
from __future__ import annotations

from collections import defaultdict
from collections.abc import Callable, MutableMapping, Mapping, Awaitable
from types import TracebackType
Expand Down Expand Up @@ -59,6 +61,31 @@ def build(self) -> ServiceContainer:
raise NotImplementedError


class _CyclicDependencyGuardServiceContainer(ServiceContainer):
def __init__(self, decorated: ServiceContainer, root_service_id: ServiceId):
self._decorated = decorated
self._seen_service_ids = [root_service_id]
self._lock = AsynchronizedLock.threading()

@override
async def get(self, service_id: ServiceId) -> Service:
print('GET')
print(self._seen_service_ids)
print(service_id)
if service_id in self._seen_service_ids:
raise _CyclicDependency([*self._seen_service_ids, service_id])
self._seen_service_ids.append(service_id)
return await self._decorated.get(service_id)

@override
async def start(self) -> None:
await self._decorated.start()

@override
async def stop(self) -> None:
await self._decorated.stop()


class _DefaultServiceContainer(ServiceContainer):
def __init__(self, service_factories: Mapping[ServiceId, ServiceFactory]):
self._service_factories = service_factories
Expand Down Expand Up @@ -86,7 +113,8 @@ async def _initialize(self, service_id: ServiceId) -> Service:
service_factory = self._service_factories[service_id]
except KeyError:
raise _ServiceNotFound(f'Service "{service_id}" is unknown.')
return await service_factory(self)
initializing_service_container = _CyclicDependencyGuardServiceContainer(self, service_id)
return await service_factory(initializing_service_container)

async def start(self) -> None:
assert not self._started
Expand Down
18 changes: 9 additions & 9 deletions betty/tests/test_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import pytest

from betty.service import _DefaultServiceContainerBuilder, ServiceId, _ServiceNotFound, ServiceContainer, \
from betty.service import _DefaultServiceContainerBuilder, _ServiceNotFound, ServiceContainer, \
_CyclicDependency


Expand All @@ -15,13 +15,13 @@ def __init__(self, dependency: DummyService):
pass


class DummyLeftHandCyclingDependencyService:
def __init__(self, dependency: DummyRightHandCyclingDependencyService):
class DummyLeftHandCyclicDependencyService:
def __init__(self, dependency: DummyRightHandCyclicDependencyService):
pass


class DummyRightHandCyclingDependencyService:
def __init__(self, dependency: DummyLeftHandCyclingDependencyService):
class DummyRightHandCyclicDependencyService:
def __init__(self, dependency: DummyLeftHandCyclicDependencyService):
pass


Expand Down Expand Up @@ -72,11 +72,11 @@ async def test_with_cyclic_dependency(self) -> None:
left_hand_dependency_service_id = 'MyFirstLeftHandDependency'
right_hand_dependency_service_id = 'MyFirstRightHandDependency'

async def _new_dummy_left_hand_dependency_service(services: ServiceContainer) -> DummyLeftHandCyclingDependencyService:
return DummyLeftHandCyclingDependencyService(await services.get(right_hand_dependency_service_id))
async def _new_dummy_left_hand_dependency_service(services: ServiceContainer) -> DummyLeftHandCyclicDependencyService:
return DummyLeftHandCyclicDependencyService(await services.get(right_hand_dependency_service_id))

async def _new_dummy_right_hand_dependency_service(services: ServiceContainer) -> DummyRightHandCyclingDependencyService:
return DummyRightHandCyclingDependencyService(await services.get(left_hand_dependency_service_id))
async def _new_dummy_right_hand_dependency_service(services: ServiceContainer) -> DummyRightHandCyclicDependencyService:
return DummyRightHandCyclicDependencyService(await services.get(left_hand_dependency_service_id))
builder = _DefaultServiceContainerBuilder()
builder.define(left_hand_dependency_service_id, service_factory=_new_dummy_left_hand_dependency_service)
builder.define(right_hand_dependency_service_id, service_factory=_new_dummy_right_hand_dependency_service)
Expand Down

0 comments on commit c3187f3

Please sign in to comment.