Skip to content

Commit

Permalink
Merge pull request #6557 from drew2a/refactoring/maybe_component
Browse files Browse the repository at this point in the history
Add maybe_component
  • Loading branch information
drew2a authored Nov 16, 2021
2 parents 9dfe1ab + 00dfd49 commit 8876ca4
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 3 deletions.
19 changes: 18 additions & 1 deletion src/tribler-core/tribler_core/components/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from asyncio import Event, create_task, gather, get_event_loop
from itertools import count
from pathlib import Path
from typing import Dict, List, Optional, Set, Type, TypeVar
from typing import Dict, List, Optional, Set, Type, TypeVar, Union

from tribler_common.simpledefs import STATEDIR_CHANNELS_DIR, STATEDIR_DB_DIR

Expand Down Expand Up @@ -113,6 +113,7 @@ def _reraise_startup_exception_in_separate_task(self):
async def exception_reraiser():
# the exception should be intercepted by event loop exception handler
raise self._startup_exception

get_event_loop().create_task(exception_reraiser())

def set_startup_exception(self, exc: Exception):
Expand All @@ -133,6 +134,11 @@ def __exit__(self, exc_type, exc_val, exc_tb):
T = TypeVar('T', bound='Component')


class NoneComponent:
def __getattr__(self, item):
return NoneComponent()


class Component:
tribler_should_stop_on_component_error = True

Expand Down Expand Up @@ -230,6 +236,17 @@ async def get_component(self, dependency: Type[T]) -> Optional[T]:

return dep

async def maybe_component(self, dependency: Type[T]) -> Union[T, NoneComponent]:
""" This method returns instance of the dependency in case this instance can be created
otherwise it returns instance of NoneComponent class
Example of using:
libtorrent_component = await self.maybe_component(LibtorrentComponent)
print(libtorrent_component.download_manager.libtorrent_port) # No NPE exception
"""
return await self.get_component(dependency) or NoneComponent()

def release_component(self, dependency: Type[T]):
dep = dependency.instance()
if dep:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from tribler_core.components.base import Component, MissedDependency, Session, SessionError
from tribler_core.components.base import Component, MissedDependency, NoneComponent, Session, SessionError

pytestmark = pytest.mark.asyncio

Expand Down Expand Up @@ -146,7 +146,7 @@ async def shutdown(self):
assert component.stopped


def test_session_context_manager(loop, tribler_config): # pylint: disable=unused-argument
def test_session_context_manager(loop, tribler_config): # pylint: disable=unused-argument
session1 = Session(tribler_config, [])
session2 = Session(tribler_config, [])
session3 = Session(tribler_config, [])
Expand All @@ -168,3 +168,22 @@ def test_session_context_manager(loop, tribler_config): # pylint: disable=unus

with pytest.raises(SessionError, match="Default session was not set"):
Session.current()


async def test_maybe_component(loop, tribler_config): # pylint: disable=unused-argument
class ComponentA(Component):
pass

class ComponentB(Component):
pass

session = Session(tribler_config, [ComponentA()])
with session:
await session.start()
component_a = await ComponentA.instance().maybe_component(ComponentA)
component_b = await ComponentA.instance().maybe_component(ComponentB)

assert isinstance(component_a, ComponentA)
assert isinstance(component_b, NoneComponent)
assert isinstance(component_b.any_attribute, NoneComponent)
assert isinstance(component_b.any_attribute.any_nested_attribute, NoneComponent)

0 comments on commit 8876ca4

Please sign in to comment.