From e40d8e712622be5f432914c01844a16b8ac394b9 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Tue, 15 Dec 2015 00:00:57 +0100 Subject: [PATCH 1/5] Added suport for importing songs exported from Lyrix. --- openlp/plugins/songs/lib/importer.py | 23 +++- openlp/plugins/songs/lib/importers/lyrix.py | 119 ++++++++++++++++++++ 2 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 openlp/plugins/songs/lib/importers/lyrix.py diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index aebbd3a9e..1701b0c50 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -46,6 +46,7 @@ from .importers.propresenter import ProPresenterImport from .importers.worshipassistant import WorshipAssistantImport from .importers.powerpraise import PowerPraiseImport from .importers.presentationmanager import PresentationManagerImport +from .importers.lyrix import LyrixImport log = logging.getLogger(__name__) @@ -166,6 +167,8 @@ class SongFormat(object): WorshipAssistant = 21 WorshipCenterPro = 22 ZionWorx = 23 + Lyrix = 24 + VideoPsalm = 25 # Set optional attribute defaults __defaults__ = { @@ -361,6 +364,22 @@ class SongFormat(object): 'First convert your ZionWorx database to a CSV text file, as ' 'explained in the User Manual.') + }, + Lyrix: { + 'class': LyrixImport, + 'name': 'Lyrix', + 'prefix': 'lyrix', + 'filter': '%s (*.txt)' % translate('SongsPlugin.ImportWizardForm', 'Lyrix Files'), + 'comboBoxText': translate('SongsPlugin.ImportWizardForm', 'Exported Lyrix files') + }, + VideoPsalm: { + #'class': VideoPsalmImport, + 'name': 'VideoPsalm', + 'prefix': 'videopsalm', + 'filter': '%s (*.json)' % translate('SongsPlugin.ImportWizardForm', 'VideoPsalm Files'), + 'comboBoxText': translate('SongsPlugin.ImportWizardForm', 'Exported VideoPsalm files'), + 'descriptionText': translate('SongsPlugin.ImportWizardForm','The VideoPsalm songbooks are normally located ' + 'in %s') % 'C:\\Users\\Public\\Documents\\VideoPsalm\\SongBooks\\' } } @@ -393,7 +412,9 @@ class SongFormat(object): SongFormat.WordsOfWorship, SongFormat.WorshipAssistant, SongFormat.WorshipCenterPro, - SongFormat.ZionWorx + SongFormat.ZionWorx, + SongFormat.Lyrix, + SongFormat.VideoPsalm ] @staticmethod diff --git a/openlp/plugins/songs/lib/importers/lyrix.py b/openlp/plugins/songs/lib/importers/lyrix.py new file mode 100644 index 000000000..984eb5f6d --- /dev/null +++ b/openlp/plugins/songs/lib/importers/lyrix.py @@ -0,0 +1,119 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2015 OpenLP Developers # +# --------------------------------------------------------------------------- # +# 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:`lyrix` module provides the functionality for importing songs which are +exproted from Lyrix.""" + +import logging +import re + +from lxml import objectify +from lxml.etree import Error, LxmlError + +from openlp.core.common import translate +from openlp.plugins.songs.lib import VerseType +from openlp.plugins.songs.lib.importers.songimport import SongImport +from openlp.plugins.songs.lib.ui import SongStrings + +log = logging.getLogger(__name__) + + +class LyrixImport(SongImport): + """ + Import songs exported from Lyrix + """ + + def __init__(self, manager, **kwargs): + """ + Initialise the class. + """ + super(LyrixImport, self).__init__(manager, **kwargs) + + def do_import(self): + """ + Receive a single file or a list of files to import. + """ + if not isinstance(self.import_source, list): + return + self.import_wizard.progress_bar.setMaximum(len(self.import_source)) + for filename in self.import_source: + if self.stop_import_flag: + return + song_file = open(filename, 'rt', encoding='cp1251') + self.do_import_file(song_file) + song_file.close() + + def do_import_file(self, file): + """ + Process the OpenSong file - pass in a file-like object, not a file path. + """ + self.set_defaults() + # Setup variables + line_number = 0 + song_title = 'Standard Song Title' + ccli = '0' + current_verse = '' + verses = [] + author = '' + copyright = '' + try: + # Read the file + for line in file: + line_number += 1 + if line_number == 4: + song_title = line.strip() + if line_number < 7: + continue + # Detect and get CCLI number + if line.lower().startswith('ccli'): + ccli = re.findall('\d+', line)[0] + try: + # If the CCLI was found, we are near the end + # Find author + line = next(file) + author = line[line.find(':')+2:].strip() + # Find copyright + copyright = next(file) + except StopIteration: + pass + break + if line.strip() == '': + if current_verse != '': + verses.append(current_verse) + current_verse = '' + else: + if current_verse == '': + current_verse += line.strip() + else: + current_verse += '\n' + line.strip() + except Exception as e: + self.log_error(translate('SongsPlugin.LyrixImport', 'File %s' % file.name), + translate('SongsPlugin.LyrixImport', 'Error: %s') % e) + return + self.title = song_title + self.parse_author(author) + self.ccli_number = ccli + self.add_copyright(copyright) + for verse in verses: + self.add_verse(verse, 'v') + if not self.finish(): + self.log_error(file.name) \ No newline at end of file From 6b8178a0b42b5c68230c3127c46c40403284ffde Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Thu, 17 Dec 2015 22:39:52 +0100 Subject: [PATCH 2/5] Added support of importing VideoPsalm songbooks. --- openlp/plugins/songs/lib/importer.py | 34 ++--- openlp/plugins/songs/lib/importers/lyrix.py | 7 +- .../plugins/songs/lib/importers/videopsalm.py | 134 ++++++++++++++++++ .../openlp_plugins/songs/test_videopsalm.py | 49 +++++++ .../videopsalmsongs/as-safe-a-stronghold.json | 34 +++++ .../videopsalm-as-safe-a-stronghold.json | 47 ++++++ 6 files changed, 283 insertions(+), 22 deletions(-) create mode 100644 openlp/plugins/songs/lib/importers/videopsalm.py create mode 100644 tests/functional/openlp_plugins/songs/test_videopsalm.py create mode 100644 tests/resources/videopsalmsongs/as-safe-a-stronghold.json create mode 100644 tests/resources/videopsalmsongs/videopsalm-as-safe-a-stronghold.json diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 1701b0c50..10c20b225 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -47,6 +47,7 @@ from .importers.worshipassistant import WorshipAssistantImport from .importers.powerpraise import PowerPraiseImport from .importers.presentationmanager import PresentationManagerImport from .importers.lyrix import LyrixImport +from .importers.videopsalm import VideoPsalmImport log = logging.getLogger(__name__) @@ -247,6 +248,13 @@ class SongFormat(object): 'prefix': 'foilPresenter', 'filter': '%s (*.foil)' % translate('SongsPlugin.ImportWizardForm', 'Foilpresenter Song Files') }, + Lyrix: { + 'class': LyrixImport, + 'name': 'Lyrix', + 'prefix': 'lyrix', + 'filter': '%s (*.txt)' % translate('SongsPlugin.ImportWizardForm', 'Lyrix Files'), + 'comboBoxText': translate('SongsPlugin.ImportWizardForm', 'Lyrix (exported txt-files)') + }, MediaShout: { 'name': 'MediaShout', 'prefix': 'mediaShout', @@ -327,6 +335,16 @@ class SongFormat(object): 'prefix': 'sundayPlus', 'filter': '%s (*.ptf)' % translate('SongsPlugin.ImportWizardForm', 'SundayPlus Song Files') }, + VideoPsalm: { + 'class': VideoPsalmImport, + 'name': 'VideoPsalm', + 'prefix': 'videopsalm', + 'selectMode': SongFormatSelect.SingleFile, + 'filter': '%s (*.json)' % translate('SongsPlugin.ImportWizardForm', 'VideoPsalm Files'), + 'comboBoxText': translate('SongsPlugin.ImportWizardForm', 'VideoPsalm'), + 'descriptionText': translate('SongsPlugin.ImportWizardForm','The VideoPsalm songbooks are normally located ' + 'in %s') % 'C:\\Users\\Public\\Documents\\VideoPsalm\\SongBooks\\' + }, WordsOfWorship: { 'class': WordsOfWorshipImport, 'name': 'Words of Worship', @@ -364,22 +382,6 @@ class SongFormat(object): 'First convert your ZionWorx database to a CSV text file, as ' 'explained in the User Manual.') - }, - Lyrix: { - 'class': LyrixImport, - 'name': 'Lyrix', - 'prefix': 'lyrix', - 'filter': '%s (*.txt)' % translate('SongsPlugin.ImportWizardForm', 'Lyrix Files'), - 'comboBoxText': translate('SongsPlugin.ImportWizardForm', 'Exported Lyrix files') - }, - VideoPsalm: { - #'class': VideoPsalmImport, - 'name': 'VideoPsalm', - 'prefix': 'videopsalm', - 'filter': '%s (*.json)' % translate('SongsPlugin.ImportWizardForm', 'VideoPsalm Files'), - 'comboBoxText': translate('SongsPlugin.ImportWizardForm', 'Exported VideoPsalm files'), - 'descriptionText': translate('SongsPlugin.ImportWizardForm','The VideoPsalm songbooks are normally located ' - 'in %s') % 'C:\\Users\\Public\\Documents\\VideoPsalm\\SongBooks\\' } } diff --git a/openlp/plugins/songs/lib/importers/lyrix.py b/openlp/plugins/songs/lib/importers/lyrix.py index 984eb5f6d..f6e5bb3a9 100644 --- a/openlp/plugins/songs/lib/importers/lyrix.py +++ b/openlp/plugins/songs/lib/importers/lyrix.py @@ -26,13 +26,8 @@ exproted from Lyrix.""" import logging import re -from lxml import objectify -from lxml.etree import Error, LxmlError - from openlp.core.common import translate -from openlp.plugins.songs.lib import VerseType from openlp.plugins.songs.lib.importers.songimport import SongImport -from openlp.plugins.songs.lib.ui import SongStrings log = logging.getLogger(__name__) @@ -64,7 +59,7 @@ class LyrixImport(SongImport): def do_import_file(self, file): """ - Process the OpenSong file - pass in a file-like object, not a file path. + Process the Lyrix file - pass in a file-like object, not a file path. """ self.set_defaults() # Setup variables diff --git a/openlp/plugins/songs/lib/importers/videopsalm.py b/openlp/plugins/songs/lib/importers/videopsalm.py new file mode 100644 index 000000000..134649997 --- /dev/null +++ b/openlp/plugins/songs/lib/importers/videopsalm.py @@ -0,0 +1,134 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2015 OpenLP Developers # +# --------------------------------------------------------------------------- # +# 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:`lyrix` module provides the functionality for importing songs which are +exproted from Lyrix.""" + +import logging +import json +import os + +from openlp.core.common import translate +from openlp.plugins.songs.lib import VerseType +from openlp.plugins.songs.lib.importers.songimport import SongImport +from openlp.plugins.songs.lib.ui import SongStrings + +log = logging.getLogger(__name__) + + +class VideoPsalmImport(SongImport): + """ + Import songs exported from Lyrix + """ + + def __init__(self, manager, **kwargs): + """ + Initialise the class. + """ + super(VideoPsalmImport, self).__init__(manager, **kwargs) + + def do_import(self): + """ + Process the VideoPsalm file - pass in a file-like object, not a file path. + """ + self.set_defaults() + # Open SongBook file + song_file = open(self.import_source, 'rt', encoding='utf-8-sig') + try: + file_content = song_file.read() + processed_content = '' + inside_quotes = False + # The VideoPsalm format is not valid json, it uses illegal line breaks and unquoted keys, this must be fixed. + file_content_it = iter(file_content) + for c in file_content_it: + if c == '"': + inside_quotes = not inside_quotes + # Detect invalid linebreak + if c == '\n': + if inside_quotes: + processed_content += '\\n' + # Put keys in quotes + elif c.isalnum() and not inside_quotes: + processed_content += '"' + c + c = next(file_content_it) + while c.isalnum(): + processed_content += c + c = next(file_content_it) + processed_content += '"' + c + else: + processed_content += c + songbook = json.loads(processed_content.strip()) + # Get song array + songs = songbook['Songs'] + self.import_wizard.progress_bar.setMaximum(len(songs)) + songbook_name = songbook['Text'] + media_folder = os.path.normpath(os.path.join(os.path.dirname(song_file.name), '..', 'Audio')) + for song in songs: + #song['Composer'] + try: + self.title = song['Text'] + except KeyError: + pass + try: + self.add_author(song['Author']) + except KeyError: + pass + try: + self.add_copyright(song['Copyright'].replace('\n', ' ').strip()) + except KeyError: + pass + try: + self.ccli_number = song['CCLI'] + except KeyError: + pass + try: + self.song_book_name = songbook_name + except KeyError: + pass + try: + self.topics = song['Theme'].splitlines() + except KeyError: + pass + #try: + # self.add_media_file(os.path.join(media_folder, song['AudioFile'])) + #except KeyError: + # pass + try: + self.add_comment(song['Memo1']) + except KeyError: + pass + try: + self.add_comment(song['Memo2']) + except KeyError: + pass + try: + self.add_comment(song['Memo3']) + except KeyError: + pass + for verse in song['Verses']: + self.add_verse(verse['Text'], 'v') + if not self.finish(): + self.log_error('Could not import %s' % self.title) + except Exception as e: + self.log_error(translate('SongsPlugin.VideoPsalmImport', 'File %s' % file.name), + translate('SongsPlugin.VideoPsalmImport', 'Error: %s') % e) + song_file.close() \ No newline at end of file diff --git a/tests/functional/openlp_plugins/songs/test_videopsalm.py b/tests/functional/openlp_plugins/songs/test_videopsalm.py new file mode 100644 index 000000000..5f2cd9fde --- /dev/null +++ b/tests/functional/openlp_plugins/songs/test_videopsalm.py @@ -0,0 +1,49 @@ +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2015 OpenLP Developers # +# --------------------------------------------------------------------------- # +# 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 # +############################################################################### +""" +This module contains tests for the OpenSong song importer. +""" + +import os +from unittest import TestCase + +from tests.helpers.songfileimport import SongImportTestHelper +from openlp.plugins.songs.lib.importers.opensong import OpenSongImport +from openlp.core.common import Registry +from tests.functional import patch, MagicMock + +TEST_PATH = os.path.abspath( + os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'videopsalmsongs')) + + +class TestVideoPsalmFileImport(SongImportTestHelper): + + def __init__(self, *args, **kwargs): + self.importer_class_name = 'VideoPsalmImport' + self.importer_module_name = 'videopsalm' + super(TestVideoPsalmFileImport, self).__init__(*args, **kwargs) + + def test_song_import(self): + """ + Test that loading an VideoPsalm file works correctly on various files + """ + self.file_import(os.path.join(TEST_PATH, 'videopsalm-as-safe-a-stronghold.json'), + self.load_external_result_data(os.path.join(TEST_PATH, 'as-safe-a-stronghold.json'))) diff --git a/tests/resources/videopsalmsongs/as-safe-a-stronghold.json b/tests/resources/videopsalmsongs/as-safe-a-stronghold.json new file mode 100644 index 000000000..a48ff1f9d --- /dev/null +++ b/tests/resources/videopsalmsongs/as-safe-a-stronghold.json @@ -0,0 +1,34 @@ +{ + "authors": [ + "Martin Luther" + ], + "ccli_number": "12345", + "comments": "This is\nthe first comment\nThis is\nthe second comment\nThis is\nthe third comment\n", + "copyright": "Public Domain", + "song_book_name": "SongBook1", + "song_number": 0, + "title": "A Safe Stronghold Our God is Still", + "topics": [ + "tema1", + "tema2" + ], + "verse_order_list": [], + "verses": [ + [ + "As safe a stronghold our God is still,\nA trusty shield and weapon;\nHe’ll help us clear from all the ill\nThat hath us now o’ertaken.\nThe ancient prince of hell\nHath risen with purpose fell;\nStrong mail of craft and power\nHe weareth in this hour;\nOn earth is not His fellow.", + "v" + ], + [ + "With force of arms we nothing can,\nFull soon were we down-ridden;\nBut for us fights the proper Man,\nWhom God Himself hath bidden.\nAsk ye: Who is this same?\nChrist Jesus is His name,\nThe Lord Sabaoth’s Son;\nHe, and no other one,\nShall conquer in the battle.", + "v" + ], + [ + "And were this world all devils o’er,\nAnd watching to devour us,\nWe lay it not to heart so sore;\nNot they can overpower us.\nAnd let the prince of ill\nLook grim as e’er he will,\nHe harms us not a whit;\nFor why? his doom is writ;\nA word shall quickly slay him.", + "v" + ], + [ + "God’s word, for all their craft and force,\nOne moment will not linger,\nBut, spite of hell, shall have its course;\n’Tis written by His finger.\nAnd though they take our life,\nGoods, honour, children, wife,\nYet is their profit small:\nThese things shall vanish all;\nThe city of God remaineth.", + "v" + ] + ] +} diff --git a/tests/resources/videopsalmsongs/videopsalm-as-safe-a-stronghold.json b/tests/resources/videopsalmsongs/videopsalm-as-safe-a-stronghold.json new file mode 100644 index 000000000..d3e9296c7 --- /dev/null +++ b/tests/resources/videopsalmsongs/videopsalm-as-safe-a-stronghold.json @@ -0,0 +1,47 @@ +{Abbreviation:"SB1",Copyright:"Public domain",Songs:[{ID:3,Composer:"Unknown",Author:"Martin Luther",Copyright:"Public +Domain",Theme:"tema1 +tema2",CCLI:"12345",Alias:"A safe stronghold",Memo1:"This is +the first comment +",Memo2:"This is +the second comment +",Memo3:"This is +the third comment +",Reference:"reference",Guid:"jtCkrJdPIUOmECjaQylg/g",Verses:[{ +Text:"As safe a stronghold our God is still, +A trusty shield and weapon; +He’ll help us clear from all the ill +That hath us now o’ertaken. +The ancient prince of hell +Hath risen with purpose fell; +Strong mail of craft and power +He weareth in this hour; +On earth is not His fellow."},{ID:2, +Text:"With force of arms we nothing can, +Full soon were we down-ridden; +But for us fights the proper Man, +Whom God Himself hath bidden. +Ask ye: Who is this same? +Christ Jesus is His name, +The Lord Sabaoth’s Son; +He, and no other one, +Shall conquer in the battle."},{ID:3, +Text:"And were this world all devils o’er, +And watching to devour us, +We lay it not to heart so sore; +Not they can overpower us. +And let the prince of ill +Look grim as e’er he will, +He harms us not a whit; +For why? his doom is writ; +A word shall quickly slay him."},{ID:4, +Text:"God’s word, for all their craft and force, +One moment will not linger, +But, spite of hell, shall have its course; +’Tis written by His finger. +And though they take our life, +Goods, honour, children, wife, +Yet is their profit small: +These things shall vanish all; +The city of God remaineth."}],AudioFile:"282.mp3",IsAudioFileEnabled:1, +Text:"A Safe Stronghold Our God is Still"}],Guid:"khiHU2blX0Kb41dGdbDLhA",VersionDate:"20121012000000", +Text:"SongBook1"} From 037d3f4f7dd68fca2a3e7f777855f211ce73d83b Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Fri, 18 Dec 2015 23:24:20 +0100 Subject: [PATCH 3/5] Added support for author types in tests + some VideoPsalm fixes --- openlp/plugins/songs/lib/importer.py | 4 +- openlp/plugins/songs/lib/importers/lyrix.py | 4 +- .../plugins/songs/lib/importers/songimport.py | 10 +-- .../plugins/songs/lib/importers/videopsalm.py | 63 ++++++++----------- tests/helpers/songfileimport.py | 5 +- .../videopsalmsongs/as-safe-a-stronghold.json | 3 +- 6 files changed, 41 insertions(+), 48 deletions(-) diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 1d08e2c36..2be9beb40 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -342,8 +342,8 @@ class SongFormat(object): 'selectMode': SongFormatSelect.SingleFile, 'filter': '%s (*.json)' % translate('SongsPlugin.ImportWizardForm', 'VideoPsalm Files'), 'comboBoxText': translate('SongsPlugin.ImportWizardForm', 'VideoPsalm'), - 'descriptionText': translate('SongsPlugin.ImportWizardForm','The VideoPsalm songbooks are normally located ' - 'in %s') % 'C:\\Users\\Public\\Documents\\VideoPsalm\\SongBooks\\' + 'descriptionText': translate('SongsPlugin.ImportWizardForm', 'The VideoPsalm songbooks are normally located' + ' in %s') % 'C:\\Users\\Public\\Documents\\VideoPsalm\\SongBooks\\' }, WordsOfWorship: { 'class': WordsOfWorshipImport, diff --git a/openlp/plugins/songs/lib/importers/lyrix.py b/openlp/plugins/songs/lib/importers/lyrix.py index f6e5bb3a9..5caa46258 100644 --- a/openlp/plugins/songs/lib/importers/lyrix.py +++ b/openlp/plugins/songs/lib/importers/lyrix.py @@ -85,7 +85,7 @@ class LyrixImport(SongImport): # If the CCLI was found, we are near the end # Find author line = next(file) - author = line[line.find(':')+2:].strip() + author = line[line.find(':') + 2:].strip() # Find copyright copyright = next(file) except StopIteration: @@ -111,4 +111,4 @@ class LyrixImport(SongImport): for verse in verses: self.add_verse(verse, 'v') if not self.finish(): - self.log_error(file.name) \ No newline at end of file + self.log_error(file.name) diff --git a/openlp/plugins/songs/lib/importers/songimport.py b/openlp/plugins/songs/lib/importers/songimport.py index 9f6caa901..d3b725f85 100644 --- a/openlp/plugins/songs/lib/importers/songimport.py +++ b/openlp/plugins/songs/lib/importers/songimport.py @@ -255,13 +255,13 @@ class SongImport(QtCore.QObject): if author2: self.add_author(author2) - def add_author(self, author): + def add_author(self, author, type=None): """ Add an author to the list """ - if author in self.authors: + if (author, type) in self.authors: return - self.authors.append(author) + self.authors.append((author, type)) def add_media_file(self, filename, weight=0): """ @@ -360,13 +360,13 @@ class SongImport(QtCore.QObject): song.comments = self.comments song.theme_name = self.theme_name song.ccli_number = self.ccli_number - for author_text in self.authors: + for author_text, author_type in self.authors: author = self.manager.get_object_filtered(Author, Author.display_name == author_text) if not author: author = Author.populate(display_name=author_text, last_name=author_text.split(' ')[-1], first_name=' '.join(author_text.split(' ')[:-1])) - song.add_author(author) + song.add_author(author, author_type) if self.song_book_name: song_book = self.manager.get_object_filtered(Book, Book.name == self.song_book_name) if song_book is None: diff --git a/openlp/plugins/songs/lib/importers/videopsalm.py b/openlp/plugins/songs/lib/importers/videopsalm.py index 134649997..871f4b4a7 100644 --- a/openlp/plugins/songs/lib/importers/videopsalm.py +++ b/openlp/plugins/songs/lib/importers/videopsalm.py @@ -30,7 +30,7 @@ import os from openlp.core.common import translate from openlp.plugins.songs.lib import VerseType from openlp.plugins.songs.lib.importers.songimport import SongImport -from openlp.plugins.songs.lib.ui import SongStrings +from openlp.plugins.songs.lib.db import AuthorType log = logging.getLogger(__name__) @@ -57,7 +57,7 @@ class VideoPsalmImport(SongImport): file_content = song_file.read() processed_content = '' inside_quotes = False - # The VideoPsalm format is not valid json, it uses illegal line breaks and unquoted keys, this must be fixed. + # The VideoPsalm format is not valid json, it uses illegal line breaks and unquoted keys, this must be fixed file_content_it = iter(file_content) for c in file_content_it: if c == '"': @@ -83,47 +83,36 @@ class VideoPsalmImport(SongImport): songbook_name = songbook['Text'] media_folder = os.path.normpath(os.path.join(os.path.dirname(song_file.name), '..', 'Audio')) for song in songs: - #song['Composer'] - try: + self.song_book_name = songbook_name + if 'Text' in song: self.title = song['Text'] - except KeyError: - pass - try: - self.add_author(song['Author']) - except KeyError: - pass - try: + composer = None + author = None + if 'Composer' in song: + composer = song['Composer'] + if 'Author' in song: + author = song['Author'] + if author and composer == author: + self.add_author(author, AuthorType.WordsAndMusic) + else: + if author: + self.add_author(author, AuthorType.Words) + if composer: + self.add_author(composer, AuthorType.Music) + if 'Copyright' in song: self.add_copyright(song['Copyright'].replace('\n', ' ').strip()) - except KeyError: - pass - try: + if 'CCLI' in song: self.ccli_number = song['CCLI'] - except KeyError: - pass - try: - self.song_book_name = songbook_name - except KeyError: - pass - try: + if 'Theme' in song: self.topics = song['Theme'].splitlines() - except KeyError: - pass - #try: - # self.add_media_file(os.path.join(media_folder, song['AudioFile'])) - #except KeyError: - # pass - try: + if 'AudioFile' in song: + self.add_media_file(os.path.join(media_folder, song['AudioFile'])) + if 'Memo1' in song: self.add_comment(song['Memo1']) - except KeyError: - pass - try: + if 'Memo2' in song: self.add_comment(song['Memo2']) - except KeyError: - pass - try: + if 'Memo3' in song: self.add_comment(song['Memo3']) - except KeyError: - pass for verse in song['Verses']: self.add_verse(verse['Text'], 'v') if not self.finish(): @@ -131,4 +120,4 @@ class VideoPsalmImport(SongImport): except Exception as e: self.log_error(translate('SongsPlugin.VideoPsalmImport', 'File %s' % file.name), translate('SongsPlugin.VideoPsalmImport', 'Error: %s') % e) - song_file.close() \ No newline at end of file + song_file.close() diff --git a/tests/helpers/songfileimport.py b/tests/helpers/songfileimport.py index 470c319d2..7cf6d115a 100644 --- a/tests/helpers/songfileimport.py +++ b/tests/helpers/songfileimport.py @@ -124,7 +124,10 @@ class SongImportTestHelper(TestCase): self.assertEqual(importer.title, title, 'title for %s should be "%s"' % (source_file_name, title)) for author in author_calls: - self.mocked_add_author.assert_any_call(author) + if isinstance(author, str): + self.mocked_add_author.assert_any_call(author) + else: + self.mocked_add_author.assert_any_call(author[0], author[1]) if song_copyright: self.mocked_add_copyright.assert_called_with(song_copyright) if ccli_number: diff --git a/tests/resources/videopsalmsongs/as-safe-a-stronghold.json b/tests/resources/videopsalmsongs/as-safe-a-stronghold.json index a48ff1f9d..4755e5027 100644 --- a/tests/resources/videopsalmsongs/as-safe-a-stronghold.json +++ b/tests/resources/videopsalmsongs/as-safe-a-stronghold.json @@ -1,6 +1,7 @@ { "authors": [ - "Martin Luther" + ["Martin Luther", "words"], + ["Unknown", "music"] ], "ccli_number": "12345", "comments": "This is\nthe first comment\nThis is\nthe second comment\nThis is\nthe third comment\n", From 2a4205c0a1c7638449e10e8bd4736fd5ec8c2831 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Sun, 20 Dec 2015 17:46:39 +0100 Subject: [PATCH 4/5] Migrated songselect and songbeamer tests to the SongImportTestHelper based structure. --- openlp/plugins/songs/lib/importer.py | 6 +- .../plugins/songs/lib/importers/cclifile.py | 8 +- .../songs/test_songbeamerimport.py | 76 ++++--------------- .../openlp_plugins/songs/test_songselect.py | 73 ++++-------------- .../songbeamersongs/Lobsinget dem Herrn.json | 12 +++ tests/resources/songselect/TestSong-bin.json | 25 ++++++ tests/resources/songselect/TestSong-txt.json | 21 +++++ 7 files changed, 96 insertions(+), 125 deletions(-) create mode 100644 tests/resources/songbeamersongs/Lobsinget dem Herrn.json create mode 100644 tests/resources/songselect/TestSong-bin.json create mode 100644 tests/resources/songselect/TestSong-txt.json diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 2be9beb40..3ff22814e 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -250,10 +250,10 @@ class SongFormat(object): }, Lyrix: { 'class': LyrixImport, - 'name': 'Lyrix', + 'name': 'LyriX', 'prefix': 'lyrix', - 'filter': '%s (*.txt)' % translate('SongsPlugin.ImportWizardForm', 'Lyrix Files'), - 'comboBoxText': translate('SongsPlugin.ImportWizardForm', 'Lyrix (exported txt-files)') + 'filter': '%s (*.txt)' % translate('SongsPlugin.ImportWizardForm', 'LyriX Files'), + 'comboBoxText': translate('SongsPlugin.ImportWizardForm', 'LyriX (Exported TXT-files)') }, MediaShout: { 'name': 'MediaShout', diff --git a/openlp/plugins/songs/lib/importers/cclifile.py b/openlp/plugins/songs/lib/importers/cclifile.py index 3a283df16..a92d91764 100644 --- a/openlp/plugins/songs/lib/importers/cclifile.py +++ b/openlp/plugins/songs/lib/importers/cclifile.py @@ -48,7 +48,7 @@ class CCLIFileImport(SongImport): :param manager: The song manager for the running OpenLP installation. :param kwargs: The files to be imported. """ - SongImport.__init__(self, manager, **kwargs) + super(CCLIFileImport, self).__init__(manager, **kwargs) def do_import(self): """ @@ -161,7 +161,7 @@ class CCLIFileImport(SongImport): elif line.startswith('Author='): song_author = line[7:].strip() elif line.startswith('Copyright='): - self.copyright = line[10:].strip() + self.add_copyright(line[10:].strip()) elif line.startswith('Themes='): song_topics = line[7:].strip().replace(' | ', '/t') elif line.startswith('Fields='): @@ -318,14 +318,14 @@ class CCLIFileImport(SongImport): if line_number == 2: line_number += 1 if clean_line.startswith('©'): - self.copyright = clean_line + self.add_copyright(clean_line) else: song_author = clean_line # n=3, authors elif line_number == 3: line_number += 1 if song_author: - self.copyright = clean_line + self.add_copyright(clean_line) else: song_author = clean_line # line_number=4, comments lines before last line diff --git a/tests/functional/openlp_plugins/songs/test_songbeamerimport.py b/tests/functional/openlp_plugins/songs/test_songbeamerimport.py index 82ca7335a..b34ff80eb 100644 --- a/tests/functional/openlp_plugins/songs/test_songbeamerimport.py +++ b/tests/functional/openlp_plugins/songs/test_songbeamerimport.py @@ -26,27 +26,28 @@ This module contains tests for the Songbeamer song importer. import os from unittest import TestCase +from tests.helpers.songfileimport import SongImportTestHelper from tests.functional import MagicMock, patch from openlp.plugins.songs.lib.importers.songbeamer import SongBeamerImport -from openlp.plugins.songs.lib import VerseType from openlp.core.common import Registry TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'songbeamersongs')) -SONG_TEST_DATA = { - 'Lobsinget dem Herrn.sng': { - 'title': 'GL 1 - Lobsinget dem Herrn', - 'verses': [ - ('1. Lobsinget dem Herrn,\no preiset Ihn gern!\nAnbetung und Lob Ihm gebühret.\n', 'v'), - ('2. Lobsingt Seiner Lieb´,\ndie einzig ihn trieb,\nzu sterben für unsere Sünden!\n', 'v'), - ('3. Lobsingt Seiner Macht!\nSein Werk ist vollbracht:\nEr sitzet zur Rechten des Vaters.\n', 'v'), - ('4. Lobsingt seiner Treu´,\ndie immerdar neu,\nbis Er uns zur Herrlichket führet!\n\n', 'v') - ], - 'song_book_name': 'Glaubenslieder I', - 'song_number': "1", - 'authors': ['Carl Brockhaus', 'Johann Jakob Vetter'] - } -} + + +class TestSongBeamerFileImport(SongImportTestHelper): + + def __init__(self, *args, **kwargs): + self.importer_class_name = 'SongBeamerImport' + self.importer_module_name = 'songbeamer' + super(TestSongBeamerFileImport, self).__init__(*args, **kwargs) + + def test_song_import(self): + """ + Test that loading an OpenSong file works correctly on various files + """ + self.file_import([os.path.join(TEST_PATH, 'Lobsinget dem Herrn.sng')], + self.load_external_result_data(os.path.join(TEST_PATH, 'Lobsinget dem Herrn.json'))) class TestSongBeamerImport(TestCase): @@ -115,51 +116,6 @@ class TestSongBeamerImport(TestCase): 'do_import should return None when import_source is a list and stop_import_flag is True') mocked_import_wizard.progress_bar.setMaximum.assert_called_with(len(importer.import_source)) - def file_import_test(self): - """ - Test the actual import of real song files and check that the imported data is correct. - """ - - # GIVEN: Test files with a mocked out SongImport class, a mocked out "manager", a mocked out "import_wizard", - # and mocked out "author", "add_copyright", "add_verse", "finish" methods. - with patch('openlp.plugins.songs.lib.importers.songbeamer.SongImport'): - for song_file in SONG_TEST_DATA: - mocked_manager = MagicMock() - mocked_import_wizard = MagicMock() - mocked_add_verse = MagicMock() - mocked_finish = MagicMock() - mocked_finish.return_value = True - importer = SongBeamerImport(mocked_manager, filenames=[]) - importer.import_wizard = mocked_import_wizard - importer.stop_import_flag = False - importer.add_verse = mocked_add_verse - importer.finish = mocked_finish - - # WHEN: Importing each file - importer.import_source = [os.path.join(TEST_PATH, song_file)] - title = SONG_TEST_DATA[song_file]['title'] - add_verse_calls = SONG_TEST_DATA[song_file]['verses'] - song_book_name = SONG_TEST_DATA[song_file]['song_book_name'] - song_number = SONG_TEST_DATA[song_file]['song_number'] - song_authors = SONG_TEST_DATA[song_file]['authors'] - - # THEN: do_import should return none, the song data should be as expected, and finish should have been - # called. - self.assertIsNone(importer.do_import(), 'do_import should return None when it has completed') - self.assertEqual(importer.title, title, 'title for %s should be "%s"' % (song_file, title)) - for verse_text, verse_tag in add_verse_calls: - mocked_add_verse.assert_any_call(verse_text, verse_tag) - if song_book_name: - self.assertEqual(importer.song_book_name, song_book_name, - 'song_book_name for %s should be "%s"' % (song_file, song_book_name)) - if song_number: - self.assertEqual(importer.song_number, song_number, - 'song_number for %s should be %s' % (song_file, song_number)) - if song_authors: - for author in importer.authors: - self.assertIn(author, song_authors) - mocked_finish.assert_called_with() - def check_verse_marks_test(self): """ Tests different lines to see if a verse mark is detected or not diff --git a/tests/functional/openlp_plugins/songs/test_songselect.py b/tests/functional/openlp_plugins/songs/test_songselect.py index a13cc800c..9896c8d6f 100644 --- a/tests/functional/openlp_plugins/songs/test_songselect.py +++ b/tests/functional/openlp_plugins/songs/test_songselect.py @@ -28,6 +28,7 @@ from urllib.error import URLError from PyQt4 import QtGui +from tests.helpers.songfileimport import SongImportTestHelper from openlp.core import Registry from openlp.plugins.songs.forms.songselectform import SongSelectForm, SearchWorker from openlp.plugins.songs.lib import Song @@ -37,6 +38,9 @@ from openlp.plugins.songs.lib.importers.cclifile import CCLIFileImport from tests.functional import MagicMock, patch, call from tests.helpers.testmixin import TestMixin +TEST_PATH = os.path.abspath( + os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'songselect')) + class TestSongSelectImport(TestCase, TestMixin): """ @@ -645,68 +649,21 @@ class TestSongSelectForm(TestCase, TestMixin): mocked_view_button.setEnabled.assert_called_with(True) -class TestSongSelectFileImport(TestCase, TestMixin): - """ - Test SongSelect file import - """ - def setUp(self): - """ - Initial setups - """ - Registry.create() - test_song_name = 'TestSong' - self.file_name = os.path.join('tests', 'resources', 'songselect', test_song_name) - self.title = 'Test Song' - self.ccli_number = '0000000' - self.authors = ['Author One', 'Author Two'] - self.topics = ['Adoration', 'Praise'] +class TestSongSelectFileImport(SongImportTestHelper): - def songselect_import_bin_file_test(self): - """ - Verify import SongSelect BIN file parses file properly - """ - # GIVEN: Text file to import and mocks - copyright_bin = '2011 OpenLP Programmer One (Admin. by OpenLP One) | ' \ - 'Openlp Programmer Two (Admin. by OpenLP Two)' - verses_bin = [ - ['v1', 'Line One Verse One\nLine Two Verse One\nLine Three Verse One\nLine Four Verse One', None], - ['v2', 'Line One Verse Two\nLine Two Verse Two\nLine Three Verse Two\nLine Four Verse Two', None] - ] - song_import = CCLIFileImport(manager=None, filename=['{}.bin'.format(self.file_name)]) + def __init__(self, *args, **kwargs): + self.importer_class_name = 'CCLIFileImport' + self.importer_module_name = 'cclifile' + super(TestSongSelectFileImport, self).__init__(*args, **kwargs) - with patch.object(song_import, 'import_wizard'), patch.object(song_import, 'finish'): - # WHEN: We call the song importer - song_import.do_import() - # 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') - self.assertEquals(song_import.authors, self.authors, 'Author(s) should match') - self.assertEquals(song_import.copyright, copyright_bin, 'Copyright should match') - self.assertEquals(song_import.topics, self.topics, 'Theme(s) should match') - self.assertEquals(song_import.verses, verses_bin, 'Verses should match with test verses') - - def songselect_import_text_file_test(self): + def test_song_import(self): """ - Verify import SongSelect TEXT file parses file properly + Test that loading an OpenSong file works correctly on various files """ - # GIVEN: Text file to import and mocks - copyright_txt = '© 2011 OpenLP Programmer One (Admin. by OpenLP One)' - verses_txt = [ - ['v1', 'Line One Verse One\r\nLine Two Verse One\r\nLine Three Verse One\r\nLine Four Verse One', None], - ['v2', 'Line One Verse Two\r\nLine Two Verse Two\r\nLine Three Verse Two\r\nLine Four Verse Two', None] - ] - song_import = CCLIFileImport(manager=None, filename=['{}.txt'.format(self.file_name)]) - - with patch.object(song_import, 'import_wizard'), patch.object(song_import, 'finish'): - # WHEN: We call the song importer - song_import.do_import() - - # 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') - self.assertEquals(song_import.authors, self.authors, 'Author(s) should match') - self.assertEquals(song_import.copyright, copyright_txt, 'Copyright should match') - self.assertEquals(song_import.verses, verses_txt, 'Verses should match with test verses') + self.file_import([os.path.join(TEST_PATH, 'TestSong.bin')], + self.load_external_result_data(os.path.join(TEST_PATH, 'TestSong-bin.json'))) + self.file_import([os.path.join(TEST_PATH, 'TestSong.txt')], + self.load_external_result_data(os.path.join(TEST_PATH, 'TestSong-txt.json'))) class TestSearchWorker(TestCase, TestMixin): diff --git a/tests/resources/songbeamersongs/Lobsinget dem Herrn.json b/tests/resources/songbeamersongs/Lobsinget dem Herrn.json new file mode 100644 index 000000000..d2069a687 --- /dev/null +++ b/tests/resources/songbeamersongs/Lobsinget dem Herrn.json @@ -0,0 +1,12 @@ +{ + "title": "GL 1 - Lobsinget dem Herrn", + "verses": [ + ["1. Lobsinget dem Herrn,\no preiset Ihn gern!\nAnbetung und Lob Ihm gebühret.\n", "v"], + ["2. Lobsingt Seiner Lieb´,\ndie einzig ihn trieb,\nzu sterben für unsere Sünden!\n", "v"], + ["3. Lobsingt Seiner Macht!\nSein Werk ist vollbracht:\nEr sitzet zur Rechten des Vaters.\n", "v"], + ["4. Lobsingt seiner Treu´,\ndie immerdar neu,\nbis Er uns zur Herrlichket führet!\n\n", "v"] + ], + "song_book_name": "Glaubenslieder I", + "song_number": "1", + "authors": ["Carl Brockhaus", "Johann Jakob Vetter"] +} diff --git a/tests/resources/songselect/TestSong-bin.json b/tests/resources/songselect/TestSong-bin.json new file mode 100644 index 000000000..10fafb89b --- /dev/null +++ b/tests/resources/songselect/TestSong-bin.json @@ -0,0 +1,25 @@ +{ + "authors": [ + "Author One", + "Author Two" + ], + "ccli_number": "0000000", + "song_number": 0, + "title": "Test Song", + "topics": [ + "Adoration", + "Praise" + ], + "copyright": "2011 OpenLP Programmer One (Admin. by OpenLP One) | Openlp Programmer Two (Admin. by OpenLP Two)", + "verse_order_list": [], + "verses": [ + [ + "Line One Verse One\nLine Two Verse One\nLine Three Verse One\nLine Four Verse One\n", + "v" + ], + [ + "Line One Verse Two\nLine Two Verse Two\nLine Three Verse Two\nLine Four Verse Two\n", + "v" + ] + ] +} diff --git a/tests/resources/songselect/TestSong-txt.json b/tests/resources/songselect/TestSong-txt.json new file mode 100644 index 000000000..e90a7fad0 --- /dev/null +++ b/tests/resources/songselect/TestSong-txt.json @@ -0,0 +1,21 @@ +{ + "authors": [ + "Author One", + "Author Two" + ], + "ccli_number": "0000000", + "song_number": 0, + "title": "Test Song", + "copyright": "© 2011 OpenLP Programmer One (Admin. by OpenLP One)", + "verse_order_list": [], + "verses": [ + [ + "Line One Verse One\nLine Two Verse One\nLine Three Verse One\nLine Four Verse One\n", + "v" + ], + [ + "Line One Verse Two\nLine Two Verse Two\nLine Three Verse Two\nLine Four Verse Two\n", + "v" + ] + ] +} From 89ae1ae738e62d4a9fdbdd8cf10bc48e0118e964 Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Sun, 20 Dec 2015 20:28:14 +0100 Subject: [PATCH 5/5] Added tests for LyriX import. --- openlp/plugins/songs/lib/importers/lyrix.py | 15 +++--- .../openlp_plugins/songs/test_lyriximport.py | 53 +++++++++++++++++++ .../openlp_plugins/songs/test_videopsalm.py | 2 +- tests/helpers/songfileimport.py | 2 +- tests/resources/lyrixsongs/A002.TXT | 34 ++++++++++++ tests/resources/lyrixsongs/A06.TXT | 31 +++++++++++ tests/resources/lyrixsongs/AO05.TXT | 48 +++++++++++++++++ tests/resources/lyrixsongs/Amazing Grace.json | 26 +++++++++ .../resources/lyrixsongs/Amazing Grace2.json | 33 ++++++++++++ .../lyrixsongs/in die regterhand.json | 18 +++++++ 10 files changed, 253 insertions(+), 9 deletions(-) create mode 100644 tests/functional/openlp_plugins/songs/test_lyriximport.py create mode 100644 tests/resources/lyrixsongs/A002.TXT create mode 100644 tests/resources/lyrixsongs/A06.TXT create mode 100644 tests/resources/lyrixsongs/AO05.TXT create mode 100644 tests/resources/lyrixsongs/Amazing Grace.json create mode 100644 tests/resources/lyrixsongs/Amazing Grace2.json create mode 100644 tests/resources/lyrixsongs/in die regterhand.json diff --git a/openlp/plugins/songs/lib/importers/lyrix.py b/openlp/plugins/songs/lib/importers/lyrix.py index 5caa46258..4facbafc8 100644 --- a/openlp/plugins/songs/lib/importers/lyrix.py +++ b/openlp/plugins/songs/lib/importers/lyrix.py @@ -73,9 +73,10 @@ class LyrixImport(SongImport): try: # Read the file for line in file: + line = line.strip() line_number += 1 if line_number == 4: - song_title = line.strip() + song_title = line if line_number < 7: continue # Detect and get CCLI number @@ -84,22 +85,22 @@ class LyrixImport(SongImport): try: # If the CCLI was found, we are near the end # Find author - line = next(file) - author = line[line.find(':') + 2:].strip() + line = next(file).strip() + author = line[line.find(':') + 2:] # Find copyright - copyright = next(file) + copyright = next(file).strip() except StopIteration: pass break - if line.strip() == '': + if line == '': if current_verse != '': verses.append(current_verse) current_verse = '' else: if current_verse == '': - current_verse += line.strip() + current_verse += line else: - current_verse += '\n' + line.strip() + current_verse += '\n' + line except Exception as e: self.log_error(translate('SongsPlugin.LyrixImport', 'File %s' % file.name), translate('SongsPlugin.LyrixImport', 'Error: %s') % e) diff --git a/tests/functional/openlp_plugins/songs/test_lyriximport.py b/tests/functional/openlp_plugins/songs/test_lyriximport.py new file mode 100644 index 000000000..1a239c00e --- /dev/null +++ b/tests/functional/openlp_plugins/songs/test_lyriximport.py @@ -0,0 +1,53 @@ +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2015 OpenLP Developers # +# --------------------------------------------------------------------------- # +# 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 # +############################################################################### +""" +This module contains tests for the LyriX song importer. +""" + +import os +from unittest import TestCase + +from tests.helpers.songfileimport import SongImportTestHelper +from openlp.plugins.songs.lib.importers.opensong import OpenSongImport +from openlp.core.common import Registry +from tests.functional import patch, MagicMock + +TEST_PATH = os.path.abspath( + os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'lyrixsongs')) + + +class TestLyrixFileImport(SongImportTestHelper): + + def __init__(self, *args, **kwargs): + self.importer_class_name = 'LyrixImport' + self.importer_module_name = 'lyrix' + super(TestLyrixFileImport, self).__init__(*args, **kwargs) + + def test_song_import(self): + """ + Test that loading an LyriX file works correctly on various files + """ + self.file_import([os.path.join(TEST_PATH, 'A06.TXT')], + self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json'))) + self.file_import([os.path.join(TEST_PATH, 'A002.TXT')], + self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace2.json'))) + self.file_import([os.path.join(TEST_PATH, 'AO05.TXT')], + self.load_external_result_data(os.path.join(TEST_PATH, 'in die regterhand.json'))) diff --git a/tests/functional/openlp_plugins/songs/test_videopsalm.py b/tests/functional/openlp_plugins/songs/test_videopsalm.py index 5f2cd9fde..348f7f0f3 100644 --- a/tests/functional/openlp_plugins/songs/test_videopsalm.py +++ b/tests/functional/openlp_plugins/songs/test_videopsalm.py @@ -19,7 +19,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### """ -This module contains tests for the OpenSong song importer. +This module contains tests for the VideoPsalm song importer. """ import os diff --git a/tests/helpers/songfileimport.py b/tests/helpers/songfileimport.py index 7cf6d115a..723cb8a36 100644 --- a/tests/helpers/songfileimport.py +++ b/tests/helpers/songfileimport.py @@ -127,7 +127,7 @@ class SongImportTestHelper(TestCase): if isinstance(author, str): self.mocked_add_author.assert_any_call(author) else: - self.mocked_add_author.assert_any_call(author[0], author[1]) + self.mocked_add_author.assert_any_call(*author) if song_copyright: self.mocked_add_copyright.assert_called_with(song_copyright) if ccli_number: diff --git a/tests/resources/lyrixsongs/A002.TXT b/tests/resources/lyrixsongs/A002.TXT new file mode 100644 index 000000000..c2d82cd4f --- /dev/null +++ b/tests/resources/lyrixsongs/A002.TXT @@ -0,0 +1,34 @@ + +------------- +A002 +AMAZING GRACE +------------- + +1. AMAZING GRACE! HOW SWEET THE SOUND +THAT SAVED A WRETCH LIKE ME; +I ONCE WAS LOST, BUT NOW AM FOUND; +WAS BLIND, BUT NOW I SEE. + +2. 'TWAS GRACE THAT TAUGHT MY HEART TO FEAR +AND GRACE MY FEARS RELIEVED; +HOW PRECIOUS DID THAT GRACE APPEAR, +THE HOUR I FIRST BELIEVED! + +3. THROUGH MANY DANGERS, TRIALS AND SNARES +I HAVE ALREADY COME; +'TIS GRACE THAT BROUGHT ME SAFE THUS FAR +AND GRACE WILL LEAD ME HOME. + +4. THE LORD HAS PROMISED GOOD TO ME, +HIS WORD MY HOPE SECURES; +HE WILL MY SHIELD AND FORTRESS BE +AS LONG AS LIFE ENDURES. + +5. WHEN WE'VE BEEN THERE TEN THOUSAND YEARS +BRIGHT SHINING AS THE SUN, +WE'VE NO LESS DAYS TO SING GOD'S PRAISE +THAN WHEN WE'D FIRST BEGUN. + +CCLI no.: 22025 +Words/Music: Edwin Excell, John Newton, John P. Rees +Public Domain diff --git a/tests/resources/lyrixsongs/A06.TXT b/tests/resources/lyrixsongs/A06.TXT new file mode 100644 index 000000000..97c5be52b --- /dev/null +++ b/tests/resources/lyrixsongs/A06.TXT @@ -0,0 +1,31 @@ + +---------------------------------- +A06 +AMAZING GRACE, HOW SWEET THE SOUND +---------------------------------- + +1. AMAZING GRACE, HOW SWEET THE SOUND +THAT SAVED A WRETCH LIKE ME +I ONCE WAS LOST, BUT NOW I'M FOUND +WAS BLIND, BUT NOW I SEE + +2. 'TWAS GRACE THAT TAUGHT MY HEART TO FEAR +AND GRACE MY FEARS RELIEVED +HOW PRECIOUS DID THAT GRACE APPEAR +THE HOUR I FIRST BELIEVED + +3. THROUGH MANY DANGERS, TOILS AND SNARES +I HAVE ALREADY COME, 'TWAS GRACE +THAT BROUGHT ME SAFE THUS FAR +AND GRACE WILL LEAD ME HOME + +4. WHEN WE'VE BEEN THERE TEN THOUSAND YEARS +BRIGHT SHINING AS THE SUN +WE'VE NO LESS DAYS TO SING GOD'S PRAISE +THAN WHEN WE'VE FIRST BEGUN + +5. PRAISE GOD, PRAISE GOD +PRAISE GOD, PRAISE GOD +PRAISE GOD, PRAISE GOD +PRAISE GOD.. + diff --git a/tests/resources/lyrixsongs/AO05.TXT b/tests/resources/lyrixsongs/AO05.TXT new file mode 100644 index 000000000..0700ba42f --- /dev/null +++ b/tests/resources/lyrixsongs/AO05.TXT @@ -0,0 +1,48 @@ + +-------------------------------- +AO05 +IN DIE REGTERHAND VAN HOM WAT IN +-------------------------------- + +1. IN DIE REGTERHAND VAN HOM +WAT IN MAJESTEIT REGEER +Lê DIE BOEKROL VAN VERLOSSING +SEWEMAAL VERSEëL +EN NIEMAND KON GEVIND WORD +OM SY SEëLS OOP TE BREEK +TOT DIE LAM VAN GOD NA VORE KOM +OM DIE BOEKROL SELF TE NEEM +DIE VIER-EN-TWINTIG OUDERLINGE +VAL TOE VOOR HOM NEER +SAAM MET AL DIE ENG'LE +IN DIE GANSE HEMELLEëR, +EN ELKE WESE WAT ASEM HET +OP DIE AARDE, IN DIE SEE, EN OOR DIE +LENGTE EN DIE BREEDTE +VAN DIE SKEPPING BRING HOM EER + +2. HERE U ALLEEN IS WAARDIG +OM DIE LEWENSBOEK TE NEEM +EN U ALLEEN IS MAGTIG +OM SY SEëLS OOP TE BREEK, +WANT U'T VIR ONS GESTERWE, +MET U BLOED HET U BETAAL +OM ONS LOS TE KOOP +UIT ELKE STAM EN NASIE,VOLK EN TAAL + +AL DIE LOF EN DIE KRAG +EN DIE EER +EN DIE HEERLIKHEID +EN RYKDON EN STERKTE +AAN U ALLEEN O HEER +AL DIE LOF EN DIE KRAG +EN DIE EER +EN WYSHEID AAN DIE LAM +OP DIE TROON +WAT NOU EN TOT IN +EWIGHEID REGEER +NOU EN TOT IN EWIGHEID +REGEER +DIE LAM WAT TOT IN +EWIGHEID REGEER + diff --git a/tests/resources/lyrixsongs/Amazing Grace.json b/tests/resources/lyrixsongs/Amazing Grace.json new file mode 100644 index 000000000..ef92bffaf --- /dev/null +++ b/tests/resources/lyrixsongs/Amazing Grace.json @@ -0,0 +1,26 @@ +{ + "title": "AMAZING GRACE, HOW SWEET THE SOUND", + "verse_order_list": [], + "verses": [ + [ + "1. AMAZING GRACE, HOW SWEET THE SOUND\nTHAT SAVED A WRETCH LIKE ME\nI ONCE WAS LOST, BUT NOW I'M FOUND\nWAS BLIND, BUT NOW I SEE", + "v" + ], + [ + "2. 'TWAS GRACE THAT TAUGHT MY HEART TO FEAR\nAND GRACE MY FEARS RELIEVED\nHOW PRECIOUS DID THAT GRACE APPEAR\nTHE HOUR I FIRST BELIEVED", + "v" + ], + [ + "3. THROUGH MANY DANGERS, TOILS AND SNARES\nI HAVE ALREADY COME, 'TWAS GRACE\nTHAT BROUGHT ME SAFE THUS FAR\nAND GRACE WILL LEAD ME HOME", + "v" + ], + [ + "4. WHEN WE'VE BEEN THERE TEN THOUSAND YEARS\nBRIGHT SHINING AS THE SUN\nWE'VE NO LESS DAYS TO SING GOD'S PRAISE\nTHAN WHEN WE'VE FIRST BEGUN", + "v" + ], + [ + "5. PRAISE GOD, PRAISE GOD\nPRAISE GOD, PRAISE GOD\nPRAISE GOD, PRAISE GOD\nPRAISE GOD..", + "v" + ] + ] +} diff --git a/tests/resources/lyrixsongs/Amazing Grace2.json b/tests/resources/lyrixsongs/Amazing Grace2.json new file mode 100644 index 000000000..07c52b5b7 --- /dev/null +++ b/tests/resources/lyrixsongs/Amazing Grace2.json @@ -0,0 +1,33 @@ +{ + "authors": [ + "John Newton", + "Edwin Excell", + "John P. Rees" + ], + "ccli_number": "22025", + "copyright": "Public Domain", + "title": "AMAZING GRACE", + "verse_order_list": [], + "verses": [ + [ + "1. AMAZING GRACE! HOW SWEET THE SOUND\nTHAT SAVED A WRETCH LIKE ME;\nI ONCE WAS LOST, BUT NOW AM FOUND;\nWAS BLIND, BUT NOW I SEE.", + "v" + ], + [ + "2. 'TWAS GRACE THAT TAUGHT MY HEART TO FEAR\nAND GRACE MY FEARS RELIEVED;\nHOW PRECIOUS DID THAT GRACE APPEAR,\nTHE HOUR I FIRST BELIEVED!", + "v" + ], + [ + "3. THROUGH MANY DANGERS, TRIALS AND SNARES\nI HAVE ALREADY COME;\n'TIS GRACE THAT BROUGHT ME SAFE THUS FAR\nAND GRACE WILL LEAD ME HOME.", + "v" + ], + [ + "4. THE LORD HAS PROMISED GOOD TO ME,\nHIS WORD MY HOPE SECURES;\nHE WILL MY SHIELD AND FORTRESS BE\nAS LONG AS LIFE ENDURES.", + "v" + ], + [ + "5. WHEN WE'VE BEEN THERE TEN THOUSAND YEARS\nBRIGHT SHINING AS THE SUN,\nWE'VE NO LESS DAYS TO SING GOD'S PRAISE\nTHAN WHEN WE'D FIRST BEGUN.", + "v" + ] + ] +} diff --git a/tests/resources/lyrixsongs/in die regterhand.json b/tests/resources/lyrixsongs/in die regterhand.json new file mode 100644 index 000000000..f5860def5 --- /dev/null +++ b/tests/resources/lyrixsongs/in die regterhand.json @@ -0,0 +1,18 @@ +{ + "title": "IN DIE REGTERHAND VAN HOM WAT IN", + "verse_order_list": [], + "verses": [ + [ + "1. IN DIE REGTERHAND VAN HOM\nWAT IN MAJESTEIT REGEER\nLк DIE BOEKROL VAN VERLOSSING\nSEWEMAAL VERSEлL\nEN NIEMAND KON GEVIND WORD\nOM SY SEлLS OOP TE BREEK\nTOT DIE LAM VAN GOD NA VORE KOM\nOM DIE BOEKROL SELF TE NEEM\nDIE VIER-EN-TWINTIG OUDERLINGE\nVAL TOE VOOR HOM NEER\nSAAM MET AL DIE ENG'LE\nIN DIE GANSE HEMELLEлR,\nEN ELKE WESE WAT ASEM HET\nOP DIE AARDE, IN DIE SEE, EN OOR DIE\nLENGTE EN DIE BREEDTE\nVAN DIE SKEPPING BRING HOM EER", + "v" + ], + [ + "2. HERE U ALLEEN IS WAARDIG\nOM DIE LEWENSBOEK TE NEEM\nEN U ALLEEN IS MAGTIG\nOM SY SEлLS OOP TE BREEK,\nWANT U'T VIR ONS GESTERWE,\nMET U BLOED HET U BETAAL\nOM ONS LOS TE KOOP\nUIT ELKE STAM EN NASIE,VOLK EN TAAL", + "v" + ], + [ + "AL DIE LOF EN DIE KRAG\nEN DIE EER\nEN DIE HEERLIKHEID\nEN RYKDON EN STERKTE\nAAN U ALLEEN O HEER\nAL DIE LOF EN DIE KRAG\nEN DIE EER\nEN WYSHEID AAN DIE LAM\nOP DIE TROON\nWAT NOU EN TOT IN\nEWIGHEID REGEER\nNOU EN TOT IN EWIGHEID\nREGEER\nDIE LAM WAT TOT IN\nEWIGHEID REGEER", + "v" + ] + ] +}