mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-11-23 03:24:20 +00:00
📖 Log more things
This commit is contained in:
parent
0e986b6eb2
commit
f61566ac24
6 changed files with 107 additions and 15 deletions
|
@ -1,6 +1,6 @@
|
|||
[tool.poetry]
|
||||
name = "royalnet"
|
||||
version = "6.2.8"
|
||||
version = "6.2.9"
|
||||
description = "A multipurpose bot framework"
|
||||
authors = ["Stefano Pigozzi <me@steffo.eu>"]
|
||||
license = "AGPL-3.0-or-later"
|
||||
|
|
|
@ -69,6 +69,7 @@ class FullCommand(c.Conversation):
|
|||
.. todo:: Document this.
|
||||
"""
|
||||
|
||||
# I have no idea what is wrong with this.
|
||||
super().__init__(self.run)
|
||||
|
||||
if len(names) < 1:
|
||||
|
|
|
@ -4,11 +4,14 @@ This module contains the base :class:`.PDA` class.
|
|||
|
||||
import asyncio
|
||||
import royalnet.royaltyping as t
|
||||
import logging
|
||||
|
||||
if t.TYPE_CHECKING:
|
||||
from royalnet.engineer.pda.implementations.base import PDAImplementation
|
||||
DispenserKey = t.TypeVar("DispenserKey")
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PDA:
|
||||
"""
|
||||
|
@ -28,10 +31,14 @@ class PDA:
|
|||
return len(self.implementations)
|
||||
|
||||
async def _run(self):
|
||||
log.info("Running all implementations...")
|
||||
await asyncio.gather(*[implementation.run() for implementation in self.implementations.values()])
|
||||
log.fatal("All implementations have finished running?!")
|
||||
|
||||
def run(self):
|
||||
log.debug("Running blockingly all implementations...")
|
||||
asyncio.run(self._run())
|
||||
log.fatal("Blocking call has finished?!")
|
||||
|
||||
|
||||
__all__ = (
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
"""
|
||||
.. todo:: Document this.
|
||||
This module contains the base :class:`~royalnet.engineer.pda.extensions.base.PDAExtension`\\ .
|
||||
"""
|
||||
|
||||
import royalnet.royaltyping as t
|
||||
|
@ -9,17 +9,18 @@ import contextlib
|
|||
|
||||
class PDAExtension(metaclass=abc.ABCMeta):
|
||||
"""
|
||||
.. todo:: Document this.
|
||||
A :class:`.PDAExtension` is an object which extends a
|
||||
:class:`~royalnet.engineer.pda.implementations.base.PDAImplementation` by providing additional kwargs to
|
||||
:class:`~royalnet.engineer.conversation.Conversation`\\ s.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
@contextlib.asynccontextmanager
|
||||
async def kwargs(self, kwargs: t.Kwargs) -> t.Kwargs:
|
||||
"""
|
||||
.. todo:: Document this.
|
||||
An :func:`~contextlib.asynccontextmanager` which takes the kwargs that would be passed to the
|
||||
:class:`~royalnet.engineer.conversation.Conversation`\\ , modifies them (for example by adding new items) and
|
||||
yields them, then performs cleanup operations.
|
||||
"""
|
||||
|
||||
yield NotImplemented
|
||||
|
|
|
@ -1,33 +1,65 @@
|
|||
"""
|
||||
.. todo:: Document this.
|
||||
This module contains the :class:`~royalnet.engineer.pda.extensions.base.PDAExtension`\\ s that allow
|
||||
:class:`~royalnet.engineer.conversation.Conversation`\\ s to access a database.
|
||||
"""
|
||||
|
||||
import royalnet.royaltyping as t
|
||||
import sqlalchemy
|
||||
import sqlalchemy.orm
|
||||
import contextlib
|
||||
import logging
|
||||
|
||||
from . import base
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SQLAlchemyExtension(base.PDAExtension):
|
||||
"""
|
||||
.. todo:: Document this.
|
||||
Extends a :class:`~royalnet.engineer.pda.implementations.base.PDAImplementation` by adding a :mod:`sqlalchemy`
|
||||
session to conversations through the ``_session`` kwarg.
|
||||
"""
|
||||
|
||||
def __init__(self, engine: sqlalchemy.engine.Engine, session_kwargs: t.Kwargs = None):
|
||||
def __init__(self, engine: sqlalchemy.engine.Engine, session_kwargs: t.Kwargs = None, kwarg_name: str = "_session"):
|
||||
super().__init__()
|
||||
self.engine: sqlalchemy.engine.Engine = engine
|
||||
"""
|
||||
The :class:`sqlalchemy.engine.Engine` to use.
|
||||
"""
|
||||
|
||||
self.Session: sqlalchemy.orm.sessionmaker = sqlalchemy.orm.sessionmaker(bind=self.engine)
|
||||
"""
|
||||
The :class:`sqlalchemy.orm.sessionmaker` to use when creating new sessions.
|
||||
"""
|
||||
|
||||
self.session_kwargs: t.Kwargs = {"future": True, **(session_kwargs or {})}
|
||||
"""
|
||||
Additional kwargs to be passed to the :class:`sqlalchemy.orm.sessionmaker` when instantiating a new Session.
|
||||
|
||||
Defaults to ``{"future": True}`` .
|
||||
"""
|
||||
|
||||
self.kwarg_name: str = kwarg_name
|
||||
"""
|
||||
The name of the kwarg to add.
|
||||
|
||||
Defaults to ``"_session"``.
|
||||
"""
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.__class__.__qualname__} with engine {self.engine}>"
|
||||
|
||||
@contextlib.asynccontextmanager
|
||||
async def kwargs(self, kwargs: dict[str, t.Any]) -> dict[str, t.Any]:
|
||||
async def kwargs(self, kwargs: t.Kwargs) -> t.Kwargs:
|
||||
log.debug(f"{self!r}: Creating session...")
|
||||
with self.Session(**self.session_kwargs) as session:
|
||||
log.debug(f"{self!r}: Yielding kwargs...")
|
||||
yield {
|
||||
**kwargs,
|
||||
"_session": session,
|
||||
self.kwarg_name: session,
|
||||
}
|
||||
log.debug(f"{self!r}: Closing session...")
|
||||
log.debug(f"{self!r}: Session closed!")
|
||||
|
||||
|
||||
__all__ = (
|
||||
|
|
|
@ -6,6 +6,7 @@ import royalnet.royaltyping as t
|
|||
import abc
|
||||
import contextlib
|
||||
import asyncio
|
||||
import logging
|
||||
from royalnet.engineer.dispenser import Dispenser
|
||||
|
||||
if t.TYPE_CHECKING:
|
||||
|
@ -39,6 +40,16 @@ class PDAImplementation(metaclass=abc.ABCMeta):
|
|||
.. todo:: Document this.
|
||||
"""
|
||||
|
||||
self.logger_name: str = f"{__name__}.PDAImplementation.{self.namespace}.{name}"
|
||||
"""
|
||||
.. todo:: Document this.
|
||||
"""
|
||||
|
||||
self.log: logging.Logger = logging.getLogger(self.logger_name)
|
||||
"""
|
||||
.. todo:: Document this.
|
||||
"""
|
||||
|
||||
def __repr__(self):
|
||||
return f"<PDAImplementation {self.name}>"
|
||||
|
||||
|
@ -50,9 +61,13 @@ class PDAImplementation(metaclass=abc.ABCMeta):
|
|||
.. todo:: Document this.
|
||||
"""
|
||||
|
||||
self.log.debug(f"Trying to bind to {pda!r}...")
|
||||
if self.bound_to is not None:
|
||||
raise ImplementationAlreadyBound()
|
||||
self.log.error(f"Already bound to {pda!r}!")
|
||||
raise ImplementationAlreadyBoundError()
|
||||
|
||||
self.bound_to = pda
|
||||
self.log.info(f"Bound to {pda!r}!")
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
|
@ -65,6 +80,10 @@ class PDAImplementation(metaclass=abc.ABCMeta):
|
|||
|
||||
@abc.abstractmethod
|
||||
async def run(self):
|
||||
"""
|
||||
.. todo:: Document this.
|
||||
"""
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
|
@ -74,7 +93,7 @@ class ImplementationException(Exception):
|
|||
"""
|
||||
|
||||
|
||||
class ImplementationAlreadyBound(ImplementationException):
|
||||
class ImplementationAlreadyBoundError(ImplementationException):
|
||||
"""
|
||||
.. todo:: Document this.
|
||||
"""
|
||||
|
@ -107,6 +126,7 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
|
|||
:return: The created :class:`list`\\ .
|
||||
"""
|
||||
|
||||
self.log.debug(f"Creating conversations list...")
|
||||
return []
|
||||
|
||||
def _create_dispensers(self) -> dict[t.Any, "Dispenser"]:
|
||||
|
@ -116,6 +136,7 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
|
|||
:return: The created dictionary (empty by default).
|
||||
"""
|
||||
|
||||
self.log.debug(f"Creating dispensers list...")
|
||||
return {}
|
||||
|
||||
def get_dispenser(self, key: "DispenserKey") -> t.Optional["Dispenser"]:
|
||||
|
@ -128,6 +149,7 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
|
|||
.. seealso:: :meth:`dict.get`
|
||||
"""
|
||||
|
||||
self.log.debug(f"Getting dispenser: {key!r}")
|
||||
return self.dispensers.get(key)
|
||||
|
||||
def _create_dispenser(self) -> "Dispenser":
|
||||
|
@ -137,6 +159,7 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
|
|||
:return: The created dispenser.
|
||||
"""
|
||||
|
||||
self.log.debug(f"Creating new dispenser...")
|
||||
return Dispenser()
|
||||
|
||||
def get_or_create_dispenser(self, key: "DispenserKey") -> "Dispenser":
|
||||
|
@ -145,6 +168,7 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
|
|||
"""
|
||||
|
||||
if key not in self.dispensers:
|
||||
self.log.debug(f"{self!r}: Dispenser {key!r} does not exist, creating a new one...")
|
||||
self.dispensers[key] = self._create_dispenser()
|
||||
return self.get_dispenser(key=key)
|
||||
|
||||
|
@ -162,6 +186,8 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
|
|||
:param conv: The :class:`~royalnet.engineer.conversation.Conversation` to create the args for.
|
||||
:return: The corresponding :func:`contextlib.asynccontextmanager`\\ .
|
||||
"""
|
||||
|
||||
self.log.debug(f"Creating kwargs for: {conv!r}")
|
||||
|
||||
default_kwargs = {
|
||||
"_pda": self.bound_to,
|
||||
|
@ -170,6 +196,7 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
|
|||
}
|
||||
|
||||
async with self._kwargs(default_kwargs, self.extensions) as kwargs:
|
||||
self.log.info(f"Yielding kwargs for {conv!r}: {kwargs!r}")
|
||||
yield kwargs
|
||||
|
||||
@contextlib.asynccontextmanager
|
||||
|
@ -179,11 +206,15 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
|
|||
"""
|
||||
|
||||
if len(remaining) == 0:
|
||||
self.log.debug(f"Kwargs recursion ended!")
|
||||
yield kwargs
|
||||
else:
|
||||
extension = remaining.pop(0)
|
||||
self.log.debug(f"Getting kwargs from {extension}, {len(remaining)} left...")
|
||||
async with extension.kwargs(kwargs) as kwargs:
|
||||
self.log.debug(f"Recursing...")
|
||||
async with self._kwargs(kwargs=kwargs, remaining=remaining) as kwargs:
|
||||
self.log.debug(f"Bubbling up yields...")
|
||||
yield kwargs
|
||||
|
||||
def register_conversation(self, conversation: "ConversationProtocol") -> None:
|
||||
|
@ -194,6 +225,7 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
|
|||
:param conversation: The :class:`~royalnet.engineer.conversation.Conversation` to register.
|
||||
"""
|
||||
|
||||
self.log.debug(f"Registering: {conversation!r}")
|
||||
self.conversations.append(conversation)
|
||||
|
||||
def unregister_conversation(self, conversation: "ConversationProtocol") -> None:
|
||||
|
@ -204,6 +236,7 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
|
|||
:param conversation: The :class:`~royalnet.engineer.conversation.Conversation` to unregister.
|
||||
"""
|
||||
|
||||
self.log.debug(f"Unregistering: {conversation!r}")
|
||||
self.conversations.remove(conversation)
|
||||
|
||||
@abc.abstractmethod
|
||||
|
@ -226,6 +259,7 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
|
|||
:return: The completed :class:`~royalnet.engineer.command.FulLCommand` .
|
||||
"""
|
||||
|
||||
self.log.debug(f"Completing: {names!r} → {partial!r}")
|
||||
return partial.complete(names=names, pattern=self._partialcommand_pattern(partial))
|
||||
|
||||
def register_partialcommand(self, partial: "PartialCommand", names: list[str]) -> "FullCommand":
|
||||
|
@ -247,6 +281,7 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
|
|||
"""
|
||||
|
||||
async with self.kwargs(conv=conv) as kwargs:
|
||||
self.log.debug(f"Running {conv!r} in {dispenser!r}...")
|
||||
await dispenser.run(conv=conv, **kwargs)
|
||||
|
||||
async def _run_all_conversations(self, dispenser: "Dispenser") -> list[asyncio.Task]:
|
||||
|
@ -254,11 +289,20 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
|
|||
.. todo:: Document this.
|
||||
"""
|
||||
|
||||
self.log.info(f"Running in {dispenser!r} all conversations...")
|
||||
|
||||
tasks: list[asyncio.Task] = []
|
||||
for conv in self.conversations:
|
||||
|
||||
self.log.debug(f"Creating task for: {conv!r}")
|
||||
task = asyncio.create_task(self._run_conversation(dispenser=dispenser, conv=conv))
|
||||
|
||||
tasks.append(task)
|
||||
|
||||
self.log.debug(f"Running a event loop cycle...")
|
||||
await asyncio.sleep(0)
|
||||
|
||||
self.log.info(f"Tasks created: {tasks!r}")
|
||||
return tasks
|
||||
|
||||
async def put_projectile(self, key: DispenserKey, projectile: "Projectile") -> None:
|
||||
|
@ -271,15 +315,22 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
|
|||
:param projectile: The :class:`~royalnet.engineer.bullet.projectile.Projectile` to insert.
|
||||
"""
|
||||
|
||||
self.log.debug(f"Finding dispenser {key!r} to put {projectile!r} in...")
|
||||
dispenser = self.get_or_create_dispenser(key=key)
|
||||
|
||||
self.log.debug(f"Running all conversations...")
|
||||
await self._run_all_conversations(dispenser=dispenser)
|
||||
|
||||
self.log.debug(f"Putting {projectile!r} in {dispenser!r}...")
|
||||
await dispenser.put(projectile)
|
||||
|
||||
self.log.debug(f"Running a event loop cycle...")
|
||||
await asyncio.sleep(0)
|
||||
|
||||
|
||||
__all__ = (
|
||||
"PDAImplementation",
|
||||
"ImplementationException",
|
||||
"ImplementationAlreadyBound",
|
||||
"ImplementationAlreadyBoundError",
|
||||
"ConversationListImplementation",
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue