openlp-core team mailing list archive
-
openlp-core team
-
Mailing list archive
-
Message #22079
[Merge] lp:~sam92/openlp/fix-songbeamer-import into lp:openlp
Samuel Mehrbrodt has proposed merging lp:~sam92/openlp/fix-songbeamer-import into lp:openlp.
Requested reviews:
Jonathan Corwin (j-corwin)
Raoul Snyman (raoul-snyman)
Phill (phill-ridout)
For more details, see:
https://code.launchpad.net/~sam92/openlp/fix-songbeamer-import/+merge/192169
Fix SongBeamer Import and add Testcase
The read() call failed when the file was not unicode. So I first open the file in binary mode without encoding. After the encoding has been detected, the file is read with the proper encoding.
I tested this with ~800 SongBeamer files.
The Song I used for the test is public domain.
--
https://code.launchpad.net/~sam92/openlp/fix-songbeamer-import/+merge/192169
Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/plugins/songs/lib/songbeamerimport.py'
--- openlp/plugins/songs/lib/songbeamerimport.py 2013-08-31 18:17:38 +0000
+++ openlp/plugins/songs/lib/songbeamerimport.py 2013-10-22 15:13:00 +0000
@@ -102,10 +102,10 @@
"""
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))
- if not isinstance(self.import_source, list):
- return
- for file in self.import_source:
+ for import_file in self.import_source:
# TODO: check that it is a valid SongBeamer file
if self.stop_import_flag:
return
@@ -113,12 +113,13 @@
self.currentVerse = ''
self.currentVerseType = VerseType.tags[VerseType.Verse]
read_verses = False
- file_name = os.path.split(file)[1]
- if os.path.isfile(file):
- detect_file = open(file, 'r')
+ file_name = os.path.split(import_file)[1]
+ if os.path.isfile(import_file):
+ # First open in binary mode to detect the encoding
+ detect_file = open(import_file, 'rb')
details = chardet.detect(detect_file.read())
detect_file.close()
- infile = codecs.open(file, 'r', details['encoding'])
+ infile = codecs.open(import_file, 'r', details['encoding'])
song_data = infile.readlines()
infile.close()
else:
@@ -149,7 +150,7 @@
self.replaceHtmlTags()
self.addVerse(self.currentVerse, self.currentVerseType)
if not self.finish():
- self.logError(file)
+ self.logError(import_file)
def replaceHtmlTags(self):
"""
=== added file 'tests/functional/openlp_plugins/songs/test_songbeamerimport.py'
--- tests/functional/openlp_plugins/songs/test_songbeamerimport.py 1970-01-01 00:00:00 +0000
+++ tests/functional/openlp_plugins/songs/test_songbeamerimport.py 2013-10-22 15:13:00 +0000
@@ -0,0 +1,157 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 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 #
+###############################################################################
+
+"""
+This module contains tests for the Songbeamer song importer.
+"""
+
+import os
+from unittest import TestCase
+
+from tests.functional import MagicMock, patch
+from openlp.plugins.songs.lib.songbeamerimport import SongBeamerImport
+
+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!\n'
+ 'Anbetung und Lob Ihm gebühret.\n', 'v'),
+ ('2. Lobsingt Seiner Lieb´,\ndie einzig ihn trieb,\n'
+ 'zu sterben für unsere Sünden!\n', 'v'),
+ ('3. Lobsingt Seiner Macht!\nSein Werk ist vollbracht:\n'
+ 'Er sitzet zur Rechten des Vaters.\n', 'v'),
+ ('4. Lobsingt seiner Treu´,\ndie immerdar neu,\n'
+ 'bis Er uns zur Herrlichket führet!\n\n', 'v')],
+ 'song_book_name': 'Glaubenslieder I',
+ 'song_number': "1"}
+ }
+
+
+class TestSongBeamerImport(TestCase):
+ """
+ Test the functions in the :mod:`songbeamerimport` module.
+ """
+ def create_importer_test(self):
+ """
+ Test creating an instance of the SongBeamer file importer
+ """
+ # GIVEN: A mocked out SongImport class, and a mocked out "manager"
+ with patch('openlp.plugins.songs.lib.songbeamerimport.SongImport'):
+ mocked_manager = MagicMock()
+
+ # WHEN: An importer object is created
+ importer = SongBeamerImport(mocked_manager)
+
+ # THEN: The importer object should not be None
+ self.assertIsNotNone(importer, 'Import should not be none')
+
+ def invalid_import_source_test(self):
+ """
+ Test SongBeamerImport.doImport handles different invalid import_source values
+ """
+ # GIVEN: A mocked out SongImport class, and a mocked out "manager"
+ with patch('openlp.plugins.songs.lib.songbeamerimport.SongImport'):
+ mocked_manager = MagicMock()
+ mocked_import_wizard = MagicMock()
+ importer = SongBeamerImport(mocked_manager)
+ importer.import_wizard = mocked_import_wizard
+ importer.stop_import_flag = True
+
+ # WHEN: Import source is not a list
+ for source in ['not a list', 0]:
+ importer.import_source = source
+
+ # THEN: doImport should return none and the progress bar maximum should not be set.
+ self.assertIsNone(importer.doImport(), 'doImport should return None when import_source is not a list')
+ self.assertEquals(mocked_import_wizard.progress_bar.setMaximum.called, False,
+ 'setMaxium on import_wizard.progress_bar should not have been called')
+
+ def valid_import_source_test(self):
+ """
+ Test SongBeamerImport.doImport handles different invalid import_source values
+ """
+ # GIVEN: A mocked out SongImport class, and a mocked out "manager"
+ with patch('openlp.plugins.songs.lib.songbeamerimport.SongImport'):
+ mocked_manager = MagicMock()
+ mocked_import_wizard = MagicMock()
+ importer = SongBeamerImport(mocked_manager)
+ importer.import_wizard = mocked_import_wizard
+ importer.stop_import_flag = True
+
+ # WHEN: Import source is a list
+ importer.import_source = ['List', 'of', 'files']
+
+ # THEN: doImport should return none and the progress bar setMaximum should be called with the length of
+ # import_source.
+ self.assertIsNone(importer.doImport(),
+ 'doImport 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.songbeamerimport.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)
+ importer.import_wizard = mocked_import_wizard
+ importer.stop_import_flag = False
+ importer.addVerse = 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']
+
+ # THEN: doImport should return none, the song data should be as expected, and finish should have been
+ # called.
+ self.assertIsNone(importer.doImport(), 'doImport should return None when it has completed')
+ self.assertEquals(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.assertEquals(importer.songBookName, song_book_name, 'songBookName for %s should be "%s"'
+ % (song_file, song_book_name))
+ if song_number:
+ self.assertEquals(importer.songNumber, song_number, 'songNumber for %s should be %s'
+ % (song_file, song_number))
+ mocked_finish.assert_called_with()
=== added directory 'tests/resources/songbeamersongs'
=== added file 'tests/resources/songbeamersongs/Lobsinget dem Herrn.sng'
--- tests/resources/songbeamersongs/Lobsinget dem Herrn.sng 1970-01-01 00:00:00 +0000
+++ tests/resources/songbeamersongs/Lobsinget dem Herrn.sng 2013-10-22 15:13:00 +0000
@@ -0,0 +1,25 @@
+#LangCount=1
+#Title=GL 1 - Lobsinget dem Herrn
+#Editor=SongBeamer 4.20
+#Version=3
+#Format=F/K//
+#TitleFormat=U
+#ChurchSongID=0001
+#Songbook=Glaubenslieder I / 1
+---
+1. Lobsinget dem Herrn,
+o preiset Ihn gern!
+Anbetung und Lob Ihm geb�
+ ---
+2. Lobsingt Seiner Lieb�,
+die einzig ihn trieb,
+zu sterben f�ere S�
+ ---
+3. Lobsingt Seiner Macht!
+Sein Werk ist vollbracht:
+Er sitzet zur Rechten des Vaters.
+ ---
+4. Lobsingt seiner Treu�,
+die immerdar neu,
+bis Er uns zur Herrlichket f�
+
Follow ups