forked from openlp/openlp
First changes now working
This commit is contained in:
commit
3d602d41b3
|
@ -20,35 +20,10 @@
|
|||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
from .errors import NotFound, ServerError, HttpError
|
||||
from .http import WSGIApplication, application
|
||||
from openlp.core.api.http.endpoint import Endpoint
|
||||
from openlp.core.api.http import register_endpoint
|
||||
from openlp.core.api.tab import ApiTab
|
||||
from openlp.core.api.controller import ApiController
|
||||
from openlp.core.api.poll import Poller
|
||||
|
||||
|
||||
def _route_from_url(url_prefix, url):
|
||||
"""
|
||||
Create a route from the URL
|
||||
"""
|
||||
url_prefix = '/{prefix}/'.format(prefix=url_prefix.strip('/'))
|
||||
if not url:
|
||||
url = url_prefix[:-1]
|
||||
else:
|
||||
url = url_prefix + url
|
||||
url = url.replace('//', '/')
|
||||
return url
|
||||
|
||||
|
||||
def register_endpoint(end_point):
|
||||
"""
|
||||
Register an endpoint with the app
|
||||
"""
|
||||
for url, view_func, method, secure in end_point.routes:
|
||||
route = _route_from_url(end_point.url_prefix, url)
|
||||
application.add_route(route, view_func, method, secure)
|
||||
|
||||
from .endpoint import Endpoint
|
||||
from .apitab import ApiTab
|
||||
from .websockets import WebSocketServer, Poll
|
||||
from .http import HttpServer
|
||||
from .apicontroller import ApiController
|
||||
|
||||
__all__ = ['Poll', 'ApiController', 'HttpServer', 'application']
|
||||
__all__ = ['Endpoint', 'ApiController', 'ApiTab', 'register_endpoint']
|
|
@ -21,13 +21,11 @@
|
|||
###############################################################################
|
||||
import logging
|
||||
|
||||
from openlp.core.api import WebSocketServer, Poll, HttpServer
|
||||
from openlp.core.api.http.server import HttpServer
|
||||
from openlp.core.api.websockets import WebSocketServer
|
||||
from openlp.core.api.poll import Poller
|
||||
from openlp.core.common import OpenLPMixin, Registry, RegistryMixin, RegistryProperties
|
||||
|
||||
# These are here to load the endpoints
|
||||
from openlp.core.api.coreendpoints import stage_endpoint
|
||||
from openlp.core.api.controllerendpoints import controller_endpoint
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
@ -48,7 +46,8 @@ class ApiController(RegistryMixin, OpenLPMixin, RegistryProperties):
|
|||
"""
|
||||
Register the poll return service and start the servers.
|
||||
"""
|
||||
self.poll = Poll()
|
||||
Registry().register('api_poll', self.poll)
|
||||
self.websocket_server = WebSocketServer()
|
||||
self.poller = Poller()
|
||||
Registry().register('Poller', self.poller)
|
||||
self.ws_server = WebSocketServer()
|
||||
self.http_server = HttpServer()
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
"""
|
||||
openlp/core/api/endpoint.py: Endpoint stuff
|
||||
"""
|
||||
|
||||
|
||||
class Endpoint(object):
|
||||
"""
|
||||
This is an endpoint for the API
|
||||
"""
|
||||
def __init__(self, url_prefix):
|
||||
"""
|
||||
Create an endpoint with a URL prefix
|
||||
"""
|
||||
print("init")
|
||||
self.url_prefix = url_prefix
|
||||
self.routes = []
|
||||
|
||||
def add_url_route(self, url, view_func, method, secure):
|
||||
"""
|
||||
Add a url route to the list of routes
|
||||
"""
|
||||
self.routes.append((url, view_func, method, secure))
|
||||
|
||||
def route(self, rule, method='GET', secure=False):
|
||||
"""
|
||||
Set up a URL route
|
||||
"""
|
||||
def decorator(func):
|
||||
"""
|
||||
Make this a decorator
|
||||
"""
|
||||
self.add_url_route(rule, func, method, secure)
|
||||
return func
|
||||
return decorator
|
|
@ -0,0 +1,48 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2016 OpenLP Developers #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# This program is free software; you can redistribute it and/or modify it #
|
||||
# under the terms of the GNU General Public License as published by the Free #
|
||||
# Software Foundation; version 2 of the License. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT #
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
|
||||
# more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License along #
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
from openlp.core.api.http.wsgiapp import WSGIApplication
|
||||
|
||||
application = WSGIApplication('api')
|
||||
|
||||
|
||||
def _route_from_url(url_prefix, url):
|
||||
"""
|
||||
Create a route from the URL
|
||||
"""
|
||||
url_prefix = '/{prefix}/'.format(prefix=url_prefix.strip('/'))
|
||||
if not url:
|
||||
url = url_prefix[:-1]
|
||||
else:
|
||||
url = url_prefix + url
|
||||
url = url.replace('//', '/')
|
||||
return url
|
||||
|
||||
|
||||
def register_endpoint(end_point):
|
||||
"""
|
||||
Register an endpoint with the app
|
||||
"""
|
||||
for url, view_func, method, secure in end_point.routes:
|
||||
route = _route_from_url(end_point.url_prefix, url)
|
||||
application.add_route(route, view_func, method, secure)
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2016 OpenLP Developers #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# This program is free software; you can redistribute it and/or modify it #
|
||||
# under the terms of the GNU General Public License as published by the Free #
|
||||
# Software Foundation; version 2 of the License. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT #
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
|
||||
# more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License along #
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
openlp/core/api/endpoint.py: Endpoint stuff
|
||||
"""
|
||||
|
||||
|
||||
class Endpoint(object):
|
||||
"""
|
||||
This is an endpoint for the HTTP API
|
||||
"""
|
||||
def __init__(self, url_prefix):
|
||||
"""
|
||||
Create an endpoint with a URL prefix
|
||||
"""
|
||||
print("init")
|
||||
self.url_prefix = url_prefix
|
||||
self.routes = []
|
||||
|
||||
def add_url_route(self, url, view_func, method, secure):
|
||||
"""
|
||||
Add a url route to the list of routes
|
||||
"""
|
||||
self.routes.append((url, view_func, method, secure))
|
||||
|
||||
def route(self, rule, method='GET', secure=False):
|
||||
"""
|
||||
Set up a URL route
|
||||
"""
|
||||
def decorator(func):
|
||||
"""
|
||||
Make this a decorator
|
||||
"""
|
||||
self.add_url_route(rule, func, method, secure)
|
||||
return func
|
||||
return decorator
|
|
@ -114,7 +114,6 @@ def main_image(request):
|
|||
# return json.dumps({'results': result}).encode()
|
||||
pass
|
||||
|
||||
|
||||
@stage_endpoint.route(r'^/(\w+)/thumbnails([^/]+)?/(.*)$')
|
||||
def main_image(request):
|
||||
"""
|
|
@ -63,3 +63,5 @@ class ServerError(HttpError):
|
|||
Make this a 500
|
||||
"""
|
||||
super(ServerError, self).__init__(500, 'Server Error')
|
||||
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2016 OpenLP Developers #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# This program is free software; you can redistribute it and/or modify it #
|
||||
# under the terms of the GNU General Public License as published by the Free #
|
||||
# Software Foundation; version 2 of the License. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT #
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
|
||||
# more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License along #
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The :mod:`http` module contains the API web server. This is a lightweight web server used by remotes to interact
|
||||
with OpenLP. It uses JSON to communicate with the remotes.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from PyQt5 import QtCore
|
||||
from waitress import serve
|
||||
|
||||
from openlp.core.api.http import application
|
||||
from openlp.core.common import RegistryProperties, OpenLPMixin
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HttpWorker(QtCore.QObject):
|
||||
"""
|
||||
A special Qt thread class to allow the HTTP server to run at the same time as the UI.
|
||||
"""
|
||||
def __init__(self):
|
||||
"""
|
||||
Constructor for the thread class.
|
||||
|
||||
:param server: The http server class.
|
||||
"""
|
||||
print("http init")
|
||||
super(HttpWorker, self).__init__()
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
Run the thread.
|
||||
"""
|
||||
print("runnnn")
|
||||
serve(application, host='0.0.0.0', port=4318)
|
||||
|
||||
def stop(self):
|
||||
pass
|
||||
|
||||
|
||||
class HttpServer(RegistryProperties, OpenLPMixin):
|
||||
"""
|
||||
Wrapper round a server instance
|
||||
"""
|
||||
def __init__(self):
|
||||
"""
|
||||
Initialise the http server, and start the http server
|
||||
"""
|
||||
super(HttpServer, self).__init__()
|
||||
self.worker = HttpWorker()
|
||||
self.thread = QtCore.QThread()
|
||||
self.worker.moveToThread(self.thread)
|
||||
self.thread.started.connect(self.worker.run)
|
||||
self.thread.start()
|
|
@ -19,64 +19,20 @@
|
|||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The :mod:`http` module contains the API web server. This is a lightweight web server used by remotes to interact
|
||||
with OpenLP. It uses JSON to communicate with the remotes.
|
||||
App stuff
|
||||
"""
|
||||
|
||||
import logging
|
||||
import json
|
||||
import re
|
||||
|
||||
from PyQt5 import QtCore
|
||||
from waitress import serve
|
||||
from webob import Request, Response
|
||||
|
||||
from openlp.core.api import NotFound, ServerError, HttpError
|
||||
from openlp.core.common import RegistryProperties, OpenLPMixin
|
||||
from openlp.core.api.http.errors import HttpError, NotFound, ServerError
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HttpThread(QtCore.QObject):
|
||||
"""
|
||||
A special Qt thread class to allow the HTTP server to run at the same time as the UI.
|
||||
"""
|
||||
def __init__(self):
|
||||
"""
|
||||
Constructor for the thread class.
|
||||
|
||||
:param server: The http server class.
|
||||
"""
|
||||
super().__init__()
|
||||
|
||||
def start(self):
|
||||
"""
|
||||
Run the thread.
|
||||
"""
|
||||
serve(application, host='0.0.0.0', port=4318)
|
||||
|
||||
def stop(self):
|
||||
pass
|
||||
|
||||
|
||||
class HttpServer(RegistryProperties, OpenLPMixin):
|
||||
"""
|
||||
Wrapper round a server instance
|
||||
"""
|
||||
def __init__(self):
|
||||
"""
|
||||
Initialise the http server, and start the http server
|
||||
"""
|
||||
super(HttpServer, self).__init__()
|
||||
self.thread = QtCore.QThread()
|
||||
self.worker = HttpThread()
|
||||
self.worker.moveToThread(self.thread)
|
||||
self.thread.started.connect(self.worker.start)
|
||||
self.thread.start()
|
||||
|
||||
|
||||
def _make_response(view_result):
|
||||
"""
|
||||
Create a Response object from response
|
||||
|
@ -167,5 +123,3 @@ class WSGIApplication(object):
|
|||
"""
|
||||
return self.wsgi_app(environ, start_response)
|
||||
|
||||
|
||||
application = WSGIApplication('api')
|
|
@ -25,7 +25,7 @@ import json
|
|||
from openlp.core.common import RegistryProperties, Settings
|
||||
|
||||
|
||||
class Poll(RegistryProperties):
|
||||
class Poller(RegistryProperties):
|
||||
"""
|
||||
Access by the web layer to get status type information from the application
|
||||
"""
|
||||
|
@ -33,7 +33,7 @@ class Poll(RegistryProperties):
|
|||
"""
|
||||
Constructor for the poll builder class.
|
||||
"""
|
||||
super(Poll, self).__init__()
|
||||
super(Poller, self).__init__()
|
||||
|
||||
def poll(self):
|
||||
"""
|
||||
|
|
|
@ -29,7 +29,6 @@ import asyncio
|
|||
import websockets
|
||||
import logging
|
||||
import time
|
||||
import json
|
||||
|
||||
from PyQt5 import QtCore
|
||||
|
||||
|
@ -48,13 +47,15 @@ class WebSocketWorker(QtCore.QObject):
|
|||
|
||||
:param server: The http server class.
|
||||
"""
|
||||
super().__init__()
|
||||
print("ws init")
|
||||
self.ws_server = server
|
||||
super(WebSocketWorker, self).__init__()
|
||||
|
||||
def start(self):
|
||||
def run(self):
|
||||
"""
|
||||
Run the thread.
|
||||
"""
|
||||
print("ws run")
|
||||
self.ws_server.start_server()
|
||||
|
||||
def stop(self):
|
||||
|
@ -67,14 +68,14 @@ class WebSocketServer(RegistryProperties, OpenLPMixin):
|
|||
"""
|
||||
def __init__(self):
|
||||
"""
|
||||
Initialise the http server, and start the WebSockets server
|
||||
Initialise and start the WebSockets server
|
||||
"""
|
||||
super(WebSocketServer, self).__init__()
|
||||
self.settings_section = 'remotes'
|
||||
self.thread = QtCore.QThread()
|
||||
self.worker = WebSocketWorker(self)
|
||||
self.thread = QtCore.QThread()
|
||||
self.worker.moveToThread(self.thread)
|
||||
self.thread.started.connect(self.worker.start)
|
||||
self.thread.started.connect(self.worker.run)
|
||||
self.thread.start()
|
||||
|
||||
def start_server(self):
|
||||
|
@ -126,17 +127,18 @@ class WebSocketServer(RegistryProperties, OpenLPMixin):
|
|||
log.debug("web socket handler registered with client")
|
||||
previous_poll = None
|
||||
previous_main_poll = None
|
||||
api_poll = Registry().get('api_poll')
|
||||
poller = Registry().get('Poller')
|
||||
# TODO: FIXME: These URLs need to be named better
|
||||
if path == '/poll':
|
||||
while True:
|
||||
current_poll = api_poll.poll()
|
||||
current_poll = poller.poll()
|
||||
if current_poll != previous_poll:
|
||||
yield from request.send(current_poll)
|
||||
previous_poll = current_poll
|
||||
yield from asyncio.sleep(0.2)
|
||||
elif path == '/main_poll':
|
||||
while True:
|
||||
main_poll = api_poll.main_poll()
|
||||
main_poll = poller.main_poll()
|
||||
if main_poll != previous_main_poll:
|
||||
yield from request.send(main_poll)
|
||||
previous_main_poll = main_poll
|
||||
|
@ -150,41 +152,3 @@ class WebSocketServer(RegistryProperties, OpenLPMixin):
|
|||
self.http_thread.stop()
|
||||
self.httpd = None
|
||||
log.debug('Stopped the server.')
|
||||
|
||||
|
||||
class Poll(RegistryProperties):
|
||||
"""
|
||||
Access by the web layer to get status type information from the application
|
||||
"""
|
||||
def __init__(self):
|
||||
"""
|
||||
Constructor for the poll builder class.
|
||||
"""
|
||||
super(Poll, self).__init__()
|
||||
|
||||
def poll(self):
|
||||
"""
|
||||
Poll OpenLP to determine the current slide number and item name.
|
||||
"""
|
||||
result = {
|
||||
'service': self.service_manager.service_id,
|
||||
'slide': self.live_controller.selected_row or 0,
|
||||
'item': self.live_controller.service_item.unique_identifier if self.live_controller.service_item else '',
|
||||
'twelve': Settings().value('remotes/twelve hour'),
|
||||
'blank': self.live_controller.blank_screen.isChecked(),
|
||||
'theme': self.live_controller.theme_screen.isChecked(),
|
||||
'display': self.live_controller.desktop_screen.isChecked(),
|
||||
'version': 2,
|
||||
'isSecure': Settings().value('remotes/authentication enabled'),
|
||||
'isAuthorised': False
|
||||
}
|
||||
return json.dumps({'results': result}).encode()
|
||||
|
||||
def main_poll(self):
|
||||
"""
|
||||
Poll OpenLP to determine the current slide count.
|
||||
"""
|
||||
result = {
|
||||
'slide_count': self.live_controller.slide_count
|
||||
}
|
||||
return json.dumps({'results': result}).encode()
|
||||
|
|
|
@ -35,9 +35,9 @@ class TestApiController(TestCase):
|
|||
"""
|
||||
A test suite to test out the Error in the API code
|
||||
"""
|
||||
@patch('openlp.core.api.apicontroller.Poll')
|
||||
@patch('openlp.core.api.apicontroller.WebSocketServer')
|
||||
@patch('openlp.core.api.apicontroller.HttpServer')
|
||||
@patch('openlp.core.api.controller.Poll')
|
||||
@patch('openlp.core.api.controller.WebSocketServer')
|
||||
@patch('openlp.core.api.controller.http.HttpServer')
|
||||
def test_bootstrap(self, mock_http, mock_ws, mock_poll):
|
||||
"""
|
||||
Test the Not Found error displays the correct information
|
||||
|
|
|
@ -25,7 +25,7 @@ Functional tests to test the API Error Class.
|
|||
|
||||
from unittest import TestCase
|
||||
|
||||
from openlp.core.api.errors import NotFound, ServerError
|
||||
from openlp.core.api.http.errors import NotFound, ServerError
|
||||
|
||||
|
||||
class TestApiError(TestCase):
|
||||
|
|
Loading…
Reference in New Issue