Fixed some pylint warnings

This commit is contained in:
Fabio Manganiello 2018-07-30 22:08:06 +02:00
parent a0ac30e9b6
commit 81803a364d
6 changed files with 113 additions and 70 deletions

View File

@ -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

View File

@ -1,3 +1,10 @@
"""
Platypush
.. moduleauthor:: Fabio Manganiello <blacklight86@gmail.com>
.. license:: MIT
"""
import argparse
import logging
import sys
@ -18,30 +25,29 @@ from .message.response import Response
__author__ = 'Fabio Manganiello <blacklight86@gmail.com>'
__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:

View File

@ -1,3 +1,8 @@
"""
.. moduleauthor:: Fabio Manganiello <blacklight86@gmail.com>
.. license:: MIT
"""
import importlib
import logging
import sys

View File

@ -1,3 +1,8 @@
"""
.. moduleauthor:: Fabio Manganiello <blacklight86@gmail.com>
.. 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:

View File

@ -1,22 +1,24 @@
"""
.. moduleauthor:: Fabio Manganiello <blacklight86@gmail.com>
.. 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:

View File

@ -1,3 +1,8 @@
"""
.. moduleauthor:: Fabio Manganiello <blacklight86@gmail.com>
.. 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: