← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~phill-ridout/openlp/TODOne into lp:openlp

 

Phill has proposed merging lp:~phill-ridout/openlp/TODOne into lp:openlp.

Requested reviews:
  OpenLP Core (openlp-core)

For more details, see:
https://code.launchpad.net/~phill-ridout/openlp/TODOne/+merge/324815

I've TODOne some of the TODO's. As well as some other clean ups

lp:~phill-ridout/openlp/TODOne (revision 2742)
[SUCCESS] https://ci.openlp.io/job/Branch-01-Pull/2039/
[SUCCESS] https://ci.openlp.io/job/Branch-02-Functional-Tests/1949/
[SUCCESS] https://ci.openlp.io/job/Branch-03-Interface-Tests/1878/
[SUCCESS] https://ci.openlp.io/job/Branch-04a-Code_Analysis/1258/
[SUCCESS] https://ci.openlp.io/job/Branch-04b-Test_Coverage/1109/
[SUCCESS] https://ci.openlp.io/job/Branch-04c-Code_Analysis2/238/
[FAILURE] https://ci.openlp.io/job/Branch-05-AppVeyor-Tests/84/
Stopping after failure
-- 
Your team OpenLP Core is requested to review the proposed merge of lp:~phill-ridout/openlp/TODOne into lp:openlp.
=== modified file 'openlp/core/__init__.py'
--- openlp/core/__init__.py	2017-04-11 08:05:13 +0000
+++ openlp/core/__init__.py	2017-05-30 20:33:49 +0000
@@ -251,8 +251,7 @@
             if QtWidgets.QMessageBox.question(None, translate('OpenLP', 'Backup'),
                                               translate('OpenLP', 'OpenLP has been upgraded, do you want to create\n'
                                                                   'a backup of the old data folder?'),
-                                              QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
-                                              QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.Yes:
+                                              defaultButton=QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.Yes:
                 # Create copy of data folder
                 data_folder_path = AppLocation.get_data_path()
                 timestamp = time.strftime("%Y%m%d-%H%M%S")

=== modified file 'openlp/core/common/languagemanager.py'
--- openlp/core/common/languagemanager.py	2017-03-28 00:36:54 +0000
+++ openlp/core/common/languagemanager.py	2017-05-30 20:33:49 +0000
@@ -140,8 +140,8 @@
             reg_ex = QtCore.QRegExp("^.*i18n/(.*).qm")
             if reg_ex.exactMatch(qmf):
                 name = '{regex}'.format(regex=reg_ex.cap(1))
-                # TODO: Test before converting to python3 string format
-                LanguageManager.__qm_list__['%#2i %s' % (counter + 1, LanguageManager.language_name(qmf))] = name
+                LanguageManager.__qm_list__[
+                    '{count:>2i} {name}'.format(count=counter + 1, name=LanguageManager.language_name(qmf))] = name
 
     @staticmethod
     def get_qm_list():

=== modified file 'openlp/core/common/uistrings.py'
--- openlp/core/common/uistrings.py	2017-01-08 19:12:12 +0000
+++ openlp/core/common/uistrings.py	2017-05-30 20:33:49 +0000
@@ -154,8 +154,6 @@
         self.Split = translate('OpenLP.Ui', 'Optional &Split')
         self.SplitToolTip = translate('OpenLP.Ui',
                                       'Split a slide into two only if it does not fit on the screen as one slide.')
-        # TODO: WHERE is this used at? cannot find where it's used at in code.
-        self.StartTimeCode = translate('OpenLP.Ui', 'Start {code}')
         self.StopPlaySlidesInLoop = translate('OpenLP.Ui', 'Stop Play Slides in Loop')
         self.StopPlaySlidesToEnd = translate('OpenLP.Ui', 'Stop Play Slides to End')
         self.Theme = translate('OpenLP.Ui', 'Theme', 'Singular')

=== modified file 'openlp/core/lib/exceptions.py'
--- openlp/core/lib/exceptions.py	2016-12-31 11:01:36 +0000
+++ openlp/core/lib/exceptions.py	2017-05-30 20:33:49 +0000
@@ -24,7 +24,6 @@
 """
 
 
-# TODO: Test  __init__ & __str__
 class ValidationError(Exception):
     """
     The :class:`~openlp.core.lib.exceptions.ValidationError` exception provides a custom exception for validating

=== modified file 'openlp/core/lib/imagemanager.py'
--- openlp/core/lib/imagemanager.py	2016-12-31 11:01:36 +0000
+++ openlp/core/lib/imagemanager.py	2017-05-30 20:33:49 +0000
@@ -110,6 +110,8 @@
         :param width: The width of the image, defaults to -1 meaning that the screen width will be used.
         :param height: The height of the image, defaults to -1 meaning that the screen height will be used.
         """
+        if not os.path.exists(path):
+            raise FileNotFoundError('{path} not found'.format(path=path))
         self.path = path
         self.image = None
         self.image_bytes = None
@@ -119,9 +121,7 @@
         self.timestamp = 0
         self.width = width
         self.height = height
-        # FIXME: We assume that the path exist. The caller has to take care that it exists!
-        if os.path.exists(path):
-            self.timestamp = os.stat(path).st_mtime
+        self.timestamp = os.stat(path).st_mtime
         self.secondary_priority = Image.secondary_priority
         Image.secondary_priority += 1
 

=== modified file 'openlp/core/ui/advancedtab.py'
--- openlp/core/ui/advancedtab.py	2017-05-22 18:22:43 +0000
+++ openlp/core/ui/advancedtab.py	2017-05-30 20:33:49 +0000
@@ -495,9 +495,7 @@
                                                           'location of the OpenLP data directory to:\n\n{path}'
                                                           '\n\nThe data directory will be changed when OpenLP is '
                                                           'closed.').format(path=new_data_path),
-                                                QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes |
-                                                                                      QtWidgets.QMessageBox.No),
-                                                QtWidgets.QMessageBox.No)
+                                                defaultButton=QtWidgets.QMessageBox.No)
         if answer != QtWidgets.QMessageBox.Yes:
             self.data_directory_path_edit.path = AppLocation.get_data_path()
             return

=== modified file 'openlp/core/ui/firsttimeform.py'
--- openlp/core/ui/firsttimeform.py	2016-12-31 11:01:36 +0000
+++ openlp/core/ui/firsttimeform.py	2017-05-30 20:33:49 +0000
@@ -206,7 +206,6 @@
                 trace_error_handler(log)
         self.update_screen_list_combo()
         self.application.process_events()
-        # TODO: Tested at home
         self.downloading = translate('OpenLP.FirstTimeWizard', 'Downloading {name}...')
         if self.has_run_wizard:
             self.songs_check_box.setChecked(self.plugin_manager.get_plugin_by_name('songs').is_active())
@@ -563,7 +562,6 @@
             item = self.songs_list_widget.item(i)
             if item.checkState() == QtCore.Qt.Checked:
                 filename, sha256 = item.data(QtCore.Qt.UserRole)
-                # TODO: Tested at home
                 self._increment_progress_bar(self.downloading.format(name=filename), 0)
                 self.previous_size = 0
                 destination = os.path.join(songs_destination, str(filename))
@@ -576,7 +574,6 @@
             item = bibles_iterator.value()
             if item.parent() and item.checkState(0) == QtCore.Qt.Checked:
                 bible, sha256 = item.data(0, QtCore.Qt.UserRole)
-                # TODO: Tested at home
                 self._increment_progress_bar(self.downloading.format(name=bible), 0)
                 self.previous_size = 0
                 if not url_get_file(self, '{path}{name}'.format(path=self.bibles_url, name=bible),
@@ -589,7 +586,6 @@
             item = self.themes_list_widget.item(i)
             if item.checkState() == QtCore.Qt.Checked:
                 theme, sha256 = item.data(QtCore.Qt.UserRole)
-                # TODO: Tested at home
                 self._increment_progress_bar(self.downloading.format(name=theme), 0)
                 self.previous_size = 0
                 if not url_get_file(self, '{path}{name}'.format(path=self.themes_url, name=theme),

=== modified file 'openlp/core/ui/formattingtagcontroller.py'
--- openlp/core/ui/formattingtagcontroller.py	2016-12-31 11:01:36 +0000
+++ openlp/core/ui/formattingtagcontroller.py	2017-05-30 20:33:49 +0000
@@ -130,8 +130,7 @@
                     elif not match.group('empty'):
                         end_tags.append(tag)
                 match = self.html_tag_regex.search(start_html, match.end())
-            # TODO: Verify format() works with lambda
-            return ''.join(map(lambda tag: '</%s>' % tag, reversed(end_tags)))
+            return ''.join(map(lambda tag: '</{tag}>'.format(tag=tag), reversed(end_tags)))
 
     def start_tag_changed(self, start_html, end_html):
         """

=== modified file 'openlp/core/ui/formattingtagform.py'
--- openlp/core/ui/formattingtagform.py	2016-12-31 11:01:36 +0000
+++ openlp/core/ui/formattingtagform.py	2017-05-30 20:33:49 +0000
@@ -122,8 +122,7 @@
                                                     self.tag_table_widget.item(count, 2).text(),
                                                     self.tag_table_widget.item(count, 3).text())
             if error:
-                QtWidgets.QMessageBox.warning(self, translate('OpenLP.FormattingTagForm', 'Validation Error'), error,
-                                              QtWidgets.QMessageBox.Ok)
+                QtWidgets.QMessageBox.warning(self, translate('OpenLP.FormattingTagForm', 'Validation Error'), error)
                 self.tag_table_widget.selectRow(count)
                 return
             count += 1
@@ -198,6 +197,5 @@
                 if tag:
                     self.tag_table_widget.setItem(pre_row, 3, QtWidgets.QTableWidgetItem(tag))
             if errors:
-                QtWidgets.QMessageBox.warning(self, translate('OpenLP.FormattingTagForm', 'Validation Error'), errors,
-                                              QtWidgets.QMessageBox.Ok)
+                QtWidgets.QMessageBox.warning(self, translate('OpenLP.FormattingTagForm', 'Validation Error'), errors)
             self.tag_table_widget.resizeRowsToContents()

=== modified file 'openlp/core/ui/lib/pathedit.py'
--- openlp/core/ui/lib/pathedit.py	2017-05-22 18:22:43 +0000
+++ openlp/core/ui/lib/pathedit.py	2017-05-30 20:33:49 +0000
@@ -46,16 +46,16 @@
 
         :param parent: The parent of the widget. This is just passed to the super method.
         :type parent: QWidget or None
-        
+
         :param dialog_caption: Used to customise the caption in the QFileDialog.
-        :param dialog_caption: str
-        
+        :type dialog_caption: str
+
         :param default_path: The default path. This is set as the path when the revert button is clicked
         :type default_path: str
 
         :param show_revert: Used to determin if the 'revert button' should be visible.
         :type show_revert: bool
-        
+
         :return: None
         :rtype: None
         """
@@ -72,7 +72,7 @@
         Set up the widget
         :param show_revert: Show or hide the revert button
         :type show_revert: bool
-        
+
         :return: None
         :rtype: None
         """

=== modified file 'openlp/core/ui/lib/wizard.py'
--- openlp/core/ui/lib/wizard.py	2016-12-31 11:01:36 +0000
+++ openlp/core/ui/lib/wizard.py	2017-05-30 20:33:49 +0000
@@ -50,13 +50,13 @@
     # These strings should need a good reason to be retranslated elsewhere.
     FinishedImport = translate('OpenLP.Ui', 'Finished import.')
     FormatLabel = translate('OpenLP.Ui', 'Format:')
-    HeaderStyle = '<span style="font-size:14pt; font-weight:600;">%s</span>'
+    HeaderStyle = '<span style="font-size:14pt; font-weight:600;">{text}</span>'
     Importing = translate('OpenLP.Ui', 'Importing')
-    ImportingType = translate('OpenLP.Ui', 'Importing "%s"...')
+    ImportingType = translate('OpenLP.Ui', 'Importing "{source}"...')
     ImportSelect = translate('OpenLP.Ui', 'Select Import Source')
     ImportSelectLong = translate('OpenLP.Ui', 'Select the import format and the location to import from.')
-    OpenTypeFile = translate('OpenLP.Ui', 'Open %s File')
-    OpenTypeFolder = translate('OpenLP.Ui', 'Open %s Folder')
+    OpenTypeFile = translate('OpenLP.Ui', 'Open {file_type} File')
+    OpenTypeFolder = translate('OpenLP.Ui', 'Open {folder_name} Folder')
     PercentSymbolFormat = translate('OpenLP.Ui', '%p%')
     Ready = translate('OpenLP.Ui', 'Ready.')
     StartingImport = translate('OpenLP.Ui', 'Starting import...')

=== modified file 'openlp/core/ui/mainwindow.py'
--- openlp/core/ui/mainwindow.py	2017-03-23 04:43:13 +0000
+++ openlp/core/ui/mainwindow.py	2017-05-30 20:33:49 +0000
@@ -920,8 +920,7 @@
         QtWidgets.QMessageBox.information(self, translate('OpenLP.MainWindow', 'Import settings'),
                                           translate('OpenLP.MainWindow',
                                                     'OpenLP will now close.  Imported settings will '
-                                                    'be applied the next time you start OpenLP.'),
-                                          QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Ok))
+                                                    'be applied the next time you start OpenLP.'))
         self.settings_imported = True
         self.clean_up()
         QtCore.QCoreApplication.exit()
@@ -1316,7 +1315,6 @@
         self.recent_files_menu.clear()
         for file_id, filename in enumerate(recent_files_to_display):
             log.debug('Recent file name: {name}'.format(name=filename))
-            # TODO: Should be good
             action = create_action(self, '',
                                    text='&{n} {name}'.format(n=file_id + 1,
                                                              name=os.path.splitext(os.path.basename(str(filename)))[0]),

=== modified file 'openlp/core/ui/media/mediacontroller.py'
--- openlp/core/ui/media/mediacontroller.py	2017-05-15 10:09:59 +0000
+++ openlp/core/ui/media/mediacontroller.py	2017-05-30 20:33:49 +0000
@@ -466,9 +466,10 @@
         player = self.media_players[used_players[0]]
         if suffix not in player.video_extensions_list and suffix not in player.audio_extensions_list:
             # Media could not be loaded correctly
-            critical_error_message_box(translate('MediaPlugin.MediaItem', 'Unsupported Media File'),
-                                       translate('MediaPlugin.MediaItem', 'File %s not supported using player %s') %
-                                       (service_item.get_frame_path(), used_players[0]))
+            critical_error_message_box(
+                translate('MediaPlugin.MediaItem', 'Unsupported Media File'),
+                translate('MediaPlugin.MediaItem', 'File {file_path} not supported using player {player_name}'
+                          ).format(file_path=service_item.get_frame_path(), player_name=used_players[0]))
             return False
         media_data = MediaInfoWrapper.parse(service_item.get_frame_path())
         # duration returns in milli seconds

=== modified file 'openlp/core/ui/pluginform.py'
--- openlp/core/ui/pluginform.py	2016-12-31 11:01:36 +0000
+++ openlp/core/ui/pluginform.py	2017-05-30 20:33:49 +0000
@@ -60,7 +60,6 @@
         self._clear_details()
         self.programatic_change = True
         plugin_list_width = 0
-        # TODO: Tested at home
         for plugin in self.plugin_manager.plugins:
             item = QtWidgets.QListWidgetItem(self.plugin_list_widget)
             # We do this just to make 100% sure the status is an integer as
@@ -137,7 +136,6 @@
             self.active_plugin.app_startup()
         else:
             self.active_plugin.toggle_status(PluginStatus.Inactive)
-        # TODO: Tested at home
         status_text = translate('OpenLP.PluginForm', '{name} (Inactive)')
         if self.active_plugin.status == PluginStatus.Active:
             status_text = translate('OpenLP.PluginForm', '{name} (Active)')

=== modified file 'openlp/core/ui/shortcutlistform.py'
--- openlp/core/ui/shortcutlistform.py	2016-12-31 11:01:36 +0000
+++ openlp/core/ui/shortcutlistform.py	2017-05-30 20:33:49 +0000
@@ -279,9 +279,7 @@
             return
         if QtWidgets.QMessageBox.question(self, translate('OpenLP.ShortcutListDialog', 'Restore Default Shortcuts'),
                                           translate('OpenLP.ShortcutListDialog', 'Do you want to restore all '
-                                                    'shortcuts to their defaults?'),
-                                          QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes |
-                                                                                QtWidgets.QMessageBox.No)
+                                                    'shortcuts to their defaults?')
                                           ) == QtWidgets.QMessageBox.No:
             return
         self._adjust_button(self.primary_push_button, False, text='')

=== modified file 'openlp/core/ui/thememanager.py'
--- openlp/core/ui/thememanager.py	2016-12-31 11:01:36 +0000
+++ openlp/core/ui/thememanager.py	2017-05-30 20:33:49 +0000
@@ -256,10 +256,9 @@
         Renames an existing theme to a new name
         :param field:
         """
-        # TODO: Check for delayed format() conversions
         if self._validate_theme_action(translate('OpenLP.ThemeManager', 'You must select a theme to rename.'),
                                        translate('OpenLP.ThemeManager', 'Rename Confirmation'),
-                                       translate('OpenLP.ThemeManager', 'Rename %s theme?'), False, False):
+                                       translate('OpenLP.ThemeManager', 'Rename {theme_name} theme?'), False, False):
             item = self.theme_list_widget.currentItem()
             old_theme_name = item.data(QtCore.Qt.UserRole)
             self.file_rename_form.file_name_edit.setText(old_theme_name)
@@ -333,10 +332,9 @@
         Delete a theme triggered by the UI.
         :param field:
         """
-        # TODO: Verify delayed format() conversions
         if self._validate_theme_action(translate('OpenLP.ThemeManager', 'You must select a theme to delete.'),
                                        translate('OpenLP.ThemeManager', 'Delete Confirmation'),
-                                       translate('OpenLP.ThemeManager', 'Delete %s theme?')):
+                                       translate('OpenLP.ThemeManager', 'Delete {theme_name} theme?')):
             item = self.theme_list_widget.currentItem()
             theme = item.text()
             row = self.theme_list_widget.row(item)
@@ -530,9 +528,7 @@
                                              translate('OpenLP.ThemeManager',
                                                        'Theme {name} already exists. '
                                                        'Do you want to replace it?').format(name=theme_name),
-                                             QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes |
-                                                                                   QtWidgets.QMessageBox.No),
-                                             QtWidgets.QMessageBox.No)
+                                             defaultButton=QtWidgets.QMessageBox.No)
         return ret == QtWidgets.QMessageBox.Yes
 
     def unzip_theme(self, file_name, directory):
@@ -748,9 +744,8 @@
             # confirm deletion
             if confirm:
                 answer = QtWidgets.QMessageBox.question(
-                    self, confirm_title, confirm_text % theme,
-                    QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No),
-                    QtWidgets.QMessageBox.No)
+                    self, confirm_title, confirm_text.format(theme_name=theme),
+                    defaultButton=QtWidgets.QMessageBox.No)
                 if answer == QtWidgets.QMessageBox.No:
                     return False
             # should be the same unless default

=== modified file 'openlp/plugins/alerts/alertsplugin.py'
--- openlp/plugins/alerts/alertsplugin.py	2016-12-31 11:01:36 +0000
+++ openlp/plugins/alerts/alertsplugin.py	2017-05-30 20:33:49 +0000
@@ -88,21 +88,20 @@
         }
     }
 """
-# TODO: Verify format() with variable templates
 CSS = """
-    #alert {
+    #alert {{
         position: absolute;
         left: 0px;
         top: 0px;
         z-index: 10;
-        width: 100%%;
-        vertical-align: %s;
-        font-family: %s;
-        font-size: %spt;
-        color: %s;
-        background-color: %s;
+        width: 100%;
+        vertical-align: {vertical_align};
+        font-family: {font_family};
+        font-size: {font_size:d}pt;
+        color: {color};
+        background-color: {background_color};
         word-wrap: break-word;
-    }
+    }}
 """
 
 HTML = """
@@ -228,8 +227,11 @@
         Add CSS to the main display.
         """
         align = VerticalType.Names[self.settings_tab.location]
-        return CSS % (align, self.settings_tab.font_face, self.settings_tab.font_size, self.settings_tab.font_color,
-                      self.settings_tab.background_color)
+        return CSS.format(vertical_align=align,
+                          font_family=self.settings_tab.font_face,
+                          font_size=self.settings_tab.font_size,
+                          color=self.settings_tab.font_color,
+                          background_color=self.settings_tab.background_color)
 
     @staticmethod
     def get_display_html():

=== modified file 'openlp/plugins/alerts/forms/alertform.py'
--- openlp/plugins/alerts/forms/alertform.py	2016-12-31 11:01:36 +0000
+++ openlp/plugins/alerts/forms/alertform.py	2017-05-30 20:33:49 +0000
@@ -180,9 +180,7 @@
                                            translate('AlertsPlugin.AlertForm', 'No Parameter Found'),
                                            translate('AlertsPlugin.AlertForm',
                                                      'You have not entered a parameter to be replaced.\n'
-                                                     'Do you want to continue anyway?'),
-                                           QtWidgets.QMessageBox.StandardButtons(
-                                               QtWidgets.QMessageBox.No | QtWidgets.QMessageBox.Yes)
+                                                     'Do you want to continue anyway?')
                                            ) == QtWidgets.QMessageBox.No:
             self.parameter_edit.setFocus()
             return False
@@ -193,9 +191,7 @@
                                            translate('AlertsPlugin.AlertForm', 'No Placeholder Found'),
                                            translate('AlertsPlugin.AlertForm',
                                                      'The alert text does not contain \'<>\'.\n'
-                                                     'Do you want to continue anyway?'),
-                                           QtWidgets.QMessageBox.StandardButtons(
-                                               QtWidgets.QMessageBox.No | QtWidgets.QMessageBox.Yes)
+                                                     'Do you want to continue anyway?')
                                            ) == QtWidgets.QMessageBox.No:
             self.parameter_edit.setFocus()
             return False

=== modified file 'openlp/plugins/bibles/forms/bibleimportform.py'
--- openlp/plugins/bibles/forms/bibleimportform.py	2017-05-12 21:05:50 +0000
+++ openlp/plugins/bibles/forms/bibleimportform.py	2017-05-30 20:33:49 +0000
@@ -421,8 +421,8 @@
         Allow for localisation of the bible import wizard.
         """
         self.setWindowTitle(translate('BiblesPlugin.ImportWizardForm', 'Bible Import Wizard'))
-        self.title_label.setText(WizardStrings.HeaderStyle % translate('OpenLP.Ui',
-                                                                       'Welcome to the Bible Import Wizard'))
+        self.title_label.setText(WizardStrings.HeaderStyle.format(text=translate('OpenLP.Ui',
+                                                                                 'Welcome to the Bible Import Wizard')))
         self.information_label.setText(
             translate('BiblesPlugin.ImportWizardForm',
                       'This wizard will help you to import Bibles from a variety of '

=== modified file 'openlp/plugins/bibles/lib/__init__.py'
--- openlp/plugins/bibles/lib/__init__.py	2017-02-18 07:23:15 +0000
+++ openlp/plugins/bibles/lib/__init__.py	2017-05-30 20:33:49 +0000
@@ -221,18 +221,16 @@
         REFERENCE_SEPARATORS['sep_{role}'.format(role=role)] = '\s*(?:{source})\s*'.format(source=source_string)
         REFERENCE_SEPARATORS['sep_{role}_default'.format(role=role)] = default_separators[index]
     # verse range match: (<chapter>:)?<verse>(-((<chapter>:)?<verse>|end)?)?
-    # TODO: Check before converting this string
-    range_regex = '(?:(?P<from_chapter>[0-9]+)%(sep_v)s)?' \
-        '(?P<from_verse>[0-9]+)(?P<range_to>%(sep_r)s(?:(?:(?P<to_chapter>' \
-        '[0-9]+)%(sep_v)s)?(?P<to_verse>[0-9]+)|%(sep_e)s)?)?' % REFERENCE_SEPARATORS
-    # TODO: Test before converting re.compile strings
-    REFERENCE_MATCHES['range'] = re.compile('^\s*%s\s*$' % range_regex, re.UNICODE)
+    range_regex = '(?:(?P<from_chapter>[0-9]+){sep_v})?' \
+        '(?P<from_verse>[0-9]+)(?P<range_to>{sep_r}(?:(?:(?P<to_chapter>' \
+        '[0-9]+){sep_v})?(?P<to_verse>[0-9]+)|{sep_e})?)?'.format_map(REFERENCE_SEPARATORS)
+    REFERENCE_MATCHES['range'] = re.compile(r'^\s*{range}\s*$'.format(range=range_regex), re.UNICODE)
     REFERENCE_MATCHES['range_separator'] = re.compile(REFERENCE_SEPARATORS['sep_l'], re.UNICODE)
     # full reference match: <book>(<range>(,(?!$)|(?=$)))+
     REFERENCE_MATCHES['full'] = \
-        re.compile('^\s*(?!\s)(?P<book>[\d]*[^\d\.]+)\.*(?<!\s)\s*'
-                   '(?P<ranges>(?:%(range_regex)s(?:%(sep_l)s(?!\s*$)|(?=\s*$)))+)\s*$'
-                   % dict(list(REFERENCE_SEPARATORS.items()) + [('range_regex', range_regex)]), re.UNICODE)
+        re.compile(r'^\s*(?!\s)(?P<book>[\d]*[^\d\.]+)\.*(?<!\s)\s*'
+                   r'(?P<ranges>(?:{range_regex}(?:{sep_l}(?!\s*$)|(?=\s*$)))+)\s*$'.format(
+                       range_regex=range_regex, sep_l=REFERENCE_SEPARATORS['sep_l']), re.UNICODE)
 
 
 def get_reference_separator(separator_type):

=== modified file 'openlp/plugins/bibles/lib/db.py'
--- openlp/plugins/bibles/lib/db.py	2017-02-18 07:23:15 +0000
+++ openlp/plugins/bibles/lib/db.py	2017-05-30 20:33:49 +0000
@@ -305,9 +305,8 @@
         book_escaped = book
         for character in RESERVED_CHARACTERS:
             book_escaped = book_escaped.replace(character, '\\' + character)
-        # TODO: Verify regex patters before using format()
-        regex_book = re.compile('\s*%s\s*' % '\s*'.join(
-            book_escaped.split()), re.UNICODE | re.IGNORECASE)
+        regex_book = re.compile('\\s*{book}\\s*'.format(book='\\s*'.join(book_escaped.split())),
+                                re.UNICODE | re.IGNORECASE)
         if language_selection == LanguageSelection.Bible:
             db_book = self.get_book(book)
             if db_book:

=== modified file 'openlp/plugins/bibles/lib/importers/http.py'
--- openlp/plugins/bibles/lib/importers/http.py	2016-12-31 11:01:36 +0000
+++ openlp/plugins/bibles/lib/importers/http.py	2017-05-30 20:33:49 +0000
@@ -90,6 +90,8 @@
     """
     Extract verses from BibleGateway
     """
+    NAME = 'BibleGateway'
+
     def __init__(self, proxy_url=None):
         log.debug('BGExtract.init("{url}")'.format(url=proxy_url))
         self.proxy_url = proxy_url
@@ -357,6 +359,8 @@
     """
     Extract verses from Bibleserver.com
     """
+    NAME = 'BibleServer'
+
     def __init__(self, proxy_url=None):
         log.debug('BSExtract.init("{url}")'.format(url=proxy_url))
         self.proxy_url = proxy_url
@@ -458,6 +462,8 @@
     """
     Extract verses from CrossWalk/BibleStudyTools
     """
+    NAME = 'Crosswalk'
+
     def __init__(self, proxy_url=None):
         log.debug('CWExtract.init("{url}")'.format(url=proxy_url))
         self.proxy_url = proxy_url

=== modified file 'openlp/plugins/custom/lib/mediaitem.py'
--- openlp/plugins/custom/lib/mediaitem.py	2016-12-31 11:01:36 +0000
+++ openlp/plugins/custom/lib/mediaitem.py	2017-05-30 20:33:49 +0000
@@ -190,9 +190,7 @@
                     translate('CustomPlugin.MediaItem',
                               'Are you sure you want to delete the "{items:d}" '
                               'selected custom slide(s)?').format(items=len(items)),
-                    QtWidgets.QMessageBox.StandardButtons(
-                        QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No),
-                    QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.No:
+                    defaultButton=QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.No:
                 return
             row_list = [item.row() for item in self.list_view.selectedIndexes()]
             row_list.sort(reverse=True)

=== modified file 'openlp/plugins/images/lib/mediaitem.py'
--- openlp/plugins/images/lib/mediaitem.py	2016-12-31 11:01:36 +0000
+++ openlp/plugins/images/lib/mediaitem.py	2017-05-30 20:33:49 +0000
@@ -246,9 +246,7 @@
                                 translate('ImagePlugin.MediaItem', 'Remove group'),
                                 translate('ImagePlugin.MediaItem',
                                           'Are you sure you want to remove "{name}" and everything in it?'
-                                          ).format(name=item_data.group_name),
-                                QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes |
-                                                                      QtWidgets.QMessageBox.No)
+                                          ).format(name=item_data.group_name)
                         ) == QtWidgets.QMessageBox.Yes:
                             self.recursively_delete_group(item_data)
                             self.manager.delete_object(ImageGroups, row_item.data(0, QtCore.Qt.UserRole).id)
@@ -597,8 +595,7 @@
                 self, translate('ImagePlugin.MediaItem', 'Missing Image(s)'),
                 translate('ImagePlugin.MediaItem', 'The following image(s) no longer exist: {names}\n'
                           'Do you want to add the other images anyway?'
-                          ).format(names='\n'.join(missing_items_file_names)),
-                QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.No | QtWidgets.QMessageBox.Yes)) == \
+                          ).format(names='\n'.join(missing_items_file_names))) == \
                 QtWidgets.QMessageBox.No:
             return False
         # Continue with the existing images.

=== modified file 'openlp/plugins/presentations/lib/pdfcontroller.py'
--- openlp/plugins/presentations/lib/pdfcontroller.py	2017-05-14 10:11:10 +0000
+++ openlp/plugins/presentations/lib/pdfcontroller.py	2017-05-30 20:33:49 +0000
@@ -253,15 +253,14 @@
         try:
             if not os.path.isdir(self.get_temp_folder()):
                 os.makedirs(self.get_temp_folder())
+            # The %03d in the file name is handled by each binary
             if self.controller.mudrawbin:
                 log.debug('loading presentation using mudraw')
-                # TODO: Find out where the string conversion actually happens
                 runlog = check_output([self.controller.mudrawbin, '-w', str(size.width()), '-h', str(size.height()),
                                        '-o', os.path.join(self.get_temp_folder(), 'mainslide%03d.png'), self.file_path],
                                       startupinfo=self.startupinfo)
             elif self.controller.mutoolbin:
                 log.debug('loading presentation using mutool')
-                # TODO: Find out where the string convertsion actually happens
                 runlog = check_output([self.controller.mutoolbin, 'draw', '-w', str(size.width()), '-h',
                                        str(size.height()),
                                        '-o', os.path.join(self.get_temp_folder(), 'mainslide%03d.png'), self.file_path],
@@ -269,7 +268,6 @@
             elif self.controller.gsbin:
                 log.debug('loading presentation using gs')
                 resolution = self.gs_get_resolution(size)
-                # TODO: Find out where the string conversion actually happens
                 runlog = check_output([self.controller.gsbin, '-dSAFER', '-dNOPAUSE', '-dBATCH', '-sDEVICE=png16m',
                                        '-r' + str(resolution), '-dTextAlphaBits=4', '-dGraphicsAlphaBits=4',
                                        '-sOutputFile=' + os.path.join(self.get_temp_folder(), 'mainslide%03d.png'),

=== modified file 'openlp/plugins/presentations/lib/powerpointcontroller.py'
--- openlp/plugins/presentations/lib/powerpointcontroller.py	2017-05-14 10:11:10 +0000
+++ openlp/plugins/presentations/lib/powerpointcontroller.py	2017-05-30 20:33:49 +0000
@@ -542,5 +542,5 @@
                     text += shape.TextFrame.TextRange.Text + '\n'
     except pywintypes.com_error as e:
         log.warning('Failed to extract text from powerpoint slide')
-        log.warning(e)
+        log.exception(e)
     return text

=== modified file 'openlp/plugins/presentations/presentationplugin.py'
--- openlp/plugins/presentations/presentationplugin.py	2017-05-22 18:27:40 +0000
+++ openlp/plugins/presentations/presentationplugin.py	2017-05-30 20:33:49 +0000
@@ -1,4 +1,4 @@
-    # -*- coding: utf-8 -*-
+# -*- coding: utf-8 -*-
 # vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
 
 ###############################################################################

=== modified file 'openlp/plugins/remotes/remoteplugin.py'
--- openlp/plugins/remotes/remoteplugin.py	2016-12-31 11:01:36 +0000
+++ openlp/plugins/remotes/remoteplugin.py	2017-05-30 20:33:49 +0000
@@ -122,5 +122,4 @@
                                           translate('RemotePlugin', 'Server Config Change'),
                                           translate('RemotePlugin',
                                                     'Server configuration changes will require a restart '
-                                                    'to take effect.'),
-                                          QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Ok))
+                                                    'to take effect.'))

=== modified file 'openlp/plugins/songs/forms/duplicatesongremovalform.py'
--- openlp/plugins/songs/forms/duplicatesongremovalform.py	2016-12-31 11:01:36 +0000
+++ openlp/plugins/songs/forms/duplicatesongremovalform.py	2017-05-30 20:33:49 +0000
@@ -130,9 +130,9 @@
         Song wizard localisation.
         """
         self.setWindowTitle(translate('Wizard', 'Wizard'))
-        # TODO: Check format() using template strings
-        self.title_label.setText(WizardStrings.HeaderStyle % translate('OpenLP.Ui',
-                                                                       'Welcome to the Duplicate Song Removal Wizard'))
+        self.title_label.setText(
+            WizardStrings.HeaderStyle.format(text=translate('OpenLP.Ui',
+                                                            'Welcome to the Duplicate Song Removal Wizard')))
         self.information_label.setText(
             translate("Wizard",
                       'This wizard will help you to remove duplicate songs from the song database. You will have a '
@@ -216,8 +216,7 @@
         self.button(QtWidgets.QWizard.CancelButton).hide()
         QtWidgets.QMessageBox.information(
             self, translate('Wizard', 'Information'),
-            translate('Wizard', 'No duplicate songs have been found in the database.'),
-            QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Ok))
+            translate('Wizard', 'No duplicate songs have been found in the database.'))
 
     def add_duplicates_to_song_list(self, search_song, duplicate_song):
         """

=== modified file 'openlp/plugins/songs/forms/editsongform.py'
--- openlp/plugins/songs/forms/editsongform.py	2017-03-02 04:34:24 +0000
+++ openlp/plugins/songs/forms/editsongform.py	2017-05-30 20:33:49 +0000
@@ -203,8 +203,7 @@
                                 'There is no verse corresponding to "{invalid}". Valid entries are {valid}.\n'
                                 'Please enter the verses separated by spaces.').format(invalid=invalid_verses[0],
                                                                                        valid=valid)
-            critical_error_message_box(title=translate('SongsPlugin.EditSongForm', 'Invalid Verse Order'),
-                                       message=msg)
+            critical_error_message_box(title=translate('SongsPlugin.EditSongForm', 'Invalid Verse Order'), message=msg)
         return len(invalid_verses) == 0
 
     def _validate_song(self):
@@ -579,8 +578,7 @@
                     self,
                     translate('SongsPlugin.EditSongForm', 'Add Author'),
                     translate('SongsPlugin.EditSongForm', 'This author does not exist, do you want to add them?'),
-                    QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
-                    QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.Yes:
+                    defaultButton=QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.Yes:
                 if text.find(' ') == -1:
                     author = Author.populate(first_name='', last_name='', display_name=text)
                 else:
@@ -658,8 +656,7 @@
             if QtWidgets.QMessageBox.question(
                     self, translate('SongsPlugin.EditSongForm', 'Add Topic'),
                     translate('SongsPlugin.EditSongForm', 'This topic does not exist, do you want to add it?'),
-                    QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
-                    QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.Yes:
+                    defaultButton=QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.Yes:
                 topic = Topic.populate(name=text)
                 self.manager.save_object(topic)
                 topic_item = QtWidgets.QListWidgetItem(str(topic.name))
@@ -705,8 +702,7 @@
             if QtWidgets.QMessageBox.question(
                     self, translate('SongsPlugin.EditSongForm', 'Add Songbook'),
                     translate('SongsPlugin.EditSongForm', 'This Songbook does not exist, do you want to add it?'),
-                    QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
-                    QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.Yes:
+                    defaultButton=QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.Yes:
                 songbook = Book.populate(name=text)
                 self.manager.save_object(songbook)
                 self.add_songbook_entry_to_list(songbook.id, songbook.name, self.songbook_entry_edit.text())

=== modified file 'openlp/plugins/songs/forms/songexportform.py'
--- openlp/plugins/songs/forms/songexportform.py	2016-12-31 11:01:36 +0000
+++ openlp/plugins/songs/forms/songexportform.py	2017-05-30 20:33:49 +0000
@@ -121,7 +121,7 @@
         self.selected_list_widget = QtWidgets.QListWidget(self.export_song_page)
         self.selected_list_widget.setObjectName('selected_list_widget')
         self.grid_layout.addWidget(self.selected_list_widget, 1, 0, 1, 1)
-        # FIXME: self.horizontal_layout is already defined above?!?!?
+        # FIXME: self.horizontal_layout is already defined above?!?!? Replace with Path Eidt!
         self.horizontal_layout = QtWidgets.QHBoxLayout()
         self.horizontal_layout.setObjectName('horizontal_layout')
         self.directory_label = QtWidgets.QLabel(self.export_song_page)
@@ -143,9 +143,8 @@
         Song wizard localisation.
         """
         self.setWindowTitle(translate('SongsPlugin.ExportWizardForm', 'Song Export Wizard'))
-        # TODO: Verify format() with template variables
-        self.title_label.setText(WizardStrings.HeaderStyle %
-                                 translate('OpenLP.Ui', 'Welcome to the Song Export Wizard'))
+        self.title_label.setText(
+            WizardStrings.HeaderStyle.format(text=translate('OpenLP.Ui', 'Welcome to the Song Export Wizard')))
         self.information_label.setText(
             translate('SongsPlugin.ExportWizardForm', 'This wizard will help to export your songs to the open and free '
                                                       '<strong>OpenLyrics </strong> worship song format.'))

=== modified file 'openlp/plugins/songs/forms/songimportform.py'
--- openlp/plugins/songs/forms/songimportform.py	2016-12-31 11:01:36 +0000
+++ openlp/plugins/songs/forms/songimportform.py	2017-05-30 20:33:49 +0000
@@ -132,9 +132,8 @@
         Song wizard localisation.
         """
         self.setWindowTitle(translate('SongsPlugin.ImportWizardForm', 'Song Import Wizard'))
-        # TODO: Verify format() with template variables
-        self.title_label.setText(WizardStrings.HeaderStyle % translate('OpenLP.Ui',
-                                                                       'Welcome to the Song Import Wizard'))
+        self.title_label.setText(
+            WizardStrings.HeaderStyle.format(text=translate('OpenLP.Ui', 'Welcome to the Song Import Wizard')))
         self.information_label.setText(
             translate('SongsPlugin.ImportWizardForm',
                       'This wizard will help you to import songs from a variety of formats. Click the next button '
@@ -272,12 +271,11 @@
         select_mode, format_name, ext_filter = SongFormat.get(this_format, 'selectMode', 'name', 'filter')
         file_path_edit = self.format_widgets[this_format]['file_path_edit']
         if select_mode == SongFormatSelect.SingleFile:
-            # TODO: Verify format() with template variables
-            self.get_file_name(
-                WizardStrings.OpenTypeFile % format_name, file_path_edit, 'last directory import', ext_filter)
+            self.get_file_name(WizardStrings.OpenTypeFile.format(file_type=format_name),
+                               file_path_edit, 'last directory import', ext_filter)
         elif select_mode == SongFormatSelect.SingleFolder:
-            # TODO: Verify format() with template variables
-            self.get_folder(WizardStrings.OpenTypeFolder % format_name, file_path_edit, 'last directory import')
+            self.get_folder(
+                WizardStrings.OpenTypeFolder.format(folder_name=format_name), file_path_edit, 'last directory import')
 
     def on_add_button_clicked(self):
         """
@@ -286,8 +284,7 @@
         this_format = self.current_format
         select_mode, format_name, ext_filter, custom_title = \
             SongFormat.get(this_format, 'selectMode', 'name', 'filter', 'getFilesTitle')
-        # TODO: Verify format() with template variables
-        title = custom_title if custom_title else WizardStrings.OpenTypeFile % format_name
+        title = custom_title if custom_title else WizardStrings.OpenTypeFile.format(file_type=format_name)
         if select_mode == SongFormatSelect.MultipleFiles:
             self.get_files(title, self.format_widgets[this_format]['file_list_widget'], ext_filter)
             self.source_page.completeChanged.emit()

=== modified file 'openlp/plugins/songs/forms/songselectform.py'
--- openlp/plugins/songs/forms/songselectform.py	2017-02-18 07:23:15 +0000
+++ openlp/plugins/songs/forms/songselectform.py	2017-05-30 20:33:49 +0000
@@ -248,8 +248,7 @@
                 translate('SongsPlugin.SongSelectForm', 'WARNING: Saving your username and password is INSECURE, your '
                                                         'password is stored in PLAIN TEXT. Click Yes to save your '
                                                         'password or No to cancel this.'),
-                QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No),
-                QtWidgets.QMessageBox.No)
+                defaultButton=QtWidgets.QMessageBox.No)
             if answer == QtWidgets.QMessageBox.No:
                 self.save_password_checkbox.setChecked(False)
 
@@ -397,8 +396,7 @@
                                           translate('SongsPlugin.SongSelectForm',
                                                     'Your song has been imported, would you '
                                                     'like to import more songs?'),
-                                          QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
-                                          QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.Yes:
+                                          defaultButton=QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.Yes:
             self.on_back_button_clicked()
         else:
             self.application.process_events()

=== modified file 'openlp/plugins/songs/lib/importer.py'
--- openlp/plugins/songs/lib/importer.py	2017-05-22 19:07:07 +0000
+++ openlp/plugins/songs/lib/importer.py	2017-05-30 20:33:49 +0000
@@ -265,7 +265,7 @@
         },
         EasyWorshipService: {
             'class': EasyWorshipSongImport,
-            'name': 'EasyWorship Service File',
+            'name': 'EasyWorship Service',
             'prefix': 'ew',
             'selectMode': SongFormatSelect.SingleFile,
             'filter': '{text} (*.ews)'.format(text=translate('SongsPlugin.ImportWizardForm',

=== modified file 'openlp/plugins/songs/lib/importers/foilpresenter.py'
--- openlp/plugins/songs/lib/importers/foilpresenter.py	2016-12-31 11:01:36 +0000
+++ openlp/plugins/songs/lib/importers/foilpresenter.py	2017-05-30 20:33:49 +0000
@@ -121,8 +121,8 @@
         for file_path in self.import_source:
             if self.stop_import_flag:
                 return
-            # TODO: Verify format() with template strings
-            self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % os.path.basename(file_path))
+            self.import_wizard.increment_progress_bar(
+                WizardStrings.ImportingType.format(source=os.path.basename(file_path)))
             try:
                 parsed_file = etree.parse(file_path, parser)
                 xml = etree.tostring(parsed_file).decode()

=== modified file 'openlp/plugins/songs/lib/importers/openlp.py'
--- openlp/plugins/songs/lib/importers/openlp.py	2017-03-28 05:15:05 +0000
+++ openlp/plugins/songs/lib/importers/openlp.py	2017-05-30 20:33:49 +0000
@@ -275,11 +275,9 @@
             self.manager.save_object(new_song)
             if progress_dialog:
                 progress_dialog.setValue(progress_dialog.value() + 1)
-                # TODO: Verify format() with template strings
-                progress_dialog.setLabelText(WizardStrings.ImportingType % new_song.title)
+                progress_dialog.setLabelText(WizardStrings.ImportingType.format(source=new_song.title))
             else:
-                # TODO: Verify format() with template strings
-                self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % new_song.title)
+                self.import_wizard.increment_progress_bar(WizardStrings.ImportingType.format(source=new_song.title))
             if self.stop_import_flag:
                 break
         self.source_session.close()

=== modified file 'openlp/plugins/songs/lib/importers/openlyrics.py'
--- openlp/plugins/songs/lib/importers/openlyrics.py	2016-12-31 11:01:36 +0000
+++ openlp/plugins/songs/lib/importers/openlyrics.py	2017-05-30 20:33:49 +0000
@@ -58,8 +58,8 @@
         for file_path in self.import_source:
             if self.stop_import_flag:
                 return
-            # TODO: Verify format() with template strings
-            self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % os.path.basename(file_path))
+            self.import_wizard.increment_progress_bar(
+                WizardStrings.ImportingType.format(source=os.path.basename(file_path)))
             try:
                 # Pass a file object, because lxml does not cope with some
                 # special characters in the path (see lp:757673 and lp:744337).

=== modified file 'openlp/plugins/songs/lib/importers/powerpraise.py'
--- openlp/plugins/songs/lib/importers/powerpraise.py	2016-12-31 11:01:36 +0000
+++ openlp/plugins/songs/lib/importers/powerpraise.py	2017-05-30 20:33:49 +0000
@@ -41,8 +41,8 @@
         for file_path in self.import_source:
             if self.stop_import_flag:
                 return
-            # TODO: Verify format() with template strings
-            self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % os.path.basename(file_path))
+            self.import_wizard.increment_progress_bar(
+                WizardStrings.ImportingType.format(source=os.path.basename(file_path)))
             root = objectify.parse(open(file_path, 'rb')).getroot()
             self.process_song(root)
 

=== modified file 'openlp/plugins/songs/lib/importers/presentationmanager.py'
--- openlp/plugins/songs/lib/importers/presentationmanager.py	2017-03-23 04:43:13 +0000
+++ openlp/plugins/songs/lib/importers/presentationmanager.py	2017-05-30 20:33:49 +0000
@@ -44,8 +44,8 @@
         for file_path in self.import_source:
             if self.stop_import_flag:
                 return
-            # TODO: Verify format() with template strings
-            self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % os.path.basename(file_path))
+            self.import_wizard.increment_progress_bar(
+                WizardStrings.ImportingType.format(source=os.path.basename(file_path)))
             try:
                 tree = etree.parse(file_path, parser=etree.XMLParser(recover=True))
             except etree.XMLSyntaxError:

=== modified file 'openlp/plugins/songs/lib/importers/propresenter.py'
--- openlp/plugins/songs/lib/importers/propresenter.py	2016-12-31 11:01:36 +0000
+++ openlp/plugins/songs/lib/importers/propresenter.py	2017-05-30 20:33:49 +0000
@@ -46,8 +46,8 @@
         for file_path in self.import_source:
             if self.stop_import_flag:
                 return
-            # TODO: Verify format() with template strings
-            self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % os.path.basename(file_path))
+            self.import_wizard.increment_progress_bar(
+                WizardStrings.ImportingType.format(source=os.path.basename(file_path)))
             root = objectify.parse(open(file_path, 'rb')).getroot()
             self.process_song(root, file_path)
 

=== modified file 'openlp/plugins/songs/lib/importers/songimport.py'
--- openlp/plugins/songs/lib/importers/songimport.py	2017-05-11 20:01:43 +0000
+++ openlp/plugins/songs/lib/importers/songimport.py	2017-05-30 20:33:49 +0000
@@ -347,8 +347,7 @@
         song = Song()
         song.title = self.title
         if self.import_wizard is not None:
-            # TODO: Verify format() with template variables
-            self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % song.title)
+            self.import_wizard.increment_progress_bar(WizardStrings.ImportingType.format(source=song.title))
         song.alternate_title = self.alternate_title
         # Values will be set when cleaning the song.
         song.search_title = ''

=== modified file 'openlp/plugins/songs/lib/importers/songshowplus.py'
--- openlp/plugins/songs/lib/importers/songshowplus.py	2016-12-31 11:01:36 +0000
+++ openlp/plugins/songs/lib/importers/songshowplus.py	2017-05-30 20:33:49 +0000
@@ -101,8 +101,7 @@
             self.other_count = 0
             self.other_list = {}
             file_name = os.path.split(file)[1]
-            # TODO: Verify format() with template variables
-            self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % file_name, 0)
+            self.import_wizard.increment_progress_bar(WizardStrings.ImportingType.format(source=file_name), 0)
             song_data = open(file, 'rb')
             while True:
                 block_key, = struct.unpack("I", song_data.read(4))

=== modified file 'openlp/plugins/songs/lib/mediaitem.py'
--- openlp/plugins/songs/lib/mediaitem.py	2017-01-25 21:17:27 +0000
+++ openlp/plugins/songs/lib/mediaitem.py	2017-05-30 20:33:49 +0000
@@ -500,8 +500,7 @@
                     translate('SongsPlugin.MediaItem',
                               'Are you sure you want to delete the "{items:d}" '
                               'selected song(s)?').format(items=len(items)),
-                    QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No),
-                    QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.No:
+                    defaultButton=QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.No:
                 return
             self.application.set_busy_cursor()
             self.main_window.display_progress_bar(len(items))

=== modified file 'openlp/plugins/songs/lib/openlyricsxml.py'
--- openlp/plugins/songs/lib/openlyricsxml.py	2017-02-26 21:14:49 +0000
+++ openlp/plugins/songs/lib/openlyricsxml.py	2017-05-30 20:33:49 +0000
@@ -70,8 +70,7 @@
 log = logging.getLogger(__name__)
 
 NAMESPACE = 'http://openlyrics.info/namespace/2009/song'
-# TODO: Verify format() with template variable
-NSMAP = '{' + NAMESPACE + '}' + '%s'
+NSMAP = '{{' + NAMESPACE + '}}{tag}'
 
 
 class SongXML(object):
@@ -616,15 +615,13 @@
         text = ''
         use_endtag = True
         # Skip <comment> elements - not yet supported.
-        # TODO: Verify format() with template variables
-        if element.tag == NSMAP % 'comment':
+        if element.tag == NSMAP.format(tag='comment'):
             if element.tail:
                 # Append tail text at comment element.
                 text += element.tail
             return text
         # Convert chords to ChordPro format which OpenLP uses internally
-        # TODO: Verify format() with template variables
-        elif element.tag == NSMAP % 'chord':
+        elif element.tag == NSMAP.format(tag='chord'):
             if Settings().value('songs/enable chords') and not Settings().value('songs/disable chords import'):
                 text += '[{chord}]'.format(chord=element.get('name'))
             if element.tail:
@@ -632,15 +629,13 @@
                 text += element.tail
             return text
         # Convert line breaks <br/> to \n.
-        # TODO: Verify format() with template variables
-        elif newlines and element.tag == NSMAP % 'br':
+        elif newlines and element.tag == NSMAP.format(tag='br'):
             text += '\n'
             if element.tail:
                 text += element.tail
             return text
         # Start formatting tag.
-        # TODO: Verify format() with template variables
-        if element.tag == NSMAP % 'tag':
+        if element.tag == NSMAP.format(tag='tag'):
             text += '{{{name}}}'.format(name=element.get('name'))
             # Some formattings may have only start tag.
             # Handle this case if element has no children and contains no text.
@@ -654,8 +649,7 @@
             # Use recursion since nested formatting tags are allowed.
             text += self._process_lines_mixed_content(child, newlines)
         # Append text from tail and add formatting end tag.
-        # TODO: Verify format() with template variables
-        if element.tag == NSMAP % 'tag' and use_endtag:
+        if element.tag == NSMAP.format(tag='tag') and use_endtag:
             text += '{{/{name}}}'.format(name=element.get('name'))
         # Append text from tail.
         if element.tail:
@@ -682,8 +676,7 @@
             # Loop over the "line" elements removing comments
             for line in element:
                 # Skip comment lines.
-                # TODO: Verify format() with template variables
-                if line.tag == NSMAP % 'comment':
+                if line.tag == NSMAP.format(tag='comment'):
                     continue
                 if text:
                     text += '\n'

=== modified file 'openlp/plugins/songusage/forms/songusagedeleteform.py'
--- openlp/plugins/songusage/forms/songusagedeleteform.py	2016-12-31 11:01:36 +0000
+++ openlp/plugins/songusage/forms/songusagedeleteform.py	2017-05-30 20:33:49 +0000
@@ -53,9 +53,7 @@
                                                            'Delete Selected Song Usage Events?'),
                                                  translate('SongUsagePlugin.SongUsageDeleteForm',
                                                            'Are you sure you want to delete selected Song Usage data?'),
-                                                 QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes |
-                                                                                       QtWidgets.QMessageBox.No),
-                                                 QtWidgets.QMessageBox.No)
+                                                 defaultButton=QtWidgets.QMessageBox.No)
             if ret == QtWidgets.QMessageBox.Yes:
                 delete_date = self.delete_calendar.selectedDate().toPyDate()
                 self.manager.delete_all_objects(SongUsageItem, SongUsageItem.usagedate <= delete_date)

=== modified file 'openlp/plugins/songusage/forms/songusagedetaildialog.py'
--- openlp/plugins/songusage/forms/songusagedetaildialog.py	2017-05-22 18:22:43 +0000
+++ openlp/plugins/songusage/forms/songusagedetaildialog.py	2017-05-30 20:33:49 +0000
@@ -69,7 +69,7 @@
         self.file_horizontal_layout.setSpacing(8)
         self.file_horizontal_layout.setContentsMargins(8, 8, 8, 8)
         self.file_horizontal_layout.setObjectName('file_horizontal_layout')
-        self.report_path_edit = PathEdit(self.file_group_box, path_type = PathType.Directories, show_revert=False)
+        self.report_path_edit = PathEdit(self.file_group_box, path_type=PathType.Directories, show_revert=False)
         self.file_horizontal_layout.addWidget(self.report_path_edit)
         self.vertical_layout.addWidget(self.file_group_box)
         self.button_box = create_button_box(song_usage_detail_dialog, 'button_box', ['cancel', 'ok'])

=== modified file 'tests/functional/openlp_core_ui/test_formattingtagsform.py'
--- tests/functional/openlp_core_ui/test_formattingtagsform.py	2017-04-24 05:17:55 +0000
+++ tests/functional/openlp_core_ui/test_formattingtagsform.py	2017-05-30 20:33:49 +0000
@@ -27,12 +27,6 @@
 
 from openlp.core.ui.formattingtagform import FormattingTagForm
 
-# TODO: Tests Still TODO
-# __init__
-# exec
-# on_saved_clicked
-# _reloadTable
-
 
 class TestFormattingTagForm(TestCase):
 

=== modified file 'tests/functional/openlp_core_ui/test_thememanager.py'
--- tests/functional/openlp_core_ui/test_thememanager.py	2017-05-08 19:04:14 +0000
+++ tests/functional/openlp_core_ui/test_thememanager.py	2017-05-30 20:33:49 +0000
@@ -176,7 +176,7 @@
             self.assertTrue(result)
             mocked_qmessagebox_question.assert_called_once_with(
                 theme_manager, 'Theme Already Exists', 'Theme Theme Name already exists. Do you want to replace it?',
-                ANY, ANY)
+                defaultButton=ANY)
 
     def test_over_write_message_box_no(self):
         """
@@ -196,7 +196,7 @@
             self.assertFalse(result)
             mocked_qmessagebox_question.assert_called_once_with(
                 theme_manager, 'Theme Already Exists', 'Theme Theme Name already exists. Do you want to replace it?',
-                ANY, ANY)
+                defaultButton=ANY)
 
     def test_unzip_theme(self):
         """

=== modified file 'tests/functional/openlp_plugins/bibles/test_bibleserver.py'
--- tests/functional/openlp_plugins/bibles/test_bibleserver.py	2017-04-24 05:17:55 +0000
+++ tests/functional/openlp_plugins/bibles/test_bibleserver.py	2017-05-30 20:33:49 +0000
@@ -29,45 +29,11 @@
 
 from openlp.plugins.bibles.lib.importers.http import BSExtract
 
-# TODO: Items left to test
-#   BGExtract
-#       __init__
-#       _remove_elements
-#       _extract_verse
-#       _clean_soup
-#       _extract_verses
-#       _extract_verses_old
-#       get_bible_chapter
-#       get_books_from_http
-#       _get_application
-#   CWExtract
-#       __init__
-#       get_bible_chapter
-#       get_books_from_http
-#       _get_application
-#   HTTPBible
-#       __init__
-#       do_import
-#       get_verses
-#       get_chapter
-#       get_books
-#       get_chapter_count
-#       get_verse_count
-#       _get_application
-#   get_soup_for_bible_ref
-#   send_error_message
-
 
 class TestBSExtract(TestCase):
     """
     Test the BSExtractClass
     """
-    # TODO: Items left to test
-    #   BSExtract
-    #       __init__
-    #       get_bible_chapter
-    #       get_books_from_http
-    #       _get_application
     def setUp(self):
         self.get_soup_for_bible_ref_patcher = patch('openlp.plugins.bibles.lib.importers.http.get_soup_for_bible_ref')
         self.log_patcher = patch('openlp.plugins.bibles.lib.importers.http.log')

=== modified file 'tests/functional/openlp_plugins/bibles/test_mediaitem.py'
--- tests/functional/openlp_plugins/bibles/test_mediaitem.py	2017-02-18 07:23:15 +0000
+++ tests/functional/openlp_plugins/bibles/test_mediaitem.py	2017-05-30 20:33:49 +0000
@@ -197,9 +197,6 @@
         self.assertTrue(self.media_item.has_delete_icon, 'Check that the icon is called as True.')
         self.assertFalse(self.media_item.add_to_service_item, 'Check that the icon is called as False')
 
-    # TODO: Test add_end_header_bar
-    # TODO: Test setupUi
-
     def test_on_focus_search_tab_visible(self):
         """
         Test the correct widget gets focus when the BibleMediaItem receives focus
@@ -1345,8 +1342,6 @@
             self.assertTrue(self.mocked_main_window.information_message.called)
             mocked_display_results.assert_called_once_with()
 
-    # TODO: Test text_search
-
     def test_on_search_edit_text_changed_search_while_typing_disabled(self):
         """
         Test on_search_edit_text_changed when 'search while typing' is disabled

=== modified file 'tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py'
--- tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py	2017-04-24 05:17:55 +0000
+++ tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py	2017-05-30 20:33:49 +0000
@@ -42,11 +42,6 @@
     """
     Test the PptviewController Class
     """
-# TODO: Items left to test
-#   PptviewController
-#       start_process(self)
-#       kill
-
     def setUp(self):
         """
         Set up the patches and mocks need for all tests.
@@ -103,24 +98,6 @@
     """
     Test the PptviewDocument Class
     """
-    # TODO: Items left to test
-    #   PptviewDocument
-    #       __init__
-    #       create_thumbnails
-    #       close_presentation
-    #       is_loaded
-    #       is_active
-    #       blank_screen
-    #       unblank_screen
-    #       is_blank
-    #       stop_presentation
-    #       start_presentation
-    #       get_slide_number
-    #       get_slide_count
-    #       goto_slide
-    #       next_step
-    #       previous_step
-
     def setUp(self):
         """
         Set up the patches and mocks need for all tests.

=== modified file 'tests/functional/openlp_plugins/presentations/test_presentationcontroller.py'
--- tests/functional/openlp_plugins/presentations/test_presentationcontroller.py	2017-04-24 05:17:55 +0000
+++ tests/functional/openlp_plugins/presentations/test_presentationcontroller.py	2017-05-30 20:33:49 +0000
@@ -36,19 +36,6 @@
     """
     Test the PresentationController.
     """
-    # TODO: Items left to test
-    #   PresentationController
-    #       __init__
-    #       enabled
-    #       is_available
-    #       check_available
-    #       start_process
-    #       kill
-    #       add_document
-    #       remove_doc
-    #       close_presentation
-    #       _get_plugin_manager
-
     def setUp(self):
         self.get_thumbnail_folder_patcher = \
             patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder')
@@ -183,32 +170,6 @@
     """
     Test the PresentationDocument Class
     """
-    # TODO: Items left to test
-    #   PresentationDocument
-    #       __init__
-    #       presentation_deleted
-    #       get_thumbnail_folder
-    #       get_temp_folder
-    #       check_thumbnails
-    #       close_presentation
-    #       is_active
-    #       is_loaded
-    #       blank_screen
-    #       unblank_screen
-    #       is_blank
-    #       stop_presentation
-    #       start_presentation
-    #       get_slide_number
-    #       get_slide_count
-    #       goto_slide
-    #       next_step
-    #       previous_step
-    #       convert_thumbnail
-    #       get_thumbnail_path
-    #       poll_slidenumber
-    #       get_slide_text
-    #       get_slide_notes
-
     def setUp(self):
         """
         Set up the patches and mocks need for all tests.

=== modified file 'tests/functional/openlp_plugins/songs/test_foilpresenterimport.py'
--- tests/functional/openlp_plugins/songs/test_foilpresenterimport.py	2017-04-24 05:17:55 +0000
+++ tests/functional/openlp_plugins/songs/test_foilpresenterimport.py	2017-05-30 20:33:49 +0000
@@ -36,18 +36,6 @@
     """
     Test the functions in the :mod:`foilpresenterimport` module.
     """
-    # TODO: The following modules still need tests written for
-    #   xml_to_song
-    #   to_str
-    #   _process_authors
-    #   _process_cclinumber
-    #   _process_comments
-    #   _process_copyright
-    #   _process_lyrics
-    #   _process_songbooks
-    #   _process_titles
-    #   _process_topics
-
     def setUp(self):
         self.to_str_patcher = patch('openlp.plugins.songs.lib.importers.foilpresenter.to_str')
         self.clean_song_patcher = patch('openlp.plugins.songs.lib.importers.foilpresenter.clean_song')

=== modified file 'tests/functional/openlp_plugins/songs/test_songselect.py'
--- tests/functional/openlp_plugins/songs/test_songselect.py	2017-03-10 22:48:59 +0000
+++ tests/functional/openlp_plugins/songs/test_songselect.py	2017-05-30 20:33:49 +0000
@@ -612,8 +612,7 @@
         mocked_song_select_importer.save_song.assert_called_with(None)
         mocked_question.assert_called_with(ssform, 'Song Imported',
                                            'Your song has been imported, would you like to import more songs?',
-                                           QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
-                                           QtWidgets.QMessageBox.Yes)
+                                           defaultButton=QtWidgets.QMessageBox.Yes)
         mocked_on_back_button_clicked.assert_called_with()
         self.assertIsNone(ssform.song)
 
@@ -639,8 +638,7 @@
         mocked_song_select_importer.save_song.assert_called_with(None)
         mocked_question.assert_called_with(ssform, 'Song Imported',
                                            'Your song has been imported, would you like to import more songs?',
-                                           QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
-                                           QtWidgets.QMessageBox.Yes)
+                                           defaultButton=QtWidgets.QMessageBox.Yes)
         mocked_done.assert_called_with(QtWidgets.QDialog.Accepted)
         self.assertIsNone(ssform.song)
 


Follow ups