forked from platypush/platypush
Implemented RunnablePlugin.wait_stop() utility method
This commit is contained in:
parent
061268cdaf
commit
d52ae2fb80
3 changed files with 93 additions and 71 deletions
|
@ -19,12 +19,12 @@ def action(f):
|
|||
result = f(*args, **kwargs)
|
||||
|
||||
if result and isinstance(result, Response):
|
||||
result.errors = result.errors \
|
||||
if isinstance(result.errors, list) else [result.errors]
|
||||
result.errors = (
|
||||
result.errors if isinstance(result.errors, list) else [result.errors]
|
||||
)
|
||||
response = result
|
||||
elif isinstance(result, tuple) and len(result) == 2:
|
||||
response.errors = result[1] \
|
||||
if isinstance(result[1], list) else [result[1]]
|
||||
response.errors = result[1] if isinstance(result[1], list) else [result[1]]
|
||||
|
||||
if len(response.errors) == 1 and response.errors[0] is None:
|
||||
response.errors = []
|
||||
|
@ -39,12 +39,14 @@ def action(f):
|
|||
return _execute_action
|
||||
|
||||
|
||||
class Plugin(EventGenerator, ExtensionWithManifest): # lgtm [py/missing-call-to-init]
|
||||
""" Base plugin class """
|
||||
class Plugin(EventGenerator, ExtensionWithManifest): # lgtm [py/missing-call-to-init]
|
||||
"""Base plugin class"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__()
|
||||
self.logger = logging.getLogger('platypush:plugin:' + get_plugin_name_by_class(self.__class__))
|
||||
self.logger = logging.getLogger(
|
||||
'platypush:plugin:' + get_plugin_name_by_class(self.__class__)
|
||||
)
|
||||
if 'logging' in kwargs:
|
||||
self.logger.setLevel(getattr(logging, kwargs['logging'].upper()))
|
||||
|
||||
|
@ -53,8 +55,9 @@ class Plugin(EventGenerator, ExtensionWithManifest): # lgtm [py/missing-call-t
|
|||
)
|
||||
|
||||
def run(self, method, *args, **kwargs):
|
||||
assert method in self.registered_actions, '{} is not a registered action on {}'.\
|
||||
format(method, self.__class__.__name__)
|
||||
assert (
|
||||
method in self.registered_actions
|
||||
), '{} is not a registered action on {}'.format(method, self.__class__.__name__)
|
||||
return getattr(self, method)(*args, **kwargs)
|
||||
|
||||
|
||||
|
@ -62,6 +65,7 @@ class RunnablePlugin(Plugin):
|
|||
"""
|
||||
Class for runnable plugins - i.e. plugins that have a start/stop method and can be started.
|
||||
"""
|
||||
|
||||
def __init__(self, poll_interval: Optional[float] = None, **kwargs):
|
||||
"""
|
||||
:param poll_interval: How often the :meth:`.loop` function should be execute (default: None, no pause/interval).
|
||||
|
@ -78,6 +82,9 @@ class RunnablePlugin(Plugin):
|
|||
def should_stop(self):
|
||||
return self._should_stop.is_set()
|
||||
|
||||
def wait_stop(self, timeout=None):
|
||||
return self._should_stop.wait(timeout)
|
||||
|
||||
def start(self):
|
||||
set_thread_name(self.__class__.__name__)
|
||||
self._thread = threading.Thread(target=self._runner)
|
||||
|
|
|
@ -2,7 +2,11 @@ import os
|
|||
from typing import Sequence, Dict, Tuple, Union, Optional
|
||||
|
||||
from platypush.plugins import RunnablePlugin, action
|
||||
from platypush.schemas.irc import IRCServerSchema, IRCServerStatusSchema, IRCChannelSchema
|
||||
from platypush.schemas.irc import (
|
||||
IRCServerSchema,
|
||||
IRCServerStatusSchema,
|
||||
IRCChannelSchema,
|
||||
)
|
||||
|
||||
from ._bot import IRCBot
|
||||
from .. import ChatPlugin
|
||||
|
@ -59,29 +63,19 @@ class ChatIrcPlugin(RunnablePlugin, ChatPlugin):
|
|||
|
||||
@property
|
||||
def _bots_by_server(self) -> Dict[str, IRCBot]:
|
||||
return {
|
||||
bot.server: bot
|
||||
for srv, bot in self._bots.items()
|
||||
}
|
||||
return {bot.server: bot for srv, bot in self._bots.items()}
|
||||
|
||||
@property
|
||||
def _bots_by_server_and_port(self) -> Dict[Tuple[str, int], IRCBot]:
|
||||
return {
|
||||
(bot.server, bot.port): bot
|
||||
for srv, bot in self._bots.items()
|
||||
}
|
||||
return {(bot.server, bot.port): bot for srv, bot in self._bots.items()}
|
||||
|
||||
@property
|
||||
def _bots_by_alias(self) -> Dict[str, IRCBot]:
|
||||
return {
|
||||
bot.alias: bot
|
||||
for srv, bot in self._bots.items()
|
||||
if bot.alias
|
||||
}
|
||||
return {bot.alias: bot for srv, bot in self._bots.items() if bot.alias}
|
||||
|
||||
def main(self):
|
||||
self._connect()
|
||||
self._should_stop.wait()
|
||||
self.wait_stop()
|
||||
|
||||
def _connect(self):
|
||||
for srv, bot in self._bots.items():
|
||||
|
@ -109,7 +103,11 @@ class ChatIrcPlugin(RunnablePlugin, ChatPlugin):
|
|||
|
||||
@action
|
||||
def send_file(
|
||||
self, file: str, server: Union[str, Tuple[str, int]], nick: str, bind_address: Optional[str] = None
|
||||
self,
|
||||
file: str,
|
||||
server: Union[str, Tuple[str, int]],
|
||||
nick: str,
|
||||
bind_address: Optional[str] = None,
|
||||
):
|
||||
"""
|
||||
Send a file to an IRC user over DCC connection.
|
||||
|
@ -127,7 +125,10 @@ class ChatIrcPlugin(RunnablePlugin, ChatPlugin):
|
|||
|
||||
@action
|
||||
def send_message(
|
||||
self, text: str, server: Union[str, Tuple[str, int]], target: Union[str, Sequence[str]]
|
||||
self,
|
||||
text: str,
|
||||
server: Union[str, Tuple[str, int]],
|
||||
target: Union[str, Sequence[str]],
|
||||
):
|
||||
"""
|
||||
Send a message to a channel or a nick.
|
||||
|
@ -139,15 +140,14 @@ class ChatIrcPlugin(RunnablePlugin, ChatPlugin):
|
|||
"""
|
||||
bot = self._get_bot(server)
|
||||
method = (
|
||||
bot.connection.privmsg if isinstance(target, str)
|
||||
bot.connection.privmsg
|
||||
if isinstance(target, str)
|
||||
else bot.connection.privmsg_many
|
||||
)
|
||||
method(target, text)
|
||||
|
||||
@action
|
||||
def send_notice(
|
||||
self, text: str, server: Union[str, Tuple[str, int]], target: str
|
||||
):
|
||||
def send_notice(self, text: str, server: Union[str, Tuple[str, int]], target: str):
|
||||
"""
|
||||
Send a notice to a channel or a nick.
|
||||
|
||||
|
@ -192,22 +192,28 @@ class ChatIrcPlugin(RunnablePlugin, ChatPlugin):
|
|||
channel_name = channel
|
||||
channel = bot.channels.get(channel)
|
||||
assert channel, f'Not connected to channel {channel}'
|
||||
return IRCChannelSchema().dump({
|
||||
'is_invite_only': channel.is_invite_only(),
|
||||
'is_moderated': channel.is_moderated(),
|
||||
'is_protected': channel.is_protected(),
|
||||
'is_secret': channel.is_secret(),
|
||||
'name': channel_name,
|
||||
'modes': channel.modes,
|
||||
'opers': list(channel.opers()),
|
||||
'owners': channel.owners(),
|
||||
'users': list(channel.users()),
|
||||
'voiced': list(channel.voiced()),
|
||||
})
|
||||
return IRCChannelSchema().dump(
|
||||
{
|
||||
'is_invite_only': channel.is_invite_only(),
|
||||
'is_moderated': channel.is_moderated(),
|
||||
'is_protected': channel.is_protected(),
|
||||
'is_secret': channel.is_secret(),
|
||||
'name': channel_name,
|
||||
'modes': channel.modes,
|
||||
'opers': list(channel.opers()),
|
||||
'owners': channel.owners(),
|
||||
'users': list(channel.users()),
|
||||
'voiced': list(channel.voiced()),
|
||||
}
|
||||
)
|
||||
|
||||
@action
|
||||
def send_ctcp_message(
|
||||
self, ctcp_type: str, body: str, server: Union[str, Tuple[str, int]], target: str
|
||||
self,
|
||||
ctcp_type: str,
|
||||
body: str,
|
||||
server: Union[str, Tuple[str, int]],
|
||||
target: str,
|
||||
):
|
||||
"""
|
||||
Send a CTCP message to a target.
|
||||
|
@ -222,7 +228,7 @@ class ChatIrcPlugin(RunnablePlugin, ChatPlugin):
|
|||
|
||||
@action
|
||||
def send_ctcp_reply(
|
||||
self, body: str, server: Union[str, Tuple[str, int]], target: str
|
||||
self, body: str, server: Union[str, Tuple[str, int]], target: str
|
||||
):
|
||||
"""
|
||||
Send a CTCP REPLY command.
|
||||
|
@ -235,7 +241,9 @@ class ChatIrcPlugin(RunnablePlugin, ChatPlugin):
|
|||
bot.connection.ctcp_reply(target, body)
|
||||
|
||||
@action
|
||||
def disconnect(self, server: Union[str, Tuple[str, int]], message: Optional[str] = None):
|
||||
def disconnect(
|
||||
self, server: Union[str, Tuple[str, int]], message: Optional[str] = None
|
||||
):
|
||||
"""
|
||||
Disconnect from a server.
|
||||
|
||||
|
@ -246,9 +254,7 @@ class ChatIrcPlugin(RunnablePlugin, ChatPlugin):
|
|||
bot.connection.disconnect(message or bot.stop_message)
|
||||
|
||||
@action
|
||||
def invite(
|
||||
self, nick: str, channel: str, server: Union[str, Tuple[str, int]]
|
||||
):
|
||||
def invite(self, nick: str, channel: str, server: Union[str, Tuple[str, int]]):
|
||||
"""
|
||||
Invite a nick to a channel.
|
||||
|
||||
|
@ -272,7 +278,11 @@ class ChatIrcPlugin(RunnablePlugin, ChatPlugin):
|
|||
|
||||
@action
|
||||
def kick(
|
||||
self, nick: str, channel: str, server: Union[str, Tuple[str, int]], reason: Optional[str] = None
|
||||
self,
|
||||
nick: str,
|
||||
channel: str,
|
||||
server: Union[str, Tuple[str, int]],
|
||||
reason: Optional[str] = None,
|
||||
):
|
||||
"""
|
||||
Kick a nick from a channel.
|
||||
|
@ -286,9 +296,7 @@ class ChatIrcPlugin(RunnablePlugin, ChatPlugin):
|
|||
bot.connection.kick(channel, nick, reason)
|
||||
|
||||
@action
|
||||
def mode(
|
||||
self, target: str, command: str, server: Union[str, Tuple[str, int]]
|
||||
):
|
||||
def mode(self, target: str, command: str, server: Union[str, Tuple[str, int]]):
|
||||
"""
|
||||
Send a MODE command on the selected target.
|
||||
|
||||
|
@ -324,8 +332,10 @@ class ChatIrcPlugin(RunnablePlugin, ChatPlugin):
|
|||
|
||||
@action
|
||||
def part(
|
||||
self, channel: Union[str, Sequence[str]], server: Union[str, Tuple[str, int]],
|
||||
message: Optional[str] = None
|
||||
self,
|
||||
channel: Union[str, Sequence[str]],
|
||||
server: Union[str, Tuple[str, int]],
|
||||
message: Optional[str] = None,
|
||||
):
|
||||
"""
|
||||
Parts/exits a channel.
|
||||
|
@ -339,9 +349,7 @@ class ChatIrcPlugin(RunnablePlugin, ChatPlugin):
|
|||
bot.connection.part(channels=channels, message=message or bot.stop_message)
|
||||
|
||||
@action
|
||||
def quit(
|
||||
self, server: Union[str, Tuple[str, int]], message: Optional[str] = None
|
||||
):
|
||||
def quit(self, server: Union[str, Tuple[str, int]], message: Optional[str] = None):
|
||||
"""
|
||||
Send a QUIT command.
|
||||
|
||||
|
@ -363,7 +371,12 @@ class ChatIrcPlugin(RunnablePlugin, ChatPlugin):
|
|||
bot.connection.send_raw(message)
|
||||
|
||||
@action
|
||||
def topic(self, channel: str, server: Union[str, Tuple[str, int]], topic: Optional[str] = None) -> str:
|
||||
def topic(
|
||||
self,
|
||||
channel: str,
|
||||
server: Union[str, Tuple[str, int]],
|
||||
topic: Optional[str] = None,
|
||||
) -> str:
|
||||
"""
|
||||
Get/set the topic of an IRC channel.
|
||||
|
||||
|
|
|
@ -27,11 +27,11 @@ class GpioPlugin(RunnablePlugin):
|
|||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
pins: Optional[Dict[str, int]] = None,
|
||||
monitored_pins: Optional[Collection[Union[str, int]]] = None,
|
||||
mode: str = 'board',
|
||||
**kwargs
|
||||
self,
|
||||
pins: Optional[Dict[str, int]] = None,
|
||||
monitored_pins: Optional[Collection[Union[str, int]]] = None,
|
||||
mode: str = 'board',
|
||||
**kwargs
|
||||
):
|
||||
"""
|
||||
:param mode: Specify ``board`` if you want to use the board PIN numbers,
|
||||
|
@ -64,8 +64,9 @@ class GpioPlugin(RunnablePlugin):
|
|||
self._initialized_pins = {}
|
||||
self._monitored_pins = monitored_pins or []
|
||||
self.pins_by_name = pins if pins else {}
|
||||
self.pins_by_number = {number: name
|
||||
for (name, number) in self.pins_by_name.items()}
|
||||
self.pins_by_number = {
|
||||
number: name for (name, number) in self.pins_by_name.items()
|
||||
}
|
||||
|
||||
def _init_board(self):
|
||||
import RPi.GPIO as GPIO
|
||||
|
@ -98,6 +99,7 @@ class GpioPlugin(RunnablePlugin):
|
|||
def on_gpio_event(self):
|
||||
def callback(pin: int):
|
||||
import RPi.GPIO as GPIO
|
||||
|
||||
value = GPIO.input(pin)
|
||||
pin = self.pins_by_number.get(pin, pin)
|
||||
get_bus().post(GPIOEvent(pin=pin, value=value))
|
||||
|
@ -106,23 +108,23 @@ class GpioPlugin(RunnablePlugin):
|
|||
|
||||
def main(self):
|
||||
import RPi.GPIO as GPIO
|
||||
|
||||
if not self._monitored_pins:
|
||||
return # No need to start the monitor
|
||||
|
||||
self._init_board()
|
||||
monitored_pins = [
|
||||
self._get_pin_number(pin) for pin in self._monitored_pins
|
||||
]
|
||||
monitored_pins = [self._get_pin_number(pin) for pin in self._monitored_pins]
|
||||
|
||||
for pin in monitored_pins:
|
||||
GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
|
||||
GPIO.add_event_detect(pin, GPIO.BOTH, callback=self.on_gpio_event())
|
||||
|
||||
self._should_stop.wait()
|
||||
self.wait_stop()
|
||||
|
||||
@action
|
||||
def write(self, pin: Union[int, str], value: Union[int, bool],
|
||||
name: Optional[str] = None) -> Dict[str, Any]:
|
||||
def write(
|
||||
self, pin: Union[int, str], value: Union[int, bool], name: Optional[str] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Write a byte value to a pin.
|
||||
|
||||
|
|
Loading…
Reference in a new issue