diff --git a/platypush/plugins/__init__.py b/platypush/plugins/__init__.py index 8338620e..ff69c263 100644 --- a/platypush/plugins/__init__.py +++ b/platypush/plugins/__init__.py @@ -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) diff --git a/platypush/plugins/chat/irc/__init__.py b/platypush/plugins/chat/irc/__init__.py index e7abdae2..681c5915 100644 --- a/platypush/plugins/chat/irc/__init__.py +++ b/platypush/plugins/chat/irc/__init__.py @@ -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. diff --git a/platypush/plugins/gpio/__init__.py b/platypush/plugins/gpio/__init__.py index 53f677a6..d312bfc0 100644 --- a/platypush/plugins/gpio/__init__.py +++ b/platypush/plugins/gpio/__init__.py @@ -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.