Merge lp:~john+ubuntu-g/openlp/singingthefaith into lp:openlp

Proposed by John Lines
Status: Superseded
Proposed branch: lp:~john+ubuntu-g/openlp/singingthefaith
Merge into: lp:openlp
Diff against target: 633 lines (+549/-11)
8 files modified
openlp/plugins/songs/lib/importer.py (+22/-10)
openlp/plugins/songs/lib/importers/singingthefaith.py (+396/-0)
tests/functional/openlp_plugins/songs/test_singingthefaithimport.py (+48/-0)
tests/helpers/songfileimport.py (+2/-1)
tests/resources/songs/singingthefaith/H1.txt (+9/-0)
tests/resources/songs/singingthefaith/H2.txt (+30/-0)
tests/resources/songs/singingthefaith/STF001.json (+13/-0)
tests/resources/songs/singingthefaith/STF002.json (+29/-0)
To merge this branch: bzr merge lp:~john+ubuntu-g/openlp/singingthefaith
Reviewer Review Type Date Requested Status
Tomas Groth Needs Fixing
Phill Needs Fixing
Raoul Snyman Pending
Review via email: mp+369490@code.launchpad.net

This proposal supersedes a proposal from 2019-06-30.

This proposal has been superseded by a proposal from 2019-07-19.

Commit message

Initial merge of SingingTheFaithImport, including update to importer.py

Description of the change

Singing The Faith is the new Authorized Hymn book for the Methodist Church of Great Britain.
There is an electronic version of the Hymn book, for Windows only, which can export Hymns as text files.

This import module smooths the process of converting these text files into OpenLP. The input format is messy and not intended for automatic processing so the importer uses a combination of heuristics and a hints file. This version has not been tested on all the hymns in Singing The Faith, but deals with most of the, more than 100, hymns it has been tested with.

Note that it includes a test module, which works for the single verse case. Multiple verse songs import OK, but tests fail.

To post a comment you must log in.
Revision history for this message
Raoul Snyman (raoul-snyman) wrote : Posted in a previous version of this proposal

Linux tests failed, please see https://ci.openlp.io/job/MP-02-Linux_Tests/191/ for more details

Revision history for this message
Raoul Snyman (raoul-snyman) wrote : Posted in a previous version of this proposal

The test is failing because the "add_verse" method is not called, or not called with that exact data. I've broken up the error message into 3 parts below for easier reading.

AssertionError:

add_verse('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.', 'v1')

call not found

review: Needs Fixing
Revision history for this message
Phill (phill-ridout) wrote : Posted in a previous version of this proposal

A few in-line comments. Also you don't need to use parenthesis around the expressions in the if statements.

Revision history for this message
John Lines (john+ubuntu-g) wrote : Posted in a previous version of this proposal

> A few in-line comments. Also you don't need to use parenthesis around the
> expressions in the if statements.

Thanks - have updated to use Path more, and have removed redudant parentheses round expressions in if statements

Revision history for this message
Raoul Snyman (raoul-snyman) wrote : Posted in a previous version of this proposal

Hey John, a couple things.

1. You have a ton of linting issues. I started commenting, and then I realised that it would be better to just point you to flake8. See the link at the bottom of my comment for a quick introduction to linting and flake8.

2. You have some inconsistent indentation. Indentation in Python is very important, so we take it seriously. Also, please make sure you are indenting using spaces and not tabs.

3. You are not committing your code with the e-mail address associated with Launchpad. Please can you fix that by issuing a bzr whoami "John Lines <email address hidden>"

4. Once you've made all your changes, and you're ready for another review, you need to resubmit your merge proposal. Do this by clicking the "Resubmit" link in the top right hand corner of the page.

5. If you're struggling with anything, pop into our IRC channel, there's usually someone around who is happy to help.

https://medium.com/python-pandemonium/what-is-flake8-and-why-we-should-use-it-b89bd78073f2

review: Needs Fixing
Revision history for this message
John Lines (john+ubuntu-g) wrote : Posted in a previous version of this proposal

1. Thanks for the info on flake8 - is now flake8 clean - you are quite right - it is better for me to learn about the tools.
2. Think indentation is fixed - flake8 was handy as well
3. Email address now set in my bzr config
4. Can you have another look at the change now.

Revision history for this message
Raoul Snyman (raoul-snyman) wrote : Posted in a previous version of this proposal

Linux tests passed!

Revision history for this message
Raoul Snyman (raoul-snyman) wrote : Posted in a previous version of this proposal

Linting failed, please see https://ci.openlp.io/job/MP-03-Linting/132/ for more details

Revision history for this message
John Lines (john+ubuntu-g) wrote : Posted in a previous version of this proposal

Fix lint tests outside main importer code

Revision history for this message
Raoul Snyman (raoul-snyman) wrote :

Linux tests passed!

Revision history for this message
Raoul Snyman (raoul-snyman) wrote :

Linting passed!

Revision history for this message
Raoul Snyman (raoul-snyman) wrote :

macOS tests passed!

Revision history for this message
Phill (phill-ridout) wrote :

Please change your string formatting to use the 'new' style with the format function. ( https://pyformat.info/ ) also string formatting is preferred over concatenation (i.e, "part1" + var + "part2")

single quotes for strings, not double quotes

do_import_file is very long can this be split in to smaller methods?

review: Needs Fixing
2890. By John Lines

Minimize differences needed to run under OpenLP 2.4.6

2891. By John Lines

Convert double to single quotes, make hint variable names consistent

2892. By John Lines

New style string formatting, restructure indent=0 cases

Revision history for this message
Tomas Groth (tomasgroth) wrote :

Generally it looks good to me, though I haven't tested. But a few things to fix.

review: Needs Fixing
2893. By John Lines

New hints for AddSpaceAfterSemi and CCLI

2894. By John Lines

Update GPL version, use constructor, add comment to signal unepected verse order

Revision history for this message
John Lines (john+ubuntu-g) wrote :

Using new string formatting, constructor for class.

2895. By John Lines

Add AddSpaceAfterColon hint

2896. By John Lines

Add BlankLine hint and deal with a leading asterisk on a verse number

2897. By John Lines

Merge trunk updates

2898. By John Lines

enable whole song impoerter test

2899. By John Lines

Strip unwanted formatting characters

2900. By John Lines

Implement BoldLine hint

2901. By John Lines

Make Based on Psalm an automatic comment, do not automatically make Authors type Word

2902. By John Lines

Fix typo

2903. By John Lines

Merge trunk updates

2904. By John Lines

Use .format in importer.py

2905. By John Lines

Implement SongbookNumberInTitle hint

2906. By John Lines

Upload hints.tag into resources

2907. By John Lines

fix tests to allow for SongbookNumberInTitle defaulting to false and add hints tests

2908. By John Lines

Merge trunk updates

2909. By John Lines

add tests with hints subdirectory

2910. By John Lines

Linting fix

2911. By John Lines

put default hints plugin directory and chnage name to singingthefaith-hints.tag

2912. By John Lines

Merge trunk updates

2913. By John Lines

Tweaks to hints - now version 3, H470 and H567

Unmerged revisions

2913. By John Lines

Tweaks to hints - now version 3, H470 and H567

2912. By John Lines

Merge trunk updates

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'openlp/plugins/songs/lib/importer.py'
--- openlp/plugins/songs/lib/importer.py 2019-04-13 13:00:22 +0000
+++ openlp/plugins/songs/lib/importer.py 2019-07-19 11:11:28 +0000
@@ -42,6 +42,7 @@
42from .importers.powersong import PowerSongImport42from .importers.powersong import PowerSongImport
43from .importers.presentationmanager import PresentationManagerImport43from .importers.presentationmanager import PresentationManagerImport
44from .importers.propresenter import ProPresenterImport44from .importers.propresenter import ProPresenterImport
45from .importers.singingthefaith import SingingTheFaithImport
45from .importers.songbeamer import SongBeamerImport46from .importers.songbeamer import SongBeamerImport
46from .importers.songpro import SongProImport47from .importers.songpro import SongProImport
47from .importers.songshowplus import SongShowPlusImport48from .importers.songshowplus import SongShowPlusImport
@@ -173,16 +174,17 @@
173 PowerSong = 16174 PowerSong = 16
174 PresentationManager = 17175 PresentationManager = 17
175 ProPresenter = 18176 ProPresenter = 18
176 SongBeamer = 19177 SingingTheFaith = 19
177 SongPro = 20178 SongBeamer = 20
178 SongShowPlus = 21179 SongPro = 21
179 SongsOfFellowship = 22180 SongShowPlus = 22
180 SundayPlus = 23181 SongsOfFellowship = 23
181 VideoPsalm = 24182 SundayPlus = 24
182 WordsOfWorship = 25183 VideoPsalm = 25
183 WorshipAssistant = 26184 WordsOfWorship = 26
184 WorshipCenterPro = 27185 WorshipAssistant = 27
185 ZionWorx = 28186 WorshipCenterPro = 28
187 ZionWorx = 29
186188
187 # Set optional attribute defaults189 # Set optional attribute defaults
188 __defaults__ = {190 __defaults__ = {
@@ -343,6 +345,15 @@
343 'filter': '{text} (*.pro4 *.pro5 *.pro6)'.format(text=translate('SongsPlugin.ImportWizardForm',345 'filter': '{text} (*.pro4 *.pro5 *.pro6)'.format(text=translate('SongsPlugin.ImportWizardForm',
344 'ProPresenter Song Files'))346 'ProPresenter Song Files'))
345 },347 },
348 SingingTheFaith: {
349 'class': SingingTheFaithImport,
350 'name': 'SingingTheFaith',
351 'prefix': 'singingTheFaith',
352 'filter': '%s (*.txt)' % translate('SongsPlugin.ImportWizardForm', 'Singing The Faith Exported Files'),
353 'descriptionText': translate('SongsPlugin.ImportWizardForm',
354 'First use Singing The Faith Electonic edition to export '
355 'the song(s) in Text format.')
356 },
346 SongBeamer: {357 SongBeamer: {
347 'class': SongBeamerImport,358 'class': SongBeamerImport,
348 'name': 'SongBeamer',359 'name': 'SongBeamer',
@@ -462,6 +473,7 @@
462 SongFormat.PowerSong,473 SongFormat.PowerSong,
463 SongFormat.PresentationManager,474 SongFormat.PresentationManager,
464 SongFormat.ProPresenter,475 SongFormat.ProPresenter,
476 SongFormat.SingingTheFaith,
465 SongFormat.SongBeamer,477 SongFormat.SongBeamer,
466 SongFormat.SongPro,478 SongFormat.SongPro,
467 SongFormat.SongShowPlus,479 SongFormat.SongShowPlus,
468480
=== added file 'openlp/plugins/songs/lib/importers/singingthefaith.py'
--- openlp/plugins/songs/lib/importers/singingthefaith.py 1970-01-01 00:00:00 +0000
+++ openlp/plugins/songs/lib/importers/singingthefaith.py 2019-07-19 11:11:28 +0000
@@ -0,0 +1,396 @@
1# -*- coding: utf-8 -*-
2# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
3
4###############################################################################
5# OpenLP - Open Source Lyrics Projection #
6# --------------------------------------------------------------------------- #
7# Copyright (c) 2008-2019 OpenLP Developers #
8# --------------------------------------------------------------------------- #
9# This program is free software; you can redistribute it and/or modify it #
10# under the terms of the GNU General Public License as published by the Free #
11# Software Foundation; version 3 of the License. #
12# #
13# This program is distributed in the hope that it will be useful, but WITHOUT #
14# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
15# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
16# more details. #
17# #
18# You should have received a copy of the GNU General Public License along #
19# with this program; if not, write to the Free Software Foundation, Inc., 59 #
20# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
21###############################################################################
22"""
23The :mod:`singingthefaith` module provides the functionality for importing songs which are
24exported from Singing The Faith - an Authorised songbook for the Methodist Church of
25Great Britain."""
26
27import logging
28import re
29from pathlib import Path
30
31from openlp.core.common.i18n import translate
32from openlp.plugins.songs.lib.importers.songimport import SongImport
33
34log = logging.getLogger(__name__)
35
36
37class SingingTheFaithImport(SongImport):
38 """
39 Import songs exported from SingingTheFaith
40 """
41
42 def __init__(self, manager, **kwargs):
43 """
44 Initialise the class.
45 """
46 super(SingingTheFaithImport, self).__init__(manager, **kwargs)
47 self.hints_available = False
48 self.checks_needed = True
49 self.hint_line = {}
50 self.hint_file_version = '0'
51 self.hint_verse_order = ''
52 self.hint_song_title = ''
53 self.hint_comments = ''
54 self.hint_ccli = ''
55 self.hint_ignore_indent = False
56
57 def do_import(self):
58 """
59 Receive a single file or a list of files to import.
60 """
61 if not isinstance(self.import_source, list):
62 return
63 self.import_wizard.progress_bar.setMaximum(len(self.import_source))
64 for file_path in self.import_source:
65 if self.stop_import_flag:
66 return
67 if isinstance(file_path, str):
68 song_file = open(file_path, 'rt', encoding='cp1251')
69 self.do_import_file(song_file)
70 song_file.close()
71 else:
72 with file_path.open('rt', encoding='cp1251') as song_file:
73 self.do_import_file(song_file)
74
75 def do_import_file(self, file):
76 """
77 Process the SingingTheFaith file - pass in a file-like object, not a file path.
78 """
79 singing_the_faith_version = 1
80 self.set_defaults()
81 # Setup variables
82 line_number = 0
83 old_indent = 0
84 # The chorus indent is how many spaces the chorus is indented - it might be 6,
85 # but we test for >= and I do not know how consistent to formatting of the
86 # exported songs is.
87 chorus_indent = 5
88 song_title = 'STF000 -'
89 song_number = '0'
90 ccli = '0'
91 current_verse = ''
92 current_verse_type = 'v'
93 current_verse_number = 1
94 # Potentially we could try to track current chorus number to automatically handle
95 # more than 1 chorus, currently unused.
96 # current_chorus_number = 1
97 has_chorus = False
98 chorus_written = False
99 auto_verse_order_ok = False
100 copyright = ''
101 # the check_flag is prepended to the title, removed if the import should be OK
102 # all the songs which need manual editing should sort below all the OK songs
103 check_flag = 'z'
104
105 self.add_comment('Imported with Singing The Faith Importer v ' + str(singing_the_faith_version))
106
107 # Get the file_song_number - so we can use it for hints
108 filename = Path(file.name)
109 song_number_file = filename.stem
110 song_number_match = re.search(r'\d+', song_number_file)
111 if song_number_match:
112 song_number_file = song_number_match.group()
113
114 # See if there is a hints file in the same location as the file
115 dir_path = filename.parent
116 hints_file_path = dir_path / 'hints.tag'
117 try:
118 with hints_file_path.open('r') as hints_file:
119 hints_available = self.read_hints(hints_file, song_number_file)
120 except FileNotFoundError:
121 hints_available = False
122
123 try:
124 for line in file:
125 line_number += 1
126 if hints_available and str(line_number) in self.hint_line:
127 hint = self.hint_line[str(line_number)]
128 # Set to false if this hint does not replace the line
129 line_replaced = True
130 if hint == 'Comment':
131 line.strip()
132 self.add_comment(line)
133 continue
134 elif hint == 'Ignore':
135 continue
136 elif hint == 'Author':
137 # add as a raw author - do not split and make them a words author
138 line.strip()
139 self.add_author(line, 'words')
140 line_number += 1
141 next(file)
142 continue
143 elif hint.startswith('VariantVerse'):
144 vv, hintverse, replace = hint.split(' ', 2)
145 this_verse = self.verses[int(hintverse) - 1]
146 this_verse_str = this_verse[1]
147 new_verse = this_verse_str
148 # There might be multiple replace pairs separated by |
149 replaces = replace.split('|')
150 for rep in replaces:
151 source_str, dest_str = rep.split('/')
152 new_verse = new_verse.replace(source_str, dest_str)
153 self.add_verse(new_verse, 'v')
154 self.verse_order_list.append('v{}'.format(str(current_verse_number)))
155 current_verse_number += 1
156 line_number += 1
157 next(file)
158 continue
159 elif hint == 'AddSpaceAfterSemi':
160 line = line.replace(';', '; ')
161 line_replaced = False
162 # note - do not use contine here as the line should now be processed as normal.
163 elif hint == 'AddSpaceAfterColon':
164 line = line.replace(':', ': ')
165 line_replaced = False
166 elif hint == 'BlankLine':
167 line = ' *Blank*'
168 line_replaced = False
169 else:
170 self.log_error(translate('SongsPlugin.SingingTheFaithImport',
171 'File {file})'.format(file=file.name)),
172 translate('SongsPlugin.SingingTheFaithImport',
173 'Unknown hint {hint}').format(hint=hint))
174 if line_replaced:
175 return
176 # STF exported lines have a leading verse number at the start of each verse.
177 # remove them - note that we want to track the indent as that shows a chorus
178 # so will deal with that before stripping all leading spaces.
179 indent = 0
180 if line.strip():
181 # One hymn has one line which starts '* 6' at the start of a verse
182 # Strip this out
183 if line.startswith('* 6'):
184 line = line.lstrip('* ')
185 verse_num_match = re.search(r'^\d+', line)
186 if verse_num_match:
187 # Could extract the verse number and check it against the calculated
188 # verse number - TODO
189 # verse_num = verse_num_match.group()
190 line = line.lstrip('0123456789')
191 indent_match = re.search(r'^\s+', line)
192 if indent_match:
193 indent = len(indent_match.group())
194 # Assuming we have sorted out what is verse and what is chorus, strip lines,
195 # unless ignoreIndent
196 if self.hint_ignore_indent:
197 line = line.rstrip()
198 else:
199 line = line.strip()
200 if line_number == 2:
201 # note that songs seem to start with a blank line so the title is line 2
202 # Also we strip blanks from the title, even if ignoring indent.
203 song_title = line.strip()
204 # Detect the 'Reproduced from Singing the Faith Electronic Words Edition' line
205 if line.startswith('Reproduced from Singing the Faith Electronic Words Edition'):
206 song_number_match = re.search(r'\d+', line)
207 if song_number_match:
208 song_number = song_number_match.group()
209 continue
210 elif indent == 0:
211 # If the indent is 0 and it contains '(c)' then it is a Copyright line
212 if '(c)' in line:
213 copyright = line
214 continue
215 elif (line.startswith('Liturgical ') or line.startswith('From The ') or
216 line.startswith('From Common ')):
217 self.add_comment(line)
218 continue
219 # If indent is 0 it may be the author, unless it was one of the cases covered above
220 elif len(line) > 0:
221 # May have more than one author, separated by ' and '
222 authors = line.split(' and ')
223 for a in authors:
224 self.parse_author(a)
225 continue
226 # If a blank line has bee replaced by *Blank* then put it back to being
227 # a simple space since this is past stripping blanks
228 if '*Blank*' in line:
229 line = ' '
230 if line == '':
231 if current_verse != '':
232 self.add_verse(current_verse, current_verse_type)
233 self.verse_order_list.append(current_verse_type + str(current_verse_number))
234 if current_verse_type == 'c':
235 chorus_written = True
236 else:
237 current_verse_number += 1
238 current_verse = ''
239 if chorus_written:
240 current_verse_type = 'v'
241 else:
242 # If the line is indented more than or equal chorus_indent then assume it is a chorus
243 # If the indent has just changed then start a new verse just like hitting a blank line
244 if not self.hint_ignore_indent and ((indent >= chorus_indent) and (old_indent < indent)):
245 if current_verse != '':
246 self.add_verse(current_verse, current_verse_type)
247 self.verse_order_list.append(current_verse_type + str(current_verse_number))
248 if current_verse_type == 'v':
249 current_verse_number += 1
250 current_verse = line
251 current_verse_type = 'c'
252 old_indent = indent
253 chorus_written = False
254 has_chorus = True
255 continue
256 if current_verse == '':
257 current_verse += line
258 else:
259 current_verse += '\n' + line
260 old_indent = indent
261 except Exception as e:
262 self.log_error(translate('SongsPlugin.SingingTheFaithImport', 'File {file}').format(file=file.name),
263 translate('SongsPlugin.SingingTheFaithImport', 'Error: {error}').format(error=e))
264 return
265
266 if self.hint_song_title:
267 song_title = self.hint_song_title
268 self.title = '{}STF{} - {title}'.format(check_flag, song_number.zfill(3), title=song_title)
269 self.song_book_name = 'Singing The Faith'
270 self.song_number = song_number
271 self.ccli_number = ccli
272 self.add_copyright(copyright)
273 # If we have a chorus then the generated Verse order can not be used directly, but we can generate
274 # one for two special cases - Verse followed by one chorus (to be repeated after every verse)
275 # of Chorus, followed by verses. If hints for ManualCheck or VerseOrder are supplied ignore this
276 if has_chorus and not self.hint_verse_order and not self.checks_needed:
277 auto_verse_order_ok = False
278 # Popular case V1 C2 V2 ...
279 if self.verse_order_list: # protect against odd cases
280 if (self.verse_order_list[0] == 'v1') and (self.verse_order_list[1] == 'c2'):
281 new_verse_order_list = ['v1', 'c1']
282 i = 2
283 auto_verse_order_ok = True
284 elif (self.verse_order_list[0] == 'c1') and (self.verse_order_list[1] == 'v1'):
285 new_verse_order_list = ['c1', 'v1', 'c1']
286 i = 2
287 auto_verse_order_ok = True
288 # if we are in a case we can deal with
289 if auto_verse_order_ok:
290 while i < len(self.verse_order_list):
291 if self.verse_order_list[i].startswith('v'):
292 new_verse_order_list.append(self.verse_order_list[i])
293 new_verse_order_list.append('c1')
294 else:
295 auto_verse_order_ok = False
296 self.add_comment('Importer detected unexpected verse order entry {}'.format(
297 self.verse_order_list[i]))
298 i += 1
299 self.verse_order_list = new_verse_order_list
300 else:
301 if not auto_verse_order_ok:
302 self.verse_order_list = []
303 if self.hint_verse_order:
304 self.verse_order_list = self.hint_verse_order.split(',')
305 if self.hint_comments:
306 self.add_comment(self.hint_comments)
307 if self.hint_ccli:
308 self.ccli_number = self.hint_ccli
309 # Write the title last as by now we will know if we need checks
310 if hints_available and not self.checks_needed:
311 check_flag = ''
312 elif not hints_available and not has_chorus:
313 check_flag = ''
314 elif not hints_available and has_chorus and auto_verse_order_ok:
315 check_flag = ''
316 self.title = '{}STF{} - {title}'.format(check_flag, song_number.zfill(3), title=song_title)
317 if not self.finish():
318 self.log_error(file.name)
319
320 def read_hints(self, file, song_number):
321 """
322 Read the hints used to transform a particular song into version which can be projected,
323 or improve the transformation process beyond the standard heuristics. Not every song will
324 have, or need, hints.
325 """
326 hintfound = False
327 self.hint_verse_order = ''
328 self.hint_line.clear()
329 self.hint_comments = ''
330 self.hint_song_title = ''
331 self.hint_ignore_indent = False
332 self.hint_ccli = ''
333 for tl in file:
334 if not tl.strip():
335 return hintfound
336 tagval = tl.split(':')
337 tag = tagval[0].strip()
338 val = tagval[1].strip()
339 if tag == 'Version':
340 self.hint_file_version = val
341 continue
342 if (tag == 'Hymn') and (val == song_number):
343 self.add_comment('Using hints version {}'.format(str(self.hint_file_version)))
344 hintfound = True
345 # Assume, unless the hints has ManualCheck that if hinted all will be OK
346 self.checks_needed = False
347 for tl in file:
348 tagval = tl.split(':')
349 tag = tagval[0].strip()
350 val = tagval[1].strip()
351 if tag == 'End':
352 return hintfound
353 elif tag == 'CommentsLine':
354 vals = val.split(',')
355 for v in vals:
356 self.hint_line[v] = 'Comment'
357 elif tag == 'IgnoreLine':
358 vals = val.split(',')
359 for v in vals:
360 self.hint_line[v] = 'Ignore'
361 elif tag == 'AuthorLine':
362 vals = val.split(',')
363 for v in vals:
364 self.hint_line[v] = 'Author'
365 elif tag == 'AddSpaceAfterSemi':
366 vals = val.split(',')
367 for v in vals:
368 self.hint_line[v] = 'AddSpaceAfterSemi'
369 elif tag == 'AddSpaceAfterColon':
370 vals = val.split(',')
371 for v in vals:
372 self.hint_line[v] = 'AddSpaceAfterColon'
373 elif tag == 'BlankLine':
374 vals = val.split(',')
375 for v in vals:
376 self.hint_line[v] = 'BlankLine'
377 elif tag == 'VerseOrder':
378 self.hint_verse_order = val
379 elif tag == 'ManualCheck':
380 self.checks_needed = True
381 elif tag == 'IgnoreIndent':
382 self.hint_ignore_indent = True
383 elif tag == 'VariantVerse':
384 vvline = val.split(' ', 1)
385 self.hint_line[vvline[0].strip()] = 'VariantVerse {}'.format(vvline[1].strip())
386 elif tag == 'SongTitle':
387 self.hint_song_title = val
388 elif tag == 'AddComment':
389 self.hint_comments += '\n' + val
390 elif tag == 'CCLI':
391 self.hint_ccli = val
392 elif tag == 'Hymn':
393 self.log_error(file.name, 'Missing End tag in hint for Hymn: {}'.format(song_number))
394 else:
395 self.log_error(file.name, 'Unknown tag {} value {}'.format(tag, val))
396 return hintfound
0397
=== added file 'tests/functional/openlp_plugins/songs/test_singingthefaithimport.py'
--- tests/functional/openlp_plugins/songs/test_singingthefaithimport.py 1970-01-01 00:00:00 +0000
+++ tests/functional/openlp_plugins/songs/test_singingthefaithimport.py 2019-07-19 11:11:28 +0000
@@ -0,0 +1,48 @@
1# -*- coding: utf-8 -*-
2# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
3
4##########################################################################
5# OpenLP - Open Source Lyrics Projection #
6# ---------------------------------------------------------------------- #
7# Copyright (c) 2008-2019 OpenLP Developers #
8# ---------------------------------------------------------------------- #
9# This program is free software: you can redistribute it and/or modify #
10# it under the terms of the GNU General Public License as published by #
11# the Free Software Foundation, either version 3 of the License, or #
12# (at your option) any later version. #
13# #
14# This program is distributed in the hope that it will be useful, #
15# but WITHOUT ANY WARRANTY; without even the implied warranty of #
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
17# GNU General Public License for more details. #
18# #
19# You should have received a copy of the GNU General Public License #
20# along with this program. If not, see <https://www.gnu.org/licenses/>. #
21##########################################################################
22"""
23This module contains tests for the SingingTheFaith song importer.
24"""
25from tests.helpers.songfileimport import SongImportTestHelper
26from tests.utils.constants import RESOURCE_PATH
27
28
29TEST_PATH = RESOURCE_PATH / 'songs' / 'singingthefaith'
30
31
32class TestSingingTheFaithFileImport(SongImportTestHelper):
33
34 def __init__(self, *args, **kwargs):
35 self.importer_class_name = 'SingingTheFaithImport'
36 self.importer_module_name = 'singingthefaith'
37 super(TestSingingTheFaithFileImport, self).__init__(*args, **kwargs)
38
39 def test_song_import(self):
40 """
41 Test that loading a Singing The Faith file works correctly on various files
42 """
43 # Single verse
44 self.file_import([TEST_PATH / 'H1.txt'],
45 self.load_external_result_data(TEST_PATH / 'STF001.json'))
46 # Whole song
47 self.file_import([TEST_PATH / 'H2.txt'],
48 self.load_external_result_data(TEST_PATH / 'STF002.json'))
049
=== modified file 'tests/helpers/songfileimport.py'
--- tests/helpers/songfileimport.py 2019-05-22 06:47:00 +0000
+++ tests/helpers/songfileimport.py 2019-07-19 11:11:28 +0000
@@ -123,7 +123,8 @@
123 log.debug("Song copyright imported: %s" % importer.song_number)123 log.debug("Song copyright imported: %s" % importer.song_number)
124 log.debug("Topics imported: %s" % importer.topics)124 log.debug("Topics imported: %s" % importer.topics)
125125
126 assert importer.title == title, 'title for %s should be "%s"' % (source_file_name, title)126 assert importer.title == title, \
127 'title for %s should be "%s" and is "%s"' % (source_file_name, title, importer.title)
127 for author in author_calls:128 for author in author_calls:
128 if isinstance(author, str):129 if isinstance(author, str):
129 self.mocked_add_author.assert_any_call(author)130 self.mocked_add_author.assert_any_call(author)
130131
=== added directory 'tests/resources/songs/singingthefaith'
=== added file 'tests/resources/songs/singingthefaith/H1.txt'
--- tests/resources/songs/singingthefaith/H1.txt 1970-01-01 00:00:00 +0000
+++ tests/resources/songs/singingthefaith/H1.txt 2019-07-19 11:11:28 +0000
@@ -0,0 +1,9 @@
1
21 Amazing Grace! how sweet the sound!
3 That saved a wretch like me!
4 I once was lost, but now am found;
5 Was blind, but now I see.
6
7John Newton (d. 1807)
8
9Reproduced from Singing the Faith Electronic Words Edition, number 1 - or not as this is a hand made test file
010
=== added file 'tests/resources/songs/singingthefaith/H2.txt'
--- tests/resources/songs/singingthefaith/H2.txt 1970-01-01 00:00:00 +0000
+++ tests/resources/songs/singingthefaith/H2.txt 2019-07-19 11:11:28 +0000
@@ -0,0 +1,30 @@
1
21 Amazing Grace! how sweet the sound!
3 That saved a wretch like me!
4 I once was lost, but now am found;
5 Was blind, but now I see.
6
72 'Twas grace that taught my heart to fear,
8 And grace my fears relieved.
9 How precious did that grace appear,
10 The hour I first believed.
11
123 The Lord has promised good to me,
13 His Word my hope secures.
14 He will my shield and portion be
15 As long as life endures.
16
174 Thro' many dangers, toils and snares
18 I have already come.
19 'Tis grace that brought me safe thus far,
20 And grace will lead me home.
21
225 When we've been there ten thousand years,
23 Bright shining as the sun,
24 We've no less days to sing God's praise,
25 Than when we first begun.
26
27
28John Newton (d. 1807)
29
30Reproduced from Singing the Faith Electronic Words Edition, number 2 - or not as this is a hand made test file
031
=== added file 'tests/resources/songs/singingthefaith/STF001.json'
--- tests/resources/songs/singingthefaith/STF001.json 1970-01-01 00:00:00 +0000
+++ tests/resources/songs/singingthefaith/STF001.json 2019-07-19 11:11:28 +0000
@@ -0,0 +1,13 @@
1{
2 "title": "STF001 - Amazing Grace! how sweet the sound!",
3 "authors": [
4 "John Newton (d. 1807)"
5 ],
6 "verse_order_list": ["v1"],
7 "verses": [
8 [
9 "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.",
10 "v"
11 ]
12 ]
13}
014
=== added file 'tests/resources/songs/singingthefaith/STF002.json'
--- tests/resources/songs/singingthefaith/STF002.json 1970-01-01 00:00:00 +0000
+++ tests/resources/songs/singingthefaith/STF002.json 2019-07-19 11:11:28 +0000
@@ -0,0 +1,29 @@
1{
2 "title": "STF002 - Amazing Grace! how sweet the sound!",
3 "authors": [
4 "John Newton (d. 1807)"
5 ],
6 "verse_order_list": ["v1", "v2", "v3", "v4", "v5"],
7 "verses": [
8 [
9 "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.",
10 "v"
11 ],
12 [
13 "'Twas grace that taught my heart to fear,\nAnd grace my fears relieved.\nHow precious did that grace appear,\nThe hour I first believed.",
14 "v"
15 ],
16 [
17 "The Lord has promised good to me,\nHis Word my hope secures.\nHe will my shield and portion be\nAs long as life endures.",
18 "v"
19 ],
20 [
21 "Thro' many dangers, toils and snares\nI have already come.\n'Tis grace that brought me safe thus far,\nAnd grace will lead me home.",
22 "v"
23 ],
24 [
25 "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 first begun.",
26 "v"
27 ]
28 ]
29}