diff --git a/.bzrignore b/.bzrignore index 01c96078a..9fa1b4bb0 100644 --- a/.bzrignore +++ b/.bzrignore @@ -45,3 +45,4 @@ tags output htmlcov openlp-test-projectordb.sqlite +.cache diff --git a/copyright.txt b/copyright.txt index ea62548f4..711ded4ae 100644 --- a/copyright.txt +++ b/copyright.txt @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp.py b/openlp.py index 9bccc526f..38e270a9d 100755 --- a/openlp.py +++ b/openlp.py @@ -5,7 +5,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -39,7 +39,7 @@ def set_up_fault_handling(): """ # Create the cache directory if it doesn't exist, and enable the fault handler to log to an error log file create_paths(AppLocation.get_directory(AppLocation.CacheDir)) - faulthandler.enable(open(str(AppLocation.get_directory(AppLocation.CacheDir) / 'error.log'), 'wb')) + faulthandler.enable((AppLocation.get_directory(AppLocation.CacheDir) / 'error.log').open('wb')) if __name__ == '__main__': diff --git a/openlp/__init__.py b/openlp/__init__.py index 2074ec39a..acd4725ec 100644 --- a/openlp/__init__.py +++ b/openlp/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index b3fa9b6a6..a25aadd1c 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/api/__init__.py b/openlp/core/api/__init__.py index 015f0cec3..f3081d022 100644 --- a/openlp/core/api/__init__.py +++ b/openlp/core/api/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -20,9 +20,9 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from openlp.core.api.http.endpoint import Endpoint from openlp.core.api.http import register_endpoint, requires_auth -from openlp.core.api.tab import ApiTab +from openlp.core.api.http.endpoint import Endpoint from openlp.core.api.poll import Poller +from openlp.core.api.tab import ApiTab __all__ = ['Endpoint', 'ApiTab', 'register_endpoint', 'requires_auth'] diff --git a/openlp/core/api/deploy.py b/openlp/core/api/deploy.py index a42f83f0c..e336019d3 100644 --- a/openlp/core/api/deploy.py +++ b/openlp/core/api/deploy.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -25,8 +25,8 @@ Download and "install" the remote web client from zipfile import ZipFile from openlp.core.common.applocation import AppLocation +from openlp.core.common.httputils import download_file, get_web_page, get_url_file_size from openlp.core.common.registry import Registry -from openlp.core.common.httputils import url_get_file, get_web_page, get_url_file_size def deploy_zipfile(app_root_path, zip_name): @@ -65,7 +65,7 @@ def download_and_check(callback=None): sha256, version = download_sha256() file_size = get_url_file_size('https://get.openlp.org/webclient/site.zip') callback.setRange(0, file_size) - if url_get_file(callback, 'https://get.openlp.org/webclient/site.zip', - AppLocation.get_section_data_path('remotes') / 'site.zip', - sha256=sha256): + if download_file(callback, 'https://get.openlp.org/webclient/site.zip', + AppLocation.get_section_data_path('remotes') / 'site.zip', + sha256=sha256): deploy_zipfile(AppLocation.get_section_data_path('remotes'), 'site.zip') diff --git a/openlp/core/api/endpoint/__init__.py b/openlp/core/api/endpoint/__init__.py index fcba538e5..ffc1d8628 100644 --- a/openlp/core/api/endpoint/__init__.py +++ b/openlp/core/api/endpoint/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/api/endpoint/controller.py b/openlp/core/api/endpoint/controller.py index 13e8d1681..4e897f370 100644 --- a/openlp/core/api/endpoint/controller.py +++ b/openlp/core/api/endpoint/controller.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -19,14 +19,14 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +import json import logging import os -import urllib.request import urllib.error -import json +import urllib.request -from openlp.core.api.http.endpoint import Endpoint from openlp.core.api.http import requires_auth +from openlp.core.api.http.endpoint import Endpoint from openlp.core.common.applocation import AppLocation from openlp.core.common.path import Path from openlp.core.common.registry import Registry diff --git a/openlp/core/api/endpoint/core.py b/openlp/core/api/endpoint/core.py index 8b9bcc4c0..9ad95f4df 100644 --- a/openlp/core/api/endpoint/core.py +++ b/openlp/core/api/endpoint/core.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -27,11 +27,10 @@ import os from openlp.core.api.http import requires_auth from openlp.core.api.http.endpoint import Endpoint -from openlp.core.common.registry import Registry from openlp.core.common.i18n import UiStrings, translate +from openlp.core.common.registry import Registry from openlp.core.lib import PluginStatus, StringContent, image_to_byte - template_dir = 'templates' static_dir = 'static' blank_dir = os.path.join(static_dir, 'index') diff --git a/openlp/core/api/endpoint/pluginhelpers.py b/openlp/core/api/endpoint/pluginhelpers.py index b8f606fbc..a74fa524a 100644 --- a/openlp/core/api/endpoint/pluginhelpers.py +++ b/openlp/core/api/endpoint/pluginhelpers.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/api/endpoint/remote.py b/openlp/core/api/endpoint/remote.py index 3a408f74e..0e637339f 100644 --- a/openlp/core/api/endpoint/remote.py +++ b/openlp/core/api/endpoint/remote.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -21,9 +21,8 @@ ############################################################################### import logging -from openlp.core.api.http.endpoint import Endpoint from openlp.core.api.endpoint.core import TRANSLATED_STRINGS - +from openlp.core.api.http.endpoint import Endpoint log = logging.getLogger(__name__) diff --git a/openlp/core/api/endpoint/service.py b/openlp/core/api/endpoint/service.py index ab9ae6740..b642c3151 100644 --- a/openlp/core/api/endpoint/service.py +++ b/openlp/core/api/endpoint/service.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -19,14 +19,13 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -import logging import json +import logging from openlp.core.api.http import requires_auth from openlp.core.api.http.endpoint import Endpoint from openlp.core.common.registry import Registry - log = logging.getLogger(__name__) service_endpoint = Endpoint('service') diff --git a/openlp/core/api/http/__init__.py b/openlp/core/api/http/__init__.py index 8ff08b1e7..9b8086519 100644 --- a/openlp/core/api/http/__init__.py +++ b/openlp/core/api/http/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,10 +22,11 @@ import base64 from functools import wraps + from webob import Response -from openlp.core.common.settings import Settings from openlp.core.api.http.wsgiapp import WSGIApplication +from openlp.core.common.settings import Settings from .errors import NotFound, ServerError, HttpError application = WSGIApplication('api') diff --git a/openlp/core/api/http/endpoint.py b/openlp/core/api/http/endpoint.py index 011b7e73a..29184f6f8 100644 --- a/openlp/core/api/http/endpoint.py +++ b/openlp/core/api/http/endpoint.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/api/http/errors.py b/openlp/core/api/http/errors.py index acb851aad..4b344ff97 100644 --- a/openlp/core/api/http/errors.py +++ b/openlp/core/api/http/errors.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/api/http/server.py b/openlp/core/api/http/server.py index c80275801..914ce2278 100644 --- a/openlp/core/api/http/server.py +++ b/openlp/core/api/http/server.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -27,40 +27,33 @@ import logging import time from PyQt5 import QtCore, QtWidgets -from waitress import serve +from waitress.server import create_server from openlp.core.api.deploy import download_and_check, download_sha256 from openlp.core.api.endpoint.controller import controller_endpoint, api_controller_endpoint from openlp.core.api.endpoint.core import chords_endpoint, stage_endpoint, blank_endpoint, main_endpoint -from openlp.core.api.endpoint.service import service_endpoint, api_service_endpoint from openlp.core.api.endpoint.remote import remote_endpoint -from openlp.core.api.http import register_endpoint +from openlp.core.api.endpoint.service import service_endpoint, api_service_endpoint from openlp.core.api.http import application +from openlp.core.api.http import register_endpoint from openlp.core.api.poll import Poller from openlp.core.common.applocation import AppLocation from openlp.core.common.i18n import UiStrings +from openlp.core.common.i18n import translate from openlp.core.common.mixins import LogMixin, RegistryProperties from openlp.core.common.path import create_paths from openlp.core.common.registry import Registry, RegistryBase from openlp.core.common.settings import Settings -from openlp.core.common.i18n import translate +from openlp.core.threading import ThreadWorker, run_thread log = logging.getLogger(__name__) -class HttpWorker(QtCore.QObject): +class HttpWorker(ThreadWorker): """ 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(HttpWorker, self).__init__() - - def run(self): + def start(self): """ Run the thread. """ @@ -68,12 +61,21 @@ class HttpWorker(QtCore.QObject): port = Settings().value('api/port') Registry().execute('get_website_version') try: - serve(application, host=address, port=port) + self.server = create_server(application, host=address, port=port) + self.server.run() except OSError: log.exception('An error occurred when serving the application.') + self.quit.emit() def stop(self): - pass + """ + A method to stop the worker + """ + if hasattr(self, 'server'): + # Loop through all the channels and close them to stop the server + for channel in self.server._map.values(): + if hasattr(channel, 'close'): + channel.close() class HttpServer(RegistryBase, RegistryProperties, LogMixin): @@ -85,12 +87,9 @@ class HttpServer(RegistryBase, RegistryProperties, LogMixin): Initialise the http server, and start the http server """ super(HttpServer, self).__init__(parent) - if Registry().get_flag('no_web_server'): - self.worker = HttpWorker() - self.thread = QtCore.QThread() - self.worker.moveToThread(self.thread) - self.thread.started.connect(self.worker.run) - self.thread.start() + if not Registry().get_flag('no_web_server'): + worker = HttpWorker() + run_thread(worker, 'http_server') Registry().register_function('download_website', self.first_time) Registry().register_function('get_website_version', self.website_version) Registry().set_flag('website_version', '0.0') @@ -167,7 +166,7 @@ class DownloadProgressDialog(QtWidgets.QProgressDialog): self.was_cancelled = False self.previous_size = 0 - def _download_progress(self, count, block_size): + def update_progress(self, count, block_size): """ Calculate and display the download progress. """ diff --git a/openlp/core/api/http/wsgiapp.py b/openlp/core/api/http/wsgiapp.py index 4c863b7cb..3c262e365 100644 --- a/openlp/core/api/http/wsgiapp.py +++ b/openlp/core/api/http/wsgiapp.py @@ -5,7 +5,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -30,9 +30,8 @@ import re from webob import Request, Response from webob.static import DirectoryApp -from openlp.core.common.applocation import AppLocation from openlp.core.api.http.errors import HttpError, NotFound, ServerError - +from openlp.core.common.applocation import AppLocation ARGS_REGEX = re.compile(r'''\{(\w+)(?::([^}]+))?\}''', re.VERBOSE) diff --git a/openlp/core/api/poll.py b/openlp/core/api/poll.py index d2d36f60a..b3149d470 100644 --- a/openlp/core/api/poll.py +++ b/openlp/core/api/poll.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/api/tab.py b/openlp/core/api/tab.py index ddca61176..eaa021800 100644 --- a/openlp/core/api/tab.py +++ b/openlp/core/api/tab.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/api/websockets.py b/openlp/core/api/websockets.py index 3417eb74d..5528b4250 100644 --- a/openlp/core/api/websockets.py +++ b/openlp/core/api/websockets.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -24,41 +24,92 @@ The :mod:`http` module contains the API web server. This is a lightweight web se with OpenLP. It uses JSON to communicate with the remotes. """ import asyncio -import websockets import json import logging import time -from PyQt5 import QtCore +from websockets import serve from openlp.core.common.mixins import LogMixin, RegistryProperties from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings +from openlp.core.threading import ThreadWorker, run_thread log = logging.getLogger(__name__) -class WebSocketWorker(QtCore.QObject): +async def handle_websocket(request, path): + """ + Handle web socket requests and return the poll information + + Check every 0.2 seconds to get the latest position and send if it changed. This only gets triggered when the first + client connects. + + :param request: request from client + :param path: determines the endpoints supported + """ + log.debug('WebSocket handler registered with client') + previous_poll = None + previous_main_poll = None + poller = Registry().get('poller') + if path == '/state': + while True: + current_poll = poller.poll() + if current_poll != previous_poll: + await request.send(json.dumps(current_poll).encode()) + previous_poll = current_poll + await asyncio.sleep(0.2) + elif path == '/live_changed': + while True: + main_poll = poller.main_poll() + if main_poll != previous_main_poll: + await request.send(main_poll) + previous_main_poll = main_poll + await asyncio.sleep(0.2) + + +class WebSocketWorker(ThreadWorker, RegistryProperties, LogMixin): """ A special Qt thread class to allow the WebSockets server to run at the same time as the UI. """ - def __init__(self, server): + def start(self): """ - Constructor for the thread class. - - :param server: The http server class. + Run the worker. """ - self.ws_server = server - super(WebSocketWorker, self).__init__() - - def run(self): - """ - Run the thread. - """ - self.ws_server.start_server() + address = Settings().value('api/ip address') + port = Settings().value('api/websocket port') + # Start the event loop + self.event_loop = asyncio.new_event_loop() + asyncio.set_event_loop(self.event_loop) + # Create the websocker server + loop = 1 + self.server = None + while not self.server: + try: + self.server = serve(handle_websocket, address, port) + log.debug('WebSocket server started on {addr}:{port}'.format(addr=address, port=port)) + except Exception: + log.exception('Failed to start WebSocket server') + loop += 1 + time.sleep(0.1) + if not self.server and loop > 3: + log.error('Unable to start WebSocket server {addr}:{port}, giving up'.format(addr=address, port=port)) + if self.server: + # If the websocket server exists, start listening + self.event_loop.run_until_complete(self.server) + self.event_loop.run_forever() + self.quit.emit() def stop(self): - self.ws_server.stop = True + """ + Stop the websocket server + """ + if hasattr(self.server, 'ws_server'): + self.server.ws_server.close() + elif hasattr(self.server, 'server'): + self.server.server.close() + self.event_loop.stop() + self.event_loop.close() class WebSocketServer(RegistryProperties, LogMixin): @@ -70,74 +121,6 @@ class WebSocketServer(RegistryProperties, LogMixin): Initialise and start the WebSockets server """ super(WebSocketServer, self).__init__() - if Registry().get_flag('no_web_server'): - self.settings_section = 'api' - self.worker = WebSocketWorker(self) - self.thread = QtCore.QThread() - self.worker.moveToThread(self.thread) - self.thread.started.connect(self.worker.run) - self.thread.start() - - def start_server(self): - """ - Start the correct server and save the handler - """ - address = Settings().value(self.settings_section + '/ip address') - port = Settings().value(self.settings_section + '/websocket port') - self.start_websocket_instance(address, port) - # If web socket server start listening - if hasattr(self, 'ws_server') and self.ws_server: - event_loop = asyncio.new_event_loop() - asyncio.set_event_loop(event_loop) - event_loop.run_until_complete(self.ws_server) - event_loop.run_forever() - else: - log.debug('Failed to start ws server on port {port}'.format(port=port)) - - def start_websocket_instance(self, address, port): - """ - Start the server - - :param address: The server address - :param port: The run port - """ - loop = 1 - while loop < 4: - try: - self.ws_server = websockets.serve(self.handle_websocket, address, port) - log.debug("Web Socket Server started for class {address} {port}".format(address=address, port=port)) - break - except Exception as e: - log.error('Failed to start ws server {why}'.format(why=e)) - loop += 1 - time.sleep(0.1) - - @staticmethod - async def handle_websocket(request, path): - """ - Handle web socket requests and return the poll information. - Check ever 0.2 seconds to get the latest position and send if changed. - Only gets triggered when 1st client attaches - - :param request: request from client - :param path: determines the endpoints supported - :return: - """ - log.debug("web socket handler registered with client") - previous_poll = None - previous_main_poll = None - poller = Registry().get('poller') - if path == '/state': - while True: - current_poll = poller.poll() - if current_poll != previous_poll: - await request.send(json.dumps(current_poll).encode()) - previous_poll = current_poll - await asyncio.sleep(0.2) - elif path == '/live_changed': - while True: - main_poll = poller.main_poll() - if main_poll != previous_main_poll: - await request.send(main_poll) - previous_main_poll = main_poll - await asyncio.sleep(0.2) + if not Registry().get_flag('no_web_server'): + worker = WebSocketWorker() + run_thread(worker, 'websocket_server') diff --git a/openlp/core/app.py b/openlp/core/app.py index 114a62807..2a6cf8494 100644 --- a/openlp/core/app.py +++ b/openlp/core/app.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -42,7 +42,6 @@ from openlp.core.common.mixins import LogMixin from openlp.core.common.path import create_paths, copytree from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings -from openlp.core.version import check_for_update, get_version from openlp.core.display.screens import ScreenList from openlp.core.resources import qInitResources from openlp.core.ui import SplashScreen @@ -51,7 +50,7 @@ from openlp.core.ui.firsttimeform import FirstTimeForm from openlp.core.ui.firsttimelanguageform import FirstTimeLanguageForm from openlp.core.ui.mainwindow import MainWindow from openlp.core.ui.style import get_application_stylesheet - +from openlp.core.version import check_for_update, get_version __all__ = ['OpenLP', 'main'] @@ -64,8 +63,8 @@ class OpenLP(QtWidgets.QApplication, LogMixin): The core application class. This class inherits from Qt's QApplication class in order to provide the core of the application. """ - args = [] + worker_threads = {} def exec(self): """ @@ -305,8 +304,7 @@ def parse_options(args=None): 'off a USB flash drive (not implemented).') parser.add_argument('-d', '--dev-version', dest='dev_version', action='store_true', help='Ignore the version file and pull the version directly from Bazaar') - parser.add_argument('-s', '--style', dest='style', help='Set the Qt5 style (passed directly to Qt5).') - parser.add_argument('-w', '--no-web-server', dest='no_web_server', action='store_false', + parser.add_argument('-w', '--no-web-server', dest='no_web_server', action='store_true', help='Turn off the Web and Socket Server ') parser.add_argument('rargs', nargs='?', default=[]) # Parse command line options and deal with them. Use args supplied pragmatically if possible. @@ -344,8 +342,6 @@ def main(args=None): log.setLevel(logging.WARNING) else: log.setLevel(logging.INFO) - if args and args.style: - qt_args.extend(['-style', args.style]) # Throw the rest of the arguments at Qt, just in case. qt_args.extend(args.rargs) # Bug #1018855: Set the WM_CLASS property in X11 @@ -359,7 +355,7 @@ def main(args=None): application.setOrganizationDomain('openlp.org') application.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True) application.setAttribute(QtCore.Qt.AA_DontCreateNativeWidgetSiblings, True) - if args and args.portable: + if args.portable: application.setApplicationName('OpenLPPortable') Settings.setDefaultFormat(Settings.IniFormat) # Get location OpenLPPortable.ini diff --git a/openlp/core/common/__init__.py b/openlp/core/common/__init__.py index 99e222041..e4c806f22 100644 --- a/openlp/core/common/__init__.py +++ b/openlp/core/common/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -30,13 +30,13 @@ import os import re import sys import traceback -from chardet.universaldetector import UniversalDetector from ipaddress import IPv4Address, IPv6Address, AddressValueError from shutil import which from subprocess import check_output, CalledProcessError, STDOUT from PyQt5 import QtGui from PyQt5.QtCore import QCryptographicHash as QHash +from chardet.universaldetector import UniversalDetector log = logging.getLogger(__name__ + '.__init__') @@ -80,6 +80,7 @@ def extension_loader(glob_pattern, excluded_files=[]): extension_path = extension_path.relative_to(app_dir) if extension_path.name in excluded_files: continue + log.debug('Attempting to import %s', extension_path) module_name = path_to_module(extension_path) try: importlib.import_module(module_name) diff --git a/openlp/core/common/actions.py b/openlp/core/common/actions.py index a5b417017..f4fbdd9db 100644 --- a/openlp/core/common/actions.py +++ b/openlp/core/common/actions.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -29,7 +29,6 @@ from PyQt5 import QtCore, QtGui, QtWidgets from openlp.core.common.settings import Settings - log = logging.getLogger(__name__) diff --git a/openlp/core/common/applocation.py b/openlp/core/common/applocation.py index 279c49002..14e6e4577 100644 --- a/openlp/core/common/applocation.py +++ b/openlp/core/common/applocation.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -157,7 +157,7 @@ def _get_os_dir_path(dir_type): return directory return Path('/usr', 'share', 'openlp') if XDG_BASE_AVAILABLE: - if dir_type == AppLocation.DataDir or dir_type == AppLocation.CacheDir: + if dir_type == AppLocation.DataDir: return Path(BaseDirectory.xdg_data_home, 'openlp') elif dir_type == AppLocation.CacheDir: return Path(BaseDirectory.xdg_cache_home, 'openlp') diff --git a/openlp/core/common/db.py b/openlp/core/common/db.py index a88577932..ef5b7b2b7 100644 --- a/openlp/core/common/db.py +++ b/openlp/core/common/db.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -27,7 +27,6 @@ from copy import deepcopy import sqlalchemy - log = logging.getLogger(__name__) diff --git a/openlp/core/common/httputils.py b/openlp/core/common/httputils.py index 21b778b80..e7d11fad5 100644 --- a/openlp/core/common/httputils.py +++ b/openlp/core/common/httputils.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -20,7 +20,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### """ -The :mod:`openlp.core.utils` module provides the utility libraries for OpenLP. +The :mod:`openlp.core.common.httputils` module provides the utility methods for downloading stuff. """ import hashlib import logging @@ -104,7 +104,7 @@ def get_web_page(url, headers=None, update_openlp=False, proxies=None): if retries >= CONNECTION_RETRIES: raise ConnectionError('Unable to connect to {url}, see log for details'.format(url=url)) retries += 1 - except: + except: # noqa # Don't know what's happening, so reraise the original log.exception('Unknown error when trying to connect to {url}'.format(url=url)) raise @@ -136,12 +136,12 @@ def get_url_file_size(url): continue -def url_get_file(callback, url, file_path, sha256=None): +def download_file(update_object, url, file_path, sha256=None): """" Download a file given a URL. The file is retrieved in chunks, giving the ability to cancel the download at any point. Returns False on download error. - :param callback: the class which needs to be updated + :param update_object: the object which needs to be updated :param url: URL to download :param file_path: Destination file :param sha256: The check sum value to be checked against the download value @@ -158,13 +158,14 @@ def url_get_file(callback, url, file_path, sha256=None): hasher = hashlib.sha256() # Download until finished or canceled. for chunk in response.iter_content(chunk_size=block_size): - if callback.was_cancelled: + if hasattr(update_object, 'was_cancelled') and update_object.was_cancelled: break saved_file.write(chunk) if sha256: hasher.update(chunk) block_count += 1 - callback._download_progress(block_count, block_size) + if hasattr(update_object, 'update_progress'): + update_object.update_progress(block_count, block_size) response.close() if sha256 and hasher.hexdigest() != sha256: log.error('sha256 sums did not match for file %s, got %s, expected %s', file_path, hasher.hexdigest(), @@ -183,7 +184,7 @@ def url_get_file(callback, url, file_path, sha256=None): retries += 1 time.sleep(0.1) continue - if callback.was_cancelled and file_path.exists(): + if hasattr(update_object, 'was_cancelled') and update_object.was_cancelled and file_path.exists(): file_path.unlink() return True diff --git a/openlp/core/common/i18n.py b/openlp/core/common/i18n.py index 9149f3fe6..cb0c2904c 100644 --- a/openlp/core/common/i18n.py +++ b/openlp/core/common/i18n.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/common/json.py b/openlp/core/common/json.py index f0e45ee2a..ed785ee72 100644 --- a/openlp/core/common/json.py +++ b/openlp/core/common/json.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/common/mixins.py b/openlp/core/common/mixins.py index a07940e10..28c478b93 100644 --- a/openlp/core/common/mixins.py +++ b/openlp/core/common/mixins.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,8 +22,8 @@ """ Provide Error Handling and login Services """ -import logging import inspect +import logging from openlp.core.common import is_win, trace_error_handler from openlp.core.common.registry import Registry diff --git a/openlp/core/common/path.py b/openlp/core/common/path.py index 0e4b45c2a..ec251c5f1 100644 --- a/openlp/core/common/path.py +++ b/openlp/core/common/path.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -26,9 +26,9 @@ from contextlib import suppress from openlp.core.common import is_win if is_win(): - from pathlib import WindowsPath as PathVariant + from pathlib import WindowsPath as PathVariant # pragma: nocover else: - from pathlib import PosixPath as PathVariant + from pathlib import PosixPath as PathVariant # pragma: nocover log = logging.getLogger(__name__) diff --git a/openlp/core/common/registry.py b/openlp/core/common/registry.py index 45d41b083..5018fc66d 100644 --- a/openlp/core/common/registry.py +++ b/openlp/core/common/registry.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/common/settings.py b/openlp/core/common/settings.py index 54f1d9b2a..1c1186feb 100644 --- a/openlp/core/common/settings.py +++ b/openlp/core/common/settings.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -23,8 +23,8 @@ This class contains the core default settings. """ import datetime -import logging import json +import logging import os from tempfile import gettempdir diff --git a/openlp/core/display/__init__.py b/openlp/core/display/__init__.py index dea4ef4db..a35bd3243 100644 --- a/openlp/core/display/__init__.py +++ b/openlp/core/display/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/display/renderer.py b/openlp/core/display/renderer.py index 836e5edea..54d0aaf10 100644 --- a/openlp/core/display/renderer.py +++ b/openlp/core/display/renderer.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -21,10 +21,11 @@ ############################################################################### import re - from string import Template + from PyQt5 import QtGui, QtCore, QtWebKitWidgets +from openlp.core.common import ThemeLevel from openlp.core.common.mixins import LogMixin, RegistryProperties from openlp.core.common.path import path_to_str from openlp.core.common.registry import Registry, RegistryBase @@ -32,7 +33,6 @@ from openlp.core.common.settings import Settings from openlp.core.display.screens import ScreenList from openlp.core.lib import FormattingTags, ImageSource, ItemCapabilities, ServiceItem, expand_tags, build_chords_css, \ build_lyrics_format_css, build_lyrics_outline_css -from openlp.core.common import ThemeLevel from openlp.core.ui.maindisplay import MainDisplay VERSE = 'The Lord said to {r}Noah{/r}: \n' \ diff --git a/openlp/core/display/screens.py b/openlp/core/display/screens.py index 0a1a4cd28..f0a05f31b 100644 --- a/openlp/core/display/screens.py +++ b/openlp/core/display/screens.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -23,14 +23,14 @@ The :mod:`screen` module provides management functionality for a machines' displays. """ -import logging import copy +import logging from PyQt5 import QtCore +from openlp.core.common.i18n import translate from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings -from openlp.core.common.i18n import translate log = logging.getLogger(__name__) diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index 0c6e64546..bcc87c19e 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -25,9 +25,8 @@ OpenLP work. """ import html import logging -import os -import re import math +import re from PyQt5 import QtCore, QtGui, QtWidgets diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index 9e3c5aff9..6898e0469 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/lib/exceptions.py b/openlp/core/lib/exceptions.py index 26ff56a79..63cebfa8c 100644 --- a/openlp/core/lib/exceptions.py +++ b/openlp/core/lib/exceptions.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/lib/formattingtags.py b/openlp/core/lib/formattingtags.py index c364d388e..33fd28a5a 100644 --- a/openlp/core/lib/formattingtags.py +++ b/openlp/core/lib/formattingtags.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -24,8 +24,8 @@ Provide HTML Tag management and Formatting Tag access class """ import json -from openlp.core.common.settings import Settings from openlp.core.common.i18n import translate +from openlp.core.common.settings import Settings class FormattingTags(object): diff --git a/openlp/core/lib/htmlbuilder.py b/openlp/core/lib/htmlbuilder.py index 0330f10c8..f6a0c6e61 100644 --- a/openlp/core/lib/htmlbuilder.py +++ b/openlp/core/lib/htmlbuilder.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -407,8 +407,8 @@ is the function which has to be called from outside. The generated and returned """ import logging - from string import Template + from PyQt5 import QtWebKit from openlp.core.common.settings import Settings diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index 81a1b659d..f452278c1 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -26,8 +26,8 @@ wait for the conversion to happen. """ import logging import os -import time import queue +import time from PyQt5 import QtCore @@ -35,13 +35,14 @@ from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings from openlp.core.display.screens import ScreenList from openlp.core.lib import resize_image, image_to_byte +from openlp.core.threading import ThreadWorker, run_thread log = logging.getLogger(__name__) -class ImageThread(QtCore.QThread): +class ImageWorker(ThreadWorker): """ - A special Qt thread class to speed up the display of images. This is threaded so it loads the frames and generates + A thread worker class to speed up the display of images. This is threaded so it loads the frames and generates byte stream in background. """ def __init__(self, manager): @@ -51,14 +52,21 @@ class ImageThread(QtCore.QThread): ``manager`` The image manager. """ - super(ImageThread, self).__init__(None) + super().__init__() self.image_manager = manager - def run(self): + def start(self): """ - Run the thread. + Start the worker """ self.image_manager.process() + self.quit.emit() + + def stop(self): + """ + Stop the worker + """ + self.image_manager.stop_manager = True class Priority(object): @@ -130,7 +138,7 @@ class Image(object): class PriorityQueue(queue.PriorityQueue): """ - Customised ``Queue.PriorityQueue``. + Customised ``queue.PriorityQueue``. Each item in the queue must be a tuple with three values. The first value is the :class:`Image`'s ``priority`` attribute, the second value the :class:`Image`'s ``secondary_priority`` attribute. The last value the :class:`Image` @@ -179,7 +187,6 @@ class ImageManager(QtCore.QObject): self.width = current_screen['size'].width() self.height = current_screen['size'].height() self._cache = {} - self.image_thread = ImageThread(self) self._conversion_queue = PriorityQueue() self.stop_manager = False Registry().register_function('images_regenerate', self.process_updates) @@ -230,9 +237,13 @@ class ImageManager(QtCore.QObject): """ Flush the queue to updated any data to update """ - # We want only one thread. - if not self.image_thread.isRunning(): - self.image_thread.start() + try: + worker = ImageWorker(self) + run_thread(worker, 'image_manager') + except KeyError: + # run_thread() will throw a KeyError if this thread already exists, so ignore it so that we don't + # try to start another thread when one is already running + pass def get_image(self, path, source, width=-1, height=-1): """ @@ -305,9 +316,7 @@ class ImageManager(QtCore.QObject): if image.path == path and image.timestamp != os.stat(path).st_mtime: image.timestamp = os.stat(path).st_mtime self._reset_image(image) - # We want only one thread. - if not self.image_thread.isRunning(): - self.image_thread.start() + self.process_updates() def process(self): """ diff --git a/openlp/core/lib/json/__init__.py b/openlp/core/lib/json/__init__.py index ea62548f4..711ded4ae 100644 --- a/openlp/core/lib/json/__init__.py +++ b/openlp/core/lib/json/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 55306267c..f5fc6d445 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -23,14 +23,13 @@ Provides the generic functions for interfacing plugins with the Media Manager. """ import logging -import os import re from PyQt5 import QtCore, QtWidgets from openlp.core.common.i18n import UiStrings, translate -from openlp.core.common.path import Path, path_to_str, str_to_path from openlp.core.common.mixins import RegistryProperties +from openlp.core.common.path import path_to_str, str_to_path from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings from openlp.core.lib import ServiceItem, StringContent, ServiceItemContext @@ -332,8 +331,7 @@ class MediaManagerItem(QtWidgets.QWidget, RegistryProperties): """ new_file_paths = [] error_shown = False - for file_name in data['files']: - file_path = str_to_path(file_name) + for file_path in data['file_paths']: if file_path.suffix[1:].lower() not in self.on_new_file_masks: if not error_shown: critical_error_message_box( diff --git a/openlp/core/lib/plugin.py b/openlp/core/lib/plugin.py index 7e3b2e416..acb874119 100644 --- a/openlp/core/lib/plugin.py +++ b/openlp/core/lib/plugin.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/lib/pluginmanager.py b/openlp/core/lib/pluginmanager.py index d4a02f8c0..00f2dd6d1 100644 --- a/openlp/core/lib/pluginmanager.py +++ b/openlp/core/lib/pluginmanager.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -71,7 +71,7 @@ class PluginManager(RegistryBase, LogMixin, RegistryProperties): """ Scan a directory for objects inheriting from the ``Plugin`` class. """ - glob_pattern = os.path.join('plugins', '*', '*plugin.py') + glob_pattern = os.path.join('plugins', '*', '[!.]*plugin.py') extension_loader(glob_pattern) plugin_classes = Plugin.__subclasses__() plugin_objects = [] diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py index 3a824d424..5d11f0c1f 100644 --- a/openlp/core/lib/serviceitem.py +++ b/openlp/core/lib/serviceitem.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -26,9 +26,9 @@ type and capability of an item. import datetime import html import logging +import ntpath import os import uuid -import ntpath from PyQt5 import QtGui diff --git a/openlp/core/lib/settingstab.py b/openlp/core/lib/settingstab.py index 06009ee3d..324628cd9 100644 --- a/openlp/core/lib/settingstab.py +++ b/openlp/core/lib/settingstab.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/lib/theme.py b/openlp/core/lib/theme.py index 92d12ebfd..b8baa97a5 100644 --- a/openlp/core/lib/theme.py +++ b/openlp/core/lib/theme.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/lib/ui.py b/openlp/core/lib/ui.py index 0d5b3c0bd..ac8441cf3 100644 --- a/openlp/core/lib/ui.py +++ b/openlp/core/lib/ui.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -32,7 +32,6 @@ from openlp.core.common.i18n import UiStrings, translate from openlp.core.common.registry import Registry from openlp.core.lib import build_icon - log = logging.getLogger(__name__) diff --git a/openlp/core/projectors/__init__.py b/openlp/core/projectors/__init__.py index 66cfd6080..bde2301fe 100644 --- a/openlp/core/projectors/__init__.py +++ b/openlp/core/projectors/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/projectors/constants.py b/openlp/core/projectors/constants.py index a9410d109..cabef8169 100644 --- a/openlp/core/projectors/constants.py +++ b/openlp/core/projectors/constants.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -32,9 +32,128 @@ log.debug('projector_constants loaded') # Set common constants. CR = chr(0x0D) # \r LF = chr(0x0A) # \n -PJLINK_PORT = 4352 -TIMEOUT = 30.0 +PJLINK_CLASS = '1' # Default to class 1 until we query the projector PJLINK_MAX_PACKET = 136 +PJLINK_PREFIX = '%' +PJLINK_PORT = 4352 +PJLINK_SUFFIX = CR +PJLINK_TIMEOUT = 30.0 + +# Error and status codes +S_OK = E_OK = 0 # E_OK included since I sometimes forget + +# Error codes. Start at 200 so we don't duplicate system error codes. +E_GENERAL = 200 # Unknown error +E_NOT_CONNECTED = 201 +E_UNDEFINED = 202 # PJLink ERR1 +E_PARAMETER = 203 # PJLink ERR2 +E_UNAVAILABLE = 204 # PJLink ERR3 +E_PROJECTOR = 205 # PJLink ERR4 +E_AUTHENTICATION = 206 # PJLink ERRA +E_NO_AUTHENTICATION = 207 # PJLink authentication mismatch between projector and program +E_PREFIX = 208 # PJLink invalid prefix for packet +E_CLASS = 209 # PJLink class version mismatch +E_INVALID_DATA = 210 +E_WARN = 211 +E_ERROR = 212 +E_FAN = 213 +E_LAMP = 214 +E_TEMP = 215 +E_COVER = 216 +E_FILTER = 217 +E_UNKNOWN = 218 + +# Remap Qt socket error codes to local error codes +E_CONNECTION_REFUSED = 230 +E_REMOTE_HOST_CLOSED_CONNECTION = 231 +E_HOST_NOT_FOUND = 232 +E_SOCKET_ACCESS = 233 +E_SOCKET_RESOURCE = 234 +E_SOCKET_TIMEOUT = 235 +E_DATAGRAM_TOO_LARGE = 236 +E_NETWORK = 237 +E_ADDRESS_IN_USE = 238 +E_SOCKET_ADDRESS_NOT_AVAILABLE = 239 +E_UNSUPPORTED_SOCKET_OPERATION = 240 +E_PROXY_AUTHENTICATION_REQUIRED = 241 +E_SLS_HANDSHAKE_FAILED = 242 +E_UNFINISHED_SOCKET_OPERATION = 243 +E_PROXY_CONNECTION_REFUSED = 244 +E_PROXY_CONNECTION_CLOSED = 245 +E_PROXY_CONNECTION_TIMEOUT = 246 +E_PROXY_NOT_FOUND = 247 +E_PROXY_PROTOCOL = 248 +E_UNKNOWN_SOCKET_ERROR = 249 + +# Status codes start at 300 + +# Remap Qt socket states to local status codes +S_NOT_CONNECTED = 300 +S_HOST_LOOKUP = 301 +S_CONNECTING = 302 +S_CONNECTED = 303 +S_BOUND = 304 +S_LISTENING = 305 # Listed as internal use only in QAbstractSocket +S_CLOSING = 306 + +# Projector states +S_INITIALIZE = 310 +S_STATUS = 311 +S_OFF = 312 +S_STANDBY = 313 +S_WARMUP = 314 +S_ON = 315 +S_COOLDOWN = 316 +S_INFO = 317 + +# Information that does not affect status +S_NETWORK_IDLE = 400 +S_NETWORK_SENDING = 401 +S_NETWORK_RECEIVING = 402 + +# Map PJlink errors to local status +PJLINK_ERRORS = { + 'ERRA': E_AUTHENTICATION, # Authentication error + 'ERR1': E_UNDEFINED, # Undefined command error + 'ERR2': E_PARAMETER, # Invalid parameter error + 'ERR3': E_UNAVAILABLE, # Projector busy + 'ERR4': E_PROJECTOR, # Projector or display failure + E_AUTHENTICATION: 'ERRA', + E_UNDEFINED: 'ERR1', + E_PARAMETER: 'ERR2', + E_UNAVAILABLE: 'ERR3', + E_PROJECTOR: 'ERR4' +} + +# Map QAbstractSocketState enums to local status +QSOCKET_STATE = { + 0: S_NOT_CONNECTED, # 'UnconnectedState', + 1: S_HOST_LOOKUP, # 'HostLookupState', + 2: S_CONNECTING, # 'ConnectingState', + 3: S_CONNECTED, # 'ConnectedState', + 4: S_BOUND, # 'BoundState', + 5: S_LISTENING, # 'ListeningState' - Noted as "Internal Use Only" on Qt website + 6: S_CLOSING, # 'ClosingState', + S_NOT_CONNECTED: 0, + S_HOST_LOOKUP: 1, + S_CONNECTING: 2, + S_CONNECTED: 3, + S_BOUND: 4, + S_LISTENING: 5, + S_CLOSING: 6 +} + +PROJECTOR_STATE = [ + S_INITIALIZE, + S_STATUS, + S_OFF, + S_STANDBY, + S_WARMUP, + S_ON, + S_COOLDOWN, + S_INFO +] + # NOTE: Changed format to account for some commands are both class 1 and 2 PJLINK_VALID_CMD = { 'ACKN': {'version': ['2', ], @@ -144,227 +263,140 @@ PJLINK_VALID_CMD = { } } -# QAbstractSocketState enums converted to string -S_QSOCKET_STATE = { - 0: 'QSocketState - UnconnectedState', - 1: 'QSocketState - HostLookupState', - 2: 'QSocketState - ConnectingState', - 3: 'QSocketState - ConnectedState', - 4: 'QSocketState - BoundState', - 5: 'QSocketState - ListeningState (internal use only)', - 6: 'QSocketState - ClosingState', - 'UnconnectedState': 0, - 'HostLookupState': 1, - 'ConnectingState': 2, - 'ConnectedState': 3, - 'BoundState': 4, - 'ListeningState': 5, - 'ClosingState': 6 -} +CONNECTION_ERRORS = [ + E_ADDRESS_IN_USE, + E_CONNECTION_REFUSED, + E_DATAGRAM_TOO_LARGE, + E_HOST_NOT_FOUND, + E_NETWORK, + E_NOT_CONNECTED, + E_PROXY_AUTHENTICATION_REQUIRED, + E_PROXY_CONNECTION_CLOSED, + E_PROXY_CONNECTION_REFUSED, + E_PROXY_CONNECTION_TIMEOUT, + E_PROXY_NOT_FOUND, + E_PROXY_PROTOCOL, + E_REMOTE_HOST_CLOSED_CONNECTION, + E_SLS_HANDSHAKE_FAILED, + E_SOCKET_ACCESS, + E_SOCKET_ADDRESS_NOT_AVAILABLE, + E_SOCKET_RESOURCE, + E_SOCKET_TIMEOUT, + E_UNFINISHED_SOCKET_OPERATION, + E_UNKNOWN_SOCKET_ERROR, + E_UNSUPPORTED_SOCKET_OPERATION +] -# Error and status codes -S_OK = E_OK = 0 # E_OK included since I sometimes forget -# Error codes. Start at 200 so we don't duplicate system error codes. -E_GENERAL = 200 # Unknown error -E_NOT_CONNECTED = 201 -E_FAN = 202 -E_LAMP = 203 -E_TEMP = 204 -E_COVER = 205 -E_FILTER = 206 -E_NO_AUTHENTICATION = 207 # PIN set and no authentication set on projector -E_UNDEFINED = 208 # ERR1 -E_PARAMETER = 209 # ERR2 -E_UNAVAILABLE = 210 # ERR3 -E_PROJECTOR = 211 # ERR4 -E_INVALID_DATA = 212 -E_WARN = 213 -E_ERROR = 214 -E_AUTHENTICATION = 215 # ERRA -E_CLASS = 216 -E_PREFIX = 217 +PROJECTOR_ERRORS = [ + E_AUTHENTICATION, + E_CLASS, + E_INVALID_DATA, + E_NO_AUTHENTICATION, + E_PARAMETER, + E_PREFIX, + E_PROJECTOR, + E_UNAVAILABLE, + E_UNDEFINED, + E_UNKNOWN +] -# Remap Qt socket error codes to projector error codes -E_CONNECTION_REFUSED = 230 -E_REMOTE_HOST_CLOSED_CONNECTION = 231 -E_HOST_NOT_FOUND = 232 -E_SOCKET_ACCESS = 233 -E_SOCKET_RESOURCE = 234 -E_SOCKET_TIMEOUT = 235 -E_DATAGRAM_TOO_LARGE = 236 -E_NETWORK = 237 -E_ADDRESS_IN_USE = 238 -E_SOCKET_ADDRESS_NOT_AVAILABLE = 239 -E_UNSUPPORTED_SOCKET_OPERATION = 240 -E_PROXY_AUTHENTICATION_REQUIRED = 241 -E_SLS_HANDSHAKE_FAILED = 242 -E_UNFINISHED_SOCKET_OPERATION = 243 -E_PROXY_CONNECTION_REFUSED = 244 -E_PROXY_CONNECTION_CLOSED = 245 -E_PROXY_CONNECTION_TIMEOUT = 246 -E_PROXY_NOT_FOUND = 247 -E_PROXY_PROTOCOL = 248 -E_UNKNOWN_SOCKET_ERROR = -1 - -# Status codes start at 300 -S_NOT_CONNECTED = 300 -S_CONNECTING = 301 -S_CONNECTED = 302 -S_INITIALIZE = 303 -S_STATUS = 304 -S_OFF = 305 -S_STANDBY = 306 -S_WARMUP = 307 -S_ON = 308 -S_COOLDOWN = 309 -S_INFO = 310 - -# Information that does not affect status -S_NETWORK_SENDING = 400 -S_NETWORK_RECEIVED = 401 - -CONNECTION_ERRORS = { - E_NOT_CONNECTED, E_NO_AUTHENTICATION, E_AUTHENTICATION, E_CLASS, - E_PREFIX, E_CONNECTION_REFUSED, E_REMOTE_HOST_CLOSED_CONNECTION, - E_HOST_NOT_FOUND, E_SOCKET_ACCESS, E_SOCKET_RESOURCE, E_SOCKET_TIMEOUT, - E_DATAGRAM_TOO_LARGE, E_NETWORK, E_ADDRESS_IN_USE, E_SOCKET_ADDRESS_NOT_AVAILABLE, - E_UNSUPPORTED_SOCKET_OPERATION, E_PROXY_AUTHENTICATION_REQUIRED, - E_SLS_HANDSHAKE_FAILED, E_UNFINISHED_SOCKET_OPERATION, E_PROXY_CONNECTION_REFUSED, - E_PROXY_CONNECTION_CLOSED, E_PROXY_CONNECTION_TIMEOUT, E_PROXY_NOT_FOUND, - E_PROXY_PROTOCOL, E_UNKNOWN_SOCKET_ERROR -} - -PJLINK_ERRORS = { - 'ERRA': E_AUTHENTICATION, # Authentication error - 'ERR1': E_UNDEFINED, # Undefined command error - 'ERR2': E_PARAMETER, # Invalid parameter error - 'ERR3': E_UNAVAILABLE, # Projector busy - 'ERR4': E_PROJECTOR, # Projector or display failure - E_AUTHENTICATION: 'ERRA', - E_UNDEFINED: 'ERR1', - E_PARAMETER: 'ERR2', - E_UNAVAILABLE: 'ERR3', - E_PROJECTOR: 'ERR4' -} - -# Map error/status codes to string -ERROR_STRING = { - 0: 'S_OK', - E_GENERAL: 'E_GENERAL', - E_NOT_CONNECTED: 'E_NOT_CONNECTED', - E_FAN: 'E_FAN', - E_LAMP: 'E_LAMP', - E_TEMP: 'E_TEMP', - E_COVER: 'E_COVER', - E_FILTER: 'E_FILTER', - E_AUTHENTICATION: 'E_AUTHENTICATION', - E_NO_AUTHENTICATION: 'E_NO_AUTHENTICATION', - E_UNDEFINED: 'E_UNDEFINED', - E_PARAMETER: 'E_PARAMETER', - E_UNAVAILABLE: 'E_UNAVAILABLE', - E_PROJECTOR: 'E_PROJECTOR', - E_INVALID_DATA: 'E_INVALID_DATA', - E_WARN: 'E_WARN', - E_ERROR: 'E_ERROR', - E_CLASS: 'E_CLASS', - E_PREFIX: 'E_PREFIX', # Last projector error - E_CONNECTION_REFUSED: 'E_CONNECTION_REFUSED', # First QtSocket error - E_REMOTE_HOST_CLOSED_CONNECTION: 'E_REMOTE_HOST_CLOSED_CONNECTION', - E_HOST_NOT_FOUND: 'E_HOST_NOT_FOUND', - E_SOCKET_ACCESS: 'E_SOCKET_ACCESS', - E_SOCKET_RESOURCE: 'E_SOCKET_RESOURCE', - E_SOCKET_TIMEOUT: 'E_SOCKET_TIMEOUT', - E_DATAGRAM_TOO_LARGE: 'E_DATAGRAM_TOO_LARGE', - E_NETWORK: 'E_NETWORK', +# Show status code as string +STATUS_CODE = { E_ADDRESS_IN_USE: 'E_ADDRESS_IN_USE', - E_SOCKET_ADDRESS_NOT_AVAILABLE: 'E_SOCKET_ADDRESS_NOT_AVAILABLE', - E_UNSUPPORTED_SOCKET_OPERATION: 'E_UNSUPPORTED_SOCKET_OPERATION', + E_AUTHENTICATION: 'E_AUTHENTICATION', + E_CLASS: 'E_CLASS', + E_CONNECTION_REFUSED: 'E_CONNECTION_REFUSED', + E_COVER: 'E_COVER', + E_DATAGRAM_TOO_LARGE: 'E_DATAGRAM_TOO_LARGE', + E_ERROR: 'E_ERROR', + E_FAN: 'E_FAN', + E_FILTER: 'E_FILTER', + E_GENERAL: 'E_GENERAL', + E_HOST_NOT_FOUND: 'E_HOST_NOT_FOUND', + E_INVALID_DATA: 'E_INVALID_DATA', + E_LAMP: 'E_LAMP', + E_NETWORK: 'E_NETWORK', + E_NO_AUTHENTICATION: 'E_NO_AUTHENTICATION', + E_NOT_CONNECTED: 'E_NOT_CONNECTED', + E_PARAMETER: 'E_PARAMETER', + E_PREFIX: 'E_PREFIX', + E_PROJECTOR: 'E_PROJECTOR', E_PROXY_AUTHENTICATION_REQUIRED: 'E_PROXY_AUTHENTICATION_REQUIRED', - E_SLS_HANDSHAKE_FAILED: 'E_SLS_HANDSHAKE_FAILED', - E_UNFINISHED_SOCKET_OPERATION: 'E_UNFINISHED_SOCKET_OPERATION', - E_PROXY_CONNECTION_REFUSED: 'E_PROXY_CONNECTION_REFUSED', E_PROXY_CONNECTION_CLOSED: 'E_PROXY_CONNECTION_CLOSED', + E_PROXY_CONNECTION_REFUSED: 'E_PROXY_CONNECTION_REFUSED', E_PROXY_CONNECTION_TIMEOUT: 'E_PROXY_CONNECTION_TIMEOUT', E_PROXY_NOT_FOUND: 'E_PROXY_NOT_FOUND', E_PROXY_PROTOCOL: 'E_PROXY_PROTOCOL', - E_UNKNOWN_SOCKET_ERROR: 'E_UNKNOWN_SOCKET_ERROR' -} - -STATUS_STRING = { - S_NOT_CONNECTED: 'S_NOT_CONNECTED', - S_CONNECTING: 'S_CONNECTING', - S_CONNECTED: 'S_CONNECTED', - S_STATUS: 'S_STATUS', - S_OFF: 'S_OFF', - S_INITIALIZE: 'S_INITIALIZE', - S_STANDBY: 'S_STANDBY', - S_WARMUP: 'S_WARMUP', - S_ON: 'S_ON', + E_REMOTE_HOST_CLOSED_CONNECTION: 'E_REMOTE_HOST_CLOSED_CONNECTION', + E_SLS_HANDSHAKE_FAILED: 'E_SLS_HANDSHAKE_FAILED', + E_SOCKET_ACCESS: 'E_SOCKET_ACCESS', + E_SOCKET_ADDRESS_NOT_AVAILABLE: 'E_SOCKET_ADDRESS_NOT_AVAILABLE', + E_SOCKET_RESOURCE: 'E_SOCKET_RESOURCE', + E_SOCKET_TIMEOUT: 'E_SOCKET_TIMEOUT', + E_TEMP: 'E_TEMP', + E_UNAVAILABLE: 'E_UNAVAILABLE', + E_UNDEFINED: 'E_UNDEFINED', + E_UNFINISHED_SOCKET_OPERATION: 'E_UNFINISHED_SOCKET_OPERATION', + E_UNKNOWN: 'E_UNKNOWN', + E_UNKNOWN_SOCKET_ERROR: 'E_UNKNOWN_SOCKET_ERROR', + E_UNSUPPORTED_SOCKET_OPERATION: 'E_UNSUPPORTED_SOCKET_OPERATION', + E_WARN: 'E_WARN', + S_BOUND: 'S_BOUND', S_COOLDOWN: 'S_COOLDOWN', + S_CLOSING: 'S_CLOSING', + S_CONNECTED: 'S_CONNECTED', + S_CONNECTING: 'S_CONNECTING', + S_HOST_LOOKUP: 'S_HOST_LOOKUP', S_INFO: 'S_INFO', + S_INITIALIZE: 'S_INITIALIZE', + S_LISTENING: 'S_LISTENING', + S_NETWORK_RECEIVING: 'S_NETWORK_RECEIVING', S_NETWORK_SENDING: 'S_NETWORK_SENDING', - S_NETWORK_RECEIVED: 'S_NETWORK_RECEIVED' + S_NETWORK_IDLE: 'S_NETWORK_IDLE', + S_NOT_CONNECTED: 'S_NOT_CONNECTED', + S_OFF: 'S_OFF', + S_OK: 'S_OK', # S_OK or E_OK + S_ON: 'S_ON', + S_STANDBY: 'S_STANDBY', + S_STATUS: 'S_STATUS', + S_WARMUP: 'S_WARMUP', } -# Map error/status codes to message strings -ERROR_MSG = { - E_OK: translate('OpenLP.ProjectorConstants', 'OK'), # E_OK | S_OK - E_GENERAL: translate('OpenLP.ProjectorConstants', 'General projector error'), - E_NOT_CONNECTED: translate('OpenLP.ProjectorConstants', 'Not connected error'), - E_LAMP: translate('OpenLP.ProjectorConstants', 'Lamp error'), - E_FAN: translate('OpenLP.ProjectorConstants', 'Fan error'), - E_TEMP: translate('OpenLP.ProjectorConstants', 'High temperature detected'), - E_COVER: translate('OpenLP.ProjectorConstants', 'Cover open detected'), - E_FILTER: translate('OpenLP.ProjectorConstants', 'Check filter'), - E_AUTHENTICATION: translate('OpenLP.ProjectorConstants', 'Authentication Error'), - E_UNDEFINED: translate('OpenLP.ProjectorConstants', 'Undefined Command'), - E_PARAMETER: translate('OpenLP.ProjectorConstants', 'Invalid Parameter'), - E_UNAVAILABLE: translate('OpenLP.ProjectorConstants', 'Projector Busy'), - E_PROJECTOR: translate('OpenLP.ProjectorConstants', 'Projector/Display Error'), - E_INVALID_DATA: translate('OpenLP.ProjectorConstants', 'Invalid packet received'), - E_WARN: translate('OpenLP.ProjectorConstants', 'Warning condition detected'), - E_ERROR: translate('OpenLP.ProjectorConstants', 'Error condition detected'), - E_CLASS: translate('OpenLP.ProjectorConstants', 'PJLink class not supported'), - E_PREFIX: translate('OpenLP.ProjectorConstants', 'Invalid prefix character'), - E_CONNECTION_REFUSED: translate('OpenLP.ProjectorConstants', - 'The connection was refused by the peer (or timed out)'), - E_REMOTE_HOST_CLOSED_CONNECTION: translate('OpenLP.ProjectorConstants', - 'The remote host closed the connection'), - E_HOST_NOT_FOUND: translate('OpenLP.ProjectorConstants', 'The host address was not found'), - E_SOCKET_ACCESS: translate('OpenLP.ProjectorConstants', - 'The socket operation failed because the application ' - 'lacked the required privileges'), - E_SOCKET_RESOURCE: translate('OpenLP.ProjectorConstants', - 'The local system ran out of resources (e.g., too many sockets)'), - E_SOCKET_TIMEOUT: translate('OpenLP.ProjectorConstants', - 'The socket operation timed out'), - E_DATAGRAM_TOO_LARGE: translate('OpenLP.ProjectorConstants', - 'The datagram was larger than the operating system\'s limit'), - E_NETWORK: translate('OpenLP.ProjectorConstants', - 'An error occurred with the network (Possibly someone pulled the plug?)'), +# Map status codes to message strings +STATUS_MSG = { E_ADDRESS_IN_USE: translate('OpenLP.ProjectorConstants', 'The address specified with socket.bind() ' 'is already in use and was set to be exclusive'), - E_SOCKET_ADDRESS_NOT_AVAILABLE: translate('OpenLP.ProjectorConstants', - 'The address specified to socket.bind() ' - 'does not belong to the host'), - E_UNSUPPORTED_SOCKET_OPERATION: translate('OpenLP.ProjectorConstants', - 'The requested socket operation is not supported by the local ' - 'operating system (e.g., lack of IPv6 support)'), + E_AUTHENTICATION: translate('OpenLP.ProjectorConstants', 'PJLink returned "ERRA: Authentication Error"'), + E_CONNECTION_REFUSED: translate('OpenLP.ProjectorConstants', + 'The connection was refused by the peer (or timed out)'), + E_COVER: translate('OpenLP.ProjectorConstants', 'Projector cover open detected'), + E_CLASS: translate('OpenLP.ProjectorConstants', 'PJLink class not supported'), + E_DATAGRAM_TOO_LARGE: translate('OpenLP.ProjectorConstants', + "The datagram was larger than the operating system's limit"), + E_ERROR: translate('OpenLP.ProjectorConstants', 'Error condition detected'), + E_FAN: translate('OpenLP.ProjectorConstants', 'Projector fan error'), + E_FILTER: translate('OpenLP.ProjectorConstants', 'Projector check filter'), + E_GENERAL: translate('OpenLP.ProjectorConstants', 'General projector error'), + E_HOST_NOT_FOUND: translate('OpenLP.ProjectorConstants', 'The host address was not found'), + E_INVALID_DATA: translate('OpenLP.ProjectorConstants', 'PJLink invalid packet received'), + E_LAMP: translate('OpenLP.ProjectorConstants', 'Projector lamp error'), + E_NETWORK: translate('OpenLP.ProjectorConstants', + 'An error occurred with the network (Possibly someone pulled the plug?)'), + E_NO_AUTHENTICATION: translate('OpenLP.ProjectorConstants', 'PJlink authentication Mismatch Error'), + E_NOT_CONNECTED: translate('OpenLP.ProjectorConstants', 'Projector not connected error'), + E_PARAMETER: translate('OpenLP.ProjectorConstants', 'PJLink returned "ERR2: Invalid Parameter"'), + E_PREFIX: translate('OpenLP.ProjectorConstants', 'PJLink Invalid prefix character'), + E_PROJECTOR: translate('OpenLP.ProjectorConstants', 'PJLink returned "ERR4: Projector/Display Error"'), E_PROXY_AUTHENTICATION_REQUIRED: translate('OpenLP.ProjectorConstants', 'The socket is using a proxy, ' 'and the proxy requires authentication'), - E_SLS_HANDSHAKE_FAILED: translate('OpenLP.ProjectorConstants', - 'The SSL/TLS handshake failed'), - E_UNFINISHED_SOCKET_OPERATION: translate('OpenLP.ProjectorConstants', - 'The last operation attempted has not finished yet ' - '(still in progress in the background)'), - E_PROXY_CONNECTION_REFUSED: translate('OpenLP.ProjectorConstants', - 'Could not contact the proxy server because the connection ' - 'to that server was denied'), E_PROXY_CONNECTION_CLOSED: translate('OpenLP.ProjectorConstants', 'The connection to the proxy server was closed unexpectedly ' '(before the connection to the final peer was established)'), + E_PROXY_CONNECTION_REFUSED: translate('OpenLP.ProjectorConstants', + 'Could not contact the proxy server because the connection ' + 'to that server was denied'), E_PROXY_CONNECTION_TIMEOUT: translate('OpenLP.ProjectorConstants', 'The connection to the proxy server timed out or the proxy ' 'server stopped responding in the authentication phase.'), @@ -373,51 +405,91 @@ ERROR_MSG = { E_PROXY_PROTOCOL: translate('OpenLP.ProjectorConstants', 'The connection negotiation with the proxy server failed because the ' 'response from the proxy server could not be understood'), - E_UNKNOWN_SOCKET_ERROR: translate('OpenLP.ProjectorConstants', 'An unidentified error occurred'), - S_NOT_CONNECTED: translate('OpenLP.ProjectorConstants', 'Not connected'), - S_CONNECTING: translate('OpenLP.ProjectorConstants', 'Connecting'), + E_REMOTE_HOST_CLOSED_CONNECTION: translate('OpenLP.ProjectorConstants', + 'The remote host closed the connection'), + E_SLS_HANDSHAKE_FAILED: translate('OpenLP.ProjectorConstants', + 'The SSL/TLS handshake failed'), + E_SOCKET_ADDRESS_NOT_AVAILABLE: translate('OpenLP.ProjectorConstants', + 'The address specified to socket.bind() ' + 'does not belong to the host'), + E_SOCKET_ACCESS: translate('OpenLP.ProjectorConstants', + 'The socket operation failed because the application ' + 'lacked the required privileges'), + E_SOCKET_RESOURCE: translate('OpenLP.ProjectorConstants', + 'The local system ran out of resources (e.g., too many sockets)'), + E_SOCKET_TIMEOUT: translate('OpenLP.ProjectorConstants', + 'The socket operation timed out'), + E_TEMP: translate('OpenLP.ProjectorConstants', 'Projector high temperature detected'), + E_UNAVAILABLE: translate('OpenLP.ProjectorConstants', 'PJLink returned "ERR3: Busy"'), + E_UNDEFINED: translate('OpenLP.ProjectorConstants', 'PJLink returned "ERR1: Undefined Command"'), + E_UNFINISHED_SOCKET_OPERATION: translate('OpenLP.ProjectorConstants', + 'The last operation attempted has not finished yet ' + '(still in progress in the background)'), + E_UNKNOWN: translate('OpenLP.ProjectorConstants', 'Unknown condiction detected'), + E_UNKNOWN_SOCKET_ERROR: translate('OpenLP.ProjectorConstants', 'An unidentified socket error occurred'), + E_UNSUPPORTED_SOCKET_OPERATION: translate('OpenLP.ProjectorConstants', + 'The requested socket operation is not supported by the local ' + 'operating system (e.g., lack of IPv6 support)'), + E_WARN: translate('OpenLP.ProjectorConstants', 'Warning condition detected'), + S_BOUND: translate('OpenLP.ProjectorConstants', 'Socket is bount to an address or port'), + S_CLOSING: translate('OpenLP.ProjectorConstants', 'Socket is about to close'), S_CONNECTED: translate('OpenLP.ProjectorConstants', 'Connected'), - S_STATUS: translate('OpenLP.ProjectorConstants', 'Getting status'), - S_OFF: translate('OpenLP.ProjectorConstants', 'Off'), - S_INITIALIZE: translate('OpenLP.ProjectorConstants', 'Initialize in progress'), - S_STANDBY: translate('OpenLP.ProjectorConstants', 'Power in standby'), - S_WARMUP: translate('OpenLP.ProjectorConstants', 'Warmup in progress'), - S_ON: translate('OpenLP.ProjectorConstants', 'Power is on'), + S_CONNECTING: translate('OpenLP.ProjectorConstants', 'Connecting'), S_COOLDOWN: translate('OpenLP.ProjectorConstants', 'Cooldown in progress'), + S_HOST_LOOKUP: translate('OpenLP.ProjectorConstants', 'Performing a host name lookup'), S_INFO: translate('OpenLP.ProjectorConstants', 'Projector Information available'), + S_INITIALIZE: translate('OpenLP.ProjectorConstants', 'Initialize in progress'), + S_LISTENING: translate('OpenLP.ProjectorConstants', 'Socket it listening (internal use only)'), + S_NETWORK_IDLE: translate('OpenLP.ProjectorConstants', 'No network activity at this time'), + S_NETWORK_RECEIVING: translate('OpenLP.ProjectorConstants', 'Received data'), S_NETWORK_SENDING: translate('OpenLP.ProjectorConstants', 'Sending data'), - S_NETWORK_RECEIVED: translate('OpenLP.ProjectorConstants', 'Received data') + S_NOT_CONNECTED: translate('OpenLP.ProjectorConstants', 'Not Connected'), + S_OFF: translate('OpenLP.ProjectorConstants', 'Off'), + S_OK: translate('OpenLP.ProjectorConstants', 'OK'), + S_ON: translate('OpenLP.ProjectorConstants', 'Power is on'), + S_STANDBY: translate('OpenLP.ProjectorConstants', 'Power in standby'), + S_STATUS: translate('OpenLP.ProjectorConstants', 'Getting status'), + S_WARMUP: translate('OpenLP.ProjectorConstants', 'Warmup in progress'), } -# Map ERST return code positions to equipment +# Map ERST reply positions to equipment +PJLINK_ERST_LIST = { + "FAN": translate('OpenLP.PJLink', 'Fan'), + "LAMP": translate('OpenLP.PJLink', 'Lamp'), + "TEMP": translate('OpenLP.PJLink', 'Temperature'), + "COVER": translate('OpenLP.PJLink', 'Cover'), + "FILTER": translate('OpenLP.PJLink', 'Filter'), + "OTHER": translate('OpenPL.PJLink', 'Other') +} + +# Map projector item to ERST data position PJLINK_ERST_DATA = { - 'DATA_LENGTH': 6, - 0: 'FAN', - 1: 'LAMP', - 2: 'TEMP', - 3: 'COVER', - 4: 'FILTER', - 5: 'OTHER', + 'DATA_LENGTH': 6, # Zero based so enums are 0-5 'FAN': 0, 'LAMP': 1, 'TEMP': 2, 'COVER': 3, 'FILTER': 4, - 'OTHER': 5 + 'OTHER': 5, + 0: 'FAN', + 1: 'LAMP', + 2: 'TEMP', + 3: 'COVER', + 4: 'FILTER', + 5: 'OTHER' } -# Map for ERST return codes to string +# Map ERST reply codes to string PJLINK_ERST_STATUS = { - '0': 'OK', - '1': ERROR_STRING[E_WARN], - '2': ERROR_STRING[E_ERROR], - 'OK': '0', - E_OK: '0', + '0': S_OK, + '1': E_WARN, + '2': E_ERROR, + S_OK: '0', E_WARN: '1', E_ERROR: '2' } -# Map for POWR return codes to status code +# Map POWR return codes to status code PJLINK_POWR_STATUS = { '0': S_STANDBY, '1': S_ON, diff --git a/openlp/core/projectors/db.py b/openlp/core/projectors/db.py index fe8785861..f9297fae9 100644 --- a/openlp/core/projectors/db.py +++ b/openlp/core/projectors/db.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -152,6 +152,7 @@ class Projector(Base, CommonMixin): location: Column(String(30)) notes: Column(String(200)) pjlink_name: Column(String(128)) # From projector + pjlink_class Column(String(5)) # From projector manufacturer: Column(String(128)) # From projector model: Column(String(128)) # From projector other: Column(String(128)) # From projector @@ -168,7 +169,7 @@ class Projector(Base, CommonMixin): Return basic representation of Source table entry. """ return '< Projector(id="{data}", ip="{ip}", port="{port}", mac_adx="{mac}", pin="{pin}", name="{name}", ' \ - 'location="{location}", notes="{notes}", pjlink_name="{pjlink_name}", ' \ + 'location="{location}", notes="{notes}", pjlink_name="{pjlink_name}", pjlink_class="{pjlink_class}", ' \ 'manufacturer="{manufacturer}", model="{model}", serial_no="{serial}", other="{other}", ' \ 'sources="{sources}", source_list="{source_list}", model_filter="{mfilter}", ' \ 'model_lamp="{mlamp}", sw_version="{sw_ver}") >'.format(data=self.id, @@ -180,6 +181,7 @@ class Projector(Base, CommonMixin): location=self.location, notes=self.notes, pjlink_name=self.pjlink_name, + pjlink_class=self.pjlink_class, manufacturer=self.manufacturer, model=self.model, other=self.other, @@ -197,6 +199,7 @@ class Projector(Base, CommonMixin): location = Column(String(30)) notes = Column(String(200)) pjlink_name = Column(String(128)) + pjlink_class = Column(String(5)) manufacturer = Column(String(128)) model = Column(String(128)) other = Column(String(128)) diff --git a/openlp/core/projectors/editform.py b/openlp/core/projectors/editform.py index 4ae1f96d9..a88681836 100644 --- a/openlp/core/projectors/editform.py +++ b/openlp/core/projectors/editform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -30,8 +30,8 @@ from PyQt5 import QtCore, QtWidgets from openlp.core.common import verify_ip_address from openlp.core.common.i18n import translate from openlp.core.lib import build_icon -from openlp.core.projectors.db import Projector from openlp.core.projectors.constants import PJLINK_PORT +from openlp.core.projectors.db import Projector log = logging.getLogger(__name__) log.debug('editform loaded') diff --git a/openlp/core/projectors/manager.py b/openlp/core/projectors/manager.py index b352858b1..3bc7373fa 100644 --- a/openlp/core/projectors/manager.py +++ b/openlp/core/projectors/manager.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -35,12 +35,28 @@ from openlp.core.common.registry import RegistryBase from openlp.core.common.settings import Settings from openlp.core.lib.ui import create_widget_action from openlp.core.projectors import DialogSourceStyle -from openlp.core.projectors.constants import ERROR_MSG, ERROR_STRING, E_AUTHENTICATION, E_ERROR, \ - E_NETWORK, E_NOT_CONNECTED, E_UNKNOWN_SOCKET_ERROR, STATUS_STRING, S_CONNECTED, S_CONNECTING, S_COOLDOWN, \ - S_INITIALIZE, S_NOT_CONNECTED, S_OFF, S_ON, S_STANDBY, S_WARMUP +from openlp.core.projectors.constants import \ + E_AUTHENTICATION, \ + E_ERROR, \ + E_NETWORK, \ + E_NOT_CONNECTED, \ + E_UNKNOWN_SOCKET_ERROR, \ + S_CONNECTED, \ + S_CONNECTING, \ + S_COOLDOWN, \ + S_INITIALIZE, \ + S_NOT_CONNECTED, \ + S_OFF, \ + S_ON, \ + S_STANDBY, \ + S_WARMUP, \ + STATUS_CODE, \ + STATUS_MSG, \ + QSOCKET_STATE + from openlp.core.projectors.db import ProjectorDB -from openlp.core.projectors.pjlink import PJLink, PJLinkUDP from openlp.core.projectors.editform import ProjectorEditForm +from openlp.core.projectors.pjlink import PJLink, PJLinkUDP from openlp.core.projectors.sourceselectform import SourceSelectTabs, SourceSelectSingle from openlp.core.widgets.toolbar import OpenLPToolbar @@ -292,8 +308,7 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM self.settings_section = 'projector' self.projectordb = projectordb self.projector_list = [] - self.pjlink_udp = PJLinkUDP() - self.pjlink_udp.projector_list = self.projector_list + self.pjlink_udp = PJLinkUDP(self.projector_list) self.source_select_form = None def bootstrap_initialise(self): @@ -440,11 +455,12 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM :param opt: Needed by PyQt5 """ projector = item.data(QtCore.Qt.UserRole) - if projector.link.state() != projector.link.ConnectedState: + if QSOCKET_STATE[projector.link.state()] != S_CONNECTED: try: + log.debug('ProjectorManager: Calling connect_to_host() on "{ip}"'.format(ip=projector.link.ip)) projector.link.connect_to_host() except: - pass + log.debug('ProjectorManager: "{ip}" already connected - skipping'.format(ip=projector.link.ip)) return def on_connect_projector(self, opt=None): @@ -506,8 +522,8 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM except (AttributeError, TypeError): pass try: - projector.timer.stop() - projector.timer.timeout.disconnect(projector.link.poll_loop) + projector.poll_timer.stop() + projector.poll_timer.timeout.disconnect(projector.link.poll_loop) except (AttributeError, TypeError): pass try: @@ -515,7 +531,6 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM projector.socket_timer.timeout.disconnect(projector.link.socket_abort) except (AttributeError, TypeError): pass - projector.thread.quit() new_list = [] for item in self.projector_list: if item.link.db_item.id == projector.link.db_item.id: @@ -647,7 +662,7 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM 'Other info'), data=projector.link.other_info) message += '{title}: {data}
'.format(title=translate('OpenLP.ProjectorManager', 'Power status'), - data=ERROR_MSG[projector.link.power]) + data=STATUS_MSG[projector.link.power]) message += '{title}: {data}
'.format(title=translate('OpenLP.ProjectorManager', 'Shutter is'), data=translate('OpenLP.ProjectorManager', 'Closed') if projector.link.shutter @@ -692,7 +707,7 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM else: message += '{data}'.format(data=translate('OpenLP.ProjectorManager', 'Current errors/warnings')) for (key, val) in projector.link.projector_errors.items(): - message += '{key}: {data}
'.format(key=key, data=ERROR_MSG[val]) + message += '{key}: {data}
'.format(key=key, data=STATUS_MSG[val]) QtWidgets.QMessageBox.information(self, translate('OpenLP.ProjectorManager', 'Projector Information'), message) def _add_projector(self, projector): @@ -717,39 +732,18 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM """ item = ProjectorItem(link=self._add_projector(projector)) item.db_item = projector - icon = QtGui.QIcon(QtGui.QPixmap(STATUS_ICONS[S_NOT_CONNECTED])) - item.icon = icon - widget = QtWidgets.QListWidgetItem(icon, + item.icon = QtGui.QIcon(QtGui.QPixmap(STATUS_ICONS[S_NOT_CONNECTED])) + widget = QtWidgets.QListWidgetItem(item.icon, item.link.name, self.projector_list_widget ) widget.setData(QtCore.Qt.UserRole, item) item.link.db_item = item.db_item item.widget = widget - thread = QtCore.QThread(parent=self) - thread.my_parent = self - item.moveToThread(thread) - thread.started.connect(item.link.thread_started) - thread.finished.connect(item.link.thread_stopped) - thread.finished.connect(thread.deleteLater) item.link.changeStatus.connect(self.update_status) item.link.projectorAuthentication.connect(self.authentication_error) item.link.projectorNoAuthentication.connect(self.no_authentication_error) item.link.projectorUpdateIcons.connect(self.update_icons) - timer = QtCore.QTimer(self) - timer.setInterval(self.poll_time) - timer.timeout.connect(item.link.poll_loop) - item.timer = timer - # Timeout in case of brain-dead projectors or cable disconnected - socket_timer = QtCore.QTimer(self) - socket_timer.setInterval(11000) - socket_timer.timeout.connect(item.link.socket_abort) - item.socket_timer = socket_timer - thread.start() - item.thread = thread - item.link.timer = timer - item.link.socket_timer = socket_timer - item.link.widget = item.widget self.projector_list.append(item) if start: item.link.connect_to_host() @@ -817,31 +811,18 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM if ip == list_item.link.ip: item = list_item break - message = translate('OpenLP.ProjectorManager', 'No message') if msg is None else msg - if status in STATUS_STRING: - status_code = STATUS_STRING[status] - message = ERROR_MSG[status] if msg is None else msg - elif status in ERROR_STRING: - status_code = ERROR_STRING[status] - message = ERROR_MSG[status] if msg is None else msg - else: - status_code = status - message = ERROR_MSG[status] if msg is None else msg - log.debug('({name}) updateStatus(status={status}) message: "{message}"'.format(name=item.link.name, - status=status_code, - message=message)) - if status in STATUS_ICONS: - if item.status == status: - return - item.status = status - item.icon = QtGui.QIcon(QtGui.QPixmap(STATUS_ICONS[status])) - if status in ERROR_STRING: - status_code = ERROR_STRING[status] - elif status in STATUS_STRING: - status_code = STATUS_STRING[status] - log.debug('({name}) Updating icon with {code}'.format(name=item.link.name, code=status_code)) - item.widget.setIcon(item.icon) - self.update_icons() + if item is None: + log.error('ProjectorManager: Unknown item "{ip}" - not updating status'.format(ip=ip)) + return + elif item.status == status: + log.debug('ProjectorManager: No status change for "{ip}" - not updating status'.format(ip=ip)) + return + + item.status = status + item.icon = QtGui.QIcon(QtGui.QPixmap(STATUS_ICONS[status])) + log.debug('({name}) Updating icon with {code}'.format(name=item.link.name, code=STATUS_CODE[status])) + item.widget.setIcon(item.icon) + return self.update_icons() def get_toolbar_item(self, name, enabled=False, hidden=False): item = self.one_toolbar.findChild(QtWidgets.QAction, name) @@ -877,7 +858,7 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM self.get_toolbar_item('show_projector_multiple', hidden=True) elif count == 1: projector = self.projector_list_widget.selectedItems()[0].data(QtCore.Qt.UserRole) - connected = projector.link.state() == projector.link.ConnectedState + connected = QSOCKET_STATE[projector.link.state()] == S_CONNECTED power = projector.link.power == S_ON self.get_toolbar_item('connect_projector_multiple', hidden=True) self.get_toolbar_item('disconnect_projector_multiple', hidden=True) diff --git a/openlp/core/projectors/pjlink.py b/openlp/core/projectors/pjlink.py index 12ae7e1d0..3517fb1e4 100644 --- a/openlp/core/projectors/pjlink.py +++ b/openlp/core/projectors/pjlink.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -54,11 +54,12 @@ from PyQt5 import QtCore, QtNetwork from openlp.core.common import qmd5_hash from openlp.core.common.i18n import translate -from openlp.core.projectors.constants import CONNECTION_ERRORS, CR, ERROR_MSG, ERROR_STRING, \ - E_AUTHENTICATION, E_CONNECTION_REFUSED, E_GENERAL, E_INVALID_DATA, E_NETWORK, E_NOT_CONNECTED, E_OK, \ - E_PARAMETER, E_PROJECTOR, E_SOCKET_TIMEOUT, E_UNAVAILABLE, E_UNDEFINED, PJLINK_ERRORS, PJLINK_ERST_DATA, \ - PJLINK_ERST_STATUS, PJLINK_MAX_PACKET, PJLINK_PORT, PJLINK_POWR_STATUS, PJLINK_VALID_CMD, \ - STATUS_STRING, S_CONNECTED, S_CONNECTING, S_INFO, S_NOT_CONNECTED, S_OFF, S_OK, S_ON, S_QSOCKET_STATE, S_STATUS +from openlp.core.projectors.constants import CONNECTION_ERRORS, PJLINK_CLASS, PJLINK_DEFAULT_CODES, PJLINK_ERRORS, \ + PJLINK_ERST_DATA, PJLINK_ERST_STATUS, PJLINK_MAX_PACKET, PJLINK_PREFIX, PJLINK_PORT, PJLINK_POWR_STATUS, \ + PJLINK_SUFFIX, PJLINK_VALID_CMD, PROJECTOR_STATE, STATUS_CODE, STATUS_MSG, QSOCKET_STATE, \ + E_AUTHENTICATION, E_CONNECTION_REFUSED, E_GENERAL, E_INVALID_DATA, E_NETWORK, E_NOT_CONNECTED, \ + E_SOCKET_TIMEOUT, \ + S_CONNECTED, S_CONNECTING, S_NOT_CONNECTED, S_OFF, S_OK, S_ON log = logging.getLogger(__name__) log.debug('pjlink loaded') @@ -69,12 +70,9 @@ __all__ = ['PJLink'] SocketError = QtNetwork.QAbstractSocket.SocketError SocketSTate = QtNetwork.QAbstractSocket.SocketState -PJLINK_PREFIX = '%' -PJLINK_CLASS = '1' # Default to class 1 until we query the projector # Add prefix here, but defer linkclass expansion until later when we have the actual # PJLink class for the command PJLINK_HEADER = '{prefix}{{linkclass}}'.format(prefix=PJLINK_PREFIX) -PJLINK_SUFFIX = CR class PJLinkUDP(QtNetwork.QUdpSocket): @@ -91,11 +89,11 @@ class PJLinkUDP(QtNetwork.QUdpSocket): 'SRCH' # Class 2 (reply is ACKN) ] - def __init__(self, port=PJLINK_PORT): + def __init__(self, projector_list, port=PJLINK_PORT): """ Initialize socket """ - + self.projector_list = projector_list self.port = port @@ -123,8 +121,6 @@ class PJLinkCommands(object): 'LAMP': self.process_lamp, 'NAME': self.process_name, 'PJLINK': self.process_pjlink, - # TODO: Part of check_login refactor - remove when done - # 'PJLINK': self.check_login, 'POWR': self.process_powr, 'SNUM': self.process_snum, 'SVER': self.process_sver, @@ -136,8 +132,9 @@ class PJLinkCommands(object): """ Initialize instance variables. Also used to reset projector-specific information to default. """ - log.debug('({ip}) reset_information() connect status is {state}'.format(ip=self.ip, - state=S_QSOCKET_STATE[self.state()])) + conn_state = STATUS_CODE[QSOCKET_STATE[self.state()]] + log.debug('({ip}) reset_information() connect status is {state}'.format(ip=self.entry.name, + state=conn_state)) self.fan = None # ERST self.filter_time = None # FILT self.lamp = None # LAMP @@ -148,7 +145,6 @@ class PJLinkCommands(object): self.model_lamp = None # RLMP self.mute = None # AVMT self.other_info = None # INFO - self.pjlink_class = PJLINK_CLASS # Default class self.pjlink_name = None # NAME self.power = S_OFF # POWR self.serial_no = None # SNUM @@ -159,11 +155,11 @@ class PJLinkCommands(object): self.source_available = None # INST self.source = None # INPT # These should be part of PJLink() class, but set here for convenience - if hasattr(self, 'timer'): - log.debug('({ip}): Calling timer.stop()'.format(ip=self.ip)) - self.timer.stop() + if hasattr(self, 'poll_timer'): + log.debug('({ip}): Calling poll_timer.stop()'.format(ip=self.entry.name)) + self.poll_timer.stop() if hasattr(self, 'socket_timer'): - log.debug('({ip}): Calling socket_timer.stop()'.format(ip=self.ip)) + log.debug('({ip}): Calling socket_timer.stop()'.format(ip=self.entry.name)) self.socket_timer.stop() self.send_busy = False self.send_queue = [] @@ -176,49 +172,32 @@ class PJLinkCommands(object): :param cmd: Command to process :param data: Data being processed """ - log.debug('({ip}) Processing command "{cmd}" with data "{data}"'.format(ip=self.ip, + log.debug('({ip}) Processing command "{cmd}" with data "{data}"'.format(ip=self.entry.name, cmd=cmd, data=data)) # cmd should already be in uppercase, but data may be in mixed-case. # Due to some replies should stay as mixed-case, validate using separate uppercase check _data = data.upper() # Check if we have a future command not available yet - if cmd not in PJLINK_VALID_CMD: - log.error('({ip}) Ignoring command="{cmd}" (Invalid/Unknown)'.format(ip=self.ip, cmd=cmd)) + if cmd not in self.pjlink_functions: + log.warning('({ip}) Unable to process command="{cmd}" (Future option?)'.format(ip=self.entry.name, cmd=cmd)) return elif _data == 'OK': - log.debug('({ip}) Command "{cmd}" returned OK'.format(ip=self.ip, cmd=cmd)) + log.debug('({ip}) Command "{cmd}" returned OK'.format(ip=self.entry.name, cmd=cmd)) # A command returned successfully, so do a query on command to verify status return self.send_command(cmd=cmd) - elif cmd not in self.pjlink_functions: - log.warning('({ip}) Unable to process command="{cmd}" (Future option?)'.format(ip=self.ip, cmd=cmd)) - return elif _data in PJLINK_ERRORS: # Oops - projector error - log.error('({ip}) Projector returned error "{data}"'.format(ip=self.ip, data=data)) - if _data == PJLINK_ERRORS[E_AUTHENTICATION]: - # Authentication error + log.error('({ip}) {cmd}: {err}'.format(ip=self.entry.name, + cmd=cmd, + err=STATUS_MSG[PJLINK_ERRORS[_data]])) + if PJLINK_ERRORS[_data] == E_AUTHENTICATION: self.disconnect_from_host() - self.change_status(E_AUTHENTICATION) - log.debug('({ip}) emitting projectorAuthentication() signal'.format(ip=self.ip)) self.projectorAuthentication.emit(self.name) - elif _data == PJLINK_ERRORS[E_UNDEFINED]: - # Projector does not recognize command - self.change_status(E_UNDEFINED, '{error}: "{data}"'.format(error=ERROR_MSG[E_UNDEFINED], - data=cmd)) - elif _data == PJLINK_ERRORS[E_PARAMETER]: - # Invalid parameter - self.change_status(E_PARAMETER) - elif _data == PJLINK_ERRORS[E_UNAVAILABLE]: - # Projector busy - self.change_status(E_UNAVAILABLE) - elif _data == PJLINK_ERRORS[E_PROJECTOR]: - # Projector/display error - self.change_status(E_PROJECTOR) - return + return self.change_status(status=E_AUTHENTICATION) # Command checks already passed - log.debug('({ip}) Calling function for {cmd}'.format(ip=self.ip, cmd=cmd)) - self.pjlink_functions[cmd](data) + log.debug('({ip}) Calling function for {cmd}'.format(ip=self.entry.name, cmd=cmd)) + self.pjlink_functions[cmd](data=data) def process_avmt(self, data): """ @@ -237,7 +216,7 @@ class PJLinkCommands(object): '31': {'shutter': True, 'mute': True} } if data not in settings: - log.warning('({ip}) Invalid shutter response: {data}'.format(ip=self.ip, data=data)) + log.warning('({ip}) Invalid shutter response: {data}'.format(ip=self.entry.name, data=data)) return shutter = settings[data]['shutter'] mute = settings[data]['mute'] @@ -261,7 +240,7 @@ class PJLinkCommands(object): # : Received: '%1CLSS=Class 1' (Optoma) # : Received: '%1CLSS=Version1' (BenQ) if len(data) > 1: - log.warning('({ip}) Non-standard CLSS reply: "{data}"'.format(ip=self.ip, data=data)) + log.warning('({ip}) Non-standard CLSS reply: "{data}"'.format(ip=self.entry.name, data=data)) # Due to stupid projectors not following standards (Optoma, BenQ comes to mind), # AND the different responses that can be received, the semi-permanent way to # fix the class reply is to just remove all non-digit characters. @@ -269,17 +248,23 @@ class PJLinkCommands(object): clss = re.findall('\d', data)[0] # Should only be the first match except IndexError: log.error('({ip}) No numbers found in class version reply "{data}" - ' - 'defaulting to class "1"'.format(ip=self.ip, data=data)) + 'defaulting to class "1"'.format(ip=self.entry.name, data=data)) clss = '1' elif not data.isdigit(): log.error('({ip}) NAN CLSS version reply "{data}" - ' - 'defaulting to class "1"'.format(ip=self.ip, data=data)) + 'defaulting to class "1"'.format(ip=self.entry.name, data=data)) clss = '1' else: clss = data self.pjlink_class = clss - log.debug('({ip}) Setting pjlink_class for this projector to "{data}"'.format(ip=self.ip, + log.debug('({ip}) Setting pjlink_class for this projector to "{data}"'.format(ip=self.entry.name, data=self.pjlink_class)) + # Since we call this one on first connect, setup polling from here + if not self.no_poll: + log.debug('({ip}) process_pjlink(): Starting timer'.format(ip=self.entry.name)) + self.poll_timer.setInterval(1000) # Set 1 second for initial information + self.poll_timer.start() + return def process_erst(self, data): @@ -291,15 +276,15 @@ class PJLinkCommands(object): """ if len(data) != PJLINK_ERST_DATA['DATA_LENGTH']: count = PJLINK_ERST_DATA['DATA_LENGTH'] - log.warning('{ip}) Invalid error status response "{data}": length != {count}'.format(ip=self.ip, - data=data, - count=count)) + log.warning('({ip}) Invalid error status response "{data}": length != {count}'.format(ip=self.entry.name, + data=data, + count=count)) return try: datacheck = int(data) except ValueError: # Bad data - ignore - log.warning('({ip}) Invalid error status response "{data}"'.format(ip=self.ip, data=data)) + log.warning('({ip}) Invalid error status response "{data}"'.format(ip=self.entry.name, data=data)) return if datacheck == 0: self.projector_errors = None @@ -313,22 +298,22 @@ class PJLinkCommands(object): data[PJLINK_ERST_DATA['COVER']], data[PJLINK_ERST_DATA['FILTER']], data[PJLINK_ERST_DATA['OTHER']]) - if fan != PJLINK_ERST_STATUS[E_OK]: + if fan != PJLINK_ERST_STATUS[S_OK]: self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Fan')] = \ PJLINK_ERST_STATUS[fan] - if lamp != PJLINK_ERST_STATUS[E_OK]: + if lamp != PJLINK_ERST_STATUS[S_OK]: self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Lamp')] = \ PJLINK_ERST_STATUS[lamp] - if temp != PJLINK_ERST_STATUS[E_OK]: + if temp != PJLINK_ERST_STATUS[S_OK]: self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Temperature')] = \ PJLINK_ERST_STATUS[temp] - if cover != PJLINK_ERST_STATUS[E_OK]: + if cover != PJLINK_ERST_STATUS[S_OK]: self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Cover')] = \ PJLINK_ERST_STATUS[cover] - if filt != PJLINK_ERST_STATUS[E_OK]: + if filt != PJLINK_ERST_STATUS[S_OK]: self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Filter')] = \ PJLINK_ERST_STATUS[filt] - if other != PJLINK_ERST_STATUS[E_OK]: + if other != PJLINK_ERST_STATUS[S_OK]: self.projector_errors[translate('OpenLP.ProjectorPJLink', 'Other')] = \ PJLINK_ERST_STATUS[other] return @@ -341,7 +326,8 @@ class PJLinkCommands(object): :param data: Projector manufacturer """ self.manufacturer = data - log.debug('({ip}) Setting projector manufacturer data to "{data}"'.format(ip=self.ip, data=self.manufacturer)) + log.debug('({ip}) Setting projector manufacturer data to "{data}"'.format(ip=self.entry.name, + data=self.manufacturer)) return def process_inf2(self, data): @@ -352,7 +338,7 @@ class PJLinkCommands(object): :param data: Model name """ self.model = data - log.debug('({ip}) Setting projector model to "{data}"'.format(ip=self.ip, data=self.model)) + log.debug('({ip}) Setting projector model to "{data}"'.format(ip=self.entry.name, data=self.model)) return def process_info(self, data): @@ -363,7 +349,7 @@ class PJLinkCommands(object): :param data: Projector other info """ self.other_info = data - log.debug('({ip}) Setting projector other_info to "{data}"'.format(ip=self.ip, data=self.other_info)) + log.debug('({ip}) Setting projector other_info to "{data}"'.format(ip=self.entry.name, data=self.other_info)) return def process_inpt(self, data): @@ -373,8 +359,19 @@ class PJLinkCommands(object): :param data: Currently selected source """ + # First, see if we have a valid input based on what is installed (if available) + if self.source_available is not None: + # We have available inputs, so verify it's in the list + if data not in self.source_available: + log.warn('({ip}) Input source not listed in available sources - ignoring'.format(ip=self.entry.name)) + return + elif data not in PJLINK_DEFAULT_CODES: + # Hmm - no sources available yet, so check with PJLink defaults + log.warn('({ip}) Input source not listed as a PJLink available source ' + '- ignoring'.format(ip=self.entry.name)) + return self.source = data - log.info('({ip}) Setting data source to "{data}"'.format(ip=self.ip, data=self.source)) + log.debug('({ip}) Setting data source to "{data}"'.format(ip=self.entry.name, data=self.source)) return def process_inst(self, data): @@ -390,8 +387,7 @@ class PJLinkCommands(object): sources.append(source) sources.sort() self.source_available = sources - self.projectorUpdateIcons.emit() - log.debug('({ip}) Setting projector sources_available to "{data}"'.format(ip=self.ip, + log.debug('({ip}) Setting projector sources_available to "{data}"'.format(ip=self.entry.name, data=self.source_available)) return @@ -413,7 +409,7 @@ class PJLinkCommands(object): fill = {'Hours': int(lamp_list[0]), 'On': False if lamp_list[1] == '0' else True} except ValueError: # In case of invalid entry - log.warning('({ip}) process_lamp(): Invalid data "{data}"'.format(ip=self.ip, data=data)) + log.warning('({ip}) process_lamp(): Invalid data "{data}"'.format(ip=self.entry.name, data=data)) return lamps.append(fill) lamp_list.pop(0) # Remove lamp hours @@ -429,7 +425,7 @@ class PJLinkCommands(object): :param data: Projector name """ self.pjlink_name = data - log.debug('({ip}) Setting projector PJLink name to "{data}"'.format(ip=self.ip, data=self.pjlink_name)) + log.debug('({ip}) Setting projector PJLink name to "{data}"'.format(ip=self.entry.name, data=self.pjlink_name)) return def process_pjlink(self, data): @@ -438,42 +434,38 @@ class PJLinkCommands(object): :param data: Initial packet with authentication scheme """ - log.debug('({ip}) Processing PJLINK command'.format(ip=self.ip)) + log.debug('({ip}) Processing PJLINK command'.format(ip=self.entry.name)) chk = data.split(' ') if len(chk[0]) != 1: # Invalid - after splitting, first field should be 1 character, either '0' or '1' only - log.error('({ip}) Invalid initial authentication scheme - aborting'.format(ip=self.ip)) + log.error('({ip}) Invalid initial authentication scheme - aborting'.format(ip=self.entry.name)) return self.disconnect_from_host() elif chk[0] == '0': # Normal connection no authentication if len(chk) > 1: # Invalid data - there should be nothing after a normal authentication scheme - log.error('({ip}) Normal connection with extra information - aborting'.format(ip=self.ip)) + log.error('({ip}) Normal connection with extra information - aborting'.format(ip=self.entry.name)) return self.disconnect_from_host() elif self.pin: - log.error('({ip}) Normal connection but PIN set - aborting'.format(ip=self.ip)) + log.error('({ip}) Normal connection but PIN set - aborting'.format(ip=self.entry.name)) return self.disconnect_from_host() else: data_hash = None elif chk[0] == '1': if len(chk) < 2: # Not enough information for authenticated connection - log.error('({ip}) Authenticated connection but not enough info - aborting'.format(ip=self.ip)) + log.error('({ip}) Authenticated connection but not enough info - aborting'.format(ip=self.entry.name)) return self.disconnect_from_host() elif not self.pin: - log.error('({ip}) Authenticate connection but no PIN - aborting'.format(ip=self.ip)) + log.error('({ip}) Authenticate connection but no PIN - aborting'.format(ip=self.entry.name)) return self.disconnect_from_host() else: data_hash = str(qmd5_hash(salt=chk[1].encode('utf-8'), data=self.pin.encode('utf-8')), encoding='ascii') # Passed basic checks, so start connection self.readyRead.connect(self.get_socket) - if not self.no_poll: - log.debug('({ip}) process_pjlink(): Starting timer'.format(ip=self.ip)) - self.timer.setInterval(2000) # Set 2 seconds for initial information - self.timer.start() self.change_status(S_CONNECTED) - log.debug('({ip}) process_pjlink(): Sending "CLSS" initial command'.format(ip=self.ip)) + log.debug('({ip}) process_pjlink(): Sending "CLSS" initial command'.format(ip=self.entry.name)) # Since this is an initial connection, make it a priority just in case return self.send_command(cmd="CLSS", salt=data_hash, priority=True) @@ -484,7 +476,7 @@ class PJLinkCommands(object): :param data: Power status """ - log.debug('({ip}: Processing POWR command'.format(ip=self.ip)) + log.debug('({ip}: Processing POWR command'.format(ip=self.entry.name)) if data in PJLINK_POWR_STATUS: power = PJLINK_POWR_STATUS[data] update_icons = self.power != power @@ -497,7 +489,7 @@ class PJLinkCommands(object): self.send_command('INST') else: # Log unknown status response - log.warning('({ip}) Unknown power response: "{data}"'.format(ip=self.ip, data=data)) + log.warning('({ip}) Unknown power response: "{data}"'.format(ip=self.entry.name, data=data)) return def process_rfil(self, data): @@ -507,9 +499,9 @@ class PJLinkCommands(object): if self.model_filter is None: self.model_filter = data else: - log.warning('({ip}) Filter model already set'.format(ip=self.ip)) - log.warning('({ip}) Saved model: "{old}"'.format(ip=self.ip, old=self.model_filter)) - log.warning('({ip}) New model: "{new}"'.format(ip=self.ip, new=data)) + log.warning('({ip}) Filter model already set'.format(ip=self.entry.name)) + log.warning('({ip}) Saved model: "{old}"'.format(ip=self.entry.name, old=self.model_filter)) + log.warning('({ip}) New model: "{new}"'.format(ip=self.entry.name, new=data)) def process_rlmp(self, data): """ @@ -518,9 +510,9 @@ class PJLinkCommands(object): if self.model_lamp is None: self.model_lamp = data else: - log.warning('({ip}) Lamp model already set'.format(ip=self.ip)) - log.warning('({ip}) Saved lamp: "{old}"'.format(ip=self.ip, old=self.model_lamp)) - log.warning('({ip}) New lamp: "{new}"'.format(ip=self.ip, new=data)) + log.warning('({ip}) Lamp model already set'.format(ip=self.entry.name)) + log.warning('({ip}) Saved lamp: "{old}"'.format(ip=self.entry.name, old=self.model_lamp)) + log.warning('({ip}) New lamp: "{new}"'.format(ip=self.entry.name, new=data)) def process_snum(self, data): """ @@ -529,16 +521,17 @@ class PJLinkCommands(object): :param data: Serial number from projector. """ if self.serial_no is None: - log.debug('({ip}) Setting projector serial number to "{data}"'.format(ip=self.ip, data=data)) + log.debug('({ip}) Setting projector serial number to "{data}"'.format(ip=self.entry.name, data=data)) self.serial_no = data self.db_update = False else: # Compare serial numbers and see if we got the same projector if self.serial_no != data: - log.warning('({ip}) Projector serial number does not match saved serial number'.format(ip=self.ip)) - log.warning('({ip}) Saved: "{old}"'.format(ip=self.ip, old=self.serial_no)) - log.warning('({ip}) Received: "{new}"'.format(ip=self.ip, new=data)) - log.warning('({ip}) NOT saving serial number'.format(ip=self.ip)) + log.warning('({ip}) Projector serial number does not match saved serial ' + 'number'.format(ip=self.entry.name)) + log.warning('({ip}) Saved: "{old}"'.format(ip=self.entry.name, old=self.serial_no)) + log.warning('({ip}) Received: "{new}"'.format(ip=self.entry.name, new=data)) + log.warning('({ip}) NOT saving serial number'.format(ip=self.entry.name)) self.serial_no_received = data def process_sver(self, data): @@ -550,18 +543,16 @@ class PJLinkCommands(object): log.warning('Invalid software version - too long') return elif self.sw_version is None: - log.debug('({ip}) Setting projector software version to "{data}"'.format(ip=self.ip, data=data)) - self.sw_version = data - self.db_update = True + log.debug('({ip}) Setting projector software version to "{data}"'.format(ip=self.entry.name, data=data)) else: - # Compare software version and see if we got the same projector - if self.serial_no != data: + if self.sw_version != data: log.warning('({ip}) Projector software version does not match saved ' - 'software version'.format(ip=self.ip)) - log.warning('({ip}) Saved: "{old}"'.format(ip=self.ip, old=self.sw_version)) - log.warning('({ip}) Received: "{new}"'.format(ip=self.ip, new=data)) - log.warning('({ip}) Saving new serial number as sw_version_received'.format(ip=self.ip)) - self.sw_version_received = data + 'software version'.format(ip=self.entry.name)) + log.warning('({ip}) Saved: "{old}"'.format(ip=self.entry.name, old=self.sw_version)) + log.warning('({ip}) Received: "{new}"'.format(ip=self.entry.name, new=data)) + log.warning('({ip}) Updating software version'.format(ip=self.entry.name)) + self.sw_version = data + self.db_update = True class PJLink(QtNetwork.QTcpSocket, PJLinkCommands): @@ -599,14 +590,14 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands): self.notes = self.entry.notes self.pin = self.entry.pin self.port = self.entry.port + self.pjlink_class = PJLINK_CLASS if self.entry.pjlink_class is None else self.entry.pjlink_class self.db_update = False # Use to check if db needs to be updated prior to exiting # Poll time 20 seconds unless called with something else self.poll_time = 20000 if 'poll_time' not in kwargs else kwargs['poll_time'] * 1000 - # Timeout 5 seconds unless called with something else + # Socket timeout (in case of brain-dead projectors) 5 seconds unless called with something else self.socket_timeout = 5000 if 'socket_timeout' not in kwargs else kwargs['socket_timeout'] * 1000 # In case we're called from somewhere that only wants information self.no_poll = 'no_poll' in kwargs - self.i_am_running = False self.status_connect = S_NOT_CONNECTED self.last_command = '' self.projector_status = S_NOT_CONNECTED @@ -616,61 +607,29 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands): self.max_size = PJLINK_MAX_PACKET + 2 self.setReadBufferSize(self.max_size) self.reset_information() - # Set from ProjectorManager.add_projector() - self.widget = None # QListBox entry - self.timer = None # Timer that calls the poll_loop self.send_queue = [] self.priority_queue = [] self.send_busy = False - # Socket timer for some possible brain-dead projectors or network cable pulled - self.socket_timer = None - - def thread_started(self): - """ - Connects signals to methods when thread is started. - """ - log.debug('({ip}) Thread starting'.format(ip=self.ip)) - self.i_am_running = True + # Poll timer for status updates + self.poll_timer = QtCore.QTimer(self) # Timer that calls the poll_loop + self.poll_timer.setInterval(self.poll_time) + self.poll_timer.timeout.connect(self.poll_loop) + # Socket timer for some possible brain-dead projectors or network issues + self.socket_timer = QtCore.QTimer(self) + self.socket_timer.setInterval(self.socket_timeout) + self.socket_timer.timeout.connect(self.socket_abort) + # Socket status signals self.connected.connect(self.check_login) self.disconnected.connect(self.disconnect_from_host) self.error.connect(self.get_error) self.projectorReceivedData.connect(self._send_command) - def thread_stopped(self): - """ - Cleanups when thread is stopped. - """ - log.debug('({ip}) Thread stopped'.format(ip=self.ip)) - try: - self.connected.disconnect(self.check_login) - except TypeError: - pass - try: - self.disconnected.disconnect(self.disconnect_from_host) - except TypeError: - pass - try: - self.error.disconnect(self.get_error) - except TypeError: - pass - try: - self.projectorReceivedData.disconnect(self._send_command) - except TypeError: - pass - try: - self.readyRead.disconnect(self.get_socket) # Set in process_pjlink - except TypeError: - pass - self.disconnect_from_host() - self.deleteLater() - self.i_am_running = False - def socket_abort(self): """ Aborts connection and closes socket in case of brain-dead projectors. Should normally be called by socket_timer(). """ - log.debug('({ip}) socket_abort() - Killing connection'.format(ip=self.ip)) + log.debug('({ip}) socket_abort() - Killing connection'.format(ip=self.entry.name)) self.disconnect_from_host(abort=True) def poll_loop(self): @@ -678,23 +637,14 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands): Retrieve information from projector that changes. Normally called by timer(). """ - if self.state() != S_QSOCKET_STATE['ConnectedState']: - log.warning('({ip}) poll_loop(): Not connected - returning'.format(ip=self.ip)) + if QSOCKET_STATE[self.state()] != S_CONNECTED: + log.warning('({ip}) poll_loop(): Not connected - returning'.format(ip=self.entry.name)) + # Stop timer just in case it's missed elsewhere + self.poll_timer.stop() return - log.debug('({ip}) poll_loop(): Updating projector status'.format(ip=self.ip)) - # Reset timer in case we were called from a set command - if self.timer.interval() < self.poll_time: - # Reset timer to 5 seconds - self.timer.setInterval(self.poll_time) - # Restart timer - self.timer.start() - # These commands may change during connection - check_list = ['POWR', 'ERST', 'LAMP', 'AVMT', 'INPT'] - if self.pjlink_class == '2': - check_list.extend(['FILT', 'FREZ']) - for command in check_list: - self.send_command(command) + log.debug('({ip}) poll_loop(): Updating projector status'.format(ip=self.entry.name)) # The following commands do not change, so only check them once + # Call them first in case other functions rely on something here if self.power == S_ON and self.source_available is None: self.send_command('INST') if self.other_info is None: @@ -715,22 +665,30 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands): self.send_command('RFIL') if self.model_lamp is None: self.send_command('RLMP') + # These commands may change during connection + check_list = ['POWR', 'ERST', 'LAMP', 'AVMT', 'INPT'] + if self.pjlink_class == '2': + check_list.extend(['FILT', 'FREZ']) + for command in check_list: + self.send_command(command) + # Reset the poll_timer for normal operations in case of initial connection + self.poll_timer.setInterval(self.poll_time) def _get_status(self, status): """ Helper to retrieve status/error codes and convert to strings. :param status: Status/Error code - :returns: (Status/Error code, String) + :returns: tuple (-1 if code not INT, None) + :returns: tuple (string: code as string, None if no description) + :returns: tuple (string: code as string, string: Status/Error description) """ if not isinstance(status, int): - return -1, 'Invalid status code' - elif status in ERROR_STRING: - return ERROR_STRING[status], ERROR_MSG[status] - elif status in STATUS_STRING: - return STATUS_STRING[status], ERROR_MSG[status] + return -1, None + elif status not in STATUS_MSG: + return None, None else: - return status, translate('OpenLP.PJLink', 'Unknown status') + return STATUS_CODE[status], STATUS_MSG[status] def change_status(self, status, msg=None): """ @@ -740,31 +698,48 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands): :param status: Status code :param msg: Optional message """ - message = translate('OpenLP.PJLink', 'No message') if msg is None else msg - (code, message) = self._get_status(status) - if msg is not None: - message = msg + if status in STATUS_CODE: + log.debug('({ip}) Changing status to {status} ' + '"{msg}"'.format(ip=self.entry.name, + status=STATUS_CODE[status], + msg=msg if msg is not None else STATUS_MSG[status])) + else: + log.warning('({ip}) Unknown status change code: {code}'.format(ip=self.entry.name, + code=status)) + return if status in CONNECTION_ERRORS: - # Projector, connection state - self.projector_status = self.error_status = self.status_connect = E_NOT_CONNECTED - elif status >= S_NOT_CONNECTED and status < S_STATUS: + # Connection state error affects both socket and projector + self.error_status = status + self.status_connect = E_NOT_CONNECTED + elif status >= S_NOT_CONNECTED and status in QSOCKET_STATE: + # Socket connection status update self.status_connect = status - self.projector_status = S_NOT_CONNECTED - elif status <= S_INFO: - self.status_connect = S_CONNECTED + elif status >= S_NOT_CONNECTED and status in PROJECTOR_STATE: + # Only affects the projector status self.projector_status = status + + # These log entries are for troubleshooting only (status_code, status_message) = self._get_status(self.status_connect) - log.debug('({ip}) status_connect: {code}: "{message}"'.format(ip=self.ip, + log.debug('({ip}) status_connect: {code}: "{message}"'.format(ip=self.entry.name, code=status_code, message=status_message if msg is None else msg)) (status_code, status_message) = self._get_status(self.projector_status) - log.debug('({ip}) projector_status: {code}: "{message}"'.format(ip=self.ip, + log.debug('({ip}) projector_status: {code}: "{message}"'.format(ip=self.entry.name, code=status_code, message=status_message if msg is None else msg)) (status_code, status_message) = self._get_status(self.error_status) - log.debug('({ip}) error_status: {code}: "{message}"'.format(ip=self.ip, + log.debug('({ip}) error_status: {code}: "{message}"'.format(ip=self.entry.name, code=status_code, message=status_message if msg is None else msg)) + + # Now that we logged extra information for debugging, broadcast the original change/message + (code, message) = self._get_status(status) + if msg is not None: + message = msg + elif message is None: + # No message for status code + message = translate('OpenLP.PJLink', 'No message') if msg is None else msg + self.changeStatus.emit(self.ip, status, message) self.projectorUpdateIcons.emit() @@ -775,27 +750,27 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands): :param data: Optional data if called from another routine """ - log.debug('({ip}) check_login(data="{data}")'.format(ip=self.ip, data=data)) + log.debug('({ip}) check_login(data="{data}")'.format(ip=self.entry.name, data=data)) if data is None: # Reconnected setup? if not self.waitForReadyRead(2000): # Possible timeout issue - log.error('({ip}) Socket timeout waiting for login'.format(ip=self.ip)) + log.error('({ip}) Socket timeout waiting for login'.format(ip=self.entry.name)) self.change_status(E_SOCKET_TIMEOUT) return read = self.readLine(self.max_size) self.readLine(self.max_size) # Clean out any trailing whitespace if read is None: - log.warning('({ip}) read is None - socket error?'.format(ip=self.ip)) + log.warning('({ip}) read is None - socket error?'.format(ip=self.entry.name)) return elif len(read) < 8: - log.warning('({ip}) Not enough data read - skipping'.format(ip=self.ip)) + log.warning('({ip}) Not enough data read - skipping'.format(ip=self.entry.name)) return data = decode(read, 'utf-8') # Possibility of extraneous data on input when reading. # Clean out extraneous characters in buffer. - self.readLine(self.max_size) - log.debug('({ip}) check_login() read "{data}"'.format(ip=self.ip, data=data.strip())) + self.read(1024) + log.debug('({ip}) check_login() read "{data}"'.format(ip=self.entry.name, data=data.strip())) # At this point, we should only have the initial login prompt with # possible authentication # PJLink initial login will be: @@ -803,75 +778,26 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands): # 'PJLink 1 XXXXXX' Authenticated login - extra processing required. if not data.startswith('PJLINK'): # Invalid initial packet - close socket - log.error('({ip}) Invalid initial packet received - closing socket'.format(ip=self.ip)) + log.error('({ip}) Invalid initial packet received - closing socket'.format(ip=self.entry.name)) return self.disconnect_from_host() - log.debug('({ip}) check_login(): Formatting initial connection prompt to PJLink packet'.format(ip=self.ip)) + # Convert the initial login prompt with the expected PJLink normal command format for processing + log.debug('({ip}) check_login(): Formatting initial connection prompt' + 'to PJLink packet'.format(ip=self.entry.name)) return self.get_data('{start}{clss}{data}'.format(start=PJLINK_PREFIX, clss='1', data=data.replace(' ', '=', 1)).encode('utf-8')) - # TODO: The below is replaced by process_pjlink() - remove when working properly - """ - if '=' in data: - # Processing a login reply - data_check = data.strip().split('=') - else: - # Process initial connection - data_check = data.strip().split(' ') - log.debug('({ip}) data_check="{data}"'.format(ip=self.ip, data=data_check)) - # Check for projector reporting an error - if data_check[1].upper() == 'ERRA': - # Authentication error - self.disconnect_from_host() - self.change_status(E_AUTHENTICATION) - log.debug('({ip}) emitting projectorAuthentication() signal'.format(ip=self.ip)) - return - elif (data_check[1] == '0') and (self.pin): - # Pin set and no authentication needed - log.warning('({ip}) Regular connection but PIN set'.format(ip=self.name)) - self.disconnect_from_host() - self.change_status(E_AUTHENTICATION) - log.debug('({ip}) Emitting projectorNoAuthentication() signal'.format(ip=self.ip)) - self.projectorNoAuthentication.emit(self.name) - return - elif data_check[1] == '1': - # Authenticated login with salt - if not self.pin: - log.warning('({ip}) Authenticated connection but no pin set'.format(ip=self.ip)) - self.disconnect_from_host() - self.change_status(E_AUTHENTICATION) - log.debug('({ip}) Emitting projectorAuthentication() signal'.format(ip=self.ip)) - self.projectorAuthentication.emit(self.ip) - return - else: - log.debug('({ip}) Setting hash with salt="{data}"'.format(ip=self.ip, data=data_check[2])) - log.debug('({ip}) pin="{data}"'.format(ip=self.ip, data=self.pin)) - data_hash = str(qmd5_hash(salt=data_check[2].encode('utf-8'), data=self.pin.encode('utf-8')), - encoding='ascii') - else: - data_hash = None - # We're connected at this point, so go ahead and setup regular I/O - self.readyRead.connect(self.get_socket) - self.projectorReceivedData.connect(self._send_command) - # Initial data we should know about - self.send_command(cmd='CLSS', salt=data_hash) - self.waitForReadyRead() - if (not self.no_poll) and (self.state() == self.ConnectedState): - log.debug('({ip}) Starting timer'.format(ip=self.ip)) - self.timer.setInterval(2000) # Set 2 seconds for initial information - self.timer.start() - """ def _trash_buffer(self, msg=None): """ Clean out extraneous stuff in the buffer. """ - log.warning('({ip}) {message}'.format(ip=self.ip, message='Invalid packet' if msg is None else msg)) + log.warning('({ip}) {message}'.format(ip=self.entry.name, message='Invalid packet' if msg is None else msg)) self.send_busy = False trash_count = 0 while self.bytesAvailable() > 0: trash = self.read(self.max_size) trash_count += len(trash) - log.debug('({ip}) Finished cleaning buffer - {count} bytes dropped'.format(ip=self.ip, + log.debug('({ip}) Finished cleaning buffer - {count} bytes dropped'.format(ip=self.entry.name, count=trash_count)) return @@ -883,9 +809,9 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands): :param data: Data to process. buffer must be formatted as a proper PJLink packet. :param ip: Destination IP for buffer. """ - log.debug('({ip}) get_buffer(data="{buff}" ip="{ip_in}"'.format(ip=self.ip, buff=data, ip_in=ip)) + log.debug('({ip}) get_buffer(data="{buff}" ip="{ip_in}"'.format(ip=self.entry.name, buff=data, ip_in=ip)) if ip is None: - log.debug("({ip}) get_buffer() Don't know who data is for - exiting".format(ip=self.ip)) + log.debug("({ip}) get_buffer() Don't know who data is for - exiting".format(ip=self.entry.name)) return return self.get_data(buff=data, ip=ip) @@ -894,21 +820,20 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands): """ Get data from TCP socket. """ - log.debug('({ip}) get_socket(): Reading data'.format(ip=self.ip)) - if self.state() != self.ConnectedState: - log.debug('({ip}) get_socket(): Not connected - returning'.format(ip=self.ip)) + log.debug('({ip}) get_socket(): Reading data'.format(ip=self.entry.name)) + if QSOCKET_STATE[self.state()] != S_CONNECTED: + log.debug('({ip}) get_socket(): Not connected - returning'.format(ip=self.entry.name)) self.send_busy = False return # Although we have a packet length limit, go ahead and use a larger buffer read = self.readLine(1024) - log.debug('({ip}) get_socket(): "{buff}"'.format(ip=self.ip, buff=read)) + log.debug('({ip}) get_socket(): "{buff}"'.format(ip=self.entry.name, buff=read)) if read == -1: # No data available - log.debug('({ip}) get_socket(): No data available (-1)'.format(ip=self.ip)) + log.debug('({ip}) get_socket(): No data available (-1)'.format(ip=self.entry.name)) return self.receive_data_signal() self.socket_timer.stop() - self.get_data(buff=read, ip=self.ip) - return self.receive_data_signal() + return self.get_data(buff=read, ip=self.ip) def get_data(self, buff, ip=None): """ @@ -921,20 +846,24 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands): # set to default here if ip is None: ip = self.ip - log.debug('({ip}) get_data(ip="{ip_in}" buffer="{buff}"'.format(ip=self.ip, ip_in=ip, buff=buff)) + log.debug('({ip}) get_data(ip="{ip_in}" buffer="{buff}"'.format(ip=self.entry.name, ip_in=ip, buff=buff)) # NOTE: Class2 has changed to some values being UTF-8 data_in = decode(buff, 'utf-8') data = data_in.strip() # Initial packet checks if (len(data) < 7): - return self._trash_buffer(msg='get_data(): Invalid packet - length') + self._trash_buffer(msg='get_data(): Invalid packet - length') + return self.receive_data_signal() elif len(data) > self.max_size: - return self._trash_buffer(msg='get_data(): Invalid packet - too long') + self._trash_buffer(msg='get_data(): Invalid packet - too long') + return self.receive_data_signal() elif not data.startswith(PJLINK_PREFIX): - return self._trash_buffer(msg='get_data(): Invalid packet - PJLink prefix missing') + self._trash_buffer(msg='get_data(): Invalid packet - PJLink prefix missing') + return self.receive_data_signal() elif '=' not in data: - return self._trash_buffer(msg='get_data(): Invalid reply - Does not have "="') - log.debug('({ip}) get_data(): Checking new data "{data}"'.format(ip=self.ip, data=data)) + self._trash_buffer(msg='get_data(): Invalid reply - Does not have "="') + return self.receive_data_signal() + log.debug('({ip}) get_data(): Checking new data "{data}"'.format(ip=self.entry.name, data=data)) header, data = data.split('=') # At this point, the header should contain: # "PVCCCC" @@ -946,16 +875,19 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands): version, cmd = header[1], header[2:].upper() except ValueError as e: self.change_status(E_INVALID_DATA) - log.warning('({ip}) get_data(): Received data: "{data}"'.format(ip=self.ip, data=data_in)) - return self._trash_buffer('get_data(): Expected header + command + data') + log.warning('({ip}) get_data(): Received data: "{data}"'.format(ip=self.entry.name, data=data_in)) + self._trash_buffer('get_data(): Expected header + command + data') + return self.receive_data_signal() if cmd not in PJLINK_VALID_CMD: - log.warning('({ip}) get_data(): Invalid packet - unknown command "{data}"'.format(ip=self.ip, data=cmd)) - return self._trash_buffer(msg='get_data(): Unknown command "{data}"'.format(data=cmd)) + log.warning('({ip}) get_data(): Invalid packet - unknown command "{data}"'.format(ip=self.entry.name, + data=cmd)) + self._trash_buffer(msg='get_data(): Unknown command "{data}"'.format(data=cmd)) + return self.receive_data_signal() if int(self.pjlink_class) < int(version): log.warning('({ip}) get_data(): Projector returned class reply higher ' - 'than projector stated class'.format(ip=self.ip)) - self.send_busy = False - return self.process_command(cmd, data) + 'than projector stated class'.format(ip=self.entry.name)) + self.process_command(cmd, data) + return self.receive_data_signal() @QtCore.pyqtSlot(QtNetwork.QAbstractSocket.SocketError) def get_error(self, err): @@ -965,12 +897,14 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands): :param err: Error code """ - log.debug('({ip}) get_error(err={error}): {data}'.format(ip=self.ip, error=err, data=self.errorString())) + log.debug('({ip}) get_error(err={error}): {data}'.format(ip=self.entry.name, + error=err, + data=self.errorString())) if err <= 18: # QSocket errors. Redefined in projector.constants so we don't mistake # them for system errors check = err + E_CONNECTION_REFUSED - self.timer.stop() + self.poll_timer.stop() else: check = err if check < E_GENERAL: @@ -993,13 +927,13 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands): :param salt: Optional salt for md5 hash initial authentication :param priority: Option to send packet now rather than queue it up """ - if self.state() != self.ConnectedState: - log.warning('({ip}) send_command(): Not connected - returning'.format(ip=self.ip)) + if QSOCKET_STATE[self.state()] != S_CONNECTED: + log.warning('({ip}) send_command(): Not connected - returning'.format(ip=self.entry.name)) return self.reset_information() if cmd not in PJLINK_VALID_CMD: - log.error('({ip}) send_command(): Invalid command requested - ignoring.'.format(ip=self.ip)) + log.error('({ip}) send_command(): Invalid command requested - ignoring.'.format(ip=self.entry.name)) return - log.debug('({ip}) send_command(): Building cmd="{command}" opts="{data}"{salt}'.format(ip=self.ip, + log.debug('({ip}) send_command(): Building cmd="{command}" opts="{data}"{salt}'.format(ip=self.entry.name, command=cmd, data=opts, salt='' if salt is None @@ -1012,23 +946,23 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands): header = PJLINK_HEADER.format(linkclass=cmd_ver[0]) else: # NOTE: Once we get to version 3 then think about looping - log.error('({ip}): send_command(): PJLink class check issue? Aborting'.format(ip=self.ip)) + log.error('({ip}): send_command(): PJLink class check issue? Aborting'.format(ip=self.entry.name)) return out = '{salt}{header}{command} {options}{suffix}'.format(salt="" if salt is None else salt, header=header, command=cmd, options=opts, - suffix=CR) + suffix=PJLINK_SUFFIX) if out in self.priority_queue: - log.debug('({ip}) send_command(): Already in priority queue - skipping'.format(ip=self.ip)) + log.debug('({ip}) send_command(): Already in priority queue - skipping'.format(ip=self.entry.name)) elif out in self.send_queue: - log.debug('({ip}) send_command(): Already in normal queue - skipping'.format(ip=self.ip)) + log.debug('({ip}) send_command(): Already in normal queue - skipping'.format(ip=self.entry.name)) else: if priority: - log.debug('({ip}) send_command(): Adding to priority queue'.format(ip=self.ip)) + log.debug('({ip}) send_command(): Adding to priority queue'.format(ip=self.entry.name)) self.priority_queue.append(out) else: - log.debug('({ip}) send_command(): Adding to normal queue'.format(ip=self.ip)) + log.debug('({ip}) send_command(): Adding to normal queue'.format(ip=self.entry.name)) self.send_queue.append(out) if self.priority_queue or self.send_queue: # May be some initial connection setup so make sure we send data @@ -1043,43 +977,45 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands): :param utf8: Send as UTF-8 string otherwise send as ASCII string """ # Funny looking data check, but it's a quick check for data=None - log.debug('({ip}) _send_command(data="{data}")'.format(ip=self.ip, data=data.strip() if data else data)) - log.debug('({ip}) _send_command(): Connection status: {data}'.format(ip=self.ip, - data=S_QSOCKET_STATE[self.state()])) - if self.state() != self.ConnectedState: - log.debug('({ip}) _send_command() Not connected - abort'.format(ip=self.ip)) + log.debug('({ip}) _send_command(data="{data}")'.format(ip=self.entry.name, data=data.strip() if data else data)) + conn_state = STATUS_CODE[QSOCKET_STATE[self.state()]] + log.debug('({ip}) _send_command(): Connection status: {data}'.format(ip=self.entry.name, + data=conn_state)) + if QSOCKET_STATE[self.state()] != S_CONNECTED: + log.debug('({ip}) _send_command() Not connected - abort'.format(ip=self.entry.name)) self.send_busy = False return self.disconnect_from_host() if data and data not in self.priority_queue: - log.debug('({ip}) _send_command(): Priority packet - adding to priority queue'.format(ip=self.ip)) + log.debug('({ip}) _send_command(): Priority packet - adding to priority queue'.format(ip=self.entry.name)) self.priority_queue.append(data) if self.send_busy: # Still waiting for response from last command sent - log.debug('({ip}) _send_command(): Still busy, returning'.format(ip=self.ip)) - log.debug('({ip}) _send_command(): Priority queue = {data}'.format(ip=self.ip, data=self.priority_queue)) - log.debug('({ip}) _send_command(): Normal queue = {data}'.format(ip=self.ip, data=self.send_queue)) + log.debug('({ip}) _send_command(): Still busy, returning'.format(ip=self.entry.name)) + log.debug('({ip}) _send_command(): Priority queue = {data}'.format(ip=self.entry.name, + data=self.priority_queue)) + log.debug('({ip}) _send_command(): Normal queue = {data}'.format(ip=self.entry.name, data=self.send_queue)) return if len(self.priority_queue) != 0: out = self.priority_queue.pop(0) - log.debug('({ip}) _send_command(): Getting priority queued packet'.format(ip=self.ip)) + log.debug('({ip}) _send_command(): Getting priority queued packet'.format(ip=self.entry.name)) elif len(self.send_queue) != 0: out = self.send_queue.pop(0) - log.debug('({ip}) _send_command(): Getting normal queued packet'.format(ip=self.ip)) + log.debug('({ip}) _send_command(): Getting normal queued packet'.format(ip=self.entry.name)) else: # No data to send - log.debug('({ip}) _send_command(): No data to send'.format(ip=self.ip)) + log.debug('({ip}) _send_command(): No data to send'.format(ip=self.entry.name)) self.send_busy = False return self.send_busy = True - log.debug('({ip}) _send_command(): Sending "{data}"'.format(ip=self.ip, data=out.strip())) + log.debug('({ip}) _send_command(): Sending "{data}"'.format(ip=self.entry.name, data=out.strip())) self.socket_timer.start() sent = self.write(out.encode('{string_encoding}'.format(string_encoding='utf-8' if utf8 else 'ascii'))) self.waitForBytesWritten(2000) # 2 seconds should be enough if sent == -1: # Network error? - log.warning('({ip}) _send_command(): -1 received - disconnecting from host'.format(ip=self.ip)) + log.warning('({ip}) _send_command(): -1 received - disconnecting from host'.format(ip=self.entry.name)) self.change_status(E_NETWORK, translate('OpenLP.PJLink', 'Error while sending data to projector')) self.disconnect_from_host() @@ -1088,10 +1024,11 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands): """ Initiate connection to projector. """ - log.debug('{ip}) connect_to_host(): Starting connection'.format(ip=self.ip)) - if self.state() == self.ConnectedState: - log.warning('({ip}) connect_to_host(): Already connected - returning'.format(ip=self.ip)) + log.debug('({ip}) connect_to_host(): Starting connection'.format(ip=self.entry.name)) + if QSOCKET_STATE[self.state()] == S_CONNECTED: + log.warning('({ip}) connect_to_host(): Already connected - returning'.format(ip=self.entry.name)) return + self.error_status = S_OK self.change_status(S_CONNECTING) self.connectToHost(self.ip, self.port if isinstance(self.port, int) else int(self.port)) @@ -1100,18 +1037,19 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands): """ Close socket and cleanup. """ - if abort or self.state() != self.ConnectedState: + if abort or QSOCKET_STATE[self.state()] != S_NOT_CONNECTED: if abort: - log.warning('({ip}) disconnect_from_host(): Aborting connection'.format(ip=self.ip)) + log.warning('({ip}) disconnect_from_host(): Aborting connection'.format(ip=self.entry.name)) + self.abort() else: - log.warning('({ip}) disconnect_from_host(): Not connected'.format(ip=self.ip)) - self.disconnectFromHost() + log.warning('({ip}) disconnect_from_host(): Not connected'.format(ip=self.entry.name)) + self.disconnectFromHost() try: self.readyRead.disconnect(self.get_socket) except TypeError: pass log.debug('({ip}) disconnect_from_host() ' - 'Current status {data}'.format(ip=self.ip, data=self._get_status(self.status_connect)[0])) + 'Current status {data}'.format(ip=self.entry.name, data=self._get_status(self.status_connect)[0])) if abort: self.change_status(E_NOT_CONNECTED) else: @@ -1122,70 +1060,70 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands): """ Send command to retrieve shutter status. """ - log.debug('({ip}) Sending AVMT command'.format(ip=self.ip)) + log.debug('({ip}) Sending AVMT command'.format(ip=self.entry.name)) return self.send_command(cmd='AVMT') def get_available_inputs(self): """ Send command to retrieve available source inputs. """ - log.debug('({ip}) Sending INST command'.format(ip=self.ip)) + log.debug('({ip}) Sending INST command'.format(ip=self.entry.name)) return self.send_command(cmd='INST') def get_error_status(self): """ Send command to retrieve currently known errors. """ - log.debug('({ip}) Sending ERST command'.format(ip=self.ip)) + log.debug('({ip}) Sending ERST command'.format(ip=self.entry.name)) return self.send_command(cmd='ERST') def get_input_source(self): """ Send command to retrieve currently selected source input. """ - log.debug('({ip}) Sending INPT command'.format(ip=self.ip)) + log.debug('({ip}) Sending INPT command'.format(ip=self.entry.name)) return self.send_command(cmd='INPT') def get_lamp_status(self): """ Send command to return the lap status. """ - log.debug('({ip}) Sending LAMP command'.format(ip=self.ip)) + log.debug('({ip}) Sending LAMP command'.format(ip=self.entry.name)) return self.send_command(cmd='LAMP') def get_manufacturer(self): """ Send command to retrieve manufacturer name. """ - log.debug('({ip}) Sending INF1 command'.format(ip=self.ip)) + log.debug('({ip}) Sending INF1 command'.format(ip=self.entry.name)) return self.send_command(cmd='INF1') def get_model(self): """ Send command to retrieve the model name. """ - log.debug('({ip}) Sending INF2 command'.format(ip=self.ip)) + log.debug('({ip}) Sending INF2 command'.format(ip=self.entry.name)) return self.send_command(cmd='INF2') def get_name(self): """ Send command to retrieve name as set by end-user (if set). """ - log.debug('({ip}) Sending NAME command'.format(ip=self.ip)) + log.debug('({ip}) Sending NAME command'.format(ip=self.entry.name)) return self.send_command(cmd='NAME') def get_other_info(self): """ Send command to retrieve extra info set by manufacturer. """ - log.debug('({ip}) Sending INFO command'.format(ip=self.ip)) + log.debug('({ip}) Sending INFO command'.format(ip=self.entry.name)) return self.send_command(cmd='INFO') def get_power_status(self): """ Send command to retrieve power status. """ - log.debug('({ip}) Sending POWR command'.format(ip=self.ip)) + log.debug('({ip}) Sending POWR command'.format(ip=self.entry.name)) return self.send_command(cmd='POWR') def set_input_source(self, src=None): @@ -1195,46 +1133,47 @@ class PJLink(QtNetwork.QTcpSocket, PJLinkCommands): :param src: Video source to select in projector """ - log.debug('({ip}) set_input_source(src="{data}")'.format(ip=self.ip, data=src)) + log.debug('({ip}) set_input_source(src="{data}")'.format(ip=self.entry.name, data=src)) if self.source_available is None: return elif src not in self.source_available: return - log.debug('({ip}) Setting input source to "{data}"'.format(ip=self.ip, data=src)) - self.send_command(cmd='INPT', opts=src) + log.debug('({ip}) Setting input source to "{data}"'.format(ip=self.entry.name, data=src)) + self.send_command(cmd='INPT', opts=src, priority=True) self.poll_loop() def set_power_on(self): """ Send command to turn power to on. """ - log.debug('({ip}) Setting POWR to 1 (on)'.format(ip=self.ip)) - self.send_command(cmd='POWR', opts='1') + log.debug('({ip}) Setting POWR to 1 (on)'.format(ip=self.entry.name)) + self.send_command(cmd='POWR', opts='1', priority=True) self.poll_loop() def set_power_off(self): """ Send command to turn power to standby. """ - log.debug('({ip}) Setting POWR to 0 (standby)'.format(ip=self.ip)) - self.send_command(cmd='POWR', opts='0') + log.debug('({ip}) Setting POWR to 0 (standby)'.format(ip=self.entry.name)) + self.send_command(cmd='POWR', opts='0', priority=True) self.poll_loop() def set_shutter_closed(self): """ Send command to set shutter to closed position. """ - log.debug('({ip}) Setting AVMT to 11 (shutter closed)'.format(ip=self.ip)) - self.send_command(cmd='AVMT', opts='11') + log.debug('({ip}) Setting AVMT to 11 (shutter closed)'.format(ip=self.entry.name)) + self.send_command(cmd='AVMT', opts='11', priority=True) self.poll_loop() def set_shutter_open(self): """ Send command to set shutter to open position. """ - log.debug('({ip}) Setting AVMT to "10" (shutter open)'.format(ip=self.ip)) - self.send_command(cmd='AVMT', opts='10') + log.debug('({ip}) Setting AVMT to "10" (shutter open)'.format(ip=self.entry.name)) + self.send_command(cmd='AVMT', opts='10', priority=True) self.poll_loop() + self.projectorUpdateIcons.emit() def receive_data_signal(self): """ diff --git a/openlp/core/projectors/sourceselectform.py b/openlp/core/projectors/sourceselectform.py index aaf8170ac..b9c3501a4 100644 --- a/openlp/core/projectors/sourceselectform.py +++ b/openlp/core/projectors/sourceselectform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -31,8 +31,8 @@ from PyQt5 import QtCore, QtWidgets from openlp.core.common import is_macosx from openlp.core.common.i18n import translate from openlp.core.lib import build_icon -from openlp.core.projectors.db import ProjectorSource from openlp.core.projectors.constants import PJLINK_DEFAULT_SOURCES, PJLINK_DEFAULT_CODES +from openlp.core.projectors.db import ProjectorSource log = logging.getLogger(__name__) diff --git a/openlp/core/projectors/tab.py b/openlp/core/projectors/tab.py index 29e6a9511..2f308d83a 100644 --- a/openlp/core/projectors/tab.py +++ b/openlp/core/projectors/tab.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/projectors/upgrade.py b/openlp/core/projectors/upgrade.py index 83cd2defb..d3837eda0 100644 --- a/openlp/core/projectors/upgrade.py +++ b/openlp/core/projectors/upgrade.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -33,7 +33,7 @@ from openlp.core.lib.db import get_upgrade_op log = logging.getLogger(__name__) # Initial projector DB was unversioned -__version__ = 2 +__version__ = 3 log.debug('Projector DB upgrade module loading') @@ -71,3 +71,23 @@ def upgrade_2(session, metadata): new_op.add_column('projector', Column('model_filter', types.String(30), server_default=null())) new_op.add_column('projector', Column('model_lamp', types.String(30), server_default=null())) log.debug('{status} projector DB upgrade to version 2'.format(status='Updated' if upgrade_db else 'Skipping')) + + +def upgrade_3(session, metadata): + """ + Version 3 upgrade. + + Update Projector() table to inlcude PJLink class as part of record. + + pjlink_version: Column(String(1)) + + :param session: DB Session instance + :param metadata: Metadata of current DB + """ + log.debug('Checking projector DB upgrade to version 3') + projector_table = Table('projector', metadata, autoload=True) + upgrade_db = 'pjlink_class' not in [col.name for col in projector_table.c.values()] + if upgrade_db: + new_op = get_upgrade_op(session) + new_op.add_column('projector', Column('pjlink_class', types.String(5), server_default=null())) + log.debug('{status} projector DB upgrade to version 3'.format(status='Updated' if upgrade_db else 'Skipping')) diff --git a/openlp/core/threading.py b/openlp/core/threading.py index 36dfd481f..626bbb93e 100644 --- a/openlp/core/threading.py +++ b/openlp/core/threading.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -24,26 +24,41 @@ The :mod:`openlp.core.threading` module contains some common threading code """ from PyQt5 import QtCore +from openlp.core.common.registry import Registry -def run_thread(parent, worker, prefix='', auto_start=True): + +class ThreadWorker(QtCore.QObject): + """ + The :class:`~openlp.core.threading.ThreadWorker` class provides a base class for all worker objects + """ + quit = QtCore.pyqtSignal() + + def start(self): + """ + The start method is how the worker runs. Basically, put your code here. + """ + raise NotImplementedError('Your base class needs to override this method and run self.quit.emit() at the end.') + + +def run_thread(worker, thread_name, can_start=True): """ Create a thread and assign a worker to it. This removes a lot of boilerplate code from the codebase. - :param object parent: The parent object so that the thread and worker are not orphaned. :param QObject worker: A QObject-based worker object which does the actual work. - :param str prefix: A prefix to be applied to the attribute names. - :param bool auto_start: Automatically start the thread. Defaults to True. + :param str thread_name: The name of the thread, used to keep track of the thread. + :param bool can_start: Start the thread. Defaults to True. """ - # Set up attribute names - thread_name = 'thread' - worker_name = 'worker' - if prefix: - thread_name = '_'.join([prefix, thread_name]) - worker_name = '_'.join([prefix, worker_name]) + if not thread_name: + raise ValueError('A thread_name is required when calling the "run_thread" function') + application = Registry().get('application') + if thread_name in application.worker_threads: + raise KeyError('A thread with the name "{}" has already been created, please use another'.format(thread_name)) # Create the thread and add the thread and the worker to the parent thread = QtCore.QThread() - setattr(parent, thread_name, thread) - setattr(parent, worker_name, worker) + application.worker_threads[thread_name] = { + 'thread': thread, + 'worker': worker + } # Move the worker into the thread's context worker.moveToThread(thread) # Connect slots and signals @@ -51,5 +66,50 @@ def run_thread(parent, worker, prefix='', auto_start=True): worker.quit.connect(thread.quit) worker.quit.connect(worker.deleteLater) thread.finished.connect(thread.deleteLater) - if auto_start: + thread.finished.connect(make_remove_thread(thread_name)) + if can_start: thread.start() + + +def get_thread_worker(thread_name): + """ + Get the worker by the thread name + + :param str thread_name: The name of the thread + :returns: The worker for this thread name + """ + thread_info = Registry().get('application').worker_threads.get(thread_name) + if not thread_info: + raise KeyError('No thread named "{}" exists'.format(thread_name)) + return thread_info.get('worker') + + +def is_thread_finished(thread_name): + """ + Check if a thread is finished running. + + :param str thread_name: The name of the thread + :returns: True if the thread is finished, False if it is still running + """ + app = Registry().get('application') + return thread_name not in app.worker_threads or app.worker_threads[thread_name]['thread'].isFinished() + + +def make_remove_thread(thread_name): + """ + Create a function to remove the thread once the thread is finished. + + :param str thread_name: The name of the thread which should be removed from the thread registry. + :returns: A function which will remove the thread from the thread registry. + """ + + def remove_thread(): # pragma: nocover + """ + Stop and remove a registered thread + + :param str thread_name: The name of the thread to stop and remove + """ + application = Registry().get('application') + if thread_name in application.worker_threads: + del application.worker_threads[thread_name] + return remove_thread diff --git a/openlp/core/ui/__init__.py b/openlp/core/ui/__init__.py index 5c2463e5d..e6cd930b1 100644 --- a/openlp/core/ui/__init__.py +++ b/openlp/core/ui/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/aboutdialog.py b/openlp/core/ui/aboutdialog.py index 8cd422ecf..d60f0ee0c 100644 --- a/openlp/core/ui/aboutdialog.py +++ b/openlp/core/ui/aboutdialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/aboutform.py b/openlp/core/ui/aboutform.py index e2b4eca87..5967108d5 100644 --- a/openlp/core/ui/aboutform.py +++ b/openlp/core/ui/aboutform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -26,8 +26,8 @@ import webbrowser from PyQt5 import QtCore, QtWidgets -from openlp.core.version import get_version from openlp.core.common.i18n import translate +from openlp.core.version import get_version from .aboutdialog import UiAboutDialog diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py index 2d434c0c6..ffec0e5b8 100644 --- a/openlp/core/ui/advancedtab.py +++ b/openlp/core/ui/advancedtab.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/exceptiondialog.py b/openlp/core/ui/exceptiondialog.py index 0cdd3d28d..bb46868a2 100644 --- a/openlp/core/ui/exceptiondialog.py +++ b/openlp/core/ui/exceptiondialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/exceptionform.py b/openlp/core/ui/exceptionform.py index 45124dac8..b981bddbc 100644 --- a/openlp/core/ui/exceptionform.py +++ b/openlp/core/ui/exceptionform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/filerenamedialog.py b/openlp/core/ui/filerenamedialog.py index 0c2e089af..9db2dbb06 100644 --- a/openlp/core/ui/filerenamedialog.py +++ b/openlp/core/ui/filerenamedialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/filerenameform.py b/openlp/core/ui/filerenameform.py index 249ea1f10..471242207 100644 --- a/openlp/core/ui/filerenameform.py +++ b/openlp/core/ui/filerenameform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/firsttimeform.py b/openlp/core/ui/firsttimeform.py index 37fac2dd4..631ae4dfc 100644 --- a/openlp/core/ui/firsttimeform.py +++ b/openlp/core/ui/firsttimeform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -23,12 +23,10 @@ This module contains the first time wizard. """ import logging -import os -import socket import time -import urllib.request -import urllib.parse import urllib.error +import urllib.parse +import urllib.request from configparser import ConfigParser, MissingSectionHeaderError, NoOptionError, NoSectionError from tempfile import gettempdir @@ -36,54 +34,55 @@ from PyQt5 import QtCore, QtWidgets from openlp.core.common import clean_button_text, trace_error_handler from openlp.core.common.applocation import AppLocation +from openlp.core.common.httputils import get_web_page, get_url_file_size, download_file from openlp.core.common.i18n import translate -from openlp.core.common.path import Path, create_paths from openlp.core.common.mixins import RegistryProperties +from openlp.core.common.path import Path, create_paths from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings from openlp.core.lib import PluginStatus, build_icon from openlp.core.lib.ui import critical_error_message_box -from openlp.core.common.httputils import get_web_page, get_url_file_size, url_get_file, CONNECTION_TIMEOUT -from .firsttimewizard import UiFirstTimeWizard, FirstTimePage +from openlp.core.threading import ThreadWorker, run_thread, get_thread_worker, is_thread_finished +from openlp.core.ui.firsttimewizard import UiFirstTimeWizard, FirstTimePage log = logging.getLogger(__name__) -class ThemeScreenshotWorker(QtCore.QObject): +class ThemeScreenshotWorker(ThreadWorker): """ This thread downloads a theme's screenshot """ screenshot_downloaded = QtCore.pyqtSignal(str, str, str) - finished = QtCore.pyqtSignal() def __init__(self, themes_url, title, filename, sha256, screenshot): """ Set up the worker object """ - self.was_download_cancelled = False + self.was_cancelled = False self.themes_url = themes_url self.title = title self.filename = filename self.sha256 = sha256 self.screenshot = screenshot - socket.setdefaulttimeout(CONNECTION_TIMEOUT) - super(ThemeScreenshotWorker, self).__init__() + super().__init__() - def run(self): + def start(self): """ - Overridden method to run the thread. + Run the worker """ - if self.was_download_cancelled: + if self.was_cancelled: return try: - urllib.request.urlretrieve('{host}{name}'.format(host=self.themes_url, name=self.screenshot), - os.path.join(gettempdir(), 'openlp', self.screenshot)) - # Signal that the screenshot has been downloaded - self.screenshot_downloaded.emit(self.title, self.filename, self.sha256) - except: + download_path = Path(gettempdir()) / 'openlp' / self.screenshot + is_success = download_file(self, '{host}{name}'.format(host=self.themes_url, name=self.screenshot), + download_path) + if is_success and not self.was_cancelled: + # Signal that the screenshot has been downloaded + self.screenshot_downloaded.emit(self.title, self.filename, self.sha256) + except: # noqa log.exception('Unable to download screenshot') finally: - self.finished.emit() + self.quit.emit() @QtCore.pyqtSlot(bool) def set_download_canceled(self, toggle): @@ -145,12 +144,13 @@ class FirstTimeForm(QtWidgets.QWizard, UiFirstTimeWizard, RegistryProperties): return FirstTimePage.Progress elif self.currentId() == FirstTimePage.Themes: self.application.set_busy_cursor() - while not all([thread.isFinished() for thread in self.theme_screenshot_threads]): + while not all([is_thread_finished(thread_name) for thread_name in self.theme_screenshot_threads]): time.sleep(0.1) self.application.process_events() # Build the screenshot icons, as this can not be done in the thread. self._build_theme_screenshots() self.application.set_normal_cursor() + self.theme_screenshot_threads = [] return FirstTimePage.Defaults else: return self.get_next_page_id() @@ -171,7 +171,6 @@ class FirstTimeForm(QtWidgets.QWizard, UiFirstTimeWizard, RegistryProperties): self.screens = screens self.was_cancelled = False self.theme_screenshot_threads = [] - self.theme_screenshot_workers = [] self.has_run_wizard = False def _download_index(self): @@ -256,14 +255,10 @@ class FirstTimeForm(QtWidgets.QWizard, UiFirstTimeWizard, RegistryProperties): sha256 = self.config.get('theme_{theme}'.format(theme=theme), 'sha256', fallback='') screenshot = self.config.get('theme_{theme}'.format(theme=theme), 'screenshot') worker = ThemeScreenshotWorker(self.themes_url, title, filename, sha256, screenshot) - self.theme_screenshot_workers.append(worker) worker.screenshot_downloaded.connect(self.on_screenshot_downloaded) - thread = QtCore.QThread(self) - self.theme_screenshot_threads.append(thread) - thread.started.connect(worker.run) - worker.finished.connect(thread.quit) - worker.moveToThread(thread) - thread.start() + thread_name = 'theme_screenshot_{title}'.format(title=title) + run_thread(worker, thread_name) + self.theme_screenshot_threads.append(thread_name) self.application.process_events() def set_defaults(self): @@ -353,12 +348,14 @@ class FirstTimeForm(QtWidgets.QWizard, UiFirstTimeWizard, RegistryProperties): Process the triggering of the cancel button. """ self.was_cancelled = True - if self.theme_screenshot_workers: - for worker in self.theme_screenshot_workers: - worker.set_download_canceled(True) + if self.theme_screenshot_threads: + for thread_name in self.theme_screenshot_threads: + worker = get_thread_worker(thread_name) + if worker: + worker.set_download_canceled(True) # Was the thread created. if self.theme_screenshot_threads: - while any([thread.isRunning() for thread in self.theme_screenshot_threads]): + while any([not is_thread_finished(thread_name) for thread_name in self.theme_screenshot_threads]): time.sleep(0.1) self.application.set_normal_cursor() @@ -401,7 +398,7 @@ class FirstTimeForm(QtWidgets.QWizard, UiFirstTimeWizard, RegistryProperties): screenshot = self.config.get('theme_{theme}'.format(theme=theme), 'screenshot') item = self.themes_list_widget.item(index) if item: - item.setIcon(build_icon(os.path.join(gettempdir(), 'openlp', screenshot))) + item.setIcon(build_icon(Path(gettempdir(), 'openlp', screenshot))) def _download_progress(self, count, block_size): """ @@ -550,9 +547,9 @@ class FirstTimeForm(QtWidgets.QWizard, UiFirstTimeWizard, RegistryProperties): Download selected songs, bibles and themes. Returns False on download error """ # Build directories for downloads - songs_destination = os.path.join(gettempdir(), 'openlp') - bibles_destination = str(AppLocation.get_section_data_path('bibles')) - themes_destination = str(AppLocation.get_section_data_path('themes')) + songs_destination_path = Path(gettempdir(), 'openlp') + bibles_destination_path = AppLocation.get_section_data_path('bibles') + themes_destination_path = AppLocation.get_section_data_path('themes') missed_files = [] # Download songs for i in range(self.songs_list_widget.count()): @@ -561,9 +558,9 @@ class FirstTimeForm(QtWidgets.QWizard, UiFirstTimeWizard, RegistryProperties): filename, sha256 = item.data(QtCore.Qt.UserRole) self._increment_progress_bar(self.downloading.format(name=filename), 0) self.previous_size = 0 - destination = Path(songs_destination, str(filename)) - if not url_get_file(self, '{path}{name}'.format(path=self.songs_url, name=filename), - destination, sha256): + destination = songs_destination_path / str(filename) + if not download_file(self, '{path}{name}'.format(path=self.songs_url, name=filename), + destination, sha256): missed_files.append('Song: {name}'.format(name=filename)) # Download Bibles bibles_iterator = QtWidgets.QTreeWidgetItemIterator(self.bibles_tree_widget) @@ -573,9 +570,8 @@ class FirstTimeForm(QtWidgets.QWizard, UiFirstTimeWizard, RegistryProperties): bible, sha256 = item.data(0, QtCore.Qt.UserRole) self._increment_progress_bar(self.downloading.format(name=bible), 0) self.previous_size = 0 - if not url_get_file(self, '{path}{name}'.format(path=self.bibles_url, name=bible), - Path(bibles_destination, bible), - sha256): + if not download_file(self, '{path}{name}'.format(path=self.bibles_url, name=bible), + bibles_destination_path / bible, sha256): missed_files.append('Bible: {name}'.format(name=bible)) bibles_iterator += 1 # Download themes @@ -585,9 +581,8 @@ class FirstTimeForm(QtWidgets.QWizard, UiFirstTimeWizard, RegistryProperties): theme, sha256 = item.data(QtCore.Qt.UserRole) self._increment_progress_bar(self.downloading.format(name=theme), 0) self.previous_size = 0 - if not url_get_file(self, '{path}{name}'.format(path=self.themes_url, name=theme), - Path(themes_destination, theme), - sha256): + if not download_file(self, '{path}{name}'.format(path=self.themes_url, name=theme), + themes_destination_path / theme, sha256): missed_files.append('Theme: {name}'.format(name=theme)) if missed_files: file_list = '' diff --git a/openlp/core/ui/firsttimelanguagedialog.py b/openlp/core/ui/firsttimelanguagedialog.py index abe12aa63..21aeac5e5 100644 --- a/openlp/core/ui/firsttimelanguagedialog.py +++ b/openlp/core/ui/firsttimelanguagedialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/firsttimelanguageform.py b/openlp/core/ui/firsttimelanguageform.py index 1131883bf..aae5ee739 100644 --- a/openlp/core/ui/firsttimelanguageform.py +++ b/openlp/core/ui/firsttimelanguageform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/firsttimewizard.py b/openlp/core/ui/firsttimewizard.py index 5212479ef..9f9261015 100644 --- a/openlp/core/ui/firsttimewizard.py +++ b/openlp/core/ui/firsttimewizard.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/formattingtagcontroller.py b/openlp/core/ui/formattingtagcontroller.py index 4b9d75fee..198a9f975 100644 --- a/openlp/core/ui/formattingtagcontroller.py +++ b/openlp/core/ui/formattingtagcontroller.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/formattingtagdialog.py b/openlp/core/ui/formattingtagdialog.py index fa36fa818..f9a12489c 100644 --- a/openlp/core/ui/formattingtagdialog.py +++ b/openlp/core/ui/formattingtagdialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/formattingtagform.py b/openlp/core/ui/formattingtagform.py index ab0bfc79f..e4045e59e 100644 --- a/openlp/core/ui/formattingtagform.py +++ b/openlp/core/ui/formattingtagform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -28,8 +28,8 @@ from PyQt5 import QtCore, QtWidgets from openlp.core.common.i18n import translate from openlp.core.lib import FormattingTags -from openlp.core.ui.formattingtagdialog import Ui_FormattingTagDialog from openlp.core.ui.formattingtagcontroller import FormattingTagController +from openlp.core.ui.formattingtagdialog import Ui_FormattingTagDialog class EditColumn(object): diff --git a/openlp/core/ui/generaltab.py b/openlp/core/ui/generaltab.py index a908ac91d..7197aee7b 100644 --- a/openlp/core/ui/generaltab.py +++ b/openlp/core/ui/generaltab.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 80cccdb4c..181d241ff 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index ee07cbd69..43357c837 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -23,10 +23,7 @@ This is the main window, where all the action happens. """ import logging -import os -import shutil import sys -import time from datetime import datetime from distutils import dir_util from distutils.errors import DistutilsFileError @@ -40,25 +37,24 @@ from openlp.core.common import is_win, is_macosx, add_actions from openlp.core.common.actions import ActionList, CategoryOrder from openlp.core.common.applocation import AppLocation from openlp.core.common.i18n import LanguageManager, UiStrings, translate -from openlp.core.common.path import Path, copyfile, create_paths from openlp.core.common.mixins import RegistryProperties +from openlp.core.common.path import Path, copyfile, create_paths from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings -from openlp.core.display.screens import ScreenList from openlp.core.display.renderer import Renderer +from openlp.core.display.screens import ScreenList from openlp.core.lib import PluginManager, ImageManager, PluginStatus, build_icon from openlp.core.lib.ui import create_action from openlp.core.projectors.manager import ProjectorManager from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, ThemeManager, LiveController, PluginForm, \ ShortcutListForm, FormattingTagForm, PreviewController from openlp.core.ui.firsttimeform import FirstTimeForm -from openlp.core.widgets.dialogs import FileDialog -from openlp.core.widgets.docks import OpenLPDockWidget, MediaDockManager from openlp.core.ui.media import MediaController from openlp.core.ui.printserviceform import PrintServiceForm from openlp.core.ui.style import PROGRESSBAR_STYLE, get_library_stylesheet from openlp.core.version import get_version - +from openlp.core.widgets.dialogs import FileDialog +from openlp.core.widgets.docks import OpenLPDockWidget, MediaDockManager log = logging.getLogger(__name__) @@ -481,8 +477,6 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, RegistryProperties): """ super(MainWindow, self).__init__() Registry().register('main_window', self) - self.version_thread = None - self.version_worker = None self.clipboard = self.application.clipboard() self.arguments = ''.join(self.application.args) # Set up settings sections for the main application (not for use by plugins). @@ -504,8 +498,8 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, RegistryProperties): Settings().set_up_default_values() self.about_form = AboutForm(self) MediaController() - websockets.WebSocketServer() - server.HttpServer() + self.ws_server = websockets.WebSocketServer() + self.http_server = server.HttpServer(self) SettingsForm(self) self.formatting_tag_form = FormattingTagForm(self) self.shortcut_form = ShortcutListForm(self) @@ -552,6 +546,41 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, RegistryProperties): # Reset the cursor self.application.set_normal_cursor() + def _wait_for_threads(self): + """ + Wait for the threads + """ + # Sometimes the threads haven't finished, let's wait for them + wait_dialog = QtWidgets.QProgressDialog('Waiting for some things to finish...', '', 0, 0, self) + wait_dialog.setWindowModality(QtCore.Qt.WindowModal) + wait_dialog.setAutoClose(False) + wait_dialog.setCancelButton(None) + wait_dialog.show() + for thread_name in self.application.worker_threads.keys(): + log.debug('Waiting for thread %s', thread_name) + self.application.processEvents() + thread = self.application.worker_threads[thread_name]['thread'] + worker = self.application.worker_threads[thread_name]['worker'] + try: + if worker and hasattr(worker, 'stop'): + # If the worker has a stop method, run it + worker.stop() + if thread and thread.isRunning(): + # If the thread is running, let's wait 5 seconds for it + retry = 0 + while thread.isRunning() and retry < 50: + # Make the GUI responsive while we wait + self.application.processEvents() + thread.wait(100) + retry += 1 + if thread.isRunning(): + # If the thread is still running after 5 seconds, kill it + thread.terminate() + except RuntimeError: + # Ignore the RuntimeError that is thrown when Qt has already deleted the C++ thread object + pass + wait_dialog.close() + def bootstrap_post_set_up(self): """ process the bootstrap post setup request @@ -698,7 +727,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, RegistryProperties): # Update the theme widget self.theme_manager_contents.load_themes() # Check if any Bibles downloaded. If there are, they will be processed. - Registry().execute('bibles_load_list', True) + Registry().execute('bibles_load_list') self.application.set_normal_cursor() def is_display_blank(self): @@ -1003,39 +1032,14 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, RegistryProperties): if not self.application.is_event_loop_active: event.ignore() return - # Sometimes the version thread hasn't finished, let's wait for it - try: - if self.version_thread and self.version_thread.isRunning(): - wait_dialog = QtWidgets.QProgressDialog('Waiting for some things to finish...', '', 0, 0, self) - wait_dialog.setWindowModality(QtCore.Qt.WindowModal) - wait_dialog.setAutoClose(False) - wait_dialog.setCancelButton(None) - wait_dialog.show() - retry = 0 - while self.version_thread.isRunning() and retry < 50: - self.application.processEvents() - self.version_thread.wait(100) - retry += 1 - if self.version_thread.isRunning(): - self.version_thread.terminate() - wait_dialog.close() - except RuntimeError: - # Ignore the RuntimeError that is thrown when Qt has already deleted the C++ thread object - pass - # If we just did a settings import, close without saving changes. - if self.settings_imported: - self.clean_up(False) - event.accept() if self.service_manager_contents.is_modified(): ret = self.service_manager_contents.save_modified_service() if ret == QtWidgets.QMessageBox.Save: if self.service_manager_contents.decide_save_method(): - self.clean_up() event.accept() else: event.ignore() elif ret == QtWidgets.QMessageBox.Discard: - self.clean_up() event.accept() else: event.ignore() @@ -1051,13 +1055,16 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, RegistryProperties): close_button.setText(translate('OpenLP.MainWindow', '&Exit OpenLP')) msg_box.setDefaultButton(QtWidgets.QMessageBox.Close) if msg_box.exec() == QtWidgets.QMessageBox.Close: - self.clean_up() event.accept() else: event.ignore() else: - self.clean_up() event.accept() + if event.isAccepted(): + # Wait for all the threads to complete + self._wait_for_threads() + # If we just did a settings import, close without saving changes. + self.clean_up(save_settings=not self.settings_imported) def clean_up(self, save_settings=True): """ @@ -1065,9 +1072,6 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, RegistryProperties): :param save_settings: Switch to prevent saving settings. Defaults to **True**. """ - self.image_manager.stop_manager = True - while self.image_manager.image_thread.isRunning(): - time.sleep(0.1) if save_settings: if Settings().value('advanced/save current plugin'): Settings().setValue('advanced/current media plugin', self.media_tool_box.currentIndex()) diff --git a/openlp/core/ui/media/__init__.py b/openlp/core/ui/media/__init__.py index 145f5e8bd..da80aee5f 100644 --- a/openlp/core/ui/media/__init__.py +++ b/openlp/core/ui/media/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/media/endpoint.py b/openlp/core/ui/media/endpoint.py index af7623003..dce41de8d 100644 --- a/openlp/core/ui/media/endpoint.py +++ b/openlp/core/ui/media/endpoint.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -24,8 +24,8 @@ The :mod:`~openlp.core.api.endpoint` module contains various API endpoints """ import logging -from openlp.core.api.http.endpoint import Endpoint from openlp.core.api.http import requires_auth +from openlp.core.api.http.endpoint import Endpoint from openlp.core.common.registry import Registry log = logging.getLogger(__name__) diff --git a/openlp/core/ui/media/mediacontroller.py b/openlp/core/ui/media/mediacontroller.py index 10c384b0c..ed593dd88 100644 --- a/openlp/core/ui/media/mediacontroller.py +++ b/openlp/core/ui/media/mediacontroller.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -23,9 +23,10 @@ The :mod:`~openlp.core.ui.media.mediacontroller` module contains a base class for media components and other widgets related to playing media, such as sliders. """ +import datetime import logging import os -import datetime + from PyQt5 import QtCore, QtWidgets from openlp.core.api.http import register_endpoint @@ -37,14 +38,13 @@ from openlp.core.common.settings import Settings from openlp.core.lib import ItemCapabilities from openlp.core.lib.ui import critical_error_message_box from openlp.core.ui import DisplayControllerType -from openlp.core.ui.media.endpoint import media_endpoint -from openlp.core.ui.media.vendor.mediainfoWrapper import MediaInfoWrapper -from openlp.core.ui.media.mediaplayer import MediaPlayer -from openlp.core.ui.media import MediaState, MediaInfo, MediaType, get_media_players, set_media_players,\ +from openlp.core.ui.media import MediaState, MediaInfo, MediaType, get_media_players, set_media_players, \ parse_optical_path +from openlp.core.ui.media.endpoint import media_endpoint +from openlp.core.ui.media.mediaplayer import MediaPlayer +from openlp.core.ui.media.vendor.mediainfoWrapper import MediaInfoWrapper from openlp.core.widgets.toolbar import OpenLPToolbar - log = logging.getLogger(__name__) TICK_TIME = 200 @@ -181,7 +181,8 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): """ log.debug('_check_available_media_players') controller_dir = os.path.join('core', 'ui', 'media') - glob_pattern = os.path.join(controller_dir, '*player.py') + # Find all files that do not begin with '.' (lp:#1738047) and end with player.py + glob_pattern = os.path.join(controller_dir, '[!.]*player.py') extension_loader(glob_pattern, ['mediaplayer.py']) player_classes = MediaPlayer.__subclasses__() for player_class in player_classes: diff --git a/openlp/core/ui/media/mediaplayer.py b/openlp/core/ui/media/mediaplayer.py index 77d089c89..a8273cdb5 100644 --- a/openlp/core/ui/media/mediaplayer.py +++ b/openlp/core/ui/media/mediaplayer.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/media/playertab.py b/openlp/core/ui/media/playertab.py index 28d7798ee..d6b3aee5a 100644 --- a/openlp/core/ui/media/playertab.py +++ b/openlp/core/ui/media/playertab.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/media/systemplayer.py b/openlp/core/ui/media/systemplayer.py index a6423db02..063c9acea 100644 --- a/openlp/core/ui/media/systemplayer.py +++ b/openlp/core/ui/media/systemplayer.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -31,7 +31,7 @@ from PyQt5 import QtCore, QtMultimedia, QtMultimediaWidgets from openlp.core.common.i18n import translate from openlp.core.ui.media import MediaState from openlp.core.ui.media.mediaplayer import MediaPlayer - +from openlp.core.threading import ThreadWorker, run_thread, is_thread_finished log = logging.getLogger(__name__) @@ -294,39 +294,38 @@ class SystemPlayer(MediaPlayer): :param path: Path to file to be checked :return: True if file can be played otherwise False """ - thread = QtCore.QThread() check_media_worker = CheckMediaWorker(path) check_media_worker.setVolume(0) - check_media_worker.moveToThread(thread) - check_media_worker.finished.connect(thread.quit) - thread.started.connect(check_media_worker.play) - thread.start() - while thread.isRunning(): + run_thread(check_media_worker, 'check_media') + while not is_thread_finished('check_media'): self.application.processEvents() return check_media_worker.result -class CheckMediaWorker(QtMultimedia.QMediaPlayer): +class CheckMediaWorker(QtMultimedia.QMediaPlayer, ThreadWorker): """ Class used to check if a media file is playable """ - finished = QtCore.pyqtSignal() - def __init__(self, path): super(CheckMediaWorker, self).__init__(None, QtMultimedia.QMediaPlayer.VideoSurface) - self.result = None + self.path = path + def start(self): + """ + Start the thread worker + """ + self.result = None self.error.connect(functools.partial(self.signals, 'error')) self.mediaStatusChanged.connect(functools.partial(self.signals, 'media')) - - self.setMedia(QtMultimedia.QMediaContent(QtCore.QUrl.fromLocalFile(path))) + self.setMedia(QtMultimedia.QMediaContent(QtCore.QUrl.fromLocalFile(self.path))) + self.play() def signals(self, origin, status): if origin == 'media' and status == self.BufferedMedia: self.result = True self.stop() - self.finished.emit() + self.quit.emit() elif origin == 'error' and status != self.NoError: self.result = False self.stop() - self.finished.emit() + self.quit.emit() diff --git a/openlp/core/ui/media/vendor/__init__.py b/openlp/core/ui/media/vendor/__init__.py index 2b8cd2dd2..7d9d02f89 100644 --- a/openlp/core/ui/media/vendor/__init__.py +++ b/openlp/core/ui/media/vendor/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/media/vendor/mediainfoWrapper.py b/openlp/core/ui/media/vendor/mediainfoWrapper.py index 97d936d6b..d28fe1395 100644 --- a/openlp/core/ui/media/vendor/mediainfoWrapper.py +++ b/openlp/core/ui/media/vendor/mediainfoWrapper.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/media/vendor/vlc.py b/openlp/core/ui/media/vendor/vlc.py index 7383621b0..b7c7cfdce 100644 --- a/openlp/core/ui/media/vendor/vlc.py +++ b/openlp/core/ui/media/vendor/vlc.py @@ -40,11 +40,10 @@ C{get_instance} method of L{MediaPlayer} and L{MediaListPlayer}. """ import ctypes -from ctypes.util import find_library +import functools import os import sys -import functools - +from ctypes.util import find_library # Used by EventManager in override.py from inspect import getargspec diff --git a/openlp/core/ui/media/vlcplayer.py b/openlp/core/ui/media/vlcplayer.py index 840471cfe..7f39a70df 100644 --- a/openlp/core/ui/media/vlcplayer.py +++ b/openlp/core/ui/media/vlcplayer.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,13 +22,14 @@ """ The :mod:`~openlp.core.ui.media.vlcplayer` module contains our VLC component wrapper """ -from datetime import datetime -from distutils.version import LooseVersion +import ctypes import logging import os -import threading import sys -import ctypes +import threading +from datetime import datetime +from distutils.version import LooseVersion + from PyQt5 import QtWidgets from openlp.core.common import is_win, is_macosx, is_linux diff --git a/openlp/core/ui/media/webkitplayer.py b/openlp/core/ui/media/webkitplayer.py index e9142463e..5845d655e 100644 --- a/openlp/core/ui/media/webkitplayer.py +++ b/openlp/core/ui/media/webkitplayer.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -26,8 +26,8 @@ import logging from PyQt5 import QtGui, QtWebKitWidgets -from openlp.core.common.settings import Settings from openlp.core.common.i18n import translate +from openlp.core.common.settings import Settings from openlp.core.ui.media import MediaState from openlp.core.ui.media.mediaplayer import MediaPlayer diff --git a/openlp/core/ui/plugindialog.py b/openlp/core/ui/plugindialog.py index 76087a33a..8aabea21d 100644 --- a/openlp/core/ui/plugindialog.py +++ b/openlp/core/ui/plugindialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/pluginform.py b/openlp/core/ui/pluginform.py index 43fa5e68d..6eb296b70 100644 --- a/openlp/core/ui/pluginform.py +++ b/openlp/core/ui/pluginform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/printservicedialog.py b/openlp/core/ui/printservicedialog.py index ee3b07080..769f9f699 100644 --- a/openlp/core/ui/printservicedialog.py +++ b/openlp/core/ui/printservicedialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/printserviceform.py b/openlp/core/ui/printserviceform.py index 07ab24496..ba1b318d7 100644 --- a/openlp/core/ui/printserviceform.py +++ b/openlp/core/ui/printserviceform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -24,8 +24,8 @@ The actual print service dialog """ import datetime import html -import lxml.html +import lxml.html from PyQt5 import QtCore, QtGui, QtWidgets, QtPrintSupport from openlp.core.common.applocation import AppLocation diff --git a/openlp/core/ui/serviceitemeditdialog.py b/openlp/core/ui/serviceitemeditdialog.py index 80be015f8..5206ff136 100644 --- a/openlp/core/ui/serviceitemeditdialog.py +++ b/openlp/core/ui/serviceitemeditdialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/serviceitemeditform.py b/openlp/core/ui/serviceitemeditform.py index 0a4b7cab6..dce243f7d 100644 --- a/openlp/core/ui/serviceitemeditform.py +++ b/openlp/core/ui/serviceitemeditform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 29718e09a..5d355f88a 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -370,7 +370,7 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi :rtype: None """ self._service_path = file_path - self.main_window.set_service_modified(self.is_modified(), file_path.name) + self.set_modified(self.is_modified()) Settings().setValue('servicemanager/last file', file_path) if file_path and file_path.suffix == '.oszl': self._save_lite = True diff --git a/openlp/core/ui/servicenoteform.py b/openlp/core/ui/servicenoteform.py index 179248570..b4e61ce69 100644 --- a/openlp/core/ui/servicenoteform.py +++ b/openlp/core/ui/servicenoteform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/settingsdialog.py b/openlp/core/ui/settingsdialog.py index 0e591e6ad..a6b91368c 100644 --- a/openlp/core/ui/settingsdialog.py +++ b/openlp/core/ui/settingsdialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/settingsform.py b/openlp/core/ui/settingsform.py index 4d7c4ff6c..e3190eab6 100644 --- a/openlp/core/ui/settingsform.py +++ b/openlp/core/ui/settingsform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/shortcutlistdialog.py b/openlp/core/ui/shortcutlistdialog.py index 22da4109f..522a30022 100644 --- a/openlp/core/ui/shortcutlistdialog.py +++ b/openlp/core/ui/shortcutlistdialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/shortcutlistform.py b/openlp/core/ui/shortcutlistform.py index 92a0e789f..779b86eea 100644 --- a/openlp/core/ui/shortcutlistform.py +++ b/openlp/core/ui/shortcutlistform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 16c710754..66b5ac51e 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -42,7 +42,6 @@ from openlp.core.ui import HideMode, MainDisplay, Display, DisplayControllerType from openlp.core.widgets.toolbar import OpenLPToolbar from openlp.core.widgets.views import ListPreviewWidget - # Threshold which has to be trespassed to toggle. HIDE_MENU_THRESHOLD = 27 AUDIO_TIME_LABEL_STYLESHEET = 'background-color: palette(background); ' \ diff --git a/openlp/core/ui/splashscreen.py b/openlp/core/ui/splashscreen.py index dd9764a2e..6e6ca4b97 100644 --- a/openlp/core/ui/splashscreen.py +++ b/openlp/core/ui/splashscreen.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/starttimedialog.py b/openlp/core/ui/starttimedialog.py index fd5163593..05118bce6 100644 --- a/openlp/core/ui/starttimedialog.py +++ b/openlp/core/ui/starttimedialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/starttimeform.py b/openlp/core/ui/starttimeform.py index 00d0bff40..9d8bee4cf 100644 --- a/openlp/core/ui/starttimeform.py +++ b/openlp/core/ui/starttimeform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/style.py b/openlp/core/ui/style.py index 764a3bd26..23f22c540 100644 --- a/openlp/core/ui/style.py +++ b/openlp/core/ui/style.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -24,7 +24,7 @@ The :mod:`~openlp.core.ui.dark` module looks for and loads a dark theme """ from PyQt5 import QtGui -from openlp.core.common import is_macosx, is_win +from openlp.core.common import is_win from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py index f8449986a..29b04477c 100644 --- a/openlp/core/ui/themeform.py +++ b/openlp/core/ui/themeform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/themelayoutdialog.py b/openlp/core/ui/themelayoutdialog.py index d9ed9638d..159ac7c9e 100644 --- a/openlp/core/ui/themelayoutdialog.py +++ b/openlp/core/ui/themelayoutdialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/themelayoutform.py b/openlp/core/ui/themelayoutform.py index 2b4b114f6..5c676d2d5 100644 --- a/openlp/core/ui/themelayoutform.py +++ b/openlp/core/ui/themelayoutform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index fae75f81d..4a544b11d 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/themestab.py b/openlp/core/ui/themestab.py index d578e0082..077f59d83 100644 --- a/openlp/core/ui/themestab.py +++ b/openlp/core/ui/themestab.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/ui/themewizard.py b/openlp/core/ui/themewizard.py index d7bc5f822..9e75c1e82 100644 --- a/openlp/core/ui/themewizard.py +++ b/openlp/core/ui/themewizard.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/version.py b/openlp/core/version.py index 6ba1b9ecc..ff0fe65b3 100644 --- a/openlp/core/version.py +++ b/openlp/core/version.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -35,7 +35,7 @@ from PyQt5 import QtCore from openlp.core.common.applocation import AppLocation from openlp.core.common.settings import Settings -from openlp.core.threading import run_thread +from openlp.core.threading import ThreadWorker, run_thread log = logging.getLogger(__name__) @@ -44,14 +44,13 @@ CONNECTION_TIMEOUT = 30 CONNECTION_RETRIES = 2 -class VersionWorker(QtCore.QObject): +class VersionWorker(ThreadWorker): """ A worker class to fetch the version of OpenLP from the website. This is run from within a thread so that it doesn't affect the loading time of OpenLP. """ new_version = QtCore.pyqtSignal(dict) no_internet = QtCore.pyqtSignal() - quit = QtCore.pyqtSignal() def __init__(self, last_check_date, current_version): """ @@ -75,13 +74,11 @@ class VersionWorker(QtCore.QObject): * If a version number's minor version is an even number, it is a stable release. """ log.debug('VersionWorker - Start') - # I'm not entirely sure why this was here, I'm commenting it out until I hit the same scenario - time.sleep(1) - download_url = 'http://www.openlp.org/files/version.txt' + download_url = 'https://www.openlp.org/files/version.txt' if self.current_version['build']: - download_url = 'http://www.openlp.org/files/nightly_version.txt' + download_url = 'https://www.openlp.org/files/nightly_version.txt' elif int(self.current_version['version'].split('.')[1]) % 2 != 0: - download_url = 'http://www.openlp.org/files/dev_version.txt' + download_url = 'https://www.openlp.org/files/dev_version.txt' headers = { 'User-Agent': 'OpenLP/{version} {system}/{release}; '.format(version=self.current_version['full'], system=platform.system(), @@ -92,7 +89,7 @@ class VersionWorker(QtCore.QObject): while retries < 3: try: response = requests.get(download_url, headers=headers) - remote_version = response.text + remote_version = response.text.strip() log.debug('New version found: %s', remote_version) break except OSError: @@ -112,22 +109,22 @@ def update_check_date(): Settings().setValue('core/last version test', date.today().strftime('%Y-%m-%d')) -def check_for_update(parent): +def check_for_update(main_window): """ Run a thread to download and check the version of OpenLP - :param MainWindow parent: The parent object for the thread. Usually the OpenLP main window. + :param MainWindow main_window: The OpenLP main window. """ last_check_date = Settings().value('core/last version test') if date.today().strftime('%Y-%m-%d') <= last_check_date: log.debug('Version check skipped, last checked today') return worker = VersionWorker(last_check_date, get_version()) - worker.new_version.connect(parent.on_new_version) + worker.new_version.connect(main_window.on_new_version) worker.quit.connect(update_check_date) # TODO: Use this to figure out if there's an Internet connection? # worker.no_internet.connect(parent.on_no_internet) - run_thread(parent, worker, 'version') + run_thread(worker, 'version') def get_version(): diff --git a/openlp/core/widgets/__init__.py b/openlp/core/widgets/__init__.py index ea62548f4..711ded4ae 100644 --- a/openlp/core/widgets/__init__.py +++ b/openlp/core/widgets/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/widgets/buttons.py b/openlp/core/widgets/buttons.py index 6eef707b2..d69c365cd 100644 --- a/openlp/core/widgets/buttons.py +++ b/openlp/core/widgets/buttons.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/widgets/dialogs.py b/openlp/core/widgets/dialogs.py index f1c2bcc24..ee46b5992 100755 --- a/openlp/core/widgets/dialogs.py +++ b/openlp/core/widgets/dialogs.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,7 +22,7 @@ """ Patch the QFileDialog so it accepts and returns Path objects""" from PyQt5 import QtWidgets -from openlp.core.common.path import Path, path_to_str, replace_params, str_to_path +from openlp.core.common.path import path_to_str, replace_params, str_to_path class FileDialog(QtWidgets.QFileDialog): diff --git a/openlp/core/widgets/docks.py b/openlp/core/widgets/docks.py index a1b4e9789..6fac23705 100644 --- a/openlp/core/widgets/docks.py +++ b/openlp/core/widgets/docks.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/widgets/edits.py b/openlp/core/widgets/edits.py index 89310a713..48fc5f853 100644 --- a/openlp/core/widgets/edits.py +++ b/openlp/core/widgets/edits.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/widgets/enums.py b/openlp/core/widgets/enums.py index f79dd775c..630505afa 100644 --- a/openlp/core/widgets/enums.py +++ b/openlp/core/widgets/enums.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/widgets/toolbar.py b/openlp/core/widgets/toolbar.py index 8c76ce50e..758a62605 100644 --- a/openlp/core/widgets/toolbar.py +++ b/openlp/core/widgets/toolbar.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/core/widgets/views.py b/openlp/core/widgets/views.py index 219dd145f..5adec3e27 100644 --- a/openlp/core/widgets/views.py +++ b/openlp/core/widgets/views.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -23,18 +23,36 @@ The :mod:`listpreviewwidget` is a widget that lists the slides in the slide controller. It is based on a QTableWidget but represents its contents in list form. """ -import os - from PyQt5 import QtCore, QtGui, QtWidgets from openlp.core.common import is_win from openlp.core.common.i18n import UiStrings from openlp.core.common.mixins import RegistryProperties +from openlp.core.common.path import Path from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings from openlp.core.lib import ImageSource, ItemCapabilities, ServiceItem +def handle_mime_data_urls(mime_data): + """ + Process the data from a drag and drop operation. + + :param PyQt5.QtCore.QMimeData mime_data: The mime data from the drag and drop opperation. + :return: A list of file paths that were dropped + :rtype: list[openlp.core.common.path.Path] + """ + file_paths = [] + for url in mime_data.urls(): + local_path = Path(url.toLocalFile()) + if local_path.is_file(): + file_paths.append(local_path) + elif local_path.is_dir(): + for path in local_path.iterdir(): + file_paths.append(path) + return file_paths + + class ListPreviewWidget(QtWidgets.QTableWidget, RegistryProperties): """ A special type of QTableWidget which lists the slides in the slide controller @@ -326,17 +344,9 @@ class ListWidgetWithDnD(QtWidgets.QListWidget): if event.mimeData().hasUrls(): event.setDropAction(QtCore.Qt.CopyAction) event.accept() - files = [] - for url in event.mimeData().urls(): - local_file = os.path.normpath(url.toLocalFile()) - if os.path.isfile(local_file): - files.append(local_file) - elif os.path.isdir(local_file): - listing = os.listdir(local_file) - for file in listing: - files.append(os.path.join(local_file, file)) + file_paths = handle_mime_data_urls(event.mimeData()) Registry().execute('{mime_data}_dnd'.format(mime_data=self.mime_data_text), - {'files': files}) + {'file_paths': file_paths}) else: event.ignore() @@ -454,16 +464,9 @@ class TreeWidgetWithDnD(QtWidgets.QTreeWidget): if event.mimeData().hasUrls(): event.setDropAction(QtCore.Qt.CopyAction) event.accept() - files = [] - for url in event.mimeData().urls(): - local_file = url.toLocalFile() - if os.path.isfile(local_file): - files.append(local_file) - elif os.path.isdir(local_file): - listing = os.listdir(local_file) - for file_name in listing: - files.append(os.path.join(local_file, file_name)) - Registry().execute('%s_dnd' % self.mime_data_text, {'files': files, 'target': self.itemAt(event.pos())}) + file_paths = handle_mime_data_urls(event.mimeData()) + Registry().execute('%s_dnd' % self.mime_data_text, + {'file_paths': file_paths, 'target': self.itemAt(event.pos())}) elif self.allow_internal_dnd: event.setDropAction(QtCore.Qt.CopyAction) event.accept() diff --git a/openlp/core/widgets/wizard.py b/openlp/core/widgets/wizard.py index dc8288bc9..32db6c1ff 100644 --- a/openlp/core/widgets/wizard.py +++ b/openlp/core/widgets/wizard.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/__init__.py b/openlp/plugins/__init__.py index a4aa03078..3b728280b 100644 --- a/openlp/plugins/__init__.py +++ b/openlp/plugins/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/alerts/__init__.py b/openlp/plugins/alerts/__init__.py index 4b28c04f7..a40745253 100644 --- a/openlp/plugins/alerts/__init__.py +++ b/openlp/plugins/alerts/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py index 992c5c360..429e8dc37 100644 --- a/openlp/plugins/alerts/alertsplugin.py +++ b/openlp/plugins/alerts/alertsplugin.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/alerts/endpoint.py b/openlp/plugins/alerts/endpoint.py index 19449b863..e4b9a64bd 100644 --- a/openlp/plugins/alerts/endpoint.py +++ b/openlp/plugins/alerts/endpoint.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -19,17 +19,16 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -import logging import json +import logging import urllib from urllib.parse import urlparse -from openlp.core.api.http.endpoint import Endpoint from openlp.core.api.http import requires_auth +from openlp.core.api.http.endpoint import Endpoint from openlp.core.common.registry import Registry from openlp.core.lib import PluginStatus - log = logging.getLogger(__name__) alerts_endpoint = Endpoint('alert') diff --git a/openlp/plugins/alerts/forms/__init__.py b/openlp/plugins/alerts/forms/__init__.py index e390edf32..ff297ae8f 100644 --- a/openlp/plugins/alerts/forms/__init__.py +++ b/openlp/plugins/alerts/forms/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/alerts/forms/alertdialog.py b/openlp/plugins/alerts/forms/alertdialog.py index 79dff94c0..5c2ddb920 100644 --- a/openlp/plugins/alerts/forms/alertdialog.py +++ b/openlp/plugins/alerts/forms/alertdialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/alerts/forms/alertform.py b/openlp/plugins/alerts/forms/alertform.py index c7f9487c4..481853fa9 100644 --- a/openlp/plugins/alerts/forms/alertform.py +++ b/openlp/plugins/alerts/forms/alertform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -25,7 +25,6 @@ from PyQt5 import QtCore, QtWidgets from openlp.core.common.i18n import translate from openlp.core.common.registry import Registry from openlp.plugins.alerts.lib.db import AlertItem - from .alertdialog import Ui_AlertDialog diff --git a/openlp/plugins/alerts/lib/__init__.py b/openlp/plugins/alerts/lib/__init__.py index 6add50bd2..4aae58891 100644 --- a/openlp/plugins/alerts/lib/__init__.py +++ b/openlp/plugins/alerts/lib/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/alerts/lib/alertsmanager.py b/openlp/plugins/alerts/lib/alertsmanager.py index e5ae93093..4d843c5c7 100644 --- a/openlp/plugins/alerts/lib/alertsmanager.py +++ b/openlp/plugins/alerts/lib/alertsmanager.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/alerts/lib/alertstab.py b/openlp/plugins/alerts/lib/alertstab.py index 51d92cf06..b93f74db4 100644 --- a/openlp/plugins/alerts/lib/alertstab.py +++ b/openlp/plugins/alerts/lib/alertstab.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/alerts/lib/db.py b/openlp/plugins/alerts/lib/db.py index ab33f43ee..f0a0afb97 100644 --- a/openlp/plugins/alerts/lib/db.py +++ b/openlp/plugins/alerts/lib/db.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/bibles/__init__.py b/openlp/plugins/bibles/__init__.py index 64fae038b..86b09cd15 100644 --- a/openlp/plugins/bibles/__init__.py +++ b/openlp/plugins/bibles/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/bibles/bibleplugin.py b/openlp/plugins/bibles/bibleplugin.py index 7d5baf859..aecdadfdb 100644 --- a/openlp/plugins/bibles/bibleplugin.py +++ b/openlp/plugins/bibles/bibleplugin.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -23,11 +23,11 @@ import logging from openlp.core.api.http import register_endpoint -from openlp.core.common.i18n import UiStrings, translate from openlp.core.common.actions import ActionList +from openlp.core.common.i18n import UiStrings, translate from openlp.core.lib import Plugin, StringContent, build_icon -from openlp.plugins.bibles.endpoint import api_bibles_endpoint, bibles_endpoint from openlp.core.lib.ui import create_action +from openlp.plugins.bibles.endpoint import api_bibles_endpoint, bibles_endpoint from openlp.plugins.bibles.lib import BibleManager, BiblesTab, BibleMediaItem, LayoutStyle, DisplayStyle, \ LanguageSelection from openlp.plugins.bibles.lib.mediaitem import BibleSearch diff --git a/openlp/plugins/bibles/endpoint.py b/openlp/plugins/bibles/endpoint.py index 4d34eb966..b3177b146 100644 --- a/openlp/plugins/bibles/endpoint.py +++ b/openlp/plugins/bibles/endpoint.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -21,11 +21,10 @@ ############################################################################### import logging -from openlp.core.api.http.endpoint import Endpoint -from openlp.core.api.http.errors import NotFound from openlp.core.api.endpoint.pluginhelpers import search, live, service from openlp.core.api.http import requires_auth - +from openlp.core.api.http.endpoint import Endpoint +from openlp.core.api.http.errors import NotFound log = logging.getLogger(__name__) diff --git a/openlp/plugins/bibles/forms/__init__.py b/openlp/plugins/bibles/forms/__init__.py index 1b0055d67..34cdce3cd 100644 --- a/openlp/plugins/bibles/forms/__init__.py +++ b/openlp/plugins/bibles/forms/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -24,9 +24,9 @@ The :mod:`forms` module contains all the ui functionality for the bibles plugin. """ -from .booknameform import BookNameForm -from .languageform import LanguageForm from .bibleimportform import BibleImportForm +from .booknameform import BookNameForm from .editbibleform import EditBibleForm +from .languageform import LanguageForm __all__ = ['BookNameForm', 'LanguageForm', 'BibleImportForm', 'EditBibleForm'] diff --git a/openlp/plugins/bibles/forms/bibleimportform.py b/openlp/plugins/bibles/forms/bibleimportform.py index 35dd82eeb..d32711b62 100644 --- a/openlp/plugins/bibles/forms/bibleimportform.py +++ b/openlp/plugins/bibles/forms/bibleimportform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -24,9 +24,10 @@ The bible import functions for OpenLP """ import logging import urllib.error -from lxml import etree from PyQt5 import QtWidgets +from lxml import etree + try: from pysword import modules PYSWORD_AVAILABLE = True @@ -336,6 +337,7 @@ class BibleImportForm(OpenLPWizard): self.sword_layout.addWidget(self.sword_tab_widget) self.sword_disabled_label = QtWidgets.QLabel(self.sword_widget) self.sword_disabled_label.setObjectName('SwordDisabledLabel') + self.sword_disabled_label.setWordWrap(True) self.sword_layout.addWidget(self.sword_disabled_label) self.select_stack.addWidget(self.sword_widget) self.wordproject_widget = QtWidgets.QWidget(self.select_page) diff --git a/openlp/plugins/bibles/forms/booknamedialog.py b/openlp/plugins/bibles/forms/booknamedialog.py index 07d749755..05beaff19 100644 --- a/openlp/plugins/bibles/forms/booknamedialog.py +++ b/openlp/plugins/bibles/forms/booknamedialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/bibles/forms/booknameform.py b/openlp/plugins/bibles/forms/booknameform.py index 7c8a2c3cd..b8a3aac20 100644 --- a/openlp/plugins/bibles/forms/booknameform.py +++ b/openlp/plugins/bibles/forms/booknameform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -26,8 +26,8 @@ Module implementing BookNameForm. import logging import re -from PyQt5.QtWidgets import QDialog from PyQt5 import QtCore +from PyQt5.QtWidgets import QDialog from openlp.core.common.i18n import translate from openlp.core.lib.ui import critical_error_message_box diff --git a/openlp/plugins/bibles/forms/editbibledialog.py b/openlp/plugins/bibles/forms/editbibledialog.py index 799c2af7c..f57239da6 100644 --- a/openlp/plugins/bibles/forms/editbibledialog.py +++ b/openlp/plugins/bibles/forms/editbibledialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/bibles/forms/editbibleform.py b/openlp/plugins/bibles/forms/editbibleform.py index 8899087ba..bc89827d2 100644 --- a/openlp/plugins/bibles/forms/editbibleform.py +++ b/openlp/plugins/bibles/forms/editbibleform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -28,9 +28,9 @@ from PyQt5 import QtCore, QtWidgets from openlp.core.common.i18n import UiStrings, translate from openlp.core.common.mixins import RegistryProperties from openlp.core.lib.ui import critical_error_message_box -from .editbibledialog import Ui_EditBibleDialog from openlp.plugins.bibles.lib import BibleStrings from openlp.plugins.bibles.lib.db import BiblesResourcesDB +from .editbibledialog import Ui_EditBibleDialog log = logging.getLogger(__name__) diff --git a/openlp/plugins/bibles/forms/languagedialog.py b/openlp/plugins/bibles/forms/languagedialog.py index fad18bf05..0af3a0393 100644 --- a/openlp/plugins/bibles/forms/languagedialog.py +++ b/openlp/plugins/bibles/forms/languagedialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/bibles/forms/languageform.py b/openlp/plugins/bibles/forms/languageform.py index 80ce9e989..3f9f28780 100644 --- a/openlp/plugins/bibles/forms/languageform.py +++ b/openlp/plugins/bibles/forms/languageform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -25,14 +25,13 @@ Module implementing LanguageForm. """ import logging -from PyQt5.QtWidgets import QDialog from PyQt5 import QtCore +from PyQt5.QtWidgets import QDialog from openlp.core.common.i18n import LANGUAGES, translate from openlp.core.lib.ui import critical_error_message_box from openlp.plugins.bibles.forms.languagedialog import Ui_LanguageDialog - log = logging.getLogger(__name__) diff --git a/openlp/plugins/bibles/lib/__init__.py b/openlp/plugins/bibles/lib/__init__.py index f9d93a43e..73c1ca68d 100644 --- a/openlp/plugins/bibles/lib/__init__.py +++ b/openlp/plugins/bibles/lib/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -29,7 +29,6 @@ import re from openlp.core.common.i18n import translate from openlp.core.common.settings import Settings - log = logging.getLogger(__name__) diff --git a/openlp/plugins/bibles/lib/bibleimport.py b/openlp/plugins/bibles/lib/bibleimport.py index 7efb46f5d..4804362c6 100644 --- a/openlp/plugins/bibles/lib/bibleimport.py +++ b/openlp/plugins/bibles/lib/bibleimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -20,12 +20,13 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from lxml import etree, objectify from zipfile import is_zipfile +from lxml import etree, objectify + +from openlp.core.common.i18n import get_language, translate from openlp.core.common.mixins import LogMixin, RegistryProperties from openlp.core.common.registry import Registry -from openlp.core.common.i18n import get_language, translate from openlp.core.lib import ValidationError from openlp.core.lib.ui import critical_error_message_box from openlp.plugins.bibles.lib.db import AlternativeBookNamesDB, BibleDB, BiblesResourcesDB diff --git a/openlp/plugins/bibles/lib/biblestab.py b/openlp/plugins/bibles/lib/biblestab.py index c5e67840a..c98ff2943 100644 --- a/openlp/plugins/bibles/lib/biblestab.py +++ b/openlp/plugins/bibles/lib/biblestab.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index 13aeadfae..040115d56 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -19,9 +19,9 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### + import chardet import logging -import os import re import sqlite3 import time diff --git a/openlp/plugins/bibles/lib/importers/__init__.py b/openlp/plugins/bibles/lib/importers/__init__.py index f83bbd595..ffd057b71 100644 --- a/openlp/plugins/bibles/lib/importers/__init__.py +++ b/openlp/plugins/bibles/lib/importers/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/bibles/lib/importers/csvbible.py b/openlp/plugins/bibles/lib/importers/csvbible.py index 46124fd5e..29d22ff7d 100644 --- a/openlp/plugins/bibles/lib/importers/csvbible.py +++ b/openlp/plugins/bibles/lib/importers/csvbible.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/bibles/lib/importers/http.py b/openlp/plugins/bibles/lib/importers/http.py index b88dbe7a9..4eee26256 100644 --- a/openlp/plugins/bibles/lib/importers/http.py +++ b/openlp/plugins/bibles/lib/importers/http.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -25,8 +25,8 @@ The :mod:`http` module enables OpenLP to retrieve scripture from bible websites. import logging import re import socket -import urllib.parse import urllib.error +import urllib.parse from bs4 import BeautifulSoup, NavigableString, Tag diff --git a/openlp/plugins/bibles/lib/importers/opensong.py b/openlp/plugins/bibles/lib/importers/opensong.py index 8400c9bf7..215ea76c5 100644 --- a/openlp/plugins/bibles/lib/importers/opensong.py +++ b/openlp/plugins/bibles/lib/importers/opensong.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/bibles/lib/importers/osis.py b/openlp/plugins/bibles/lib/importers/osis.py index cde57954a..b18a1bea3 100644 --- a/openlp/plugins/bibles/lib/importers/osis.py +++ b/openlp/plugins/bibles/lib/importers/osis.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/bibles/lib/importers/sword.py b/openlp/plugins/bibles/lib/importers/sword.py index dcb392754..08ffaaccc 100644 --- a/openlp/plugins/bibles/lib/importers/sword.py +++ b/openlp/plugins/bibles/lib/importers/sword.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -21,6 +21,7 @@ ############################################################################### import logging + from pysword import modules from openlp.core.common.i18n import translate @@ -28,7 +29,6 @@ from openlp.core.lib.ui import critical_error_message_box from openlp.plugins.bibles.lib.bibleimport import BibleImport from openlp.plugins.bibles.lib.db import BiblesResourcesDB - log = logging.getLogger(__name__) diff --git a/openlp/plugins/bibles/lib/importers/wordproject.py b/openlp/plugins/bibles/lib/importers/wordproject.py index 90d23a2b5..95a957c80 100644 --- a/openlp/plugins/bibles/lib/importers/wordproject.py +++ b/openlp/plugins/bibles/lib/importers/wordproject.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/bibles/lib/importers/zefania.py b/openlp/plugins/bibles/lib/importers/zefania.py index 2b5eb68b8..e8904d56c 100644 --- a/openlp/plugins/bibles/lib/importers/zefania.py +++ b/openlp/plugins/bibles/lib/importers/zefania.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -27,7 +27,6 @@ from openlp.core.lib.ui import critical_error_message_box from openlp.plugins.bibles.lib.bibleimport import BibleImport from openlp.plugins.bibles.lib.db import BiblesResourcesDB - log = logging.getLogger(__name__) # Tags we don't use and can remove the content diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index 37586b4be..1e1b4243d 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -33,8 +33,9 @@ from .importers.csvbible import CSVBible from .importers.http import HTTPBible from .importers.opensong import OpenSongBible from .importers.osis import OSISBible -from .importers.zefania import ZefaniaBible from .importers.wordproject import WordProjectBible +from .importers.zefania import ZefaniaBible + try: from .importers.sword import SwordBible except: diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index fdfc4b51d..dc5792dac 100755 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/bibles/lib/upgrade.py b/openlp/plugins/bibles/lib/upgrade.py index 24f613b2d..c53f9d324 100644 --- a/openlp/plugins/bibles/lib/upgrade.py +++ b/openlp/plugins/bibles/lib/upgrade.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/bibles/lib/versereferencelist.py b/openlp/plugins/bibles/lib/versereferencelist.py index d41eeadf1..c6a9e7ec2 100644 --- a/openlp/plugins/bibles/lib/versereferencelist.py +++ b/openlp/plugins/bibles/lib/versereferencelist.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/custom/__init__.py b/openlp/plugins/custom/__init__.py index a3cf0b4c1..b0dc776c2 100644 --- a/openlp/plugins/custom/__init__.py +++ b/openlp/plugins/custom/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/custom/customplugin.py b/openlp/plugins/custom/customplugin.py index 8cb02ab17..77022b5f1 100644 --- a/openlp/plugins/custom/customplugin.py +++ b/openlp/plugins/custom/customplugin.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/custom/endpoint.py b/openlp/plugins/custom/endpoint.py index ca5c39088..eb07683c8 100644 --- a/openlp/plugins/custom/endpoint.py +++ b/openlp/plugins/custom/endpoint.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -21,11 +21,10 @@ ############################################################################### import logging -from openlp.core.api.http.endpoint import Endpoint -from openlp.core.api.http.errors import NotFound from openlp.core.api.endpoint.pluginhelpers import search, live, service from openlp.core.api.http import requires_auth - +from openlp.core.api.http.endpoint import Endpoint +from openlp.core.api.http.errors import NotFound log = logging.getLogger(__name__) diff --git a/openlp/plugins/custom/forms/__init__.py b/openlp/plugins/custom/forms/__init__.py index ea62548f4..711ded4ae 100644 --- a/openlp/plugins/custom/forms/__init__.py +++ b/openlp/plugins/custom/forms/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/custom/forms/editcustomdialog.py b/openlp/plugins/custom/forms/editcustomdialog.py index e0f5646d3..79771e4b2 100644 --- a/openlp/plugins/custom/forms/editcustomdialog.py +++ b/openlp/plugins/custom/forms/editcustomdialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py index ee2d7b415..0ab518960 100644 --- a/openlp/plugins/custom/forms/editcustomform.py +++ b/openlp/plugins/custom/forms/editcustomform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/custom/forms/editcustomslidedialog.py b/openlp/plugins/custom/forms/editcustomslidedialog.py index 5ccc94cc6..9d7e50411 100644 --- a/openlp/plugins/custom/forms/editcustomslidedialog.py +++ b/openlp/plugins/custom/forms/editcustomslidedialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/custom/forms/editcustomslideform.py b/openlp/plugins/custom/forms/editcustomslideform.py index 77f086dbb..4619abb82 100644 --- a/openlp/plugins/custom/forms/editcustomslideform.py +++ b/openlp/plugins/custom/forms/editcustomslideform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/custom/lib/__init__.py b/openlp/plugins/custom/lib/__init__.py index 6ecd423b3..da3fe3e02 100644 --- a/openlp/plugins/custom/lib/__init__.py +++ b/openlp/plugins/custom/lib/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -20,6 +20,6 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +from .customtab import CustomTab from .customxmlhandler import CustomXMLBuilder, CustomXMLParser from .mediaitem import CustomMediaItem -from .customtab import CustomTab diff --git a/openlp/plugins/custom/lib/customtab.py b/openlp/plugins/custom/lib/customtab.py index 2239ac2ce..40a36f6c7 100644 --- a/openlp/plugins/custom/lib/customtab.py +++ b/openlp/plugins/custom/lib/customtab.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/custom/lib/customxmlhandler.py b/openlp/plugins/custom/lib/customxmlhandler.py index a205b1d6a..399d31def 100644 --- a/openlp/plugins/custom/lib/customxmlhandler.py +++ b/openlp/plugins/custom/lib/customxmlhandler.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -36,9 +36,9 @@ The basic XML is of the format:: """ import logging - from xml.dom.minidom import Document from xml.etree.ElementTree import dump + from lxml import etree, objectify log = logging.getLogger(__name__) diff --git a/openlp/plugins/custom/lib/db.py b/openlp/plugins/custom/lib/db.py index 6581ee5ae..ab8daf554 100644 --- a/openlp/plugins/custom/lib/db.py +++ b/openlp/plugins/custom/lib/db.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py index 35eddc117..d4e7f8cfd 100644 --- a/openlp/plugins/custom/lib/mediaitem.py +++ b/openlp/plugins/custom/lib/mediaitem.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/images/__init__.py b/openlp/plugins/images/__init__.py index cf47999d2..d07ab9f04 100644 --- a/openlp/plugins/images/__init__.py +++ b/openlp/plugins/images/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/images/endpoint.py b/openlp/plugins/images/endpoint.py index 05c1e64b4..710cc07a8 100644 --- a/openlp/plugins/images/endpoint.py +++ b/openlp/plugins/images/endpoint.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -21,11 +21,10 @@ ############################################################################### import logging -from openlp.core.api.http.endpoint import Endpoint -from openlp.core.api.http.errors import NotFound from openlp.core.api.endpoint.pluginhelpers import search, live, service, display_thumbnails from openlp.core.api.http import requires_auth - +from openlp.core.api.http.endpoint import Endpoint +from openlp.core.api.http.errors import NotFound log = logging.getLogger(__name__) diff --git a/openlp/plugins/images/forms/__init__.py b/openlp/plugins/images/forms/__init__.py index babff4678..f7a6b947b 100644 --- a/openlp/plugins/images/forms/__init__.py +++ b/openlp/plugins/images/forms/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/images/forms/addgroupdialog.py b/openlp/plugins/images/forms/addgroupdialog.py index 665fcd824..bd11df702 100644 --- a/openlp/plugins/images/forms/addgroupdialog.py +++ b/openlp/plugins/images/forms/addgroupdialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/images/forms/addgroupform.py b/openlp/plugins/images/forms/addgroupform.py index 88f9377f3..bcfa1ad21 100644 --- a/openlp/plugins/images/forms/addgroupform.py +++ b/openlp/plugins/images/forms/addgroupform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/images/forms/choosegroupdialog.py b/openlp/plugins/images/forms/choosegroupdialog.py index 35e959fb5..49e3f5f5b 100644 --- a/openlp/plugins/images/forms/choosegroupdialog.py +++ b/openlp/plugins/images/forms/choosegroupdialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/images/forms/choosegroupform.py b/openlp/plugins/images/forms/choosegroupform.py index 5867481b9..2f61bf6db 100644 --- a/openlp/plugins/images/forms/choosegroupform.py +++ b/openlp/plugins/images/forms/choosegroupform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/images/imageplugin.py b/openlp/plugins/images/imageplugin.py index cfa5448f5..d814ec47b 100644 --- a/openlp/plugins/images/imageplugin.py +++ b/openlp/plugins/images/imageplugin.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -20,10 +20,10 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from PyQt5 import QtGui - import logging +from PyQt5 import QtGui + from openlp.core.api.http import register_endpoint from openlp.core.common.i18n import translate from openlp.core.common.settings import Settings diff --git a/openlp/plugins/images/lib/__init__.py b/openlp/plugins/images/lib/__init__.py index aa49ec62e..668d437ce 100644 --- a/openlp/plugins/images/lib/__init__.py +++ b/openlp/plugins/images/lib/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -20,5 +20,5 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from .mediaitem import ImageMediaItem from .imagetab import ImageTab +from .mediaitem import ImageMediaItem diff --git a/openlp/plugins/images/lib/db.py b/openlp/plugins/images/lib/db.py index be7c299b3..6e4656d0e 100644 --- a/openlp/plugins/images/lib/db.py +++ b/openlp/plugins/images/lib/db.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/images/lib/imagetab.py b/openlp/plugins/images/lib/imagetab.py index e2b64a6cc..3f559bb0d 100644 --- a/openlp/plugins/images/lib/imagetab.py +++ b/openlp/plugins/images/lib/imagetab.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index 25a8d2353..fa1dc6b91 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -37,7 +37,6 @@ from openlp.core.widgets.views import TreeWidgetWithDnD from openlp.plugins.images.forms import AddGroupForm, ChooseGroupForm from openlp.plugins.images.lib.db import ImageFilenames, ImageGroups - log = logging.getLogger(__name__) diff --git a/openlp/plugins/images/lib/upgrade.py b/openlp/plugins/images/lib/upgrade.py index bc1310d79..b2452db89 100644 --- a/openlp/plugins/images/lib/upgrade.py +++ b/openlp/plugins/images/lib/upgrade.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/media/__init__.py b/openlp/plugins/media/__init__.py index 6d87bbe3b..dbc14f050 100644 --- a/openlp/plugins/media/__init__.py +++ b/openlp/plugins/media/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/media/endpoint.py b/openlp/plugins/media/endpoint.py index c7b703358..443401b7a 100644 --- a/openlp/plugins/media/endpoint.py +++ b/openlp/plugins/media/endpoint.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -21,11 +21,10 @@ ############################################################################### import logging -from openlp.core.api.http.endpoint import Endpoint -from openlp.core.api.http.errors import NotFound from openlp.core.api.endpoint.pluginhelpers import search, live, service from openlp.core.api.http import requires_auth - +from openlp.core.api.http.endpoint import Endpoint +from openlp.core.api.http.errors import NotFound log = logging.getLogger(__name__) diff --git a/openlp/plugins/media/forms/__init__.py b/openlp/plugins/media/forms/__init__.py index ea62548f4..711ded4ae 100644 --- a/openlp/plugins/media/forms/__init__.py +++ b/openlp/plugins/media/forms/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/media/forms/mediaclipselectordialog.py b/openlp/plugins/media/forms/mediaclipselectordialog.py index 38ecda99c..22f239cf5 100644 --- a/openlp/plugins/media/forms/mediaclipselectordialog.py +++ b/openlp/plugins/media/forms/mediaclipselectordialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/media/forms/mediaclipselectorform.py b/openlp/plugins/media/forms/mediaclipselectorform.py index be9e69fbd..7c0db8db7 100644 --- a/openlp/plugins/media/forms/mediaclipselectorform.py +++ b/openlp/plugins/media/forms/mediaclipselectorform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -19,21 +19,21 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -import os import logging +import os import re -from time import sleep from datetime import datetime +from time import sleep from PyQt5 import QtCore, QtGui, QtWidgets from openlp.core.common import is_win, is_linux, is_macosx -from openlp.core.common.path import Path from openlp.core.common.i18n import translate from openlp.core.common.mixins import RegistryProperties -from openlp.plugins.media.forms.mediaclipselectordialog import Ui_MediaClipSelector +from openlp.core.common.path import Path from openlp.core.lib.ui import critical_error_message_box from openlp.core.ui.media.vlcplayer import get_vlc +from openlp.plugins.media.forms.mediaclipselectordialog import Ui_MediaClipSelector if is_win(): from win32com.client import Dispatch diff --git a/openlp/plugins/media/lib/__init__.py b/openlp/plugins/media/lib/__init__.py index 4b5b36f57..c6c0f31ae 100644 --- a/openlp/plugins/media/lib/__init__.py +++ b/openlp/plugins/media/lib/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index 1c7556aa9..0ed7643bc 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -27,8 +27,8 @@ from PyQt5 import QtCore, QtWidgets from openlp.core.common.applocation import AppLocation from openlp.core.common.i18n import UiStrings, translate, get_natural_key -from openlp.core.common.path import Path, path_to_str, create_paths from openlp.core.common.mixins import RegistryProperties +from openlp.core.common.path import Path, path_to_str, create_paths from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings from openlp.core.lib import ItemCapabilities, MediaManagerItem, MediaType, ServiceItem, ServiceItemContext, \ @@ -302,7 +302,7 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties): Initialize media item. """ self.list_view.clear() - self.service_path = os.path.join(str(AppLocation.get_section_data_path(self.settings_section)), 'thumbnails') + self.service_path = str(AppLocation.get_section_data_path(self.settings_section) / 'thumbnails') create_paths(Path(self.service_path)) self.load_list([path_to_str(file) for file in Settings().value(self.settings_section + '/media files')]) self.rebuild_players() diff --git a/openlp/plugins/media/lib/mediatab.py b/openlp/plugins/media/lib/mediatab.py index 84c339a27..9842be5b6 100644 --- a/openlp/plugins/media/lib/mediatab.py +++ b/openlp/plugins/media/lib/mediatab.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/media/mediaplugin.py b/openlp/plugins/media/mediaplugin.py index 461e78746..3800f3978 100644 --- a/openlp/plugins/media/mediaplugin.py +++ b/openlp/plugins/media/mediaplugin.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -23,7 +23,6 @@ The Media plugin """ import logging -import os import re from PyQt5 import QtCore @@ -37,7 +36,6 @@ from openlp.core.lib import Plugin, StringContent, build_icon from openlp.plugins.media.endpoint import api_media_endpoint, media_endpoint from openlp.plugins.media.lib import MediaMediaItem, MediaTab - log = logging.getLogger(__name__) diff --git a/openlp/plugins/presentations/__init__.py b/openlp/plugins/presentations/__init__.py index 5de863e21..07940b983 100644 --- a/openlp/plugins/presentations/__init__.py +++ b/openlp/plugins/presentations/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/presentations/endpoint.py b/openlp/plugins/presentations/endpoint.py index 99c828b4b..b5839283b 100644 --- a/openlp/plugins/presentations/endpoint.py +++ b/openlp/plugins/presentations/endpoint.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -21,11 +21,10 @@ ############################################################################### import logging -from openlp.core.api.http.endpoint import Endpoint -from openlp.core.api.http.errors import NotFound from openlp.core.api.endpoint.pluginhelpers import search, live, service, display_thumbnails from openlp.core.api.http import requires_auth - +from openlp.core.api.http.endpoint import Endpoint +from openlp.core.api.http.errors import NotFound log = logging.getLogger(__name__) diff --git a/openlp/plugins/presentations/lib/__init__.py b/openlp/plugins/presentations/lib/__init__.py index 40565539c..8cc7c1942 100644 --- a/openlp/plugins/presentations/lib/__init__.py +++ b/openlp/plugins/presentations/lib/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/presentations/lib/impresscontroller.py b/openlp/plugins/presentations/lib/impresscontroller.py index 64561fbec..ee54d6337 100644 --- a/openlp/plugins/presentations/lib/impresscontroller.py +++ b/openlp/plugins/presentations/lib/impresscontroller.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py index 923953040..c0915378f 100644 --- a/openlp/plugins/presentations/lib/mediaitem.py +++ b/openlp/plugins/presentations/lib/mediaitem.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -24,10 +24,10 @@ import logging from PyQt5 import QtCore, QtGui, QtWidgets from openlp.core.common.i18n import UiStrings, translate, get_natural_key -from openlp.core.common.path import Path, path_to_str, str_to_path +from openlp.core.common.path import path_to_str, str_to_path from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings -from openlp.core.lib import MediaManagerItem, ItemCapabilities, ServiceItemContext,\ +from openlp.core.lib import MediaManagerItem, ItemCapabilities, ServiceItemContext, \ build_icon, check_item_selected, create_thumb, validate_thumb from openlp.core.lib.ui import critical_error_message_box, create_horizontal_adjusting_combo_box from openlp.plugins.presentations.lib import MessageListener diff --git a/openlp/plugins/presentations/lib/messagelistener.py b/openlp/plugins/presentations/lib/messagelistener.py index bb09b5592..7d2eefd0f 100644 --- a/openlp/plugins/presentations/lib/messagelistener.py +++ b/openlp/plugins/presentations/lib/messagelistener.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -24,9 +24,9 @@ import logging from PyQt5 import QtCore +from openlp.core.common.path import Path from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings -from openlp.core.common.path import Path from openlp.core.lib import ServiceItemContext from openlp.core.ui import HideMode from openlp.plugins.presentations.lib.pdfcontroller import PDF_CONTROLLER_FILETYPES diff --git a/openlp/plugins/presentations/lib/pdfcontroller.py b/openlp/plugins/presentations/lib/pdfcontroller.py index 715e4e3e7..126442af3 100644 --- a/openlp/plugins/presentations/lib/pdfcontroller.py +++ b/openlp/plugins/presentations/lib/pdfcontroller.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index fb3d8b2cb..72ed20746 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/presentations/lib/pptviewcontroller.py b/openlp/plugins/presentations/lib/pptviewcontroller.py index 40d9b2c65..4a9c9f267 100644 --- a/openlp/plugins/presentations/lib/pptviewcontroller.py +++ b/openlp/plugins/presentations/lib/pptviewcontroller.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -20,8 +20,8 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### import logging -import zipfile import re +import zipfile from xml.etree import ElementTree from openlp.core.common import is_win diff --git a/openlp/plugins/presentations/lib/pptviewlib/README.TXT b/openlp/plugins/presentations/lib/pptviewlib/README.TXT index fe5b4669d..85bbf7954 100644 --- a/openlp/plugins/presentations/lib/pptviewlib/README.TXT +++ b/openlp/plugins/presentations/lib/pptviewlib/README.TXT @@ -1,6 +1,6 @@ PPTVIEWLIB - Control PowerPoint Viewer 2003/2007 (for openlp.org) -Copyright (C) 2008-2017 Jonathan Corwin (j@corwin.co.uk) +Copyright (C) 2008-2018 Jonathan Corwin (j@corwin.co.uk) This library wrappers the free Microsoft PowerPoint Viewer (2003/2007) program, allowing it to be more easily controlled from another program. diff --git a/openlp/plugins/presentations/lib/pptviewlib/ppttest.py b/openlp/plugins/presentations/lib/pptviewlib/ppttest.py index bea341a49..008e66164 100644 --- a/openlp/plugins/presentations/lib/pptviewlib/ppttest.py +++ b/openlp/plugins/presentations/lib/pptviewlib/ppttest.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -21,10 +21,11 @@ ############################################################################### import sys -from PyQt5 import QtWidgets from ctypes import * from ctypes.wintypes import RECT +from PyQt5 import QtWidgets + class PPTViewer(QtWidgets.QWidget): """ diff --git a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp index d2a49ccf8..152451749 100644 --- a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp +++ b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.cpp @@ -1,7 +1,7 @@ /****************************************************************************** * OpenLP - Open Source Lyrics Projection * * --------------------------------------------------------------------------- * -* Copyright (c) 2008-2017 OpenLP Developers * +* Copyright (c) 2008-2018 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 * diff --git a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.h b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.h index ec72e0b28..0cd4ea36e 100644 --- a/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.h +++ b/openlp/plugins/presentations/lib/pptviewlib/pptviewlib.h @@ -1,7 +1,7 @@ /****************************************************************************** * OpenLP - Open Source Lyrics Projection * * --------------------------------------------------------------------------- * -* Copyright (c) 2008-2017 OpenLP Developers * +* Copyright (c) 2008-2018 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 * diff --git a/openlp/plugins/presentations/lib/presentationcontroller.py b/openlp/plugins/presentations/lib/presentationcontroller.py index d364f4e48..074272fe4 100644 --- a/openlp/plugins/presentations/lib/presentationcontroller.py +++ b/openlp/plugins/presentations/lib/presentationcontroller.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/presentations/lib/presentationtab.py b/openlp/plugins/presentations/lib/presentationtab.py index d6a4f5190..d2856d143 100644 --- a/openlp/plugins/presentations/lib/presentationtab.py +++ b/openlp/plugins/presentations/lib/presentationtab.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/presentations/presentationplugin.py b/openlp/plugins/presentations/presentationplugin.py index a68a22176..b0fd8d7cf 100644 --- a/openlp/plugins/presentations/presentationplugin.py +++ b/openlp/plugins/presentations/presentationplugin.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -23,8 +23,8 @@ The :mod:`openlp.plugins.presentations.presentationplugin` module provides the ability for OpenLP to display presentations from a variety of document formats. """ -import os import logging +import os from PyQt5 import QtCore @@ -129,7 +129,8 @@ class PresentationPlugin(Plugin): """ log.debug('check_pre_conditions') controller_dir = os.path.join('plugins', 'presentations', 'lib') - glob_pattern = os.path.join(controller_dir, '*controller.py') + # Find all files that do not begin with '.' (lp:#1738047) and end with controller.py + glob_pattern = os.path.join(controller_dir, '[!.]*controller.py') extension_loader(glob_pattern, ['presentationcontroller.py']) controller_classes = PresentationController.__subclasses__() for controller_class in controller_classes: diff --git a/openlp/plugins/songs/__init__.py b/openlp/plugins/songs/__init__.py index fe3be1376..867b4703a 100644 --- a/openlp/plugins/songs/__init__.py +++ b/openlp/plugins/songs/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/endpoint.py b/openlp/plugins/songs/endpoint.py index c8af62764..c56c78826 100644 --- a/openlp/plugins/songs/endpoint.py +++ b/openlp/plugins/songs/endpoint.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -21,11 +21,10 @@ ############################################################################### import logging -from openlp.core.api.http.endpoint import Endpoint -from openlp.core.api.http.errors import NotFound from openlp.core.api.endpoint.pluginhelpers import search, live, service from openlp.core.api.http import requires_auth - +from openlp.core.api.http.endpoint import Endpoint +from openlp.core.api.http.errors import NotFound log = logging.getLogger(__name__) diff --git a/openlp/plugins/songs/forms/__init__.py b/openlp/plugins/songs/forms/__init__.py index 066c8780d..b95871295 100644 --- a/openlp/plugins/songs/forms/__init__.py +++ b/openlp/plugins/songs/forms/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/forms/authorsdialog.py b/openlp/plugins/songs/forms/authorsdialog.py index d4f560e9b..a65789277 100644 --- a/openlp/plugins/songs/forms/authorsdialog.py +++ b/openlp/plugins/songs/forms/authorsdialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/forms/authorsform.py b/openlp/plugins/songs/forms/authorsform.py index 75ae61035..9ef42131d 100644 --- a/openlp/plugins/songs/forms/authorsform.py +++ b/openlp/plugins/songs/forms/authorsform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/forms/duplicatesongremovalform.py b/openlp/plugins/songs/forms/duplicatesongremovalform.py index 8e7724808..548d16c78 100644 --- a/openlp/plugins/songs/forms/duplicatesongremovalform.py +++ b/openlp/plugins/songs/forms/duplicatesongremovalform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -32,9 +32,9 @@ from openlp.core.common.i18n import translate from openlp.core.common.mixins import RegistryProperties from openlp.core.common.registry import Registry from openlp.core.widgets.wizard import OpenLPWizard, WizardStrings +from openlp.plugins.songs.forms.songreviewwidget import SongReviewWidget from openlp.plugins.songs.lib import delete_song from openlp.plugins.songs.lib.db import Song -from openlp.plugins.songs.forms.songreviewwidget import SongReviewWidget from openlp.plugins.songs.lib.songcompare import songs_probably_equal log = logging.getLogger(__name__) diff --git a/openlp/plugins/songs/forms/editsongdialog.py b/openlp/plugins/songs/forms/editsongdialog.py index 9cf133f06..79001d323 100644 --- a/openlp/plugins/songs/forms/editsongdialog.py +++ b/openlp/plugins/songs/forms/editsongdialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 6e0772418..36b144aef 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -30,8 +30,8 @@ from PyQt5 import QtCore, QtWidgets from openlp.core.common.applocation import AppLocation from openlp.core.common.i18n import UiStrings, translate, get_natural_key -from openlp.core.common.path import create_paths, copyfile from openlp.core.common.mixins import RegistryProperties +from openlp.core.common.path import create_paths, copyfile from openlp.core.common.registry import Registry from openlp.core.lib import PluginStatus, MediaType, create_separated_list from openlp.core.lib.ui import set_case_insensitive_completer, critical_error_message_box, find_and_set_in_combo_box diff --git a/openlp/plugins/songs/forms/editversedialog.py b/openlp/plugins/songs/forms/editversedialog.py index 76dc70c17..fb4f4fd68 100644 --- a/openlp/plugins/songs/forms/editversedialog.py +++ b/openlp/plugins/songs/forms/editversedialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,8 +22,8 @@ from PyQt5 import QtWidgets -from openlp.core.common.settings import Settings from openlp.core.common.i18n import UiStrings, translate +from openlp.core.common.settings import Settings from openlp.core.lib import build_icon from openlp.core.lib.ui import create_button_box from openlp.core.widgets.edits import SpellTextEdit diff --git a/openlp/plugins/songs/forms/editverseform.py b/openlp/plugins/songs/forms/editverseform.py index 09ba1e300..436c5039f 100644 --- a/openlp/plugins/songs/forms/editverseform.py +++ b/openlp/plugins/songs/forms/editverseform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -20,14 +20,14 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -import re import logging +import re from PyQt5 import QtCore, QtGui, QtWidgets -from openlp.core.lib.ui import critical_error_message_box from openlp.core.common.i18n import translate from openlp.core.common.settings import Settings +from openlp.core.lib.ui import critical_error_message_box from openlp.plugins.songs.forms.editversedialog import Ui_EditVerseDialog from openlp.plugins.songs.lib import VerseType, transpose_lyrics diff --git a/openlp/plugins/songs/forms/mediafilesdialog.py b/openlp/plugins/songs/forms/mediafilesdialog.py index 41a6862d3..93987b82a 100644 --- a/openlp/plugins/songs/forms/mediafilesdialog.py +++ b/openlp/plugins/songs/forms/mediafilesdialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/forms/mediafilesform.py b/openlp/plugins/songs/forms/mediafilesform.py index 8718471ea..29a0603cf 100644 --- a/openlp/plugins/songs/forms/mediafilesform.py +++ b/openlp/plugins/songs/forms/mediafilesform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -21,7 +21,6 @@ ############################################################################### import logging -import os from PyQt5 import QtCore, QtWidgets diff --git a/openlp/plugins/songs/forms/songbookdialog.py b/openlp/plugins/songs/forms/songbookdialog.py index 4a248cb48..b9c2019af 100644 --- a/openlp/plugins/songs/forms/songbookdialog.py +++ b/openlp/plugins/songs/forms/songbookdialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/forms/songbookform.py b/openlp/plugins/songs/forms/songbookform.py index 594768aaf..1976d866d 100644 --- a/openlp/plugins/songs/forms/songbookform.py +++ b/openlp/plugins/songs/forms/songbookform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/forms/songexportform.py b/openlp/plugins/songs/forms/songexportform.py index c6446d74c..f67eae94b 100644 --- a/openlp/plugins/songs/forms/songexportform.py +++ b/openlp/plugins/songs/forms/songexportform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index af88bfb35..6941cbea2 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/forms/songmaintenancedialog.py b/openlp/plugins/songs/forms/songmaintenancedialog.py index 728861f26..a8da63723 100644 --- a/openlp/plugins/songs/forms/songmaintenancedialog.py +++ b/openlp/plugins/songs/forms/songmaintenancedialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/forms/songmaintenanceform.py b/openlp/plugins/songs/forms/songmaintenanceform.py index 7f0236d24..4bdb12a57 100644 --- a/openlp/plugins/songs/forms/songmaintenanceform.py +++ b/openlp/plugins/songs/forms/songmaintenanceform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -29,8 +29,8 @@ from openlp.core.common.mixins import RegistryProperties from openlp.core.common.registry import Registry from openlp.core.lib.ui import critical_error_message_box from openlp.plugins.songs.forms.authorsform import AuthorsForm -from openlp.plugins.songs.forms.topicsform import TopicsForm from openlp.plugins.songs.forms.songbookform import SongBookForm +from openlp.plugins.songs.forms.topicsform import TopicsForm from openlp.plugins.songs.lib.db import Author, Book, Topic, Song from .songmaintenancedialog import Ui_SongMaintenanceDialog diff --git a/openlp/plugins/songs/forms/songreviewwidget.py b/openlp/plugins/songs/forms/songreviewwidget.py index 960e8ebec..9d98af6e9 100644 --- a/openlp/plugins/songs/forms/songreviewwidget.py +++ b/openlp/plugins/songs/forms/songreviewwidget.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/forms/songselectdialog.py b/openlp/plugins/songs/forms/songselectdialog.py index bc0bd7415..66bb9b29f 100644 --- a/openlp/plugins/songs/forms/songselectdialog.py +++ b/openlp/plugins/songs/forms/songselectdialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/forms/songselectform.py b/openlp/plugins/songs/forms/songselectform.py index 5d175bb5e..4c37bf390 100644 --- a/openlp/plugins/songs/forms/songselectform.py +++ b/openlp/plugins/songs/forms/songselectform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -27,24 +27,23 @@ from time import sleep from PyQt5 import QtCore, QtWidgets -from openlp.core.common import is_win from openlp.core.common.i18n import translate -from openlp.core.common.registry import Registry +from openlp.core.common.mixins import RegistryProperties from openlp.core.common.settings import Settings +from openlp.core.threading import ThreadWorker, run_thread from openlp.plugins.songs.forms.songselectdialog import Ui_SongSelectDialog from openlp.plugins.songs.lib.songselect import SongSelectImport log = logging.getLogger(__name__) -class SearchWorker(QtCore.QObject): +class SearchWorker(ThreadWorker): """ Run the actual SongSelect search, and notify the GUI when we find each song. """ show_info = QtCore.pyqtSignal(str, str) found_song = QtCore.pyqtSignal(dict) finished = QtCore.pyqtSignal() - quit = QtCore.pyqtSignal() def __init__(self, importer, search_text): super().__init__() @@ -74,7 +73,7 @@ class SearchWorker(QtCore.QObject): self.found_song.emit(song) -class SongSelectForm(QtWidgets.QDialog, Ui_SongSelectDialog): +class SongSelectForm(QtWidgets.QDialog, Ui_SongSelectDialog, RegistryProperties): """ The :class:`SongSelectForm` class is the SongSelect dialog. """ @@ -90,8 +89,6 @@ class SongSelectForm(QtWidgets.QDialog, Ui_SongSelectDialog): """ Initialise the SongSelectForm """ - self.thread = None - self.worker = None self.song_count = 0 self.song = None self.set_progress_visible(False) @@ -311,17 +308,11 @@ class SongSelectForm(QtWidgets.QDialog, Ui_SongSelectDialog): search_history = self.search_combobox.getItems() Settings().setValue(self.plugin.settings_section + '/songselect searches', '|'.join(search_history)) # Create thread and run search - self.thread = QtCore.QThread() - self.worker = SearchWorker(self.song_select_importer, self.search_combobox.currentText()) - self.worker.moveToThread(self.thread) - self.thread.started.connect(self.worker.start) - self.worker.show_info.connect(self.on_search_show_info) - self.worker.found_song.connect(self.on_search_found_song) - self.worker.finished.connect(self.on_search_finished) - self.worker.quit.connect(self.thread.quit) - self.worker.quit.connect(self.worker.deleteLater) - self.thread.finished.connect(self.thread.deleteLater) - self.thread.start() + worker = SearchWorker(self.song_select_importer, self.search_combobox.currentText()) + worker.show_info.connect(self.on_search_show_info) + worker.found_song.connect(self.on_search_found_song) + worker.finished.connect(self.on_search_finished) + run_thread(worker, 'songselect') def on_stop_button_clicked(self): """ @@ -408,16 +399,3 @@ class SongSelectForm(QtWidgets.QDialog, Ui_SongSelectDialog): """ self.search_progress_bar.setVisible(is_visible) self.stop_button.setVisible(is_visible) - - @property - def application(self): - """ - Adds the openlp to the class dynamically. - Windows needs to access the application in a dynamic manner. - """ - if is_win(): - return Registry().get('application') - else: - if not hasattr(self, '_application'): - self._application = Registry().get('application') - return self._application diff --git a/openlp/plugins/songs/forms/topicsdialog.py b/openlp/plugins/songs/forms/topicsdialog.py index fe5020941..bd80548b9 100644 --- a/openlp/plugins/songs/forms/topicsdialog.py +++ b/openlp/plugins/songs/forms/topicsdialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/forms/topicsform.py b/openlp/plugins/songs/forms/topicsform.py index 2956c7e26..101a8e705 100644 --- a/openlp/plugins/songs/forms/topicsform.py +++ b/openlp/plugins/songs/forms/topicsform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/lib/__init__.py b/openlp/plugins/songs/lib/__init__.py index 74334ef0d..2578d0f92 100644 --- a/openlp/plugins/songs/lib/__init__.py +++ b/openlp/plugins/songs/lib/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/lib/db.py b/openlp/plugins/songs/lib/db.py index 0963fd084..bf78d8d55 100644 --- a/openlp/plugins/songs/lib/db.py +++ b/openlp/plugins/songs/lib/db.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index e306dae87..43628a87b 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -27,28 +27,28 @@ import logging from openlp.core.common import is_win from openlp.core.common.i18n import UiStrings, translate from openlp.core.widgets.wizard import WizardStrings -from .importers.opensong import OpenSongImport +from .importers.cclifile import CCLIFileImport +from .importers.chordpro import ChordProImport +from .importers.dreambeam import DreamBeamImport from .importers.easyslides import EasySlidesImport +from .importers.easyworship import EasyWorshipSongImport +from .importers.foilpresenter import FoilPresenterImport +from .importers.lyrix import LyrixImport from .importers.openlp import OpenLPSongImport from .importers.openlyrics import OpenLyricsImport -from .importers.wordsofworship import WordsOfWorshipImport -from .importers.cclifile import CCLIFileImport -from .importers.dreambeam import DreamBeamImport -from .importers.powersong import PowerSongImport -from .importers.easyworship import EasyWorshipSongImport -from .importers.songbeamer import SongBeamerImport -from .importers.songshowplus import SongShowPlusImport -from .importers.songpro import SongProImport -from .importers.sundayplus import SundayPlusImport -from .importers.foilpresenter import FoilPresenterImport -from .importers.zionworx import ZionWorxImport -from .importers.propresenter import ProPresenterImport -from .importers.worshipassistant import WorshipAssistantImport +from .importers.opensong import OpenSongImport from .importers.powerpraise import PowerPraiseImport +from .importers.powersong import PowerSongImport from .importers.presentationmanager import PresentationManagerImport -from .importers.lyrix import LyrixImport +from .importers.propresenter import ProPresenterImport +from .importers.songbeamer import SongBeamerImport +from .importers.songpro import SongProImport +from .importers.songshowplus import SongShowPlusImport +from .importers.sundayplus import SundayPlusImport from .importers.videopsalm import VideoPsalmImport -from .importers.chordpro import ChordProImport +from .importers.wordsofworship import WordsOfWorshipImport +from .importers.worshipassistant import WorshipAssistantImport +from .importers.zionworx import ZionWorxImport log = logging.getLogger(__name__) diff --git a/openlp/plugins/songs/lib/importers/__init__.py b/openlp/plugins/songs/lib/importers/__init__.py index 42de076d0..d73429473 100644 --- a/openlp/plugins/songs/lib/importers/__init__.py +++ b/openlp/plugins/songs/lib/importers/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/lib/importers/cclifile.py b/openlp/plugins/songs/lib/importers/cclifile.py index 10a8b09e1..1389918c1 100644 --- a/openlp/plugins/songs/lib/importers/cclifile.py +++ b/openlp/plugins/songs/lib/importers/cclifile.py @@ -1,10 +1,13 @@ # -*- coding: utf-8 -*- # vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 +import codecs +import logging + ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -20,8 +23,6 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### import chardet -import codecs -import logging from openlp.core.common.i18n import translate from openlp.plugins.songs.lib import VerseType diff --git a/openlp/plugins/songs/lib/importers/dreambeam.py b/openlp/plugins/songs/lib/importers/dreambeam.py index eb2ec1ded..532bd865d 100644 --- a/openlp/plugins/songs/lib/importers/dreambeam.py +++ b/openlp/plugins/songs/lib/importers/dreambeam.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/lib/importers/easyslides.py b/openlp/plugins/songs/lib/importers/easyslides.py index 6d717bdb4..8f847c5f3 100644 --- a/openlp/plugins/songs/lib/importers/easyslides.py +++ b/openlp/plugins/songs/lib/importers/easyslides.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/lib/importers/easyworship.py b/openlp/plugins/songs/lib/importers/easyworship.py index 8f096099f..b2c216de2 100644 --- a/openlp/plugins/songs/lib/importers/easyworship.py +++ b/openlp/plugins/songs/lib/importers/easyworship.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -25,11 +25,10 @@ The :mod:`easyworship` module provides the functionality for importing EasyWorsh import logging import os import re +import sqlite3 import struct import zlib -import sqlite3 - from openlp.core.common.i18n import translate from openlp.core.common.path import Path from openlp.plugins.songs.lib import VerseType diff --git a/openlp/plugins/songs/lib/importers/foilpresenter.py b/openlp/plugins/songs/lib/importers/foilpresenter.py index f164dfda2..82601f18b 100644 --- a/openlp/plugins/songs/lib/importers/foilpresenter.py +++ b/openlp/plugins/songs/lib/importers/foilpresenter.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -90,10 +90,10 @@ from lxml import etree, objectify from openlp.core.common.i18n import translate from openlp.core.widgets.wizard import WizardStrings from openlp.plugins.songs.lib import clean_song, VerseType -from openlp.plugins.songs.lib.importers.songimport import SongImport from openlp.plugins.songs.lib.db import Author, Book, Song, Topic -from openlp.plugins.songs.lib.ui import SongStrings +from openlp.plugins.songs.lib.importers.songimport import SongImport from openlp.plugins.songs.lib.openlyricsxml import SongXML +from openlp.plugins.songs.lib.ui import SongStrings log = logging.getLogger(__name__) diff --git a/openlp/plugins/songs/lib/importers/lyrix.py b/openlp/plugins/songs/lib/importers/lyrix.py index c8dbac24b..386fe43e2 100644 --- a/openlp/plugins/songs/lib/importers/lyrix.py +++ b/openlp/plugins/songs/lib/importers/lyrix.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/lib/importers/mediashout.py b/openlp/plugins/songs/lib/importers/mediashout.py index 9df9baa0f..5ecd53bd3 100644 --- a/openlp/plugins/songs/lib/importers/mediashout.py +++ b/openlp/plugins/songs/lib/importers/mediashout.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -27,9 +27,10 @@ a MediaShout database into the OpenLP database. # WARNING: See https://docs.python.org/3/library/sqlite3.html for value substitution # in SQL statements -import pyodbc import logging +import pyodbc + from openlp.core.common.i18n import translate from openlp.plugins.songs.lib.importers.songimport import SongImport diff --git a/openlp/plugins/songs/lib/importers/openlp.py b/openlp/plugins/songs/lib/importers/openlp.py index 80a981d02..8800f568d 100644 --- a/openlp/plugins/songs/lib/importers/openlp.py +++ b/openlp/plugins/songs/lib/importers/openlp.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/lib/importers/openlyrics.py b/openlp/plugins/songs/lib/importers/openlyrics.py index f443cfb34..62bb91414 100644 --- a/openlp/plugins/songs/lib/importers/openlyrics.py +++ b/openlp/plugins/songs/lib/importers/openlyrics.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -29,8 +29,8 @@ from lxml import etree from openlp.core.widgets.wizard import WizardStrings from openlp.plugins.songs.lib.importers.songimport import SongImport -from openlp.plugins.songs.lib.ui import SongStrings from openlp.plugins.songs.lib.openlyricsxml import OpenLyrics, OpenLyricsError +from openlp.plugins.songs.lib.ui import SongStrings log = logging.getLogger(__name__) diff --git a/openlp/plugins/songs/lib/importers/openoffice.py b/openlp/plugins/songs/lib/importers/openoffice.py index f2a8b2147..e1862c936 100644 --- a/openlp/plugins/songs/lib/importers/openoffice.py +++ b/openlp/plugins/songs/lib/importers/openoffice.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/lib/importers/opensong.py b/openlp/plugins/songs/lib/importers/opensong.py index 6cd690562..25e52777a 100644 --- a/openlp/plugins/songs/lib/importers/opensong.py +++ b/openlp/plugins/songs/lib/importers/opensong.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/lib/importers/opspro.py b/openlp/plugins/songs/lib/importers/opspro.py index f7dba83b8..5edcfdd39 100644 --- a/openlp/plugins/songs/lib/importers/opspro.py +++ b/openlp/plugins/songs/lib/importers/opspro.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -29,9 +29,10 @@ a OPS Pro database into the OpenLP database. import logging import re -import pyodbc import struct +import pyodbc + from openlp.core.common.i18n import translate from openlp.plugins.songs.lib.importers.songimport import SongImport diff --git a/openlp/plugins/songs/lib/importers/powerpraise.py b/openlp/plugins/songs/lib/importers/powerpraise.py index fd6f64360..dfe545d64 100644 --- a/openlp/plugins/songs/lib/importers/powerpraise.py +++ b/openlp/plugins/songs/lib/importers/powerpraise.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/lib/importers/powersong.py b/openlp/plugins/songs/lib/importers/powersong.py index 7fac4ef75..d73e3ed9c 100644 --- a/openlp/plugins/songs/lib/importers/powersong.py +++ b/openlp/plugins/songs/lib/importers/powersong.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -24,10 +24,9 @@ The :mod:`powersong` module provides the functionality for importing PowerSong songs into the OpenLP database. """ import logging -import fnmatch -import os from openlp.core.common.i18n import translate +from openlp.core.common.path import Path from openlp.plugins.songs.lib.importers.songimport import SongImport log = logging.getLogger(__name__) @@ -89,26 +88,25 @@ class PowerSongImport(SongImport): """ from openlp.plugins.songs.lib.importer import SongFormat ps_string = SongFormat.get(SongFormat.PowerSong, 'name') - if isinstance(self.import_source, str): - if os.path.isdir(self.import_source): + if isinstance(self.import_source, Path): + if self.import_source.is_dir(): dir = self.import_source self.import_source = [] - for file in os.listdir(dir): - if fnmatch.fnmatch(file, '*.song'): - self.import_source.append(os.path.join(dir, file)) + for path in dir.glob('*.song'): + self.import_source.append(path) else: - self.import_source = '' + self.import_source = None if not self.import_source or not isinstance(self.import_source, list): self.log_error(translate('SongsPlugin.PowerSongImport', 'No songs to import.'), translate('SongsPlugin.PowerSongImport', 'No {text} files found.').format(text=ps_string)) return self.import_wizard.progress_bar.setMaximum(len(self.import_source)) - for file in self.import_source: + for file_path in self.import_source: if self.stop_import_flag: return self.set_defaults() parse_error = False - with open(file, 'rb') as song_data: + with file_path.open('rb') as song_data: while True: try: label = self._read_string(song_data) @@ -117,7 +115,7 @@ class PowerSongImport(SongImport): field = self._read_string(song_data) except ValueError: parse_error = True - self.log_error(os.path.basename(file), + self.log_error(file_path.name, translate('SongsPlugin.PowerSongImport', 'Invalid {text} file. Unexpected byte value.').format(text=ps_string)) break @@ -135,7 +133,7 @@ class PowerSongImport(SongImport): continue # Check that file had TITLE field if not self.title: - self.log_error(os.path.basename(file), + self.log_error(file_path.name, translate('SongsPlugin.PowerSongImport', 'Invalid {text} file. Missing "TITLE" header.').format(text=ps_string)) continue diff --git a/openlp/plugins/songs/lib/importers/presentationmanager.py b/openlp/plugins/songs/lib/importers/presentationmanager.py index c8f9a16f9..9b16f24a6 100644 --- a/openlp/plugins/songs/lib/importers/presentationmanager.py +++ b/openlp/plugins/songs/lib/importers/presentationmanager.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -27,8 +27,8 @@ import re from lxml import objectify, etree -from openlp.core.common.i18n import translate from openlp.core.common import get_file_encoding +from openlp.core.common.i18n import translate from openlp.core.widgets.wizard import WizardStrings from openlp.plugins.songs.lib.importers.songimport import SongImport diff --git a/openlp/plugins/songs/lib/importers/propresenter.py b/openlp/plugins/songs/lib/importers/propresenter.py index 0de0e5300..f5e0058db 100644 --- a/openlp/plugins/songs/lib/importers/propresenter.py +++ b/openlp/plugins/songs/lib/importers/propresenter.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -25,6 +25,7 @@ ProPresenter song files into the current installation database. """ import base64 import logging + from lxml import objectify from openlp.core.widgets.wizard import WizardStrings diff --git a/openlp/plugins/songs/lib/importers/songbeamer.py b/openlp/plugins/songs/lib/importers/songbeamer.py index adc364325..e4276dd20 100644 --- a/openlp/plugins/songs/lib/importers/songbeamer.py +++ b/openlp/plugins/songs/lib/importers/songbeamer.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,15 +22,15 @@ """ The :mod:`songbeamer` module provides the functionality for importing SongBeamer songs into the OpenLP database. """ +import base64 import logging +import math import os import re -import base64 -import math from openlp.core.common import is_win, is_macosx, get_file_encoding -from openlp.core.common.settings import Settings from openlp.core.common.path import Path +from openlp.core.common.settings import Settings from openlp.plugins.songs.lib import VerseType from openlp.plugins.songs.lib.importers.songimport import SongImport diff --git a/openlp/plugins/songs/lib/importers/songimport.py b/openlp/plugins/songs/lib/importers/songimport.py index 2bd8c0e56..aab98e00d 100644 --- a/openlp/plugins/songs/lib/importers/songimport.py +++ b/openlp/plugins/songs/lib/importers/songimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -33,8 +33,8 @@ from openlp.core.common.registry import Registry from openlp.core.widgets.wizard import WizardStrings from openlp.plugins.songs.lib import clean_song, VerseType from openlp.plugins.songs.lib.db import Song, Author, Topic, Book, MediaFile -from openlp.plugins.songs.lib.ui import SongStrings from openlp.plugins.songs.lib.openlyricsxml import SongXML +from openlp.plugins.songs.lib.ui import SongStrings log = logging.getLogger(__name__) diff --git a/openlp/plugins/songs/lib/importers/songpro.py b/openlp/plugins/songs/lib/importers/songpro.py index 261c2c728..9f52e62dc 100644 --- a/openlp/plugins/songs/lib/importers/songpro.py +++ b/openlp/plugins/songs/lib/importers/songpro.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/lib/importers/songshowplus.py b/openlp/plugins/songs/lib/importers/songshowplus.py index 3109fae1d..ceadbdf8f 100644 --- a/openlp/plugins/songs/lib/importers/songshowplus.py +++ b/openlp/plugins/songs/lib/importers/songshowplus.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/lib/importers/songsoffellowship.py b/openlp/plugins/songs/lib/importers/songsoffellowship.py index bbba654c9..d0c0a6720 100644 --- a/openlp/plugins/songs/lib/importers/songsoffellowship.py +++ b/openlp/plugins/songs/lib/importers/songsoffellowship.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -27,13 +27,11 @@ # http://wiki.services.openoffice.org/wiki/Python import logging -import os import re from openlp.core.common import is_win from .openoffice import OpenOfficeImport - log = logging.getLogger(__name__) if is_win(): diff --git a/openlp/plugins/songs/lib/importers/sundayplus.py b/openlp/plugins/songs/lib/importers/sundayplus.py index e0ce16aa1..180c76e19 100644 --- a/openlp/plugins/songs/lib/importers/sundayplus.py +++ b/openlp/plugins/songs/lib/importers/sundayplus.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -19,7 +19,6 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -import os import re from openlp.plugins.songs.lib import VerseType, retrieve_windows_encoding @@ -60,21 +59,24 @@ class SundayPlusImport(SongImport): for file_path in self.import_source: if self.stop_import_flag: return - with file_path.open('rb') as song_file: - self.do_import_file(song_file) + self.do_import_file(file_path) - def do_import_file(self, file): + def do_import_file(self, file_path): """ - Process the Sunday Plus file object. + Process the Sunday Plus song file + + :param openlp.core.common.path.Path file_path: The song file to import + :rtype: None """ - self.set_defaults() - if not self.parse(file.read()): - self.log_error(file.name) - return - if self.title == '': - self.title = self.title_from_filename(file.name) - if not self.finish(): - self.log_error(file.name) + with file_path.open('rb') as song_file: + self.set_defaults() + if not self.parse(song_file.read()): + self.log_error(file_path.name) + return + if self.title == '': + self.title = self.title_from_file_path(file_path) + if not self.finish(): + self.log_error(file_path.name) def parse(self, data, cell=False): """ @@ -174,16 +176,15 @@ class SundayPlusImport(SongImport): i += 1 return True - def title_from_filename(self, filename): + def title_from_file_path(self, file_path): """ Extract the title from the filename - :param filename: File name - :return: + :param openlp.core.common.path.Path file_path: File being imported + :return: The song title + :rtype: str """ - title = os.path.split(filename)[1] - if title.endswith('.ptf'): - title = title[:-4] + title = file_path.stem # For some strange reason all example files names ended with 1-7. if title.endswith('1-7'): title = title[:-3] diff --git a/openlp/plugins/songs/lib/importers/videopsalm.py b/openlp/plugins/songs/lib/importers/videopsalm.py index 180dbd333..156d98f69 100644 --- a/openlp/plugins/songs/lib/importers/videopsalm.py +++ b/openlp/plugins/songs/lib/importers/videopsalm.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -27,10 +27,10 @@ import logging import re from openlp.core.common.i18n import translate -from openlp.core.common.settings import Settings from openlp.core.common.path import Path -from openlp.plugins.songs.lib.importers.songimport import SongImport +from openlp.core.common.settings import Settings from openlp.plugins.songs.lib.db import AuthorType +from openlp.plugins.songs.lib.importers.songimport import SongImport log = logging.getLogger(__name__) diff --git a/openlp/plugins/songs/lib/importers/wordsofworship.py b/openlp/plugins/songs/lib/importers/wordsofworship.py index e1c561361..dff14efe4 100644 --- a/openlp/plugins/songs/lib/importers/wordsofworship.py +++ b/openlp/plugins/songs/lib/importers/wordsofworship.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -23,9 +23,8 @@ The :mod:`wordsofworship` module provides the functionality for importing Words of Worship songs into the OpenLP database. """ -import os import logging -from openlp.core.common.path import Path +import os from openlp.core.common.i18n import translate from openlp.plugins.songs.lib.importers.songimport import SongImport diff --git a/openlp/plugins/songs/lib/importers/worshipassistant.py b/openlp/plugins/songs/lib/importers/worshipassistant.py index f9354427d..02df16b4a 100644 --- a/openlp/plugins/songs/lib/importers/worshipassistant.py +++ b/openlp/plugins/songs/lib/importers/worshipassistant.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/lib/importers/worshipcenterpro.py b/openlp/plugins/songs/lib/importers/worshipcenterpro.py index 6bba00682..6ae24f7bc 100644 --- a/openlp/plugins/songs/lib/importers/worshipcenterpro.py +++ b/openlp/plugins/songs/lib/importers/worshipcenterpro.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -25,6 +25,7 @@ a WorshipCenter Pro database into the OpenLP database. """ import logging import re + import pyodbc from openlp.core.common.i18n import translate diff --git a/openlp/plugins/songs/lib/importers/zionworx.py b/openlp/plugins/songs/lib/importers/zionworx.py index 23817c31a..345f3ac44 100644 --- a/openlp/plugins/songs/lib/importers/zionworx.py +++ b/openlp/plugins/songs/lib/importers/zionworx.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index c6ad9c927..3d46311df 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/lib/openlyricsexport.py b/openlp/plugins/songs/lib/openlyricsexport.py index b07298253..ff3e4fe3e 100644 --- a/openlp/plugins/songs/lib/openlyricsexport.py +++ b/openlp/plugins/songs/lib/openlyricsexport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -29,8 +29,8 @@ from lxml import etree from openlp.core.common import clean_filename from openlp.core.common.i18n import translate -from openlp.core.common.path import create_paths from openlp.core.common.mixins import RegistryProperties +from openlp.core.common.path import create_paths from openlp.plugins.songs.lib.openlyricsxml import OpenLyrics log = logging.getLogger(__name__) diff --git a/openlp/plugins/songs/lib/openlyricsxml.py b/openlp/plugins/songs/lib/openlyricsxml.py index ef47fa77b..63a528cfe 100644 --- a/openlp/plugins/songs/lib/openlyricsxml.py +++ b/openlp/plugins/songs/lib/openlyricsxml.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -63,8 +63,8 @@ from lxml import etree, objectify from openlp.core.common.i18n import translate from openlp.core.common.settings import Settings -from openlp.core.version import get_version from openlp.core.lib import FormattingTags +from openlp.core.version import get_version from openlp.plugins.songs.lib import VerseType, clean_song from openlp.plugins.songs.lib.db import Author, AuthorType, Book, Song, Topic diff --git a/openlp/plugins/songs/lib/songcompare.py b/openlp/plugins/songs/lib/songcompare.py index 06314cac0..09c55f877 100644 --- a/openlp/plugins/songs/lib/songcompare.py +++ b/openlp/plugins/songs/lib/songcompare.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/lib/songselect.py b/openlp/plugins/songs/lib/songselect.py index 85ada339f..61de5b574 100644 --- a/openlp/plugins/songs/lib/songselect.py +++ b/openlp/plugins/songs/lib/songselect.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -25,11 +25,11 @@ The :mod:`~openlp.plugins.songs.lib.songselect` module contains the SongSelect i import logging import random import re +from html import unescape +from html.parser import HTMLParser from http.cookiejar import CookieJar from urllib.parse import urlencode from urllib.request import HTTPCookieProcessor, URLError, build_opener -from html.parser import HTMLParser -from html import unescape from bs4 import BeautifulSoup, NavigableString diff --git a/openlp/plugins/songs/lib/songstab.py b/openlp/plugins/songs/lib/songstab.py index 69f9bb1cd..173957b82 100644 --- a/openlp/plugins/songs/lib/songstab.py +++ b/openlp/plugins/songs/lib/songstab.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/lib/ui.py b/openlp/plugins/songs/lib/ui.py index e318577a0..71ce32b99 100644 --- a/openlp/plugins/songs/lib/ui.py +++ b/openlp/plugins/songs/lib/ui.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/lib/upgrade.py b/openlp/plugins/songs/lib/upgrade.py index eca18876b..cfa7f2730 100644 --- a/openlp/plugins/songs/lib/upgrade.py +++ b/openlp/plugins/songs/lib/upgrade.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/reporting.py b/openlp/plugins/songs/reporting.py index 808c05b57..afbb2559d 100644 --- a/openlp/plugins/songs/reporting.py +++ b/openlp/plugins/songs/reporting.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index b35cbe2c9..e8fff3f2a 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -25,8 +25,8 @@ for the Songs plugin. """ import logging -import os import sqlite3 +from pathlib import Path from tempfile import gettempdir from PyQt5 import QtCore, QtWidgets @@ -316,17 +316,16 @@ class SongsPlugin(Plugin): self.application.process_events() self.on_tools_reindex_item_triggered() self.application.process_events() - db_dir = os.path.join(gettempdir(), 'openlp') - if not os.path.exists(db_dir): + db_dir_path = Path(gettempdir(), 'openlp') + if not db_dir_path.exists(): return - song_dbs = [] + song_db_paths = [] song_count = 0 - for sfile in os.listdir(db_dir): - if sfile.startswith('songs_') and sfile.endswith('.sqlite'): - self.application.process_events() - song_dbs.append(os.path.join(db_dir, sfile)) - song_count += SongsPlugin._count_songs(os.path.join(db_dir, sfile)) - if not song_dbs: + for db_file_path in db_dir_path.glob('songs_*.sqlite'): + self.application.process_events() + song_db_paths.append(db_file_path) + song_count += SongsPlugin._count_songs(db_file_path) + if not song_db_paths: return self.application.process_events() progress = QtWidgets.QProgressDialog(self.main_window) @@ -338,8 +337,8 @@ class SongsPlugin(Plugin): progress.setMinimumDuration(0) progress.forceShow() self.application.process_events() - for db in song_dbs: - importer = OpenLPSongImport(self.manager, file_path=db) + for db_path in song_db_paths: + importer = OpenLPSongImport(self.manager, file_path=db_path) importer.do_import(progress) self.application.process_events() progress.setValue(song_count) @@ -373,13 +372,15 @@ class SongsPlugin(Plugin): self.manager.delete_object(Song, song.id) @staticmethod - def _count_songs(db_file): + def _count_songs(db_path): """ Provide a count of the songs in the database - :param db_file: the database name to count + :param openlp.core.common.path.Path db_path: The database to use + :return: The number of songs in the db. + :rtype: int """ - connection = sqlite3.connect(db_file) + connection = sqlite3.connect(str(db_path)) cursor = connection.cursor() cursor.execute('SELECT COUNT(id) AS song_count FROM songs') song_count = cursor.fetchone()[0] diff --git a/openlp/plugins/songusage/__init__.py b/openlp/plugins/songusage/__init__.py index 3847c7d97..87358b136 100644 --- a/openlp/plugins/songusage/__init__.py +++ b/openlp/plugins/songusage/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songusage/forms/__init__.py b/openlp/plugins/songusage/forms/__init__.py index 17252dcf5..1ab5ed70c 100644 --- a/openlp/plugins/songusage/forms/__init__.py +++ b/openlp/plugins/songusage/forms/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songusage/forms/songusagedeletedialog.py b/openlp/plugins/songusage/forms/songusagedeletedialog.py index fe199009b..59f2ef042 100644 --- a/openlp/plugins/songusage/forms/songusagedeletedialog.py +++ b/openlp/plugins/songusage/forms/songusagedeletedialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songusage/forms/songusagedeleteform.py b/openlp/plugins/songusage/forms/songusagedeleteform.py index 9042756d6..23a994ff5 100644 --- a/openlp/plugins/songusage/forms/songusagedeleteform.py +++ b/openlp/plugins/songusage/forms/songusagedeleteform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -24,8 +24,8 @@ from PyQt5 import QtCore, QtWidgets from openlp.core.common.i18n import translate from openlp.core.common.mixins import RegistryProperties -from openlp.plugins.songusage.lib.db import SongUsageItem from openlp.plugins.songusage.forms.songusagedeletedialog import Ui_SongUsageDeleteDialog +from openlp.plugins.songusage.lib.db import SongUsageItem class SongUsageDeleteForm(QtWidgets.QDialog, Ui_SongUsageDeleteDialog, RegistryProperties): diff --git a/openlp/plugins/songusage/forms/songusagedetaildialog.py b/openlp/plugins/songusage/forms/songusagedetaildialog.py index 7f6d1c16b..ead4d7b3d 100644 --- a/openlp/plugins/songusage/forms/songusagedetaildialog.py +++ b/openlp/plugins/songusage/forms/songusagedetaildialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songusage/forms/songusagedetailform.py b/openlp/plugins/songusage/forms/songusagedetailform.py index dc3393c8d..f25f56bee 100644 --- a/openlp/plugins/songusage/forms/songusagedetailform.py +++ b/openlp/plugins/songusage/forms/songusagedetailform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -26,8 +26,8 @@ from sqlalchemy.sql import and_ from openlp.core.common.i18n import translate from openlp.core.common.mixins import RegistryProperties -from openlp.core.common.settings import Settings from openlp.core.common.path import create_paths +from openlp.core.common.settings import Settings from openlp.core.lib.ui import critical_error_message_box from openlp.plugins.songusage.lib.db import SongUsageItem from .songusagedetaildialog import Ui_SongUsageDetailDialog diff --git a/openlp/plugins/songusage/lib/__init__.py b/openlp/plugins/songusage/lib/__init__.py index a3365baed..2136c10a8 100644 --- a/openlp/plugins/songusage/lib/__init__.py +++ b/openlp/plugins/songusage/lib/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songusage/lib/db.py b/openlp/plugins/songusage/lib/db.py index 0a06f640a..9ef223d3f 100644 --- a/openlp/plugins/songusage/lib/db.py +++ b/openlp/plugins/songusage/lib/db.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songusage/lib/upgrade.py b/openlp/plugins/songusage/lib/upgrade.py index f83022d84..8f30d986a 100644 --- a/openlp/plugins/songusage/lib/upgrade.py +++ b/openlp/plugins/songusage/lib/upgrade.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/openlp/plugins/songusage/songusageplugin.py b/openlp/plugins/songusage/songusageplugin.py index 79f21a8cf..455ab3713 100644 --- a/openlp/plugins/songusage/songusageplugin.py +++ b/openlp/plugins/songusage/songusageplugin.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/scripts/appveyor-webhook.py b/scripts/appveyor-webhook.py index 630c404d7..f969b0e70 100755 --- a/scripts/appveyor-webhook.py +++ b/scripts/appveyor-webhook.py @@ -5,7 +5,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/scripts/check_dependencies.py b/scripts/check_dependencies.py index 1d8ffff3e..9eaa8fe25 100755 --- a/scripts/check_dependencies.py +++ b/scripts/check_dependencies.py @@ -5,7 +5,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/scripts/clean_up_resources.py b/scripts/clean_up_resources.py index 77fddc47a..baad3e1f6 100755 --- a/scripts/clean_up_resources.py +++ b/scripts/clean_up_resources.py @@ -5,7 +5,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/scripts/generate_resources.sh b/scripts/generate_resources.sh index 84d345756..231a9bdca 100755 --- a/scripts/generate_resources.sh +++ b/scripts/generate_resources.sh @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/scripts/jenkins_script.py b/scripts/jenkins_script.py index c7ca693be..5a1e67c45 100755 --- a/scripts/jenkins_script.py +++ b/scripts/jenkins_script.py @@ -5,7 +5,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -57,16 +57,17 @@ class OpenLPJobs(object): This class holds any jobs we have on jenkins and we actually need in this script. """ Branch_Pull = 'Branch-01-Pull' - Branch_Functional = 'Branch-02-Functional-Tests' - Branch_Interface = 'Branch-03-Interface-Tests' - Branch_PEP = 'Branch-04a-Code_Analysis' - Branch_Coverage = 'Branch-04b-Test_Coverage' - Branch_Pylint = 'Branch-04c-Code_Analysis2' - Branch_AppVeyor = 'Branch-05-AppVeyor-Tests' - Branch_macOS = 'Branch-07-macOS-Tests' + Branch_Linux_Tests = 'Branch-02a-Linux-Tests' + Branch_macOS_Tests = 'Branch-02b-macOS-Tests' + Branch_Build_Source = 'Branch-03a-Build-Source' + Branch_Build_macOS = 'Branch-03b-Build-macOS' + Branch_Code_Analysis = 'Branch-04a-Code-Analysis' + Branch_Test_Coverage = 'Branch-04b-Test-Coverage' + Branch_Lint_Check = 'Branch-04c-Lint-Check' + Branch_AppVeyor_Tests = 'Branch-05-AppVeyor-Tests' - Jobs = [Branch_Pull, Branch_Functional, Branch_Interface, Branch_PEP, Branch_Coverage, Branch_Pylint, - Branch_AppVeyor, Branch_macOS] + Jobs = [Branch_Pull, Branch_Linux_Tests, Branch_macOS_Tests, Branch_Build_Source, Branch_Build_macOS, + Branch_Code_Analysis, Branch_Test_Coverage, Branch_AppVeyor_Tests] class Colour(object): @@ -157,11 +158,12 @@ class JenkinsTrigger(object): """ queue_info = self.server.get_queue_info() tries = 0 - while queue_info and tries < 50: + loop_count = 100 + while queue_info and tries < loop_count: tries += 1 - time.sleep(0.5) + time.sleep(1) queue_info = self.server.get_queue_info() - if tries >= 50: + if tries >= loop_count: raise Exception('Build has not started yet, it may be stuck in the queue.') return self.server.get_build_info(job_name, build_number) diff --git a/scripts/lp-merge.py b/scripts/lp-merge.py index c59e03705..393cf7e9f 100755 --- a/scripts/lp-merge.py +++ b/scripts/lp-merge.py @@ -5,7 +5,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/scripts/resources.patch b/scripts/resources.patch index 11fa85531..6be6ac514 100644 --- a/scripts/resources.patch +++ b/scripts/resources.patch @@ -14,7 +14,7 @@ +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # -+# Copyright (c) 2008-2017 OpenLP Developers # ++# Copyright (c) 2008-2018 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 # diff --git a/scripts/translation_utils.py b/scripts/translation_utils.py index 0489eec23..44f2476f5 100755 --- a/scripts/translation_utils.py +++ b/scripts/translation_utils.py @@ -5,7 +5,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/scripts/websocket_client.py b/scripts/websocket_client.py index bf1aa5e0f..03a208a6f 100755 --- a/scripts/websocket_client.py +++ b/scripts/websocket_client.py @@ -5,7 +5,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/setup.py b/setup.py index 24a4d15db..fdbcdaea5 100755 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/__init__.py b/tests/__init__.py index 051801ce1..0980890eb 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/functional/__init__.py b/tests/functional/__init__.py index bb8d97f15..3acbe4f00 100644 --- a/tests/functional/__init__.py +++ b/tests/functional/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,7 +22,6 @@ """ Base directory for tests """ -import sys from PyQt5 import QtWidgets # Only one QApplication can be created. Use QtWidgets.QApplication.instance() when you need to "create" a QApplication. diff --git a/tests/functional/openlp_core/__init__.py b/tests/functional/openlp_core/__init__.py index e69de29bb..711ded4ae 100644 --- a/tests/functional/openlp_core/__init__.py +++ b/tests/functional/openlp_core/__init__.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2018 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 # +############################################################################### diff --git a/tests/functional/openlp_core/api/__init__.py b/tests/functional/openlp_core/api/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/functional/openlp_core/api/__init__.py +++ b/tests/functional/openlp_core/api/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/functional/openlp_core/api/http/__init__.py b/tests/functional/openlp_core/api/http/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/functional/openlp_core/api/http/__init__.py +++ b/tests/functional/openlp_core/api/http/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/functional/openlp_core/api/http/test_error.py b/tests/functional/openlp_core/api/http/test_error.py index 599ecfc03..8e13a1dcc 100644 --- a/tests/functional/openlp_core/api/http/test_error.py +++ b/tests/functional/openlp_core/api/http/test_error.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,38 +22,40 @@ """ Functional tests to test the API Error Class. """ - -from unittest import TestCase - -from openlp.core.api.http.errors import NotFound, ServerError +from openlp.core.api.http.errors import HttpError, NotFound, ServerError -class TestApiError(TestCase): +def test_http_error(): """ - A test suite to test out the Error in the API code + Test the HTTPError class """ - def test_not_found(self): - """ - Test the Not Found error displays the correct information - """ - # GIVEN: - # WHEN: I raise an exception - with self.assertRaises(Exception) as context: - raise NotFound() + # GIVEN: An HTTPError class + # WHEN: An instance is created + error = HttpError(400, 'Access Denied') - # THEN: we get an error and a status - assert 'Not Found' == context.exception.message, 'A Not Found exception should be thrown' - assert 404 == context.exception.status, 'A 404 status should be thrown' + # THEN: The to_response() method should return the correct information + assert error.to_response() == ('Access Denied', 400), 'to_response() should have returned the correct info' - def test_server_error(self): - """ - Test the server error displays the correct information - """ - # GIVEN: - # WHEN: I raise an exception - with self.assertRaises(Exception) as context: - raise ServerError() - # THEN: we get an error and a status - assert'Server Error' == context.exception.message, 'A Not Found exception should be thrown' - assert 500 == context.exception.status, 'A 500 status should be thrown' +def test_not_found(): + """ + Test the Not Found error displays the correct information + """ + # GIVEN: A NotFound class + # WHEN: An instance is created + error = NotFound() + + # THEN: The to_response() method should return the correct information + assert error.to_response() == ('Not Found', 404), 'to_response() should have returned the correct info' + + +def test_server_error(): + """ + Test the server error displays the correct information + """ + # GIVEN: A ServerError class + # WHEN: An instance of the class is created + error = ServerError() + + # THEN: The to_response() method should return the correct information + assert error.to_response() == ('Server Error', 500), 'to_response() should have returned the correct info' diff --git a/tests/functional/openlp_core/api/http/test_http.py b/tests/functional/openlp_core/api/http/test_http.py index 7dd8418ae..257e0c6d1 100644 --- a/tests/functional/openlp_core/api/http/test_http.py +++ b/tests/functional/openlp_core/api/http/test_http.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -25,8 +25,8 @@ Functional tests to test the Http Server Class. from unittest import TestCase from unittest.mock import MagicMock, patch -from openlp.core.common.registry import Registry from openlp.core.api.http.server import HttpServer +from openlp.core.common.registry import Registry class TestHttpServer(TestCase): @@ -42,23 +42,8 @@ class TestHttpServer(TestCase): Registry().register('service_list', MagicMock()) @patch('openlp.core.api.http.server.HttpWorker') - @patch('openlp.core.api.http.server.QtCore.QThread') - def test_server_start(self, mock_qthread, mock_thread): - """ - Test the starting of the Waitress Server with the disable flag set off - """ - # GIVEN: A new httpserver - # WHEN: I start the server - Registry().set_flag('no_web_server', True) - HttpServer() - - # THEN: the api environment should have been created - assert mock_qthread.call_count == 1, 'The qthread should have been called once' - assert mock_thread.call_count == 1, 'The http thread should have been called once' - - @patch('openlp.core.api.http.server.HttpWorker') - @patch('openlp.core.api.http.server.QtCore.QThread') - def test_server_start_not_required(self, mock_qthread, mock_thread): + @patch('openlp.core.api.http.server.run_thread') + def test_server_start(self, mocked_run_thread, MockHttpWorker): """ Test the starting of the Waitress Server with the disable flag set off """ @@ -68,5 +53,20 @@ class TestHttpServer(TestCase): HttpServer() # THEN: the api environment should have been created - assert mock_qthread.call_count == 0, 'The qthread should not have have been called' - assert mock_thread.call_count == 0, 'The http thread should not have been called' + assert mocked_run_thread.call_count == 1, 'The qthread should have been called once' + assert MockHttpWorker.call_count == 1, 'The http thread should have been called once' + + @patch('openlp.core.api.http.server.HttpWorker') + @patch('openlp.core.api.http.server.run_thread') + def test_server_start_not_required(self, mocked_run_thread, MockHttpWorker): + """ + Test the starting of the Waitress Server with the disable flag set off + """ + # GIVEN: A new httpserver + # WHEN: I start the server + Registry().set_flag('no_web_server', True) + HttpServer() + + # THEN: the api environment should have been created + assert mocked_run_thread.call_count == 0, 'The qthread should not have have been called' + assert MockHttpWorker.call_count == 0, 'The http thread should not have been called' diff --git a/tests/functional/openlp_core/api/http/test_wsgiapp.py b/tests/functional/openlp_core/api/http/test_wsgiapp.py index 17b3ae8c5..a7cf331b5 100644 --- a/tests/functional/openlp_core/api/http/test_wsgiapp.py +++ b/tests/functional/openlp_core/api/http/test_wsgiapp.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -23,12 +23,11 @@ Functional test the routing code. """ import os - from unittest import TestCase from unittest.mock import MagicMock -from openlp.core.api.http.endpoint import Endpoint from openlp.core.api.http import register_endpoint, application, NotFound +from openlp.core.api.http.endpoint import Endpoint ROOT_DIR = os.path.dirname(os.path.realpath(__file__)) diff --git a/tests/functional/openlp_core/api/test_deploy.py b/tests/functional/openlp_core/api/test_deploy.py index 0aaf1308b..d46ac8d43 100644 --- a/tests/functional/openlp_core/api/test_deploy.py +++ b/tests/functional/openlp_core/api/test_deploy.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -21,11 +21,12 @@ ############################################################################### from tempfile import mkdtemp from unittest import TestCase +from unittest.mock import MagicMock, patch -from openlp.core.api.deploy import deploy_zipfile -from openlp.core.common.path import Path, copyfile +from openlp.core.api.deploy import deploy_zipfile, download_sha256, download_and_check +from openlp.core.common.path import Path -TEST_PATH = (Path(__file__).parent / '..' / '..' / '..' / 'resources').resolve() +CONFIG_FILE = '2c266badff1e3d140664c50fd1460a2b332b24d5ad8c267fa62e506b5eb6d894 deploy/site.zip\n2017_06_27' class TestRemoteDeploy(TestCase): @@ -45,17 +46,95 @@ class TestRemoteDeploy(TestCase): """ self.app_root_path.rmtree() - def test_deploy_zipfile(self): + @patch('openlp.core.api.deploy.ZipFile') + def test_deploy_zipfile(self, MockZipFile): """ Remote Deploy tests - test the dummy zip file is processed correctly """ # GIVEN: A new downloaded zip file - zip_path = TEST_PATH / 'remotes' / 'site.zip' - app_root_path = self.app_root_path / 'site.zip' - copyfile(zip_path, app_root_path) + mocked_zipfile = MagicMock() + MockZipFile.return_value = mocked_zipfile + root_path = Path('/tmp/remotes') - # WHEN: I process the zipfile - deploy_zipfile(self.app_root_path, 'site.zip') + # WHEN: deploy_zipfile() is called + deploy_zipfile(root_path, 'site.zip') - # THEN: test if www directory has been created - assert (self.app_root_path / 'www').is_dir(), 'We should have a www directory' + # THEN: the zip file should have been extracted to the right location + MockZipFile.assert_called_once_with('/tmp/remotes/site.zip') + mocked_zipfile.extractall.assert_called_once_with('/tmp/remotes') + + @patch('openlp.core.api.deploy.Registry') + @patch('openlp.core.api.deploy.get_web_page') + def test_download_sha256_connection_error(self, mocked_get_web_page, MockRegistry): + """ + Test that if a ConnectionError occurs while downloading a sha256 False is returned + """ + # GIVEN: A bunch of mocks + MockRegistry.return_value.get.return_value.applicationVersion.return_value = '1.0' + mocked_get_web_page.side_effect = ConnectionError() + + # WHEN: download_sha256() is called + result = download_sha256() + + # THEN: The result should be False + assert result is False, 'download_sha256() should return False when encountering ConnectionError' + + @patch('openlp.core.api.deploy.Registry') + @patch('openlp.core.api.deploy.get_web_page') + def test_download_sha256_no_config(self, mocked_get_web_page, MockRegistry): + """ + Test that if there's no config when downloading a sha256 None is returned + """ + # GIVEN: A bunch of mocks + MockRegistry.return_value.get.return_value.applicationVersion.return_value = '1.0' + mocked_get_web_page.return_value = None + + # WHEN: download_sha256() is called + result = download_sha256() + + # THEN: The result should be Nonw + assert result is None, 'download_sha256() should return None when there is a problem downloading the page' + + @patch('openlp.core.api.deploy.Registry') + @patch('openlp.core.api.deploy.get_web_page') + def test_download_sha256(self, mocked_get_web_page, MockRegistry): + """ + Test that the sha256 and the version are returned + """ + # GIVEN: A bunch of mocks + MockRegistry.return_value.get.return_value.applicationVersion.return_value = '1.0' + mocked_get_web_page.return_value = CONFIG_FILE + + # WHEN: download_sha256() is called + result = download_sha256() + + # THEN: The result should be Nonw + assert result == ('2c266badff1e3d140664c50fd1460a2b332b24d5ad8c267fa62e506b5eb6d894', '2017_06_27'), \ + 'download_sha256() should return a tuple of sha256 and version' + + @patch('openlp.core.api.deploy.Registry') + @patch('openlp.core.api.deploy.download_sha256') + @patch('openlp.core.api.deploy.get_url_file_size') + @patch('openlp.core.api.deploy.download_file') + @patch('openlp.core.api.deploy.AppLocation.get_section_data_path') + @patch('openlp.core.api.deploy.deploy_zipfile') + def test_download_and_check(self, mocked_deploy_zipfile, mocked_get_data_path, mocked_download_file, + mocked_get_url_file_size, mocked_download_sha256, MockRegistry): + # GIVEN: A bunch of mocks + mocked_get_data_path.return_value = Path('/tmp/remotes') + mocked_download_file.return_value = True + mocked_get_url_file_size.return_value = 5 + mocked_download_sha256.return_value = ('asdfgh', '0.1') + MockRegistry.return_value.get.return_value.applicationVersion.return_value = '1.0' + mocked_callback = MagicMock() + + # WHEN: download_and_check() is called + download_and_check(mocked_callback) + + # THEN: The correct things should have been done + mocked_download_sha256.assert_called_once_with() + mocked_get_url_file_size.assert_called_once_with('https://get.openlp.org/webclient/site.zip') + mocked_callback.setRange.assert_called_once_with(0, 5) + mocked_download_file.assert_called_once_with(mocked_callback, 'https://get.openlp.org/webclient/site.zip', + Path('/tmp/remotes/site.zip'), sha256='asdfgh') + mocked_deploy_zipfile.assert_called_once_with(Path('/tmp/remotes'), 'site.zip') diff --git a/tests/functional/openlp_core/api/test_tab.py b/tests/functional/openlp_core/api/test_tab.py index bd701784d..0de0b6d94 100644 --- a/tests/functional/openlp_core/api/test_tab.py +++ b/tests/functional/openlp_core/api/test_tab.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,16 +22,15 @@ """ This module contains tests for the lib submodule of the Remotes plugin. """ -import os import re from unittest import TestCase from unittest.mock import patch from PyQt5 import QtWidgets +from openlp.core.api.tab import ApiTab from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings -from openlp.core.api.tab import ApiTab from tests.helpers.testmixin import TestMixin __default_settings__ = { @@ -45,7 +44,6 @@ __default_settings__ = { 'remotes/download version': '0000_00_00' } ZERO_URL = '0.0.0.0' -TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources')) class TestApiTab(TestCase, TestMixin): diff --git a/tests/functional/openlp_core/api/test_websockets.py b/tests/functional/openlp_core/api/test_websockets.py index 7da90123d..3d9bcf682 100644 --- a/tests/functional/openlp_core/api/test_websockets.py +++ b/tests/functional/openlp_core/api/test_websockets.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -25,10 +25,10 @@ Functional tests to test the Http Server Class. from unittest import TestCase from unittest.mock import MagicMock, patch +from openlp.core.api.poll import Poller +from openlp.core.api.websockets import WebSocketServer from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings -from openlp.core.api.websockets import WebSocketServer -from openlp.core.api.poll import Poller from tests.helpers.testmixin import TestMixin __default_settings__ = { @@ -63,34 +63,34 @@ class TestWSServer(TestCase, TestMixin): self.destroy_settings() @patch('openlp.core.api.websockets.WebSocketWorker') - @patch('openlp.core.api.websockets.QtCore.QThread') - def test_serverstart(self, mock_qthread, mock_worker): + @patch('openlp.core.api.websockets.run_thread') + def test_serverstart(self, mocked_run_thread, MockWebSocketWorker): """ Test the starting of the WebSockets Server with the disabled flag set on """ # GIVEN: A new httpserver # WHEN: I start the server - Registry().set_flag('no_web_server', True) + Registry().set_flag('no_web_server', False) WebSocketServer() # THEN: the api environment should have been created - assert mock_qthread.call_count == 1, 'The qthread should have been called once' - assert mock_worker.call_count == 1, 'The http thread should have been called once' + assert mocked_run_thread.call_count == 1, 'The qthread should have been called once' + assert MockWebSocketWorker.call_count == 1, 'The http thread should have been called once' @patch('openlp.core.api.websockets.WebSocketWorker') - @patch('openlp.core.api.websockets.QtCore.QThread') - def test_serverstart_not_required(self, mock_qthread, mock_worker): + @patch('openlp.core.api.websockets.run_thread') + def test_serverstart_not_required(self, mocked_run_thread, MockWebSocketWorker): """ Test the starting of the WebSockets Server with the disabled flag set off """ # GIVEN: A new httpserver and the server is not required # WHEN: I start the server - Registry().set_flag('no_web_server', False) + Registry().set_flag('no_web_server', True) WebSocketServer() # THEN: the api environment should have been created - assert mock_qthread.call_count == 0, 'The qthread should not have been called' - assert mock_worker.call_count == 0, 'The http thread should not have been called' + assert mocked_run_thread.call_count == 0, 'The qthread should not have been called' + assert MockWebSocketWorker.call_count == 0, 'The http thread should not have been called' def test_main_poll(self): """ diff --git a/tests/functional/openlp_core/common/__init__.py b/tests/functional/openlp_core/common/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/functional/openlp_core/common/__init__.py +++ b/tests/functional/openlp_core/common/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/functional/openlp_core/common/test_actions.py b/tests/functional/openlp_core/common/test_actions.py index 7d5ac6fca..517d76fab 100644 --- a/tests/functional/openlp_core/common/test_actions.py +++ b/tests/functional/openlp_core/common/test_actions.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -29,7 +29,6 @@ from PyQt5 import QtGui, QtCore, QtWidgets from openlp.core.common.actions import CategoryActionList, ActionList from openlp.core.common.settings import Settings - from tests.helpers.testmixin import TestMixin diff --git a/tests/functional/openlp_core/common/test_applocation.py b/tests/functional/openlp_core/common/test_applocation.py index 551287476..5d54deba3 100644 --- a/tests/functional/openlp_core/common/test_applocation.py +++ b/tests/functional/openlp_core/common/test_applocation.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/functional/openlp_core/common/test_common.py b/tests/functional/openlp_core/common/test_common.py index 368705821..b4554d198 100644 --- a/tests/functional/openlp_core/common/test_common.py +++ b/tests/functional/openlp_core/common/test_common.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/functional/openlp_core/common/test_db.py b/tests/functional/openlp_core/common/test_db.py index 75bdde228..7fe59b35f 100644 --- a/tests/functional/openlp_core/common/test_db.py +++ b/tests/functional/openlp_core/common/test_db.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/functional/openlp_core/common/test_httputils.py b/tests/functional/openlp_core/common/test_httputils.py index b7c08993f..7d3966279 100644 --- a/tests/functional/openlp_core/common/test_httputils.py +++ b/tests/functional/openlp_core/common/test_httputils.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -27,9 +27,8 @@ import tempfile from unittest import TestCase from unittest.mock import MagicMock, patch -from openlp.core.common.httputils import get_user_agent, get_web_page, get_url_file_size, url_get_file +from openlp.core.common.httputils import get_user_agent, get_web_page, get_url_file_size, download_file from openlp.core.common.path import Path - from tests.helpers.testmixin import TestMixin @@ -236,7 +235,7 @@ class TestHttpUtils(TestCase, TestMixin): mocked_requests.get.side_effect = OSError # WHEN: Attempt to retrieve a file - url_get_file(MagicMock(), url='http://localhost/test', file_path=Path(self.tempfile)) + download_file(MagicMock(), url='http://localhost/test', file_path=Path(self.tempfile)) # THEN: socket.timeout should have been caught # NOTE: Test is if $tmpdir/tempfile is still there, then test fails since ftw deletes bad downloaded files diff --git a/tests/functional/openlp_core/common/test_i18n.py b/tests/functional/openlp_core/common/test_i18n.py index 4f4ca2aec..16d321f4f 100644 --- a/tests/functional/openlp_core/common/test_i18n.py +++ b/tests/functional/openlp_core/common/test_i18n.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/functional/openlp_core/common/test_init.py b/tests/functional/openlp_core/common/test_init.py index 9965a07ee..83f0c1c7c 100644 --- a/tests/functional/openlp_core/common/test_init.py +++ b/tests/functional/openlp_core/common/test_init.py @@ -22,15 +22,13 @@ """ Functional tests to test the AppLocation class and related methods. """ -import os from io import BytesIO from unittest import TestCase from unittest.mock import MagicMock, PropertyMock, call, patch -from openlp.core.common import add_actions, clean_filename, delete_file, get_file_encoding, get_filesystem_encoding, \ +from openlp.core.common import add_actions, clean_filename, delete_file, get_file_encoding, get_filesystem_encoding, \ get_uno_command, get_uno_instance from openlp.core.common.path import Path - from tests.helpers.testmixin import TestMixin diff --git a/tests/functional/openlp_core/common/test_json.py b/tests/functional/openlp_core/common/test_json.py index 18cba3b4e..31392c70d 100644 --- a/tests/functional/openlp_core/common/test_json.py +++ b/tests/functional/openlp_core/common/test_json.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -26,8 +26,8 @@ import json from unittest import TestCase from unittest.mock import patch -from openlp.core.common.path import Path from openlp.core.common.json import OpenLPJsonDecoder, OpenLPJsonEncoder +from openlp.core.common.path import Path class TestOpenLPJsonDecoder(TestCase): diff --git a/tests/functional/openlp_core/common/test_mixins.py b/tests/functional/openlp_core/common/test_mixins.py index f49c2b797..ba202a2ab 100644 --- a/tests/functional/openlp_core/common/test_mixins.py +++ b/tests/functional/openlp_core/common/test_mixins.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/functional/openlp_core/common/test_path.py b/tests/functional/openlp_core/common/test_path.py index b069c251d..39bb68f92 100644 --- a/tests/functional/openlp_core/common/test_path.py +++ b/tests/functional/openlp_core/common/test_path.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -27,7 +27,7 @@ from unittest import TestCase from unittest.mock import ANY, MagicMock, patch from openlp.core.common.path import Path, copy, copyfile, copytree, create_paths, path_to_str, replace_params, \ - str_to_path, which + str_to_path, which, files_to_paths class TestShutil(TestCase): @@ -401,3 +401,16 @@ class TestPath(TestCase): except: # THEN: `create_paths` raises an exception pass + + def test_files_to_paths(self): + """ + Test the files_to_paths() method + """ + # GIVEN: A list of string filenames + test_files = ['/tmp/openlp/file1.txt', '/tmp/openlp/file2.txt'] + + # WHEN: files_to_paths is called + result = files_to_paths(test_files) + + # THEN: The result should be a list of Paths + assert result == [Path('/tmp/openlp/file1.txt'), Path('/tmp/openlp/file2.txt')] diff --git a/tests/functional/openlp_core/common/test_projector_utilities.py b/tests/functional/openlp_core/common/test_projector_utilities.py index 5a3f886cf..ecdb5a240 100644 --- a/tests/functional/openlp_core/common/test_projector_utilities.py +++ b/tests/functional/openlp_core/common/test_projector_utilities.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -26,7 +26,6 @@ Package to test the openlp.core.ui.projector.networkutils package. from unittest import TestCase from openlp.core.common import verify_ip_address, md5_hash, qmd5_hash - from tests.resources.projector.data import TEST_PIN, TEST_SALT, TEST_HASH salt = TEST_SALT diff --git a/tests/functional/openlp_core/common/test_registry.py b/tests/functional/openlp_core/common/test_registry.py index 6f3cc5752..b5cf106b2 100644 --- a/tests/functional/openlp_core/common/test_registry.py +++ b/tests/functional/openlp_core/common/test_registry.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,14 +22,11 @@ """ Package to test the openlp.core.lib package. """ -import os from unittest import TestCase from unittest.mock import MagicMock from openlp.core.common.registry import Registry, RegistryBase -TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '../', '..', 'resources')) - class TestRegistry(TestCase): diff --git a/tests/functional/openlp_core/common/test_settings.py b/tests/functional/openlp_core/common/test_settings.py index 4cad58af0..d39b0adf8 100644 --- a/tests/functional/openlp_core/common/test_settings.py +++ b/tests/functional/openlp_core/common/test_settings.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -28,7 +28,6 @@ from unittest.mock import call, patch from openlp.core.common import settings from openlp.core.common.settings import Settings, media_players_conv - from tests.helpers.testmixin import TestMixin diff --git a/tests/functional/openlp_core/display/__init__.py b/tests/functional/openlp_core/display/__init__.py index 96d55e7e8..a1a7979b5 100644 --- a/tests/functional/openlp_core/display/__init__.py +++ b/tests/functional/openlp_core/display/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/functional/openlp_core/display/test_renderer.py b/tests/functional/openlp_core/display/test_renderer.py index b1478c7b9..c1d03a1e1 100644 --- a/tests/functional/openlp_core/display/test_renderer.py +++ b/tests/functional/openlp_core/display/test_renderer.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -28,12 +28,11 @@ from unittest.mock import MagicMock, patch from PyQt5 import QtCore from openlp.core.common.registry import Registry -from openlp.core.display.screens import ScreenList from openlp.core.display.renderer import Renderer, words_split, get_start_tags +from openlp.core.display.screens import ScreenList from openlp.core.lib import ServiceItem from openlp.core.lib.theme import Theme - SCREEN = { 'primary': False, 'number': 1, diff --git a/tests/functional/openlp_core/display/test_screens.py b/tests/functional/openlp_core/display/test_screens.py index 960f9d0a8..0d36b7ceb 100644 --- a/tests/functional/openlp_core/display/test_screens.py +++ b/tests/functional/openlp_core/display/test_screens.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/functional/openlp_core/lib/test_db.py b/tests/functional/openlp_core/lib/test_db.py index 033508965..cc928ac56 100644 --- a/tests/functional/openlp_core/lib/test_db.py +++ b/tests/functional/openlp_core/lib/test_db.py @@ -23,14 +23,13 @@ Package to test the openlp.core.lib package. """ import shutil - from tempfile import mkdtemp from unittest import TestCase from unittest.mock import patch, MagicMock -from sqlalchemy.pool import NullPool -from sqlalchemy.orm.scoping import ScopedSession from sqlalchemy import MetaData +from sqlalchemy.orm.scoping import ScopedSession +from sqlalchemy.pool import NullPool from openlp.core.common.path import Path from openlp.core.lib.db import init_db, get_upgrade_op, delete_database, upgrade_db diff --git a/tests/functional/openlp_core/lib/test_htmlbuilder.py b/tests/functional/openlp_core/lib/test_htmlbuilder.py index ffd796ecb..11bfde2b6 100644 --- a/tests/functional/openlp_core/lib/test_htmlbuilder.py +++ b/tests/functional/openlp_core/lib/test_htmlbuilder.py @@ -10,7 +10,6 @@ from openlp.core.common.settings import Settings from openlp.core.lib.htmlbuilder import build_html, build_background_css, build_lyrics_css, build_lyrics_outline_css, \ build_lyrics_format_css, build_footer_css, webkit_version, build_chords_css from openlp.core.lib.theme import HorizontalType, VerticalType - from tests.helpers.testmixin import TestMixin HTML = """ diff --git a/tests/functional/openlp_core/lib/test_image_manager.py b/tests/functional/openlp_core/lib/test_image_manager.py index 3c47e81a1..9cee73739 100644 --- a/tests/functional/openlp_core/lib/test_image_manager.py +++ b/tests/functional/openlp_core/lib/test_image_manager.py @@ -25,20 +25,113 @@ Package to test the openlp.core.ui package. import os import time from threading import Lock -from unittest import TestCase -from unittest.mock import patch +from unittest import TestCase, skip +from unittest.mock import MagicMock, patch from PyQt5 import QtGui from openlp.core.common.registry import Registry from openlp.core.display.screens import ScreenList -from openlp.core.lib.imagemanager import ImageManager, Priority - +from openlp.core.lib.imagemanager import ImageWorker, ImageManager, Priority, PriorityQueue from tests.helpers.testmixin import TestMixin +from tests.utils.constants import RESOURCE_PATH -TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources')) +TEST_PATH = str(RESOURCE_PATH) +class TestImageWorker(TestCase, TestMixin): + """ + Test all the methods in the ImageWorker class + """ + def test_init(self): + """ + Test the constructor of the ImageWorker + """ + # GIVEN: An ImageWorker class and a mocked ImageManager + mocked_image_manager = MagicMock() + + # WHEN: Creating the ImageWorker + worker = ImageWorker(mocked_image_manager) + + # THEN: The image_manager attribute should be set correctly + assert worker.image_manager is mocked_image_manager, \ + 'worker.image_manager should have been the mocked_image_manager' + + @patch('openlp.core.lib.imagemanager.ThreadWorker.quit') + def test_start(self, mocked_quit): + """ + Test that the start() method of the image worker calls the process method and then emits quit. + """ + # GIVEN: A mocked image_manager and a new image worker + mocked_image_manager = MagicMock() + worker = ImageWorker(mocked_image_manager) + + # WHEN: start() is called + worker.start() + + # THEN: process() should have been called and quit should have been emitted + mocked_image_manager.process.assert_called_once_with() + mocked_quit.emit.assert_called_once_with() + + def test_stop(self): + """ + Test that the stop method does the right thing + """ + # GIVEN: A mocked image_manager and a worker + mocked_image_manager = MagicMock() + worker = ImageWorker(mocked_image_manager) + + # WHEN: The stop() method is called + worker.stop() + + # THEN: The stop_manager attrivute should have been set to True + assert mocked_image_manager.stop_manager is True, 'mocked_image_manager.stop_manager should have been True' + + +class TestPriorityQueue(TestCase, TestMixin): + """ + Test the PriorityQueue class + """ + @patch('openlp.core.lib.imagemanager.PriorityQueue.remove') + @patch('openlp.core.lib.imagemanager.PriorityQueue.put') + def test_modify_priority(self, mocked_put, mocked_remove): + """ + Test the modify_priority() method of PriorityQueue + """ + # GIVEN: An instance of a PriorityQueue and a mocked image + mocked_image = MagicMock() + mocked_image.priority = Priority.Normal + mocked_image.secondary_priority = Priority.Low + queue = PriorityQueue() + + # WHEN: modify_priority is called with a mocked image and a new priority + queue.modify_priority(mocked_image, Priority.High) + + # THEN: The remove() method should have been called, image priority updated and put() called + mocked_remove.assert_called_once_with(mocked_image) + assert mocked_image.priority == Priority.High, 'The priority should have been Priority.High' + mocked_put.assert_called_once_with((Priority.High, Priority.Low, mocked_image)) + + def test_remove(self): + """ + Test the remove() method of PriorityQueue + """ + # GIVEN: A PriorityQueue instance with a mocked image and queue + mocked_image = MagicMock() + mocked_image.priority = Priority.High + mocked_image.secondary_priority = Priority.Normal + queue = PriorityQueue() + + # WHEN: An image is removed + with patch.object(queue, 'queue') as mocked_queue: + mocked_queue.__contains__.return_value = True + queue.remove(mocked_image) + + # THEN: The mocked queue.remove() method should have been called + mocked_queue.remove.assert_called_once_with((Priority.High, Priority.Normal, mocked_image)) + + +@skip('Probably not going to use ImageManager in WebEngine/Reveal.js') class TestImageManager(TestCase, TestMixin): def setUp(self): @@ -57,10 +150,10 @@ class TestImageManager(TestCase, TestMixin): Delete all the C++ objects at the end so that we don't have a segfault """ self.image_manager.stop_manager = True - self.image_manager.image_thread.wait() del self.app - def test_basic_image_manager(self): + @patch('openlp.core.lib.imagemanager.run_thread') + def test_basic_image_manager(self, mocked_run_thread): """ Test the Image Manager setup basic functionality """ @@ -72,13 +165,13 @@ class TestImageManager(TestCase, TestMixin): image = self.image_manager.get_image(full_path, 'church.jpg') # THEN returned record is a type of image - self.assertEqual(isinstance(image, QtGui.QImage), True, 'The returned object should be a QImage') + assert isinstance(image, QtGui.QImage), 'The returned object should be a QImage' # WHEN: The image bytes are requested. byte_array = self.image_manager.get_image_bytes(full_path, 'church.jpg') # THEN: Type should be a str. - self.assertEqual(isinstance(byte_array, str), True, 'The returned object should be a str') + assert isinstance(byte_array, str), 'The returned object should be a str' # WHEN the image is retrieved has not been loaded # THEN a KeyError is thrown @@ -86,7 +179,8 @@ class TestImageManager(TestCase, TestMixin): self.image_manager.get_image(TEST_PATH, 'church1.jpg') assert context.exception is not '', 'KeyError exception should have been thrown for missing image' - def test_different_dimension_image(self): + @patch('openlp.core.lib.imagemanager.run_thread') + def test_different_dimension_image(self, mocked_run_thread): """ Test the Image Manager with dimensions """ @@ -104,71 +198,72 @@ class TestImageManager(TestCase, TestMixin): self.image_manager.add_image(full_path, 'church.jpg', None, 100, 100) # THEN: the cache should contain two pictures - self.assertEqual(len(self.image_manager._cache), 2, - 'Image manager should consider two dimensions of the same picture as different') + assert len(self.image_manager._cache) == 2, \ + 'Image manager should consider two dimensions of the same picture as different' # WHEN: adding the same image with first dimensions self.image_manager.add_image(full_path, 'church.jpg', None, 80, 80) # THEN: the cache should still contain only two pictures - self.assertEqual(len(self.image_manager._cache), 2, 'Same dimensions should not be added again') + assert len(self.image_manager._cache) == 2, 'Same dimensions should not be added again' # WHEN: calling with correct image, but wrong dimensions with self.assertRaises(KeyError) as context: self.image_manager.get_image(full_path, 'church.jpg', 120, 120) assert context.exception is not '', 'KeyError exception should have been thrown for missing dimension' - def test_process_cache(self): + @patch('openlp.core.lib.imagemanager.resize_image') + @patch('openlp.core.lib.imagemanager.image_to_byte') + @patch('openlp.core.lib.imagemanager.run_thread') + def test_process_cache(self, mocked_run_thread, mocked_image_to_byte, mocked_resize_image): """ Test the process_cache method """ - with patch('openlp.core.lib.imagemanager.resize_image') as mocked_resize_image, \ - patch('openlp.core.lib.imagemanager.image_to_byte') as mocked_image_to_byte: - # GIVEN: Mocked functions - mocked_resize_image.side_effect = self.mocked_resize_image - mocked_image_to_byte.side_effect = self.mocked_image_to_byte - image1 = 'church.jpg' - image2 = 'church2.jpg' - image3 = 'church3.jpg' - image4 = 'church4.jpg' + # GIVEN: Mocked functions + mocked_resize_image.side_effect = self.mocked_resize_image + mocked_image_to_byte.side_effect = self.mocked_image_to_byte + image1 = 'church.jpg' + image2 = 'church2.jpg' + image3 = 'church3.jpg' + image4 = 'church4.jpg' - # WHEN: Add the images. Then get the lock (=queue can not be processed). - self.lock.acquire() - self.image_manager.add_image(TEST_PATH, image1, None) - self.image_manager.add_image(TEST_PATH, image2, None) + # WHEN: Add the images. Then get the lock (=queue can not be processed). + self.lock.acquire() + self.image_manager.add_image(TEST_PATH, image1, None) + self.image_manager.add_image(TEST_PATH, image2, None) - # THEN: All images have been added to the queue, and only the first image is not be in the list anymore, but - # is being processed (see mocked methods/functions). - # Note: Priority.Normal means, that the resize_image() was not completed yet (because afterwards the # - # priority is adjusted to Priority.Lowest). - assert self.get_image_priority(image1) == Priority.Normal, "image1's priority should be 'Priority.Normal'" - assert self.get_image_priority(image2) == Priority.Normal, "image2's priority should be 'Priority.Normal'" + # THEN: All images have been added to the queue, and only the first image is not be in the list anymore, but + # is being processed (see mocked methods/functions). + # Note: Priority.Normal means, that the resize_image() was not completed yet (because afterwards the # + # priority is adjusted to Priority.Lowest). + assert self.get_image_priority(image1) == Priority.Normal, "image1's priority should be 'Priority.Normal'" + assert self.get_image_priority(image2) == Priority.Normal, "image2's priority should be 'Priority.Normal'" - # WHEN: Add more images. - self.image_manager.add_image(TEST_PATH, image3, None) - self.image_manager.add_image(TEST_PATH, image4, None) - # Allow the queue to process. - self.lock.release() - # Request some "data". - self.image_manager.get_image_bytes(TEST_PATH, image4) - self.image_manager.get_image(TEST_PATH, image3) - # Now the mocked methods/functions do not have to sleep anymore. - self.sleep_time = 0 - # Wait for the queue to finish. - while not self.image_manager._conversion_queue.empty(): - time.sleep(0.1) - # Because empty() is not reliable, wait a litte; just to make sure. + # WHEN: Add more images. + self.image_manager.add_image(TEST_PATH, image3, None) + self.image_manager.add_image(TEST_PATH, image4, None) + # Allow the queue to process. + self.lock.release() + # Request some "data". + self.image_manager.get_image_bytes(TEST_PATH, image4) + self.image_manager.get_image(TEST_PATH, image3) + # Now the mocked methods/functions do not have to sleep anymore. + self.sleep_time = 0 + # Wait for the queue to finish. + while not self.image_manager._conversion_queue.empty(): time.sleep(0.1) - # THEN: The images' priority reflect how they were processed. - assert self.image_manager._conversion_queue.qsize() == 0, "The queue should be empty." - assert self.get_image_priority(image1) == Priority.Lowest, \ - "The image should have not been requested (=Lowest)" - assert self.get_image_priority(image2) == Priority.Lowest, \ - "The image should have not been requested (=Lowest)" - assert self.get_image_priority(image3) == Priority.Low, \ - "Only the QImage should have been requested (=Low)." - assert self.get_image_priority(image4) == Priority.Urgent, \ - "The image bytes should have been requested (=Urgent)." + # Because empty() is not reliable, wait a litte; just to make sure. + time.sleep(0.1) + # THEN: The images' priority reflect how they were processed. + assert self.image_manager._conversion_queue.qsize() == 0, "The queue should be empty." + assert self.get_image_priority(image1) == Priority.Lowest, \ + "The image should have not been requested (=Lowest)" + assert self.get_image_priority(image2) == Priority.Lowest, \ + "The image should have not been requested (=Lowest)" + assert self.get_image_priority(image3) == Priority.Low, \ + "Only the QImage should have been requested (=Low)." + assert self.get_image_priority(image4) == Priority.Urgent, \ + "The image bytes should have been requested (=Urgent)." def get_image_priority(self, image): """ diff --git a/tests/functional/openlp_core/lib/test_lib.py b/tests/functional/openlp_core/lib/test_lib.py index 7cc44ec4e..b771d0da0 100644 --- a/tests/functional/openlp_core/lib/test_lib.py +++ b/tests/functional/openlp_core/lib/test_lib.py @@ -22,7 +22,6 @@ """ Package to test the openlp.core.lib package. """ -import os from unittest import TestCase from unittest.mock import MagicMock, patch @@ -32,8 +31,7 @@ from openlp.core.common.path import Path from openlp.core.lib import FormattingTags, build_icon, check_item_selected, clean_tags, compare_chord_lyric, \ create_separated_list, create_thumb, expand_chords, expand_chords_for_printing, expand_tags, find_formatting_tags, \ get_text_file_string, image_to_byte, resize_image, str_to_bool, validate_thumb - -TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources')) +from tests.utils.constants import RESOURCE_PATH class TestLib(TestCase): @@ -273,8 +271,8 @@ class TestLib(TestCase): Test the create_thumb() function with a given size. """ # GIVEN: An image to create a thumb of. - image_path = Path(TEST_PATH, 'church.jpg') - thumb_path = Path(TEST_PATH, 'church_thumb.jpg') + image_path = RESOURCE_PATH / 'church.jpg' + thumb_path = RESOURCE_PATH / 'church_thumb.jpg' thumb_size = QtCore.QSize(10, 20) # Remove the thumb so that the test actually tests if the thumb will be created. Maybe it was not deleted in the @@ -291,7 +289,7 @@ class TestLib(TestCase): icon = create_thumb(image_path, thumb_path, size=thumb_size) # THEN: Check if the thumb was created and scaled to the given size. - self.assertTrue(thumb_path.exists(), 'Test was not ran, because the thumb already exists') + assert thumb_path.exists() is True, 'Test was not ran, because the thumb already exists' assert isinstance(icon, QtGui.QIcon), 'The icon should be a QIcon' assert icon.isNull() is False, 'The icon should not be null' assert thumb_size == QtGui.QImageReader(str(thumb_path)).size(), 'The thumb should have the given size' @@ -307,8 +305,8 @@ class TestLib(TestCase): Test the create_thumb() function with no size specified. """ # GIVEN: An image to create a thumb of. - image_path = Path(TEST_PATH, 'church.jpg') - thumb_path = Path(TEST_PATH, 'church_thumb.jpg') + image_path = RESOURCE_PATH / 'church.jpg' + thumb_path = RESOURCE_PATH / 'church_thumb.jpg' expected_size = QtCore.QSize(63, 88) # Remove the thumb so that the test actually tests if the thumb will be created. Maybe it was not deleted in the @@ -325,7 +323,7 @@ class TestLib(TestCase): icon = create_thumb(image_path, thumb_path) # THEN: Check if the thumb was created, retaining its aspect ratio. - self.assertTrue(thumb_path.exists(), 'Test was not ran, because the thumb already exists') + assert thumb_path.exists() is True, 'Test was not ran, because the thumb already exists' assert isinstance(icon, QtGui.QIcon), 'The icon should be a QIcon' assert icon.isNull() is False, 'The icon should not be null' assert expected_size == QtGui.QImageReader(str(thumb_path)).size(), 'The thumb should have the given size' @@ -341,8 +339,8 @@ class TestLib(TestCase): Test the create_thumb() function with invalid size specified. """ # GIVEN: An image to create a thumb of. - image_path = Path(TEST_PATH, 'church.jpg') - thumb_path = Path(TEST_PATH, 'church_thumb.jpg') + image_path = RESOURCE_PATH / 'church.jpg' + thumb_path = RESOURCE_PATH / 'church_thumb.jpg' thumb_size = QtCore.QSize(-1, -1) expected_size = QtCore.QSize(63, 88) @@ -376,8 +374,8 @@ class TestLib(TestCase): Test the create_thumb() function with a size of only width specified. """ # GIVEN: An image to create a thumb of. - image_path = Path(TEST_PATH, 'church.jpg') - thumb_path = Path(TEST_PATH, 'church_thumb.jpg') + image_path = RESOURCE_PATH / 'church.jpg' + thumb_path = RESOURCE_PATH / 'church_thumb.jpg' thumb_size = QtCore.QSize(100, -1) expected_size = QtCore.QSize(100, 137) @@ -411,8 +409,8 @@ class TestLib(TestCase): Test the create_thumb() function with a size of only height specified. """ # GIVEN: An image to create a thumb of. - image_path = Path(TEST_PATH, 'church.jpg') - thumb_path = Path(TEST_PATH, 'church_thumb.jpg') + image_path = RESOURCE_PATH / 'church.jpg' + thumb_path = RESOURCE_PATH / 'church_thumb.jpg' thumb_size = QtCore.QSize(-1, 100) expected_size = QtCore.QSize(72, 100) @@ -430,7 +428,7 @@ class TestLib(TestCase): icon = create_thumb(image_path, thumb_path, size=thumb_size) # THEN: Check if the thumb was created, retaining its aspect ratio. - self.assertTrue(thumb_path.exists(), 'Test was not ran, because the thumb already exists') + assert thumb_path.exists() is True, 'Test was not ran, because the thumb already exists' assert isinstance(icon, QtGui.QIcon), 'The icon should be a QIcon' assert icon.isNull() is False, 'The icon should not be null' assert expected_size == QtGui.QImageReader(str(thumb_path)).size(), 'The thumb should have the given size' @@ -446,8 +444,8 @@ class TestLib(TestCase): Test the create_thumb() function with a size of only height specified. """ # GIVEN: An image to create a thumb of. - image_path = Path(TEST_PATH, 'church.jpg') - thumb_path = Path(TEST_PATH, 'church_thumb.jpg') + image_path = RESOURCE_PATH / 'church.jpg' + thumb_path = RESOURCE_PATH / 'church_thumb.jpg' thumb_size = QtCore.QSize(-1, 100) expected_size_1 = QtCore.QSize(88, 88) expected_size_2 = QtCore.QSize(100, 100) @@ -468,7 +466,7 @@ class TestLib(TestCase): icon = create_thumb(image_path, thumb_path, size=None) # THEN: Check if the thumb was created with aspect ratio of 1. - self.assertTrue(thumb_path.exists(), 'Test was not ran, because the thumb already exists') + assert thumb_path.exists() is True, 'Test was not ran, because the thumb already exists' assert isinstance(icon, QtGui.QIcon), 'The icon should be a QIcon' assert icon.isNull() is False, 'The icon should not be null' assert expected_size_1 == QtGui.QImageReader(str(thumb_path)).size(), 'The thumb should have the given size' @@ -639,7 +637,7 @@ class TestLib(TestCase): Test the resize_thumb() function """ # GIVEN: A path to an image. - image_path = os.path.join(TEST_PATH, 'church.jpg') + image_path = str(RESOURCE_PATH / 'church.jpg') wanted_width = 777 wanted_height = 72 # We want the background to be white. @@ -660,7 +658,7 @@ class TestLib(TestCase): Test the resize_thumb() function ignoring aspect ratio """ # GIVEN: A path to an image. - image_path = os.path.join(TEST_PATH, 'church.jpg') + image_path = str(RESOURCE_PATH / 'church.jpg') wanted_width = 1000 wanted_height = 1000 # We want the background to be white. @@ -789,7 +787,7 @@ class TestLib(TestCase): ret = compare_chord_lyric(chord, lyrics) # THEN: The returned value should 0 because the lyric is longer than the chord - self.assertEquals(0, ret, 'The returned value should 0 because the lyric is longer than the chord') + assert 0 == ret, 'The returned value should 0 because the lyric is longer than the chord' def test_compare_chord_lyric_long_chord(self): """ diff --git a/tests/functional/openlp_core/lib/test_mediamanageritem.py b/tests/functional/openlp_core/lib/test_mediamanageritem.py index 6c659a5bc..aba4d4c06 100644 --- a/tests/functional/openlp_core/lib/test_mediamanageritem.py +++ b/tests/functional/openlp_core/lib/test_mediamanageritem.py @@ -26,7 +26,6 @@ from unittest import TestCase from unittest.mock import MagicMock, patch from openlp.core.lib import MediaManagerItem - from tests.helpers.testmixin import TestMixin diff --git a/tests/functional/openlp_core/lib/test_path.py b/tests/functional/openlp_core/lib/test_path.py deleted file mode 100644 index f59a1ce08..000000000 --- a/tests/functional/openlp_core/lib/test_path.py +++ /dev/null @@ -1,87 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 - -############################################################################### -# OpenLP - Open Source Lyrics Projection # -# --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 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 # -############################################################################### -""" -Package to test the openlp.core.lib.path package. -""" -import os -from unittest import TestCase - -from openlp.core.common.path import Path, path_to_str, str_to_path - - -class TestPath(TestCase): - """ - Tests for the :mod:`openlp.core.lib.path` module - """ - - def test_path_to_str_type_error(self): - """ - Test that `path_to_str` raises a type error when called with an invalid type - """ - # GIVEN: The `path_to_str` function - # WHEN: Calling `path_to_str` with an invalid Type - # THEN: A TypeError should have been raised - with self.assertRaises(TypeError): - path_to_str(str()) - - def test_path_to_str_none(self): - """ - Test that `path_to_str` correctly converts the path parameter when passed with None - """ - # GIVEN: The `path_to_str` function - # WHEN: Calling the `path_to_str` function with None - result = path_to_str(None) - - # THEN: `path_to_str` should return an empty string - self.assertEqual(result, '') - - def test_path_to_str_path_object(self): - """ - Test that `path_to_str` correctly converts the path parameter when passed a Path object - """ - # GIVEN: The `path_to_str` function - # WHEN: Calling the `path_to_str` function with a Path object - result = path_to_str(Path('test/path')) - - # THEN: `path_to_str` should return a string representation of the Path object - self.assertEqual(result, os.path.join('test', 'path')) - - def test_str_to_path_type_error(self): - """ - Test that `str_to_path` raises a type error when called with an invalid type - """ - # GIVEN: The `str_to_path` function - # WHEN: Calling `str_to_path` with an invalid Type - # THEN: A TypeError should have been raised - with self.assertRaises(TypeError): - str_to_path(Path()) - - def test_str_to_path_empty_str(self): - """ - Test that `str_to_path` correctly converts the string parameter when passed with and empty string - """ - # GIVEN: The `str_to_path` function - # WHEN: Calling the `str_to_path` function with None - result = str_to_path('') - - # THEN: `path_to_str` should return None - self.assertEqual(result, None) diff --git a/tests/functional/openlp_core/lib/test_pluginmanager.py b/tests/functional/openlp_core/lib/test_pluginmanager.py index 163f52877..553221ff2 100644 --- a/tests/functional/openlp_core/lib/test_pluginmanager.py +++ b/tests/functional/openlp_core/lib/test_pluginmanager.py @@ -27,8 +27,8 @@ from unittest.mock import MagicMock from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings -from openlp.core.lib.pluginmanager import PluginManager from openlp.core.lib import PluginStatus +from openlp.core.lib.pluginmanager import PluginManager class TestPluginManager(TestCase): diff --git a/tests/functional/openlp_core/lib/test_serviceitem.py b/tests/functional/openlp_core/lib/test_serviceitem.py index d069f18bf..63544458a 100644 --- a/tests/functional/openlp_core/lib/test_serviceitem.py +++ b/tests/functional/openlp_core/lib/test_serviceitem.py @@ -31,8 +31,8 @@ from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings from openlp.core.lib import ItemCapabilities, ServiceItem, ServiceItemType, FormattingTags from tests.helpers.testmixin import TestMixin - from tests.utils import assert_length, convert_file_service_item +from tests.utils.constants import RESOURCE_PATH VERSE = 'The Lord said to {r}Noah{/r}: \n'\ 'There\'s gonna be a {su}floody{/su}, {sb}floody{/sb}\n'\ @@ -59,7 +59,7 @@ RENDERED_VERSE = 'The Lord said to Noa 'e'\ 'n of the Lord\n' FOOTER = ['Arky Arky (Unknown)', 'Public Domain', 'CCLI 123456'] -TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'service')) +TEST_PATH = str(RESOURCE_PATH / 'service') __default_settings__ = { 'songs/enable chords': True, diff --git a/tests/functional/openlp_core/lib/test_theme.py b/tests/functional/openlp_core/lib/test_theme.py index 4e6407d1c..bdafa3ea8 100644 --- a/tests/functional/openlp_core/lib/test_theme.py +++ b/tests/functional/openlp_core/lib/test_theme.py @@ -22,7 +22,6 @@ """ Package to test the openlp.core.lib.theme package. """ -import os from pathlib import Path from unittest import TestCase diff --git a/tests/functional/openlp_core/lib/test_ui.py b/tests/functional/openlp_core/lib/test_ui.py index 7c1e94f36..42fab0191 100644 --- a/tests/functional/openlp_core/lib/test_ui.py +++ b/tests/functional/openlp_core/lib/test_ui.py @@ -23,14 +23,14 @@ Package to test the openlp.core.lib.ui package. """ from unittest import TestCase -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock, patch, call from PyQt5 import QtCore, QtGui, QtWidgets from openlp.core.common.i18n import UiStrings, translate from openlp.core.lib.ui import add_welcome_page, create_button_box, create_horizontal_adjusting_combo_box, \ create_button, create_action, create_valign_selection_widgets, find_and_set_in_combo_box, create_widget_action, \ - set_case_insensitive_completer + set_case_insensitive_completer, critical_error_message_box class TestUi(TestCase): @@ -80,6 +80,34 @@ class TestUi(TestCase): assert 1 == len(btnbox.buttons()) assert QtWidgets.QDialogButtonBox.HelpRole, btnbox.buttonRole(btnbox.buttons()[0]) + @patch('openlp.core.lib.ui.Registry') + def test_critical_error_message_box(self, MockRegistry): + """ + Test the critical_error_message_box() function + """ + # GIVEN: A mocked Registry + # WHEN: critical_error_message_box() is called + critical_error_message_box('Error', 'This is an error') + + # THEN: The error_message() method on the main window should be called + MockRegistry.return_value.get.return_value.error_message.assert_called_once_with('Error', 'This is an error') + + @patch('openlp.core.lib.ui.QtWidgets.QMessageBox.critical') + def test_critical_error_question(self, mocked_critical): + """ + Test the critical_error_message_box() function + """ + # GIVEN: A mocked critical() method and some other mocks + mocked_parent = MagicMock() + + # WHEN: critical_error_message_box() is called + critical_error_message_box(None, 'This is a question', mocked_parent, True) + + # THEN: The error_message() method on the main window should be called + mocked_critical.assert_called_once_with(mocked_parent, 'Error', 'This is a question', + QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes | + QtWidgets.QMessageBox.No)) + def test_create_horizontal_adjusting_combo_box(self): """ Test creating a horizontal adjusting combo box @@ -92,65 +120,64 @@ class TestUi(TestCase): # THEN: We should get a ComboBox assert isinstance(combo, QtWidgets.QComboBox) - assert 'combo1' == combo.objectName() + assert combo.objectName() == 'combo1' assert QtWidgets.QComboBox.AdjustToMinimumContentsLength == combo.sizeAdjustPolicy() - def test_create_button(self): + @patch('openlp.core.lib.ui.log') + def test_create_button(self, mocked_log): """ Test creating a button """ # GIVEN: A dialog dialog = QtWidgets.QDialog() - # WHEN: We create the button - btn = create_button(dialog, 'my_btn') - - # THEN: We should get a button with a name - assert isinstance(btn, QtWidgets.QPushButton) - assert 'my_btn' == btn.objectName() - assert btn.isEnabled() is True - # WHEN: We create a button with some attributes - btn = create_button(dialog, 'my_btn', text='Hello', tooltip='How are you?', enabled=False) + btn = create_button(dialog, 'my_btn', text='Hello', tooltip='How are you?', enabled=False, role='test', test=1) # THEN: We should get a button with those attributes assert isinstance(btn, QtWidgets.QPushButton) - assert 'Hello' == btn.text() - assert 'How are you?' == btn.toolTip() + assert btn.objectName() == 'my_btn' + assert btn.text() == 'Hello' + assert btn.toolTip() == 'How are you?' assert btn.isEnabled() is False + assert mocked_log.warning.call_args_list == [call('The role "test" is not defined in create_push_button().'), + call('Parameter test was not consumed in create_button().')] + + def test_create_tool_button(self): + """ + Test creating a toolbutton + """ + # GIVEN: A dialog + dialog = QtWidgets.QDialog() # WHEN: We create a toolbutton btn = create_button(dialog, 'my_btn', btn_class='toolbutton') # THEN: We should get a toolbutton assert isinstance(btn, QtWidgets.QToolButton) - assert 'my_btn' == btn.objectName() + assert btn.objectName() == 'my_btn' assert btn.isEnabled() is True - def test_create_action(self): + @patch('openlp.core.lib.ui.log') + def test_create_action(self, mocked_log): """ Test creating an action """ # GIVEN: A dialog dialog = QtWidgets.QDialog() - # WHEN: We create an action - action = create_action(dialog, 'my_action') - - # THEN: We should get a QAction - assert isinstance(action, QtWidgets.QAction) - assert 'my_action' == action.objectName() - # WHEN: We create an action with some properties action = create_action(dialog, 'my_action', text='my text', icon=':/wizards/wizard_firsttime.bmp', - tooltip='my tooltip', statustip='my statustip') + tooltip='my tooltip', statustip='my statustip', test=1) # THEN: These properties should be set assert isinstance(action, QtWidgets.QAction) - assert 'my text' == action.text() + assert action.objectName() == 'my_action' + assert action.text() == 'my text' assert isinstance(action.icon(), QtGui.QIcon) - assert 'my tooltip' == action.toolTip() - assert 'my statustip' == action.statusTip() + assert action.toolTip() == 'my tooltip' + assert action.statusTip() == 'my statustip' + mocked_log.warning.assert_called_once_with('Parameter test was not consumed in create_action().') def test_create_action_on_mac_osx(self): """ diff --git a/tests/functional/openlp_core/projectors/test_projector_bugfixes_01.py b/tests/functional/openlp_core/projectors/test_projector_bugfixes_01.py index da0aae47f..0f5307b53 100644 --- a/tests/functional/openlp_core/projectors/test_projector_bugfixes_01.py +++ b/tests/functional/openlp_core/projectors/test_projector_bugfixes_01.py @@ -24,58 +24,32 @@ Package to test the openlp.core.projectors.pjlink base package. """ from unittest import TestCase -from openlp.core.projectors.db import Projector -from openlp.core.projectors.pjlink import PJLink - -from tests.resources.projector.data import TEST1_DATA +# from openlp.core.projectors.db import Projector +# from openlp.core.projectors.pjlink import PJLink +# from tests.resources.projector.data import TEST1_DATA class TestPJLinkBugs(TestCase): """ Tests for the PJLink module bugfixes """ - def setUp(self): - ''' - Initialization - ''' - self.pjlink_test = PJLink(Projector(**TEST1_DATA), no_poll=True) - - def tearDown(self): - ''' - Cleanups - ''' - self.pjlink_test = None - - def test_bug_1550891_process_clss_nonstandard_reply_1(self): + def bug_1550891_process_clss_nonstandard_reply_1(self): """ Bugfix 1550891: CLSS request returns non-standard reply with Optoma/Viewsonic projector """ - # GIVEN: Test object - pjlink = self.pjlink_test + # Test now part of test_projector_pjlink_commands_01 + # Keeping here for bug reference + pass - # WHEN: Process non-standard reply - pjlink.process_clss('Class 1') - - # THEN: Projector class should be set with proper value - self.assertEqual(pjlink.pjlink_class, '1', - 'Non-standard class reply should have set class=1') - - def test_bug_1550891_process_clss_nonstandard_reply_2(self): + def bug_1550891_process_clss_nonstandard_reply_2(self): """ Bugfix 1550891: CLSS request returns non-standard reply with BenQ projector """ - # GIVEN: Test object - pjlink = self.pjlink_test + # Test now part of test_projector_pjlink_commands_01 + # Keeping here for bug reference + pass - # WHEN: Process non-standard reply - pjlink.process_clss('Version2') - - # THEN: Projector class should be set with proper value - # NOTE: At this time BenQ is Class 1, but we're trying a different value to verify - self.assertEqual(pjlink.pjlink_class, '2', - 'Non-standard class reply should have set class=2') - - def test_bug_1593882_no_pin_authenticated_connection(self): + def bug_1593882_no_pin_authenticated_connection(self): """ Test bug 1593882 no pin and authenticated request exception """ @@ -83,7 +57,7 @@ class TestPJLinkBugs(TestCase): # Keeping here for bug reference pass - def test_bug_1593883_pjlink_authentication(self): + def bug_1593883_pjlink_authentication(self): """ Test bugfix 1593883 pjlink authentication and ticket 92187 """ @@ -91,17 +65,10 @@ class TestPJLinkBugs(TestCase): # Keeping here for bug reference pass - def test_bug_1734275_process_lamp_nonstandard_reply(self): + def bug_1734275_process_lamp_nonstandard_reply(self): """ - Test bugfix 17342785 non-standard LAMP response + Test bugfix 17342785 non-standard LAMP response with one lamp hours only """ - # GIVEN: Test object - pjlink = self.pjlink_test - - # WHEN: Process lamp command called with only hours and no lamp power state - pjlink.process_lamp("45") - - # THEN: Lamp should show hours as 45 and lamp power as Unavailable - self.assertEqual(len(pjlink.lamp), 1, 'There should only be 1 lamp available') - self.assertEqual(pjlink.lamp[0]['Hours'], 45, 'Lamp hours should have equalled 45') - self.assertIsNone(pjlink.lamp[0]['On'], 'Lamp power should be "None"') + # Test now part of test_projector_pjlink_commands_01 + # Keeping here for bug reference + pass diff --git a/tests/functional/openlp_core/projectors/test_projector_constants.py b/tests/functional/openlp_core/projectors/test_projector_constants.py index ed1afa677..6ef4d2118 100644 --- a/tests/functional/openlp_core/projectors/test_projector_constants.py +++ b/tests/functional/openlp_core/projectors/test_projector_constants.py @@ -23,12 +23,51 @@ Package to test the openlp.core.projectors.constants module. """ from unittest import TestCase +from openlp.core.projectors import constants +from openlp.core.projectors.constants import STATUS_CODE, STATUS_MSG class TestProjectorConstants(TestCase): """ Test specific functions in the projector constants module. """ + def test_defined_codes_in_status_code(self): + """ + Test defined status/error codes have equivalent strings + """ + check = [] + missing_str = [] + + # GIVEN: List of defined E_* and S_* items defined in constants + for item in constants.__dict__: + if item.startswith('E_') or item.startswith('S_'): + check.append(item) + + # WHEN: Verify defined list against STATUS_STR + for item in check: + if constants.__dict__[item] not in STATUS_CODE: + missing_str.append(item) + + # THEN: There should be no missing items + assert 0 == len(missing_str), 'Status string missing: {msg}'.format(msg=missing_str) + + def test_status_code_in_status_message(self): + """ + Test if entries in STATUS_CODE have equivalent descriptions in STATUS_MSG + """ + missing_msg = [] + + # GIVEN: Test items + check = STATUS_CODE + + # WHEN: Verify each entry in STATUS_MSG against STATUS_CODE + for item in check: + if item not in STATUS_MSG: + missing_msg.append(item) + + # THEN: There should be no missing items + assert 0 == len(missing_msg), 'Status message missing: {msg}'.format(msg=missing_msg) + def test_build_pjlink_video_label(self): """ Test building PJLINK_DEFAULT_CODES dictionary diff --git a/tests/functional/openlp_core/projectors/test_projector_db.py b/tests/functional/openlp_core/projectors/test_projector_db.py index 1dfe47a54..81bd3f006 100644 --- a/tests/functional/openlp_core/projectors/test_projector_db.py +++ b/tests/functional/openlp_core/projectors/test_projector_db.py @@ -28,7 +28,6 @@ PREREQUISITE: add_record() and get_all() functions validated. import os import shutil from tempfile import mkdtemp - from unittest import TestCase from unittest.mock import patch @@ -36,7 +35,6 @@ from openlp.core.lib.db import upgrade_db from openlp.core.projectors import upgrade from openlp.core.projectors.constants import PJLINK_PORT from openlp.core.projectors.db import Manufacturer, Model, Projector, ProjectorDB, ProjectorSource, Source - from tests.resources.projector.data import TEST_DB_PJLINK1, TEST_DB, TEST1_DATA, TEST2_DATA, TEST3_DATA from tests.utils.constants import TEST_RESOURCES_PATH @@ -109,7 +107,7 @@ class TestProjectorDBUpdate(TestCase): def test_upgrade_old_projector_db(self): """ - Test that we can upgrade an old song db to the current schema + Test that we can upgrade a version 1 db to the current schema """ # GIVEN: An old prjector db old_db = os.path.join(TEST_RESOURCES_PATH, "projector", TEST_DB_PJLINK1) @@ -121,8 +119,7 @@ class TestProjectorDBUpdate(TestCase): updated_to_version, latest_version = upgrade_db(db_url, upgrade) # THEN: the song db should have been upgraded to the latest version - self.assertEqual(updated_to_version, latest_version, - 'The projector DB should have been upgrade to the latest version') + assert updated_to_version == latest_version, 'The projector DB should have been upgrade to the latest version' class TestProjectorDB(TestCase): @@ -159,8 +156,7 @@ class TestProjectorDB(TestCase): record = self.projector.get_projector_by_ip(TEST2_DATA['ip']) # THEN: Verify proper record returned - self.assertTrue(compare_data(Projector(**TEST2_DATA), record), - 'Record found should have been test_2 data') + assert compare_data(Projector(**TEST2_DATA), record) is True, 'Record found should have been test_2 data' def test_find_record_by_name(self): """ @@ -173,8 +169,7 @@ class TestProjectorDB(TestCase): record = self.projector.get_projector_by_name(TEST2_DATA['name']) # THEN: Verify proper record returned - self.assertTrue(compare_data(Projector(**TEST2_DATA), record), - 'Record found should have been test_2 data') + assert compare_data(Projector(**TEST2_DATA), record) is True, 'Record found should have been test_2 data' def test_record_delete(self): """ @@ -189,7 +184,7 @@ class TestProjectorDB(TestCase): # THEN: Verify record not retrievable found = self.projector.get_projector_by_ip(TEST3_DATA['ip']) - self.assertFalse(found, 'test_3 record should have been deleted') + assert found is None, 'test_3 record should have been deleted' def test_record_edit(self): """ @@ -214,12 +209,12 @@ class TestProjectorDB(TestCase): record.model_filter = TEST3_DATA['model_filter'] record.model_lamp = TEST3_DATA['model_lamp'] updated = self.projector.update_projector(record) - self.assertTrue(updated, 'Save updated record should have returned True') + assert updated is True, 'Save updated record should have returned True' record = self.projector.get_projector_by_ip(TEST3_DATA['ip']) # THEN: Record ID should remain the same, but data should be changed - self.assertEqual(record_id, record.id, 'Edited record should have the same ID') - self.assertTrue(compare_data(Projector(**TEST3_DATA), record), 'Edited record should have new data') + assert record_id == record.id, 'Edited record should have the same ID' + assert compare_data(Projector(**TEST3_DATA), record) is True, 'Edited record should have new data' def test_source_add(self): """ @@ -237,7 +232,7 @@ class TestProjectorDB(TestCase): # THEN: Projector should have the same source entry item = self.projector.get_projector_by_id(item_id) - self.assertTrue(compare_source(item.source_list[0], source)) + assert compare_source(item.source_list[0], source) is True, 'Source entry should be the same' def test_manufacturer_repr(self): """ @@ -250,8 +245,8 @@ class TestProjectorDB(TestCase): manufacturer.name = 'OpenLP Test' # THEN: __repr__ should return a proper string - self.assertEqual(str(manufacturer), '', - 'Manufacturer.__repr__() should have returned a proper representation string') + assert str(manufacturer) == '', \ + 'Manufacturer.__repr__() should have returned a proper representation string' def test_model_repr(self): """ @@ -264,8 +259,8 @@ class TestProjectorDB(TestCase): model.name = 'OpenLP Test' # THEN: __repr__ should return a proper string - self.assertEqual(str(model), '', - 'Model.__repr__() should have returned a proper representation string') + assert str(model) == '', \ + 'Model.__repr__() should have returned a proper representation string' def test_source_repr(self): """ @@ -280,19 +275,25 @@ class TestProjectorDB(TestCase): source.text = 'Input text' # THEN: __repr__ should return a proper string - self.assertEqual(str(source), '', - 'Source.__repr__() should have returned a proper representation string') + assert str(source) == '', \ + 'Source.__repr__() should have returned a proper representation string' def test_projector_repr(self): """ Test Projector.__repr__() text """ # GIVEN: Test object + test_string = '< Projector(id="0", ip="127.0.0.1", port="4352", mac_adx="None", pin="None", ' \ + 'name="Test One", location="Somewhere over the rainbow", notes="Not again", ' \ + 'pjlink_name="TEST", pjlink_class="None", manufacturer="IN YOUR DREAMS", model="OpenLP", ' \ + 'serial_no="None", other="None", sources="None", source_list="[]", model_filter="None", ' \ + 'model_lamp="None", sw_version="None") >' + projector = Projector() # WHEN: projector() is populated # NOTE: projector.[pin, other, sources, sw_version, serial_no, sw_version, model_lamp, model_filter] - # should all return None. + # should all return None. # projector.source_list should return an empty list projector.id = 0 projector.ip = '127.0.0.1' @@ -305,13 +306,7 @@ class TestProjectorDB(TestCase): projector.model = 'OpenLP' # THEN: __repr__ should return a proper string - self.assertEqual(str(projector), - '< Projector(id="0", ip="127.0.0.1", port="4352", mac_adx="None", pin="None", ' - 'name="Test One", location="Somewhere over the rainbow", notes="Not again", ' - 'pjlink_name="TEST", manufacturer="IN YOUR DREAMS", model="OpenLP", serial_no="None", ' - 'other="None", sources="None", source_list="[]", model_filter="None", model_lamp="None", ' - 'sw_version="None") >', - 'Projector.__repr__() should have returned a proper representation string') + assert str(projector) == test_string, 'Projector.__repr__() should have returned a proper string' def test_projectorsource_repr(self): """ @@ -328,9 +323,8 @@ class TestProjectorDB(TestCase): self.projector.add_source(source) # THEN: __repr__ should return a proper string - self.assertEqual(str(source), - '', - 'ProjectorSource.__repr__)_ should have returned a proper representation string') + assert str(source) == '', \ + 'ProjectorSource.__repr__)_ should have returned a proper representation string' def test_get_projector_by_id_none(self): """ @@ -343,7 +337,7 @@ class TestProjectorDB(TestCase): results = projector.get_projector_by_id(dbid=123134556409824506) # THEN: Verify return was None - self.assertEqual(results, None, 'Returned results should have equaled None') + assert results is None, 'Returned results should have equaled None' def test_get_projector_all_none(self): """ @@ -356,7 +350,7 @@ class TestProjectorDB(TestCase): results = projector.get_projector_all() # THEN: Verify results is None - self.assertEqual(results, [], 'Returned results should have returned an empty list') + assert [] == results, 'Returned results should have returned an empty list' def test_get_projector_all_one(self): """ @@ -370,8 +364,8 @@ class TestProjectorDB(TestCase): results = self.projector.get_projector_all() # THEN: We should have a list with one entry - self.assertEqual(len(results), 1, 'Returned results should have returned a list with one entry') - self.assertTrue((projector in results), 'Result should have been equal to TEST1_DATA') + assert 1 == len(results), 'Returned results should have returned a list with one entry' + assert (projector in results) is True, 'Result should have been equal to TEST1_DATA' def test_get_projector_all_many(self): """ @@ -389,11 +383,9 @@ class TestProjectorDB(TestCase): results = self.projector.get_projector_all() # THEN: We should have a list with three entries - self.assertEqual(len(results), len(projector_list), - 'Returned results should have returned a list with three entries') + assert len(results) == len(projector_list), 'Returned results should have returned a list with three entries' for projector in results: - self.assertTrue((projector in projector_list), - 'Projector DB entry should have been in expected list') + assert (projector in projector_list) is True, 'Projector DB entry should have been in expected list' def test_get_projector_by_name_fail(self): """ @@ -406,7 +398,7 @@ class TestProjectorDB(TestCase): results = self.projector.get_projector_by_name(name=TEST2_DATA['name']) # THEN: We should have None - self.assertEqual(results, None, 'projector.get_projector_by_name() should have returned None') + assert results is None, 'projector.get_projector_by_name() should have returned None' def test_add_projector_fail(self): """ @@ -419,7 +411,7 @@ class TestProjectorDB(TestCase): results = self.projector.add_projector(Projector(**TEST1_DATA)) # THEN: We should have failed to add new entry - self.assertFalse(results, 'add_projector() should have failed') + assert results is False, 'add_projector() should have failed' def test_update_projector_default_fail(self): """ @@ -432,7 +424,7 @@ class TestProjectorDB(TestCase): results = projector.update_projector() # THEN: We should have failed - self.assertFalse(results, 'update_projector(projector=None) should have returned False') + assert results is False, 'update_projector(projector=None) should have returned False' def test_update_projector_not_in_db_fail(self): """ @@ -446,7 +438,7 @@ class TestProjectorDB(TestCase): results = self.projector.update_projector(projector) # THEN: Results should be False - self.assertFalse(results, 'update_projector(projector=projector) should have returned False') + assert results is False, 'update_projector(projector=projector) should have returned False' def test_delete_projector_fail(self): """ @@ -459,4 +451,4 @@ class TestProjectorDB(TestCase): results = self.projector.delete_projector(Projector(**TEST2_DATA)) # THEN: Results should be False - self.assertFalse(results, 'delete_projector() should have returned False') + assert results is False, 'delete_projector() should have returned False' diff --git a/tests/functional/openlp_core/projectors/test_projector_pjlink_base.py b/tests/functional/openlp_core/projectors/test_projector_pjlink_base.py index c86904bad..b3d45fb68 100644 --- a/tests/functional/openlp_core/projectors/test_projector_pjlink_base.py +++ b/tests/functional/openlp_core/projectors/test_projector_pjlink_base.py @@ -25,10 +25,21 @@ Package to test the openlp.core.projectors.pjlink base package. from unittest import TestCase from unittest.mock import call, patch, MagicMock -from openlp.core.projectors.constants import E_PARAMETER, ERROR_STRING, S_ON, S_CONNECTED, S_QSOCKET_STATE +import openlp.core.projectors.pjlink +from openlp.core.projectors.constants import \ + E_NOT_CONNECTED, \ + E_PARAMETER, \ + E_UNKNOWN_SOCKET_ERROR, \ + STATUS_CODE, \ + STATUS_MSG, \ + S_CONNECTED, \ + S_CONNECTING, \ + S_NOT_CONNECTED, \ + S_OK, \ + S_ON, \ + QSOCKET_STATE from openlp.core.projectors.db import Projector from openlp.core.projectors.pjlink import PJLink - from tests.resources.projector.data import TEST1_DATA pjlink_test = PJLink(Projector(**TEST1_DATA), no_poll=True) @@ -38,55 +49,44 @@ class TestPJLinkBase(TestCase): """ Tests for the PJLink module """ - def setUp(self): - ''' - TestPJLinkCommands part 2 initialization - ''' - self.pjlink_test = PJLink(Projector(**TEST1_DATA), no_poll=True) - - def tearDown(self): - ''' - TestPJLinkCommands part 2 cleanups - ''' - self.pjlink_test = None - - @patch.object(pjlink_test, 'change_status') - def test_status_change(self, mock_change_status): + def test_status_change(self): """ Test process_command call with ERR2 (Parameter) status """ # GIVEN: Test object - pjlink = pjlink_test + with patch('openlp.core.projectors.pjlink.PJLink.changeStatus') as mock_changeStatus: - # WHEN: process_command is called with "ERR2" status from projector - pjlink.process_command('POWR', 'ERR2') + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - # THEN: change_status should have called change_status with E_UNDEFINED - # as first parameter - mock_change_status.called_with(E_PARAMETER, - 'change_status should have been called with "{}"'.format( - ERROR_STRING[E_PARAMETER])) + # WHEN: process_command is called with "ERR2" status from projector + pjlink.process_command('POWR', 'ERR2') - @patch.object(pjlink_test, 'disconnect_from_host') - def test_socket_abort(self, mock_disconnect): + # THEN: change_status should have called change_status with E_UNDEFINED + # as first parameter + mock_changeStatus.called_with(E_PARAMETER, + 'change_status should have been called with "{}"'.format( + STATUS_CODE[E_PARAMETER])) + + def test_socket_abort(self): """ Test PJLink.socket_abort calls disconnect_from_host """ # GIVEN: Test object - pjlink = pjlink_test + with patch('openlp.core.projectors.pjlink.PJLink.disconnect_from_host') as mock_disconnect: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - # WHEN: Calling socket_abort - pjlink.socket_abort() + # WHEN: Calling socket_abort + pjlink.socket_abort() - # THEN: disconnect_from_host should be called - self.assertTrue(mock_disconnect.called, 'Should have called disconnect_from_host') + # THEN: disconnect_from_host should be called + assert mock_disconnect.called is True, 'Should have called disconnect_from_host' def test_poll_loop_not_connected(self): """ Test PJLink.poll_loop not connected return """ # GIVEN: Test object and mocks - pjlink = pjlink_test + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) pjlink.state = MagicMock() pjlink.timer = MagicMock() pjlink.state.return_value = False @@ -96,48 +96,432 @@ class TestPJLinkBase(TestCase): pjlink.poll_loop() # THEN: poll_loop should exit without calling any other method - self.assertFalse(pjlink.timer.called, 'Should have returned without calling any other method') + assert pjlink.timer.called is False, 'Should have returned without calling any other method' - def test_poll_loop_start(self): + def test_poll_loop_set_interval(self): """ Test PJLink.poll_loop makes correct calls """ # GIVEN: Mocks and test data - mock_state = patch.object(self.pjlink_test, 'state').start() - mock_state.return_value = S_QSOCKET_STATE['ConnectedState'] - mock_timer = patch.object(self.pjlink_test, 'timer').start() - mock_timer.interval.return_value = 10 - mock_send_command = patch.object(self.pjlink_test, 'send_command').start() + with patch('openlp.core.projectors.pjlink.PJLink.send_command') as mock_send_command: - pjlink = self.pjlink_test - pjlink.poll_time = 20 - pjlink.power = S_ON - pjlink.source_available = None - pjlink.other_info = None - pjlink.manufacturer = None - pjlink.model = None - pjlink.pjlink_name = None - pjlink.ConnectedState = S_CONNECTED - call_list = [ - call('POWR'), - call('ERST'), - call('LAMP'), - call('AVMT'), - call('INPT'), - call('INST'), - call('INFO'), - call('INF1'), - call('INF2'), - call('NAME'), - ] + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.state = MagicMock() + pjlink.state.return_value = QSOCKET_STATE[S_CONNECTED] + pjlink.poll_timer = MagicMock() + pjlink.poll_timer.interval.return_value = 10 - # WHEN: PJLink.poll_loop is called - pjlink.poll_loop() + pjlink.poll_time = 20 + pjlink.power = S_ON + pjlink.source_available = None + pjlink.other_info = None + pjlink.manufacturer = None + pjlink.model = None + pjlink.pjlink_name = None + call_list = [ + call('POWR'), + call('ERST'), + call('LAMP'), + call('AVMT'), + call('INPT'), + call('INST'), + call('INFO'), + call('INF1'), + call('INF2'), + call('NAME'), + ] - # THEN: proper calls were made to retrieve projector data - # First, call to update the timer with the next interval - self.assertTrue(mock_timer.setInterval.called) - # Next, should have called the timer to start - self.assertTrue(mock_timer.start.called, 'Should have started the timer') - # Finally, should have called send_command with a list of projetctor status checks - mock_send_command.assert_has_calls(call_list, 'Should have queued projector queries') + # WHEN: PJLink.poll_loop is called + pjlink.poll_loop() + + # THEN: proper calls were made to retrieve projector data + # First, call to update the timer with the next interval + assert pjlink.poll_timer.setInterval.called is True, 'Timer update interval should have been called' + # Finally, should have called send_command with a list of projetctor status checks + mock_send_command.assert_has_calls(call_list, 'Should have queued projector queries') + + def test_projector_change_status_unknown_socket_error(self): + """ + Test change_status with connection error + """ + # GIVEN: Test object and mocks + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') as mock_changeStatus, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons: + + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.projector_status = 0 + pjlink.status_connect = 0 + log_debug_calls = [ + call('({ip}) Changing status to {status} "{msg}"'.format(ip=pjlink.name, + status=STATUS_CODE[E_UNKNOWN_SOCKET_ERROR], + msg=STATUS_MSG[E_UNKNOWN_SOCKET_ERROR])), + call('({ip}) status_connect: {code}: "{msg}"'.format(ip=pjlink.name, + code=STATUS_CODE[E_NOT_CONNECTED], + msg=STATUS_MSG[E_NOT_CONNECTED])), + call('({ip}) projector_status: {code}: "{msg}"'.format(ip=pjlink.name, + code=STATUS_CODE[S_OK], + msg=STATUS_MSG[S_OK])), + call('({ip}) error_status: {code}: "{msg}"'.format(ip=pjlink.name, + code=STATUS_CODE[E_UNKNOWN_SOCKET_ERROR], + msg=STATUS_MSG[E_UNKNOWN_SOCKET_ERROR]))] + + # WHEN: change_status called with unknown socket error + pjlink.change_status(status=E_UNKNOWN_SOCKET_ERROR) + + # THEN: Proper settings should change and signals sent + mock_log.debug.assert_has_calls(log_debug_calls) + assert pjlink.projector_status == S_OK, 'Projector status should not have changed' + assert pjlink.status_connect == E_NOT_CONNECTED, 'Status connect should be NOT CONNECTED' + assert mock_UpdateIcons.emit.called is True, 'Should have called UpdateIcons' + mock_changeStatus.emit.assert_called_once_with(pjlink.ip, E_UNKNOWN_SOCKET_ERROR, + STATUS_MSG[E_UNKNOWN_SOCKET_ERROR]) + + def test_projector_change_status_connection_status_connecting(self): + """ + Test change_status with connecting status + """ + # GIVEN: Test object and mocks + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') as mock_changeStatus, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons: + + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.projector_status = 0 + pjlink.status_connect = 0 + log_debug_calls = [ + call('({ip}) Changing status to {status} "{msg}"'.format(ip=pjlink.name, + status=STATUS_CODE[S_CONNECTING], + msg=STATUS_MSG[S_CONNECTING])), + call('({ip}) status_connect: {code}: "{msg}"'.format(ip=pjlink.name, + code=STATUS_CODE[S_CONNECTING], + msg=STATUS_MSG[S_CONNECTING])), + call('({ip}) projector_status: {code}: "{msg}"'.format(ip=pjlink.name, + code=STATUS_CODE[S_OK], + msg=STATUS_MSG[S_OK])), + call('({ip}) error_status: {code}: "{msg}"'.format(ip=pjlink.name, + code=STATUS_CODE[S_OK], + msg=STATUS_MSG[S_OK]))] + + # WHEN: change_status called with CONNECTING + pjlink.change_status(status=S_CONNECTING) + + # THEN: Proper settings should change and signals sent + mock_log.debug.assert_has_calls(log_debug_calls) + mock_changeStatus.emit.assert_called_once_with(pjlink.ip, S_CONNECTING, STATUS_MSG[S_CONNECTING]) + assert pjlink.projector_status == S_OK, 'Projector status should not have changed' + assert pjlink.status_connect == S_CONNECTING, 'Status connect should be CONNECTING' + assert mock_UpdateIcons.emit.called is True, 'Should have called UpdateIcons' + + def test_projector_change_status_connection_status_connected(self): + """ + Test change_status with connected status + """ + # GIVEN: Test object and mocks + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') as mock_changeStatus: + + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.projector_status = 0 + pjlink.status_connect = 0 + log_debug_calls = [ + call('({ip}) Changing status to {status} "{msg}"'.format(ip=pjlink.name, + status=STATUS_CODE[S_CONNECTED], + msg=STATUS_MSG[S_CONNECTED])), + call('({ip}) status_connect: {code}: "{msg}"'.format(ip=pjlink.name, + code=STATUS_CODE[S_CONNECTED], + msg=STATUS_MSG[S_CONNECTED])), + call('({ip}) projector_status: {code}: "{msg}"'.format(ip=pjlink.name, + code=STATUS_CODE[S_OK], + msg=STATUS_MSG[S_OK])), + call('({ip}) error_status: {code}: "{msg}"'.format(ip=pjlink.name, + code=STATUS_CODE[S_OK], + msg=STATUS_MSG[S_OK]))] + + # WHEN: change_status called with CONNECTED + pjlink.change_status(status=S_CONNECTED) + + # THEN: Proper settings should change and signals sent + mock_log.debug.assert_has_calls(log_debug_calls) + mock_changeStatus.emit.assert_called_once_with(pjlink.ip, S_CONNECTED, 'Connected') + assert pjlink.projector_status == S_OK, 'Projector status should not have changed' + assert pjlink.status_connect == S_CONNECTED, 'Status connect should be CONNECTED' + + def test_projector_change_status_connection_status_with_message(self): + """ + Test change_status with connection status + """ + # GIVEN: Test object and mocks + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') as mock_changeStatus: + + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.projector_status = 0 + pjlink.status_connect = 0 + test_message = 'Different Status Message than default' + log_debug_calls = [ + call('({ip}) Changing status to {status} "{msg}"'.format(ip=pjlink.name, + status=STATUS_CODE[S_ON], + msg=test_message)), + call('({ip}) status_connect: {code}: "{msg}"'.format(ip=pjlink.name, + code=STATUS_CODE[S_OK], + msg=test_message)), + call('({ip}) projector_status: {code}: "{msg}"'.format(ip=pjlink.name, + code=STATUS_CODE[S_ON], + msg=test_message)), + call('({ip}) error_status: {code}: "{msg}"'.format(ip=pjlink.name, + code=STATUS_CODE[S_OK], + msg=test_message))] + + # WHEN: change_status called with projector ON status + pjlink.change_status(status=S_ON, msg=test_message) + + # THEN: Proper settings should change and signals sent + mock_log.debug.assert_has_calls(log_debug_calls) + mock_changeStatus.emit.assert_called_once_with(pjlink.ip, S_ON, test_message) + assert pjlink.projector_status == S_ON, 'Projector status should be ON' + assert pjlink.status_connect == S_OK, 'Status connect should not have changed' + + def test_projector_get_av_mute_status(self): + """ + Test sending command to retrieve shutter/audio state + """ + # GIVEN: Test object and mocks + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + test_data = 'AVMT' + log_debug_calls = [call('({ip}) reset_information() connect status is ' + '{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED])), + call('({ip}) Sending {cmd} command'.format(ip=pjlink.name, cmd=test_data))] + + # WHEN: get_av_mute_status is called + pjlink.get_av_mute_status() + + # THEN: log data and send_command should have been called + mock_log.debug.assert_has_calls(log_debug_calls) + mock_send_command.assert_called_once_with(cmd=test_data) + + def test_projector_get_available_inputs(self): + """ + Test sending command to retrieve avaliable inputs + """ + # GIVEN: Test object and mocks + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + test_data = 'INST' + log_debug_calls = [call('({ip}) reset_information() connect status is ' + '{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED])), + call('({ip}) Sending {cmd} command'.format(ip=pjlink.name, cmd=test_data))] + + # WHEN: get_available_inputs is called + pjlink.get_available_inputs() + + # THEN: log data and send_command should have been called + mock_log.debug.assert_has_calls(log_debug_calls) + mock_send_command.assert_called_once_with(cmd=test_data) + + def test_projector_get_error_status(self): + """ + Test sending command to retrieve projector error status + """ + # GIVEN: Test object and mocks + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + test_data = 'ERST' + log_debug_calls = [call('({ip}) reset_information() connect status is ' + '{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED])), + call('({ip}) Sending {cmd} command'.format(ip=pjlink.name, cmd=test_data))] + + # WHEN: get_error_status is called + pjlink.get_error_status() + + # THEN: log data and send_command should have been called + mock_log.debug.assert_has_calls(log_debug_calls) + mock_send_command.assert_called_once_with(cmd=test_data) + + def test_projector_get_input_source(self): + """ + Test sending command to retrieve current input + """ + # GIVEN: Test object and mocks + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + test_data = 'INPT' + log_debug_calls = [call('({ip}) reset_information() connect status is ' + '{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED])), + call('({ip}) Sending {cmd} command'.format(ip=pjlink.name, cmd=test_data))] + + # WHEN: get_input_source is called + pjlink.get_input_source() + + # THEN: log data and send_command should have been called + mock_log.debug.assert_has_calls(log_debug_calls) + mock_send_command.assert_called_once_with(cmd=test_data) + + def test_projector_get_lamp_status(self): + """ + Test sending command to retrieve lamp(s) status + """ + # GIVEN: Test object and mocks + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + test_data = 'LAMP' + log_debug_calls = [call('({ip}) reset_information() connect status is ' + '{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED])), + call('({ip}) Sending {cmd} command'.format(ip=pjlink.name, cmd=test_data))] + + # WHEN: get_input_source is called + pjlink.get_lamp_status() + + # THEN: log data and send_command should have been called + mock_log.debug.assert_has_calls(log_debug_calls) + mock_send_command.assert_called_once_with(cmd=test_data) + + def test_projector_get_manufacturer(self): + """ + Test sending command to retrieve manufacturer name + """ + # GIVEN: Test object and mocks + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + test_data = 'INF1' + log_debug_calls = [call('({ip}) reset_information() connect status is ' + '{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED])), + call('({ip}) Sending {cmd} command'.format(ip=pjlink.name, cmd=test_data))] + + # WHEN: get_input_source is called + pjlink.get_manufacturer() + + # THEN: log data and send_command should have been called + mock_log.debug.assert_has_calls(log_debug_calls) + mock_send_command.assert_called_once_with(cmd=test_data) + + def test_projector_get_model(self): + """ + Test sending command to get model information + """ + # GIVEN: Test object and mocks + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + test_data = 'INF2' + log_debug_calls = [call('({ip}) reset_information() connect status is ' + '{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED])), + call('({ip}) Sending {cmd} command'.format(ip=pjlink.name, cmd=test_data))] + + # WHEN: get_input_source is called + pjlink.get_model() + + # THEN: log data and send_command should have been called + mock_log.debug.assert_has_calls(log_debug_calls) + mock_send_command.assert_called_once_with(cmd=test_data) + + def test_projector_get_name(self): + """ + Test sending command to get user-assigned name + """ + # GIVEN: Test object and mocks + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + test_data = 'NAME' + log_debug_calls = [call('({ip}) reset_information() connect status is ' + '{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED])), + call('({ip}) Sending {cmd} command'.format(ip=pjlink.name, cmd=test_data))] + + # WHEN: get_input_source is called + pjlink.get_name() + + # THEN: log data and send_command should have been called + mock_log.debug.assert_has_calls(log_debug_calls) + mock_send_command.assert_called_once_with(cmd=test_data) + + def test_projector_get_other_info(self): + """ + Test sending command to retrieve other information + """ + # GIVEN: Test object and mocks + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + test_data = 'INFO' + log_debug_calls = [call('({ip}) reset_information() connect status is ' + '{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED])), + call('({ip}) Sending {cmd} command'.format(ip=pjlink.name, cmd=test_data))] + + # WHEN: get_input_source is called + pjlink.get_other_info() + + # THEN: log data and send_command should have been called + mock_log.debug.assert_has_calls(log_debug_calls) + mock_send_command.assert_called_once_with(cmd=test_data) + + def test_projector_get_power_status(self): + """ + Test sending command to retrieve current power state + """ + # GIVEN: Test object and mocks + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + test_data = 'POWR' + log_debug_calls = [call('({ip}) reset_information() connect status is ' + '{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED])), + call('({ip}) Sending {cmd} command'.format(ip=pjlink.name, cmd=test_data))] + + # WHEN: get_input_source is called + pjlink.get_power_status() + + # THEN: log data and send_command should have been called + mock_log.debug.assert_has_calls(log_debug_calls) + mock_send_command.assert_called_once_with(cmd=test_data) + + def test_projector_get_status_invalid(self): + """ + Test to check returned information for error code + """ + # GIVEN: Test object + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + test_string = 'NaN test' + + # WHEN: get_status called + code, message = pjlink._get_status(status=test_string) + + # THEN: Proper data should have been returned + assert code == -1, 'Should have returned -1 as a bad status check' + assert message is None, 'Invalid code type should have returned None for message' + + def test_projector_get_status_valid(self): + """ + Test to check returned information for status codes + """ + # GIVEN: Test object + test_message = 'Not Connected' + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + + # WHEN: get_status called + code, message = pjlink._get_status(status=S_NOT_CONNECTED) + + # THEN: Proper strings should have been returned + assert code == 'S_NOT_CONNECTED', 'Code returned should have been the same code that was sent' + assert message == test_message, 'Description of code should have been returned' + + def test_projector_get_status_unknown(self): + """ + Test to check returned information for unknown code + """ + # GIVEN: Test object + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + + # WHEN: get_status called + code, message = pjlink._get_status(status=9999) + + # THEN: Proper strings should have been returned + assert code is None, 'Code returned should have been the same code that was sent' + assert message is None, 'Should have returned None as message' diff --git a/tests/functional/openlp_core/projectors/test_projector_pjlink_cmd_routing.py b/tests/functional/openlp_core/projectors/test_projector_pjlink_cmd_routing.py index 4ff133061..d6c549177 100644 --- a/tests/functional/openlp_core/projectors/test_projector_pjlink_cmd_routing.py +++ b/tests/functional/openlp_core/projectors/test_projector_pjlink_cmd_routing.py @@ -24,209 +24,215 @@ Package to test the openlp.core.projectors.pjlink command routing. """ from unittest import TestCase -from unittest.mock import patch, MagicMock +from unittest.mock import MagicMock, call, patch import openlp.core.projectors.pjlink -from openlp.core.projectors.constants import PJLINK_ERRORS, \ +from openlp.core.projectors.constants import PJLINK_ERRORS, PJLINK_PREFIX, STATUS_MSG, \ E_AUTHENTICATION, E_PARAMETER, E_PROJECTOR, E_UNAVAILABLE, E_UNDEFINED from openlp.core.projectors.db import Projector from openlp.core.projectors.pjlink import PJLink -''' -from openlp.core.projectors.constants import ERROR_STRING, PJLINK_ERST_DATA, PJLINK_ERST_STATUS, \ - PJLINK_POWR_STATUS, PJLINK_VALID_CMD, E_WARN, E_ERROR, S_OFF, S_STANDBY, S_ON -''' -from tests.resources.projector.data import TEST_PIN, TEST1_DATA - -pjlink_test = PJLink(Projector(**TEST1_DATA), pin=TEST_PIN, no_poll=True) -pjlink_test.ip = '127.0.0.1' +from tests.resources.projector.data import TEST1_DATA class TestPJLinkRouting(TestCase): """ Tests for the PJLink module command routing """ - def setUp(self): - ''' - TestPJLinkCommands part 2 initialization - ''' - self.pjlink_test = PJLink(Projector(**TEST1_DATA), no_poll=True) + def test_get_data_unknown_command(self): + """ + Test not a valid command + """ + # GIVEN: Test object + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, '_trash_buffer') as mock_buffer: - def tearDown(self): - ''' - TestPJLinkCommands part 2 cleanups - ''' - self.pjlink_test = None + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.pjlink_functions = MagicMock() + log_warning_text = [call('({ip}) get_data(): Invalid packet - ' + 'unknown command "UNK"'.format(ip=pjlink.name))] + log_debug_text = [call('({ip}) get_data(ip="111.111.111.111" ' + 'buffer="b\'%1UNK=Huh?\'"'.format(ip=pjlink.name)), + call('({ip}) get_data(): Checking new data "%1UNK=Huh?"'.format(ip=pjlink.name))] - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_process_command_call_clss(self, mock_log): + # WHEN: get_data called with an unknown command + pjlink.get_data(buff='{prefix}1UNK=Huh?'.format(prefix=PJLINK_PREFIX).encode('utf-8')) + + # THEN: Appropriate log entries should have been made and methods called/not called + mock_log.debug.assert_has_calls(log_debug_text) + mock_log.warning.assert_has_calls(log_warning_text) + assert pjlink.pjlink_functions.called is False, 'Should not have accessed pjlink_functions' + assert mock_buffer.called is True, 'Should have called _trash_buffer' + + def test_process_command_call_clss(self): """ Test process_command calls proper function """ - # GIVEN: Test object - pjlink = pjlink_test - log_text = '(127.0.0.1) Calling function for CLSS' - mock_log.reset_mock() - mock_process_clss = MagicMock() - pjlink.pjlink_functions['CLSS'] = mock_process_clss + # GIVEN: Test object and mocks + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss: - # WHEN: process_command is called with valid function and data - pjlink.process_command(cmd='CLSS', data='1') + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + log_debug_calls = [call('({ip}) Processing command "CLSS" with data "1"'.format(ip=pjlink.name)), + call('({ip}) Calling function for CLSS'.format(ip=pjlink.name))] - # THEN: Process method should have been called properly - mock_log.debug.assert_called_with(log_text) - mock_process_clss.assert_called_with('1') + # WHEN: process_command is called with valid function and data + pjlink.process_command(cmd='CLSS', data='1') - @patch.object(pjlink_test, 'change_status') - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_process_command_err1(self, mock_log, mock_change_status): - """ - Test ERR1 - Undefined projector function - """ - # GIVEN: Test object - pjlink = pjlink_test - log_text = '(127.0.0.1) Projector returned error "ERR1"' - mock_change_status.reset_mock() - mock_log.reset_mock() + # THEN: Appropriate log entries should have been made and methods called + mock_log.debug.assert_has_calls(log_debug_calls) + mock_process_clss.assert_called_once_with(data='1') - # WHEN: process_command called with ERR1 - pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNDEFINED]) - - # THEN: Error should be logged and status_change should be called - mock_change_status.assert_called_once_with(E_UNDEFINED, 'Undefined Command: "CLSS"') - mock_log.error.assert_called_with(log_text) - - @patch.object(pjlink_test, 'change_status') - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_process_command_err2(self, mock_log, mock_change_status): - """ - Test ERR2 - Parameter Error - """ - # GIVEN: Test object - pjlink = pjlink_test - log_text = '(127.0.0.1) Projector returned error "ERR2"' - mock_change_status.reset_mock() - mock_log.reset_mock() - - # WHEN: process_command called with ERR2 - pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PARAMETER]) - - # THEN: Error should be logged and status_change should be called - mock_change_status.assert_called_once_with(E_PARAMETER) - mock_log.error.assert_called_with(log_text) - - @patch.object(pjlink_test, 'change_status') - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_process_command_err3(self, mock_log, mock_change_status): - """ - Test ERR3 - Unavailable error - """ - # GIVEN: Test object - pjlink = pjlink_test - log_text = '(127.0.0.1) Projector returned error "ERR3"' - mock_change_status.reset_mock() - mock_log.reset_mock() - - # WHEN: process_command called with ERR3 - pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNAVAILABLE]) - - # THEN: Error should be logged and status_change should be called - mock_change_status.assert_called_once_with(E_UNAVAILABLE) - mock_log.error.assert_called_with(log_text) - - @patch.object(pjlink_test, 'change_status') - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_process_command_err4(self, mock_log, mock_change_status): - """ - Test ERR3 - Unavailable error - """ - # GIVEN: Test object - pjlink = pjlink_test - log_text = '(127.0.0.1) Projector returned error "ERR4"' - mock_change_status.reset_mock() - mock_log.reset_mock() - - # WHEN: process_command called with ERR3 - pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PROJECTOR]) - - # THEN: Error should be logged and status_change should be called - mock_change_status.assert_called_once_with(E_PROJECTOR) - mock_log.error.assert_called_with(log_text) - - @patch.object(pjlink_test, 'projectorAuthentication') - @patch.object(pjlink_test, 'change_status') - @patch.object(pjlink_test, 'disconnect_from_host') - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_process_command_erra(self, mock_log, mock_disconnect, mock_change_status, mock_err_authenticate): + def test_process_command_erra(self): """ Test ERRA - Authentication Error """ # GIVEN: Test object - pjlink = pjlink_test - log_text = '(127.0.0.1) Projector returned error "ERRA"' - mock_change_status.reset_mock() - mock_log.reset_mock() + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'process_pjlink') as mock_process_pjlink, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'disconnect_from_host') as mock_disconnect, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorAuthentication') as mock_authentication: - # WHEN: process_command called with ERRA - pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_AUTHENTICATION]) + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + log_error_calls = [call('({ip}) PJLINK: {msg}'.format(ip=pjlink.name, msg=STATUS_MSG[E_AUTHENTICATION]))] + log_debug_calls = [call('({ip}) Processing command "PJLINK" with data "ERRA"'.format(ip=pjlink.name))] - # THEN: Error should be logged and several methods should be called - self.assertTrue(mock_disconnect.called, 'disconnect_from_host should have been called') - mock_change_status.assert_called_once_with(E_AUTHENTICATION) - mock_log.error.assert_called_with(log_text) + # WHEN: process_command called with ERRA + pjlink.process_command(cmd='PJLINK', data=PJLINK_ERRORS[E_AUTHENTICATION]) + + # THEN: Appropriate log entries should have been made and methods called/not called + assert mock_disconnect.called is True, 'disconnect_from_host should have been called' + mock_log.error.assert_has_calls(log_error_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + mock_change_status.assert_called_once_with(status=E_AUTHENTICATION) + mock_authentication.emit.assert_called_once_with(pjlink.name) + mock_process_pjlink.assert_not_called() + + def test_process_command_err1(self): + """ + Test ERR1 - Undefined projector function + """ + # GIVEN: Test object + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss: + + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + log_error_text = [call('({ip}) CLSS: {msg}'.format(ip=pjlink.name, msg=STATUS_MSG[E_UNDEFINED]))] + log_debug_text = [call('({ip}) Processing command "CLSS" with data "ERR1"'.format(ip=pjlink.name)), + call('({ip}) Calling function for CLSS'.format(ip=pjlink.name))] + + # WHEN: process_command called with ERR1 + pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNDEFINED]) + + # THEN: Appropriate log entries should have been made and methods called + mock_log.error.assert_has_calls(log_error_text) + mock_log.debug.assert_has_calls(log_debug_text) + mock_process_clss.assert_called_once_with(data=PJLINK_ERRORS[E_UNDEFINED]) + + def test_process_command_err2(self): + """ + Test ERR2 - Parameter Error + """ + # GIVEN: Test object + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss: + + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + log_error_text = [call('({ip}) CLSS: {msg}'.format(ip=pjlink.name, msg=STATUS_MSG[E_PARAMETER]))] + log_debug_text = [call('({ip}) Processing command "CLSS" with data "ERR2"'.format(ip=pjlink.name)), + call('({ip}) Calling function for CLSS'.format(ip=pjlink.name))] + + # WHEN: process_command called with ERR2 + pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PARAMETER]) + + # THEN: Appropriate log entries should have been made and methods called/not called + mock_log.error.assert_has_calls(log_error_text) + mock_log.debug.assert_has_calls(log_debug_text) + mock_process_clss.assert_called_once_with(data=PJLINK_ERRORS[E_PARAMETER]) + + def test_process_command_err3(self): + """ + Test ERR3 - Unavailable error + """ + # GIVEN: Test object + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss: + + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + log_error_text = [call('({ip}) CLSS: {msg}'.format(ip=pjlink.name, msg=STATUS_MSG[E_UNAVAILABLE]))] + log_debug_text = [call('({ip}) Processing command "CLSS" with data "ERR3"'.format(ip=pjlink.name)), + call('({ip}) Calling function for CLSS'.format(ip=pjlink.name))] + + # WHEN: process_command called with ERR3 + pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNAVAILABLE]) + + # THEN: Appropriate log entries should have been made and methods called + mock_log.error.assert_has_calls(log_error_text) + mock_log.debug.assert_has_calls(log_debug_text) + mock_process_clss.assert_called_once_with(data=PJLINK_ERRORS[E_UNAVAILABLE]) + + def test_process_command_err4(self): + """ + Test ERR3 - Unavailable error + """ + # GIVEN: Test object + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss: + + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + log_error_text = [call('({ip}) CLSS: {msg}'.format(ip=pjlink.name, msg=STATUS_MSG[E_PROJECTOR]))] + log_debug_text = [call('({ip}) Processing command "CLSS" with data "ERR4"'.format(ip=pjlink.name)), + call('({ip}) Calling function for CLSS'.format(ip=pjlink.name))] + + # WHEN: process_command called with ERR4 + pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PROJECTOR]) + + # THEN: Appropriate log entries should have been made and methods called + mock_log.error.assert_has_calls(log_error_text) + mock_log.debug.assert_has_calls(log_debug_text) + mock_process_clss.assert_called_once_with(data=PJLINK_ERRORS[E_PROJECTOR]) def test_process_command_future(self): """ Test command valid but no method to process yet """ - # GIVEN: Initial mocks and data - mock_log = patch.object(openlp.core.projectors.pjlink, 'log').start() - mock_functions = patch.object(self.pjlink_test, 'pjlink_functions').start() - mock_functions.return_value = [] - - pjlink = self.pjlink_test - log_text = '(111.111.111.111) Unable to process command="CLSS" (Future option?)' - - # WHEN: process_command called with an unknown command - pjlink.process_command(cmd='CLSS', data='DONT CARE') - - # THEN: Error should be logged and no command called - self.assertFalse(mock_functions.called, 'Should not have gotten to the end of the method') - mock_log.warning.assert_called_once_with(log_text) - - @patch.object(pjlink_test, 'pjlink_functions') - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_process_command_invalid(self, mock_log, mock_functions): - """ - Test not a valid command - """ # GIVEN: Test object - pjlink = pjlink_test - mock_functions.reset_mock() - mock_log.reset_mock() + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss: - # WHEN: process_command called with an unknown command - pjlink.process_command(cmd='Unknown', data='Dont Care') - log_text = '(127.0.0.1) Ignoring command="Unknown" (Invalid/Unknown)' + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.pjlink_functions = MagicMock() + log_warning_text = [call('({ip}) Unable to process command="CLSS" (Future option?)'.format(ip=pjlink.name))] + log_debug_text = [call('({ip}) Processing command "CLSS" with data "Huh?"'.format(ip=pjlink.name))] - # THEN: Error should be logged and no command called - self.assertFalse(mock_functions.called, 'Should not have gotten to the end of the method') - mock_log.error.assert_called_once_with(log_text) + # WHEN: Processing a possible future command + pjlink.process_command(cmd='CLSS', data="Huh?") + + # THEN: Appropriate log entries should have been made and methods called/not called + mock_log.debug.assert_has_calls(log_debug_text) + mock_log.warning.assert_has_calls(log_warning_text) + assert pjlink.pjlink_functions.called is False, 'Should not have accessed pjlink_functions' + assert mock_process_clss.called is False, 'Should not have called process_clss' def test_process_command_ok(self): """ Test command returned success """ # GIVEN: Initial mocks and data - mock_log = patch.object(openlp.core.projectors.pjlink, 'log').start() - mock_send_command = patch.object(self.pjlink_test, 'send_command').start() + # GIVEN: Test object and mocks + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss: - pjlink = self.pjlink_test - log_text = '(111.111.111.111) Command "POWR" returned OK' + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + log_debug_calls = [call('({ip}) Processing command "CLSS" with data "OK"'.format(ip=pjlink.name)), + call('({ip}) Command "CLSS" returned OK'.format(ip=pjlink.name))] - # WHEN: process_command called with a command that returns OK - pjlink.process_command(cmd='POWR', data='OK') + # WHEN: process_command is called with valid function and data + pjlink.process_command(cmd='CLSS', data='OK') - # THEN: Appropriate calls should have been made - mock_log.debug.assert_called_with(log_text) - mock_send_command.assert_called_once_with(cmd='POWR') + # THEN: Appropriate log entries should have been made and methods called + mock_log.debug.assert_has_calls(log_debug_calls) + mock_send_command.assert_called_once_with(cmd='CLSS') + mock_process_clss.assert_not_called() diff --git a/tests/functional/openlp_core/projectors/test_projector_pjlink_commands_01.py b/tests/functional/openlp_core/projectors/test_projector_pjlink_commands_01.py index 8340a0fd0..42d46f735 100644 --- a/tests/functional/openlp_core/projectors/test_projector_pjlink_commands_01.py +++ b/tests/functional/openlp_core/projectors/test_projector_pjlink_commands_01.py @@ -23,938 +23,664 @@ Package to test the openlp.core.projectors.pjlink commands package. """ from unittest import TestCase -from unittest.mock import patch +from unittest.mock import call, patch import openlp.core.projectors.pjlink -from openlp.core.projectors.constants import ERROR_STRING, PJLINK_ERST_DATA, PJLINK_ERST_STATUS, \ +from openlp.core.projectors.constants import \ + PJLINK_ERST_DATA, \ + PJLINK_ERST_STATUS, \ PJLINK_POWR_STATUS, \ - E_ERROR, E_NOT_CONNECTED, E_SOCKET_ADDRESS_NOT_AVAILABLE, E_UNKNOWN_SOCKET_ERROR, E_WARN, \ - S_CONNECTED, S_OFF, S_ON, S_NOT_CONNECTED, S_CONNECTING, S_STANDBY + STATUS_CODE, \ + E_ERROR, \ + E_WARN, \ + S_OK, \ + S_ON, \ + S_NOT_CONNECTED, \ + S_STANDBY from openlp.core.projectors.db import Projector from openlp.core.projectors.pjlink import PJLink -from tests.resources.projector.data import TEST_PIN, TEST1_DATA - -pjlink_test = PJLink(Projector(**TEST1_DATA), pin=TEST_PIN, no_poll=True) -pjlink_test.ip = '127.0.0.1' - -# Create a list of ERST positional data so we don't have to redo the same buildup multiple times -PJLINK_ERST_POSITIONS = [] -for pos in range(0, len(PJLINK_ERST_DATA)): - if pos in PJLINK_ERST_DATA: - PJLINK_ERST_POSITIONS.append(PJLINK_ERST_DATA[pos]) +from tests.resources.projector.data import TEST1_DATA class TestPJLinkCommands(TestCase): """ Tests for the PJLinkCommands class part 1 """ - @patch.object(pjlink_test, 'changeStatus') - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_change_status_connection_error(self, mock_log, mock_change_status): - """ - Test change_status with connection error - """ - # GIVEN: Test object - pjlink = pjlink_test - pjlink.projector_status = 0 - pjlink.status_connect = 0 - test_code = E_UNKNOWN_SOCKET_ERROR - mock_change_status.reset_mock() - mock_log.reset_mock() - - # WHEN: change_status called with unknown socket error - pjlink.change_status(status=test_code, msg=None) - - # THEN: Proper settings should change and signals sent - self.assertEqual(pjlink.projector_status, E_NOT_CONNECTED, 'Projector status should be NOT CONNECTED') - self.assertEqual(pjlink.status_connect, E_NOT_CONNECTED, 'Status connect should be NOT CONNECTED') - mock_change_status.emit.assert_called_once_with(pjlink.ip, E_UNKNOWN_SOCKET_ERROR, - 'An unidentified error occurred') - self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times') - - @patch.object(pjlink_test, 'changeStatus') - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_change_status_connection_status_connecting(self, mock_log, mock_change_status): - """ - Test change_status with connection status - """ - # GIVEN: Test object - pjlink = pjlink_test - pjlink.projector_status = 0 - pjlink.status_connect = 0 - test_code = S_CONNECTING - mock_change_status.reset_mock() - mock_log.reset_mock() - - # WHEN: change_status called with unknown socket error - pjlink.change_status(status=test_code, msg=None) - - # THEN: Proper settings should change and signals sent - self.assertEqual(pjlink.projector_status, S_NOT_CONNECTED, 'Projector status should be NOT CONNECTED') - self.assertEqual(pjlink.status_connect, S_CONNECTING, 'Status connect should be CONNECTING') - mock_change_status.emit.assert_called_once_with(pjlink.ip, S_CONNECTING, 'Connecting') - self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times') - - @patch.object(pjlink_test, 'changeStatus') - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_change_status_connection_status_connected(self, mock_log, mock_change_status): - """ - Test change_status with connection status - """ - # GIVEN: Test object - pjlink = pjlink_test - pjlink.projector_status = 0 - pjlink.status_connect = 0 - test_code = S_ON - mock_change_status.reset_mock() - mock_log.reset_mock() - - # WHEN: change_status called with unknown socket error - pjlink.change_status(status=test_code, msg=None) - - # THEN: Proper settings should change and signals sent - self.assertEqual(pjlink.projector_status, S_ON, 'Projector status should be ON') - self.assertEqual(pjlink.status_connect, S_CONNECTED, 'Status connect should be CONNECTED') - mock_change_status.emit.assert_called_once_with(pjlink.ip, S_ON, 'Power is on') - self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times') - - @patch.object(pjlink_test, 'changeStatus') - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_change_status_connection_status_with_message(self, mock_log, mock_change_status): - """ - Test change_status with connection status - """ - # GIVEN: Test object - pjlink = pjlink_test - pjlink.projector_status = 0 - pjlink.status_connect = 0 - test_message = 'Different Status Message than default' - test_code = S_ON - mock_change_status.reset_mock() - mock_log.reset_mock() - - # WHEN: change_status called with unknown socket error - pjlink.change_status(status=test_code, msg=test_message) - - # THEN: Proper settings should change and signals sent - self.assertEqual(pjlink.projector_status, S_ON, 'Projector status should be ON') - self.assertEqual(pjlink.status_connect, S_CONNECTED, 'Status connect should be CONNECTED') - mock_change_status.emit.assert_called_once_with(pjlink.ip, S_ON, test_message) - self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times') - - @patch.object(pjlink_test, 'send_command') - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_get_av_mute_status(self, mock_log, mock_send_command): - """ - Test sending command to retrieve shutter/audio state - """ - # GIVEN: Test object - pjlink = pjlink_test - mock_log.reset_mock() - mock_send_command.reset_mock() - test_data = 'AVMT' - test_log = '(127.0.0.1) Sending AVMT command' - - # WHEN: get_av_mute_status is called - pjlink.get_av_mute_status() - - # THEN: log data and send_command should have been called - mock_log.debug.assert_called_once_with(test_log) - mock_send_command.assert_called_once_with(cmd=test_data) - - @patch.object(pjlink_test, 'send_command') - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_get_available_inputs(self, mock_log, mock_send_command): - """ - Test sending command to retrieve avaliable inputs - """ - # GIVEN: Test object - pjlink = pjlink_test - mock_log.reset_mock() - mock_send_command.reset_mock() - test_data = 'INST' - test_log = '(127.0.0.1) Sending INST command' - - # WHEN: get_available_inputs is called - pjlink.get_available_inputs() - - # THEN: log data and send_command should have been called - mock_log.debug.assert_called_once_with(test_log) - mock_send_command.assert_called_once_with(cmd=test_data) - - @patch.object(pjlink_test, 'send_command') - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_get_error_status(self, mock_log, mock_send_command): - """ - Test sending command to retrieve projector error status - """ - # GIVEN: Test object - pjlink = pjlink_test - mock_log.reset_mock() - mock_send_command.reset_mock() - test_data = 'ERST' - test_log = '(127.0.0.1) Sending ERST command' - - # WHEN: get_error_status is called - pjlink.get_error_status() - - # THEN: log data and send_command should have been called - mock_log.debug.assert_called_once_with(test_log) - mock_send_command.assert_called_once_with(cmd=test_data) - - @patch.object(pjlink_test, 'send_command') - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_get_input_source(self, mock_log, mock_send_command): - """ - Test sending command to retrieve current input - """ - # GIVEN: Test object - pjlink = pjlink_test - mock_log.reset_mock() - mock_send_command.reset_mock() - test_data = 'INPT' - test_log = '(127.0.0.1) Sending INPT command' - - # WHEN: get_input_source is called - pjlink.get_input_source() - - # THEN: log data and send_command should have been called - mock_log.debug.assert_called_once_with(test_log) - mock_send_command.assert_called_once_with(cmd=test_data) - - @patch.object(pjlink_test, 'send_command') - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_get_lamp_status(self, mock_log, mock_send_command): - """ - Test sending command to retrieve lamp(s) status - """ - # GIVEN: Test object - pjlink = pjlink_test - mock_log.reset_mock() - mock_send_command.reset_mock() - test_data = 'LAMP' - test_log = '(127.0.0.1) Sending LAMP command' - - # WHEN: get_lamp_status is called - pjlink.get_lamp_status() - - # THEN: log data and send_command should have been called - mock_log.debug.assert_called_once_with(test_log) - mock_send_command.assert_called_once_with(cmd=test_data) - - @patch.object(pjlink_test, 'send_command') - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_get_manufacturer(self, mock_log, mock_send_command): - """ - Test sending command to retrieve manufacturer name - """ - # GIVEN: Test object - pjlink = pjlink_test - mock_log.reset_mock() - mock_send_command.reset_mock() - test_data = 'INF1' - test_log = '(127.0.0.1) Sending INF1 command' - - # WHEN: get_manufacturer is called - pjlink.get_manufacturer() - - # THEN: log data and send_command should have been called - mock_log.debug.assert_called_once_with(test_log) - mock_send_command.assert_called_once_with(cmd=test_data) - - @patch.object(pjlink_test, 'send_command') - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_get_model(self, mock_log, mock_send_command): - """ - Test sending command to get model information - """ - # GIVEN: Test object - pjlink = pjlink_test - mock_log.reset_mock() - mock_send_command.reset_mock() - test_data = 'INF2' - test_log = '(127.0.0.1) Sending INF2 command' - - # WHEN: get_model is called - pjlink.get_model() - - # THEN: log data and send_command should have been called - mock_log.debug.assert_called_once_with(test_log) - mock_send_command.assert_called_once_with(cmd=test_data) - - @patch.object(pjlink_test, 'send_command') - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_get_name(self, mock_log, mock_send_command): - """ - Test sending command to get user-assigned name - """ - # GIVEN: Test object - pjlink = pjlink_test - mock_log.reset_mock() - mock_send_command.reset_mock() - test_data = 'NAME' - test_log = '(127.0.0.1) Sending NAME command' - - # WHEN: get_name is called - pjlink.get_name() - - # THEN: log data and send_command should have been called - mock_log.debug.assert_called_once_with(test_log) - mock_send_command.assert_called_once_with(cmd=test_data) - - @patch.object(pjlink_test, 'send_command') - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_get_other_info(self, mock_log, mock_send_command): - """ - Test sending command to retrieve other information - """ - # GIVEN: Test object - pjlink = pjlink_test - mock_log.reset_mock() - mock_send_command.reset_mock() - test_data = 'INFO' - test_log = '(127.0.0.1) Sending INFO command' - - # WHEN: get_other_info is called - pjlink.get_other_info() - - # THEN: log data and send_command should have been called - mock_log.debug.assert_called_once_with(test_log) - mock_send_command.assert_called_once_with(cmd=test_data) - - @patch.object(pjlink_test, 'send_command') - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_get_power_status(self, mock_log, mock_send_command): - """ - Test sending command to retrieve current power state - """ - # GIVEN: Test object - pjlink = pjlink_test - mock_log.reset_mock() - mock_send_command.reset_mock() - test_data = 'POWR' - test_log = '(127.0.0.1) Sending POWR command' - - # WHEN: get_power_status called - pjlink.get_power_status() - - # THEN: log data and send_command should have been called - mock_log.debug.assert_called_once_with(test_log) - mock_send_command.assert_called_once_with(cmd=test_data) - - def test_projector_get_status_error(self): - """ - Test to check returned information for error code - """ - # GIVEN: Test object - pjlink = pjlink_test - test_string = 'E_SOCKET_ADDRESS_NOT_AVAILABLE' - test_message = 'The address specified to socket.bind() does not belong to the host' - - # WHEN: get_status called - string, message = pjlink._get_status(status=E_SOCKET_ADDRESS_NOT_AVAILABLE) - - # THEN: Proper strings should have been returned - self.assertEqual(string, test_string, 'Code as string should have been returned') - self.assertEqual(message, test_message, 'Description of code should have been returned') - - def test_projector_get_status_invalid(self): - """ - Test to check returned information for error code - """ - # GIVEN: Test object - pjlink = pjlink_test - test_string = 'Test string since get_status will only work with int' - test_message = 'Invalid status code' - - # WHEN: get_status called - string, message = pjlink._get_status(status=test_string) - - # THEN: Proper strings should have been returned - self.assertEqual(string, -1, 'Should have returned -1 as a bad status check') - self.assertEqual(message, test_message, 'Error message should have been returned') - - def test_projector_get_status_status(self): - """ - Test to check returned information for status codes - """ - # GIVEN: Test object - pjlink = pjlink_test - test_string = 'S_NOT_CONNECTED' - test_message = 'Not connected' - - # WHEN: get_status called - string, message = pjlink._get_status(status=S_NOT_CONNECTED) - - # THEN: Proper strings should have been returned - self.assertEqual(string, test_string, 'Code as string should have been returned') - self.assertEqual(message, test_message, 'Description of code should have been returned') - - def test_projector_get_status_unknown(self): - """ - Test to check returned information for unknown code - """ - # GIVEN: Test object - pjlink = pjlink_test - test_string = 999999 - test_message = 'Unknown status' - - # WHEN: get_status called - string, message = pjlink._get_status(status=test_string) - - # THEN: Proper strings should have been returned - self.assertEqual(string, test_string, 'Received code should have been returned') - self.assertEqual(message, test_message, 'Unknown status string should have been returned') - def test_projector_process_inf1(self): """ Test saving INF1 data (manufacturer) """ - # GIVEN: Test object - pjlink = pjlink_test - pjlink.manufacturer = None test_data = 'TEst INformation MultiCase' + # GIVEN: Test object + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.manufacturer = None + # WHEN: process_inf called with test data pjlink.process_inf1(data=test_data) # THEN: Data should be saved - self.assertEqual(pjlink.manufacturer, test_data, 'Test data should have been saved') + assert pjlink.manufacturer == test_data, 'Test data should have been saved' def test_projector_process_inf2(self): """ Test saving INF2 data (model) """ - # GIVEN: Test object - pjlink = pjlink_test - pjlink.model = None test_data = 'TEst moDEl MultiCase' + # GIVEN: Test object + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.model = None + # WHEN: process_inf called with test data pjlink.process_inf2(data=test_data) # THEN: Data should be saved - self.assertEqual(pjlink.model, test_data, 'Test data should have been saved') + assert pjlink.model == test_data, 'Test data should have been saved' def test_projector_process_info(self): """ Test saving INFO data (other information) """ - # GIVEN: Test object - pjlink = pjlink_test - pjlink.other_info = None test_data = 'TEst ExtrANEous MultiCase INformatoin that MFGR might Set' + # GIVEN: Test object + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.other_info = None + # WHEN: process_inf called with test data pjlink.process_info(data=test_data) # THEN: Data should be saved - self.assertEqual(pjlink.other_info, test_data, 'Test data should have been saved') + assert pjlink.other_info == test_data, 'Test data should have been saved' - @patch.object(pjlink_test, 'projectorUpdateIcons') - def test_projector_process_avmt_bad_data(self, mock_UpdateIcons): + def test_projector_process_avmt_bad_data(self): """ Test avmt bad data fail """ # GIVEN: Test object - pjlink = pjlink_test - pjlink.shutter = True - pjlink.mute = True + with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.shutter = True + pjlink.mute = True - # WHEN: Called with an invalid setting - pjlink.process_avmt('36') + # WHEN: Called with an invalid setting + pjlink.process_avmt('36') - # THEN: Shutter should be closed and mute should be True - self.assertTrue(pjlink.shutter, 'Shutter should changed') - self.assertTrue(pjlink.mute, 'Audio should not have changed') - self.assertFalse(mock_UpdateIcons.emit.called, 'Update icons should NOT have been called') + # THEN: Shutter should be closed and mute should be True + assert pjlink.shutter is True, 'Shutter should changed' + assert pjlink.mute is True, 'Audio should not have changed' + assert mock_UpdateIcons.emit.called is False, 'Update icons should NOT have been called' - @patch.object(pjlink_test, 'projectorUpdateIcons') - def test_projector_process_avmt_closed_muted(self, mock_UpdateIcons): + def test_projector_process_avmt_closed_muted(self): """ Test avmt status shutter closed and mute off """ # GIVEN: Test object - pjlink = pjlink_test - pjlink.shutter = False - pjlink.mute = False + with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.shutter = False + pjlink.mute = False - # WHEN: Called with setting shutter to closed and mute on - pjlink.process_avmt('31') + # WHEN: Called with setting shutter to closed and mute on + pjlink.process_avmt('31') - # THEN: Shutter should be closed and mute should be True - self.assertTrue(pjlink.shutter, 'Shutter should have been set to closed') - self.assertTrue(pjlink.mute, 'Audio should be muted') - self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called') + # THEN: Shutter should be closed and mute should be True + assert pjlink.shutter is True, 'Shutter should have been set to closed' + assert pjlink.mute is True, 'Audio should be muted' + assert mock_UpdateIcons.emit.called is True, 'Update icons should have been called' - @patch.object(pjlink_test, 'projectorUpdateIcons') - def test_projector_process_avmt_shutter_closed(self, mock_UpdateIcons): + def test_projector_process_avmt_shutter_closed(self): """ Test avmt status shutter closed and audio unchanged """ # GIVEN: Test object - pjlink = pjlink_test - pjlink.shutter = False - pjlink.mute = True + with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.shutter = False + pjlink.mute = True - # WHEN: Called with setting shutter closed and mute off - pjlink.process_avmt('11') + # WHEN: Called with setting shutter closed and mute off + pjlink.process_avmt('11') - # THEN: Shutter should be True and mute should be False - self.assertTrue(pjlink.shutter, 'Shutter should have been set to closed') - self.assertTrue(pjlink.mute, 'Audio should not have changed') - self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called') + # THEN: Shutter should be True and mute should be False + assert pjlink.shutter is True, 'Shutter should have been set to closed' + assert pjlink.mute is True, 'Audio should not have changed' + assert mock_UpdateIcons.emit.called is True, 'Update icons should have been called' - @patch.object(pjlink_test, 'projectorUpdateIcons') - def test_projector_process_avmt_audio_muted(self, mock_UpdateIcons): + def test_projector_process_avmt_audio_muted(self): """ Test avmt status shutter unchanged and mute on """ # GIVEN: Test object - pjlink = pjlink_test - pjlink.shutter = True - pjlink.mute = False + with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.shutter = True + pjlink.mute = False - # WHEN: Called with setting shutter closed and mute on - pjlink.process_avmt('21') + # WHEN: Called with setting shutter closed and mute on + pjlink.process_avmt('21') - # THEN: Shutter should be closed and mute should be True - self.assertTrue(pjlink.shutter, 'Shutter should not have changed') - self.assertTrue(pjlink.mute, 'Audio should be off') - self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called') + # THEN: Shutter should be closed and mute should be True + assert pjlink.shutter is True, 'Shutter should not have changed' + assert pjlink.mute is True, 'Audio should be off' + assert mock_UpdateIcons.emit.called is True, 'Update icons should have been called' - @patch.object(pjlink_test, 'projectorUpdateIcons') - def test_projector_process_avmt_open_unmuted(self, mock_UpdateIcons): + def test_projector_process_avmt_open_unmuted(self): """ Test avmt status shutter open and mute off """ # GIVEN: Test object - pjlink = pjlink_test - pjlink.shutter = True - pjlink.mute = True + with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.shutter = True + pjlink.mute = True - # WHEN: Called with setting shutter to closed and mute on - pjlink.process_avmt('30') + # WHEN: Called with setting shutter to closed and mute on + pjlink.process_avmt('30') - # THEN: Shutter should be closed and mute should be True - self.assertFalse(pjlink.shutter, 'Shutter should have been set to open') - self.assertFalse(pjlink.mute, 'Audio should be on') - self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called') + # THEN: Shutter should be closed and mute should be True + assert pjlink.shutter is False, 'Shutter should have been set to open' + assert pjlink.mute is False, 'Audio should be on' + assert mock_UpdateIcons.emit.called is True, 'Update icons should have been called' def test_projector_process_clss_one(self): """ Test class 1 sent from projector """ # GIVEN: Test object - pjlink = pjlink_test + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) # WHEN: Process class response pjlink.process_clss('1') # THEN: Projector class should be set to 1 - self.assertEqual(pjlink.pjlink_class, '1', - 'Projector should have set class=1') + assert pjlink.pjlink_class == '1', 'Projector should have set class=1' def test_projector_process_clss_two(self): """ Test class 2 sent from projector """ # GIVEN: Test object - pjlink = pjlink_test + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) # WHEN: Process class response pjlink.process_clss('2') # THEN: Projector class should be set to 1 - self.assertEqual(pjlink.pjlink_class, '2', - 'Projector should have set class=2') + assert pjlink.pjlink_class == '2', 'Projector should have set class=2' - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_process_clss_invalid_nan(self, mock_log): + def test_projector_process_clss_invalid_nan(self): """ Test CLSS reply has no class number """ # GIVEN: Test object - pjlink = pjlink_test + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + log_debug_calls = [call('({ip}) reset_information() connect status is ' + '{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED])), + call('({ip}) Setting pjlink_class for this projector to "1"'.format(ip=pjlink.name))] + log_error_calls = [call('({ip}) NAN CLSS version reply "Z" - ' + 'defaulting to class "1"'.format(ip=pjlink.name))] - # WHEN: Process invalid reply - pjlink.process_clss('Z') - log_text = '(127.0.0.1) NAN CLSS version reply "Z" - defaulting to class "1"' + # WHEN: Process invalid reply + pjlink.process_clss('Z') - # THEN: Projector class should be set with default value - self.assertEqual(pjlink.pjlink_class, '1', - 'Non-standard class reply should have set class=1') - mock_log.error.assert_called_once_with(log_text) + # THEN: Projector class should be set with default value + assert pjlink.pjlink_class == '1', 'Invalid NaN class reply should have set class=1' + mock_log.error.assert_has_calls(log_error_calls) + mock_log.debug.assert_has_calls(log_debug_calls) - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_process_clss_invalid_no_version(self, mock_log): + def test_projector_process_clss_invalid_no_version(self): """ Test CLSS reply has no class number """ # GIVEN: Test object - pjlink = pjlink_test + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + log_debug_calls = [call('({ip}) reset_information() connect status is ' + '{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED])), + call('({ip}) Setting pjlink_class for this projector to "1"'.format(ip=pjlink.name))] + log_error_calls = [call('({ip}) No numbers found in class version reply "Invalid" ' + '- defaulting to class "1"'.format(ip=pjlink.name))] - # WHEN: Process invalid reply - pjlink.process_clss('Invalid') - log_text = '(127.0.0.1) No numbers found in class version reply "Invalid" - defaulting to class "1"' + # WHEN: Process invalid reply + pjlink.process_clss('Invalid') - # THEN: Projector class should be set with default value - self.assertEqual(pjlink.pjlink_class, '1', - 'Non-standard class reply should have set class=1') - mock_log.error.assert_called_once_with(log_text) + # THEN: Projector class should be set with default value + assert pjlink.pjlink_class == '1', 'Invalid class reply should have set class=1' + mock_log.error.assert_has_calls(log_error_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + + def test_projector_process_clss_nonstandard_reply_1(self): + """ + Test CLSS request returns non-standard reply 1 + """ + # GIVEN: Test object + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + + # WHEN: Process non-standard reply + pjlink.process_clss('Class 1') + + # THEN: Projector class should be set with proper value + assert '1' == pjlink.pjlink_class, 'Non-standard class reply should have set class=1' + + def test_projector_process_clss_nonstandard_reply_2(self): + """ + Test CLSS request returns non-standard reply 2 + """ + # GIVEN: Test object + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + + # WHEN: Process non-standard reply + pjlink.process_clss('Version2') + + # THEN: Projector class should be set with proper value + assert '2' == pjlink.pjlink_class, 'Non-standard class reply should have set class=2' def test_projector_process_erst_all_ok(self): """ - Test test_projector_process_erst_all_ok + Test to verify pjlink.projector_errors is set to None when no errors """ + chk_data = '0' * PJLINK_ERST_DATA['DATA_LENGTH'] + # GIVEN: Test object - pjlink = pjlink_test - chk_test = PJLINK_ERST_STATUS['OK'] - chk_param = chk_test * len(PJLINK_ERST_POSITIONS) + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) # WHEN: process_erst with no errors - pjlink.process_erst(chk_param) + pjlink.process_erst(chk_data) # THEN: PJLink instance errors should be None - self.assertIsNone(pjlink.projector_errors, 'projector_errors should have been set to None') + assert pjlink.projector_errors is None, 'projector_errors should have been set to None' - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_process_erst_data_invalid_length(self, mock_log): + def test_projector_process_erst_data_invalid_length(self): """ Test test_projector_process_erst_data_invalid_length """ # GIVEN: Test object - pjlink = pjlink_test - pjlink.projector_errors = None - log_text = '127.0.0.1) Invalid error status response "11111111": length != 6' + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.projector_errors = None + chk_data = '0' * (PJLINK_ERST_DATA['DATA_LENGTH'] + 1) + log_debug_calls = [call('({ip}) reset_information() connect status is ' + '{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED]))] + log_warn_calls = [call('({ip}) Invalid error status response "0000000": ' + 'length != {chk}'.format(ip=pjlink.name, chk=PJLINK_ERST_DATA['DATA_LENGTH']))] - # WHEN: process_erst called with invalid data (too many values - pjlink.process_erst('11111111') + # WHEN: process_erst called with invalid data (too many values + pjlink.process_erst(chk_data) - # THEN: pjlink.projector_errors should be empty and warning logged - self.assertIsNone(pjlink.projector_errors, 'There should be no errors') - self.assertTrue(mock_log.warning.called, 'Warning should have been logged') - mock_log.warning.assert_called_once_with(log_text) + # THEN: pjlink.projector_errors should be empty and warning logged + assert pjlink.projector_errors is None, 'There should be no errors' + mock_log.debug.assert_has_calls(log_debug_calls) + mock_log.warning.assert_has_calls(log_warn_calls) - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_process_erst_data_invalid_nan(self, mock_log): + def test_projector_process_erst_data_invalid_nan(self): """ Test test_projector_process_erst_data_invalid_nan """ # GIVEN: Test object - pjlink = pjlink_test - pjlink.projector_errors = None - log_text = '(127.0.0.1) Invalid error status response "1111Z1"' + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.projector_errors = None + chk_data = 'Z' + ('0' * (PJLINK_ERST_DATA['DATA_LENGTH'] - 1)) + log_debug_calls = [call('({ip}) reset_information() connect status is ' + '{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED]))] + log_warn_calls = [call('({ip}) Invalid error status response "Z00000"'.format(ip=pjlink.name))] - # WHEN: process_erst called with invalid data (too many values - pjlink.process_erst('1111Z1') + # WHEN: process_erst called with invalid data (too many values + pjlink.process_erst(chk_data) - # THEN: pjlink.projector_errors should be empty and warning logged - self.assertIsNone(pjlink.projector_errors, 'There should be no errors') - self.assertTrue(mock_log.warning.called, 'Warning should have been logged') - mock_log.warning.assert_called_once_with(log_text) + # THEN: pjlink.projector_errors should be empty and warning logged + assert pjlink.projector_errors is None, 'There should be no errors' + mock_log.debug.assert_has_calls(log_debug_calls) + mock_log.warning.assert_has_calls(log_warn_calls) def test_projector_process_erst_all_warn(self): """ Test test_projector_process_erst_all_warn """ + chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[E_WARN], + lamp=PJLINK_ERST_STATUS[E_WARN], + temp=PJLINK_ERST_STATUS[E_WARN], + cover=PJLINK_ERST_STATUS[E_WARN], + filt=PJLINK_ERST_STATUS[E_WARN], + other=PJLINK_ERST_STATUS[E_WARN]) + chk_test = {'Fan': E_WARN, + 'Lamp': E_WARN, + 'Temperature': E_WARN, + 'Cover': E_WARN, + 'Filter': E_WARN, + 'Other': E_WARN} + # GIVEN: Test object - pjlink = pjlink_test - chk_test = PJLINK_ERST_STATUS[E_WARN] - chk_string = ERROR_STRING[E_WARN] - chk_param = chk_test * len(PJLINK_ERST_POSITIONS) + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.projector_errors = None # WHEN: process_erst with status set to WARN - pjlink.process_erst(chk_param) + pjlink.process_erst(chk_data) # THEN: PJLink instance errors should match chk_value - for chk in pjlink.projector_errors: - self.assertEqual(pjlink.projector_errors[chk], chk_string, - 'projector_errors["{chk}"] should have been set to "{err}"'.format(chk=chk, - err=chk_string)) + assert pjlink.projector_errors == chk_test, 'Projector errors should be all E_WARN' def test_projector_process_erst_all_error(self): """ Test test_projector_process_erst_all_error """ + chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[E_ERROR], + lamp=PJLINK_ERST_STATUS[E_ERROR], + temp=PJLINK_ERST_STATUS[E_ERROR], + cover=PJLINK_ERST_STATUS[E_ERROR], + filt=PJLINK_ERST_STATUS[E_ERROR], + other=PJLINK_ERST_STATUS[E_ERROR]) + chk_test = {'Fan': E_ERROR, + 'Lamp': E_ERROR, + 'Temperature': E_ERROR, + 'Cover': E_ERROR, + 'Filter': E_ERROR, + 'Other': E_ERROR} + # GIVEN: Test object - pjlink = pjlink_test - chk_test = PJLINK_ERST_STATUS[E_ERROR] - chk_string = ERROR_STRING[E_ERROR] - chk_param = chk_test * len(PJLINK_ERST_POSITIONS) + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.projector_errors = None # WHEN: process_erst with status set to WARN - pjlink.process_erst(chk_param) + pjlink.process_erst(chk_data) # THEN: PJLink instance errors should match chk_value - for chk in pjlink.projector_errors: - self.assertEqual(pjlink.projector_errors[chk], chk_string, - 'projector_errors["{chk}"] should have been set to "{err}"'.format(chk=chk, - err=chk_string)) + assert pjlink.projector_errors == chk_test, 'Projector errors should be all E_ERROR' def test_projector_process_erst_warn_cover_only(self): """ Test test_projector_process_erst_warn_cover_only """ + chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[S_OK], + lamp=PJLINK_ERST_STATUS[S_OK], + temp=PJLINK_ERST_STATUS[S_OK], + cover=PJLINK_ERST_STATUS[E_WARN], + filt=PJLINK_ERST_STATUS[S_OK], + other=PJLINK_ERST_STATUS[S_OK]) + chk_test = {'Cover': E_WARN} + # GIVEN: Test object - pjlink = pjlink_test - chk_test = PJLINK_ERST_STATUS[E_WARN] - chk_string = ERROR_STRING[E_WARN] - pos = PJLINK_ERST_DATA['COVER'] - build_chk = [] - for check in range(0, len(PJLINK_ERST_POSITIONS)): - if check == pos: - build_chk.append(chk_test) - else: - build_chk.append(PJLINK_ERST_STATUS['OK']) - chk_param = ''.join(build_chk) + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.projector_errors = None - # WHEN: process_erst with cover only set to WARN and all others set to OK - pjlink.process_erst(chk_param) + # WHEN: process_erst with status set to WARN + pjlink.process_erst(chk_data) - # THEN: Only COVER should have an error - self.assertEqual(len(pjlink.projector_errors), 1, 'projector_errors should only have 1 error') - self.assertTrue(('Cover' in pjlink.projector_errors), 'projector_errors should have an error for "Cover"') - self.assertEqual(pjlink.projector_errors['Cover'], - chk_string, - 'projector_errors["Cover"] should have error "{err}"'.format(err=chk_string)) + # THEN: PJLink instance errors should match only cover warning + assert 1 == len(pjlink.projector_errors), 'There should only be 1 error listed in projector_errors' + assert 'Cover' in pjlink.projector_errors, '"Cover" should be the only error listed' + assert pjlink.projector_errors['Cover'] == E_WARN, '"Cover" should have E_WARN listed as error' + assert chk_test == pjlink.projector_errors, 'projector_errors should match test errors' - def test_projector_process_inpt(self): + def test_projector_process_inpt_valid(self): """ Test input source status shows current input """ # GIVEN: Test object - pjlink = pjlink_test - pjlink.source = '0' + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.source = '11' + log_debug_calls = [call('({ip}) reset_information() connect status is ' + 'S_NOT_CONNECTED'.format(ip=pjlink.name))] + chk_source_available = ['11', '12', '21', '22', '31', '32'] + pjlink.source_available = chk_source_available - # WHEN: Called with input source - pjlink.process_inpt('1') + # WHEN: Called with input source + pjlink.process_inpt('21') - # THEN: Input selected should reflect current input - self.assertEqual(pjlink.source, '1', 'Input source should be set to "1"') + # THEN: Input selected should reflect current input + assert pjlink.source == '21', 'Input source should be set to "21"' + mock_log.debug.assert_has_calls(log_debug_calls) - @patch.object(pjlink_test, 'projectorUpdateIcons') - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_process_inst(self, mock_log, mock_UpdateIcons): + def test_projector_process_input_not_in_list(self): + """ + Test setting input outside of available inputs + + TODO: Future test + """ + pass + + def test_projector_process_input_not_in_default(self): + """ + Test setting input with no sources available + TODO: Future test + """ + pass + + def test_projector_process_input_invalid(self): + """ + Test setting input with an invalid value + + TODO: Future test + """ + + def test_projector_process_inst_class_1(self): """ Test saving video source available information """ # GIVEN: Test object - pjlink = pjlink_test - pjlink.source_available = [] - test_data = '21 10 30 31 11 20' - test_saved = ["10", "11", "20", "21", "30", "31"] - log_data = "(127.0.0.1) Setting projector sources_available to " \ - "\"['10', '11', '20', '21', '30', '31']\"" - mock_UpdateIcons.reset_mock() - mock_log.reset_mock() + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.source_available = [] + log_debug_calls = [call('({ip}) Setting projector sources_available to ' + '"[\'11\', \'12\', \'21\', \'22\', \'31\', \'32\']"'.format(ip=pjlink.name))] + chk_data = '21 12 11 22 32 31' # Although they should already be sorted, use unsorted to verify method + chk_test = ['11', '12', '21', '22', '31', '32'] - # WHEN: process_inst called with test data - pjlink.process_inst(data=test_data) + # WHEN: process_inst called with test data + pjlink.process_inst(data=chk_data) - # THEN: Data should have been sorted and saved properly - self.assertEqual(pjlink.source_available, test_saved, "Sources should have been sorted and saved") - mock_log.debug.assert_called_once_with(log_data) - self.assertTrue(mock_UpdateIcons.emit.called, 'Update Icons should have been called') + # THEN: Data should have been sorted and saved properly + assert pjlink.source_available == chk_test, "Sources should have been sorted and saved" + mock_log.debug.assert_has_calls(log_debug_calls) - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_process_lamp_invalid(self, mock_log): + def test_projector_process_lamp_invalid(self): """ Test status multiple lamp on/off and hours """ # GIVEN: Test object - pjlink = pjlink_test - pjlink.lamp = [{'Hours': 00000, 'On': True}, - {'Hours': 11111, 'On': False}] - log_data = '(127.0.0.1) process_lamp(): Invalid data "11111 1 22222 0 333A3 1"' + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.lamp = [{'Hours': 00000, 'On': True}, + {'Hours': 11111, 'On': False}] + log_data = [call('({ip}) process_lamp(): Invalid data "11111 1 22222 0 333A3 1"'.format(ip=pjlink.name))] - # WHEN: Call process_command with invalid lamp data - pjlink.process_lamp('11111 1 22222 0 333A3 1') + # WHEN: Call process_command with invalid lamp data + pjlink.process_lamp('11111 1 22222 0 333A3 1') - # THEN: lamps should not have changed - self.assertEqual(len(pjlink.lamp), 2, - 'Projector should have kept 2 lamps specified') - self.assertEqual(pjlink.lamp[0]['On'], True, - 'Lamp 1 power status should have been set to TRUE') - self.assertEqual(pjlink.lamp[0]['Hours'], 00000, - 'Lamp 1 hours should have been left at 00000') - self.assertEqual(pjlink.lamp[1]['On'], False, - 'Lamp 2 power status should have been set to FALSE') - self.assertEqual(pjlink.lamp[1]['Hours'], 11111, - 'Lamp 2 hours should have been left at 11111') - mock_log.warning.assert_called_once_with(log_data) + # THEN: lamps should not have changed + assert 2 == len(pjlink.lamp), 'Projector should have kept 2 lamps specified' + assert pjlink.lamp[0]['On'] is True, 'Lamp 1 power status should have stayed TRUE' + assert 00000 == pjlink.lamp[0]['Hours'], 'Lamp 1 hours should have been left at 00000' + assert pjlink.lamp[1]['On'] is False, 'Lamp 2 power status should have stayed FALSE' + assert 11111 == pjlink.lamp[1]['Hours'], 'Lamp 2 hours should have been left at 11111' + mock_log.warning.assert_has_calls(log_data) def test_projector_process_lamp_multiple(self): """ Test status multiple lamp on/off and hours """ # GIVEN: Test object - pjlink = pjlink_test - pjlink.lamps = [] + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.lamp = [] - # WHEN: Call process_command with lamp data + # WHEN: Call process_command with invalid lamp data pjlink.process_lamp('11111 1 22222 0 33333 1') # THEN: Lamp should have been set with proper lamp status - self.assertEqual(len(pjlink.lamp), 3, - 'Projector should have 3 lamps specified') - self.assertEqual(pjlink.lamp[0]['On'], True, - 'Lamp 1 power status should have been set to TRUE') - self.assertEqual(pjlink.lamp[0]['Hours'], 11111, - 'Lamp 1 hours should have been set to 11111') - self.assertEqual(pjlink.lamp[1]['On'], False, - 'Lamp 2 power status should have been set to FALSE') - self.assertEqual(pjlink.lamp[1]['Hours'], 22222, - 'Lamp 2 hours should have been set to 22222') - self.assertEqual(pjlink.lamp[2]['On'], True, - 'Lamp 3 power status should have been set to TRUE') - self.assertEqual(pjlink.lamp[2]['Hours'], 33333, - 'Lamp 3 hours should have been set to 33333') + assert 3 == len(pjlink.lamp), 'Projector should have 3 lamps specified' + assert pjlink.lamp[0]['On'] is True, 'Lamp 1 power status should have been set to TRUE' + assert 11111 == pjlink.lamp[0]['Hours'], 'Lamp 1 hours should have been set to 11111' + assert pjlink.lamp[1]['On'] is False, 'Lamp 2 power status should have been set to FALSE' + assert 22222 == pjlink.lamp[1]['Hours'], 'Lamp 2 hours should have been set to 22222' + assert pjlink.lamp[2]['On'] is True, 'Lamp 3 power status should have been set to TRUE' + assert 33333 == pjlink.lamp[2]['Hours'], 'Lamp 3 hours should have been set to 33333' def test_projector_process_lamp_single(self): """ Test status lamp on/off and hours """ - # GIVEN: Test object - pjlink = pjlink_test - pjlink.lamps = [] - # WHEN: Call process_command with lamp data + # GIVEN: Test object + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.lamp = [] + + # WHEN: Call process_command with invalid lamp data pjlink.process_lamp('22222 1') # THEN: Lamp should have been set with status=ON and hours=22222 - self.assertEqual(pjlink.lamp[0]['On'], True, - 'Lamp power status should have been set to TRUE') - self.assertEqual(pjlink.lamp[0]['Hours'], 22222, - 'Lamp hours should have been set to 22222') + assert 1 == len(pjlink.lamp), 'Projector should have only 1 lamp' + assert pjlink.lamp[0]['On'] is True, 'Lamp power status should have been set to TRUE' + assert 22222 == pjlink.lamp[0]['Hours'], 'Lamp hours should have been set to 22222' - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_process_name(self, mock_log): + def test_projector_process_lamp_single_hours_only(self): + """ + Test process lamp with 1 lamp reply hours only and no on/off status + """ + # GIVEN: Test object + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.lamp = [] + + # WHEN: Process lamp command called with only hours and no lamp power state + pjlink.process_lamp("45") + + # THEN: Lamp should show hours as 45 and lamp power as Unavailable + assert 1 == len(pjlink.lamp), 'There should only be 1 lamp available' + assert 45 == pjlink.lamp[0]['Hours'], 'Lamp hours should have equalled 45' + assert pjlink.lamp[0]['On'] is None, 'Lamp power should be "None"' + + def test_projector_process_name(self): """ Test saving NAME data from projector """ - # GIVEN: Test data - pjlink = pjlink_test - test_data = "Some Name the End-User Set IN Projector" - test_log = '(127.0.0.1) Setting projector PJLink name to "Some Name the End-User Set IN Projector"' - mock_log.reset_mock() + # GIVEN: Test object + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + chk_data = "Some Name the End-User Set IN Projector" + log_debug_calls = [call('({ip}) Setting projector PJLink name to ' + '"Some Name the End-User Set IN Projector"'.format(ip=pjlink.name))] - # WHEN: process_name called with test data - pjlink.process_name(data=test_data) + # WHEN: process_name called with test data + pjlink.process_name(data=chk_data) - # THEN: name should be set and logged - self.assertEqual(pjlink.pjlink_name, test_data, 'Name test data should have been saved') - mock_log.debug.assert_called_once_with(test_log) + # THEN: name should be set and logged + assert pjlink.pjlink_name == chk_data, 'Name test data should have been saved' + mock_log.debug.assert_has_calls(log_debug_calls) - @patch.object(pjlink_test, 'projectorUpdateIcons') - @patch.object(pjlink_test, 'send_command') - @patch.object(pjlink_test, 'change_status') - def test_projector_process_powr_on(self, - mock_change_status, - mock_send_command, - mock_UpdateIcons): + def test_projector_process_powr_on(self): """ Test status power to ON """ - # GIVEN: Test object and preset - pjlink = pjlink_test - pjlink.power = S_STANDBY - test_data = PJLINK_POWR_STATUS[S_ON] + # GIVEN: Test object + with patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons: - # WHEN: Call process_command with turn power on command - pjlink.process_command(cmd='POWR', data=test_data) + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.power = S_STANDBY - # THEN: Power should be set to ON - self.assertEqual(pjlink.power, S_ON, 'Power should have been set to ON') - mock_send_command.assert_called_once_with('INST') - mock_change_status.assert_called_once_with(PJLINK_POWR_STATUS[test_data]) - self.assertEqual(mock_UpdateIcons.emit.called, True, 'projectorUpdateIcons should have been called') + # WHEN: process_name called with test data + pjlink.process_powr(data=PJLINK_POWR_STATUS[S_ON]) - @patch.object(pjlink_test, 'projectorUpdateIcons') - @patch.object(pjlink_test, 'send_command') - @patch.object(pjlink_test, 'change_status') - def test_projector_process_powr_invalid(self, - mock_change_status, - mock_send_command, - mock_UpdateIcons): + # THEN: Power should be set to ON + assert pjlink.power == S_ON, 'Power should have been set to ON' + assert mock_UpdateIcons.emit.called is True, 'projectorUpdateIcons should have been called' + mock_send_command.assert_called_once_with('INST') + mock_change_status.assert_called_once_with(S_ON) + + def test_projector_process_powr_invalid(self): """ Test process_powr invalid call """ - # GIVEN: Test object and preset - pjlink = pjlink_test - pjlink.power = S_STANDBY - test_data = '99' + # GIVEN: Test object + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons: - # WHEN: Call process_command with turn power on command - pjlink.process_command(cmd='POWR', data=test_data) + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.power = S_STANDBY + log_warn_calls = [call('({ip}) Unknown power response: "99"'.format(ip=pjlink.name))] - # THEN: Power should be set to ON - self.assertEqual(pjlink.power, S_STANDBY, 'Power should not have changed') - self.assertFalse(mock_change_status.called, 'Change status should not have been called') - self.assertFalse(mock_send_command.called, 'send_command("INST") should not have been called') - self.assertFalse(mock_UpdateIcons.emit.called, 'projectorUpdateIcons should not have been called') + # WHEN: process_name called with test data + pjlink.process_powr(data='99') - @patch.object(pjlink_test, 'projectorUpdateIcons') - @patch.object(pjlink_test, 'send_command') - @patch.object(pjlink_test, 'change_status') - def test_projector_process_powr_off(self, - mock_change_status, - mock_send_command, - mock_UpdateIcons): + # THEN: Power should be set to ON + assert pjlink.power == S_STANDBY, 'Power should not have changed' + assert mock_UpdateIcons.emit.called is False, 'projectorUpdateIcons() should not have been called' + mock_change_status.called is False, 'change_status() should not have been called' + mock_send_command.called is False, 'send_command() should not have been called' + mock_log.warning.assert_has_calls(log_warn_calls) + + def test_projector_process_powr_off(self): """ Test status power to STANDBY """ - # GIVEN: Test object and preset - pjlink = pjlink_test - pjlink.power = S_ON - test_data = PJLINK_POWR_STATUS[S_STANDBY] + # GIVEN: Test object + with patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \ + patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons: - # WHEN: Call process_command with turn power on command - pjlink.process_command(cmd='POWR', data=test_data) + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.power = S_ON - # THEN: Power should be set to STANDBY - self.assertEqual(pjlink.power, S_STANDBY, 'Power should have been set to STANDBY') - self.assertEqual(mock_UpdateIcons.emit.called, True, 'projectorUpdateIcons should have been called') - mock_change_status.assert_called_once_with(PJLINK_POWR_STATUS[test_data]) - self.assertFalse(mock_send_command.called, "send_command['INST'] should not have been called") + # WHEN: process_name called with test data + pjlink.process_powr(data=PJLINK_POWR_STATUS[S_STANDBY]) + + # THEN: Power should be set to ON + assert pjlink.power == S_STANDBY, 'Power should have changed to S_STANDBY' + assert mock_UpdateIcons.emit.called is True, 'projectorUpdateIcons should have been called' + mock_change_status.called is True, 'change_status should have been called' + mock_send_command.called is False, 'send_command should not have been called' def test_projector_process_rfil_save(self): """ Test saving filter type """ - # GIVEN: Test object - pjlink = pjlink_test - pjlink.model_filter = None filter_model = 'Filter Type Test' + # GIVEN: Test object + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.model_filter = None + # WHEN: Filter model is received pjlink.process_rfil(data=filter_model) # THEN: Filter model number should be saved - self.assertEqual(pjlink.model_filter, filter_model, 'Filter type should have been saved') + assert pjlink.model_filter == filter_model, 'Filter type should have been saved' def test_projector_process_rfil_nosave(self): """ Test saving filter type previously saved """ # GIVEN: Test object - pjlink = pjlink_test - pjlink.model_filter = 'Old filter type' - filter_model = 'Filter Type Test' + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: - # WHEN: Filter model is received - pjlink.process_rfil(data=filter_model) + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.model_filter = 'Old filter type' + filter_model = 'Filter Type Test' + log_warn_calls = [call('({ip}) Filter model already set'.format(ip=pjlink.name)), + call('({ip}) Saved model: "Old filter type"'.format(ip=pjlink.name)), + call('({ip}) New model: "Filter Type Test"'.format(ip=pjlink.name))] - # THEN: Filter model number should be saved - self.assertNotEquals(pjlink.model_filter, filter_model, 'Filter type should NOT have been saved') + # WHEN: Filter model is received + pjlink.process_rfil(data=filter_model) + + # THEN: Filter model number should be saved + assert pjlink.model_filter != filter_model, 'Filter type should NOT have been saved' + mock_log.warning.assert_has_calls(log_warn_calls) def test_projector_process_rlmp_save(self): """ Test saving lamp type """ # GIVEN: Test object - pjlink = pjlink_test + # GIVEN: Test object + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) pjlink.model_lamp = None lamp_model = 'Lamp Type Test' @@ -962,159 +688,130 @@ class TestPJLinkCommands(TestCase): pjlink.process_rlmp(data=lamp_model) # THEN: Filter model number should be saved - self.assertEqual(pjlink.model_lamp, lamp_model, 'Lamp type should have been saved') + assert pjlink.model_lamp == lamp_model, 'Lamp type should have been saved' def test_projector_process_rlmp_nosave(self): """ Test saving lamp type previously saved """ # GIVEN: Test object - pjlink = pjlink_test - pjlink.model_lamp = 'Old lamp type' - lamp_model = 'Filter Type Test' + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: - # WHEN: Filter model is received - pjlink.process_rlmp(data=lamp_model) + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.model_lamp = 'Old lamp type' + lamp_model = 'Lamp Type Test' + log_warn_calls = [call('({ip}) Lamp model already set'.format(ip=pjlink.name)), + call('({ip}) Saved lamp: "Old lamp type"'.format(ip=pjlink.name)), + call('({ip}) New lamp: "Lamp Type Test"'.format(ip=pjlink.name))] - # THEN: Filter model number should be saved - self.assertNotEquals(pjlink.model_lamp, lamp_model, 'Lamp type should NOT have been saved') + # WHEN: Filter model is received + pjlink.process_rlmp(data=lamp_model) + + # THEN: Filter model number should be saved + assert pjlink.model_lamp != lamp_model, 'Lamp type should NOT have been saved' + mock_log.warning.assert_has_calls(log_warn_calls) def test_projector_process_snum_set(self): """ Test saving serial number from projector """ # GIVEN: Test object - pjlink = pjlink_test - pjlink.serial_no = None - test_number = 'Test Serial Number' + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: - # WHEN: No serial number is set and we receive serial number command - pjlink.process_snum(data=test_number) + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.serial_no = None + log_debug_calls = [call('({ip}) Setting projector serial number to ' + '"Test Serial Number"'.format(ip=pjlink.name))] + test_number = 'Test Serial Number' - # THEN: Serial number should be set - self.assertEqual(pjlink.serial_no, test_number, - 'Projector serial number should have been set') + # WHEN: No serial number is set and we receive serial number command + pjlink.process_snum(data=test_number) + + # THEN: Serial number should be set + assert pjlink.serial_no == test_number, 'Projector serial number should have been set' + mock_log.debug.assert_has_calls(log_debug_calls) def test_projector_process_snum_different(self): """ Test projector serial number different than saved serial number """ # GIVEN: Test object - pjlink = pjlink_test - pjlink.serial_no = 'Previous serial number' - test_number = 'Test Serial Number' + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.serial_no = 'Previous serial number' + log_warn_calls = [call('({ip}) Projector serial number does not match ' + 'saved serial number'.format(ip=pjlink.name)), + call('({ip}) Saved: "Previous serial number"'.format(ip=pjlink.name)), + call('({ip}) Received: "Test Serial Number"'.format(ip=pjlink.name)), + call('({ip}) NOT saving serial number'.format(ip=pjlink.name))] + test_number = 'Test Serial Number' - # WHEN: No serial number is set and we receive serial number command - pjlink.process_snum(data=test_number) + # WHEN: No serial number is set and we receive serial number command + pjlink.process_snum(data=test_number) - # THEN: Serial number should be set - self.assertNotEquals(pjlink.serial_no, test_number, - 'Projector serial number should NOT have been set') + # THEN: Serial number should be set + assert pjlink.serial_no != test_number, 'Projector serial number should NOT have been set' + mock_log.warning.assert_has_calls(log_warn_calls) - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_process_sver(self, mock_log): + def test_projector_process_sver(self): """ Test invalid software version information - too long """ # GIVEN: Test object - pjlink = pjlink_test - pjlink.sw_version = None - pjlink.sw_version_received = None - test_data = 'Test 1 Subtest 1' - test_log = '(127.0.0.1) Setting projector software version to "Test 1 Subtest 1"' - mock_log.reset_mock() + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.sw_version = None + pjlink.sw_version_received = None + test_data = 'Test 1 Subtest 1' + log_debug_calls = [call('({ip}) Setting projector software version to ' + '"Test 1 Subtest 1"'.format(ip=pjlink.name))] - # WHEN: process_sver called with invalid data - pjlink.process_sver(data=test_data) + # WHEN: process_sver called with invalid data + pjlink.process_sver(data=test_data) - # THEN: Version information should not change - self.assertEqual(pjlink.sw_version, test_data, 'Software version should have been updated') - self.assertIsNone(pjlink.sw_version_received, 'Received software version should not have changed') - mock_log.debug.assert_called_once_with(test_log) + # THEN: Version information should not change + assert pjlink.sw_version == test_data, 'Software version should have been updated' + mock_log.debug.assert_has_calls(log_debug_calls) - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_process_sver_changed(self, mock_log): + def test_projector_process_sver_changed(self): """ Test invalid software version information - Received different than saved """ # GIVEN: Test object - pjlink = pjlink_test - test_data_new = 'Test 1 Subtest 2' - test_data_old = 'Test 1 Subtest 1' - pjlink.sw_version = test_data_old - pjlink.sw_version_received = None - test_log = '(127.0.0.1) Saving new serial number as sw_version_received' - mock_log.reset_mock() + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + test_data_old = 'Test 1 Subtest 1' + test_data_new = 'Test 1 Subtest 2' + log_warn_calls = [call('({ip}) Projector software version does not match ' + 'saved software version'.format(ip=pjlink.name)), + call('({ip}) Saved: "Test 1 Subtest 1"'.format(ip=pjlink.name)), + call('({ip}) Received: "Test 1 Subtest 2"'.format(ip=pjlink.name)), + call('({ip}) Updating software version'.format(ip=pjlink.name))] + pjlink.sw_version = test_data_old - # WHEN: process_sver called with invalid data - pjlink.process_sver(data=test_data_new) + # WHEN: process_sver called with invalid data + pjlink.process_sver(data=test_data_new) - # THEN: Version information should not change - self.assertEqual(pjlink.sw_version, test_data_old, 'Software version should not have been updated') - self.assertEqual(pjlink.sw_version_received, test_data_new, - 'Received software version should have been changed') - self.assertEqual(mock_log.warning.call_count, 4, 'log.warn should have been called 4 times') - # There was 4 calls, but only the last one is checked with this method - mock_log.warning.assert_called_with(test_log) + # THEN: Version information should not change + assert pjlink.sw_version == test_data_new, 'Software version should have changed' + mock_log.warning.assert_has_calls(log_warn_calls) - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_projector_process_sver_invalid(self, mock_log): + def test_projector_process_sver_invalid(self): """ Test invalid software version information - too long """ - # GIVEN: Test object - pjlink = pjlink_test - pjlink.sw_version = None - pjlink.sw_version_received = None test_data = 'This is a test software version line that is too long based on PJLink version 2 specs' - test_log = "Invalid software version - too long" - mock_log.reset_mock() + log_warn_calls = [call('Invalid software version - too long')] - # WHEN: process_sver called with invalid data - pjlink.process_sver(data=test_data) + # GIVEN: Test object + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + pjlink.sw_version = None - # THEN: Version information should not change - self.assertIsNone(pjlink.sw_version, 'Software version should not have changed') - self.assertIsNone(pjlink.sw_version_received, 'Received software version should not have changed') - mock_log.warning.assert_called_once_with(test_log) + # WHEN: process_sver called with invalid data + pjlink.process_sver(data=test_data) - def test_projector_reset_information(self): - """ - Test reset_information() resets all information and stops timers - """ - # GIVEN: Test object and test data - pjlink = pjlink_test - pjlink.power = S_ON - pjlink.pjlink_name = 'OPENLPTEST' - pjlink.manufacturer = 'PJLINK' - pjlink.model = '1' - pjlink.shutter = True - pjlink.mute = True - pjlink.lamp = True - pjlink.fan = True - pjlink.source_available = True - pjlink.other_info = 'ANOTHER TEST' - pjlink.send_queue = True - pjlink.send_busy = True - - # WHEN: reset_information() is called - with patch.object(pjlink, 'timer') as mock_timer: - with patch.object(pjlink, 'socket_timer') as mock_socket_timer: - pjlink.reset_information() - - # THEN: All information should be reset and timers stopped - self.assertEqual(pjlink.power, S_OFF, 'Projector power should be OFF') - self.assertIsNone(pjlink.pjlink_name, 'Projector pjlink_name should be None') - self.assertIsNone(pjlink.manufacturer, 'Projector manufacturer should be None') - self.assertIsNone(pjlink.model, 'Projector model should be None') - self.assertIsNone(pjlink.shutter, 'Projector shutter should be None') - self.assertIsNone(pjlink.mute, 'Projector shuttter should be None') - self.assertIsNone(pjlink.lamp, 'Projector lamp should be None') - self.assertIsNone(pjlink.fan, 'Projector fan should be None') - self.assertIsNone(pjlink.source_available, 'Projector source_available should be None') - self.assertIsNone(pjlink.source, 'Projector source should be None') - self.assertIsNone(pjlink.other_info, 'Projector other_info should be None') - self.assertEqual(pjlink.send_queue, [], 'Projector send_queue should be an empty list') - self.assertFalse(pjlink.send_busy, 'Projector send_busy should be False') - self.assertTrue(mock_timer.stop.called, 'Projector timer.stop() should have been called') - self.assertTrue(mock_socket_timer.stop.called, 'Projector socket_timer.stop() should have been called') + # THEN: Version information should not change + assert pjlink.sw_version is None, 'Software version should not have changed' + assert pjlink.sw_version_received is None, 'Received software version should not have changed' + mock_log.warning.assert_has_calls(log_warn_calls) diff --git a/tests/functional/openlp_core/projectors/test_projector_pjlink_commands_02.py b/tests/functional/openlp_core/projectors/test_projector_pjlink_commands_02.py index 62ba4ec76..132a43df1 100644 --- a/tests/functional/openlp_core/projectors/test_projector_pjlink_commands_02.py +++ b/tests/functional/openlp_core/projectors/test_projector_pjlink_commands_02.py @@ -26,10 +26,9 @@ from unittest import TestCase from unittest.mock import patch, call import openlp.core.projectors.pjlink -from openlp.core.projectors.constants import S_CONNECTED +from openlp.core.projectors.constants import S_CONNECTED, S_OFF, S_ON from openlp.core.projectors.db import Projector from openlp.core.projectors.pjlink import PJLink - from tests.resources.projector.data import TEST_HASH, TEST_PIN, TEST_SALT, TEST1_DATA @@ -37,17 +36,52 @@ class TestPJLinkCommands(TestCase): """ Tests for the PJLinkCommands class part 2 """ - def setUp(self): - ''' - TestPJLinkCommands part 2 initialization - ''' - self.pjlink_test = PJLink(Projector(**TEST1_DATA), no_poll=True) + def test_projector_reset_information(self): + """ + Test reset_information() resets all information and stops timers + """ + # GIVEN: Test object + with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + log_debug_calls = [call('({ip}): Calling poll_timer.stop()'.format(ip=pjlink.name)), + call('({ip}): Calling socket_timer.stop()'.format(ip=pjlink.name))] + # timer and socket_timer not available until instantiation, so mock here + with patch.object(pjlink, 'socket_timer') as mock_socket_timer, \ + patch.object(pjlink, 'poll_timer') as mock_timer: - def tearDown(self): - ''' - TestPJLinkCommands part 2 cleanups - ''' - self.pjlink_test = None + pjlink.power = S_ON + pjlink.pjlink_name = 'OPENLPTEST' + pjlink.manufacturer = 'PJLINK' + pjlink.model = '1' + pjlink.shutter = True + pjlink.mute = True + pjlink.lamp = True + pjlink.fan = True + pjlink.source_available = True + pjlink.other_info = 'ANOTHER TEST' + pjlink.send_queue = True + pjlink.send_busy = True + + # WHEN: reset_information() is called + pjlink.reset_information() + + # THEN: All information should be reset and timers stopped + assert pjlink.power == S_OFF, 'Projector power should be OFF' + assert pjlink.pjlink_name is None, 'Projector pjlink_name should be None' + assert pjlink.manufacturer is None, 'Projector manufacturer should be None' + assert pjlink.model is None, 'Projector model should be None' + assert pjlink.shutter is None, 'Projector shutter should be None' + assert pjlink.mute is None, 'Projector shuttter should be None' + assert pjlink.lamp is None, 'Projector lamp should be None' + assert pjlink.fan is None, 'Projector fan should be None' + assert pjlink.source_available is None, 'Projector source_available should be None' + assert pjlink.source is None, 'Projector source should be None' + assert pjlink.other_info is None, 'Projector other_info should be None' + assert pjlink.send_queue == [], 'Projector send_queue should be an empty list' + assert pjlink.send_busy is False, 'Projector send_busy should be False' + assert mock_timer.stop.called is True, 'Projector timer.stop() should have been called' + assert mock_socket_timer.stop.called is True, 'Projector socket_timer.stop() should have been called' + mock_log.debug.assert_has_calls(log_debug_calls) def test_process_pjlink_normal(self): """ @@ -55,13 +89,14 @@ class TestPJLinkCommands(TestCase): """ # GIVEN: Initial mocks and data mock_log = patch.object(openlp.core.projectors.pjlink, "log").start() - mock_disconnect_from_host = patch.object(self.pjlink_test, 'disconnect_from_host').start() - mock_send_command = patch.object(self.pjlink_test, 'send_command').start() - mock_readyRead = patch.object(self.pjlink_test, 'readyRead').start() - mock_change_status = patch.object(self.pjlink_test, 'change_status').start() - pjlink = self.pjlink_test + mock_disconnect_from_host = patch('openlp.core.projectors.pjlink.PJLink.disconnect_from_host').start() + mock_send_command = patch('openlp.core.projectors.pjlink.PJLink.send_command').start() + mock_readyRead = patch('openlp.core.projectors.pjlink.PJLink.readyRead').start() + mock_change_status = patch('openlp.core.projectors.pjlink.PJLink.change_status').start() + + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) pjlink.pin = None - log_check = [call("({111.111.111.111}) process_pjlink(): Sending 'CLSS' initial command'"), ] + log_check = [call('({ip}) process_pjlink(): Sending "CLSS" initial command'.format(ip=pjlink.name)), ] # WHEN: process_pjlink called with no authentication required pjlink.process_pjlink(data="0") @@ -69,7 +104,7 @@ class TestPJLinkCommands(TestCase): # THEN: proper processing should have occured mock_log.debug.has_calls(log_check) mock_disconnect_from_host.assert_not_called() - self.assertEqual(mock_readyRead.connect.call_count, 1, 'Should have only been called once') + assert 1 == mock_readyRead.connect.call_count, 'Should have only been called once' mock_change_status.assert_called_once_with(S_CONNECTED) mock_send_command.assert_called_with(cmd='CLSS', priority=True, salt=None) @@ -79,13 +114,14 @@ class TestPJLinkCommands(TestCase): """ # GIVEN: Initial mocks and data mock_log = patch.object(openlp.core.projectors.pjlink, "log").start() - mock_disconnect_from_host = patch.object(self.pjlink_test, 'disconnect_from_host').start() - mock_send_command = patch.object(self.pjlink_test, 'send_command').start() - mock_readyRead = patch.object(self.pjlink_test, 'readyRead').start() - mock_change_status = patch.object(self.pjlink_test, 'change_status').start() - pjlink = self.pjlink_test + mock_disconnect_from_host = patch('openlp.core.projectors.pjlink.PJLink.disconnect_from_host').start() + mock_send_command = patch('openlp.core.projectors.pjlink.PJLink.send_command').start() + mock_readyRead = patch('openlp.core.projectors.pjlink.PJLink.readyRead').start() + mock_change_status = patch('openlp.core.projectors.pjlink.PJLink.change_status').start() + + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) pjlink.pin = TEST_PIN - log_check = [call("({111.111.111.111}) process_pjlink(): Sending 'CLSS' initial command'"), ] + log_check = [call('({ip}) process_pjlink(): Sending "CLSS" initial command'.format(ip=pjlink.name)), ] # WHEN: process_pjlink called with no authentication required pjlink.process_pjlink(data='1 {salt}'.format(salt=TEST_SALT)) @@ -93,7 +129,7 @@ class TestPJLinkCommands(TestCase): # THEN: proper processing should have occured mock_log.debug.has_calls(log_check) mock_disconnect_from_host.assert_not_called() - self.assertEqual(mock_readyRead.connect.call_count, 1, 'Should have only been called once') + assert 1 == mock_readyRead.connect.call_count, 'Should have only been called once' mock_change_status.assert_called_once_with(S_CONNECTED) mock_send_command.assert_called_with(cmd='CLSS', priority=True, salt=TEST_HASH) @@ -102,20 +138,20 @@ class TestPJLinkCommands(TestCase): Test process_pjlinnk called with no authentication but pin is set """ # GIVEN: Initial mocks and data - # GIVEN: Initial mocks and data mock_log = patch.object(openlp.core.projectors.pjlink, 'log').start() - mock_disconnect_from_host = patch.object(self.pjlink_test, 'disconnect_from_host').start() - mock_send_command = patch.object(self.pjlink_test, 'send_command').start() - pjlink = self.pjlink_test + mock_disconnect_from_host = patch('openlp.core.projectors.pjlink.PJLink.disconnect_from_host').start() + mock_send_command = patch('openlp.core.projectors.pjlink.PJLink.send_command').start() + + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) pjlink.pin = TEST_PIN - log_check = [call('(111.111.111.111) Normal connection but PIN set - aborting'), ] + log_check = [call('({ip}) Normal connection but PIN set - aborting'.format(ip=pjlink.name)), ] # WHEN: process_pjlink called with invalid authentication scheme pjlink.process_pjlink(data='0') # THEN: Proper calls should be made mock_log.error.assert_has_calls(log_check) - self.assertEqual(mock_disconnect_from_host.call_count, 1, 'Should have only been called once') + assert 1 == mock_disconnect_from_host.call_count, 'Should have only been called once' mock_send_command.assert_not_called() def test_process_pjlink_normal_with_salt_error(self): @@ -123,20 +159,20 @@ class TestPJLinkCommands(TestCase): Test process_pjlinnk called with no authentication but pin is set """ # GIVEN: Initial mocks and data - # GIVEN: Initial mocks and data mock_log = patch.object(openlp.core.projectors.pjlink, 'log').start() - mock_disconnect_from_host = patch.object(self.pjlink_test, 'disconnect_from_host').start() - mock_send_command = patch.object(self.pjlink_test, 'send_command').start() - pjlink = self.pjlink_test + mock_disconnect_from_host = patch('openlp.core.projectors.pjlink.PJLink.disconnect_from_host').start() + mock_send_command = patch('openlp.core.projectors.pjlink.PJLink.send_command').start() + + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) pjlink.pin = TEST_PIN - log_check = [call('(111.111.111.111) Normal connection with extra information - aborting'), ] + log_check = [call('({ip}) Normal connection with extra information - aborting'.format(ip=pjlink.name)), ] # WHEN: process_pjlink called with invalid authentication scheme pjlink.process_pjlink(data='0 {salt}'.format(salt=TEST_SALT)) # THEN: Proper calls should be made mock_log.error.assert_has_calls(log_check) - self.assertEqual(mock_disconnect_from_host.call_count, 1, 'Should have only been called once') + assert 1 == mock_disconnect_from_host.call_count, 'Should have only been called once' mock_send_command.assert_not_called() def test_process_pjlink_invalid_authentication_scheme_length_error(self): @@ -145,17 +181,18 @@ class TestPJLinkCommands(TestCase): """ # GIVEN: Initial mocks and data mock_log = patch.object(openlp.core.projectors.pjlink, 'log').start() - mock_disconnect_from_host = patch.object(self.pjlink_test, 'disconnect_from_host').start() - mock_send_command = patch.object(self.pjlink_test, 'send_command').start() - pjlink = self.pjlink_test - log_check = [call('(111.111.111.111) Invalid initial authentication scheme - aborting'), ] + mock_disconnect_from_host = patch('openlp.core.projectors.pjlink.PJLink.disconnect_from_host').start() + mock_send_command = patch('openlp.core.projectors.pjlink.PJLink.send_command').start() + + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + log_check = [call('({ip}) Invalid initial authentication scheme - aborting'.format(ip=pjlink.name)), ] # WHEN: process_pjlink called with invalid authentication scheme pjlink.process_pjlink(data='01') # THEN: socket should be closed and invalid data logged mock_log.error.assert_has_calls(log_check) - self.assertEqual(mock_disconnect_from_host.call_count, 1, 'Should have only been called once') + assert 1 == mock_disconnect_from_host.call_count, 'Should have only been called once' mock_send_command.assert_not_called() def test_process_pjlink_invalid_authentication_data_length_error(self): @@ -164,17 +201,18 @@ class TestPJLinkCommands(TestCase): """ # GIVEN: Initial mocks and data mock_log = patch.object(openlp.core.projectors.pjlink, 'log').start() - mock_disconnect_from_host = patch.object(self.pjlink_test, 'disconnect_from_host').start() - mock_send_command = patch.object(self.pjlink_test, 'send_command').start() - log_check = [call('(111.111.111.111) Authenticated connection but not enough info - aborting'), ] - pjlink = self.pjlink_test + mock_disconnect_from_host = patch('openlp.core.projectors.pjlink.PJLink.disconnect_from_host').start() + mock_send_command = patch('openlp.core.projectors.pjlink.PJLink.send_command').start() + + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + log_check = [call('({ip}) Authenticated connection but not enough info - aborting'.format(ip=pjlink.name)), ] # WHEN: process_pjlink called with no salt pjlink.process_pjlink(data='1') # THEN: socket should be closed and invalid data logged mock_log.error.assert_has_calls(log_check) - self.assertEqual(mock_disconnect_from_host.call_count, 1, 'Should have only been called once') + assert 1 == mock_disconnect_from_host.call_count, 'Should have only been called once' mock_send_command.assert_not_called() def test_process_pjlink_authenticate_pin_not_set_error(self): @@ -183,16 +221,17 @@ class TestPJLinkCommands(TestCase): """ # GIVEN: Initial mocks and data mock_log = patch.object(openlp.core.projectors.pjlink, 'log').start() - mock_disconnect_from_host = patch.object(self.pjlink_test, 'disconnect_from_host').start() - mock_send_command = patch.object(self.pjlink_test, 'send_command').start() - log_check = [call('(111.111.111.111) Authenticate connection but no PIN - aborting'), ] - pjlink = self.pjlink_test + mock_disconnect_from_host = patch('openlp.core.projectors.pjlink.PJLink.disconnect_from_host').start() + mock_send_command = patch('openlp.core.projectors.pjlink.PJLink.send_command').start() + + pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) pjlink.pin = None + log_check = [call('({ip}) Authenticate connection but no PIN - aborting'.format(ip=pjlink.name)), ] # WHEN: process_pjlink called with no salt pjlink.process_pjlink(data='1 {salt}'.format(salt=TEST_SALT)) # THEN: socket should be closed and invalid data logged mock_log.error.assert_has_calls(log_check) - self.assertEqual(mock_disconnect_from_host.call_count, 1, 'Should have only been called once') + assert 1 == mock_disconnect_from_host.call_count, 'Should have only been called once' mock_send_command.assert_not_called() diff --git a/tests/functional/openlp_core/test_app.py b/tests/functional/openlp_core/test_app.py index eccb81447..cd365c443 100644 --- a/tests/functional/openlp_core/test_app.py +++ b/tests/functional/openlp_core/test_app.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -19,7 +19,6 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -import os import sys from unittest import TestCase, skip from unittest.mock import MagicMock, patch @@ -28,8 +27,7 @@ from PyQt5 import QtCore, QtWidgets from openlp.core.app import OpenLP, parse_options from openlp.core.common.settings import Settings - -TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'resources')) +from tests.utils.constants import RESOURCE_PATH def test_parse_options_basic(): @@ -38,14 +36,15 @@ def test_parse_options_basic(): """ # GIVEN: a a set of system arguments. sys.argv[1:] = [] + # WHEN: We we parse them to expand to options - args = parse_options(None) + args = parse_options() + # THEN: the following fields will have been extracted. assert args.dev_version is False, 'The dev_version flag should be False' assert args.loglevel == 'warning', 'The log level should be set to warning' assert args.no_error_form is False, 'The no_error_form should be set to False' assert args.portable is False, 'The portable flag should be set to false' - assert args.style is None, 'There are no style flags to be processed' assert args.rargs == [], 'The service file should be blank' @@ -55,14 +54,15 @@ def test_parse_options_debug(): """ # GIVEN: a a set of system arguments. sys.argv[1:] = ['-l debug'] + # WHEN: We we parse them to expand to options - args = parse_options(None) + args = parse_options() + # THEN: the following fields will have been extracted. assert args.dev_version is False, 'The dev_version flag should be False' assert args.loglevel == ' debug', 'The log level should be set to debug' assert args.no_error_form is False, 'The no_error_form should be set to False' assert args.portable is False, 'The portable flag should be set to false' - assert args.style is None, 'There are no style flags to be processed' assert args.rargs == [], 'The service file should be blank' @@ -72,14 +72,15 @@ def test_parse_options_debug_and_portable(): """ # GIVEN: a a set of system arguments. sys.argv[1:] = ['--portable'] + # WHEN: We we parse them to expand to options - args = parse_options(None) + args = parse_options() + # THEN: the following fields will have been extracted. assert args.dev_version is False, 'The dev_version flag should be False' assert args.loglevel == 'warning', 'The log level should be set to warning' assert args.no_error_form is False, 'The no_error_form should be set to False' assert args.portable is True, 'The portable flag should be set to true' - assert args.style is None, 'There are no style flags to be processed' assert args.rargs == [], 'The service file should be blank' @@ -89,14 +90,15 @@ def test_parse_options_all_no_file(): """ # GIVEN: a a set of system arguments. sys.argv[1:] = ['-l debug', '-d'] + # WHEN: We we parse them to expand to options - args = parse_options(None) + args = parse_options() + # THEN: the following fields will have been extracted. assert args.dev_version is True, 'The dev_version flag should be True' assert args.loglevel == ' debug', 'The log level should be set to debug' assert args.no_error_form is False, 'The no_error_form should be set to False' assert args.portable is False, 'The portable flag should be set to false' - assert args.style is None, 'There are no style flags to be processed' assert args.rargs == [], 'The service file should be blank' @@ -106,14 +108,15 @@ def test_parse_options_file(): """ # GIVEN: a a set of system arguments. sys.argv[1:] = ['dummy_temp'] + # WHEN: We we parse them to expand to options - args = parse_options(None) + args = parse_options() + # THEN: the following fields will have been extracted. assert args.dev_version is False, 'The dev_version flag should be False' assert args.loglevel == 'warning', 'The log level should be set to warning' assert args.no_error_form is False, 'The no_error_form should be set to False' assert args.portable is False, 'The portable flag should be set to false' - assert args.style is None, 'There are no style flags to be processed' assert args.rargs == 'dummy_temp', 'The service file should not be blank' @@ -123,14 +126,15 @@ def test_parse_options_file_and_debug(): """ # GIVEN: a a set of system arguments. sys.argv[1:] = ['-l debug', 'dummy_temp'] + # WHEN: We we parse them to expand to options - args = parse_options(None) + args = parse_options() + # THEN: the following fields will have been extracted. assert args.dev_version is False, 'The dev_version flag should be False' assert args.loglevel == ' debug', 'The log level should be set to debug' assert args.no_error_form is False, 'The no_error_form should be set to False' assert args.portable is False, 'The portable flag should be set to false' - assert args.style is None, 'There are no style flags to be processed' assert args.rargs == 'dummy_temp', 'The service file should not be blank' @@ -280,7 +284,7 @@ class TestOpenLP(TestCase): Test the reimplemented event method """ # GIVEN: A file path and a QEvent. - file_path = os.path.join(TEST_PATH, 'church.jpg') + file_path = str(RESOURCE_PATH / 'church.jpg') mocked_file_method = MagicMock(return_value=file_path) event = QtCore.QEvent(QtCore.QEvent.FileOpen) event.file = mocked_file_method @@ -289,9 +293,9 @@ class TestOpenLP(TestCase): result = self.openlp.event(event) # THEN: The path should be inserted. - self.assertTrue(result, "The method should have returned True.") + assert result is True, "The method should have returned True." mocked_file_method.assert_called_once_with() - self.assertEqual(self.openlp.args[0], file_path, "The path should be in args.") + assert self.openlp.args[0] == file_path, "The path should be in args." @patch('openlp.core.app.is_macosx') def test_application_activate_event(self, mocked_is_macosx): @@ -309,8 +313,8 @@ class TestOpenLP(TestCase): result = self.openlp.event(event) # THEN: - self.assertTrue(result, "The method should have returned True.") - # self.assertFalse(self.openlp.main_window.isMinimized()) + assert result is True, "The method should have returned True." + # assert self.openlp.main_window.isMinimized() is False @patch('openlp.core.app.get_version') @patch('openlp.core.app.QtWidgets.QMessageBox.question') @@ -321,11 +325,11 @@ class TestOpenLP(TestCase): # GIVEN: Mocked data version and OpenLP version which are the same old_install = False MOCKED_VERSION = { - 'full': '2.2.0-bzr000', - 'version': '2.2.0', + 'full': '2.4.0-bzr000', + 'version': '2.4.0', 'build': 'bzr000' } - Settings().setValue('core/application version', '2.2.0') + Settings().setValue('core/application version', '2.4.0') mocked_get_version.return_value = MOCKED_VERSION mocked_question.return_value = QtWidgets.QMessageBox.No @@ -333,8 +337,8 @@ class TestOpenLP(TestCase): self.openlp.backup_on_upgrade(old_install, False) # THEN: It should not ask if we want to create a backup - self.assertEqual(Settings().value('core/application version'), '2.2.0', 'Version should be the same!') - self.assertEqual(mocked_question.call_count, 0, 'No question should have been asked!') + assert Settings().value('core/application version') == '2.4.0', 'Version should be the same!' + assert mocked_question.call_count == 0, 'No question should have been asked!' @patch('openlp.core.app.get_version') @patch('openlp.core.app.QtWidgets.QMessageBox.question') @@ -345,8 +349,8 @@ class TestOpenLP(TestCase): # GIVEN: Mocked data version and OpenLP version which are different old_install = True MOCKED_VERSION = { - 'full': '2.2.0-bzr000', - 'version': '2.2.0', + 'full': '2.4.0-bzr000', + 'version': '2.4.0', 'build': 'bzr000' } Settings().setValue('core/application version', '2.0.5') @@ -359,7 +363,7 @@ class TestOpenLP(TestCase): self.openlp.backup_on_upgrade(old_install, True) # THEN: It should ask if we want to create a backup - self.assertEqual(Settings().value('core/application version'), '2.2.0', 'Version should be upgraded!') - self.assertEqual(mocked_question.call_count, 1, 'A question should have been asked!') + assert Settings().value('core/application version') == '2.4.0', 'Version should be upgraded!' + assert mocked_question.call_count == 1, 'A question should have been asked!' self.openlp.splash.hide.assert_called_once_with() self.openlp.splash.show.assert_called_once_with() diff --git a/tests/functional/openlp_core/test_threading.py b/tests/functional/openlp_core/test_threading.py new file mode 100644 index 000000000..177f4bf99 --- /dev/null +++ b/tests/functional/openlp_core/test_threading.py @@ -0,0 +1,191 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2018 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 # +############################################################################### +""" +Package to test the openlp.core.threading package. +""" +from inspect import isfunction +from unittest.mock import MagicMock, call, patch + +from openlp.core.threading import ThreadWorker, run_thread, get_thread_worker, is_thread_finished, make_remove_thread + + +def test_run_thread_no_name(): + """ + Test that trying to run a thread without a name results in an exception being thrown + """ + # GIVEN: A fake worker + # WHEN: run_thread() is called without a name + try: + run_thread(MagicMock(), '') + assert False, 'A ValueError should have been thrown to prevent blank names' + except ValueError: + # THEN: A ValueError should have been thrown + assert True, 'A ValueError was correctly thrown' + + +@patch('openlp.core.threading.Registry') +def test_run_thread_exists(MockRegistry): + """ + Test that trying to run a thread with a name that already exists will throw a KeyError + """ + # GIVEN: A mocked registry with a main window object + mocked_application = MagicMock() + mocked_application.worker_threads = {'test_thread': MagicMock()} + MockRegistry.return_value.get.return_value = mocked_application + + # WHEN: run_thread() is called + try: + run_thread(MagicMock(), 'test_thread') + assert False, 'A KeyError should have been thrown to show that a thread with this name already exists' + except KeyError: + assert True, 'A KeyError was correctly thrown' + + +@patch('openlp.core.threading.QtCore.QThread') +@patch('openlp.core.threading.Registry') +def test_run_thread(MockRegistry, MockQThread): + """ + Test that running a thread works correctly + """ + # GIVEN: A mocked registry with a main window object + mocked_application = MagicMock() + mocked_application.worker_threads = {} + MockRegistry.return_value.get.return_value = mocked_application + + # WHEN: run_thread() is called + run_thread(MagicMock(), 'test_thread') + + # THEN: The thread should be in the threads list and the correct methods should have been called + assert len(mocked_application.worker_threads.keys()) == 1, 'There should be 1 item in the list of threads' + assert list(mocked_application.worker_threads.keys()) == ['test_thread'], \ + 'The test_thread item should be in the list' + mocked_worker = mocked_application.worker_threads['test_thread']['worker'] + mocked_thread = mocked_application.worker_threads['test_thread']['thread'] + mocked_worker.moveToThread.assert_called_once_with(mocked_thread) + mocked_thread.started.connect.assert_called_once_with(mocked_worker.start) + expected_quit_calls = [call(mocked_thread.quit), call(mocked_worker.deleteLater)] + assert mocked_worker.quit.connect.call_args_list == expected_quit_calls, \ + 'The workers quit signal should be connected twice' + assert mocked_thread.finished.connect.call_args_list[0] == call(mocked_thread.deleteLater), \ + 'The threads finished signal should be connected to its deleteLater slot' + assert mocked_thread.finished.connect.call_count == 2, 'The signal should have been connected twice' + mocked_thread.start.assert_called_once_with() + + +def test_thread_worker(): + """ + Test that creating a thread worker object and calling start throws and NotImplementedError + """ + # GIVEN: A ThreadWorker class + worker = ThreadWorker() + + try: + # WHEN: calling start() + worker.start() + assert False, 'A NotImplementedError should have been thrown' + except NotImplementedError: + # A NotImplementedError should be thrown + pass + except Exception: + assert False, 'A NotImplementedError should have been thrown' + + +@patch('openlp.core.threading.Registry') +def test_get_thread_worker(MockRegistry): + """ + Test that calling the get_thread_worker() function returns the correct worker + """ + # GIVEN: A mocked thread worker + mocked_worker = MagicMock() + MockRegistry.return_value.get.return_value.worker_threads = {'test_thread': {'worker': mocked_worker}} + + # WHEN: get_thread_worker() is called + worker = get_thread_worker('test_thread') + + # THEN: The mocked worker is returned + assert worker is mocked_worker, 'The mocked worker should have been returned' + + +@patch('openlp.core.threading.Registry') +def test_get_thread_worker_mising(MockRegistry): + """ + Test that calling the get_thread_worker() function raises a KeyError if it does not exist + """ + # GIVEN: A mocked thread worker + MockRegistry.return_value.get.return_value.worker_threads = {} + + try: + # WHEN: get_thread_worker() is called + get_thread_worker('test_thread') + assert False, 'A KeyError should have been raised' + except KeyError: + # THEN: The mocked worker is returned + pass + except Exception: + assert False, 'A KeyError should have been raised' + + +@patch('openlp.core.threading.Registry') +def test_is_thread_finished(MockRegistry): + """ + Test the is_thread_finished() function + """ + # GIVEN: A mock thread and worker + mocked_thread = MagicMock() + mocked_thread.isFinished.return_value = False + MockRegistry.return_value.get.return_value.worker_threads = {'test': {'thread': mocked_thread}} + + # WHEN: is_thread_finished() is called + result = is_thread_finished('test') + + # THEN: The result should be correct + assert result is False, 'is_thread_finished should have returned False' + + +@patch('openlp.core.threading.Registry') +def test_is_thread_finished_missing(MockRegistry): + """ + Test that calling the is_thread_finished() function returns True if the thread doesn't exist + """ + # GIVEN: A mocked thread worker + MockRegistry.return_value.get.return_value.worker_threads = {} + + # WHEN: get_thread_worker() is called + result = is_thread_finished('test_thread') + + # THEN: The result should be correct + assert result is True, 'is_thread_finished should return True when a thread is missing' + + +def test_make_remove_thread(): + """ + Test the make_remove_thread() function + """ + # GIVEN: A thread name + thread_name = 'test_thread' + + # WHEN: make_remove_thread() is called + rm_func = make_remove_thread(thread_name) + + # THEN: The result should be a function + assert isfunction(rm_func), 'make_remove_thread should return a function' + assert rm_func.__name__ == 'remove_thread' diff --git a/tests/functional/openlp_core/test_version.py b/tests/functional/openlp_core/test_version.py index c5790a9b6..8d9d59fb1 100644 --- a/tests/functional/openlp_core/test_version.py +++ b/tests/functional/openlp_core/test_version.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -63,7 +63,7 @@ def test_worker_start(mock_requests, mock_platform): worker.start() # THEN: The check completes and the signal is emitted - expected_download_url = 'http://www.openlp.org/files/version.txt' + expected_download_url = 'https://www.openlp.org/files/version.txt' expected_headers = {'User-Agent': 'OpenLP/2.0 Linux/4.12.0-1-amd64; '} mock_requests.get.assert_called_once_with(expected_download_url, headers=expected_headers) mock_new_version.emit.assert_called_once_with('2.4.6') @@ -88,7 +88,7 @@ def test_worker_start_dev_version(mock_requests, mock_platform): worker.start() # THEN: The check completes and the signal is emitted - expected_download_url = 'http://www.openlp.org/files/dev_version.txt' + expected_download_url = 'https://www.openlp.org/files/dev_version.txt' expected_headers = {'User-Agent': 'OpenLP/2.1.3 Linux/4.12.0-1-amd64; '} mock_requests.get.assert_called_once_with(expected_download_url, headers=expected_headers) mock_new_version.emit.assert_called_once_with('2.4.6') @@ -113,13 +113,38 @@ def test_worker_start_nightly_version(mock_requests, mock_platform): worker.start() # THEN: The check completes and the signal is emitted - expected_download_url = 'http://www.openlp.org/files/nightly_version.txt' + expected_download_url = 'https://www.openlp.org/files/nightly_version.txt' expected_headers = {'User-Agent': 'OpenLP/2.1-bzr2345 Linux/4.12.0-1-amd64; '} mock_requests.get.assert_called_once_with(expected_download_url, headers=expected_headers) mock_new_version.emit.assert_called_once_with('2.4.6') mock_quit.emit.assert_called_once_with() +@patch('openlp.core.version.platform') +@patch('openlp.core.version.requests') +def test_worker_empty_response(mock_requests, mock_platform): + """Test the VersionWorkder.start() method for empty responses""" + # GIVEN: A last check date, current version, and an instance of worker + last_check_date = '1970-01-01' + current_version = {'full': '2.1-bzr2345', 'version': '2.1', 'build': '2345'} + mock_platform.system.return_value = 'Linux' + mock_platform.release.return_value = '4.12.0-1-amd64' + mock_requests.get.return_value = MagicMock(text='\n') + worker = VersionWorker(last_check_date, current_version) + + # WHEN: The worker is run + with patch.object(worker, 'new_version') as mock_new_version, \ + patch.object(worker, 'quit') as mock_quit: + worker.start() + + # THEN: The check completes and the signal is emitted + expected_download_url = 'https://www.openlp.org/files/nightly_version.txt' + expected_headers = {'User-Agent': 'OpenLP/2.1-bzr2345 Linux/4.12.0-1-amd64; '} + mock_requests.get.assert_called_once_with(expected_download_url, headers=expected_headers) + assert mock_new_version.emit.call_count == 0 + mock_quit.emit.assert_called_once_with() + + @patch('openlp.core.version.platform') @patch('openlp.core.version.requests') def test_worker_start_connection_error(mock_requests, mock_platform): @@ -138,7 +163,7 @@ def test_worker_start_connection_error(mock_requests, mock_platform): worker.start() # THEN: The check completes and the signal is emitted - expected_download_url = 'http://www.openlp.org/files/version.txt' + expected_download_url = 'https://www.openlp.org/files/version.txt' expected_headers = {'User-Agent': 'OpenLP/2.0 Linux/4.12.0-1-amd64; '} mock_requests.get.assert_called_with(expected_download_url, headers=expected_headers) assert mock_requests.get.call_count == 3 diff --git a/tests/functional/openlp_core/ui/lib/__init__.py b/tests/functional/openlp_core/ui/lib/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/functional/openlp_core/ui/media/__init__.py b/tests/functional/openlp_core/ui/media/__init__.py index c43523cae..d8d1f2db7 100644 --- a/tests/functional/openlp_core/ui/media/__init__.py +++ b/tests/functional/openlp_core/ui/media/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/functional/openlp_core/ui/media/test_mediacontroller.py b/tests/functional/openlp_core/ui/media/test_mediacontroller.py index f468b02be..8fb141c13 100644 --- a/tests/functional/openlp_core/ui/media/test_mediacontroller.py +++ b/tests/functional/openlp_core/ui/media/test_mediacontroller.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -25,10 +25,9 @@ Package to test the openlp.core.ui.media package. from unittest import TestCase from unittest.mock import MagicMock, patch +from openlp.core.common.registry import Registry from openlp.core.ui.media.mediacontroller import MediaController from openlp.core.ui.media.mediaplayer import MediaPlayer -from openlp.core.common.registry import Registry - from tests.helpers.testmixin import TestMixin @@ -54,10 +53,10 @@ class TestMediaController(TestCase, TestMixin): media_controller._generate_extensions_lists() # THEN: extensions list should have been copied from the player to the mediacontroller - self.assertListEqual(media_player.video_extensions_list, media_controller.video_extensions_list, - 'Video extensions should be the same') - self.assertListEqual(media_player.audio_extensions_list, media_controller.audio_extensions_list, - 'Audio extensions should be the same') + assert media_player.video_extensions_list == media_controller.video_extensions_list, \ + 'Video extensions should be the same' + assert media_player.audio_extensions_list == media_controller.audio_extensions_list, \ + 'Audio extensions should be the same' def test_resize(self): """ @@ -96,7 +95,7 @@ class TestMediaController(TestCase, TestMixin): ret = media_controller._check_file_type(mocked_controller, mocked_display, mocked_service_item) # THEN: it should return False - self.assertFalse(ret, '_check_file_type should return False when no mediaplayers are available.') + assert ret is False, '_check_file_type should return False when no mediaplayers are available.' @patch('openlp.core.ui.media.mediacontroller.MediaController._get_used_players') @patch('openlp.core.ui.media.mediacontroller.UiStrings') @@ -119,7 +118,7 @@ class TestMediaController(TestCase, TestMixin): ret = media_controller._check_file_type(mocked_controller, mocked_display, mocked_service_item) # THEN: it should return False - self.assertFalse(ret, '_check_file_type should return False when the processor for service_item is None.') + assert ret is False, '_check_file_type should return False when the processor for service_item is None.' @patch('openlp.core.ui.media.mediacontroller.MediaController._get_used_players') @patch('openlp.core.ui.media.mediacontroller.UiStrings') @@ -148,8 +147,8 @@ class TestMediaController(TestCase, TestMixin): ret = media_controller._check_file_type(mocked_controller, mocked_display, mocked_service_item) # THEN: it should return True - self.assertTrue(ret, '_check_file_type should return True when mediaplayers are available and ' - 'the service item has an automatic processor.') + assert ret is True, '_check_file_type should return True when mediaplayers are available and ' \ + 'the service item has an automatic processor.' @patch('openlp.core.ui.media.mediacontroller.MediaController._get_used_players') @patch('openlp.core.ui.media.mediacontroller.UiStrings') @@ -178,8 +177,8 @@ class TestMediaController(TestCase, TestMixin): ret = media_controller._check_file_type(mocked_controller, mocked_display, mocked_service_item) # THEN: it should return True - self.assertTrue(ret, '_check_file_type should return True when the players available are different' - 'from the processor from the service item.') + assert ret is True, '_check_file_type should return True when the players available are different' \ + 'from the processor from the service item.' def test_media_play_msg(self): """ diff --git a/tests/functional/openlp_core/ui/media/test_systemplayer.py b/tests/functional/openlp_core/ui/media/test_systemplayer.py index 2fe2e0619..fc03e2541 100644 --- a/tests/functional/openlp_core/ui/media/test_systemplayer.py +++ b/tests/functional/openlp_core/ui/media/test_systemplayer.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -64,17 +64,17 @@ class TestSystemPlayer(TestCase): player = SystemPlayer(self) # THEN: The correct initial values should be set up - self.assertEqual('system', player.name) - self.assertEqual('System', player.original_name) - self.assertEqual('&System', player.display_name) - self.assertEqual(self, player.parent) - self.assertEqual(ADDITIONAL_EXT, player.additional_extensions) + assert 'system' == player.name + assert 'System' == player.original_name + assert '&System' == player.display_name + assert self == player.parent + assert ADDITIONAL_EXT == player.additional_extensions MockQMediaPlayer.assert_called_once_with(None, QtMultimedia.QMediaPlayer.VideoSurface) mocked_mimetypes.init.assert_called_once_with() mocked_media_player.service.assert_called_once_with() mocked_media_player.supportedMimeTypes.assert_called_once_with() - self.assertEqual(['*.aiff'], player.audio_extensions_list) - self.assertEqual(['*.afl', '*.asf'], player.video_extensions_list) + assert ['*.aiff'] == player.audio_extensions_list + assert ['*.afl', '*.asf'] == player.video_extensions_list @patch('openlp.core.ui.media.systemplayer.QtMultimediaWidgets.QVideoWidget') @patch('openlp.core.ui.media.systemplayer.QtMultimedia.QMediaPlayer') @@ -96,15 +96,15 @@ class TestSystemPlayer(TestCase): # THEN: The player should have a display widget MockQVideoWidget.assert_called_once_with(mocked_display) - self.assertEqual(mocked_video_widget, mocked_display.video_widget) + assert mocked_video_widget == mocked_display.video_widget mocked_display.size.assert_called_once_with() mocked_video_widget.resize.assert_called_once_with([1, 2, 3, 4]) MockQMediaPlayer.assert_called_with(mocked_display) - self.assertEqual(mocked_media_player, mocked_display.media_player) + assert mocked_media_player == mocked_display.media_player mocked_media_player.setVideoOutput.assert_called_once_with(mocked_video_widget) mocked_video_widget.raise_.assert_called_once_with() mocked_video_widget.hide.assert_called_once_with() - self.assertTrue(player.has_own_widget) + assert player.has_own_widget is True def test_disconnect_slots(self): """ @@ -133,7 +133,7 @@ class TestSystemPlayer(TestCase): result = player.check_available() # THEN: it should be available - self.assertTrue(result) + assert result is True def test_load_valid_media(self): """ @@ -157,7 +157,7 @@ class TestSystemPlayer(TestCase): mocked_display.media_player.setMedia.assert_called_once_with( QtMultimedia.QMediaContent(QtCore.QUrl.fromLocalFile('/path/to/file'))) mocked_volume.assert_called_once_with(mocked_display, 1) - self.assertTrue(result) + assert result is True def test_load_invalid_media(self): """ @@ -171,14 +171,14 @@ class TestSystemPlayer(TestCase): # WHEN: The load() method is run with patch.object(player, 'check_media') as mocked_check_media, \ - patch.object(player, 'volume') as mocked_volume: + patch.object(player, 'volume'): mocked_check_media.return_value = False result = player.load(mocked_display) # THEN: stuff mocked_display.controller.media_info.file_info.absoluteFilePath.assert_called_once_with() mocked_check_media.assert_called_once_with('/path/to/file') - self.assertFalse(result) + assert result is False def test_resize(self): """ @@ -227,7 +227,7 @@ class TestSystemPlayer(TestCase): mocked_display.media_player.durationChanged.connect.assert_called_once_with('function') mocked_set_state.assert_called_once_with(MediaState.Playing, mocked_display) mocked_display.video_widget.raise_.assert_called_once_with() - self.assertTrue(result) + assert result is True @patch('openlp.core.ui.media.systemplayer.functools') def test_play_is_preview(self, mocked_functools): @@ -258,7 +258,7 @@ class TestSystemPlayer(TestCase): mocked_display.media_player.durationChanged.connect.assert_called_once_with('function') mocked_set_state.assert_called_once_with(MediaState.Playing, mocked_display) mocked_display.video_widget.raise_.assert_called_once_with() - self.assertTrue(result) + assert result is True def test_pause_is_live(self): """ @@ -419,14 +419,13 @@ class TestSystemPlayer(TestCase): expected_position_calls = [call(), call()] expected_block_signals_calls = [call(True), call(False)] mocked_display.media_player.state.assert_called_once_with() - self.assertEqual(1, mocked_stop.call_count) - self.assertEqual(expected_stop_calls, mocked_stop.call_args_list) - self.assertEqual(2, mocked_display.media_player.position.call_count) - self.assertEqual(expected_position_calls, mocked_display.media_player.position.call_args_list) + assert 1 == mocked_stop.call_count + assert expected_stop_calls == mocked_stop.call_args_list + assert 2 == mocked_display.media_player.position.call_count + assert expected_position_calls == mocked_display.media_player.position.call_args_list mocked_set_visible.assert_called_once_with(mocked_display, False) mocked_display.controller.seek_slider.isSliderDown.assert_called_once_with() - self.assertEqual(expected_block_signals_calls, - mocked_display.controller.seek_slider.blockSignals.call_args_list) + assert expected_block_signals_calls == mocked_display.controller.seek_slider.blockSignals.call_args_list mocked_display.controller.seek_slider.setSliderPosition.assert_called_once_with(2) def test_get_media_display_css(self): @@ -440,7 +439,7 @@ class TestSystemPlayer(TestCase): result = player.get_media_display_css() # THEN: The css should be empty - self.assertEqual('', result) + assert '' == result @patch('openlp.core.ui.media.systemplayer.QtMultimedia.QMediaPlayer') def test_get_info(self, MockQMediaPlayer): @@ -459,11 +458,12 @@ class TestSystemPlayer(TestCase): # THEN: The info should be correct expected_info = 'This media player uses your operating system to provide media capabilities.
' \ 'Audio
[]
Video
[]
' - self.assertEqual(expected_info, result) + assert expected_info == result @patch('openlp.core.ui.media.systemplayer.CheckMediaWorker') - @patch('openlp.core.ui.media.systemplayer.QtCore.QThread') - def test_check_media(self, MockQThread, MockCheckMediaWorker): + @patch('openlp.core.ui.media.systemplayer.run_thread') + @patch('openlp.core.ui.media.systemplayer.is_thread_finished') + def test_check_media(self, mocked_is_thread_finished, mocked_run_thread, MockCheckMediaWorker): """ Test the check_media() method of the SystemPlayer """ @@ -473,12 +473,8 @@ class TestSystemPlayer(TestCase): Registry().create() Registry().register('application', mocked_application) player = SystemPlayer(self) - mocked_thread = MagicMock() - mocked_thread.isRunning.side_effect = [True, False] - mocked_thread.quit = 'quit' # actually supposed to be a slot, but it's all mocked out anyway - MockQThread.return_value = mocked_thread + mocked_is_thread_finished.side_effect = [False, True] mocked_check_media_worker = MagicMock() - mocked_check_media_worker.play = 'play' mocked_check_media_worker.result = True MockCheckMediaWorker.return_value = mocked_check_media_worker @@ -486,16 +482,13 @@ class TestSystemPlayer(TestCase): result = player.check_media(valid_file) # THEN: It should return True - MockQThread.assert_called_once_with() MockCheckMediaWorker.assert_called_once_with(valid_file) mocked_check_media_worker.setVolume.assert_called_once_with(0) - mocked_check_media_worker.moveToThread.assert_called_once_with(mocked_thread) - mocked_check_media_worker.finished.connect.assert_called_once_with('quit') - mocked_thread.started.connect.assert_called_once_with('play') - mocked_thread.start.assert_called_once_with() - self.assertEqual(2, mocked_thread.isRunning.call_count) + mocked_run_thread.assert_called_once_with(mocked_check_media_worker, 'check_media') + mocked_is_thread_finished.assert_called_with('check_media') + assert mocked_is_thread_finished.call_count == 2, 'is_thread_finished() should have been called twice' mocked_application.processEvents.assert_called_once_with() - self.assertTrue(result) + assert result is True class TestCheckMediaWorker(TestCase): @@ -513,7 +506,7 @@ class TestCheckMediaWorker(TestCase): worker = CheckMediaWorker(path) # THEN: The correct values should be set up - self.assertIsNotNone(worker) + assert worker is not None def test_signals_media(self): """ @@ -524,13 +517,13 @@ class TestCheckMediaWorker(TestCase): # WHEN: signals() is called with media and BufferedMedia with patch.object(worker, 'stop') as mocked_stop, \ - patch.object(worker, 'finished') as mocked_finished: + patch.object(worker, 'quit') as mocked_quit: worker.signals('media', worker.BufferedMedia) # THEN: The worker should exit and the result should be True mocked_stop.assert_called_once_with() - mocked_finished.emit.assert_called_once_with() - self.assertTrue(worker.result) + mocked_quit.emit.assert_called_once_with() + assert worker.result is True def test_signals_error(self): """ @@ -541,10 +534,10 @@ class TestCheckMediaWorker(TestCase): # WHEN: signals() is called with error and BufferedMedia with patch.object(worker, 'stop') as mocked_stop, \ - patch.object(worker, 'finished') as mocked_finished: + patch.object(worker, 'quit') as mocked_quit: worker.signals('error', None) # THEN: The worker should exit and the result should be True mocked_stop.assert_called_once_with() - mocked_finished.emit.assert_called_once_with() - self.assertFalse(worker.result) + mocked_quit.emit.assert_called_once_with() + assert worker.result is False diff --git a/tests/functional/openlp_core/ui/media/test_vlcplayer.py b/tests/functional/openlp_core/ui/media/test_vlcplayer.py index 96ab629c6..24c929563 100644 --- a/tests/functional/openlp_core/ui/media/test_vlcplayer.py +++ b/tests/functional/openlp_core/ui/media/test_vlcplayer.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -24,14 +24,13 @@ Package to test the openlp.core.ui.media.vlcplayer package. """ import os import sys -from datetime import datetime, timedelta +from datetime import timedelta from unittest import TestCase, skip from unittest.mock import MagicMock, patch, call from openlp.core.common.registry import Registry from openlp.core.ui.media import MediaState, MediaType from openlp.core.ui.media.vlcplayer import AUDIO_EXT, VIDEO_EXT, VlcPlayer, get_vlc - from tests.helpers import MockDateTime from tests.helpers.testmixin import TestMixin @@ -64,7 +63,7 @@ class TestVLCPlayer(TestCase, TestMixin): get_vlc() # THEN: The extra environment variable should be there - self.assertNotIn('openlp.core.ui.media.vendor.vlc', sys.modules) + assert 'openlp.core.ui.media.vendor.vlc' not in sys.modules @patch('openlp.core.ui.media.vlcplayer.is_macosx') def test_fix_vlc_22_plugin_path(self, mocked_is_macosx): @@ -78,9 +77,8 @@ class TestVLCPlayer(TestCase, TestMixin): get_vlc() # THEN: The extra environment variable should be there - self.assertIn('VLC_PLUGIN_PATH', os.environ, - 'The plugin path should be in the environment variables') - self.assertEqual('/Applications/VLC.app/Contents/MacOS/plugins', os.environ['VLC_PLUGIN_PATH']) + assert 'VLC_PLUGIN_PATH' in os.environ, 'The plugin path should be in the environment variables' + assert '/Applications/VLC.app/Contents/MacOS/plugins' == os.environ['VLC_PLUGIN_PATH'] @patch.dict(os.environ) @patch('openlp.core.ui.media.vlcplayer.is_macosx') @@ -95,8 +93,7 @@ class TestVLCPlayer(TestCase, TestMixin): get_vlc() # THEN: The extra environment variable should NOT be there - self.assertNotIn('VLC_PLUGIN_PATH', os.environ, - 'The plugin path should NOT be in the environment variables') + assert 'VLC_PLUGIN_PATH' not in os.environ, 'The plugin path should NOT be in the environment variables' def test_init(self): """ @@ -109,12 +106,12 @@ class TestVLCPlayer(TestCase, TestMixin): vlc_player = VlcPlayer(None) # THEN: The correct variables are set - self.assertEqual('VLC', vlc_player.original_name) - self.assertEqual('&VLC', vlc_player.display_name) - self.assertIsNone(vlc_player.parent) - self.assertTrue(vlc_player.can_folder) - self.assertListEqual(AUDIO_EXT, vlc_player.audio_extensions_list) - self.assertListEqual(VIDEO_EXT, vlc_player.video_extensions_list) + assert 'VLC' == vlc_player.original_name + assert '&VLC' == vlc_player.display_name + assert vlc_player.parent is None + assert vlc_player.can_folder is True + assert AUDIO_EXT == vlc_player.audio_extensions_list + assert VIDEO_EXT == vlc_player.video_extensions_list @patch('openlp.core.ui.media.vlcplayer.is_win') @patch('openlp.core.ui.media.vlcplayer.is_macosx') @@ -151,20 +148,20 @@ class TestVLCPlayer(TestCase, TestMixin): vlc_player.setup(mocked_display) # THEN: The VLC widget should be set up correctly - self.assertEqual(mocked_display.vlc_widget, mocked_qframe) + assert mocked_display.vlc_widget == mocked_qframe mocked_qframe.setFrameStyle.assert_called_with(1) mocked_settings.value.assert_called_with('advanced/hide mouse') mocked_vlc.Instance.assert_called_with('--no-video-title-show --no-audio --no-video-title-show ' '--mouse-hide-timeout=0') - self.assertEqual(mocked_display.vlc_instance, mocked_instance) + assert mocked_display.vlc_instance == mocked_instance mocked_instance.media_player_new.assert_called_with() - self.assertEqual(mocked_display.vlc_media_player, mocked_media_player_new) + assert mocked_display.vlc_media_player == mocked_media_player_new mocked_display.size.assert_called_with() mocked_qframe.resize.assert_called_with((10, 10)) mocked_qframe.raise_.assert_called_with() mocked_qframe.hide.assert_called_with() mocked_media_player_new.set_xwindow.assert_called_with(2) - self.assertTrue(vlc_player.has_own_widget) + assert vlc_player.has_own_widget is True @patch('openlp.core.ui.media.vlcplayer.is_win') @patch('openlp.core.ui.media.vlcplayer.is_macosx') @@ -328,7 +325,7 @@ class TestVLCPlayer(TestCase, TestMixin): is_available = vlc_player.check_available() # THEN: VLC should be available - self.assertTrue(is_available) + assert is_available is True @patch('openlp.core.ui.media.vlcplayer.get_vlc') def test_check_not_available(self, mocked_get_vlc): @@ -343,7 +340,7 @@ class TestVLCPlayer(TestCase, TestMixin): is_available = vlc_player.check_available() # THEN: VLC should NOT be available - self.assertFalse(is_available) + assert is_available is False @patch('openlp.core.ui.media.vlcplayer.get_vlc') @patch('openlp.core.ui.media.vlcplayer.os.path.normcase') @@ -376,11 +373,11 @@ class TestVLCPlayer(TestCase, TestMixin): # THEN: The video should be loaded mocked_normcase.assert_called_with(media_path) mocked_display.vlc_instance.media_new_path.assert_called_with(media_path) - self.assertEqual(mocked_vlc_media, mocked_display.vlc_media) + assert mocked_vlc_media == mocked_display.vlc_media mocked_display.vlc_media_player.set_media.assert_called_with(mocked_vlc_media) mocked_vlc_media.parse.assert_called_with() mocked_volume.assert_called_with(mocked_display, 100) - self.assertTrue(result) + assert result is True @patch('openlp.core.ui.media.vlcplayer.is_win') @patch('openlp.core.ui.media.vlcplayer.get_vlc') @@ -421,11 +418,11 @@ class TestVLCPlayer(TestCase, TestMixin): # THEN: The video should be loaded mocked_normcase.assert_called_with(media_path) mocked_display.vlc_instance.media_new_location.assert_called_with('cdda://' + media_path) - self.assertEqual(mocked_vlc_media, mocked_display.vlc_media) + assert mocked_vlc_media == mocked_display.vlc_media mocked_display.vlc_media_player.set_media.assert_called_with(mocked_vlc_media) mocked_vlc_media.parse.assert_called_with() mocked_volume.assert_called_with(mocked_display, 100) - self.assertTrue(result) + assert result is True @patch('openlp.core.ui.media.vlcplayer.is_win') @patch('openlp.core.ui.media.vlcplayer.get_vlc') @@ -466,11 +463,11 @@ class TestVLCPlayer(TestCase, TestMixin): # THEN: The video should be loaded mocked_normcase.assert_called_with(media_path) mocked_display.vlc_instance.media_new_location.assert_called_with('cdda:///' + media_path) - self.assertEqual(mocked_vlc_media, mocked_display.vlc_media) + assert mocked_vlc_media == mocked_display.vlc_media mocked_display.vlc_media_player.set_media.assert_called_with(mocked_vlc_media) mocked_vlc_media.parse.assert_called_with() mocked_volume.assert_called_with(mocked_display, 100) - self.assertTrue(result) + assert result is True @patch('openlp.core.ui.media.vlcplayer.is_win') @patch('openlp.core.ui.media.vlcplayer.get_vlc') @@ -511,11 +508,11 @@ class TestVLCPlayer(TestCase, TestMixin): # THEN: The video should be loaded mocked_normcase.assert_called_with(media_path) mocked_display.vlc_instance.media_new_location.assert_called_with('cdda://' + media_path) - self.assertEqual(mocked_vlc_media, mocked_display.vlc_media) - self.assertEqual(0, mocked_subitems.item_at_index.call_count) + assert mocked_vlc_media == mocked_display.vlc_media + assert 0 == mocked_subitems.item_at_index.call_count mocked_display.vlc_media_player.set_media.assert_called_with(mocked_vlc_media) - self.assertEqual(0, mocked_vlc_media.parse.call_count) - self.assertFalse(result) + assert 0 == mocked_vlc_media.parse.call_count + assert result is False @patch('openlp.core.ui.media.vlcplayer.get_vlc') @patch('openlp.core.ui.media.vlcplayer.datetime', MockDateTime) @@ -538,7 +535,7 @@ class TestVLCPlayer(TestCase, TestMixin): result = vlc_player.media_state_wait(mocked_display, 2) # THEN: The results should be True - self.assertTrue(result) + assert result is True @patch('openlp.core.ui.media.vlcplayer.get_vlc') @patch('openlp.core.ui.media.vlcplayer.datetime', MockDateTime) @@ -561,7 +558,7 @@ class TestVLCPlayer(TestCase, TestMixin): result = vlc_player.media_state_wait(mocked_display, 2) # THEN: The results should be True - self.assertFalse(result) + assert result is False @patch('openlp.core.ui.media.vlcplayer.get_vlc') @patch('openlp.core.ui.media.vlcplayer.datetime', MockDateTime) @@ -586,7 +583,7 @@ class TestVLCPlayer(TestCase, TestMixin): result = vlc_player.media_state_wait(mocked_display, 3) # THEN: The results should be True - self.assertFalse(result) + assert result is False def test_resize(self): """ @@ -636,9 +633,9 @@ class TestVLCPlayer(TestCase, TestMixin): # THEN: A bunch of things should happen to play the media mocked_thread.start.assert_called_with() mocked_volume.assert_called_with(mocked_display, 100) - self.assertEqual(MediaState.Playing, vlc_player.get_live_state()) + assert MediaState.Playing == vlc_player.get_live_state() mocked_display.vlc_widget.raise_.assert_called_with() - self.assertTrue(result, 'The value returned from play() should be True') + assert result is True, 'The value returned from play() should be True' @patch('openlp.core.ui.media.vlcplayer.threading') @patch('openlp.core.ui.media.vlcplayer.get_vlc') @@ -666,7 +663,7 @@ class TestVLCPlayer(TestCase, TestMixin): # THEN: A thread should be started, but the method should return False mocked_thread.start.assert_called_with() - self.assertFalse(result) + assert result is False @patch('openlp.core.ui.media.vlcplayer.threading') @patch('openlp.core.ui.media.vlcplayer.get_vlc') @@ -705,9 +702,9 @@ class TestVLCPlayer(TestCase, TestMixin): mocked_display.vlc_media_player.audio_set_track.assert_called_with(1) mocked_display.vlc_media_player.video_set_spu.assert_called_with(1) mocked_volume.assert_called_with(mocked_display, 100) - self.assertEqual(MediaState.Playing, vlc_player.get_live_state()) + assert MediaState.Playing == vlc_player.get_live_state() mocked_display.vlc_widget.raise_.assert_called_with() - self.assertTrue(result, 'The value returned from play() should be True') + assert result is True, 'The value returned from play() should be True' @patch('openlp.core.ui.media.vlcplayer.get_vlc') def test_pause(self, mocked_get_vlc): @@ -732,7 +729,7 @@ class TestVLCPlayer(TestCase, TestMixin): mocked_display.vlc_media.get_state.assert_called_with() mocked_display.vlc_media_player.pause.assert_called_with() mocked_media_state_wait.assert_called_with(mocked_display, 2) - self.assertEqual(MediaState.Paused, vlc_player.get_live_state()) + assert MediaState.Paused == vlc_player.get_live_state() @patch('openlp.core.ui.media.vlcplayer.get_vlc') def test_pause_not_playing(self, mocked_get_vlc): @@ -752,7 +749,7 @@ class TestVLCPlayer(TestCase, TestMixin): # THEN: The pause method should exit early mocked_display.vlc_media.get_state.assert_called_with() - self.assertEqual(0, mocked_display.vlc_media_player.pause.call_count) + assert 0 == mocked_display.vlc_media_player.pause.call_count @patch('openlp.core.ui.media.vlcplayer.get_vlc') def test_pause_fail(self, mocked_get_vlc): @@ -777,7 +774,7 @@ class TestVLCPlayer(TestCase, TestMixin): mocked_display.vlc_media.get_state.assert_called_with() mocked_display.vlc_media_player.pause.assert_called_with() mocked_media_state_wait.assert_called_with(mocked_display, 2) - self.assertNotEqual(MediaState.Paused, vlc_player.state) + assert MediaState.Paused is not vlc_player.state @patch('openlp.core.ui.media.vlcplayer.threading') def test_stop(self, mocked_threading): @@ -798,7 +795,7 @@ class TestVLCPlayer(TestCase, TestMixin): # THEN: A thread should have been started to stop VLC mocked_threading.Thread.assert_called_with(target=mocked_stop) mocked_thread.start.assert_called_with() - self.assertEqual(MediaState.Stopped, vlc_player.get_live_state()) + assert MediaState.Stopped == vlc_player.get_live_state() def test_volume(self): """ @@ -828,7 +825,7 @@ class TestVLCPlayer(TestCase, TestMixin): vlc_player.volume(mocked_display, 10) # THEN: The volume should NOT have been set - self.assertEqual(0, mocked_display.vlc_media_player.audio_set_volume.call_count) + assert 0 == mocked_display.vlc_media_player.audio_set_volume.call_count def test_seek_unseekable_media(self): """ @@ -845,7 +842,7 @@ class TestVLCPlayer(TestCase, TestMixin): # THEN: nothing should happen mocked_display.vlc_media_player.is_seekable.assert_called_with() - self.assertEqual(0, mocked_display.vlc_media_player.set_time.call_count) + assert 0 == mocked_display.vlc_media_player.set_time.call_count def test_seek_seekable_media(self): """ @@ -896,7 +893,7 @@ class TestVLCPlayer(TestCase, TestMixin): # THEN: The media should be stopped and invisible mocked_display.vlc_media_player.stop.assert_called_with() mocked_display.vlc_widget.setVisible.assert_called_with(False) - self.assertEqual(MediaState.Off, vlc_player.get_live_state()) + assert MediaState.Off == vlc_player.get_live_state() def test_set_visible_has_own_widget(self): """ @@ -926,7 +923,7 @@ class TestVLCPlayer(TestCase, TestMixin): vlc_player.set_visible(mocked_display, True) # THEN: The media should be stopped and invsibile - self.assertEqual(0, mocked_display.vlc_widget.setVisible.call_count) + assert 0 == mocked_display.vlc_widget.setVisible.call_count @patch('openlp.core.ui.media.vlcplayer.get_vlc') def test_update_ui(self, mocked_get_vlc): @@ -953,12 +950,12 @@ class TestVLCPlayer(TestCase, TestMixin): # THEN: Certain methods should be called mocked_stop.assert_called_with(mocked_display) - self.assertEqual(2, mocked_stop.call_count) + assert 2 == mocked_stop.call_count mocked_display.vlc_media_player.get_time.assert_called_with() mocked_set_visible.assert_called_with(mocked_display, False) mocked_controller.seek_slider.setSliderPosition.assert_called_with(400000) expected_calls = [call(True), call(False)] - self.assertEqual(expected_calls, mocked_controller.seek_slider.blockSignals.call_args_list) + assert expected_calls == mocked_controller.seek_slider.blockSignals.call_args_list @patch('openlp.core.ui.media.vlcplayer.get_vlc') def test_update_ui_dvd(self, mocked_get_vlc): @@ -987,12 +984,12 @@ class TestVLCPlayer(TestCase, TestMixin): # THEN: Certain methods should be called mocked_stop.assert_called_with(mocked_display) - self.assertEqual(2, mocked_stop.call_count) + assert 2 == mocked_stop.call_count mocked_display.vlc_media_player.get_time.assert_called_with() mocked_set_visible.assert_called_with(mocked_display, False) mocked_controller.seek_slider.setSliderPosition.assert_called_with(300) expected_calls = [call(True), call(False)] - self.assertEqual(expected_calls, mocked_controller.seek_slider.blockSignals.call_args_list) + assert expected_calls == mocked_controller.seek_slider.blockSignals.call_args_list @patch('openlp.core.ui.media.vlcplayer.translate') def test_get_info(self, mocked_translate): @@ -1007,6 +1004,6 @@ class TestVLCPlayer(TestCase, TestMixin): info = vlc_player.get_info() # THEN: The information should be correct - self.assertEqual('VLC is an external player which supports a number of different formats.
' - 'Audio
' + str(AUDIO_EXT) + '
Video
' + - str(VIDEO_EXT) + '
', info) + assert 'VLC is an external player which supports a number of different formats.
' \ + 'Audio
' + str(AUDIO_EXT) + '
Video
' + \ + str(VIDEO_EXT) + '
' == info diff --git a/tests/functional/openlp_core/ui/media/test_webkitplayer.py b/tests/functional/openlp_core/ui/media/test_webkitplayer.py index cba946338..ecdda4353 100644 --- a/tests/functional/openlp_core/ui/media/test_webkitplayer.py +++ b/tests/functional/openlp_core/ui/media/test_webkitplayer.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -47,8 +47,7 @@ class TestWebkitPlayer(TestCase): available = webkit_player.check_available() # THEN: The player should not be available when '[object HTMLUnknownElement]' is returned - self.assertEqual(False, available, - 'The WebkitPlayer should not be available when video feature detection fails') + assert available is False, 'The WebkitPlayer should not be available when video feature detection fails' def test_check_available_video_enabled(self): """ @@ -64,5 +63,4 @@ class TestWebkitPlayer(TestCase): available = webkit_player.check_available() # THEN: The player should be available when '[object HTMLVideoElement]' is returned - self.assertEqual(True, available, - 'The WebkitPlayer should be available when video feature detection passes') + assert available is True, 'The WebkitPlayer should be available when video feature detection passes' diff --git a/tests/functional/openlp_core/ui/test_aboutform.py b/tests/functional/openlp_core/ui/test_aboutform.py index 0cba7b008..049fb68c4 100644 --- a/tests/functional/openlp_core/ui/test_aboutform.py +++ b/tests/functional/openlp_core/ui/test_aboutform.py @@ -27,7 +27,6 @@ from unittest import TestCase from unittest.mock import patch from openlp.core.ui.aboutform import AboutForm - from tests.helpers.testmixin import TestMixin @@ -59,8 +58,8 @@ class TestFirstTimeForm(TestCase, TestMixin): about_form = AboutForm(None) # THEN: The build number should be in the text - self.assertTrue('OpenLP 3.1.5 build 3000' in about_form.about_text_edit.toPlainText(), - "The build number should be set correctly") + assert 'OpenLP 3.1.5 build 3000' in about_form.about_text_edit.toPlainText(), \ + "The build number should be set correctly" def test_about_form_date(self): """ @@ -74,5 +73,4 @@ class TestFirstTimeForm(TestCase, TestMixin): license_text = about_form.license_text_edit.toPlainText() # THEN: The date should be in the text twice. - self.assertTrue(license_text.count(date_string, 0) == 2, - "The text string should be added twice to the license string") + assert license_text.count(date_string, 0) == 2, "The text string should be added twice to the license string" diff --git a/tests/functional/openlp_core/ui/test_advancedtab.py b/tests/functional/openlp_core/ui/test_advancedtab.py index ca7bb8ca5..3f4069dc2 100644 --- a/tests/functional/openlp_core/ui/test_advancedtab.py +++ b/tests/functional/openlp_core/ui/test_advancedtab.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -27,7 +27,6 @@ from unittest import TestCase from openlp.core.common.registry import Registry from openlp.core.ui.advancedtab import AdvancedTab from openlp.core.ui.settingsform import SettingsForm - from tests.helpers.testmixin import TestMixin @@ -50,7 +49,7 @@ class TestAdvancedTab(TestCase, TestMixin): advanced_tab = AdvancedTab(settings_form) # THEN: - self.assertEqual("Advanced", advanced_tab.tab_title, 'The tab title should be Advanced') + assert "Advanced" == advanced_tab.tab_title, 'The tab title should be Advanced' def test_change_search_as_type(self): """ @@ -64,6 +63,6 @@ class TestAdvancedTab(TestCase, TestMixin): advanced_tab.on_search_as_type_check_box_changed(True) # THEN: we should have two post save processed to run - self.assertEqual(2, len(settings_form.processes), 'Two post save processes should be created') - self.assertTrue("songs_config_updated" in settings_form.processes, 'The songs plugin should be called') - self.assertTrue("custom_config_updated" in settings_form.processes, 'The custom plugin should be called') + assert 2 == len(settings_form.processes), 'Two post save processes should be created' + assert "songs_config_updated" in settings_form.processes, 'The songs plugin should be called' + assert "custom_config_updated" in settings_form.processes, 'The custom plugin should be called' diff --git a/tests/functional/openlp_core/ui/test_exceptionform.py b/tests/functional/openlp_core/ui/test_exceptionform.py index 3bc99d63f..207805f37 100644 --- a/tests/functional/openlp_core/ui/test_exceptionform.py +++ b/tests/functional/openlp_core/ui/test_exceptionform.py @@ -24,14 +24,12 @@ Package to test the openlp.core.ui.exeptionform package. """ import os import tempfile - from unittest import TestCase from unittest.mock import call, patch -from openlp.core.common.registry import Registry from openlp.core.common.path import Path +from openlp.core.common.registry import Registry from openlp.core.ui import exceptionform - from tests.helpers.testmixin import TestMixin exceptionform.WEBKIT_VERSION = 'Webkit Test' diff --git a/tests/functional/openlp_core/ui/test_first_time.py b/tests/functional/openlp_core/ui/test_first_time.py index 2be5e1ad6..b6404d2b1 100644 --- a/tests/functional/openlp_core/ui/test_first_time.py +++ b/tests/functional/openlp_core/ui/test_first_time.py @@ -26,7 +26,6 @@ from unittest import TestCase from unittest.mock import patch from openlp.core.common.httputils import CONNECTION_RETRIES, get_web_page - from tests.helpers.testmixin import TestMixin diff --git a/tests/functional/openlp_core/ui/test_firsttimeform.py b/tests/functional/openlp_core/ui/test_firsttimeform.py index 543d4334c..cd507452e 100644 --- a/tests/functional/openlp_core/ui/test_firsttimeform.py +++ b/tests/functional/openlp_core/ui/test_firsttimeform.py @@ -24,14 +24,12 @@ Package to test the openlp.core.ui.firsttimeform package. """ import os import tempfile -import urllib from unittest import TestCase from unittest.mock import MagicMock, patch -from openlp.core.common.registry import Registry from openlp.core.common.path import Path +from openlp.core.common.registry import Registry from openlp.core.ui.firsttimeform import FirstTimeForm - from tests.helpers.testmixin import TestMixin FAKE_CONFIG = """ @@ -90,12 +88,11 @@ class TestFirstTimeForm(TestCase, TestMixin): frw.initialize(expected_screens) # THEN: The screens should be set up, and the default values initialised - self.assertEqual(expected_screens, frw.screens, 'The screens should be correct') - self.assertTrue(frw.web_access, 'The default value of self.web_access should be True') - self.assertFalse(frw.was_cancelled, 'The default value of self.was_cancelled should be False') - self.assertListEqual([], frw.theme_screenshot_threads, 'The list of threads should be empty') - self.assertListEqual([], frw.theme_screenshot_workers, 'The list of workers should be empty') - self.assertFalse(frw.has_run_wizard, 'has_run_wizard should be False') + assert expected_screens == frw.screens, 'The screens should be correct' + assert frw.web_access is True, 'The default value of self.web_access should be True' + assert frw.was_cancelled is False, 'The default value of self.was_cancelled should be False' + assert [] == frw.theme_screenshot_threads, 'The list of threads should be empty' + assert frw.has_run_wizard is False, 'has_run_wizard should be False' def test_set_defaults(self): """ @@ -124,7 +121,7 @@ class TestFirstTimeForm(TestCase, TestMixin): # THEN: The default values should have been set mocked_restart.assert_called_with() - self.assertEqual('http://openlp.org/files/frw/', frw.web, 'The default URL should be set') + assert 'http://openlp.org/files/frw/' == frw.web, 'The default URL should be set' mocked_cancel_button.clicked.connect.assert_called_with(frw.on_cancel_button_clicked) mocked_no_internet_finish_btn.clicked.connect.assert_called_with(frw.on_no_internet_finish_button_clicked) mocked_currentIdChanged.connect.assert_called_with(frw.on_current_id_changed) @@ -157,32 +154,33 @@ class TestFirstTimeForm(TestCase, TestMixin): mocked_display_combo_box.count.assert_called_with() mocked_display_combo_box.setCurrentIndex.assert_called_with(1) - def test_on_cancel_button_clicked(self): + @patch('openlp.core.ui.firsttimeform.time') + @patch('openlp.core.ui.firsttimeform.get_thread_worker') + @patch('openlp.core.ui.firsttimeform.is_thread_finished') + def test_on_cancel_button_clicked(self, mocked_is_thread_finished, mocked_get_thread_worker, mocked_time): """ Test that the cancel button click slot shuts down the threads correctly """ # GIVEN: A FRW, some mocked threads and workers (that isn't quite done) and other mocked stuff + mocked_worker = MagicMock() + mocked_get_thread_worker.return_value = mocked_worker + mocked_is_thread_finished.side_effect = [False, True] frw = FirstTimeForm(None) frw.initialize(MagicMock()) - mocked_worker = MagicMock() - mocked_thread = MagicMock() - mocked_thread.isRunning.side_effect = [True, False] - frw.theme_screenshot_workers.append(mocked_worker) - frw.theme_screenshot_threads.append(mocked_thread) - with patch('openlp.core.ui.firsttimeform.time') as mocked_time, \ - patch.object(frw.application, 'set_normal_cursor') as mocked_set_normal_cursor: + frw.theme_screenshot_threads = ['test_thread'] + with patch.object(frw.application, 'set_normal_cursor') as mocked_set_normal_cursor: # WHEN: on_cancel_button_clicked() is called frw.on_cancel_button_clicked() # THEN: The right things should be called in the right order - self.assertTrue(frw.was_cancelled, 'The was_cancelled property should have been set to True') + assert frw.was_cancelled is True, 'The was_cancelled property should have been set to True' + mocked_get_thread_worker.assert_called_once_with('test_thread') mocked_worker.set_download_canceled.assert_called_with(True) - mocked_thread.isRunning.assert_called_with() - self.assertEqual(2, mocked_thread.isRunning.call_count, 'isRunning() should have been called twice') - mocked_time.sleep.assert_called_with(0.1) - self.assertEqual(1, mocked_time.sleep.call_count, 'sleep() should have only been called once') - mocked_set_normal_cursor.assert_called_with() + mocked_is_thread_finished.assert_called_with('test_thread') + assert mocked_is_thread_finished.call_count == 2, 'isRunning() should have been called twice' + mocked_time.sleep.assert_called_once_with(0.1) + mocked_set_normal_cursor.assert_called_once_with() def test_broken_config(self): """ @@ -198,7 +196,7 @@ class TestFirstTimeForm(TestCase, TestMixin): first_time_form._download_index() # THEN: The First Time Form should not have web access - self.assertFalse(first_time_form.web_access, 'There should not be web access with a broken config file') + assert first_time_form.web_access is False, 'There should not be web access with a broken config file' def test_invalid_config(self): """ @@ -214,7 +212,7 @@ class TestFirstTimeForm(TestCase, TestMixin): first_time_form._download_index() # THEN: The First Time Form should not have web access - self.assertFalse(first_time_form.web_access, 'There should not be web access with an invalid config file') + assert first_time_form.web_access is False, 'There should not be web access with an invalid config file' @patch('openlp.core.ui.firsttimeform.get_web_page') @patch('openlp.core.ui.firsttimeform.QtWidgets.QMessageBox') diff --git a/tests/functional/openlp_core/ui/test_formattingtagscontroller.py b/tests/functional/openlp_core/ui/test_formattingtagscontroller.py index dfd05bcf0..f4fb9f571 100644 --- a/tests/functional/openlp_core/ui/test_formattingtagscontroller.py +++ b/tests/functional/openlp_core/ui/test_formattingtagscontroller.py @@ -43,7 +43,7 @@ class TestFormattingTagController(TestCase): result = self.services._strip(tag) # THEN: The tag should be returned with the wrappers removed. - self.assertEqual(result, 'tag', 'FormattingTagForm._strip should return u\'tag\' when called with u\'{tag}\'') + assert result == 'tag', 'FormattingTagForm._strip should return u\'tag\' when called with u\'{tag}\'' def test_end_tag_changed_processes_correctly(self): """ @@ -64,11 +64,9 @@ class TestFormattingTagController(TestCase): error, result = self.services.end_tag_changed(test['start'], test['end']) # THEN: The result should match the predetermined value. - self.assertTrue(result == test['gen'], - 'Function should handle end tag correctly : %s and %s for %s ' % - (test['gen'], result, test['start'])) - self.assertTrue(error == test['valid'], 'Function should not generate unexpected error messages : %s ' % - error) + assert result == test['gen'], \ + 'Function should handle end tag correctly : %s and %s for %s ' % (test['gen'], result, test['start']) + assert error == test['valid'], 'Function should not generate unexpected error messages : %s ' % error def test_start_tag_changed_processes_correctly(self): """ @@ -88,10 +86,9 @@ class TestFormattingTagController(TestCase): error, result = self.services.start_tag_changed(test['start'], test['end']) # THEN: The result should match the predetermined value. - self.assertTrue(result == test['gen'], 'Function should handle end tag correctly : %s and %s ' % - (test['gen'], result)) - self.assertTrue(error == test['valid'], 'Function should not generate unexpected error messages : %s ' % - error) + assert result == test['gen'], \ + 'Function should handle end tag correctly : %s and %s ' % (test['gen'], result) + assert error == test['valid'], 'Function should not generate unexpected error messages : %s ' % error def test_start_html_to_end_html(self): """ @@ -106,5 +103,4 @@ class TestFormattingTagController(TestCase): result = self.services.start_html_to_end_html(test1) # THEN: The result should match the predetermined value. - self.assertTrue(result == test2, 'Calculated end tag should be valid: %s and %s = %s' % - (test1, test2, result)) + assert result == test2, 'Calculated end tag should be valid: %s and %s = %s' % (test1, test2, result) diff --git a/tests/functional/openlp_core/ui/test_formattingtagsform.py b/tests/functional/openlp_core/ui/test_formattingtagsform.py index c4069a553..e45f94855 100644 --- a/tests/functional/openlp_core/ui/test_formattingtagsform.py +++ b/tests/functional/openlp_core/ui/test_formattingtagsform.py @@ -83,8 +83,8 @@ class TestFormattingTagForm(TestCase): call(row_count, 2, mocked_table_widget), call(row_count, 3, mocked_table_widget) ] - self.assertEqual(expected_set_item_calls, form.tag_table_widget.setItem.call_args_list, - 'setItem should have been called correctly') + assert expected_set_item_calls == form.tag_table_widget.setItem.call_args_list, \ + 'setItem should have been called correctly' form.tag_table_widget.resizeRowsToContents.assert_called_with() form.tag_table_widget.scrollToBottom.assert_called_with() form.tag_table_widget.selectRow.assert_called_with(row_count) diff --git a/tests/functional/openlp_core/ui/test_maindisplay.py b/tests/functional/openlp_core/ui/test_maindisplay.py index 1516418f4..cbfefa6a2 100644 --- a/tests/functional/openlp_core/ui/test_maindisplay.py +++ b/tests/functional/openlp_core/ui/test_maindisplay.py @@ -34,7 +34,6 @@ from openlp.core.display.screens import ScreenList from openlp.core.lib import PluginManager from openlp.core.ui import MainDisplay, AudioPlayer from openlp.core.ui.maindisplay import TRANSPARENT_STYLESHEET, OPAQUE_STYLESHEET - from tests.helpers.testmixin import TestMixin if is_macosx(): @@ -83,7 +82,7 @@ class TestMainDisplay(TestCase, TestMixin): main_display = MainDisplay(display) # THEN: The controller should be a live controller. - self.assertEqual(main_display.is_live, True, 'The main display should be a live controller') + assert main_display.is_live is True, 'The main display should be a live controller' def test_set_transparency_enabled(self): """ @@ -97,12 +96,12 @@ class TestMainDisplay(TestCase, TestMixin): main_display.set_transparency(True) # THEN: The transparent stylesheet should be used - self.assertEqual(TRANSPARENT_STYLESHEET, main_display.styleSheet(), - 'The MainDisplay should use the transparent stylesheet') - self.assertFalse(main_display.autoFillBackground(), - 'The MainDisplay should not have autoFillBackground set') - self.assertTrue(main_display.testAttribute(QtCore.Qt.WA_TranslucentBackground), - 'The MainDisplay should have a translucent background') + assert TRANSPARENT_STYLESHEET == main_display.styleSheet(), \ + 'The MainDisplay should use the transparent stylesheet' + assert main_display.autoFillBackground() is False, \ + 'The MainDisplay should not have autoFillBackground set' + assert main_display.testAttribute(QtCore.Qt.WA_TranslucentBackground) is True, \ + 'The MainDisplay should have a translucent background' def test_set_transparency_disabled(self): """ @@ -116,10 +115,10 @@ class TestMainDisplay(TestCase, TestMixin): main_display.set_transparency(False) # THEN: The opaque stylesheet should be used - self.assertEqual(OPAQUE_STYLESHEET, main_display.styleSheet(), - 'The MainDisplay should use the opaque stylesheet') - self.assertFalse(main_display.testAttribute(QtCore.Qt.WA_TranslucentBackground), - 'The MainDisplay should not have a translucent background') + assert OPAQUE_STYLESHEET == main_display.styleSheet(), \ + 'The MainDisplay should use the opaque stylesheet' + assert main_display.testAttribute(QtCore.Qt.WA_TranslucentBackground) is False, \ + 'The MainDisplay should not have a translucent background' def test_css_changed(self): """ @@ -156,9 +155,9 @@ class TestMainDisplay(TestCase, TestMixin): main_display = MainDisplay(display) # THEN: The window flags should be the same as those needed on Mac OS X. - self.assertEqual(QtCore.Qt.Window | QtCore.Qt.FramelessWindowHint | QtCore.Qt.NoDropShadowWindowHint, - main_display.windowFlags(), - 'The window flags should be Qt.Window, Qt.FramelessWindowHint, and Qt.NoDropShadowWindowHint.') + assert QtCore.Qt.Window | QtCore.Qt.FramelessWindowHint | QtCore.Qt.NoDropShadowWindowHint == \ + main_display.windowFlags(), \ + 'The window flags should be Qt.Window, Qt.FramelessWindowHint, and Qt.NoDropShadowWindowHint.' @skipUnless(is_macosx(), 'Can only run test on Mac OS X due to pyobjc dependency.') def test_macosx_display(self): @@ -181,10 +180,10 @@ class TestMainDisplay(TestCase, TestMixin): pyobjc_nsview = objc_object(cobject=nsview_pointer) # THEN: The window level and collection behavior should be the same as those needed for Mac OS X. - self.assertEqual(pyobjc_nsview.window().level(), NSMainMenuWindowLevel + 2, - 'Window level should be NSMainMenuWindowLevel + 2') - self.assertEqual(pyobjc_nsview.window().collectionBehavior(), NSWindowCollectionBehaviorManaged, - 'Window collection behavior should be NSWindowCollectionBehaviorManaged') + assert pyobjc_nsview.window().level() == NSMainMenuWindowLevel + 2, \ + 'Window level should be NSMainMenuWindowLevel + 2' + assert pyobjc_nsview.window().collectionBehavior() == NSWindowCollectionBehaviorManaged, \ + 'Window collection behavior should be NSWindowCollectionBehaviorManaged' @patch('openlp.core.ui.maindisplay.Settings') def test_show_display_startup_logo(self, MockedSettings): @@ -250,9 +249,9 @@ class TestMainDisplay(TestCase, TestMixin): main_display.build_html(service_item) # THEN: the following should had not been called - self.assertEquals(main_display.web_view.setHtml.call_count, 1, 'setHTML should be called once') - self.assertEquals(main_display.media_controller.video.call_count, 0, - 'Media Controller video should not have been called') + assert main_display.web_view.setHtml.call_count == 1, 'setHTML should be called once' + assert main_display.media_controller.video.call_count == 0, \ + 'Media Controller video should not have been called' @patch('openlp.core.ui.maindisplay.Settings') @patch('openlp.core.ui.maindisplay.build_html') @@ -282,9 +281,9 @@ class TestMainDisplay(TestCase, TestMixin): main_display.build_html(service_item) # THEN: the following should had not been called - self.assertEquals(main_display.web_view.setHtml.call_count, 1, 'setHTML should be called once') - self.assertEquals(main_display.media_controller.video.call_count, 1, - 'Media Controller video should have been called once') + assert main_display.web_view.setHtml.call_count == 1, 'setHTML should be called once' + assert main_display.media_controller.video.call_count == 1, \ + 'Media Controller video should have been called once' def test_calling_next_item_in_playlist(): diff --git a/tests/functional/openlp_core/ui/test_mainwindow.py b/tests/functional/openlp_core/ui/test_mainwindow.py index 9dee80c0d..fb00b3522 100644 --- a/tests/functional/openlp_core/ui/test_mainwindow.py +++ b/tests/functional/openlp_core/ui/test_mainwindow.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -32,7 +32,6 @@ from openlp.core.common.i18n import UiStrings from openlp.core.common.registry import Registry from openlp.core.display.screens import ScreenList from openlp.core.ui.mainwindow import MainWindow - from tests.helpers.testmixin import TestMixin from tests.utils.constants import TEST_RESOURCES_PATH @@ -61,9 +60,10 @@ class TestMainWindow(TestCase, TestMixin): # Mock cursor busy/normal methods. self.app.set_busy_cursor = MagicMock() self.app.set_normal_cursor = MagicMock() + self.app.process_events = MagicMock() self.app.args = [] Registry().register('application', self.app) - Registry().set_flag('no_web_server', False) + Registry().set_flag('no_web_server', True) self.add_toolbar_action_patcher = patch('openlp.core.ui.mainwindow.create_action') self.mocked_add_toolbar_action = self.add_toolbar_action_patcher.start() self.mocked_add_toolbar_action.side_effect = self._create_mock_action @@ -75,8 +75,8 @@ class TestMainWindow(TestCase, TestMixin): """ Delete all the C++ objects and stop all the patchers """ - self.add_toolbar_action_patcher.stop() del self.main_window + self.add_toolbar_action_patcher.stop() def test_cmd_line_file(self): """ @@ -93,20 +93,20 @@ class TestMainWindow(TestCase, TestMixin): # THEN the service from the arguments is loaded mocked_load_file.assert_called_with(service) - def test_cmd_line_arg(self): + @patch('openlp.core.ui.servicemanager.ServiceManager.load_file') + def test_cmd_line_arg(self, mocked_load_file): """ Test that passing a non service file does nothing. """ # GIVEN a non service file as an argument to openlp service = os.path.join('openlp.py') self.main_window.arguments = [service] - with patch('openlp.core.ui.servicemanager.ServiceManager.load_file') as mocked_load_file: - # WHEN the argument is processed - self.main_window.open_cmd_line_files("") + # WHEN the argument is processed + self.main_window.open_cmd_line_files(service) - # THEN the file should not be opened - assert mocked_load_file.called is False, 'load_file should not have been called' + # THEN the file should not be opened + assert mocked_load_file.called is False, 'load_file should not have been called' def test_main_window_title(self): """ @@ -117,8 +117,8 @@ class TestMainWindow(TestCase, TestMixin): # WHEN no changes are made to the service # THEN the main window's title shoud be the same as the OpenLP string in the UiStrings class - self.assertEqual(self.main_window.windowTitle(), UiStrings().OpenLP, - 'The main window\'s title should be the same as the OpenLP string in UiStrings class') + assert self.main_window.windowTitle() == UiStrings().OpenLP, \ + 'The main window\'s title should be the same as the OpenLP string in UiStrings class' def test_set_service_modifed(self): """ @@ -130,8 +130,8 @@ class TestMainWindow(TestCase, TestMixin): self.main_window.set_service_modified(True, 'test.osz') # THEN the main window's title should be set to the - self.assertEqual(self.main_window.windowTitle(), '%s - %s*' % (UiStrings().OpenLP, 'test.osz'), - 'The main window\'s title should be set to " - test.osz*"') + assert self.main_window.windowTitle(), '%s - %s*' % (UiStrings().OpenLP, 'test.osz') == \ + 'The main window\'s title should be set to " - test.osz*"' def test_set_service_unmodified(self): """ @@ -143,8 +143,8 @@ class TestMainWindow(TestCase, TestMixin): self.main_window.set_service_modified(False, 'test.osz') # THEN the main window's title should be set to the - self.assertEqual(self.main_window.windowTitle(), '%s - %s' % (UiStrings().OpenLP, 'test.osz'), - 'The main window\'s title should be set to " - test.osz"') + assert self.main_window.windowTitle(), '%s - %s' % (UiStrings().OpenLP, 'test.osz') == \ + 'The main window\'s title should be set to " - test.osz"' def test_mainwindow_configuration(self): """ @@ -204,7 +204,7 @@ class TestMainWindow(TestCase, TestMixin): self.main_window.on_search_shortcut_triggered() # THEN: The media manager dock is made visible - self.assertEqual(0, mocked_media_manager_dock.setVisible.call_count) + assert 0 == mocked_media_manager_dock.setVisible.call_count mocked_widget.on_focus.assert_called_with() @patch('openlp.core.ui.mainwindow.FirstTimeForm') diff --git a/tests/functional/openlp_core/ui/test_media.py b/tests/functional/openlp_core/ui/test_media.py index a3c2217fb..eef1907e3 100644 --- a/tests/functional/openlp_core/ui/test_media.py +++ b/tests/functional/openlp_core/ui/test_media.py @@ -28,7 +28,6 @@ from unittest.mock import patch from PyQt5 import QtCore from openlp.core.ui.media import get_media_players, parse_optical_path - from tests.helpers.testmixin import TestMixin @@ -52,8 +51,8 @@ class TestMedia(TestCase, TestMixin): used_players, overridden_player = get_media_players() # THEN: the used_players should be an empty list, and the overridden player should be an empty string - self.assertEqual([], used_players, 'Used players should be an empty list') - self.assertEqual('', overridden_player, 'Overridden player should be an empty string') + assert [] == used_players, 'Used players should be an empty list' + assert '' == overridden_player, 'Overridden player should be an empty string' def test_get_media_players_no_players(self): """ @@ -73,8 +72,8 @@ class TestMedia(TestCase, TestMixin): used_players, overridden_player = get_media_players() # THEN: the used_players should be an empty list, and the overridden player should be an empty string - self.assertEqual([], used_players, 'Used players should be an empty list') - self.assertEqual('auto', overridden_player, 'Overridden player should be "auto"') + assert [] == used_players, 'Used players should be an empty list' + assert 'auto' == overridden_player, 'Overridden player should be "auto"' def test_get_media_players_with_valid_list(self): """ @@ -94,8 +93,8 @@ class TestMedia(TestCase, TestMixin): used_players, overridden_player = get_media_players() # THEN: the used_players should be an empty list, and the overridden player should be an empty string - self.assertEqual(['vlc', 'webkit', 'system'], used_players, 'Used players should be correct') - self.assertEqual('', overridden_player, 'Overridden player should be an empty string') + assert ['vlc', 'webkit', 'system'] == used_players, 'Used players should be correct' + assert '' == overridden_player, 'Overridden player should be an empty string' def test_get_media_players_with_overridden_player(self): """ @@ -115,8 +114,8 @@ class TestMedia(TestCase, TestMixin): used_players, overridden_player = get_media_players() # THEN: the used_players should be an empty list, and the overridden player should be an empty string - self.assertEqual(['vlc', 'webkit', 'system'], used_players, 'Used players should be correct') - self.assertEqual('vlc,webkit,system', overridden_player, 'Overridden player should be a string of players') + assert ['vlc', 'webkit', 'system'] == used_players, 'Used players should be correct' + assert 'vlc,webkit,system' == overridden_player, 'Overridden player should be a string of players' def test_parse_optical_path_linux(self): """ @@ -138,13 +137,13 @@ class TestMedia(TestCase, TestMixin): (device_path, title_track, audio_track, subtitle_track, start, end, name) = parse_optical_path(path) # THEN: The return values should match the original values - self.assertEqual(org_title_track, title_track, 'Returned title_track should match the original') - self.assertEqual(org_audio_track, audio_track, 'Returned audio_track should match the original') - self.assertEqual(org_subtitle_track, subtitle_track, 'Returned subtitle_track should match the original') - self.assertEqual(org_start, start, 'Returned start should match the original') - self.assertEqual(org_end, end, 'Returned end should match the original') - self.assertEqual(org_name, name, 'Returned end should match the original') - self.assertEqual(org_device_path, device_path, 'Returned device_path should match the original') + assert org_title_track == title_track, 'Returned title_track should match the original' + assert org_audio_track == audio_track, 'Returned audio_track should match the original' + assert org_subtitle_track == subtitle_track, 'Returned subtitle_track should match the original' + assert org_start == start, 'Returned start should match the original' + assert org_end == end, 'Returned end should match the original' + assert org_name == name, 'Returned end should match the original' + assert org_device_path == device_path, 'Returned device_path should match the original' def test_parse_optical_path_win(self): """ @@ -166,10 +165,10 @@ class TestMedia(TestCase, TestMixin): (device_path, title_track, audio_track, subtitle_track, start, end, name) = parse_optical_path(path) # THEN: The return values should match the original values - self.assertEqual(org_title_track, title_track, 'Returned title_track should match the original') - self.assertEqual(org_audio_track, audio_track, 'Returned audio_track should match the original') - self.assertEqual(org_subtitle_track, subtitle_track, 'Returned subtitle_track should match the original') - self.assertEqual(org_start, start, 'Returned start should match the original') - self.assertEqual(org_end, end, 'Returned end should match the original') - self.assertEqual(org_name, name, 'Returned end should match the original') - self.assertEqual(org_device_path, device_path, 'Returned device_path should match the original') + assert org_title_track == title_track, 'Returned title_track should match the original' + assert org_audio_track == audio_track, 'Returned audio_track should match the original' + assert org_subtitle_track == subtitle_track, 'Returned subtitle_track should match the original' + assert org_start == start, 'Returned start should match the original' + assert org_end == end, 'Returned end should match the original' + assert org_name == name, 'Returned end should match the original' + assert org_device_path == device_path, 'Returned device_path should match the original' diff --git a/tests/functional/openlp_core/ui/test_servicemanager.py b/tests/functional/openlp_core/ui/test_servicemanager.py index 3c0958506..191bd236e 100644 --- a/tests/functional/openlp_core/ui/test_servicemanager.py +++ b/tests/functional/openlp_core/ui/test_servicemanager.py @@ -54,7 +54,7 @@ class TestServiceManager(TestCase): ServiceManager(None) # WHEN: the default service manager is built. # THEN: The the controller should be registered in the registry. - self.assertNotEqual(Registry().get('service_manager'), None, 'The base service manager should be registered') + assert Registry().get('service_manager') is not None, 'The base service manager should be registered' def test_create_basic_service(self): """ @@ -67,9 +67,9 @@ class TestServiceManager(TestCase): service_manager.service_theme = 'test_theme' service = service_manager.create_basic_service()[0] # THEN: The controller should be registered in the registry. - self.assertNotEqual(service, None, 'The base service should be created') - self.assertEqual(service['openlp_core']['service-theme'], 'test_theme', 'The test theme should be saved') - self.assertEqual(service['openlp_core']['lite-service'], False, 'The lite service should be saved') + assert service is not None, 'The base service should be created' + assert service['openlp_core']['service-theme'] == 'test_theme', 'The test theme should be saved' + assert service['openlp_core']['lite-service'] is False, 'The lite service should be saved' def test_supported_suffixes(self): """ @@ -81,9 +81,9 @@ class TestServiceManager(TestCase): service_manager.supported_suffixes('txt') service_manager.supported_suffixes(['pptx', 'ppt']) # THEN: The suffixes should be available to test. - self.assertEqual('txt' in service_manager.suffixes, True, 'The suffix txt should be in the list') - self.assertEqual('ppt' in service_manager.suffixes, True, 'The suffix ppt should be in the list') - self.assertEqual('pptx' in service_manager.suffixes, True, 'The suffix pptx should be in the list') + assert 'txt' in service_manager.suffixes, 'The suffix txt should be in the list' + assert 'ppt' in service_manager.suffixes, 'The suffix ppt should be in the list' + assert 'pptx' in service_manager.suffixes, 'The suffix pptx should be in the list' def test_build_context_menu(self): """ @@ -114,20 +114,20 @@ class TestServiceManager(TestCase): # WHEN I define a context menu service_manager.context_menu(1) # THEN the following calls should have occurred. - self.assertEqual(service_manager.edit_action.setVisible.call_count, 1, 'Should have been called once') - self.assertEqual(service_manager.rename_action.setVisible.call_count, 1, 'Should have been called once') - self.assertEqual(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have been called once') - self.assertEqual(service_manager.maintain_action.setVisible.call_count, 1, 'Should have been called once') - self.assertEqual(service_manager.notes_action.setVisible.call_count, 1, 'Should have been called once') - self.assertEqual(service_manager.time_action.setVisible.call_count, 1, 'Should have been called once') - self.assertEqual(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have been called once') - self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1, - 'Should have been called once') - self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.theme_menu.menuAction().setVisible.call_count, 1, - 'Should have been called once') + assert service_manager.edit_action.setVisible.call_count == 1, 'Should have been called once' + assert service_manager.rename_action.setVisible.call_count == 1, 'Should have been called once' + assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have been called once' + assert service_manager.maintain_action.setVisible.call_count == 1, 'Should have been called once' + assert service_manager.notes_action.setVisible.call_count == 1, 'Should have been called once' + assert service_manager.time_action.setVisible.call_count == 1, 'Should have been called once' + assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have been called once' + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ + 'Should have been called once' + assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' + assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' + assert service_manager.theme_menu.menuAction().setVisible.call_count == 1, \ + 'Should have been called once' def test_build_song_context_menu(self): """ @@ -169,29 +169,29 @@ class TestServiceManager(TestCase): # WHEN I define a context menu service_manager.context_menu(1) # THEN the following calls should have occurred. - self.assertEqual(service_manager.edit_action.setVisible.call_count, 2, 'Should have be called twice') - self.assertEqual(service_manager.rename_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1, - 'Should have be called once') - self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.theme_menu.menuAction().setVisible.call_count, 2, - 'Should have be called twice') + assert service_manager.edit_action.setVisible.call_count == 2, 'Should have be called twice' + assert service_manager.rename_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.maintain_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ + 'Should have be called once' + assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' + assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' + assert service_manager.theme_menu.menuAction().setVisible.call_count == 2, \ + 'Should have be called twice' # THEN we add a 2nd display frame service_item._display_frames.append(MagicMock()) service_manager.context_menu(1) # THEN the following additional calls should have occurred. - self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 2, - 'Should have be called twice') - self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 1, 'Should have be called once') + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 2, \ + 'Should have be called twice' + assert service_manager.auto_play_slides_once.setChecked.call_count == 1, 'Should have be called once' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 1, 'Should have be called once' + assert service_manager.timed_slide_interval.setChecked.call_count == 1, 'Should have be called once' def test_build_bible_context_menu(self): """ @@ -233,29 +233,29 @@ class TestServiceManager(TestCase): # WHEN I define a context menu service_manager.context_menu(1) # THEN the following calls should have occurred. - self.assertEqual(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.rename_action.setVisible.call_count, 2, 'Should have be called twice') - self.assertEqual(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1, - 'Should have be called once') - self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.theme_menu.menuAction().setVisible.call_count, 2, - 'Should have be called twice') + assert service_manager.edit_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.rename_action.setVisible.call_count == 2, 'Should have be called twice' + assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.maintain_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ + 'Should have be called once' + assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' + assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' + assert service_manager.theme_menu.menuAction().setVisible.call_count == 2, \ + 'Should have be called twice' # THEN we add a 2nd display frame service_item._display_frames.append(MagicMock()) service_manager.context_menu(1) # THEN the following additional calls should have occurred. - self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 2, - 'Should have be called twice') - self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 1, 'Should have be called once') + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 2, \ + 'Should have be called twice' + assert service_manager.auto_play_slides_once.setChecked.call_count == 1, 'Should have be called once' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 1, 'Should have be called once' + assert service_manager.timed_slide_interval.setChecked.call_count == 1, 'Should have be called once' def test_build_custom_context_menu(self): """ @@ -298,29 +298,29 @@ class TestServiceManager(TestCase): # WHEN I define a context menu service_manager.context_menu(1) # THEN the following calls should have occurred. - self.assertEqual(service_manager.edit_action.setVisible.call_count, 2, 'Should have be called twice') - self.assertEqual(service_manager.rename_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1, - 'Should have be called once') - self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.theme_menu.menuAction().setVisible.call_count, 2, - 'Should have be called twice') + assert service_manager.edit_action.setVisible.call_count == 2, 'Should have be called twice' + assert service_manager.rename_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.maintain_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ + 'Should have be called once' + assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' + assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' + assert service_manager.theme_menu.menuAction().setVisible.call_count == 2, \ + 'Should have be called twice' # THEN we add a 2nd display frame service_item._display_frames.append(MagicMock()) service_manager.context_menu(1) # THEN the following additional calls should have occurred. - self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 2, - 'Should have be called twice') - self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 1, 'Should have be called once') + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 2, \ + 'Should have be called twice' + assert service_manager.auto_play_slides_once.setChecked.call_count == 1, 'Should have be called once' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 1, 'Should have be called once' + assert service_manager.timed_slide_interval.setChecked.call_count == 1, 'Should have be called once' def test_build_image_context_menu(self): """ @@ -361,29 +361,29 @@ class TestServiceManager(TestCase): # WHEN I define a context menu service_manager.context_menu(1) # THEN the following calls should have occurred. - self.assertEqual(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.rename_action.setVisible.call_count, 2, 'Should have be called twice') - self.assertEqual(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.maintain_action.setVisible.call_count, 2, 'Should have be called twice') - self.assertEqual(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1, - 'Should have be called once') - self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.theme_menu.menuAction().setVisible.call_count, 1, - 'Should have be called once') + assert service_manager.edit_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.rename_action.setVisible.call_count == 2, 'Should have be called twice' + assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.maintain_action.setVisible.call_count == 2, 'Should have be called twice' + assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ + 'Should have be called once' + assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' + assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' + assert service_manager.theme_menu.menuAction().setVisible.call_count == 1, \ + 'Should have be called once' # THEN we add a 2nd display frame and regenerate the menu. service_item._raw_frames.append(MagicMock()) service_manager.context_menu(1) # THEN the following additional calls should have occurred. - self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 2, - 'Should have be called twice') - self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 1, 'Should have be called once') + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 2, \ + 'Should have be called twice' + assert service_manager.auto_play_slides_once.setChecked.call_count == 1, 'Should have be called once' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 1, 'Should have be called once' + assert service_manager.timed_slide_interval.setChecked.call_count == 1, 'Should have be called once' def test_build_media_context_menu(self): """ @@ -422,25 +422,25 @@ class TestServiceManager(TestCase): # WHEN I define a context menu service_manager.context_menu(1) # THEN the following calls should have occurred. - self.assertEqual(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.rename_action.setVisible.call_count, 2, 'Should have be called twice') - self.assertEqual(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.auto_start_action.setVisible.call_count, 2, 'Should have be called twice') - self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1, - 'Should have be called once') - self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.theme_menu.menuAction().setVisible.call_count, 1, - 'Should have be called once') + assert service_manager.edit_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.rename_action.setVisible.call_count == 2, 'Should have be called twice' + assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.maintain_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_start_action.setVisible.call_count == 2, 'Should have be called twice' + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ + 'Should have be called once' + assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' + assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' + assert service_manager.theme_menu.menuAction().setVisible.call_count == 1, \ + 'Should have be called once' # THEN I change the length of the media and regenerate the menu. service_item.set_media_length(5) service_manager.context_menu(1) # THEN the following additional calls should have occurred. - self.assertEqual(service_manager.time_action.setVisible.call_count, 3, 'Should have be called three times') + assert service_manager.time_action.setVisible.call_count == 3, 'Should have be called three times' def test_build_presentation_pdf_context_menu(self): """ @@ -480,20 +480,20 @@ class TestServiceManager(TestCase): # WHEN I define a context menu service_manager.context_menu(1) # THEN the following calls should have occurred. - self.assertEqual(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.rename_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.maintain_action.setVisible.call_count, 2, 'Should have be called twice') - self.assertEqual(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1, - 'Should have be called once') - self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.theme_menu.menuAction().setVisible.call_count, 1, - 'Should have be called once') + assert service_manager.edit_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.rename_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.maintain_action.setVisible.call_count == 2, 'Should have be called twice' + assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ + 'Should have be called once' + assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' + assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' + assert service_manager.theme_menu.menuAction().setVisible.call_count == 1, \ + 'Should have be called once' def test_build_presentation_non_pdf_context_menu(self): """ @@ -530,20 +530,20 @@ class TestServiceManager(TestCase): # WHEN I define a context menu service_manager.context_menu(1) # THEN the following calls should have occurred. - self.assertEqual(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.rename_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once') - self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1, - 'Should have be called once') - self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called') - self.assertEqual(service_manager.theme_menu.menuAction().setVisible.call_count, 1, - 'Should have be called once') + assert service_manager.edit_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.rename_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.create_custom_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.maintain_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.notes_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.time_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_start_action.setVisible.call_count == 1, 'Should have be called once' + assert service_manager.auto_play_slides_menu.menuAction().setVisible.call_count == 1, \ + 'Should have be called once' + assert service_manager.auto_play_slides_once.setChecked.call_count == 0, 'Should not be called' + assert service_manager.auto_play_slides_loop.setChecked.call_count == 0, 'Should not be called' + assert service_manager.timed_slide_interval.setChecked.call_count == 0, 'Should not be called' + assert service_manager.theme_menu.menuAction().setVisible.call_count == 1, \ + 'Should have be called once' @patch('openlp.core.ui.servicemanager.Settings') @patch('PyQt5.QtCore.QTimer.singleShot') @@ -576,7 +576,7 @@ class TestServiceManager(TestCase): # WHEN: on_single_click_preview() is called service_manager.on_single_click_preview() # THEN: timer should not be started - self.assertEqual(mocked_singleShot.call_count, 0, 'Should not be called') + assert mocked_singleShot.call_count == 0, 'Should not be called' @patch('openlp.core.ui.servicemanager.Settings') @patch('PyQt5.QtCore.QTimer.singleShot') @@ -595,7 +595,7 @@ class TestServiceManager(TestCase): service_manager.on_single_click_preview() # THEN: timer should not be started mocked_make_live.assert_called_with() - self.assertEqual(mocked_singleShot.call_count, 0, 'Should not be called') + assert mocked_singleShot.call_count == 0, 'Should not be called' @patch('openlp.core.ui.servicemanager.ServiceManager.make_preview') def test_single_click_timeout_single(self, mocked_make_preview): @@ -607,8 +607,7 @@ class TestServiceManager(TestCase): # WHEN: on_single_click_preview() is called service_manager.on_single_click_preview_timeout() # THEN: make_preview() should have been called - self.assertEqual(mocked_make_preview.call_count, 1, - 'ServiceManager.make_preview() should have been called once') + assert mocked_make_preview.call_count == 1, 'ServiceManager.make_preview() should have been called once' @patch('openlp.core.ui.servicemanager.ServiceManager.make_preview') @patch('openlp.core.ui.servicemanager.ServiceManager.make_live') @@ -622,7 +621,7 @@ class TestServiceManager(TestCase): service_manager.on_double_click_live() service_manager.on_single_click_preview_timeout() # THEN: make_preview() should not have been called - self.assertEqual(mocked_make_preview.call_count, 0, 'ServiceManager.make_preview() should not be called') + assert mocked_make_preview.call_count == 0, 'ServiceManager.make_preview() should not be called' @patch('openlp.core.ui.servicemanager.shutil.copy') @patch('openlp.core.ui.servicemanager.zipfile') @@ -650,7 +649,7 @@ class TestServiceManager(TestCase): result = service_manager.save_file() # THEN: The "save_as" method is called to save the service - self.assertTrue(result) + assert result is True mocked_save_file_as.assert_called_with() @patch('openlp.core.ui.servicemanager.shutil.copy') @@ -678,7 +677,7 @@ class TestServiceManager(TestCase): result = service_manager.save_local_file() # THEN: The "save_as" method is called to save the service - self.assertTrue(result) + assert result is True mocked_save_file_as.assert_called_with() @patch('openlp.core.ui.servicemanager.ServiceManager.regenerate_service_items') @@ -699,8 +698,8 @@ class TestServiceManager(TestCase): service_manager.theme_change() # THEN: The the theme toolbar should not be visible - self.assertFalse(service_manager.toolbar.actions['theme_combo_box'].isVisible(), - 'The visibility should be False') + assert service_manager.toolbar.actions['theme_combo_box'].isVisible() is False, \ + 'The visibility should be False' @patch('openlp.core.ui.servicemanager.ServiceManager.regenerate_service_items') def test_theme_change_service(self, mocked_regenerate_service_items): @@ -720,8 +719,8 @@ class TestServiceManager(TestCase): service_manager.theme_change() # THEN: The the theme toolbar should be visible - self.assertTrue(service_manager.toolbar.actions['theme_combo_box'].isVisible(), - 'The visibility should be True') + assert service_manager.toolbar.actions['theme_combo_box'].isVisible() is True, \ + 'The visibility should be True' @patch('openlp.core.ui.servicemanager.ServiceManager.regenerate_service_items') def test_theme_change_song(self, mocked_regenerate_service_items): @@ -741,5 +740,5 @@ class TestServiceManager(TestCase): service_manager.theme_change() # THEN: The the theme toolbar should be visible - self.assertTrue(service_manager.toolbar.actions['theme_combo_box'].isVisible(), - 'The visibility should be True') + assert service_manager.toolbar.actions['theme_combo_box'].isVisible() is True, \ + 'The visibility should be True' diff --git a/tests/functional/openlp_core/ui/test_settingsform.py b/tests/functional/openlp_core/ui/test_settingsform.py index 6cbc0534e..2e911f8a5 100644 --- a/tests/functional/openlp_core/ui/test_settingsform.py +++ b/tests/functional/openlp_core/ui/test_settingsform.py @@ -57,7 +57,7 @@ class TestSettingsForm(TestCase): # THEN: The general tab should have been inserted into the stacked layout and an item inserted into the list mocked_add_widget.assert_called_with(general_tab) - self.assertEqual(1, mocked_add_item.call_count, 'addItem should have been called') + assert 1 == mocked_add_item.call_count, 'addItem should have been called' def test_insert_tab_not_visible(self): """ @@ -75,7 +75,7 @@ class TestSettingsForm(TestCase): # THEN: The general tab should have been inserted, but no list item should have been inserted into the list mocked_add_widget.assert_called_with(general_tab) - self.assertEqual(0, mocked_add_item.call_count, 'addItem should not have been called') + assert 0 == mocked_add_item.call_count, 'addItem should not have been called' def test_accept_with_inactive_plugins(self): """ @@ -107,7 +107,7 @@ class TestSettingsForm(TestCase): # THEN: The general tab's save() method should have been called, but not the themes tab mocked_general_save.assert_called_with() - self.assertEqual(0, mocked_theme_save.call_count, 'The Themes tab\'s save() should not have been called') + assert 0 == mocked_theme_save.call_count, 'The Themes tab\'s save() should not have been called' def test_list_item_changed_invalid_item(self): """ @@ -128,7 +128,7 @@ class TestSettingsForm(TestCase): settings_form.list_item_changed(100) # THEN: The rest of the method should not have been called - self.assertEqual(0, mocked_count.call_count, 'The count method of the stacked layout should not be called') + assert 0 == mocked_count.call_count, 'The count method of the stacked layout should not be called' def test_reject_with_inactive_items(self): """ @@ -158,7 +158,7 @@ class TestSettingsForm(TestCase): # THEN: The general tab's cancel() method should have been called, but not the themes tab mocked_general_cancel.assert_called_with() - self.assertEqual(0, mocked_theme_cancel.call_count, 'The Themes tab\'s cancel() should not have been called') + assert 0 == mocked_theme_cancel.call_count, 'The Themes tab\'s cancel() should not have been called' def test_register_post_process(self): """ diff --git a/tests/functional/openlp_core/ui/test_slidecontroller.py b/tests/functional/openlp_core/ui/test_slidecontroller.py index bc13f6db8..c33daf21a 100644 --- a/tests/functional/openlp_core/ui/test_slidecontroller.py +++ b/tests/functional/openlp_core/ui/test_slidecontroller.py @@ -29,12 +29,18 @@ from PyQt5 import QtCore, QtGui from openlp.core.common.registry import Registry from openlp.core.lib import ServiceItemAction -from openlp.core.ui import SlideController, LiveController, PreviewController -from openlp.core.ui.slidecontroller import InfoLabel, WIDE_MENU, NON_TEXT_MENU +from openlp.core.ui.slidecontroller import InfoLabel, SlideController, LiveController, PreviewController, \ + NON_TEXT_MENU, WIDE_MENU class TestSlideController(TestCase): + def setUp(self): + """ + Set up the components need for all tests. + """ + Registry.create() + def test_initial_slide_controller(self): """ Test the initial slide controller state . @@ -44,7 +50,7 @@ class TestSlideController(TestCase): # WHEN: the default controller is built. # THEN: The controller should not be a live controller. - self.assertEqual(slide_controller.is_live, False, 'The base slide controller should not be a live controller') + assert slide_controller.is_live is False, 'The base slide controller should not be a live controller' def test_text_service_item_blank(self): """ @@ -121,8 +127,8 @@ class TestSlideController(TestCase): # THEN: Only on_blank_display() should have been called with an argument of True mocked_on_blank_display.assert_called_once_with(True) - self.assertEqual(0, mocked_on_theme_display.call_count, 'on_theme_display should not have been called') - self.assertEqual(0, mocked_on_hide_display.call_count, 'on_hide_display should not have been called') + assert 0 == mocked_on_theme_display.call_count, 'on_theme_display should not have been called' + assert 0 == mocked_on_hide_display.call_count, 'on_hide_display should not have been called' def test_toggle_display_hide(self): """ @@ -142,8 +148,8 @@ class TestSlideController(TestCase): # THEN: Only on_blank_display() should have been called with an argument of True mocked_on_blank_display.assert_called_once_with(True) - self.assertEqual(0, mocked_on_theme_display.call_count, 'on_theme_display should not have been called') - self.assertEqual(0, mocked_on_hide_display.call_count, 'on_hide_display should not have been called') + assert 0 == mocked_on_theme_display.call_count, 'on_theme_display should not have been called' + assert 0 == mocked_on_hide_display.call_count, 'on_hide_display should not have been called' def test_toggle_display_theme(self): """ @@ -163,8 +169,8 @@ class TestSlideController(TestCase): # THEN: Only on_theme_display() should have been called with an argument of True mocked_on_theme_display.assert_called_once_with(True) - self.assertEqual(0, mocked_on_blank_display.call_count, 'on_blank_display should not have been called') - self.assertEqual(0, mocked_on_hide_display.call_count, 'on_hide_display should not have been called') + assert 0 == mocked_on_blank_display.call_count, 'on_blank_display should not have been called' + assert 0 == mocked_on_hide_display.call_count, 'on_hide_display should not have been called' def test_toggle_display_desktop(self): """ @@ -184,8 +190,8 @@ class TestSlideController(TestCase): # THEN: Only on_hide_display() should have been called with an argument of True mocked_on_hide_display.assert_called_once_with(True) - self.assertEqual(0, mocked_on_blank_display.call_count, 'on_blank_display should not have been called') - self.assertEqual(0, mocked_on_theme_display.call_count, 'on_theme_display should not have been called') + assert 0 == mocked_on_blank_display.call_count, 'on_blank_display should not have been called' + assert 0 == mocked_on_theme_display.call_count, 'on_theme_display should not have been called' def test_toggle_display_show(self): """ @@ -348,7 +354,7 @@ class TestSlideController(TestCase): # THEN: The value of slide_limits should be 10 mocked_value.assert_called_once_with('advanced/slide limits') - self.assertEqual(10, slide_controller.slide_limits, 'Slide limits should have been updated to 10') + assert 10 == slide_controller.slide_limits, 'Slide limits should have been updated to 10' def test_enable_tool_bar_live(self): """ @@ -368,7 +374,7 @@ class TestSlideController(TestCase): # THEN: The enable_live_tool_bar() method is called, not enable_preview_tool_bar() mocked_enable_live_tool_bar.assert_called_once_with(mocked_service_item) - self.assertEqual(0, mocked_enable_preview_tool_bar.call_count, 'The preview method should not have been called') + assert 0 == mocked_enable_preview_tool_bar.call_count, 'The preview method should not have been called' def test_enable_tool_bar_preview(self): """ @@ -388,7 +394,7 @@ class TestSlideController(TestCase): # THEN: The enable_preview_tool_bar() method is called, not enable_live_tool_bar() mocked_enable_preview_tool_bar.assert_called_once_with(mocked_service_item) - self.assertEqual(0, mocked_enable_live_tool_bar.call_count, 'The live method should not have been called') + assert 0 == mocked_enable_live_tool_bar.call_count, 'The live method should not have been called' def test_refresh_service_item_text(self): """ @@ -409,7 +415,7 @@ class TestSlideController(TestCase): # THEN: The item should be re-processed mocked_service_item.is_text.assert_called_once_with() - self.assertEqual(0, mocked_service_item.is_image.call_count, 'is_image should not have been called') + assert 0 == mocked_service_item.is_image.call_count, 'is_image should not have been called' mocked_service_item.render.assert_called_once_with() mocked_process_item.assert_called_once_with(mocked_service_item, 5) @@ -456,9 +462,8 @@ class TestSlideController(TestCase): # THEN: The item should be re-processed mocked_service_item.is_text.assert_called_once_with() mocked_service_item.is_image.assert_called_once_with() - self.assertEqual(0, mocked_service_item.render.call_count, 'The render() method should not have been called') - self.assertEqual(0, mocked_process_item.call_count, - 'The mocked_process_item() method should not have been called') + assert 0 == mocked_service_item.render.call_count, 'The render() method should not have been called' + assert 0 == mocked_process_item.call_count, 'The mocked_process_item() method should not have been called' def test_add_service_item_with_song_edit(self): """ @@ -477,7 +482,7 @@ class TestSlideController(TestCase): # THEN: The item is processed, the slide number is correct, and the song is not editable (or something) mocked_item.render.assert_called_once_with() - self.assertFalse(slide_controller.song_edit, 'song_edit should be False') + assert slide_controller.song_edit is False, 'song_edit should be False' mocked_process_item.assert_called_once_with(mocked_item, 2) def test_add_service_item_without_song_edit(self): @@ -497,7 +502,7 @@ class TestSlideController(TestCase): # THEN: The item is processed, the slide number is correct, and the song is not editable (or something) mocked_item.render.assert_called_once_with() - self.assertFalse(slide_controller.song_edit, 'song_edit should be False') + assert slide_controller.song_edit is False, 'song_edit should be False' mocked_process_item.assert_called_once_with(mocked_item, 0) def test_replace_service_manager_item_different_items(self): @@ -517,9 +522,9 @@ class TestSlideController(TestCase): slide_controller.replace_service_manager_item(mocked_item) # THEN: The service item should not be processed - self.assertEqual(0, mocked_process_item.call_count, 'The _process_item() method should not have been called') - self.assertEqual(0, mocked_preview_widget.current_slide_number.call_count, - 'The preview_widgetcurrent_slide_number.() method should not have been called') + assert 0 == mocked_process_item.call_count, 'The _process_item() method should not have been called' + assert 0 == mocked_preview_widget.current_slide_number.call_count, \ + 'The preview_widget current_slide_number.() method should not have been called' def test_replace_service_manager_item_same_item(self): """ @@ -583,7 +588,7 @@ class TestSlideController(TestCase): slide_controller.on_slide_selected_index([10]) # THEN: It should have exited early - self.assertEqual(0, mocked_item.is_command.call_count, 'The service item should have not been called') + assert 0 == mocked_item.is_command.call_count, 'The service item should have not been called' @patch.object(Registry, 'execute') def test_on_slide_selected_index_service_item_command(self, mocked_execute): @@ -612,8 +617,8 @@ class TestSlideController(TestCase): mocked_item.is_command.assert_called_once_with() mocked_execute.assert_called_once_with('mocked item_slide', [mocked_item, True, 9]) mocked_update_preview.assert_called_once_with() - self.assertEqual(0, mocked_preview_widget.change_slide.call_count, 'Change slide should not have been called') - self.assertEqual(0, mocked_slide_selected.call_count, 'slide_selected should not have been called') + assert 0 == mocked_preview_widget.change_slide.call_count, 'Change slide should not have been called' + assert 0 == mocked_slide_selected.call_count, 'slide_selected should not have been called' @patch.object(Registry, 'execute') def test_on_slide_selected_index_service_item_not_command(self, mocked_execute): @@ -639,8 +644,8 @@ class TestSlideController(TestCase): # THEN: It should have sent a notification mocked_item.is_command.assert_called_once_with() - self.assertEqual(0, mocked_execute.call_count, 'Execute should not have been called') - self.assertEqual(0, mocked_update_preview.call_count, 'Update preview should not have been called') + assert 0 == mocked_execute.call_count, 'Execute should not have been called' + assert 0 == mocked_update_preview.call_count, 'Update preview should not have been called' mocked_preview_widget.change_slide.assert_called_once_with(7) mocked_slide_selected.assert_called_once_with() @@ -685,9 +690,9 @@ class TestSlideController(TestCase): slide_controller._process_item(mocked_media_item, 0) # THEN: Registry.execute should have been called to stop the presentation - self.assertEqual(2, mocked_execute.call_count, 'Execute should have been called 2 times') - self.assertEqual('mocked_presentation_item_stop', mocked_execute.call_args_list[1][0][0], - 'The presentation should have been stopped.') + assert 2 == mocked_execute.call_count, 'Execute should have been called 2 times' + assert 'mocked_presentation_item_stop' == mocked_execute.call_args_list[1][0][0], \ + 'The presentation should have been stopped.' def test_live_stolen_focus_shortcuts(self): """ @@ -737,8 +742,8 @@ class TestSlideController(TestCase): slide_controller.on_preview_double_click() # THEN: The call to addActions should be correct - self.assertEqual(1, slide_controller.on_go_live.call_count, 'on_go_live should have been called once.') - self.assertEqual(0, slide_controller.on_preview_add_to_service.call_count, 'Should have not been called.') + assert 1 == slide_controller.on_go_live.call_count, 'on_go_live should have been called once.' + assert 0 == slide_controller.on_preview_add_to_service.call_count, 'Should have not been called.' @patch('openlp.core.ui.slidecontroller.Settings') def test_on_preview_double_click_add_to_service(self, MockedSettings): @@ -760,8 +765,8 @@ class TestSlideController(TestCase): slide_controller.on_preview_double_click() # THEN: The call to addActions should be correct - self.assertEqual(0, slide_controller.on_go_live.call_count, 'on_go_live Should have not been called.') - self.assertEqual(1, slide_controller.on_preview_add_to_service.call_count, 'Should have been called once.') + assert 0 == slide_controller.on_go_live.call_count, 'on_go_live Should have not been called.' + assert 1 == slide_controller.on_preview_add_to_service.call_count, 'Should have been called once.' @patch(u'openlp.core.ui.slidecontroller.SlideController.image_manager') @patch(u'PyQt5.QtCore.QTimer.singleShot') @@ -800,11 +805,10 @@ class TestSlideController(TestCase): slide_controller.update_preview() # THEN: A screen_grab should have been called - self.assertEqual(0, slide_controller.slide_preview.setPixmap.call_count, 'setPixmap should not be called') - self.assertEqual(0, slide_controller.display.preview.call_count, 'display.preview() should not be called') - self.assertEqual(2, mocked_singleShot.call_count, - 'Timer to grab_maindisplay should have been called 2 times') - self.assertEqual(0, mocked_image_manager.get_image.call_count, 'image_manager not be called') + assert 0 == slide_controller.slide_preview.setPixmap.call_count, 'setPixmap should not be called' + assert 0 == slide_controller.display.preview.call_count, 'display.preview() should not be called' + assert 2 == mocked_singleShot.call_count, 'Timer to grab_maindisplay should have been called 2 times' + assert 0 == mocked_image_manager.get_image.call_count, 'image_manager not be called' @patch(u'openlp.core.ui.slidecontroller.SlideController.image_manager') @patch(u'PyQt5.QtCore.QTimer.singleShot') @@ -843,10 +847,10 @@ class TestSlideController(TestCase): slide_controller.update_preview() # THEN: setPixmap and the image_manager should have been called - self.assertEqual(1, slide_controller.slide_preview.setPixmap.call_count, 'setPixmap should be called') - self.assertEqual(0, slide_controller.display.preview.call_count, 'display.preview() should not be called') - self.assertEqual(0, mocked_singleShot.call_count, 'Timer to grab_maindisplay should not be called') - self.assertEqual(1, mocked_image_manager.get_image.call_count, 'image_manager should be called') + assert 1 == slide_controller.slide_preview.setPixmap.call_count, 'setPixmap should be called' + assert 0 == slide_controller.display.preview.call_count, 'display.preview() should not be called' + assert 0 == mocked_singleShot.call_count, 'Timer to grab_maindisplay should not be called' + assert 1 == mocked_image_manager.get_image.call_count, 'image_manager should be called' @patch(u'openlp.core.ui.slidecontroller.SlideController.image_manager') @patch(u'PyQt5.QtCore.QTimer.singleShot') @@ -885,10 +889,10 @@ class TestSlideController(TestCase): slide_controller.update_preview() # THEN: setPixmap should have been called - self.assertEqual(1, slide_controller.slide_preview.setPixmap.call_count, 'setPixmap should be called') - self.assertEqual(0, slide_controller.display.preview.call_count, 'display.preview() should not be called') - self.assertEqual(0, mocked_singleShot.call_count, 'Timer to grab_maindisplay should not be called') - self.assertEqual(0, mocked_image_manager.get_image.call_count, 'image_manager should not be called') + assert 1 == slide_controller.slide_preview.setPixmap.call_count, 'setPixmap should be called' + assert 0 == slide_controller.display.preview.call_count, 'display.preview() should not be called' + assert 0 == mocked_singleShot.call_count, 'Timer to grab_maindisplay should not be called' + assert 0 == mocked_image_manager.get_image.call_count, 'image_manager should not be called' @patch(u'openlp.core.ui.slidecontroller.SlideController.image_manager') @patch(u'PyQt5.QtCore.QTimer.singleShot') @@ -927,10 +931,10 @@ class TestSlideController(TestCase): slide_controller.update_preview() # THEN: setPixmap and display.preview should have been called - self.assertEqual(1, slide_controller.slide_preview.setPixmap.call_count, 'setPixmap should be called') - self.assertEqual(1, slide_controller.display.preview.call_count, 'display.preview() should be called') - self.assertEqual(0, mocked_singleShot.call_count, 'Timer to grab_maindisplay should not be called') - self.assertEqual(0, mocked_image_manager.get_image.call_count, 'image_manager should not be called') + assert 1 == slide_controller.slide_preview.setPixmap.call_count, 'setPixmap should be called' + assert 1 == slide_controller.display.preview.call_count, 'display.preview() should be called' + assert 0 == mocked_singleShot.call_count, 'Timer to grab_maindisplay should not be called' + assert 0 == mocked_image_manager.get_image.call_count, 'image_manager should not be called' class TestInfoLabel(TestCase): @@ -1023,7 +1027,7 @@ class TestLiveController(TestCase): # WHEN: the default controller is built. # THEN: The controller should not be a live controller. - self.assertEqual(live_controller.is_live, True, 'The slide controller should be a live controller') + assert live_controller.is_live is True, 'The slide controller should be a live controller' class TestPreviewLiveController(TestCase): @@ -1038,4 +1042,4 @@ class TestPreviewLiveController(TestCase): # WHEN: the default controller is built. # THEN: The controller should not be a live controller. - self.assertEqual(preview_controller.is_live, False, 'The slide controller should be a Preview controller') + assert preview_controller.is_live is False, 'The slide controller should be a Preview controller' diff --git a/tests/functional/openlp_core/ui/test_style.py b/tests/functional/openlp_core/ui/test_style.py index fc017e87d..17f7cf873 100644 --- a/tests/functional/openlp_core/ui/test_style.py +++ b/tests/functional/openlp_core/ui/test_style.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/functional/openlp_core/ui/test_themeform.py b/tests/functional/openlp_core/ui/test_themeform.py index e487742cc..31e4f4acb 100644 --- a/tests/functional/openlp_core/ui/test_themeform.py +++ b/tests/functional/openlp_core/ui/test_themeform.py @@ -49,5 +49,5 @@ class TestThemeManager(TestCase): self.instance.on_image_path_edit_path_changed(Path('/', 'new', 'pat.h')) # THEN: The theme background file should be set and `set_background_page_values` should have been called - self.assertEqual(self.instance.theme.background_filename, Path('/', 'new', 'pat.h')) + assert self.instance.theme.background_filename == Path('/', 'new', 'pat.h') mocked_set_background_page_values.assert_called_once_with() diff --git a/tests/functional/openlp_core/ui/test_thememanager.py b/tests/functional/openlp_core/ui/test_thememanager.py index f44f558b0..ba5f7fc05 100644 --- a/tests/functional/openlp_core/ui/test_thememanager.py +++ b/tests/functional/openlp_core/ui/test_thememanager.py @@ -30,11 +30,10 @@ from unittest.mock import ANY, MagicMock, patch from PyQt5 import QtWidgets -from openlp.core.common.registry import Registry from openlp.core.common.path import Path +from openlp.core.common.registry import Registry from openlp.core.ui import ThemeManager - -from tests.utils.constants import TEST_RESOURCES_PATH +from tests.utils.constants import RESOURCE_PATH class TestThemeManager(TestCase): @@ -60,7 +59,7 @@ class TestThemeManager(TestCase): """ # GIVEN: A new ThemeManager instance. theme_manager = ThemeManager() - theme_manager.theme_path = Path(TEST_RESOURCES_PATH, 'themes') + theme_manager.theme_path = RESOURCE_PATH / 'themes' mocked_zipfile_init.return_value = None # WHEN: The theme is exported @@ -68,7 +67,7 @@ class TestThemeManager(TestCase): # THEN: The zipfile should be created at the given path mocked_zipfile_init.assert_called_with(os.path.join('some', 'path', 'Default.otz'), 'w') - mocked_zipfile_write.assert_called_with(os.path.join(TEST_RESOURCES_PATH, 'themes', 'Default', 'Default.xml'), + mocked_zipfile_write.assert_called_with(str(RESOURCE_PATH / 'themes' / 'Default' / 'Default.xml'), os.path.join('Default', 'Default.xml')) def test_initial_theme_manager(self): @@ -80,7 +79,7 @@ class TestThemeManager(TestCase): # WHEN: the default theme manager is built. # THEN: The the controller should be registered in the registry. - self.assertIsNotNone(Registry().get('theme_manager'), 'The base theme manager should be registered') + assert Registry().get('theme_manager') is not None, 'The base theme manager should be registered' @patch('openlp.core.ui.thememanager.copyfile') @patch('openlp.core.ui.thememanager.create_paths') @@ -100,8 +99,8 @@ class TestThemeManager(TestCase): mocked_theme.extract_formatted_xml.return_value = 'fake_theme_xml'.encode() # WHEN: Calling _write_theme with path to the same image, but the path written slightly different - file_name1 = Path(TEST_RESOURCES_PATH, 'church.jpg') - theme_manager._write_theme(mocked_theme, file_name1, file_name1) + file_path_1 = RESOURCE_PATH / 'church.jpg' + theme_manager._write_theme(mocked_theme, file_path_1, file_path_1) # THEN: The mocked_copyfile should not have been called assert mocked_copyfile.called is False, 'copyfile should not be called' @@ -123,9 +122,9 @@ class TestThemeManager(TestCase): mocked_theme.filename = "filename" # WHEN: Calling _write_theme with path to different images - file_name1 = Path(TEST_RESOURCES_PATH, 'church.jpg') - file_name2 = Path(TEST_RESOURCES_PATH, 'church2.jpg') - theme_manager._write_theme(mocked_theme, file_name1, file_name2) + file_path_1 = RESOURCE_PATH / 'church.jpg' + file_path_2 = RESOURCE_PATH / 'church2.jpg' + theme_manager._write_theme(mocked_theme, file_path_1, file_path_2) # THEN: The mocked_copyfile should not have been called assert mocked_copyfile.called is True, 'copyfile should be called' @@ -147,8 +146,8 @@ class TestThemeManager(TestCase): theme_manager._write_theme(mocked_theme, None, None) # THEN: It should have been created - self.assertTrue(os.path.exists(os.path.join(self.temp_folder, 'theme 愛 name', 'theme 愛 name.json')), - 'Theme with special characters should have been created!') + assert os.path.exists(os.path.join(self.temp_folder, 'theme 愛 name', 'theme 愛 name.json')) is True, \ + 'Theme with special characters should have been created!' @patch('openlp.core.ui.thememanager.QtWidgets.QMessageBox.question', return_value=QtWidgets.QMessageBox.Yes) @patch('openlp.core.ui.thememanager.translate') @@ -200,14 +199,14 @@ class TestThemeManager(TestCase): theme_manager.generate_and_save_image = MagicMock() theme_manager.theme_path = None folder_path = Path(mkdtemp()) - theme_file = Path(TEST_RESOURCES_PATH, 'themes', 'Moss_on_tree.otz') + theme_file_path = RESOURCE_PATH / 'themes' / 'Moss_on_tree.otz' # WHEN: We try to unzip it - theme_manager.unzip_theme(theme_file, folder_path) + theme_manager.unzip_theme(theme_file_path, folder_path) # THEN: Files should be unpacked - self.assertTrue((folder_path / 'Moss on tree' / 'Moss on tree.xml').exists()) - self.assertEqual(mocked_critical_error_message_box.call_count, 0, 'No errors should have happened') + assert (folder_path / 'Moss on tree' / 'Moss on tree.xml').exists() is True + assert mocked_critical_error_message_box.call_count == 0, 'No errors should have happened' folder_path.rmtree() def test_unzip_theme_invalid_version(self): @@ -228,4 +227,4 @@ class TestThemeManager(TestCase): theme_manager.unzip_theme('theme.file', 'folder') # THEN: The critical_error_message_box should have been called - self.assertEqual(mocked_critical_error_message_box.call_count, 1, 'Should have been called once') + assert mocked_critical_error_message_box.call_count == 1, 'Should have been called once' diff --git a/tests/functional/openlp_core/ui/test_themetab.py b/tests/functional/openlp_core/ui/test_themetab.py index 82a2568cd..f27f4a2ca 100644 --- a/tests/functional/openlp_core/ui/test_themetab.py +++ b/tests/functional/openlp_core/ui/test_themetab.py @@ -26,9 +26,8 @@ from unittest import TestCase from unittest.mock import MagicMock from openlp.core.common.registry import Registry -from openlp.core.ui.themestab import ThemesTab from openlp.core.ui.settingsform import SettingsForm - +from openlp.core.ui.themestab import ThemesTab from tests.helpers.testmixin import TestMixin @@ -51,7 +50,7 @@ class TestThemeTab(TestCase, TestMixin): themes_tab = ThemesTab(settings_form) # THEN: - self.assertEqual("Themes", themes_tab.tab_title, 'The tab title should be Theme') + assert "Themes" == themes_tab.tab_title, 'The tab title should be Theme' def test_save_triggers_processes_true(self): """ @@ -66,7 +65,7 @@ class TestThemeTab(TestCase, TestMixin): themes_tab.save() # THEN: we should have two post save processed to run - self.assertEqual(1, len(settings_form.processes), 'One post save processes should be created') + assert 1 == len(settings_form.processes), 'One post save processes should be created' def test_save_triggers_processes_false(self): """ @@ -81,4 +80,4 @@ class TestThemeTab(TestCase, TestMixin): themes_tab.save() # THEN: we should have two post save processed to run - self.assertEqual(0, len(settings_form.processes), 'No post save processes should be created') + assert 0 == len(settings_form.processes), 'No post save processes should be created' diff --git a/tests/functional/openlp_core/widgets/__init__.py b/tests/functional/openlp_core/widgets/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/functional/openlp_core/widgets/__init__.py +++ b/tests/functional/openlp_core/widgets/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/functional/openlp_core/widgets/test_buttons.py b/tests/functional/openlp_core/widgets/test_buttons.py index 4abd38da4..2bc6d8c5c 100644 --- a/tests/functional/openlp_core/widgets/test_buttons.py +++ b/tests/functional/openlp_core/widgets/test_buttons.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -60,8 +60,7 @@ class TestColorDialog(TestCase): widget = ColorButton() # THEN: The widget __init__ method should have the correct properties and methods called - self.assertEqual(widget.parent, None, - 'The parent should be the same as the one that the class was instianted with') + assert widget.parent is None, 'The parent should be the same as the one that the class was instianted with' self.mocked_change_color.assert_called_once_with('#ffffff') mocked_set_tool_tip.assert_called_once_with('Tool Tip Text') self.mocked_clicked.connect.assert_called_once_with(widget.on_clicked) @@ -80,7 +79,7 @@ class TestColorDialog(TestCase): widget.change_color('#000000') # THEN: The _color attribute should be set to #000000 and setStyleSheet should have been called twice - self.assertEqual(widget._color, '#000000', '_color should have been set to #000000') + assert widget._color == '#000000', '_color should have been set to #000000' mocked_set_style_sheet.assert_has_calls( [call('background-color: #ffffff'), call('background-color: #000000')]) @@ -98,7 +97,7 @@ class TestColorDialog(TestCase): value = widget.color # THEN: The value set in _color should be returned - self.assertEqual(value, '#000000', 'The value returned should be equal to the one we set') + assert value == '#000000', 'The value returned should be equal to the one we set' # @patch('openlp.core.widgets.buttons.ColorButton.__init__', **{'return_value': None}) def test_color_setter(self): @@ -130,10 +129,10 @@ class TestColorDialog(TestCase): widget.on_clicked() # THEN: change_color should not have been called and the colorChanged signal should not have been emitted - self.assertFalse(self.mocked_change_color.called, - 'change_color should not have been called with an invalid color') - self.assertFalse(self.mocked_color_changed.emit.called, - 'colorChange signal should not have been emitted with an invalid color') + assert self.mocked_change_color.called is False, \ + 'change_color should not have been called with an invalid color' + assert self.mocked_color_changed.emit.called is False, \ + 'colorChange signal should not have been emitted with an invalid color' def test_on_clicked_same_color(self): """ @@ -152,10 +151,10 @@ class TestColorDialog(TestCase): widget.on_clicked() # THEN: change_color should not have been called and the colorChanged signal should not have been emitted - self.assertFalse(self.mocked_change_color.called, - 'change_color should not have been called when the color has not changed') - self.assertFalse(self.mocked_color_changed.emit.called, - 'colorChange signal should not have been emitted when the color has not changed') + assert self.mocked_change_color.called is False, \ + 'change_color should not have been called when the color has not changed' + assert self.mocked_color_changed.emit.called is False, \ + 'colorChange signal should not have been emitted when the color has not changed' def test_on_clicked_new_color(self): """ diff --git a/tests/functional/openlp_core/widgets/test_dialogs.py b/tests/functional/openlp_core/widgets/test_dialogs.py index fd65de33e..87a0811c4 100755 --- a/tests/functional/openlp_core/widgets/test_dialogs.py +++ b/tests/functional/openlp_core/widgets/test_dialogs.py @@ -22,7 +22,7 @@ class TestFileDialogPatches(TestCase): instance = FileDialog() # THEN: The instance should be an instance of QFileDialog - self.assertIsInstance(instance, QtWidgets.QFileDialog) + assert isinstance(instance, QtWidgets.QFileDialog) def test_get_existing_directory_user_abort(self): """ @@ -34,7 +34,7 @@ class TestFileDialogPatches(TestCase): result = FileDialog.getExistingDirectory() # THEN: The result should be None - self.assertEqual(result, None) + assert result is None def test_get_existing_directory_user_accepts(self): """ @@ -47,7 +47,7 @@ class TestFileDialogPatches(TestCase): result = FileDialog.getExistingDirectory() # THEN: getExistingDirectory() should return a Path object pointing to the chosen file - self.assertEqual(result, Path('test', 'dir')) + assert result == Path('test', 'dir') def test_get_existing_directory_param_order(self): """ @@ -77,7 +77,7 @@ class TestFileDialogPatches(TestCase): result = FileDialog.getOpenFileName() # THEN: First value should be None - self.assertEqual(result[0], None) + assert result[0] is None def test_get_open_file_name_user_accepts(self): """ @@ -92,7 +92,7 @@ class TestFileDialogPatches(TestCase): # THEN: getOpenFileName() should return a tuple with the first value set to a Path object pointing to the # chosen file - self.assertEqual(result[0], Path('test', 'chosen.file')) + assert result[0] == Path('test', 'chosen.file') def test_get_open_file_name_selected_filter(self): """ @@ -104,7 +104,7 @@ class TestFileDialogPatches(TestCase): result = FileDialog.getOpenFileName() # THEN: getOpenFileName() should return a tuple with the second value set to a the selected filter - self.assertEqual(result[1], 'selected filter') + assert result[1] == 'selected filter' def test_get_open_file_names_user_abort(self): """ @@ -117,7 +117,7 @@ class TestFileDialogPatches(TestCase): result = FileDialog.getOpenFileNames() # THEN: First value should be an empty list - self.assertEqual(result[0], []) + assert result[0] == [] def test_get_open_file_names_user_accepts(self): """ @@ -132,7 +132,7 @@ class TestFileDialogPatches(TestCase): # THEN: getOpenFileNames() should return a tuple with the first value set to a list of Path objects pointing # to the chosen file - self.assertEqual(result[0], [Path('test', 'chosen.file1'), Path('test', 'chosen.file2')]) + assert result[0] == [Path('test', 'chosen.file1'), Path('test', 'chosen.file2')] def test_get_open_file_names_selected_filter(self): """ @@ -145,7 +145,7 @@ class TestFileDialogPatches(TestCase): result = FileDialog.getOpenFileNames() # THEN: getOpenFileNames() should return a tuple with the second value set to a the selected filter - self.assertEqual(result[1], 'selected filter') + assert result[1] == 'selected filter' def test_get_save_file_name_user_abort(self): """ @@ -158,7 +158,7 @@ class TestFileDialogPatches(TestCase): result = FileDialog.getSaveFileName() # THEN: First value should be None - self.assertEqual(result[0], None) + assert result[0] is None def test_get_save_file_name_user_accepts(self): """ @@ -173,7 +173,7 @@ class TestFileDialogPatches(TestCase): # THEN: getSaveFileName() should return a tuple with the first value set to a Path object pointing to the # chosen file - self.assertEqual(result[0], Path('test', 'chosen.file')) + assert result[0] == Path('test', 'chosen.file') def test_get_save_file_name_selected_filter(self): """ @@ -185,4 +185,4 @@ class TestFileDialogPatches(TestCase): result = FileDialog.getSaveFileName() # THEN: getSaveFileName() should return a tuple with the second value set to a the selected filter - self.assertEqual(result[1], 'selected filter') + assert result[1] == 'selected filter' diff --git a/tests/functional/openlp_core/widgets/test_edits.py b/tests/functional/openlp_core/widgets/test_edits.py index 5ce6dc9df..603df3a83 100755 --- a/tests/functional/openlp_core/widgets/test_edits.py +++ b/tests/functional/openlp_core/widgets/test_edits.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -27,9 +27,9 @@ from unittest import TestCase from unittest.mock import MagicMock, PropertyMock, patch from openlp.core.common.path import Path +from openlp.core.widgets.dialogs import FileDialog from openlp.core.widgets.edits import PathEdit from openlp.core.widgets.enums import PathEditType -from openlp.core.widgets.dialogs import FileDialog class TestPathEdit(TestCase): @@ -49,7 +49,7 @@ class TestPathEdit(TestCase): # WHEN: Reading the `path` property # THEN: The value that we set should be returned - self.assertEqual(self.widget.path, Path('getter', 'test', 'pat.h')) + assert self.widget.path == Path('getter', 'test', 'pat.h') def test_path_setter(self): """ @@ -63,7 +63,7 @@ class TestPathEdit(TestCase): # THEN: The `_path` instance variable should be set with the test data. The `line_edit` text and tooltip # should have also been set. - self.assertEqual(self.widget._path, Path('setter', 'test', 'pat.h')) + assert self.widget._path == Path('setter', 'test', 'pat.h') self.widget.line_edit.setToolTip.assert_called_once_with(os.path.join('setter', 'test', 'pat.h')) self.widget.line_edit.setText.assert_called_once_with(os.path.join('setter', 'test', 'pat.h')) @@ -74,7 +74,7 @@ class TestPathEdit(TestCase): # GIVEN: An instance of PathEdit # WHEN: Reading the `path` property # THEN: The default value should be returned - self.assertEqual(self.widget.path_type, PathEditType.Files) + assert self.widget.path_type == PathEditType.Files def test_path_type_setter(self): """ @@ -88,7 +88,7 @@ class TestPathEdit(TestCase): # THEN: The `_path_type` instance variable should be set with the test data and not the default. The # update_button_tool_tips should have been called. - self.assertEqual(self.widget._path_type, PathEditType.Directories) + assert self.widget._path_type == PathEditType.Directories mocked_update_button_tool_tips.assert_called_once_with() def test_update_button_tool_tips_directories(self): @@ -139,7 +139,7 @@ class TestPathEdit(TestCase): mocked_get_existing_directory.assert_called_once_with(self.widget, 'Select Directory', Path('test', 'path'), FileDialog.ShowDirsOnly) - self.assertFalse(mocked_get_open_file_name.called) + assert mocked_get_open_file_name.called is False def test_on_browse_button_clicked_directory_custom_caption(self): """ @@ -162,7 +162,7 @@ class TestPathEdit(TestCase): mocked_get_existing_directory.assert_called_once_with(self.widget, 'Directory Caption', Path('test', 'path'), FileDialog.ShowDirsOnly) - self.assertFalse(mocked_get_open_file_name.called) + assert mocked_get_open_file_name.called is False def test_on_browse_button_clicked_file(self): """ @@ -181,7 +181,7 @@ class TestPathEdit(TestCase): # THEN: The FileDialog.getOpenFileName should have been called with the default caption mocked_get_open_file_name.assert_called_once_with(self.widget, 'Select File', Path('test', 'pat.h'), self.widget.filters) - self.assertFalse(mocked_get_existing_directory.called) + assert mocked_get_existing_directory.called is False def test_on_browse_button_clicked_file_custom_caption(self): """ @@ -203,7 +203,7 @@ class TestPathEdit(TestCase): # THEN: The FileDialog.getOpenFileName should have been called with the custom caption mocked_get_open_file_name.assert_called_once_with(self.widget, 'File Caption', Path('test', 'pat.h'), self.widget.filters) - self.assertFalse(mocked_get_existing_directory.called) + assert mocked_get_existing_directory.called is False def test_on_browse_button_clicked_user_cancels(self): """ @@ -219,7 +219,7 @@ class TestPathEdit(TestCase): self.widget.on_browse_button_clicked() # THEN: normpath should not have been called - self.assertTrue(mocked_get_open_file_name.called) + assert mocked_get_open_file_name.called is True def test_on_browse_button_clicked_user_accepts(self): """ @@ -236,8 +236,8 @@ class TestPathEdit(TestCase): self.widget.on_browse_button_clicked() # THEN: normpath and `on_new_path` should have been called - self.assertTrue(mocked_get_open_file_name.called) - self.assertTrue(self.widget.on_new_path.called) + assert mocked_get_open_file_name.called is True + assert self.widget.on_new_path.called is True def test_on_revert_button_clicked(self): """ @@ -280,7 +280,7 @@ class TestPathEdit(TestCase): self.widget.on_new_path(Path('/old', 'test', 'pat.h')) # THEN: The `pathChanged` signal should not be emitted - self.assertFalse(self.widget.pathChanged.emit.called) + assert self.widget.pathChanged.emit.called is False def test_on_new_path_change(self): """ diff --git a/tests/functional/openlp_core/widgets/test_views.py b/tests/functional/openlp_core/widgets/test_views.py index 0fa028f11..a0bbb4437 100644 --- a/tests/functional/openlp_core/widgets/test_views.py +++ b/tests/functional/openlp_core/widgets/test_views.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,6 +22,7 @@ """ Package to test the openlp.core.widgets.views package. """ +import os from types import GeneratorType from unittest import TestCase from unittest.mock import MagicMock, patch, call @@ -30,7 +31,59 @@ from PyQt5 import QtGui from openlp.core.common.i18n import UiStrings from openlp.core.lib import ImageSource -from openlp.core.widgets.views import ListPreviewWidget, ListWidgetWithDnD, TreeWidgetWithDnD +from openlp.core.widgets.views import ListPreviewWidget, ListWidgetWithDnD, TreeWidgetWithDnD, handle_mime_data_urls + + +class TestHandleMimeDataUrls(TestCase): + """ + Test the :func:`openlp.core.widgets.views.handle_mime_data_urls` function. + """ + def test_files(self): + """ + Test handle_mime_data_urls when the data points to some files. + """ + # GIVEN: Some mocked objects that return True when is_file is called, and some mocked mime data + mocked_path_instance_1 = MagicMock(**{'is_file.return_value': True}) + mocked_path_instance_2 = MagicMock(**{'is_file.return_value': True}) + with patch('openlp.core.widgets.views.Path', + side_effect=[mocked_path_instance_1, mocked_path_instance_2]) as mocked_path: + mocked_q_url_1 = MagicMock(**{'toLocalFile.return_value': os.path.join('file', 'test', 'path', '1.ext')}) + mocked_q_url_2 = MagicMock(**{'toLocalFile.return_value': os.path.join('file', 'test', 'path', '2.ext')}) + mocked_q_mime_data = MagicMock(**{'urls.return_value': [mocked_q_url_1, mocked_q_url_2]}) + + # WHEN: Calling handle_mime_data_urls with the mocked mime data + result = handle_mime_data_urls(mocked_q_mime_data) + + # THEN: Both mocked Path objects should be returned in the list + mocked_path.assert_has_calls([call(os.path.join('file', 'test', 'path', '1.ext')), + call(os.path.join('file', 'test', 'path', '2.ext'))]) + assert result == [mocked_path_instance_1, mocked_path_instance_2] + + def test_directory(self): + """ + Test handle_mime_data_urls when the data points to some directories. + """ + # GIVEN: Some mocked objects that return True when is_dir is called, and some mocked mime data + mocked_path_instance_1 = MagicMock() + mocked_path_instance_2 = MagicMock() + mocked_path_instance_3 = MagicMock() + mocked_path_instance_4 = MagicMock(**{'is_file.return_value': False, 'is_directory.return_value': True, + 'iterdir.return_value': [mocked_path_instance_1, mocked_path_instance_2]}) + mocked_path_instance_5 = MagicMock(**{'is_file.return_value': False, 'is_directory.return_value': True, + 'iterdir.return_value': [mocked_path_instance_3]}) + with patch('openlp.core.widgets.views.Path', + side_effect=[mocked_path_instance_4, mocked_path_instance_5]) as mocked_path: + mocked_q_url_1 = MagicMock(**{'toLocalFile.return_value': os.path.join('file', 'test', 'path')}) + mocked_q_url_2 = MagicMock(**{'toLocalFile.return_value': os.path.join('file', 'test', 'path')}) + mocked_q_mime_data = MagicMock(**{'urls.return_value': [mocked_q_url_1, mocked_q_url_2]}) + + # WHEN: Calling handle_mime_data_urls with the mocked mime data + result = handle_mime_data_urls(mocked_q_mime_data) + + # THEN: The three mocked Path file objects should be returned in the list + mocked_path.assert_has_calls([call(os.path.join('file', 'test', 'path')), + call(os.path.join('file', 'test', 'path'))]) + assert result == [mocked_path_instance_1, mocked_path_instance_2, mocked_path_instance_3] class TestListPreviewWidget(TestCase): @@ -71,8 +124,8 @@ class TestListPreviewWidget(TestCase): list_preview_widget = ListPreviewWidget(None, 1) # THEN: The object is not None, and the _setup() method was called. - self.assertIsNotNone(list_preview_widget, 'The ListPreviewWidget object should not be None') - self.assertEquals(list_preview_widget.screen_ratio, 1, 'Should not be called') + assert list_preview_widget is not None, 'The ListPreviewWidget object should not be None' + assert list_preview_widget.screen_ratio == 1, 'Should not be called' @patch(u'openlp.core.widgets.views.ListPreviewWidget.image_manager') @patch(u'openlp.core.widgets.views.ListPreviewWidget.resizeRowsToContents') @@ -116,7 +169,7 @@ class TestListPreviewWidget(TestCase): list_preview_widget.replace_service_item(mocked_cmd_service_item, 200, 0) # THEN: The ImageManager should be called in the appriopriate manner for each service item. - self.assertEquals(mocked_image_manager.get_image.call_count, 4, 'Should be called once for each slide') + assert mocked_image_manager.get_image.call_count == 4, 'Should be called once for each slide' calls = [call('TEST1', ImageSource.ImagePlugin), call('TEST2', ImageSource.ImagePlugin), call('TEST3', ImageSource.CommandPlugins), call('TEST4', ImageSource.CommandPlugins)] mocked_image_manager.get_image.assert_has_calls(calls) @@ -150,8 +203,8 @@ class TestListPreviewWidget(TestCase): # THEN: setRowHeight() should not be called, while resizeRowsToContents() should be called twice # (once each in __recalculate_layout and replace_service_item) - self.assertEquals(mocked_resizeRowsToContents.call_count, 2, 'Should be called') - self.assertEquals(mocked_setRowHeight.call_count, 0, 'Should not be called') + assert mocked_resizeRowsToContents.call_count == 2, 'Should be called' + assert mocked_setRowHeight.call_count == 0, 'Should not be called' @patch(u'openlp.core.widgets.views.ListPreviewWidget.resizeRowsToContents') @patch(u'openlp.core.widgets.views.ListPreviewWidget.setRowHeight') @@ -185,8 +238,8 @@ class TestListPreviewWidget(TestCase): # THEN: resizeRowsToContents() should not be called, while setRowHeight() should be called # twice for each slide. - self.assertEquals(mocked_resizeRowsToContents.call_count, 0, 'Should not be called') - self.assertEquals(mocked_setRowHeight.call_count, 6, 'Should be called 3 times for each slide') + assert mocked_resizeRowsToContents.call_count == 0, 'Should not be called' + assert mocked_setRowHeight.call_count == 6, 'Should be called 3 times for each slide' calls = [call(0, 200), call(1, 200), call(0, 400), call(1, 400), call(0, 400), call(1, 400)] mocked_setRowHeight.assert_has_calls(calls) @@ -220,8 +273,8 @@ class TestListPreviewWidget(TestCase): # THEN: resizeRowsToContents() should not be called, while setRowHeight() should be called # twice for each slide. - self.assertEquals(mocked_resizeRowsToContents.call_count, 0, 'Should not be called') - self.assertEquals(mocked_setRowHeight.call_count, 4, 'Should be called twice for each slide') + assert mocked_resizeRowsToContents.call_count == 0, 'Should not be called' + assert mocked_setRowHeight.call_count == 4, 'Should be called twice for each slide' calls = [call(0, 100), call(1, 100), call(0, 100), call(1, 100)] mocked_setRowHeight.assert_has_calls(calls) @@ -258,8 +311,8 @@ class TestListPreviewWidget(TestCase): # THEN: resizeRowsToContents() should not be called, while setRowHeight() should be called # twice for each slide. - self.assertEquals(mocked_resizeRowsToContents.call_count, 0, 'Should not be called') - self.assertEquals(mocked_setRowHeight.call_count, 6, 'Should be called 3 times for each slide') + assert mocked_resizeRowsToContents.call_count == 0, 'Should not be called' + assert mocked_setRowHeight.call_count == 6, 'Should be called 3 times for each slide' calls = [call(0, 100), call(1, 100), call(0, 150), call(1, 150), call(0, 100), call(1, 100)] mocked_setRowHeight.assert_has_calls(calls) @@ -295,7 +348,7 @@ class TestListPreviewWidget(TestCase): list_preview_widget.row_resized(0, 100, 150) # THEN: self.cellWidget(row, 0).children()[1].setMaximumWidth() should not be called - self.assertEquals(mocked_cellWidget_child.setMaximumWidth.call_count, 0, 'Should not be called') + assert mocked_cellWidget_child.setMaximumWidth.call_count == 0, 'Should not be called' @patch(u'openlp.core.widgets.views.ListPreviewWidget.resizeRowsToContents') @patch(u'openlp.core.widgets.views.ListPreviewWidget.setRowHeight') @@ -332,7 +385,7 @@ class TestListPreviewWidget(TestCase): list_preview_widget.row_resized(0, 100, 150) # THEN: self.cellWidget(row, 0).children()[1].setMaximumWidth() should not be called - self.assertEquals(mocked_cellWidget_child.setMaximumWidth.call_count, 0, 'Should not be called') + assert mocked_cellWidget_child.setMaximumWidth.call_count == 0, 'Should not be called' @patch(u'openlp.core.widgets.views.ListPreviewWidget.resizeRowsToContents') @patch(u'openlp.core.widgets.views.ListPreviewWidget.setRowHeight') @@ -435,10 +488,10 @@ class TestListPreviewWidget(TestCase): list_preview_widget.change_slide(0) # THEN: no further functions should be called - self.assertEquals(mocked_slide_count.call_count, 0, 'Should not be called') - self.assertEquals(mocked_scrollToItem.call_count, 0, 'Should not be called') - self.assertEquals(mocked_selectRow.call_count, 0, 'Should not be called') - self.assertEquals(mocked_item.call_count, 0, 'Should not be called') + assert mocked_slide_count.call_count == 0, 'Should not be called' + assert mocked_scrollToItem.call_count == 0, 'Should not be called' + assert mocked_selectRow.call_count == 0, 'Should not be called' + assert mocked_item.call_count == 0, 'Should not be called' @patch(u'openlp.core.widgets.views.ListPreviewWidget.selectRow') @patch(u'openlp.core.widgets.views.ListPreviewWidget.scrollToItem') @@ -463,10 +516,10 @@ class TestListPreviewWidget(TestCase): list_preview_widget.change_slide(0) # THEN: no further functions should be called - self.assertEquals(mocked_slide_count.call_count, 3, 'Should be called') - self.assertEquals(mocked_scrollToItem.call_count, 2, 'Should be called') - self.assertEquals(mocked_selectRow.call_count, 2, 'Should be called') - self.assertEquals(mocked_item.call_count, 2, 'Should be called') + assert mocked_slide_count.call_count == 3, 'Should be called' + assert mocked_scrollToItem.call_count == 2, 'Should be called' + assert mocked_selectRow.call_count == 2, 'Should be called' + assert mocked_item.call_count == 2, 'Should be called' calls = [call(0, 0), call(0, 0)] mocked_item.assert_has_calls(calls) @@ -495,10 +548,10 @@ class TestListPreviewWidget(TestCase): list_preview_widget.change_slide(1) # THEN: no further functions should be called - self.assertEquals(mocked_slide_count.call_count, 3, 'Should be called') - self.assertEquals(mocked_scrollToItem.call_count, 3, 'Should be called') - self.assertEquals(mocked_selectRow.call_count, 3, 'Should be called') - self.assertEquals(mocked_item.call_count, 3, 'Should be called') + assert mocked_slide_count.call_count == 3, 'Should be called' + assert mocked_scrollToItem.call_count == 3, 'Should be called' + assert mocked_selectRow.call_count == 3, 'Should be called' + assert mocked_item.call_count == 3, 'Should be called' calls = [call(0, 0), call(1, 0), call(2, 0)] mocked_item.assert_has_calls(calls) @@ -518,7 +571,7 @@ class TestListWidgetWithDnD(TestCase): widget.clear() # THEN: The results text should be the standard 'no results' text. - self.assertEqual(widget.no_results_text, UiStrings().NoResults) + assert widget.no_results_text == UiStrings().NoResults def test_clear_search_while_typing(self): """ @@ -531,7 +584,7 @@ class TestListWidgetWithDnD(TestCase): widget.clear(search_while_typing=True) # THEN: The results text should be the 'short results' text. - self.assertEqual(widget.no_results_text, UiStrings().ShortResults) + assert widget.no_results_text == UiStrings().ShortResults def test_all_items_no_list_items(self): """ @@ -546,8 +599,8 @@ class TestListWidgetWithDnD(TestCase): result = widget.allItems() # THEN: An instance of a Generator object should be returned. The generator should not yeild any results - self.assertIsInstance(result, GeneratorType) - self.assertEqual(list(result), []) + assert isinstance(result, GeneratorType) + assert list(result) == [] def test_all_items_list_items(self): """ @@ -562,8 +615,8 @@ class TestListWidgetWithDnD(TestCase): result = widget.allItems() # THEN: An instance of a Generator object should be returned. The generator should not yeild any results - self.assertIsInstance(result, GeneratorType) - self.assertEqual(list(result), [5, 3]) + assert isinstance(result, GeneratorType) + assert list(result) == [5, 3] def test_paint_event(self): """ @@ -582,7 +635,7 @@ class TestListWidgetWithDnD(TestCase): # THEN: The overridden paintEvnet should have been called mocked_paint_event.assert_called_once_with(mocked_event) - self.assertFalse(mocked_viewport.called) + assert mocked_viewport.called is False def test_paint_event_no_items(self): """ diff --git a/tests/functional/openlp_plugins/__init__.py b/tests/functional/openlp_plugins/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/functional/openlp_plugins/__init__.py +++ b/tests/functional/openlp_plugins/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/functional/openlp_plugins/alerts/__init__.py b/tests/functional/openlp_plugins/alerts/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/functional/openlp_plugins/alerts/__init__.py +++ b/tests/functional/openlp_plugins/alerts/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/functional/openlp_plugins/alerts/test_manager.py b/tests/functional/openlp_plugins/alerts/test_manager.py index c286e81cd..a2aadcc16 100644 --- a/tests/functional/openlp_plugins/alerts/test_manager.py +++ b/tests/functional/openlp_plugins/alerts/test_manager.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,10 +22,8 @@ """ This module contains tests for the CSV Bible importer. """ -import os -import json from unittest import TestCase -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock from openlp.core.common.registry import Registry from openlp.plugins.alerts.lib.alertsmanager import AlertsManager @@ -51,7 +49,7 @@ class TestAlertManager(TestCase): alert_manager.alert_text('') # THEN: the display should not have been triggered - self.assertFalse(alert_manager.display_alert.called, 'The Alert should not have been called') + assert alert_manager.display_alert.called is False, 'The Alert should not have been called' def test_trigger_message_text(self): """ @@ -65,7 +63,7 @@ class TestAlertManager(TestCase): alert_manager.alert_text(['This is a string']) # THEN: the display should have been triggered - self.assertTrue(alert_manager.display_alert.called, 'The Alert should have been called') + assert alert_manager.display_alert.called is True, 'The Alert should have been called' def test_line_break_message_text(self): """ @@ -79,5 +77,5 @@ class TestAlertManager(TestCase): alert_manager.alert_text(['This is \n a string']) # THEN: the display should have been triggered - self.assertTrue(alert_manager.display_alert.called, 'The Alert should have been called') + assert alert_manager.display_alert.called is True, 'The Alert should have been called' alert_manager.display_alert.assert_called_once_with('This is a string') diff --git a/tests/functional/openlp_plugins/bibles/__init__.py b/tests/functional/openlp_plugins/bibles/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/functional/openlp_plugins/bibles/__init__.py +++ b/tests/functional/openlp_plugins/bibles/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/functional/openlp_plugins/bibles/test_bibleimport.py b/tests/functional/openlp_plugins/bibles/test_bibleimport.py index 9b9a8fae8..013bbc267 100644 --- a/tests/functional/openlp_plugins/bibles/test_bibleimport.py +++ b/tests/functional/openlp_plugins/bibles/test_bibleimport.py @@ -26,8 +26,8 @@ from io import BytesIO from unittest import TestCase from unittest.mock import MagicMock, patch -from lxml import etree, objectify from PyQt5.QtWidgets import QDialog +from lxml import etree, objectify from openlp.core.common.i18n import Language from openlp.core.common.path import Path diff --git a/tests/functional/openlp_plugins/bibles/test_bibleserver.py b/tests/functional/openlp_plugins/bibles/test_bibleserver.py index bc05a601f..5d49a7a18 100644 --- a/tests/functional/openlp_plugins/bibles/test_bibleserver.py +++ b/tests/functional/openlp_plugins/bibles/test_bibleserver.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -75,9 +75,8 @@ class TestBSExtract(TestCase): self.mock_urllib.parse.quote.assert_called_once_with(b'NIV') self.mock_get_soup_for_bible_ref.assert_called_once_with( 'http://m.bibleserver.com/overlay/selectBook?translation=NIV') - self.assertIsNone(result, - 'BSExtract.get_books_from_http should return None when get_soup_for_bible_ref returns a ' - 'false value') + assert result is None, \ + 'BSExtract.get_books_from_http should return None when get_soup_for_bible_ref returns a false value' def test_get_books_from_http_no_content(self): """ @@ -106,9 +105,8 @@ class TestBSExtract(TestCase): self.mock_soup.find.assert_called_once_with('ul') self.mock_log.error.assert_called_once_with('No books found in the Bibleserver response.') self.mock_send_error_message.assert_called_once_with('parse') - self.assertIsNone(result, - 'BSExtract.get_books_from_http should return None when get_soup_for_bible_ref returns a ' - 'false value') + assert result is None, \ + 'BSExtract.get_books_from_http should return None when get_soup_for_bible_ref returns a false value' def test_get_books_from_http_content(self): """ @@ -138,6 +136,6 @@ class TestBSExtract(TestCase): self.mock_urllib.parse.quote.assert_called_once_with(b'NIV') self.mock_get_soup_for_bible_ref.assert_called_once_with( 'http://m.bibleserver.com/overlay/selectBook?translation=NIV') - self.assertFalse(self.mock_log.error.called, 'log.error should not have been called') - self.assertFalse(self.mock_send_error_message.called, 'send_error_message should not have been called') - self.assertEqual(result, ['Genesis', 'Leviticus']) + assert self.mock_log.error.called is False, 'log.error should not have been called' + assert self.mock_send_error_message.called is False, 'send_error_message should not have been called' + assert result == ['Genesis', 'Leviticus'] diff --git a/tests/functional/openlp_plugins/bibles/test_csvimport.py b/tests/functional/openlp_plugins/bibles/test_csvimport.py index 4d948f53b..db07706eb 100644 --- a/tests/functional/openlp_plugins/bibles/test_csvimport.py +++ b/tests/functional/openlp_plugins/bibles/test_csvimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -23,8 +23,6 @@ This module contains tests for the CSV Bible importer. """ import csv -import json -import os from collections import namedtuple from unittest import TestCase from unittest.mock import ANY, MagicMock, PropertyMock, call, patch @@ -33,10 +31,10 @@ from openlp.core.common.path import Path from openlp.core.lib.exceptions import ValidationError from openlp.plugins.bibles.lib.bibleimport import BibleImport from openlp.plugins.bibles.lib.importers.csvbible import Book, CSVBible, Verse +from tests.utils import load_external_result_data +from tests.utils.constants import RESOURCE_PATH - -TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), - '..', '..', '..', 'resources', 'bibles')) +TEST_PATH = RESOURCE_PATH / 'bibles' class TestCSVImport(TestCase): @@ -64,9 +62,9 @@ class TestCSVImport(TestCase): CSVBible(mocked_manager, path='.', name='.', books_path=Path('books.csv'), verse_path=Path('verse.csv')) # THEN: The importer should be an instance of BibleImport - self.assertIsInstance(importer, BibleImport) - self.assertEqual(importer.books_path, Path('books.csv')) - self.assertEqual(importer.verses_path, Path('verse.csv')) + assert isinstance(importer, BibleImport) + assert importer.books_path == Path('books.csv') + assert importer.verses_path == Path('verse.csv') def test_book_namedtuple(self): """ @@ -77,10 +75,10 @@ class TestCSVImport(TestCase): result = Book('id', 'testament_id', 'name', 'abbreviation') # THEN: The attributes should match up with the data we used - self.assertEqual(result.id, 'id') - self.assertEqual(result.testament_id, 'testament_id') - self.assertEqual(result.name, 'name') - self.assertEqual(result.abbreviation, 'abbreviation') + assert result.id == 'id' + assert result.testament_id == 'testament_id' + assert result.name == 'name' + assert result.abbreviation == 'abbreviation' def test_verse_namedtuple(self): """ @@ -91,10 +89,10 @@ class TestCSVImport(TestCase): result = Verse('book_id_name', 'chapter_number', 'number', 'text') # THEN: The attributes should match up with the data we used - self.assertEqual(result.book_id_name, 'book_id_name') - self.assertEqual(result.chapter_number, 'chapter_number') - self.assertEqual(result.number, 'number') - self.assertEqual(result.text, 'text') + assert result.book_id_name == 'book_id_name' + assert result.chapter_number == 'chapter_number' + assert result.number == 'number' + assert result.text == 'text' def test_get_book_name_id(self): """ @@ -109,7 +107,7 @@ class TestCSVImport(TestCase): actual_result = CSVBible.get_book_name(name, books) # THEN: get_book_name() should return the book name associated with that id from the books dictionary - self.assertEqual(actual_result, expected_result) + assert actual_result == expected_result def test_get_book_name(self): """ @@ -124,7 +122,7 @@ class TestCSVImport(TestCase): actual_result = CSVBible.get_book_name(name, books) # THEN: get_book_name() should return the input - self.assertEqual(actual_result, expected_result) + assert actual_result == expected_result def test_parse_csv_file(self): """ @@ -144,8 +142,8 @@ class TestCSVImport(TestCase): result = CSVBible.parse_csv_file(Path('file.csv'), TestTuple) # THEN: A list of TestTuple instances with the parsed data should be returned - self.assertEqual(result, [TestTuple('1', 'Line 1', 'Data 1'), TestTuple('2', 'Line 2', 'Data 2'), - TestTuple('3', 'Line 3', 'Data 3')]) + assert result == [TestTuple('1', 'Line 1', 'Data 1'), TestTuple('2', 'Line 2', 'Data 2'), + TestTuple('3', 'Line 3', 'Data 3')] mocked_open.assert_called_once_with('r', encoding='utf-8', newline='') mocked_reader.assert_called_once_with(ANY, delimiter=',', quotechar='"') @@ -162,7 +160,7 @@ class TestCSVImport(TestCase): # THEN: A ValidationError should be raised with self.assertRaises(ValidationError) as context: CSVBible.parse_csv_file(Path('file.csv'), None) - self.assertEqual(context.exception.msg, 'Parsing "file.csv" failed') + assert context.exception.msg == 'Parsing "file.csv" failed' def test_parse_csv_file_csverror(self): """ @@ -178,7 +176,7 @@ class TestCSVImport(TestCase): # THEN: A ValidationError should be raised with self.assertRaises(ValidationError) as context: CSVBible.parse_csv_file(Path('file.csv'), None) - self.assertEqual(context.exception.msg, 'Parsing "file.csv" failed') + assert context.exception.msg == 'Parsing "file.csv" failed' def test_process_books_stopped_import(self): """ @@ -197,8 +195,8 @@ class TestCSVImport(TestCase): result = importer.process_books(['Book 1']) # THEN: increment_progress_bar should not be called and the return value should be an empty dictionary - self.assertFalse(importer.wizard.increment_progress_bar.called) - self.assertEqual(result, {}) + assert importer.wizard.increment_progress_bar.called is False + assert result == {} def test_process_books(self): """ @@ -222,9 +220,9 @@ class TestCSVImport(TestCase): # THEN: translate and find_and_create_book should have been called with both book names. # The returned data should be a dictionary with both song's id and names. - self.assertEqual(importer.find_and_create_book.mock_calls, - [call('1. Mosebog', 2, 10), call('2. Mosebog', 2, 10)]) - self.assertDictEqual(result, {1: '1. Mosebog', 2: '2. Mosebog'}) + assert importer.find_and_create_book.mock_calls == \ + [call('1. Mosebog', 2, 10), call('2. Mosebog', 2, 10)] + assert result == {1: '1. Mosebog', 2: '2. Mosebog'} def test_process_verses_stopped_import(self): """ @@ -244,8 +242,8 @@ class TestCSVImport(TestCase): result = importer.process_verses(['Dummy Verse'], []) # THEN: get_book_name should not be called and the return value should be None - self.assertFalse(importer.get_book_name.called) - self.assertIsNone(result) + assert importer.get_book_name.called is False + assert result is None def test_process_verses_successful(self): """ @@ -272,13 +270,13 @@ class TestCSVImport(TestCase): importer.process_verses(verses, books) # THEN: create_verse is called with the test data - self.assertEqual(importer.get_book_name.mock_calls, [call(1, books), call(1, books)]) + assert importer.get_book_name.mock_calls == [call(1, books), call(1, books)] importer.get_book.assert_called_once_with('1. Mosebog') - self.assertEqual(importer.session.commit.call_count, 2) - self.assertEqual(importer.create_verse.mock_calls, - [call('1', 1, 1, 'I Begyndelsen skabte Gud Himmelen og Jorden.'), - call('1', 1, 2, 'Og Jorden var øde og tom, og der var Mørke over Verdensdybet. ' - 'Men Guds Ånd svævede over Vandene.')]) + assert importer.session.commit.call_count == 2 + assert importer.create_verse.mock_calls == \ + [call('1', 1, 1, 'I Begyndelsen skabte Gud Himmelen og Jorden.'), + call('1', 1, 2, 'Og Jorden var øde og tom, og der var Mørke over Verdensdybet. ' + 'Men Guds Ånd svævede over Vandene.')] def test_do_import_invalid_language_id(self): """ @@ -296,7 +294,7 @@ class TestCSVImport(TestCase): # THEN: The False should be returned. importer.get_language.assert_called_once_with('Bible Name') - self.assertFalse(result) + assert result is False def test_do_import_success(self): """ @@ -320,11 +318,11 @@ class TestCSVImport(TestCase): # THEN: parse_csv_file should be called twice, # and True should be returned. - self.assertEqual(importer.parse_csv_file.mock_calls, - [call(Path('books.csv'), Book), call(Path('verses.csv'), Verse)]) + assert importer.parse_csv_file.mock_calls == \ + [call(Path('books.csv'), Book), call(Path('verses.csv'), Verse)] importer.process_books.assert_called_once_with(['Book 1']) importer.process_verses.assert_called_once_with(['Verse 1'], ['Book 1']) - self.assertTrue(result) + assert result is True def test_file_import(self): """ @@ -332,10 +330,9 @@ class TestCSVImport(TestCase): """ # GIVEN: Test files with a mocked out "manager", "import_wizard", and mocked functions # get_book_ref_id_by_name, create_verse, create_book, session and get_language. - result_file = open(os.path.join(TEST_PATH, 'dk1933.json'), 'rb') - test_data = json.loads(result_file.read().decode()) - books_file = Path(TEST_PATH, 'dk1933-books.csv') - verses_file = Path(TEST_PATH, 'dk1933-verses.csv') + test_data = load_external_result_data(TEST_PATH / 'dk1933.json') + books_file = TEST_PATH / 'dk1933-books.csv' + verses_file = TEST_PATH / 'dk1933-verses.csv' with patch('openlp.plugins.bibles.lib.importers.csvbible.CSVBible.application'): mocked_manager = MagicMock() mocked_import_wizard = MagicMock() @@ -353,7 +350,7 @@ class TestCSVImport(TestCase): importer.do_import() # THEN: The create_verse() method should have been called with each verse in the file. - self.assertTrue(importer.create_verse.called) + assert importer.create_verse.called is True for verse_tag, verse_text in test_data['verses']: importer.create_verse.assert_any_call(importer.get_book().id, 1, verse_tag, verse_text) importer.create_book.assert_any_call('1. Mosebog', importer.get_book_ref_id_by_name(), 1) diff --git a/tests/functional/openlp_plugins/bibles/test_db.py b/tests/functional/openlp_plugins/bibles/test_db.py index 7a65fcdd3..8a00a53c7 100644 --- a/tests/functional/openlp_plugins/bibles/test_db.py +++ b/tests/functional/openlp_plugins/bibles/test_db.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/functional/openlp_plugins/bibles/test_lib.py b/tests/functional/openlp_plugins/bibles/test_lib.py index 5ae8ae85d..594b3e8cc 100644 --- a/tests/functional/openlp_plugins/bibles/test_lib.py +++ b/tests/functional/openlp_plugins/bibles/test_lib.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -27,7 +27,6 @@ from unittest.mock import MagicMock, patch from openlp.plugins.bibles import lib from openlp.plugins.bibles.lib import SearchResults, get_reference_match - from tests.helpers.testmixin import TestMixin @@ -59,7 +58,7 @@ class TestLib(TestCase, TestMixin): _ = lib.get_reference_separator(key) # THEN: get_reference_separator should return the correct separator - self.assertEqual(separators[key], value) + assert separators[key] == value mocked_update_reference_separators.assert_called_once_with() def test_reference_matched_full(self): @@ -116,13 +115,13 @@ class TestLib(TestCase, TestMixin): # THEN: A match should be returned, and the book and reference should match the # expected result - self.assertIsNotNone(match, '{text} should provide a match'.format(text=reference_text)) - self.assertEqual(book_result, match.group('book'), - '{text} does not provide the expected result for the book group.' - .format(text=reference_text)) - self.assertEqual(ranges_result, match.group('ranges'), - '{text} does not provide the expected result for the ranges group.' - .format(text=reference_text)) + assert match is not None, '{text} should provide a match'.format(text=reference_text) + assert book_result == match.group('book'), \ + '{text} does not provide the expected result for the book group.'\ + .format(text=reference_text) + assert ranges_result == match.group('ranges'), \ + '{text} does not provide the expected result for the ranges group.' \ + .format(text=reference_text) def test_reference_matched_range(self): """ @@ -158,12 +157,12 @@ class TestLib(TestCase, TestMixin): # THEN: A match should be returned, and the to/from chapter/verses should match as # expected - self.assertIsNotNone(match, '{text} should provide a match'.format(text=reference_text)) - self.assertEqual(match.group('from_chapter'), from_chapter) - self.assertEqual(match.group('from_verse'), from_verse) - self.assertEqual(match.group('range_to'), range_to) - self.assertEqual(match.group('to_chapter'), to_chapter) - self.assertEqual(match.group('to_verse'), to_verse) + assert match is not None, '{text} should provide a match'.format(text=reference_text) + assert match.group('from_chapter') == from_chapter + assert match.group('from_verse') == from_verse + assert match.group('range_to') == range_to + assert match.group('to_chapter') == to_chapter + assert match.group('to_verse') == to_verse def test_reference_matched_range_separator(self): # GIVEN: Some test data which contains different references to parse, with the expected results. @@ -199,7 +198,7 @@ class TestLib(TestCase, TestMixin): references = full_reference_match.split(reference_text) # THEN: The list of references should be as the expected results - self.assertEqual(references, ranges) + assert references == ranges def test_search_results_creation(self): """ @@ -218,10 +217,10 @@ class TestLib(TestCase, TestMixin): search_results = SearchResults(book, chapter, verse_list) # THEN: It should have a book, a chapter and a verse list - self.assertIsNotNone(search_results, 'The search_results object should not be None') - self.assertEqual(search_results.book, book, 'The book should be "Genesis"') - self.assertEqual(search_results.chapter, chapter, 'The chapter should be 1') - self.assertDictEqual(search_results.verse_list, verse_list, 'The verse lists should be identical') + assert search_results is not None, 'The search_results object should not be None' + assert search_results.book == book, 'The book should be "Genesis"' + assert search_results.chapter == chapter, 'The chapter should be 1' + assert search_results.verse_list == verse_list, 'The verse lists should be identical' def test_search_results_has_verse_list(self): """ @@ -234,7 +233,7 @@ class TestLib(TestCase, TestMixin): has_verse_list = search_results.has_verse_list() # THEN: It should be True - self.assertTrue(has_verse_list, 'The SearchResults object should have a verse list') + assert has_verse_list is True, 'The SearchResults object should have a verse list' def test_search_results_has_no_verse_list(self): """ @@ -247,4 +246,4 @@ class TestLib(TestCase, TestMixin): has_verse_list = search_results.has_verse_list() # THEN: It should be False - self.assertFalse(has_verse_list, 'The SearchResults object should have a verse list') + assert has_verse_list is False, 'The SearchResults object should have a verse list' diff --git a/tests/functional/openlp_plugins/bibles/test_manager.py b/tests/functional/openlp_plugins/bibles/test_manager.py index 73e64d130..b5a4d4f1c 100644 --- a/tests/functional/openlp_plugins/bibles/test_manager.py +++ b/tests/functional/openlp_plugins/bibles/test_manager.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -63,7 +63,7 @@ class TestManager(TestCase): # THEN: The session should have been closed and set to None, the bible should be deleted, and the result of # the deletion returned. - self.assertTrue(result) + assert result is True mocked_close_all.assert_called_once_with() - self.assertIsNone(mocked_bible.session) + assert mocked_bible.session is None mocked_delete_file.assert_called_once_with(Path('bibles', 'KJV.sqlite')) diff --git a/tests/functional/openlp_plugins/bibles/test_mediaitem.py b/tests/functional/openlp_plugins/bibles/test_mediaitem.py index ddc66254f..1d5425b2a 100755 --- a/tests/functional/openlp_plugins/bibles/test_mediaitem.py +++ b/tests/functional/openlp_plugins/bibles/test_mediaitem.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -27,12 +27,11 @@ from unittest.mock import MagicMock, call, patch from PyQt5 import QtCore, QtWidgets -from tests.helpers.testmixin import TestMixin - from openlp.core.common.registry import Registry from openlp.core.lib import MediaManagerItem from openlp.plugins.bibles.lib.mediaitem import BibleMediaItem, BibleSearch, ResultsTab, SearchStatus, SearchTabs, \ get_reference_separators, VALID_TEXT_SEARCH +from tests.helpers.testmixin import TestMixin class TestBibleMediaItemModulefunctions(TestCase): @@ -53,9 +52,9 @@ class TestBibleMediaItemModulefunctions(TestCase): # THEN: The expected result should be returned if expected_result is None: - self.assertIsNone(result, expected_result) + assert result is None, expected_result else: - self.assertEqual(result.regs, expected_result) + assert result.regs == expected_result def test_get_reference_separators(self): """ @@ -69,7 +68,7 @@ class TestBibleMediaItemModulefunctions(TestCase): # THEN: The result should contain the 'verse', 'range', 'list' keys and get_reference_separator should have # been called with the expected values. - self.assertTrue(all(key in result for key in ('verse', 'range', 'list'))) + assert all(key in result for key in ('verse', 'range', 'list')) is True mocked_get_reference_separator.assert_has_calls( [call('sep_v_display'), call('sep_r_display'), call('sep_l_display')]) @@ -80,9 +79,9 @@ class TestBibleMediaItemModulefunctions(TestCase): # GIVEN: The BibleSearch class # WHEN: Testing its attributes # THEN: The BibleSearch class should have the following enumrations - self.assertTrue(hasattr(BibleSearch, 'Combined')) - self.assertTrue(hasattr(BibleSearch, 'Reference')) - self.assertTrue(hasattr(BibleSearch, 'Text')) + assert hasattr(BibleSearch, 'Combined') + assert hasattr(BibleSearch, 'Reference') + assert hasattr(BibleSearch, 'Text') def test_bible_media_item_subclass(self): """ @@ -91,7 +90,7 @@ class TestBibleMediaItemModulefunctions(TestCase): # GIVEN: The :class:`BibleMediaItem` # WHEN: Checking if it is a subclass of MediaManagerItem # THEN: BibleMediaItem should be a subclass of MediaManagerItem - self.assertTrue(issubclass(BibleMediaItem, MediaManagerItem)) + assert issubclass(BibleMediaItem, MediaManagerItem) def test_bible_media_item_signals(self): """ @@ -99,10 +98,10 @@ class TestBibleMediaItemModulefunctions(TestCase): """ # GIVEN: The :class:`BibleMediaItem` # THEN: The :class:`BibleMediaItem` should contain the following pyqtSignal's - self.assertTrue(hasattr(BibleMediaItem, 'bibles_go_live')) - self.assertTrue(hasattr(BibleMediaItem, 'bibles_add_to_service')) - self.assertTrue(isinstance(BibleMediaItem.bibles_go_live, QtCore.pyqtSignal)) - self.assertTrue(isinstance(BibleMediaItem.bibles_add_to_service, QtCore.pyqtSignal)) + assert hasattr(BibleMediaItem, 'bibles_go_live') + assert hasattr(BibleMediaItem, 'bibles_add_to_service') + assert isinstance(BibleMediaItem.bibles_go_live, QtCore.pyqtSignal) + assert isinstance(BibleMediaItem.bibles_add_to_service, QtCore.pyqtSignal) class TestMediaItem(TestCase, TestMixin): @@ -166,7 +165,7 @@ class TestMediaItem(TestCase, TestMixin): # GIVEN: An instance of :class:`BibleMediaItem` # WEHN: Checking its class # THEN: It should be a subclass of :class:`MediaManagerItem` - self.assertTrue(isinstance(self.media_item, MediaManagerItem)) + assert isinstance(self.media_item, MediaManagerItem) def test_steup_item(self): """ @@ -193,11 +192,11 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.required_icons() # THEN: The correct icons should be set - self.assertTrue(self.media_item.has_import_icon, 'Check that the icon is as True.') - self.assertFalse(self.media_item.has_new_icon, 'Check that the icon is called as False.') - self.assertTrue(self.media_item.has_edit_icon, 'Check that the icon is called as True.') - self.assertTrue(self.media_item.has_delete_icon, 'Check that the icon is called as True.') - self.assertFalse(self.media_item.add_to_service_item, 'Check that the icon is called as False') + assert self.media_item.has_import_icon is True, 'Check that the icon is as True.' + assert self.media_item.has_new_icon is False, 'Check that the icon is called as False.' + assert self.media_item.has_edit_icon is True, 'Check that the icon is called as True.' + assert self.media_item.has_delete_icon is True, 'Check that the icon is called as True.' + assert self.media_item.add_to_service_item is False, 'Check that the icon is called as False' def test_on_focus_search_tab_visible(self): """ @@ -305,8 +304,8 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.initialise() # THEN: The search_edit search types should have been set. - self.assertTrue(self.media_item.search_edit.set_search_types.called) - self.assertFalse(self.media_item.search_edit.set_current_search_type.called) + assert self.media_item.search_edit.set_search_types.called is True + assert self.media_item.search_edit.set_current_search_type.called is False def test_initalise_reset_search_type(self): """ @@ -323,7 +322,7 @@ class TestMediaItem(TestCase, TestMixin): # THEN: The search_edit search types should have been set and that the current search type should be set to # 'Combined' - self.assertTrue(self.media_item.search_edit.set_search_types.called) + assert self.media_item.search_edit.set_search_types.called is True self.media_item.search_edit.set_current_search_type.assert_called_once_with(BibleSearch.Combined) def test_populate_bible_combo_boxes(self): @@ -373,7 +372,7 @@ class TestMediaItem(TestCase, TestMixin): result = self.media_item.get_common_books(self.mocked_bible_1) # THEN: The book of the bible should be returned - self.assertEqual(result, self.book_list_1) + assert result == self.book_list_1 def test_get_common_books_second_book(self): """ @@ -384,7 +383,7 @@ class TestMediaItem(TestCase, TestMixin): result = self.media_item.get_common_books(self.mocked_bible_1, self.mocked_bible_2) # THEN: Only the books contained in both bibles should be returned - self.assertEqual(result, [self.mocked_book_2, self.mocked_book_3]) + assert result == [self.mocked_book_2, self.mocked_book_3] def test_initialise_advanced_bible_no_bible(self): """ @@ -399,7 +398,7 @@ class TestMediaItem(TestCase, TestMixin): result = self.media_item.initialise_advanced_bible() # THEN: initialise_advanced_bible should return with put calling get_common_books - self.assertIsNone(result) + assert result is None mocked_get_common_books.assert_not_called() def test_initialise_advanced_bible_add_books_with_last_id_found(self): @@ -515,8 +514,8 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.on_import_click() # THEN: BibleImport wizard should have been instianted and reload_bibles should not have been called - self.assertTrue(mocked_bible_import_form.called) - self.assertFalse(mocked_reload_bibles.called) + assert mocked_bible_import_form.called is True + assert mocked_reload_bibles.called is False def test_on_import_click_wizard_not_canceled(self): """ @@ -532,8 +531,8 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.on_import_click() # THEN: BibleImport wizard should have been instianted and reload_bibles should not have been called - self.assertFalse(mocked_import_wizard.called) - self.assertTrue(mocked_reload_bibles.called) + assert mocked_import_wizard.called is False + assert mocked_reload_bibles.called is True def test_on_edit_click_no_bible(self): """ @@ -547,7 +546,7 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.on_edit_click() # THEN: EditBibleForm should not have been instianted - self.assertFalse(mocked_edit_bible_form.called) + assert mocked_edit_bible_form.called is False def test_on_edit_click_user_cancel_edit_form(self): """ @@ -565,8 +564,8 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.on_edit_click() # THEN: EditBibleForm should have been been instianted but reload_bibles should not have been called - self.assertTrue(mocked_edit_bible_form.called) - self.assertFalse(mocked_reload_bibles.called) + assert mocked_edit_bible_form.called is True + assert mocked_reload_bibles.called is False def test_on_edit_click_user_accepts_edit_form(self): """ @@ -585,8 +584,8 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.on_edit_click() # THEN: EditBibleForm should have been been instianted and reload_bibles should have been called - self.assertTrue(mocked_edit_bible_form.called) - self.assertTrue(mocked_reload_bibles.called) + assert mocked_edit_bible_form.called is True + assert mocked_reload_bibles.called is True def test_on_delete_click_no_bible(self): """ @@ -600,7 +599,7 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.on_delete_click() # THEN: QMessageBox.question should not have been called - self.assertFalse(mocked_qmessage_box.question.called) + assert mocked_qmessage_box.question.called is False def test_on_delete_click_response_no(self): """ @@ -615,8 +614,8 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.on_delete_click() # THEN: QMessageBox.question should have been called, but the delete_bible should not have been called - self.assertTrue(mocked_qmessage_box.called) - self.assertFalse(self.mocked_plugin.manager.delete_bible.called) + assert mocked_qmessage_box.called is True + assert self.mocked_plugin.manager.delete_bible.called is False def test_on_delete_click_response_yes(self): """ @@ -632,8 +631,8 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.on_delete_click() # THEN: QMessageBox.question should and delete_bible should not have been called - self.assertTrue(mocked_qmessage_box.called) - self.assertTrue(self.mocked_plugin.manager.delete_bible.called) + assert mocked_qmessage_box.called is True + assert self.mocked_plugin.manager.delete_bible.called is True def test_on_search_tab_bar_current_changed_search_tab_selected(self): """ @@ -711,8 +710,8 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.on_clear_button_clicked() # THEN: The list_view and the search_edit should be cleared - self.assertEqual(self.media_item.current_results, []) - self.assertEqual(self.media_item.list_view.takeItem.call_count, 2) + assert self.media_item.current_results == [] + assert self.media_item.list_view.takeItem.call_count == 2 self.media_item.list_view.row.assert_has_calls([call('Some'), call('Results')]) def test_on_save_results_button_clicked(self): @@ -733,7 +732,7 @@ class TestMediaItem(TestCase, TestMixin): # THEN: The selected results in the list_view should be added to the 'saved_results' list. And the saved_tab # total should be updated. - self.assertEqual(self.media_item.saved_results, ['R1', 'R2', 'R3']) + assert self.media_item.saved_results == ['R1', 'R2', 'R3'] mocked_on_results_view_tab_total_update.assert_called_once_with(ResultsTab.Saved) def test_on_style_combo_box_changed(self): @@ -746,8 +745,8 @@ class TestMediaItem(TestCase, TestMixin): # WHEN: Calling on_style_combo_box_index_changed self.media_item.on_style_combo_box_index_changed(2) - # THEN: The layput_style settimg should have been set - self.assertEqual(self.media_item.settings.layout_style, 2) + # THEN: The layout_style setting should have been set + assert self.media_item.settings.layout_style == 2 self.media_item.settings.layout_style_combo_box.setCurrentIndex.assert_called_once_with(2) self.mocked_settings_instance.setValue.assert_called_once_with('bibles/verse layout style', 2) @@ -763,9 +762,9 @@ class TestMediaItem(TestCase, TestMixin): # WHEN: Calling on_version_combo_box_index_changed self.media_item.on_version_combo_box_index_changed() - # THEN: The vesion should be saved to settings and the 'select tab' should be initialised - self.assertFalse(self.mocked_settings_instance.setValue.called) - self.assertTrue(self.media_item.initialise_advanced_bible.called) + # THEN: The version should be saved to settings and the 'select tab' should be initialised + assert self.mocked_settings_instance.setValue.called is False + assert self.media_item.initialise_advanced_bible.called is True def test_on_version_combo_box_index_changed_bible_selected(self): """ @@ -781,9 +780,9 @@ class TestMediaItem(TestCase, TestMixin): # WHEN: Calling on_version_combo_box_index_changed self.media_item.on_version_combo_box_index_changed() - # THEN: The vesion should be saved to settings and the 'select tab' should be initialised + # THEN: The version should be saved to settings and the 'select tab' should be initialised self.mocked_settings_instance.setValue.assert_called_once_with('bibles/primary bible', 'ABC') - self.assertTrue(self.media_item.initialise_advanced_bible.called) + assert self.media_item.initialise_advanced_bible.called is True def test_on_second_combo_box_index_changed_mode_not_changed(self): """ @@ -798,15 +797,15 @@ class TestMediaItem(TestCase, TestMixin): patch('openlp.plugins.bibles.lib.mediaitem.critical_error_message_box') \ as mocked_critical_error_message_box: - # WHEN: The previously selected bible is one bible and the new selection is annother bible + # WHEN: The previously selected bible is one bible and the new selection is another bible self.media_item.second_bible = self.mocked_bible_1 self.media_item.second_combo_box = MagicMock(**{'currentData.return_value': self.mocked_bible_2}) self.media_item.on_second_combo_box_index_changed(5) # THEN: The new bible should now be the current bible - self.assertFalse(mocked_critical_error_message_box.called) + assert mocked_critical_error_message_box.called is False self.media_item.style_combo_box.setEnabled.assert_called_once_with(False) - self.assertEqual(self.media_item.second_bible, self.mocked_bible_2) + assert self.media_item.second_bible == self.mocked_bible_2 def test_on_second_combo_box_index_changed_single_to_dual_user_abort(self): """ @@ -828,11 +827,11 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.saved_results = ['saved_results'] self.media_item.on_second_combo_box_index_changed(5) - # THEN: The list_view should be cleared and the currently selected bible should not be channged - self.assertTrue(mocked_critical_error_message_box.called) - self.assertTrue(self.media_item.second_combo_box.setCurrentIndex.called) - self.assertFalse(self.media_item.style_combo_box.setEnabled.called) - self.assertEqual(self.media_item.second_bible, None) + # THEN: The list_view should be cleared and the currently selected bible should not be changed + assert mocked_critical_error_message_box.called is True + assert self.media_item.second_combo_box.setCurrentIndex.called is True + assert self.media_item.style_combo_box.setEnabled.called is False + assert self.media_item.second_bible is None def test_on_second_combo_box_index_changed_single_to_dual(self): """ @@ -857,10 +856,10 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.on_second_combo_box_index_changed(5) # THEN: The selected bible should be set as the current bible - self.assertTrue(mocked_critical_error_message_box.called) + assert mocked_critical_error_message_box.called is True self.media_item.style_combo_box.setEnabled.assert_called_once_with(False) - self.assertTrue(mocked_initialise_advanced_bible.called) - self.assertEqual(self.media_item.second_bible, self.mocked_bible_1) + assert mocked_initialise_advanced_bible.called is True + assert self.media_item.second_bible == self.mocked_bible_1 def test_on_second_combo_box_index_changed_dual_to_single(self): """ @@ -884,10 +883,10 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.on_second_combo_box_index_changed(0) # THEN: The selected bible should be set as the current bible - self.assertTrue(mocked_critical_error_message_box.called) + assert mocked_critical_error_message_box.called is True self.media_item.style_combo_box.setEnabled.assert_called_once_with(True) - self.assertFalse(mocked_initialise_advanced_bible.called) - self.assertEqual(self.media_item.second_bible, None) + assert mocked_initialise_advanced_bible.called is False + assert self.media_item.second_bible is None def test_on_advanced_book_combo_box(self): """ @@ -907,7 +906,7 @@ class TestMediaItem(TestCase, TestMixin): # THEN: The user should be informed that the bible cannot be used and the search button should be disabled self.mocked_plugin.manager.get_book_by_id.assert_called_once_with('Bible 1', 2) self.media_item.search_button.setEnabled.assert_called_once_with(False) - self.assertTrue(mocked_critical_error_message_box.called) + assert mocked_critical_error_message_box.called is True def test_on_advanced_book_combo_box_set_up_comboboxes(self): """ @@ -930,7 +929,7 @@ class TestMediaItem(TestCase, TestMixin): # THEN: The verse selection combobox's should be set up self.mocked_plugin.manager.get_book_by_id.assert_called_once_with('Bible 1', 2) self.media_item.search_button.setEnabled.assert_called_once_with(True) - self.assertEqual(mocked_adjust_combo_box.call_count, 4) + assert mocked_adjust_combo_box.call_count == 4 def test_on_from_chapter_activated_invalid_to_chapter(self): """ @@ -951,9 +950,9 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.on_from_chapter_activated() # THEN: The to_verse and to_chapter comboboxes should be updated appropriately - self.assertEqual(mocked_adjust_combo_box.call_args_list, [ + assert mocked_adjust_combo_box.call_args_list == [ call(1, 20, self.media_item.from_verse), call(1, 20, self.media_item.to_verse, False), - call(10, 25, self.media_item.to_chapter, False)]) + call(10, 25, self.media_item.to_chapter, False)] def test_on_from_chapter_activated_same_chapter(self): """ @@ -974,9 +973,9 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.on_from_chapter_activated() # THEN: The to_verse and to_chapter comboboxes should be updated appropriately - self.assertEqual(mocked_adjust_combo_box.call_args_list, [ + assert mocked_adjust_combo_box.call_args_list == [ call(1, 20, self.media_item.from_verse), call(1, 20, self.media_item.to_verse, True), - call(5, 25, self.media_item.to_chapter, False)]) + call(5, 25, self.media_item.to_chapter, False)] def test_on_from_chapter_activated_lower_chapter(self): """ @@ -996,8 +995,8 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.on_from_chapter_activated() # THEN: The to_verse and to_chapter comboboxes should be updated appropriately - self.assertEqual(mocked_adjust_combo_box.call_args_list, [ - call(1, 20, self.media_item.from_verse), call(5, 25, self.media_item.to_chapter, True)]) + assert mocked_adjust_combo_box.call_args_list == [ + call(1, 20, self.media_item.from_verse), call(5, 25, self.media_item.to_chapter, True)] def test_on_from_verse(self): """ @@ -1012,7 +1011,7 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.on_from_verse() # THEN: select_book_combo_box.currentData should nto be called - self.assertFalse(self.media_item.select_book_combo_box.currentData.called) + assert self.media_item.select_book_combo_box.currentData.called is False def test_on_from_verse_equal(self): """ @@ -1107,8 +1106,8 @@ class TestMediaItem(TestCase, TestMixin): # THEN: The combo_box should be cleared, and new items added mocked_combo_box.clear.assert_called_once_with() - self.assertEqual(mocked_combo_box.addItem.call_args_list, - [call('10', 10), call('11', 11), call('12', 12), call('13', 13)]) + assert mocked_combo_box.addItem.call_args_list == \ + [call('10', 10), call('11', 11), call('12', 12), call('13', 13)] def test_adjust_combo_box_restore_found(self): """ @@ -1123,8 +1122,8 @@ class TestMediaItem(TestCase, TestMixin): # THEN: The combo_box should be cleared, and new items added. Finally the previously selected item should be # reselected mocked_combo_box.clear.assert_called_once_with() - self.assertEqual(mocked_combo_box.addItem.call_args_list, - [call('10', 10), call('11', 11), call('12', 12), call('13', 13)]) + assert mocked_combo_box.addItem.call_args_list == \ + [call('10', 10), call('11', 11), call('12', 12), call('13', 13)] mocked_combo_box.setCurrentIndex.assert_called_once_with(2) def test_adjust_combo_box_restore_not_found(self): @@ -1140,8 +1139,8 @@ class TestMediaItem(TestCase, TestMixin): # THEN: The combo_box should be cleared, and new items added. Finally the first item should be selected mocked_combo_box.clear.assert_called_once_with() - self.assertEqual(mocked_combo_box.addItem.call_args_list, - [call('10', 10), call('11', 11), call('12', 12), call('13', 13)]) + assert mocked_combo_box.addItem.call_args_list == \ + [call('10', 10), call('11', 11), call('12', 12), call('13', 13)] mocked_combo_box.setCurrentIndex.assert_called_once_with(0) def test_on_search_button_no_bible(self): @@ -1154,7 +1153,7 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.on_search_button_clicked() # THEN: The user should be informed that there are no bibles selected - self.assertEqual(self.mocked_main_window.information_message.call_count, 1) + assert self.mocked_main_window.information_message.call_count == 1 def test_on_search_button_search_tab(self): """ @@ -1207,7 +1206,7 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.select_search() # THEN: reference_search should only be called once - self.assertEqual(self.mocked_plugin.manager.get_verses.call_count, 1) + assert self.mocked_plugin.manager.get_verses.call_count == 1 mocked_display_results.assert_called_once_with() def test_select_search_dual_bibles(self): @@ -1228,7 +1227,7 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.select_search() # THEN: reference_search should be called twice - self.assertEqual(self.mocked_plugin.manager.get_verses.call_count, 2) + assert self.mocked_plugin.manager.get_verses.call_count == 2 mocked_display_results.assert_called_once_with() def test_text_reference_search_single_bible(self): @@ -1244,7 +1243,7 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.text_reference_search('Search Text') # THEN: reference_search should only be called once - self.assertEqual(self.mocked_plugin.manager.get_verses.call_count, 1) + assert self.mocked_plugin.manager.get_verses.call_count == 1 mocked_display_results.assert_called_once_with() def text_reference_search(self, search_text, search_while_type=False): @@ -1272,7 +1271,7 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.text_reference_search('Search Text') # THEN: reference_search should only be called once - self.assertEqual(self.mocked_plugin.manager.get_verses.call_count, 1) + assert self.mocked_plugin.manager.get_verses.call_count == 1 mocked_display_results.assert_called_once_with() def test_text_reference_search_dual_bible(self): @@ -1288,7 +1287,7 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.text_reference_search('Search Text') # THEN: reference_search should be called twice - self.assertEqual(self.mocked_plugin.manager.get_verses.call_count, 2) + assert self.mocked_plugin.manager.get_verses.call_count == 2 mocked_display_results.assert_called_once_with() def test_on_text_search_single_bible(self): @@ -1305,7 +1304,7 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.on_text_search('Search Text') # THEN: The search results should be the same as those returned by plugin.manager.verse_search - self.assertEqual(self.media_item.search_results, ['results', 'list']) + assert self.media_item.search_results == ['results', 'list'] mocked_display_results.assert_called_once_with() def test_on_text_search_no_results(self): @@ -1322,7 +1321,7 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.on_text_search('Search Text') # THEN: The search results should be an empty list - self.assertEqual(self.media_item.search_results, []) + assert self.media_item.search_results == [] mocked_display_results.assert_called_once_with() def test_on_text_search_all_results_in_both_books(self): @@ -1345,10 +1344,10 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.on_text_search('Search Text') # THEN: The search results for both bibles should be returned - self.assertEqual(self.media_item.search_results, [mocked_verse_1, mocked_verse_2]) - self.assertEqual(self.media_item.second_search_results, [mocked_verse_1a, mocked_verse_2a]) - self.assertFalse(self.mocked_log.debug.called) - self.assertFalse(self.mocked_main_window.information_message.called) + assert self.media_item.search_results == [mocked_verse_1, mocked_verse_2] + assert self.media_item.second_search_results == [mocked_verse_1a, mocked_verse_2a] + assert self.mocked_log.debug.called is False + assert self.mocked_main_window.information_message.called is False mocked_display_results.assert_called_once_with() def test_on_text_search_not_all_results_in_both_books(self): @@ -1372,10 +1371,10 @@ class TestMediaItem(TestCase, TestMixin): # THEN: The search results included in both bibles should be returned and the user should be notified of # the missing verses - self.assertEqual(self.media_item.search_results, [mocked_verse_1]) - self.assertEqual(self.media_item.second_search_results, [mocked_verse_1a]) - self.assertEqual(self.mocked_log.debug.call_count, 2) - self.assertTrue(self.mocked_main_window.information_message.called) + assert self.media_item.search_results == [mocked_verse_1] + assert self.media_item.second_search_results == [mocked_verse_1a] + assert self.mocked_log.debug.call_count == 2 + assert self.mocked_main_window.information_message.called is True mocked_display_results.assert_called_once_with() def test_on_search_edit_text_changed_search_while_typing_disabled(self): @@ -1391,7 +1390,7 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.on_search_edit_text_changed() # THEN: The method should not have checked if the timer is active - self.assertFalse(self.media_item.search_timer.isActive.called) + assert self.media_item.search_timer.isActive.called is False def test_on_search_edit_text_changed_search_while_typing_enabled(self): """ @@ -1422,7 +1421,7 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.on_search_timer_timeout() # THEN: The search_status should be set to SearchAsYouType and text_search should have been called - self.assertEqual(self.media_item.search_status, SearchStatus.SearchAsYouType) + assert self.media_item.search_status == SearchStatus.SearchAsYouType mocked_text_search.assert_called_once_with() def test_display_results_no_results(self): @@ -1441,7 +1440,7 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.display_results() # THEN: No items should be added to the list - self.assertFalse(self.media_item.list_view.addItem.called) + assert self.media_item.list_view.addItem.called is False def test_display_results_results(self): """ diff --git a/tests/functional/openlp_plugins/bibles/test_opensongimport.py b/tests/functional/openlp_plugins/bibles/test_opensongimport.py index eab4d33a9..d02fffd5e 100644 --- a/tests/functional/openlp_plugins/bibles/test_opensongimport.py +++ b/tests/functional/openlp_plugins/bibles/test_opensongimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,22 +22,19 @@ """ This module contains tests for the OpenSong Bible importer. """ -import json -import os from unittest import TestCase from unittest.mock import MagicMock, patch, call from lxml import objectify -from openlp.core.common.path import Path from openlp.core.common.registry import Registry -from openlp.plugins.bibles.lib.importers.opensong import OpenSongBible, get_text, parse_chapter_number from openlp.plugins.bibles.lib.bibleimport import BibleImport - +from openlp.plugins.bibles.lib.importers.opensong import OpenSongBible, get_text, parse_chapter_number from tests.helpers.testmixin import TestMixin +from tests.utils import load_external_result_data +from tests.utils.constants import RESOURCE_PATH -TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), - '..', '..', '..', 'resources', 'bibles')) +TEST_PATH = RESOURCE_PATH / 'bibles' class TestOpenSongImport(TestCase, TestMixin): @@ -68,7 +65,7 @@ class TestOpenSongImport(TestCase, TestMixin): importer = OpenSongBible(mocked_manager, path='.', name='.', file_path=None) # THEN: The importer should be an instance of BibleDB - self.assertIsInstance(importer, BibleImport) + assert isinstance(importer, BibleImport) def test_get_text_no_text(self): """ @@ -81,7 +78,7 @@ class TestOpenSongImport(TestCase, TestMixin): result = get_text(test_data) # THEN: A blank string should be returned - self.assertEqual(result, '') + assert result == '' def test_get_text_text(self): """ @@ -98,7 +95,7 @@ class TestOpenSongImport(TestCase, TestMixin): result = get_text(test_data) # THEN: The text returned should be as expected - self.assertEqual(result, 'Element text sub_text_tail text sub_text_tail tail sub_text text sub_tail tail') + assert result == 'Element text sub_text_tail text sub_text_tail tail sub_text text sub_tail tail' def test_parse_chapter_number(self): """ @@ -109,7 +106,7 @@ class TestOpenSongImport(TestCase, TestMixin): result = parse_chapter_number('10', 0) # THEN: The 10 should be returned as an Int - self.assertEqual(result, 10) + assert result == 10 def test_parse_chapter_number_empty_attribute(self): """ @@ -120,7 +117,7 @@ class TestOpenSongImport(TestCase, TestMixin): result = parse_chapter_number('', 12) # THEN: parse_chapter_number should increment the previous verse number - self.assertEqual(result, 13) + assert result == 13 def test_parse_verse_number_valid_verse_no(self): """ @@ -133,7 +130,7 @@ class TestOpenSongImport(TestCase, TestMixin): result = importer.parse_verse_number('15', 0) # THEN: parse_verse_number should return the verse number - self.assertEqual(result, 15) + assert result == 15 def test_parse_verse_number_verse_range(self): """ @@ -146,7 +143,7 @@ class TestOpenSongImport(TestCase, TestMixin): result = importer.parse_verse_number('24-26', 0) # THEN: parse_verse_number should return the first verse number in the range - self.assertEqual(result, 24) + assert result == 24 def test_parse_verse_number_invalid_verse_no(self): """ @@ -159,7 +156,7 @@ class TestOpenSongImport(TestCase, TestMixin): result = importer.parse_verse_number('invalid', 41) # THEN: parse_verse_number should increment the previous verse number - self.assertEqual(result, 42) + assert result == 42 def test_parse_verse_number_empty_attribute(self): """ @@ -171,7 +168,7 @@ class TestOpenSongImport(TestCase, TestMixin): result = importer.parse_verse_number('', 14) # THEN: parse_verse_number should increment the previous verse number - self.assertEqual(result, 15) + assert result == 15 def test_parse_verse_number_invalid_type(self): """ @@ -187,7 +184,7 @@ class TestOpenSongImport(TestCase, TestMixin): # THEN: parse_verse_number should log the verse number it was called with increment the previous verse # number mocked_log_warning.assert_called_once_with('Illegal verse number: (1, 2, 3)') - self.assertEqual(result, 13) + assert result == 13 def test_process_books_stop_import(self): """ @@ -201,7 +198,7 @@ class TestOpenSongImport(TestCase, TestMixin): importer.process_books(['Book']) # THEN: find_and_create_book should not have been called - self.assertFalse(self.mocked_find_and_create_book.called) + assert self.mocked_find_and_create_book.called is False def test_process_books_completes(self): """ @@ -226,11 +223,10 @@ class TestOpenSongImport(TestCase, TestMixin): importer.process_books([book1, book2]) # THEN: find_and_create_book and process_books should be called with the details from the mocked books - self.assertEqual(self.mocked_find_and_create_book.call_args_list, - [call('Name1', 2, 10), call('Name2', 2, 10)]) - self.assertEqual(mocked_process_chapters.call_args_list, - [call('db_book1', 'Chapter1'), call('db_book2', 'Chapter2')]) - self.assertEqual(importer.session.commit.call_count, 2) + assert self.mocked_find_and_create_book.call_args_list == [call('Name1', 2, 10), call('Name2', 2, 10)] + assert mocked_process_chapters.call_args_list == \ + [call('db_book1', 'Chapter1'), call('db_book2', 'Chapter2')] + assert importer.session.commit.call_count == 2 def test_process_chapters_stop_import(self): """ @@ -245,7 +241,7 @@ class TestOpenSongImport(TestCase, TestMixin): importer.process_chapters('Book', ['Chapter1']) # THEN: importer.parse_chapter_number not have been called - self.assertFalse(importer.parse_chapter_number.called) + assert importer.parse_chapter_number.called is False @patch('openlp.plugins.bibles.lib.importers.opensong.parse_chapter_number', **{'side_effect': [1, 2]}) def test_process_chapters_completes(self, mocked_parse_chapter_number): @@ -273,12 +269,11 @@ class TestOpenSongImport(TestCase, TestMixin): importer.process_chapters(book, [chapter1, chapter2]) # THEN: parse_chapter_number, process_verses and increment_process_bar should have been called - self.assertEqual(mocked_parse_chapter_number.call_args_list, [call('1', 0), call('2', 1)]) - self.assertEqual( - importer.process_verses.call_args_list, - [call(book, 1, ['Chapter1 Verses']), call(book, 2, ['Chapter2 Verses'])]) - self.assertEqual(importer.wizard.increment_progress_bar.call_args_list, - [call('Importing Book 1...'), call('Importing Book 2...')]) + assert mocked_parse_chapter_number.call_args_list == [call('1', 0), call('2', 1)] + assert importer.process_verses.call_args_list == \ + [call(book, 1, ['Chapter1 Verses']), call(book, 2, ['Chapter2 Verses'])] + assert importer.wizard.increment_progress_bar.call_args_list == [call('Importing Book 1...'), + call('Importing Book 2...')] def test_process_verses_stop_import(self): """ @@ -293,7 +288,7 @@ class TestOpenSongImport(TestCase, TestMixin): importer.process_verses('Book', 1, 'Verses') # THEN: importer.parse_verse_number not have been called - self.assertFalse(importer.parse_verse_number.called) + assert importer.parse_verse_number.called is False def test_process_verses_completes(self): """ @@ -324,11 +319,10 @@ class TestOpenSongImport(TestCase, TestMixin): importer.process_verses(book, 1, [verse1, verse2]) # THEN: parse_chapter_number, process_verses and increment_process_bar should have been called - self.assertEqual(mocked_parse_verse_number.call_args_list, [call('1', 0), call('2', 1)]) - self.assertEqual(mocked_get_text.call_args_list, [call(verse1), call(verse2)]) - self.assertEqual( - importer.create_verse.call_args_list, - [call(1, 1, 1, 'Verse1 Text'), call(1, 1, 2, 'Verse2 Text')]) + assert mocked_parse_verse_number.call_args_list == [call('1', 0), call('2', 1)] + assert mocked_get_text.call_args_list == [call(verse1), call(verse2)] + assert importer.create_verse.call_args_list == \ + [call(1, 1, 1, 'Verse1 Text'), call(1, 1, 2, 'Verse2 Text')] def test_do_import_parse_xml_fails(self): """ @@ -345,8 +339,8 @@ class TestOpenSongImport(TestCase, TestMixin): result = importer.do_import() # THEN: do_import should return False and get_language_id should have not been called - self.assertFalse(result) - self.assertFalse(mocked_language_id.called) + assert result is False + assert mocked_language_id.called is False def test_do_import_no_language(self): """ @@ -364,8 +358,8 @@ class TestOpenSongImport(TestCase, TestMixin): result = importer.do_import() # THEN: do_import should return False and process_books should have not been called - self.assertFalse(result) - self.assertFalse(mocked_process_books.called) + assert result is False + assert mocked_process_books.called is False def test_do_import_completes(self): """ @@ -383,7 +377,7 @@ class TestOpenSongImport(TestCase, TestMixin): result = importer.do_import() # THEN: do_import should return True - self.assertTrue(result) + assert result is True class TestOpenSongImportFileImports(TestCase, TestMixin): @@ -401,8 +395,7 @@ class TestOpenSongImportFileImports(TestCase, TestMixin): """ # GIVEN: Test files with a mocked out "manager", "import_wizard", and mocked functions # get_book_ref_id_by_name, create_verse, create_book, session and get_language. - result_file = open(os.path.join(TEST_PATH, 'dk1933.json'), 'rb') - test_data = json.loads(result_file.read().decode()) + test_data = load_external_result_data(TEST_PATH / 'dk1933.json') bible_file = 'opensong-dk1933.xml' with patch('openlp.plugins.bibles.lib.importers.opensong.OpenSongBible.application'): mocked_manager = MagicMock() @@ -417,10 +410,10 @@ class TestOpenSongImportFileImports(TestCase, TestMixin): importer.get_language.return_value = 'Danish' # WHEN: Importing bible file - importer.file_path = Path(TEST_PATH, bible_file) + importer.file_path = TEST_PATH / bible_file importer.do_import() # THEN: The create_verse() method should have been called with each verse in the file. - self.assertTrue(importer.create_verse.called) + assert importer.create_verse.called is True for verse_tag, verse_text in test_data['verses']: importer.create_verse.assert_any_call(importer.create_book().id, 1, int(verse_tag), verse_text) diff --git a/tests/functional/openlp_plugins/bibles/test_osisimport.py b/tests/functional/openlp_plugins/bibles/test_osisimport.py index 02c6c3654..93cc7d05d 100644 --- a/tests/functional/openlp_plugins/bibles/test_osisimport.py +++ b/tests/functional/openlp_plugins/bibles/test_osisimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,17 +22,16 @@ """ This module contains tests for the OSIS Bible importer. """ -import os -import json from unittest import TestCase from unittest.mock import MagicMock, call, patch -from openlp.core.common.path import Path from openlp.plugins.bibles.lib.bibleimport import BibleImport from openlp.plugins.bibles.lib.db import BibleDB from openlp.plugins.bibles.lib.importers.osis import OSISBible +from tests.utils import load_external_result_data +from tests.utils.constants import RESOURCE_PATH -TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'bibles')) +TEST_PATH = RESOURCE_PATH / 'bibles' class TestOsisImport(TestCase): @@ -67,7 +66,7 @@ class TestOsisImport(TestCase): importer = OSISBible(mocked_manager, path='.', name='.', file_path=None) # THEN: The importer should be an instance of BibleDB - self.assertIsInstance(importer, BibleDB) + assert isinstance(importer, BibleDB) def test_process_books_stop_import(self): """ @@ -82,7 +81,7 @@ class TestOsisImport(TestCase): importer.process_books(mocked_data) # THEN: find_and_create_book should not have been called - self.assertFalse(self.mocked_find_and_create_book.called) + assert self.mocked_find_and_create_book.called is False def test_process_books_completes(self): """ @@ -106,11 +105,9 @@ class TestOsisImport(TestCase): importer.process_books(mocked_data) # THEN: find_and_create_book and process_books should be called with the details from the mocked books - self.assertEqual(self.mocked_find_and_create_book.call_args_list, - [call('Name1', 2, 10), call('Name2', 2, 10)]) - self.assertEqual(mocked_process_chapters.call_args_list, - [call('db_book1', book1), call('db_book2', book2)]) - self.assertEqual(importer.session.commit.call_count, 2) + assert self.mocked_find_and_create_book.call_args_list == [call('Name1', 2, 10), call('Name2', 2, 10)] + assert mocked_process_chapters.call_args_list == [call('db_book1', book1), call('db_book2', book2)] + assert importer.session.commit.call_count == 2 def test_process_chapters_verse_in_chapter_verse_text(self): """ @@ -185,8 +182,8 @@ class TestOsisImport(TestCase): importer.process_chapters(test_book, [test_chapter]) # THEN: neither set_current_chapter or process_verse should have been called - self.assertFalse(mocked_set_current_chapter.called) - self.assertFalse(mocked_process_verse.called) + assert mocked_set_current_chapter.called is False + assert mocked_process_verse.called is False def test_process_chapters_milestones_chapter_sid(self): """ @@ -209,7 +206,7 @@ class TestOsisImport(TestCase): # THEN: set_current_chapter should have been called with the test data mocked_set_current_chapter.assert_called_once_with(test_book.name, 2) - self.assertFalse(mocked_process_verse.called) + assert mocked_process_verse.called is False def test_process_chapters_milestones_verse_tag(self): """ @@ -233,7 +230,7 @@ class TestOsisImport(TestCase): importer.process_chapters(test_book, [test_verse]) # THEN: process_verse should have been called with the test data - self.assertFalse(mocked_set_current_chapter.called) + assert mocked_set_current_chapter.called is False mocked_process_verse.assert_called_once_with(test_book, 0, test_verse, use_milestones=True) def test_process_verse_no_osis_id(self): @@ -252,7 +249,7 @@ class TestOsisImport(TestCase): importer.process_verse(test_book, 2, test_verse) # THEN: create_verse should not have been called - self.assertFalse(self.mocked_create_verse.called) + assert self.mocked_create_verse.called is False def test_process_verse_use_milestones_no_s_id(self): """ @@ -271,7 +268,7 @@ class TestOsisImport(TestCase): importer.process_verse(test_book, 2, test_verse) # THEN: create_verse should not have been called - self.assertFalse(self.mocked_create_verse.called) + assert self.mocked_create_verse.called is False def test_process_verse_use_milestones_no_tail(self): """ @@ -289,7 +286,7 @@ class TestOsisImport(TestCase): importer.process_verse(test_book, 2, test_verse, use_milestones=True) # THEN: create_verse should not have been called - self.assertFalse(self.mocked_create_verse.called) + assert self.mocked_create_verse.called is False def test_process_verse_use_milestones_success(self): """ @@ -327,7 +324,7 @@ class TestOsisImport(TestCase): importer.process_verse(test_book, 2, test_verse) # THEN: create_verse should not have been called - self.assertFalse(self.mocked_create_verse.called) + assert self.mocked_create_verse.called is False def test_process_verse_success(self): """ @@ -363,8 +360,8 @@ class TestOsisImport(TestCase): result = importer.do_import() # THEN: do_import should return False and get_language_id should have not been called - self.assertFalse(result) - self.assertFalse(mocked_language_id.called) + assert result is False + assert mocked_language_id.called is False def test_do_import_no_language(self): """ @@ -382,8 +379,8 @@ class TestOsisImport(TestCase): result = importer.do_import() # THEN: do_import should return False and process_books should have not been called - self.assertFalse(result) - self.assertFalse(mocked_process_books.called) + assert result is False + assert mocked_process_books.called is False def test_do_import_completes(self): """ @@ -401,7 +398,7 @@ class TestOsisImport(TestCase): result = importer.do_import() # THEN: do_import should return True - self.assertTrue(result) + assert result is True class TestOsisImportFileImports(TestCase): @@ -422,8 +419,7 @@ class TestOsisImportFileImports(TestCase): """ # GIVEN: Test files with a mocked out "manager", "import_wizard", and mocked functions # get_book_ref_id_by_name, create_verse, create_book, session and get_language. - result_file = open(os.path.join(TEST_PATH, 'dk1933.json'), 'rb') - test_data = json.loads(result_file.read().decode()) + test_data = load_external_result_data(TEST_PATH / 'dk1933.json') bible_file = 'osis-dk1933.xml' with patch('openlp.plugins.bibles.lib.importers.osis.OSISBible.application'): mocked_manager = MagicMock() @@ -438,11 +434,11 @@ class TestOsisImportFileImports(TestCase): importer.get_language.return_value = 'Danish' # WHEN: Importing bible file - importer.file_path = Path(TEST_PATH, bible_file) + importer.file_path = TEST_PATH / bible_file importer.do_import() # THEN: The create_verse() method should have been called with each verse in the file. - self.assertTrue(importer.create_verse.called) + assert importer.create_verse.called is True for verse_tag, verse_text in test_data['verses']: importer.create_verse.assert_any_call(importer.create_book().id, 1, verse_tag, verse_text) @@ -452,8 +448,7 @@ class TestOsisImportFileImports(TestCase): """ # GIVEN: Test files with a mocked out "manager", "import_wizard", and mocked functions # get_book_ref_id_by_name, create_verse, create_book, session and get_language. - result_file = open(os.path.join(TEST_PATH, 'kjv.json'), 'rb') - test_data = json.loads(result_file.read().decode()) + test_data = load_external_result_data(TEST_PATH / 'kjv.json') bible_file = 'osis-kjv.xml' with patch('openlp.plugins.bibles.lib.importers.osis.OSISBible.application'): mocked_manager = MagicMock() @@ -468,11 +463,11 @@ class TestOsisImportFileImports(TestCase): importer.get_language.return_value = 'English' # WHEN: Importing bible file - importer.file_path = Path(TEST_PATH, bible_file) + importer.file_path = TEST_PATH / bible_file importer.do_import() # THEN: The create_verse() method should have been called with each verse in the file. - self.assertTrue(importer.create_verse.called) + assert importer.create_verse.called is True for verse_tag, verse_text in test_data['verses']: importer.create_verse.assert_any_call(importer.create_book().id, 1, verse_tag, verse_text) @@ -482,8 +477,7 @@ class TestOsisImportFileImports(TestCase): """ # GIVEN: Test files with a mocked out "manager", "import_wizard", and mocked functions # get_book_ref_id_by_name, create_verse, create_book, session and get_language. - result_file = open(os.path.join(TEST_PATH, 'web.json'), 'rb') - test_data = json.loads(result_file.read().decode()) + test_data = load_external_result_data(TEST_PATH / 'web.json') bible_file = 'osis-web.xml' with patch('openlp.plugins.bibles.lib.importers.osis.OSISBible.application'): mocked_manager = MagicMock() @@ -498,11 +492,11 @@ class TestOsisImportFileImports(TestCase): importer.get_language.return_value = 'English' # WHEN: Importing bible file - importer.file_path = Path(TEST_PATH, bible_file) + importer.file_path = TEST_PATH / bible_file importer.do_import() # THEN: The create_verse() method should have been called with each verse in the file. - self.assertTrue(importer.create_verse.called) + assert importer.create_verse.called for verse_tag, verse_text in test_data['verses']: importer.create_verse.assert_any_call(importer.create_book().id, 1, verse_tag, verse_text) @@ -512,8 +506,7 @@ class TestOsisImportFileImports(TestCase): """ # GIVEN: Test files with a mocked out "manager", "import_wizard", and mocked functions # get_book_ref_id_by_name, create_verse, create_book, session and get_language. - result_file = open(os.path.join(TEST_PATH, 'dk1933.json'), 'rb') - test_data = json.loads(result_file.read().decode()) + test_data = load_external_result_data(TEST_PATH / 'dk1933.json') bible_file = 'osis-dk1933-empty-verse.xml' with patch('openlp.plugins.bibles.lib.importers.osis.OSISBible.application'): mocked_manager = MagicMock() @@ -528,10 +521,10 @@ class TestOsisImportFileImports(TestCase): importer.get_language.return_value = 'Danish' # WHEN: Importing bible file - importer.file_path = Path(TEST_PATH, bible_file) + importer.file_path = TEST_PATH / bible_file importer.do_import() # THEN: The create_verse() method should have been called with each verse in the file. - self.assertTrue(importer.create_verse.called) + assert importer.create_verse.called is True for verse_tag, verse_text in test_data['verses']: importer.create_verse.assert_any_call(importer.create_book().id, 1, verse_tag, verse_text) diff --git a/tests/functional/openlp_plugins/bibles/test_swordimport.py b/tests/functional/openlp_plugins/bibles/test_swordimport.py index 34e011498..aecf5c597 100644 --- a/tests/functional/openlp_plugins/bibles/test_swordimport.py +++ b/tests/functional/openlp_plugins/bibles/test_swordimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,9 +22,6 @@ """ This module contains tests for the SWORD Bible importer. """ - -import os -import json from unittest import TestCase, skipUnless from unittest.mock import MagicMock, patch @@ -36,8 +33,10 @@ except ImportError: from openlp.plugins.bibles.lib.db import BibleDB -TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), - '..', '..', '..', 'resources', 'bibles')) +from tests.utils import load_external_result_data +from tests.utils.constants import RESOURCE_PATH + +TEST_PATH = RESOURCE_PATH / 'bibles' @skipUnless(HAS_PYSWORD, 'pysword not installed') @@ -67,7 +66,7 @@ class TestSwordImport(TestCase): importer = SwordBible(mocked_manager, path='.', name='.', file_path=None, sword_key='', sword_path='') # THEN: The importer should be an instance of BibleDB - self.assertIsInstance(importer, BibleDB) + assert isinstance(importer, BibleDB) @patch('openlp.plugins.bibles.lib.importers.sword.SwordBible.application') @patch('openlp.plugins.bibles.lib.importers.sword.modules') @@ -81,8 +80,7 @@ class TestSwordImport(TestCase): mocked_manager = MagicMock() mocked_import_wizard = MagicMock() importer = SwordBible(mocked_manager, path='.', name='.', file_path=None, sword_key='', sword_path='') - result_file = open(os.path.join(TEST_PATH, 'dk1933.json'), 'rb') - test_data = json.loads(result_file.read().decode()) + test_data = load_external_result_data(TEST_PATH / 'dk1933.json') importer.wizard = mocked_import_wizard importer.get_book_ref_id_by_name = MagicMock() importer.create_verse = MagicMock() @@ -106,6 +104,6 @@ class TestSwordImport(TestCase): importer.do_import() # THEN: The create_verse() method should have been called with each verse in the file. - self.assertTrue(importer.create_verse.called) + assert importer.create_verse.called is True for verse_tag, verse_text in test_data['verses']: importer.create_verse.assert_any_call(importer.create_book().id, 1, int(verse_tag), verse_text) diff --git a/tests/functional/openlp_plugins/bibles/test_versereferencelist.py b/tests/functional/openlp_plugins/bibles/test_versereferencelist.py index b40db5076..b88af89c3 100644 --- a/tests/functional/openlp_plugins/bibles/test_versereferencelist.py +++ b/tests/functional/openlp_plugins/bibles/test_versereferencelist.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -48,14 +48,12 @@ class TestVerseReferenceList(TestCase): reference_list.add(book, chapter, verse, version, copyright_, permission) # THEN: The entries should be in the first entry of the list - self.assertEqual(reference_list.current_index, 0, 'The current index should be 0') - self.assertEqual(reference_list.verse_list[0]['book'], book, 'The book in first entry should be %s' % book) - self.assertEqual(reference_list.verse_list[0]['chapter'], chapter, 'The chapter in first entry should be %u' % - chapter) - self.assertEqual(reference_list.verse_list[0]['start'], verse, 'The start in first entry should be %u' % verse) - self.assertEqual(reference_list.verse_list[0]['version'], version, 'The version in first entry should be %s' % - version) - self.assertEqual(reference_list.verse_list[0]['end'], verse, 'The end in first entry should be %u' % verse) + assert reference_list.current_index == 0, 'The current index should be 0' + assert reference_list.verse_list[0]['book'] == book, 'The book in first entry should be %s' % book + assert reference_list.verse_list[0]['chapter'] == chapter, 'The chapter in first entry should be %u' % chapter + assert reference_list.verse_list[0]['start'] == verse, 'The start in first entry should be %u' % verse + assert reference_list.verse_list[0]['version'] == version, 'The version in first entry should be %s' % version + assert reference_list.verse_list[0]['end'] == verse, 'The end in first entry should be %u' % verse def test_add_next_verse(self): """ @@ -76,9 +74,8 @@ class TestVerseReferenceList(TestCase): reference_list.add(book, chapter, next_verse, version, copyright_, permission) # THEN: The current index should be 0 and the end pointer of the entry should be '2' - self.assertEqual(reference_list.current_index, 0, 'The current index should be 0') - self.assertEqual(reference_list.verse_list[0]['end'], next_verse, - 'The end in first entry should be %u' % next_verse) + assert reference_list.current_index == 0, 'The current index should be 0' + assert reference_list.verse_list[0]['end'] == next_verse, 'The end in first entry should be %u' % next_verse def test_add_another_verse(self): """ @@ -101,7 +98,7 @@ class TestVerseReferenceList(TestCase): reference_list.add(another_book, another_chapter, another_verse, version, copyright_, permission) # THEN: the current index should be 1 - self.assertEqual(reference_list.current_index, 1, 'The current index should be 1') + assert reference_list.current_index == 1, 'The current index should be 1' def test_add_version(self): """ @@ -117,10 +114,10 @@ class TestVerseReferenceList(TestCase): reference_list.add_version(version, copyright_, permission) # THEN: the data will be appended to the list - self.assertEqual(len(reference_list.version_list), 1, 'The version data should be appended') - self.assertEqual(reference_list.version_list[0], - {'version': version, 'copyright': copyright_, 'permission': permission}, - 'The version data should be appended') + assert len(reference_list.version_list) == 1, 'The version data should be appended' + assert reference_list.version_list[0] == \ + {'version': version, 'copyright': copyright_, 'permission': permission}, \ + 'The version data should be appended' def test_add_existing_version(self): """ @@ -137,4 +134,4 @@ class TestVerseReferenceList(TestCase): reference_list.add_version(version, copyright_, permission) # THEN: the data will not be appended to the list - self.assertEqual(len(reference_list.version_list), 1, 'The version data should not be appended') + assert len(reference_list.version_list) == 1, 'The version data should not be appended' diff --git a/tests/functional/openlp_plugins/bibles/test_wordprojectimport.py b/tests/functional/openlp_plugins/bibles/test_wordprojectimport.py index fbf5b0412..388da45f9 100644 --- a/tests/functional/openlp_plugins/bibles/test_wordprojectimport.py +++ b/tests/functional/openlp_plugins/bibles/test_wordprojectimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,18 +22,16 @@ """ This module contains tests for the WordProject Bible importer. """ -import os from unittest import TestCase from unittest.mock import MagicMock, patch, call from openlp.core.common.path import Path from openlp.plugins.bibles.lib.importers.wordproject import WordProjectBible +from tests.utils.constants import RESOURCE_PATH - -TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), - '..', '..', '..', 'resources', 'bibles')) -INDEX_PAGE = open(os.path.join(TEST_PATH, 'wordproject_index.htm')).read() -CHAPTER_PAGE = open(os.path.join(TEST_PATH, 'wordproject_chapter.htm')).read() +TEST_PATH = RESOURCE_PATH / 'bibles' +INDEX_PAGE = (TEST_PATH / 'wordproject_index.htm').read_bytes().decode() +CHAPTER_PAGE = (TEST_PATH / 'wordproject_chapter.htm').read_bytes().decode() class TestWordProjectImport(TestCase): diff --git a/tests/functional/openlp_plugins/bibles/test_zefaniaimport.py b/tests/functional/openlp_plugins/bibles/test_zefaniaimport.py index d423a2153..3252ac152 100644 --- a/tests/functional/openlp_plugins/bibles/test_zefaniaimport.py +++ b/tests/functional/openlp_plugins/bibles/test_zefaniaimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,17 +22,15 @@ """ This module contains tests for the Zefania Bible importer. """ -import os -import json from unittest import TestCase from unittest.mock import MagicMock, patch -from openlp.core.common.path import Path -from openlp.plugins.bibles.lib.importers.zefania import ZefaniaBible from openlp.plugins.bibles.lib.db import BibleDB +from openlp.plugins.bibles.lib.importers.zefania import ZefaniaBible +from tests.utils import load_external_result_data +from tests.utils.constants import RESOURCE_PATH -TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), - '..', '..', '..', 'resources', 'bibles')) +TEST_PATH = RESOURCE_PATH / 'bibles' class TestZefaniaImport(TestCase): @@ -59,7 +57,7 @@ class TestZefaniaImport(TestCase): importer = ZefaniaBible(mocked_manager, path='.', name='.', file_path=None) # THEN: The importer should be an instance of BibleDB - self.assertIsInstance(importer, BibleDB) + assert isinstance(importer, BibleDB) def test_file_import(self): """ @@ -67,8 +65,7 @@ class TestZefaniaImport(TestCase): """ # GIVEN: Test files with a mocked out "manager", "import_wizard", and mocked functions # get_book_ref_id_by_name, create_verse, create_book, session and get_language. - result_file = open(os.path.join(TEST_PATH, 'dk1933.json'), 'rb') - test_data = json.loads(result_file.read().decode()) + test_data = load_external_result_data(TEST_PATH / 'dk1933.json') bible_file = 'zefania-dk1933.xml' with patch('openlp.plugins.bibles.lib.importers.zefania.ZefaniaBible.application'): mocked_manager = MagicMock() @@ -82,11 +79,11 @@ class TestZefaniaImport(TestCase): importer.get_language.return_value = 'Danish' # WHEN: Importing bible file - importer.file_path = Path(TEST_PATH, bible_file) + importer.file_path = TEST_PATH / bible_file importer.do_import() # THEN: The create_verse() method should have been called with each verse in the file. - self.assertTrue(importer.create_verse.called) + assert importer.create_verse.called is True for verse_tag, verse_text in test_data['verses']: importer.create_verse.assert_any_call(importer.create_book().id, 1, verse_tag, verse_text) importer.create_book.assert_any_call('Genesis', 1, 1) @@ -97,8 +94,7 @@ class TestZefaniaImport(TestCase): """ # GIVEN: Test files with a mocked out "manager", "import_wizard", and mocked functions # get_book_ref_id_by_name, create_verse, create_book, session and get_language. - result_file = open(os.path.join(TEST_PATH, 'rst.json'), 'rb') - test_data = json.loads(result_file.read().decode()) + test_data = load_external_result_data(TEST_PATH / 'rst.json') bible_file = 'zefania-rst.xml' with patch('openlp.plugins.bibles.lib.importers.zefania.ZefaniaBible.application'): mocked_manager = MagicMock() @@ -112,11 +108,11 @@ class TestZefaniaImport(TestCase): importer.get_language.return_value = 'Russian' # WHEN: Importing bible file - importer.file_path = Path(TEST_PATH, bible_file) + importer.file_path = TEST_PATH / bible_file importer.do_import() # THEN: The create_verse() method should have been called with each verse in the file. - self.assertTrue(importer.create_verse.called) + assert importer.create_verse.called is True for verse_tag, verse_text in test_data['verses']: importer.create_verse.assert_any_call(importer.create_book().id, 1, verse_tag, verse_text) importer.create_book.assert_any_call('Exodus', 2, 1) diff --git a/tests/functional/openlp_plugins/custom/__init__.py b/tests/functional/openlp_plugins/custom/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/functional/openlp_plugins/custom/__init__.py +++ b/tests/functional/openlp_plugins/custom/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/functional/openlp_plugins/custom/test_mediaitem.py b/tests/functional/openlp_plugins/custom/test_mediaitem.py index d75fa727d..faa091bef 100644 --- a/tests/functional/openlp_plugins/custom/test_mediaitem.py +++ b/tests/functional/openlp_plugins/custom/test_mediaitem.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -30,7 +30,6 @@ from PyQt5 import QtCore from openlp.core.common.registry import Registry from openlp.core.lib import ServiceItem, PluginStatus from openlp.plugins.custom.lib import CustomMediaItem - from tests.helpers.testmixin import TestMixin FOOTER = ['Arky Arky (Unknown)', 'Public Domain', 'CCLI 123456'] @@ -73,7 +72,7 @@ class TestMediaItem(TestCase, TestMixin): item = self.media_item.service_load(service_item) # THEN: the processing should be ignored - self.assertEqual(item, None, 'The Service item is inactive so processing should be bypassed') + assert item is None, 'The Service item is inactive so processing should be bypassed' def test_service_load_basic_custom_false(self): """ @@ -95,8 +94,8 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.service_load(service_item) # THEN: the item should not be added to the database. - self.assertEqual(self.media_item.create_from_service_item.call_count, 0, - 'The item should not have been added to the database') + assert self.media_item.create_from_service_item.call_count == 0, \ + 'The item should not have been added to the database' def test_service_load_basic_custom_true(self): """ @@ -118,5 +117,5 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.service_load(service_item) # THEN: the item should not be added to the database. - self.assertEqual(self.media_item.create_from_service_item.call_count, 1, - 'The item should have been added to the database') + assert self.media_item.create_from_service_item.call_count == 1, \ + 'The item should have been added to the database' diff --git a/tests/functional/openlp_plugins/images/__init__.py b/tests/functional/openlp_plugins/images/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/functional/openlp_plugins/images/__init__.py +++ b/tests/functional/openlp_plugins/images/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/functional/openlp_plugins/images/test_imagetab.py b/tests/functional/openlp_plugins/images/test_imagetab.py index 1000001c2..813be4e88 100644 --- a/tests/functional/openlp_plugins/images/test_imagetab.py +++ b/tests/functional/openlp_plugins/images/test_imagetab.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -30,7 +30,6 @@ from PyQt5 import QtWidgets from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings from openlp.plugins.images.lib import ImageTab - from tests.helpers.testmixin import TestMixin __default_settings__ = { @@ -74,8 +73,8 @@ class TestImageMediaItem(TestCase, TestMixin): # WHEN: the save is invoked self.form.save() # THEN: the post process should not be requested - self.assertEqual(0, self.form.settings_form.register_post_process.call_count, - 'Image Post processing should not have been requested') + assert 0 == self.form.settings_form.register_post_process.call_count, \ + 'Image Post processing should not have been requested' def test_save_tab_change(self): """ @@ -86,7 +85,7 @@ class TestImageMediaItem(TestCase, TestMixin): # WHEN: the save is invoked self.form.save() # THEN: the post process should be requested - self.assertEqual(1, self.form.settings_form.register_post_process.call_count, - 'Image Post processing should have been requested') + assert 1 == self.form.settings_form.register_post_process.call_count, \ + 'Image Post processing should have been requested' # THEN: The color should be set - self.assertEqual(self.form.background_color, '#999999', 'The updated color should have been saved') + assert self.form.background_color == '#999999', 'The updated color should have been saved' diff --git a/tests/functional/openlp_plugins/images/test_lib.py b/tests/functional/openlp_plugins/images/test_lib.py index 877ad722d..76eb20dab 100644 --- a/tests/functional/openlp_plugins/images/test_lib.py +++ b/tests/functional/openlp_plugins/images/test_lib.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -27,8 +27,8 @@ from unittest.mock import ANY, MagicMock, patch from PyQt5 import QtCore, QtWidgets -from openlp.core.common.registry import Registry from openlp.core.common.path import Path +from openlp.core.common.registry import Registry from openlp.plugins.images.lib.db import ImageFilenames, ImageGroups from openlp.plugins.images.lib.mediaitem import ImageMediaItem @@ -98,8 +98,8 @@ class TestImageMediaItem(TestCase): self.media_item.save_new_images_list(image_list) # THEN: The save_object() method should not have been called - self.assertEquals(self.media_item.manager.save_object.call_count, 0, - 'The save_object() method should not have been called') + assert self.media_item.manager.save_object.call_count == 0, \ + 'The save_object() method should not have been called' @patch('openlp.plugins.images.lib.mediaitem.ImageMediaItem.load_full_list') def test_save_new_images_list_single_image_with_reload(self, mocked_load_full_list): @@ -115,7 +115,7 @@ class TestImageMediaItem(TestCase): self.media_item.save_new_images_list(image_list, reload_list=True) # THEN: load_full_list() should have been called - self.assertEquals(mocked_load_full_list.call_count, 1, 'load_full_list() should have been called') + assert mocked_load_full_list.call_count == 1, 'load_full_list() should have been called' # CLEANUP: Remove added attribute from ImageFilenames delattr(ImageFilenames, 'file_path') @@ -133,7 +133,7 @@ class TestImageMediaItem(TestCase): self.media_item.save_new_images_list(image_list, reload_list=False) # THEN: load_full_list() should not have been called - self.assertEquals(mocked_load_full_list.call_count, 0, 'load_full_list() should not have been called') + assert mocked_load_full_list.call_count == 0, 'load_full_list() should not have been called' @patch('openlp.plugins.images.lib.mediaitem.ImageMediaItem.load_full_list') def test_save_new_images_list_multiple_images(self, mocked_load_full_list): @@ -148,8 +148,8 @@ class TestImageMediaItem(TestCase): self.media_item.save_new_images_list(image_list, reload_list=False) # THEN: load_full_list() should not have been called - self.assertEquals(self.media_item.manager.save_object.call_count, 3, - 'load_full_list() should have been called three times') + assert self.media_item.manager.save_object.call_count == 3, \ + 'load_full_list() should have been called three times' @patch('openlp.plugins.images.lib.mediaitem.ImageMediaItem.load_full_list') def test_save_new_images_list_other_objects_in_list(self, mocked_load_full_list): @@ -164,8 +164,7 @@ class TestImageMediaItem(TestCase): self.media_item.save_new_images_list(image_list, reload_list=False) # THEN: load_full_list() should not have been called - self.assertEquals(self.media_item.manager.save_object.call_count, 2, - 'load_full_list() should have been called only once') + assert self.media_item.manager.save_object.call_count == 2, 'load_full_list() should have been called only once' def test_on_reset_click(self): """ @@ -201,9 +200,9 @@ class TestImageMediaItem(TestCase): self.media_item.recursively_delete_group(test_group) # THEN: delete_file() should have been called 12 times and manager.delete_object() 7 times. - self.assertEquals(mocked_delete_file.call_count, 12, 'delete_file() should have been called 12 times') - self.assertEquals(self.media_item.manager.delete_object.call_count, 7, - 'manager.delete_object() should be called exactly 7 times') + assert mocked_delete_file.call_count == 12, 'delete_file() should have been called 12 times' + assert self.media_item.manager.delete_object.call_count == 7, \ + 'manager.delete_object() should be called exactly 7 times' # CLEANUP: Remove added attribute from Image Filenames and ImageGroups delattr(ImageFilenames, 'group_id') @@ -258,7 +257,7 @@ class TestImageMediaItem(TestCase): self.media_item.on_delete_click() # THEN: delete_file should have been called twice - self.assertEquals(mocked_delete_file.call_count, 2, 'delete_file() should have been called twice') + assert mocked_delete_file.call_count == 2, 'delete_file() should have been called twice' def test_create_item_from_id(self): """ @@ -276,9 +275,9 @@ class TestImageMediaItem(TestCase): item = self.media_item.create_item_from_id('1') # THEN: A QTreeWidgetItem should be created with the above model object as it's data - self.assertIsInstance(item, QtWidgets.QTreeWidgetItem) - self.assertEqual('test_file_1.jpg', item.text(0)) + assert isinstance(item, QtWidgets.QTreeWidgetItem) + assert 'test_file_1.jpg' == item.text(0) item_data = item.data(0, QtCore.Qt.UserRole) - self.assertIsInstance(item_data, ImageFilenames) - self.assertEqual(1, item_data.id) - self.assertEqual(Path('/', 'tmp', 'test_file_1.jpg'), item_data.file_path) + assert isinstance(item_data, ImageFilenames) + assert 1 == item_data.id + assert Path('/', 'tmp', 'test_file_1.jpg') == item_data.file_path diff --git a/tests/functional/openlp_plugins/images/test_upgrade.py b/tests/functional/openlp_plugins/images/test_upgrade.py index 471c33609..20c090a2b 100644 --- a/tests/functional/openlp_plugins/images/test_upgrade.py +++ b/tests/functional/openlp_plugins/images/test_upgrade.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -34,7 +34,6 @@ from openlp.core.common.settings import Settings from openlp.core.lib.db import Manager from openlp.plugins.images.lib import upgrade from openlp.plugins.images.lib.db import ImageFilenames, init_schema - from tests.helpers.testmixin import TestMixin from tests.utils.constants import TEST_RESOURCES_PATH @@ -80,6 +79,6 @@ class TestImageDBUpgrade(TestCase, TestMixin): 2: Path('/', 'test', 'dir', 'image2.jpg'), 3: Path('/', 'test', 'dir', 'subdir', 'image3.jpg')} - self.assertEqual(len(upgraded_results), 3) + assert len(upgraded_results) == 3 for result in upgraded_results: - self.assertEqual(expected_result_data[result.id], result.file_path) + assert expected_result_data[result.id] == result.file_path diff --git a/tests/functional/openlp_plugins/media/test_mediaitem.py b/tests/functional/openlp_plugins/media/test_mediaitem.py index 4f753c237..8e1035161 100644 --- a/tests/functional/openlp_plugins/media/test_mediaitem.py +++ b/tests/functional/openlp_plugins/media/test_mediaitem.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -27,10 +27,9 @@ from unittest.mock import MagicMock, patch from PyQt5 import QtCore -from openlp.core.common.settings import Settings from openlp.core.common.path import Path +from openlp.core.common.settings import Settings from openlp.plugins.media.lib.mediaitem import MediaMediaItem - from tests.helpers.testmixin import TestMixin __default_settings__ = { @@ -71,7 +70,7 @@ class MediaItemTest(TestCase, TestMixin): # WHEN: Retrieving the test file result = self.media_item.search('test.mp4', False) # THEN: a file should be found - self.assertEqual(result, [['test.mp4', 'test.mp4']], 'The result file contain the file name') + assert result == [['test.mp4', 'test.mp4']], 'The result file contain the file name' def test_search_not_found(self): """ @@ -82,4 +81,4 @@ class MediaItemTest(TestCase, TestMixin): # WHEN: Retrieving the test file result = self.media_item.search('test.mpx', False) # THEN: a file should be found - self.assertEqual(result, [], 'The result file should be empty') + assert result == [], 'The result file should be empty' diff --git a/tests/functional/openlp_plugins/media/test_mediaplugin.py b/tests/functional/openlp_plugins/media/test_mediaplugin.py index 3ab5b3034..4af0a9603 100644 --- a/tests/functional/openlp_plugins/media/test_mediaplugin.py +++ b/tests/functional/openlp_plugins/media/test_mediaplugin.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -27,7 +27,6 @@ from unittest.mock import patch from openlp.core.common.registry import Registry from openlp.plugins.media.mediaplugin import MediaPlugin, process_check_binary - from tests.helpers.testmixin import TestMixin @@ -56,9 +55,9 @@ class MediaPluginTest(TestCase, TestMixin): # GIVEN: The MediaPlugin # WHEN: Retrieving the about text # THEN: about() should return a string object - self.assertIsInstance(MediaPlugin.about(), str) + assert isinstance(MediaPlugin.about(), str) # THEN: about() should return a non-empty string - self.assertNotEquals(len(MediaPlugin.about()), 0) + assert len(MediaPlugin.about()) is not 0 @patch('openlp.plugins.media.mediaplugin.check_binary_exists') def test_process_check_binary_pass(self, mocked_checked_binary_exists): @@ -71,7 +70,7 @@ class MediaPluginTest(TestCase, TestMixin): result = process_check_binary('MediaInfo') # THEN: The the result should be True - self.assertTrue(result, 'Mediainfo should have been found') + assert result is True, 'Mediainfo should have been found' @patch('openlp.plugins.media.mediaplugin.check_binary_exists') def test_process_check_binary_fail(self, mocked_checked_binary_exists): @@ -84,4 +83,4 @@ class MediaPluginTest(TestCase, TestMixin): result = process_check_binary("MediaInfo1") # THEN: The the result should be True - self.assertFalse(result, "Mediainfo should not have been found") + assert result is False, "Mediainfo should not have been found" diff --git a/tests/functional/openlp_plugins/presentations/__init__.py b/tests/functional/openlp_plugins/presentations/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/functional/openlp_plugins/presentations/__init__.py +++ b/tests/functional/openlp_plugins/presentations/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/functional/openlp_plugins/presentations/test_impresscontroller.py b/tests/functional/openlp_plugins/presentations/test_impresscontroller.py index f08e0b8ac..d3a911cec 100644 --- a/tests/functional/openlp_plugins/presentations/test_impresscontroller.py +++ b/tests/functional/openlp_plugins/presentations/test_impresscontroller.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,17 +22,17 @@ """ Functional tests to test the Impress class and related methods. """ -from unittest import TestCase -from unittest.mock import MagicMock import shutil from tempfile import mkdtemp +from unittest import TestCase +from unittest.mock import MagicMock, patch -from openlp.core.common.settings import Settings from openlp.core.common.path import Path +from openlp.core.common.settings import Settings from openlp.plugins.presentations.lib.impresscontroller import ImpressController, ImpressDocument, TextType from openlp.plugins.presentations.presentationplugin import __default_settings__ -from tests.utils.constants import TEST_RESOURCES_PATH +from tests.utils.constants import RESOURCE_PATH from tests.helpers.testmixin import TestMixin @@ -69,8 +69,61 @@ class TestImpressController(TestCase, TestMixin): controller = ImpressController(plugin=self.mock_plugin) # THEN: The name of the presentation controller should be correct - self.assertEqual('Impress', controller.name, - 'The name of the presentation controller should be correct') + assert 'Impress' == controller.name, 'The name of the presentation controller should be correct' + + @patch('openlp.plugins.presentations.lib.impresscontroller.log') + def test_check_available(self, mocked_log): + """ + Test `ImpressController.check_available` on Windows + """ + # GIVEN: An instance of :class:`ImpressController` + controller = ImpressController(plugin=self.mock_plugin) + + # WHEN: `check_available` is called on Windows and `get_com_servicemanager` returns None + with patch('openlp.plugins.presentations.lib.impresscontroller.is_win', return_value=True), \ + patch.object(controller, 'get_com_servicemanager', return_value=None) as mocked_get_com_servicemanager: + result = controller.check_available() + + # THEN: `check_available` should return False + assert mocked_get_com_servicemanager.called is True + assert result is False + + @patch('openlp.plugins.presentations.lib.impresscontroller.log') + def test_check_available1(self, mocked_log): + """ + Test `ImpressController.check_available` on Windows + """ + # GIVEN: An instance of :class:`ImpressController` + controller = ImpressController(plugin=self.mock_plugin) + + # WHEN: `check_available` is called on Windows and `get_com_servicemanager` returns an object + mocked_com_object = MagicMock() + with patch('openlp.plugins.presentations.lib.impresscontroller.is_win', return_value=True), \ + patch.object(controller, 'get_com_servicemanager', return_value=mocked_com_object) \ + as mocked_get_com_servicemanager: + result = controller.check_available() + + # THEN: `check_available` should return True + assert mocked_get_com_servicemanager.called is True + assert result is True + + @patch('openlp.plugins.presentations.lib.impresscontroller.log') + @patch('openlp.plugins.presentations.lib.impresscontroller.is_win', return_value=False) + def test_check_available2(self, mocked_is_win, mocked_log): + """ + Test `ImpressController.check_available` when not on Windows + """ + # GIVEN: An instance of :class:`ImpressController` + controller = ImpressController(plugin=self.mock_plugin) + + # WHEN: `check_available` is called on Windows and `uno_available` is True + with patch('openlp.plugins.presentations.lib.impresscontroller.uno_available', True), \ + patch.object(controller, 'get_com_servicemanager') as mocked_get_com_servicemanager: + result = controller.check_available() + + # THEN: `check_available` should return True + assert mocked_get_com_servicemanager.called is False + assert result is True class TestImpressDocument(TestCase): @@ -81,7 +134,7 @@ class TestImpressDocument(TestCase): mocked_plugin = MagicMock() mocked_plugin.settings_section = 'presentations' Settings().extend_default_settings(__default_settings__) - self.file_name = Path(TEST_RESOURCES_PATH, 'presentations', 'test.pptx') + self.file_name = RESOURCE_PATH / 'presentations' / 'test.pptx' self.ppc = ImpressController(mocked_plugin) self.doc = ImpressDocument(self.ppc, self.file_name) @@ -125,22 +178,21 @@ class TestImpressDocument(TestCase): result = self.doc._ImpressDocument__get_text_from_page(0, TextType.Notes) # THEN: the result should be an empty string - self.assertEqual(result, '', 'Result should be an empty string') + assert result == '', 'Result should be an empty string' # WHEN: regardless of the type of text, index 0x00 is out of bounds result = self.doc._ImpressDocument__get_text_from_page(0, TextType.Title) # THEN: result should be an empty string - self.assertEqual(result, '', 'Result should be an empty string') + assert result == '', 'Result should be an empty string' # WHEN: when called with 2, it should also be out of bounds result = self.doc._ImpressDocument__get_text_from_page(2, TextType.SlideText) # THEN: result should be an empty string ... and, getByIndex should # have never been called - self.assertEqual(result, '', 'Result should be an empty string') - self.assertEqual(self.doc.document.getDrawPages().getByIndex.call_count, 0, - 'There should be no call to getByIndex') + assert result == '', 'Result should be an empty string' + assert self.doc.document.getDrawPages().getByIndex.call_count == 0, 'There should be no call to getByIndex' def test_get_text_from_page_wrong_type(self): """ @@ -154,9 +206,8 @@ class TestImpressDocument(TestCase): result = self.doc._ImpressDocument__get_text_from_page(1, 3) # THEN: result should be an empty string - self.assertEqual(result, '', 'Result should be and empty string') - self.assertEqual(self.doc.document.getDrawPages().getByIndex.call_count, 0, - 'There should be no call to getByIndex') + assert result == '', 'Result should be and empty string' + assert self.doc.document.getDrawPages().getByIndex.call_count == 0, 'There should be no call to getByIndex' def test_get_text_from_page_valid_params(self): """ @@ -170,19 +221,19 @@ class TestImpressDocument(TestCase): result = self.doc._ImpressDocument__get_text_from_page(1, TextType.Notes) # THEN: result should be 'Note\nNote\n' - self.assertEqual(result, 'Note\nNote\n', 'Result should be \'Note\\n\' times the count of notes in the page') + assert result == 'Note\nNote\n', 'Result should be \'Note\\n\' times the count of notes in the page' # WHEN: get the Title result = self.doc._ImpressDocument__get_text_from_page(1, TextType.Title) # THEN: result should be 'Title\n' - self.assertEqual(result, 'Title\n', 'Result should be exactly \'Title\\n\'') + assert result == 'Title\n', 'Result should be exactly \'Title\\n\'' # WHEN: get all text result = self.doc._ImpressDocument__get_text_from_page(1, TextType.SlideText) # THEN: result should be 'Title\nString\nString\n' - self.assertEqual(result, 'Title\nString\nString\n', 'Result should be exactly \'Title\\nString\\nString\\n\'') + assert result == 'Title\nString\nString\n', 'Result should be exactly \'Title\\nString\\nString\\n\'' def _mock_a_LibreOffice_document(self, page_count, note_count, text_count): """ diff --git a/tests/functional/openlp_plugins/presentations/test_mediaitem.py b/tests/functional/openlp_plugins/presentations/test_mediaitem.py index fd28b9b03..f8375be2c 100644 --- a/tests/functional/openlp_plugins/presentations/test_mediaitem.py +++ b/tests/functional/openlp_plugins/presentations/test_mediaitem.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -25,10 +25,9 @@ This module contains tests for the lib submodule of the Presentations plugin. from unittest import TestCase from unittest.mock import patch, MagicMock, call -from openlp.core.common.registry import Registry from openlp.core.common.path import Path +from openlp.core.common.registry import Registry from openlp.plugins.presentations.lib.mediaitem import PresentationMediaItem - from tests.helpers.testmixin import TestMixin @@ -81,11 +80,11 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.build_file_mask_string() # THEN: The file mask should be generated correctly - self.assertIn('*.odp', self.media_item.on_new_file_masks, 'The file mask should contain the odp extension') - self.assertIn('*.ppt', self.media_item.on_new_file_masks, 'The file mask should contain the ppt extension') - self.assertIn('*.pdf', self.media_item.on_new_file_masks, 'The file mask should contain the pdf extension') - self.assertIn('*.xps', self.media_item.on_new_file_masks, 'The file mask should contain the xps extension') - self.assertIn('*.oxps', self.media_item.on_new_file_masks, 'The file mask should contain the oxps extension') + assert '*.odp' in self.media_item.on_new_file_masks, 'The file mask should contain the odp extension' + assert '*.ppt' in self.media_item.on_new_file_masks, 'The file mask should contain the ppt extension' + assert '*.pdf' in self.media_item.on_new_file_masks, 'The file mask should contain the pdf extension' + assert '*.xps' in self.media_item.on_new_file_masks, 'The file mask should contain the xps extension' + assert '*.oxps' in self.media_item.on_new_file_masks, 'The file mask should contain the oxps extension' def test_clean_up_thumbnails(self): """ diff --git a/tests/functional/openlp_plugins/presentations/test_messagelistener.py b/tests/functional/openlp_plugins/presentations/test_messagelistener.py index e38eeaf90..051f1e1a4 100644 --- a/tests/functional/openlp_plugins/presentations/test_messagelistener.py +++ b/tests/functional/openlp_plugins/presentations/test_messagelistener.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -28,7 +28,6 @@ from unittest.mock import patch, MagicMock from openlp.core.common.registry import Registry from openlp.plugins.presentations.lib.mediaitem import MessageListener, PresentationMediaItem from openlp.plugins.presentations.lib.messagelistener import Controller - from tests.helpers.testmixin import TestMixin @@ -73,7 +72,7 @@ class TestMessageListener(TestCase, TestMixin): ml.startup([mock_item, False, False, False]) # THEN: The controllers will be setup. - self.assertTrue(len(controllers), 'We have loaded a controller') + assert len(controllers) > 0, 'We have loaded a controller' @patch('openlp.plugins.presentations.lib.mediaitem.MessageListener._setup') def test_start_presentation_with_no_player(self, media_mock): @@ -105,7 +104,7 @@ class TestMessageListener(TestCase, TestMixin): ml.startup([mock_item, False, False, False]) # THEN: The controllers will be setup. - self.assertTrue(len(controllers), 'We have loaded a controller') + assert len(controllers) > 0, 'We have loaded a controller' @patch('openlp.plugins.presentations.lib.mediaitem.MessageListener._setup') def test_start_pdf_presentation(self, media_mock): @@ -125,7 +124,7 @@ class TestMessageListener(TestCase, TestMixin): ml.startup([mock_item, False, False, False]) # THEN: The handler should be set to None - self.assertIsNone(ml.handler, 'The handler should be None') + assert ml.handler is None, 'The handler should be None' class TestController(TestCase, TestMixin): @@ -148,4 +147,4 @@ class TestController(TestCase, TestMixin): controller.add_handler(mocked_doc_controller, MagicMock(), True, 0) # THEN: slidenumber should be 0 - self.assertEqual(controller.doc.slidenumber, 0, 'doc.slidenumber should be 0') + assert controller.doc.slidenumber == 0, 'doc.slidenumber should be 0' diff --git a/tests/functional/openlp_plugins/presentations/test_pdfcontroller.py b/tests/functional/openlp_plugins/presentations/test_pdfcontroller.py index 9bd492983..80f84f9fa 100644 --- a/tests/functional/openlp_plugins/presentations/test_pdfcontroller.py +++ b/tests/functional/openlp_plugins/presentations/test_pdfcontroller.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -23,19 +23,18 @@ This module contains tests for the PdfController """ import os -import shutil from tempfile import mkdtemp from unittest import TestCase, SkipTest from unittest.mock import MagicMock, patch from PyQt5 import QtCore, QtGui -from openlp.plugins.presentations.lib.pdfcontroller import PdfController, PdfDocument -from openlp.core.common.settings import Settings from openlp.core.common.path import Path +from openlp.core.common.settings import Settings from openlp.core.display.screens import ScreenList +from openlp.plugins.presentations.lib.pdfcontroller import PdfController, PdfDocument -from tests.utils.constants import TEST_RESOURCES_PATH +from tests.utils.constants import RESOURCE_PATH from tests.helpers.testmixin import TestMixin __default_settings__ = { @@ -92,14 +91,14 @@ class TestPdfController(TestCase, TestMixin): controller = PdfController(plugin=self.mock_plugin) # THEN: The name of the presentation controller should be correct - self.assertEqual('Pdf', controller.name, 'The name of the presentation controller should be correct') + assert 'Pdf' == controller.name, 'The name of the presentation controller should be correct' def test_load_pdf(self): """ Test loading of a Pdf using the PdfController """ # GIVEN: A Pdf-file - test_file = Path(TEST_RESOURCES_PATH, 'presentations', 'pdf_test1.pdf') + test_file_path = RESOURCE_PATH / 'presentations' / 'pdf_test1.pdf' # WHEN: The Pdf is loaded controller = PdfController(plugin=self.mock_plugin) @@ -107,19 +106,19 @@ class TestPdfController(TestCase, TestMixin): raise SkipTest('Could not detect mudraw or ghostscript, so skipping PDF test') controller.temp_folder = self.temp_folder_path controller.thumbnail_folder = self.thumbnail_folder_path - document = PdfDocument(controller, test_file) + document = PdfDocument(controller, test_file_path) loaded = document.load_presentation() # THEN: The load should succeed and we should be able to get a pagecount - self.assertTrue(loaded, 'The loading of the PDF should succeed.') - self.assertEqual(3, document.get_slide_count(), 'The pagecount of the PDF should be 3.') + assert loaded is True, 'The loading of the PDF should succeed.' + assert 3 == document.get_slide_count(), 'The pagecount of the PDF should be 3.' def test_load_pdf_pictures(self): """ Test loading of a Pdf and check size of generate pictures """ # GIVEN: A Pdf-file - test_file = Path(TEST_RESOURCES_PATH, 'presentations', 'pdf_test1.pdf') + test_file_path = RESOURCE_PATH / 'presentations' / 'pdf_test1.pdf' # WHEN: The Pdf is loaded controller = PdfController(plugin=self.mock_plugin) @@ -127,19 +126,19 @@ class TestPdfController(TestCase, TestMixin): raise SkipTest('Could not detect mudraw or ghostscript, so skipping PDF test') controller.temp_folder = self.temp_folder_path controller.thumbnail_folder = self.thumbnail_folder_path - document = PdfDocument(controller, test_file) + document = PdfDocument(controller, test_file_path) loaded = document.load_presentation() # THEN: The load should succeed and pictures should be created and have been scales to fit the screen - self.assertTrue(loaded, 'The loading of the PDF should succeed.') + assert loaded is True, 'The loading of the PDF should succeed.' image = QtGui.QImage(os.path.join(str(self.temp_folder_path), 'pdf_test1.pdf', 'mainslide001.png')) # Based on the converter used the resolution will differ a bit if controller.gsbin: - self.assertEqual(760, image.height(), 'The height should be 760') - self.assertEqual(537, image.width(), 'The width should be 537') + assert 760 == image.height(), 'The height should be 760' + assert 537 == image.width(), 'The width should be 537' else: - self.assertEqual(768, image.height(), 'The height should be 768') - self.assertEqual(543, image.width(), 'The width should be 543') + assert 768 == image.height(), 'The height should be 768' + assert 543 == image.width(), 'The width should be 543' @patch('openlp.plugins.presentations.lib.pdfcontroller.check_binary_exists') def test_process_check_binary_mudraw(self, mocked_check_binary_exists): @@ -157,7 +156,7 @@ class TestPdfController(TestCase, TestMixin): ret = PdfController.process_check_binary('test') # THEN: mudraw should be detected - self.assertEqual('mudraw', ret, 'mudraw should have been detected') + assert 'mudraw' == ret, 'mudraw should have been detected' @patch('openlp.plugins.presentations.lib.pdfcontroller.check_binary_exists') def test_process_check_binary_new_motool(self, mocked_check_binary_exists): @@ -177,7 +176,7 @@ class TestPdfController(TestCase, TestMixin): ret = PdfController.process_check_binary('test') # THEN: mutool should be detected - self.assertEqual('mutool', ret, 'mutool should have been detected') + assert 'mutool' == ret, 'mutool should have been detected' @patch('openlp.plugins.presentations.lib.pdfcontroller.check_binary_exists') def test_process_check_binary_old_motool(self, mocked_check_binary_exists): @@ -194,7 +193,7 @@ class TestPdfController(TestCase, TestMixin): ret = PdfController.process_check_binary('test') # THEN: mutool should be detected - self.assertIsNone(ret, 'old mutool should not be accepted!') + assert ret is None, 'old mutool should not be accepted!' @patch('openlp.plugins.presentations.lib.pdfcontroller.check_binary_exists') def test_process_check_binary_gs(self, mocked_check_binary_exists): @@ -210,4 +209,4 @@ class TestPdfController(TestCase, TestMixin): ret = PdfController.process_check_binary('test') # THEN: mutool should be detected - self.assertEqual('gs', ret, 'mutool should have been detected') + assert 'gs' == ret, 'mutool should have been detected' diff --git a/tests/functional/openlp_plugins/presentations/test_powerpointcontroller.py b/tests/functional/openlp_plugins/presentations/test_powerpointcontroller.py index 5bab87b6a..3ebe0ede8 100644 --- a/tests/functional/openlp_plugins/presentations/test_powerpointcontroller.py +++ b/tests/functional/openlp_plugins/presentations/test_powerpointcontroller.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -24,15 +24,14 @@ Functional tests to test the PowerPointController class and related methods. """ import os import shutil +from tempfile import mkdtemp from unittest import TestCase from unittest.mock import patch, MagicMock -from tempfile import mkdtemp from openlp.core.common import is_win from openlp.core.common.settings import Settings from openlp.plugins.presentations.lib.powerpointcontroller import PowerpointController, PowerpointDocument, \ _get_text_from_shapes - from tests.helpers.testmixin import TestMixin from tests.utils.constants import TEST_RESOURCES_PATH @@ -77,8 +76,7 @@ class TestPowerpointController(TestCase, TestMixin): controller = PowerpointController(plugin=self.mock_plugin) # THEN: The name of the presentation controller should be correct - self.assertEqual('Powerpoint', controller.name, - 'The name of the presentation controller should be correct') + assert 'Powerpoint' == controller.name, 'The name of the presentation controller should be correct' class TestPowerpointDocument(TestCase, TestMixin): @@ -157,7 +155,7 @@ class TestPowerpointDocument(TestCase, TestMixin): result = doc.is_loaded() # THEN: result should be true - self.assertEqual(result, True, 'The result should be True') + assert result is True, 'The result should be True' else: self.skipTest('Powerpoint not available, skipping test.') @@ -217,7 +215,7 @@ class TestPowerpointDocument(TestCase, TestMixin): result = _get_text_from_shapes(shapes) # THEN: it should return the text - self.assertEqual(result, 'slideText\nslideText\n', 'result should match \'slideText\nslideText\n\'') + assert result == 'slideText\nslideText\n', 'result should match \'slideText\nslideText\n\'' def test_get_text_from_shapes_with_no_shapes(self): """ @@ -230,7 +228,7 @@ class TestPowerpointDocument(TestCase, TestMixin): result = _get_text_from_shapes(shapes) # THEN: it should not fail but return empty string - self.assertEqual(result, '', 'result should be empty') + assert result == '', 'result should be empty' def test_goto_slide(self): """ @@ -250,7 +248,7 @@ class TestPowerpointDocument(TestCase, TestMixin): doc.goto_slide(1) # THEN: next_step() should be call to try to advance to the next effect. - self.assertTrue(doc.next_step.called, 'next_step() should have been called!') + assert doc.next_step.called is True, 'next_step() should have been called!' def test_blank_screen(self): """ @@ -268,9 +266,9 @@ class TestPowerpointDocument(TestCase, TestMixin): doc.blank_screen() # THEN: The view state, doc.blank_slide and doc.blank_click should have new values - self.assertEquals(doc.presentation.SlideShowWindow.View.State, 3, 'The View State should be 3') - self.assertEquals(doc.blank_slide, 2, 'doc.blank_slide should be 2 because of the PowerPoint version') - self.assertEquals(doc.blank_click, 3, 'doc.blank_click should be 3 because of the PowerPoint version') + assert doc.presentation.SlideShowWindow.View.State == 3, 'The View State should be 3' + assert doc.blank_slide == 2, 'doc.blank_slide should be 2 because of the PowerPoint version' + assert doc.blank_click == 3, 'doc.blank_click should be 3 because of the PowerPoint version' def test_unblank_screen(self): """ @@ -295,10 +293,10 @@ class TestPowerpointDocument(TestCase, TestMixin): doc.unblank_screen() # THEN: The view state have new value, and several function should have been called - self.assertEquals(doc.presentation.SlideShowWindow.View.State, 1, 'The View State should be 1') - self.assertEquals(doc.presentation.SlideShowWindow.Activate.called, True, - 'SlideShowWindow.Activate should have been called') - self.assertEquals(doc.presentation.SlideShowWindow.View.GotoSlide.called, True, - 'View.GotoSlide should have been called because of the PowerPoint version') - self.assertEquals(doc.presentation.SlideShowWindow.View.GotoClick.called, True, - 'View.GotoClick should have been called because of the PowerPoint version') + assert doc.presentation.SlideShowWindow.View.State == 1, 'The View State should be 1' + assert doc.presentation.SlideShowWindow.Activate.called is True, \ + 'SlideShowWindow.Activate should have been called' + assert doc.presentation.SlideShowWindow.View.GotoSlide.called is True, \ + 'View.GotoSlide should have been called because of the PowerPoint version' + assert doc.presentation.SlideShowWindow.View.GotoClick.called is True, \ + 'View.GotoClick should have been called because of the PowerPoint version' diff --git a/tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py b/tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py index 1245be274..5e6a7abdd 100644 --- a/tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py +++ b/tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -27,12 +27,11 @@ from tempfile import mkdtemp from unittest import TestCase, skipIf from unittest.mock import MagicMock, patch -from openlp.plugins.presentations.lib.pptviewcontroller import PptviewDocument, PptviewController from openlp.core.common import is_win from openlp.core.common.path import Path - +from openlp.plugins.presentations.lib.pptviewcontroller import PptviewDocument, PptviewController from tests.helpers.testmixin import TestMixin -from tests.utils.constants import TEST_RESOURCES_PATH +from tests.utils.constants import RESOURCE_PATH class TestPptviewController(TestCase, TestMixin): @@ -67,8 +66,7 @@ class TestPptviewController(TestCase, TestMixin): controller = PptviewController(plugin=self.mock_plugin) # THEN: The name of the presentation controller should be correct - self.assertEqual('Powerpoint Viewer', controller.name, - 'The name of the presentation controller should be correct') + assert 'Powerpoint Viewer' == controller.name, 'The name of the presentation controller should be correct' def test_check_available(self): """ @@ -86,9 +84,9 @@ class TestPptviewController(TestCase, TestMixin): # THEN: On windows it should return True, on other platforms False if is_win(): - self.assertTrue(available, 'check_available should return True on windows.') + assert available is True, 'check_available should return True on windows.' else: - self.assertFalse(available, 'check_available should return False when not on windows.') + assert available is False, 'check_available should return False when not on windows.' class TestPptviewDocument(TestCase): @@ -165,7 +163,7 @@ class TestPptviewDocument(TestCase): result = instance.load_presentation() # THEN: The temp folder should be created and PptviewDocument.load_presentation should return False - self.assertFalse(result) + assert result is False def test_create_titles_and_notes(self): """ @@ -173,7 +171,7 @@ class TestPptviewDocument(TestCase): """ # GIVEN: mocked PresentationController.save_titles_and_notes and a pptx file doc = PptviewDocument(self.mock_controller, self.mock_presentation) - doc.file_path = Path(TEST_RESOURCES_PATH, 'presentations', 'test.pptx') + doc.file_path = RESOURCE_PATH / 'presentations' / 'test.pptx' doc.save_titles_and_notes = MagicMock() # WHEN reading the titles and notes @@ -205,7 +203,7 @@ class TestPptviewDocument(TestCase): # THEN: File existens should have been checked, and not have been opened. doc.save_titles_and_notes.assert_called_once_with(None, None) mocked_path_exists.assert_called_with() - self.assertEqual(mocked_open.call_count, 0, 'There should be no calls to open a file.') + assert mocked_open.call_count == 0, 'There should be no calls to open a file.' def test_create_titles_and_notes_invalid_file(self): """ @@ -217,7 +215,7 @@ class TestPptviewDocument(TestCase): mocked_is_zf.return_value = False mocked_open.filesize = 10 doc = PptviewDocument(self.mock_controller, self.mock_presentation) - doc.file_path = Path(TEST_RESOURCES_PATH, 'presentations', 'test.ppt') + doc.file_path = RESOURCE_PATH / 'presentations' / 'test.ppt' doc.save_titles_and_notes = MagicMock() # WHEN: reading the titles and notes @@ -225,4 +223,4 @@ class TestPptviewDocument(TestCase): # THEN: doc.save_titles_and_notes.assert_called_once_with(None, None) - self.assertEqual(mocked_is_zf.call_count, 1, 'is_zipfile should have been called once') + assert mocked_is_zf.call_count == 1, 'is_zipfile should have been called once' diff --git a/tests/functional/openlp_plugins/presentations/test_presentationcontroller.py b/tests/functional/openlp_plugins/presentations/test_presentationcontroller.py index a921ef81e..4383122e8 100644 --- a/tests/functional/openlp_plugins/presentations/test_presentationcontroller.py +++ b/tests/functional/openlp_plugins/presentations/test_presentationcontroller.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -58,8 +58,8 @@ class TestPresentationController(TestCase): # WHEN: The PresentationController is created # THEN: The name of the presentation controller should be correct - self.assertEqual('PresentationController', self.presentation.name, - 'The name of the presentation controller should be correct') + assert 'PresentationController' == self.presentation.name, \ + 'The name of the presentation controller should be correct' def test_save_titles_and_notes(self): """ @@ -76,7 +76,7 @@ class TestPresentationController(TestCase): self.document.save_titles_and_notes(titles, notes) # THEN: the last call to open should have been for slideNotes2.txt - self.assertEqual(mocked_write_text.call_count, 3, 'There should be exactly three files written') + assert mocked_write_text.call_count == 3, 'There should be exactly three files written' mocked_write_text.assert_has_calls([call('uno\ndos'), call('one'), call('two')]) def test_save_titles_and_notes_with_None(self): @@ -93,7 +93,7 @@ class TestPresentationController(TestCase): self.document.save_titles_and_notes(titles, notes) # THEN: No file should have been created - self.assertEqual(mocked_open.call_count, 0, 'No file should be created') + assert mocked_open.call_count == 0, 'No file should be created' def test_get_titles_and_notes(self): """ @@ -112,11 +112,11 @@ class TestPresentationController(TestCase): result_titles, result_notes = self.document.get_titles_and_notes() # THEN: it should return two items for the titles and two empty strings for the notes - self.assertIs(type(result_titles), list, 'result_titles should be of type list') - self.assertEqual(len(result_titles), 2, 'There should be two items in the titles') - self.assertIs(type(result_notes), list, 'result_notes should be of type list') - self.assertEqual(len(result_notes), 2, 'There should be two items in the notes') - self.assertEqual(mocked_read_text.call_count, 3, 'Three files should be read') + assert type(result_titles) is list, 'result_titles should be of type list' + assert len(result_titles) == 2, 'There should be two items in the titles' + assert type(result_notes) is list, 'result_notes should be of type list' + assert len(result_notes) == 2, 'There should be two items in the notes' + assert mocked_read_text.call_count == 3, 'Three files should be read' def test_get_titles_and_notes_with_file_not_found(self): """ @@ -132,10 +132,10 @@ class TestPresentationController(TestCase): result_titles, result_notes = self.document.get_titles_and_notes() # THEN: it should return two empty lists - self.assertIsInstance(result_titles, list, 'result_titles should be of type list') - self.assertEqual(len(result_titles), 0, 'there be no titles') - self.assertIsInstance(result_notes, list, 'result_notes should be a list') - self.assertEqual(len(result_notes), 0, 'but the list should be empty') + assert isinstance(result_titles, list), 'result_titles should be of type list' + assert len(result_titles) == 0, 'there be no titles' + assert isinstance(result_notes, list), 'result_notes should be a list' + assert len(result_notes) == 0, 'but the list should be empty' def test_get_titles_and_notes_with_file_error(self): """ @@ -151,7 +151,7 @@ class TestPresentationController(TestCase): result_titles, result_notes = self.document.get_titles_and_notes() # THEN: it should return two empty lists - self.assertIs(type(result_titles), list, 'result_titles should be a list') + assert type(result_titles) is list, 'result_titles should be a list' class TestPresentationDocument(TestCase): @@ -226,4 +226,4 @@ class TestPresentationDocument(TestCase): result = instance.load_presentation() # THEN: load_presentation should return false - self.assertFalse(result, "PresentationDocument.load_presentation should return false.") + assert result is False, "PresentationDocument.load_presentation should return false." diff --git a/tests/functional/openlp_plugins/songs/__init__.py b/tests/functional/openlp_plugins/songs/__init__.py index 8e4693e5e..f66326757 100644 --- a/tests/functional/openlp_plugins/songs/__init__.py +++ b/tests/functional/openlp_plugins/songs/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/functional/openlp_plugins/songs/test_chordproimport.py b/tests/functional/openlp_plugins/songs/test_chordproimport.py index 51ab19f25..d2b8ee1dc 100644 --- a/tests/functional/openlp_plugins/songs/test_chordproimport.py +++ b/tests/functional/openlp_plugins/songs/test_chordproimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,15 +22,12 @@ """ This module contains tests for the OpenSong song importer. """ -import os - -from openlp.core.common.path import Path - -from tests.helpers.songfileimport import SongImportTestHelper from unittest.mock import patch, MagicMock -TEST_PATH = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'chordprosongs')) +from tests.helpers.songfileimport import SongImportTestHelper +from tests.utils.constants import RESOURCE_PATH + +TEST_PATH = RESOURCE_PATH / 'songs' / 'chordpro' class TestChordProFileImport(SongImportTestHelper): @@ -50,5 +47,5 @@ class TestChordProFileImport(SongImportTestHelper): mocked_returned_settings.value.side_effect = lambda value: True if value == 'songs/enable chords' else False mocked_settings.return_value = mocked_returned_settings # Do the test import - self.file_import([Path(TEST_PATH, 'swing-low.chordpro')], - self.load_external_result_data(os.path.join(TEST_PATH, 'swing-low.json'))) + self.file_import([TEST_PATH / 'swing-low.chordpro'], + self.load_external_result_data(TEST_PATH / 'swing-low.json')) diff --git a/tests/functional/openlp_plugins/songs/test_db.py b/tests/functional/openlp_plugins/songs/test_db.py index 797359139..1078bfca4 100644 --- a/tests/functional/openlp_plugins/songs/test_db.py +++ b/tests/functional/openlp_plugins/songs/test_db.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -24,12 +24,12 @@ This module contains tests for the db submodule of the Songs plugin. """ import os import shutil -from unittest import TestCase from tempfile import mkdtemp +from unittest import TestCase -from openlp.plugins.songs.lib.db import Song, Author, AuthorType, Book -from openlp.plugins.songs.lib import upgrade from openlp.core.lib.db import upgrade_db +from openlp.plugins.songs.lib import upgrade +from openlp.plugins.songs.lib.db import Song, Author, AuthorType, Book from tests.utils.constants import TEST_RESOURCES_PATH @@ -66,10 +66,10 @@ class TestDB(TestCase): song.add_author(author) # THEN: The author should have been added with author_type=None - self.assertEqual(1, len(song.authors_songs)) - self.assertEqual("Max", song.authors_songs[0].author.first_name) - self.assertEqual("Mustermann", song.authors_songs[0].author.last_name) - self.assertIsNone(song.authors_songs[0].author_type) + assert 1 == len(song.authors_songs) + assert "Max" == song.authors_songs[0].author.first_name + assert "Mustermann" == song.authors_songs[0].author.last_name + assert song.authors_songs[0].author_type is None def test_add_author_with_type(self): """ @@ -86,10 +86,10 @@ class TestDB(TestCase): song.add_author(author, AuthorType.Words) # THEN: The author should have been added with author_type=None - self.assertEqual(1, len(song.authors_songs)) - self.assertEqual("Max", song.authors_songs[0].author.first_name) - self.assertEqual("Mustermann", song.authors_songs[0].author.last_name) - self.assertEqual(AuthorType.Words, song.authors_songs[0].author_type) + assert 1 == len(song.authors_songs) + assert "Max" == song.authors_songs[0].author.first_name + assert "Mustermann" == song.authors_songs[0].author.last_name + assert AuthorType.Words == song.authors_songs[0].author_type def test_remove_author(self): """ @@ -105,7 +105,7 @@ class TestDB(TestCase): song.remove_author(author) # THEN: It should have been removed - self.assertEqual(0, len(song.authors_songs)) + assert 0 == len(song.authors_songs) def test_remove_author_with_type(self): """ @@ -122,8 +122,8 @@ class TestDB(TestCase): song.remove_author(author, AuthorType.Translation) # THEN: It should have been removed and the other author should still be there - self.assertEqual(1, len(song.authors_songs)) - self.assertEqual(None, song.authors_songs[0].author_type) + assert 1 == len(song.authors_songs) + assert song.authors_songs[0].author_type is None def test_get_author_type_from_translated_text(self): """ @@ -136,7 +136,7 @@ class TestDB(TestCase): author_type = AuthorType.from_translated_text(author_type_name) # THEN: The type should be correct - self.assertEqual(author_type, AuthorType.Words) + assert author_type == AuthorType.Words def test_author_get_display_name(self): """ @@ -150,7 +150,7 @@ class TestDB(TestCase): display_name = author.get_display_name() # THEN: It should return only the name - self.assertEqual("John Doe", display_name) + assert "John Doe" == display_name def test_author_get_display_name_with_type_words(self): """ @@ -164,7 +164,7 @@ class TestDB(TestCase): display_name = author.get_display_name(AuthorType.Words) # THEN: It should return the name with the type in brackets - self.assertEqual("John Doe (Words)", display_name) + assert "John Doe (Words)" == display_name def test_author_get_display_name_with_type_translation(self): """ @@ -178,7 +178,7 @@ class TestDB(TestCase): display_name = author.get_display_name(AuthorType.Translation) # THEN: It should return the name with the type in brackets - self.assertEqual("John Doe (Translation)", display_name) + assert "John Doe (Translation)" == display_name def test_add_songbooks(self): """ @@ -195,7 +195,7 @@ class TestDB(TestCase): song.add_songbook_entry(songbook, "550A") # THEN: The song should have two songbook entries - self.assertEqual(len(song.songbook_entries), 2, 'There should be two Songbook entries.') + assert len(song.songbook_entries) == 2, 'There should be two Songbook entries.' def test_upgrade_old_song_db(self): """ @@ -211,8 +211,7 @@ class TestDB(TestCase): updated_to_version, latest_version = upgrade_db(db_url, upgrade) # THEN: the song db should have been upgraded to the latest version - self.assertEqual(updated_to_version, latest_version, - 'The song DB should have been upgrade to the latest version') + assert updated_to_version == latest_version, 'The song DB should have been upgrade to the latest version' def test_upgrade_invalid_song_db(self): """ @@ -228,5 +227,4 @@ class TestDB(TestCase): updated_to_version, latest_version = upgrade_db(db_url, upgrade) # THEN: the song db should have been upgraded to the latest version without errors - self.assertEqual(updated_to_version, latest_version, - 'The song DB should have been upgrade to the latest version') + assert updated_to_version == latest_version, 'The song DB should have been upgrade to the latest version' diff --git a/tests/functional/openlp_plugins/songs/test_easyslidesimport.py b/tests/functional/openlp_plugins/songs/test_easyslidesimport.py index 6e0e6848b..7e6c52e96 100644 --- a/tests/functional/openlp_plugins/songs/test_easyslidesimport.py +++ b/tests/functional/openlp_plugins/songs/test_easyslidesimport.py @@ -3,7 +3,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -21,14 +21,10 @@ """ This module contains tests for the EasySlides song importer. """ -import os - -from openlp.core.common.path import Path - from tests.helpers.songfileimport import SongImportTestHelper +from tests.utils.constants import RESOURCE_PATH -TEST_PATH = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'easyslidessongs')) +TEST_PATH = RESOURCE_PATH / 'songs' / 'easyslides' class TestEasySlidesFileImport(SongImportTestHelper): @@ -42,7 +38,7 @@ class TestEasySlidesFileImport(SongImportTestHelper): """ Test that loading an EasySlides file works correctly on various files """ - self.file_import(Path(TEST_PATH, 'amazing-grace.xml'), - self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json'))) - self.file_import(Path(TEST_PATH, 'Export_2017-01-12_BB.xml'), - self.load_external_result_data(os.path.join(TEST_PATH, 'Export_2017-01-12_BB.json'))) + self.file_import(TEST_PATH / 'amazing-grace.xml', + self.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) + self.file_import(TEST_PATH / 'Export_2017-01-12_BB.xml', + self.load_external_result_data(TEST_PATH / 'Export_2017-01-12_BB.json')) diff --git a/tests/functional/openlp_plugins/songs/test_editsongform.py b/tests/functional/openlp_plugins/songs/test_editsongform.py index 5a5e861c7..650f9ca91 100644 --- a/tests/functional/openlp_plugins/songs/test_editsongform.py +++ b/tests/functional/openlp_plugins/songs/test_editsongform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -29,7 +29,6 @@ from PyQt5 import QtCore from openlp.core.common.registry import Registry from openlp.plugins.songs.forms.editsongform import EditSongForm - from tests.helpers.testmixin import TestMixin @@ -64,7 +63,7 @@ class TestEditSongForm(TestCase, TestMixin): valid = self.edit_song_form._validate_tags(tags) # THEN they should be valid - self.assertTrue(valid, "The tags list should be valid") + assert valid is True, "The tags list should be valid" def test_validate_nonmatching_tags(self): # Given a set of tags @@ -74,7 +73,7 @@ class TestEditSongForm(TestCase, TestMixin): valid = self.edit_song_form._validate_tags(tags) # THEN they should be valid - self.assertTrue(valid, "The tags list should be valid") + assert valid is True, "The tags list should be valid" @patch('openlp.plugins.songs.forms.editsongform.set_case_insensitive_completer') def test_load_objects(self, mocked_set_case_insensitive_completer): diff --git a/tests/functional/openlp_plugins/songs/test_editverseform.py b/tests/functional/openlp_plugins/songs/test_editverseform.py index 10b339dc2..f269b262c 100644 --- a/tests/functional/openlp_plugins/songs/test_editverseform.py +++ b/tests/functional/openlp_plugins/songs/test_editverseform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -29,7 +29,6 @@ from PyQt5 import QtCore from openlp.core.common.settings import Settings from openlp.plugins.songs.forms.editverseform import EditVerseForm - from tests.helpers.testmixin import TestMixin __default_settings__ = { @@ -71,7 +70,7 @@ class TestEditVerseForm(TestCase, TestMixin): self.edit_verse_form.update_suggested_verse_number() # THEN the verse number must not be changed - self.assertEqual(3, self.edit_verse_form.verse_number_box.value(), 'The verse number should be 3') + assert 3 == self.edit_verse_form.verse_number_box.value(), 'The verse number should be 3' def test_on_divide_split_button_clicked(self): """ @@ -84,8 +83,8 @@ class TestEditVerseForm(TestCase, TestMixin): # WHEN the method is called self.edit_verse_form.on_forced_split_button_clicked() # THEN the verse number must not be changed - self.assertEqual('[--}{--]\nText\n', self.edit_verse_form.verse_text_edit.toPlainText(), - 'The verse number should be [--}{--]\nText\n') + assert '[--}{--]\nText\n' == self.edit_verse_form.verse_text_edit.toPlainText(), \ + 'The verse number should be [--}{--]\nText\n' def test_on_split_button_clicked(self): """ @@ -98,5 +97,5 @@ class TestEditVerseForm(TestCase, TestMixin): # WHEN the method is called self.edit_verse_form.on_overflow_split_button_clicked() # THEN the verse number must not be changed - self.assertEqual('[---]\nText\n', self.edit_verse_form.verse_text_edit.toPlainText(), - 'The verse number should be [---]\nText\n') + assert '[---]\nText\n' == self.edit_verse_form.verse_text_edit.toPlainText(), \ + 'The verse number should be [---]\nText\n' diff --git a/tests/functional/openlp_plugins/songs/test_ewimport.py b/tests/functional/openlp_plugins/songs/test_ewimport.py index e384319f0..39835e677 100644 --- a/tests/functional/openlp_plugins/songs/test_ewimport.py +++ b/tests/functional/openlp_plugins/songs/test_ewimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -28,9 +28,9 @@ from unittest.mock import MagicMock, patch from openlp.core.common.registry import Registry from openlp.plugins.songs.lib.importers.easyworship import EasyWorshipSongImport, FieldDescEntry, FieldType +from tests.utils.constants import RESOURCE_PATH -TEST_PATH = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'easyworshipsongs')) +TEST_PATH = RESOURCE_PATH / 'songs' / 'easyworship' SONG_TEST_DATA = [ {'title': 'Amazing Grace', 'authors': ['John Newton'], @@ -108,7 +108,7 @@ class EasyWorshipSongImportLogger(EasyWorshipSongImport): self._title_assignment_list.append(title) -class TestFieldDesc: +class DataTestFieldDesc: def __init__(self, name, field_type, size): self.name = name self.field_type = field_type @@ -120,11 +120,11 @@ CODE_PAGE_MAPPINGS = [ (852, 'cp1250'), (737, 'cp1253'), (775, 'cp1257'), (855, 'cp1251'), (857, 'cp1254'), (866, 'cp1251'), (869, 'cp1253'), (862, 'cp1255'), (874, 'cp874')] TEST_FIELD_DESCS = [ - TestFieldDesc('Title', FieldType.String, 50), - TestFieldDesc('Text Percentage Bottom', FieldType.Int16, 2), TestFieldDesc('RecID', FieldType.Int32, 4), - TestFieldDesc('Default Background', FieldType.Logical, 1), TestFieldDesc('Words', FieldType.Memo, 250), - TestFieldDesc('Words', FieldType.Memo, 250), TestFieldDesc('BK Bitmap', FieldType.Blob, 10), - TestFieldDesc('Last Modified', FieldType.Timestamp, 10)] + DataTestFieldDesc('Title', FieldType.String, 50), + DataTestFieldDesc('Text Percentage Bottom', FieldType.Int16, 2), DataTestFieldDesc('RecID', FieldType.Int32, 4), + DataTestFieldDesc('Default Background', FieldType.Logical, 1), DataTestFieldDesc('Words', FieldType.Memo, 250), + DataTestFieldDesc('Words', FieldType.Memo, 250), DataTestFieldDesc('BK Bitmap', FieldType.Blob, 10), + DataTestFieldDesc('Last Modified', FieldType.Timestamp, 10)] TEST_FIELDS = [ b'A Heart Like Thine\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0', 32868, 2147483750, 129, b'{\\rtf1\\ansi\\deff0\\deftab254{\\fonttbl{\\f0\\fnil\\fcharset0 Arial;}{\\f1\\fnil\\fcharset0 Verdana;}}' @@ -165,11 +165,10 @@ class TestEasyWorshipSongImport(TestCase): field_desc_entry = FieldDescEntry(name, field_type, size) # THEN: - self.assertIsNotNone(field_desc_entry, 'Import should not be none') - self.assertEqual(field_desc_entry.name, name, 'FieldDescEntry.name should be the same as the name argument') - self.assertEqual(field_desc_entry.field_type, field_type, - 'FieldDescEntry.type should be the same as the type argument') - self.assertEqual(field_desc_entry.size, size, 'FieldDescEntry.size should be the same as the size argument') + assert field_desc_entry is not None, 'Import should not be none' + assert field_desc_entry.name == name, 'FieldDescEntry.name should be the same as the name argument' + assert field_desc_entry.field_type == field_type, 'FieldDescEntry.type should be the same as the type argument' + assert field_desc_entry.size == size, 'FieldDescEntry.size should be the same as the size argument' def test_create_importer(self): """ @@ -183,7 +182,7 @@ class TestEasyWorshipSongImport(TestCase): importer = EasyWorshipSongImport(mocked_manager, file_paths=[]) # THEN: The importer object should not be None - self.assertIsNotNone(importer, 'Import should not be none') + assert importer is not None, 'Import should not be none' def test_find_field_exists(self): """ @@ -201,7 +200,7 @@ class TestEasyWorshipSongImport(TestCase): for field_name in existing_fields: # THEN: The item corresponding the index returned should have the same name attribute - self.assertEqual(importer.field_descriptions[importer.db_find_field(field_name)].name, field_name) + assert importer.field_descriptions[importer.db_find_field(field_name)].name == field_name def test_find_non_existing_field(self): """ @@ -236,7 +235,7 @@ class TestEasyWorshipSongImport(TestCase): # THEN: db_set_record_struct should return None and Struct should be called with a value representing # the list of field descriptions - self.assertIsNone(return_value, 'db_set_record_struct should return None') + assert return_value is None, 'db_set_record_struct should return None' mocked_struct.Struct.assert_called_with('>50sHIB250s250s10sQ') @patch('openlp.plugins.songs.lib.importers.easyworship.SongImport') @@ -257,9 +256,8 @@ class TestEasyWorshipSongImport(TestCase): return_value = importer.db_get_field(field_index) # THEN: db_get_field should return the known results - self.assertEqual(return_value, result, - 'db_get_field should return "%s" when called with "%s"' % - (result, TEST_FIELDS[field_index])) + assert return_value == result, 'db_get_field should return "%s" when called with "%s"' % \ + (result, TEST_FIELDS[field_index]) @patch('openlp.plugins.songs.lib.importers.easyworship.SongImport') def test_get_memo_field(self, MockSongImport): @@ -285,7 +283,7 @@ class TestEasyWorshipSongImport(TestCase): # THEN: db_get_field should return the appropriate value with the appropriate mocked objects being # called - self.assertEqual(importer.db_get_field(field_index), get_field_result) + assert importer.db_get_field(field_index) == get_field_result for call in get_field_read_calls: mocked_memo_file.read.assert_any_call(call) for call in get_field_seek_calls: @@ -330,7 +328,7 @@ class TestEasyWorshipSongImport(TestCase): mocked_stat.return_value.st_size = 0x7FF # THEN: do_import should return None having called Path.stat() - self.assertIsNone(importer.do_import(), 'do_import should return None when db_size is less than 0x800') + assert importer.do_import() is None, 'do_import should return None when db_size is less than 0x800' mocked_stat.assert_called_once_with() @patch('openlp.plugins.songs.lib.importers.easyworship.SongImport') @@ -353,11 +351,10 @@ class TestEasyWorshipSongImport(TestCase): # THEN: do_import should return None having called closed the open files db and memo files. for effect in struct_unpack_return_values: - self.assertIsNone(importer.do_import(), 'do_import should return None when db_size is less than 0x800') - self.assertEqual(mocked_open().close.call_count, 2, - 'The open db and memo files should have been closed') + assert importer.do_import() is None, 'do_import should return None when db_size is less than 0x800' + assert mocked_open().close.call_count == 2, 'The open db and memo files should have been closed' mocked_open().close.reset_mock() - self.assertIs(mocked_open().seek.called, False, 'db_file.seek should not have been called.') + assert mocked_open().seek.called is False, 'db_file.seek should not have been called.' @patch('openlp.plugins.songs.lib.importers.easyworship.SongImport') @patch('openlp.plugins.songs.lib.importers.easyworship.Path.is_file', return_value=True) @@ -383,14 +380,14 @@ class TestEasyWorshipSongImport(TestCase): mocked_retrieve_windows_encoding.return_value = False # THEN: do_import should return None having called retrieve_windows_encoding with the correct encoding. - self.assertIsNone(importer.do_import(), 'do_import should return None when db_size is less than 0x800') + assert importer.do_import() is None, 'do_import should return None when db_size is less than 0x800' mocked_retrieve_windows_encoding.assert_any_call(encoding) def test_db_file_import(self): - return self._run_db_file_import(os.path.join(TEST_PATH, 'Songs.DB')) + return self._run_db_file_import(TEST_PATH / 'Songs.DB') def test_sqlite_db_file_import(self): - return self._run_db_file_import(os.path.join(TEST_PATH, 'ew6')) + return self._run_db_file_import(TEST_PATH / 'ew6') def _run_db_file_import(self, source_path): """ @@ -420,12 +417,13 @@ class TestEasyWorshipSongImport(TestCase): importer.topics = [] # WHEN: Importing each file - importer.import_source = source_path + # TODO: To Path object + importer.import_source = str(source_path) import_result = importer.do_import() # THEN: do_import should return none, the song data should be as expected, and finish should have been # called. - self.assertIsNone(import_result, 'do_import should return None when it has completed') + assert import_result is None, 'do_import should return None when it has completed' for song_data in SONG_TEST_DATA: title = song_data['title'] author_calls = song_data['authors'] @@ -433,19 +431,18 @@ class TestEasyWorshipSongImport(TestCase): ccli_number = song_data['ccli_number'] add_verse_calls = song_data['verses'] verse_order_list = song_data['verse_order_list'] - self.assertIn(title, importer._title_assignment_list, 'title for %s should be "%s"' % (title, title)) + assert title in importer._title_assignment_list, 'title for %s should be "%s"' % (title, title) for author in author_calls: mocked_add_author.assert_any_call(author) if song_copyright: - self.assertEqual(importer.copyright, song_copyright) + assert importer.copyright == song_copyright if ccli_number: - self.assertEqual(importer.ccli_number, ccli_number, - 'ccli_number for %s should be %s' % (title, ccli_number)) + assert importer.ccli_number == ccli_number, 'ccli_number for %s should be %s' % (title, ccli_number) for verse_text, verse_tag in add_verse_calls: mocked_add_verse.assert_any_call(verse_text, verse_tag) if verse_order_list: - self.assertEqual(importer.verse_order_list, verse_order_list, - 'verse_order_list for %s should be %s' % (title, verse_order_list)) + assert importer.verse_order_list == verse_order_list, \ + 'verse_order_list for %s should be %s' % (title, verse_order_list) mocked_finish.assert_called_with() @patch('openlp.plugins.songs.lib.importers.easyworship.SongImport') @@ -475,14 +472,14 @@ class TestEasyWorshipSongImport(TestCase): importer.topics = [] # WHEN: Importing ews file - importer.import_source = os.path.join(TEST_PATH, 'test1.ews') + importer.import_source = str(TEST_PATH / 'test1.ews') import_result = importer.do_import() # THEN: do_import should return none, the song data should be as expected, and finish should have been # called. title = EWS_SONG_TEST_DATA['title'] - self.assertIsNone(import_result, 'do_import should return None when it has completed') - self.assertIn(title, importer._title_assignment_list, 'title for should be "%s"' % title) + assert import_result is None, 'do_import should return None when it has completed' + assert title in importer._title_assignment_list, 'title for should be "%s"' % title mocked_add_author.assert_any_call(EWS_SONG_TEST_DATA['authors'][0]) for verse_text, verse_tag in EWS_SONG_TEST_DATA['verses']: mocked_add_verse.assert_any_call(verse_text, verse_tag) @@ -505,4 +502,4 @@ class TestEasyWorshipSongImport(TestCase): importer.set_song_import_object('Test Author', b'Det som var fr\x86n begynnelsen') # THEN: The import should fail - self.assertEquals(importer.entry_error_log, 'Unexpected data formatting.', 'Import should fail') + assert importer.entry_error_log == 'Unexpected data formatting.', 'Import should fail' diff --git a/tests/functional/openlp_plugins/songs/test_foilpresenterimport.py b/tests/functional/openlp_plugins/songs/test_foilpresenterimport.py index d3d705722..9c0af59a4 100644 --- a/tests/functional/openlp_plugins/songs/test_foilpresenterimport.py +++ b/tests/functional/openlp_plugins/songs/test_foilpresenterimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,15 +22,11 @@ """ This module contains tests for the SongShow Plus song importer. """ -import os from unittest import TestCase from unittest.mock import patch, MagicMock from openlp.plugins.songs.lib.importers.foilpresenter import FoilPresenter -TEST_PATH = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..', '..', '/resources/foilpresentersongs')) - class TestFoilPresenter(TestCase): """ @@ -106,7 +102,7 @@ class TestFoilPresenter(TestCase): foil_presenter_instance = FoilPresenter(mocked_manager, mocked_song_import) # THEN: The instance should not be None - self.assertIsNotNone(foil_presenter_instance, 'foil_presenter instance should not be none') + assert foil_presenter_instance is not None, 'foil_presenter instance should not be none' def test_no_xml(self): """ @@ -122,7 +118,7 @@ class TestFoilPresenter(TestCase): result = foil_presenter_instance.xml_to_song(arg) # Then: xml_to_song should return False - self.assertEqual(result, None, 'xml_to_song should return None when called with %s' % arg) + assert result is None, 'xml_to_song should return None when called with %s' % arg def test_encoding_declaration_removal(self): """ @@ -169,6 +165,6 @@ class TestFoilPresenter(TestCase): result = foil_presenter_instance._process_lyrics(mock_foilpresenterfolie, mocked_song) # THEN: _process_lyrics should return None and the song_import log_error method should have been called once - self.assertIsNone(result) + assert result is None self.mocked_song_import.log_error.assert_called_once_with('Element Text', 'Translated String') self.process_lyrics_patcher.start() diff --git a/tests/functional/openlp_plugins/songs/test_lib.py b/tests/functional/openlp_plugins/songs/test_lib.py index 334282a44..09011a3e3 100644 --- a/tests/functional/openlp_plugins/songs/test_lib.py +++ b/tests/functional/openlp_plugins/songs/test_lib.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -63,7 +63,7 @@ class TestLib(TestCase): result = clean_string(dirty_string) # THEN: The string should be cleaned up and lower-cased - self.assertEqual(result, 'aint gonna find you there ', 'The string should be cleaned up properly') + assert result == 'aint gonna find you there ', 'The string should be cleaned up properly' def test_clean_title(self): """ @@ -76,7 +76,7 @@ class TestLib(TestCase): result = clean_title(dirty_string) # THEN: The string should be cleaned up - self.assertEqual(result, 'This is a dirty string', 'The title should be cleaned up properly: "%s"' % result) + assert result == 'This is a dirty string', 'The title should be cleaned up properly: "%s"' % result def test_songs_probably_equal_same_song(self): """ @@ -275,7 +275,7 @@ class TestLib(TestCase): new_chord = transpose_chord(chord, 1, 'english') # THEN: The chord should be transposed up one note - self.assertEqual(new_chord, 'C#', 'The chord should be transposed up.') + assert new_chord == 'C#', 'The chord should be transposed up.' def test_transpose_chord_up_adv(self): """ @@ -288,7 +288,7 @@ class TestLib(TestCase): new_chord = transpose_chord(chord, 1, 'english') # THEN: The chord should be transposed up one note - self.assertEqual(new_chord, '(C#/E)', 'The chord should be transposed up.') + assert new_chord == '(C#/E)', 'The chord should be transposed up.' def test_transpose_chord_down(self): """ @@ -301,7 +301,7 @@ class TestLib(TestCase): new_chord = transpose_chord(chord, -1, 'english') # THEN: The chord should be transposed down one note - self.assertEqual(new_chord, 'B', 'The chord should be transposed down.') + assert new_chord == 'B', 'The chord should be transposed down.' def test_transpose_chord_error(self): """ @@ -314,8 +314,8 @@ class TestLib(TestCase): # THEN: An exception should be raised with self.assertRaises(ValueError) as err: new_chord = transpose_chord(chord, -1, 'english') - self.assertEqual(err.exception.args[0], '\'T\' is not in list', - 'ValueError exception should have been thrown for invalid chord') + assert err.exception.args[0] == '\'T\' is not in list', \ + 'ValueError exception should have been thrown for invalid chord' @patch('openlp.plugins.songs.lib.transpose_verse') @patch('openlp.plugins.songs.lib.Settings') @@ -361,13 +361,13 @@ class TestVerseType(TestCase): result = VerseType.translated_tag('v') # THEN: The result should be "V" - self.assertEqual(result, 'V', 'The result should be "V"') + assert result == 'V', 'The result should be "V"' # WHEN: We run the translated_tag() method with a "chorus" result = VerseType.translated_tag('c') # THEN: The result should be "C" - self.assertEqual(result, 'C', 'The result should be "C"') + assert result == 'C', 'The result should be "C"' def test_translated_invalid_tag(self): """ @@ -381,7 +381,7 @@ class TestVerseType(TestCase): result = VerseType.translated_tag('z') # THEN: The result should be "O" - self.assertEqual(result, 'O', 'The result should be "O", but was "%s"' % result) + assert result == 'O', 'The result should be "O", but was "%s"' % result def test_translated_invalid_tag_with_specified_default(self): """ @@ -395,7 +395,7 @@ class TestVerseType(TestCase): result = VerseType.translated_tag('q', VerseType.Bridge) # THEN: The result should be "B" - self.assertEqual(result, 'B', 'The result should be "B", but was "%s"' % result) + assert result == 'B', 'The result should be "B", but was "%s"' % result def test_translated_invalid_tag_with_invalid_default(self): """ @@ -409,7 +409,7 @@ class TestVerseType(TestCase): result = VerseType.translated_tag('q', 29) # THEN: The result should be "O" - self.assertEqual(result, 'O', 'The result should be "O", but was "%s"' % result) + assert result == 'O', 'The result should be "O", but was "%s"' % result def test_translated_name(self): """ @@ -423,13 +423,13 @@ class TestVerseType(TestCase): result = VerseType.translated_name('v') # THEN: The result should be "Verse" - self.assertEqual(result, 'Verse', 'The result should be "Verse"') + assert result == 'Verse', 'The result should be "Verse"' # WHEN: We run the translated_name() method with a "chorus" result = VerseType.translated_name('c') # THEN: The result should be "Chorus" - self.assertEqual(result, 'Chorus', 'The result should be "Chorus"') + assert result == 'Chorus', 'The result should be "Chorus"' def test_translated_invalid_name(self): """ @@ -443,7 +443,7 @@ class TestVerseType(TestCase): result = VerseType.translated_name('z') # THEN: The result should be "Other" - self.assertEqual(result, 'Other', 'The result should be "Other", but was "%s"' % result) + assert result == 'Other', 'The result should be "Other", but was "%s"' % result def test_translated_invalid_name_with_specified_default(self): """ @@ -457,7 +457,7 @@ class TestVerseType(TestCase): result = VerseType.translated_name('q', VerseType.Bridge) # THEN: The result should be "Bridge" - self.assertEqual(result, 'Bridge', 'The result should be "Bridge", but was "%s"' % result) + assert result == 'Bridge', 'The result should be "Bridge", but was "%s"' % result def test_translated_invalid_name_with_invalid_default(self): """ @@ -471,7 +471,7 @@ class TestVerseType(TestCase): result = VerseType.translated_name('q', 29) # THEN: The result should be "Other" - self.assertEqual(result, 'Other', 'The result should be "Other", but was "%s"' % result) + assert result == 'Other', 'The result should be "Other", but was "%s"' % result def test_from_tag(self): """ @@ -485,7 +485,7 @@ class TestVerseType(TestCase): result = VerseType.from_tag('v') # THEN: The result should be VerseType.Verse - self.assertEqual(result, VerseType.Verse, 'The result should be VerseType.Verse, but was "%s"' % result) + assert result == VerseType.Verse, 'The result should be VerseType.Verse, but was "%s"' % result def test_from_tag_with_invalid_tag(self): """ @@ -499,7 +499,7 @@ class TestVerseType(TestCase): result = VerseType.from_tag('w') # THEN: The result should be VerseType.Other - self.assertEqual(result, VerseType.Other, 'The result should be VerseType.Other, but was "%s"' % result) + assert result == VerseType.Other, 'The result should be VerseType.Other, but was "%s"' % result def test_from_tag_with_specified_default(self): """ @@ -513,7 +513,7 @@ class TestVerseType(TestCase): result = VerseType.from_tag('x', VerseType.Chorus) # THEN: The result should be VerseType.Chorus - self.assertEqual(result, VerseType.Chorus, 'The result should be VerseType.Chorus, but was "%s"' % result) + assert result == VerseType.Chorus, 'The result should be VerseType.Chorus, but was "%s"' % result def test_from_tag_with_invalid_intdefault(self): """ @@ -527,7 +527,7 @@ class TestVerseType(TestCase): result = VerseType.from_tag('m', 29) # THEN: The result should be VerseType.Other - self.assertEqual(result, VerseType.Other, 'The result should be VerseType.Other, but was "%s"' % result) + assert result == VerseType.Other, 'The result should be VerseType.Other, but was "%s"' % result def test_from_tag_with_invalid_default(self): """ @@ -541,7 +541,7 @@ class TestVerseType(TestCase): result = VerseType.from_tag('@', 'asdf') # THEN: The result should be VerseType.Other - self.assertEqual(result, VerseType.Other, 'The result should be VerseType.Other, but was "%s"' % result) + assert result == VerseType.Other, 'The result should be VerseType.Other, but was "%s"' % result def test_from_tag_with_none_default(self): """ @@ -555,7 +555,7 @@ class TestVerseType(TestCase): result = VerseType.from_tag('m', None) # THEN: The result should be None - self.assertIsNone(result, 'The result should be None, but was "%s"' % result) + assert result is None, 'The result should be None, but was "%s"' % result @patch('openlp.plugins.songs.lib.VerseType.translated_tags', new_callable=PropertyMock, return_value=['x']) def test_from_loose_input_with_invalid_input(self, mocked_translated_tags): @@ -567,7 +567,7 @@ class TestVerseType(TestCase): result = VerseType.from_loose_input('m', None) # THEN: The result should be None - self.assertIsNone(result, 'The result should be None, but was "%s"' % result) + assert result is None, 'The result should be None, but was "%s"' % result @patch('openlp.plugins.songs.lib.VerseType.translated_tags', new_callable=PropertyMock, return_value=['x']) def test_from_loose_input_with_valid_input(self, mocked_translated_tags): @@ -579,4 +579,4 @@ class TestVerseType(TestCase): result = VerseType.from_loose_input('v') # THEN: The result should be a Verse - self.assertEqual(result, VerseType.Verse, 'The result should be a verse, but was "%s"' % result) + assert result == VerseType.Verse, 'The result should be a verse, but was "%s"' % result diff --git a/tests/functional/openlp_plugins/songs/test_lyriximport.py b/tests/functional/openlp_plugins/songs/test_lyriximport.py index 2732b3154..eea29fceb 100644 --- a/tests/functional/openlp_plugins/songs/test_lyriximport.py +++ b/tests/functional/openlp_plugins/songs/test_lyriximport.py @@ -3,7 +3,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -21,14 +21,10 @@ """ This module contains tests for the LyriX song importer. """ -import os - -from openlp.core.common.path import Path - from tests.helpers.songfileimport import SongImportTestHelper +from tests.utils.constants import RESOURCE_PATH -TEST_PATH = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'lyrixsongs')) +TEST_PATH = RESOURCE_PATH / 'songs' / 'lyrix' class TestLyrixFileImport(SongImportTestHelper): @@ -42,9 +38,9 @@ class TestLyrixFileImport(SongImportTestHelper): """ Test that loading an LyriX file works correctly on various files """ - self.file_import([Path(TEST_PATH, 'A06.TXT')], - self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json'))) - self.file_import([Path(TEST_PATH, 'A002.TXT')], - self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace2.json'))) - self.file_import([Path(TEST_PATH, 'AO05.TXT')], - self.load_external_result_data(os.path.join(TEST_PATH, 'in die regterhand.json'))) + self.file_import([TEST_PATH / 'A06.TXT'], + self.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) + self.file_import([TEST_PATH / 'A002.TXT'], + self.load_external_result_data(TEST_PATH / 'Amazing Grace2.json')) + self.file_import([TEST_PATH / 'AO05.TXT'], + self.load_external_result_data(TEST_PATH / 'in die regterhand.json')) diff --git a/tests/functional/openlp_plugins/songs/test_mediaitem.py b/tests/functional/openlp_plugins/songs/test_mediaitem.py index 530c1cf6b..9af310e26 100644 --- a/tests/functional/openlp_plugins/songs/test_mediaitem.py +++ b/tests/functional/openlp_plugins/songs/test_mediaitem.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -32,7 +32,6 @@ from openlp.core.common.settings import Settings from openlp.core.lib import ServiceItem from openlp.plugins.songs.lib.db import AuthorType, Song from openlp.plugins.songs.lib.mediaitem import SongMediaItem - from tests.helpers.testmixin import TestMixin @@ -324,10 +323,9 @@ class TestMediaItem(TestCase, TestMixin): author_list = self.media_item.generate_footer(service_item, mock_song) # THEN: I get the following Array returned - self.assertEqual(service_item.raw_footer, ['My Song', 'Written by: my author', 'My copyright'], - 'The array should be returned correctly with a song, one author and copyright') - self.assertEqual(author_list, ['my author'], - 'The author list should be returned correctly with one author') + assert service_item.raw_footer == ['My Song', 'Written by: my author', 'My copyright'], \ + 'The array should be returned correctly with a song, one author and copyright' + assert author_list == ['my author'], 'The author list should be returned correctly with one author' @patch(u'openlp.plugins.songs.lib.mediaitem.Settings') def test_build_song_footer_one_author_hide_written_by(self, MockedSettings): @@ -356,11 +354,10 @@ class TestMediaItem(TestCase, TestMixin): author_list = self.media_item.generate_footer(service_item, mock_song) # THEN: I get the following Array returned - self.assertEqual(service_item.raw_footer, ['My Song', 'my author', 'My copyright'], - 'The array should be returned correctly with a song, one author and copyright,' - 'text Written by should not be part of the text.') - self.assertEqual(author_list, ['my author'], - 'The author list should be returned correctly with one author') + assert service_item.raw_footer == ['My Song', 'my author', 'My copyright'], \ + 'The array should be returned correctly with a song, one author and copyright, ' \ + 'text Written by should not be part of the text.' + assert author_list == ['my author'], 'The author list should be returned correctly with one author' def test_build_song_footer_two_authors(self): """ @@ -395,11 +392,11 @@ class TestMediaItem(TestCase, TestMixin): author_list = self.media_item.generate_footer(service_item, mock_song) # THEN: I get the following Array returned - self.assertEqual(service_item.raw_footer, ['My Song', 'Words: another author', 'Music: my author', - 'Translation: translator', 'My copyright'], - 'The array should be returned correctly with a song, two authors and copyright') - self.assertEqual(author_list, ['another author', 'my author', 'translator'], - 'The author list should be returned correctly with two authors') + assert service_item.raw_footer == ['My Song', 'Words: another author', 'Music: my author', + 'Translation: translator', 'My copyright'], \ + 'The array should be returned correctly with a song, two authors and copyright' + assert author_list == ['another author', 'my author', 'translator'], \ + 'The author list should be returned correctly with two authors' def test_build_song_footer_base_ccli(self): """ @@ -416,16 +413,16 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.generate_footer(service_item, mock_song) # THEN: I get the following Array returned - self.assertEqual(service_item.raw_footer, ['My Song', 'My copyright', 'CCLI License: 1234'], - 'The array should be returned correctly with a song, an author, copyright and ccli') + assert service_item.raw_footer == ['My Song', 'My copyright', 'CCLI License: 1234'], \ + 'The array should be returned correctly with a song, an author, copyright and ccli' # WHEN: I amend the CCLI value Settings().setValue('core/ccli number', '4321') self.media_item.generate_footer(service_item, mock_song) # THEN: I would get an amended footer string - self.assertEqual(service_item.raw_footer, ['My Song', 'My copyright', 'CCLI License: 4321'], - 'The array should be returned correctly with a song, an author, copyright and amended ccli') + assert service_item.raw_footer == ['My Song', 'My copyright', 'CCLI License: 4321'], \ + 'The array should be returned correctly with a song, an author, copyright and amended ccli' def test_build_song_footer_base_songbook(self): """ @@ -451,14 +448,14 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.generate_footer(service_item, song) # THEN: The songbook should not be in the footer - self.assertEqual(service_item.raw_footer, ['My Song', 'My copyright']) + assert service_item.raw_footer == ['My Song', 'My copyright'] # WHEN: I activate the "display songbook" option self.media_item.display_songbook = True self.media_item.generate_footer(service_item, song) # THEN: The songbook should be in the footer - self.assertEqual(service_item.raw_footer, ['My Song', 'My copyright', 'My songbook #12, Thy songbook #502A']) + assert service_item.raw_footer == ['My Song', 'My copyright', 'My songbook #12, Thy songbook #502A'] def test_build_song_footer_copyright_enabled(self): """ @@ -475,7 +472,7 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.generate_footer(service_item, mock_song) # THEN: The copyright symbol should be in the footer - self.assertEqual(service_item.raw_footer, ['My Song', '© My copyright']) + assert service_item.raw_footer == ['My Song', '© My copyright'] def test_build_song_footer_copyright_disabled(self): """ @@ -491,7 +488,7 @@ class TestMediaItem(TestCase, TestMixin): self.media_item.generate_footer(service_item, mock_song) # THEN: The copyright symbol should not be in the footer - self.assertEqual(service_item.raw_footer, ['My Song', 'My copyright']) + assert service_item.raw_footer == ['My Song', 'My copyright'] def test_authors_match(self): """ @@ -517,7 +514,7 @@ class TestMediaItem(TestCase, TestMixin): result = self.media_item._authors_match(song, authors_str) # THEN: They should match - self.assertTrue(result, "Authors should match") + assert result is True, "Authors should match" def test_authors_dont_match(self): # GIVEN: A song and a string with authors @@ -540,7 +537,7 @@ class TestMediaItem(TestCase, TestMixin): result = self.media_item._authors_match(song, authors_str) # THEN: They should not match - self.assertFalse(result, "Authors should not match") + assert result is False, "Authors should not match" def test_build_remote_search(self): """ @@ -559,7 +556,7 @@ class TestMediaItem(TestCase, TestMixin): search_results = self.media_item.search('My Song', False) # THEN: The correct formatted results are returned - self.assertEqual(search_results, [[123, 'My Song', 'My alternative']]) + assert search_results == [[123, 'My Song', 'My alternative']] @patch('openlp.plugins.songs.lib.mediaitem.Book') @patch('openlp.plugins.songs.lib.mediaitem.SongBookEntry') @@ -590,4 +587,4 @@ class TestMediaItem(TestCase, TestMixin): mocked_or.assert_called_once_with('%jesus%', '%jesus%', '%jesus%', '%jesus%', '%jesus%') self.mocked_plugin.manager.session.query.assert_called_once_with(MockedSong) - self.assertEqual(self.mocked_plugin.manager.session.query.mock_calls[4][0], '().join().join().filter().all') + assert self.mocked_plugin.manager.session.query.mock_calls[4][0] == '().join().join().filter().all' diff --git a/tests/functional/openlp_plugins/songs/test_mediashout.py b/tests/functional/openlp_plugins/songs/test_mediashout.py index 8fc452ea4..15adfded0 100644 --- a/tests/functional/openlp_plugins/songs/test_mediashout.py +++ b/tests/functional/openlp_plugins/songs/test_mediashout.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -27,6 +27,7 @@ from unittest import TestCase, skipUnless from unittest.mock import MagicMock, patch, call from openlp.core.common.registry import Registry + try: from openlp.plugins.songs.lib.importers.mediashout import MediaShoutImport CAN_RUN_TESTS = True @@ -54,7 +55,7 @@ class TestMediaShoutImport(TestCase): importer = MediaShoutImport(MagicMock(), file_path='mediashout.db') # THEN: It should not be None - self.assertIsNotNone(importer) + assert importer is not None @patch('openlp.plugins.songs.lib.importers.mediashout.pyodbc') def test_do_import_fails_to_connect(self, mocked_pyodbc): @@ -112,7 +113,7 @@ class TestMediaShoutImport(TestCase): call('SELECT Name FROM Groups INNER JOIN SongGroups ON SongGroups.GroupId = Groups.GroupId ' 'WHERE SongGroups.Record = ?', 1.0) ] - self.assertEqual(expected_execute_calls, mocked_cursor.execute.call_args_list) + assert expected_execute_calls == mocked_cursor.execute.call_args_list mocked_process_song.assert_called_once_with(song, [verse], [play_order], [theme, group]) @patch('openlp.plugins.songs.lib.importers.mediashout.pyodbc') @@ -172,16 +173,16 @@ class TestMediaShoutImport(TestCase): # THEN: It should be added to the database mocked_set_defaults.assert_called_once_with() - self.assertEqual('Amazing Grace', importer.title) + assert 'Amazing Grace' == importer.title mocked_parse_author.assert_called_once_with('William Wilberforce') mocked_add_copyright.assert_called_once_with('Public Domain') - self.assertEqual('Great old hymn', importer.comments) - self.assertEqual(['Grace', 'Hymns'], importer.topics) - self.assertEqual('Hymns', importer.song_book_name) - self.assertEqual('', importer.song_number) + assert 'Great old hymn' == importer.comments + assert ['Grace', 'Hymns'] == importer.topics + assert 'Hymns' == importer.song_book_name + assert '' == importer.song_number mocked_add_verse.assert_called_once_with( 'Amazing grace, how sweet the sound\nThat saved a wretch like me', 'V1') - self.assertEqual(['V1'], importer.verse_order_list) + assert ['V1'] == importer.verse_order_list mocked_finish.assert_called_once_with() def test_process_song_with_song_number(self): @@ -214,14 +215,14 @@ class TestMediaShoutImport(TestCase): # THEN: It should be added to the database mocked_set_defaults.assert_called_once_with() - self.assertEqual('Amazing Grace', importer.title) + assert 'Amazing Grace' == importer.title mocked_parse_author.assert_called_once_with('William Wilberforce') mocked_add_copyright.assert_called_once_with('Public Domain') - self.assertEqual('Great old hymn', importer.comments) - self.assertEqual(['Grace', 'Hymns'], importer.topics) - self.assertEqual('Hymns', importer.song_book_name) - self.assertEqual('2', importer.song_number) + assert 'Great old hymn' == importer.comments + assert ['Grace', 'Hymns'] == importer.topics + assert 'Hymns' == importer.song_book_name + assert '2' == importer.song_number mocked_add_verse.assert_called_once_with( 'Amazing grace, how sweet the sound\nThat saved a wretch like me', 'V1') - self.assertEqual(['V1'], importer.verse_order_list) + assert ['V1'], importer.verse_order_list mocked_finish.assert_called_once_with() diff --git a/tests/functional/openlp_plugins/songs/test_openlpimporter.py b/tests/functional/openlp_plugins/songs/test_openlpimporter.py index 590d09b79..5bf9d3a9a 100644 --- a/tests/functional/openlp_plugins/songs/test_openlpimporter.py +++ b/tests/functional/openlp_plugins/songs/test_openlpimporter.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -51,7 +51,7 @@ class TestOpenLPImport(TestCase): importer = OpenLPSongImport(mocked_manager, file_paths=[]) # THEN: The importer object should not be None - self.assertIsNotNone(importer, 'Import should not be none') + assert importer is not None, 'Import should not be none' def test_invalid_import_source(self): """ @@ -70,6 +70,6 @@ class TestOpenLPImport(TestCase): importer.import_source = source # THEN: do_import should return none and the progress bar maximum should not be set. - self.assertIsNone(importer.do_import(), 'do_import should return None when import_source is not a list') - self.assertEqual(mocked_import_wizard.progress_bar.setMaximum.called, False, - 'setMaximum on import_wizard.progress_bar should not have been called') + assert importer.do_import() is None, 'do_import should return None when import_source is not a list' + assert mocked_import_wizard.progress_bar.setMaximum.called is False, \ + 'setMaximum on import_wizard.progress_bar should not have been called' diff --git a/tests/functional/openlp_plugins/songs/test_openlyricsexport.py b/tests/functional/openlp_plugins/songs/test_openlyricsexport.py index 85bf0818c..ba9e959af 100644 --- a/tests/functional/openlp_plugins/songs/test_openlyricsexport.py +++ b/tests/functional/openlp_plugins/songs/test_openlyricsexport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -26,10 +26,9 @@ from tempfile import mkdtemp from unittest import TestCase from unittest.mock import MagicMock, patch -from openlp.core.common.registry import Registry from openlp.core.common.path import Path +from openlp.core.common.registry import Registry from openlp.plugins.songs.lib.openlyricsexport import OpenLyricsExport - from tests.helpers.testmixin import TestMixin @@ -72,9 +71,7 @@ class TestOpenLyricsExport(TestCase, TestMixin): ol_export.do_export() # THEN: The exporter should have created 2 files - self.assertTrue((self.temp_folder / - '{title} ({display_name}).xml'.format( - title=song.title, display_name=author.display_name)).exists()) - self.assertTrue((self.temp_folder / - '{title} ({display_name})-1.xml'.format( - title=song.title, display_name=author.display_name)).exists()) + assert (self.temp_folder / '{title} ({display_name}).xml'.format( + title=song.title, display_name=author.display_name)).exists() is True + assert (self.temp_folder / '{title} ({display_name})-1.xml'.format( + title=song.title, display_name=author.display_name)).exists() is True diff --git a/tests/functional/openlp_plugins/songs/test_openlyricsimport.py b/tests/functional/openlp_plugins/songs/test_openlyricsimport.py index 088711fbc..d3356666e 100644 --- a/tests/functional/openlp_plugins/songs/test_openlyricsimport.py +++ b/tests/functional/openlp_plugins/songs/test_openlyricsimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,24 +22,21 @@ """ This module contains tests for the OpenLyrics song importer. """ -import os import json from unittest import TestCase from unittest.mock import MagicMock, patch from lxml import etree, objectify -from openlp.core.common.path import Path from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings from openlp.plugins.songs.lib.importers.openlyrics import OpenLyricsImport from openlp.plugins.songs.lib.importers.songimport import SongImport from openlp.plugins.songs.lib.openlyricsxml import OpenLyrics - from tests.helpers.testmixin import TestMixin +from tests.utils.constants import RESOURCE_PATH -TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), - '..', '..', '..', 'resources', 'openlyricssongs')) +TEST_PATH = RESOURCE_PATH / 'songs' / 'openlyrics' SONG_TEST_DATA = { 'What a friend we have in Jesus.xml': { 'title': 'What A Friend We Have In Jesus', @@ -114,7 +111,7 @@ class TestOpenLyricsImport(TestCase, TestMixin): importer = OpenLyricsImport(mocked_manager, file_paths=[]) # THEN: The importer should be an instance of SongImport - self.assertIsInstance(importer, SongImport) + assert isinstance(importer, SongImport) def test_file_import(self): """ @@ -130,11 +127,11 @@ class TestOpenLyricsImport(TestCase, TestMixin): importer.open_lyrics.xml_to_song = MagicMock() # WHEN: Importing each file - importer.import_source = [Path(TEST_PATH, song_file)] + importer.import_source = [TEST_PATH / song_file] importer.do_import() # THEN: The xml_to_song() method should have been called - self.assertTrue(importer.open_lyrics.xml_to_song.called) + assert importer.open_lyrics.xml_to_song.called is True def test_process_formatting_tags(self): """ @@ -145,7 +142,7 @@ class TestOpenLyricsImport(TestCase, TestMixin): Settings().setValue('formattingTags/html_tags', json.dumps(start_tags)) ol = OpenLyrics(mocked_manager) parser = etree.XMLParser(remove_blank_text=True) - parsed_file = etree.parse(open(os.path.join(TEST_PATH, 'duchu-tags.xml'), 'rb'), parser) + parsed_file = etree.parse((TEST_PATH / 'duchu-tags.xml').open('rb'), parser) xml = etree.tostring(parsed_file).decode() song_xml = objectify.fromstring(xml) @@ -153,9 +150,8 @@ class TestOpenLyricsImport(TestCase, TestMixin): ol._process_formatting_tags(song_xml, False) # THEN: New tags should have been saved - self.assertListEqual(json.loads(json.dumps(result_tags)), - json.loads(str(Settings().value('formattingTags/html_tags'))), - 'The formatting tags should contain both the old and the new') + assert json.loads(json.dumps(result_tags)) == json.loads(str(Settings().value('formattingTags/html_tags'))), \ + 'The formatting tags should contain both the old and the new' def test_process_author(self): """ @@ -173,8 +169,8 @@ class TestOpenLyricsImport(TestCase, TestMixin): ol._process_authors(properties_xml, mocked_song) # THEN: add_author should have been called twice - self.assertEquals(mocked_song.method_calls[0][1][1], 'words+music') - self.assertEquals(mocked_song.method_calls[1][1][1], 'words') + assert mocked_song.method_calls[0][1][1] == 'words+music' + assert mocked_song.method_calls[1][1][1] == 'words' def test_process_songbooks(self): """ @@ -192,5 +188,5 @@ class TestOpenLyricsImport(TestCase, TestMixin): ol._process_songbooks(properties_xml, mocked_song) # THEN: add_songbook_entry should have been called twice - self.assertEquals(mocked_song.method_calls[0][1][1], '48') - self.assertEquals(mocked_song.method_calls[1][1][1], '445 A') + assert mocked_song.method_calls[0][1][1] == '48' + assert mocked_song.method_calls[1][1][1] == '445 A' diff --git a/tests/functional/openlp_plugins/songs/test_openoffice.py b/tests/functional/openlp_plugins/songs/test_openoffice.py index 45ef2acfd..8821865d7 100644 --- a/tests/functional/openlp_plugins/songs/test_openoffice.py +++ b/tests/functional/openlp_plugins/songs/test_openoffice.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -26,7 +26,6 @@ from unittest import TestCase, skipIf from unittest.mock import MagicMock, patch from openlp.core.common.registry import Registry - from tests.helpers.testmixin import TestMixin try: @@ -59,7 +58,7 @@ class TestOpenOfficeImport(TestCase, TestMixin): importer = OpenOfficeImport(mocked_manager, file_paths=[]) # THEN: The importer object should not be None - self.assertIsNotNone(importer, 'Import should not be none') + assert importer is not None, 'Import should not be none' @patch('openlp.plugins.songs.lib.importers.openoffice.SongImport') def test_close_ooo_file(self, mocked_songimport): @@ -76,4 +75,4 @@ class TestOpenOfficeImport(TestCase, TestMixin): importer.close_ooo_file() # THEN: The document attribute should be None even if an exception is raised') - self.assertIsNone(importer.document, 'Document should be None even if an exception is raised') + assert importer.document is None, 'Document should be None even if an exception is raised' diff --git a/tests/functional/openlp_plugins/songs/test_opensongimport.py b/tests/functional/openlp_plugins/songs/test_opensongimport.py index a8582b3e4..b4c892f3e 100644 --- a/tests/functional/openlp_plugins/songs/test_opensongimport.py +++ b/tests/functional/openlp_plugins/songs/test_opensongimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,18 +22,15 @@ """ This module contains tests for the OpenSong song importer. """ -import os from unittest import TestCase from unittest.mock import patch, MagicMock from openlp.core.common.registry import Registry -from openlp.core.common.path import Path from openlp.plugins.songs.lib.importers.opensong import OpenSongImport - from tests.helpers.songfileimport import SongImportTestHelper +from tests.utils.constants import RESOURCE_PATH -TEST_PATH = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'opensongsongs')) +TEST_PATH = RESOURCE_PATH / 'songs' / 'opensong' class TestOpenSongFileImport(SongImportTestHelper): @@ -53,16 +50,16 @@ class TestOpenSongFileImport(SongImportTestHelper): mocked_returned_settings.value.side_effect = lambda value: True if value == 'songs/enable chords' else False mocked_settings.return_value = mocked_returned_settings # Do the test import - self.file_import([Path(TEST_PATH, 'Amazing Grace')], - self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json'))) - self.file_import([Path(TEST_PATH, 'Beautiful Garden Of Prayer')], - self.load_external_result_data(os.path.join(TEST_PATH, 'Beautiful Garden Of Prayer.json'))) - self.file_import([Path(TEST_PATH, 'One, Two, Three, Four, Five')], - self.load_external_result_data(os.path.join(TEST_PATH, 'One, Two, Three, Four, Five.json'))) - self.file_import([Path(TEST_PATH, 'Amazing Grace2')], - self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json'))) - self.file_import([Path(TEST_PATH, 'Amazing Grace with bad CCLI')], - self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace without CCLI.json'))) + self.file_import([TEST_PATH / 'Amazing Grace'], + self.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) + self.file_import([TEST_PATH / 'Beautiful Garden Of Prayer'], + self.load_external_result_data(TEST_PATH / 'Beautiful Garden Of Prayer.json')) + self.file_import([TEST_PATH / 'One, Two, Three, Four, Five'], + self.load_external_result_data(TEST_PATH / 'One, Two, Three, Four, Five.json')) + self.file_import([TEST_PATH / 'Amazing Grace2'], + self.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) + self.file_import([TEST_PATH / 'Amazing Grace with bad CCLI'], + self.load_external_result_data(TEST_PATH / 'Amazing Grace without CCLI.json')) class TestOpenSongImport(TestCase): @@ -87,7 +84,7 @@ class TestOpenSongImport(TestCase): importer = OpenSongImport(mocked_manager, file_paths=[]) # THEN: The importer object should not be None - self.assertIsNotNone(importer, 'Import should not be none') + assert importer is not None, 'Import should not be none' def test_invalid_import_source(self): """ @@ -106,9 +103,9 @@ class TestOpenSongImport(TestCase): importer.import_source = source # THEN: do_import should return none and the progress bar maximum should not be set. - self.assertIsNone(importer.do_import(), 'do_import should return None when import_source is not a list') - self.assertEqual(mocked_import_wizard.progress_bar.setMaximum.called, False, - 'setMaximum on import_wizard.progress_bar should not have been called') + assert importer.do_import() is None, 'do_import should return None when import_source is not a list' + assert mocked_import_wizard.progress_bar.setMaximum.called is False, \ + 'setMaximum on import_wizard.progress_bar should not have been called' def test_valid_import_source(self): """ @@ -127,6 +124,6 @@ class TestOpenSongImport(TestCase): # THEN: do_import should return none and the progress bar setMaximum should be called with the length of # import_source. - self.assertIsNone(importer.do_import(), 'do_import should return None when import_source is a list ' - 'and stop_import_flag is True') + assert importer.do_import() is None, \ + 'do_import should return None when import_source is a list and stop_import_flag is True' mocked_import_wizard.progress_bar.setMaximum.assert_called_with(len(importer.import_source)) diff --git a/tests/functional/openlp_plugins/songs/test_opsproimport.py b/tests/functional/openlp_plugins/songs/test_opsproimport.py index 8dac8eca4..2c9e61ee9 100644 --- a/tests/functional/openlp_plugins/songs/test_opsproimport.py +++ b/tests/functional/openlp_plugins/songs/test_opsproimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,8 +22,6 @@ """ This module contains tests for the WorshipCenter Pro song importer. """ -import os -import json from unittest import TestCase, skipUnless from unittest.mock import patch, MagicMock @@ -34,7 +32,10 @@ try: except ImportError: CAN_RUN_TESTS = False -TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'opsprosongs')) +from tests.utils import load_external_result_data +from tests.utils.constants import RESOURCE_PATH + +TEST_PATH = RESOURCE_PATH / 'songs' / 'opspro' def _get_item(data, key): @@ -59,8 +60,7 @@ def _build_data(test_file, dual_language): song.Version = '1' song.Origin = '...' lyrics = MagicMock() - test_file = open(os.path.join(TEST_PATH, test_file), 'rb') - lyrics.Lyrics = test_file.read().decode() + lyrics.Lyrics = (TEST_PATH / test_file).read_bytes().decode() lyrics.Type = 1 lyrics.IsDualLanguage = dual_language return song, lyrics @@ -89,7 +89,7 @@ class TestOpsProSongImport(TestCase): importer = OPSProImport(mocked_manager, file_paths=[]) # THEN: The importer object should not be None - self.assertIsNotNone(importer, 'Import should not be none') + assert importer is not None, 'Import should not be none' @patch('openlp.plugins.songs.lib.importers.opspro.SongImport') def test_detect_chorus(self, mocked_songimport): @@ -106,10 +106,9 @@ class TestOpsProSongImport(TestCase): importer.process_song(song, lyrics, []) # THEN: The imported data should look like expected - result_file = open(os.path.join(TEST_PATH, 'You are so faithful.json'), 'rb') - result_data = json.loads(result_file.read().decode()) - self.assertListEqual(importer.verses, _get_item(result_data, 'verses')) - self.assertListEqual(importer.verse_order_list_generated, _get_item(result_data, 'verse_order_list')) + result_data = load_external_result_data(TEST_PATH / 'You are so faithful.json') + assert importer.verses == _get_item(result_data, 'verses') + assert importer.verse_order_list_generated == _get_item(result_data, 'verse_order_list') @patch('openlp.plugins.songs.lib.importers.opspro.SongImport') def test_join_and_split(self, mocked_songimport): @@ -126,10 +125,9 @@ class TestOpsProSongImport(TestCase): importer.process_song(song, lyrics, []) # THEN: The imported data should look like expected - result_file = open(os.path.join(TEST_PATH, 'Amazing Grace.json'), 'rb') - result_data = json.loads(result_file.read().decode()) - self.assertListEqual(importer.verses, _get_item(result_data, 'verses')) - self.assertListEqual(importer.verse_order_list_generated, _get_item(result_data, 'verse_order_list')) + result_data = load_external_result_data(TEST_PATH / 'Amazing Grace.json') + assert importer.verses == _get_item(result_data, 'verses') + assert importer.verse_order_list_generated == _get_item(result_data, 'verse_order_list') @patch('openlp.plugins.songs.lib.importers.opspro.SongImport') def test_trans_off_tag(self, mocked_songimport): @@ -146,10 +144,9 @@ class TestOpsProSongImport(TestCase): importer.process_song(song, lyrics, []) # THEN: The imported data should look like expected - result_file = open(os.path.join(TEST_PATH, 'Amazing Grace.json'), 'rb') - result_data = json.loads(result_file.read().decode()) - self.assertListEqual(importer.verses, _get_item(result_data, 'verses')) - self.assertListEqual(importer.verse_order_list_generated, _get_item(result_data, 'verse_order_list')) + result_data = load_external_result_data(TEST_PATH / 'Amazing Grace.json') + assert importer.verses == _get_item(result_data, 'verses') + assert importer.verse_order_list_generated == _get_item(result_data, 'verse_order_list') @patch('openlp.plugins.songs.lib.importers.opspro.SongImport') def test_trans_tag(self, mocked_songimport): @@ -166,7 +163,6 @@ class TestOpsProSongImport(TestCase): importer.process_song(song, lyrics, []) # THEN: The imported data should look like expected - result_file = open(os.path.join(TEST_PATH, 'Amazing Grace3.json'), 'rb') - result_data = json.loads(result_file.read().decode()) - self.assertListEqual(importer.verses, _get_item(result_data, 'verses')) - self.assertListEqual(importer.verse_order_list_generated, _get_item(result_data, 'verse_order_list')) + result_data = load_external_result_data(TEST_PATH / 'Amazing Grace3.json') + assert importer.verses == _get_item(result_data, 'verses') + assert importer.verse_order_list_generated == _get_item(result_data, 'verse_order_list') diff --git a/tests/functional/openlp_plugins/songs/test_powerpraiseimport.py b/tests/functional/openlp_plugins/songs/test_powerpraiseimport.py index 4df5806ae..ae823fb03 100644 --- a/tests/functional/openlp_plugins/songs/test_powerpraiseimport.py +++ b/tests/functional/openlp_plugins/songs/test_powerpraiseimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -23,14 +23,10 @@ The :mod:`powerpraiseimport` module provides the functionality for importing ProPresenter song files into the current installation database. """ -import os - -from openlp.core.common.path import Path - from tests.helpers.songfileimport import SongImportTestHelper +from tests.utils.constants import RESOURCE_PATH -TEST_PATH = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'powerpraisesongs')) +TEST_PATH = RESOURCE_PATH / 'songs' / 'powerpraise' class TestPowerPraiseFileImport(SongImportTestHelper): @@ -44,7 +40,7 @@ class TestPowerPraiseFileImport(SongImportTestHelper): """ Test that loading a PowerPraise file works correctly """ - self.file_import([Path(TEST_PATH, 'Naher, mein Gott zu Dir.ppl')], - self.load_external_result_data(os.path.join(TEST_PATH, 'Naher, mein Gott zu Dir.json'))) - self.file_import([Path(TEST_PATH, 'You are so faithful.ppl')], - self.load_external_result_data(os.path.join(TEST_PATH, 'You are so faithful.json'))) + self.file_import([TEST_PATH / 'Naher, mein Gott zu Dir.ppl'], + self.load_external_result_data(TEST_PATH / 'Naher, mein Gott zu Dir.json')) + self.file_import([TEST_PATH / 'You are so faithful.ppl'], + self.load_external_result_data(TEST_PATH / 'You are so faithful.json')) diff --git a/tests/functional/openlp_plugins/songs/test_presentationmanagerimport.py b/tests/functional/openlp_plugins/songs/test_presentationmanagerimport.py index 5391c31af..88524a38d 100644 --- a/tests/functional/openlp_plugins/songs/test_presentationmanagerimport.py +++ b/tests/functional/openlp_plugins/songs/test_presentationmanagerimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,14 +22,10 @@ """ This module contains tests for the PresentationManager song importer. """ -import os - -from openlp.core.common.path import Path - from tests.helpers.songfileimport import SongImportTestHelper +from tests.utils.constants import RESOURCE_PATH -TEST_PATH = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'presentationmanagersongs')) +TEST_PATH = RESOURCE_PATH / 'songs' / 'presentationmanager' class TestPresentationManagerFileImport(SongImportTestHelper): @@ -43,7 +39,7 @@ class TestPresentationManagerFileImport(SongImportTestHelper): """ Test that loading a PresentationManager file works correctly """ - self.file_import([Path(TEST_PATH, 'Great Is Thy Faithfulness.sng')], - self.load_external_result_data(os.path.join(TEST_PATH, 'Great Is Thy Faithfulness.json'))) - self.file_import([Path(TEST_PATH, 'Amazing Grace.sng')], - self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json'))) + self.file_import([TEST_PATH / 'Great Is Thy Faithfulness.sng'], + self.load_external_result_data(TEST_PATH / 'Great Is Thy Faithfulness.json')) + self.file_import([TEST_PATH / 'Amazing Grace.sng'], + self.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) diff --git a/tests/functional/openlp_plugins/songs/test_propresenterimport.py b/tests/functional/openlp_plugins/songs/test_propresenterimport.py index e93dd6d9f..fccae340d 100644 --- a/tests/functional/openlp_plugins/songs/test_propresenterimport.py +++ b/tests/functional/openlp_plugins/songs/test_propresenterimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -23,14 +23,10 @@ The :mod:`propresenterimport` module provides the functionality for importing ProPresenter song files into the current installation database. """ -import os - -from openlp.core.common.path import Path - from tests.helpers.songfileimport import SongImportTestHelper +from tests.utils.constants import RESOURCE_PATH -TEST_PATH = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'propresentersongs')) +TEST_PATH = RESOURCE_PATH / 'songs' / 'propresenter' class TestProPresenterFileImport(SongImportTestHelper): @@ -44,19 +40,19 @@ class TestProPresenterFileImport(SongImportTestHelper): """ Test that loading a ProPresenter 4 file works correctly """ - self.file_import([Path(TEST_PATH, 'Amazing Grace.pro4')], - self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json'))) + self.file_import([TEST_PATH / 'Amazing Grace.pro4'], + self.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) def test_pro5_song_import(self): """ Test that loading a ProPresenter 5 file works correctly """ - self.file_import([Path(TEST_PATH, 'Amazing Grace.pro5')], - self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json'))) + self.file_import([TEST_PATH / 'Amazing Grace.pro5'], + self.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) def test_pro6_song_import(self): """ Test that loading a ProPresenter 6 file works correctly """ - self.file_import([Path(TEST_PATH, 'Amazing Grace.pro6')], - self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json'))) + self.file_import([TEST_PATH / 'Amazing Grace.pro6'], + self.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) diff --git a/tests/functional/openlp_plugins/songs/test_songbeamerimport.py b/tests/functional/openlp_plugins/songs/test_songbeamerimport.py index 165abd1a9..4118ac837 100644 --- a/tests/functional/openlp_plugins/songs/test_songbeamerimport.py +++ b/tests/functional/openlp_plugins/songs/test_songbeamerimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,18 +22,15 @@ """ This module contains tests for the Songbeamer song importer. """ -import os from unittest import TestCase from unittest.mock import MagicMock, patch from openlp.core.common.registry import Registry -from openlp.core.common.path import Path from openlp.plugins.songs.lib.importers.songbeamer import SongBeamerImport, SongBeamerTypes - from tests.helpers.songfileimport import SongImportTestHelper +from tests.utils.constants import RESOURCE_PATH -TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), - '..', '..', '..', 'resources', 'songbeamersongs')) +TEST_PATH = RESOURCE_PATH / 'songs' / 'songbeamer' class TestSongBeamerFileImport(SongImportTestHelper): @@ -52,19 +49,19 @@ class TestSongBeamerFileImport(SongImportTestHelper): mocked_returned_settings = MagicMock() mocked_returned_settings.value.side_effect = lambda value: True if value == 'songs/enable chords' else False mocked_settings.return_value = mocked_returned_settings - self.file_import([Path(TEST_PATH, 'Amazing Grace.sng')], - self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json'))) - self.file_import([Path(TEST_PATH, 'Lobsinget dem Herrn.sng')], - self.load_external_result_data(os.path.join(TEST_PATH, 'Lobsinget dem Herrn.json'))) - self.file_import([Path(TEST_PATH, 'When I Call On You.sng')], - self.load_external_result_data(os.path.join(TEST_PATH, 'When I Call On You.json'))) + self.file_import([TEST_PATH / 'Amazing Grace.sng'], + self.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) + self.file_import([TEST_PATH / 'Lobsinget dem Herrn.sng'], + self.load_external_result_data(TEST_PATH / 'Lobsinget dem Herrn.json')) + self.file_import([TEST_PATH / 'When I Call On You.sng'], + self.load_external_result_data(TEST_PATH / 'When I Call On You.json')) def test_cp1252_encoded_file(self): """ Test that a CP1252 encoded file get's decoded properly. """ - self.file_import([Path(TEST_PATH, 'cp1252song.sng')], - self.load_external_result_data(os.path.join(TEST_PATH, 'cp1252song.json'))) + self.file_import([TEST_PATH / 'cp1252song.sng'], + self.load_external_result_data(TEST_PATH / 'cp1252song.json')) class TestSongBeamerImport(TestCase): @@ -99,7 +96,7 @@ class TestSongBeamerImport(TestCase): importer = SongBeamerImport(mocked_manager, file_paths=[]) # THEN: The importer object should not be None - self.assertIsNotNone(importer, 'Import should not be none') + assert importer is not None, 'Import should not be none' def test_invalid_import_source(self): """ @@ -115,10 +112,10 @@ class TestSongBeamerImport(TestCase): self.importer.import_source = source # THEN: do_import should return none and the progress bar maximum should not be set. - self.assertIsNone(self.importer.do_import(), - 'do_import should return None when import_source is not a list') - self.assertEqual(mocked_import_wizard.progress_bar.setMaximum.called, False, - 'setMaxium on import_wizard.progress_bar should not have been called') + assert self.importer.do_import() is None, \ + 'do_import should return None when import_source is not a list' + assert mocked_import_wizard.progress_bar.setMaximum.called is False, \ + 'setMaxium on import_wizard.progress_bar should not have been called' def test_valid_import_source(self): """ @@ -134,8 +131,8 @@ class TestSongBeamerImport(TestCase): # THEN: do_import should return none and the progress bar setMaximum should be called with the length of # import_source. - self.assertIsNone(self.importer.do_import(), - 'do_import should return None when import_source is a list and stop_import_flag is True') + assert self.importer.do_import() is None, \ + 'do_import should return None when import_source is a list and stop_import_flag is True' mocked_import_wizard.progress_bar.setMaximum.assert_called_with(len(self.importer.import_source)) def test_check_verse_marks(self): @@ -149,8 +146,8 @@ class TestSongBeamerImport(TestCase): # WHEN: line is being checked for verse marks result = self.importer.check_verse_marks(line) # THEN: we should get back true and c as self.importer.current_verse_type - self.assertTrue(result, 'Versemark for should be found, value true') - self.assertEqual(self.importer.current_verse_type, 'c', ' should be interpreted as ') + assert result is True, 'Versemark for should be found, value true' + assert self.importer.current_verse_type == 'c', ' should be interpreted as ' # GIVEN: line with unnumbered verse-type and trailing space line = 'ReFrain ' @@ -158,8 +155,8 @@ class TestSongBeamerImport(TestCase): # WHEN: line is being checked for verse marks result = self.importer.check_verse_marks(line) # THEN: we should get back true and c as self.importer.current_verse_type - self.assertTrue(result, 'Versemark for should be found, value true') - self.assertEqual(self.importer.current_verse_type, 'c', ' should be interpreted as ') + assert result is True, 'Versemark for should be found, value true' + assert self.importer.current_verse_type == 'c', ' should be interpreted as ' # GIVEN: line with numbered verse-type line = 'VersE 1' @@ -167,8 +164,8 @@ class TestSongBeamerImport(TestCase): # WHEN: line is being checked for verse marks result = self.importer.check_verse_marks(line) # THEN: we should get back true and v1 as self.importer.current_verse_type - self.assertTrue(result, 'Versemark for should be found, value true') - self.assertEqual(self.importer.current_verse_type, 'v1', u' should be interpreted as ') + assert result is True, 'Versemark for should be found, value true' + assert self.importer.current_verse_type == 'v1', u' should be interpreted as ' # GIVEN: line with special unnumbered verse-mark (used in Songbeamer to allow usage of non-supported tags) line = '$$M=special' @@ -176,8 +173,8 @@ class TestSongBeamerImport(TestCase): # WHEN: line is being checked for verse marks result = self.importer.check_verse_marks(line) # THEN: we should get back true and o as self.importer.current_verse_type - self.assertTrue(result, 'Versemark for <$$M=special> should be found, value true') - self.assertEqual(self.importer.current_verse_type, 'o', u'<$$M=special> should be interpreted as ') + assert result is True, 'Versemark for <$$M=special> should be found, value true' + assert self.importer.current_verse_type == 'o', u'<$$M=special> should be interpreted as ' # GIVEN: line with song-text with 3 words line = 'Jesus my saviour' @@ -185,9 +182,8 @@ class TestSongBeamerImport(TestCase): # WHEN: line is being checked for verse marks result = self.importer.check_verse_marks(line) # THEN: we should get back false and none as self.importer.current_verse_type - self.assertFalse(result, 'No versemark for should be found, value false') - self.assertIsNone(self.importer.current_verse_type, - ' should be interpreted as none versemark') + assert result is False, 'No versemark for should be found, value false' + assert self.importer.current_verse_type is None, ' should be interpreted as none versemark' # GIVEN: line with song-text with 2 words line = 'Praise him' @@ -195,8 +191,8 @@ class TestSongBeamerImport(TestCase): # WHEN: line is being checked for verse marks result = self.importer.check_verse_marks(line) # THEN: we should get back false and none as self.importer.current_verse_type - self.assertFalse(result, 'No versemark for should be found, value false') - self.assertIsNone(self.importer.current_verse_type, ' should be interpreted as none versemark') + assert result is False, 'No versemark for should be found, value false' + assert self.importer.current_verse_type is None, ' should be interpreted as none versemark' # GIVEN: line with only a space (could occur, nothing regular) line = ' ' @@ -204,8 +200,8 @@ class TestSongBeamerImport(TestCase): # WHEN: line is being checked for verse marks result = self.importer.check_verse_marks(line) # THEN: we should get back false and none as self.importer.current_verse_type - self.assertFalse(result, 'No versemark for < > should be found, value false') - self.assertIsNone(self.importer.current_verse_type, '< > should be interpreted as none versemark') + assert result is False, 'No versemark for < > should be found, value false' + assert self.importer.current_verse_type is None, '< > should be interpreted as none versemark' # GIVEN: blank line (could occur, nothing regular) line = '' @@ -213,8 +209,8 @@ class TestSongBeamerImport(TestCase): # WHEN: line is being checked for verse marks result = self.importer.check_verse_marks(line) # THEN: we should get back false and none as self.importer.current_verse_type - self.assertFalse(result, 'No versemark for <> should be found, value false') - self.assertIsNone(self.importer.current_verse_type, '<> should be interpreted as none versemark') + assert result is False, 'No versemark for <> should be found, value false' + assert self.importer.current_verse_type is None, '<> should be interpreted as none versemark' def test_verse_marks_defined_in_lowercase(self): """ @@ -223,4 +219,4 @@ class TestSongBeamerImport(TestCase): # GIVEN: SongBeamber MarkTypes for tag in SongBeamerTypes.MarkTypes.keys(): # THEN: tag should be defined in lowercase - self.assertEquals(tag, tag.lower(), 'Tags should be defined in lowercase') + assert tag == tag.lower(), 'Tags should be defined in lowercase' diff --git a/tests/functional/openlp_plugins/songs/test_songformat.py b/tests/functional/openlp_plugins/songs/test_songformat.py index 4573613a4..c1e674a03 100644 --- a/tests/functional/openlp_plugins/songs/test_songformat.py +++ b/tests/functional/openlp_plugins/songs/test_songformat.py @@ -39,8 +39,8 @@ class TestSongFormat(TestCase): # GIVEN: The SongFormat class # WHEN: Retrieving the format list # THEN: All SongFormats should be returned - self.assertEquals(len(SongFormat.get_format_list()), len(SongFormat.__attributes__), - "The returned SongFormats don't match the stored ones") + assert len(SongFormat.get_format_list()) == len(SongFormat.__attributes__), \ + "The returned SongFormats don't match the stored ones" def test_get_attributed_no_attributes(self): """ @@ -50,8 +50,8 @@ class TestSongFormat(TestCase): # WHEN: Retrieving all attributes of a SongFormat for song_format in SongFormat.get_format_list(): # THEN: All attributes associated with the SongFormat should be returned - self.assertEquals(SongFormat.get(song_format), SongFormat.__attributes__[song_format], - "The returned attributes don't match the stored ones") + assert SongFormat.get(song_format) == SongFormat.__attributes__[song_format], \ + "The returned attributes don't match the stored ones" def test_get_attributed_single_attribute(self): """ @@ -62,14 +62,14 @@ class TestSongFormat(TestCase): # WHEN: Retrieving an attribute that overrides the default values for attribute in SongFormat.get(song_format).keys(): # THEN: Return the attribute - self.assertEquals(SongFormat.get(song_format, attribute), SongFormat.get(song_format)[attribute], - "The returned attribute doesn't match the stored one") + assert SongFormat.get(song_format, attribute) == SongFormat.get(song_format)[attribute], \ + "The returned attribute doesn't match the stored one" # WHEN: Retrieving an attribute that was not overridden for attribute in SongFormat.__defaults__.keys(): if attribute not in SongFormat.get(song_format).keys(): # THEN: Return the default value - self.assertEquals(SongFormat.get(song_format, attribute), SongFormat.__defaults__[attribute], - "The returned attribute does not match the default values stored") + assert SongFormat.get(song_format, attribute) == SongFormat.__defaults__[attribute], \ + "The returned attribute does not match the default values stored" def test_get_attributed_multiple_attributes(self): """ @@ -79,9 +79,8 @@ class TestSongFormat(TestCase): # WHEN: Retrieving multiple attributes at the same time for song_format in SongFormat.get_format_list(): # THEN: Return all attributes that were specified - self.assertEquals(len(SongFormat.get(song_format, 'canDisable', 'availability')), 2, - "Did not return the correct number of attributes" - " when retrieving multiple attributes at once") + assert len(SongFormat.get(song_format, 'canDisable', 'availability')) == 2, \ + "Did not return the correct number of attributes when retrieving multiple attributes at once" def test_get_format_list_returns_ordered_list(self): """ @@ -91,5 +90,5 @@ class TestSongFormat(TestCase): # GIVEN: The SongFormat class # WHEN: Retrieving all formats # THEN: The returned list should be sorted according to the ordering defined in SongFormat - self.assertEquals(sorted(SongFormat.get_format_list()), SongFormat.get_format_list(), - "The list returned should be sorted according to the ordering in SongFormat") + assert sorted(SongFormat.get_format_list()) == SongFormat.get_format_list(), \ + "The list returned should be sorted according to the ordering in SongFormat" diff --git a/tests/functional/openlp_plugins/songs/test_songproimport.py b/tests/functional/openlp_plugins/songs/test_songproimport.py index 4e874165b..4b3b7884c 100644 --- a/tests/functional/openlp_plugins/songs/test_songproimport.py +++ b/tests/functional/openlp_plugins/songs/test_songproimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -23,14 +23,10 @@ The :mod:`songproimport` module provides the functionality for importing SongPro song files into the current installation database. """ -import os - -from openlp.core.common.path import Path - from tests.helpers.songfileimport import SongImportTestHelper +from tests.utils.constants import RESOURCE_PATH -TEST_PATH = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'songprosongs')) +TEST_PATH = RESOURCE_PATH / 'songs' / 'songpro' class TestSongProFileImport(SongImportTestHelper): @@ -44,5 +40,5 @@ class TestSongProFileImport(SongImportTestHelper): """ Test that loading an SongPro file works correctly """ - self.file_import(Path(TEST_PATH, 'amazing-grace.txt'), - self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json'))) + self.file_import(TEST_PATH / 'amazing-grace.txt', + self.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) diff --git a/tests/functional/openlp_plugins/songs/test_songselect.py b/tests/functional/openlp_plugins/songs/test_songselect.py index fa2b2931d..aa55fca20 100644 --- a/tests/functional/openlp_plugins/songs/test_songselect.py +++ b/tests/functional/openlp_plugins/songs/test_songselect.py @@ -5,7 +5,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -23,7 +23,6 @@ """ This module contains tests for the CCLI SongSelect importer. """ -import os from unittest import TestCase from unittest.mock import MagicMock, patch, call from urllib.error import URLError @@ -31,16 +30,14 @@ from urllib.error import URLError from PyQt5 import QtWidgets from openlp.core.common.registry import Registry -from openlp.core.common.path import Path from openlp.plugins.songs.forms.songselectform import SongSelectForm, SearchWorker from openlp.plugins.songs.lib import Song from openlp.plugins.songs.lib.songselect import SongSelectImport, LOGOUT_URL, BASE_URL - from tests.helpers.songfileimport import SongImportTestHelper from tests.helpers.testmixin import TestMixin +from tests.utils.constants import RESOURCE_PATH -TEST_PATH = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'songselect')) +TEST_PATH = RESOURCE_PATH / 'songs' / 'songselect' class TestSongSelectImport(TestCase, TestMixin): @@ -57,10 +54,10 @@ class TestSongSelectImport(TestCase, TestMixin): importer = SongSelectImport(None) # THEN: The object should have the correct properties - self.assertIsNone(importer.db_manager, 'The db_manager should be None') - self.assertIsNotNone(importer.html_parser, 'There should be a valid html_parser object') - self.assertIsNotNone(importer.opener, 'There should be a valid opener object') - self.assertEqual(1, mocked_build_opener.call_count, 'The build_opener method should have been called once') + assert importer.db_manager is None, 'The db_manager should be None' + assert importer.html_parser is not None, 'There should be a valid html_parser object' + assert importer.opener is not None, 'There should be a valid opener object' + assert 1 == mocked_build_opener.call_count, 'The build_opener method should have been called once' @patch('openlp.plugins.songs.lib.songselect.build_opener') @patch('openlp.plugins.songs.lib.songselect.BeautifulSoup') @@ -83,11 +80,11 @@ class TestSongSelectImport(TestCase, TestMixin): result = importer.login('username', 'password', mock_callback) # THEN: callback was called 3 times, open was called twice, find was called twice, and False was returned - self.assertEqual(3, mock_callback.call_count, 'callback should have been called 3 times') - self.assertEqual(2, mocked_login_page.find.call_count, 'find should have been called twice') - self.assertEqual(1, mocked_posted_page.find.call_count, 'find should have been called once') - self.assertEqual(2, mocked_opener.open.call_count, 'opener should have been called twice') - self.assertFalse(result, 'The login method should have returned False') + assert 3 == mock_callback.call_count, 'callback should have been called 3 times' + assert 2 == mocked_login_page.find.call_count, 'find should have been called twice' + assert 1 == mocked_posted_page.find.call_count, 'find should have been called once' + assert 2 == mocked_opener.open.call_count, 'opener should have been called twice' + assert result is False, 'The login method should have returned False' @patch('openlp.plugins.songs.lib.songselect.build_opener') def test_login_except(self, mocked_build_opener): @@ -103,8 +100,8 @@ class TestSongSelectImport(TestCase, TestMixin): result = importer.login('username', 'password', mock_callback) # THEN: callback was called 1 time and False was returned - self.assertEqual(1, mock_callback.call_count, 'callback should have been called 1 times') - self.assertFalse(result, 'The login method should have returned False') + assert 1 == mock_callback.call_count, 'callback should have been called 1 times' + assert result is False, 'The login method should have returned False' @patch('openlp.plugins.songs.lib.songselect.build_opener') @patch('openlp.plugins.songs.lib.songselect.BeautifulSoup') @@ -127,11 +124,11 @@ class TestSongSelectImport(TestCase, TestMixin): result = importer.login('username', 'password', mock_callback) # THEN: callback was called 3 times, open was called twice, find was called twice, and True was returned - self.assertEqual(3, mock_callback.call_count, 'callback should have been called 3 times') - self.assertEqual(2, mocked_login_page.find.call_count, 'find should have been called twice on the login page') - self.assertEqual(1, mocked_posted_page.find.call_count, 'find should have been called once on the posted page') - self.assertEqual(2, mocked_opener.open.call_count, 'opener should have been called twice') - self.assertTrue(result, 'The login method should have returned True') + assert 3 == mock_callback.call_count, 'callback should have been called 3 times' + assert 2 == mocked_login_page.find.call_count, 'find should have been called twice on the login page' + assert 1 == mocked_posted_page.find.call_count, 'find should have been called once on the posted page' + assert 2 == mocked_opener.open.call_count, 'opener should have been called twice' + assert result is True, 'The login method should have returned True' @patch('openlp.plugins.songs.lib.songselect.build_opener') @patch('openlp.plugins.songs.lib.songselect.BeautifulSoup') @@ -156,11 +153,11 @@ class TestSongSelectImport(TestCase, TestMixin): result = importer.login('username', 'password', mock_callback) # THEN: callback was called 3 times, open was called twice, find was called twice, and True was returned - self.assertEqual(3, mock_callback.call_count, 'callback should have been called 3 times') - self.assertEqual(2, mocked_login_page.find.call_count, 'find should have been called twice on the login page') - self.assertEqual(1, mocked_posted_page.find.call_count, 'find should have been called once on the posted page') - self.assertEqual('https://profile.ccli.com/do/login', mocked_opener.open.call_args_list[1][0][0]) - self.assertTrue(result, 'The login method should have returned True') + assert 3 == mock_callback.call_count, 'callback should have been called 3 times' + assert 2 == mocked_login_page.find.call_count, 'find should have been called twice on the login page' + assert 1 == mocked_posted_page.find.call_count, 'find should have been called once on the posted page' + assert 'https://profile.ccli.com/do/login', mocked_opener.open.call_args_list[1][0][0] + assert result is True, 'The login method should have returned True' @patch('openlp.plugins.songs.lib.songselect.build_opener') def test_logout(self, mocked_build_opener): @@ -176,7 +173,7 @@ class TestSongSelectImport(TestCase, TestMixin): importer.logout() # THEN: The opener is called once with the logout url - self.assertEqual(1, mocked_opener.open.call_count, 'opener should have been called once') + assert 1 == mocked_opener.open.call_count, 'opener should have been called once' mocked_opener.open.assert_called_with(LOGOUT_URL) @patch('openlp.plugins.songs.lib.songselect.build_opener') @@ -198,11 +195,11 @@ class TestSongSelectImport(TestCase, TestMixin): results = importer.search('text', 1000, mock_callback) # THEN: callback was never called, open was called once, find_all was called once, an empty list returned - self.assertEqual(0, mock_callback.call_count, 'callback should not have been called') - self.assertEqual(1, mocked_opener.open.call_count, 'open should have been called once') - self.assertEqual(1, mocked_results_page.find_all.call_count, 'find_all should have been called once') + assert 0 == mock_callback.call_count, 'callback should not have been called' + assert 1 == mocked_opener.open.call_count, 'open should have been called once' + assert 1 == mocked_results_page.find_all.call_count, 'find_all should have been called once' mocked_results_page.find_all.assert_called_with('div', 'song-result') - self.assertEqual([], results, 'The search method should have returned an empty list') + assert [] == results, 'The search method should have returned an empty list' @patch('openlp.plugins.songs.lib.songselect.build_opener') @patch('openlp.plugins.songs.lib.songselect.BeautifulSoup') @@ -238,15 +235,15 @@ class TestSongSelectImport(TestCase, TestMixin): results = importer.search('text', 1000, mock_callback) # THEN: callback was never called, open was called once, find_all was called once, an empty list returned - self.assertEqual(2, mock_callback.call_count, 'callback should have been called twice') - self.assertEqual(2, mocked_opener.open.call_count, 'open should have been called twice') - self.assertEqual(2, mocked_results_page.find_all.call_count, 'find_all should have been called twice') + assert 2 == mock_callback.call_count, 'callback should have been called twice' + assert 2 == mocked_opener.open.call_count, 'open should have been called twice' + assert 2 == mocked_results_page.find_all.call_count, 'find_all should have been called twice' mocked_results_page.find_all.assert_called_with('div', 'song-result') expected_list = [ {'title': 'Title 1', 'authors': ['James', 'John'], 'link': BASE_URL + '/url1'}, {'title': 'Title 2', 'authors': ['Philip'], 'link': BASE_URL + '/url2'} ] - self.assertListEqual(expected_list, results, 'The search method should have returned two songs') + assert expected_list == results, 'The search method should have returned two songs' @patch('openlp.plugins.songs.lib.songselect.build_opener') @patch('openlp.plugins.songs.lib.songselect.BeautifulSoup') @@ -289,13 +286,13 @@ class TestSongSelectImport(TestCase, TestMixin): results = importer.search('text', 2, mock_callback) # THEN: callback was called twice, open was called twice, find_all was called twice, max results returned - self.assertEqual(2, mock_callback.call_count, 'callback should have been called twice') - self.assertEqual(2, mocked_opener.open.call_count, 'open should have been called twice') - self.assertEqual(2, mocked_results_page.find_all.call_count, 'find_all should have been called twice') + assert 2 == mock_callback.call_count, 'callback should have been called twice' + assert 2 == mocked_opener.open.call_count, 'open should have been called twice' + assert 2 == mocked_results_page.find_all.call_count, 'find_all should have been called twice' mocked_results_page.find_all.assert_called_with('div', 'song-result') expected_list = [{'title': 'Title 1', 'authors': ['James', 'John'], 'link': BASE_URL + '/url1'}, {'title': 'Title 2', 'authors': ['Philip'], 'link': BASE_URL + '/url2'}] - self.assertListEqual(expected_list, results, 'The search method should have returned two songs') + assert expected_list == results, 'The search method should have returned two songs' @patch('openlp.plugins.songs.lib.songselect.build_opener') @patch('openlp.plugins.songs.lib.songselect.BeautifulSoup') @@ -311,7 +308,7 @@ class TestSongSelectImport(TestCase, TestMixin): importer.stop() # THEN: Searching should have stopped - self.assertFalse(importer.run_search, 'Searching should have been stopped') + assert importer.run_search is False, 'Searching should have been stopped' @patch('openlp.plugins.songs.lib.songselect.build_opener') def test_get_song_page_raises_exception(self, mocked_build_opener): @@ -330,7 +327,7 @@ class TestSongSelectImport(TestCase, TestMixin): # THEN: The callback should have been called once and None should be returned mocked_callback.assert_called_with() - self.assertIsNone(result, 'The get_song() method should have returned None') + assert result is None, 'The get_song() method should have returned None' @patch('openlp.plugins.songs.lib.songselect.build_opener') @patch('openlp.plugins.songs.lib.songselect.BeautifulSoup') @@ -347,8 +344,8 @@ class TestSongSelectImport(TestCase, TestMixin): result = importer.get_song({'link': 'link'}, callback=mocked_callback) # THEN: The callback should have been called twice and None should be returned - self.assertEqual(2, mocked_callback.call_count, 'The callback should have been called twice') - self.assertIsNone(result, 'The get_song() method should have returned None') + assert 2 == mocked_callback.call_count, 'The callback should have been called twice' + assert result is None, 'The get_song() method should have returned None' @patch('openlp.plugins.songs.lib.songselect.build_opener') @patch('openlp.plugins.songs.lib.songselect.BeautifulSoup') @@ -384,19 +381,18 @@ class TestSongSelectImport(TestCase, TestMixin): result = importer.get_song(fake_song, callback=mocked_callback) # THEN: The callback should have been called three times and the song should be returned - self.assertEqual(3, mocked_callback.call_count, 'The callback should have been called twice') - self.assertIsNotNone(result, 'The get_song() method should have returned a song dictionary') - self.assertEqual(2, mocked_lyrics_page.find.call_count, 'The find() method should have been called twice') - self.assertEqual(2, mocked_find_all.call_count, 'The find_all() method should have been called twice') - self.assertEqual([call('div', 'song-viewer lyrics'), call('div', 'song-viewer lyrics')], - mocked_lyrics_page.find.call_args_list, - 'The find() method should have been called with the right arguments') - self.assertEqual([call('p'), call('h3')], mocked_find_all.call_args_list, - 'The find_all() method should have been called with the right arguments') - self.assertIn('copyright', result, 'The returned song should have a copyright') - self.assertIn('ccli_number', result, 'The returned song should have a CCLI number') - self.assertIn('verses', result, 'The returned song should have verses') - self.assertEqual(3, len(result['verses']), 'Three verses should have been returned') + assert 3 == mocked_callback.call_count, 'The callback should have been called twice' + assert result is not None, 'The get_song() method should have returned a song dictionary' + assert 2 == mocked_lyrics_page.find.call_count, 'The find() method should have been called twice' + assert 2 == mocked_find_all.call_count, 'The find_all() method should have been called twice' + assert [call('div', 'song-viewer lyrics'), call('div', 'song-viewer lyrics')] == \ + mocked_lyrics_page.find.call_args_list, 'The find() method should have been called with the right arguments' + assert [call('p'), call('h3')] == mocked_find_all.call_args_list, \ + 'The find_all() method should have been called with the right arguments' + assert 'copyright' in result, 'The returned song should have a copyright' + assert 'ccli_number' in result, 'The returned song should have a CCLI number' + assert 'verses' in result, 'The returned song should have verses' + assert 3 == len(result['verses']), 'Three verses should have been returned' @patch('openlp.plugins.songs.lib.songselect.clean_song') @patch('openlp.plugins.songs.lib.songselect.Topic') @@ -427,14 +423,13 @@ class TestSongSelectImport(TestCase, TestMixin): result = importer.save_song(song_dict) # THEN: The return value should be a Song class and the mocked_db_manager should have been called - self.assertIsInstance(result, Song, 'The returned value should be a Song object') + assert isinstance(result, Song), 'The returned value should be a Song object' mocked_clean_song.assert_called_with(mocked_db_manager, result) - self.assertEqual(2, mocked_db_manager.save_object.call_count, - 'The save_object() method should have been called twice') + assert 2 == mocked_db_manager.save_object.call_count, \ + 'The save_object() method should have been called twice' mocked_db_manager.get_object_filtered.assert_called_with(MockedAuthor, False) - MockedAuthor.populate.assert_called_with(first_name='Public', last_name='Domain', - display_name='Public Domain') - self.assertEqual(1, len(result.authors_songs), 'There should only be one author') + MockedAuthor.populate.assert_called_with(first_name='Public', last_name='Domain', display_name='Public Domain') + assert 1 == len(result.authors_songs), 'There should only be one author' @patch('openlp.plugins.songs.lib.songselect.clean_song') @patch('openlp.plugins.songs.lib.songselect.Author') @@ -463,13 +458,13 @@ class TestSongSelectImport(TestCase, TestMixin): result = importer.save_song(song_dict) # THEN: The return value should be a Song class and the mocked_db_manager should have been called - self.assertIsInstance(result, Song, 'The returned value should be a Song object') + assert isinstance(result, Song), 'The returned value should be a Song object' mocked_clean_song.assert_called_with(mocked_db_manager, result) - self.assertEqual(2, mocked_db_manager.save_object.call_count, - 'The save_object() method should have been called twice') + assert 2 == mocked_db_manager.save_object.call_count, \ + 'The save_object() method should have been called twice' mocked_db_manager.get_object_filtered.assert_called_with(MockedAuthor, False) - self.assertEqual(0, MockedAuthor.populate.call_count, 'A new author should not have been instantiated') - self.assertEqual(1, len(result.authors_songs), 'There should only be one author') + assert 0 == MockedAuthor.populate.call_count, 'A new author should not have been instantiated' + assert 1 == len(result.authors_songs), 'There should only be one author' @patch('openlp.plugins.songs.lib.songselect.clean_song') @patch('openlp.plugins.songs.lib.songselect.Author') @@ -498,14 +493,13 @@ class TestSongSelectImport(TestCase, TestMixin): result = importer.save_song(song_dict) # THEN: The return value should be a Song class and the mocked_db_manager should have been called - self.assertIsInstance(result, Song, 'The returned value should be a Song object') + assert isinstance(result, Song), 'The returned value should be a Song object' mocked_clean_song.assert_called_with(mocked_db_manager, result) - self.assertEqual(2, mocked_db_manager.save_object.call_count, - 'The save_object() method should have been called twice') + assert 2 == mocked_db_manager.save_object.call_count, \ + 'The save_object() method should have been called twice' mocked_db_manager.get_object_filtered.assert_called_with(MockedAuthor, False) - MockedAuthor.populate.assert_called_with(first_name='Unknown', last_name='', - display_name='Unknown') - self.assertEqual(1, len(result.authors_songs), 'There should only be one author') + MockedAuthor.populate.assert_called_with(first_name='Unknown', last_name='', display_name='Unknown') + assert 1 == len(result.authors_songs), 'There should only be one author' class TestSongSelectForm(TestCase, TestMixin): @@ -534,8 +528,8 @@ class TestSongSelectForm(TestCase, TestMixin): ssform = SongSelectForm(None, mocked_plugin, mocked_db_manager) # THEN: The correct properties should have been assigned - self.assertEqual(mocked_plugin, ssform.plugin, 'The correct plugin should have been assigned') - self.assertEqual(mocked_db_manager, ssform.db_manager, 'The correct db_manager should have been assigned') + assert mocked_plugin == ssform.plugin, 'The correct plugin should have been assigned' + assert mocked_db_manager == ssform.db_manager, 'The correct db_manager should have been assigned' @patch('openlp.plugins.songs.forms.songselectform.SongSelectImport') @patch('openlp.plugins.songs.forms.songselectform.QtWidgets.QMessageBox.critical') @@ -570,23 +564,21 @@ class TestSongSelectForm(TestCase, TestMixin): expected_login_spacer_calls = [call(False), call(True)] expected_login_progress_visible_calls = [call(True), call(False)] expected_login_progress_value_calls = [call(0), call(0)] - self.assertEqual(expected_username_calls, mocked_username_edit.setEnabled.call_args_list, - 'The username edit should be disabled then enabled') - self.assertEqual(expected_password_calls, mocked_password_edit.setEnabled.call_args_list, - 'The password edit should be disabled then enabled') - self.assertEqual(expected_save_password_calls, mocked_save_password_checkbox.setEnabled.call_args_list, - 'The save password checkbox should be disabled then enabled') - self.assertEqual(expected_login_btn_calls, mocked_login_button.setEnabled.call_args_list, - 'The login button should be disabled then enabled') - self.assertEqual(expected_login_spacer_calls, mocked_login_spacer.setVisible.call_args_list, - 'Thee login spacer should be make invisible, then visible') - self.assertEqual(expected_login_progress_visible_calls, - mocked_login_progress_bar.setVisible.call_args_list, - 'Thee login progress bar should be make visible, then invisible') - self.assertEqual(expected_login_progress_value_calls, mocked_login_progress_bar.setValue.call_args_list, - 'Thee login progress bar should have the right values set') - self.assertEqual(2, mocked_process_events.call_count, - 'The process_events() method should be called twice') + assert expected_username_calls == mocked_username_edit.setEnabled.call_args_list, \ + 'The username edit should be disabled then enabled' + assert expected_password_calls == mocked_password_edit.setEnabled.call_args_list, \ + 'The password edit should be disabled then enabled' + assert expected_save_password_calls == mocked_save_password_checkbox.setEnabled.call_args_list, \ + 'The save password checkbox should be disabled then enabled' + assert expected_login_btn_calls == mocked_login_button.setEnabled.call_args_list, \ + 'The login button should be disabled then enabled' + assert expected_login_spacer_calls == mocked_login_spacer.setVisible.call_args_list, \ + 'Thee login spacer should be make invisible, then visible' + assert expected_login_progress_visible_calls == mocked_login_progress_bar.setVisible.call_args_list, \ + 'Thee login progress bar should be make visible, then invisible' + assert expected_login_progress_value_calls == mocked_login_progress_bar.setValue.call_args_list, \ + 'Thee login progress bar should have the right values set' + assert 2 == mocked_process_events.call_count, 'The process_events() method should be called twice' mocked_critical.assert_called_with(ssform, 'Error Logging In', 'There was a problem logging in, ' 'perhaps your username or password is ' 'incorrect?') @@ -615,7 +607,7 @@ class TestSongSelectForm(TestCase, TestMixin): 'Your song has been imported, would you like to import more songs?', defaultButton=QtWidgets.QMessageBox.Yes) mocked_on_back_button_clicked.assert_called_with() - self.assertIsNone(ssform.song) + assert ssform.song is None @patch('openlp.plugins.songs.forms.songselectform.QtWidgets.QMessageBox.question') @patch('openlp.plugins.songs.forms.songselectform.translate') @@ -641,7 +633,7 @@ class TestSongSelectForm(TestCase, TestMixin): 'Your song has been imported, would you like to import more songs?', defaultButton=QtWidgets.QMessageBox.Yes) mocked_done.assert_called_with(QtWidgets.QDialog.Accepted) - self.assertIsNone(ssform.song) + assert ssform.song is None def test_on_back_button_clicked(self): """ @@ -769,13 +761,13 @@ class TestSongSelectForm(TestCase, TestMixin): # THEN: The view button, search box and search button should be enabled mocked_song_select_importer.stop.assert_called_with() - self.assertTrue(ssform.search_button.isEnabled()) - self.assertTrue(ssform.search_combobox.isEnabled()) + assert ssform.search_button.isEnabled() is True + assert ssform.search_combobox.isEnabled() is True @patch('openlp.plugins.songs.forms.songselectform.Settings') - @patch('openlp.plugins.songs.forms.songselectform.QtCore.QThread') + @patch('openlp.plugins.songs.forms.songselectform.run_thread') @patch('openlp.plugins.songs.forms.songselectform.SearchWorker') - def test_on_search_button_clicked(self, MockedSearchWorker, MockedQtThread, MockedSettings): + def test_on_search_button_clicked(self, MockedSearchWorker, mocked_run_thread, MockedSettings): """ Test that search fields are disabled when search button is clicked. """ @@ -787,8 +779,8 @@ class TestSongSelectForm(TestCase, TestMixin): ssform.on_search_button_clicked() # THEN: The search box and search button should be disabled - self.assertFalse(ssform.search_button.isEnabled()) - self.assertFalse(ssform.search_combobox.isEnabled()) + assert ssform.search_button.isEnabled() is False + assert ssform.search_combobox.isEnabled() is False def test_on_search_finished(self): """ @@ -802,8 +794,8 @@ class TestSongSelectForm(TestCase, TestMixin): ssform.on_search_finished() # THEN: The search box and search button should be enabled - self.assertTrue(ssform.search_button.isEnabled()) - self.assertTrue(ssform.search_combobox.isEnabled()) + assert ssform.search_button.isEnabled() is True + assert ssform.search_combobox.isEnabled() is True class TestSongSelectFileImport(SongImportTestHelper): @@ -817,10 +809,8 @@ class TestSongSelectFileImport(SongImportTestHelper): """ Test that loading an OpenSong file works correctly on various files """ - self.file_import([Path(TEST_PATH, 'TestSong.bin')], - self.load_external_result_data(os.path.join(TEST_PATH, 'TestSong-bin.json'))) - self.file_import([Path(TEST_PATH, 'TestSong.txt')], - self.load_external_result_data(os.path.join(TEST_PATH, 'TestSong-txt.json'))) + self.file_import([TEST_PATH / 'TestSong.bin'], self.load_external_result_data(TEST_PATH / 'TestSong-bin.json')) + self.file_import([TEST_PATH / 'TestSong.txt'], self.load_external_result_data(TEST_PATH / 'TestSong-txt.json')) class TestSearchWorker(TestCase, TestMixin): @@ -839,8 +829,8 @@ class TestSearchWorker(TestCase, TestMixin): worker = SearchWorker(importer, search_text) # THEN: The correct values should be set - self.assertIs(importer, worker.importer, 'The importer should be the right object') - self.assertEqual(search_text, worker.search_text, 'The search text should be correct') + assert importer is worker.importer, 'The importer should be the right object' + assert search_text == worker.search_text, 'The search text should be correct' def test_start(self): """ diff --git a/tests/functional/openlp_plugins/songs/test_songshowplusimport.py b/tests/functional/openlp_plugins/songs/test_songshowplusimport.py index 79e8ba593..9f3df41a9 100644 --- a/tests/functional/openlp_plugins/songs/test_songshowplusimport.py +++ b/tests/functional/openlp_plugins/songs/test_songshowplusimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,18 +22,15 @@ """ This module contains tests for the SongShow Plus song importer. """ -import os from unittest import TestCase from unittest.mock import patch, MagicMock -from openlp.core.common.path import Path from openlp.plugins.songs.lib import VerseType from openlp.plugins.songs.lib.importers.songshowplus import SongShowPlusImport - from tests.helpers.songfileimport import SongImportTestHelper +from tests.utils.constants import RESOURCE_PATH -TEST_PATH = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'songshowplussongs')) +TEST_PATH = RESOURCE_PATH / 'songs' / 'songshowplus' class TestSongShowPlusFileImport(SongImportTestHelper): @@ -47,14 +44,14 @@ class TestSongShowPlusFileImport(SongImportTestHelper): """ Test that loading a SongShow Plus file works correctly on various files """ - self.file_import([Path(TEST_PATH, 'Amazing Grace.sbsong')], - self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json'))) - self.file_import([Path(TEST_PATH, 'Beautiful Garden Of Prayer.sbsong')], - self.load_external_result_data(os.path.join(TEST_PATH, 'Beautiful Garden Of Prayer.json'))) - self.file_import([Path(TEST_PATH, 'a mighty fortress is our god.sbsong')], - self.load_external_result_data(os.path.join(TEST_PATH, 'a mighty fortress is our god.json'))) - self.file_import([Path(TEST_PATH, 'cleanse-me.sbsong')], - self.load_external_result_data(os.path.join(TEST_PATH, 'cleanse-me.json'))) + self.file_import([TEST_PATH / 'Amazing Grace.sbsong'], + self.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) + self.file_import([TEST_PATH / 'Beautiful Garden Of Prayer.sbsong'], + self.load_external_result_data(TEST_PATH / 'Beautiful Garden Of Prayer.json')) + self.file_import([TEST_PATH / 'a mighty fortress is our god.sbsong'], + self.load_external_result_data(TEST_PATH / 'a mighty fortress is our god.json')) + self.file_import([TEST_PATH / 'cleanse-me.sbsong'], + self.load_external_result_data(TEST_PATH / 'cleanse-me.json')) class TestSongShowPlusImport(TestCase): @@ -73,7 +70,7 @@ class TestSongShowPlusImport(TestCase): importer = SongShowPlusImport(mocked_manager, file_paths=[]) # THEN: The importer object should not be None - self.assertIsNotNone(importer, 'Import should not be none') + assert importer is not None, 'Import should not be none' def test_invalid_import_source(self): """ @@ -92,9 +89,9 @@ class TestSongShowPlusImport(TestCase): importer.import_source = source # THEN: do_import should return none and the progress bar maximum should not be set. - self.assertIsNone(importer.do_import(), 'do_import should return None when import_source is not a list') - self.assertEqual(mocked_import_wizard.progress_bar.setMaximum.called, False, - 'setMaximum on import_wizard.progress_bar should not have been called') + assert importer.do_import() is None, 'do_import should return None when import_source is not a list' + assert mocked_import_wizard.progress_bar.setMaximum.called is False, \ + 'setMaximum on import_wizard.progress_bar should not have been called' def test_valid_import_source(self): """ @@ -113,8 +110,8 @@ class TestSongShowPlusImport(TestCase): # THEN: do_import should return none and the progress bar setMaximum should be called with the length of # import_source. - self.assertIsNone(importer.do_import(), 'do_import should return None when import_source is a list ' - 'and stop_import_flag is True') + assert importer.do_import() is None, \ + 'do_import should return None when import_source is a list and stop_import_flag is True' mocked_import_wizard.progress_bar.setMaximum.assert_called_with(len(importer.import_source)) def test_to_openlp_verse_tag(self): @@ -141,9 +138,9 @@ class TestSongShowPlusImport(TestCase): # THEN: The returned value should should correlate with the input arguments for original_tag, openlp_tag in test_values: - self.assertEqual(importer.to_openlp_verse_tag(original_tag), openlp_tag, - 'SongShowPlusImport.to_openlp_verse_tag should return "%s" when called with "%s"' % - (openlp_tag, original_tag)) + assert importer.to_openlp_verse_tag(original_tag) == openlp_tag, \ + 'SongShowPlusImport.to_openlp_verse_tag should return "%s" when called with "%s"' % \ + (openlp_tag, original_tag) def test_to_openlp_verse_tag_verse_order(self): """ @@ -170,6 +167,6 @@ class TestSongShowPlusImport(TestCase): # THEN: The returned value should should correlate with the input arguments for original_tag, openlp_tag in test_values: - self.assertEqual(importer.to_openlp_verse_tag(original_tag, ignore_unique=True), openlp_tag, - 'SongShowPlusImport.to_openlp_verse_tag should return "%s" when called with "%s"' % - (openlp_tag, original_tag)) + assert importer.to_openlp_verse_tag(original_tag, ignore_unique=True) == openlp_tag, \ + 'SongShowPlusImport.to_openlp_verse_tag should return "%s" when called with "%s"' % \ + (openlp_tag, original_tag) diff --git a/tests/functional/openlp_plugins/songs/test_sundayplusimport.py b/tests/functional/openlp_plugins/songs/test_sundayplusimport.py index 5a5977943..05874de46 100644 --- a/tests/functional/openlp_plugins/songs/test_sundayplusimport.py +++ b/tests/functional/openlp_plugins/songs/test_sundayplusimport.py @@ -3,7 +3,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -21,15 +21,12 @@ """ This module contains tests for the SundayPlus song importer. """ -import os from unittest.mock import patch -from openlp.core.common.path import Path - from tests.helpers.songfileimport import SongImportTestHelper +from tests.utils.constants import RESOURCE_PATH -TEST_PATH = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'sundayplussongs')) +TEST_PATH = RESOURCE_PATH / 'songs' / 'sundayplus' class TestSundayPlusFileImport(SongImportTestHelper): @@ -46,5 +43,5 @@ class TestSundayPlusFileImport(SongImportTestHelper): with patch('openlp.plugins.songs.lib.importers.sundayplus.retrieve_windows_encoding') as \ mocked_retrieve_windows_encoding: mocked_retrieve_windows_encoding.return_value = 'cp1252' - self.file_import([Path(TEST_PATH, 'Amazing Grace.ptf')], - self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json'))) + self.file_import([TEST_PATH / 'Amazing Grace.ptf'], + self.load_external_result_data(TEST_PATH / 'Amazing Grace.json')) diff --git a/tests/functional/openlp_plugins/songs/test_videopsalm.py b/tests/functional/openlp_plugins/songs/test_videopsalm.py index 69e4d9127..8c97ab8a0 100644 --- a/tests/functional/openlp_plugins/songs/test_videopsalm.py +++ b/tests/functional/openlp_plugins/songs/test_videopsalm.py @@ -3,7 +3,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -21,15 +21,12 @@ """ This module contains tests for the VideoPsalm song importer. """ -import os - -from openlp.core.common.path import Path - -from tests.helpers.songfileimport import SongImportTestHelper from unittest.mock import patch, MagicMock -TEST_PATH = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'videopsalmsongs')) +from tests.helpers.songfileimport import SongImportTestHelper +from tests.utils.constants import RESOURCE_PATH + +TEST_PATH = RESOURCE_PATH / 'songs' / 'videopsalm' class TestVideoPsalmFileImport(SongImportTestHelper): @@ -49,7 +46,7 @@ class TestVideoPsalmFileImport(SongImportTestHelper): mocked_returned_settings.value.side_effect = lambda value: True if value == 'songs/enable chords' else False mocked_settings.return_value = mocked_returned_settings # Do the test import - self.file_import(Path(TEST_PATH, 'videopsalm-as-safe-a-stronghold.json'), - self.load_external_result_data(os.path.join(TEST_PATH, 'as-safe-a-stronghold.json'))) - self.file_import(Path(TEST_PATH, 'videopsalm-as-safe-a-stronghold2.json'), - self.load_external_result_data(os.path.join(TEST_PATH, 'as-safe-a-stronghold2.json'))) + self.file_import(TEST_PATH / 'videopsalm-as-safe-a-stronghold.json', + self.load_external_result_data(TEST_PATH / 'as-safe-a-stronghold.json')) + self.file_import(TEST_PATH / 'videopsalm-as-safe-a-stronghold2.json', + self.load_external_result_data(TEST_PATH / 'as-safe-a-stronghold2.json')) diff --git a/tests/functional/openlp_plugins/songs/test_wordsofworshipimport.py b/tests/functional/openlp_plugins/songs/test_wordsofworshipimport.py index c0cb9b47d..445f1545f 100644 --- a/tests/functional/openlp_plugins/songs/test_wordsofworshipimport.py +++ b/tests/functional/openlp_plugins/songs/test_wordsofworshipimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,15 +22,10 @@ """ This module contains tests for the Words of Worship song importer. """ -import os - -from openlp.core.common.path import Path - from tests.helpers.songfileimport import SongImportTestHelper -from openlp.plugins.songs.lib.importers.wordsofworship import WordsOfWorshipImport +from tests.utils.constants import RESOURCE_PATH -TEST_PATH = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'wordsofworshipsongs')) +TEST_PATH = RESOURCE_PATH / 'songs' / 'wordsofworship' class TestWordsOfWorshipFileImport(SongImportTestHelper): @@ -44,10 +39,9 @@ class TestWordsOfWorshipFileImport(SongImportTestHelper): """ Test that loading a Words of Worship file works correctly """ - self.file_import([Path(TEST_PATH, 'Amazing Grace (6 Verses).wow-song')], - self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace (6 Verses).json'))) - self.file_import([Path(TEST_PATH, 'When morning gilds the skies.wsg')], - self.load_external_result_data(os.path.join(TEST_PATH, 'When morning gilds the skies.json'))) - self.file_import([Path(TEST_PATH, 'Holy Holy Holy Lord God Almighty.wow-song')], - self.load_external_result_data(os.path.join(TEST_PATH, - 'Holy Holy Holy Lord God Almighty.json'))) + self.file_import([TEST_PATH / 'Amazing Grace (6 Verses).wow-song'], + self.load_external_result_data(TEST_PATH / 'Amazing Grace (6 Verses).json')) + self.file_import([TEST_PATH / 'When morning gilds the skies.wsg'], + self.load_external_result_data(TEST_PATH / 'When morning gilds the skies.json')) + self.file_import([TEST_PATH / 'Holy Holy Holy Lord God Almighty.wow-song'], + self.load_external_result_data(TEST_PATH / 'Holy Holy Holy Lord God Almighty.json')) diff --git a/tests/functional/openlp_plugins/songs/test_worshipassistantimport.py b/tests/functional/openlp_plugins/songs/test_worshipassistantimport.py index be0179a98..c29970680 100644 --- a/tests/functional/openlp_plugins/songs/test_worshipassistantimport.py +++ b/tests/functional/openlp_plugins/songs/test_worshipassistantimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -23,14 +23,10 @@ The :mod:`worshipassistantimport` module provides the functionality for importing WorshipAssistant song files into the current installation database. """ -import os - -from openlp.core.common.path import Path - from tests.helpers.songfileimport import SongImportTestHelper +from tests.utils.constants import RESOURCE_PATH -TEST_PATH = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'worshipassistantsongs')) +TEST_PATH = RESOURCE_PATH / 'songs' / 'worshipassistant' class TestWorshipAssistantFileImport(SongImportTestHelper): @@ -44,9 +40,8 @@ class TestWorshipAssistantFileImport(SongImportTestHelper): """ Test that loading an Worship Assistant file works correctly """ - self.file_import(Path(TEST_PATH, 'du_herr.csv'), - self.load_external_result_data(os.path.join(TEST_PATH, 'du_herr.json'))) - self.file_import(Path(TEST_PATH, 'would_you_be_free.csv'), - self.load_external_result_data(os.path.join(TEST_PATH, 'would_you_be_free.json'))) - self.file_import(Path(TEST_PATH, 'would_you_be_free2.csv'), - self.load_external_result_data(os.path.join(TEST_PATH, 'would_you_be_free.json'))) + self.file_import(TEST_PATH / 'du_herr.csv', self.load_external_result_data(TEST_PATH / 'du_herr.json')) + self.file_import(TEST_PATH / 'would_you_be_free.csv', + self.load_external_result_data(TEST_PATH / 'would_you_be_free.json')) + self.file_import(TEST_PATH / 'would_you_be_free2.csv', + self.load_external_result_data(TEST_PATH / 'would_you_be_free.json')) diff --git a/tests/functional/openlp_plugins/songs/test_worshipcenterproimport.py b/tests/functional/openlp_plugins/songs/test_worshipcenterproimport.py index 02c365a4b..7a78a144d 100644 --- a/tests/functional/openlp_plugins/songs/test_worshipcenterproimport.py +++ b/tests/functional/openlp_plugins/songs/test_worshipcenterproimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -34,7 +34,7 @@ except ImportError: CAN_RUN_TESTS = False -class TestRecord(object): +class DBTestRecord(object): """ Microsoft Access Driver is not available on non Microsoft Systems for this reason the :class:`TestRecord` is used to simulate a recordset that would be returned by pyobdc. @@ -66,12 +66,12 @@ if CAN_RUN_TESTS: self._title_assignment_list.append(title) -RECORDSET_TEST_DATA = [TestRecord(1, 'TITLE', 'Amazing Grace'), - TestRecord(1, 'AUTHOR', 'John Newton'), - TestRecord(1, 'CCLISONGID', '12345'), - TestRecord(1, 'COMMENTS', 'The original version'), - TestRecord(1, 'COPY', 'Public Domain'), - TestRecord( +RECORDSET_TEST_DATA = [DBTestRecord(1, 'TITLE', 'Amazing Grace'), + DBTestRecord(1, 'AUTHOR', 'John Newton'), + DBTestRecord(1, 'CCLISONGID', '12345'), + DBTestRecord(1, 'COMMENTS', 'The original version'), + DBTestRecord(1, 'COPY', 'Public Domain'), + DBTestRecord( 1, 'LYRICS', 'Amazing grace! How&crlf;sweet the sound&crlf;That saved a wretch like me!&crlf;' 'I once was lost,&crlf;but now am found;&crlf;Was blind, but now I see.&crlf;&crlf;' @@ -88,8 +88,8 @@ RECORDSET_TEST_DATA = [TestRecord(1, 'TITLE', 'Amazing Grace'), 'Shall be forever mine.&crlf;&crlf;When we\'ve been there&crlf;ten thousand years,&crlf;' 'Bright shining as the sun,&crlf;We\'ve no less days to&crlf;sing God\'s praise&crlf;' 'Than when we\'d first begun.&crlf;&crlf;'), - TestRecord(2, 'TITLE', 'Beautiful Garden Of Prayer, The'), - TestRecord( + DBTestRecord(2, 'TITLE', 'Beautiful Garden Of Prayer, The'), + DBTestRecord( 2, 'LYRICS', 'There\'s a garden where&crlf;Jesus is waiting,&crlf;' 'There\'s a place that&crlf;is wondrously fair,&crlf;For it glows with the&crlf;' @@ -156,7 +156,7 @@ class TestWorshipCenterProSongImport(TestCase): importer = WorshipCenterProImport(mocked_manager, file_paths=[]) # THEN: The importer object should not be None - self.assertIsNotNone(importer, 'Import should not be none') + assert importer is not None, 'Import should not be none' def test_pyodbc_exception(self): """ @@ -181,7 +181,7 @@ class TestWorshipCenterProSongImport(TestCase): return_value = importer.do_import() # THEN: do_import should return None, and pyodbc, translate & log_error are called with known calls - self.assertIsNone(return_value, 'do_import should return None when pyodbc raises an exception.') + assert return_value is None, 'do_import should return None when pyodbc raises an exception.' mocked_pyodbc_connect.assert_called_with('DRIVER={Microsoft Access Driver (*.mdb)};DBQ=import_source') mocked_translate.assert_called_with('SongsPlugin.WorshipCenterProImport', 'Unable to connect the WorshipCenter Pro database.') @@ -220,7 +220,7 @@ class TestWorshipCenterProSongImport(TestCase): # THEN: do_import should return None, and pyodbc, import_wizard, importer.title and add_verse are called # with known calls - self.assertIsNone(return_value, 'do_import should return None when pyodbc raises an exception.') + assert return_value is None, 'do_import should return None when pyodbc raises an exception.' mocked_pyodbc.connect.assert_called_with('DRIVER={Microsoft Access Driver (*.mdb)};DBQ=import_source') mocked_pyodbc.connect().cursor.assert_any_call() mocked_pyodbc.connect().cursor().execute.assert_called_with('SELECT ID, Field, Value FROM __SONGDATA') @@ -229,8 +229,7 @@ class TestWorshipCenterProSongImport(TestCase): add_verse_call_count = 0 for song_data in SONG_TEST_DATA: title_value = song_data['title'] - self.assertIn(title_value, importer._title_assignment_list, - 'title should have been set to %s' % title_value) + assert title_value in importer._title_assignment_list, 'title should have been set to %s' % title_value verse_calls = song_data['verses'] add_verse_call_count += len(verse_calls) for call in verse_calls: @@ -241,5 +240,4 @@ class TestWorshipCenterProSongImport(TestCase): mocked_add_comment.assert_any_call(song_data['comments']) if 'copyright' in song_data: mocked_add_copyright.assert_any_call(song_data['copyright']) - self.assertEqual(mocked_add_verse.call_count, add_verse_call_count, - 'Incorrect number of calls made to add_verse') + assert mocked_add_verse.call_count == add_verse_call_count, 'Incorrect number of calls made to add_verse' diff --git a/tests/functional/openlp_plugins/songs/test_zionworximport.py b/tests/functional/openlp_plugins/songs/test_zionworximport.py index 42991382e..0856e273e 100644 --- a/tests/functional/openlp_plugins/songs/test_zionworximport.py +++ b/tests/functional/openlp_plugins/songs/test_zionworximport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,19 +22,16 @@ """ This module contains tests for the ZionWorx song importer. """ -import os from unittest import TestCase from unittest.mock import MagicMock, patch from openlp.core.common.registry import Registry -from openlp.core.common.path import Path -from openlp.plugins.songs.lib.importers.zionworx import ZionWorxImport from openlp.plugins.songs.lib.importers.songimport import SongImport - +from openlp.plugins.songs.lib.importers.zionworx import ZionWorxImport from tests.helpers.songfileimport import SongImportTestHelper +from tests.utils.constants import RESOURCE_PATH -TEST_PATH = os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'zionworxsongs')) +TEST_PATH = RESOURCE_PATH / 'songs' / 'zionworx' class TestZionWorxImport(TestCase): @@ -59,7 +56,7 @@ class TestZionWorxImport(TestCase): importer = ZionWorxImport(mocked_manager, file_paths=[]) # THEN: The importer should be an instance of SongImport - self.assertIsInstance(importer, SongImport) + assert isinstance(importer, SongImport) class TestZionWorxFileImport(SongImportTestHelper): @@ -73,5 +70,4 @@ class TestZionWorxFileImport(SongImportTestHelper): """ Test that loading an ZionWorx file works correctly on various files """ - self.file_import(Path(TEST_PATH, 'zionworx.csv'), - self.load_external_result_data(os.path.join(TEST_PATH, 'zionworx.json'))) + self.file_import(TEST_PATH / 'zionworx.csv', self.load_external_result_data(TEST_PATH / 'zionworx.json')) diff --git a/tests/functional/openlp_plugins/songusage/__init__.py b/tests/functional/openlp_plugins/songusage/__init__.py index 624faead7..07a369a94 100644 --- a/tests/functional/openlp_plugins/songusage/__init__.py +++ b/tests/functional/openlp_plugins/songusage/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/functional/openlp_plugins/songusage/test_songusage.py b/tests/functional/openlp_plugins/songusage/test_songusage.py index 92f972271..f360efa94 100644 --- a/tests/functional/openlp_plugins/songusage/test_songusage.py +++ b/tests/functional/openlp_plugins/songusage/test_songusage.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -43,10 +43,10 @@ class TestSongUsage(TestCase): # GIVEN: The SongUsagePlugin # WHEN: Retrieving the about text # THEN: about() should return a string object - self.assertIsInstance(SongUsagePlugin.about(), str) + assert isinstance(SongUsagePlugin.about(), str) # THEN: about() should return a non-empty string - self.assertNotEquals(len(SongUsagePlugin.about()), 0) - self.assertNotEquals(len(SongUsagePlugin.about()), 0) + assert len(SongUsagePlugin.about()) is not 0 + assert len(SongUsagePlugin.about()) is not 0 @patch('openlp.plugins.songusage.songusageplugin.Manager') def test_song_usage_init(self, MockedManager): @@ -62,8 +62,8 @@ class TestSongUsage(TestCase): # THEN: It should be initialised correctly MockedManager.assert_called_with('songusage', init_schema, upgrade_mod=upgrade) - self.assertEqual(mocked_manager, song_usage.manager) - self.assertFalse(song_usage.song_usage_active) + assert mocked_manager == song_usage.manager + assert song_usage.song_usage_active is False @patch('openlp.plugins.songusage.songusageplugin.Manager') def test_check_pre_conditions(self, MockedManager): @@ -80,7 +80,7 @@ class TestSongUsage(TestCase): ret = song_usage.check_pre_conditions() # THEN: It should return True - self.assertTrue(ret) + assert ret is True @patch('openlp.plugins.songusage.songusageplugin.Manager') def test_toggle_song_usage_state(self, MockedManager): @@ -96,4 +96,4 @@ class TestSongUsage(TestCase): song_usage.toggle_song_usage_state() # THEN: song_usage_state should have been toogled - self.assertFalse(song_usage.song_usage_active) + assert song_usage.song_usage_active is False diff --git a/tests/helpers/__init__.py b/tests/helpers/__init__.py index 3cf5e4696..a37de888f 100644 --- a/tests/helpers/__init__.py +++ b/tests/helpers/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/helpers/songfileimport.py b/tests/helpers/songfileimport.py index 2128d28f9..ee41cbfec 100644 --- a/tests/helpers/songfileimport.py +++ b/tests/helpers/songfileimport.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -29,7 +29,6 @@ from unittest import TestCase from unittest.mock import MagicMock, patch, call from openlp.core.common.registry import Registry -from openlp.plugins.songs.lib.importers.opensong import OpenSongImport log = logging.getLogger(__name__) @@ -78,12 +77,13 @@ class SongImportTestHelper(TestCase): self.add_author_patcher.stop() self.song_import_patcher.stop() - def load_external_result_data(self, file_name): + def load_external_result_data(self, file_path): """ A method to load and return an object containing the song data from an external file. + + :param openlp.core.common.path.Path file_path: The path of the file to load """ - result_file = open(file_name, 'rb') - return json.loads(result_file.read().decode()) + return json.loads(file_path.read_bytes().decode()) def file_import(self, source_file_name, result_data): """ @@ -108,7 +108,7 @@ class SongImportTestHelper(TestCase): verse_order_list = self._get_data(result_data, 'verse_order_list') # THEN: do_import should return none, the song data should be as expected, and finish should have been called. - self.assertIsNone(importer.do_import(), 'do_import should return None when it has completed') + assert importer.do_import() is None, 'do_import should return None when it has completed' # Debug information - will be displayed when the test fails log.debug("Title imported: %s" % importer.title) @@ -122,7 +122,7 @@ class SongImportTestHelper(TestCase): log.debug("Song copyright imported: %s" % importer.song_number) log.debug("Topics imported: %s" % importer.topics) - self.assertEqual(importer.title, title, 'title for %s should be "%s"' % (source_file_name, title)) + assert importer.title == title, 'title for %s should be "%s"' % (source_file_name, title) for author in author_calls: if isinstance(author, str): self.mocked_add_author.assert_any_call(author) @@ -131,27 +131,27 @@ class SongImportTestHelper(TestCase): if song_copyright: self.mocked_add_copyright.assert_called_with(song_copyright) if ccli_number: - self.assertEqual(importer.ccli_number, ccli_number, - 'ccli_number for %s should be %s' % (source_file_name, ccli_number)) + assert importer.ccli_number == ccli_number, \ + 'ccli_number for %s should be %s' % (source_file_name, ccli_number) expected_calls = [] for verse_text, verse_tag in add_verse_calls: self.mocked_add_verse.assert_any_call(verse_text, verse_tag) expected_calls.append(call(verse_text, verse_tag)) self.mocked_add_verse.assert_has_calls(expected_calls, any_order=False) if topics: - self.assertEqual(importer.topics, topics, 'topics for %s should be %s' % (source_file_name, topics)) + assert importer.topics == topics, 'topics for %s should be %s' % (source_file_name, topics) if comments: - self.assertEqual(importer.comments, comments, - 'comments for %s should be "%s"' % (source_file_name, comments)) + assert importer.comments == comments, \ + 'comments for %s should be "%s"' % (source_file_name, comments) if song_book_name: - self.assertEqual(importer.song_book_name, song_book_name, - 'song_book_name for %s should be "%s"' % (source_file_name, song_book_name)) + assert importer.song_book_name == song_book_name, \ + 'song_book_name for %s should be "%s"' % (source_file_name, song_book_name) if song_number: - self.assertEqual(importer.song_number, song_number, - 'song_number for %s should be %s' % (source_file_name, song_number)) + assert importer.song_number == song_number, \ + 'song_number for %s should be %s' % (source_file_name, song_number) if verse_order_list: - self.assertEqual(importer.verse_order_list, verse_order_list, - 'verse_order_list for %s should be %s' % (source_file_name, verse_order_list)) + assert importer.verse_order_list == verse_order_list, \ + 'verse_order_list for %s should be %s' % (source_file_name, verse_order_list) self.mocked_finish.assert_called_with() def _get_data(self, data, key): diff --git a/tests/helpers/testmixin.py b/tests/helpers/testmixin.py index facd949f9..73c8f4130 100644 --- a/tests/helpers/testmixin.py +++ b/tests/helpers/testmixin.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -26,6 +26,7 @@ import os from tempfile import mkstemp from PyQt5 import QtCore, QtWidgets + from openlp.core.common.settings import Settings diff --git a/tests/interfaces/__init__.py b/tests/interfaces/__init__.py index 14e1634ea..615fa43e9 100644 --- a/tests/interfaces/__init__.py +++ b/tests/interfaces/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/interfaces/openlp_core/__init__.py b/tests/interfaces/openlp_core/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/interfaces/openlp_core/__init__.py +++ b/tests/interfaces/openlp_core/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/interfaces/openlp_core/api/__init__.py b/tests/interfaces/openlp_core/api/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/interfaces/openlp_core/api/__init__.py +++ b/tests/interfaces/openlp_core/api/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/interfaces/openlp_core/common/__init__.py b/tests/interfaces/openlp_core/common/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/interfaces/openlp_core/common/__init__.py +++ b/tests/interfaces/openlp_core/common/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/interfaces/openlp_core/common/test_utils.py b/tests/interfaces/openlp_core/common/test_utils.py index 9669e3038..300eb2c0b 100644 --- a/tests/interfaces/openlp_core/common/test_utils.py +++ b/tests/interfaces/openlp_core/common/test_utils.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -26,7 +26,8 @@ from unittest import TestCase from openlp.core.common import is_not_image_file from openlp.core.common.path import Path -from tests.utils.constants import TEST_RESOURCES_PATH + +from tests.utils.constants import RESOURCE_PATH from tests.helpers.testmixin import TestMixin @@ -59,10 +60,10 @@ class TestUtils(TestCase, TestMixin): Test the method handles an image file """ # Given and empty string - file_name = Path(TEST_RESOURCES_PATH, 'church.jpg') + file_path = RESOURCE_PATH / 'church.jpg' # WHEN testing for it - result = is_not_image_file(file_name) + result = is_not_image_file(file_path) # THEN the result is false assert result is False, 'The file is present so the test should return False' @@ -72,10 +73,10 @@ class TestUtils(TestCase, TestMixin): Test the method handles a non image file """ # Given and empty string - file_name = Path(TEST_RESOURCES_PATH, 'serviceitem_custom_1.osj') + file_path = RESOURCE_PATH / 'serviceitem_custom_1.osj' # WHEN testing for it - result = is_not_image_file(file_name) + result = is_not_image_file(file_path) # THEN the result is false assert result is True, 'The file is not an image file so the test should return True' diff --git a/tests/interfaces/openlp_core/lib/__init__.py b/tests/interfaces/openlp_core/lib/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/interfaces/openlp_core/lib/__init__.py +++ b/tests/interfaces/openlp_core/lib/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/interfaces/openlp_core/lib/test_pluginmanager.py b/tests/interfaces/openlp_core/lib/test_pluginmanager.py index 588c15520..13478c21c 100644 --- a/tests/interfaces/openlp_core/lib/test_pluginmanager.py +++ b/tests/interfaces/openlp_core/lib/test_pluginmanager.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,19 +22,18 @@ """ Package to test the openlp.core.lib.pluginmanager package. """ -import sys import gc +import sys from tempfile import mkdtemp from unittest import TestCase from unittest.mock import MagicMock, patch from PyQt5 import QtWidgets +from openlp.core.common.path import Path from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings -from openlp.core.common.path import Path from openlp.core.lib.pluginmanager import PluginManager - from tests.helpers.testmixin import TestMixin @@ -86,11 +85,11 @@ class TestPluginManager(TestCase, TestMixin): # THEN: We should find the "Songs", "Bibles", etc in the plugins list plugin_names = [plugin.name for plugin in plugin_manager.plugins] - self.assertIn('songs', plugin_names, 'There should be a "songs" plugin') - self.assertIn('bibles', plugin_names, 'There should be a "bibles" plugin') - self.assertIn('presentations', plugin_names, 'There should be a "presentations" plugin') - self.assertIn('images', plugin_names, 'There should be a "images" plugin') - self.assertIn('media', plugin_names, 'There should be a "media" plugin') - self.assertIn('custom', plugin_names, 'There should be a "custom" plugin') - self.assertIn('songusage', plugin_names, 'There should be a "songusage" plugin') - self.assertIn('alerts', plugin_names, 'There should be a "alerts" plugin') + assert 'songs' in plugin_names, 'There should be a "songs" plugin' + assert 'bibles' in plugin_names, 'There should be a "bibles" plugin' + assert 'presentations' in plugin_names, 'There should be a "presentations" plugin' + assert 'images' in plugin_names, 'There should be a "images" plugin' + assert 'media' in plugin_names, 'There should be a "media" plugin' + assert 'custom' in plugin_names, 'There should be a "custom" plugin' + assert 'songusage'in plugin_names, 'There should be a "songusage" plugin' + assert 'alerts' in plugin_names, 'There should be a "alerts" plugin' diff --git a/tests/interfaces/openlp_core/ui/__init__.py b/tests/interfaces/openlp_core/ui/__init__.py index 7efaa18af..27683018c 100644 --- a/tests/interfaces/openlp_core/ui/__init__.py +++ b/tests/interfaces/openlp_core/ui/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/interfaces/openlp_core/ui/lib/__init__.py b/tests/interfaces/openlp_core/ui/lib/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/interfaces/openlp_core/ui/lib/__init__.py +++ b/tests/interfaces/openlp_core/ui/lib/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/interfaces/openlp_core/ui/media/__init__.py b/tests/interfaces/openlp_core/ui/media/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/interfaces/openlp_core/ui/media/__init__.py +++ b/tests/interfaces/openlp_core/ui/media/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/interfaces/openlp_core/ui/media/vendor/__init__.py b/tests/interfaces/openlp_core/ui/media/vendor/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/interfaces/openlp_core/ui/media/vendor/__init__.py +++ b/tests/interfaces/openlp_core/ui/media/vendor/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/interfaces/openlp_core/ui/media/vendor/test_mediainfoWrapper.py b/tests/interfaces/openlp_core/ui/media/vendor/test_mediainfoWrapper.py index 6ec2431b9..1d106e1d4 100644 --- a/tests/interfaces/openlp_core/ui/media/vendor/test_mediainfoWrapper.py +++ b/tests/interfaces/openlp_core/ui/media/vendor/test_mediainfoWrapper.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,13 +22,12 @@ """ Package to test the openlp.core.ui.media package. """ - -import os from unittest import TestCase from openlp.core.ui.media.vendor.mediainfoWrapper import MediaInfoWrapper +from tests.utils.constants import RESOURCE_PATH -TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', '..', 'resources', 'media')) +TEST_PATH = RESOURCE_PATH / 'media' TEST_MEDIA = [['avi_file.avi', 61495], ['mp3_file.mp3', 134426], ['mpg_file.mpg', 9404], ['mp4_file.mp4', 188336]] @@ -40,11 +39,10 @@ class TestMediainfoWrapper(TestCase): """ for test_data in TEST_MEDIA: # GIVEN: a media file - full_path = os.path.normpath(os.path.join(TEST_PATH, test_data[0])) + full_path = str(TEST_PATH / test_data[0]) # WHEN the media data is retrieved results = MediaInfoWrapper.parse(full_path) # THEN you can determine the run time - self.assertEqual(results.tracks[0].duration, test_data[1], 'The correct duration is returned for ' + - test_data[0]) + assert results.tracks[0].duration == test_data[1], 'The correct duration is returned for ' + test_data[0] diff --git a/tests/interfaces/openlp_core/ui/test_filerenamedialog.py b/tests/interfaces/openlp_core/ui/test_filerenamedialog.py index cb074af1a..e268aef2f 100644 --- a/tests/interfaces/openlp_core/ui/test_filerenamedialog.py +++ b/tests/interfaces/openlp_core/ui/test_filerenamedialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -29,7 +29,6 @@ from PyQt5 import QtTest, QtWidgets from openlp.core.common.registry import Registry from openlp.core.ui import filerenameform - from tests.helpers.testmixin import TestMixin @@ -63,19 +62,19 @@ class TestStartFileRenameForm(TestCase, TestMixin): self.form.exec() # THEN: the window title is set correctly - self.assertEqual(self.form.windowTitle(), 'File Rename', 'The window title should be "File Rename"') + assert self.form.windowTitle() == 'File Rename', 'The window title should be "File Rename"' # WHEN: The form is executed with False arg self.form.exec(False) # THEN: the window title is set correctly - self.assertEqual(self.form.windowTitle(), 'File Rename', 'The window title should be "File Rename"') + assert self.form.windowTitle() == 'File Rename', 'The window title should be "File Rename"' # WHEN: The form is executed with True arg self.form.exec(True) # THEN: the window title is set correctly - self.assertEqual(self.form.windowTitle(), 'File Copy', 'The window title should be "File Copy"') + assert self.form.windowTitle() == 'File Copy', 'The window title should be "File Copy"' def test_line_edit_focus(self): """ @@ -104,4 +103,4 @@ class TestStartFileRenameForm(TestCase, TestMixin): # THEN: The text in the QLineEdit should be the same as the input string with the invalid characters filtered # out. - self.assertEqual(self.form.file_name_edit.text(), 'Invalid File Name') + assert self.form.file_name_edit.text() == 'Invalid File Name' diff --git a/tests/interfaces/openlp_core/ui/test_mainwindow.py b/tests/interfaces/openlp_core/ui/test_mainwindow.py index 4a8ced265..529408d2c 100644 --- a/tests/interfaces/openlp_core/ui/test_mainwindow.py +++ b/tests/interfaces/openlp_core/ui/test_mainwindow.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -27,7 +27,6 @@ from unittest.mock import MagicMock, patch from openlp.core.common.registry import Registry from openlp.core.ui.mainwindow import MainWindow - from tests.helpers.testmixin import TestMixin @@ -45,21 +44,21 @@ class TestMainWindow(TestCase, TestMixin): self.app.set_normal_cursor = MagicMock() self.app.args = [] Registry().register('application', self.app) - Registry().set_flag('no_web_server', False) + Registry().set_flag('no_web_server', True) # Mock classes and methods used by mainwindow. - with patch('openlp.core.ui.mainwindow.SettingsForm') as mocked_settings_form, \ - patch('openlp.core.ui.mainwindow.ImageManager') as mocked_image_manager, \ - patch('openlp.core.ui.mainwindow.LiveController') as mocked_live_controller, \ - patch('openlp.core.ui.mainwindow.PreviewController') as mocked_preview_controller, \ - patch('openlp.core.ui.mainwindow.OpenLPDockWidget') as mocked_dock_widget, \ - patch('openlp.core.ui.mainwindow.QtWidgets.QToolBox') as mocked_q_tool_box_class, \ - patch('openlp.core.ui.mainwindow.QtWidgets.QMainWindow.addDockWidget') as mocked_add_dock_method, \ - patch('openlp.core.ui.mainwindow.ServiceManager') as mocked_service_manager, \ - patch('openlp.core.ui.mainwindow.ThemeManager') as mocked_theme_manager, \ - patch('openlp.core.ui.mainwindow.ProjectorManager') as mocked_projector_manager, \ - patch('openlp.core.ui.mainwindow.Renderer') as mocked_renderer, \ - patch('openlp.core.ui.mainwindow.websockets.WebSocketServer') as mocked_websocketserver, \ - patch('openlp.core.ui.mainwindow.server.HttpServer') as mocked_httpserver: + with patch('openlp.core.ui.mainwindow.SettingsForm'), \ + patch('openlp.core.ui.mainwindow.ImageManager'), \ + patch('openlp.core.ui.mainwindow.LiveController'), \ + patch('openlp.core.ui.mainwindow.PreviewController'), \ + patch('openlp.core.ui.mainwindow.OpenLPDockWidget'), \ + patch('openlp.core.ui.mainwindow.QtWidgets.QToolBox'), \ + patch('openlp.core.ui.mainwindow.QtWidgets.QMainWindow.addDockWidget'), \ + patch('openlp.core.ui.mainwindow.ServiceManager'), \ + patch('openlp.core.ui.mainwindow.ThemeManager'), \ + patch('openlp.core.ui.mainwindow.ProjectorManager'), \ + patch('openlp.core.ui.mainwindow.Renderer'), \ + patch('openlp.core.ui.mainwindow.websockets.WebSocketServer'), \ + patch('openlp.core.ui.mainwindow.server.HttpServer'): self.main_window = MainWindow() def tearDown(self): diff --git a/tests/interfaces/openlp_core/ui/test_projectoreditform.py b/tests/interfaces/openlp_core/ui/test_projectoreditform.py index ec2539a29..0cb33afe2 100644 --- a/tests/interfaces/openlp_core/ui/test_projectoreditform.py +++ b/tests/interfaces/openlp_core/ui/test_projectoreditform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -30,10 +30,8 @@ from unittest.mock import patch from openlp.core.common.registry import Registry from openlp.core.projectors.db import Projector, ProjectorDB from openlp.core.projectors.editform import ProjectorEditForm -from openlp.core.projectors.manager import ProjectorManager - from tests.helpers.testmixin import TestMixin -from tests.resources.projector.data import TEST_DB, TEST1_DATA, TEST2_DATA +from tests.resources.projector.data import TEST_DB, TEST1_DATA class TestProjectorEditForm(TestCase, TestMixin): diff --git a/tests/interfaces/openlp_core/ui/test_projectormanager.py b/tests/interfaces/openlp_core/ui/test_projectormanager.py index 484d4d68a..4fc6ec791 100644 --- a/tests/interfaces/openlp_core/ui/test_projectormanager.py +++ b/tests/interfaces/openlp_core/ui/test_projectormanager.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -30,7 +30,6 @@ from openlp.core.common.registry import Registry from openlp.core.projectors.db import ProjectorDB from openlp.core.projectors.editform import ProjectorEditForm from openlp.core.projectors.manager import ProjectorManager - from tests.helpers.testmixin import TestMixin from tests.resources.projector.data import TEST_DB @@ -70,8 +69,8 @@ class TestProjectorManager(TestCase, TestMixin): # WHEN: we call bootstrap_initialise self.projector_manager.bootstrap_initialise() # THEN: ProjectorDB is setup - self.assertEqual(type(self.projector_manager.projectordb), ProjectorDB, - 'Initialization should have created a ProjectorDB() instance') + assert type(self.projector_manager.projectordb) == ProjectorDB, \ + 'Initialization should have created a ProjectorDB() instance' def test_bootstrap_post_set_up(self): """ @@ -85,10 +84,9 @@ class TestProjectorManager(TestCase, TestMixin): self.projector_manager.bootstrap_post_set_up() # THEN: verify calls to retrieve saved projectors and edit page initialized - self.assertEqual(1, self.projector_manager._load_projectors.call_count, - 'Initialization should have called load_projectors()') - self.assertEqual(type(self.projector_manager.projector_form), ProjectorEditForm, - 'Initialization should have created a Projector Edit Form') - self.assertIs(self.projector_manager.projectordb, - self.projector_manager.projector_form.projectordb, - 'ProjectorEditForm should be using same ProjectorDB() instance as ProjectorManager') + assert 1 == self.projector_manager._load_projectors.call_count, \ + 'Initialization should have called load_projectors()' + assert type(self.projector_manager.projector_form) == ProjectorEditForm, \ + 'Initialization should have created a Projector Edit Form' + assert self.projector_manager.projectordb is self.projector_manager.projector_form.projectordb, \ + 'ProjectorEditForm should be using same ProjectorDB() instance as ProjectorManager' diff --git a/tests/interfaces/openlp_core/ui/test_projectorsourceform.py b/tests/interfaces/openlp_core/ui/test_projectorsourceform.py index 815fe6ded..5ddf5641a 100644 --- a/tests/interfaces/openlp_core/ui/test_projectorsourceform.py +++ b/tests/interfaces/openlp_core/ui/test_projectorsourceform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -32,10 +32,9 @@ from unittest.mock import patch from PyQt5.QtWidgets import QDialog from openlp.core.common.registry import Registry -from openlp.core.projectors.db import ProjectorDB, Projector from openlp.core.projectors.constants import PJLINK_DEFAULT_CODES, PJLINK_DEFAULT_SOURCES +from openlp.core.projectors.db import ProjectorDB, Projector from openlp.core.projectors.sourceselectform import source_group, SourceSelectSingle - from tests.helpers.testmixin import TestMixin from tests.resources.projector.data import TEST_DB, TEST1_DATA @@ -111,8 +110,7 @@ class ProjectorSourceFormTest(TestCase, TestMixin): check = source_group(codes, PJLINK_DEFAULT_CODES) # THEN: return dictionary should match test dictionary - self.assertEquals(check, build_source_dict(), - "Source group dictionary should match test dictionary") + assert check == build_source_dict(), "Source group dictionary should match test dictionary" @patch.object(QDialog, 'exec') def test_source_select_edit_button(self, mocked_qdialog): @@ -130,9 +128,8 @@ class ProjectorSourceFormTest(TestCase, TestMixin): projector = select_form.projector # THEN: Verify all 4 buttons are available - self.assertEquals(len(select_form.button_box.buttons()), 4, - 'SourceSelect dialog box should have "OK", "Cancel" ' - '"Rest", and "Revert" buttons available') + assert len(select_form.button_box.buttons()) == 4, \ + 'SourceSelect dialog box should have "OK", "Cancel", "Rest", and "Revert" buttons available' @patch.object(QDialog, 'exec') def test_source_select_noedit_button(self, mocked_qdialog): @@ -150,6 +147,5 @@ class ProjectorSourceFormTest(TestCase, TestMixin): projector = select_form.projector # THEN: Verify only 2 buttons are available - self.assertEquals(len(select_form.button_box.buttons()), 2, - 'SourceSelect dialog box should only have "OK" ' - 'and "Cancel" buttons available') + assert len(select_form.button_box.buttons()) == 2, \ + 'SourceSelect dialog box should only have "OK" and "Cancel" buttons available' diff --git a/tests/interfaces/openlp_core/ui/test_servicemanager.py b/tests/interfaces/openlp_core/ui/test_servicemanager.py index 3426fffcb..04a960c72 100644 --- a/tests/interfaces/openlp_core/ui/test_servicemanager.py +++ b/tests/interfaces/openlp_core/ui/test_servicemanager.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -30,7 +30,6 @@ from PyQt5 import QtCore, QtGui, QtWidgets from openlp.core.common.registry import Registry from openlp.core.lib import ServiceItem, ItemCapabilities from openlp.core.ui.servicemanager import ServiceManager - from tests.helpers.testmixin import TestMixin @@ -79,8 +78,8 @@ class TestServiceManager(TestCase, TestMixin): self.service_manager.setup_ui(self.service_manager) # THEN the count of items should be zero - self.assertEqual(self.service_manager.service_manager_list.topLevelItemCount(), 0, - 'The service manager list should be empty ') + assert self.service_manager.service_manager_list.topLevelItemCount() == 0, \ + 'The service manager list should be empty ' @patch('openlp.core.ui.servicemanager.QtWidgets.QTreeWidget.itemAt') @patch('openlp.core.ui.servicemanager.QtWidgets.QWidget.mapToGlobal') @@ -447,8 +446,8 @@ class TestServiceManager(TestCase, TestMixin): # THEN selection should be expanded selected_index = self.service_manager.service_manager_list.currentIndex() above_selected_index = self.service_manager.service_manager_list.indexAbove(selected_index) - self.assertTrue(self.service_manager.service_manager_list.isExpanded(above_selected_index), - 'Item should have been expanded') + assert self.service_manager.service_manager_list.isExpanded(above_selected_index) is True, \ + 'Item should have been expanded' self.service_manager.expanded.assert_called_once_with(song_item) def test_on_collapse_selection_with_parent_selected(self): @@ -468,10 +467,10 @@ class TestServiceManager(TestCase, TestMixin): # THEN selection should be expanded selected_index = self.service_manager.service_manager_list.currentIndex() - self.assertFalse(self.service_manager.service_manager_list.isExpanded(selected_index), - 'Item should have been collapsed') - self.assertTrue(self.service_manager.service_manager_list.currentItem() == song_item, - 'Top item should have been selected') + assert self.service_manager.service_manager_list.isExpanded(selected_index) is False, \ + 'Item should have been collapsed' + assert self.service_manager.service_manager_list.currentItem() == song_item, \ + 'Top item should have been selected' self.service_manager.collapsed.assert_called_once_with(song_item) def test_on_collapse_selection_with_child_selected(self): @@ -491,8 +490,8 @@ class TestServiceManager(TestCase, TestMixin): # THEN selection should be expanded selected_index = self.service_manager.service_manager_list.currentIndex() - self.assertFalse(self.service_manager.service_manager_list.isExpanded(selected_index), - 'Item should have been collapsed') - self.assertTrue(self.service_manager.service_manager_list.currentItem() == song_item, - 'Top item should have been selected') + assert self.service_manager.service_manager_list.isExpanded(selected_index) is False, \ + 'Item should have been collapsed' + assert self.service_manager.service_manager_list.currentItem() == song_item, \ + 'Top item should have been selected' self.service_manager.collapsed.assert_called_once_with(song_item) diff --git a/tests/interfaces/openlp_core/ui/test_servicenotedialog.py b/tests/interfaces/openlp_core/ui/test_servicenotedialog.py index 94e34be44..065b35198 100644 --- a/tests/interfaces/openlp_core/ui/test_servicenotedialog.py +++ b/tests/interfaces/openlp_core/ui/test_servicenotedialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -29,7 +29,6 @@ from PyQt5 import QtCore, QtTest, QtWidgets from openlp.core.common.registry import Registry from openlp.core.ui import servicenoteform - from tests.helpers.testmixin import TestMixin @@ -66,7 +65,7 @@ class TestStartNoteDialog(TestCase, TestMixin): QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) # THEN the following input text is returned - self.assertEqual(self.form.text_edit.toPlainText(), '', 'The returned text should be empty') + assert self.form.text_edit.toPlainText() == '', 'The returned text should be empty' # WHEN displaying the UI, having set the text and pressing enter text = 'OpenLP is the best worship software' @@ -77,7 +76,7 @@ class TestStartNoteDialog(TestCase, TestMixin): QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) # THEN the following text is returned - self.assertEqual(self.form.text_edit.toPlainText(), text, 'The text originally entered should still be there') + assert self.form.text_edit.toPlainText() == text, 'The text originally entered should still be there' # WHEN displaying the UI, having set the text and pressing enter self.form.text_edit.setPlainText('') @@ -88,4 +87,4 @@ class TestStartNoteDialog(TestCase, TestMixin): QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) # THEN the following text is returned - self.assertEqual(self.form.text_edit.toPlainText(), text, 'The new text should be returned') + assert self.form.text_edit.toPlainText() == text, 'The new text should be returned' diff --git a/tests/interfaces/openlp_core/ui/test_settings_form.py b/tests/interfaces/openlp_core/ui/test_settings_form.py index f4ec5ccbc..39cb783f0 100644 --- a/tests/interfaces/openlp_core/ui/test_settings_form.py +++ b/tests/interfaces/openlp_core/ui/test_settings_form.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -28,9 +28,8 @@ from unittest.mock import MagicMock, patch from PyQt5 import QtCore, QtTest from openlp.core.common.registry import Registry -from openlp.core.ui import settingsform from openlp.core.display.screens import ScreenList - +from openlp.core.ui import settingsform from tests.helpers.testmixin import TestMixin SCREEN = { diff --git a/tests/interfaces/openlp_core/ui/test_shortcutlistform.py b/tests/interfaces/openlp_core/ui/test_shortcutlistform.py index a95390236..ff1a76555 100644 --- a/tests/interfaces/openlp_core/ui/test_shortcutlistform.py +++ b/tests/interfaces/openlp_core/ui/test_shortcutlistform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -29,7 +29,6 @@ from PyQt5 import QtCore, QtWidgets from openlp.core.common.registry import Registry from openlp.core.ui.shortcutlistform import ShortcutListForm - from tests.helpers.testmixin import TestMixin @@ -67,9 +66,9 @@ class TestShortcutform(TestCase, TestMixin): self.form._adjust_button(button, checked, enabled, text) # THEN: The button should be changed. - self.assertEqual(button.text(), text, 'The text should match.') + assert button.text() == text, 'The text should match.' mocked_check_method.assert_called_once_with(True) - self.assertEqual(button.isEnabled(), enabled, 'The button should be disabled.') + assert button.isEnabled() == enabled, 'The button should be disabled.' def test_space_key_press_event(self): """ @@ -85,7 +84,7 @@ class TestShortcutform(TestCase, TestMixin): # THEN: The key should be released mocked_key_release_event.assert_called_with(mocked_event) - self.assertEqual(0, mocked_event.accept.call_count) + assert 0 == mocked_event.accept.call_count def test_primary_push_button_checked_key_press_event(self): """ @@ -102,7 +101,7 @@ class TestShortcutform(TestCase, TestMixin): # THEN: The key should be released mocked_key_release_event.assert_called_with(mocked_event) - self.assertEqual(0, mocked_event.accept.call_count) + assert 0 == mocked_event.accept.call_count def test_alternate_push_button_checked_key_press_event(self): """ @@ -119,7 +118,7 @@ class TestShortcutform(TestCase, TestMixin): # THEN: The key should be released mocked_key_release_event.assert_called_with(mocked_event) - self.assertEqual(0, mocked_event.accept.call_count) + assert 0 == mocked_event.accept.call_count def test_escape_key_press_event(self): """ @@ -148,7 +147,7 @@ class TestShortcutform(TestCase, TestMixin): self.form.on_default_radio_button_clicked(False) # THEN: The method should exit early (i.e. the rest of the methods are not called) - self.assertEqual(0, mocked_current_item_action.call_count) + assert 0 == mocked_current_item_action.call_count def test_on_default_radio_button_clicked_no_action(self): """ @@ -164,7 +163,7 @@ class TestShortcutform(TestCase, TestMixin): # THEN: The method should exit early (i.e. the rest of the methods are not called) mocked_current_item_action.assert_called_with() - self.assertEqual(0, mocked_action_shortcuts.call_count) + assert 0 == mocked_action_shortcuts.call_count def test_on_default_radio_button_clicked(self): """ @@ -202,7 +201,7 @@ class TestShortcutform(TestCase, TestMixin): self.form.on_custom_radio_button_clicked(False) # THEN: The method should exit early (i.e. the rest of the methods are not called) - self.assertEqual(0, mocked_current_item_action.call_count) + assert 0 == mocked_current_item_action.call_count def test_on_custom_radio_button_clicked(self): """ diff --git a/tests/interfaces/openlp_core/ui/test_starttimedialog.py b/tests/interfaces/openlp_core/ui/test_starttimedialog.py index 5d0140e0d..f830bba28 100644 --- a/tests/interfaces/openlp_core/ui/test_starttimedialog.py +++ b/tests/interfaces/openlp_core/ui/test_starttimedialog.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -29,7 +29,6 @@ from PyQt5 import QtCore, QtTest, QtWidgets from openlp.core.common.registry import Registry from openlp.core.ui import starttimeform - from tests.helpers.testmixin import TestMixin @@ -56,28 +55,24 @@ class TestStartTimeDialog(TestCase, TestMixin): """ Test StartTimeDialog are defaults correct """ - self.assertEqual(self.form.hour_spin_box.minimum(), 0, 'The minimum hour should stay the same as the dialog') - self.assertEqual(self.form.hour_spin_box.maximum(), 4, 'The maximum hour should stay the same as the dialog') - self.assertEqual(self.form.minute_spin_box.minimum(), 0, - 'The minimum minute should stay the same as the dialog') - self.assertEqual(self.form.minute_spin_box.maximum(), 59, - 'The maximum minute should stay the same as the dialog') - self.assertEqual(self.form.second_spin_box.minimum(), 0, - 'The minimum second should stay the same as the dialog') - self.assertEqual(self.form.second_spin_box.maximum(), 59, - 'The maximum second should stay the same as the dialog') - self.assertEqual(self.form.hour_finish_spin_box.minimum(), 0, - 'The minimum finish hour should stay the same as the dialog') - self.assertEqual(self.form.hour_finish_spin_box.maximum(), 4, - 'The maximum finish hour should stay the same as the dialog') - self.assertEqual(self.form.minute_finish_spin_box.minimum(), 0, - 'The minimum finish minute should stay the same as the dialog') - self.assertEqual(self.form.minute_finish_spin_box.maximum(), 59, - 'The maximum finish minute should stay the same as the dialog') - self.assertEqual(self.form.second_finish_spin_box.minimum(), 0, - 'The minimum finish second should stay the same as the dialog') - self.assertEqual(self.form.second_finish_spin_box.maximum(), 59, - 'The maximum finish second should stay the same as the dialog') + assert self.form.hour_spin_box.minimum() == 0, 'The minimum hour should stay the same as the dialog' + assert self.form.hour_spin_box.maximum() == 4, 'The maximum hour should stay the same as the dialog' + assert self.form.minute_spin_box.minimum() == 0, 'The minimum minute should stay the same as the dialog' + assert self.form.minute_spin_box.maximum() == 59, 'The maximum minute should stay the same as the dialog' + assert self.form.second_spin_box.minimum() == 0, 'The minimum second should stay the same as the dialog' + assert self.form.second_spin_box.maximum() == 59, 'The maximum second should stay the same as the dialog' + assert self.form.hour_finish_spin_box.minimum() == 0, \ + 'The minimum finish hour should stay the same as the dialog' + assert self.form.hour_finish_spin_box.maximum() == 4, \ + 'The maximum finish hour should stay the same as the dialog' + assert self.form.minute_finish_spin_box.minimum() == 0, \ + 'The minimum finish minute should stay the same as the dialog' + assert self.form.minute_finish_spin_box.maximum() == 59, \ + 'The maximum finish minute should stay the same as the dialog' + assert self.form.second_finish_spin_box.minimum() == 0, \ + 'The minimum finish second should stay the same as the dialog' + assert self.form.second_finish_spin_box.maximum() == 59, \ + 'The maximum finish second should stay the same as the dialog' def test_time_display(self): """ @@ -97,10 +92,10 @@ class TestStartTimeDialog(TestCase, TestMixin): QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) # THEN the following input values are returned - self.assertEqual(self.form.hour_spin_box.value(), 0) - self.assertEqual(self.form.minute_spin_box.value(), 1) - self.assertEqual(self.form.second_spin_box.value(), 1) - self.assertEqual(self.form.item['service_item'].start_time, 61, 'The start time should stay the same') + assert self.form.hour_spin_box.value() == 0 + assert self.form.minute_spin_box.value() == 1 + assert self.form.second_spin_box.value() == 1 + assert self.form.item['service_item'].start_time == 61, 'The start time should stay the same' # WHEN displaying the UI, changing the time to 2min 3secs and pressing enter self.form.item = {'service_item': mocked_serviceitem} @@ -112,7 +107,7 @@ class TestStartTimeDialog(TestCase, TestMixin): QtTest.QTest.mouseClick(ok_widget, QtCore.Qt.LeftButton) # THEN the following values are returned - self.assertEqual(self.form.hour_spin_box.value(), 0) - self.assertEqual(self.form.minute_spin_box.value(), 2) - self.assertEqual(self.form.second_spin_box.value(), 3) - self.assertEqual(self.form.item['service_item'].start_time, 123, 'The start time should have changed') + assert self.form.hour_spin_box.value() == 0 + assert self.form.minute_spin_box.value() == 2 + assert self.form.second_spin_box.value() == 3 + assert self.form.item['service_item'].start_time == 123, 'The start time should have changed' diff --git a/tests/interfaces/openlp_core/ui/test_thememanager.py b/tests/interfaces/openlp_core/ui/test_thememanager.py index 0808b12d0..e308ae00e 100644 --- a/tests/interfaces/openlp_core/ui/test_thememanager.py +++ b/tests/interfaces/openlp_core/ui/test_thememanager.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -25,11 +25,10 @@ Interface tests to test the themeManager class and related methods. from unittest import TestCase from unittest.mock import patch, MagicMock +from openlp.core.common.path import Path from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings -from openlp.core.common.path import Path from openlp.core.ui import ThemeManager - from tests.helpers.testmixin import TestMixin @@ -121,4 +120,4 @@ class TestThemeManager(TestCase, TestMixin): self.theme_manager.bootstrap_post_set_up() # THEN: - self.assertEqual(1, self.theme_manager.load_themes.call_count, "load_themes should have been called once") + assert 1 == self.theme_manager.load_themes.call_count, "load_themes should have been called once" diff --git a/tests/interfaces/openlp_core/widgets/__init__.py b/tests/interfaces/openlp_core/widgets/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/interfaces/openlp_core/widgets/__init__.py +++ b/tests/interfaces/openlp_core/widgets/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/interfaces/openlp_core/widgets/test_edits.py b/tests/interfaces/openlp_core/widgets/test_edits.py index 3951e5f80..373b54d35 100644 --- a/tests/interfaces/openlp_core/widgets/test_edits.py +++ b/tests/interfaces/openlp_core/widgets/test_edits.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -29,7 +29,6 @@ from PyQt5 import QtCore, QtGui, QtTest, QtWidgets from openlp.core.common.registry import Registry from openlp.core.widgets.edits import SearchEdit, HistoryComboBox - from tests.helpers.testmixin import TestMixin @@ -86,8 +85,8 @@ class TestSearchEdit(TestCase, TestMixin): # THEN: The first search type should be the first one in the list. The selected type should be saved in the # settings - self.assertEqual(self.search_edit.current_search_type(), SearchTypes.First, - "The first search type should be selected.") + assert self.search_edit.current_search_type() == SearchTypes.First, \ + "The first search type should be selected." self.mocked_settings().setValue.assert_called_once_with('settings_section/last used search type', 0) def test_set_current_search_type(self): @@ -99,11 +98,11 @@ class TestSearchEdit(TestCase, TestMixin): result = self.search_edit.set_current_search_type(SearchTypes.Second) # THEN: - self.assertTrue(result, "The call should return success (True).") - self.assertEqual(self.search_edit.current_search_type(), SearchTypes.Second, - "The search type should be SearchTypes.Second") - self.assertEqual(self.search_edit.placeholderText(), SECOND_PLACEHOLDER_TEXT, - "The correct placeholder text should be 'Second Placeholder Text'.") + assert result is True, "The call should return success (True)." + assert self.search_edit.current_search_type() == SearchTypes.Second, \ + "The search type should be SearchTypes.Second" + assert self.search_edit.placeholderText() == SECOND_PLACEHOLDER_TEXT, \ + "The correct placeholder text should be 'Second Placeholder Text'." self.mocked_settings().setValue.assert_has_calls( [call('settings_section/last used search type', 0), call('settings_section/last used search type', 1)]) @@ -166,4 +165,4 @@ class TestHistoryComboBox(TestCase, TestMixin): self.combo.addItem('test2') # THEN: The list of items should contain both strings. - self.assertEqual(self.combo.getItems(), ['test1', 'test2']) + assert self.combo.getItems() == ['test1', 'test2'] diff --git a/tests/interfaces/openlp_core/widgets/test_views.py b/tests/interfaces/openlp_core/widgets/test_views.py index f4a493f4d..a4b0cb4fb 100644 --- a/tests/interfaces/openlp_core/widgets/test_views.py +++ b/tests/interfaces/openlp_core/widgets/test_views.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -30,9 +30,8 @@ from PyQt5 import QtGui, QtWidgets from openlp.core.common.registry import Registry from openlp.core.lib import ServiceItem from openlp.core.widgets.views import ListPreviewWidget - -from tests.utils.osdinteraction import read_service_from_file from tests.helpers.testmixin import TestMixin +from tests.utils.osdinteraction import read_service_from_file class TestListPreviewWidget(TestCase, TestMixin): @@ -64,7 +63,7 @@ class TestListPreviewWidget(TestCase, TestMixin): # GIVEN: A new ListPreviewWidget instance. # WHEN: No SlideItem has been added yet. # THEN: The count of items should be zero. - self.assertEqual(self.preview_widget.slide_count(), 0, 'The slide list should be empty.') + assert self.preview_widget.slide_count() == 0, 'The slide list should be empty.' def test_initial_slide_number(self): """ @@ -73,7 +72,7 @@ class TestListPreviewWidget(TestCase, TestMixin): # GIVEN: A new ListPreviewWidget instance. # WHEN: No SlideItem has been added yet. # THEN: The number of the current item should be -1. - self.assertEqual(self.preview_widget.current_slide_number(), -1, 'The slide number should be -1.') + assert self.preview_widget.current_slide_number() == -1, 'The slide number should be -1.' def test_replace_service_item(self): """ @@ -87,8 +86,8 @@ class TestListPreviewWidget(TestCase, TestMixin): # WHEN: Added to the preview widget. self.preview_widget.replace_service_item(service_item, 1, 1) # THEN: The slide count and number should fit. - self.assertEqual(self.preview_widget.slide_count(), 2, 'The slide count should be 2.') - self.assertEqual(self.preview_widget.current_slide_number(), 1, 'The current slide number should be 1.') + assert self.preview_widget.slide_count() == 2, 'The slide count should be 2.' + assert self.preview_widget.current_slide_number() == 1, 'The current slide number should be 1.' def test_change_slide(self): """ @@ -103,4 +102,4 @@ class TestListPreviewWidget(TestCase, TestMixin): self.preview_widget.replace_service_item(service_item, 1, 0) self.preview_widget.change_slide(1) # THEN: The current_slide_number should reflect the change. - self.assertEqual(self.preview_widget.current_slide_number(), 1, 'The current slide number should be 1.') + assert self.preview_widget.current_slide_number() == 1, 'The current slide number should be 1.' diff --git a/tests/interfaces/openlp_plugins/__init__.py b/tests/interfaces/openlp_plugins/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/interfaces/openlp_plugins/__init__.py +++ b/tests/interfaces/openlp_plugins/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/interfaces/openlp_plugins/bibles/__init__.py b/tests/interfaces/openlp_plugins/bibles/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/interfaces/openlp_plugins/bibles/__init__.py +++ b/tests/interfaces/openlp_plugins/bibles/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/interfaces/openlp_plugins/bibles/forms/__init__.py b/tests/interfaces/openlp_plugins/bibles/forms/__init__.py index e69de29bb..711ded4ae 100644 --- a/tests/interfaces/openlp_plugins/bibles/forms/__init__.py +++ b/tests/interfaces/openlp_plugins/bibles/forms/__init__.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2018 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 # +############################################################################### diff --git a/tests/interfaces/openlp_plugins/bibles/forms/test_bibleimportform.py b/tests/interfaces/openlp_plugins/bibles/forms/test_bibleimportform.py index cbbef1372..840039fbe 100644 --- a/tests/interfaces/openlp_plugins/bibles/forms/test_bibleimportform.py +++ b/tests/interfaces/openlp_plugins/bibles/forms/test_bibleimportform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -28,8 +28,7 @@ from unittest.mock import MagicMock, patch from PyQt5 import QtWidgets from openlp.core.common.registry import Registry -from openlp.plugins.bibles.forms.bibleimportform import BibleImportForm, PYSWORD_AVAILABLE - +from openlp.plugins.bibles.forms.bibleimportform import BibleImportForm from tests.helpers.testmixin import TestMixin @@ -78,7 +77,7 @@ class TestBibleImportForm(TestCase, TestMixin): self.form.on_web_update_button_clicked() # THEN: The webbible list should still be empty - self.assertEqual(self.form.web_bible_list, {}, 'The webbible list should be empty') + assert self.form.web_bible_list == {}, 'The webbible list should be empty' def test_custom_init(self): """ diff --git a/tests/interfaces/openlp_plugins/bibles/test_lib_http.py b/tests/interfaces/openlp_plugins/bibles/test_lib_http.py index 1ec6cb8ba..3160a2ad6 100644 --- a/tests/interfaces/openlp_plugins/bibles/test_lib_http.py +++ b/tests/interfaces/openlp_plugins/bibles/test_lib_http.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -53,8 +53,8 @@ class TestBibleHTTP(TestCase): books = handler.get_books_from_http('NIV') # THEN: We should get back a valid service item - self.assertEqual(len(books), 66, 'The bible should not have had any books added or removed') - self.assertEqual(books[0], 'Genesis', 'The first bible book should be Genesis') + assert len(books) == 66, 'The bible should not have had any books added or removed' + assert books[0] == 'Genesis', 'The first bible book should be Genesis' def test_bible_gateway_extract_books_support_redirect(self): """ @@ -67,7 +67,7 @@ class TestBibleHTTP(TestCase): books = handler.get_books_from_http('DN1933') # THEN: We should get back a valid service item - self.assertEqual(len(books), 66, 'This bible should have 66 books') + assert len(books) == 66, 'This bible should have 66 books' def test_bible_gateway_extract_verse(self): """ @@ -80,8 +80,7 @@ class TestBibleHTTP(TestCase): results = handler.get_bible_chapter('NIV', 'John', 3) # THEN: We should get back a valid service item - self.assertEqual(len(results.verse_list), 36, - 'The book of John should not have had any verses added or removed') + assert len(results.verse_list) == 36, 'The book of John should not have had any verses added or removed' def test_bible_gateway_extract_verse_nkjv(self): """ @@ -94,8 +93,7 @@ class TestBibleHTTP(TestCase): results = handler.get_bible_chapter('NKJV', 'John', 3) # THEN: We should get back a valid service item - self.assertEqual(len(results.verse_list), 36, - 'The book of John should not have had any verses added or removed') + assert len(results.verse_list) == 36, 'The book of John should not have had any verses added or removed' def test_crosswalk_extract_books(self): """ @@ -108,7 +106,7 @@ class TestBibleHTTP(TestCase): books = handler.get_books_from_http('niv') # THEN: We should get back a valid service item - self.assertEqual(len(books), 66, 'The bible should not have had any books added or removed') + assert len(books) == 66, 'The bible should not have had any books added or removed' def test_crosswalk_extract_verse(self): """ @@ -121,8 +119,7 @@ class TestBibleHTTP(TestCase): results = handler.get_bible_chapter('niv', 'john', 3) # THEN: We should get back a valid service item - self.assertEqual(len(results.verse_list), 36, - 'The book of John should not have had any verses added or removed') + assert len(results.verse_list) == 36, 'The book of John should not have had any verses added or removed' def test_bibleserver_get_bibles(self): """ @@ -135,9 +132,9 @@ class TestBibleHTTP(TestCase): bibles = handler.get_bibles_from_http() # THEN: The list should not be None, and some known bibles should be there - self.assertIsNotNone(bibles) - self.assertIn(('New Int. Readers Version', 'NIRV', 'en'), bibles) - self.assertIn(('Священное Писание, Восточный перевод', 'CARS', 'ru'), bibles) + assert bibles is not None + assert ('New Int. Readers Version', 'NIRV', 'en') in bibles + assert ('Священное Писание, Восточный перевод', 'CARS', 'ru') in bibles def test_biblegateway_get_bibles(self): """ @@ -150,8 +147,8 @@ class TestBibleHTTP(TestCase): bibles = handler.get_bibles_from_http() # THEN: The list should not be None, and some known bibles should be there - self.assertIsNotNone(bibles) - self.assertIn(('Holman Christian Standard Bible (HCSB)', 'HCSB', 'en'), bibles) + assert bibles is not None + assert ('Holman Christian Standard Bible (HCSB)', 'HCSB', 'en') in bibles def test_crosswalk_get_bibles(self): """ @@ -164,8 +161,8 @@ class TestBibleHTTP(TestCase): bibles = handler.get_bibles_from_http() # THEN: The list should not be None, and some known bibles should be there - self.assertIsNotNone(bibles) - self.assertIn(('Giovanni Diodati 1649 (Italian)', 'gdb', 'it'), bibles) + assert bibles is not None + assert ('Giovanni Diodati 1649 (Italian)', 'gdb', 'it') in bibles def test_crosswalk_get_verse_text(self): """ @@ -178,7 +175,6 @@ class TestBibleHTTP(TestCase): niv_genesis_chapter_one = handler.get_bible_chapter('niv', 'Genesis', 1) # THEN: The verse list should contain the verses - self.assertTrue(niv_genesis_chapter_one.has_verse_list()) - self.assertEquals('In the beginning God created the heavens and the earth.', - niv_genesis_chapter_one.verse_list[1], - 'The first chapter of genesis should have been fetched.') + assert niv_genesis_chapter_one.has_verse_list() is True + assert 'In the beginning God created the heavens and the earth.' == niv_genesis_chapter_one.verse_list[1], \ + 'The first chapter of genesis should have been fetched.' diff --git a/tests/interfaces/openlp_plugins/bibles/test_lib_manager.py b/tests/interfaces/openlp_plugins/bibles/test_lib_manager.py index 45e68a572..4252a2064 100644 --- a/tests/interfaces/openlp_plugins/bibles/test_lib_manager.py +++ b/tests/interfaces/openlp_plugins/bibles/test_lib_manager.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -28,9 +28,8 @@ from unittest.mock import MagicMock, patch from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings from openlp.plugins.bibles.lib import BibleManager, LanguageSelection - -from tests.utils.constants import TEST_RESOURCES_PATH from tests.helpers.testmixin import TestMixin +from tests.utils.constants import TEST_RESOURCES_PATH class TestBibleManager(TestCase, TestMixin): @@ -79,7 +78,7 @@ class TestBibleManager(TestCase, TestMixin): # WHEN asking for the books of the bible books = self.manager.get_books('tests') # THEN a list of books should be returned - self.assertEqual(66, len(books), 'There should be 66 books in the bible') + assert 66 == len(books), 'There should be 66 books in the bible' def test_get_book_by_id(self): """ @@ -89,7 +88,7 @@ class TestBibleManager(TestCase, TestMixin): # WHEN asking for the book of the bible book = self.manager.get_book_by_id('tests', 54) # THEN a book should be returned - self.assertEqual('1 Timothy', book.name, '1 Timothy should have been returned from the bible') + assert '1 Timothy' == book.name, '1 Timothy should have been returned from the bible' def test_get_chapter_count(self): """ @@ -100,7 +99,7 @@ class TestBibleManager(TestCase, TestMixin): book = self.manager.get_book_by_id('tests', 54) chapter = self.manager.get_chapter_count('tests', book) # THEN the chapter count should be returned - self.assertEqual(6, chapter, '1 Timothy should have 6 chapters returned from the bible') + assert 6 == chapter, '1 Timothy should have 6 chapters returned from the bible' def test_get_verse_count_by_book_ref_id(self): """ @@ -110,4 +109,4 @@ class TestBibleManager(TestCase, TestMixin): # WHEN asking for the number of verses in a book of the bible verses = self.manager.get_verse_count_by_book_ref_id('tests', 54, 3) # THEN the chapter count should be returned - self.assertEqual(16, verses, '1 Timothy v3 should have 16 verses returned from the bible') + assert 16 == verses, '1 Timothy v3 should have 16 verses returned from the bible' diff --git a/tests/interfaces/openlp_plugins/bibles/test_lib_parse_reference.py b/tests/interfaces/openlp_plugins/bibles/test_lib_parse_reference.py index 18f5f5762..bf1057667 100644 --- a/tests/interfaces/openlp_plugins/bibles/test_lib_parse_reference.py +++ b/tests/interfaces/openlp_plugins/bibles/test_lib_parse_reference.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -28,9 +28,8 @@ from unittest.mock import MagicMock, patch from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings from openlp.plugins.bibles.lib import BibleManager, parse_reference, LanguageSelection - -from tests.utils.constants import TEST_RESOURCES_PATH from tests.helpers.testmixin import TestMixin +from tests.utils.constants import TEST_RESOURCES_PATH class TestBibleManager(TestCase, TestMixin): @@ -79,7 +78,7 @@ class TestBibleManager(TestCase, TestMixin): # WHEN asking to parse the bible reference results = parse_reference('1 Timothy 1', self.manager.db_cache['tests'], MagicMock(), 54) # THEN a verse array should be returned - self.assertEqual([(54, 1, 1, -1)], results, "The bible verses should matches the expected results") + assert [(54, 1, 1, -1)] == results, "The bible verses should matches the expected results" def test_parse_reference_two(self): """ @@ -89,7 +88,7 @@ class TestBibleManager(TestCase, TestMixin): # WHEN asking to parse the bible reference results = parse_reference('1 Timothy 1:1-2', self.manager.db_cache['tests'], MagicMock(), 54) # THEN a verse array should be returned - self.assertEqual([(54, 1, 1, 2)], results, "The bible verses should matches the expected results") + assert [(54, 1, 1, 2)] == results, "The bible verses should matches the expected results" def test_parse_reference_three(self): """ @@ -99,8 +98,8 @@ class TestBibleManager(TestCase, TestMixin): # WHEN asking to parse the bible reference results = parse_reference('1 Timothy 1:1-2:1', self.manager.db_cache['tests'], MagicMock(), 54) # THEN a verse array should be returned - self.assertEqual([(54, 1, 1, -1), (54, 2, 1, 1)], results, - "The bible verses should match the expected results") + assert [(54, 1, 1, -1), (54, 2, 1, 1)] == results, \ + "The bible verses should match the expected results" def test_parse_reference_four(self): """ @@ -110,7 +109,7 @@ class TestBibleManager(TestCase, TestMixin): # WHEN asking to parse the bible reference results = parse_reference('Raoul 1', self.manager.db_cache['tests'], MagicMock()) # THEN a verse array should be returned - self.assertEqual([], results, "The bible Search should return an empty list") + assert [] == results, "The bible Search should return an empty list" def test_parse_reference_five(self): """ @@ -120,4 +119,4 @@ class TestBibleManager(TestCase, TestMixin): # WHEN asking to parse the bible reference results = parse_reference('1 Timothy 1:3-end', self.manager.db_cache['tests'], MagicMock(), 54) # THEN a verse array should be returned - self.assertEqual([(54, 1, 3, -1)], results, "The bible verses should matches the expected results") + assert [(54, 1, 3, -1)] == results, "The bible verses should matches the expected results" diff --git a/tests/interfaces/openlp_plugins/custom/__init__.py b/tests/interfaces/openlp_plugins/custom/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/interfaces/openlp_plugins/custom/__init__.py +++ b/tests/interfaces/openlp_plugins/custom/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/interfaces/openlp_plugins/custom/forms/__init__.py b/tests/interfaces/openlp_plugins/custom/forms/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/interfaces/openlp_plugins/custom/forms/__init__.py +++ b/tests/interfaces/openlp_plugins/custom/forms/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/interfaces/openlp_plugins/custom/forms/test_customform.py b/tests/interfaces/openlp_plugins/custom/forms/test_customform.py index 5f486a219..96f265970 100644 --- a/tests/interfaces/openlp_plugins/custom/forms/test_customform.py +++ b/tests/interfaces/openlp_plugins/custom/forms/test_customform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -28,9 +28,7 @@ from unittest.mock import MagicMock, patch from PyQt5 import QtTest, QtCore, QtWidgets from openlp.core.common.registry import Registry -from openlp.plugins.custom.lib.mediaitem import CustomMediaItem from openlp.plugins.custom.forms.editcustomform import EditCustomForm - from tests.helpers.testmixin import TestMixin @@ -78,8 +76,8 @@ class TestEditCustomForm(TestCase, TestMixin): self.form.load_custom(0) # THEN: The line edits should not contain any text. - self.assertEqual(self.form.title_edit.text(), '', 'The title edit should be empty') - self.assertEqual(self.form.credit_edit.text(), '', 'The credit edit should be empty') + assert self.form.title_edit.text() == '', 'The title edit should be empty' + assert self.form.credit_edit.text() == '', 'The credit edit should be empty' def test_on_add_button_clicked(self): """ diff --git a/tests/interfaces/openlp_plugins/custom/forms/test_customslideform.py b/tests/interfaces/openlp_plugins/custom/forms/test_customslideform.py index 97d9bb652..f7d5abdd7 100644 --- a/tests/interfaces/openlp_plugins/custom/forms/test_customslideform.py +++ b/tests/interfaces/openlp_plugins/custom/forms/test_customslideform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -29,7 +29,6 @@ from PyQt5 import QtWidgets from openlp.core.common.registry import Registry from openlp.plugins.custom.forms.editcustomslideform import EditCustomSlideForm - from tests.helpers.testmixin import TestMixin diff --git a/tests/interfaces/openlp_plugins/media/__init__.py b/tests/interfaces/openlp_plugins/media/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/interfaces/openlp_plugins/media/__init__.py +++ b/tests/interfaces/openlp_plugins/media/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/interfaces/openlp_plugins/media/forms/__init__.py b/tests/interfaces/openlp_plugins/media/forms/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/interfaces/openlp_plugins/media/forms/__init__.py +++ b/tests/interfaces/openlp_plugins/media/forms/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/interfaces/openlp_plugins/media/forms/test_mediaclipselectorform.py b/tests/interfaces/openlp_plugins/media/forms/test_mediaclipselectorform.py index a49a35d48..69e98da5d 100644 --- a/tests/interfaces/openlp_plugins/media/forms/test_mediaclipselectorform.py +++ b/tests/interfaces/openlp_plugins/media/forms/test_mediaclipselectorform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/interfaces/openlp_plugins/songs/__init__.py b/tests/interfaces/openlp_plugins/songs/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/interfaces/openlp_plugins/songs/__init__.py +++ b/tests/interfaces/openlp_plugins/songs/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/interfaces/openlp_plugins/songs/forms/__init__.py b/tests/interfaces/openlp_plugins/songs/forms/__init__.py index ea62548f4..711ded4ae 100644 --- a/tests/interfaces/openlp_plugins/songs/forms/__init__.py +++ b/tests/interfaces/openlp_plugins/songs/forms/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # diff --git a/tests/interfaces/openlp_plugins/songs/forms/test_authorsform.py b/tests/interfaces/openlp_plugins/songs/forms/test_authorsform.py index a2de38693..85523d541 100644 --- a/tests/interfaces/openlp_plugins/songs/forms/test_authorsform.py +++ b/tests/interfaces/openlp_plugins/songs/forms/test_authorsform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -58,9 +58,9 @@ class TestAuthorsForm(TestCase, TestMixin): """ Test the AuthorForm defaults are correct """ - self.assertEqual(self.form.first_name_edit.text(), '', 'The first name edit should be empty') - self.assertEqual(self.form.last_name_edit.text(), '', 'The last name edit should be empty') - self.assertEqual(self.form.display_edit.text(), '', 'The display name edit should be empty') + assert self.form.first_name_edit.text() == '', 'The first name edit should be empty' + assert self.form.last_name_edit.text() == '', 'The last name edit should be empty' + assert self.form.display_edit.text() == '', 'The display name edit should be empty' def test_get_first_name_property(self): """ @@ -73,7 +73,7 @@ class TestAuthorsForm(TestCase, TestMixin): self.form.first_name_edit.setText(first_name) # THEN: The first_name property should have the correct value - self.assertEqual(self.form.first_name, first_name, 'The first name property should be correct') + assert self.form.first_name == first_name, 'The first name property should be correct' def test_set_first_name_property(self): """ @@ -86,7 +86,7 @@ class TestAuthorsForm(TestCase, TestMixin): self.form.first_name = first_name # THEN: The first_name_edit should have the correct value - self.assertEqual(self.form.first_name_edit.text(), first_name, 'The first name should be set correctly') + assert self.form.first_name_edit.text() == first_name, 'The first name should be set correctly' def test_get_last_name_property(self): """ @@ -99,7 +99,7 @@ class TestAuthorsForm(TestCase, TestMixin): self.form.last_name_edit.setText(last_name) # THEN: The last_name property should have the correct value - self.assertEqual(self.form.last_name, last_name, 'The last name property should be correct') + assert self.form.last_name == last_name, 'The last name property should be correct' def test_set_last_name_property(self): """ @@ -112,7 +112,7 @@ class TestAuthorsForm(TestCase, TestMixin): self.form.last_name = last_name # THEN: The last_name_edit should have the correct value - self.assertEqual(self.form.last_name_edit.text(), last_name, 'The last name should be set correctly') + assert self.form.last_name_edit.text() == last_name, 'The last name should be set correctly' def test_get_display_name_property(self): """ @@ -125,7 +125,7 @@ class TestAuthorsForm(TestCase, TestMixin): self.form.display_edit.setText(display_name) # THEN: The display_name property should have the correct value - self.assertEqual(self.form.display_name, display_name, 'The display name property should be correct') + assert self.form.display_name == display_name, 'The display name property should be correct' def test_set_display_name_property(self): """ @@ -138,7 +138,7 @@ class TestAuthorsForm(TestCase, TestMixin): self.form.display_name = display_name # THEN: The display_name_edit should have the correct value - self.assertEqual(self.form.display_edit.text(), display_name, 'The display name should be set correctly') + assert self.form.display_edit.text() == display_name, 'The display name should be set correctly' @patch('openlp.plugins.songs.forms.authorsform.QtWidgets.QDialog.exec') def test_exec(self, mocked_exec): diff --git a/tests/interfaces/openlp_plugins/songs/forms/test_editsongform.py b/tests/interfaces/openlp_plugins/songs/forms/test_editsongform.py index 446368373..ab9384863 100644 --- a/tests/interfaces/openlp_plugins/songs/forms/test_editsongform.py +++ b/tests/interfaces/openlp_plugins/songs/forms/test_editsongform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -31,7 +31,6 @@ from openlp.core.common.i18n import UiStrings from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings from openlp.plugins.songs.forms.editsongform import EditSongForm - from tests.helpers.testmixin import TestMixin __default_settings__ = { @@ -69,10 +68,10 @@ class TestEditSongForm(TestCase, TestMixin): """ Test that the EditSongForm defaults are correct """ - self.assertFalse(self.form.verse_edit_button.isEnabled(), 'The verse edit button should not be enabled') - self.assertFalse(self.form.verse_delete_button.isEnabled(), 'The verse delete button should not be enabled') - self.assertFalse(self.form.author_remove_button.isEnabled(), 'The author remove button should not be enabled') - self.assertFalse(self.form.topic_remove_button.isEnabled(), 'The topic remove button should not be enabled') + assert self.form.verse_edit_button.isEnabled() is False, 'The verse edit button should not be enabled' + assert self.form.verse_delete_button.isEnabled() is False, 'The verse delete button should not be enabled' + assert self.form.author_remove_button.isEnabled() is False, 'The author remove button should not be enabled' + assert self.form.topic_remove_button.isEnabled() is False, 'The topic remove button should not be enabled' def test_is_verse_edit_form_executed(self): pass @@ -147,10 +146,10 @@ class TestEditSongForm(TestCase, TestMixin): # GIVEN; Mocked methods form = self.form # THEN: CCLI label should be CCLI song label - self.assertNotEquals(form.ccli_label.text(), UiStrings().CCLINumberLabel, - 'CCLI label should not be "{}"'.format(UiStrings().CCLINumberLabel)) - self.assertEquals(form.ccli_label.text(), UiStrings().CCLISongNumberLabel, - 'CCLI label text should be "{}"'.format(UiStrings().CCLISongNumberLabel)) + assert form.ccli_label.text() is not UiStrings().CCLINumberLabel, \ + 'CCLI label should not be "{}"'.format(UiStrings().CCLINumberLabel) + assert form.ccli_label.text() == UiStrings().CCLISongNumberLabel, \ + 'CCLI label text should be "{}"'.format(UiStrings().CCLISongNumberLabel) def test_verse_order_lowercase(self): """ @@ -165,4 +164,4 @@ class TestEditSongForm(TestCase, TestMixin): form.on_verse_order_text_changed(form.verse_order_edit.text()) # THEN: The verse order should be converted to uppercase - self.assertEqual(form.verse_order_edit.text(), 'V1 V2 C1 V3 C1 V4 C1') + assert form.verse_order_edit.text() == 'V1 V2 C1 V3 C1 V4 C1' diff --git a/tests/interfaces/openlp_plugins/songs/forms/test_editverseform.py b/tests/interfaces/openlp_plugins/songs/forms/test_editverseform.py index d12305089..500d52af3 100644 --- a/tests/interfaces/openlp_plugins/songs/forms/test_editverseform.py +++ b/tests/interfaces/openlp_plugins/songs/forms/test_editverseform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -68,7 +68,7 @@ class TestEditVerseForm(TestCase, TestMixin): # GIVEN: An EditVerseForm instance # WHEN: The form is shown # THEN: The default value is correct - self.assertEqual(self.form.verse_text_edit.toPlainText(), '', 'The verse edit box is empty.') + assert self.form.verse_text_edit.toPlainText() == '', 'The verse edit box is empty.' def test_type_verse_text(self): """ @@ -81,8 +81,8 @@ class TestEditVerseForm(TestCase, TestMixin): QtTest.QTest.keyClicks(self.form.verse_text_edit, text) # THEN: The verse text edit should have the verse text in it - self.assertEqual(text, self.form.verse_text_edit.toPlainText(), - 'The verse text edit should have the typed out verse') + assert text == self.form.verse_text_edit.toPlainText(), \ + 'The verse text edit should have the typed out verse' def test_insert_verse(self): """ @@ -93,8 +93,8 @@ class TestEditVerseForm(TestCase, TestMixin): QtTest.QTest.mouseClick(self.form.insert_button, QtCore.Qt.LeftButton) # THEN: The verse text edit should have a Verse:1 in it - self.assertIn('---[Verse:1]---', self.form.verse_text_edit.toPlainText(), - 'The verse text edit should have a verse marker') + assert '---[Verse:1]---' in self.form.verse_text_edit.toPlainText(), \ + 'The verse text edit should have a verse marker' def test_insert_verse_2(self): """ @@ -106,8 +106,8 @@ class TestEditVerseForm(TestCase, TestMixin): QtTest.QTest.mouseClick(self.form.insert_button, QtCore.Qt.LeftButton) # THEN: The verse text edit should have a Verse:1 in it - self.assertIn('---[Verse:2]---', self.form.verse_text_edit.toPlainText(), - 'The verse text edit should have a "Verse 2" marker') + assert '---[Verse:2]---' in self.form.verse_text_edit.toPlainText(), \ + 'The verse text edit should have a "Verse 2" marker' def test_insert_chorus(self): """ @@ -119,5 +119,5 @@ class TestEditVerseForm(TestCase, TestMixin): QtTest.QTest.mouseClick(self.form.insert_button, QtCore.Qt.LeftButton) # THEN: The verse text edit should have a Chorus:1 in it - self.assertIn('---[Chorus:1]---', self.form.verse_text_edit.toPlainText(), - 'The verse text edit should have a "Chorus 1" marker') + assert '---[Chorus:1]---' in self.form.verse_text_edit.toPlainText(), \ + 'The verse text edit should have a "Chorus 1" marker' diff --git a/tests/interfaces/openlp_plugins/songs/forms/test_songmaintenanceform.py b/tests/interfaces/openlp_plugins/songs/forms/test_songmaintenanceform.py index d9786db7a..6b1788690 100644 --- a/tests/interfaces/openlp_plugins/songs/forms/test_songmaintenanceform.py +++ b/tests/interfaces/openlp_plugins/songs/forms/test_songmaintenanceform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -30,7 +30,6 @@ from PyQt5 import QtCore, QtWidgets from openlp.core.common.i18n import UiStrings from openlp.core.common.registry import Registry from openlp.plugins.songs.forms.songmaintenanceform import SongMaintenanceForm - from tests.helpers.testmixin import TestMixin diff --git a/tests/interfaces/openlp_plugins/songs/forms/test_topicsform.py b/tests/interfaces/openlp_plugins/songs/forms/test_topicsform.py index 07808339f..a5449b26a 100644 --- a/tests/interfaces/openlp_plugins/songs/forms/test_topicsform.py +++ b/tests/interfaces/openlp_plugins/songs/forms/test_topicsform.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -57,7 +57,7 @@ class TestTopicsForm(TestCase, TestMixin): """ Test the TopicsForm defaults are correct """ - self.assertEqual(self.form.name_edit.text(), '', 'The first name edit should be empty') + assert self.form.name_edit.text() == '', 'The first name edit should be empty' def test_get_name_property(self): """ @@ -70,7 +70,7 @@ class TestTopicsForm(TestCase, TestMixin): self.form.name_edit.setText(topic_name) # THEN: The name property should have the correct value - self.assertEqual(self.form.name, topic_name, 'The name property should be correct') + assert self.form.name == topic_name, 'The name property should be correct' def test_set_name_property(self): """ @@ -83,4 +83,4 @@ class TestTopicsForm(TestCase, TestMixin): self.form.name = topic_name # THEN: The name_edit should have the correct value - self.assertEqual(self.form.name_edit.text(), topic_name, 'The topic name should be set correctly') + assert self.form.name_edit.text() == topic_name, 'The topic name should be set correctly' diff --git a/tests/resources/projector/data.py b/tests/resources/projector/data.py index d9baa80d0..acfb51df9 100644 --- a/tests/resources/projector/data.py +++ b/tests/resources/projector/data.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -23,9 +23,6 @@ The :mod:`tests.resources.projector.data file contains test data """ -import os -from tempfile import gettempdir - # Test data TEST_DB_PJLINK1 = 'projector_pjlink1.sqlite' diff --git a/tests/resources/chordprosongs/swing-low.chordpro b/tests/resources/songs/chordpro/swing-low.chordpro similarity index 100% rename from tests/resources/chordprosongs/swing-low.chordpro rename to tests/resources/songs/chordpro/swing-low.chordpro diff --git a/tests/resources/chordprosongs/swing-low.json b/tests/resources/songs/chordpro/swing-low.json similarity index 100% rename from tests/resources/chordprosongs/swing-low.json rename to tests/resources/songs/chordpro/swing-low.json diff --git a/tests/resources/easyslidessongs/Amazing Grace.json b/tests/resources/songs/easyslides/Amazing Grace.json similarity index 100% rename from tests/resources/easyslidessongs/Amazing Grace.json rename to tests/resources/songs/easyslides/Amazing Grace.json diff --git a/tests/resources/easyslidessongs/Export_2017-01-12_BB.json b/tests/resources/songs/easyslides/Export_2017-01-12_BB.json similarity index 100% rename from tests/resources/easyslidessongs/Export_2017-01-12_BB.json rename to tests/resources/songs/easyslides/Export_2017-01-12_BB.json diff --git a/tests/resources/easyslidessongs/Export_2017-01-12_BB.xml b/tests/resources/songs/easyslides/Export_2017-01-12_BB.xml similarity index 100% rename from tests/resources/easyslidessongs/Export_2017-01-12_BB.xml rename to tests/resources/songs/easyslides/Export_2017-01-12_BB.xml diff --git a/tests/resources/easyslidessongs/amazing-grace.xml b/tests/resources/songs/easyslides/amazing-grace.xml similarity index 100% rename from tests/resources/easyslidessongs/amazing-grace.xml rename to tests/resources/songs/easyslides/amazing-grace.xml diff --git a/tests/resources/easyworshipsongs/Songs.DB b/tests/resources/songs/easyworship/Songs.DB similarity index 100% rename from tests/resources/easyworshipsongs/Songs.DB rename to tests/resources/songs/easyworship/Songs.DB diff --git a/tests/resources/easyworshipsongs/Songs.MB b/tests/resources/songs/easyworship/Songs.MB similarity index 100% rename from tests/resources/easyworshipsongs/Songs.MB rename to tests/resources/songs/easyworship/Songs.MB diff --git a/tests/resources/easyworshipsongs/ew6/Databases/Data/SongWords.db b/tests/resources/songs/easyworship/ew6/Databases/Data/SongWords.db similarity index 100% rename from tests/resources/easyworshipsongs/ew6/Databases/Data/SongWords.db rename to tests/resources/songs/easyworship/ew6/Databases/Data/SongWords.db diff --git a/tests/resources/easyworshipsongs/ew6/Databases/Data/Songs.db b/tests/resources/songs/easyworship/ew6/Databases/Data/Songs.db similarity index 100% rename from tests/resources/easyworshipsongs/ew6/Databases/Data/Songs.db rename to tests/resources/songs/easyworship/ew6/Databases/Data/Songs.db diff --git a/tests/resources/easyworshipsongs/test1.ews b/tests/resources/songs/easyworship/test1.ews similarity index 100% rename from tests/resources/easyworshipsongs/test1.ews rename to tests/resources/songs/easyworship/test1.ews diff --git a/tests/resources/lyrixsongs/A002.TXT b/tests/resources/songs/lyrix/A002.TXT similarity index 100% rename from tests/resources/lyrixsongs/A002.TXT rename to tests/resources/songs/lyrix/A002.TXT diff --git a/tests/resources/lyrixsongs/A06.TXT b/tests/resources/songs/lyrix/A06.TXT similarity index 100% rename from tests/resources/lyrixsongs/A06.TXT rename to tests/resources/songs/lyrix/A06.TXT diff --git a/tests/resources/lyrixsongs/AO05.TXT b/tests/resources/songs/lyrix/AO05.TXT similarity index 100% rename from tests/resources/lyrixsongs/AO05.TXT rename to tests/resources/songs/lyrix/AO05.TXT diff --git a/tests/resources/lyrixsongs/Amazing Grace.json b/tests/resources/songs/lyrix/Amazing Grace.json similarity index 100% rename from tests/resources/lyrixsongs/Amazing Grace.json rename to tests/resources/songs/lyrix/Amazing Grace.json diff --git a/tests/resources/lyrixsongs/Amazing Grace2.json b/tests/resources/songs/lyrix/Amazing Grace2.json similarity index 100% rename from tests/resources/lyrixsongs/Amazing Grace2.json rename to tests/resources/songs/lyrix/Amazing Grace2.json diff --git a/tests/resources/lyrixsongs/in die regterhand.json b/tests/resources/songs/lyrix/in die regterhand.json similarity index 100% rename from tests/resources/lyrixsongs/in die regterhand.json rename to tests/resources/songs/lyrix/in die regterhand.json diff --git a/tests/resources/openlyricssongs/What a friend we have in Jesus.xml b/tests/resources/songs/openlyrics/What a friend we have in Jesus.xml similarity index 100% rename from tests/resources/openlyricssongs/What a friend we have in Jesus.xml rename to tests/resources/songs/openlyrics/What a friend we have in Jesus.xml diff --git a/tests/resources/openlyricssongs/duchu-tags.xml b/tests/resources/songs/openlyrics/duchu-tags.xml similarity index 100% rename from tests/resources/openlyricssongs/duchu-tags.xml rename to tests/resources/songs/openlyrics/duchu-tags.xml diff --git a/tests/resources/opensongsongs/Amazing Grace b/tests/resources/songs/opensong/Amazing Grace similarity index 100% rename from tests/resources/opensongsongs/Amazing Grace rename to tests/resources/songs/opensong/Amazing Grace diff --git a/tests/resources/opensongsongs/Amazing Grace with bad CCLI b/tests/resources/songs/opensong/Amazing Grace with bad CCLI similarity index 100% rename from tests/resources/opensongsongs/Amazing Grace with bad CCLI rename to tests/resources/songs/opensong/Amazing Grace with bad CCLI diff --git a/tests/resources/opensongsongs/Amazing Grace without CCLI.json b/tests/resources/songs/opensong/Amazing Grace without CCLI.json similarity index 100% rename from tests/resources/opensongsongs/Amazing Grace without CCLI.json rename to tests/resources/songs/opensong/Amazing Grace without CCLI.json diff --git a/tests/resources/opensongsongs/Amazing Grace.json b/tests/resources/songs/opensong/Amazing Grace.json similarity index 100% rename from tests/resources/opensongsongs/Amazing Grace.json rename to tests/resources/songs/opensong/Amazing Grace.json diff --git a/tests/resources/opensongsongs/Amazing Grace2 b/tests/resources/songs/opensong/Amazing Grace2 similarity index 100% rename from tests/resources/opensongsongs/Amazing Grace2 rename to tests/resources/songs/opensong/Amazing Grace2 diff --git a/tests/resources/opensongsongs/Beautiful Garden Of Prayer b/tests/resources/songs/opensong/Beautiful Garden Of Prayer similarity index 100% rename from tests/resources/opensongsongs/Beautiful Garden Of Prayer rename to tests/resources/songs/opensong/Beautiful Garden Of Prayer diff --git a/tests/resources/opensongsongs/Beautiful Garden Of Prayer.json b/tests/resources/songs/opensong/Beautiful Garden Of Prayer.json similarity index 100% rename from tests/resources/opensongsongs/Beautiful Garden Of Prayer.json rename to tests/resources/songs/opensong/Beautiful Garden Of Prayer.json diff --git a/tests/resources/opensongsongs/One, Two, Three, Four, Five b/tests/resources/songs/opensong/One, Two, Three, Four, Five similarity index 100% rename from tests/resources/opensongsongs/One, Two, Three, Four, Five rename to tests/resources/songs/opensong/One, Two, Three, Four, Five diff --git a/tests/resources/opensongsongs/One, Two, Three, Four, Five.json b/tests/resources/songs/opensong/One, Two, Three, Four, Five.json similarity index 100% rename from tests/resources/opensongsongs/One, Two, Three, Four, Five.json rename to tests/resources/songs/opensong/One, Two, Three, Four, Five.json diff --git a/tests/resources/opsprosongs/Amazing Grace.json b/tests/resources/songs/opspro/Amazing Grace.json similarity index 100% rename from tests/resources/opsprosongs/Amazing Grace.json rename to tests/resources/songs/opspro/Amazing Grace.json diff --git a/tests/resources/opsprosongs/Amazing Grace3.json b/tests/resources/songs/opspro/Amazing Grace3.json similarity index 100% rename from tests/resources/opsprosongs/Amazing Grace3.json rename to tests/resources/songs/opspro/Amazing Grace3.json diff --git a/tests/resources/opsprosongs/You are so faithful.json b/tests/resources/songs/opspro/You are so faithful.json similarity index 100% rename from tests/resources/opsprosongs/You are so faithful.json rename to tests/resources/songs/opspro/You are so faithful.json diff --git a/tests/resources/opsprosongs/amazing grace.txt b/tests/resources/songs/opspro/amazing grace.txt similarity index 100% rename from tests/resources/opsprosongs/amazing grace.txt rename to tests/resources/songs/opspro/amazing grace.txt diff --git a/tests/resources/opsprosongs/amazing grace2.txt b/tests/resources/songs/opspro/amazing grace2.txt similarity index 100% rename from tests/resources/opsprosongs/amazing grace2.txt rename to tests/resources/songs/opspro/amazing grace2.txt diff --git a/tests/resources/opsprosongs/amazing grace3.txt b/tests/resources/songs/opspro/amazing grace3.txt similarity index 100% rename from tests/resources/opsprosongs/amazing grace3.txt rename to tests/resources/songs/opspro/amazing grace3.txt diff --git a/tests/resources/opsprosongs/you are so faithfull.txt b/tests/resources/songs/opspro/you are so faithfull.txt similarity index 100% rename from tests/resources/opsprosongs/you are so faithfull.txt rename to tests/resources/songs/opspro/you are so faithfull.txt diff --git a/tests/resources/powerpraisesongs/Naher, mein Gott zu Dir.json b/tests/resources/songs/powerpraise/Naher, mein Gott zu Dir.json similarity index 100% rename from tests/resources/powerpraisesongs/Naher, mein Gott zu Dir.json rename to tests/resources/songs/powerpraise/Naher, mein Gott zu Dir.json diff --git a/tests/resources/powerpraisesongs/Naher, mein Gott zu Dir.ppl b/tests/resources/songs/powerpraise/Naher, mein Gott zu Dir.ppl similarity index 100% rename from tests/resources/powerpraisesongs/Naher, mein Gott zu Dir.ppl rename to tests/resources/songs/powerpraise/Naher, mein Gott zu Dir.ppl diff --git a/tests/resources/powerpraisesongs/You are so faithful.json b/tests/resources/songs/powerpraise/You are so faithful.json similarity index 100% rename from tests/resources/powerpraisesongs/You are so faithful.json rename to tests/resources/songs/powerpraise/You are so faithful.json diff --git a/tests/resources/powerpraisesongs/You are so faithful.ppl b/tests/resources/songs/powerpraise/You are so faithful.ppl similarity index 100% rename from tests/resources/powerpraisesongs/You are so faithful.ppl rename to tests/resources/songs/powerpraise/You are so faithful.ppl diff --git a/tests/resources/presentationmanagersongs/Amazing Grace.json b/tests/resources/songs/presentationmanager/Amazing Grace.json similarity index 100% rename from tests/resources/presentationmanagersongs/Amazing Grace.json rename to tests/resources/songs/presentationmanager/Amazing Grace.json diff --git a/tests/resources/presentationmanagersongs/Amazing Grace.sng b/tests/resources/songs/presentationmanager/Amazing Grace.sng similarity index 100% rename from tests/resources/presentationmanagersongs/Amazing Grace.sng rename to tests/resources/songs/presentationmanager/Amazing Grace.sng diff --git a/tests/resources/presentationmanagersongs/Great Is Thy Faithfulness.json b/tests/resources/songs/presentationmanager/Great Is Thy Faithfulness.json similarity index 100% rename from tests/resources/presentationmanagersongs/Great Is Thy Faithfulness.json rename to tests/resources/songs/presentationmanager/Great Is Thy Faithfulness.json diff --git a/tests/resources/presentationmanagersongs/Great Is Thy Faithfulness.sng b/tests/resources/songs/presentationmanager/Great Is Thy Faithfulness.sng similarity index 100% rename from tests/resources/presentationmanagersongs/Great Is Thy Faithfulness.sng rename to tests/resources/songs/presentationmanager/Great Is Thy Faithfulness.sng diff --git a/tests/resources/propresentersongs/Amazing Grace.json b/tests/resources/songs/propresenter/Amazing Grace.json similarity index 100% rename from tests/resources/propresentersongs/Amazing Grace.json rename to tests/resources/songs/propresenter/Amazing Grace.json diff --git a/tests/resources/propresentersongs/Amazing Grace.pro4 b/tests/resources/songs/propresenter/Amazing Grace.pro4 similarity index 100% rename from tests/resources/propresentersongs/Amazing Grace.pro4 rename to tests/resources/songs/propresenter/Amazing Grace.pro4 diff --git a/tests/resources/propresentersongs/Amazing Grace.pro5 b/tests/resources/songs/propresenter/Amazing Grace.pro5 similarity index 100% rename from tests/resources/propresentersongs/Amazing Grace.pro5 rename to tests/resources/songs/propresenter/Amazing Grace.pro5 diff --git a/tests/resources/propresentersongs/Amazing Grace.pro6 b/tests/resources/songs/propresenter/Amazing Grace.pro6 similarity index 100% rename from tests/resources/propresentersongs/Amazing Grace.pro6 rename to tests/resources/songs/propresenter/Amazing Grace.pro6 diff --git a/tests/resources/songbeamersongs/Amazing Grace.json b/tests/resources/songs/songbeamer/Amazing Grace.json similarity index 100% rename from tests/resources/songbeamersongs/Amazing Grace.json rename to tests/resources/songs/songbeamer/Amazing Grace.json diff --git a/tests/resources/songbeamersongs/Amazing Grace.sng b/tests/resources/songs/songbeamer/Amazing Grace.sng similarity index 100% rename from tests/resources/songbeamersongs/Amazing Grace.sng rename to tests/resources/songs/songbeamer/Amazing Grace.sng diff --git a/tests/resources/songbeamersongs/Lobsinget dem Herrn.json b/tests/resources/songs/songbeamer/Lobsinget dem Herrn.json similarity index 100% rename from tests/resources/songbeamersongs/Lobsinget dem Herrn.json rename to tests/resources/songs/songbeamer/Lobsinget dem Herrn.json diff --git a/tests/resources/songbeamersongs/Lobsinget dem Herrn.sng b/tests/resources/songs/songbeamer/Lobsinget dem Herrn.sng similarity index 100% rename from tests/resources/songbeamersongs/Lobsinget dem Herrn.sng rename to tests/resources/songs/songbeamer/Lobsinget dem Herrn.sng diff --git a/tests/resources/songbeamersongs/When I Call On You.json b/tests/resources/songs/songbeamer/When I Call On You.json similarity index 100% rename from tests/resources/songbeamersongs/When I Call On You.json rename to tests/resources/songs/songbeamer/When I Call On You.json diff --git a/tests/resources/songbeamersongs/When I Call On You.sng b/tests/resources/songs/songbeamer/When I Call On You.sng similarity index 100% rename from tests/resources/songbeamersongs/When I Call On You.sng rename to tests/resources/songs/songbeamer/When I Call On You.sng diff --git a/tests/resources/songbeamersongs/cp1252song.json b/tests/resources/songs/songbeamer/cp1252song.json similarity index 100% rename from tests/resources/songbeamersongs/cp1252song.json rename to tests/resources/songs/songbeamer/cp1252song.json diff --git a/tests/resources/songbeamersongs/cp1252song.sng b/tests/resources/songs/songbeamer/cp1252song.sng similarity index 100% rename from tests/resources/songbeamersongs/cp1252song.sng rename to tests/resources/songs/songbeamer/cp1252song.sng diff --git a/tests/resources/songprosongs/Amazing Grace.json b/tests/resources/songs/songpro/Amazing Grace.json similarity index 100% rename from tests/resources/songprosongs/Amazing Grace.json rename to tests/resources/songs/songpro/Amazing Grace.json diff --git a/tests/resources/songprosongs/amazing-grace.txt b/tests/resources/songs/songpro/amazing-grace.txt similarity index 100% rename from tests/resources/songprosongs/amazing-grace.txt rename to tests/resources/songs/songpro/amazing-grace.txt diff --git a/tests/resources/songselect/TestSong-bin.json b/tests/resources/songs/songselect/TestSong-bin.json similarity index 100% rename from tests/resources/songselect/TestSong-bin.json rename to tests/resources/songs/songselect/TestSong-bin.json diff --git a/tests/resources/songselect/TestSong-txt.json b/tests/resources/songs/songselect/TestSong-txt.json similarity index 100% rename from tests/resources/songselect/TestSong-txt.json rename to tests/resources/songs/songselect/TestSong-txt.json diff --git a/tests/resources/songselect/TestSong.bin b/tests/resources/songs/songselect/TestSong.bin similarity index 100% rename from tests/resources/songselect/TestSong.bin rename to tests/resources/songs/songselect/TestSong.bin diff --git a/tests/resources/songselect/TestSong.txt b/tests/resources/songs/songselect/TestSong.txt similarity index 100% rename from tests/resources/songselect/TestSong.txt rename to tests/resources/songs/songselect/TestSong.txt diff --git a/tests/resources/songshowplussongs/Amazing Grace.json b/tests/resources/songs/songshowplus/Amazing Grace.json similarity index 100% rename from tests/resources/songshowplussongs/Amazing Grace.json rename to tests/resources/songs/songshowplus/Amazing Grace.json diff --git a/tests/resources/songshowplussongs/Amazing Grace.sbsong b/tests/resources/songs/songshowplus/Amazing Grace.sbsong similarity index 100% rename from tests/resources/songshowplussongs/Amazing Grace.sbsong rename to tests/resources/songs/songshowplus/Amazing Grace.sbsong diff --git a/tests/resources/songshowplussongs/Beautiful Garden Of Prayer.json b/tests/resources/songs/songshowplus/Beautiful Garden Of Prayer.json similarity index 100% rename from tests/resources/songshowplussongs/Beautiful Garden Of Prayer.json rename to tests/resources/songs/songshowplus/Beautiful Garden Of Prayer.json diff --git a/tests/resources/songshowplussongs/Beautiful Garden Of Prayer.sbsong b/tests/resources/songs/songshowplus/Beautiful Garden Of Prayer.sbsong similarity index 100% rename from tests/resources/songshowplussongs/Beautiful Garden Of Prayer.sbsong rename to tests/resources/songs/songshowplus/Beautiful Garden Of Prayer.sbsong diff --git a/tests/resources/songshowplussongs/a mighty fortress is our god.json b/tests/resources/songs/songshowplus/a mighty fortress is our god.json similarity index 100% rename from tests/resources/songshowplussongs/a mighty fortress is our god.json rename to tests/resources/songs/songshowplus/a mighty fortress is our god.json diff --git a/tests/resources/songshowplussongs/a mighty fortress is our god.sbsong b/tests/resources/songs/songshowplus/a mighty fortress is our god.sbsong similarity index 100% rename from tests/resources/songshowplussongs/a mighty fortress is our god.sbsong rename to tests/resources/songs/songshowplus/a mighty fortress is our god.sbsong diff --git a/tests/resources/songshowplussongs/cleanse-me.json b/tests/resources/songs/songshowplus/cleanse-me.json similarity index 100% rename from tests/resources/songshowplussongs/cleanse-me.json rename to tests/resources/songs/songshowplus/cleanse-me.json diff --git a/tests/resources/songshowplussongs/cleanse-me.sbsong b/tests/resources/songs/songshowplus/cleanse-me.sbsong similarity index 100% rename from tests/resources/songshowplussongs/cleanse-me.sbsong rename to tests/resources/songs/songshowplus/cleanse-me.sbsong diff --git a/tests/resources/sundayplussongs/Amazing Grace.json b/tests/resources/songs/sundayplus/Amazing Grace.json similarity index 100% rename from tests/resources/sundayplussongs/Amazing Grace.json rename to tests/resources/songs/sundayplus/Amazing Grace.json diff --git a/tests/resources/sundayplussongs/Amazing Grace.ptf b/tests/resources/songs/sundayplus/Amazing Grace.ptf similarity index 100% rename from tests/resources/sundayplussongs/Amazing Grace.ptf rename to tests/resources/songs/sundayplus/Amazing Grace.ptf diff --git a/tests/resources/videopsalmsongs/as-safe-a-stronghold.json b/tests/resources/songs/videopsalm/as-safe-a-stronghold.json similarity index 100% rename from tests/resources/videopsalmsongs/as-safe-a-stronghold.json rename to tests/resources/songs/videopsalm/as-safe-a-stronghold.json diff --git a/tests/resources/videopsalmsongs/as-safe-a-stronghold2.json b/tests/resources/songs/videopsalm/as-safe-a-stronghold2.json similarity index 100% rename from tests/resources/videopsalmsongs/as-safe-a-stronghold2.json rename to tests/resources/songs/videopsalm/as-safe-a-stronghold2.json diff --git a/tests/resources/videopsalmsongs/videopsalm-as-safe-a-stronghold.json b/tests/resources/songs/videopsalm/videopsalm-as-safe-a-stronghold.json similarity index 100% rename from tests/resources/videopsalmsongs/videopsalm-as-safe-a-stronghold.json rename to tests/resources/songs/videopsalm/videopsalm-as-safe-a-stronghold.json diff --git a/tests/resources/videopsalmsongs/videopsalm-as-safe-a-stronghold2.json b/tests/resources/songs/videopsalm/videopsalm-as-safe-a-stronghold2.json similarity index 100% rename from tests/resources/videopsalmsongs/videopsalm-as-safe-a-stronghold2.json rename to tests/resources/songs/videopsalm/videopsalm-as-safe-a-stronghold2.json diff --git a/tests/resources/wordsofworshipsongs/Amazing Grace (6 Verses).json b/tests/resources/songs/wordsofworship/Amazing Grace (6 Verses).json similarity index 100% rename from tests/resources/wordsofworshipsongs/Amazing Grace (6 Verses).json rename to tests/resources/songs/wordsofworship/Amazing Grace (6 Verses).json diff --git a/tests/resources/wordsofworshipsongs/Amazing Grace (6 Verses).wow-song b/tests/resources/songs/wordsofworship/Amazing Grace (6 Verses).wow-song similarity index 100% rename from tests/resources/wordsofworshipsongs/Amazing Grace (6 Verses).wow-song rename to tests/resources/songs/wordsofworship/Amazing Grace (6 Verses).wow-song diff --git a/tests/resources/wordsofworshipsongs/Holy Holy Holy Lord God Almighty.json b/tests/resources/songs/wordsofworship/Holy Holy Holy Lord God Almighty.json similarity index 100% rename from tests/resources/wordsofworshipsongs/Holy Holy Holy Lord God Almighty.json rename to tests/resources/songs/wordsofworship/Holy Holy Holy Lord God Almighty.json diff --git a/tests/resources/wordsofworshipsongs/Holy Holy Holy Lord God Almighty.wow-song b/tests/resources/songs/wordsofworship/Holy Holy Holy Lord God Almighty.wow-song similarity index 100% rename from tests/resources/wordsofworshipsongs/Holy Holy Holy Lord God Almighty.wow-song rename to tests/resources/songs/wordsofworship/Holy Holy Holy Lord God Almighty.wow-song diff --git a/tests/resources/wordsofworshipsongs/When morning gilds the skies.json b/tests/resources/songs/wordsofworship/When morning gilds the skies.json similarity index 100% rename from tests/resources/wordsofworshipsongs/When morning gilds the skies.json rename to tests/resources/songs/wordsofworship/When morning gilds the skies.json diff --git a/tests/resources/wordsofworshipsongs/When morning gilds the skies.wsg b/tests/resources/songs/wordsofworship/When morning gilds the skies.wsg similarity index 100% rename from tests/resources/wordsofworshipsongs/When morning gilds the skies.wsg rename to tests/resources/songs/wordsofworship/When morning gilds the skies.wsg diff --git a/tests/resources/worshipassistantsongs/du_herr.csv b/tests/resources/songs/worshipassistant/du_herr.csv similarity index 100% rename from tests/resources/worshipassistantsongs/du_herr.csv rename to tests/resources/songs/worshipassistant/du_herr.csv diff --git a/tests/resources/worshipassistantsongs/du_herr.json b/tests/resources/songs/worshipassistant/du_herr.json similarity index 100% rename from tests/resources/worshipassistantsongs/du_herr.json rename to tests/resources/songs/worshipassistant/du_herr.json diff --git a/tests/resources/worshipassistantsongs/would_you_be_free.csv b/tests/resources/songs/worshipassistant/would_you_be_free.csv similarity index 100% rename from tests/resources/worshipassistantsongs/would_you_be_free.csv rename to tests/resources/songs/worshipassistant/would_you_be_free.csv diff --git a/tests/resources/worshipassistantsongs/would_you_be_free.json b/tests/resources/songs/worshipassistant/would_you_be_free.json similarity index 100% rename from tests/resources/worshipassistantsongs/would_you_be_free.json rename to tests/resources/songs/worshipassistant/would_you_be_free.json diff --git a/tests/resources/worshipassistantsongs/would_you_be_free2.csv b/tests/resources/songs/worshipassistant/would_you_be_free2.csv similarity index 100% rename from tests/resources/worshipassistantsongs/would_you_be_free2.csv rename to tests/resources/songs/worshipassistant/would_you_be_free2.csv diff --git a/tests/resources/zionworxsongs/zionworx.csv b/tests/resources/songs/zionworx/zionworx.csv similarity index 100% rename from tests/resources/zionworxsongs/zionworx.csv rename to tests/resources/songs/zionworx/zionworx.csv diff --git a/tests/resources/zionworxsongs/zionworx.json b/tests/resources/songs/zionworx/zionworx.json similarity index 100% rename from tests/resources/zionworxsongs/zionworx.json rename to tests/resources/songs/zionworx/zionworx.json diff --git a/tests/utils/__init__.py b/tests/utils/__init__.py index dd4d78354..7614193ce 100644 --- a/tests/utils/__init__.py +++ b/tests/utils/__init__.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -19,8 +19,8 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -import os import json +import os def assert_length(expected, iterable, msg=None): @@ -41,3 +41,12 @@ def convert_file_service_item(test_path, name, row=0): finally: open_file.close() return first_line + + +def load_external_result_data(file_path): + """ + A method to load and return an object containing the song data from an external file. + + :param openlp.core.common.path.Path file_path: The path of the file to load + """ + return json.loads(file_path.read_bytes().decode()) diff --git a/tests/utils/constants.py b/tests/utils/constants.py index 45b2ee8ba..e65797261 100644 --- a/tests/utils/constants.py +++ b/tests/utils/constants.py @@ -1,5 +1,28 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2018 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 # +############################################################################### import os +from openlp.core.common.path import Path + OPENLP_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) TEST_RESOURCES_PATH = os.path.join(OPENLP_PATH, 'tests', 'resources') +RESOURCE_PATH = Path(TEST_RESOURCES_PATH) diff --git a/tests/utils/osdinteraction.py b/tests/utils/osdinteraction.py index d6beb54bf..8dbf93901 100644 --- a/tests/utils/osdinteraction.py +++ b/tests/utils/osdinteraction.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -23,8 +23,8 @@ The :mod:`osdinteraction` provides miscellaneous functions for interacting with OSD files. """ -import os import json +import os from tests.utils.constants import TEST_RESOURCES_PATH diff --git a/tests/utils/test_bzr_tags.py b/tests/utils/test_bzr_tags.py index 52f49692c..b6dc8f4ee 100644 --- a/tests/utils/test_bzr_tags.py +++ b/tests/utils/test_bzr_tags.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -23,9 +23,8 @@ Package to test for proper bzr tags. """ import os -from unittest import TestCase - from subprocess import Popen, PIPE +from unittest import TestCase TAGS1 = {'1.9.0', '1.9.1', '1.9.2', '1.9.3', '1.9.4', '1.9.5', '1.9.6', '1.9.7', '1.9.8', '1.9.9', '1.9.10', '1.9.11', '1.9.12', '2.0', '2.1.0', '2.1.1', '2.1.2', '2.1.3', '2.1.4', '2.1.5', '2.1.6', '2.2', @@ -52,4 +51,4 @@ class TestBzrTags(TestCase): count1 += 1 # THEN the tags should match the accepted tags - self.assertEqual(count, count1, 'List of tags should match') + assert count == count1, 'List of tags should match' diff --git a/tests/utils/test_pylint.py b/tests/utils/test_pylint.py index 50ca64db6..8ef9425c9 100644 --- a/tests/utils/test_pylint.py +++ b/tests/utils/test_pylint.py @@ -4,7 +4,7 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2017 OpenLP Developers # +# Copyright (c) 2008-2018 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 # @@ -22,7 +22,6 @@ """ Package to test for proper bzr tags. """ -import os import platform import sys from unittest import TestCase, SkipTest @@ -80,7 +79,7 @@ class TestPylint(TestCase): print(stderr) # THEN: The output should be empty - self.assertTrue(filtered_stdout == '', 'PyLint should find no errors') + assert filtered_stdout == '', 'PyLint should find no errors' def _filter_tolerated_errors(self, pylint_output): """