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

Proposed by John Lines on 2019-07-19
Status: Superseded
Proposed branch: lp:~john+ubuntu-g/openlp/singingthefaith
Merge into: lp:openlp
Diff against target: 1336 lines (+1247/-11)
9 files modified
openlp/plugins/songs/lib/importer.py (+23/-10)
openlp/plugins/songs/lib/importers/singingthefaith.py (+427/-0)
resources/hints.tag (+666/-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 2019-07-19 Needs Information on 2019-08-29
Phill 2019-07-19 Pending
Raoul Snyman 2019-07-19 Pending
Review via email: mp+370364@code.launchpad.net

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

This proposal has been superseded by a proposal from 2019-08-29.

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 600, hymns it has been tested with.

Documentation for the source format and hints file is at https://wiki.openlp.org/Development:SingingTheFaith_Format

The change includes a test module, which works for the single verse case, and for a whole song.

To post a comment you must log in.
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

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
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.

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

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
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.

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

Linux tests passed!

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

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

Fix lint tests outside main importer code

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

Linux tests passed!

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

Linting passed!

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

macOS tests passed!

Phill (phill-ridout) wrote : Posted in a previous version of this proposal

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
Tomas Groth (tomasgroth) wrote : Posted in a previous version of this proposal

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

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

Using new string formatting, constructor for class.

Raoul Snyman (raoul-snyman) wrote :

Linux tests passed!

Raoul Snyman (raoul-snyman) wrote :

Linting passed!

2899. By John Lines on 2019-07-27

Strip unwanted formatting characters

2900. By John Lines on 2019-07-28

Implement BoldLine hint

Phill (phill-ridout) wrote :

Just a few more inline comments.

2901. By John Lines on 2019-07-28

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

2902. By John Lines on 2019-07-28

Fix typo

2903. By John Lines on 2019-08-12

Merge trunk updates

Raoul Snyman (raoul-snyman) wrote :

Hey John, if you're ready for us to take another look at this, make sure to resubmit it.

Tomas Groth (tomasgroth) wrote :

Is there any reason the hint file isn't included? If it is not bundled with OpenLP, then where is the user supposed to get it from?

2904. By John Lines on 2019-08-23

Use .format in importer.py

2905. By John Lines on 2019-08-23

Implement SongbookNumberInTitle hint

John Lines (john+ubuntu-g) wrote :

The use of STFnnn - in the title is now controlled by a hint. Also other code tidying.

Tomas Groth (tomasgroth) wrote :

Hi John,

I still don't get why the hint file is not included...
If you already made the file, why should others have to do it? I assume that the "Singing The Faith" files that can be imported are the same for all potential users?

review: Needs Information
2906. By John Lines on 2019-08-29

Upload hints.tag into resources

2907. By John Lines on 2019-09-03

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

2908. By John Lines on 2019-09-03

Merge trunk updates

2909. By John Lines on 2019-09-03

add tests with hints subdirectory

2910. By John Lines on 2019-09-03

Linting fix

2911. By John Lines on 2019-09-04

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

Unmerged revisions

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-08-29 21:51:57 +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,16 @@
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': '{text} (*.txt)'.format(text=translate('SongsPlugin.ImportWizardForm',
353 'Singing The Faith Exported Files')),
354 'descriptionText': translate('SongsPlugin.ImportWizardForm',
355 'First use Singing The Faith Electonic edition to export '
356 'the song(s) in Text format.')
357 },
346 SongBeamer: {358 SongBeamer: {
347 'class': SongBeamerImport,359 'class': SongBeamerImport,
348 'name': 'SongBeamer',360 'name': 'SongBeamer',
@@ -462,6 +474,7 @@
462 SongFormat.PowerSong,474 SongFormat.PowerSong,
463 SongFormat.PresentationManager,475 SongFormat.PresentationManager,
464 SongFormat.ProPresenter,476 SongFormat.ProPresenter,
477 SongFormat.SingingTheFaith,
465 SongFormat.SongBeamer,478 SongFormat.SongBeamer,
466 SongFormat.SongPro,479 SongFormat.SongPro,
467 SongFormat.SongShowPlus,480 SongFormat.SongShowPlus,
468481
=== 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-08-29 21:51:57 +0000
@@ -0,0 +1,427 @@
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 self.hint_songbook_number_in_title = False
57
58 def do_import(self):
59 """
60 Receive a single file or a list of files to import.
61 """
62 if not isinstance(self.import_source, list):
63 return
64 self.import_wizard.progress_bar.setMaximum(len(self.import_source))
65 for file_path in self.import_source:
66 if self.stop_import_flag:
67 return
68 # If this is backported to version 2.4 then do_import is called with a filename
69 # rather than a path object if called from the development version.
70 # Check here to minimise differences between versions.
71 if isinstance(file_path, str):
72 song_file = open(file_path, 'rt', encoding='cp1251')
73 self.do_import_file(song_file)
74 song_file.close()
75 else:
76 with file_path.open('rt', encoding='cp1251') as song_file:
77 self.do_import_file(song_file)
78
79 def do_import_file(self, file):
80 """
81 Process the SingingTheFaith file - pass in a file-like object, not a file path.
82 """
83 singing_the_faith_version = 1
84 self.set_defaults()
85 # Setup variables
86 line_number = 0
87 old_indent = 0
88 # The chorus indent is how many spaces the chorus is indented - it might be 6,
89 # but we test for >= and I do not know how consistent to formatting of the
90 # exported songs is.
91 chorus_indent = 5
92 # Initialise the song title - the format of the title finally produced can be affected
93 # by the SongbookNumberInTitle option in the hints file
94 song_title = 'STF000 -'
95 song_number = '0'
96 ccli = '0'
97 current_verse = ''
98 current_verse_type = 'v'
99 current_verse_number = 1
100 # Potentially we could try to track current chorus number to automatically handle
101 # more than 1 chorus, currently unused.
102 # current_chorus_number = 1
103 has_chorus = False
104 chorus_written = False
105 auto_verse_order_ok = False
106 copyright = ''
107 # the check_flag is prepended to the title, removed if the import should be OK
108 # all the songs which need manual editing should sort below all the OK songs
109 check_flag = 'z'
110
111 self.add_comment(
112 'Imported with Singing The Faith Importer v{no}'.format(no=singing_the_faith_version))
113
114 # Get the file_song_number - so we can use it for hints
115 filename = Path(file.name)
116 song_number_file = filename.stem
117 song_number_match = re.search(r'\d+', song_number_file)
118 if song_number_match:
119 song_number_file = song_number_match.group()
120
121 # See if there is a hints file in the same location as the file
122 dir_path = filename.parent
123 hints_file_path = dir_path / 'hints.tag'
124 try:
125 with hints_file_path.open('r') as hints_file:
126 hints_available = self.read_hints(hints_file, song_number_file)
127 except FileNotFoundError:
128 hints_available = False
129
130 try:
131 for line in file:
132 line_number += 1
133 # Strip out leftover formatting (\i and \b)
134 line = line.replace('\\i', '')
135 line = line.replace('\\b', '')
136 if hints_available and str(line_number) in self.hint_line:
137 hint = self.hint_line[str(line_number)]
138 # Set to false if this hint does not replace the line
139 line_replaced = True
140 if hint == 'Comment':
141 line.strip()
142 self.add_comment(line)
143 continue
144 elif hint == 'Ignore':
145 continue
146 elif hint == 'Author':
147 # add as a raw author - do not split
148 line.strip()
149 self.add_author(line)
150 line_number += 1
151 next(file)
152 continue
153 elif hint.startswith('VariantVerse'):
154 vv, hintverse, replace = hint.split(' ', 2)
155 this_verse = self.verses[int(hintverse) - 1]
156 this_verse_str = this_verse[1]
157 new_verse = this_verse_str
158 # There might be multiple replace pairs separated by |
159 replaces = replace.split('|')
160 for rep in replaces:
161 source_str, dest_str = rep.split('/')
162 new_verse = new_verse.replace(source_str, dest_str)
163 self.add_verse(new_verse, 'v')
164 self.verse_order_list.append('v{}'.format(str(current_verse_number)))
165 current_verse_number += 1
166 line_number += 1
167 next(file)
168 continue
169 elif hint == 'AddSpaceAfterSemi':
170 line = line.replace(';', '; ')
171 line_replaced = False
172 # note - do not use contine here as the line should now be processed as normal.
173 elif hint == 'AddSpaceAfterColon':
174 line = line.replace(':', ': ')
175 line_replaced = False
176 elif hint == 'BlankLine':
177 line = ' *Blank*'
178 line_replaced = False
179 elif hint == 'BoldLine':
180 # processing of the hint is deferred, but pick it up as a known hint here
181 line_replaced = False
182 else:
183 self.log_error(translate('SongsPlugin.SingingTheFaithImport',
184 'File {file})'.format(file=file.name)),
185 translate('SongsPlugin.SingingTheFaithImport',
186 'Unknown hint {hint}').format(hint=hint))
187 if line_replaced:
188 return
189 # STF exported lines have a leading verse number at the start of each verse.
190 # remove them - note that we want to track the indent as that shows a chorus
191 # so will deal with that before stripping all leading spaces.
192 indent = 0
193 if line.strip():
194 # One hymn has one line which starts '* 6' at the start of a verse
195 # Strip this out
196 if line.startswith('* 6'):
197 line = line.lstrip('* ')
198 verse_num_match = re.search(r'^\d+', line)
199 if verse_num_match:
200 # Could extract the verse number and check it against the calculated
201 # verse number - TODO
202 # verse_num = verse_num_match.group()
203 line = line.lstrip('0123456789')
204 indent_match = re.search(r'^\s+', line)
205 if indent_match:
206 indent = len(indent_match.group())
207 # Assuming we have sorted out what is verse and what is chorus, strip lines,
208 # unless ignoreIndent
209 if self.hint_ignore_indent:
210 line = line.rstrip()
211 else:
212 line = line.strip()
213 if line_number == 2:
214 # note that songs seem to start with a blank line so the title is line 2
215 # Also we strip blanks from the title, even if ignoring indent.
216 song_title = line.strip()
217 # Process possible line formatting hints after the verse number has been removed
218 if hints_available and str(line_number) in self.hint_line and hint == 'BoldLine':
219 line = '{{st}}{0}{{/st}}'.format(line)
220 # Detect the 'Reproduced from Singing the Faith Electronic Words Edition' line
221 if line.startswith('Reproduced from Singing the Faith Electronic Words Edition'):
222 song_number_match = re.search(r'\d+', line)
223 if song_number_match:
224 song_number = song_number_match.group()
225 continue
226 elif indent == 0:
227 # If the indent is 0 and it contains '(c)' then it is a Copyright line
228 if '(c)' in line:
229 copyright = line
230 continue
231 elif (line.startswith('Liturgical ') or line.startswith('From The ') or
232 line.startswith('From Common ') or line.startswith('Based on Psalm ')):
233 self.add_comment(line)
234 continue
235 # If indent is 0 it may be the author, unless it was one of the cases covered above
236 elif len(line) > 0:
237 # May have more than one author, separated by ' and '
238 authors = line.split(' and ')
239 for a in authors:
240 self.parse_author(a)
241 continue
242 # If a blank line has bee replaced by *Blank* then put it back to being
243 # a simple space since this is past stripping blanks
244 if '*Blank*' in line:
245 line = ' '
246 if line == '':
247 if current_verse != '':
248 self.add_verse(current_verse, current_verse_type)
249 self.verse_order_list.append(current_verse_type + str(current_verse_number))
250 if current_verse_type == 'c':
251 chorus_written = True
252 else:
253 current_verse_number += 1
254 current_verse = ''
255 if chorus_written:
256 current_verse_type = 'v'
257 else:
258 # If the line is indented more than or equal chorus_indent then assume it is a chorus
259 # If the indent has just changed then start a new verse just like hitting a blank line
260 if not self.hint_ignore_indent and ((indent >= chorus_indent) and (old_indent < indent)):
261 if current_verse != '':
262 self.add_verse(current_verse, current_verse_type)
263 self.verse_order_list.append(current_verse_type + str(current_verse_number))
264 if current_verse_type == 'v':
265 current_verse_number += 1
266 current_verse = line
267 current_verse_type = 'c'
268 old_indent = indent
269 chorus_written = False
270 has_chorus = True
271 continue
272 if current_verse == '':
273 current_verse += line
274 else:
275 current_verse += '\n' + line
276 old_indent = indent
277 except Exception as e:
278 self.log_error(translate('SongsPlugin.SingingTheFaithImport', 'File {file}').format(file=file.name),
279 translate('SongsPlugin.SingingTheFaithImport', 'Error: {error}').format(error=e))
280 return
281
282 if self.hint_song_title:
283 song_title = self.hint_song_title
284 self.title = '{}STF{} - {title}'.format(check_flag, song_number.zfill(3), title=song_title)
285 self.song_book_name = 'Singing The Faith'
286 self.song_number = song_number
287 self.ccli_number = ccli
288 self.add_copyright(copyright)
289 # If we have a chorus then the generated Verse order can not be used directly, but we can generate
290 # one for two special cases - Verse followed by one chorus (to be repeated after every verse)
291 # of Chorus, followed by verses. If hints for ManualCheck or VerseOrder are supplied ignore this
292 if has_chorus and not self.hint_verse_order and not self.checks_needed:
293 auto_verse_order_ok = False
294 # Popular case V1 C2 V2 ...
295 if self.verse_order_list: # protect against odd cases
296 if self.verse_order_list[0] == 'v1' and self.verse_order_list[1] == 'c2':
297 new_verse_order_list = ['v1', 'c1']
298 i = 2
299 auto_verse_order_ok = True
300 elif self.verse_order_list[0] == 'c1' and self.verse_order_list[1] == 'v1':
301 new_verse_order_list = ['c1', 'v1', 'c1']
302 i = 2
303 auto_verse_order_ok = True
304 # if we are in a case we can deal with
305 if auto_verse_order_ok:
306 while i < len(self.verse_order_list):
307 if self.verse_order_list[i].startswith('v'):
308 new_verse_order_list.append(self.verse_order_list[i])
309 new_verse_order_list.append('c1')
310 else:
311 auto_verse_order_ok = False
312 self.add_comment('Importer detected unexpected verse order entry {}'.format(
313 self.verse_order_list[i]))
314 i += 1
315 self.verse_order_list = new_verse_order_list
316 else:
317 if not auto_verse_order_ok:
318 self.verse_order_list = []
319 if self.hint_verse_order:
320 self.verse_order_list = self.hint_verse_order.split(',')
321 if self.hint_comments:
322 self.add_comment(self.hint_comments)
323 if self.hint_ccli:
324 self.ccli_number = self.hint_ccli
325 # Write the title last as by now we will know if we need checks
326 if hints_available and not self.checks_needed:
327 check_flag = ''
328 elif not hints_available and not has_chorus:
329 check_flag = ''
330 elif not hints_available and has_chorus and auto_verse_order_ok:
331 check_flag = ''
332 if self.hint_songbook_number_in_title:
333 self.title = '{}STF{} - {title}'.format(check_flag, song_number.zfill(3), title=song_title)
334 else:
335 self.title = '{}{title}'.format(check_flag, title=song_title)
336 if not self.finish():
337 self.log_error(file.name)
338
339 def read_hints(self, file, song_number):
340 """
341 Read the hints used to transform a particular song into version which can be projected,
342 or improve the transformation process beyond the standard heuristics. Not every song will
343 have, or need, hints.
344 """
345 hintfound = False
346 self.hint_verse_order = ''
347 self.hint_line.clear()
348 self.hint_comments = ''
349 self.hint_song_title = ''
350 self.hint_ignore_indent = False
351 self.hint_ccli = ''
352 for tl in file:
353 if not tl.strip():
354 return hintfound
355 tagval = tl.split(':')
356 tag = tagval[0].strip()
357 val = tagval[1].strip()
358 if tag == 'Version':
359 self.hint_file_version = val
360 continue
361 elif tag == 'SongbookNumberInTitle':
362 if val == 'False':
363 self.hint_songbook_number_in_title = False
364 else:
365 self.hint_songbook_number_in_title = True
366 continue
367 elif tag == 'Comment':
368 continue
369 if (tag == 'Hymn') and (val == song_number):
370 self.add_comment('Using hints version {}'.format(str(self.hint_file_version)))
371 hintfound = True
372 # Assume, unless the hints has ManualCheck that if hinted all will be OK
373 self.checks_needed = False
374 for tl in file:
375 tagval = tl.split(':')
376 tag = tagval[0].strip()
377 val = tagval[1].strip()
378 if tag == 'End':
379 return hintfound
380 elif tag == 'CommentsLine':
381 vals = val.split(',')
382 for v in vals:
383 self.hint_line[v] = 'Comment'
384 elif tag == 'IgnoreLine':
385 vals = val.split(',')
386 for v in vals:
387 self.hint_line[v] = 'Ignore'
388 elif tag == 'AuthorLine':
389 vals = val.split(',')
390 for v in vals:
391 self.hint_line[v] = 'Author'
392 elif tag == 'AddSpaceAfterSemi':
393 vals = val.split(',')
394 for v in vals:
395 self.hint_line[v] = 'AddSpaceAfterSemi'
396 elif tag == 'AddSpaceAfterColon':
397 vals = val.split(',')
398 for v in vals:
399 self.hint_line[v] = 'AddSpaceAfterColon'
400 elif tag == 'BlankLine':
401 vals = val.split(',')
402 for v in vals:
403 self.hint_line[v] = 'BlankLine'
404 elif tag == 'BoldLine':
405 vals = val.split(',')
406 for v in vals:
407 self.hint_line[v] = 'BoldLine'
408 elif tag == 'VerseOrder':
409 self.hint_verse_order = val
410 elif tag == 'ManualCheck':
411 self.checks_needed = True
412 elif tag == 'IgnoreIndent':
413 self.hint_ignore_indent = True
414 elif tag == 'VariantVerse':
415 vvline = val.split(' ', 1)
416 self.hint_line[vvline[0].strip()] = 'VariantVerse {}'.format(vvline[1].strip())
417 elif tag == 'SongTitle':
418 self.hint_song_title = val
419 elif tag == 'AddComment':
420 self.hint_comments += '\n' + val
421 elif tag == 'CCLI':
422 self.hint_ccli = val
423 elif tag == 'Hymn':
424 self.log_error(file.name, 'Missing End tag in hint for Hymn: {}'.format(song_number))
425 else:
426 self.log_error(file.name, 'Unknown tag {} value {}'.format(tag, val))
427 return hintfound
0428
=== added file 'resources/hints.tag'
--- resources/hints.tag 1970-01-01 00:00:00 +0000
+++ resources/hints.tag 2019-08-29 21:51:57 +0000
@@ -0,0 +1,666 @@
1Tag-STFHints-version: 1.0
2Version: 2
3SongbookNumberInTitle: True
4End:
5Hymn: 2
6VerseOrder: V1,C1,V2,C1,V3,C1
7End:
8Hymn: 8
9AddSpaceAfterColon: 2,11,20,33
10End:
11Hymn: 10
12CommentsLine: 17
13End:
14Hymn: 11
15CommentsLine: 24
16End:
17Hymn: 15
18VerseOrder: V1,C1,V2,C1,C2,C1
19End:
20Hymn: 18
21CommentsLine: 16
22End:
23Hymn: 19
24CommentsLine: 8
25End:
26Hymn: 22
27CommentsLine: 20
28End:
29Hymn: 24
30IgnoreLine: 13
31VerseOrder: V1,V2,V1
32End:
33Hymn: 26
34VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C1
35End:
36Hymn: 27
37AddComment: Verse 1 is original Shona
38SongTitle: Jesu, tawa pano
39IgnoreLine: 2
40CommentsLine: 31
41End:
42Hymn: 28
43CommentsLine: 41
44End:
45Hymn: 29
46CommentsLine: 18
47End:
48Hymn: 30
49CommentsLine: 26
50End:
51Hymn: 35
52VerseOrder: V1,C1,V2,C1,V3,C1
53End:
54Hymn: 37
55IgnoreLine: 42
56VerseOrder: V1,V2,C1,V3,V4,C1
57End:
58Hymn: 38
59ManualCheck: Yes
60AddComment: Make all and cantor words Bold tagged for readability
61SongTitle: Wa wa wa Emimimo
62End:
63Hymn: 40
64VariantVerse: 15 1 Blessed be the name of the Lord/Glory to the name of the Lord|blessed be the name/glory to the name
65VariantVerse: 17 1 Blessed be the name of the Lord/Holy is the name of the Lord|blessed be the name/holy is the name
66VerseOrder: V1,C1,V2,C1,V3,C1
67End:
68Hymn: 41
69IgnoreIndent: Yes
70IgnoreLine: 35,42
71VerseOrder: V1,V2,V3,V4,V2,V3,V5,V3
72End:
73Hymn: 43
74IgnoreIndent: Yes
75CommentsLine: 40
76End:
77Hymn: 45
78IgnoreIndent: Yes
79CommentsLine: 104
80End:
81Hymn: 46
82VerseOrder: V1,C1,V2,C1,C2,C1
83End:
84Hymn: 48
85VerseOrder: V1,C1,V2,C2
86End:
87Hymn: 51
88VerseOrder: V1,C1,V2,C1,V3,C1
89End:
90Hymn: 55
91AddSpaceAfterSemi: 15
92End:
93Hymn: 60
94CommentsLine: 22
95End:
96Hymn: 61
97VerseOrder: C1,V1,C1
98End:
99Hymn: 64
100IgnoreLine: 23,25
101VerseOrder: V1,C1,C2,V2,C1,C2,C3
102End:
103Hymn: 65
104VerseOrder: V1,C1,V2,C2,V3,C1,V4,C1
105End:
106Hymn: 68
107IgnoreLine: 15,31
108VerseOrder: C1,V1,C1,V2,C2,C1
109End:
110Hymn: 71
111IgnoreLine: 23
112VerseOrder: V1,C1,V2,C1,V3
113End:
114Hymn: 74
115IgnoreIndent: Yes
116End:
117Hymn: 77
118IgnoreLine: 32
119CommentsLine: 37
120VerseOrder: V1,V2,C1,V3,C1
121End:
122Hymn: 78
123VerseOrder: V1,V2,V1,V2,V3
124End:
125Hymn: 82
126VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1
127End:
128Hymn: 84
129IgnoreIndent: Yes
130End:
131Hymn: 86
132CommentsLine: 86
133End:
134Hymn: 89
135VerseOrder: V1,V2,C1
136End:
137Hymn: 92
138IgnoreIndent: Yes
139IgnoreLine: 2,18,48
140SongTitle: Think of a world without any flowers
141End:
142Hymn: 93
143AddSpaceAfterSemi: 9,10,11,12
144IgnoreLine: 21,30,31,32,33
145VerseOrder: V1,C1,V2,C1,V3,C1
146End:
147Hymn: 94
148AuthorLine: 24
149VerseOrder: V1,C1,V2,C1,V3,C1
150End:
151Hymn: 95
152AddSpaceAfterSemi: 2
153End:
154Hymn: 98
155IgnoreLine: 17,19,24
156VerseOrder: V1,C1,V2,C1,C2,C1
157AddComment: C2 is an optional Bridge
158End:
159Hymn: 100
160VerseOrder: C1,V1,C1,V2,C1,V3,C1,V4,C1
161End:
162Hymn: 102
163VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C1
164End:
165Hymn: 103
166AddSpaceAfterColon: 2,3,11,20
167End:
168Hymn: 105
169VerseOrder: C1,V1,C1,V2,C1
170End:
171Hymn: 118
172IgnoreLine: 15,21
173CommentsLine: 28
174VerseOrder: V1,C1,C1,V2,C1,V3,C1,C1,C2
175End:
176Hymn: 123
177CommentsLine: 40
178End:
179Hymn: 140
180IgnoreLine: 14
181VerseOrder: V1,C1,V2,C1
182End:
183Hymn: 141
184AddSpaceAfterSemi: 2
185End:
186Hymn: 145
187ManualCheck: Yes
188AddComment: Make cantor and all bold, and add to all verses
189SongTitle: Night has fallen
190End:
191Hymn: 147
192AddSpaceAfterSemi: 22
193End:
194Hymn: 165
195IgnoreLine: 2,11,20,29,38
196CommentsLine: 50
197SongTitle: Advent candles tell their story
198End:
199Hymn: 166
200CommentsLine: 40
201VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C2
202End:
203Hymn: 168
204CommentsLine: 30
205End:
206Hymn: 170
207VerseOrder: V1,C1,V2,C1,V3,C1,V4,C2
208End:
209Hymn: 173
210VerseOrder: V1,C1,V2,C1,V3,C2
211End:
212Hymn: 174
213CommentsLine: 41
214End:
215Hymn: 175
216IgnoreLine: 22,29
217VerseOrder: V1,C1,V2,C1,C2,C1
218End:
219Hymn: 176
220CommentsLine: 26
221ManualCheck: Yes
222End:
223Hymn: 178
224VerseOrder: V1,C1,V2,C1,V3,C1,V4,C2
225End:
226Hymn: 186
227IgnoreIndent: Yes
228CommentsLine: 24
229End:
230Hymn: 194
231IgnoreIndent: Yes
232End:
233Hymn: 200
234AddSpaceAfterColon: 2
235CommentsLine: 24
236End:
237Hymn: 209
238IgnoreLine: 11,17,23
239VerseOrder: V1,C1,C1,V2,C1,V3,C1
240End:
241Hymn: 212
242CommentsLine: 46
243End:
244Hymn: 220
245AddSpaceAfterColon: 30
246End:
247Hymn: 227
248VerseOrder: V1,V2,V3,V4,V1
249End:
250Hymn: 228
251CommentsLine: 49
252End:
253Hymn: 234
254CommentsLine: 7
255End:
256Hymn: 235
257IgnoreIndent: Yes
258End:
259Hymn: 240
260CommentsLine: 24
261End:
262Hymn: 241
263IgnoreLine: 39
264VerseOrder: V1,C1,V2,C2,C3,C2
265AddComment: is the final chorus a repeat of C1 or C2 ?
266ManualCheck: Yes
267End:
268Hymn: 246
269VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1
270End:
271Hymn: 247
272VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C1
273End:
274Hymn: 248
275AddSpaceAfterSemi: 13
276End:
277Hymn: 249
278VerseOrder: C1,V1,C1,V2,C1,V3,C1,V4,C1
279End:
280Hymn: 252
281AddSpaceAfterColon: 1,6,9,13,16,20,23,27,30,34
282End:
283Hymn: 254
284CommentsLine: 22
285End:
286Hymn: 256
287VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C1,V6,C2
288End:
289Hymn: 258
290IgnoreLine: 14
291VerseOrder: C1,V1,C1
292End:
293Hymn: 261
294AddSpaceAfterSemi: 4
295End:
296Hymn: 267
297CommentsLine: 33
298End:
299Hymn: 274
300IgnoreLine: 21,30
301VerseOrder: V1,C1,V2,C1,C2,C1
302End:
303Hymn: 279
304IgnoreLine: 35
305VerseOrder: V1,V2,C1,V3,V4,C1
306End:
307Hymn: 285
308CommentsLine: 25
309End:
310Hymn: 298
311IgnoreIndent: Yes
312AddSpaceAfterSemi: 8
313End:
314Hymn: 299
315IgnoreLine: 26
316CommentsLine: 32
317VerseOrder: V1,C1,V2,V3,V4,C1,C2
318End:
319Hymn: 300
320AddSpaceAfterSemi: 8,9,13,17,18
321AddSpaceAfterColon: 7,15,20,25,30
322End:
323Hymn: 302
324VerseOrder: C1,V1,C1,V2,C1,V3,C1,V4,C1,V5,C1
325End:
326Hymn: 316
327VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C1,V6,C1,V7,C2
328End:
329Hymn: 321
330CommentsLine: 15
331End:
332Hymn: 323
333AddSpaceAfterSemi: 11
334End:
335Hymn: 331
336VerseOrder: V1,C1,V2,C2
337End:
338Hymn: 335
339VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C2
340End:
341Hymn: 343
342IgnoreLine: 24
343VerseOrder: V1,V2,C1,V3,C1
344End:
345Hymn: 349
346AddSpaceAfterSemi: 20,24
347IgnoreLine: 17
348AddComment: The refrain is optional
349VerseOrder: V1,V2,V3,C1,V4,V3
350End:
351Hymn: 351
352CCLI: 3350395
353End:
354Hymn: 353
355AddSpaceAfterSemi: 15
356End:
357Hymn: 364
358AddSpaceAfterSemi: 22
359End:
360Hymn: 367
361IgnoreLine: 28
362VerseOrder: V1,C1,V2,C1
363End:
364Hymn: 373
365CommentsLine: 26
366End:
367Hymn: 374
368ManualCheck: Yes
369CommentsLine: 24
370End:
371Hymn: 377
372VerseOrder: V1,C1,V2,C1,V3,C1
373End:
374Hymn: 380
375VerseOrder: V1,C1,V2,C1
376End:
377Hymn: 386
378BlankLine: 6,16
379IgnoreLine: 19,26
380VerseOrder: V1,C1,V2,C1,C2,C1
381End:
382Hymn: 389
383AuthorLine: 21
384End:
385Hymn: 401
386AddSpaceAfterSemi: 27
387End:
388Hymn: 403
389AddSpaceAfterColon: 2
390End:
391Hymn: 404
392SongTitle: Go tell everyone
393VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1
394End:
395Hymn: 405
396VerseOrder: V1,C1,V2,C1,V3,C1
397End:
398Hymn: 406
399IgnoreLine: 18,27
400End:
401Hymn: 407
402IgnoreLine: 31
403VerseOrder: V1,V2,C1,V3,C1
404End:
405Hymn: 408
406IgnoreIndent: Yes
407CommentsLine: 25
408End:
409Hymn: 410
410AddSpaceAfterSemi: 15,16
411End:
412Hymn: 419
413CommentsLine: 25
414End:
415Hymn: 420
416IgnoreIndent: Yes
417End:
418Hymn: 421
419IgnoreIndent: Yes
420CommentsLine: 55
421End:
422Hymn: 424
423IgnoreLine: 16
424VerseOrder: V1,C1,V2,C1
425End:
426Hymn: 428
427IgnoreLine: 25
428VerseOrder: V1,V2,C1,V3,C1
429End:
430Hymn: 432
431AddSpaceAfterSemi: 8
432End:
433Hymn: 433
434CommentsLine: 44
435End:
436Hymn: 447
437IgnoreLine: 19,21
438VerseOrder: V1,V2,C1,V3,C1,V1
439End:
440Hymn: 451
441IgnoreLine: 14,16
442VerseOrder: C1,V1,C1,V1,V2
443End:
444Hymn: 454
445CommentsLine: 2,42
446SongTitle: Where shall my wondering soul begin
447End:
448Hymn: 458
449CommentsLine: 2
450SongTitle: Away with our fears The glad morning appears
451End:
452Hymn: 469
453ManualCheck: Yes
454AddComment: Need a VariantChorus, Chorus2 and Chorus3 are Variants of Chorus1
455VerseOrder: V1,C1,V2,C2,V3,C2,V4,C3
456End:
457Hymn: 470
458IgnoreIndent: Yes
459End:
460Hymn: 476
461VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C1
462End:
463Hymn: 477
464VerseOrder: C1,V1,C1,V2,C1
465End:
466Hymn: 480
467CommentsLine: 28
468End:
469Hymn: 483
470AddComment: Verses 4 and 5 are the
471CommentsLine: 29
472End:
473Hymn: 488
474IgnoreLine: 25
475VerseOrder: V1,V2,C1,V3,C1
476End:
477Hymn: 492
478AddSpaceAfterSemi: 9,10,15
479End:
480Hymn: 499
481CommentsLine: 37
482End:
483Hymn: 509
484IgnoreIndent: Yes
485CommentsLine: 40
486End:
487Hymn: 517
488VerseOrder: V1,C1,V2,C1,V3,C1,V4,C2
489End:
490Hymn: 528
491CommentsLine: 32
492End:
493Hymn: 541
494IgnoreLine: 17,18,25
495VerseOrder: V1,V2,C1,V1,V2,V3,C1
496End:
497Hymn: 545
498CommentsLine: 28
499End:
500Hymn: 548
501AuthorLine: 22
502End:
503Hymn: 554
504IgnoreLine: 15,21
505VerseOrder: V1,C1,V2,C1,V3,C1,V4
506End:
507Hymn: 555
508IgnoreLine: 15
509VerseOrder: V1,V2,C1,V1
510End:
511Hymn: 559
512IgnoreIndent: Yes
513End:
514Hymn: 561
515CommentsLine: 45
516End:
517Hymn: 562
518CommentsLine: 38
519End:
520Hymn: 565
521IgnoreLine: 21
522VerseOrder: V1,V2,V1
523End:
524Hymn: 566
525AddSpaceAfterSemi: 27
526End:
527Hymn: 567
528ManualCheck: Yes
529AddComment: Check with musician what should be on the screen
530End:
531Hymn: 570
532VerseOrder: V1,C1,V2,C1,V3,C1
533End:
534Hymn: 575
535CommentsLine: 30
536End:
537Hymn: 578
538IgnoreLine: 11,18,25
539VerseOrder: C1,V1,C1,V2,C1,V3,C1
540End:
541Hymn: 586
542IgnoreLine: 22
543VerseOrder: V1,V2,C1,V3,C1
544End:
545Hymn: 587
546VerseOrder: V1,C1,V2,C2,V3
547End:
548Hymn: 582
549CommentsLine: 25
550End:
551Hymn: 594
552CommentsLine: 41
553End:
554Hymn: 601
555CommentsLine: 16
556End:
557Hymn: 603
558ManualCheck: Yes
559AddComment: Update Verse 4 for names of the couple
560CommentsLine: 22
561IgnoreIndent: Yes
562End:
563Hymn: 609
564CommentsLine: 37
565End:
566Hymn: 610
567CommentsLine: 29
568End:
569Hymn: 626
570IgnoreLine: 29,31,44
571VerseOrder: V1,C1,C2,V2,C1,C2,C3,C2
572End:
573Hymn: 631
574CommentsLine: 15
575End:
576Hymn: 627
577IgnoreLine: 25,36
578VerseOrder: V1,C1,V2,C1,C2,C1
579End:
580Hymn: 632
581IgnoreLine: 17,24
582VerseOrder: V1,C1,V2,C1,C2,C1
583End:
584Hymn: 635
585IgnoreLine: 23,25
586VerseOrder: V1,C1,C2,V2,C1,C2
587End:
588Hymn: 637
589CommentsLine: 41
590End:
591Hymn: 638
592CommentsLine: 34
593End:
594Hymn: 640
595CommentsLine: 19,20
596End:
597Hymn: 654
598IgnoreIndent: Yes
599End:
600Hymn: 657
601IgnoreLine: 20,21,23
602VerseOrder: V1,C1,C2,V2,C1,C2,C3
603End:
604Hymn: 662
605AddSpaceAfterSemi: 2,12
606End:
607Hymn: 670
608IgnoreLine: 27
609VerseOrder: V1,C1,V2,C1
610End:
611Hymn: 677
612CommentsLine: 31
613End:
614Hymn: 681
615IgnoreIndent: Yes
616End:
617Hymn: 684
618IgnoreIndent: Yes
619End:
620Hymn: 693
621IgnoreLine: 46,57
622VerseOrder: V1,V2,C1,V3,V4,C1,V5,C1
623End:
624Hymn: 697
625IgnoreIndent: Yes
626CommentsLine: 21
627End:
628Hymn: 699
629IgnoreLine: 23,32
630VerseOrder: V1,C1,V2,C1,C1,C2,C1
631End:
632Hymn: 700
633IgnoreIndent: Yes
634End:
635Hymn: 707
636IgnoreLine: 15
637VerseOrder: V1,C1,V2,C1,V3
638End:
639Hymn: 729
640IgnoreIndent: Yes
641End:
642Hymn: 741
643CommentsLine: 25
644End:
645Hymn: 753
646CommentsLine: 14
647IgnoreIndent: Yes
648End:
649Hymn: 754
650IgnoreIndent: Yes
651End:
652Hymn: 764
653IgnoreIndent: Yes
654CommentsLine: 31
655End:
656Hymn: 783
657BlankLine: 5
658End:
659Hymn: 819
660AddSpaceAfterSemi: 32
661End:
662Hymn: 820
663CommentsLine: 2
664BoldLine: 6,7,12,13,17,18,23,24,29,30,32,33,34,35
665SongTitle: Psalm 98 - O sing to the Lord a new song
666End:
0667
=== 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-08-29 21:51:57 +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-08-29 21:51:57 +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-08-29 21:51:57 +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-08-29 21:51:57 +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-08-29 21:51:57 +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-08-29 21:51:57 +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}