From 5b717db63a2425a3570710d37db4112c32e45a8b Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Mon, 2 Feb 2015 20:40:31 +0000 Subject: [PATCH 1/6] Make Zefania import guess book from number if name is unavailable. Fixes bug 1417033. Fixes: https://launchpad.net/bugs/1417033 --- openlp/plugins/bibles/lib/osis.py | 2 +- openlp/plugins/bibles/lib/zefania.py | 20 ++++++-- .../bibles/test_zefaniaimport.py | 32 ++++++++++++- tests/resources/bibles/rst.json | 16 +++++++ tests/resources/bibles/zefania-rst.xml | 48 +++++++++++++++++++ 5 files changed, 111 insertions(+), 7 deletions(-) create mode 100644 tests/resources/bibles/rst.json create mode 100644 tests/resources/bibles/zefania-rst.xml diff --git a/openlp/plugins/bibles/lib/osis.py b/openlp/plugins/bibles/lib/osis.py index 52e232ac9..07ec4ab23 100644 --- a/openlp/plugins/bibles/lib/osis.py +++ b/openlp/plugins/bibles/lib/osis.py @@ -58,7 +58,7 @@ class OSISBible(BibleDB): # NOTE: We don't need to do any of the normal encoding detection here, because lxml does it's own encoding # detection, and the two mechanisms together interfere with each other. import_file = open(self.filename, 'rb') - osis_bible_tree = etree.parse(import_file) + osis_bible_tree = etree.parse(import_file, parser=etree.XMLParser(recover=True)) namespace = {'ns': 'http://www.bibletechnologies.net/2003/OSIS/namespace'} # Find bible language language_id = None diff --git a/openlp/plugins/bibles/lib/zefania.py b/openlp/plugins/bibles/lib/zefania.py index 355fb82cf..ad8f96648 100644 --- a/openlp/plugins/bibles/lib/zefania.py +++ b/openlp/plugins/bibles/lib/zefania.py @@ -57,7 +57,7 @@ class ZefaniaBible(BibleDB): # NOTE: We don't need to do any of the normal encoding detection here, because lxml does it's own encoding # detection, and the two mechanisms together interfere with each other. import_file = open(self.filename, 'rb') - zefania_bible_tree = etree.parse(import_file) + zefania_bible_tree = etree.parse(import_file, parser=etree.XMLParser(recover=True)) # Find bible language language_id = None language = zefania_bible_tree.xpath("/XMLBIBLE/INFORMATION/language/text()") @@ -76,9 +76,19 @@ class ZefaniaBible(BibleDB): etree.strip_elements(zefania_bible_tree, ('PROLOG', 'REMARK', 'CAPTION', 'MEDIA'), with_tail=False) xmlbible = zefania_bible_tree.getroot() for BIBLEBOOK in xmlbible: - book_ref_id = self.get_book_ref_id_by_name(str(BIBLEBOOK.get('bname')), num_books) - if not book_ref_id: - book_ref_id = self.get_book_ref_id_by_localised_name(str(BIBLEBOOK.get('bname'))) + if self.stop_import_flag: + break + bname = BIBLEBOOK.get('bname') + bnumber = BIBLEBOOK.get('bnumber') + if not bname and not bnumber: + continue + if bname: + book_ref_id = self.get_book_ref_id_by_name(bname, num_books) + if not book_ref_id: + book_ref_id = self.get_book_ref_id_by_localised_name(bname) + else: + log.debug('Could not find a name, will use number, basically a guess.') + book_ref_id = int(bnumber) if not book_ref_id: log.error('Importing books from "%s" failed' % self.filename) return False @@ -94,7 +104,7 @@ class ZefaniaBible(BibleDB): self.wizard.increment_progress_bar( translate('BiblesPlugin.Zefnia', 'Importing %(bookname)s %(chapter)s...' % {'bookname': db_book.name, 'chapter': chapter_number})) - self.session.commit() + self.session.commit() self.application.process_events() except Exception as e: critical_error_message_box( diff --git a/tests/functional/openlp_plugins/bibles/test_zefaniaimport.py b/tests/functional/openlp_plugins/bibles/test_zefaniaimport.py index 0a234903c..63545a00c 100644 --- a/tests/functional/openlp_plugins/bibles/test_zefaniaimport.py +++ b/tests/functional/openlp_plugins/bibles/test_zefaniaimport.py @@ -77,7 +77,6 @@ class TestZefaniaImport(TestCase): mocked_import_wizard = MagicMock() importer = ZefaniaBible(mocked_manager, path='.', name='.', filename='') importer.wizard = mocked_import_wizard - importer.get_book_ref_id_by_name = MagicMock() importer.create_verse = MagicMock() importer.create_book = MagicMock() importer.session = MagicMock() @@ -92,3 +91,34 @@ class TestZefaniaImport(TestCase): self.assertTrue(importer.create_verse.called) for verse_tag, verse_text in test_data['verses']: importer.create_verse.assert_any_call(importer.create_book().id, '1', verse_tag, verse_text) + importer.create_book.assert_any_call('Genesis', 1, 1) + + def file_import_no_book_name_test(self): + """ + Test the import of Zefania Bible file without book names + """ + # GIVEN: Test files with a mocked out "manager", "import_wizard", and mocked functions + # get_book_ref_id_by_name, create_verse, create_book, session and get_language. + result_file = open(os.path.join(TEST_PATH, 'rst.json'), 'rb') + test_data = json.loads(result_file.read().decode()) + bible_file = 'zefania-rst.xml' + with patch('openlp.plugins.bibles.lib.zefania.ZefaniaBible.application'): + mocked_manager = MagicMock() + mocked_import_wizard = MagicMock() + importer = ZefaniaBible(mocked_manager, path='.', name='.', filename='') + importer.wizard = mocked_import_wizard + importer.create_verse = MagicMock() + importer.create_book = MagicMock() + importer.session = MagicMock() + importer.get_language = MagicMock() + importer.get_language.return_value = 'Russian' + + # WHEN: Importing bible file + importer.filename = os.path.join(TEST_PATH, bible_file) + importer.do_import() + + # THEN: The create_verse() method should have been called with each verse in the file. + self.assertTrue(importer.create_verse.called) + for verse_tag, verse_text in test_data['verses']: + importer.create_verse.assert_any_call(importer.create_book().id, '1', verse_tag, verse_text) + importer.create_book.assert_any_call('Exodus', 2, 1) diff --git a/tests/resources/bibles/rst.json b/tests/resources/bibles/rst.json new file mode 100644 index 000000000..d8aca09ac --- /dev/null +++ b/tests/resources/bibles/rst.json @@ -0,0 +1,16 @@ +{ + "book": "Exodus", + "chapter": 1, + "verses": [ + [ "1", "Вот имена сынов Израилевых, которые вошли в Египет с Иаковом, вошли каждый с домом своим:" ], + [ "2", "Рувим, Симеон, Левий и Иуда," ], + [ "3", "Иссахар, Завулон и Вениамин," ], + [ "4", "Дан и Неффалим, Гад и Асир." ], + [ "5", "Всех же душ, происшедших от чресл Иакова, было семьдесят, а Иосиф был [уже] в Египте." ], + [ "6", "И умер Иосиф и все братья его и весь род их;" ], + [ "7", "а сыны Израилевы расплодились и размножились, и возросли и усилились чрезвычайно, и наполнилась ими земля та." ], + [ "8", "И восстал в Египте новый царь, который не знал Иосифа," ], + [ "9", "и сказал народу своему: вот, народ сынов Израилевых многочислен и сильнее нас;" ], + [ "10", "перехитрим же его, чтобы он не размножался; иначе, когда случится война, соединится и он с нашими неприятелями, и вооружится против нас, и выйдет из земли [нашей]." ] + ] +} diff --git a/tests/resources/bibles/zefania-rst.xml b/tests/resources/bibles/zefania-rst.xml new file mode 100644 index 000000000..72d1230a4 --- /dev/null +++ b/tests/resources/bibles/zefania-rst.xml @@ -0,0 +1,48 @@ + + + + + + + + Russian Synodal Translation + Zefania XML Bible Markup Language + 2009-01-20 + Jens Grabner + http://www.agape-biblia.org + http://www.crosswire.org/sword/modules/ + RUS + + RST + + 1876 Russian Synodal Translation, 1956 Edition + The text was supplied by "Light in East Germany". + + + + "Light in East Germany" Tel +49 711 83 30 57 + Postfach 1340 Fax +49 711 83 13 51 + 7015 Korntal + Munchingen 1 + Germany + + + + + + + + Вторая книга Моисеева. Исход + Вот имена сынов Израилевых, которые вошли в Египет с Иаковом, вошли каждый с домом своим: + Рувим, Симеон, Левий и Иуда, + Иссахар, Завулон и Вениамин, + Дан и Неффалим, Гад и Асир. + Всех же душ, происшедших от чресл Иакова, было семьдесят, а Иосиф был [уже] в Египте. + И умер Иосиф и все братья его и весь род их; + а сыны Израилевы расплодились и размножились, и возросли и усилились чрезвычайно, и наполнилась ими земля та. + И восстал в Египте новый царь, который не знал Иосифа, + и сказал народу своему: вот, народ сынов Израилевых многочислен и сильнее нас; + перехитрим же его, чтобы он не размножался; иначе, когда случится война, соединится и он с нашими неприятелями, и вооружится против нас, и выйдет из земли [нашей]. + + + From 7287759ba51e96ba680999b20075c83a714763cc Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Tue, 3 Feb 2015 23:41:30 +0000 Subject: [PATCH 2/6] Fixed a string --- openlp/core/lib/projector/constants.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openlp/core/lib/projector/constants.py b/openlp/core/lib/projector/constants.py index db2b66878..b7f8afe99 100644 --- a/openlp/core/lib/projector/constants.py +++ b/openlp/core/lib/projector/constants.py @@ -271,8 +271,8 @@ ERROR_MSG = {E_OK: translate('OpenLP.ProjectorConstants', 'OK'), # E_OK | S_OK E_PROXY_NOT_FOUND: translate('OpenLP.ProjectorConstants', 'The proxy address set with setProxy() was not found'), E_PROXY_PROTOCOL: translate('OpenLP.ProjectorConstants', - 'The connection negotiation with the proxy server because the response ' - 'from the proxy server could not be understood'), + 'The connection negotiation with the proxy server failed because the ' + 'response from the proxy server could not be understood'), E_UNKNOWN_SOCKET_ERROR: translate('OpenLP.ProjectorConstants', 'An unidentified error occurred'), S_NOT_CONNECTED: translate('OpenLP.ProjectorConstants', 'Not connected'), S_CONNECTING: translate('OpenLP.ProjectorConstants', 'Connecting'), From a5b92f1e875c41688313cce9724563ff69eb5fa1 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Fri, 6 Feb 2015 20:29:38 +0000 Subject: [PATCH 3/6] Fix parsing biblestudytools.com. Fixes bug 1418212. Fixes: https://launchpad.net/bugs/1418212 --- openlp/plugins/bibles/lib/http.py | 34 +++++++++---------------------- 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index 2f46efebd..7334dd259 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -365,31 +365,20 @@ class CWExtract(RegistryProperties): if not soup: return None self.application.process_events() - html_verses = soup.find_all('span', 'versetext') - if not html_verses: + verses_div = soup.find_all('div', 'verse') + if not verses_div: log.error('No verses found in the CrossWalk response.') send_error_message('parse') return None verses = {} - for verse in html_verses: + for verse in verses_div: self.application.process_events() - verse_number = int(verse.contents[0].contents[0]) - verse_text = '' - for part in verse.contents: - self.application.process_events() - if isinstance(part, NavigableString): - verse_text += part - elif part and part.attrMap and \ - (part.attrMap['class'] == 'WordsOfChrist' or part.attrMap['class'] == 'strongs'): - for subpart in part.contents: - self.application.process_events() - if isinstance(subpart, NavigableString): - verse_text += subpart - elif subpart and subpart.attrMap and subpart.attrMap['class'] == 'strongs': - for subsub in subpart.contents: - self.application.process_events() - if isinstance(subsub, NavigableString): - verse_text += subsub + verse_number = int(verse.find('strong').contents[0]) + verse_span = verse.find('span') + tags_to_remove = verse_span.find_all(['a', 'sup']) + for tag in tags_to_remove: + tag.decompose() + verse_text = verse_span.get_text() self.application.process_events() # Fix up leading and trailing spaces, multiple spaces, and spaces between text and , and . verse_text = verse_text.strip('\n\r\t ') @@ -409,16 +398,13 @@ class CWExtract(RegistryProperties): soup = get_soup_for_bible_ref(chapter_url) if not soup: return None - content = soup.find('div', {'class': 'Body'}) - content = content.find('ul', {'class': 'parent'}) + content = soup.find_all(('h4', {'class': 'small-header'})) if not content: log.error('No books found in the Crosswalk response.') send_error_message('parse') return None - content = content.find_all('li') books = [] for book in content: - book = book.find('a') books.append(book.contents[0]) return books From d8e6f35694d152aeabb68ea4992ae9a8ad04527c Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Fri, 6 Feb 2015 22:17:24 +0000 Subject: [PATCH 4/6] Handle OSError exception when creating files in various places. Fixes bug 1416888. Fixes: https://launchpad.net/bugs/1416888 --- openlp/core/ui/mainwindow.py | 24 ++++++++++++------- openlp/core/ui/servicemanager.py | 6 +++++ openlp/core/ui/thememanager.py | 21 ++++++++-------- openlp/plugins/songs/forms/songexportform.py | 16 ++++++++----- .../songusage/forms/songusagedetailform.py | 6 ++++- 5 files changed, 46 insertions(+), 27 deletions(-) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 2feab127e..b4413552e 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -989,15 +989,21 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow, RegistryProperties): # Read the temp file and output the user's CONF file with blanks to # make it more readable. temp_conf = open(temp_file, 'r') - export_conf = open(export_file_name, 'w') - for file_record in temp_conf: - # Get rid of any invalid entries. - if file_record.find('@Invalid()') == -1: - file_record = file_record.replace('%20', ' ') - export_conf.write(file_record) - temp_conf.close() - export_conf.close() - os.remove(temp_file) + try: + export_conf = open(export_file_name, 'w') + for file_record in temp_conf: + # Get rid of any invalid entries. + if file_record.find('@Invalid()') == -1: + file_record = file_record.replace('%20', ' ') + export_conf.write(file_record) + temp_conf.close() + export_conf.close() + os.remove(temp_file) + except OSError as ose: + QtGui.QMessageBox.critical(self, translate('OpenLP.MainWindow', 'Export setting error'), + translate('OpenLP.MainWindow', 'While writing the export file this error ' + 'occurred:\n%s') % str(ose), + QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok)) def on_mode_default_item_clicked(self): """ diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 8bdf9c383..61299d548 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -601,6 +601,12 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage shutil.copy(temp_file_name, path_file_name) except shutil.Error: return self.save_file_as() + except OSError as ose: + QtGui.QMessageBox.critical(self, translate('OpenLP.ServiceManager', 'Error Saving File'), + translate('OpenLP.ServiceManager', 'While writing the service file this ' + 'error occurred:\n%s') % str(ose), + QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok)) + success = False self.main_window.add_recent_file(path_file_name) self.set_modified(False) delete_file(temp_file_name) diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 5ced57ea7..e3df2f4fe 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -377,17 +377,11 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager, R self.application.set_busy_cursor() if path: Settings().setValue(self.settings_section + '/last directory export', path) - try: - self._export_theme(path, theme) + if self._export_theme(path, theme): QtGui.QMessageBox.information(self, translate('OpenLP.ThemeManager', 'Theme Exported'), translate('OpenLP.ThemeManager', 'Your theme has been successfully exported.')) - except (IOError, OSError): - self.log_exception('Export Theme Failed') - critical_error_message_box(translate('OpenLP.ThemeManager', 'Theme Export Failed'), - translate('OpenLP.ThemeManager', - 'Your theme could not be exported due to an error.')) self.application.set_normal_cursor() def _export_theme(self, path, theme): @@ -397,19 +391,24 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager, R :param theme: The name of the theme to be exported """ theme_path = os.path.join(path, theme + '.otz') + theme_zip = None try: theme_zip = zipfile.ZipFile(theme_path, 'w') source = os.path.join(self.path, theme) for files in os.walk(source): for name in files[2]: theme_zip.write(os.path.join(source, name), os.path.join(theme, name)) - except (IOError, OSError): + theme_zip.close() + return True + except OSError as ose: + self.log_exception('Export Theme Failed') + critical_error_message_box(translate('OpenLP.ThemeManager', 'Theme Export Failed'), + translate('OpenLP.ThemeManager', + 'Your theme could not be exported due to this error:\n%s' % str(ose))) if theme_zip: theme_zip.close() shutil.rmtree(theme_path, True) - raise - else: - theme_zip.close() + return False def on_import_theme(self, field=None): """ diff --git a/openlp/plugins/songs/forms/songexportform.py b/openlp/plugins/songs/forms/songexportform.py index 9caf7a446..a136ccee1 100644 --- a/openlp/plugins/songs/forms/songexportform.py +++ b/openlp/plugins/songs/forms/songexportform.py @@ -244,12 +244,16 @@ class SongExportForm(OpenLPWizard): for song in self._find_list_widget_items(self.selected_list_widget) ] exporter = OpenLyricsExport(self, songs, self.directory_line_edit.text()) - if exporter.do_export(): - self.progress_label.setText( - translate('SongsPlugin.SongExportForm', - 'Finished export. To import these files use the OpenLyrics importer.')) - else: - self.progress_label.setText(translate('SongsPlugin.SongExportForm', 'Your song export failed.')) + try: + if exporter.do_export(): + self.progress_label.setText( + translate('SongsPlugin.SongExportForm', + 'Finished export. To import these files use the OpenLyrics importer.')) + else: + self.progress_label.setText(translate('SongsPlugin.SongExportForm', 'Your song export failed.')) + except OSError as ose: + self.progress_label.setText(translate('SongsPlugin.SongExportForm', 'Your song export failed due to this ' + 'error:\n%s') % str(ose)) def _find_list_widget_items(self, list_widget, text=''): """ diff --git a/openlp/plugins/songusage/forms/songusagedetailform.py b/openlp/plugins/songusage/forms/songusagedetailform.py index ba65e21df..19da1f731 100644 --- a/openlp/plugins/songusage/forms/songusagedetailform.py +++ b/openlp/plugins/songusage/forms/songusagedetailform.py @@ -27,6 +27,7 @@ from PyQt4 import QtGui from sqlalchemy.sql import and_ from openlp.core.common import RegistryProperties, Settings, check_directory_exists, translate +from openlp.core.lib.ui import critical_error_message_box from openlp.plugins.songusage.lib.db import SongUsageItem from .songusagedetaildialog import Ui_SongUsageDetailDialog @@ -104,8 +105,11 @@ class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog, RegistryPrope translate('SongUsagePlugin.SongUsageDetailForm', 'Report \n%s \nhas been successfully created. ') % report_file_name ) - except IOError: + except OSError as ose: log.exception('Failed to write out song usage records') + critical_error_message_box(translate('SongUsagePlugin.SongUsageDetailForm', 'Report Creation Failed'), + translate('SongUsagePlugin.SongUsageDetailForm', + 'The report could not be created due to this error:\n%s' % str(ose))) finally: if file_handle: file_handle.close() From 2cdc1b2fe45af4b1ca59ba8bb01cb659474e25ac Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Fri, 6 Feb 2015 22:21:01 +0000 Subject: [PATCH 5/6] Remove print --- tests/functional/openlp_plugins/songs/test_songselect.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/functional/openlp_plugins/songs/test_songselect.py b/tests/functional/openlp_plugins/songs/test_songselect.py index 5ad3a594c..700933465 100644 --- a/tests/functional/openlp_plugins/songs/test_songselect.py +++ b/tests/functional/openlp_plugins/songs/test_songselect.py @@ -506,7 +506,6 @@ class TestSongSelectFileImport(TestCase, TestMixin): # WHEN: We call the song importer song_import.do_import() - print(song_import.verses) # THEN: Song values should be equal to test values in setUp self.assertEquals(song_import.title, self.title, 'Song title should match') self.assertEquals(song_import.ccli_number, self.ccli_number, 'CCLI Song Number should match') From bab5e90e205c9e0dc702a05719057f9573bc2cb4 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Tue, 10 Feb 2015 22:25:30 +0000 Subject: [PATCH 6/6] Adjust error messages. --- openlp/core/ui/mainwindow.py | 4 ++-- openlp/core/ui/servicemanager.py | 4 ++-- openlp/core/ui/thememanager.py | 4 ++-- openlp/plugins/songs/forms/songexportform.py | 4 ++-- openlp/plugins/songusage/forms/songusagedetailform.py | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index b4413552e..0e919871a 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -1001,8 +1001,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow, RegistryProperties): os.remove(temp_file) except OSError as ose: QtGui.QMessageBox.critical(self, translate('OpenLP.MainWindow', 'Export setting error'), - translate('OpenLP.MainWindow', 'While writing the export file this error ' - 'occurred:\n%s') % str(ose), + translate('OpenLP.MainWindow', 'An error occurred while exporting the ' + 'settings: %s') % ose.strerror, QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok)) def on_mode_default_item_clicked(self): diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 61299d548..0213fb02f 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -603,8 +603,8 @@ class ServiceManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ServiceManage return self.save_file_as() except OSError as ose: QtGui.QMessageBox.critical(self, translate('OpenLP.ServiceManager', 'Error Saving File'), - translate('OpenLP.ServiceManager', 'While writing the service file this ' - 'error occurred:\n%s') % str(ose), + translate('OpenLP.ServiceManager', 'An error occurred while writing the ' + 'service file: %s') % ose.strerror, QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok)) success = False self.main_window.add_recent_file(path_file_name) diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index e3df2f4fe..030516821 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -403,8 +403,8 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager, R except OSError as ose: self.log_exception('Export Theme Failed') critical_error_message_box(translate('OpenLP.ThemeManager', 'Theme Export Failed'), - translate('OpenLP.ThemeManager', - 'Your theme could not be exported due to this error:\n%s' % str(ose))) + translate('OpenLP.ThemeManager', 'The theme export failed because this error ' + 'occurred: %s') % ose.strerror) if theme_zip: theme_zip.close() shutil.rmtree(theme_path, True) diff --git a/openlp/plugins/songs/forms/songexportform.py b/openlp/plugins/songs/forms/songexportform.py index a136ccee1..f96c46638 100644 --- a/openlp/plugins/songs/forms/songexportform.py +++ b/openlp/plugins/songs/forms/songexportform.py @@ -252,8 +252,8 @@ class SongExportForm(OpenLPWizard): else: self.progress_label.setText(translate('SongsPlugin.SongExportForm', 'Your song export failed.')) except OSError as ose: - self.progress_label.setText(translate('SongsPlugin.SongExportForm', 'Your song export failed due to this ' - 'error:\n%s') % str(ose)) + self.progress_label.setText(translate('SongsPlugin.SongExportForm', 'Your song export failed because this ' + 'error occurred: %s') % ose.strerror) def _find_list_widget_items(self, list_widget, text=''): """ diff --git a/openlp/plugins/songusage/forms/songusagedetailform.py b/openlp/plugins/songusage/forms/songusagedetailform.py index 19da1f731..a4136e88b 100644 --- a/openlp/plugins/songusage/forms/songusagedetailform.py +++ b/openlp/plugins/songusage/forms/songusagedetailform.py @@ -109,7 +109,7 @@ class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog, RegistryPrope log.exception('Failed to write out song usage records') critical_error_message_box(translate('SongUsagePlugin.SongUsageDetailForm', 'Report Creation Failed'), translate('SongUsagePlugin.SongUsageDetailForm', - 'The report could not be created due to this error:\n%s' % str(ose))) + 'An error occurred while creating the report: %s') % ose.strerror) finally: if file_handle: file_handle.close()