Update to Menu and Action
This commit is contained in:
79
menu/menu_utils.py
Normal file
79
menu/menu_utils.py
Normal file
@ -0,0 +1,79 @@
|
||||
import asyncio
|
||||
import time
|
||||
from itertools import islice
|
||||
|
||||
|
||||
def chunks(iterator, size):
|
||||
"""Yield successive n-sized chunks from an iterator."""
|
||||
iterator = iter(iterator)
|
||||
while True:
|
||||
chunk = list(islice(iterator, size))
|
||||
if not chunk:
|
||||
break
|
||||
yield chunk
|
||||
|
||||
|
||||
def run_async(coro):
|
||||
"""Run an async function in a synchronous context."""
|
||||
try:
|
||||
_ = asyncio.get_running_loop()
|
||||
return asyncio.create_task(coro)
|
||||
except RuntimeError:
|
||||
return asyncio.run(coro)
|
||||
|
||||
|
||||
class TimingMixin:
|
||||
def _start_timer(self):
|
||||
self.start_time = time.perf_counter()
|
||||
|
||||
def _stop_timer(self):
|
||||
self.end_time = time.perf_counter()
|
||||
self._duration = self.end_time - self.start_time
|
||||
|
||||
def get_duration(self) -> float | None:
|
||||
return getattr(self, "_duration", None)
|
||||
|
||||
|
||||
class MenuError(Exception):
|
||||
"""Custom exception for the Menu class."""
|
||||
|
||||
|
||||
class OptionAlreadyExistsError(MenuError):
|
||||
"""Exception raised when an option with the same key already exists in the menu."""
|
||||
|
||||
|
||||
class InvalidHookError(MenuError):
|
||||
"""Exception raised when a hook is not callable."""
|
||||
|
||||
|
||||
class InvalidActionError(MenuError):
|
||||
"""Exception raised when an action is not callable."""
|
||||
|
||||
|
||||
class NotAMenuError(MenuError):
|
||||
"""Exception raised when the provided submenu is not an instance of Menu."""
|
||||
|
||||
|
||||
class CaseInsensitiveDict(dict):
|
||||
"""A case-insensitive dictionary that treats all keys as uppercase."""
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
super().__setitem__(key.upper(), value)
|
||||
|
||||
def __getitem__(self, key):
|
||||
return super().__getitem__(key.upper())
|
||||
|
||||
def __contains__(self, key):
|
||||
return super().__contains__(key.upper())
|
||||
|
||||
def get(self, key, default=None):
|
||||
return super().get(key.upper(), default)
|
||||
|
||||
def pop(self, key, default=None):
|
||||
return super().pop(key.upper(), default)
|
||||
|
||||
def update(self, other=None, **kwargs):
|
||||
if other:
|
||||
other = {k.upper(): v for k, v in other.items()}
|
||||
kwargs = {k.upper(): v for k, v in kwargs.items()}
|
||||
super().update(other, **kwargs)
|
Reference in New Issue
Block a user