refactor(playout): add more typings
This commit is contained in:
parent
a32d9d25f1
commit
719464a272
|
@ -47,7 +47,7 @@ class StatsCollector:
|
||||||
) -> Dict[str, Stats]:
|
) -> Dict[str, Stats]:
|
||||||
response = self._session.get(
|
response = self._session.get(
|
||||||
url=self.get_output_url(output),
|
url=self.get_output_url(output),
|
||||||
auth=(output.admin_user, output.admin_password),
|
auth=(output.admin_user, output.admin_password or ""),
|
||||||
timeout=self._timeout,
|
timeout=self._timeout,
|
||||||
)
|
)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
@ -90,7 +90,7 @@ class StatsCollector:
|
||||||
outputs: List[AnyOutput],
|
outputs: List[AnyOutput],
|
||||||
*,
|
*,
|
||||||
_timestamp: Optional[datetime] = None,
|
_timestamp: Optional[datetime] = None,
|
||||||
):
|
) -> None:
|
||||||
if _timestamp is None:
|
if _timestamp is None:
|
||||||
_timestamp = datetime.utcnow()
|
_timestamp = datetime.utcnow()
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ class StatsCollectorThread(Thread):
|
||||||
self._config = config
|
self._config = config
|
||||||
self._collector = StatsCollector(legacy_client)
|
self._collector = StatsCollector(legacy_client)
|
||||||
|
|
||||||
def run(self):
|
def run(self) -> None:
|
||||||
logger.info("starting %s", self.name)
|
logger.info("starting %s", self.name)
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -38,10 +38,10 @@ class LiquidsoapClient:
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _quote(self, value: Any):
|
def _quote(self, value: Any) -> str:
|
||||||
return quote(value, double=True)
|
return quote(value, double=True)
|
||||||
|
|
||||||
def _set_var(self, name: str, value: Any):
|
def _set_var(self, name: str, value: Any) -> None:
|
||||||
self.conn.write(f"var.set {name} = {value}")
|
self.conn.write(f"var.set {name} = {value}")
|
||||||
result = self.conn.read()
|
result = self.conn.read()
|
||||||
if f"Variable {name} set" not in result:
|
if f"Variable {name} set" not in result:
|
||||||
|
@ -126,16 +126,18 @@ class LiquidsoapClient:
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
station_name: Optional[str] = None,
|
station_name: Optional[str] = None,
|
||||||
message_format: Optional[Union[MessageFormatKind, str]] = None,
|
message_format: Optional[Union[MessageFormatKind, int]] = None,
|
||||||
message_offline: Optional[str] = None,
|
message_offline: Optional[str] = None,
|
||||||
input_fade_transition: Optional[float] = None,
|
input_fade_transition: Optional[float] = None,
|
||||||
):
|
) -> None:
|
||||||
with self.conn:
|
with self.conn:
|
||||||
if station_name is not None:
|
if station_name is not None:
|
||||||
self._set_var("station_name", self._quote(station_name))
|
self._set_var("station_name", self._quote(station_name))
|
||||||
if message_format is not None:
|
if message_format is not None:
|
||||||
if isinstance(message_format, MessageFormatKind):
|
if isinstance(message_format, MessageFormatKind):
|
||||||
message_format = message_format.value
|
message_format = message_format.value
|
||||||
|
# Use an interactive.string until Liquidsoap have interactive.int
|
||||||
|
# variables
|
||||||
self._set_var("message_format", self._quote(message_format))
|
self._set_var("message_format", self._quote(message_format))
|
||||||
if message_offline is not None:
|
if message_offline is not None:
|
||||||
self._set_var("message_offline", self._quote(message_offline))
|
self._set_var("message_offline", self._quote(message_offline))
|
||||||
|
|
|
@ -46,8 +46,8 @@ class LiquidsoapConnection:
|
||||||
self._port = port
|
self._port = port
|
||||||
self._timeout = timeout
|
self._timeout = timeout
|
||||||
|
|
||||||
def address(self):
|
def address(self) -> str:
|
||||||
return f"{self._host}:{self._port}" if self._path is None else self._path
|
return f"{self._host}:{self._port}" if self._path is None else str(self._path)
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -36,7 +36,7 @@ for module in ("amqp",):
|
||||||
logging.getLogger(module).propagate = False
|
logging.getLogger(module).propagate = False
|
||||||
|
|
||||||
|
|
||||||
def wait_for_legacy(legacy_client: LegacyClient):
|
def wait_for_legacy(legacy_client: LegacyClient) -> None:
|
||||||
while not legacy_client.is_server_compatible():
|
while not legacy_client.is_server_compatible():
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ def wait_for_legacy(legacy_client: LegacyClient):
|
||||||
time.sleep(10)
|
time.sleep(10)
|
||||||
|
|
||||||
|
|
||||||
def wait_for_liquidsoap(liq_client: LiquidsoapClient):
|
def wait_for_liquidsoap(liq_client: LiquidsoapClient) -> None:
|
||||||
logger.debug("Checking if Liquidsoap is running")
|
logger.debug("Checking if Liquidsoap is running")
|
||||||
liq_version = liq_client.wait_for_version()
|
liq_version = liq_client.wait_for_version()
|
||||||
if not LIQUIDSOAP_MIN_VERSION <= liq_version:
|
if not LIQUIDSOAP_MIN_VERSION <= liq_version:
|
||||||
|
@ -64,7 +64,11 @@ def wait_for_liquidsoap(liq_client: LiquidsoapClient):
|
||||||
@click.command(context_settings={"auto_envvar_prefix": DEFAULT_ENV_PREFIX})
|
@click.command(context_settings={"auto_envvar_prefix": DEFAULT_ENV_PREFIX})
|
||||||
@cli_logging_options()
|
@cli_logging_options()
|
||||||
@cli_config_options()
|
@cli_config_options()
|
||||||
def cli(log_level: str, log_filepath: Optional[Path], config_filepath: Optional[Path]):
|
def cli(
|
||||||
|
log_level: str,
|
||||||
|
log_filepath: Optional[Path],
|
||||||
|
config_filepath: Optional[Path],
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Run playout.
|
Run playout.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -34,7 +34,7 @@ class MessageHandler(ConsumerMixin):
|
||||||
Consumer(queues, callbacks=[self.on_message], accept=["text/plain"]),
|
Consumer(queues, callbacks=[self.on_message], accept=["text/plain"]),
|
||||||
]
|
]
|
||||||
|
|
||||||
def on_message(self, body, message: Message):
|
def on_message(self, body, message: Message) -> None:
|
||||||
logger.debug("received message: %s", body)
|
logger.debug("received message: %s", body)
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
|
@ -76,7 +76,7 @@ class MessageListener:
|
||||||
self.config = config
|
self.config = config
|
||||||
self.fetch_queue = fetch_queue
|
self.fetch_queue = fetch_queue
|
||||||
|
|
||||||
def run_forever(self):
|
def run_forever(self) -> None:
|
||||||
while True:
|
while True:
|
||||||
with Connection(
|
with Connection(
|
||||||
self.config.rabbitmq.url,
|
self.config.rabbitmq.url,
|
||||||
|
|
|
@ -7,7 +7,7 @@ from pathlib import Path
|
||||||
from queue import Empty, Queue
|
from queue import Empty, Queue
|
||||||
from subprocess import DEVNULL, PIPE, run
|
from subprocess import DEVNULL, PIPE, run
|
||||||
from threading import Thread, Timer
|
from threading import Thread, Timer
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict, Union
|
||||||
|
|
||||||
from libretime_api_client.v1 import ApiClient as LegacyClient
|
from libretime_api_client.v1 import ApiClient as LegacyClient
|
||||||
from libretime_api_client.v2 import ApiClient
|
from libretime_api_client.v2 import ApiClient
|
||||||
|
@ -15,7 +15,7 @@ from requests import RequestException
|
||||||
|
|
||||||
from ..config import CACHE_DIR, POLL_INTERVAL, Config
|
from ..config import CACHE_DIR, POLL_INTERVAL, Config
|
||||||
from ..liquidsoap.client import LiquidsoapClient
|
from ..liquidsoap.client import LiquidsoapClient
|
||||||
from ..liquidsoap.models import Info, StreamPreferences, StreamState
|
from ..liquidsoap.models import Info, MessageFormatKind, StreamPreferences, StreamState
|
||||||
from ..timeout import ls_timeout
|
from ..timeout import ls_timeout
|
||||||
from .events import EventKind, Events, FileEvent, FileEvents, event_key_to_datetime
|
from .events import EventKind, Events, FileEvent, FileEvents, event_key_to_datetime
|
||||||
from .liquidsoap import PypoLiquidsoap
|
from .liquidsoap import PypoLiquidsoap
|
||||||
|
@ -75,7 +75,7 @@ class PypoFetch(Thread):
|
||||||
# Handle a message from RabbitMQ, put it into our yucky global var.
|
# Handle a message from RabbitMQ, put it into our yucky global var.
|
||||||
# Hopefully there is a better way to do this.
|
# Hopefully there is a better way to do this.
|
||||||
|
|
||||||
def handle_message(self, message: Dict[str, Any]):
|
def handle_message(self, message: Dict[str, Any]) -> None:
|
||||||
try:
|
try:
|
||||||
command = message["event_type"]
|
command = message["event_type"]
|
||||||
logger.debug("handling event %s: %s", command, message)
|
logger.debug("handling event %s: %s", command, message)
|
||||||
|
@ -123,7 +123,7 @@ class PypoFetch(Thread):
|
||||||
logger.exception(exception)
|
logger.exception(exception)
|
||||||
|
|
||||||
# Initialize Liquidsoap environment
|
# Initialize Liquidsoap environment
|
||||||
def set_bootstrap_variables(self):
|
def set_bootstrap_variables(self) -> None:
|
||||||
logger.debug("Getting information needed on bootstrap from Airtime")
|
logger.debug("Getting information needed on bootstrap from Airtime")
|
||||||
try:
|
try:
|
||||||
info = Info(**self.api_client.get_info().json())
|
info = Info(**self.api_client.get_info().json())
|
||||||
|
@ -168,28 +168,31 @@ class PypoFetch(Thread):
|
||||||
self.pypo_liquidsoap.clear_queue_tracker()
|
self.pypo_liquidsoap.clear_queue_tracker()
|
||||||
|
|
||||||
@ls_timeout
|
@ls_timeout
|
||||||
def update_liquidsoap_stream_format(self, stream_format):
|
def update_liquidsoap_stream_format(
|
||||||
|
self,
|
||||||
|
stream_format: Union[MessageFormatKind, int],
|
||||||
|
) -> None:
|
||||||
try:
|
try:
|
||||||
self.liq_client.settings_update(message_format=stream_format)
|
self.liq_client.settings_update(message_format=stream_format)
|
||||||
except (ConnectionError, TimeoutError) as exception:
|
except (ConnectionError, TimeoutError) as exception:
|
||||||
logger.exception(exception)
|
logger.exception(exception)
|
||||||
|
|
||||||
@ls_timeout
|
@ls_timeout
|
||||||
def update_liquidsoap_message_offline(self, message_offline: str):
|
def update_liquidsoap_message_offline(self, message_offline: str) -> None:
|
||||||
try:
|
try:
|
||||||
self.liq_client.settings_update(message_offline=message_offline)
|
self.liq_client.settings_update(message_offline=message_offline)
|
||||||
except (ConnectionError, TimeoutError) as exception:
|
except (ConnectionError, TimeoutError) as exception:
|
||||||
logger.exception(exception)
|
logger.exception(exception)
|
||||||
|
|
||||||
@ls_timeout
|
@ls_timeout
|
||||||
def update_liquidsoap_transition_fade(self, fade):
|
def update_liquidsoap_transition_fade(self, fade: float) -> None:
|
||||||
try:
|
try:
|
||||||
self.liq_client.settings_update(input_fade_transition=fade)
|
self.liq_client.settings_update(input_fade_transition=fade)
|
||||||
except (ConnectionError, TimeoutError) as exception:
|
except (ConnectionError, TimeoutError) as exception:
|
||||||
logger.exception(exception)
|
logger.exception(exception)
|
||||||
|
|
||||||
@ls_timeout
|
@ls_timeout
|
||||||
def update_liquidsoap_station_name(self, station_name):
|
def update_liquidsoap_station_name(self, station_name: str) -> None:
|
||||||
try:
|
try:
|
||||||
self.liq_client.settings_update(station_name=station_name)
|
self.liq_client.settings_update(station_name=station_name)
|
||||||
except (ConnectionError, TimeoutError) as exception:
|
except (ConnectionError, TimeoutError) as exception:
|
||||||
|
@ -204,7 +207,7 @@ class PypoFetch(Thread):
|
||||||
# (Folder-structure: cache/YYYY-MM-DD-hh-mm-ss)
|
# (Folder-structure: cache/YYYY-MM-DD-hh-mm-ss)
|
||||||
# - runs the cleanup routine, to get rid of unused cached files
|
# - runs the cleanup routine, to get rid of unused cached files
|
||||||
|
|
||||||
def process_schedule(self, events: Events):
|
def process_schedule(self, events: Events) -> None:
|
||||||
self.last_update_schedule_timestamp = time.time()
|
self.last_update_schedule_timestamp = time.time()
|
||||||
logger.debug(events)
|
logger.debug(events)
|
||||||
file_events: FileEvents = {}
|
file_events: FileEvents = {}
|
||||||
|
@ -300,7 +303,7 @@ class PypoFetch(Thread):
|
||||||
"Problem removing file '%s': %s", expired_file, exception
|
"Problem removing file '%s': %s", expired_file, exception
|
||||||
)
|
)
|
||||||
|
|
||||||
def manual_schedule_fetch(self):
|
def manual_schedule_fetch(self) -> bool:
|
||||||
try:
|
try:
|
||||||
self.schedule_data = get_schedule(self.api_client)
|
self.schedule_data = get_schedule(self.api_client)
|
||||||
logger.debug("Received event from API client: %s", self.schedule_data)
|
logger.debug("Received event from API client: %s", self.schedule_data)
|
||||||
|
@ -310,7 +313,7 @@ class PypoFetch(Thread):
|
||||||
logger.exception("Unable to fetch schedule: %s", exception)
|
logger.exception("Unable to fetch schedule: %s", exception)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def persistent_manual_schedule_fetch(self, max_attempts=1):
|
def persistent_manual_schedule_fetch(self, max_attempts=1) -> bool:
|
||||||
success = False
|
success = False
|
||||||
num_attempts = 0
|
num_attempts = 0
|
||||||
while not success and num_attempts < max_attempts:
|
while not success and num_attempts < max_attempts:
|
||||||
|
|
|
@ -33,7 +33,7 @@ class PypoLiquidsoap:
|
||||||
list(self.liq_queue_tracker.keys()),
|
list(self.liq_queue_tracker.keys()),
|
||||||
)
|
)
|
||||||
|
|
||||||
def play(self, media_item: AnyEvent):
|
def play(self, media_item: AnyEvent) -> None:
|
||||||
if media_item["type"] == EventKind.FILE:
|
if media_item["type"] == EventKind.FILE:
|
||||||
self.handle_file_type(media_item)
|
self.handle_file_type(media_item)
|
||||||
elif media_item["type"] == EventKind.ACTION:
|
elif media_item["type"] == EventKind.ACTION:
|
||||||
|
@ -57,7 +57,7 @@ class PypoLiquidsoap:
|
||||||
else:
|
else:
|
||||||
raise UnknownMediaItemType(str(media_item))
|
raise UnknownMediaItemType(str(media_item))
|
||||||
|
|
||||||
def handle_file_type(self, media_item: FileEvent):
|
def handle_file_type(self, media_item: FileEvent) -> None:
|
||||||
"""
|
"""
|
||||||
Wait 200 seconds (2000 iterations) for file to become ready,
|
Wait 200 seconds (2000 iterations) for file to become ready,
|
||||||
otherwise give up on it.
|
otherwise give up on it.
|
||||||
|
@ -82,13 +82,13 @@ class PypoLiquidsoap:
|
||||||
media_item["dst"],
|
media_item["dst"],
|
||||||
)
|
)
|
||||||
|
|
||||||
def handle_event_type(self, media_item: ActionEvent):
|
def handle_event_type(self, media_item: ActionEvent) -> None:
|
||||||
if media_item["event_type"] == "kick_out":
|
if media_item["event_type"] == "kick_out":
|
||||||
self.telnet_liquidsoap.disconnect_source("live_dj")
|
self.telnet_liquidsoap.disconnect_source("live_dj")
|
||||||
elif media_item["event_type"] == "switch_off":
|
elif media_item["event_type"] == "switch_off":
|
||||||
self.telnet_liquidsoap.switch_source("live_dj", "off")
|
self.telnet_liquidsoap.switch_source("live_dj", "off")
|
||||||
|
|
||||||
def is_media_item_finished(self, media_item: Optional[AnyEvent]):
|
def is_media_item_finished(self, media_item: Optional[AnyEvent]) -> bool:
|
||||||
if media_item is None:
|
if media_item is None:
|
||||||
return True
|
return True
|
||||||
return datetime.utcnow() > event_key_to_datetime(media_item["end"])
|
return datetime.utcnow() > event_key_to_datetime(media_item["end"])
|
||||||
|
@ -106,7 +106,7 @@ class PypoLiquidsoap:
|
||||||
return available_queue
|
return available_queue
|
||||||
|
|
||||||
# pylint: disable=too-many-branches
|
# pylint: disable=too-many-branches
|
||||||
def verify_correct_present_media(self, scheduled_now: List[AnyEvent]):
|
def verify_correct_present_media(self, scheduled_now: List[AnyEvent]) -> None:
|
||||||
"""
|
"""
|
||||||
verify whether Liquidsoap is currently playing the correct files.
|
verify whether Liquidsoap is currently playing the correct files.
|
||||||
if we find an item that Liquidsoap is not playing, then push it
|
if we find an item that Liquidsoap is not playing, then push it
|
||||||
|
@ -213,18 +213,18 @@ class PypoLiquidsoap:
|
||||||
except KeyError as exception:
|
except KeyError as exception:
|
||||||
logger.exception("Malformed event in schedule: %s", exception)
|
logger.exception("Malformed event in schedule: %s", exception)
|
||||||
|
|
||||||
def stop(self, queue_id: int):
|
def stop(self, queue_id: int) -> None:
|
||||||
self.telnet_liquidsoap.queue_remove(queue_id)
|
self.telnet_liquidsoap.queue_remove(queue_id)
|
||||||
self.liq_queue_tracker[queue_id] = None
|
self.liq_queue_tracker[queue_id] = None
|
||||||
|
|
||||||
def is_file(self, event: AnyEvent):
|
def is_file(self, event: AnyEvent) -> bool:
|
||||||
return event["type"] == EventKind.FILE
|
return event["type"] == EventKind.FILE
|
||||||
|
|
||||||
def clear_queue_tracker(self):
|
def clear_queue_tracker(self) -> None:
|
||||||
for queue_id in self.liq_queue_tracker:
|
for queue_id in self.liq_queue_tracker:
|
||||||
self.liq_queue_tracker[queue_id] = None
|
self.liq_queue_tracker[queue_id] = None
|
||||||
|
|
||||||
def modify_cue_point(self, link: FileEvent):
|
def modify_cue_point(self, link: FileEvent) -> None:
|
||||||
assert self.is_file(link)
|
assert self.is_file(link)
|
||||||
|
|
||||||
lateness = seconds_between(
|
lateness = seconds_between(
|
||||||
|
@ -237,7 +237,7 @@ class PypoLiquidsoap:
|
||||||
cue_in_orig = timedelta(seconds=float(link["cue_in"]))
|
cue_in_orig = timedelta(seconds=float(link["cue_in"]))
|
||||||
link["cue_in"] = cue_in_orig.total_seconds() + lateness
|
link["cue_in"] = cue_in_orig.total_seconds() + lateness
|
||||||
|
|
||||||
def clear_all_queues(self):
|
def clear_all_queues(self) -> None:
|
||||||
self.telnet_liquidsoap.queue_clear_all()
|
self.telnet_liquidsoap.queue_clear_all()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,11 +14,11 @@ from .queue import PypoLiqQueue
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def is_stream(media_item):
|
def is_stream(media_item: AnyEvent) -> bool:
|
||||||
return media_item["type"] == "stream_output_start"
|
return media_item["type"] == "stream_output_start"
|
||||||
|
|
||||||
|
|
||||||
def is_file(media_item):
|
def is_file(media_item: AnyEvent) -> bool:
|
||||||
return media_item["type"] == "file"
|
return media_item["type"] == "file"
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ class PypoPush(Thread):
|
||||||
self.plq = PypoLiqQueue(self.future_scheduled_queue, self.pypo_liquidsoap)
|
self.plq = PypoLiqQueue(self.future_scheduled_queue, self.pypo_liquidsoap)
|
||||||
self.plq.start()
|
self.plq.start()
|
||||||
|
|
||||||
def main(self):
|
def main(self) -> None:
|
||||||
loops = 0
|
loops = 0
|
||||||
heartbeat_period = math.floor(30 / PUSH_INTERVAL)
|
heartbeat_period = math.floor(30 / PUSH_INTERVAL)
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ class PypoPush(Thread):
|
||||||
|
|
||||||
return present, future
|
return present, future
|
||||||
|
|
||||||
def run(self):
|
def run(self) -> None:
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
self.main()
|
self.main()
|
||||||
|
|
|
@ -6,6 +6,7 @@ from threading import Thread
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
from ..utils import seconds_between
|
from ..utils import seconds_between
|
||||||
|
from .events import AnyEvent, event_key_to_datetime
|
||||||
from .liquidsoap import PypoLiquidsoap
|
from .liquidsoap import PypoLiquidsoap
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -24,9 +25,9 @@ class PypoLiqQueue(Thread):
|
||||||
self.queue = future_queue
|
self.queue = future_queue
|
||||||
self.pypo_liquidsoap = pypo_liquidsoap
|
self.pypo_liquidsoap = pypo_liquidsoap
|
||||||
|
|
||||||
def main(self):
|
def main(self) -> None:
|
||||||
time_until_next_play = None
|
time_until_next_play = None
|
||||||
schedule_deque = deque()
|
schedule_deque: deque[AnyEvent] = deque()
|
||||||
media_schedule = None
|
media_schedule = None
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
@ -48,7 +49,7 @@ class PypoLiqQueue(Thread):
|
||||||
if len(schedule_deque):
|
if len(schedule_deque):
|
||||||
time_until_next_play = seconds_between(
|
time_until_next_play = seconds_between(
|
||||||
datetime.utcnow(),
|
datetime.utcnow(),
|
||||||
schedule_deque[0]["start"],
|
event_key_to_datetime(schedule_deque[0]["start"]),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
time_until_next_play = None
|
time_until_next_play = None
|
||||||
|
@ -71,7 +72,7 @@ class PypoLiqQueue(Thread):
|
||||||
else:
|
else:
|
||||||
time_until_next_play = None
|
time_until_next_play = None
|
||||||
|
|
||||||
def run(self):
|
def run(self) -> None:
|
||||||
try:
|
try:
|
||||||
self.main()
|
self.main()
|
||||||
except Exception as exception: # pylint: disable=broad-exception-caught
|
except Exception as exception: # pylint: disable=broad-exception-caught
|
||||||
|
|
|
@ -18,7 +18,7 @@ from .events import (
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def insert_event(events: Events, event_key: str, event: AnyEvent):
|
def insert_event(events: Events, event_key: str, event: AnyEvent) -> None:
|
||||||
key = event_key
|
key = event_key
|
||||||
|
|
||||||
# Search for an empty slot
|
# Search for an empty slot
|
||||||
|
|
Loading…
Reference in New Issue