From a31f2c68f6a0b7eab894fde4a368e78f2864fae1 Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Tue, 11 Mar 2014 22:34:35 +0200 Subject: [PATCH 1/7] Fix bug #1136278 by trying to detect that the upgrades have already been performed --- openlp/plugins/bibles/lib/upgrade.py | 49 ++++++++++++--------- openlp/plugins/songs/lib/upgrade.py | 58 ++++++++++++++++++------- openlp/plugins/songusage/lib/upgrade.py | 15 +++++-- 3 files changed, 81 insertions(+), 41 deletions(-) diff --git a/openlp/plugins/bibles/lib/upgrade.py b/openlp/plugins/bibles/lib/upgrade.py index 8598ed8ea..5d89018c3 100644 --- a/openlp/plugins/bibles/lib/upgrade.py +++ b/openlp/plugins/bibles/lib/upgrade.py @@ -37,6 +37,7 @@ from sqlalchemy import Table, func, select, insert __version__ = 1 log = logging.getLogger(__name__) + def upgrade_setup(metadata): """ Set up the latest revision all tables, with reflection, needed for the @@ -61,31 +62,37 @@ def upgrade_1(session, metadata, tables): metadata_table = metadata.tables[u'metadata'] # Copy "Version" to "name" ("version" used by upgrade system) # TODO: Clean up in a subsequent release of OpenLP (like 2.0 final) - session.execute(insert(metadata_table).values( - key=u'name', - value=select( - [metadata_table.c.value], - metadata_table.c.key == u'Version' - ).as_scalar() - )) + if select([metadata_table.c.value], metadata_table.c.key == u'Version')\ + .as_scalar().execute().fetchall(): + session.execute(insert(metadata_table).values( + key=u'name', + value=select( + [metadata_table.c.value], + metadata_table.c.key == u'Version' + ).as_scalar() + )) # Copy "Copyright" to "copyright" # TODO: Clean up in a subsequent release of OpenLP (like 2.0 final) - session.execute(insert(metadata_table).values( - key=u'copyright', - value=select( - [metadata_table.c.value], - metadata_table.c.key == u'Copyright' - ).as_scalar() - )) + if select([metadata_table.c.value], metadata_table.c.key == u'Copyright')\ + .as_scalar().execute().fetchall(): + session.execute(insert(metadata_table).values( + key=u'copyright', + value=select( + [metadata_table.c.value], + metadata_table.c.key == u'Copyright' + ).as_scalar() + )) # Copy "Permissions" to "permissions" # TODO: Clean up in a subsequent release of OpenLP (like 2.0 final) - session.execute(insert(metadata_table).values( - key=u'permissions', - value=select( - [metadata_table.c.value], - metadata_table.c.key == u'Permissions' - ).as_scalar() - )) + if select([metadata_table.c.value], metadata_table.c.key == u'Permissions')\ + .as_scalar().execute().fetchall(): + session.execute(insert(metadata_table).values( + key=u'permissions', + value=select( + [metadata_table.c.value], + metadata_table.c.key == u'Permissions' + ).as_scalar() + )) # Copy "Bookname language" to "book_name_language" # TODO: Clean up in a subsequent release of OpenLP (like 2.0 final) value_count = session.execute( diff --git a/openlp/plugins/songs/lib/upgrade.py b/openlp/plugins/songs/lib/upgrade.py index 02759f4ae..c99ec06fb 100644 --- a/openlp/plugins/songs/lib/upgrade.py +++ b/openlp/plugins/songs/lib/upgrade.py @@ -30,18 +30,24 @@ The :mod:`upgrade` module provides a way for the database and schema that is the backend for the Songs plugin """ +import logging from sqlalchemy import Column, Table, types +from sqlalchemy.exc import NoSuchTableError, OperationalError from sqlalchemy.sql.expression import func from migrate.changeset.constraint import ForeignKeyConstraint +log = logging.getLogger(__name__) __version__ = 3 + def upgrade_setup(metadata): """ Set up the latest revision all tables, with reflection, needed for the upgrade process. If you want to drop a table, you need to remove it from here, and add it to your upgrade function. + + :param metadata: The SQLAlchemy metadata object """ tables = { u'authors': Table(u'authors', metadata, autoload=True), @@ -66,16 +72,23 @@ def upgrade_1(session, metadata, tables): In order to facilitate this one-to-many relationship, a song_id column is added to the media_files table, and a weight column so that the media files can be ordered. + + :param session: An SQLAlchemy Session object + :param metadata: An SQLAlchemy MetaData object + :param tables: A dictionary of tables """ - Table(u'media_files_songs', metadata, autoload=True).drop(checkfirst=True) - Column(u'song_id', types.Integer(), default=None)\ - .create(table=tables[u'media_files']) - Column(u'weight', types.Integer(), default=0)\ - .create(table=tables[u'media_files']) - if metadata.bind.url.get_dialect().name != 'sqlite': - # SQLite doesn't support ALTER TABLE ADD CONSTRAINT - ForeignKeyConstraint([u'song_id'], [u'songs.id'], - table=tables[u'media_files']).create() + try: + Table(u'media_files_songs', metadata, autoload=True).drop(checkfirst=True) + Column(u'song_id', types.Integer(), default=None)\ + .create(table=tables[u'media_files']) + Column(u'weight', types.Integer(), default=0)\ + .create(table=tables[u'media_files']) + if metadata.bind.url.get_dialect().name != 'sqlite': + # SQLite doesn't support ALTER TABLE ADD CONSTRAINT + ForeignKeyConstraint([u'song_id'], [u'songs.id'], + table=tables[u'media_files']).create() + except (NoSuchTableError, OperationalError): + log.info(u'Upgrade 1 has already been run, continue with upgrade') def upgrade_2(session, metadata, tables): @@ -83,11 +96,18 @@ def upgrade_2(session, metadata, tables): Version 2 upgrade. This upgrade adds a create_date and last_modified date to the songs table + + :param session: An SQLAlchemy Session object + :param metadata: An SQLAlchemy MetaData object + :param tables: A dictionary of tables """ - Column(u'create_date', types.DateTime(), default=func.now())\ - .create(table=tables[u'songs']) - Column(u'last_modified', types.DateTime(), default=func.now())\ - .create(table=tables[u'songs']) + try: + Column(u'create_date', types.DateTime(), default=func.now())\ + .create(table=tables[u'songs']) + Column(u'last_modified', types.DateTime(), default=func.now())\ + .create(table=tables[u'songs']) + except OperationalError: + log.info(u'Upgrade 2 has already been run, continue with upgrade') def upgrade_3(session, metadata, tables): @@ -95,7 +115,13 @@ def upgrade_3(session, metadata, tables): Version 3 upgrade. This upgrade adds a temporary song flag to the songs table - """ - Column(u'temporary', types.Boolean(), default=False)\ - .create(table=tables[u'songs']) + :param session: An SQLAlchemy Session object + :param metadata: An SQLAlchemy MetaData object + :param tables: A dictionary of tables + """ + try: + Column(u'temporary', types.Boolean(), default=False)\ + .create(table=tables[u'songs']) + except OperationalError: + log.info(u'Upgrade 3 has already been run, continue with upgrade') diff --git a/openlp/plugins/songusage/lib/upgrade.py b/openlp/plugins/songusage/lib/upgrade.py index 8010f710b..c7cf778e8 100644 --- a/openlp/plugins/songusage/lib/upgrade.py +++ b/openlp/plugins/songusage/lib/upgrade.py @@ -30,11 +30,15 @@ The :mod:`upgrade` module provides a way for the database and schema that is the backend for the SongsUsage plugin """ +import logging from sqlalchemy import Column, Table, types +from sqlalchemy.exc import OperationalError +log = logging.getLogger(__name__) __version__ = 1 + def upgrade_setup(metadata): """ Set up the latest revision all tables, with reflection, needed for the @@ -53,7 +57,10 @@ def upgrade_1(session, metadata, tables): This upgrade adds two new fields to the songusage database """ - Column(u'plugin_name', types.Unicode(20), default=u'') \ - .create(table=tables[u'songusage_data'], populate_default=True) - Column(u'source', types.Unicode(10), default=u'') \ - .create(table=tables[u'songusage_data'], populate_default=True) + try: + Column(u'plugin_name', types.Unicode(20), default=u'') \ + .create(table=tables[u'songusage_data'], populate_default=True) + Column(u'source', types.Unicode(10), default=u'') \ + .create(table=tables[u'songusage_data'], populate_default=True) + except OperationalError: + log.info(u'Upgrade 1 has already been run, continue with upgrade') From ad0e6a29f20b1a32ce5b453b83509f34ba5918be Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Sat, 22 Mar 2014 18:59:22 +0100 Subject: [PATCH 2/7] Fixed bug #1296104 ( Renderer broken when two option breaks next to each other) Fixes: https://launchpad.net/bugs/1296104 --- openlp/core/lib/renderer.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index 411575d77..a1f64804f 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -284,6 +284,9 @@ class Renderer(object): elif item.is_capable(ItemCapabilities.CanSoftBreak): pages = [] if u'[---]' in text: + # Remove two or more option slide breaks next to each other (causing infinite loop). + while u'\n[---]\n[---]\n' in text: + text = text.replace(u'\n[---]\n[---]\n', u'\n[---]\n') while True: slides = text.split(u'\n[---]\n', 2) # If there are (at least) two occurrences of [---] we use From 8662e76ccf1754c1fe7c16597834e5bf7fca6eb5 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Mon, 21 Apr 2014 11:18:52 +0200 Subject: [PATCH 3/7] Fix bug 1310523 Fixes: https://launchpad.net/bugs/1310523 --- openlp/plugins/songs/lib/xml.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index d53bda886..06df206fb 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -360,9 +360,9 @@ class OpenLyrics(object): verse_tag = verse[0][u'type'][0].lower() verse_number = verse[0][u'label'] verse_def = verse_tag + verse_number - verse_tags.append(verse_def) # Create the letter from the number of duplicates - verse[0][u'suffix'] = chr(96 + verse_tags.count(verse_def)) + verse[0][u'suffix'] = chr(97 + (verse_tags.count(verse_def) % 26)) + verse_tags.append(verse_def) # If the verse tag is a duplicate use the suffix letter for verse in verse_list: verse_tag = verse[0][u'type'][0].lower() From c4b4df4990e1f87f5ec72c92c774f924dd0f41aa Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Mon, 21 Apr 2014 15:40:30 +0200 Subject: [PATCH 4/7] Check on song edit form for equal verse names --- openlp/plugins/songs/forms/editsongform.py | 24 +++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 781cf691f..793f7af89 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -723,19 +723,33 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): return False cnt_errors = 0 error_list = '' - verse_tag = [] - verse_num = [] + verse_tags = [] + wrong_verse_tags = [] + wrong_verse_nums = [] for i in range(self.verseListWidget.rowCount()): item = self.verseListWidget.item(i, 0) tags = self.find_tags.findall(item.text()) + verse_tags.append(unicode(item.data(QtCore.Qt.UserRole).toString())) if self._validate_tags(tags) == False: field = unicode(item.data(QtCore.Qt.UserRole).toString()) - verse_tag.append(VerseType.translated_name(field[0])) - verse_num.append(field[1:]) + wrong_verse_tags.append(VerseType.translated_name(field[0])) + wrong_verse_nums.append(field[1:]) cnt_errors += 1; + for tag in verse_tags: + if verse_tags.count(tag) > 26: + # lp#1310523: OpenLyrics allows only a-z variants of one verse: + # http://openlyrics.info/dataformat.html#verse-name + print tag + critical_error_message_box( + message=translate('SongsPlugin.EditSongForm', + 'You have %(count)s verses named %(name)s %(number)s. ' + 'You can have at most 26 verses with the same name' % + {'count': verse_tags.count(tag), 'name': VerseType.translated_name(tag[0]), + 'number': tag[1:]})) + return False if cnt_errors > 0: for i in range(cnt_errors): - error_list += '%s %s' % (verse_tag[i], verse_num[i]) + error_list += '%s %s' % (wrong_verse_tags[i], wrong_verse_nums[i]) if i < cnt_errors-1: error_list += ', ' critical_error_message_box( From 20e9c1dd4c1d83aa233a26d965ba6de9632c58e2 Mon Sep 17 00:00:00 2001 From: Samuel Mehrbrodt Date: Mon, 21 Apr 2014 15:41:18 +0200 Subject: [PATCH 5/7] Remove print --- openlp/plugins/songs/forms/editsongform.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 793f7af89..8cbfb1c07 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -739,7 +739,6 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): if verse_tags.count(tag) > 26: # lp#1310523: OpenLyrics allows only a-z variants of one verse: # http://openlyrics.info/dataformat.html#verse-name - print tag critical_error_message_box( message=translate('SongsPlugin.EditSongForm', 'You have %(count)s verses named %(name)s %(number)s. ' From 764768f8acc3e622a699b27d62caf18a59f449e3 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Thu, 15 May 2014 21:19:53 +0200 Subject: [PATCH 6/7] fixed bug #1299837 - crash when importing EW DB with unexpected data formatting Fixes: https://launchpad.net/bugs/1299837 --- openlp/plugins/songs/lib/ewimport.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/openlp/plugins/songs/lib/ewimport.py b/openlp/plugins/songs/lib/ewimport.py index 837200aca..7dd122bf9 100644 --- a/openlp/plugins/songs/lib/ewimport.py +++ b/openlp/plugins/songs/lib/ewimport.py @@ -188,7 +188,14 @@ class EasyWorshipSongImport(SongImport): self.addAuthor(author_name.strip()) if words: # Format the lyrics - result = strip_rtf(words, self.encoding) + result = None + try: + result = strip_rtf(words, self.encoding) + except UnicodeDecodeError: + # The unicode chars in the rtf was not escaped in the expected manor + self.logError(self.title, unicode(translate('SongsPlugin.EasyWorshipSongImport', + 'Unexpected data formatting.'))) + continue if result is None: return words, self.encoding = result From bc1675419d53788cb5e585ea97239c8245217383 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Tue, 20 May 2014 18:19:06 +0200 Subject: [PATCH 7/7] Fixed spelling in comment. --- openlp/plugins/songs/lib/ewimport.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openlp/plugins/songs/lib/ewimport.py b/openlp/plugins/songs/lib/ewimport.py index 7dd122bf9..0d95cf548 100644 --- a/openlp/plugins/songs/lib/ewimport.py +++ b/openlp/plugins/songs/lib/ewimport.py @@ -192,7 +192,7 @@ class EasyWorshipSongImport(SongImport): try: result = strip_rtf(words, self.encoding) except UnicodeDecodeError: - # The unicode chars in the rtf was not escaped in the expected manor + # The unicode chars in the rtf was not escaped in the expected manner. self.logError(self.title, unicode(translate('SongsPlugin.EasyWorshipSongImport', 'Unexpected data formatting.'))) continue