Add Importer SingingTheFaith

bzr-revno: 2901
This commit is contained in:
john+ubuntu@paladyn.org 2019-09-14 08:26:59 +01:00 committed by Tim Bentley
commit a77bb78e6e
14 changed files with 1360 additions and 12 deletions

View File

@ -42,6 +42,7 @@ from .importers.powerpraise import PowerPraiseImport
from .importers.powersong import PowerSongImport
from .importers.presentationmanager import PresentationManagerImport
from .importers.propresenter import ProPresenterImport
from .importers.singingthefaith import SingingTheFaithImport
from .importers.songbeamer import SongBeamerImport
from .importers.songpro import SongProImport
from .importers.songshowplus import SongShowPlusImport
@ -173,16 +174,17 @@ class SongFormat(object):
PowerSong = 16
PresentationManager = 17
ProPresenter = 18
SongBeamer = 19
SongPro = 20
SongShowPlus = 21
SongsOfFellowship = 22
SundayPlus = 23
VideoPsalm = 24
WordsOfWorship = 25
WorshipAssistant = 26
WorshipCenterPro = 27
ZionWorx = 28
SingingTheFaith = 19
SongBeamer = 20
SongPro = 21
SongShowPlus = 22
SongsOfFellowship = 23
SundayPlus = 24
VideoPsalm = 25
WordsOfWorship = 26
WorshipAssistant = 27
WorshipCenterPro = 28
ZionWorx = 29
# Set optional attribute defaults
__defaults__ = {
@ -343,6 +345,16 @@ class SongFormat(object):
'filter': '{text} (*.pro4 *.pro5 *.pro6)'.format(text=translate('SongsPlugin.ImportWizardForm',
'ProPresenter Song Files'))
},
SingingTheFaith: {
'class': SingingTheFaithImport,
'name': 'SingingTheFaith',
'prefix': 'singingTheFaith',
'filter': '{text} (*.txt)'.format(text=translate('SongsPlugin.ImportWizardForm',
'Singing The Faith Exported Files')),
'descriptionText': translate('SongsPlugin.ImportWizardForm',
'First use Singing The Faith Electonic edition to export '
'the song(s) in Text format.')
},
SongBeamer: {
'class': SongBeamerImport,
'name': 'SongBeamer',
@ -462,6 +474,7 @@ class SongFormat(object):
SongFormat.PowerSong,
SongFormat.PresentationManager,
SongFormat.ProPresenter,
SongFormat.SingingTheFaith,
SongFormat.SongBeamer,
SongFormat.SongPro,
SongFormat.SongShowPlus,

View File

@ -0,0 +1,666 @@
Tag-STFHints-version: 1.0
Version: 2
SongbookNumberInTitle: False
End:
Hymn: 2
VerseOrder: V1,C1,V2,C1,V3,C1
End:
Hymn: 8
AddSpaceAfterColon: 2,11,20,33
End:
Hymn: 10
CommentsLine: 17
End:
Hymn: 11
CommentsLine: 24
End:
Hymn: 15
VerseOrder: V1,C1,V2,C1,C2,C1
End:
Hymn: 18
CommentsLine: 16
End:
Hymn: 19
CommentsLine: 8
End:
Hymn: 22
CommentsLine: 20
End:
Hymn: 24
IgnoreLine: 13
VerseOrder: V1,V2,V1
End:
Hymn: 26
VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C1
End:
Hymn: 27
AddComment: Verse 1 is original Shona
SongTitle: Jesu, tawa pano
IgnoreLine: 2
CommentsLine: 31
End:
Hymn: 28
CommentsLine: 41
End:
Hymn: 29
CommentsLine: 18
End:
Hymn: 30
CommentsLine: 26
End:
Hymn: 35
VerseOrder: V1,C1,V2,C1,V3,C1
End:
Hymn: 37
IgnoreLine: 42
VerseOrder: V1,V2,C1,V3,V4,C1
End:
Hymn: 38
ManualCheck: Yes
AddComment: Make all and cantor words Bold tagged for readability
SongTitle: Wa wa wa Emimimo
End:
Hymn: 40
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
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
VerseOrder: V1,C1,V2,C1,V3,C1
End:
Hymn: 41
IgnoreIndent: Yes
IgnoreLine: 35,42
VerseOrder: V1,V2,V3,V4,V2,V3,V5,V3
End:
Hymn: 43
IgnoreIndent: Yes
CommentsLine: 40
End:
Hymn: 45
IgnoreIndent: Yes
CommentsLine: 104
End:
Hymn: 46
VerseOrder: V1,C1,V2,C1,C2,C1
End:
Hymn: 48
VerseOrder: V1,C1,V2,C2
End:
Hymn: 51
VerseOrder: V1,C1,V2,C1,V3,C1
End:
Hymn: 55
AddSpaceAfterSemi: 15
End:
Hymn: 60
CommentsLine: 22
End:
Hymn: 61
VerseOrder: C1,V1,C1
End:
Hymn: 64
IgnoreLine: 23,25
VerseOrder: V1,C1,C2,V2,C1,C2,C3
End:
Hymn: 65
VerseOrder: V1,C1,V2,C2,V3,C1,V4,C1
End:
Hymn: 68
IgnoreLine: 15,31
VerseOrder: C1,V1,C1,V2,C2,C1
End:
Hymn: 71
IgnoreLine: 23
VerseOrder: V1,C1,V2,C1,V3
End:
Hymn: 74
IgnoreIndent: Yes
End:
Hymn: 77
IgnoreLine: 32
CommentsLine: 37
VerseOrder: V1,V2,C1,V3,C1
End:
Hymn: 78
VerseOrder: V1,V2,V1,V2,V3
End:
Hymn: 82
VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1
End:
Hymn: 84
IgnoreIndent: Yes
End:
Hymn: 86
CommentsLine: 86
End:
Hymn: 89
VerseOrder: V1,V2,C1
End:
Hymn: 92
IgnoreIndent: Yes
IgnoreLine: 2,18,48
SongTitle: Think of a world without any flowers
End:
Hymn: 93
AddSpaceAfterSemi: 9,10,11,12
IgnoreLine: 21,30,31,32,33
VerseOrder: V1,C1,V2,C1,V3,C1
End:
Hymn: 94
AuthorLine: 24
VerseOrder: V1,C1,V2,C1,V3,C1
End:
Hymn: 95
AddSpaceAfterSemi: 2
End:
Hymn: 98
IgnoreLine: 17,19,24
VerseOrder: V1,C1,V2,C1,C2,C1
AddComment: C2 is an optional Bridge
End:
Hymn: 100
VerseOrder: C1,V1,C1,V2,C1,V3,C1,V4,C1
End:
Hymn: 102
VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C1
End:
Hymn: 103
AddSpaceAfterColon: 2,3,11,20
End:
Hymn: 105
VerseOrder: C1,V1,C1,V2,C1
End:
Hymn: 118
IgnoreLine: 15,21
CommentsLine: 28
VerseOrder: V1,C1,C1,V2,C1,V3,C1,C1,C2
End:
Hymn: 123
CommentsLine: 40
End:
Hymn: 140
IgnoreLine: 14
VerseOrder: V1,C1,V2,C1
End:
Hymn: 141
AddSpaceAfterSemi: 2
End:
Hymn: 145
ManualCheck: Yes
AddComment: Make cantor and all bold, and add to all verses
SongTitle: Night has fallen
End:
Hymn: 147
AddSpaceAfterSemi: 22
End:
Hymn: 165
IgnoreLine: 2,11,20,29,38
CommentsLine: 50
SongTitle: Advent candles tell their story
End:
Hymn: 166
CommentsLine: 40
VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C2
End:
Hymn: 168
CommentsLine: 30
End:
Hymn: 170
VerseOrder: V1,C1,V2,C1,V3,C1,V4,C2
End:
Hymn: 173
VerseOrder: V1,C1,V2,C1,V3,C2
End:
Hymn: 174
CommentsLine: 41
End:
Hymn: 175
IgnoreLine: 22,29
VerseOrder: V1,C1,V2,C1,C2,C1
End:
Hymn: 176
CommentsLine: 26
ManualCheck: Yes
End:
Hymn: 178
VerseOrder: V1,C1,V2,C1,V3,C1,V4,C2
End:
Hymn: 186
IgnoreIndent: Yes
CommentsLine: 24
End:
Hymn: 194
IgnoreIndent: Yes
End:
Hymn: 200
AddSpaceAfterColon: 2
CommentsLine: 24
End:
Hymn: 209
IgnoreLine: 11,17,23
VerseOrder: V1,C1,C1,V2,C1,V3,C1
End:
Hymn: 212
CommentsLine: 46
End:
Hymn: 220
AddSpaceAfterColon: 30
End:
Hymn: 227
VerseOrder: V1,V2,V3,V4,V1
End:
Hymn: 228
CommentsLine: 49
End:
Hymn: 234
CommentsLine: 7
End:
Hymn: 235
IgnoreIndent: Yes
End:
Hymn: 240
CommentsLine: 24
End:
Hymn: 241
IgnoreLine: 39
VerseOrder: V1,C1,V2,C2,C3,C2
AddComment: is the final chorus a repeat of C1 or C2 ?
ManualCheck: Yes
End:
Hymn: 246
VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1
End:
Hymn: 247
VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C1
End:
Hymn: 248
AddSpaceAfterSemi: 13
End:
Hymn: 249
VerseOrder: C1,V1,C1,V2,C1,V3,C1,V4,C1
End:
Hymn: 252
AddSpaceAfterColon: 1,6,9,13,16,20,23,27,30,34
End:
Hymn: 254
CommentsLine: 22
End:
Hymn: 256
VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C1,V6,C2
End:
Hymn: 258
IgnoreLine: 14
VerseOrder: C1,V1,C1
End:
Hymn: 261
AddSpaceAfterSemi: 4
End:
Hymn: 267
CommentsLine: 33
End:
Hymn: 274
IgnoreLine: 21,30
VerseOrder: V1,C1,V2,C1,C2,C1
End:
Hymn: 279
IgnoreLine: 35
VerseOrder: V1,V2,C1,V3,V4,C1
End:
Hymn: 285
CommentsLine: 25
End:
Hymn: 298
IgnoreIndent: Yes
AddSpaceAfterSemi: 8
End:
Hymn: 299
IgnoreLine: 26
CommentsLine: 32
VerseOrder: V1,C1,V2,V3,V4,C1,C2
End:
Hymn: 300
AddSpaceAfterSemi: 8,9,13,17,18
AddSpaceAfterColon: 7,15,20,25,30
End:
Hymn: 302
VerseOrder: C1,V1,C1,V2,C1,V3,C1,V4,C1,V5,C1
End:
Hymn: 316
VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C1,V6,C1,V7,C2
End:
Hymn: 321
CommentsLine: 15
End:
Hymn: 323
AddSpaceAfterSemi: 11
End:
Hymn: 331
VerseOrder: V1,C1,V2,C2
End:
Hymn: 335
VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C2
End:
Hymn: 343
IgnoreLine: 24
VerseOrder: V1,V2,C1,V3,C1
End:
Hymn: 349
AddSpaceAfterSemi: 20,24
IgnoreLine: 17
AddComment: The refrain is optional
VerseOrder: V1,V2,V3,C1,V4,V3
End:
Hymn: 351
CCLI: 3350395
End:
Hymn: 353
AddSpaceAfterSemi: 15
End:
Hymn: 364
AddSpaceAfterSemi: 22
End:
Hymn: 367
IgnoreLine: 28
VerseOrder: V1,C1,V2,C1
End:
Hymn: 373
CommentsLine: 26
End:
Hymn: 374
ManualCheck: Yes
CommentsLine: 24
End:
Hymn: 377
VerseOrder: V1,C1,V2,C1,V3,C1
End:
Hymn: 380
VerseOrder: V1,C1,V2,C1
End:
Hymn: 386
BlankLine: 6,16
IgnoreLine: 19,26
VerseOrder: V1,C1,V2,C1,C2,C1
End:
Hymn: 389
AuthorLine: 21
End:
Hymn: 401
AddSpaceAfterSemi: 27
End:
Hymn: 403
AddSpaceAfterColon: 2
End:
Hymn: 404
SongTitle: Go tell everyone
VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1
End:
Hymn: 405
VerseOrder: V1,C1,V2,C1,V3,C1
End:
Hymn: 406
IgnoreLine: 18,27
End:
Hymn: 407
IgnoreLine: 31
VerseOrder: V1,V2,C1,V3,C1
End:
Hymn: 408
IgnoreIndent: Yes
CommentsLine: 25
End:
Hymn: 410
AddSpaceAfterSemi: 15,16
End:
Hymn: 419
CommentsLine: 25
End:
Hymn: 420
IgnoreIndent: Yes
End:
Hymn: 421
IgnoreIndent: Yes
CommentsLine: 55
End:
Hymn: 424
IgnoreLine: 16
VerseOrder: V1,C1,V2,C1
End:
Hymn: 428
IgnoreLine: 25
VerseOrder: V1,V2,C1,V3,C1
End:
Hymn: 432
AddSpaceAfterSemi: 8
End:
Hymn: 433
CommentsLine: 44
End:
Hymn: 447
IgnoreLine: 19,21
VerseOrder: V1,V2,C1,V3,C1,V1
End:
Hymn: 451
IgnoreLine: 14,16
VerseOrder: C1,V1,C1,V1,V2
End:
Hymn: 454
CommentsLine: 2,42
SongTitle: Where shall my wondering soul begin
End:
Hymn: 458
CommentsLine: 2
SongTitle: Away with our fears The glad morning appears
End:
Hymn: 469
ManualCheck: Yes
AddComment: Need a VariantChorus, Chorus2 and Chorus3 are Variants of Chorus1
VerseOrder: V1,C1,V2,C2,V3,C2,V4,C3
End:
Hymn: 470
IgnoreIndent: Yes
End:
Hymn: 476
VerseOrder: V1,C1,V2,C1,V3,C1,V4,C1,V5,C1
End:
Hymn: 477
VerseOrder: C1,V1,C1,V2,C1
End:
Hymn: 480
CommentsLine: 28
End:
Hymn: 483
AddComment: Verses 4 and 5 are the
CommentsLine: 29
End:
Hymn: 488
IgnoreLine: 25
VerseOrder: V1,V2,C1,V3,C1
End:
Hymn: 492
AddSpaceAfterSemi: 9,10,15
End:
Hymn: 499
CommentsLine: 37
End:
Hymn: 509
IgnoreIndent: Yes
CommentsLine: 40
End:
Hymn: 517
VerseOrder: V1,C1,V2,C1,V3,C1,V4,C2
End:
Hymn: 528
CommentsLine: 32
End:
Hymn: 541
IgnoreLine: 17,18,25
VerseOrder: V1,V2,C1,V1,V2,V3,C1
End:
Hymn: 545
CommentsLine: 28
End:
Hymn: 548
AuthorLine: 22
End:
Hymn: 554
IgnoreLine: 15,21
VerseOrder: V1,C1,V2,C1,V3,C1,V4
End:
Hymn: 555
IgnoreLine: 15
VerseOrder: V1,V2,C1,V1
End:
Hymn: 559
IgnoreIndent: Yes
End:
Hymn: 561
CommentsLine: 45
End:
Hymn: 562
CommentsLine: 38
End:
Hymn: 565
IgnoreLine: 21
VerseOrder: V1,V2,V1
End:
Hymn: 566
AddSpaceAfterSemi: 27
End:
Hymn: 567
ManualCheck: Yes
AddComment: Check with musician what should be on the screen
End:
Hymn: 570
VerseOrder: V1,C1,V2,C1,V3,C1
End:
Hymn: 575
CommentsLine: 30
End:
Hymn: 578
IgnoreLine: 11,18,25
VerseOrder: C1,V1,C1,V2,C1,V3,C1
End:
Hymn: 586
IgnoreLine: 22
VerseOrder: V1,V2,C1,V3,C1
End:
Hymn: 587
VerseOrder: V1,C1,V2,C2,V3
End:
Hymn: 582
CommentsLine: 25
End:
Hymn: 594
CommentsLine: 41
End:
Hymn: 601
CommentsLine: 16
End:
Hymn: 603
ManualCheck: Yes
AddComment: Update Verse 4 for names of the couple
CommentsLine: 22
IgnoreIndent: Yes
End:
Hymn: 609
CommentsLine: 37
End:
Hymn: 610
CommentsLine: 29
End:
Hymn: 626
IgnoreLine: 29,31,44
VerseOrder: V1,C1,C2,V2,C1,C2,C3,C2
End:
Hymn: 631
CommentsLine: 15
End:
Hymn: 627
IgnoreLine: 25,36
VerseOrder: V1,C1,V2,C1,C2,C1
End:
Hymn: 632
IgnoreLine: 17,24
VerseOrder: V1,C1,V2,C1,C2,C1
End:
Hymn: 635
IgnoreLine: 23,25
VerseOrder: V1,C1,C2,V2,C1,C2
End:
Hymn: 637
CommentsLine: 41
End:
Hymn: 638
CommentsLine: 34
End:
Hymn: 640
CommentsLine: 19,20
End:
Hymn: 654
IgnoreIndent: Yes
End:
Hymn: 657
IgnoreLine: 20,21,23
VerseOrder: V1,C1,C2,V2,C1,C2,C3
End:
Hymn: 662
AddSpaceAfterSemi: 2,12
End:
Hymn: 670
IgnoreLine: 27
VerseOrder: V1,C1,V2,C1
End:
Hymn: 677
CommentsLine: 31
End:
Hymn: 681
IgnoreIndent: Yes
End:
Hymn: 684
IgnoreIndent: Yes
End:
Hymn: 693
IgnoreLine: 46,57
VerseOrder: V1,V2,C1,V3,V4,C1,V5,C1
End:
Hymn: 697
IgnoreIndent: Yes
CommentsLine: 21
End:
Hymn: 699
IgnoreLine: 23,32
VerseOrder: V1,C1,V2,C1,C1,C2,C1
End:
Hymn: 700
IgnoreIndent: Yes
End:
Hymn: 707
IgnoreLine: 15
VerseOrder: V1,C1,V2,C1,V3
End:
Hymn: 729
IgnoreIndent: Yes
End:
Hymn: 741
CommentsLine: 25
End:
Hymn: 753
CommentsLine: 14
IgnoreIndent: Yes
End:
Hymn: 754
IgnoreIndent: Yes
End:
Hymn: 764
IgnoreIndent: Yes
CommentsLine: 31
End:
Hymn: 783
BlankLine: 5
End:
Hymn: 819
AddSpaceAfterSemi: 32
End:
Hymn: 820
CommentsLine: 2
BoldLine: 6,7,12,13,17,18,23,24,29,30,32,33,34,35
SongTitle: Psalm 98 - O sing to the Lord a new song
End:

View File

@ -0,0 +1,437 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2019 OpenLP Developers #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 3 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
The :mod:`singingthefaith` module provides the functionality for importing songs which are
exported from Singing The Faith - an Authorised songbook for the Methodist Church of
Great Britain."""
import logging
import re
from pathlib import Path
from openlp.core.common.i18n import translate
from openlp.plugins.songs.lib.importers.songimport import SongImport
from openlp.core.common.applocation import AppLocation
log = logging.getLogger(__name__)
class SingingTheFaithImport(SongImport):
"""
Import songs exported from SingingTheFaith
"""
def __init__(self, manager, **kwargs):
"""
Initialise the class.
"""
super(SingingTheFaithImport, self).__init__(manager, **kwargs)
self.hints_available = False
self.checks_needed = True
self.hint_line = {}
self.hint_file_version = '0'
self.hint_verse_order = ''
self.hint_song_title = ''
self.hint_comments = ''
self.hint_ccli = ''
self.hint_ignore_indent = False
self.hint_songbook_number_in_title = False
def do_import(self):
"""
Receive a single file or a list of files to import.
"""
if not isinstance(self.import_source, list):
return
self.import_wizard.progress_bar.setMaximum(len(self.import_source))
for file_path in self.import_source:
if self.stop_import_flag:
return
# If this is backported to version 2.4 then do_import is called with a filename
# rather than a path object if called from the development version.
# Check here to minimise differences between versions.
if isinstance(file_path, str):
song_file = open(file_path, 'rt', encoding='cp1251')
self.do_import_file(song_file)
song_file.close()
else:
with file_path.open('rt', encoding='cp1251') as song_file:
self.do_import_file(song_file)
def do_import_file(self, file):
"""
Process the SingingTheFaith file - pass in a file-like object, not a file path.
"""
hints_file_name = 'singingthefaith-hints.tag'
singing_the_faith_version = 1
self.set_defaults()
# Setup variables
line_number = 0
old_indent = 0
# The chorus indent is how many spaces the chorus is indented - it might be 6,
# but we test for >= and I do not know how consistent to formatting of the
# exported songs is.
chorus_indent = 5
# Initialise the song title - the format of the title finally produced can be affected
# by the SongbookNumberInTitle option in the hints file
song_title = 'STF000 -'
song_number = '0'
ccli = '0'
current_verse = ''
current_verse_type = 'v'
current_verse_number = 1
# Potentially we could try to track current chorus number to automatically handle
# more than 1 chorus, currently unused.
# current_chorus_number = 1
has_chorus = False
chorus_written = False
auto_verse_order_ok = False
copyright = ''
# the check_flag is prepended to the title, removed if the import should be OK
# all the songs which need manual editing should sort below all the OK songs
check_flag = 'z'
self.add_comment(
'Imported with Singing The Faith Importer v{no}'.format(no=singing_the_faith_version))
# Get the file_song_number - so we can use it for hints
filename = Path(file.name)
song_number_file = filename.stem
song_number_match = re.search(r'\d+', song_number_file)
if song_number_match:
song_number_file = song_number_match.group()
# See if there is a hints file in the same location as the file
dir_path = filename.parent
hints_file_path = dir_path / hints_file_name
try:
with hints_file_path.open('r') as hints_file:
hints_available = self.read_hints(hints_file, song_number_file)
except FileNotFoundError:
# Look for the hints file in the Plugins directory
hints_file_path = AppLocation.get_directory(AppLocation.PluginsDir) / 'songs' / 'lib' / \
'importers' / hints_file_name
try:
with hints_file_path.open('r') as hints_file:
hints_available = self.read_hints(hints_file, song_number_file)
except FileNotFoundError:
hints_available = False
try:
for line in file:
line_number += 1
# Strip out leftover formatting (\i and \b)
line = line.replace('\\i', '')
line = line.replace('\\b', '')
if hints_available and str(line_number) in self.hint_line:
hint = self.hint_line[str(line_number)]
# Set to false if this hint does not replace the line
line_replaced = True
if hint == 'Comment':
line.strip()
self.add_comment(line)
continue
elif hint == 'Ignore':
continue
elif hint == 'Author':
# add as a raw author - do not split
line.strip()
self.add_author(line)
line_number += 1
next(file)
continue
elif hint.startswith('VariantVerse'):
vv, hintverse, replace = hint.split(' ', 2)
this_verse = self.verses[int(hintverse) - 1]
this_verse_str = this_verse[1]
new_verse = this_verse_str
# There might be multiple replace pairs separated by |
replaces = replace.split('|')
for rep in replaces:
source_str, dest_str = rep.split('/')
new_verse = new_verse.replace(source_str, dest_str)
self.add_verse(new_verse, 'v')
self.verse_order_list.append('v{}'.format(str(current_verse_number)))
current_verse_number += 1
line_number += 1
next(file)
continue
elif hint == 'AddSpaceAfterSemi':
line = line.replace(';', '; ')
line_replaced = False
# note - do not use contine here as the line should now be processed as normal.
elif hint == 'AddSpaceAfterColon':
line = line.replace(':', ': ')
line_replaced = False
elif hint == 'BlankLine':
line = ' *Blank*'
line_replaced = False
elif hint == 'BoldLine':
# processing of the hint is deferred, but pick it up as a known hint here
line_replaced = False
else:
self.log_error(translate('SongsPlugin.SingingTheFaithImport',
'File {file})'.format(file=file.name)),
translate('SongsPlugin.SingingTheFaithImport',
'Unknown hint {hint}').format(hint=hint))
if line_replaced:
return
# STF exported lines have a leading verse number at the start of each verse.
# remove them - note that we want to track the indent as that shows a chorus
# so will deal with that before stripping all leading spaces.
indent = 0
if line.strip():
# One hymn has one line which starts '* 6' at the start of a verse
# Strip this out
if line.startswith('* 6'):
line = line.lstrip('* ')
verse_num_match = re.search(r'^\d+', line)
if verse_num_match:
# Could extract the verse number and check it against the calculated
# verse number - TODO
# verse_num = verse_num_match.group()
line = line.lstrip('0123456789')
indent_match = re.search(r'^\s+', line)
if indent_match:
indent = len(indent_match.group())
# Assuming we have sorted out what is verse and what is chorus, strip lines,
# unless ignoreIndent
if self.hint_ignore_indent:
line = line.rstrip()
else:
line = line.strip()
if line_number == 2:
# note that songs seem to start with a blank line so the title is line 2
# Also we strip blanks from the title, even if ignoring indent.
song_title = line.strip()
# Process possible line formatting hints after the verse number has been removed
if hints_available and str(line_number) in self.hint_line and hint == 'BoldLine':
line = '{{st}}{0}{{/st}}'.format(line)
# Detect the 'Reproduced from Singing the Faith Electronic Words Edition' line
if line.startswith('Reproduced from Singing the Faith Electronic Words Edition'):
song_number_match = re.search(r'\d+', line)
if song_number_match:
song_number = song_number_match.group()
continue
elif indent == 0:
# If the indent is 0 and it contains '(c)' then it is a Copyright line
if '(c)' in line:
copyright = line
continue
elif (line.startswith('Liturgical ') or line.startswith('From The ') or
line.startswith('From Common ') or line.startswith('Based on Psalm ')):
self.add_comment(line)
continue
# If indent is 0 it may be the author, unless it was one of the cases covered above
elif len(line) > 0:
# May have more than one author, separated by ' and '
authors = line.split(' and ')
for a in authors:
self.parse_author(a)
continue
# If a blank line has bee replaced by *Blank* then put it back to being
# a simple space since this is past stripping blanks
if '*Blank*' in line:
line = ' '
if line == '':
if current_verse != '':
self.add_verse(current_verse, current_verse_type)
self.verse_order_list.append(current_verse_type + str(current_verse_number))
if current_verse_type == 'c':
chorus_written = True
else:
current_verse_number += 1
current_verse = ''
if chorus_written:
current_verse_type = 'v'
else:
# If the line is indented more than or equal chorus_indent then assume it is a chorus
# If the indent has just changed then start a new verse just like hitting a blank line
if not self.hint_ignore_indent and ((indent >= chorus_indent) and (old_indent < indent)):
if current_verse != '':
self.add_verse(current_verse, current_verse_type)
self.verse_order_list.append(current_verse_type + str(current_verse_number))
if current_verse_type == 'v':
current_verse_number += 1
current_verse = line
current_verse_type = 'c'
old_indent = indent
chorus_written = False
has_chorus = True
continue
if current_verse == '':
current_verse += line
else:
current_verse += '\n' + line
old_indent = indent
except Exception as e:
self.log_error(translate('SongsPlugin.SingingTheFaithImport', 'File {file}').format(file=file.name),
translate('SongsPlugin.SingingTheFaithImport', 'Error: {error}').format(error=e))
return
if self.hint_song_title:
song_title = self.hint_song_title
self.title = '{}STF{} - {title}'.format(check_flag, song_number.zfill(3), title=song_title)
self.song_book_name = 'Singing The Faith'
self.song_number = song_number
self.ccli_number = ccli
self.add_copyright(copyright)
# If we have a chorus then the generated Verse order can not be used directly, but we can generate
# one for two special cases - Verse followed by one chorus (to be repeated after every verse)
# of Chorus, followed by verses. If hints for ManualCheck or VerseOrder are supplied ignore this
if has_chorus and not self.hint_verse_order and not self.checks_needed:
auto_verse_order_ok = False
# Popular case V1 C2 V2 ...
if self.verse_order_list: # protect against odd cases
if self.verse_order_list[0] == 'v1' and self.verse_order_list[1] == 'c2':
new_verse_order_list = ['v1', 'c1']
i = 2
auto_verse_order_ok = True
elif self.verse_order_list[0] == 'c1' and self.verse_order_list[1] == 'v1':
new_verse_order_list = ['c1', 'v1', 'c1']
i = 2
auto_verse_order_ok = True
# if we are in a case we can deal with
if auto_verse_order_ok:
while i < len(self.verse_order_list):
if self.verse_order_list[i].startswith('v'):
new_verse_order_list.append(self.verse_order_list[i])
new_verse_order_list.append('c1')
else:
auto_verse_order_ok = False
self.add_comment('Importer detected unexpected verse order entry {}'.format(
self.verse_order_list[i]))
i += 1
self.verse_order_list = new_verse_order_list
else:
if not auto_verse_order_ok:
self.verse_order_list = []
if self.hint_verse_order:
self.verse_order_list = self.hint_verse_order.split(',')
if self.hint_comments:
self.add_comment(self.hint_comments)
if self.hint_ccli:
self.ccli_number = self.hint_ccli
# Write the title last as by now we will know if we need checks
if hints_available and not self.checks_needed:
check_flag = ''
elif not hints_available and not has_chorus:
check_flag = ''
elif not hints_available and has_chorus and auto_verse_order_ok:
check_flag = ''
if self.hint_songbook_number_in_title:
self.title = '{}STF{} - {title}'.format(check_flag, song_number.zfill(3), title=song_title)
else:
self.title = '{}{title}'.format(check_flag, title=song_title)
if not self.finish():
self.log_error(file.name)
def read_hints(self, file, song_number):
"""
Read the hints used to transform a particular song into version which can be projected,
or improve the transformation process beyond the standard heuristics. Not every song will
have, or need, hints.
"""
hintfound = False
self.hint_verse_order = ''
self.hint_line.clear()
self.hint_comments = ''
self.hint_song_title = ''
self.hint_ignore_indent = False
self.hint_ccli = ''
for tl in file:
if not tl.strip():
return hintfound
tagval = tl.split(':')
tag = tagval[0].strip()
val = tagval[1].strip()
if tag == 'Version':
self.hint_file_version = val
continue
elif tag == 'SongbookNumberInTitle':
if val == 'False':
self.hint_songbook_number_in_title = False
else:
self.hint_songbook_number_in_title = True
continue
elif tag == 'Comment':
continue
if (tag == 'Hymn') and (val == song_number):
self.add_comment('Using hints version {}'.format(str(self.hint_file_version)))
hintfound = True
# Assume, unless the hints has ManualCheck that if hinted all will be OK
self.checks_needed = False
for tl in file:
tagval = tl.split(':')
tag = tagval[0].strip()
val = tagval[1].strip()
if tag == 'End':
return hintfound
elif tag == 'CommentsLine':
vals = val.split(',')
for v in vals:
self.hint_line[v] = 'Comment'
elif tag == 'IgnoreLine':
vals = val.split(',')
for v in vals:
self.hint_line[v] = 'Ignore'
elif tag == 'AuthorLine':
vals = val.split(',')
for v in vals:
self.hint_line[v] = 'Author'
elif tag == 'AddSpaceAfterSemi':
vals = val.split(',')
for v in vals:
self.hint_line[v] = 'AddSpaceAfterSemi'
elif tag == 'AddSpaceAfterColon':
vals = val.split(',')
for v in vals:
self.hint_line[v] = 'AddSpaceAfterColon'
elif tag == 'BlankLine':
vals = val.split(',')
for v in vals:
self.hint_line[v] = 'BlankLine'
elif tag == 'BoldLine':
vals = val.split(',')
for v in vals:
self.hint_line[v] = 'BoldLine'
elif tag == 'VerseOrder':
self.hint_verse_order = val
elif tag == 'ManualCheck':
self.checks_needed = True
elif tag == 'IgnoreIndent':
self.hint_ignore_indent = True
elif tag == 'VariantVerse':
vvline = val.split(' ', 1)
self.hint_line[vvline[0].strip()] = 'VariantVerse {}'.format(vvline[1].strip())
elif tag == 'SongTitle':
self.hint_song_title = val
elif tag == 'AddComment':
self.hint_comments += '\n' + val
elif tag == 'CCLI':
self.hint_ccli = val
elif tag == 'Hymn':
self.log_error(file.name, 'Missing End tag in hint for Hymn: {}'.format(song_number))
else:
self.log_error(file.name, 'Unknown tag {} value {}'.format(tag, val))
return hintfound

View File

@ -0,0 +1,63 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
##########################################################################
# OpenLP - Open Source Lyrics Projection #
# ---------------------------------------------------------------------- #
# Copyright (c) 2008-2019 OpenLP Developers #
# ---------------------------------------------------------------------- #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
##########################################################################
"""
This module contains tests for the SingingTheFaith song importer.
"""
from tests.helpers.songfileimport import SongImportTestHelper
from tests.utils.constants import RESOURCE_PATH
TEST_PATH = RESOURCE_PATH / 'songs' / 'singingthefaith'
class TestSingingTheFaithFileImport(SongImportTestHelper):
def __init__(self, *args, **kwargs):
self.importer_class_name = 'SingingTheFaithImport'
self.importer_module_name = 'singingthefaith'
super(TestSingingTheFaithFileImport, self).__init__(*args, **kwargs)
def test_song_import(self):
"""
Test that loading a Singing The Faith file works correctly on various files
"""
# Note that the previous tests without hints no longer apply as there is always a
# hints file, which contains the hints for the real Singing The Faith Songs.
# Unhinted songs here must be numbered above any real Singing The Faith Song
# Single verse
self.file_import([TEST_PATH / 'H901.txt'],
self.load_external_result_data(TEST_PATH / 'STF901.json'))
# Whole song
self.file_import([TEST_PATH / 'H902.txt'],
self.load_external_result_data(TEST_PATH / 'STF902.json'))
# Tests with hints - note that the hints directory has a hints.tag which specifies
# SongbookNumberInTitle: True
# The default is false, so the unhinted tests will not have the title, but the hinted
# song tests will need it
# Single verse
self.file_import([TEST_PATH / 'hints' / 'H1.txt'],
self.load_external_result_data(TEST_PATH / 'hints' / 'STF001.json'))
# Whole song
self.file_import([TEST_PATH / 'hints' / 'H2.txt'],
self.load_external_result_data(TEST_PATH / 'hints' / 'STF002.json'))

View File

@ -123,7 +123,8 @@ class SongImportTestHelper(TestCase):
log.debug("Song copyright imported: %s" % importer.song_number)
log.debug("Topics imported: %s" % importer.topics)
assert importer.title == title, 'title for %s should be "%s"' % (source_file_name, title)
assert importer.title == title, \
'title for %s should be "%s" and is "%s"' % (source_file_name, title, importer.title)
for author in author_calls:
if isinstance(author, str):
self.mocked_add_author.assert_any_call(author)
@ -152,7 +153,8 @@ class SongImportTestHelper(TestCase):
'song_number for %s should be %s' % (source_file_name, song_number)
if verse_order_list:
assert importer.verse_order_list == verse_order_list, \
'verse_order_list for %s should be %s' % (source_file_name, verse_order_list)
'verse_order_list for %s should be %s and is %s' % (source_file_name,
verse_order_list, importer.verse_order_list)
self.mocked_finish.assert_called_with()
def _get_data(self, data, key):

View File

@ -0,0 +1,9 @@
1 Amazing Grace! how sweet the sound!
That saved a wretch like me!
I once was lost, but now am found;
Was blind, but now I see.
John Newton (d. 1807)
Reproduced from Singing the Faith Electronic Words Edition, number 901 - or not as this is a hand made test file

View File

@ -0,0 +1,30 @@
1 Amazing Grace! how sweet the sound!
That saved a wretch like me!
I once was lost, but now am found;
Was blind, but now I see.
2 'Twas grace that taught my heart to fear,
And grace my fears relieved.
How precious did that grace appear,
The hour I first believed.
3 The Lord has promised good to me,
His Word my hope secures.
He will my shield and portion be
As long as life endures.
4 Thro' many dangers, toils and snares
I have already come.
'Tis grace that brought me safe thus far,
And grace will lead me home.
5 When we've been there ten thousand years,
Bright shining as the sun,
We've no less days to sing God's praise,
Than when we first begun.
John Newton (d. 1807)
Reproduced from Singing the Faith Electronic Words Edition, number 2 - or not as this is a hand made test file

View File

@ -0,0 +1,13 @@
{
"title": "Amazing Grace! how sweet the sound!",
"authors": [
"John Newton (d. 1807)"
],
"verse_order_list": ["v1"],
"verses": [
[
"Amazing Grace! how sweet the sound!\nThat saved a wretch like me!\nI once was lost, but now am found;\nWas blind, but now I see.",
"v"
]
]
}

View File

@ -0,0 +1,29 @@
{
"title": "Amazing Grace! how sweet the sound!",
"authors": [
"John Newton (d. 1807)"
],
"verse_order_list": ["v1", "v2", "v3", "v4", "v5"],
"verses": [
[
"Amazing Grace! how sweet the sound!\nThat saved a wretch like me!\nI once was lost, but now am found;\nWas blind, but now I see.",
"v"
],
[
"'Twas grace that taught my heart to fear,\nAnd grace my fears relieved.\nHow precious did that grace appear,\nThe hour I first believed.",
"v"
],
[
"The Lord has promised good to me,\nHis Word my hope secures.\nHe will my shield and portion be\nAs long as life endures.",
"v"
],
[
"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.",
"v"
],
[
"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.",
"v"
]
]
}

View File

@ -0,0 +1,9 @@
1 Amazing Grace! how sweet the sound!
That saved a wretch like me!
I once was lost, but now am found;
Was blind, but now I see.
John Newton (d. 1807)
Reproduced from Singing the Faith Electronic Words Edition, number 1 - or not as this is a hand made test file

View File

@ -0,0 +1,30 @@
1 Amazing Grace! how sweet the sound!
That saved a wretch like me!
I once was lost, but now am found;
Was blind, but now I see.
2 'Twas grace that taught my heart to fear,
And grace my fears relieved.
How precious did that grace appear,
The hour I first believed.
3 The Lord has promised good to me,
His Word my hope secures.
He will my shield and portion be
As long as life endures.
4 Thro' many dangers, toils and snares
I have already come.
'Tis grace that brought me safe thus far,
And grace will lead me home.
5 When we've been there ten thousand years,
Bright shining as the sun,
We've no less days to sing God's praise,
Than when we first begun.
John Newton (d. 1807)
Reproduced from Singing the Faith Electronic Words Edition, number 2 - or not as this is a hand made test file

View File

@ -0,0 +1,13 @@
{
"title": "STF001 - Amazing Grace! how sweet the sound!",
"authors": [
"John Newton (d. 1807)"
],
"verse_order_list": ["v1"],
"verses": [
[
"Amazing Grace! how sweet the sound!\nThat saved a wretch like me!\nI once was lost, but now am found;\nWas blind, but now I see.",
"v"
]
]
}

View File

@ -0,0 +1,29 @@
{
"title": "STF002 - Amazing Grace! how sweet the sound!",
"authors": [
"John Newton (d. 1807)"
],
"verse_order_list": ["v1", "v2", "v3", "v4", "v5"],
"verses": [
[
"Amazing Grace! how sweet the sound!\nThat saved a wretch like me!\nI once was lost, but now am found;\nWas blind, but now I see.",
"v"
],
[
"'Twas grace that taught my heart to fear,\nAnd grace my fears relieved.\nHow precious did that grace appear,\nThe hour I first believed.",
"v"
],
[
"The Lord has promised good to me,\nHis Word my hope secures.\nHe will my shield and portion be\nAs long as life endures.",
"v"
],
[
"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.",
"v"
],
[
"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.",
"v"
]
]
}

View File

@ -0,0 +1,5 @@
Tag-STFHints-version: 1.0
Version: 2
SongbookNumberInTitle: True
End: