1
Fork 0
mirror of https://github.com/RYGhub/royalnet.git synced 2024-11-23 11:34:18 +00:00

📖 Log more things

This commit is contained in:
Steffo 2021-04-14 01:45:13 +02:00
parent 0e986b6eb2
commit f61566ac24
Signed by: steffo
GPG key ID: 6965406171929D01
6 changed files with 107 additions and 15 deletions

View file

@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "royalnet" name = "royalnet"
version = "6.2.8" version = "6.2.9"
description = "A multipurpose bot framework" description = "A multipurpose bot framework"
authors = ["Stefano Pigozzi <me@steffo.eu>"] authors = ["Stefano Pigozzi <me@steffo.eu>"]
license = "AGPL-3.0-or-later" license = "AGPL-3.0-or-later"

View file

@ -69,6 +69,7 @@ class FullCommand(c.Conversation):
.. todo:: Document this. .. todo:: Document this.
""" """
# I have no idea what is wrong with this.
super().__init__(self.run) super().__init__(self.run)
if len(names) < 1: if len(names) < 1:

View file

@ -4,11 +4,14 @@ This module contains the base :class:`.PDA` class.
import asyncio import asyncio
import royalnet.royaltyping as t import royalnet.royaltyping as t
import logging
if t.TYPE_CHECKING: if t.TYPE_CHECKING:
from royalnet.engineer.pda.implementations.base import PDAImplementation from royalnet.engineer.pda.implementations.base import PDAImplementation
DispenserKey = t.TypeVar("DispenserKey") DispenserKey = t.TypeVar("DispenserKey")
log = logging.getLogger(__name__)
class PDA: class PDA:
""" """
@ -28,10 +31,14 @@ class PDA:
return len(self.implementations) return len(self.implementations)
async def _run(self): async def _run(self):
log.info("Running all implementations...")
await asyncio.gather(*[implementation.run() for implementation in self.implementations.values()]) await asyncio.gather(*[implementation.run() for implementation in self.implementations.values()])
log.fatal("All implementations have finished running?!")
def run(self): def run(self):
log.debug("Running blockingly all implementations...")
asyncio.run(self._run()) asyncio.run(self._run())
log.fatal("Blocking call has finished?!")
__all__ = ( __all__ = (

View file

@ -1,5 +1,5 @@
""" """
.. todo:: Document this. This module contains the base :class:`~royalnet.engineer.pda.extensions.base.PDAExtension`\\ .
""" """
import royalnet.royaltyping as t import royalnet.royaltyping as t
@ -9,17 +9,18 @@ import contextlib
class PDAExtension(metaclass=abc.ABCMeta): 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 @abc.abstractmethod
@contextlib.asynccontextmanager @contextlib.asynccontextmanager
async def kwargs(self, kwargs: t.Kwargs) -> t.Kwargs: 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 yield NotImplemented

View file

@ -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 royalnet.royaltyping as t
import sqlalchemy import sqlalchemy
import sqlalchemy.orm import sqlalchemy.orm
import contextlib import contextlib
import logging
from . import base from . import base
log = logging.getLogger(__name__)
class SQLAlchemyExtension(base.PDAExtension): 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__() super().__init__()
self.engine: sqlalchemy.engine.Engine = engine self.engine: sqlalchemy.engine.Engine = engine
"""
The :class:`sqlalchemy.engine.Engine` to use.
"""
self.Session: sqlalchemy.orm.sessionmaker = sqlalchemy.orm.sessionmaker(bind=self.engine) 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 {})} 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 @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: with self.Session(**self.session_kwargs) as session:
log.debug(f"{self!r}: Yielding kwargs...")
yield { yield {
**kwargs, **kwargs,
"_session": session, self.kwarg_name: session,
} }
log.debug(f"{self!r}: Closing session...")
log.debug(f"{self!r}: Session closed!")
__all__ = ( __all__ = (

View file

@ -6,6 +6,7 @@ import royalnet.royaltyping as t
import abc import abc
import contextlib import contextlib
import asyncio import asyncio
import logging
from royalnet.engineer.dispenser import Dispenser from royalnet.engineer.dispenser import Dispenser
if t.TYPE_CHECKING: if t.TYPE_CHECKING:
@ -39,6 +40,16 @@ class PDAImplementation(metaclass=abc.ABCMeta):
.. todo:: Document this. .. 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): def __repr__(self):
return f"<PDAImplementation {self.name}>" return f"<PDAImplementation {self.name}>"
@ -50,9 +61,13 @@ class PDAImplementation(metaclass=abc.ABCMeta):
.. todo:: Document this. .. todo:: Document this.
""" """
self.log.debug(f"Trying to bind to {pda!r}...")
if self.bound_to is not None: 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.bound_to = pda
self.log.info(f"Bound to {pda!r}!")
@property @property
@abc.abstractmethod @abc.abstractmethod
@ -65,6 +80,10 @@ class PDAImplementation(metaclass=abc.ABCMeta):
@abc.abstractmethod @abc.abstractmethod
async def run(self): async def run(self):
"""
.. todo:: Document this.
"""
raise NotImplementedError() raise NotImplementedError()
@ -74,7 +93,7 @@ class ImplementationException(Exception):
""" """
class ImplementationAlreadyBound(ImplementationException): class ImplementationAlreadyBoundError(ImplementationException):
""" """
.. todo:: Document this. .. todo:: Document this.
""" """
@ -107,6 +126,7 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
:return: The created :class:`list`\\ . :return: The created :class:`list`\\ .
""" """
self.log.debug(f"Creating conversations list...")
return [] return []
def _create_dispensers(self) -> dict[t.Any, "Dispenser"]: 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). :return: The created dictionary (empty by default).
""" """
self.log.debug(f"Creating dispensers list...")
return {} return {}
def get_dispenser(self, key: "DispenserKey") -> t.Optional["Dispenser"]: def get_dispenser(self, key: "DispenserKey") -> t.Optional["Dispenser"]:
@ -128,6 +149,7 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
.. seealso:: :meth:`dict.get` .. seealso:: :meth:`dict.get`
""" """
self.log.debug(f"Getting dispenser: {key!r}")
return self.dispensers.get(key) return self.dispensers.get(key)
def _create_dispenser(self) -> "Dispenser": def _create_dispenser(self) -> "Dispenser":
@ -137,6 +159,7 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
:return: The created dispenser. :return: The created dispenser.
""" """
self.log.debug(f"Creating new dispenser...")
return Dispenser() return Dispenser()
def get_or_create_dispenser(self, key: "DispenserKey") -> "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: 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() self.dispensers[key] = self._create_dispenser()
return self.get_dispenser(key=key) return self.get_dispenser(key=key)
@ -163,6 +187,8 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
:return: The corresponding :func:`contextlib.asynccontextmanager`\\ . :return: The corresponding :func:`contextlib.asynccontextmanager`\\ .
""" """
self.log.debug(f"Creating kwargs for: {conv!r}")
default_kwargs = { default_kwargs = {
"_pda": self.bound_to, "_pda": self.bound_to,
"_imp": self, "_imp": self,
@ -170,6 +196,7 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
} }
async with self._kwargs(default_kwargs, self.extensions) as kwargs: async with self._kwargs(default_kwargs, self.extensions) as kwargs:
self.log.info(f"Yielding kwargs for {conv!r}: {kwargs!r}")
yield kwargs yield kwargs
@contextlib.asynccontextmanager @contextlib.asynccontextmanager
@ -179,11 +206,15 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
""" """
if len(remaining) == 0: if len(remaining) == 0:
self.log.debug(f"Kwargs recursion ended!")
yield kwargs yield kwargs
else: else:
extension = remaining.pop(0) extension = remaining.pop(0)
self.log.debug(f"Getting kwargs from {extension}, {len(remaining)} left...")
async with extension.kwargs(kwargs) as kwargs: async with extension.kwargs(kwargs) as kwargs:
self.log.debug(f"Recursing...")
async with self._kwargs(kwargs=kwargs, remaining=remaining) as kwargs: async with self._kwargs(kwargs=kwargs, remaining=remaining) as kwargs:
self.log.debug(f"Bubbling up yields...")
yield kwargs yield kwargs
def register_conversation(self, conversation: "ConversationProtocol") -> None: 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. :param conversation: The :class:`~royalnet.engineer.conversation.Conversation` to register.
""" """
self.log.debug(f"Registering: {conversation!r}")
self.conversations.append(conversation) self.conversations.append(conversation)
def unregister_conversation(self, conversation: "ConversationProtocol") -> None: 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. :param conversation: The :class:`~royalnet.engineer.conversation.Conversation` to unregister.
""" """
self.log.debug(f"Unregistering: {conversation!r}")
self.conversations.remove(conversation) self.conversations.remove(conversation)
@abc.abstractmethod @abc.abstractmethod
@ -226,6 +259,7 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
:return: The completed :class:`~royalnet.engineer.command.FulLCommand` . :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)) return partial.complete(names=names, pattern=self._partialcommand_pattern(partial))
def register_partialcommand(self, partial: "PartialCommand", names: list[str]) -> "FullCommand": 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: async with self.kwargs(conv=conv) as kwargs:
self.log.debug(f"Running {conv!r} in {dispenser!r}...")
await dispenser.run(conv=conv, **kwargs) await dispenser.run(conv=conv, **kwargs)
async def _run_all_conversations(self, dispenser: "Dispenser") -> list[asyncio.Task]: async def _run_all_conversations(self, dispenser: "Dispenser") -> list[asyncio.Task]:
@ -254,11 +289,20 @@ class ConversationListImplementation(PDAImplementation, metaclass=abc.ABCMeta):
.. todo:: Document this. .. todo:: Document this.
""" """
self.log.info(f"Running in {dispenser!r} all conversations...")
tasks: list[asyncio.Task] = [] tasks: list[asyncio.Task] = []
for conv in self.conversations: 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)) task = asyncio.create_task(self._run_conversation(dispenser=dispenser, conv=conv))
tasks.append(task) tasks.append(task)
self.log.debug(f"Running a event loop cycle...")
await asyncio.sleep(0) await asyncio.sleep(0)
self.log.info(f"Tasks created: {tasks!r}")
return tasks return tasks
async def put_projectile(self, key: DispenserKey, projectile: "Projectile") -> None: 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. :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) dispenser = self.get_or_create_dispenser(key=key)
self.log.debug(f"Running all conversations...")
await self._run_all_conversations(dispenser=dispenser) await self._run_all_conversations(dispenser=dispenser)
self.log.debug(f"Putting {projectile!r} in {dispenser!r}...")
await dispenser.put(projectile) await dispenser.put(projectile)
self.log.debug(f"Running a event loop cycle...")
await asyncio.sleep(0) await asyncio.sleep(0)
__all__ = ( __all__ = (
"PDAImplementation", "PDAImplementation",
"ImplementationException", "ImplementationException",
"ImplementationAlreadyBound", "ImplementationAlreadyBoundError",
"ConversationListImplementation", "ConversationListImplementation",
) )