mirror of
https://git.deluge-torrent.org/deluge
synced 2025-08-20 17:18:44 +00:00
[Core] Refactor alert handler for readability
This commit is contained in:
parent
527cfa586c
commit
196086c1fb
1 changed files with 39 additions and 32 deletions
|
@ -14,8 +14,11 @@ This should typically only be used by the Core. Plugins should utilize the
|
||||||
`:mod:EventManager` for similar functionality.
|
`:mod:EventManager` for similar functionality.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
import contextlib
|
||||||
import logging
|
import logging
|
||||||
|
from collections import defaultdict
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
|
from typing import Any, Callable
|
||||||
|
|
||||||
from twisted.internet import reactor
|
from twisted.internet import reactor
|
||||||
|
|
||||||
|
@ -52,7 +55,7 @@ class AlertManager(component.Component):
|
||||||
self.session.apply_settings({'alert_mask': alert_mask})
|
self.session.apply_settings({'alert_mask': alert_mask})
|
||||||
|
|
||||||
# handlers is a dictionary of lists {"alert_type": [handler1,h2,..]}
|
# handlers is a dictionary of lists {"alert_type": [handler1,h2,..]}
|
||||||
self.handlers = {}
|
self.handlers = defaultdict(list)
|
||||||
self.delayed_calls = []
|
self.delayed_calls = []
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
|
@ -65,35 +68,30 @@ class AlertManager(component.Component):
|
||||||
delayed_call.cancel()
|
delayed_call.cancel()
|
||||||
self.delayed_calls = []
|
self.delayed_calls = []
|
||||||
|
|
||||||
def register_handler(self, alert_type, handler):
|
def register_handler(self, alert_type: str, handler: Callable[[Any], None]) -> None:
|
||||||
"""
|
"""
|
||||||
Registers a function that will be called when 'alert_type' is pop'd
|
Registers a function that will be called when 'alert_type' is pop'd
|
||||||
in handle_alerts. The handler function should look like: handler(alert)
|
in handle_alerts. The handler function should look like: handler(alert)
|
||||||
Where 'alert' is the actual alert object from libtorrent.
|
Where 'alert' is the actual alert object from libtorrent.
|
||||||
|
|
||||||
:param alert_type: str, this is string representation of the alert name
|
Args:
|
||||||
:param handler: func(alert), the function to be called when the alert is raised
|
alert_type: String representation of the libtorrent alert name.
|
||||||
|
Can be supplied with or without `_alert` suffix.
|
||||||
|
handler: Callback function when the alert is raised.
|
||||||
"""
|
"""
|
||||||
if alert_type not in self.handlers:
|
|
||||||
# There is no entry for this alert type yet, so lets make it with an
|
|
||||||
# empty list.
|
|
||||||
self.handlers[alert_type] = []
|
|
||||||
|
|
||||||
# Append the handler to the list in the handlers dictionary
|
|
||||||
self.handlers[alert_type].append(handler)
|
self.handlers[alert_type].append(handler)
|
||||||
log.debug('Registered handler for alert %s', alert_type)
|
log.debug('Registered handler for alert %s', alert_type)
|
||||||
|
|
||||||
def deregister_handler(self, handler):
|
def deregister_handler(self, handler: Callable[[Any], None]):
|
||||||
"""
|
"""
|
||||||
De-registers the `:param:handler` function from all alert types.
|
De-registers the `handler` function from all alert types.
|
||||||
|
|
||||||
:param handler: func, the handler function to deregister
|
Args:
|
||||||
|
handler: The handler function to deregister.
|
||||||
"""
|
"""
|
||||||
# Iterate through all handlers and remove 'handler' where found
|
for alert_type_handlers in self.handlers.values():
|
||||||
for dummy_key, value in self.handlers.items():
|
with contextlib.suppress(ValueError):
|
||||||
if handler in value:
|
alert_type_handlers.remove(handler)
|
||||||
# Handler is in this alert type list
|
|
||||||
value.remove(handler)
|
|
||||||
|
|
||||||
def handle_alerts(self):
|
def handle_alerts(self):
|
||||||
"""
|
"""
|
||||||
|
@ -112,26 +110,35 @@ class AlertManager(component.Component):
|
||||||
num_alerts,
|
num_alerts,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Loop through all alerts in the queue
|
|
||||||
for alert in alerts:
|
for alert in alerts:
|
||||||
alert_type = type(alert).__name__
|
alert_type = type(alert).__name__
|
||||||
# Display the alert message
|
# Display the alert message
|
||||||
if log.isEnabledFor(logging.DEBUG):
|
if log.isEnabledFor(logging.DEBUG):
|
||||||
log.debug('%s: %s', alert_type, decode_bytes(alert.message()))
|
log.debug('%s: %s', alert_type, decode_bytes(alert.message()))
|
||||||
|
|
||||||
|
if alert_type not in self.handlers:
|
||||||
|
continue
|
||||||
|
|
||||||
# Call any handlers for this alert type
|
# Call any handlers for this alert type
|
||||||
if alert_type in self.handlers:
|
for handler in self.handlers[alert_type]:
|
||||||
for handler in self.handlers[alert_type]:
|
if log.isEnabledFor(logging.DEBUG):
|
||||||
if log.isEnabledFor(logging.DEBUG):
|
log.debug('Handling alert: %s', alert_type)
|
||||||
log.debug('Handling alert: %s', alert_type)
|
|
||||||
# Copy alert attributes
|
alert_copy = self.create_alert_copy(alert)
|
||||||
alert_copy = SimpleNamespace(
|
self.delayed_calls.append(reactor.callLater(0, handler, alert_copy))
|
||||||
**{
|
|
||||||
attr: getattr(alert, attr)
|
@staticmethod
|
||||||
for attr in dir(alert)
|
def create_alert_copy(alert):
|
||||||
if not attr.startswith('__')
|
"""Create a Python copy of libtorrent alert
|
||||||
}
|
|
||||||
)
|
Avoid segfault if an alert is handled after next pop_alert call"""
|
||||||
self.delayed_calls.append(reactor.callLater(0, handler, alert_copy))
|
return SimpleNamespace(
|
||||||
|
**{
|
||||||
|
attr: getattr(alert, attr)
|
||||||
|
for attr in dir(alert)
|
||||||
|
if not attr.startswith('__')
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
def set_alert_queue_size(self, queue_size):
|
def set_alert_queue_size(self, queue_size):
|
||||||
"""Sets the maximum size of the libtorrent alert queue"""
|
"""Sets the maximum size of the libtorrent alert queue"""
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue