Source code for navmenu.menus

import collections.abc
from abc import ABC, abstractmethod
from typing import Iterator, Optional, Sequence

from .actions import Action
from .contents import BaseContent
from .items import BaseItem
from .responses import Message
from .keyboard import KeyboardButton, Keyboard


[docs]class BaseMenu(ABC): """A generic menu. Args: aliases: A sequence of strings that act as shortcuts to the menu. """ __slots__ = 'aliases', def __init__(self, aliases: Optional[Sequence[str]] = None): if aliases is None: aliases = [] self.aliases = aliases
[docs] @abstractmethod def select(self, action: str, payload=None) -> Optional[Iterator[Message]]: """Select an item based on action and payload and optionally return one or multiple messages. Args: action: A string indicating selected menu button. payload: An incoming message payload. Returns: None or a list of messages. """ pass
[docs] @abstractmethod def get_message(self, payload: Optional[dict] = None) -> Message: """Get a message representing the menu. Args: payload: An incoming message payload. Returns: A message representing the menu. """ pass
[docs] @abstractmethod def serialize(self) -> dict: """Serialize the class instance to a dictionary. Returns: A serialized class instance. """ res = {} if self.aliases: res['aliases'] = self.aliases return res
[docs] def enter(self, payload: Optional[dict] = None) -> Optional[Message]: """Enter the menu and optionally return a message. Args: payload: An incoming message payload. Returns: None or a message. """ pass
[docs]class CustomMenu(BaseMenu): """A menu that is controlled by a custom class. Args: handler: A class containing "select", "get_message" and "enter" methods. aliases: A sequence of strings that act as shortcuts to the menu. """ __slots__ = 'handler', def __init__(self, handler, aliases: Optional[Sequence[str]] = None) -> None: super().__init__(aliases) self.handler = handler def __repr__(self) -> str: return f'CustomMenu({self.handler})'
[docs] def select(self, action: str, payload: Optional[dict] = None) -> Optional[Iterator[Message]]: res = self.handler.select(action, payload) return res if isinstance(res, collections.abc.Sequence) else (res, )
[docs] def get_message(self, payload: Optional[dict] = None) -> Optional[Message]: return self.handler.get_message(payload)
[docs] def serialize(self) -> dict: res = { **super().serialize(), 'handler': self.handler.__name__, } return res
[docs] def enter(self, payload: Optional[dict] = None) -> Optional[Message]: return self.handler.enter(payload)