openlp-core team mailing list archive
-
openlp-core team
-
Mailing list archive
-
Message #29100
[Merge] lp:~trb143/openlp/refactor26 into lp:openlp
Tim Bentley has proposed merging lp:~trb143/openlp/refactor26 into lp:openlp.
Requested reviews:
OpenLP Core (openlp-core)
For more details, see:
https://code.launchpad.net/~trb143/openlp/refactor26/+merge/291040
More moving code around.
Utils directory is removed but more tidy ups are needed.
Changed enough code to warrant a merge.
lp:~trb143/openlp/refactor26 (revision 2670)
[SUCCESS] https://ci.openlp.io/job/Branch-01-Pull/1406/
[SUCCESS] https://ci.openlp.io/job/Branch-02-Functional-Tests/1324/
[SUCCESS] https://ci.openlp.io/job/Branch-03-Interface-Tests/1263/
[SUCCESS] https://ci.openlp.io/job/Branch-04a-Windows_Functional_Tests/1084/
[SUCCESS] https://ci.openlp.io/job/Branch-04b-Windows_Interface_Tests/675/
[SUCCESS] https://ci.openlp.io/job/Branch-05a-Code_Analysis/742/
[SUCCESS] https://ci.openlp.io/job/Branch-05b-Test_Coverage/610/
--
Your team OpenLP Core is requested to review the proposed merge of lp:~trb143/openlp/refactor26 into lp:openlp.
=== modified file 'openlp/core/__init__.py'
--- openlp/core/__init__.py 2016-03-31 16:47:42 +0000
+++ openlp/core/__init__.py 2016-04-05 20:26:45 +0000
@@ -27,26 +27,26 @@
logging and a plugin framework are contained within the openlp.core module.
"""
+import argparse
+import logging
import os
+import shutil
import sys
-import logging
-import argparse
+import time
from traceback import format_exception
-import shutil
-import time
+
from PyQt5 import QtCore, QtGui, QtWidgets
from openlp.core.common import Registry, OpenLPMixin, AppLocation, LanguageManager, Settings, UiStrings, \
check_directory_exists, is_macosx, is_win, translate
+from openlp.core.common.versionchecker import VersionThread, get_application_version
from openlp.core.lib import ScreenList
from openlp.core.resources import qInitResources
+from openlp.core.ui import SplashScreen
+from openlp.core.ui.exceptionform import ExceptionForm
+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.firsttimelanguageform import FirstTimeLanguageForm
-from openlp.core.ui.firsttimeform import FirstTimeForm
-from openlp.core.ui.exceptionform import ExceptionForm
-from openlp.core.ui import SplashScreen
-from openlp.core.utils import VersionThread, get_application_version
-
__all__ = ['OpenLP', 'main']
=== modified file 'openlp/core/common/__init__.py'
--- openlp/core/common/__init__.py 2016-04-01 17:28:40 +0000
+++ openlp/core/common/__init__.py 2016-04-05 20:26:45 +0000
@@ -30,8 +30,9 @@
import sys
import traceback
from ipaddress import IPv4Address, IPv6Address, AddressValueError
+from shutil import which
-from PyQt5 import QtCore
+from PyQt5 import QtCore, QtGui
from PyQt5.QtCore import QCryptographicHash as QHash
log = logging.getLogger(__name__ + '.__init__')
@@ -39,6 +40,9 @@
FIRST_CAMEL_REGEX = re.compile('(.)([A-Z][a-z]+)')
SECOND_CAMEL_REGEX = re.compile('([a-z0-9])([A-Z])')
+CONTROL_CHARS = re.compile(r'[\x00-\x1F\x7F-\x9F]', re.UNICODE)
+INVALID_FILE_CHARS = re.compile(r'[\\/:\*\?"<>\|\+\[\]%]', re.UNICODE)
+IMAGES_FILTER = None
def trace_error_handler(logger):
@@ -257,3 +261,113 @@
target.addSeparator()
else:
target.addAction(action)
+
+
+def get_uno_command(connection_type='pipe'):
+ """
+ Returns the UNO command to launch an libreoffice.org instance.
+ """
+ for command in ['libreoffice', 'soffice']:
+ if which(command):
+ break
+ else:
+ raise FileNotFoundError('Command not found')
+
+ OPTIONS = '--nologo --norestore --minimized --nodefault --nofirststartwizard'
+ if connection_type == 'pipe':
+ CONNECTION = '"--accept=pipe,name=openlp_pipe;urp;"'
+ else:
+ CONNECTION = '"--accept=socket,host=localhost,port=2002;urp;"'
+ return '%s %s %s' % (command, OPTIONS, CONNECTION)
+
+
+def get_uno_instance(resolver, connection_type='pipe'):
+ """
+ Returns a running libreoffice.org instance.
+
+ :param resolver: The UNO resolver to use to find a running instance.
+ """
+ log.debug('get UNO Desktop Openoffice - resolve')
+ if connection_type == 'pipe':
+ return resolver.resolve('uno:pipe,name=openlp_pipe;urp;StarOffice.ComponentContext')
+ else:
+ return resolver.resolve('uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext')
+
+
+def get_filesystem_encoding():
+ """
+ Returns the name of the encoding used to convert Unicode filenames into system file names.
+ """
+ encoding = sys.getfilesystemencoding()
+ if encoding is None:
+ encoding = sys.getdefaultencoding()
+ return encoding
+
+
+def split_filename(path):
+ """
+ Return a list of the parts in a given path.
+ """
+ path = os.path.abspath(path)
+ if not os.path.isfile(path):
+ return path, ''
+ else:
+ return os.path.split(path)
+
+
+def delete_file(file_path_name):
+ """
+ Deletes a file from the system.
+
+ :param file_path_name: The file, including path, to delete.
+ """
+ if not file_path_name:
+ return False
+ try:
+ if os.path.exists(file_path_name):
+ os.remove(file_path_name)
+ return True
+ except (IOError, OSError):
+ log.exception("Unable to delete file %s" % file_path_name)
+ return False
+
+
+def get_images_filter():
+ """
+ Returns a filter string for a file dialog containing all the supported image formats.
+ """
+ global IMAGES_FILTER
+ if not IMAGES_FILTER:
+ log.debug('Generating images filter.')
+ formats = list(map(bytes.decode, list(map(bytes, QtGui.QImageReader.supportedImageFormats()))))
+ visible_formats = '(*.%s)' % '; *.'.join(formats)
+ actual_formats = '(*.%s)' % ' *.'.join(formats)
+ IMAGES_FILTER = '%s %s %s' % (translate('OpenLP', 'Image Files'), visible_formats, actual_formats)
+ return IMAGES_FILTER
+
+
+def is_not_image_file(file_name):
+ """
+ Validate that the file is not an image file.
+
+ :param file_name: File name to be checked.
+ """
+ if not file_name:
+ return True
+ else:
+ formats = [bytes(fmt).decode().lower() for fmt in QtGui.QImageReader.supportedImageFormats()]
+ file_part, file_extension = os.path.splitext(str(file_name))
+ if file_extension[1:].lower() in formats and os.path.exists(file_name):
+ return False
+ return True
+
+
+def clean_filename(filename):
+ """
+ Removes invalid characters from the given ``filename``.
+
+ :param filename: The "dirty" file name to clean.
+ """
+ if not isinstance(filename, str):
+ filename = str(filename, 'utf-8')
+ return INVALID_FILE_CHARS.sub('_', CONTROL_CHARS.sub('', filename))
=== modified file 'openlp/core/common/languagemanager.py'
--- openlp/core/common/languagemanager.py 2016-03-31 16:42:42 +0000
+++ openlp/core/common/languagemanager.py 2016-04-05 20:26:45 +0000
@@ -22,9 +22,9 @@
"""
The :mod:`languagemanager` module provides all the translation settings and language file loading for OpenLP.
"""
+import locale
import logging
import re
-import sys
from PyQt5 import QtCore, QtWidgets
@@ -33,6 +33,9 @@
log = logging.getLogger(__name__)
+ICU_COLLATOR = None
+DIGITS_OR_NONDIGITS = re.compile(r'\d+|\D+', re.UNICODE)
+
class LanguageManager(object):
"""
@@ -144,3 +147,60 @@
if not LanguageManager.__qm_list__:
LanguageManager.init_qm_list()
return LanguageManager.__qm_list__
+
+
+def format_time(text, local_time):
+ """
+ Workaround for Python built-in time formatting function time.strftime().
+
+ time.strftime() accepts only ascii characters. This function accepts
+ unicode string and passes individual % placeholders to time.strftime().
+ This ensures only ascii characters are passed to time.strftime().
+
+ :param text: The text to be processed.
+ :param local_time: The time to be used to add to the string. This is a time object
+ """
+
+ def match_formatting(match):
+ """
+ Format the match
+ """
+ return local_time.strftime(match.group())
+
+ return re.sub('\%[a-zA-Z]', match_formatting, text)
+
+
+def get_locale_key(string):
+ """
+ Creates a key for case insensitive, locale aware string sorting.
+
+ :param string: The corresponding string.
+ """
+ string = string.lower()
+ # ICU is the prefered way to handle locale sort key, we fallback to locale.strxfrm which will work in most cases.
+ global ICU_COLLATOR
+ try:
+ if ICU_COLLATOR is None:
+ import icu
+ language = LanguageManager.get_language()
+ icu_locale = icu.Locale(language)
+ ICU_COLLATOR = icu.Collator.createInstance(icu_locale)
+ return ICU_COLLATOR.getSortKey(string)
+ except:
+ return locale.strxfrm(string).encode()
+
+
+def get_natural_key(string):
+ """
+ Generate a key for locale aware natural string sorting.
+
+ :param string: string to be sorted by
+ Returns a list of string compare keys and integers.
+ """
+ key = DIGITS_OR_NONDIGITS.findall(string)
+ key = [int(part) if part.isdigit() else get_locale_key(part) for part in key]
+ # Python 3 does not support comparison of different types anymore. So make sure, that we do not compare str
+ # and int.
+ if string and string[0].isdigit():
+ return [b''] + key
+ return key
=== added file 'openlp/core/common/versionchecker.py'
--- openlp/core/common/versionchecker.py 1970-01-01 00:00:00 +0000
+++ openlp/core/common/versionchecker.py 2016-04-05 20:26:45 +0000
@@ -0,0 +1,170 @@
+import logging
+import os
+import platform
+import sys
+import time
+import urllib.error
+import urllib.parse
+import urllib.request
+from datetime import datetime
+from distutils.version import LooseVersion
+from subprocess import Popen, PIPE
+
+from openlp.core.common import AppLocation, Settings
+
+from PyQt5 import QtCore
+
+log = logging.getLogger(__name__)
+
+APPLICATION_VERSION = {}
+CONNECTION_TIMEOUT = 30
+CONNECTION_RETRIES = 2
+
+
+class VersionThread(QtCore.QThread):
+ """
+ A special Qt thread class to fetch the version of OpenLP from the website.
+ This is threaded so that it doesn't affect the loading time of OpenLP.
+ """
+ def __init__(self, main_window):
+ """
+ Constructor for the thread class.
+
+ :param main_window: The main window Object.
+ """
+ log.debug("VersionThread - Initialise")
+ super(VersionThread, self).__init__(None)
+ self.main_window = main_window
+
+ def run(self):
+ """
+ Run the thread.
+ """
+ self.sleep(1)
+ log.debug('Version thread - run')
+ app_version = get_application_version()
+ version = check_latest_version(app_version)
+ log.debug("Versions %s and %s " % (LooseVersion(str(version)), LooseVersion(str(app_version['full']))))
+ if LooseVersion(str(version)) > LooseVersion(str(app_version['full'])):
+ self.main_window.openlp_version_check.emit('%s' % version)
+
+
+def get_application_version():
+ """
+ Returns the application version of the running instance of OpenLP::
+
+ {'full': '1.9.4-bzr1249', 'version': '1.9.4', 'build': 'bzr1249'}
+ """
+ global APPLICATION_VERSION
+ if APPLICATION_VERSION:
+ return APPLICATION_VERSION
+ if '--dev-version' in sys.argv or '-d' in sys.argv:
+ # NOTE: The following code is a duplicate of the code in setup.py. Any fix applied here should also be applied
+ # there.
+
+ # Get the revision of this tree.
+ bzr = Popen(('bzr', 'revno'), stdout=PIPE)
+ tree_revision, error = bzr.communicate()
+ tree_revision = tree_revision.decode()
+ code = bzr.wait()
+ if code != 0:
+ raise Exception('Error running bzr log')
+
+ # Get all tags.
+ bzr = Popen(('bzr', 'tags'), stdout=PIPE)
+ output, error = bzr.communicate()
+ code = bzr.wait()
+ if code != 0:
+ raise Exception('Error running bzr tags')
+ tags = list(map(bytes.decode, output.splitlines()))
+ if not tags:
+ tag_version = '0.0.0'
+ tag_revision = '0'
+ else:
+ # Remove any tag that has "?" as revision number. A "?" as revision number indicates, that this tag is from
+ # another series.
+ tags = [tag for tag in tags if tag.split()[-1].strip() != '?']
+ # Get the last tag and split it in a revision and tag name.
+ tag_version, tag_revision = tags[-1].split()
+ # If they are equal, then this tree is tarball with the source for the release. We do not want the revision
+ # number in the full version.
+ if tree_revision == tag_revision:
+ full_version = tag_version.strip()
+ else:
+ full_version = '%s-bzr%s' % (tag_version.strip(), tree_revision.strip())
+ else:
+ # We're not running the development version, let's use the file.
+ file_path = AppLocation.get_directory(AppLocation.VersionDir)
+ file_path = os.path.join(file_path, '.version')
+ version_file = None
+ try:
+ version_file = open(file_path, 'r')
+ full_version = str(version_file.read()).rstrip()
+ except IOError:
+ log.exception('Error in version file.')
+ full_version = '0.0.0-bzr000'
+ finally:
+ if version_file:
+ version_file.close()
+ bits = full_version.split('-')
+ APPLICATION_VERSION = {
+ 'full': full_version,
+ 'version': bits[0],
+ 'build': bits[1] if len(bits) > 1 else None
+ }
+ if APPLICATION_VERSION['build']:
+ log.info('Openlp version %s build %s', APPLICATION_VERSION['version'], APPLICATION_VERSION['build'])
+ else:
+ log.info('Openlp version %s' % APPLICATION_VERSION['version'])
+ return APPLICATION_VERSION
+
+
+def check_latest_version(current_version):
+ """
+ Check the latest version of OpenLP against the version file on the OpenLP
+ site.
+
+ **Rules around versions and version files:**
+
+ * If a version number has a build (i.e. -bzr1234), then it is a nightly.
+ * If a version number's minor version is an odd number, it is a development release.
+ * If a version number's minor version is an even number, it is a stable release.
+
+ :param current_version: The current version of OpenLP.
+ """
+ version_string = current_version['full']
+ # set to prod in the distribution config file.
+ settings = Settings()
+ settings.beginGroup('core')
+ last_test = settings.value('last version test')
+ this_test = str(datetime.now().date())
+ settings.setValue('last version test', this_test)
+ settings.endGroup()
+ if last_test != this_test:
+ if current_version['build']:
+ req = urllib.request.Request('http://www.openlp.org/files/nightly_version.txt')
+ else:
+ version_parts = current_version['version'].split('.')
+ if int(version_parts[1]) % 2 != 0:
+ req = urllib.request.Request('http://www.openlp.org/files/dev_version.txt')
+ else:
+ req = urllib.request.Request('http://www.openlp.org/files/version.txt')
+ req.add_header('User-Agent', 'OpenLP/%s %s/%s; ' % (current_version['full'], platform.system(),
+ platform.release()))
+ remote_version = None
+ retries = 0
+ while True:
+ try:
+ remote_version = str(urllib.request.urlopen(req, None,
+ timeout=CONNECTION_TIMEOUT).read().decode()).strip()
+ except (urllib.error.URLError, ConnectionError):
+ if retries > CONNECTION_RETRIES:
+ log.exception('Failed to download the latest OpenLP version file')
+ else:
+ retries += 1
+ time.sleep(0.1)
+ continue
+ break
+ if remote_version:
+ version_string = remote_version
+ return version_string
=== modified file 'openlp/core/lib/db.py'
--- openlp/core/lib/db.py 2016-01-07 22:18:01 +0000
+++ openlp/core/lib/db.py 2016-04-05 20:26:45 +0000
@@ -34,9 +34,8 @@
from alembic.migration import MigrationContext
from alembic.operations import Operations
-from openlp.core.common import AppLocation, Settings, translate
+from openlp.core.common import AppLocation, Settings, translate, delete_file
from openlp.core.lib.ui import critical_error_message_box
-from openlp.core.utils import delete_file
log = logging.getLogger(__name__)
=== modified file 'openlp/core/lib/plugin.py'
--- openlp/core/lib/plugin.py 2016-01-11 21:57:20 +0000
+++ openlp/core/lib/plugin.py 2016-04-05 20:26:45 +0000
@@ -24,11 +24,10 @@
"""
import logging
-
from PyQt5 import QtCore
from openlp.core.common import Registry, RegistryProperties, Settings, UiStrings
-from openlp.core.utils import get_application_version
+from openlp.core.common.versionchecker import get_application_version
log = logging.getLogger(__name__)
=== added file 'openlp/core/lib/webpagereader.py'
--- openlp/core/lib/webpagereader.py 1970-01-01 00:00:00 +0000
+++ openlp/core/lib/webpagereader.py 2016-04-05 20:26:45 +0000
@@ -0,0 +1,183 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2016 OpenLP Developers #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it #
+# under the terms of the GNU General Public License as published by the Free #
+# Software Foundation; version 2 of the License. #
+# #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
+# more details. #
+# #
+# You should have received a copy of the GNU General Public License along #
+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
+###############################################################################
+"""
+The :mod:`openlp.core.utils` module provides the utility libraries for OpenLP.
+"""
+import logging
+import socket
+import sys
+import time
+import urllib.error
+import urllib.parse
+import urllib.request
+from http.client import HTTPException
+from random import randint
+
+from openlp.core.common import Registry
+
+log = logging.getLogger(__name__ + '.__init__')
+
+USER_AGENTS = {
+ 'win32': [
+ 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36',
+ 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36',
+ 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.71 Safari/537.36'
+ ],
+ 'darwin': [
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) '
+ 'Chrome/26.0.1410.43 Safari/537.31',
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/536.11 (KHTML, like Gecko) '
+ 'Chrome/20.0.1132.57 Safari/536.11',
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/536.11 (KHTML, like Gecko) '
+ 'Chrome/20.0.1132.47 Safari/536.11',
+ ],
+ 'linux2': [
+ 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.22 (KHTML, like Gecko) Ubuntu Chromium/25.0.1364.160 '
+ 'Chrome/25.0.1364.160 Safari/537.22',
+ 'Mozilla/5.0 (X11; CrOS armv7l 2913.260.0) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.99 '
+ 'Safari/537.11',
+ 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.27 (KHTML, like Gecko) Chrome/26.0.1389.0 Safari/537.27'
+ ],
+ 'default': [
+ 'Mozilla/5.0 (X11; NetBSD amd64; rv:18.0) Gecko/20130120 Firefox/18.0'
+ ]
+}
+CONNECTION_TIMEOUT = 30
+CONNECTION_RETRIES = 2
+
+
+class HTTPRedirectHandlerFixed(urllib.request.HTTPRedirectHandler):
+ """
+ Special HTTPRedirectHandler used to work around http://bugs.python.org/issue22248
+ (Redirecting to urls with special chars)
+ """
+ def redirect_request(self, req, fp, code, msg, headers, new_url):
+ #
+ """
+ Test if the new_url can be decoded to ascii
+
+ :param req:
+ :param fp:
+ :param code:
+ :param msg:
+ :param headers:
+ :param new_url:
+ :return:
+ """
+ try:
+ new_url.encode('latin1').decode('ascii')
+ fixed_url = new_url
+ except Exception:
+ # The url could not be decoded to ascii, so we do some url encoding
+ fixed_url = urllib.parse.quote(new_url.encode('latin1').decode('utf-8', 'replace'), safe='/:')
+ return super(HTTPRedirectHandlerFixed, self).redirect_request(req, fp, code, msg, headers, fixed_url)
+
+
+def _get_user_agent():
+ """
+ Return a user agent customised for the platform the user is on.
+ """
+ browser_list = USER_AGENTS.get(sys.platform, None)
+ if not browser_list:
+ browser_list = USER_AGENTS['default']
+ random_index = randint(0, len(browser_list) - 1)
+ return browser_list[random_index]
+
+
+def get_web_page(url, header=None, update_openlp=False):
+ """
+ Attempts to download the webpage at url and returns that page or None.
+
+ :param url: The URL to be downloaded.
+ :param header: An optional HTTP header to pass in the request to the web server.
+ :param update_openlp: Tells OpenLP to update itself if the page is successfully downloaded.
+ Defaults to False.
+ """
+ # TODO: Add proxy usage. Get proxy info from OpenLP settings, add to a
+ # proxy_handler, build into an opener and install the opener into urllib2.
+ # http://docs.python.org/library/urllib2.html
+ if not url:
+ return None
+ # This is needed to work around http://bugs.python.org/issue22248 and https://bugs.launchpad.net/openlp/+bug/1251437
+ opener = urllib.request.build_opener(HTTPRedirectHandlerFixed())
+ urllib.request.install_opener(opener)
+ req = urllib.request.Request(url)
+ if not header or header[0].lower() != 'user-agent':
+ user_agent = _get_user_agent()
+ req.add_header('User-Agent', user_agent)
+ if header:
+ req.add_header(header[0], header[1])
+ log.debug('Downloading URL = %s' % url)
+ retries = 0
+ while retries <= CONNECTION_RETRIES:
+ retries += 1
+ time.sleep(0.1)
+ try:
+ page = urllib.request.urlopen(req, timeout=CONNECTION_TIMEOUT)
+ log.debug('Downloaded page {}'.format(page.geturl()))
+ break
+ except urllib.error.URLError as err:
+ log.exception('URLError on {}'.format(url))
+ log.exception('URLError: {}'.format(err.reason))
+ page = None
+ if retries > CONNECTION_RETRIES:
+ raise
+ except socket.timeout:
+ log.exception('Socket timeout: {}'.format(url))
+ page = None
+ if retries > CONNECTION_RETRIES:
+ raise
+ except socket.gaierror:
+ log.exception('Socket gaierror: {}'.format(url))
+ page = None
+ if retries > CONNECTION_RETRIES:
+ raise
+ except ConnectionRefusedError:
+ log.exception('ConnectionRefused: {}'.format(url))
+ page = None
+ if retries > CONNECTION_RETRIES:
+ raise
+ break
+ except ConnectionError:
+ log.exception('Connection error: {}'.format(url))
+ page = None
+ if retries > CONNECTION_RETRIES:
+ raise
+ except HTTPException:
+ log.exception('HTTPException error: {}'.format(url))
+ page = None
+ if retries > CONNECTION_RETRIES:
+ raise
+ except:
+ # Don't know what's happening, so reraise the original
+ raise
+ if update_openlp:
+ Registry().get('application').process_events()
+ if not page:
+ log.exception('{} could not be downloaded'.format(url))
+ return None
+ log.debug(page)
+ return page
+
+
+__all__ = ['get_application_version', 'check_latest_version',
+ 'get_web_page']
=== modified file 'openlp/core/ui/aboutform.py'
--- openlp/core/ui/aboutform.py 2016-01-09 16:26:14 +0000
+++ openlp/core/ui/aboutform.py 2016-04-05 20:26:45 +0000
@@ -26,8 +26,8 @@
from PyQt5 import QtCore, QtWidgets
+from openlp.core.common.versionchecker import get_application_version
from openlp.core.lib import translate
-from openlp.core.utils import get_application_version
from .aboutdialog import UiAboutDialog
=== modified file 'openlp/core/ui/advancedtab.py'
--- openlp/core/ui/advancedtab.py 2016-03-20 15:00:15 +0000
+++ openlp/core/ui/advancedtab.py 2016-04-05 20:26:45 +0000
@@ -29,9 +29,9 @@
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import AppLocation, Settings, SlideLimits, UiStrings, translate
+from openlp.core.common import AppLocation, Settings, SlideLimits, UiStrings, translate, get_images_filter
from openlp.core.lib import ColorButton, SettingsTab, build_icon
-from openlp.core.utils import format_time, get_images_filter
+from openlp.core.common.languagemanager import format_time
log = logging.getLogger(__name__)
=== modified file 'openlp/core/ui/exceptionform.py'
--- openlp/core/ui/exceptionform.py 2016-03-12 21:22:21 +0000
+++ openlp/core/ui/exceptionform.py 2016-04-05 20:26:45 +0000
@@ -23,18 +23,17 @@
The actual exception dialog form.
"""
import logging
-import re
import os
import platform
+import re
import bs4
import sqlalchemy
+from PyQt5 import Qt, QtCore, QtGui, QtWebKit, QtWidgets
from lxml import etree
from openlp.core.common import RegistryProperties, is_linux
-from PyQt5 import Qt, QtCore, QtGui, QtWebKit, QtWidgets
-
try:
import migrate
MIGRATE_VERSION = getattr(migrate, '__version__', '< 0.7')
@@ -74,7 +73,7 @@
VLC_VERSION = '-'
from openlp.core.common import Settings, UiStrings, translate
-from openlp.core.utils import get_application_version
+from openlp.core.common.versionchecker import get_application_version
from .exceptiondialog import Ui_ExceptionDialog
=== modified file 'openlp/core/ui/firsttimeform.py'
--- openlp/core/ui/firsttimeform.py 2015-12-31 22:46:06 +0000
+++ openlp/core/ui/firsttimeform.py 2016-04-05 20:26:45 +0000
@@ -39,7 +39,7 @@
translate, clean_button_text, trace_error_handler
from openlp.core.lib import PluginStatus, build_icon
from openlp.core.lib.ui import critical_error_message_box
-from openlp.core.utils import get_web_page, CONNECTION_RETRIES, CONNECTION_TIMEOUT
+from openlp.core.lib.webpagereader import get_web_page, CONNECTION_RETRIES, CONNECTION_TIMEOUT
from .firsttimewizard import UiFirstTimeWizard, FirstTimePage
log = logging.getLogger(__name__)
=== modified file 'openlp/core/ui/mainwindow.py'
--- openlp/core/ui/mainwindow.py 2016-04-01 17:28:40 +0000
+++ openlp/core/ui/mainwindow.py 2016-04-05 20:26:45 +0000
@@ -37,6 +37,7 @@
from openlp.core.common import Registry, RegistryProperties, AppLocation, LanguageManager, Settings, \
check_directory_exists, translate, is_win, is_macosx, add_actions
from openlp.core.common.actions import ActionList, CategoryOrder
+from openlp.core.common.versionchecker import get_application_version
from openlp.core.lib import Renderer, OpenLPDockWidget, PluginManager, ImageManager, PluginStatus, ScreenList, \
build_icon
from openlp.core.lib.ui import UiStrings, create_action
@@ -46,7 +47,6 @@
from openlp.core.ui.media import MediaController
from openlp.core.ui.printserviceform import PrintServiceForm
from openlp.core.ui.projector.manager import ProjectorManager
-from openlp.core.utils import get_application_version
log = logging.getLogger(__name__)
=== modified file 'openlp/core/ui/servicemanager.py'
--- openlp/core/ui/servicemanager.py 2016-03-31 16:34:22 +0000
+++ openlp/core/ui/servicemanager.py 2016-04-05 20:26:45 +0000
@@ -33,12 +33,12 @@
from PyQt5 import QtCore, QtGui, QtWidgets
from openlp.core.common import Registry, RegistryProperties, AppLocation, Settings, ThemeLevel, OpenLPMixin, \
- RegistryMixin, check_directory_exists, UiStrings, translate
+ RegistryMixin, check_directory_exists, UiStrings, translate, split_filename, delete_file
from openlp.core.common.actions import ActionList, CategoryOrder
from openlp.core.lib import OpenLPToolbar, ServiceItem, ItemCapabilities, PluginStatus, build_icon
from openlp.core.lib.ui import critical_error_message_box, create_widget_action, find_and_set_in_combo_box
from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm
-from openlp.core.utils import delete_file, split_filename, format_time
+from openlp.core.common.languagemanager import format_time
class ServiceManagerList(QtWidgets.QTreeWidget):
=== modified file 'openlp/core/ui/themeform.py'
--- openlp/core/ui/themeform.py 2016-01-08 21:44:22 +0000
+++ openlp/core/ui/themeform.py 2016-04-05 20:26:45 +0000
@@ -27,11 +27,10 @@
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import Registry, RegistryProperties, UiStrings, translate
+from openlp.core.common import Registry, RegistryProperties, UiStrings, translate, get_images_filter, is_not_image_file
from openlp.core.lib.theme import BackgroundType, BackgroundGradientType
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui import ThemeLayoutForm
-from openlp.core.utils import get_images_filter, is_not_image_file
from .themewizard import Ui_ThemeWizard
log = logging.getLogger(__name__)
=== modified file 'openlp/core/ui/thememanager.py'
--- openlp/core/ui/thememanager.py 2015-12-31 22:46:06 +0000
+++ openlp/core/ui/thememanager.py 2016-04-05 20:26:45 +0000
@@ -30,13 +30,13 @@
from PyQt5 import QtCore, QtGui, QtWidgets
from openlp.core.common import Registry, RegistryProperties, AppLocation, Settings, OpenLPMixin, RegistryMixin, \
- check_directory_exists, UiStrings, translate, is_win
+ check_directory_exists, UiStrings, translate, is_win, get_filesystem_encoding, delete_file
from openlp.core.lib import FileDialog, ImageSource, OpenLPToolbar, ValidationError, get_text_file_string, build_icon, \
check_item_selected, create_thumb, validate_thumb
from openlp.core.lib.theme import ThemeXML, BackgroundType
from openlp.core.lib.ui import critical_error_message_box, create_widget_action
from openlp.core.ui import FileRenameForm, ThemeForm
-from openlp.core.utils import delete_file, get_locale_key, get_filesystem_encoding
+from openlp.core.common.languagemanager import get_locale_key
class Ui_ThemeManager(object):
=== removed directory 'openlp/core/utils'
=== removed file 'openlp/core/utils/__init__.py'
--- openlp/core/utils/__init__.py 2016-04-03 15:57:52 +0000
+++ openlp/core/utils/__init__.py 1970-01-01 00:00:00 +0000
@@ -1,524 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2016 OpenLP Developers #
-# --------------------------------------------------------------------------- #
-# This program is free software; you can redistribute it and/or modify it #
-# under the terms of the GNU General Public License as published by the Free #
-# Software Foundation; version 2 of the License. #
-# #
-# This program is distributed in the hope that it will be useful, but WITHOUT #
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
-# more details. #
-# #
-# You should have received a copy of the GNU General Public License along #
-# with this program; if not, write to the Free Software Foundation, Inc., 59 #
-# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
-###############################################################################
-"""
-The :mod:`openlp.core.utils` module provides the utility libraries for OpenLP.
-"""
-import locale
-import logging
-import os
-import platform
-import re
-import socket
-import sys
-import time
-import urllib.error
-import urllib.parse
-import urllib.request
-from datetime import datetime
-from distutils.version import LooseVersion
-from http.client import HTTPException
-from random import randint
-from shutil import which
-from subprocess import Popen, PIPE
-
-from PyQt5 import QtGui, QtCore
-
-from openlp.core.common import Registry, AppLocation, Settings, is_win, is_macosx
-
-if not is_win() and not is_macosx():
- try:
- from xdg import BaseDirectory
- XDG_BASE_AVAILABLE = True
- except ImportError:
- BaseDirectory = None
- XDG_BASE_AVAILABLE = False
-
-from openlp.core.common import translate
-
-log = logging.getLogger(__name__ + '.__init__')
-
-APPLICATION_VERSION = {}
-IMAGES_FILTER = None
-ICU_COLLATOR = None
-CONTROL_CHARS = re.compile(r'[\x00-\x1F\x7F-\x9F]', re.UNICODE)
-INVALID_FILE_CHARS = re.compile(r'[\\/:\*\?"<>\|\+\[\]%]', re.UNICODE)
-DIGITS_OR_NONDIGITS = re.compile(r'\d+|\D+', re.UNICODE)
-USER_AGENTS = {
- 'win32': [
- 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36',
- 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36',
- 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.71 Safari/537.36'
- ],
- 'darwin': [
- 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) '
- 'Chrome/26.0.1410.43 Safari/537.31',
- 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/536.11 (KHTML, like Gecko) '
- 'Chrome/20.0.1132.57 Safari/536.11',
- 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/536.11 (KHTML, like Gecko) '
- 'Chrome/20.0.1132.47 Safari/536.11',
- ],
- 'linux2': [
- 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.22 (KHTML, like Gecko) Ubuntu Chromium/25.0.1364.160 '
- 'Chrome/25.0.1364.160 Safari/537.22',
- 'Mozilla/5.0 (X11; CrOS armv7l 2913.260.0) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.99 '
- 'Safari/537.11',
- 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.27 (KHTML, like Gecko) Chrome/26.0.1389.0 Safari/537.27'
- ],
- 'default': [
- 'Mozilla/5.0 (X11; NetBSD amd64; rv:18.0) Gecko/20130120 Firefox/18.0'
- ]
-}
-CONNECTION_TIMEOUT = 30
-CONNECTION_RETRIES = 2
-
-
-class VersionThread(QtCore.QThread):
- """
- A special Qt thread class to fetch the version of OpenLP from the website.
- This is threaded so that it doesn't affect the loading time of OpenLP.
- """
- def __init__(self, main_window):
- """
- Constructor for the thread class.
-
- :param main_window: The main window Object.
- """
- log.debug("VersionThread - Initialise")
- super(VersionThread, self).__init__(None)
- self.main_window = main_window
-
- def run(self):
- """
- Run the thread.
- """
- self.sleep(1)
- log.debug('Version thread - run')
- app_version = get_application_version()
- version = check_latest_version(app_version)
- log.debug("Versions %s and %s " % (LooseVersion(str(version)), LooseVersion(str(app_version['full']))))
- if LooseVersion(str(version)) > LooseVersion(str(app_version['full'])):
- self.main_window.openlp_version_check.emit('%s' % version)
-
-
-class HTTPRedirectHandlerFixed(urllib.request.HTTPRedirectHandler):
- """
- Special HTTPRedirectHandler used to work around http://bugs.python.org/issue22248
- (Redirecting to urls with special chars)
- """
- def redirect_request(self, req, fp, code, msg, headers, new_url):
- #
- """
- Test if the new_url can be decoded to ascii
-
- :param req:
- :param fp:
- :param code:
- :param msg:
- :param headers:
- :param new_url:
- :return:
- """
- try:
- new_url.encode('latin1').decode('ascii')
- fixed_url = new_url
- except Exception:
- # The url could not be decoded to ascii, so we do some url encoding
- fixed_url = urllib.parse.quote(new_url.encode('latin1').decode('utf-8', 'replace'), safe='/:')
- return super(HTTPRedirectHandlerFixed, self).redirect_request(req, fp, code, msg, headers, fixed_url)
-
-
-def get_application_version():
- """
- Returns the application version of the running instance of OpenLP::
-
- {'full': '1.9.4-bzr1249', 'version': '1.9.4', 'build': 'bzr1249'}
- """
- global APPLICATION_VERSION
- if APPLICATION_VERSION:
- return APPLICATION_VERSION
- if '--dev-version' in sys.argv or '-d' in sys.argv:
- # NOTE: The following code is a duplicate of the code in setup.py. Any fix applied here should also be applied
- # there.
-
- # Get the revision of this tree.
- bzr = Popen(('bzr', 'revno'), stdout=PIPE)
- tree_revision, error = bzr.communicate()
- tree_revision = tree_revision.decode()
- code = bzr.wait()
- if code != 0:
- raise Exception('Error running bzr log')
-
- # Get all tags.
- bzr = Popen(('bzr', 'tags'), stdout=PIPE)
- output, error = bzr.communicate()
- code = bzr.wait()
- if code != 0:
- raise Exception('Error running bzr tags')
- tags = list(map(bytes.decode, output.splitlines()))
- if not tags:
- tag_version = '0.0.0'
- tag_revision = '0'
- else:
- # Remove any tag that has "?" as revision number. A "?" as revision number indicates, that this tag is from
- # another series.
- tags = [tag for tag in tags if tag.split()[-1].strip() != '?']
- # Get the last tag and split it in a revision and tag name.
- tag_version, tag_revision = tags[-1].split()
- # If they are equal, then this tree is tarball with the source for the release. We do not want the revision
- # number in the full version.
- if tree_revision == tag_revision:
- full_version = tag_version.strip()
- else:
- full_version = '%s-bzr%s' % (tag_version.strip(), tree_revision.strip())
- else:
- # We're not running the development version, let's use the file.
- file_path = AppLocation.get_directory(AppLocation.VersionDir)
- file_path = os.path.join(file_path, '.version')
- version_file = None
- try:
- version_file = open(file_path, 'r')
- full_version = str(version_file.read()).rstrip()
- except IOError:
- log.exception('Error in version file.')
- full_version = '0.0.0-bzr000'
- finally:
- if version_file:
- version_file.close()
- bits = full_version.split('-')
- APPLICATION_VERSION = {
- 'full': full_version,
- 'version': bits[0],
- 'build': bits[1] if len(bits) > 1 else None
- }
- if APPLICATION_VERSION['build']:
- log.info('Openlp version %s build %s', APPLICATION_VERSION['version'], APPLICATION_VERSION['build'])
- else:
- log.info('Openlp version %s' % APPLICATION_VERSION['version'])
- return APPLICATION_VERSION
-
-
-def check_latest_version(current_version):
- """
- Check the latest version of OpenLP against the version file on the OpenLP
- site.
-
- **Rules around versions and version files:**
-
- * If a version number has a build (i.e. -bzr1234), then it is a nightly.
- * If a version number's minor version is an odd number, it is a development release.
- * If a version number's minor version is an even number, it is a stable release.
-
- :param current_version: The current version of OpenLP.
- """
- version_string = current_version['full']
- # set to prod in the distribution config file.
- settings = Settings()
- settings.beginGroup('core')
- last_test = settings.value('last version test')
- this_test = str(datetime.now().date())
- settings.setValue('last version test', this_test)
- settings.endGroup()
- if last_test != this_test:
- if current_version['build']:
- req = urllib.request.Request('http://www.openlp.org/files/nightly_version.txt')
- else:
- version_parts = current_version['version'].split('.')
- if int(version_parts[1]) % 2 != 0:
- req = urllib.request.Request('http://www.openlp.org/files/dev_version.txt')
- else:
- req = urllib.request.Request('http://www.openlp.org/files/version.txt')
- req.add_header('User-Agent', 'OpenLP/%s %s/%s; ' % (current_version['full'], platform.system(),
- platform.release()))
- remote_version = None
- retries = 0
- while True:
- try:
- remote_version = str(urllib.request.urlopen(req, None,
- timeout=CONNECTION_TIMEOUT).read().decode()).strip()
- except (urllib.error.URLError, ConnectionError):
- if retries > CONNECTION_RETRIES:
- log.exception('Failed to download the latest OpenLP version file')
- else:
- retries += 1
- time.sleep(0.1)
- continue
- break
- if remote_version:
- version_string = remote_version
- return version_string
-
-
-def get_filesystem_encoding():
- """
- Returns the name of the encoding used to convert Unicode filenames into system file names.
- """
- encoding = sys.getfilesystemencoding()
- if encoding is None:
- encoding = sys.getdefaultencoding()
- return encoding
-
-
-def get_images_filter():
- """
- Returns a filter string for a file dialog containing all the supported image formats.
- """
- global IMAGES_FILTER
- if not IMAGES_FILTER:
- log.debug('Generating images filter.')
- formats = list(map(bytes.decode, list(map(bytes, QtGui.QImageReader.supportedImageFormats()))))
- visible_formats = '(*.%s)' % '; *.'.join(formats)
- actual_formats = '(*.%s)' % ' *.'.join(formats)
- IMAGES_FILTER = '%s %s %s' % (translate('OpenLP', 'Image Files'), visible_formats, actual_formats)
- return IMAGES_FILTER
-
-
-def is_not_image_file(file_name):
- """
- Validate that the file is not an image file.
-
- :param file_name: File name to be checked.
- """
- if not file_name:
- return True
- else:
- formats = [bytes(fmt).decode().lower() for fmt in QtGui.QImageReader.supportedImageFormats()]
- file_part, file_extension = os.path.splitext(str(file_name))
- if file_extension[1:].lower() in formats and os.path.exists(file_name):
- return False
- return True
-
-
-def split_filename(path):
- """
- Return a list of the parts in a given path.
- """
- path = os.path.abspath(path)
- if not os.path.isfile(path):
- return path, ''
- else:
- return os.path.split(path)
-
-
-def clean_filename(filename):
- """
- Removes invalid characters from the given ``filename``.
-
- :param filename: The "dirty" file name to clean.
- """
- if not isinstance(filename, str):
- filename = str(filename, 'utf-8')
- return INVALID_FILE_CHARS.sub('_', CONTROL_CHARS.sub('', filename))
-
-
-def delete_file(file_path_name):
- """
- Deletes a file from the system.
-
- :param file_path_name: The file, including path, to delete.
- """
- if not file_path_name:
- return False
- try:
- if os.path.exists(file_path_name):
- os.remove(file_path_name)
- return True
- except (IOError, OSError):
- log.exception("Unable to delete file %s" % file_path_name)
- return False
-
-
-def _get_user_agent():
- """
- Return a user agent customised for the platform the user is on.
- """
- browser_list = USER_AGENTS.get(sys.platform, None)
- if not browser_list:
- browser_list = USER_AGENTS['default']
- random_index = randint(0, len(browser_list) - 1)
- return browser_list[random_index]
-
-
-def get_web_page(url, header=None, update_openlp=False):
- """
- Attempts to download the webpage at url and returns that page or None.
-
- :param url: The URL to be downloaded.
- :param header: An optional HTTP header to pass in the request to the web server.
- :param update_openlp: Tells OpenLP to update itself if the page is successfully downloaded.
- Defaults to False.
- """
- # TODO: Add proxy usage. Get proxy info from OpenLP settings, add to a
- # proxy_handler, build into an opener and install the opener into urllib2.
- # http://docs.python.org/library/urllib2.html
- if not url:
- return None
- # This is needed to work around http://bugs.python.org/issue22248 and https://bugs.launchpad.net/openlp/+bug/1251437
- opener = urllib.request.build_opener(HTTPRedirectHandlerFixed())
- urllib.request.install_opener(opener)
- req = urllib.request.Request(url)
- if not header or header[0].lower() != 'user-agent':
- user_agent = _get_user_agent()
- req.add_header('User-Agent', user_agent)
- if header:
- req.add_header(header[0], header[1])
- log.debug('Downloading URL = %s' % url)
- retries = 0
- while retries <= CONNECTION_RETRIES:
- retries += 1
- time.sleep(0.1)
- try:
- page = urllib.request.urlopen(req, timeout=CONNECTION_TIMEOUT)
- log.debug('Downloaded page {}'.format(page.geturl()))
- break
- except urllib.error.URLError as err:
- log.exception('URLError on {}'.format(url))
- log.exception('URLError: {}'.format(err.reason))
- page = None
- if retries > CONNECTION_RETRIES:
- raise
- except socket.timeout:
- log.exception('Socket timeout: {}'.format(url))
- page = None
- if retries > CONNECTION_RETRIES:
- raise
- except socket.gaierror:
- log.exception('Socket gaierror: {}'.format(url))
- page = None
- if retries > CONNECTION_RETRIES:
- raise
- except ConnectionRefusedError:
- log.exception('ConnectionRefused: {}'.format(url))
- page = None
- if retries > CONNECTION_RETRIES:
- raise
- break
- except ConnectionError:
- log.exception('Connection error: {}'.format(url))
- page = None
- if retries > CONNECTION_RETRIES:
- raise
- except HTTPException:
- log.exception('HTTPException error: {}'.format(url))
- page = None
- if retries > CONNECTION_RETRIES:
- raise
- except:
- # Don't know what's happening, so reraise the original
- raise
- if update_openlp:
- Registry().get('application').process_events()
- if not page:
- log.exception('{} could not be downloaded'.format(url))
- return None
- log.debug(page)
- return page
-
-
-def get_uno_command(connection_type='pipe'):
- """
- Returns the UNO command to launch an libreoffice.org instance.
- """
- for command in ['libreoffice', 'soffice']:
- if which(command):
- break
- else:
- raise FileNotFoundError('Command not found')
-
- OPTIONS = '--nologo --norestore --minimized --nodefault --nofirststartwizard'
- if connection_type == 'pipe':
- CONNECTION = '"--accept=pipe,name=openlp_pipe;urp;"'
- else:
- CONNECTION = '"--accept=socket,host=localhost,port=2002;urp;"'
- return '%s %s %s' % (command, OPTIONS, CONNECTION)
-
-
-def get_uno_instance(resolver, connection_type='pipe'):
- """
- Returns a running libreoffice.org instance.
-
- :param resolver: The UNO resolver to use to find a running instance.
- """
- log.debug('get UNO Desktop Openoffice - resolve')
- if connection_type == 'pipe':
- return resolver.resolve('uno:pipe,name=openlp_pipe;urp;StarOffice.ComponentContext')
- else:
- return resolver.resolve('uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext')
-
-
-def format_time(text, local_time):
- """
- Workaround for Python built-in time formatting function time.strftime().
-
- time.strftime() accepts only ascii characters. This function accepts
- unicode string and passes individual % placeholders to time.strftime().
- This ensures only ascii characters are passed to time.strftime().
-
- :param text: The text to be processed.
- :param local_time: The time to be used to add to the string. This is a time object
- """
- def match_formatting(match):
- """
- Format the match
- """
- return local_time.strftime(match.group())
- return re.sub('\%[a-zA-Z]', match_formatting, text)
-
-
-def get_locale_key(string):
- """
- Creates a key for case insensitive, locale aware string sorting.
-
- :param string: The corresponding string.
- """
- string = string.lower()
- # ICU is the prefered way to handle locale sort key, we fallback to locale.strxfrm which will work in most cases.
- global ICU_COLLATOR
- try:
- if ICU_COLLATOR is None:
- import icu
- from openlp.core.common.languagemanager import LanguageManager
- language = LanguageManager.get_language()
- icu_locale = icu.Locale(language)
- ICU_COLLATOR = icu.Collator.createInstance(icu_locale)
- return ICU_COLLATOR.getSortKey(string)
- except:
- return locale.strxfrm(string).encode()
-
-
-def get_natural_key(string):
- """
- Generate a key for locale aware natural string sorting.
-
- :param string: string to be sorted by
- Returns a list of string compare keys and integers.
- """
- key = DIGITS_OR_NONDIGITS.findall(string)
- key = [int(part) if part.isdigit() else get_locale_key(part) for part in key]
- # Python 3 does not support comparison of different types anymore. So make sure, that we do not compare str
- # and int.
- if string and string[0].isdigit():
- return [b''] + key
- return key
-
-__all__ = ['get_application_version', 'check_latest_version',
- 'get_filesystem_encoding', 'get_web_page', 'get_uno_command', 'get_uno_instance',
- 'delete_file', 'clean_filename', 'format_time', 'get_locale_key', 'get_natural_key']
=== modified file 'openlp/plugins/bibles/forms/bibleimportform.py'
--- openlp/plugins/bibles/forms/bibleimportform.py 2016-01-09 16:26:14 +0000
+++ openlp/plugins/bibles/forms/bibleimportform.py 2016-04-05 20:26:45 +0000
@@ -28,11 +28,11 @@
from PyQt5 import QtWidgets
-from openlp.core.common import AppLocation, Settings, UiStrings, translate
+from openlp.core.common import AppLocation, Settings, UiStrings, translate, clean_filename
from openlp.core.lib.db import delete_database
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
-from openlp.core.utils import get_locale_key
+from openlp.core.common.languagemanager import get_locale_key
from openlp.plugins.bibles.lib.manager import BibleFormat
from openlp.plugins.bibles.lib.db import BiblesResourcesDB, clean_filename
from openlp.plugins.bibles.lib.http import CWExtract, BGExtract, BSExtract
=== modified file 'openlp/plugins/bibles/forms/bibleupgradeform.py'
--- openlp/plugins/bibles/forms/bibleupgradeform.py 2015-12-31 22:46:06 +0000
+++ openlp/plugins/bibles/forms/bibleupgradeform.py 2016-04-05 20:26:45 +0000
@@ -29,10 +29,10 @@
from PyQt5 import QtCore, QtWidgets
-from openlp.core.common import Registry, AppLocation, UiStrings, Settings, check_directory_exists, translate
+from openlp.core.common import Registry, AppLocation, UiStrings, Settings, check_directory_exists, translate, \
+ delete_file
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
-from openlp.core.utils import delete_file
from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta, OldBibleDB, BiblesResourcesDB
from openlp.plugins.bibles.lib.http import BSExtract, BGExtract, CWExtract
=== modified file 'openlp/plugins/bibles/lib/db.py'
--- openlp/plugins/bibles/lib/db.py 2015-12-31 22:46:06 +0000
+++ openlp/plugins/bibles/lib/db.py 2016-04-05 20:26:45 +0000
@@ -33,10 +33,9 @@
from sqlalchemy.orm import class_mapper, mapper, relation
from sqlalchemy.orm.exc import UnmappedClassError
-from openlp.core.common import Registry, RegistryProperties, AppLocation, translate
+from openlp.core.common import Registry, RegistryProperties, AppLocation, translate, clean_filename
from openlp.core.lib.db import BaseModel, init_db, Manager
from openlp.core.lib.ui import critical_error_message_box
-from openlp.core.utils import clean_filename
from openlp.plugins.bibles.lib import upgrade
log = logging.getLogger(__name__)
=== modified file 'openlp/plugins/bibles/lib/http.py'
--- openlp/plugins/bibles/lib/http.py 2016-02-04 20:17:40 +0000
+++ openlp/plugins/bibles/lib/http.py 2016-04-05 20:26:45 +0000
@@ -32,7 +32,7 @@
from openlp.core.common import Registry, RegistryProperties, translate
from openlp.core.lib.ui import critical_error_message_box
-from openlp.core.utils import get_web_page
+from openlp.core.lib.webpagereader import get_web_page
from openlp.plugins.bibles.lib import SearchResults
from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB, Book
=== modified file 'openlp/plugins/bibles/lib/manager.py'
--- openlp/plugins/bibles/lib/manager.py 2015-12-31 22:46:06 +0000
+++ openlp/plugins/bibles/lib/manager.py 2016-04-05 20:26:45 +0000
@@ -23,8 +23,7 @@
import logging
import os
-from openlp.core.common import RegistryProperties, AppLocation, Settings, translate
-from openlp.core.utils import delete_file
+from openlp.core.common import RegistryProperties, AppLocation, Settings, translate, delete_file
from openlp.plugins.bibles.lib import parse_reference, get_reference_separator, LanguageSelection
from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta
from .csvbible import CSVBible
=== modified file 'openlp/plugins/bibles/lib/mediaitem.py'
--- openlp/plugins/bibles/lib/mediaitem.py 2016-01-08 17:44:47 +0000
+++ openlp/plugins/bibles/lib/mediaitem.py 2016-04-05 20:26:45 +0000
@@ -29,7 +29,7 @@
from openlp.core.lib.searchedit import SearchEdit
from openlp.core.lib.ui import set_case_insensitive_completer, create_horizontal_adjusting_combo_box, \
critical_error_message_box, find_and_set_in_combo_box, build_icon
-from openlp.core.utils import get_locale_key
+from openlp.core.common.languagemanager import get_locale_key
from openlp.plugins.bibles.forms.bibleimportform import BibleImportForm
from openlp.plugins.bibles.forms.editbibleform import EditBibleForm
from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle, VerseReferenceList, get_reference_separator, \
=== modified file 'openlp/plugins/custom/lib/db.py'
--- openlp/plugins/custom/lib/db.py 2015-12-31 22:46:06 +0000
+++ openlp/plugins/custom/lib/db.py 2016-04-05 20:26:45 +0000
@@ -28,7 +28,7 @@
from sqlalchemy.orm import mapper
from openlp.core.lib.db import BaseModel, init_db
-from openlp.core.utils import get_locale_key
+from openlp.core.common.languagemanager import get_locale_key
class CustomSlide(BaseModel):
=== modified file 'openlp/plugins/images/lib/mediaitem.py'
--- openlp/plugins/images/lib/mediaitem.py 2016-01-05 18:20:47 +0000
+++ openlp/plugins/images/lib/mediaitem.py 2016-04-05 20:26:45 +0000
@@ -25,11 +25,12 @@
from PyQt5 import QtCore, QtGui, QtWidgets
-from openlp.core.common import Registry, AppLocation, Settings, UiStrings, check_directory_exists, translate
+from openlp.core.common import Registry, AppLocation, Settings, UiStrings, check_directory_exists, translate, \
+ delete_file, get_images_filter
from openlp.core.lib import ItemCapabilities, MediaManagerItem, ServiceItemContext, StringContent, TreeWidgetWithDnD,\
build_icon, check_item_selected, create_thumb, validate_thumb
from openlp.core.lib.ui import create_widget_action, critical_error_message_box
-from openlp.core.utils import delete_file, get_locale_key, get_images_filter
+from openlp.core.common.languagemanager import get_locale_key
from openlp.plugins.images.forms import AddGroupForm, ChooseGroupForm
from openlp.plugins.images.lib.db import ImageFilenames, ImageGroups
=== modified file 'openlp/plugins/media/lib/mediaitem.py'
--- openlp/plugins/media/lib/mediaitem.py 2015-12-31 22:46:06 +0000
+++ openlp/plugins/media/lib/mediaitem.py 2016-04-05 20:26:45 +0000
@@ -32,7 +32,7 @@
from openlp.core.lib.ui import critical_error_message_box, create_horizontal_adjusting_combo_box
from openlp.core.ui import DisplayController, Display, DisplayControllerType
from openlp.core.ui.media import get_media_players, set_media_players, parse_optical_path, format_milliseconds
-from openlp.core.utils import get_locale_key
+from openlp.core.common.languagemanager import get_locale_key
from openlp.core.ui.media.vlcplayer import get_vlc
if get_vlc() is not None:
=== modified file 'openlp/plugins/presentations/lib/impresscontroller.py'
--- openlp/plugins/presentations/lib/impresscontroller.py 2015-12-31 22:46:06 +0000
+++ openlp/plugins/presentations/lib/impresscontroller.py 2016-04-05 20:26:45 +0000
@@ -35,7 +35,7 @@
import os
import time
-from openlp.core.common import is_win, Registry
+from openlp.core.common import is_win, Registry, get_uno_command, get_uno_instance, delete_file
if is_win():
from win32com.client import Dispatch
@@ -57,7 +57,7 @@
from PyQt5 import QtCore
from openlp.core.lib import ScreenList
-from openlp.core.utils import delete_file, get_uno_command, get_uno_instance
+from openlp.core.common import get_uno_command, get_uno_instance
from .presentationcontroller import PresentationController, PresentationDocument, TextType
=== modified file 'openlp/plugins/presentations/lib/mediaitem.py'
--- openlp/plugins/presentations/lib/mediaitem.py 2015-12-31 22:46:06 +0000
+++ openlp/plugins/presentations/lib/mediaitem.py 2016-04-05 20:26:45 +0000
@@ -29,7 +29,7 @@
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.core.utils import get_locale_key
+from openlp.core.common.languagemanager import get_locale_key
from openlp.plugins.presentations.lib import MessageListener
from openlp.plugins.presentations.lib.pdfcontroller import PDF_CONTROLLER_FILETYPES
=== modified file 'openlp/plugins/presentations/lib/pdfcontroller.py'
--- openlp/plugins/presentations/lib/pdfcontroller.py 2015-12-31 22:46:06 +0000
+++ openlp/plugins/presentations/lib/pdfcontroller.py 2016-04-05 20:26:45 +0000
@@ -27,7 +27,7 @@
from shutil import which
from subprocess import check_output, CalledProcessError, STDOUT
-from openlp.core.utils import AppLocation
+from openlp.core.common import AppLocation
from openlp.core.common import Settings, is_win, trace_error_handler
from openlp.core.lib import ScreenList
from .presentationcontroller import PresentationController, PresentationDocument
=== modified file 'openlp/plugins/presentations/lib/pptviewcontroller.py'
--- openlp/plugins/presentations/lib/pptviewcontroller.py 2015-12-31 22:46:06 +0000
+++ openlp/plugins/presentations/lib/pptviewcontroller.py 2016-04-05 20:26:45 +0000
@@ -20,7 +20,6 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
-import logging
import os
import logging
import zipfile
@@ -34,7 +33,7 @@
from ctypes import cdll
from ctypes.wintypes import RECT
-from openlp.core.utils import AppLocation
+from openlp.core.common import AppLocation
from openlp.core.lib import ScreenList
from .presentationcontroller import PresentationController, PresentationDocument
=== modified file 'openlp/plugins/songs/lib/__init__.py'
--- openlp/plugins/songs/lib/__init__.py 2015-12-31 22:46:06 +0000
+++ openlp/plugins/songs/lib/__init__.py 2016-04-05 20:26:45 +0000
@@ -29,9 +29,8 @@
from PyQt5 import QtWidgets
-from openlp.core.common import AppLocation
+from openlp.core.common import AppLocation, CONTROL_CHARS
from openlp.core.lib import translate
-from openlp.core.utils import CONTROL_CHARS
from openlp.plugins.songs.lib.db import MediaFile, Song
from .db import Author
from .ui import SongStrings
=== modified file 'openlp/plugins/songs/lib/db.py'
--- openlp/plugins/songs/lib/db.py 2016-01-09 15:23:11 +0000
+++ openlp/plugins/songs/lib/db.py 2016-04-05 20:26:45 +0000
@@ -29,7 +29,7 @@
from sqlalchemy.sql.expression import func, text
from openlp.core.lib.db import BaseModel, init_db
-from openlp.core.utils import get_natural_key
+from openlp.core.common.languagemanager import get_natural_key
from openlp.core.lib import translate
=== modified file 'openlp/plugins/songs/lib/importers/openoffice.py'
--- openlp/plugins/songs/lib/importers/openoffice.py 2015-12-31 22:46:06 +0000
+++ openlp/plugins/songs/lib/importers/openoffice.py 2016-04-05 20:26:45 +0000
@@ -25,8 +25,7 @@
from PyQt5 import QtCore
-from openlp.core.common import is_win
-from openlp.core.utils import get_uno_command, get_uno_instance
+from openlp.core.common import is_win, get_uno_command, get_uno_instance
from openlp.core.lib import translate
from .songimport import SongImport
=== modified file 'openlp/plugins/songs/lib/mediaitem.py'
--- openlp/plugins/songs/lib/mediaitem.py 2016-04-03 11:14:17 +0000
+++ openlp/plugins/songs/lib/mediaitem.py 2016-04-05 20:26:45 +0000
@@ -32,7 +32,7 @@
from openlp.core.lib import MediaManagerItem, ItemCapabilities, PluginStatus, ServiceItemContext, \
check_item_selected, create_separated_list
from openlp.core.lib.ui import create_widget_action
-from openlp.core.utils import get_natural_key
+from openlp.core.common.languagemanager import get_natural_key
from openlp.plugins.songs.forms.editsongform import EditSongForm
from openlp.plugins.songs.forms.songmaintenanceform import SongMaintenanceForm
from openlp.plugins.songs.forms.songimportform import SongImportForm
=== modified file 'openlp/plugins/songs/lib/openlyricsexport.py'
--- openlp/plugins/songs/lib/openlyricsexport.py 2015-12-31 22:46:06 +0000
+++ openlp/plugins/songs/lib/openlyricsexport.py 2016-04-05 20:26:45 +0000
@@ -28,8 +28,7 @@
from lxml import etree
-from openlp.core.common import RegistryProperties, check_directory_exists, translate
-from openlp.core.utils import clean_filename
+from openlp.core.common import RegistryProperties, check_directory_exists, translate, clean_filename
from openlp.plugins.songs.lib.openlyricsxml import OpenLyrics
log = logging.getLogger(__name__)
=== modified file 'openlp/plugins/songs/lib/openlyricsxml.py'
--- openlp/plugins/songs/lib/openlyricsxml.py 2016-01-09 15:23:11 +0000
+++ openlp/plugins/songs/lib/openlyricsxml.py 2016-04-05 20:26:45 +0000
@@ -62,10 +62,10 @@
from lxml import etree, objectify
from openlp.core.common import translate
+from openlp.core.common.versionchecker import get_application_version
from openlp.core.lib import FormattingTags
from openlp.plugins.songs.lib import VerseType, clean_song
from openlp.plugins.songs.lib.db import Author, AuthorType, Book, Song, Topic
-from openlp.core.utils import get_application_version
log = logging.getLogger(__name__)
=== modified file 'setup.py'
--- setup.py 2015-12-31 22:46:06 +0000
+++ setup.py 2016-04-05 20:26:45 +0000
@@ -65,8 +65,8 @@
return temp
-# NOTE: The following code is a duplicate of the code in openlp/core/utils/__init__.py. Any fix applied here should also
-# be applied there.
+# NOTE: The following code is a duplicate of the code in openlp/core/common/checkversion.py.
+# Any fix applied here should also be applied there.
ver_file = None
try:
# Get the revision of this tree.
=== modified file 'tests/functional/openlp_core_common/test_applocation.py'
--- tests/functional/openlp_core_common/test_applocation.py 2015-12-31 22:46:06 +0000
+++ tests/functional/openlp_core_common/test_applocation.py 2016-04-05 20:26:45 +0000
@@ -171,7 +171,7 @@
"""
Test the _get_frozen_path() function when the application is not frozen (compiled by PyInstaller)
"""
- with patch('openlp.core.utils.sys') as mocked_sys:
+ with patch('openlp.core.common.sys') as mocked_sys:
# GIVEN: The sys module "without" a "frozen" attribute
mocked_sys.frozen = None
=== modified file 'tests/functional/openlp_core_common/test_init.py'
--- tests/functional/openlp_core_common/test_init.py 2016-04-01 17:28:40 +0000
+++ tests/functional/openlp_core_common/test_init.py 2016-04-05 20:26:45 +0000
@@ -25,15 +25,29 @@
import os
from unittest import TestCase
-from openlp.core.common import add_actions
+from openlp.core.common import add_actions, get_uno_instance, get_uno_command, delete_file, get_filesystem_encoding, \
+ split_filename, clean_filename
from tests.functional import MagicMock, patch
-
-
-class TestInit(TestCase):
+from tests.helpers.testmixin import TestMixin
+
+
+class TestInit(TestCase, TestMixin):
"""
A test suite to test out various methods around the common __init__ class.
"""
+ def setUp(self):
+ """
+ Create an instance and a few example actions.
+ """
+ self.build_settings()
+
+ def tearDown(self):
+ """
+ Clean up
+ """
+ self.destroy_settings()
+
def add_actions_empty_list_test(self):
"""
Test that no actions are added when the list is empty
@@ -93,3 +107,236 @@
# THEN: The addSeparator method is called, and the addAction method is called
mocked_target.addSeparator.assert_called_with()
mocked_target.addAction.assert_called_with('action')
+
+ def get_uno_instance_pipe_test(self):
+ """
+ Test that when the UNO connection type is "pipe" the resolver is given the "pipe" URI
+ """
+ # GIVEN: A mock resolver object and UNO_CONNECTION_TYPE is "pipe"
+ mock_resolver = MagicMock()
+
+ # WHEN: get_uno_instance() is called
+ get_uno_instance(mock_resolver)
+
+ # THEN: the resolve method is called with the correct argument
+ mock_resolver.resolve.assert_called_with('uno:pipe,name=openlp_pipe;urp;StarOffice.ComponentContext')
+
+ def get_uno_instance_socket_test(self):
+ """
+ Test that when the UNO connection type is other than "pipe" the resolver is given the "socket" URI
+ """
+ # GIVEN: A mock resolver object and UNO_CONNECTION_TYPE is "socket"
+ mock_resolver = MagicMock()
+
+ # WHEN: get_uno_instance() is called
+ get_uno_instance(mock_resolver, 'socket')
+
+ # THEN: the resolve method is called with the correct argument
+ mock_resolver.resolve.assert_called_with('uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext')
+
+ def get_uno_command_libreoffice_command_exists_test(self):
+ """
+ Test the ``get_uno_command`` function uses the libreoffice command when available.
+ :return:
+ """
+
+ # GIVEN: A patched 'which' method which returns a path when called with 'libreoffice'
+ with patch('openlp.core.common.which',
+ **{'side_effect': lambda command: {'libreoffice': '/usr/bin/libreoffice'}[command]}):
+ # WHEN: Calling get_uno_command
+ result = get_uno_command()
+
+ # THEN: The command 'libreoffice' should be called with the appropriate parameters
+ self.assertEquals(result,
+ 'libreoffice --nologo --norestore --minimized --nodefault --nofirststartwizard'
+ ' "--accept=pipe,name=openlp_pipe;urp;"')
+
+ def get_uno_command_only_soffice_command_exists_test(self):
+ """
+ Test the ``get_uno_command`` function uses the soffice command when the libreoffice command is not available.
+ :return:
+ """
+
+ # GIVEN: A patched 'which' method which returns None when called with 'libreoffice' and a path when called with
+ # 'soffice'
+ with patch('openlp.core.common.which',
+ **{'side_effect': lambda command: {'libreoffice': None, 'soffice': '/usr/bin/soffice'}[
+ command]}):
+ # WHEN: Calling get_uno_command
+ result = get_uno_command()
+
+ # THEN: The command 'soffice' should be called with the appropriate parameters
+ self.assertEquals(result, 'soffice --nologo --norestore --minimized --nodefault --nofirststartwizard'
+ ' "--accept=pipe,name=openlp_pipe;urp;"')
+
+ def get_uno_command_when_no_command_exists_test(self):
+ """
+ Test the ``get_uno_command`` function raises an FileNotFoundError when neither the libreoffice or soffice
+ commands are available.
+ :return:
+ """
+
+ # GIVEN: A patched 'which' method which returns None
+ with patch('openlp.core.common.which', **{'return_value': None}):
+ # WHEN: Calling get_uno_command
+
+ # THEN: a FileNotFoundError exception should be raised
+ self.assertRaises(FileNotFoundError, get_uno_command)
+
+ def get_uno_command_connection_type_test(self):
+ """
+ Test the ``get_uno_command`` function when the connection type is anything other than pipe.
+ :return:
+ """
+
+ # GIVEN: A patched 'which' method which returns 'libreoffice'
+ with patch('openlp.core.common.which', **{'return_value': 'libreoffice'}):
+ # WHEN: Calling get_uno_command with a connection type other than pipe
+ result = get_uno_command('socket')
+
+ # THEN: The connection parameters should be set for socket
+ self.assertEqual(result, 'libreoffice --nologo --norestore --minimized --nodefault --nofirststartwizard'
+ ' "--accept=socket,host=localhost,port=2002;urp;"')
+
+ def get_filesystem_encoding_sys_function_not_called_test(self):
+ """
+ Test the get_filesystem_encoding() function does not call the sys.getdefaultencoding() function
+ """
+ # GIVEN: sys.getfilesystemencoding returns "cp1252"
+ with patch('openlp.core.common.sys.getfilesystemencoding') as mocked_getfilesystemencoding, \
+ patch('openlp.core.common.sys.getdefaultencoding') as mocked_getdefaultencoding:
+ mocked_getfilesystemencoding.return_value = 'cp1252'
+
+ # WHEN: get_filesystem_encoding() is called
+ result = get_filesystem_encoding()
+
+ # THEN: getdefaultencoding should have been called
+ mocked_getfilesystemencoding.assert_called_with()
+ self.assertEqual(0, mocked_getdefaultencoding.called, 'getdefaultencoding should not have been called')
+ self.assertEqual('cp1252', result, 'The result should be "cp1252"')
+
+ def get_filesystem_encoding_sys_function_is_called_test(self):
+ """
+ Test the get_filesystem_encoding() function calls the sys.getdefaultencoding() function
+ """
+ # GIVEN: sys.getfilesystemencoding returns None and sys.getdefaultencoding returns "utf-8"
+ with patch('openlp.core.common.sys.getfilesystemencoding') as mocked_getfilesystemencoding, \
+ patch('openlp.core.common.sys.getdefaultencoding') as mocked_getdefaultencoding:
+ mocked_getfilesystemencoding.return_value = None
+ mocked_getdefaultencoding.return_value = 'utf-8'
+
+ # WHEN: get_filesystem_encoding() is called
+ result = get_filesystem_encoding()
+
+ # THEN: getdefaultencoding should have been called
+ mocked_getfilesystemencoding.assert_called_with()
+ mocked_getdefaultencoding.assert_called_with()
+ self.assertEqual('utf-8', result, 'The result should be "utf-8"')
+
+ def split_filename_with_file_path_test(self):
+ """
+ Test the split_filename() function with a path to a file
+ """
+ # GIVEN: A path to a file.
+ if os.name == 'nt':
+ file_path = 'C:\\home\\user\\myfile.txt'
+ wanted_result = ('C:\\home\\user', 'myfile.txt')
+ else:
+ file_path = '/home/user/myfile.txt'
+ wanted_result = ('/home/user', 'myfile.txt')
+ with patch('openlp.core.common.os.path.isfile') as mocked_is_file:
+ mocked_is_file.return_value = True
+
+ # WHEN: Split the file name.
+ result = split_filename(file_path)
+
+ # THEN: A tuple should be returned.
+ self.assertEqual(wanted_result, result, 'A tuple with the dir and file name should have been returned')
+
+ def split_filename_with_dir_path_test(self):
+ """
+ Test the split_filename() function with a path to a directory
+ """
+ # GIVEN: A path to a dir.
+ if os.name == 'nt':
+ file_path = 'C:\\home\\user\\mydir'
+ wanted_result = ('C:\\home\\user\\mydir', '')
+ else:
+ file_path = '/home/user/mydir'
+ wanted_result = ('/home/user/mydir', '')
+ with patch('openlp.core.common.os.path.isfile') as mocked_is_file:
+ mocked_is_file.return_value = False
+
+ # WHEN: Split the file name.
+ result = split_filename(file_path)
+
+ # THEN: A tuple should be returned.
+ self.assertEqual(wanted_result, result,
+ 'A two-entry tuple with the directory and file name (empty) should have been returned.')
+
+ def clean_filename_test(self):
+ """
+ Test the clean_filename() function
+ """
+ # GIVEN: A invalid file name and the valid file name.
+ invalid_name = 'A_file_with_invalid_characters_[\\/:\*\?"<>\|\+\[\]%].py'
+ wanted_name = 'A_file_with_invalid_characters______________________.py'
+
+ # WHEN: Clean the name.
+ result = clean_filename(invalid_name)
+
+ # THEN: The file name should be cleaned.
+ self.assertEqual(wanted_name, result, 'The file name should not contain any special characters.')
+
+ def delete_file_no_path_test(self):
+ """
+ Test the delete_file function when called with out a valid path
+ """
+ # GIVEN: A blank path
+ # WEHN: Calling delete_file
+ result = delete_file('')
+
+ # THEN: delete_file should return False
+ self.assertFalse(result, "delete_file should return False when called with ''")
+
+ def delete_file_path_success_test(self):
+ """
+ Test the delete_file function when it successfully deletes a file
+ """
+ # GIVEN: A mocked os which returns True when os.path.exists is called
+ with patch('openlp.core.common.os', **{'path.exists.return_value': False}):
+
+ # WHEN: Calling delete_file with a file path
+ result = delete_file('path/file.ext')
+
+ # THEN: delete_file should return True
+ self.assertTrue(result, 'delete_file should return True when it successfully deletes a file')
+
+ def delete_file_path_no_file_exists_test(self):
+ """
+ Test the delete_file function when the file to remove does not exist
+ """
+ # GIVEN: A mocked os which returns False when os.path.exists is called
+ with patch('openlp.core.common.os', **{'path.exists.return_value': False}):
+
+ # WHEN: Calling delete_file with a file path
+ result = delete_file('path/file.ext')
+
+ # THEN: delete_file should return True
+ self.assertTrue(result, 'delete_file should return True when the file doesnt exist')
+
+ def delete_file_path_exception_test(self):
+ """
+ Test the delete_file function when os.remove raises an exception
+ """
+ # GIVEN: A mocked os which returns True when os.path.exists is called and raises an OSError when os.remove is
+ # called.
+ with patch('openlp.core.common.os', **{'path.exists.return_value': True, 'path.exists.side_effect': OSError}), \
+ patch('openlp.core.common.log') as mocked_log:
+
+ # WHEN: Calling delete_file with a file path
+ result = delete_file('path/file.ext')
+
+ # THEN: delete_file should log and exception and return False
+ self.assertEqual(mocked_log.exception.call_count, 1)
+ self.assertFalse(result, 'delete_file should return False when os.remove raises an OSError')
=== added file 'tests/functional/openlp_core_common/test_languagemanager.py'
--- tests/functional/openlp_core_common/test_languagemanager.py 1970-01-01 00:00:00 +0000
+++ tests/functional/openlp_core_common/test_languagemanager.py 2016-04-05 20:26:45 +0000
@@ -0,0 +1,66 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2016 OpenLP Developers #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it #
+# under the terms of the GNU General Public License as published by the Free #
+# Software Foundation; version 2 of the License. #
+# #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
+# more details. #
+# #
+# You should have received a copy of the GNU General Public License along #
+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
+###############################################################################
+"""
+Functional tests to test the AppLocation class and related methods.
+"""
+from unittest import TestCase
+
+from tests.functional import patch
+from openlp.core.common.languagemanager import get_locale_key, get_natural_key
+
+
+class TestLanguageManager(TestCase):
+ """
+ A test suite to test out various methods around the common __init__ class.
+ """
+
+ def get_locale_key_test(self):
+ """
+ Test the get_locale_key(string) function
+ """
+ with patch('openlp.core.common.languagemanager.LanguageManager.get_language') as mocked_get_language:
+ # GIVEN: The language is German
+ # 0x00C3 (A with diaresis) should be sorted as "A". 0x00DF (sharp s) should be sorted as "ss".
+ mocked_get_language.return_value = 'de'
+ unsorted_list = ['Auszug', 'Aushang', '\u00C4u\u00DFerung']
+
+ # WHEN: We sort the list and use get_locale_key() to generate the sorting keys
+ sorted_list = sorted(unsorted_list, key=get_locale_key)
+
+ # THEN: We get a properly sorted list
+ self.assertEqual(['Aushang', '\u00C4u\u00DFerung', 'Auszug'], sorted_list,
+ 'Strings should be sorted properly')
+
+ def get_natural_key_test(self):
+ """
+ Test the get_natural_key(string) function
+ """
+ with patch('openlp.core.common.languagemanager.LanguageManager.get_language') as mocked_get_language:
+ # GIVEN: The language is English (a language, which sorts digits before letters)
+ mocked_get_language.return_value = 'en'
+ unsorted_list = ['item 10a', 'item 3b', '1st item']
+
+ # WHEN: We sort the list and use get_natural_key() to generate the sorting keys
+ sorted_list = sorted(unsorted_list, key=get_natural_key)
+
+ # THEN: We get a properly sorted list
+ self.assertEqual(['1st item', 'item 3b', 'item 10a'], sorted_list, 'Numbers should be sorted naturally')
=== added file 'tests/functional/openlp_core_common/test_versionchecker.py'
--- tests/functional/openlp_core_common/test_versionchecker.py 1970-01-01 00:00:00 +0000
+++ tests/functional/openlp_core_common/test_versionchecker.py 2016-04-05 20:26:45 +0000
@@ -0,0 +1,63 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2016 OpenLP Developers #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it #
+# under the terms of the GNU General Public License as published by the Free #
+# Software Foundation; version 2 of the License. #
+# #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
+# more details. #
+# #
+# You should have received a copy of the GNU General Public License along #
+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
+###############################################################################
+"""
+Package to test the openlp.core.common.versionchecker package.
+"""
+from unittest import TestCase
+
+from openlp.core.common.settings import Settings
+from openlp.core.common.versionchecker import VersionThread
+from tests.functional import MagicMock, patch
+from tests.helpers.testmixin import TestMixin
+
+
+class TestVersionchecker(TestMixin, TestCase):
+
+ def setUp(self):
+ """
+ Create an instance and a few example actions.
+ """
+ self.build_settings()
+
+ def tearDown(self):
+ """
+ Clean up
+ """
+ self.destroy_settings()
+
+ def version_thread_triggered_test(self):
+ """
+ Test the version thread call does not trigger UI
+ :return:
+ """
+ # GIVEN: a equal version setup and the data is not today.
+ mocked_main_window = MagicMock()
+ Settings().setValue('core/last version test', '1950-04-01')
+ # WHEN: We check to see if the version is different .
+ with patch('PyQt5.QtCore.QThread'),\
+ patch('openlp.core.common.versionchecker.get_application_version') as mocked_get_application_version:
+ mocked_get_application_version.return_value = {'version': '1.0.0', 'build': '', 'full': '2.0.4'}
+ version_thread = VersionThread(mocked_main_window)
+ version_thread.run()
+ # THEN: If the version has changed the main window is notified
+ self.assertTrue(mocked_main_window.openlp_version_check.emit.called,
+ 'The main windows should have been notified')
=== added file 'tests/functional/openlp_core_lib/test_webpagereader.py'
--- tests/functional/openlp_core_lib/test_webpagereader.py 1970-01-01 00:00:00 +0000
+++ tests/functional/openlp_core_lib/test_webpagereader.py 2016-04-05 20:26:45 +0000
@@ -0,0 +1,229 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2016 OpenLP Developers #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it #
+# under the terms of the GNU General Public License as published by the Free #
+# Software Foundation; version 2 of the License. #
+# #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
+# more details. #
+# #
+# You should have received a copy of the GNU General Public License along #
+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
+###############################################################################
+"""
+Functional tests to test the AppLocation class and related methods.
+"""
+from unittest import TestCase
+
+from openlp.core.lib.webpagereader import _get_user_agent, get_web_page
+
+from tests.functional import MagicMock, patch
+
+
+class TestUtils(TestCase):
+ """
+ A test suite to test out various methods around the AppLocation class.
+ """
+ def get_user_agent_linux_test(self):
+ """
+ Test that getting a user agent on Linux returns a user agent suitable for Linux
+ """
+ with patch('openlp.core.lib.webpagereader.sys') as mocked_sys:
+
+ # GIVEN: The system is Linux
+ mocked_sys.platform = 'linux2'
+
+ # WHEN: We call _get_user_agent()
+ user_agent = _get_user_agent()
+
+ # THEN: The user agent is a Linux (or ChromeOS) user agent
+ result = 'Linux' in user_agent or 'CrOS' in user_agent
+ self.assertTrue(result, 'The user agent should be a valid Linux user agent')
+
+ def get_user_agent_windows_test(self):
+ """
+ Test that getting a user agent on Windows returns a user agent suitable for Windows
+ """
+ with patch('openlp.core.lib.webpagereader.sys') as mocked_sys:
+
+ # GIVEN: The system is Linux
+ mocked_sys.platform = 'win32'
+
+ # WHEN: We call _get_user_agent()
+ user_agent = _get_user_agent()
+
+ # THEN: The user agent is a Linux (or ChromeOS) user agent
+ self.assertIn('Windows', user_agent, 'The user agent should be a valid Windows user agent')
+
+ def get_user_agent_macos_test(self):
+ """
+ Test that getting a user agent on OS X returns a user agent suitable for OS X
+ """
+ with patch('openlp.core.lib.webpagereader.sys') as mocked_sys:
+
+ # GIVEN: The system is Linux
+ mocked_sys.platform = 'darwin'
+
+ # WHEN: We call _get_user_agent()
+ user_agent = _get_user_agent()
+
+ # THEN: The user agent is a Linux (or ChromeOS) user agent
+ self.assertIn('Mac OS X', user_agent, 'The user agent should be a valid OS X user agent')
+
+ def get_user_agent_default_test(self):
+ """
+ Test that getting a user agent on a non-Linux/Windows/OS X platform returns the default user agent
+ """
+ with patch('openlp.core.lib.webpagereader.sys') as mocked_sys:
+
+ # GIVEN: The system is Linux
+ mocked_sys.platform = 'freebsd'
+
+ # WHEN: We call _get_user_agent()
+ user_agent = _get_user_agent()
+
+ # THEN: The user agent is a Linux (or ChromeOS) user agent
+ self.assertIn('NetBSD', user_agent, 'The user agent should be the default user agent')
+
+ def get_web_page_no_url_test(self):
+ """
+ Test that sending a URL of None to the get_web_page method returns None
+ """
+ # GIVEN: A None url
+ test_url = None
+
+ # WHEN: We try to get the test URL
+ result = get_web_page(test_url)
+
+ # THEN: None should be returned
+ self.assertIsNone(result, 'The return value of get_web_page should be None')
+
+ def get_web_page_test(self):
+ """
+ Test that the get_web_page method works correctly
+ """
+ with patch('openlp.core.lib.webpagereader.urllib.request.Request') as MockRequest, \
+ patch('openlp.core.lib.webpagereader.urllib.request.urlopen') as mock_urlopen, \
+ patch('openlp.core.lib.webpagereader._get_user_agent') as mock_get_user_agent, \
+ patch('openlp.core.common.Registry') as MockRegistry:
+ # GIVEN: Mocked out objects and a fake URL
+ mocked_request_object = MagicMock()
+ MockRequest.return_value = mocked_request_object
+ mocked_page_object = MagicMock()
+ mock_urlopen.return_value = mocked_page_object
+ mock_get_user_agent.return_value = 'user_agent'
+ fake_url = 'this://is.a.fake/url'
+
+ # WHEN: The get_web_page() method is called
+ returned_page = get_web_page(fake_url)
+
+ # THEN: The correct methods are called with the correct arguments and a web page is returned
+ MockRequest.assert_called_with(fake_url)
+ mocked_request_object.add_header.assert_called_with('User-Agent', 'user_agent')
+ self.assertEqual(1, mocked_request_object.add_header.call_count,
+ 'There should only be 1 call to add_header')
+ mock_get_user_agent.assert_called_with()
+ mock_urlopen.assert_called_with(mocked_request_object, timeout=30)
+ mocked_page_object.geturl.assert_called_with()
+ self.assertEqual(0, MockRegistry.call_count, 'The Registry() object should have never been called')
+ self.assertEqual(mocked_page_object, returned_page, 'The returned page should be the mock object')
+
+ def get_web_page_with_header_test(self):
+ """
+ Test that adding a header to the call to get_web_page() adds the header to the request
+ """
+ with patch('openlp.core.lib.webpagereader.urllib.request.Request') as MockRequest, \
+ patch('openlp.core.lib.webpagereader.urllib.request.urlopen') as mock_urlopen, \
+ patch('openlp.core.lib.webpagereader._get_user_agent') as mock_get_user_agent:
+ # GIVEN: Mocked out objects, a fake URL and a fake header
+ mocked_request_object = MagicMock()
+ MockRequest.return_value = mocked_request_object
+ mocked_page_object = MagicMock()
+ mock_urlopen.return_value = mocked_page_object
+ mock_get_user_agent.return_value = 'user_agent'
+ fake_url = 'this://is.a.fake/url'
+ fake_header = ('Fake-Header', 'fake value')
+
+ # WHEN: The get_web_page() method is called
+ returned_page = get_web_page(fake_url, header=fake_header)
+
+ # THEN: The correct methods are called with the correct arguments and a web page is returned
+ MockRequest.assert_called_with(fake_url)
+ mocked_request_object.add_header.assert_called_with(fake_header[0], fake_header[1])
+ self.assertEqual(2, mocked_request_object.add_header.call_count,
+ 'There should only be 2 calls to add_header')
+ mock_get_user_agent.assert_called_with()
+ mock_urlopen.assert_called_with(mocked_request_object, timeout=30)
+ mocked_page_object.geturl.assert_called_with()
+ self.assertEqual(mocked_page_object, returned_page, 'The returned page should be the mock object')
+
+ def get_web_page_with_user_agent_in_headers_test(self):
+ """
+ Test that adding a user agent in the header when calling get_web_page() adds that user agent to the request
+ """
+ with patch('openlp.core.lib.webpagereader.urllib.request.Request') as MockRequest, \
+ patch('openlp.core.lib.webpagereader.urllib.request.urlopen') as mock_urlopen, \
+ patch('openlp.core.lib.webpagereader._get_user_agent') as mock_get_user_agent:
+ # GIVEN: Mocked out objects, a fake URL and a fake header
+ mocked_request_object = MagicMock()
+ MockRequest.return_value = mocked_request_object
+ mocked_page_object = MagicMock()
+ mock_urlopen.return_value = mocked_page_object
+ fake_url = 'this://is.a.fake/url'
+ user_agent_header = ('User-Agent', 'OpenLP/2.2.0')
+
+ # WHEN: The get_web_page() method is called
+ returned_page = get_web_page(fake_url, header=user_agent_header)
+
+ # THEN: The correct methods are called with the correct arguments and a web page is returned
+ MockRequest.assert_called_with(fake_url)
+ mocked_request_object.add_header.assert_called_with(user_agent_header[0], user_agent_header[1])
+ self.assertEqual(1, mocked_request_object.add_header.call_count,
+ 'There should only be 1 call to add_header')
+ self.assertEqual(0, mock_get_user_agent.call_count, '_get_user_agent should not have been called')
+ mock_urlopen.assert_called_with(mocked_request_object, timeout=30)
+ mocked_page_object.geturl.assert_called_with()
+ self.assertEqual(mocked_page_object, returned_page, 'The returned page should be the mock object')
+
+ def get_web_page_update_openlp_test(self):
+ """
+ Test that passing "update_openlp" as true to get_web_page calls Registry().get('app').process_events()
+ """
+ with patch('openlp.core.lib.webpagereader.urllib.request.Request') as MockRequest, \
+ patch('openlp.core.lib.webpagereader.urllib.request.urlopen') as mock_urlopen, \
+ patch('openlp.core.lib.webpagereader._get_user_agent') as mock_get_user_agent, \
+ patch('openlp.core.lib.webpagereader.Registry') as MockRegistry:
+ # GIVEN: Mocked out objects, a fake URL
+ mocked_request_object = MagicMock()
+ MockRequest.return_value = mocked_request_object
+ mocked_page_object = MagicMock()
+ mock_urlopen.return_value = mocked_page_object
+ mock_get_user_agent.return_value = 'user_agent'
+ mocked_registry_object = MagicMock()
+ mocked_application_object = MagicMock()
+ mocked_registry_object.get.return_value = mocked_application_object
+ MockRegistry.return_value = mocked_registry_object
+ fake_url = 'this://is.a.fake/url'
+
+ # WHEN: The get_web_page() method is called
+ returned_page = get_web_page(fake_url, update_openlp=True)
+
+ # THEN: The correct methods are called with the correct arguments and a web page is returned
+ MockRequest.assert_called_with(fake_url)
+ mocked_request_object.add_header.assert_called_with('User-Agent', 'user_agent')
+ self.assertEqual(1, mocked_request_object.add_header.call_count,
+ 'There should only be 1 call to add_header')
+ mock_urlopen.assert_called_with(mocked_request_object, timeout=30)
+ mocked_page_object.geturl.assert_called_with()
+ mocked_registry_object.get.assert_called_with('application')
+ mocked_application_object.process_events.assert_called_with()
+ self.assertEqual(mocked_page_object, returned_page, 'The returned page should be the mock object')
=== added file 'tests/functional/openlp_core_ui/test_first_time.py'
--- tests/functional/openlp_core_ui/test_first_time.py 1970-01-01 00:00:00 +0000
+++ tests/functional/openlp_core_ui/test_first_time.py 2016-04-05 20:26:45 +0000
@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2016 OpenLP Developers #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it #
+# under the terms of the GNU General Public License as published by the Free #
+# Software Foundation; version 2 of the License. #
+# #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
+# more details. #
+# #
+# You should have received a copy of the GNU General Public License along #
+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
+###############################################################################
+"""
+Package to test the openlp.core.utils.__init__ package.
+"""
+
+from unittest import TestCase
+import urllib.request
+import urllib.error
+import urllib.parse
+
+from tests.functional import patch
+from tests.helpers.testmixin import TestMixin
+
+from openlp.core.lib.webpagereader import CONNECTION_RETRIES, get_web_page
+
+
+class TestFirstTimeWizard(TestMixin, TestCase):
+ """
+ Test First Time Wizard import functions
+ """
+ def webpage_connection_retry_test(self):
+ """
+ Test get_web_page will attempt CONNECTION_RETRIES+1 connections - bug 1409031
+ """
+ # GIVEN: Initial settings and mocks
+ with patch.object(urllib.request, 'urlopen') as mocked_urlopen:
+ mocked_urlopen.side_effect = ConnectionError
+
+ # WHEN: A webpage is requested
+ try:
+ get_web_page(url='http://localhost')
+ except:
+ pass
+
+ # THEN: urlopen should have been called CONNECTION_RETRIES + 1 count
+ self.assertEquals(mocked_urlopen.call_count, CONNECTION_RETRIES + 1,
+ 'get_web_page() should have tried {} times'.format(CONNECTION_RETRIES))
=== removed directory 'tests/functional/openlp_core_utils'
=== removed file 'tests/functional/openlp_core_utils/__init__.py'
--- tests/functional/openlp_core_utils/__init__.py 2015-12-31 22:46:06 +0000
+++ tests/functional/openlp_core_utils/__init__.py 1970-01-01 00:00:00 +0000
@@ -1,21 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2016 OpenLP Developers #
-# --------------------------------------------------------------------------- #
-# This program is free software; you can redistribute it and/or modify it #
-# under the terms of the GNU General Public License as published by the Free #
-# Software Foundation; version 2 of the License. #
-# #
-# This program is distributed in the hope that it will be useful, but WITHOUT #
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
-# more details. #
-# #
-# You should have received a copy of the GNU General Public License along #
-# with this program; if not, write to the Free Software Foundation, Inc., 59 #
-# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
-###############################################################################
=== removed file 'tests/functional/openlp_core_utils/test_first_time.py'
--- tests/functional/openlp_core_utils/test_first_time.py 2015-12-31 22:46:06 +0000
+++ tests/functional/openlp_core_utils/test_first_time.py 1970-01-01 00:00:00 +0000
@@ -1,57 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2016 OpenLP Developers #
-# --------------------------------------------------------------------------- #
-# This program is free software; you can redistribute it and/or modify it #
-# under the terms of the GNU General Public License as published by the Free #
-# Software Foundation; version 2 of the License. #
-# #
-# This program is distributed in the hope that it will be useful, but WITHOUT #
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
-# more details. #
-# #
-# You should have received a copy of the GNU General Public License along #
-# with this program; if not, write to the Free Software Foundation, Inc., 59 #
-# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
-###############################################################################
-"""
-Package to test the openlp.core.utils.__init__ package.
-"""
-
-from unittest import TestCase
-import urllib.request
-import urllib.error
-import urllib.parse
-
-from tests.functional import MagicMock, patch
-from tests.helpers.testmixin import TestMixin
-
-from openlp.core.utils import CONNECTION_TIMEOUT, CONNECTION_RETRIES, get_web_page
-
-
-class TestFirstTimeWizard(TestMixin, TestCase):
- """
- Test First Time Wizard import functions
- """
- def webpage_connection_retry_test(self):
- """
- Test get_web_page will attempt CONNECTION_RETRIES+1 connections - bug 1409031
- """
- # GIVEN: Initial settings and mocks
- with patch.object(urllib.request, 'urlopen') as mocked_urlopen:
- mocked_urlopen.side_effect = ConnectionError
-
- # WHEN: A webpage is requested
- try:
- get_web_page(url='http://localhost')
- except:
- pass
-
- # THEN: urlopen should have been called CONNECTION_RETRIES + 1 count
- self.assertEquals(mocked_urlopen.call_count, CONNECTION_RETRIES + 1,
- 'get_web_page() should have tried {} times'.format(CONNECTION_RETRIES))
=== removed file 'tests/functional/openlp_core_utils/test_init.py'
--- tests/functional/openlp_core_utils/test_init.py 2015-12-31 22:46:06 +0000
+++ tests/functional/openlp_core_utils/test_init.py 1970-01-01 00:00:00 +0000
@@ -1,129 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2016 OpenLP Developers #
-# --------------------------------------------------------------------------- #
-# This program is free software; you can redistribute it and/or modify it #
-# under the terms of the GNU General Public License as published by the Free #
-# Software Foundation; version 2 of the License. #
-# #
-# This program is distributed in the hope that it will be useful, but WITHOUT #
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
-# more details. #
-# #
-# You should have received a copy of the GNU General Public License along #
-# with this program; if not, write to the Free Software Foundation, Inc., 59 #
-# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
-###############################################################################
-"""
-Package to test the openlp.core.utils.actions package.
-"""
-from unittest import TestCase
-
-from openlp.core.common.settings import Settings
-from openlp.core.utils import VersionThread, get_uno_command
-from tests.functional import MagicMock, patch
-from tests.helpers.testmixin import TestMixin
-
-
-class TestInitFunctions(TestMixin, TestCase):
-
- def setUp(self):
- """
- Create an instance and a few example actions.
- """
- self.build_settings()
-
- def tearDown(self):
- """
- Clean up
- """
- self.destroy_settings()
-
- def version_thread_triggered_test(self):
- """
- Test the version thread call does not trigger UI
- :return:
- """
- # GIVEN: a equal version setup and the data is not today.
- mocked_main_window = MagicMock()
- Settings().setValue('core/last version test', '1950-04-01')
- # WHEN: We check to see if the version is different .
- with patch('PyQt5.QtCore.QThread'),\
- patch('openlp.core.utils.get_application_version') as mocked_get_application_version:
- mocked_get_application_version.return_value = {'version': '1.0.0', 'build': '', 'full': '2.0.4'}
- version_thread = VersionThread(mocked_main_window)
- version_thread.run()
- # THEN: If the version has changed the main window is notified
- self.assertTrue(mocked_main_window.openlp_version_check.emit.called,
- 'The main windows should have been notified')
-
- def get_uno_command_libreoffice_command_exists_test(self):
- """
- Test the ``get_uno_command`` function uses the libreoffice command when available.
- :return:
- """
-
- # GIVEN: A patched 'which' method which returns a path when called with 'libreoffice'
- with patch('openlp.core.utils.which',
- **{'side_effect': lambda command: {'libreoffice': '/usr/bin/libreoffice'}[command]}):
-
- # WHEN: Calling get_uno_command
- result = get_uno_command()
-
- # THEN: The command 'libreoffice' should be called with the appropriate parameters
- self.assertEquals(result, 'libreoffice --nologo --norestore --minimized --nodefault --nofirststartwizard'
- ' "--accept=pipe,name=openlp_pipe;urp;"')
-
- def get_uno_command_only_soffice_command_exists_test(self):
- """
- Test the ``get_uno_command`` function uses the soffice command when the libreoffice command is not available.
- :return:
- """
-
- # GIVEN: A patched 'which' method which returns None when called with 'libreoffice' and a path when called with
- # 'soffice'
- with patch('openlp.core.utils.which',
- **{'side_effect': lambda command: {'libreoffice': None, 'soffice': '/usr/bin/soffice'}[command]}):
-
- # WHEN: Calling get_uno_command
- result = get_uno_command()
-
- # THEN: The command 'soffice' should be called with the appropriate parameters
- self.assertEquals(result, 'soffice --nologo --norestore --minimized --nodefault --nofirststartwizard'
- ' "--accept=pipe,name=openlp_pipe;urp;"')
-
- def get_uno_command_when_no_command_exists_test(self):
- """
- Test the ``get_uno_command`` function raises an FileNotFoundError when neither the libreoffice or soffice
- commands are available.
- :return:
- """
-
- # GIVEN: A patched 'which' method which returns None
- with patch('openlp.core.utils.which', **{'return_value': None}):
-
- # WHEN: Calling get_uno_command
-
- # THEN: a FileNotFoundError exception should be raised
- self.assertRaises(FileNotFoundError, get_uno_command)
-
- def get_uno_command_connection_type_test(self):
- """
- Test the ``get_uno_command`` function when the connection type is anything other than pipe.
- :return:
- """
-
- # GIVEN: A patched 'which' method which returns 'libreoffice'
- with patch('openlp.core.utils.which', **{'return_value': 'libreoffice'}):
-
- # WHEN: Calling get_uno_command with a connection type other than pipe
- result = get_uno_command('socket')
-
- # THEN: The connection parameters should be set for socket
- self.assertEqual(result, 'libreoffice --nologo --norestore --minimized --nodefault --nofirststartwizard'
- ' "--accept=socket,host=localhost,port=2002;urp;"')
=== removed file 'tests/functional/openlp_core_utils/test_utils.py'
--- tests/functional/openlp_core_utils/test_utils.py 2016-04-01 17:28:40 +0000
+++ tests/functional/openlp_core_utils/test_utils.py 1970-01-01 00:00:00 +0000
@@ -1,433 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2016 OpenLP Developers #
-# --------------------------------------------------------------------------- #
-# This program is free software; you can redistribute it and/or modify it #
-# under the terms of the GNU General Public License as published by the Free #
-# Software Foundation; version 2 of the License. #
-# #
-# This program is distributed in the hope that it will be useful, but WITHOUT #
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
-# more details. #
-# #
-# You should have received a copy of the GNU General Public License along #
-# with this program; if not, write to the Free Software Foundation, Inc., 59 #
-# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
-###############################################################################
-"""
-Functional tests to test the AppLocation class and related methods.
-"""
-import os
-from unittest import TestCase
-
-from openlp.core.utils import clean_filename, delete_file, get_filesystem_encoding, get_locale_key, \
- get_natural_key, split_filename, _get_user_agent, get_web_page, get_uno_instance
-
-from tests.functional import MagicMock, patch
-
-
-class TestUtils(TestCase):
- """
- A test suite to test out various methods around the AppLocation class.
- """
-
- def get_filesystem_encoding_sys_function_not_called_test(self):
- """
- Test the get_filesystem_encoding() function does not call the sys.getdefaultencoding() function
- """
- # GIVEN: sys.getfilesystemencoding returns "cp1252"
- with patch('openlp.core.utils.sys.getfilesystemencoding') as mocked_getfilesystemencoding, \
- patch('openlp.core.utils.sys.getdefaultencoding') as mocked_getdefaultencoding:
- mocked_getfilesystemencoding.return_value = 'cp1252'
-
- # WHEN: get_filesystem_encoding() is called
- result = get_filesystem_encoding()
-
- # THEN: getdefaultencoding should have been called
- mocked_getfilesystemencoding.assert_called_with()
- self.assertEqual(0, mocked_getdefaultencoding.called, 'getdefaultencoding should not have been called')
- self.assertEqual('cp1252', result, 'The result should be "cp1252"')
-
- def get_filesystem_encoding_sys_function_is_called_test(self):
- """
- Test the get_filesystem_encoding() function calls the sys.getdefaultencoding() function
- """
- # GIVEN: sys.getfilesystemencoding returns None and sys.getdefaultencoding returns "utf-8"
- with patch('openlp.core.utils.sys.getfilesystemencoding') as mocked_getfilesystemencoding, \
- patch('openlp.core.utils.sys.getdefaultencoding') as mocked_getdefaultencoding:
- mocked_getfilesystemencoding.return_value = None
- mocked_getdefaultencoding.return_value = 'utf-8'
-
- # WHEN: get_filesystem_encoding() is called
- result = get_filesystem_encoding()
-
- # THEN: getdefaultencoding should have been called
- mocked_getfilesystemencoding.assert_called_with()
- mocked_getdefaultencoding.assert_called_with()
- self.assertEqual('utf-8', result, 'The result should be "utf-8"')
-
- def split_filename_with_file_path_test(self):
- """
- Test the split_filename() function with a path to a file
- """
- # GIVEN: A path to a file.
- if os.name == 'nt':
- file_path = 'C:\\home\\user\\myfile.txt'
- wanted_result = ('C:\\home\\user', 'myfile.txt')
- else:
- file_path = '/home/user/myfile.txt'
- wanted_result = ('/home/user', 'myfile.txt')
- with patch('openlp.core.utils.os.path.isfile') as mocked_is_file:
- mocked_is_file.return_value = True
-
- # WHEN: Split the file name.
- result = split_filename(file_path)
-
- # THEN: A tuple should be returned.
- self.assertEqual(wanted_result, result, 'A tuple with the dir and file name should have been returned')
-
- def split_filename_with_dir_path_test(self):
- """
- Test the split_filename() function with a path to a directory
- """
- # GIVEN: A path to a dir.
- if os.name == 'nt':
- file_path = 'C:\\home\\user\\mydir'
- wanted_result = ('C:\\home\\user\\mydir', '')
- else:
- file_path = '/home/user/mydir'
- wanted_result = ('/home/user/mydir', '')
- with patch('openlp.core.utils.os.path.isfile') as mocked_is_file:
- mocked_is_file.return_value = False
-
- # WHEN: Split the file name.
- result = split_filename(file_path)
-
- # THEN: A tuple should be returned.
- self.assertEqual(wanted_result, result,
- 'A two-entry tuple with the directory and file name (empty) should have been returned.')
-
- def clean_filename_test(self):
- """
- Test the clean_filename() function
- """
- # GIVEN: A invalid file name and the valid file name.
- invalid_name = 'A_file_with_invalid_characters_[\\/:\*\?"<>\|\+\[\]%].py'
- wanted_name = 'A_file_with_invalid_characters______________________.py'
-
- # WHEN: Clean the name.
- result = clean_filename(invalid_name)
-
- # THEN: The file name should be cleaned.
- self.assertEqual(wanted_name, result, 'The file name should not contain any special characters.')
-
- def delete_file_no_path_test(self):
- """
- Test the delete_file function when called with out a valid path
- """
- # GIVEN: A blank path
- # WEHN: Calling delete_file
- result = delete_file('')
-
- # THEN: delete_file should return False
- self.assertFalse(result, "delete_file should return False when called with ''")
-
- def delete_file_path_success_test(self):
- """
- Test the delete_file function when it successfully deletes a file
- """
- # GIVEN: A mocked os which returns True when os.path.exists is called
- with patch('openlp.core.utils.os', **{'path.exists.return_value': False}):
-
- # WHEN: Calling delete_file with a file path
- result = delete_file('path/file.ext')
-
- # THEN: delete_file should return True
- self.assertTrue(result, 'delete_file should return True when it successfully deletes a file')
-
- def delete_file_path_no_file_exists_test(self):
- """
- Test the delete_file function when the file to remove does not exist
- """
- # GIVEN: A mocked os which returns False when os.path.exists is called
- with patch('openlp.core.utils.os', **{'path.exists.return_value': False}):
-
- # WHEN: Calling delete_file with a file path
- result = delete_file('path/file.ext')
-
- # THEN: delete_file should return True
- self.assertTrue(result, 'delete_file should return True when the file doesnt exist')
-
- def delete_file_path_exception_test(self):
- """
- Test the delete_file function when os.remove raises an exception
- """
- # GIVEN: A mocked os which returns True when os.path.exists is called and raises an OSError when os.remove is
- # called.
- with patch('openlp.core.utils.os', **{'path.exists.return_value': True, 'path.exists.side_effect': OSError}), \
- patch('openlp.core.utils.log') as mocked_log:
-
- # WHEN: Calling delete_file with a file path
- result = delete_file('path/file.ext')
-
- # THEN: delete_file should log and exception and return False
- self.assertEqual(mocked_log.exception.call_count, 1)
- self.assertFalse(result, 'delete_file should return False when os.remove raises an OSError')
-
- def get_locale_key_test(self):
- """
- Test the get_locale_key(string) function
- """
- with patch('openlp.core.common.languagemanager.LanguageManager.get_language') as mocked_get_language:
- # GIVEN: The language is German
- # 0x00C3 (A with diaresis) should be sorted as "A". 0x00DF (sharp s) should be sorted as "ss".
- mocked_get_language.return_value = 'de'
- unsorted_list = ['Auszug', 'Aushang', '\u00C4u\u00DFerung']
-
- # WHEN: We sort the list and use get_locale_key() to generate the sorting keys
- sorted_list = sorted(unsorted_list, key=get_locale_key)
-
- # THEN: We get a properly sorted list
- self.assertEqual(['Aushang', '\u00C4u\u00DFerung', 'Auszug'], sorted_list,
- 'Strings should be sorted properly')
-
- def get_natural_key_test(self):
- """
- Test the get_natural_key(string) function
- """
- with patch('openlp.core.common.languagemanager.LanguageManager.get_language') as mocked_get_language:
- # GIVEN: The language is English (a language, which sorts digits before letters)
- mocked_get_language.return_value = 'en'
- unsorted_list = ['item 10a', 'item 3b', '1st item']
-
- # WHEN: We sort the list and use get_natural_key() to generate the sorting keys
- sorted_list = sorted(unsorted_list, key=get_natural_key)
-
- # THEN: We get a properly sorted list
- self.assertEqual(['1st item', 'item 3b', 'item 10a'], sorted_list, 'Numbers should be sorted naturally')
-
- def get_uno_instance_pipe_test(self):
- """
- Test that when the UNO connection type is "pipe" the resolver is given the "pipe" URI
- """
- # GIVEN: A mock resolver object and UNO_CONNECTION_TYPE is "pipe"
- mock_resolver = MagicMock()
-
- # WHEN: get_uno_instance() is called
- get_uno_instance(mock_resolver)
-
- # THEN: the resolve method is called with the correct argument
- mock_resolver.resolve.assert_called_with('uno:pipe,name=openlp_pipe;urp;StarOffice.ComponentContext')
-
- def get_uno_instance_socket_test(self):
- """
- Test that when the UNO connection type is other than "pipe" the resolver is given the "socket" URI
- """
- # GIVEN: A mock resolver object and UNO_CONNECTION_TYPE is "socket"
- mock_resolver = MagicMock()
-
- # WHEN: get_uno_instance() is called
- get_uno_instance(mock_resolver, 'socket')
-
- # THEN: the resolve method is called with the correct argument
- mock_resolver.resolve.assert_called_with('uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext')
-
- def get_user_agent_linux_test(self):
- """
- Test that getting a user agent on Linux returns a user agent suitable for Linux
- """
- with patch('openlp.core.utils.sys') as mocked_sys:
-
- # GIVEN: The system is Linux
- mocked_sys.platform = 'linux2'
-
- # WHEN: We call _get_user_agent()
- user_agent = _get_user_agent()
-
- # THEN: The user agent is a Linux (or ChromeOS) user agent
- result = 'Linux' in user_agent or 'CrOS' in user_agent
- self.assertTrue(result, 'The user agent should be a valid Linux user agent')
-
- def get_user_agent_windows_test(self):
- """
- Test that getting a user agent on Windows returns a user agent suitable for Windows
- """
- with patch('openlp.core.utils.sys') as mocked_sys:
-
- # GIVEN: The system is Linux
- mocked_sys.platform = 'win32'
-
- # WHEN: We call _get_user_agent()
- user_agent = _get_user_agent()
-
- # THEN: The user agent is a Linux (or ChromeOS) user agent
- self.assertIn('Windows', user_agent, 'The user agent should be a valid Windows user agent')
-
- def get_user_agent_macos_test(self):
- """
- Test that getting a user agent on OS X returns a user agent suitable for OS X
- """
- with patch('openlp.core.utils.sys') as mocked_sys:
-
- # GIVEN: The system is Linux
- mocked_sys.platform = 'darwin'
-
- # WHEN: We call _get_user_agent()
- user_agent = _get_user_agent()
-
- # THEN: The user agent is a Linux (or ChromeOS) user agent
- self.assertIn('Mac OS X', user_agent, 'The user agent should be a valid OS X user agent')
-
- def get_user_agent_default_test(self):
- """
- Test that getting a user agent on a non-Linux/Windows/OS X platform returns the default user agent
- """
- with patch('openlp.core.utils.sys') as mocked_sys:
-
- # GIVEN: The system is Linux
- mocked_sys.platform = 'freebsd'
-
- # WHEN: We call _get_user_agent()
- user_agent = _get_user_agent()
-
- # THEN: The user agent is a Linux (or ChromeOS) user agent
- self.assertIn('NetBSD', user_agent, 'The user agent should be the default user agent')
-
- def get_web_page_no_url_test(self):
- """
- Test that sending a URL of None to the get_web_page method returns None
- """
- # GIVEN: A None url
- test_url = None
-
- # WHEN: We try to get the test URL
- result = get_web_page(test_url)
-
- # THEN: None should be returned
- self.assertIsNone(result, 'The return value of get_web_page should be None')
-
- def get_web_page_test(self):
- """
- Test that the get_web_page method works correctly
- """
- with patch('openlp.core.utils.urllib.request.Request') as MockRequest, \
- patch('openlp.core.utils.urllib.request.urlopen') as mock_urlopen, \
- patch('openlp.core.utils._get_user_agent') as mock_get_user_agent, \
- patch('openlp.core.utils.Registry') as MockRegistry:
- # GIVEN: Mocked out objects and a fake URL
- mocked_request_object = MagicMock()
- MockRequest.return_value = mocked_request_object
- mocked_page_object = MagicMock()
- mock_urlopen.return_value = mocked_page_object
- mock_get_user_agent.return_value = 'user_agent'
- fake_url = 'this://is.a.fake/url'
-
- # WHEN: The get_web_page() method is called
- returned_page = get_web_page(fake_url)
-
- # THEN: The correct methods are called with the correct arguments and a web page is returned
- MockRequest.assert_called_with(fake_url)
- mocked_request_object.add_header.assert_called_with('User-Agent', 'user_agent')
- self.assertEqual(1, mocked_request_object.add_header.call_count,
- 'There should only be 1 call to add_header')
- mock_get_user_agent.assert_called_with()
- mock_urlopen.assert_called_with(mocked_request_object, timeout=30)
- mocked_page_object.geturl.assert_called_with()
- self.assertEqual(0, MockRegistry.call_count, 'The Registry() object should have never been called')
- self.assertEqual(mocked_page_object, returned_page, 'The returned page should be the mock object')
-
- def get_web_page_with_header_test(self):
- """
- Test that adding a header to the call to get_web_page() adds the header to the request
- """
- with patch('openlp.core.utils.urllib.request.Request') as MockRequest, \
- patch('openlp.core.utils.urllib.request.urlopen') as mock_urlopen, \
- patch('openlp.core.utils._get_user_agent') as mock_get_user_agent:
- # GIVEN: Mocked out objects, a fake URL and a fake header
- mocked_request_object = MagicMock()
- MockRequest.return_value = mocked_request_object
- mocked_page_object = MagicMock()
- mock_urlopen.return_value = mocked_page_object
- mock_get_user_agent.return_value = 'user_agent'
- fake_url = 'this://is.a.fake/url'
- fake_header = ('Fake-Header', 'fake value')
-
- # WHEN: The get_web_page() method is called
- returned_page = get_web_page(fake_url, header=fake_header)
-
- # THEN: The correct methods are called with the correct arguments and a web page is returned
- MockRequest.assert_called_with(fake_url)
- mocked_request_object.add_header.assert_called_with(fake_header[0], fake_header[1])
- self.assertEqual(2, mocked_request_object.add_header.call_count,
- 'There should only be 2 calls to add_header')
- mock_get_user_agent.assert_called_with()
- mock_urlopen.assert_called_with(mocked_request_object, timeout=30)
- mocked_page_object.geturl.assert_called_with()
- self.assertEqual(mocked_page_object, returned_page, 'The returned page should be the mock object')
-
- def get_web_page_with_user_agent_in_headers_test(self):
- """
- Test that adding a user agent in the header when calling get_web_page() adds that user agent to the request
- """
- with patch('openlp.core.utils.urllib.request.Request') as MockRequest, \
- patch('openlp.core.utils.urllib.request.urlopen') as mock_urlopen, \
- patch('openlp.core.utils._get_user_agent') as mock_get_user_agent:
- # GIVEN: Mocked out objects, a fake URL and a fake header
- mocked_request_object = MagicMock()
- MockRequest.return_value = mocked_request_object
- mocked_page_object = MagicMock()
- mock_urlopen.return_value = mocked_page_object
- fake_url = 'this://is.a.fake/url'
- user_agent_header = ('User-Agent', 'OpenLP/2.2.0')
-
- # WHEN: The get_web_page() method is called
- returned_page = get_web_page(fake_url, header=user_agent_header)
-
- # THEN: The correct methods are called with the correct arguments and a web page is returned
- MockRequest.assert_called_with(fake_url)
- mocked_request_object.add_header.assert_called_with(user_agent_header[0], user_agent_header[1])
- self.assertEqual(1, mocked_request_object.add_header.call_count,
- 'There should only be 1 call to add_header')
- self.assertEqual(0, mock_get_user_agent.call_count, '_get_user_agent should not have been called')
- mock_urlopen.assert_called_with(mocked_request_object, timeout=30)
- mocked_page_object.geturl.assert_called_with()
- self.assertEqual(mocked_page_object, returned_page, 'The returned page should be the mock object')
-
- def get_web_page_update_openlp_test(self):
- """
- Test that passing "update_openlp" as true to get_web_page calls Registry().get('app').process_events()
- """
- with patch('openlp.core.utils.urllib.request.Request') as MockRequest, \
- patch('openlp.core.utils.urllib.request.urlopen') as mock_urlopen, \
- patch('openlp.core.utils._get_user_agent') as mock_get_user_agent, \
- patch('openlp.core.utils.Registry') as MockRegistry:
- # GIVEN: Mocked out objects, a fake URL
- mocked_request_object = MagicMock()
- MockRequest.return_value = mocked_request_object
- mocked_page_object = MagicMock()
- mock_urlopen.return_value = mocked_page_object
- mock_get_user_agent.return_value = 'user_agent'
- mocked_registry_object = MagicMock()
- mocked_application_object = MagicMock()
- mocked_registry_object.get.return_value = mocked_application_object
- MockRegistry.return_value = mocked_registry_object
- fake_url = 'this://is.a.fake/url'
-
- # WHEN: The get_web_page() method is called
- returned_page = get_web_page(fake_url, update_openlp=True)
-
- # THEN: The correct methods are called with the correct arguments and a web page is returned
- MockRequest.assert_called_with(fake_url)
- mocked_request_object.add_header.assert_called_with('User-Agent', 'user_agent')
- self.assertEqual(1, mocked_request_object.add_header.call_count,
- 'There should only be 1 call to add_header')
- mock_urlopen.assert_called_with(mocked_request_object, timeout=30)
- mocked_page_object.geturl.assert_called_with()
- mocked_registry_object.get.assert_called_with('application')
- mocked_application_object.process_events.assert_called_with()
- self.assertEqual(mocked_page_object, returned_page, 'The returned page should be the mock object')
=== modified file 'tests/functional/openlp_plugins/remotes/test_remotetab.py'
--- tests/functional/openlp_plugins/remotes/test_remotetab.py 2015-12-31 22:46:06 +0000
+++ tests/functional/openlp_plugins/remotes/test_remotetab.py 2016-04-05 20:26:45 +0000
@@ -99,7 +99,7 @@
"""
# GIVEN: A mocked location
with patch('openlp.core.common.Settings') as mocked_class, \
- patch('openlp.core.utils.AppLocation.get_directory') as mocked_get_directory, \
+ patch('openlp.core.common.applocation.AppLocation.get_directory') as mocked_get_directory, \
patch('openlp.core.common.check_directory_exists') as mocked_check_directory_exists, \
patch('openlp.core.common.applocation.os') as mocked_os:
# GIVEN: A mocked out Settings class and a mocked out AppLocation.get_directory()
@@ -127,7 +127,7 @@
"""
# GIVEN: A mocked location
with patch('openlp.core.common.Settings') as mocked_class, \
- patch('openlp.core.utils.AppLocation.get_directory') as mocked_get_directory, \
+ patch('openlp.core.common.applocation.AppLocation.get_directory') as mocked_get_directory, \
patch('openlp.core.common.check_directory_exists') as mocked_check_directory_exists, \
patch('openlp.core.common.applocation.os') as mocked_os:
# GIVEN: A mocked out Settings class and a mocked out AppLocation.get_directory()
=== added file 'tests/interfaces/openlp_core_common/test_utils.py'
--- tests/interfaces/openlp_core_common/test_utils.py 1970-01-01 00:00:00 +0000
+++ tests/interfaces/openlp_core_common/test_utils.py 2016-04-05 20:26:45 +0000
@@ -0,0 +1,81 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2016 OpenLP Developers #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it #
+# under the terms of the GNU General Public License as published by the Free #
+# Software Foundation; version 2 of the License. #
+# #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
+# more details. #
+# #
+# You should have received a copy of the GNU General Public License along #
+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
+###############################################################################
+"""
+Functional tests to test the AppLocation class and related methods.
+"""
+import os
+from unittest import TestCase
+
+from openlp.core.common import is_not_image_file
+from tests.utils.constants import TEST_RESOURCES_PATH
+from tests.helpers.testmixin import TestMixin
+
+
+class TestUtils(TestCase, TestMixin):
+ """
+ A test suite to test out various methods around the Utils functions.
+ """
+
+ def setUp(self):
+ """
+ Some pre-test setup required.
+ """
+ self.setup_application()
+
+ def is_not_image_empty_test(self):
+ """
+ Test the method handles an empty string
+ """
+ # Given and empty string
+ file_name = ""
+
+ # WHEN testing for it
+ result = is_not_image_file(file_name)
+
+ # THEN the result is false
+ assert result is True, 'The missing file test should return True'
+
+ def is_not_image_with_image_file_test(self):
+ """
+ Test the method handles an image file
+ """
+ # Given and empty string
+ file_name = os.path.join(TEST_RESOURCES_PATH, 'church.jpg')
+
+ # WHEN testing for it
+ result = is_not_image_file(file_name)
+
+ # THEN the result is false
+ assert result is False, 'The file is present so the test should return False'
+
+ def is_not_image_with_none_image_file_test(self):
+ """
+ Test the method handles a non image file
+ """
+ # Given and empty string
+ file_name = os.path.join(TEST_RESOURCES_PATH, 'serviceitem_custom_1.osj')
+
+ # WHEN testing for it
+ result = is_not_image_file(file_name)
+
+ # THEN the result is false
+ assert result is True, 'The file is not an image file so the test should return True'
=== removed directory 'tests/interfaces/openlp_core_utils'
=== removed file 'tests/interfaces/openlp_core_utils/__init__.py'
--- tests/interfaces/openlp_core_utils/__init__.py 2015-12-31 22:46:06 +0000
+++ tests/interfaces/openlp_core_utils/__init__.py 1970-01-01 00:00:00 +0000
@@ -1,21 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2016 OpenLP Developers #
-# --------------------------------------------------------------------------- #
-# This program is free software; you can redistribute it and/or modify it #
-# under the terms of the GNU General Public License as published by the Free #
-# Software Foundation; version 2 of the License. #
-# #
-# This program is distributed in the hope that it will be useful, but WITHOUT #
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
-# more details. #
-# #
-# You should have received a copy of the GNU General Public License along #
-# with this program; if not, write to the Free Software Foundation, Inc., 59 #
-# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
-###############################################################################
=== removed file 'tests/interfaces/openlp_core_utils/test_utils.py'
--- tests/interfaces/openlp_core_utils/test_utils.py 2015-12-31 22:46:06 +0000
+++ tests/interfaces/openlp_core_utils/test_utils.py 1970-01-01 00:00:00 +0000
@@ -1,81 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2016 OpenLP Developers #
-# --------------------------------------------------------------------------- #
-# This program is free software; you can redistribute it and/or modify it #
-# under the terms of the GNU General Public License as published by the Free #
-# Software Foundation; version 2 of the License. #
-# #
-# This program is distributed in the hope that it will be useful, but WITHOUT #
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
-# more details. #
-# #
-# You should have received a copy of the GNU General Public License along #
-# with this program; if not, write to the Free Software Foundation, Inc., 59 #
-# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
-###############################################################################
-"""
-Functional tests to test the AppLocation class and related methods.
-"""
-import os
-from unittest import TestCase
-
-from openlp.core.utils import is_not_image_file
-from tests.utils.constants import TEST_RESOURCES_PATH
-from tests.helpers.testmixin import TestMixin
-
-
-class TestUtils(TestCase, TestMixin):
- """
- A test suite to test out various methods around the Utils functions.
- """
-
- def setUp(self):
- """
- Some pre-test setup required.
- """
- self.setup_application()
-
- def is_not_image_empty_test(self):
- """
- Test the method handles an empty string
- """
- # Given and empty string
- file_name = ""
-
- # WHEN testing for it
- result = is_not_image_file(file_name)
-
- # THEN the result is false
- assert result is True, 'The missing file test should return True'
-
- def is_not_image_with_image_file_test(self):
- """
- Test the method handles an image file
- """
- # Given and empty string
- file_name = os.path.join(TEST_RESOURCES_PATH, 'church.jpg')
-
- # WHEN testing for it
- result = is_not_image_file(file_name)
-
- # THEN the result is false
- assert result is False, 'The file is present so the test should return False'
-
- def is_not_image_with_none_image_file_test(self):
- """
- Test the method handles a non image file
- """
- # Given and empty string
- file_name = os.path.join(TEST_RESOURCES_PATH, 'serviceitem_custom_1.osj')
-
- # WHEN testing for it
- result = is_not_image_file(file_name)
-
- # THEN the result is false
- assert result is True, 'The file is not an image file so the test should return True'
Follow ups