Running black

This commit is contained in:
James Barnsley
2020-02-03 16:14:04 +13:00
parent 9fa47ab734
commit df18eba73c
6 changed files with 529 additions and 623 deletions

View File

@ -3,7 +3,7 @@ import logging, json, pathlib
import pkg_resources
from mopidy import config, ext
__version__ = '3.44.0'
__version__ = "3.44.0"
logger = logging.getLogger(__name__)
@ -13,10 +13,10 @@ logger = logging.getLogger(__name__)
#
# Loads config and gets the party started. Initiates any additional frontends, etc.
##
class Extension( ext.Extension ):
class Extension(ext.Extension):
dist_name = 'Mopidy-Iris'
ext_name = 'iris'
dist_name = "Mopidy-Iris"
ext_name = "iris"
version = __version__
def get_default_config(self):
@ -24,25 +24,24 @@ class Extension( ext.Extension ):
def get_config_schema(self):
schema = config.ConfigSchema(self.ext_name)
schema['enabled'] = config.Boolean()
schema['country'] = config.String()
schema['locale'] = config.String()
schema['spotify_authorization_url'] = config.String()
schema['lastfm_authorization_url'] = config.String()
schema['genius_authorization_url'] = config.String()
schema['data_dir'] = config.String()
schema["enabled"] = config.Boolean()
schema["country"] = config.String()
schema["locale"] = config.String()
schema["spotify_authorization_url"] = config.String()
schema["lastfm_authorization_url"] = config.String()
schema["genius_authorization_url"] = config.String()
schema["data_dir"] = config.String()
return schema
def setup(self, registry):
from .frontend import IrisFrontend
# Add web extension
registry.add('http:app', {
'name': self.ext_name,
'factory': iris_factory
})
registry.add("http:app", {"name": self.ext_name, "factory": iris_factory})
# Add our frontend
registry.add('frontend', IrisFrontend)
registry.add("frontend", IrisFrontend)
##
# Frontend factory
@ -51,44 +50,12 @@ def iris_factory(config, core):
from tornado.web import StaticFileHandler
from .handlers import HttpHandler, ReactRouterHandler, WebsocketHandler
path = pathlib.Path(__file__).parent / 'static'
path = pathlib.Path(__file__).parent / "static"
return [
(
r'/http/([^/]*)',
HttpHandler,
{
'core': core,
'config': config
}
),
(
r'/ws/?',
WebsocketHandler,
{
'core': core,
'config': config
}
),
(
r'/assets/(.*)',
StaticFileHandler,
{
'path': path / 'assets'
}
),
(
r'/((.*)(?:css|js|json|map)$)',
StaticFileHandler,
{
'path': path
}
),
(
r'/(.*)',
ReactRouterHandler,
{
'path': path / 'index.html'
}
),
(r"/http/([^/]*)", HttpHandler, {"core": core, "config": config}),
(r"/ws/?", WebsocketHandler, {"core": core, "config": config}),
(r"/assets/(.*)", StaticFileHandler, {"path": path / "assets"}),
(r"/((.*)(?:css|js|json|map)$)", StaticFileHandler, {"path": path}),
(r"/(.*)", ReactRouterHandler, {"path": path / "index.html"}),
]

File diff suppressed because it is too large Load Diff

View File

@ -6,8 +6,8 @@ from .mem import iris
# import logger
logger = logging.getLogger(__name__)
class IrisFrontend(pykka.ThreadingActor, CoreListener):
class IrisFrontend(pykka.ThreadingActor, CoreListener):
def __init__(self, config, core):
super().__init__()
@ -22,7 +22,7 @@ class IrisFrontend(pykka.ThreadingActor, CoreListener):
iris.stop()
def track_playback_ended(self, tl_track, time_position):
iris.ioloop.add_callback( functools.partial(iris.check_for_radio_update) )
iris.ioloop.add_callback(functools.partial(iris.check_for_radio_update))
def tracklist_changed(self):
iris.ioloop.add_callback( functools.partial(iris.clean_queue_metadata) )
iris.ioloop.add_callback(functools.partial(iris.clean_queue_metadata))

View File

@ -7,6 +7,7 @@ from .mem import iris
logger = logging.getLogger(__name__)
class WebsocketHandler(tornado.websocket.WebSocketHandler):
# initiate (not the actual object __init__, but run shortly after)
@ -14,7 +15,7 @@ class WebsocketHandler(tornado.websocket.WebSocketHandler):
self.core = core
self.config = config
self.ioloop = tornado.ioloop.IOLoop.current()
iris.ioloop = self.ioloop # Make available elsewhere in the Frontend
iris.ioloop = self.ioloop # Make available elsewhere in the Frontend
def check_origin(self, origin):
return True
@ -23,85 +24,104 @@ class WebsocketHandler(tornado.websocket.WebSocketHandler):
# Get the client's IP. If it's local, then use it's proxy origin
ip = self.request.remote_ip
if (ip == '127.0.0.1' and hasattr(self.request.headers,'X-Forwarded-For')):
ip = self.request.headers['X-Forwarded-For']
if ip == "127.0.0.1" and hasattr(self.request.headers, "X-Forwarded-For"):
ip = self.request.headers["X-Forwarded-For"]
# Construct our initial client object, and add to our list of connections
client = {
'connection_id': iris.generateGuid(),
'ip': ip,
'created': datetime.strftime(datetime.now(), '%Y-%m-%d %H:%M:%S')
"connection_id": iris.generateGuid(),
"ip": ip,
"created": datetime.strftime(datetime.now(), "%Y-%m-%d %H:%M:%S"),
}
self.connection_id = client['connection_id']
self.connection_id = client["connection_id"]
iris.add_connection(connection=self, client=client)
async def on_message(self, message):
logger.debug("Iris websocket message received: "+message)
logger.debug("Iris websocket message received: " + message)
message = json_decode(message)
if 'id' in message:
id = message['id']
if "id" in message:
id = message["id"]
else:
id = None
if 'jsonrpc' not in message:
self.handle_result(id=id, error={'id': id, 'code': 32602, 'message': 'Invalid JSON-RPC request (missing property "jsonrpc")'})
if "jsonrpc" not in message:
self.handle_result(
id=id,
error={
"id": id,
"code": 32602,
"message": 'Invalid JSON-RPC request (missing property "jsonrpc")',
},
)
if 'params' in message:
params = message['params']
if "params" in message:
params = message["params"]
# Handle hard-coded connection_id in messages
# Otherwise include the origin connection of this message
if 'connection_id' not in params:
message['params']['connection_id'] = self.connection_id
if "connection_id" not in params:
message["params"]["connection_id"] = self.connection_id
else:
params = {}
# call the method, as specified in payload
if 'method' in message:
if "method" in message:
# make sure the method exists
if hasattr(iris, message['method']):
if hasattr(iris, message["method"]):
try:
# For async methods we need to await, but it must be ommited for syncronous methods
if asyncio.iscoroutinefunction(getattr(iris, message['method'])):
await getattr(iris, message['method'])(
if asyncio.iscoroutinefunction(getattr(iris, message["method"])):
await getattr(iris, message["method"])(
ioloop=self.ioloop,
data=params,
callback=lambda response, error=False: self.handle_result(
id=id,
method=message['method'],
method=message["method"],
response=response,
error=error
)
error=error,
),
)
else:
getattr(iris, message['method'])(
getattr(iris, message["method"])(
ioloop=self.ioloop,
data=params,
callback=lambda response, error=False: self.handle_result(
id=id,
method=message['method'],
method=message["method"],
response=response,
error=error
)
error=error,
),
)
except Exception as e:
logger.error(str(e))
else:
self.handle_result(error={'id': id, 'code': 32601, 'message': 'Method "'+message['method']+'" does not exist'}, id=id)
self.handle_result(
error={
"id": id,
"code": 32601,
"message": 'Method "' + message["method"] + '" does not exist',
},
id=id,
)
return
else:
self.handle_result(error={'id': id, 'code': 32602, 'message': 'Method key missing from request'}, id=id)
self.handle_result(
error={
"id": id,
"code": 32602,
"message": "Method key missing from request",
},
id=id,
)
return
def on_close(self):
iris.remove_connection(connection_id=self.connection_id)
@ -110,45 +130,39 @@ class WebsocketHandler(tornado.websocket.WebSocketHandler):
# This is just our callback from an Async request
##
def handle_result(self, *args, **kwargs):
id = kwargs.get('id', False)
method = kwargs.get('method', None)
response = kwargs.get('response', None)
error = kwargs.get('error', None)
request_response = {
'id': id,
'jsonrpc': '2.0',
'method': method
}
id = kwargs.get("id", False)
method = kwargs.get("method", None)
response = kwargs.get("response", None)
error = kwargs.get("error", None)
request_response = {"id": id, "jsonrpc": "2.0", "method": method}
# We've been given an error
if error:
error['id'] = id
request_response['error'] = error
error["id"] = id
request_response["error"] = error
# We've been handed an AsyncHTTPClient callback. This is the case
# when our request calls subsequent external requests (eg Spotify, Genius)
elif isinstance(response, tornado.httpclient.HTTPResponse):
request_response['result'] = response.body
request_response["result"] = response.body
# Just a regular json object, so not an external request
else:
request_response['result'] = response
request_response["result"] = response
# Respond to the original request
data = request_response
data['recipient'] = self.connection_id
data["recipient"] = self.connection_id
iris.send_message(data=data)
class HttpHandler(tornado.web.RequestHandler):
def set_default_headers(self):
self.set_header("Access-Control-Allow-Origin", "*")
self.set_header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization, Client-Security-Token, Accept-Encoding")
self.set_header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, Authorization, Client-Security-Token, Accept-Encoding",
)
def initialize(self, core, config):
self.core = core
@ -175,28 +189,25 @@ class HttpHandler(tornado.web.RequestHandler):
ioloop=self.ioloop,
request=self,
callback=lambda response, error=False: self.handle_result(
id=id,
method=slug,
response=response,
error=error
)
id=id, method=slug, response=response, error=error
),
)
else:
getattr(iris, slug)(
ioloop=self.ioloop,
request=self,
callback=lambda response, error=False: self.handle_result(
id=id,
method=slug,
response=response,
error=error
)
id=id, method=slug, response=response, error=error
),
)
except Exception as e:
logger.error(str(e))
else:
self.handle_result(id=id, error={'code': 32601, 'message': "Method "+slug+" does not exist"})
self.handle_result(
id=id,
error={"code": 32601, "message": "Method " + slug + " does not exist"},
)
return
async def post(self, slug=None):
@ -204,9 +215,11 @@ class HttpHandler(tornado.web.RequestHandler):
id = int(time.time())
try:
params = json.loads(self.request.body.decode('utf-8'))
params = json.loads(self.request.body.decode("utf-8"))
except:
self.handle_result(id=id, error={'code': 32700, 'message': "Missing or invalid payload"})
self.handle_result(
id=id, error={"code": 32700, "message": "Missing or invalid payload"}
)
return
# make sure the method exists
@ -217,30 +230,29 @@ class HttpHandler(tornado.web.RequestHandler):
data=params,
request=self.request,
callback=lambda response=False, error=False: self.handle_result(
id=id,
method=slug,
response=response,
error=error
)
id=id, method=slug, response=response, error=error
),
)
else:
getattr(iris, slug)(
data=params,
request=self.request,
callback=lambda response=False, error=False: self.handle_result(
id=id,
method=slug,
response=response,
error=error
)
id=id, method=slug, response=response, error=error
),
)
except tornado.web.HTTPError as e:
self.handle_result(id=id, error={'code': 32601, 'message': "Invalid JSON payload"})
self.handle_result(
id=id, error={"code": 32601, "message": "Invalid JSON payload"}
)
return
else:
self.handle_result(id=id, error={'code': 32601, 'message': "Method "+slug+" does not exist"})
self.handle_result(
id=id,
error={"code": 32601, "message": "Method " + slug + " does not exist"},
)
return
##
@ -248,41 +260,37 @@ class HttpHandler(tornado.web.RequestHandler):
# This is just our callback from an Async request
##
def handle_result(self, *args, **kwargs):
id = kwargs.get('id', None)
method = kwargs.get('method', None)
response = kwargs.get('response', None)
error = kwargs.get('error', None)
request_response = {
'id': id,
'jsonrpc': '2.0',
'method': method
}
id = kwargs.get("id", None)
method = kwargs.get("method", None)
response = kwargs.get("response", None)
error = kwargs.get("error", None)
request_response = {"id": id, "jsonrpc": "2.0", "method": method}
if error:
request_response['error'] = error
request_response["error"] = error
self.set_status(400)
# We've been handed an AsyncHTTPClient callback. This is the case
# when our request calls subsequent external requests (eg Spotify, Genius).
# We don't need to wrap non-HTTPResponse responses as these are dicts
elif isinstance(response, tornado.httpclient.HTTPResponse):
# Digest JSON responses into JSON
content_type = response.headers.get('Content-Type')
if content_type.startswith('application/json') or content_type.startswith('text/json'):
content_type = response.headers.get("Content-Type")
if content_type.startswith("application/json") or content_type.startswith(
"text/json"
):
body = json.loads(response.body)
# Non-JSON so just copy as-is
else:
body = json_encode(response.body)
request_response['result'] = body
request_response["result"] = body
# Regular ol successful response
else:
request_response['result'] = response
request_response["result"] = response
# Write our response
@ -305,4 +313,3 @@ class ReactRouterHandler(tornado.web.StaticFileHandler):
def get(self, path=None, include_body=True):
return super().get(self.path, include_body)

View File

@ -1,3 +1,3 @@
from .core import IrisCore
iris = IrisCore()
iris = IrisCore()

View File

@ -13,7 +13,10 @@ class IrisSystemPermissionError(IrisSystemError):
reason = "Permission denied"
def __init__(self, path):
message = "Password-less access to %s was refused. Check your /etc/sudoers file." % path.as_uri()
message = (
"Password-less access to %s was refused. Check your /etc/sudoers file."
% path.as_uri()
)
logger.error(message)
super().__init__(message)
@ -31,57 +34,56 @@ class IrisSystemThread(Thread):
def get_command(self, action=None, *, non_interactive=False):
if self._USE_SUDO:
if non_interactive:
args = [b'sudo -n']
args = [b"sudo -n"]
else:
args = [b'sudo']
args = [b"sudo"]
else:
args = []
if action is None:
action = self.action
args = args + [bytes(self.script_path), action.encode()]
return args
##
# Run the defined action
##
def run(self):
logger.info("Running system action '"+self.action+"'")
logger.info("Running system action '" + self.action + "'")
try:
self.can_run()
except IrisSystemError as e:
logger.error(e)
error = {
'message': e.reason,
'description': e.message
}
return {
'error': error
}
error = {"message": e.reason, "description": e.message}
return {"error": error}
command = self.get_command()
logger.debug("Running '%s'", os.fsdecode(b' '.join(command)))
process = subprocess.Popen(command, stdout=subprocess.PIPE, encoding='utf8')
logger.debug("Running '%s'", os.fsdecode(b" ".join(command)))
process = subprocess.Popen(command, stdout=subprocess.PIPE, encoding="utf8")
lines = ''
lines = ""
while True:
line = process.stdout.readline()
if process.poll() is not None:
break
if line:
logger.info(line)
lines = lines+'\n'+line
lines = lines + "\n" + line
# This seems to be ignored. Detected as spammy io?
#self.ioloop.add_callback(lambda: self.callback(None, None, {'output': line}))
# self.ioloop.add_callback(lambda: self.callback(None, None, {'output': line}))
if process.returncode == 0:
self.ioloop.add_callback(lambda: self.callback({'output': lines}, None, None))
self.ioloop.add_callback(
lambda: self.callback({"output": lines}, None, None)
)
else:
self.ioloop.add_callback(lambda: self.callback(None, {'error': lines}, None))
self.ioloop.add_callback(
lambda: self.callback(None, {"error": lines}, None)
)
##
# Check if we have access to the system script (system.sh)
@ -90,8 +92,10 @@ class IrisSystemThread(Thread):
##
def can_run(self, *args, **kwargs):
# Attempt an empty call to our system file
command_bytes = b' '.join(self.get_command('check', non_interactive=True))
process = subprocess.Popen(command_bytes, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
command_bytes = b" ".join(self.get_command("check", non_interactive=True))
process = subprocess.Popen(
command_bytes, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True
)
result, error = process.communicate()
exitCode = process.wait()