mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-11-29 22:44:19 +00:00
💥 Documentation and error handling
This commit is contained in:
parent
3586bd7493
commit
f21c77a0d7
3 changed files with 79 additions and 21 deletions
|
@ -114,13 +114,20 @@ class FullCommand:
|
|||
|
||||
def __call__(self, *, _sentry: s.Sentry, **kwargs) -> t.Awaitable[t.Optional[c.ConversationProtocol]]:
|
||||
"""
|
||||
.. todo:: Document this.
|
||||
:return: Get the awaitable of the :class:`.FullCommand`.
|
||||
|
||||
.. seealso:: :meth:`.run`
|
||||
"""
|
||||
return self.run(_sentry=_sentry, **kwargs)
|
||||
|
||||
async def run(self, *, _sentry: s.Sentry, **kwargs) -> t.Optional[c.ConversationProtocol]:
|
||||
"""
|
||||
.. todo:: Document this.
|
||||
Run the command.
|
||||
|
||||
:param _sentry: The :class:`~royalnet.engineer.sentry.Sentry` the command should use to receive
|
||||
:class:`~royalnet.engineer.bullet.projectiles.Projectile`\\ s.
|
||||
:param kwargs: Additional kwargs to pass to the :attr:`.teleported_f` .
|
||||
:return: :data:`None` or another :class:`~royalnet.engineer.conversation.Conversation` to switch to.
|
||||
"""
|
||||
|
||||
log.debug(f"Awaiting a bullet...")
|
||||
|
|
|
@ -46,7 +46,7 @@ class Dispenser:
|
|||
A :class:`list` of all the running sentries of this dispenser.
|
||||
"""
|
||||
|
||||
self._locked_by: t.List[ConversationProtocol] = []
|
||||
self.locked_by: t.List[ConversationProtocol] = []
|
||||
"""
|
||||
The conversation that are currently locking this dispenser.
|
||||
|
||||
|
@ -91,10 +91,10 @@ class Dispenser:
|
|||
"""
|
||||
log.debug(f"Trying to run: {conv!r}")
|
||||
|
||||
if self._locked_by:
|
||||
log.debug(f"Dispenser is locked by {self._locked_by!r}, refusing to run {conv!r}")
|
||||
if self.locked_by:
|
||||
log.debug(f"Dispenser is locked by {self.locked_by!r}, refusing to run {conv!r}")
|
||||
raise LockedDispenserError(
|
||||
f"The Dispenser is currently locked and cannot start any new Conversation.", self._locked_by)
|
||||
f"The Dispenser is currently locked and cannot start any new Conversation.", self.locked_by)
|
||||
|
||||
log.debug(f"Running: {conv!r}")
|
||||
with self.sentry() as sentry:
|
||||
|
@ -114,16 +114,16 @@ class Dispenser:
|
|||
|
||||
:param conv: The conversation that requested the lock.
|
||||
|
||||
.. seealso:: :attr:`._locked_by`
|
||||
.. seealso:: :attr:`.locked_by`
|
||||
"""
|
||||
log.debug(f"Adding lock: {conv!r}")
|
||||
self._locked_by.append(conv)
|
||||
self.locked_by.append(conv)
|
||||
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
log.debug(f"Clearing lock: {conv!r}")
|
||||
self._locked_by.remove(conv)
|
||||
self.locked_by.remove(conv)
|
||||
|
||||
|
||||
__all__ = (
|
||||
|
|
|
@ -7,7 +7,7 @@ import abc
|
|||
import contextlib
|
||||
import asyncio
|
||||
import logging
|
||||
from royalnet.engineer.dispenser import Dispenser
|
||||
from royalnet.engineer.dispenser import Dispenser, LockedDispenserError
|
||||
|
||||
if t.TYPE_CHECKING:
|
||||
from royalnet.engineer.conversation import ConversationProtocol
|
||||
|
@ -154,9 +154,9 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
|
|||
|
||||
def _create_dispenser(self) -> "Dispenser":
|
||||
"""
|
||||
Create a new dispenser.
|
||||
Create a new :class:`~royalnet.engineer.dispenser.Dispenser` .
|
||||
|
||||
:return: The created dispenser.
|
||||
:return: The created :class:`~royalnet.engineer.dispenser.Dispenser` .
|
||||
"""
|
||||
|
||||
self.log.debug(f"Creating new dispenser...")
|
||||
|
@ -164,7 +164,11 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
|
|||
|
||||
def get_or_create_dispenser(self, key: "DispenserKey") -> "Dispenser":
|
||||
"""
|
||||
.. todo:: Document this.
|
||||
Try to :meth:`.get_dispenser` the :class:`~royalnet.engineer.dispenser.Dispenser` with the specified key, or
|
||||
:meth:`._create_dispenser` a new one if it isn't available.
|
||||
|
||||
:param key: The key of the :class:`~royalnet.engineer.dispenser.Dispenser` .
|
||||
:return: The retrieved or created :class:`~royalnet.engineer.dispenser.Dispenser` .
|
||||
"""
|
||||
|
||||
if key not in self.dispensers:
|
||||
|
@ -202,7 +206,12 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
|
|||
@contextlib.asynccontextmanager
|
||||
async def _kwargs(self, kwargs: t.Kwargs, remaining: list["PDAExtension"]) -> t.Kwargs:
|
||||
"""
|
||||
.. todo:: Document this.
|
||||
:func:`contextlib.asynccontextmanager` factory used internally to recurse the generation and cleanup of
|
||||
:meth:`kwargs` .
|
||||
|
||||
:param kwargs: The current ``kwargs`` .
|
||||
:param remaining: The extensions that haven't been processed yet.
|
||||
:return: The corresponding :func:`contextlib.asynccontextmanager`\\ .
|
||||
"""
|
||||
|
||||
if len(remaining) == 0:
|
||||
|
@ -277,17 +286,59 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
|
|||
|
||||
async def _run_conversation(self, dispenser: "Dispenser", conv: "ConversationProtocol") -> None:
|
||||
"""
|
||||
.. todo:: Document this.
|
||||
Run the passed :class:`~royalnet.engineer.conversation.Conversation` in the passed
|
||||
:class:`~royalnet.engineer.dispenser.Dispenser`\\ , while passing the :meth:`.kwargs` provided by the
|
||||
:class:`.PDA` .
|
||||
|
||||
:param dispenser: The :class:`~royalnet.engineer.dispenser.Dispenser` to run the
|
||||
:class:`~royalnet.engineer.conversation.Conversation` in.
|
||||
:param conv: The :class:`~royalnet.engineer.conversation.Conversation` to run.
|
||||
"""
|
||||
|
||||
try:
|
||||
async with self.kwargs(conv=conv) as kwargs:
|
||||
self.log.debug(f"Running {conv!r} in {dispenser!r}...")
|
||||
await dispenser.run(conv=conv, **kwargs)
|
||||
except Exception as exception:
|
||||
try:
|
||||
await self._handle_conversation_exc(dispenser=dispenser, conv=conv, exception=exception)
|
||||
except Exception as exception:
|
||||
self.log.error(f"Failed to handle conversation exception: {exception!r}")
|
||||
|
||||
async def _run_all_conversations(self, dispenser: "Dispenser") -> list[asyncio.Task]:
|
||||
@abc.abstractmethod
|
||||
async def _handle_conversation_exc(
|
||||
self,
|
||||
dispenser: "Dispenser",
|
||||
conv: "ConversationProtocol",
|
||||
exception: Exception
|
||||
) -> None:
|
||||
"""
|
||||
.. todo:: Document this.
|
||||
Handle :exc:`Exception`\\ s that were not caught by :class:`~royalnet.engineer.conversation.Conversation`\\ s.
|
||||
|
||||
:param dispenser: The dispenser which hosted the :class:`~royalnet.engineer.conversation.Conversation`\\ .
|
||||
:param conv: The :class:`~royalnet.engineer.conversation.Conversation` which didn't catch the error.
|
||||
:param exception: The :class:`Exception` that was raised.
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
async def _schedule_conversations(self, dispenser: "Dispenser") -> list[asyncio.Task]:
|
||||
"""
|
||||
Schedule the execution of instance of all the :class:`~royalnet.engineer.conversation.Conversation`\\ s listed
|
||||
in :attr:`.conversations` in the specified :class:`~royalnet.engineer.dispenser.Dispenser`\\ .
|
||||
|
||||
:param dispenser: The :class:`~royalnet.engineer.dispenser.Dispenser` to run the
|
||||
:class:`~royalnet.engineer.conversation.Conversation`\\ s in.
|
||||
:return: The :class:`list` of :class:`asyncio.Task`\\ s that were created.
|
||||
|
||||
.. seealso:: :meth:`._run_conversation`
|
||||
"""
|
||||
|
||||
if dispenser.locked_by:
|
||||
self.log.warning("Tried to run a Conversation in a locked Dispenser!")
|
||||
raise LockedDispenserError(
|
||||
f"The Dispenser is currently locked and cannot start any new Conversation.",
|
||||
dispenser.locked_by
|
||||
)
|
||||
|
||||
self.log.info(f"Running in {dispenser!r} all conversations...")
|
||||
|
||||
|
@ -319,7 +370,7 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
|
|||
dispenser = self.get_or_create_dispenser(key=key)
|
||||
|
||||
self.log.debug(f"Running all conversations...")
|
||||
await self._run_all_conversations(dispenser=dispenser)
|
||||
await self._schedule_conversations(dispenser=dispenser)
|
||||
|
||||
self.log.debug(f"Putting {projectile!r} in {dispenser!r}...")
|
||||
await dispenser.put(projectile)
|
||||
|
|
Loading…
Reference in a new issue