diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index 64b024639..6b26dfabe 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -225,7 +225,7 @@ class BGExtract(RegistryProperties): url_book_name = urllib.parse.quote(book_name.encode("utf-8")) url_params = 'search=%s+%s&version=%s' % (url_book_name, chapter, version) soup = get_soup_for_bible_ref( - 'http://www.biblegateway.com/passage/?%s' % url_params, + 'http://legacy.biblegateway.com/passage/?%s' % url_params, pre_parse_regex=r'', pre_parse_substitute='') if not soup: return None @@ -252,7 +252,7 @@ class BGExtract(RegistryProperties): """ log.debug('BGExtract.get_books_from_http("%s")', version) url_params = urllib.parse.urlencode({'action': 'getVersionInfo', 'vid': '%s' % version}) - reference_url = 'http://www.biblegateway.com/versions/?%s#books' % url_params + reference_url = 'http://legacy.biblegateway.com/versions/?%s#books' % url_params page = get_web_page(reference_url) if not page: send_error_message('download') diff --git a/openlp/plugins/songs/lib/cclifileimport.py b/openlp/plugins/songs/lib/cclifileimport.py index eda235ca1..69c20d1cc 100644 --- a/openlp/plugins/songs/lib/cclifileimport.py +++ b/openlp/plugins/songs/lib/cclifileimport.py @@ -64,7 +64,7 @@ class CCLIFileImport(SongImport): filename = str(filename) log.debug('Importing CCLI File: %s', filename) if os.path.isfile(filename): - detect_file = open(filename, 'r') + detect_file = open(filename, 'rb') detect_content = detect_file.read(2048) try: str(detect_content, 'utf-8') diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 7ce637285..6d01da309 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -50,6 +50,7 @@ from .sundayplusimport import SundayPlusImport from .foilpresenterimport import FoilPresenterImport from .zionworximport import ZionWorxImport from .propresenterimport import ProPresenterImport +from .worshipassistantimport import WorshipAssistantImport # Imports that might fail @@ -167,8 +168,9 @@ class SongFormat(object): SongsOfFellowship = 16 SundayPlus = 17 WordsOfWorship = 18 - WorshipCenterPro = 19 - ZionWorx = 20 + WorshipAssistant = 19 + WorshipCenterPro = 20 + ZionWorx = 21 # Set optional attribute defaults __defaults__ = { @@ -321,6 +323,16 @@ class SongFormat(object): 'prefix': 'wordsOfWorship', 'filter': '%s (*.wsg *.wow-song)' % translate('SongsPlugin.ImportWizardForm', 'Words Of Worship Song Files') }, + WorshipAssistant: { + 'class': WorshipAssistantImport, + 'name': 'Worship Assistant 0', + 'prefix': 'worshipAssistant', + 'selectMode': SongFormatSelect.SingleFile, + 'filter': '%s (*.csv)' % translate('SongsPlugin.ImportWizardForm', 'Worship Assistant Files'), + 'comboBoxText': translate('SongsPlugin.ImportWizardForm', 'Worship Assistant (CSV)'), + 'descriptionText': translate('SongsPlugin.ImportWizardForm', + 'In Worship Assistant, export your Database to a CSV file.') + }, WorshipCenterPro: { 'name': 'WorshipCenter Pro', 'prefix': 'worshipCenterPro', @@ -370,16 +382,17 @@ class SongFormat(object): SongFormat.SongsOfFellowship, SongFormat.SundayPlus, SongFormat.WordsOfWorship, + SongFormat.WorshipAssistant, SongFormat.WorshipCenterPro, SongFormat.ZionWorx ] @staticmethod - def get(format, *attributes): + def get(song_format, *attributes): """ Return requested song format attribute(s). - :param format: A song format from SongFormat. + :param song_format: A song format from SongFormat. :param attributes: Zero or more song format attributes from SongFormat. Return type depends on number of supplied attributes: @@ -389,23 +402,23 @@ class SongFormat(object): :>1: Return tuple of requested attribute values. """ if not attributes: - return SongFormat.__attributes__.get(format) + return SongFormat.__attributes__.get(song_format) elif len(attributes) == 1: default = SongFormat.__defaults__.get(attributes[0]) - return SongFormat.__attributes__[format].get(attributes[0], default) + return SongFormat.__attributes__[song_format].get(attributes[0], default) else: values = [] for attr in attributes: default = SongFormat.__defaults__.get(attr) - values.append(SongFormat.__attributes__[format].get(attr, default)) + values.append(SongFormat.__attributes__[song_format].get(attr, default)) return tuple(values) @staticmethod - def set(format, attribute, value): + def set(song_format, attribute, value): """ Set specified song format attribute to the supplied value. """ - SongFormat.__attributes__[format][attribute] = value + SongFormat.__attributes__[song_format][attribute] = value SongFormat.set(SongFormat.SongsOfFellowship, 'availability', HAS_SOF) diff --git a/openlp/plugins/songs/lib/worshipassistantimport.py b/openlp/plugins/songs/lib/worshipassistantimport.py new file mode 100644 index 000000000..772fe8622 --- /dev/null +++ b/openlp/plugins/songs/lib/worshipassistantimport.py @@ -0,0 +1,171 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2014 Raoul Snyman # +# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan # +# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, # +# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. # +# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, # +# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # +# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, # +# Frode Woldsund, Martin Zibricky, Patrick Zimmermann # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +The :mod:`worshipassistantimport` module provides the functionality for importing +Worship Assistant songs into the OpenLP database. +""" +import chardet +import csv +import logging +import re + +from openlp.core.common import translate +from openlp.plugins.songs.lib import VerseType +from openlp.plugins.songs.lib.songimport import SongImport + +log = logging.getLogger(__name__) + +EMPTY_STR = 'NULL' + + +class WorshipAssistantImport(SongImport): + """ + The :class:`WorshipAssistantImport` class provides the ability to import songs + from Worship Assistant, via a dump of the database to a CSV file. + + The following fields are in the exported CSV file: + + * ``SONGNR`` Song ID (Discarded by importer) + * ``TITLE`` Song title + * ``AUTHOR`` Song author. + * ``COPYRIGHT`` Copyright information + * ``FIRSTLINE`` Unknown (Discarded by importer) + * ``PRIKEY`` Primary chord key (Discarded by importer) + * ``ALTKEY`` Alternate chord key (Discarded by importer) + * ``TEMPO`` Tempo (Discarded by importer) + * ``FOCUS`` Unknown (Discarded by importer) + * ``THEME`` Theme (Discarded by importer) + * ``SCRIPTURE`` Associated scripture (Discarded by importer) + * ``ACTIVE`` Boolean value (Discarded by importer) + * ``SONGBOOK`` Boolean value (Discarded by importer) + * ``TIMESIG`` Unknown (Discarded by importer) + * ``INTRODUCED`` Date the song was created (Discarded by importer) + * ``LASTUSED`` Date the song was last used (Discarded by importer) + * ``TIMESUSED`` How many times the song was used (Discarded by importer) + * ``CCLINR`` CCLI Number + * ``USER1`` User Field 1 (Discarded by importer) + * ``USER2`` User Field 2 (Discarded by importer) + * ``USER3`` User Field 3 (Discarded by importer) + * ``USER4`` User Field 4 (Discarded by importer) + * ``USER5`` User Field 5 (Discarded by importer) + * ``ROADMAP`` Verse order used for the presentation + * ``FILELINK1`` Associated file 1 (Discarded by importer) + * ``OVERMAP`` Verse order used for printing (Discarded by importer) + * ``FILELINK2`` Associated file 2 (Discarded by importer) + * ``LYRICS`` The song lyrics used for printing (Discarded by importer, LYRICS2 is used instead) + * ``INFO`` Unknown (Discarded by importer) + * ``LYRICS2`` The song lyrics used for the presentation + * ``BACKGROUND`` Custom background (Discarded by importer) + """ + def do_import(self): + """ + Receive a CSV file to import. + """ + # Get encoding + detect_file = open(self.import_source, 'rb') + detect_content = detect_file.read() + details = chardet.detect(detect_content) + detect_file.close() + songs_file = open(self.import_source, 'r', encoding=details['encoding']) + songs_reader = csv.DictReader(songs_file) + try: + records = list(songs_reader) + except csv.Error as e: + self.log_error(translate('SongsPlugin.WorshipAssistantImport', 'Error reading CSV file.'), + translate('SongsPlugin.WorshipAssistantImport', 'Line %d: %s') % + (songs_reader.line_num, e)) + return + num_records = len(records) + log.info('%s records found in CSV file' % num_records) + self.import_wizard.progress_bar.setMaximum(num_records) + for index, record in enumerate(records, 1): + if self.stop_import_flag: + return + # Ensure that all keys are uppercase + record = dict((field.upper(), value) for field, value in record.items()) + # The CSV file has a line in the middle of the file where the headers are repeated. + # We need to skip this line. + if record['TITLE'] == "TITLE" and record['AUTHOR'] == 'AUTHOR' and record['LYRICS2'] == 'LYRICS2': + continue + self.set_defaults() + verse_order_list = [] + try: + self.title = record['TITLE'] + if record['AUTHOR'] != EMPTY_STR: + self.parse_author(record['AUTHOR']) + print(record['AUTHOR']) + if record['COPYRIGHT'] != EMPTY_STR: + self.add_copyright(record['COPYRIGHT']) + if record['CCLINR'] != EMPTY_STR: + self.ccli_number = record['CCLINR'] + if record['ROADMAP'] != EMPTY_STR: + verse_order_list = record['ROADMAP'].split(',') + lyrics = record['LYRICS2'] + except UnicodeDecodeError as e: + self.log_error(translate('SongsPlugin.WorshipAssistantImport', 'Record %d' % index), + translate('SongsPlugin.WorshipAssistantImport', 'Decoding error: %s') % e) + continue + except TypeError as e: + self.log_error(translate('SongsPlugin.WorshipAssistantImport', + 'File not valid WorshipAssistant CSV format.'), 'TypeError: %s' % e) + return + verse = '' + for line in lyrics.splitlines(): + if line.startswith('['): # verse marker + # drop the square brackets + right_bracket = line.find(']') + content = line[1:right_bracket].lower() + match = re.match('(\D*)(\d+)', content) + if match is not None: + verse_tag = match.group(1) + verse_num = match.group(2) + else: + # otherwise we assume number 1 and take the whole prefix as the verse tag + verse_tag = content + verse_num = '1' + verse_index = VerseType.from_loose_input(verse_tag) if verse_tag else 0 + verse_tag = VerseType.tags[verse_index] + # Update verse order when the verse name has changed + if content != verse_tag + verse_num: + for i in range(len(verse_order_list)): + if verse_order_list[i].lower() == content.lower(): + verse_order_list[i] = verse_tag + verse_num + elif line and not line.isspace(): + verse += line + '\n' + elif verse: + self.add_verse(verse, verse_tag+verse_num) + verse = '' + if verse: + self.add_verse(verse, verse_tag+verse_num) + if verse_order_list: + self.verse_order_list = verse_order_list + if not self.finish(): + self.log_error(translate('SongsPlugin.WorshipAssistantImport', 'Record %d') % index + + (': "' + self.title + '"' if self.title else '')) + songs_file.close() diff --git a/tests/functional/openlp_plugins/songs/test_opensongimport.py b/tests/functional/openlp_plugins/songs/test_opensongimport.py index 70d3b342a..96d6bff0b 100644 --- a/tests/functional/openlp_plugins/songs/test_opensongimport.py +++ b/tests/functional/openlp_plugins/songs/test_opensongimport.py @@ -52,11 +52,11 @@ class TestOpenSongFileImport(SongImportTestHelper): """ Test that loading an OpenSong file works correctly on various files """ - self.file_import(os.path.join(TEST_PATH, 'Amazing Grace'), + self.file_import([os.path.join(TEST_PATH, 'Amazing Grace')], self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json'))) - self.file_import(os.path.join(TEST_PATH, 'Beautiful Garden Of Prayer'), + self.file_import([os.path.join(TEST_PATH, 'Beautiful Garden Of Prayer')], self.load_external_result_data(os.path.join(TEST_PATH, 'Beautiful Garden Of Prayer.json'))) - self.file_import(os.path.join(TEST_PATH, 'One, Two, Three, Four, Five'), + self.file_import([os.path.join(TEST_PATH, 'One, Two, Three, Four, Five')], self.load_external_result_data(os.path.join(TEST_PATH, 'One, Two, Three, Four, Five.json'))) diff --git a/tests/functional/openlp_plugins/songs/test_propresenterimport.py b/tests/functional/openlp_plugins/songs/test_propresenterimport.py index 971ddbdf6..10e2defc6 100644 --- a/tests/functional/openlp_plugins/songs/test_propresenterimport.py +++ b/tests/functional/openlp_plugins/songs/test_propresenterimport.py @@ -50,5 +50,5 @@ class TestProPresenterFileImport(SongImportTestHelper): """ Test that loading an ProPresenter file works correctly """ - self.file_import(os.path.join(TEST_PATH, 'Amazing Grace.pro4'), + self.file_import([os.path.join(TEST_PATH, 'Amazing Grace.pro4')], self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json'))) diff --git a/tests/functional/openlp_plugins/songs/test_songshowplusimport.py b/tests/functional/openlp_plugins/songs/test_songshowplusimport.py index 08400fdc5..dfee265e3 100644 --- a/tests/functional/openlp_plugins/songs/test_songshowplusimport.py +++ b/tests/functional/openlp_plugins/songs/test_songshowplusimport.py @@ -53,11 +53,11 @@ class TestSongShowPlusFileImport(SongImportTestHelper): """ Test that loading a SongShow Plus file works correctly on various files """ - self.file_import(os.path.join(TEST_PATH, 'Amazing Grace.sbsong'), + self.file_import([os.path.join(TEST_PATH, 'Amazing Grace.sbsong')], self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json'))) - self.file_import(os.path.join(TEST_PATH, 'Beautiful Garden Of Prayer.sbsong'), + self.file_import([os.path.join(TEST_PATH, 'Beautiful Garden Of Prayer.sbsong')], self.load_external_result_data(os.path.join(TEST_PATH, 'Beautiful Garden Of Prayer.json'))) - self.file_import(os.path.join(TEST_PATH, 'a mighty fortress is our god.sbsong'), + self.file_import([os.path.join(TEST_PATH, 'a mighty fortress is our god.sbsong')], self.load_external_result_data(os.path.join(TEST_PATH, 'a mighty fortress is our god.json'))) diff --git a/tests/functional/openlp_plugins/songs/test_worshipassistantimport.py b/tests/functional/openlp_plugins/songs/test_worshipassistantimport.py new file mode 100644 index 000000000..c0c5c7416 --- /dev/null +++ b/tests/functional/openlp_plugins/songs/test_worshipassistantimport.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2013 Raoul Snyman # +# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan # +# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, # +# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. # +# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, # +# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # +# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, # +# Frode Woldsund, Martin Zibricky, Patrick Zimmermann # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +The :mod:`worshipassistantimport` module provides the functionality for importing +WorshipAssistant song files into the current installation database. +""" + +import os + +from tests.helpers.songfileimport import SongImportTestHelper + +TEST_PATH = os.path.abspath( + os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'worshipassistantsongs')) + + +class TestWorshipAssistantFileImport(SongImportTestHelper): + + def __init__(self, *args, **kwargs): + self.importer_class_name = 'WorshipAssistantImport' + self.importer_module_name = 'worshipassistantimport' + super(TestWorshipAssistantFileImport, self).__init__(*args, **kwargs) + + def test_song_import(self): + """ + Test that loading an Worship Assistant file works correctly + """ + self.file_import(os.path.join(TEST_PATH, 'du_herr.csv'), + self.load_external_result_data(os.path.join(TEST_PATH, 'du_herr.json'))) + self.file_import(os.path.join(TEST_PATH, 'would_you_be_free.csv'), + self.load_external_result_data(os.path.join(TEST_PATH, 'would_you_be_free.json'))) diff --git a/tests/helpers/songfileimport.py b/tests/helpers/songfileimport.py index 36beef6e5..80b2ee268 100644 --- a/tests/helpers/songfileimport.py +++ b/tests/helpers/songfileimport.py @@ -95,7 +95,7 @@ class SongImportTestHelper(TestCase): importer.topics = [] # WHEN: Importing the source file - importer.import_source = [source_file_name] + importer.import_source = source_file_name add_verse_calls = self._get_data(result_data, 'verses') author_calls = self._get_data(result_data, 'authors') ccli_number = self._get_data(result_data, 'ccli_number') diff --git a/tests/resources/worshipassistantsongs/du_herr.csv b/tests/resources/worshipassistantsongs/du_herr.csv new file mode 100644 index 000000000..72c5b4735 --- /dev/null +++ b/tests/resources/worshipassistantsongs/du_herr.csv @@ -0,0 +1,30 @@ +"SongID","SongNr","Title","Author","Copyright","FirstLine","PriKey","AltKey","Tempo","Focus","Theme","Scripture","Active","Songbook","TimeSig","Introduced","LastUsed","TimesUsed","CCLINr","User1","User2","User3","User4","User5","Roadmap","Overmap","FileLink1","FileLink2","Updated","Lyrics","Info","Lyrics2","Background" +"4ee399dc-edda-4aa9-891e-a859ca093c78","NULL","Du, Herr, verläßt mich nicht","Carl Brockhaus / Johann Georg Bäßler 1806","NULL","NULL","NULL","NULL","NULL","NULL","NULL","NULL","1","1","NULL","NULL","NULL","NULL","NULL","NULL","NULL","NULL","NULL","NULL","NULL","NULL","NULL","NULL","2014-06-25 12:15:28.317","","NULL","[1] +Du, Herr, verläßt mich nicht. +Auf Dich mein Herz allein vertraut, +Mein Auge glaubend auf Dich schaut. +Du bist mein Heil, mein Licht, +Mein Fels, mein sichrer Hort. +Bin ich versucht, gibt's Not und Leid, +Du bleibst mein Trost, mein Arm im Streit, +Mein Licht am dunklen Ort. + +[2] +Ich weiß, daß Du mich liebst. +Bist mir in jeder Lage nah', +Wohin ich gehe – Du bist da, +Ja, Du mir alles gibst. +Ich überlaß mich Dir; +Denn Du, Herr, kennst mich ganz und gar +Und führst mich sicher, wunderbar, +Und bist selbst alles mir. + +[3] +In dieser Wüste hier +Find't nirgend meine Seele Ruh', +Denn meine Ruh' bist, Jesu, Du. +Wohl mir, ich geh' zu Dir! +Bald werd' ich bei Dir sein, +Bald mit den Deinen ewiglich +Anbeten, loben, preisen Dich, +Mich Deiner stets erfreun.","NULL" diff --git a/tests/resources/worshipassistantsongs/du_herr.json b/tests/resources/worshipassistantsongs/du_herr.json new file mode 100644 index 000000000..1df700df8 --- /dev/null +++ b/tests/resources/worshipassistantsongs/du_herr.json @@ -0,0 +1,21 @@ +{ + "authors": [ + "Carl Brockhaus / Johann Georg Bäßler 1806" + ], + "title": "Du, Herr, verläßt mich nicht", + "verse_order_list": [], + "verses": [ + [ + "Du, Herr, verläßt mich nicht.\nAuf Dich mein Herz allein vertraut,\nMein Auge glaubend auf Dich schaut.\nDu bist mein Heil, mein Licht,\nMein Fels, mein sichrer Hort.\nBin ich versucht, gibt's Not und Leid,\nDu bleibst mein Trost, mein Arm im Streit,\nMein Licht am dunklen Ort.\n", + "v1" + ], + [ + "Ich weiß, daß Du mich liebst.\nBist mir in jeder Lage nah',\nWohin ich gehe – Du bist da,\nJa, Du mir alles gibst.\nIch überlaß mich Dir;\nDenn Du, Herr, kennst mich ganz und gar\nUnd führst mich sicher, wunderbar,\nUnd bist selbst alles mir.\n", + "v2" + ], + [ + "In dieser Wüste hier\nFind't nirgend meine Seele Ruh',\nDenn meine Ruh' bist, Jesu, Du.\nWohl mir, ich geh' zu Dir!\nBald werd' ich bei Dir sein,\nBald mit den Deinen ewiglich\nAnbeten, loben, preisen Dich,\nMich Deiner stets erfreun.\n", + "v3" + ] + ] +} diff --git a/tests/resources/worshipassistantsongs/would_you_be_free.csv b/tests/resources/worshipassistantsongs/would_you_be_free.csv new file mode 100644 index 000000000..a454ddbf5 --- /dev/null +++ b/tests/resources/worshipassistantsongs/would_you_be_free.csv @@ -0,0 +1,30 @@ +SONGNR,TITLE,AUTHOR,COPYRIGHT,FIRSTLINE,PRIKEY,ALTKEY,TEMPO,FOCUS,THEME,SCRIPTURE,ACTIVE,SONGBOOK,TIMESIG,INTRODUCED,LASTUSED,TIMESUSED,CCLINR,USER1,USER2,USER3,USER4,USER5,ROADMAP,FILELINK1,OVERMAP,FILELINK2,LYRICS,INFO,LYRICS2,Background +"7","Would You Be Free","Jones, Lewis E.","Public Domain","Would you be free from your burden of sin?","G","","Moderate","Only To Others","","","N","Y","","1899-12-30","1899-12-30","","","","","","","","1,C,1","","","",".G C G + Would you be free from your burden of sin? +. D D7 G + There's power in the blood, power in the blood +. C G + Would you o'er evil a victory win? +. D D7 G + There's wonderful power in the blood + +.G C G + There is power, power, wonder working power +.D G + In the blood of the Lamb +. C G + There is power, power, wonder working power +. D G + In the precious blood of the Lamb +","","[1] +Would you be free from your burden of sin? +There's power in the blood, power in the blood +Would you o'er evil a victory win? +There's wonderful power in the blood + +[C] +There is power, power, wonder working power +In the blood of the Lamb +There is power, power, wonder working power +In the precious blood of the Lamb +","" diff --git a/tests/resources/worshipassistantsongs/would_you_be_free.json b/tests/resources/worshipassistantsongs/would_you_be_free.json new file mode 100644 index 000000000..96bc06a59 --- /dev/null +++ b/tests/resources/worshipassistantsongs/would_you_be_free.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "Jones", + "Lewis E" + ], + "title": "Would You Be Free", + "verse_order_list": ["v1", "c1", "v1"], + "copyright": "Public Domain", + "verses": [ + [ + "Would you be free from your burden of sin? \nThere's power in the blood, power in the blood \nWould you o'er evil a victory win? \nThere's wonderful power in the blood \n", + "v1" + ], + [ + "There is power, power, wonder working power \nIn the blood of the Lamb \nThere is power, power, wonder working power \nIn the precious blood of the Lamb \n", + "c1" + ] + ] +} diff --git a/tests/utils/test_bzr_tags.py b/tests/utils/test_bzr_tags.py index 393f4ce25..acadbd8c4 100644 --- a/tests/utils/test_bzr_tags.py +++ b/tests/utils/test_bzr_tags.py @@ -50,10 +50,6 @@ TAGS = [ ['1.9.11', '2039'], ['1.9.12', '2063'], ['2.0', '2118'], - ['2.0.1', '?'], - ['2.0.2', '?'], - ['2.0.3', '?'], - ['2.0.4', '?'], ['2.1.0', '2119'] ]