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: 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 Needs Information
Raoul Snyman Pending
Phill 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.
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 : 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 passed!

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

macOS tests passed!

Revision history for this message
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
Revision history for this message
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
Revision history for this message
John Lines (john+ubuntu-g) wrote : Posted in a previous version of this proposal

Using new string formatting, constructor for class.

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!

2899. By John Lines

Strip unwanted formatting characters

2900. By John Lines

Implement BoldLine hint

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

Just a few more inline comments.

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

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

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

Revision history for this message
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

Use .format in importer.py

2905. By John Lines

Implement SongbookNumberInTitle hint

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

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

Revision history for this message
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

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
1=== modified file 'openlp/plugins/songs/lib/importer.py'
2--- openlp/plugins/songs/lib/importer.py 2019-04-13 13:00:22 +0000
3+++ openlp/plugins/songs/lib/importer.py 2019-08-29 21:51:57 +0000
4@@ -42,6 +42,7 @@
5 from .importers.powersong import PowerSongImport
6 from .importers.presentationmanager import PresentationManagerImport
7 from .importers.propresenter import ProPresenterImport
8+from .importers.singingthefaith import SingingTheFaithImport
9 from .importers.songbeamer import SongBeamerImport
10 from .importers.songpro import SongProImport
11 from .importers.songshowplus import SongShowPlusImport
12@@ -173,16 +174,17 @@
13 PowerSong = 16
14 PresentationManager = 17
15 ProPresenter = 18
16- SongBeamer = 19
17- SongPro = 20
18- SongShowPlus = 21
19- SongsOfFellowship = 22
20- SundayPlus = 23
21- VideoPsalm = 24
22- WordsOfWorship = 25
23- WorshipAssistant = 26
24- WorshipCenterPro = 27
25- ZionWorx = 28
26+ SingingTheFaith = 19
27+ SongBeamer = 20
28+ SongPro = 21
29+ SongShowPlus = 22
30+ SongsOfFellowship = 23
31+ SundayPlus = 24
32+ VideoPsalm = 25
33+ WordsOfWorship = 26
34+ WorshipAssistant = 27
35+ WorshipCenterPro = 28
36+ ZionWorx = 29
37
38 # Set optional attribute defaults
39 __defaults__ = {
40@@ -343,6 +345,16 @@
41 'filter': '{text} (*.pro4 *.pro5 *.pro6)'.format(text=translate('SongsPlugin.ImportWizardForm',
42 'ProPresenter Song Files'))
43 },
44+ SingingTheFaith: {
45+ 'class': SingingTheFaithImport,
46+ 'name': 'SingingTheFaith',
47+ 'prefix': 'singingTheFaith',
48+ 'filter': '{text} (*.txt)'.format(text=translate('SongsPlugin.ImportWizardForm',
49+ 'Singing The Faith Exported Files')),
50+ 'descriptionText': translate('SongsPlugin.ImportWizardForm',
51+ 'First use Singing The Faith Electonic edition to export '
52+ 'the song(s) in Text format.')
53+ },
54 SongBeamer: {
55 'class': SongBeamerImport,
56 'name': 'SongBeamer',
57@@ -462,6 +474,7 @@
58 SongFormat.PowerSong,
59 SongFormat.PresentationManager,
60 SongFormat.ProPresenter,
61+ SongFormat.SingingTheFaith,
62 SongFormat.SongBeamer,
63 SongFormat.SongPro,
64 SongFormat.SongShowPlus,
65
66=== added file 'openlp/plugins/songs/lib/importers/singingthefaith.py'
67--- openlp/plugins/songs/lib/importers/singingthefaith.py 1970-01-01 00:00:00 +0000
68+++ openlp/plugins/songs/lib/importers/singingthefaith.py 2019-08-29 21:51:57 +0000
69@@ -0,0 +1,427 @@
70+# -*- coding: utf-8 -*-
71+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
72+
73+###############################################################################
74+# OpenLP - Open Source Lyrics Projection #
75+# --------------------------------------------------------------------------- #
76+# Copyright (c) 2008-2019 OpenLP Developers #
77+# --------------------------------------------------------------------------- #
78+# This program is free software; you can redistribute it and/or modify it #
79+# under the terms of the GNU General Public License as published by the Free #
80+# Software Foundation; version 3 of the License. #
81+# #
82+# This program is distributed in the hope that it will be useful, but WITHOUT #
83+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
84+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
85+# more details. #
86+# #
87+# You should have received a copy of the GNU General Public License along #
88+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
89+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
90+###############################################################################
91+"""
92+The :mod:`singingthefaith` module provides the functionality for importing songs which are
93+exported from Singing The Faith - an Authorised songbook for the Methodist Church of
94+Great Britain."""
95+
96+import logging
97+import re
98+from pathlib import Path
99+
100+from openlp.core.common.i18n import translate
101+from openlp.plugins.songs.lib.importers.songimport import SongImport
102+
103+log = logging.getLogger(__name__)
104+
105+
106+class SingingTheFaithImport(SongImport):
107+ """
108+ Import songs exported from SingingTheFaith
109+ """
110+
111+ def __init__(self, manager, **kwargs):
112+ """
113+ Initialise the class.
114+ """
115+ super(SingingTheFaithImport, self).__init__(manager, **kwargs)
116+ self.hints_available = False
117+ self.checks_needed = True
118+ self.hint_line = {}
119+ self.hint_file_version = '0'
120+ self.hint_verse_order = ''
121+ self.hint_song_title = ''
122+ self.hint_comments = ''
123+ self.hint_ccli = ''
124+ self.hint_ignore_indent = False
125+ self.hint_songbook_number_in_title = False
126+
127+ def do_import(self):
128+ """
129+ Receive a single file or a list of files to import.
130+ """
131+ if not isinstance(self.import_source, list):
132+ return
133+ self.import_wizard.progress_bar.setMaximum(len(self.import_source))
134+ for file_path in self.import_source:
135+ if self.stop_import_flag:
136+ return
137+ # If this is backported to version 2.4 then do_import is called with a filename
138+ # rather than a path object if called from the development version.
139+ # Check here to minimise differences between versions.
140+ if isinstance(file_path, str):
141+ song_file = open(file_path, 'rt', encoding='cp1251')
142+ self.do_import_file(song_file)
143+ song_file.close()
144+ else:
145+ with file_path.open('rt', encoding='cp1251') as song_file:
146+ self.do_import_file(song_file)
147+
148+ def do_import_file(self, file):
149+ """
150+ Process the SingingTheFaith file - pass in a file-like object, not a file path.
151+ """
152+ singing_the_faith_version = 1
153+ self.set_defaults()
154+ # Setup variables
155+ line_number = 0
156+ old_indent = 0
157+ # The chorus indent is how many spaces the chorus is indented - it might be 6,
158+ # but we test for >= and I do not know how consistent to formatting of the
159+ # exported songs is.
160+ chorus_indent = 5
161+ # Initialise the song title - the format of the title finally produced can be affected
162+ # by the SongbookNumberInTitle option in the hints file
163+ song_title = 'STF000 -'
164+ song_number = '0'
165+ ccli = '0'
166+ current_verse = ''
167+ current_verse_type = 'v'
168+ current_verse_number = 1
169+ # Potentially we could try to track current chorus number to automatically handle
170+ # more than 1 chorus, currently unused.
171+ # current_chorus_number = 1
172+ has_chorus = False
173+ chorus_written = False
174+ auto_verse_order_ok = False
175+ copyright = ''
176+ # the check_flag is prepended to the title, removed if the import should be OK
177+ # all the songs which need manual editing should sort below all the OK songs
178+ check_flag = 'z'
179+
180+ self.add_comment(
181+ 'Imported with Singing The Faith Importer v{no}'.format(no=singing_the_faith_version))
182+
183+ # Get the file_song_number - so we can use it for hints
184+ filename = Path(file.name)
185+ song_number_file = filename.stem
186+ song_number_match = re.search(r'\d+', song_number_file)
187+ if song_number_match:
188+ song_number_file = song_number_match.group()
189+
190+ # See if there is a hints file in the same location as the file
191+ dir_path = filename.parent
192+ hints_file_path = dir_path / 'hints.tag'
193+ try:
194+ with hints_file_path.open('r') as hints_file:
195+ hints_available = self.read_hints(hints_file, song_number_file)
196+ except FileNotFoundError:
197+ hints_available = False
198+
199+ try:
200+ for line in file:
201+ line_number += 1
202+ # Strip out leftover formatting (\i and \b)
203+ line = line.replace('\\i', '')
204+ line = line.replace('\\b', '')
205+ if hints_available and str(line_number) in self.hint_line:
206+ hint = self.hint_line[str(line_number)]
207+ # Set to false if this hint does not replace the line
208+ line_replaced = True
209+ if hint == 'Comment':
210+ line.strip()
211+ self.add_comment(line)
212+ continue
213+ elif hint == 'Ignore':
214+ continue
215+ elif hint == 'Author':
216+ # add as a raw author - do not split
217+ line.strip()
218+ self.add_author(line)
219+ line_number += 1
220+ next(file)
221+ continue
222+ elif hint.startswith('VariantVerse'):
223+ vv, hintverse, replace = hint.split(' ', 2)
224+ this_verse = self.verses[int(hintverse) - 1]
225+ this_verse_str = this_verse[1]
226+ new_verse = this_verse_str
227+ # There might be multiple replace pairs separated by |
228+ replaces = replace.split('|')
229+ for rep in replaces:
230+ source_str, dest_str = rep.split('/')
231+ new_verse = new_verse.replace(source_str, dest_str)
232+ self.add_verse(new_verse, 'v')
233+ self.verse_order_list.append('v{}'.format(str(current_verse_number)))
234+ current_verse_number += 1
235+ line_number += 1
236+ next(file)
237+ continue
238+ elif hint == 'AddSpaceAfterSemi':
239+ line = line.replace(';', '; ')
240+ line_replaced = False
241+ # note - do not use contine here as the line should now be processed as normal.
242+ elif hint == 'AddSpaceAfterColon':
243+ line = line.replace(':', ': ')
244+ line_replaced = False
245+ elif hint == 'BlankLine':
246+ line = ' *Blank*'
247+ line_replaced = False
248+ elif hint == 'BoldLine':
249+ # processing of the hint is deferred, but pick it up as a known hint here
250+ line_replaced = False
251+ else:
252+ self.log_error(translate('SongsPlugin.SingingTheFaithImport',
253+ 'File {file})'.format(file=file.name)),
254+ translate('SongsPlugin.SingingTheFaithImport',
255+ 'Unknown hint {hint}').format(hint=hint))
256+ if line_replaced:
257+ return
258+ # STF exported lines have a leading verse number at the start of each verse.
259+ # remove them - note that we want to track the indent as that shows a chorus
260+ # so will deal with that before stripping all leading spaces.
261+ indent = 0
262+ if line.strip():
263+ # One hymn has one line which starts '* 6' at the start of a verse
264+ # Strip this out
265+ if line.startswith('* 6'):
266+ line = line.lstrip('* ')
267+ verse_num_match = re.search(r'^\d+', line)
268+ if verse_num_match:
269+ # Could extract the verse number and check it against the calculated
270+ # verse number - TODO
271+ # verse_num = verse_num_match.group()
272+ line = line.lstrip('0123456789')
273+ indent_match = re.search(r'^\s+', line)
274+ if indent_match:
275+ indent = len(indent_match.group())
276+ # Assuming we have sorted out what is verse and what is chorus, strip lines,
277+ # unless ignoreIndent
278+ if self.hint_ignore_indent:
279+ line = line.rstrip()
280+ else:
281+ line = line.strip()
282+ if line_number == 2:
283+ # note that songs seem to start with a blank line so the title is line 2
284+ # Also we strip blanks from the title, even if ignoring indent.
285+ song_title = line.strip()
286+ # Process possible line formatting hints after the verse number has been removed
287+ if hints_available and str(line_number) in self.hint_line and hint == 'BoldLine':
288+ line = '{{st}}{0}{{/st}}'.format(line)
289+ # Detect the 'Reproduced from Singing the Faith Electronic Words Edition' line
290+ if line.startswith('Reproduced from Singing the Faith Electronic Words Edition'):
291+ song_number_match = re.search(r'\d+', line)
292+ if song_number_match:
293+ song_number = song_number_match.group()
294+ continue
295+ elif indent == 0:
296+ # If the indent is 0 and it contains '(c)' then it is a Copyright line
297+ if '(c)' in line:
298+ copyright = line
299+ continue
300+ elif (line.startswith('Liturgical ') or line.startswith('From The ') or
301+ line.startswith('From Common ') or line.startswith('Based on Psalm ')):
302+ self.add_comment(line)
303+ continue
304+ # If indent is 0 it may be the author, unless it was one of the cases covered above
305+ elif len(line) > 0:
306+ # May have more than one author, separated by ' and '
307+ authors = line.split(' and ')
308+ for a in authors:
309+ self.parse_author(a)
310+ continue
311+ # If a blank line has bee replaced by *Blank* then put it back to being
312+ # a simple space since this is past stripping blanks
313+ if '*Blank*' in line:
314+ line = ' '
315+ if line == '':
316+ if current_verse != '':
317+ self.add_verse(current_verse, current_verse_type)
318+ self.verse_order_list.append(current_verse_type + str(current_verse_number))
319+ if current_verse_type == 'c':
320+ chorus_written = True
321+ else:
322+ current_verse_number += 1
323+ current_verse = ''
324+ if chorus_written:
325+ current_verse_type = 'v'
326+ else:
327+ # If the line is indented more than or equal chorus_indent then assume it is a chorus
328+ # If the indent has just changed then start a new verse just like hitting a blank line
329+ if not self.hint_ignore_indent and ((indent >= chorus_indent) and (old_indent < indent)):
330+ if current_verse != '':
331+ self.add_verse(current_verse, current_verse_type)
332+ self.verse_order_list.append(current_verse_type + str(current_verse_number))
333+ if current_verse_type == 'v':
334+ current_verse_number += 1
335+ current_verse = line
336+ current_verse_type = 'c'
337+ old_indent = indent
338+ chorus_written = False
339+ has_chorus = True
340+ continue
341+ if current_verse == '':
342+ current_verse += line
343+ else:
344+ current_verse += '\n' + line
345+ old_indent = indent
346+ except Exception as e:
347+ self.log_error(translate('SongsPlugin.SingingTheFaithImport', 'File {file}').format(file=file.name),
348+ translate('SongsPlugin.SingingTheFaithImport', 'Error: {error}').format(error=e))
349+ return
350+
351+ if self.hint_song_title:
352+ song_title = self.hint_song_title
353+ self.title = '{}STF{} - {title}'.format(check_flag, song_number.zfill(3), title=song_title)
354+ self.song_book_name = 'Singing The Faith'
355+ self.song_number = song_number
356+ self.ccli_number = ccli
357+ self.add_copyright(copyright)
358+ # If we have a chorus then the generated Verse order can not be used directly, but we can generate
359+ # one for two special cases - Verse followed by one chorus (to be repeated after every verse)
360+ # of Chorus, followed by verses. If hints for ManualCheck or VerseOrder are supplied ignore this
361+ if has_chorus and not self.hint_verse_order and not self.checks_needed:
362+ auto_verse_order_ok = False
363+ # Popular case V1 C2 V2 ...
364+ if self.verse_order_list: # protect against odd cases
365+ if self.verse_order_list[0] == 'v1' and self.verse_order_list[1] == 'c2':
366+ new_verse_order_list = ['v1', 'c1']
367+ i = 2
368+ auto_verse_order_ok = True
369+ elif self.verse_order_list[0] == 'c1' and self.verse_order_list[1] == 'v1':
370+ new_verse_order_list = ['c1', 'v1', 'c1']
371+ i = 2
372+ auto_verse_order_ok = True
373+ # if we are in a case we can deal with
374+ if auto_verse_order_ok:
375+ while i < len(self.verse_order_list):
376+ if self.verse_order_list[i].startswith('v'):
377+ new_verse_order_list.append(self.verse_order_list[i])
378+ new_verse_order_list.append('c1')
379+ else:
380+ auto_verse_order_ok = False
381+ self.add_comment('Importer detected unexpected verse order entry {}'.format(
382+ self.verse_order_list[i]))
383+ i += 1
384+ self.verse_order_list = new_verse_order_list
385+ else:
386+ if not auto_verse_order_ok:
387+ self.verse_order_list = []
388+ if self.hint_verse_order:
389+ self.verse_order_list = self.hint_verse_order.split(',')
390+ if self.hint_comments:
391+ self.add_comment(self.hint_comments)
392+ if self.hint_ccli:
393+ self.ccli_number = self.hint_ccli
394+ # Write the title last as by now we will know if we need checks
395+ if hints_available and not self.checks_needed:
396+ check_flag = ''
397+ elif not hints_available and not has_chorus:
398+ check_flag = ''
399+ elif not hints_available and has_chorus and auto_verse_order_ok:
400+ check_flag = ''
401+ if self.hint_songbook_number_in_title:
402+ self.title = '{}STF{} - {title}'.format(check_flag, song_number.zfill(3), title=song_title)
403+ else:
404+ self.title = '{}{title}'.format(check_flag, title=song_title)
405+ if not self.finish():
406+ self.log_error(file.name)
407+
408+ def read_hints(self, file, song_number):
409+ """
410+ Read the hints used to transform a particular song into version which can be projected,
411+ or improve the transformation process beyond the standard heuristics. Not every song will
412+ have, or need, hints.
413+ """
414+ hintfound = False
415+ self.hint_verse_order = ''
416+ self.hint_line.clear()
417+ self.hint_comments = ''
418+ self.hint_song_title = ''
419+ self.hint_ignore_indent = False
420+ self.hint_ccli = ''
421+ for tl in file:
422+ if not tl.strip():
423+ return hintfound
424+ tagval = tl.split(':')
425+ tag = tagval[0].strip()
426+ val = tagval[1].strip()
427+ if tag == 'Version':
428+ self.hint_file_version = val
429+ continue
430+ elif tag == 'SongbookNumberInTitle':
431+ if val == 'False':
432+ self.hint_songbook_number_in_title = False
433+ else:
434+ self.hint_songbook_number_in_title = True
435+ continue
436+ elif tag == 'Comment':
437+ continue
438+ if (tag == 'Hymn') and (val == song_number):
439+ self.add_comment('Using hints version {}'.format(str(self.hint_file_version)))
440+ hintfound = True
441+ # Assume, unless the hints has ManualCheck that if hinted all will be OK
442+ self.checks_needed = False
443+ for tl in file:
444+ tagval = tl.split(':')
445+ tag = tagval[0].strip()
446+ val = tagval[1].strip()
447+ if tag == 'End':
448+ return hintfound
449+ elif tag == 'CommentsLine':
450+ vals = val.split(',')
451+ for v in vals:
452+ self.hint_line[v] = 'Comment'
453+ elif tag == 'IgnoreLine':
454+ vals = val.split(',')
455+ for v in vals:
456+ self.hint_line[v] = 'Ignore'
457+ elif tag == 'AuthorLine':
458+ vals = val.split(',')
459+ for v in vals:
460+ self.hint_line[v] = 'Author'
461+ elif tag == 'AddSpaceAfterSemi':
462+ vals = val.split(',')
463+ for v in vals:
464+ self.hint_line[v] = 'AddSpaceAfterSemi'
465+ elif tag == 'AddSpaceAfterColon':
466+ vals = val.split(',')
467+ for v in vals:
468+ self.hint_line[v] = 'AddSpaceAfterColon'
469+ elif tag == 'BlankLine':
470+ vals = val.split(',')
471+ for v in vals:
472+ self.hint_line[v] = 'BlankLine'
473+ elif tag == 'BoldLine':
474+ vals = val.split(',')
475+ for v in vals:
476+ self.hint_line[v] = 'BoldLine'
477+ elif tag == 'VerseOrder':
478+ self.hint_verse_order = val
479+ elif tag == 'ManualCheck':
480+ self.checks_needed = True
481+ elif tag == 'IgnoreIndent':
482+ self.hint_ignore_indent = True
483+ elif tag == 'VariantVerse':
484+ vvline = val.split(' ', 1)
485+ self.hint_line[vvline[0].strip()] = 'VariantVerse {}'.format(vvline[1].strip())
486+ elif tag == 'SongTitle':
487+ self.hint_song_title = val
488+ elif tag == 'AddComment':
489+ self.hint_comments += '\n' + val
490+ elif tag == 'CCLI':
491+ self.hint_ccli = val
492+ elif tag == 'Hymn':
493+ self.log_error(file.name, 'Missing End tag in hint for Hymn: {}'.format(song_number))
494+ else:
495+ self.log_error(file.name, 'Unknown tag {} value {}'.format(tag, val))
496+ return hintfound
497
498=== added file 'resources/hints.tag'
499--- resources/hints.tag 1970-01-01 00:00:00 +0000
500+++ resources/hints.tag 2019-08-29 21:51:57 +0000
501@@ -0,0 +1,666 @@
502+Tag-STFHints-version: 1.0
503+Version: 2
504+SongbookNumberInTitle: True
505+End:
506+Hymn: 2
507+VerseOrder: V1,C1,V2,C1,V3,C1
508+End:
509+Hymn: 8
510+AddSpaceAfterColon: 2,11,20,33
511+End:
512+Hymn: 10
513+CommentsLine: 17
514+End:
515+Hymn: 11
516+CommentsLine: 24
517+End:
518+Hymn: 15
519+VerseOrder: V1,C1,V2,C1,C2,C1
520+End:
521+Hymn: 18
522+CommentsLine: 16
523+End:
524+Hymn: 19
525+CommentsLine: 8
526+End:
527+Hymn: 22
528+CommentsLine: 20
529+End:
530+Hymn: 24
531+IgnoreLine: 13
532+VerseOrder: V1,V2,V1
533+End:
534+Hymn: 26
535+VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C1
536+End:
537+Hymn: 27
538+AddComment: Verse 1 is original Shona
539+SongTitle: Jesu, tawa pano
540+IgnoreLine: 2
541+CommentsLine: 31
542+End:
543+Hymn: 28
544+CommentsLine: 41
545+End:
546+Hymn: 29
547+CommentsLine: 18
548+End:
549+Hymn: 30
550+CommentsLine: 26
551+End:
552+Hymn: 35
553+VerseOrder: V1,C1,V2,C1,V3,C1
554+End:
555+Hymn: 37
556+IgnoreLine: 42
557+VerseOrder: V1,V2,C1,V3,V4,C1
558+End:
559+Hymn: 38
560+ManualCheck: Yes
561+AddComment: Make all and cantor words Bold tagged for readability
562+SongTitle: Wa wa wa Emimimo
563+End:
564+Hymn: 40
565+VariantVerse: 15 1 Blessed be the name of the Lord/Glory to the name of the Lord|blessed be the name/glory to the name
566+VariantVerse: 17 1 Blessed be the name of the Lord/Holy is the name of the Lord|blessed be the name/holy is the name
567+VerseOrder: V1,C1,V2,C1,V3,C1
568+End:
569+Hymn: 41
570+IgnoreIndent: Yes
571+IgnoreLine: 35,42
572+VerseOrder: V1,V2,V3,V4,V2,V3,V5,V3
573+End:
574+Hymn: 43
575+IgnoreIndent: Yes
576+CommentsLine: 40
577+End:
578+Hymn: 45
579+IgnoreIndent: Yes
580+CommentsLine: 104
581+End:
582+Hymn: 46
583+VerseOrder: V1,C1,V2,C1,C2,C1
584+End:
585+Hymn: 48
586+VerseOrder: V1,C1,V2,C2
587+End:
588+Hymn: 51
589+VerseOrder: V1,C1,V2,C1,V3,C1
590+End:
591+Hymn: 55
592+AddSpaceAfterSemi: 15
593+End:
594+Hymn: 60
595+CommentsLine: 22
596+End:
597+Hymn: 61
598+VerseOrder: C1,V1,C1
599+End:
600+Hymn: 64
601+IgnoreLine: 23,25
602+VerseOrder: V1,C1,C2,V2,C1,C2,C3
603+End:
604+Hymn: 65
605+VerseOrder: V1,C1,V2,C2,V3,C1,V4,C1
606+End:
607+Hymn: 68
608+IgnoreLine: 15,31
609+VerseOrder: C1,V1,C1,V2,C2,C1
610+End:
611+Hymn: 71
612+IgnoreLine: 23
613+VerseOrder: V1,C1,V2,C1,V3
614+End:
615+Hymn: 74
616+IgnoreIndent: Yes
617+End:
618+Hymn: 77
619+IgnoreLine: 32
620+CommentsLine: 37
621+VerseOrder: V1,V2,C1,V3,C1
622+End:
623+Hymn: 78
624+VerseOrder: V1,V2,V1,V2,V3
625+End:
626+Hymn: 82
627+VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1
628+End:
629+Hymn: 84
630+IgnoreIndent: Yes
631+End:
632+Hymn: 86
633+CommentsLine: 86
634+End:
635+Hymn: 89
636+VerseOrder: V1,V2,C1
637+End:
638+Hymn: 92
639+IgnoreIndent: Yes
640+IgnoreLine: 2,18,48
641+SongTitle: Think of a world without any flowers
642+End:
643+Hymn: 93
644+AddSpaceAfterSemi: 9,10,11,12
645+IgnoreLine: 21,30,31,32,33
646+VerseOrder: V1,C1,V2,C1,V3,C1
647+End:
648+Hymn: 94
649+AuthorLine: 24
650+VerseOrder: V1,C1,V2,C1,V3,C1
651+End:
652+Hymn: 95
653+AddSpaceAfterSemi: 2
654+End:
655+Hymn: 98
656+IgnoreLine: 17,19,24
657+VerseOrder: V1,C1,V2,C1,C2,C1
658+AddComment: C2 is an optional Bridge
659+End:
660+Hymn: 100
661+VerseOrder: C1,V1,C1,V2,C1,V3,C1,V4,C1
662+End:
663+Hymn: 102
664+VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C1
665+End:
666+Hymn: 103
667+AddSpaceAfterColon: 2,3,11,20
668+End:
669+Hymn: 105
670+VerseOrder: C1,V1,C1,V2,C1
671+End:
672+Hymn: 118
673+IgnoreLine: 15,21
674+CommentsLine: 28
675+VerseOrder: V1,C1,C1,V2,C1,V3,C1,C1,C2
676+End:
677+Hymn: 123
678+CommentsLine: 40
679+End:
680+Hymn: 140
681+IgnoreLine: 14
682+VerseOrder: V1,C1,V2,C1
683+End:
684+Hymn: 141
685+AddSpaceAfterSemi: 2
686+End:
687+Hymn: 145
688+ManualCheck: Yes
689+AddComment: Make cantor and all bold, and add to all verses
690+SongTitle: Night has fallen
691+End:
692+Hymn: 147
693+AddSpaceAfterSemi: 22
694+End:
695+Hymn: 165
696+IgnoreLine: 2,11,20,29,38
697+CommentsLine: 50
698+SongTitle: Advent candles tell their story
699+End:
700+Hymn: 166
701+CommentsLine: 40
702+VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C2
703+End:
704+Hymn: 168
705+CommentsLine: 30
706+End:
707+Hymn: 170
708+VerseOrder: V1,C1,V2,C1,V3,C1,V4,C2
709+End:
710+Hymn: 173
711+VerseOrder: V1,C1,V2,C1,V3,C2
712+End:
713+Hymn: 174
714+CommentsLine: 41
715+End:
716+Hymn: 175
717+IgnoreLine: 22,29
718+VerseOrder: V1,C1,V2,C1,C2,C1
719+End:
720+Hymn: 176
721+CommentsLine: 26
722+ManualCheck: Yes
723+End:
724+Hymn: 178
725+VerseOrder: V1,C1,V2,C1,V3,C1,V4,C2
726+End:
727+Hymn: 186
728+IgnoreIndent: Yes
729+CommentsLine: 24
730+End:
731+Hymn: 194
732+IgnoreIndent: Yes
733+End:
734+Hymn: 200
735+AddSpaceAfterColon: 2
736+CommentsLine: 24
737+End:
738+Hymn: 209
739+IgnoreLine: 11,17,23
740+VerseOrder: V1,C1,C1,V2,C1,V3,C1
741+End:
742+Hymn: 212
743+CommentsLine: 46
744+End:
745+Hymn: 220
746+AddSpaceAfterColon: 30
747+End:
748+Hymn: 227
749+VerseOrder: V1,V2,V3,V4,V1
750+End:
751+Hymn: 228
752+CommentsLine: 49
753+End:
754+Hymn: 234
755+CommentsLine: 7
756+End:
757+Hymn: 235
758+IgnoreIndent: Yes
759+End:
760+Hymn: 240
761+CommentsLine: 24
762+End:
763+Hymn: 241
764+IgnoreLine: 39
765+VerseOrder: V1,C1,V2,C2,C3,C2
766+AddComment: is the final chorus a repeat of C1 or C2 ?
767+ManualCheck: Yes
768+End:
769+Hymn: 246
770+VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1
771+End:
772+Hymn: 247
773+VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C1
774+End:
775+Hymn: 248
776+AddSpaceAfterSemi: 13
777+End:
778+Hymn: 249
779+VerseOrder: C1,V1,C1,V2,C1,V3,C1,V4,C1
780+End:
781+Hymn: 252
782+AddSpaceAfterColon: 1,6,9,13,16,20,23,27,30,34
783+End:
784+Hymn: 254
785+CommentsLine: 22
786+End:
787+Hymn: 256
788+VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C1,V6,C2
789+End:
790+Hymn: 258
791+IgnoreLine: 14
792+VerseOrder: C1,V1,C1
793+End:
794+Hymn: 261
795+AddSpaceAfterSemi: 4
796+End:
797+Hymn: 267
798+CommentsLine: 33
799+End:
800+Hymn: 274
801+IgnoreLine: 21,30
802+VerseOrder: V1,C1,V2,C1,C2,C1
803+End:
804+Hymn: 279
805+IgnoreLine: 35
806+VerseOrder: V1,V2,C1,V3,V4,C1
807+End:
808+Hymn: 285
809+CommentsLine: 25
810+End:
811+Hymn: 298
812+IgnoreIndent: Yes
813+AddSpaceAfterSemi: 8
814+End:
815+Hymn: 299
816+IgnoreLine: 26
817+CommentsLine: 32
818+VerseOrder: V1,C1,V2,V3,V4,C1,C2
819+End:
820+Hymn: 300
821+AddSpaceAfterSemi: 8,9,13,17,18
822+AddSpaceAfterColon: 7,15,20,25,30
823+End:
824+Hymn: 302
825+VerseOrder: C1,V1,C1,V2,C1,V3,C1,V4,C1,V5,C1
826+End:
827+Hymn: 316
828+VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C1,V6,C1,V7,C2
829+End:
830+Hymn: 321
831+CommentsLine: 15
832+End:
833+Hymn: 323
834+AddSpaceAfterSemi: 11
835+End:
836+Hymn: 331
837+VerseOrder: V1,C1,V2,C2
838+End:
839+Hymn: 335
840+VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C2
841+End:
842+Hymn: 343
843+IgnoreLine: 24
844+VerseOrder: V1,V2,C1,V3,C1
845+End:
846+Hymn: 349
847+AddSpaceAfterSemi: 20,24
848+IgnoreLine: 17
849+AddComment: The refrain is optional
850+VerseOrder: V1,V2,V3,C1,V4,V3
851+End:
852+Hymn: 351
853+CCLI: 3350395
854+End:
855+Hymn: 353
856+AddSpaceAfterSemi: 15
857+End:
858+Hymn: 364
859+AddSpaceAfterSemi: 22
860+End:
861+Hymn: 367
862+IgnoreLine: 28
863+VerseOrder: V1,C1,V2,C1
864+End:
865+Hymn: 373
866+CommentsLine: 26
867+End:
868+Hymn: 374
869+ManualCheck: Yes
870+CommentsLine: 24
871+End:
872+Hymn: 377
873+VerseOrder: V1,C1,V2,C1,V3,C1
874+End:
875+Hymn: 380
876+VerseOrder: V1,C1,V2,C1
877+End:
878+Hymn: 386
879+BlankLine: 6,16
880+IgnoreLine: 19,26
881+VerseOrder: V1,C1,V2,C1,C2,C1
882+End:
883+Hymn: 389
884+AuthorLine: 21
885+End:
886+Hymn: 401
887+AddSpaceAfterSemi: 27
888+End:
889+Hymn: 403
890+AddSpaceAfterColon: 2
891+End:
892+Hymn: 404
893+SongTitle: Go tell everyone
894+VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1
895+End:
896+Hymn: 405
897+VerseOrder: V1,C1,V2,C1,V3,C1
898+End:
899+Hymn: 406
900+IgnoreLine: 18,27
901+End:
902+Hymn: 407
903+IgnoreLine: 31
904+VerseOrder: V1,V2,C1,V3,C1
905+End:
906+Hymn: 408
907+IgnoreIndent: Yes
908+CommentsLine: 25
909+End:
910+Hymn: 410
911+AddSpaceAfterSemi: 15,16
912+End:
913+Hymn: 419
914+CommentsLine: 25
915+End:
916+Hymn: 420
917+IgnoreIndent: Yes
918+End:
919+Hymn: 421
920+IgnoreIndent: Yes
921+CommentsLine: 55
922+End:
923+Hymn: 424
924+IgnoreLine: 16
925+VerseOrder: V1,C1,V2,C1
926+End:
927+Hymn: 428
928+IgnoreLine: 25
929+VerseOrder: V1,V2,C1,V3,C1
930+End:
931+Hymn: 432
932+AddSpaceAfterSemi: 8
933+End:
934+Hymn: 433
935+CommentsLine: 44
936+End:
937+Hymn: 447
938+IgnoreLine: 19,21
939+VerseOrder: V1,V2,C1,V3,C1,V1
940+End:
941+Hymn: 451
942+IgnoreLine: 14,16
943+VerseOrder: C1,V1,C1,V1,V2
944+End:
945+Hymn: 454
946+CommentsLine: 2,42
947+SongTitle: Where shall my wondering soul begin
948+End:
949+Hymn: 458
950+CommentsLine: 2
951+SongTitle: Away with our fears The glad morning appears
952+End:
953+Hymn: 469
954+ManualCheck: Yes
955+AddComment: Need a VariantChorus, Chorus2 and Chorus3 are Variants of Chorus1
956+VerseOrder: V1,C1,V2,C2,V3,C2,V4,C3
957+End:
958+Hymn: 470
959+IgnoreIndent: Yes
960+End:
961+Hymn: 476
962+VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C1
963+End:
964+Hymn: 477
965+VerseOrder: C1,V1,C1,V2,C1
966+End:
967+Hymn: 480
968+CommentsLine: 28
969+End:
970+Hymn: 483
971+AddComment: Verses 4 and 5 are the
972+CommentsLine: 29
973+End:
974+Hymn: 488
975+IgnoreLine: 25
976+VerseOrder: V1,V2,C1,V3,C1
977+End:
978+Hymn: 492
979+AddSpaceAfterSemi: 9,10,15
980+End:
981+Hymn: 499
982+CommentsLine: 37
983+End:
984+Hymn: 509
985+IgnoreIndent: Yes
986+CommentsLine: 40
987+End:
988+Hymn: 517
989+VerseOrder: V1,C1,V2,C1,V3,C1,V4,C2
990+End:
991+Hymn: 528
992+CommentsLine: 32
993+End:
994+Hymn: 541
995+IgnoreLine: 17,18,25
996+VerseOrder: V1,V2,C1,V1,V2,V3,C1
997+End:
998+Hymn: 545
999+CommentsLine: 28
1000+End:
1001+Hymn: 548
1002+AuthorLine: 22
1003+End:
1004+Hymn: 554
1005+IgnoreLine: 15,21
1006+VerseOrder: V1,C1,V2,C1,V3,C1,V4
1007+End:
1008+Hymn: 555
1009+IgnoreLine: 15
1010+VerseOrder: V1,V2,C1,V1
1011+End:
1012+Hymn: 559
1013+IgnoreIndent: Yes
1014+End:
1015+Hymn: 561
1016+CommentsLine: 45
1017+End:
1018+Hymn: 562
1019+CommentsLine: 38
1020+End:
1021+Hymn: 565
1022+IgnoreLine: 21
1023+VerseOrder: V1,V2,V1
1024+End:
1025+Hymn: 566
1026+AddSpaceAfterSemi: 27
1027+End:
1028+Hymn: 567
1029+ManualCheck: Yes
1030+AddComment: Check with musician what should be on the screen
1031+End:
1032+Hymn: 570
1033+VerseOrder: V1,C1,V2,C1,V3,C1
1034+End:
1035+Hymn: 575
1036+CommentsLine: 30
1037+End:
1038+Hymn: 578
1039+IgnoreLine: 11,18,25
1040+VerseOrder: C1,V1,C1,V2,C1,V3,C1
1041+End:
1042+Hymn: 586
1043+IgnoreLine: 22
1044+VerseOrder: V1,V2,C1,V3,C1
1045+End:
1046+Hymn: 587
1047+VerseOrder: V1,C1,V2,C2,V3
1048+End:
1049+Hymn: 582
1050+CommentsLine: 25
1051+End:
1052+Hymn: 594
1053+CommentsLine: 41
1054+End:
1055+Hymn: 601
1056+CommentsLine: 16
1057+End:
1058+Hymn: 603
1059+ManualCheck: Yes
1060+AddComment: Update Verse 4 for names of the couple
1061+CommentsLine: 22
1062+IgnoreIndent: Yes
1063+End:
1064+Hymn: 609
1065+CommentsLine: 37
1066+End:
1067+Hymn: 610
1068+CommentsLine: 29
1069+End:
1070+Hymn: 626
1071+IgnoreLine: 29,31,44
1072+VerseOrder: V1,C1,C2,V2,C1,C2,C3,C2
1073+End:
1074+Hymn: 631
1075+CommentsLine: 15
1076+End:
1077+Hymn: 627
1078+IgnoreLine: 25,36
1079+VerseOrder: V1,C1,V2,C1,C2,C1
1080+End:
1081+Hymn: 632
1082+IgnoreLine: 17,24
1083+VerseOrder: V1,C1,V2,C1,C2,C1
1084+End:
1085+Hymn: 635
1086+IgnoreLine: 23,25
1087+VerseOrder: V1,C1,C2,V2,C1,C2
1088+End:
1089+Hymn: 637
1090+CommentsLine: 41
1091+End:
1092+Hymn: 638
1093+CommentsLine: 34
1094+End:
1095+Hymn: 640
1096+CommentsLine: 19,20
1097+End:
1098+Hymn: 654
1099+IgnoreIndent: Yes
1100+End:
1101+Hymn: 657
1102+IgnoreLine: 20,21,23
1103+VerseOrder: V1,C1,C2,V2,C1,C2,C3
1104+End:
1105+Hymn: 662
1106+AddSpaceAfterSemi: 2,12
1107+End:
1108+Hymn: 670
1109+IgnoreLine: 27
1110+VerseOrder: V1,C1,V2,C1
1111+End:
1112+Hymn: 677
1113+CommentsLine: 31
1114+End:
1115+Hymn: 681
1116+IgnoreIndent: Yes
1117+End:
1118+Hymn: 684
1119+IgnoreIndent: Yes
1120+End:
1121+Hymn: 693
1122+IgnoreLine: 46,57
1123+VerseOrder: V1,V2,C1,V3,V4,C1,V5,C1
1124+End:
1125+Hymn: 697
1126+IgnoreIndent: Yes
1127+CommentsLine: 21
1128+End:
1129+Hymn: 699
1130+IgnoreLine: 23,32
1131+VerseOrder: V1,C1,V2,C1,C1,C2,C1
1132+End:
1133+Hymn: 700
1134+IgnoreIndent: Yes
1135+End:
1136+Hymn: 707
1137+IgnoreLine: 15
1138+VerseOrder: V1,C1,V2,C1,V3
1139+End:
1140+Hymn: 729
1141+IgnoreIndent: Yes
1142+End:
1143+Hymn: 741
1144+CommentsLine: 25
1145+End:
1146+Hymn: 753
1147+CommentsLine: 14
1148+IgnoreIndent: Yes
1149+End:
1150+Hymn: 754
1151+IgnoreIndent: Yes
1152+End:
1153+Hymn: 764
1154+IgnoreIndent: Yes
1155+CommentsLine: 31
1156+End:
1157+Hymn: 783
1158+BlankLine: 5
1159+End:
1160+Hymn: 819
1161+AddSpaceAfterSemi: 32
1162+End:
1163+Hymn: 820
1164+CommentsLine: 2
1165+BoldLine: 6,7,12,13,17,18,23,24,29,30,32,33,34,35
1166+SongTitle: Psalm 98 - O sing to the Lord a new song
1167+End:
1168
1169=== added file 'tests/functional/openlp_plugins/songs/test_singingthefaithimport.py'
1170--- tests/functional/openlp_plugins/songs/test_singingthefaithimport.py 1970-01-01 00:00:00 +0000
1171+++ tests/functional/openlp_plugins/songs/test_singingthefaithimport.py 2019-08-29 21:51:57 +0000
1172@@ -0,0 +1,48 @@
1173+# -*- coding: utf-8 -*-
1174+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
1175+
1176+##########################################################################
1177+# OpenLP - Open Source Lyrics Projection #
1178+# ---------------------------------------------------------------------- #
1179+# Copyright (c) 2008-2019 OpenLP Developers #
1180+# ---------------------------------------------------------------------- #
1181+# This program is free software: you can redistribute it and/or modify #
1182+# it under the terms of the GNU General Public License as published by #
1183+# the Free Software Foundation, either version 3 of the License, or #
1184+# (at your option) any later version. #
1185+# #
1186+# This program is distributed in the hope that it will be useful, #
1187+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
1188+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
1189+# GNU General Public License for more details. #
1190+# #
1191+# You should have received a copy of the GNU General Public License #
1192+# along with this program. If not, see <https://www.gnu.org/licenses/>. #
1193+##########################################################################
1194+"""
1195+This module contains tests for the SingingTheFaith song importer.
1196+"""
1197+from tests.helpers.songfileimport import SongImportTestHelper
1198+from tests.utils.constants import RESOURCE_PATH
1199+
1200+
1201+TEST_PATH = RESOURCE_PATH / 'songs' / 'singingthefaith'
1202+
1203+
1204+class TestSingingTheFaithFileImport(SongImportTestHelper):
1205+
1206+ def __init__(self, *args, **kwargs):
1207+ self.importer_class_name = 'SingingTheFaithImport'
1208+ self.importer_module_name = 'singingthefaith'
1209+ super(TestSingingTheFaithFileImport, self).__init__(*args, **kwargs)
1210+
1211+ def test_song_import(self):
1212+ """
1213+ Test that loading a Singing The Faith file works correctly on various files
1214+ """
1215+ # Single verse
1216+ self.file_import([TEST_PATH / 'H1.txt'],
1217+ self.load_external_result_data(TEST_PATH / 'STF001.json'))
1218+ # Whole song
1219+ self.file_import([TEST_PATH / 'H2.txt'],
1220+ self.load_external_result_data(TEST_PATH / 'STF002.json'))
1221
1222=== modified file 'tests/helpers/songfileimport.py'
1223--- tests/helpers/songfileimport.py 2019-05-22 06:47:00 +0000
1224+++ tests/helpers/songfileimport.py 2019-08-29 21:51:57 +0000
1225@@ -123,7 +123,8 @@
1226 log.debug("Song copyright imported: %s" % importer.song_number)
1227 log.debug("Topics imported: %s" % importer.topics)
1228
1229- assert importer.title == title, 'title for %s should be "%s"' % (source_file_name, title)
1230+ assert importer.title == title, \
1231+ 'title for %s should be "%s" and is "%s"' % (source_file_name, title, importer.title)
1232 for author in author_calls:
1233 if isinstance(author, str):
1234 self.mocked_add_author.assert_any_call(author)
1235
1236=== added directory 'tests/resources/songs/singingthefaith'
1237=== added file 'tests/resources/songs/singingthefaith/H1.txt'
1238--- tests/resources/songs/singingthefaith/H1.txt 1970-01-01 00:00:00 +0000
1239+++ tests/resources/songs/singingthefaith/H1.txt 2019-08-29 21:51:57 +0000
1240@@ -0,0 +1,9 @@
1241+
1242+1 Amazing Grace! how sweet the sound!
1243+ That saved a wretch like me!
1244+ I once was lost, but now am found;
1245+ Was blind, but now I see.
1246+
1247+John Newton (d. 1807)
1248+
1249+Reproduced from Singing the Faith Electronic Words Edition, number 1 - or not as this is a hand made test file
1250
1251=== added file 'tests/resources/songs/singingthefaith/H2.txt'
1252--- tests/resources/songs/singingthefaith/H2.txt 1970-01-01 00:00:00 +0000
1253+++ tests/resources/songs/singingthefaith/H2.txt 2019-08-29 21:51:57 +0000
1254@@ -0,0 +1,30 @@
1255+
1256+1 Amazing Grace! how sweet the sound!
1257+ That saved a wretch like me!
1258+ I once was lost, but now am found;
1259+ Was blind, but now I see.
1260+
1261+2 'Twas grace that taught my heart to fear,
1262+ And grace my fears relieved.
1263+ How precious did that grace appear,
1264+ The hour I first believed.
1265+
1266+3 The Lord has promised good to me,
1267+ His Word my hope secures.
1268+ He will my shield and portion be
1269+ As long as life endures.
1270+
1271+4 Thro' many dangers, toils and snares
1272+ I have already come.
1273+ 'Tis grace that brought me safe thus far,
1274+ And grace will lead me home.
1275+
1276+5 When we've been there ten thousand years,
1277+ Bright shining as the sun,
1278+ We've no less days to sing God's praise,
1279+ Than when we first begun.
1280+
1281+
1282+John Newton (d. 1807)
1283+
1284+Reproduced from Singing the Faith Electronic Words Edition, number 2 - or not as this is a hand made test file
1285
1286=== added file 'tests/resources/songs/singingthefaith/STF001.json'
1287--- tests/resources/songs/singingthefaith/STF001.json 1970-01-01 00:00:00 +0000
1288+++ tests/resources/songs/singingthefaith/STF001.json 2019-08-29 21:51:57 +0000
1289@@ -0,0 +1,13 @@
1290+{
1291+ "title": "STF001 - Amazing Grace! how sweet the sound!",
1292+ "authors": [
1293+ "John Newton (d. 1807)"
1294+ ],
1295+ "verse_order_list": ["v1"],
1296+ "verses": [
1297+ [
1298+ "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.",
1299+ "v"
1300+ ]
1301+ ]
1302+}
1303
1304=== added file 'tests/resources/songs/singingthefaith/STF002.json'
1305--- tests/resources/songs/singingthefaith/STF002.json 1970-01-01 00:00:00 +0000
1306+++ tests/resources/songs/singingthefaith/STF002.json 2019-08-29 21:51:57 +0000
1307@@ -0,0 +1,29 @@
1308+{
1309+ "title": "STF002 - Amazing Grace! how sweet the sound!",
1310+ "authors": [
1311+ "John Newton (d. 1807)"
1312+ ],
1313+ "verse_order_list": ["v1", "v2", "v3", "v4", "v5"],
1314+ "verses": [
1315+ [
1316+ "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.",
1317+ "v"
1318+ ],
1319+ [
1320+ "'Twas grace that taught my heart to fear,\nAnd grace my fears relieved.\nHow precious did that grace appear,\nThe hour I first believed.",
1321+ "v"
1322+ ],
1323+ [
1324+ "The Lord has promised good to me,\nHis Word my hope secures.\nHe will my shield and portion be\nAs long as life endures.",
1325+ "v"
1326+ ],
1327+ [
1328+ "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.",
1329+ "v"
1330+ ],
1331+ [
1332+ "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.",
1333+ "v"
1334+ ]
1335+ ]
1336+}