From 81803a364d1bc4464848f425c64c92b49a926db6 Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Mon, 30 Jul 2018 22:08:06 +0200 Subject: [PATCH] Fixed some pylint warnings --- LICENSE.txt | 2 +- platypush/__init__.py | 60 ++++++++----- platypush/backend/__init__.py | 5 ++ .../backend/assistant/google/__init__.py | 21 +++-- .../backend/assistant/google/pushtotalk.py | 85 ++++++++++--------- .../backend/assistant/snowboy/__init__.py | 10 ++- 6 files changed, 113 insertions(+), 70 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 2ed6d5de7..d6902cdcf 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017, Fabio Manganiello +Copyright (c) 2017, 2018 Fabio Manganiello Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/platypush/__init__.py b/platypush/__init__.py index 674ac0a46..33da64c43 100644 --- a/platypush/__init__.py +++ b/platypush/__init__.py @@ -1,3 +1,10 @@ +""" +Platypush + +.. moduleauthor:: Fabio Manganiello +.. license:: MIT +""" + import argparse import logging import sys @@ -18,30 +25,29 @@ from .message.response import Response __author__ = 'Fabio Manganiello ' __version__ = '0.9' -#-----------# +LOGGER = logging.getLogger(__name__) -logger = logging.getLogger(__name__) - -class Daemon(object): +class Daemon: """ Main class for the Platypush daemon """ - """ Configuration file (default: either ~/.config/platypush/config.yaml or - /etc/platypush/config.yaml) """ + # Configuration file (default: either ~/.config/platypush/config.yaml or + # /etc/platypush/config.yaml config_file = None - """ Application bus. It's an internal queue where: - - backends will post the messages they receive - - plugins will post the responses they process """ + # Application bus. It's an internal queue where: + # - backends will post the messages they receive + # - plugins will post the responses they process bus = None - """ backend_name => backend_obj map """ + # backend_name => backend_obj map backends = None - """ number of executions retries before a request fails """ + # number of executions retries before a request fails n_tries = 2 def __init__(self, config_file=None, requests_to_process=None): - """ Constructor + """ + Constructor Params: config_file -- Configuration file override (default: None) requests_to_process -- Exit after processing the specified number @@ -58,7 +64,8 @@ class Daemon(object): @classmethod def build_from_cmdline(cls, args): - """ Build the app from command line arguments. + """ + Build the app from command line arguments. Params: args -- Your sys.argv[1:] [List of strings] """ @@ -70,30 +77,34 @@ class Daemon(object): return cls(config_file=opts.config) def on_message(self): - """ Default message handler """ + """ + Default message handler + """ def _f(msg): - """ on_message closure + """ + on_message closure Params: - msg -- platypush.message.Message instance """ + msg -- platypush.message.Message instance + """ if isinstance(msg, Request): try: msg.execute(n_tries=self.n_tries) except PermissionError: - logger.info('Dropped unauthorized request: {}'.format(msg)) + LOGGER.info('Dropped unauthorized request: {}'.format(msg)) self.processed_requests += 1 if self.requests_to_process \ and self.processed_requests >= self.requests_to_process: self.stop_app() elif isinstance(msg, Response): - logger.info('Received response: {}'.format(msg)) + LOGGER.info('Received response: {}'.format(msg)) elif isinstance(msg, StopEvent) and msg.targets_me(): - logger.info('Received STOP event: {}'.format(msg)) + LOGGER.info('Received STOP event: {}'.format(msg)) self.stop_app() elif isinstance(msg, Event): - logger.info('Received event: {}'.format(msg)) + LOGGER.info('Received event: {}'.format(msg)) self.event_processor.process_event(msg) return _f @@ -124,17 +135,20 @@ class Daemon(object): # Poll for messages on the bus try: self.bus.poll() - except KeyboardInterrupt as e: - logger.info('SIGINT received, terminating application') + except KeyboardInterrupt: + LOGGER.info('SIGINT received, terminating application') finally: self.stop_app() def main(): + """ + Platypush daemon main + """ + print('Starting platypush v.{}'.format(__version__)) app = Daemon.build_from_cmdline(sys.argv[1:]) app.start() # vim:sw=4:ts=4:et: - diff --git a/platypush/backend/__init__.py b/platypush/backend/__init__.py index d41fd27d5..d40b44f9e 100644 --- a/platypush/backend/__init__.py +++ b/platypush/backend/__init__.py @@ -1,3 +1,8 @@ +""" +.. moduleauthor:: Fabio Manganiello +.. license:: MIT +""" + import importlib import logging import sys diff --git a/platypush/backend/assistant/google/__init__.py b/platypush/backend/assistant/google/__init__.py index 32b61d7cd..c18902088 100644 --- a/platypush/backend/assistant/google/__init__.py +++ b/platypush/backend/assistant/google/__init__.py @@ -1,3 +1,8 @@ +""" +.. moduleauthor:: Fabio Manganiello +.. license:: MIT +""" + import json import os import subprocess @@ -36,10 +41,11 @@ class AssistantGoogleBackend(Backend): * **google-assistant-sdk[samples]** (``pip install google-assistant-sdk[samples]``) """ - def __init__(self, credentials_file=os.path.join( - os.path.expanduser('~/.config'), - 'google-oauthlib-tool', 'credentials.json'), - device_model_id='Platypush', **kwargs): + def __init__(self, + credentials_file=os.path.join( + os.path.expanduser('~/.config'), + 'google-oauthlib-tool', 'credentials.json'), + device_model_id='Platypush', **kwargs): """ :param credentials_file: Path to the Google OAuth credentials file (default: ~/.config/google-oauthlib-tool/credentials.json). See https://developers.google.com/assistant/sdk/guides/library/python/embed/install-sample#generate_credentials for how to get your own credentials file. :type credentials_file: str @@ -80,12 +86,14 @@ class AssistantGoogleBackend(Backend): def start_conversation(self): """ Starts an assistant conversation """ - if self.assistant: self.assistant.start_conversation() + if self.assistant: + self.assistant.start_conversation() def stop_conversation(self): """ Stops an assistant conversation """ - if self.assistant: self.assistant.stop_conversation() + if self.assistant: + self.assistant.stop_conversation() def run(self): @@ -98,4 +106,3 @@ class AssistantGoogleBackend(Backend): # vim:sw=4:ts=4:et: - diff --git a/platypush/backend/assistant/google/pushtotalk.py b/platypush/backend/assistant/google/pushtotalk.py index a4945b8c7..311e1a335 100644 --- a/platypush/backend/assistant/google/pushtotalk.py +++ b/platypush/backend/assistant/google/pushtotalk.py @@ -1,22 +1,24 @@ +""" +.. moduleauthor:: Fabio Manganiello +.. license:: MIT +""" + +import concurrent import json import logging import os -import threading -import time import grpc import google.auth.transport.grpc import google.auth.transport.requests import google.oauth2.credentials +from google.assistant.embedded.v1alpha2 import embedded_assistant_pb2, embedded_assistant_pb2_grpc + import googlesamples.assistant.grpc.audio_helpers as audio_helpers import googlesamples.assistant.grpc.device_helpers as device_helpers import googlesamples.assistant.grpc.assistant_helpers as assistant_helpers from tenacity import retry, stop_after_attempt, retry_if_exception -from google.assistant.embedded.v1alpha2 import ( - embedded_assistant_pb2, - embedded_assistant_pb2_grpc -) from platypush.backend import Backend @@ -53,15 +55,16 @@ class AssistantGooglePushtotalkBackend(Backend): audio_flush_size = audio_helpers.DEFAULT_AUDIO_DEVICE_FLUSH_SIZE grpc_deadline = 60 * 3 + 5 - def __init__(self, credentials_file=os.path.join( - os.path.expanduser('~'), '.config', - 'google-oauthlib-tool', 'credentials.json'), - device_config=os.path.join( - os.path.expanduser('~'), '.config', 'googlesamples-assistant', - 'device_config.json'), - lang='en-US', - conversation_start_fifo = os.path.join(os.path.sep, 'tmp', 'pushtotalk.fifo'), - *args, **kwargs): + def __init__(self, *args, + credentials_file=os.path.join( + os.path.expanduser('~'), '.config', + 'google-oauthlib-tool', 'credentials.json'), + device_config=os.path.join( + os.path.expanduser('~'), '.config', 'googlesamples-assistant', + 'device_config.json'), + lang='en-US', + conversation_start_fifo=os.path.join(os.path.sep, 'tmp', 'pushtotalk.fifo'), + **kwargs): """ :param credentials_file: Path to the Google OAuth credentials file (default: ~/.config/google-oauthlib-tool/credentials.json). See https://developers.google.com/assistant/sdk/guides/library/python/embed/install-sample#generate_credentials for how to get your own credentials file. :type credentials_file: str @@ -98,10 +101,10 @@ class AssistantGooglePushtotalkBackend(Backend): **json.load(f)) http_request = google.auth.transport.requests.Request() credentials.refresh(http_request) - except: - self.logger.error('Error loading credentials: %s', e) + except Exception as ex: + self.logger.error('Error loading credentials: %s', str(ex)) self.logger.error('Run google-oauthlib-tool to initialize ' - 'new OAuth 2.0 credentials.') + 'new OAuth 2.0 credentials.') raise # Create an authorized gRPC channel. @@ -151,43 +154,44 @@ class AssistantGooglePushtotalkBackend(Backend): self.conversation_stream.stop_playback() self.bus.post(ConversationEndEvent()) - def send_message(self, msg): - pass - def on_conversation_start(self): + """ Conversation start handler """ self.bus.post(ConversationStartEvent()) def on_conversation_end(self): + """ Conversation end handler """ self.bus.post(ConversationEndEvent()) def on_speech_recognized(self, speech): + """ Speech recognized handler """ self.bus.post(SpeechRecognizedEvent(phrase=speech)) def run(self): + """ Backend executor """ super().run() with SampleAssistant(self.lang, self.device_model_id, self.device_id, - self.conversation_stream, - self.grpc_channel, self.grpc_deadline, - self.device_handler, - on_conversation_start=self.on_conversation_start, - on_conversation_end=self.on_conversation_end, - on_speech_recognized=self.on_speech_recognized) as self.assistant: + self.conversation_stream, + self.grpc_channel, self.grpc_deadline, + self.device_handler, + on_conversation_start=self.on_conversation_start, + on_conversation_end=self.on_conversation_end, + on_speech_recognized=self.on_speech_recognized) as self.assistant: while not self.should_stop(): with open(self.conversation_start_fifo, 'r') as f: - for line in f: pass + f.read() self.logger.info('Received conversation start event') continue_conversation = True - user_request = None while continue_conversation: (user_request, continue_conversation) = self.assistant.assist() + self.logger('User request: {}'.format(user_request)) self.on_conversation_end() -class SampleAssistant(object): +class SampleAssistant: """Sample Assistant that supports conversations and device actions. Args: @@ -242,11 +246,14 @@ class SampleAssistant(object): if e: return False self.conversation_stream.close() + return True + @staticmethod def is_grpc_error_unavailable(e): + """ Returns True if the gRPC is not available """ is_grpc_error = isinstance(e, grpc.RpcError) if is_grpc_error and (e.code() == grpc.StatusCode.UNAVAILABLE): - self.logger.error('grpc unavailable error: %s', e) + print('grpc unavailable error: {}'.format(e)) return True return False @@ -288,7 +295,7 @@ class SampleAssistant(object): self.logger.info('Transcript of user request: "%s".', user_request) self.logger.info('Playing assistant response.') - if len(resp.audio_out.audio_data) > 0: + if resp.audio_out.audio_data: self.conversation_stream.write(resp.audio_out.audio_data) if resp.dialog_state_out.conversation_state: conversation_state = resp.dialog_state_out.conversation_state @@ -311,7 +318,7 @@ class SampleAssistant(object): if fs: device_actions_futures.extend(fs) - if len(device_actions_futures): + if device_actions_futures: self.logger.info('Waiting for device executions to complete.') concurrent.futures.wait(device_actions_futures) @@ -319,7 +326,7 @@ class SampleAssistant(object): try: self.conversation_stream.stop_playback() - except: + except Exception: pass if user_request and self.on_speech_recognized: @@ -331,12 +338,14 @@ class SampleAssistant(object): """Yields: AssistRequest messages to send to the API.""" dialog_state_in = embedded_assistant_pb2.DialogStateIn( - language_code=self.language_code, - conversation_state=b'' - ) + language_code=self.language_code, + conversation_state=b'' + ) + if self.conversation_state: self.logger.debug('Sending conversation state.') dialog_state_in.conversation_state = self.conversation_state + config = embedded_assistant_pb2.AssistConfig( audio_in_config=embedded_assistant_pb2.AudioInConfig( encoding='LINEAR16', @@ -353,6 +362,7 @@ class SampleAssistant(object): device_model_id=self.device_model_id, ) ) + # The first AssistRequest must contain the AssistConfig # and no audio data. yield embedded_assistant_pb2.AssistRequest(config=config) @@ -362,4 +372,3 @@ class SampleAssistant(object): # vim:sw=4:ts=4:et: - diff --git a/platypush/backend/assistant/snowboy/__init__.py b/platypush/backend/assistant/snowboy/__init__.py index 79286ec36..e76f630e7 100644 --- a/platypush/backend/assistant/snowboy/__init__.py +++ b/platypush/backend/assistant/snowboy/__init__.py @@ -1,3 +1,8 @@ +""" +.. moduleauthor:: Fabio Manganiello +.. license:: MIT +""" + import json import os import subprocess @@ -57,6 +62,10 @@ class AssistantSnowboyBackend(Backend): self.logger.info('Initialized Snowboy hotword detection') def hotword_detected(self): + """ + Callback called on hotword detection + """ + def callback(): self.bus.post(HotwordDetectedEvent(hotword=self.hotword)) return callback @@ -67,4 +76,3 @@ class AssistantSnowboyBackend(Backend): # vim:sw=4:ts=4:et: -