openlp-core team mailing list archive
-
openlp-core team
-
Mailing list archive
-
Message #25181
[Merge] lp:~tomasgroth/openlp/ftw-issues into lp:openlp
Tomas Groth has proposed merging lp:~tomasgroth/openlp/ftw-issues into lp:openlp.
Requested reviews:
Raoul Snyman (raoul-snyman)
Tim Bentley (trb143)
Related bugs:
Bug #1194622 in OpenLP: "[support-system] Traceback when importing bible with disabled bible plugin in FTW"
https://bugs.launchpad.net/openlp/+bug/1194622
Bug #1222944 in OpenLP: "Tracebacks in First Time Wizard with no internet"
https://bugs.launchpad.net/openlp/+bug/1222944
Bug #1390818 in OpenLP: "Handle connection errors in FTW gracefully"
https://bugs.launchpad.net/openlp/+bug/1390818
For more details, see:
https://code.launchpad.net/~tomasgroth/openlp/ftw-issues/+merge/242883
Made the FTW able to handle if the downloaded config file is invalid (part of bug 1222944).
Improved FTW handling of connection issues.
Update thememanager widget after theme import.
Close song db session after import to unlock file on windows, so they can be deleted.
Fix for importing old bible DBs, like KJV
Removed old pyinstaller hooks which has been moved to the packaging branch.
When bible or song plugin is disabled in FTW don't show download for those plugins in FTW. Fixes bug 1194622.
--
Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/core/lib/renderer.py'
--- openlp/core/lib/renderer.py 2014-11-20 06:58:33 +0000
+++ openlp/core/lib/renderer.py 2014-11-26 09:06:53 +0000
@@ -302,7 +302,7 @@
lines = text.strip('\n').split('\n')
pages.extend(self._paginate_slide(lines, line_end))
break
- count =+ 1
+ count += 1
else:
# Clean up line endings.
pages = self._paginate_slide(text.split('\n'), line_end)
=== modified file 'openlp/core/ui/firsttimeform.py'
--- openlp/core/ui/firsttimeform.py 2014-11-20 06:58:33 +0000
+++ openlp/core/ui/firsttimeform.py 2014-11-26 09:06:53 +0000
@@ -37,14 +37,15 @@
import urllib.parse
import urllib.error
from tempfile import gettempdir
-from configparser import ConfigParser
+from configparser import ConfigParser, MissingSectionHeaderError, NoSectionError, NoOptionError
from PyQt4 import QtCore, QtGui
from openlp.core.common import Registry, RegistryProperties, AppLocation, Settings, check_directory_exists, \
- translate, clean_button_text
+ translate, clean_button_text, trace_error_handler
from openlp.core.lib import PluginStatus, build_icon
-from openlp.core.utils import get_web_page
+from openlp.core.lib.ui import critical_error_message_box
+from openlp.core.utils import get_web_page, CONNECTION_RETRIES, CONNECTION_TIMEOUT
from .firsttimewizard import UiFirstTimeWizard, FirstTimePage
log = logging.getLogger(__name__)
@@ -89,27 +90,32 @@
super(FirstTimeForm, self).__init__(parent)
self.setup_ui(self)
+ def get_next_page_id(self):
+ """
+ Returns the id of the next FirstTimePage to go to based on enabled plugins
+ """
+ # The songs plugin is enabled
+ if FirstTimePage.Welcome < self.currentId() < FirstTimePage.Songs and self.songs_check_box.isChecked():
+ print('Go for songs! %r' % self.songs_check_box.isChecked())
+ return FirstTimePage.Songs
+ # The Bibles plugin is enabled
+ elif FirstTimePage.Welcome < self.currentId() < FirstTimePage.Bibles and self.bible_check_box.isChecked():
+ return FirstTimePage.Bibles
+ elif FirstTimePage.Welcome < self.currentId() < FirstTimePage.Themes:
+ return FirstTimePage.Themes
+ else:
+ return self.currentId() + 1
+
def nextId(self):
"""
Determine the next page in the Wizard to go to.
"""
self.application.process_events()
if self.currentId() == FirstTimePage.Plugins:
- if self.has_run_wizard:
- self.songs_check_box.setChecked(self.plugin_manager.get_plugin_by_name('songs').is_active())
- self.bible_check_box.setChecked(self.plugin_manager.get_plugin_by_name('bibles').is_active())
- self.presentation_check_box.setChecked(self.plugin_manager.get_plugin_by_name(
- 'presentations').is_active())
- self.image_check_box.setChecked(self.plugin_manager.get_plugin_by_name('images').is_active())
- self.media_check_box.setChecked(self.plugin_manager.get_plugin_by_name('media').is_active())
- self.remote_check_box.setChecked(self.plugin_manager.get_plugin_by_name('remotes').is_active())
- self.custom_check_box.setChecked(self.plugin_manager.get_plugin_by_name('custom').is_active())
- self.song_usage_check_box.setChecked(self.plugin_manager.get_plugin_by_name('songusage').is_active())
- self.alert_check_box.setChecked(self.plugin_manager.get_plugin_by_name('alerts').is_active())
if not self.web_access:
return FirstTimePage.NoInternet
else:
- return FirstTimePage.Songs
+ return self.get_next_page_id()
elif self.currentId() == FirstTimePage.Progress:
return -1
elif self.currentId() == FirstTimePage.NoInternet:
@@ -124,7 +130,7 @@
self.application.set_normal_cursor()
return FirstTimePage.Defaults
else:
- return self.currentId() + 1
+ return self.get_next_page_id()
def exec_(self):
"""
@@ -141,17 +147,23 @@
"""
self.screens = screens
# check to see if we have web access
+ self.web_access = False
self.web = 'http://openlp.org/files/frw/'
self.config = ConfigParser()
user_agent = 'OpenLP/' + Registry().get('application').applicationVersion()
- self.web_access = get_web_page('%s%s' % (self.web, 'download.cfg'), header=('User-Agent', user_agent))
- if self.web_access:
- files = self.web_access.read()
- self.config.read_string(files.decode())
- self.web = self.config.get('general', 'base url')
- self.songs_url = self.web + self.config.get('songs', 'directory') + '/'
- self.bibles_url = self.web + self.config.get('bibles', 'directory') + '/'
- self.themes_url = self.web + self.config.get('themes', 'directory') + '/'
+ web_config = get_web_page('%s%s' % (self.web, 'download.cfg'), header=('User-Agent', user_agent))
+ if web_config:
+ files = web_config.read()
+ try:
+ self.config.read_string(files.decode())
+ self.web = self.config.get('general', 'base url')
+ self.songs_url = self.web + self.config.get('songs', 'directory') + '/'
+ self.bibles_url = self.web + self.config.get('bibles', 'directory') + '/'
+ self.themes_url = self.web + self.config.get('themes', 'directory') + '/'
+ self.web_access = True
+ except (NoSectionError, NoOptionError, MissingSectionHeaderError):
+ log.debug('A problem occured while parsing the downloaded config file')
+ trace_error_handler(log)
self.update_screen_list_combo()
self.was_download_cancelled = False
self.theme_screenshot_thread = None
@@ -171,6 +183,17 @@
self.no_internet_finish_button.setVisible(False)
# Check if this is a re-run of the wizard.
self.has_run_wizard = Settings().value('core/has run wizard')
+ if self.has_run_wizard:
+ self.songs_check_box.setChecked(self.plugin_manager.get_plugin_by_name('songs').is_active())
+ self.bible_check_box.setChecked(self.plugin_manager.get_plugin_by_name('bibles').is_active())
+ self.presentation_check_box.setChecked(self.plugin_manager.get_plugin_by_name('presentations').is_active())
+ self.image_check_box.setChecked(self.plugin_manager.get_plugin_by_name('images').is_active())
+ self.media_check_box.setChecked(self.plugin_manager.get_plugin_by_name('media').is_active())
+ self.remote_check_box.setChecked(self.plugin_manager.get_plugin_by_name('remotes').is_active())
+ self.custom_check_box.setChecked(self.plugin_manager.get_plugin_by_name('custom').is_active())
+ self.song_usage_check_box.setChecked(self.plugin_manager.get_plugin_by_name('songusage').is_active())
+ self.alert_check_box.setChecked(self.plugin_manager.get_plugin_by_name('alerts').is_active())
+ self.application.set_normal_cursor()
# Sort out internet access for downloads
if self.web_access:
songs = self.config.get('songs', 'languages')
@@ -200,7 +223,6 @@
# Download the theme screenshots.
self.theme_screenshot_thread = ThemeScreenshotThread(self)
self.theme_screenshot_thread.start()
- self.application.set_normal_cursor()
def update_screen_list_combo(self):
"""
@@ -286,24 +308,42 @@
def url_get_file(self, url, f_path):
""""
Download a file given a URL. The file is retrieved in chunks, giving the ability to cancel the download at any
- point.
+ point. Returns False on download error.
+
+ :param url: URL to download
+ :param f_path: Destination file
"""
block_count = 0
block_size = 4096
- url_file = urllib.request.urlopen(url)
- filename = open(f_path, "wb")
- # Download until finished or canceled.
- while not self.was_download_cancelled:
- data = url_file.read(block_size)
- if not data:
- break
- filename.write(data)
- block_count += 1
- self._download_progress(block_count, block_size)
- filename.close()
+ retries = 0
+ while True:
+ try:
+ url_file = urllib.request.urlopen(url, timeout=CONNECTION_TIMEOUT)
+ filename = open(f_path, "wb")
+ # Download until finished or canceled.
+ while not self.was_download_cancelled:
+ data = url_file.read(block_size)
+ if not data:
+ break
+ filename.write(data)
+ block_count += 1
+ self._download_progress(block_count, block_size)
+ filename.close()
+ except ConnectionError:
+ trace_error_handler(log)
+ filename.close()
+ os.remove(f_path)
+ if retries > CONNECTION_RETRIES:
+ return False
+ else:
+ retries += 1
+ time.sleep(0.1)
+ continue
+ break
# Delete file if cancelled, it may be a partial file.
if self.was_download_cancelled:
os.remove(f_path)
+ return True
def _build_theme_screenshots(self):
"""
@@ -322,9 +362,19 @@
:param url: The URL of the file we want to download.
"""
- site = urllib.request.urlopen(url)
- meta = site.info()
- return int(meta.get("Content-Length"))
+ retries = 0
+ while True:
+ try:
+ site = urllib.request.urlopen(url, timeout=CONNECTION_TIMEOUT)
+ meta = site.info()
+ return int(meta.get("Content-Length"))
+ except ConnectionException:
+ if retries > CONNECTION_RETRIES:
+ raise
+ else:
+ retries += 1
+ time.sleep(0.1)
+ continue
def _download_progress(self, count, block_size):
"""
@@ -354,32 +404,41 @@
self.max_progress = 0
self.finish_button.setVisible(False)
self.application.process_events()
- # Loop through the songs list and increase for each selected item
- for i in range(self.songs_list_widget.count()):
- self.application.process_events()
- item = self.songs_list_widget.item(i)
- if item.checkState() == QtCore.Qt.Checked:
- filename = item.data(QtCore.Qt.UserRole)
- size = self._get_file_size('%s%s' % (self.songs_url, filename))
- self.max_progress += size
- # Loop through the Bibles list and increase for each selected item
- iterator = QtGui.QTreeWidgetItemIterator(self.bibles_tree_widget)
- while iterator.value():
- self.application.process_events()
- item = iterator.value()
- if item.parent() and item.checkState(0) == QtCore.Qt.Checked:
- filename = item.data(0, QtCore.Qt.UserRole)
- size = self._get_file_size('%s%s' % (self.bibles_url, filename))
- self.max_progress += size
- iterator += 1
- # Loop through the themes list and increase for each selected item
- for i in range(self.themes_list_widget.count()):
- self.application.process_events()
- item = self.themes_list_widget.item(i)
- if item.checkState() == QtCore.Qt.Checked:
- filename = item.data(QtCore.Qt.UserRole)
- size = self._get_file_size('%s%s' % (self.themes_url, filename))
- self.max_progress += size
+ try:
+ # Loop through the songs list and increase for each selected item
+ for i in range(self.songs_list_widget.count()):
+ self.application.process_events()
+ item = self.songs_list_widget.item(i)
+ if item.checkState() == QtCore.Qt.Checked:
+ filename = item.data(QtCore.Qt.UserRole)
+ size = self._get_file_size('%s%s' % (self.songs_url, filename))
+ self.max_progress += size
+ # Loop through the Bibles list and increase for each selected item
+ iterator = QtGui.QTreeWidgetItemIterator(self.bibles_tree_widget)
+ while iterator.value():
+ self.application.process_events()
+ item = iterator.value()
+ if item.parent() and item.checkState(0) == QtCore.Qt.Checked:
+ filename = item.data(0, QtCore.Qt.UserRole)
+ size = self._get_file_size('%s%s' % (self.bibles_url, filename))
+ self.max_progress += size
+ iterator += 1
+ # Loop through the themes list and increase for each selected item
+ for i in range(self.themes_list_widget.count()):
+ self.application.process_events()
+ item = self.themes_list_widget.item(i)
+ if item.checkState() == QtCore.Qt.Checked:
+ filename = item.data(QtCore.Qt.UserRole)
+ size = self._get_file_size('%s%s' % (self.themes_url, filename))
+ self.max_progress += size
+ except ConnectionError:
+ trace_error_handler(log)
+ critical_error_message_box(translate('OpenLP.FirstTimeWizard', 'Download Error'),
+ translate('OpenLP.FirstTimeWizard', 'There was a connection problem during '
+ 'download, so further downloads will be skipped. Try to re-run the '
+ 'First Time Wizard later.'))
+ self.max_progress = 0
+ self.web_access = None
if self.max_progress:
# Add on 2 for plugins status setting plus a "finished" point.
self.max_progress += 2
@@ -443,38 +502,11 @@
self._set_plugin_status(self.song_usage_check_box, 'songusage/status')
self._set_plugin_status(self.alert_check_box, 'alerts/status')
if self.web_access:
- # Build directories for downloads
- songs_destination = os.path.join(gettempdir(), 'openlp')
- bibles_destination = AppLocation.get_section_data_path('bibles')
- themes_destination = AppLocation.get_section_data_path('themes')
- # Download songs
- for i in range(self.songs_list_widget.count()):
- item = self.songs_list_widget.item(i)
- if item.checkState() == QtCore.Qt.Checked:
- filename = item.data(QtCore.Qt.UserRole)
- self._increment_progress_bar(self.downloading % filename, 0)
- self.previous_size = 0
- destination = os.path.join(songs_destination, str(filename))
- self.url_get_file('%s%s' % (self.songs_url, filename), destination)
- # Download Bibles
- bibles_iterator = QtGui.QTreeWidgetItemIterator(
- self.bibles_tree_widget)
- while bibles_iterator.value():
- item = bibles_iterator.value()
- if item.parent() and item.checkState(0) == QtCore.Qt.Checked:
- bible = item.data(0, QtCore.Qt.UserRole)
- self._increment_progress_bar(self.downloading % bible, 0)
- self.previous_size = 0
- self.url_get_file('%s%s' % (self.bibles_url, bible), os.path.join(bibles_destination, bible))
- bibles_iterator += 1
- # Download themes
- for i in range(self.themes_list_widget.count()):
- item = self.themes_list_widget.item(i)
- if item.checkState() == QtCore.Qt.Checked:
- theme = item.data(QtCore.Qt.UserRole)
- self._increment_progress_bar(self.downloading % theme, 0)
- self.previous_size = 0
- self.url_get_file('%s%s' % (self.themes_url, theme), os.path.join(themes_destination, theme))
+ if not self._download_selected():
+ critical_error_message_box(translate('OpenLP.FirstTimeWizard', 'Download Error'),
+ translate('OpenLP.FirstTimeWizard', 'There was a connection problem while '
+ 'downloading, so further downloads will be skipped. Try to re-run '
+ 'the First Time Wizard later.'))
# Set Default Display
if self.display_combo_box.currentIndex() != -1:
Settings().setValue('core/monitor', self.display_combo_box.currentIndex())
@@ -483,6 +515,46 @@
if self.theme_combo_box.currentIndex() != -1:
Settings().setValue('themes/global theme', self.theme_combo_box.currentText())
+ def _download_selected(self):
+ """
+ Download selected songs, bibles and themes. Returns False on download error
+ """
+ # Build directories for downloads
+ songs_destination = os.path.join(gettempdir(), 'openlp')
+ bibles_destination = AppLocation.get_section_data_path('bibles')
+ themes_destination = AppLocation.get_section_data_path('themes')
+ # Download songs
+ for i in range(self.songs_list_widget.count()):
+ item = self.songs_list_widget.item(i)
+ if item.checkState() == QtCore.Qt.Checked:
+ filename = item.data(QtCore.Qt.UserRole)
+ self._increment_progress_bar(self.downloading % filename, 0)
+ self.previous_size = 0
+ destination = os.path.join(songs_destination, str(filename))
+ if not self.url_get_file('%s%s' % (self.songs_url, filename), destination):
+ return False
+ # Download Bibles
+ bibles_iterator = QtGui.QTreeWidgetItemIterator(self.bibles_tree_widget)
+ while bibles_iterator.value():
+ item = bibles_iterator.value()
+ if item.parent() and item.checkState(0) == QtCore.Qt.Checked:
+ bible = item.data(0, QtCore.Qt.UserRole)
+ self._increment_progress_bar(self.downloading % bible, 0)
+ self.previous_size = 0
+ if not self.url_get_file('%s%s' % (self.bibles_url, bible), os.path.join(bibles_destination, bible)):
+ return False
+ bibles_iterator += 1
+ # Download themes
+ for i in range(self.themes_list_widget.count()):
+ item = self.themes_list_widget.item(i)
+ if item.checkState() == QtCore.Qt.Checked:
+ theme = item.data(QtCore.Qt.UserRole)
+ self._increment_progress_bar(self.downloading % theme, 0)
+ self.previous_size = 0
+ if not self.url_get_file('%s%s' % (self.themes_url, theme), os.path.join(themes_destination, theme)):
+ return False
+ return True
+
def _set_plugin_status(self, field, tag):
"""
Set the status of a plugin.
=== modified file 'openlp/core/ui/mainwindow.py'
--- openlp/core/ui/mainwindow.py 2014-11-13 20:15:43 +0000
+++ openlp/core/ui/mainwindow.py 2014-11-26 09:06:53 +0000
@@ -706,7 +706,10 @@
self.active_plugin.toggle_status(PluginStatus.Inactive)
# Set global theme and
Registry().execute('theme_update_global')
+ # Load the themes from files
self.theme_manager_contents.load_first_time_themes()
+ # Update the theme widget
+ self.theme_manager_contents.load_themes()
# Check if any Bibles downloaded. If there are, they will be processed.
Registry().execute('bibles_load_list', True)
self.application.set_normal_cursor()
=== modified file 'openlp/core/utils/__init__.py'
--- openlp/core/utils/__init__.py 2014-10-22 20:47:47 +0000
+++ openlp/core/utils/__init__.py 2014-11-26 09:06:53 +0000
@@ -35,6 +35,7 @@
import locale
import os
import re
+import time
from subprocess import Popen, PIPE
import sys
import urllib.request
@@ -91,6 +92,8 @@
'Mozilla/5.0 (X11; NetBSD amd64; rv:18.0) Gecko/20130120 Firefox/18.0'
]
}
+CONNECTION_TIMEOUT = 30
+CONNECTION_RETRIES = 2
class VersionThread(QtCore.QThread):
@@ -250,10 +253,19 @@
req = urllib.request.Request('http://www.openlp.org/files/version.txt')
req.add_header('User-Agent', 'OpenLP/%s' % current_version['full'])
remote_version = None
- try:
- remote_version = str(urllib.request.urlopen(req, None).read().decode()).strip()
- except IOError:
- log.exception('Failed to download the latest OpenLP version file')
+ retries = 0
+ while True:
+ try:
+ remote_version = str(urllib.request.urlopen(req, None,
+ timeout=CONNECTION_TIMEOUT).read().decode()).strip()
+ except ConnectionException:
+ 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
@@ -389,11 +401,19 @@
req.add_header(header[0], header[1])
page = None
log.debug('Downloading URL = %s' % url)
- try:
- page = urllib.request.urlopen(req)
- log.debug('Downloaded URL = %s' % page.geturl())
- except urllib.error.URLError:
- log.exception('The web page could not be downloaded')
+ retries = 0
+ while True:
+ try:
+ page = urllib.request.urlopen(req, timeout=CONNECTION_TIMEOUT)
+ log.debug('Downloaded URL = %s' % page.geturl())
+ except (urllib.error.URLError, ConnectionError):
+ if retries > CONNECTION_RETRIES:
+ log.exception('The web page could not be downloaded')
+ raise
+ else:
+ time.sleep(0.1)
+ continue
+ break
if not page:
return None
if update_openlp:
=== modified file 'openlp/plugins/bibles/bibleplugin.py'
--- openlp/plugins/bibles/bibleplugin.py 2014-04-12 20:19:22 +0000
+++ openlp/plugins/bibles/bibleplugin.py 2014-11-26 09:06:53 +0000
@@ -159,7 +159,7 @@
self.upgrade_wizard = BibleUpgradeForm(self.main_window, self.manager, self)
# If the import was not cancelled then reload.
if self.upgrade_wizard.exec_():
- self.media_item.reloadBibles()
+ self.media_item.reload_bibles()
def on_bible_import_click(self):
if self.media_item:
=== modified file 'openlp/plugins/bibles/lib/db.py'
--- openlp/plugins/bibles/lib/db.py 2014-05-02 06:42:17 +0000
+++ openlp/plugins/bibles/lib/db.py 2014-11-26 09:06:53 +0000
@@ -170,6 +170,9 @@
Returns the version name of the Bible.
"""
version_name = self.get_object(BibleMeta, 'name')
+ # Fallback to old way of naming
+ if not version_name:
+ version_name = self.get_object(BibleMeta, 'Version')
self.name = version_name.value if version_name else None
return self.name
@@ -969,11 +972,15 @@
"""
Returns the version name of the Bible.
"""
+ self.name = None
version_name = self.run_sql('SELECT value FROM metadata WHERE key = "name"')
if version_name:
self.name = version_name[0][0]
else:
- self.name = None
+ # Fallback to old way of naming
+ version_name = self.run_sql('SELECT value FROM metadata WHERE key = "Version"')
+ if version_name:
+ self.name = version_name[0][0]
return self.name
def get_metadata(self):
=== modified file 'openlp/plugins/songs/lib/importers/openlp.py'
--- openlp/plugins/songs/lib/importers/openlp.py 2014-07-04 09:35:10 +0000
+++ openlp/plugins/songs/lib/importers/openlp.py 2014-11-26 09:06:53 +0000
@@ -217,4 +217,5 @@
self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % new_song.title)
if self.stop_import_flag:
break
+ self.source_session.close()
engine.dispose()
=== removed directory 'resources/pyinstaller'
=== removed file 'resources/pyinstaller/hook-openlp.core.ui.media.py'
--- resources/pyinstaller/hook-openlp.core.ui.media.py 2013-12-24 08:56:50 +0000
+++ resources/pyinstaller/hook-openlp.core.ui.media.py 1970-01-01 00:00:00 +0000
@@ -1,32 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2014 Raoul Snyman #
-# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
-# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
-# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
-# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
-# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
-# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
-# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
-# --------------------------------------------------------------------------- #
-# This program is 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 #
-###############################################################################
-
-hiddenimports = ['openlp.core.ui.media.phononplayer',
- 'openlp.core.ui.media.vlcplayer',
- 'openlp.core.ui.media.webkitplayer']
=== removed file 'resources/pyinstaller/hook-openlp.plugins.presentations.presentationplugin.py'
--- resources/pyinstaller/hook-openlp.plugins.presentations.presentationplugin.py 2013-12-29 19:47:54 +0000
+++ resources/pyinstaller/hook-openlp.plugins.presentations.presentationplugin.py 1970-01-01 00:00:00 +0000
@@ -1,33 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2014 Raoul Snyman #
-# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
-# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
-# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
-# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
-# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
-# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
-# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
-# --------------------------------------------------------------------------- #
-# This program is 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 #
-###############################################################################
-
-hiddenimports = ['openlp.plugins.presentations.lib.impresscontroller',
- 'openlp.plugins.presentations.lib.powerpointcontroller',
- 'openlp.plugins.presentations.lib.pptviewcontroller',
- 'openlp.plugins.presentations.lib.pdfcontroller']
=== removed file 'resources/pyinstaller/hook-openlp.py'
--- resources/pyinstaller/hook-openlp.py 2013-12-24 08:56:50 +0000
+++ resources/pyinstaller/hook-openlp.py 1970-01-01 00:00:00 +0000
@@ -1,38 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2014 Raoul Snyman #
-# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
-# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
-# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
-# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
-# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
-# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
-# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
-# --------------------------------------------------------------------------- #
-# This program is 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 #
-###############################################################################
-
-hiddenimports = ['plugins.songs.songsplugin',
- 'plugins.bibles.bibleplugin',
- 'plugins.presentations.presentationplugin',
- 'plugins.media.mediaplugin',
- 'plugins.images.imageplugin',
- 'plugins.custom.customplugin',
- 'plugins.songusage.songusageplugin',
- 'plugins.remotes.remoteplugin',
- 'plugins.alerts.alertsplugin']
=== modified file 'tests/functional/openlp_core_ui/test_firsttimeform.py'
--- tests/functional/openlp_core_ui/test_firsttimeform.py 2014-10-22 20:43:05 +0000
+++ tests/functional/openlp_core_ui/test_firsttimeform.py 2014-11-26 09:06:53 +0000
@@ -49,6 +49,22 @@
directory = themes
"""
+FAKE_BROKEN_CONFIG = b"""
+[general]
+base url = http://example.com/frw/
+[songs]
+directory = songs
+[bibles]
+directory = bibles
+"""
+
+FAKE_INVALID_CONFIG = b"""
+<html>
+<head><title>This is not a config file</title></head>
+<body>Some text</body>
+</html>
+"""
+
class TestFirstTimeForm(TestCase, TestMixin):
@@ -104,3 +120,33 @@
self.assertEqual(expected_songs_url, first_time_form.songs_url, 'The songs URL should be correct')
self.assertEqual(expected_bibles_url, first_time_form.bibles_url, 'The bibles URL should be correct')
self.assertEqual(expected_themes_url, first_time_form.themes_url, 'The themes URL should be correct')
+
+ def broken_config_test(self):
+ """
+ Test if we can handle an config file with missing data
+ """
+ # GIVEN: A mocked get_web_page, a First Time Wizard, an expected screen object, and a mocked broken config file
+ with patch('openlp.core.ui.firsttimeform.get_web_page') as mocked_get_web_page:
+ first_time_form = FirstTimeForm(None)
+ mocked_get_web_page.return_value.read.return_value = FAKE_BROKEN_CONFIG
+
+ # WHEN: The First Time Wizard is initialised
+ first_time_form.initialize(MagicMock())
+
+ # THEN: The First Time Form should not have web access
+ self.assertFalse(first_time_form.web_access, 'There should not be web access with a broken config file')
+
+ def invalid_config_test(self):
+ """
+ Test if we can handle an config file in invalid format
+ """
+ # GIVEN: A mocked get_web_page, a First Time Wizard, an expected screen object, and a mocked invalid config file
+ with patch('openlp.core.ui.firsttimeform.get_web_page') as mocked_get_web_page:
+ first_time_form = FirstTimeForm(None)
+ mocked_get_web_page.return_value.read.return_value = FAKE_INVALID_CONFIG
+
+ # WHEN: The First Time Wizard is initialised
+ first_time_form.initialize(MagicMock())
+
+ # THEN: The First Time Form should not have web access
+ self.assertFalse(first_time_form.web_access, 'There should not be web access with an invalid config file')
=== modified file 'tests/functional/openlp_core_utils/test_utils.py'
--- tests/functional/openlp_core_utils/test_utils.py 2014-05-02 06:42:17 +0000
+++ tests/functional/openlp_core_utils/test_utils.py 2014-11-26 09:06:53 +0000
@@ -335,7 +335,7 @@
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)
+ 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')
@@ -365,7 +365,7 @@
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)
+ 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')
@@ -393,7 +393,7 @@
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)
+ 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')
@@ -425,7 +425,7 @@
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)
+ 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()
Follow ups