forked from openlp/openlp
Song import cleanups
This commit is contained in:
parent
1301b4cfa3
commit
75281b5cf1
@ -201,7 +201,7 @@ class SongImportForm(OpenLPWizard):
|
|||||||
def validateCurrentPage(self):
|
def validateCurrentPage(self):
|
||||||
"""
|
"""
|
||||||
Re-implement the validateCurrentPage() method. Validate the current page before moving on to the next page.
|
Re-implement the validateCurrentPage() method. Validate the current page before moving on to the next page.
|
||||||
Provide each song format class with a chance to validate its input by overriding isValidSource().
|
Provide each song format class with a chance to validate its input by overriding is_valid_source().
|
||||||
"""
|
"""
|
||||||
if self.currentPage() == self.welcome_page:
|
if self.currentPage() == self.welcome_page:
|
||||||
return True
|
return True
|
||||||
@ -217,7 +217,7 @@ class SongImportForm(OpenLPWizard):
|
|||||||
import_source = self.format_widgets[this_format]['file_path_edit'].text()
|
import_source = self.format_widgets[this_format]['file_path_edit'].text()
|
||||||
error_title = (UiStrings().IFSs if select_mode == SongFormatSelect.SingleFile else UiStrings().IFdSs)
|
error_title = (UiStrings().IFSs if select_mode == SongFormatSelect.SingleFile else UiStrings().IFdSs)
|
||||||
focus_button = self.format_widgets[this_format]['browseButton']
|
focus_button = self.format_widgets[this_format]['browseButton']
|
||||||
if not class_.isValidSource(import_source):
|
if not class_.is_valid_source(import_source):
|
||||||
critical_error_message_box(error_title, error_msg)
|
critical_error_message_box(error_title, error_msg)
|
||||||
focus_button.setFocus()
|
focus_button.setFocus()
|
||||||
return False
|
return False
|
||||||
|
@ -38,6 +38,7 @@ from .songimport import SongImport
|
|||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class CCLIFileImport(SongImport):
|
class CCLIFileImport(SongImport):
|
||||||
"""
|
"""
|
||||||
The :class:`CCLIFileImport` class provides OpenLP with the ability to import
|
The :class:`CCLIFileImport` class provides OpenLP with the ability to import
|
||||||
@ -86,13 +87,13 @@ class CCLIFileImport(SongImport):
|
|||||||
if ext.lower() == '.usr':
|
if ext.lower() == '.usr':
|
||||||
log.info('SongSelect .usr format file found: %s', filename)
|
log.info('SongSelect .usr format file found: %s', filename)
|
||||||
if not self.doImportUsrFile(lines):
|
if not self.doImportUsrFile(lines):
|
||||||
self.logError(filename)
|
self.log_error(filename)
|
||||||
elif ext.lower() == '.txt':
|
elif ext.lower() == '.txt':
|
||||||
log.info('SongSelect .txt format file found: %s', filename)
|
log.info('SongSelect .txt format file found: %s', filename)
|
||||||
if not self.doImportTxtFile(lines):
|
if not self.doImportTxtFile(lines):
|
||||||
self.logError(filename)
|
self.log_error(filename)
|
||||||
else:
|
else:
|
||||||
self.logError(filename,
|
self.log_error(filename,
|
||||||
translate('SongsPlugin.CCLIFileImport', 'The file does not have a valid extension.'))
|
translate('SongsPlugin.CCLIFileImport', 'The file does not have a valid extension.'))
|
||||||
log.info('Extension %s is not valid', filename)
|
log.info('Extension %s is not valid', filename)
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
@ -163,9 +164,9 @@ class CCLIFileImport(SongImport):
|
|||||||
if line.startswith('[S '):
|
if line.startswith('[S '):
|
||||||
ccli, line = line.split(']', 1)
|
ccli, line = line.split(']', 1)
|
||||||
if ccli.startswith('[S A'):
|
if ccli.startswith('[S A'):
|
||||||
self.ccliNumber = ccli[4:].strip()
|
self.ccli_number = ccli[4:].strip()
|
||||||
else:
|
else:
|
||||||
self.ccliNumber = ccli[3:].strip()
|
self.ccli_number = ccli[3:].strip()
|
||||||
if line.startswith('Title='):
|
if line.startswith('Title='):
|
||||||
self.title = line[6:].strip()
|
self.title = line[6:].strip()
|
||||||
elif line.startswith('Author='):
|
elif line.startswith('Author='):
|
||||||
@ -213,7 +214,7 @@ class CCLIFileImport(SongImport):
|
|||||||
verse_type = VerseType.tags[VerseType.Other]
|
verse_type = VerseType.tags[VerseType.Other]
|
||||||
verse_text = verse_lines[1]
|
verse_text = verse_lines[1]
|
||||||
if verse_text:
|
if verse_text:
|
||||||
self.addVerse(verse_text, verse_type)
|
self.add_verse(verse_text, verse_type)
|
||||||
check_first_verse_line = False
|
check_first_verse_line = False
|
||||||
# Handle multiple authors
|
# Handle multiple authors
|
||||||
author_list = song_author.split('/')
|
author_list = song_author.split('/')
|
||||||
@ -223,7 +224,7 @@ class CCLIFileImport(SongImport):
|
|||||||
separated = author.split(',')
|
separated = author.split(',')
|
||||||
if len(separated) > 1:
|
if len(separated) > 1:
|
||||||
author = ' '.join(map(str.strip, reversed(separated)))
|
author = ' '.join(map(str.strip, reversed(separated)))
|
||||||
self.addAuthor(author.strip())
|
self.add_author(author.strip())
|
||||||
self.topics = [topic.strip() for topic in song_topics.split('/t')]
|
self.topics = [topic.strip() for topic in song_topics.split('/t')]
|
||||||
return self.finish()
|
return self.finish()
|
||||||
|
|
||||||
@ -272,7 +273,7 @@ class CCLIFileImport(SongImport):
|
|||||||
continue
|
continue
|
||||||
elif verse_start:
|
elif verse_start:
|
||||||
if verse_text:
|
if verse_text:
|
||||||
self.addVerse(verse_text, verse_type)
|
self.add_verse(verse_text, verse_type)
|
||||||
verse_text = ''
|
verse_text = ''
|
||||||
verse_start = False
|
verse_start = False
|
||||||
else:
|
else:
|
||||||
@ -286,7 +287,7 @@ class CCLIFileImport(SongImport):
|
|||||||
if clean_line.startswith('CCLI'):
|
if clean_line.startswith('CCLI'):
|
||||||
line_number += 1
|
line_number += 1
|
||||||
ccli_parts = clean_line.split(' ')
|
ccli_parts = clean_line.split(' ')
|
||||||
self.ccliNumber = ccli_parts[len(ccli_parts) - 1]
|
self.ccli_number = ccli_parts[len(ccli_parts) - 1]
|
||||||
elif not verse_start:
|
elif not verse_start:
|
||||||
# We have the verse descriptor
|
# We have the verse descriptor
|
||||||
verse_desc_parts = clean_line.split(' ')
|
verse_desc_parts = clean_line.split(' ')
|
||||||
@ -348,5 +349,5 @@ class CCLIFileImport(SongImport):
|
|||||||
author_list = song_author.split('|')
|
author_list = song_author.split('|')
|
||||||
# Clean spaces before and after author names.
|
# Clean spaces before and after author names.
|
||||||
for author_name in author_list:
|
for author_name in author_list:
|
||||||
self.addAuthor(author_name.strip())
|
self.add_author(author_name.strip())
|
||||||
return self.finish()
|
return self.finish()
|
||||||
|
@ -92,18 +92,18 @@ class DreamBeamImport(SongImport):
|
|||||||
for file in self.import_source:
|
for file in self.import_source:
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
return
|
return
|
||||||
self.setDefaults()
|
self.set_defaults()
|
||||||
parser = etree.XMLParser(remove_blank_text=True)
|
parser = etree.XMLParser(remove_blank_text=True)
|
||||||
try:
|
try:
|
||||||
parsed_file = etree.parse(open(file, 'r'), parser)
|
parsed_file = etree.parse(open(file, 'r'), parser)
|
||||||
except etree.XMLSyntaxError:
|
except etree.XMLSyntaxError:
|
||||||
log.exception('XML syntax error in file %s' % file)
|
log.exception('XML syntax error in file %s' % file)
|
||||||
self.logError(file, SongStrings.XMLSyntaxError)
|
self.log_error(file, SongStrings.XMLSyntaxError)
|
||||||
continue
|
continue
|
||||||
xml = etree.tostring(parsed_file).decode()
|
xml = etree.tostring(parsed_file).decode()
|
||||||
song_xml = objectify.fromstring(xml)
|
song_xml = objectify.fromstring(xml)
|
||||||
if song_xml.tag != 'DreamSong':
|
if song_xml.tag != 'DreamSong':
|
||||||
self.logError(file,
|
self.log_error(file,
|
||||||
translate('SongsPlugin.DreamBeamImport', 'Invalid DreamBeam song file. Missing DreamSong tag.'))
|
translate('SongsPlugin.DreamBeamImport', 'Invalid DreamBeam song file. Missing DreamSong tag.'))
|
||||||
continue
|
continue
|
||||||
if hasattr(song_xml, 'Version'):
|
if hasattr(song_xml, 'Version'):
|
||||||
@ -121,14 +121,14 @@ class DreamBeamImport(SongImport):
|
|||||||
verse_type = lyrics_item.get('Type')
|
verse_type = lyrics_item.get('Type')
|
||||||
verse_number = lyrics_item.get('Number')
|
verse_number = lyrics_item.get('Number')
|
||||||
verse_text = str(lyrics_item.text)
|
verse_text = str(lyrics_item.text)
|
||||||
self.addVerse(verse_text, ('%s%s' % (verse_type[:1], verse_number)))
|
self.add_verse(verse_text, ('%s%s' % (verse_type[:1], verse_number)))
|
||||||
if hasattr(song_xml, 'Collection'):
|
if hasattr(song_xml, 'Collection'):
|
||||||
self.songBookName = str(song_xml.Collection.text)
|
self.song_book_name = str(song_xml.Collection.text)
|
||||||
if hasattr(song_xml, 'Number'):
|
if hasattr(song_xml, 'Number'):
|
||||||
self.songNumber = str(song_xml.Number.text)
|
self.song_number = str(song_xml.Number.text)
|
||||||
if hasattr(song_xml, 'Sequence'):
|
if hasattr(song_xml, 'Sequence'):
|
||||||
for LyricsSequenceItem in (song_xml.Sequence.iterchildren()):
|
for LyricsSequenceItem in (song_xml.Sequence.iterchildren()):
|
||||||
self.verseOrderList.append("%s%s" % (LyricsSequenceItem.get('Type')[:1],
|
self.verse_order_list.append("%s%s" % (LyricsSequenceItem.get('Type')[:1],
|
||||||
LyricsSequenceItem.get('Number')))
|
LyricsSequenceItem.get('Number')))
|
||||||
if hasattr(song_xml, 'Notes'):
|
if hasattr(song_xml, 'Notes'):
|
||||||
self.comments = str(song_xml.Notes.text)
|
self.comments = str(song_xml.Notes.text)
|
||||||
@ -138,15 +138,15 @@ class DreamBeamImport(SongImport):
|
|||||||
if hasattr(song_xml.Text1, 'Text'):
|
if hasattr(song_xml.Text1, 'Text'):
|
||||||
self.lyrics = str(song_xml.Text1.Text.text)
|
self.lyrics = str(song_xml.Text1.Text.text)
|
||||||
for verse in self.lyrics.split('\n\n\n'):
|
for verse in self.lyrics.split('\n\n\n'):
|
||||||
self.addVerse(verse)
|
self.add_verse(verse)
|
||||||
if hasattr(song_xml.Text2, 'Text'):
|
if hasattr(song_xml.Text2, 'Text'):
|
||||||
author_copyright = song_xml.Text2.Text.text
|
author_copyright = song_xml.Text2.Text.text
|
||||||
if author_copyright:
|
if author_copyright:
|
||||||
author_copyright = str(author_copyright)
|
author_copyright = str(author_copyright)
|
||||||
if author_copyright.find(
|
if author_copyright.find(
|
||||||
str(SongStrings.CopyrightSymbol)) >= 0:
|
str(SongStrings.CopyrightSymbol)) >= 0:
|
||||||
self.addCopyright(author_copyright)
|
self.add_copyright(author_copyright)
|
||||||
else:
|
else:
|
||||||
self.parse_author(author_copyright)
|
self.parse_author(author_copyright)
|
||||||
if not self.finish():
|
if not self.finish():
|
||||||
self.logError(file)
|
self.log_error(file)
|
||||||
|
@ -68,9 +68,9 @@ class EasySlidesImport(SongImport):
|
|||||||
if hasattr(song, 'Title2'):
|
if hasattr(song, 'Title2'):
|
||||||
self._add_unicode_attribute('alternateTitle', song.Title2)
|
self._add_unicode_attribute('alternateTitle', song.Title2)
|
||||||
if hasattr(song, 'SongNumber'):
|
if hasattr(song, 'SongNumber'):
|
||||||
self._add_unicode_attribute('songNumber', song.SongNumber)
|
self._add_unicode_attribute('song_number', song.SongNumber)
|
||||||
if self.songNumber == '0':
|
if self.song_number == '0':
|
||||||
self.songNumber = ''
|
self.song_number = ''
|
||||||
self._addAuthors(song)
|
self._addAuthors(song)
|
||||||
if hasattr(song, 'Copyright'):
|
if hasattr(song, 'Copyright'):
|
||||||
self._add_copyright(song.Copyright)
|
self._add_copyright(song.Copyright)
|
||||||
@ -79,13 +79,13 @@ class EasySlidesImport(SongImport):
|
|||||||
if hasattr(song, 'LicenceAdmin2'):
|
if hasattr(song, 'LicenceAdmin2'):
|
||||||
self._add_copyright(song.LicenceAdmin2)
|
self._add_copyright(song.LicenceAdmin2)
|
||||||
if hasattr(song, 'BookReference'):
|
if hasattr(song, 'BookReference'):
|
||||||
self._add_unicode_attribute('songBookName', song.BookReference)
|
self._add_unicode_attribute('song_book_name', song.BookReference)
|
||||||
self._parseAndAddLyrics(song)
|
self._parseAndAddLyrics(song)
|
||||||
if self._success:
|
if self._success:
|
||||||
if not self.finish():
|
if not self.finish():
|
||||||
self.logError(song.Title1 if song.Title1 else '')
|
self.log_error(song.Title1 if song.Title1 else '')
|
||||||
else:
|
else:
|
||||||
self.setDefaults()
|
self.set_defaults()
|
||||||
|
|
||||||
def _add_unicode_attribute(self, self_attribute, import_attribute, mandatory=False):
|
def _add_unicode_attribute(self, self_attribute, import_attribute, mandatory=False):
|
||||||
"""
|
"""
|
||||||
@ -132,7 +132,7 @@ class EasySlidesImport(SongImport):
|
|||||||
The imported variable to get the data from.
|
The imported variable to get the data from.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self.addCopyright(str(element).strip())
|
self.add_copyright(str(element).strip())
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
log.exception('Unicode error on decoding copyright: %s' % element)
|
log.exception('Unicode error on decoding copyright: %s' % element)
|
||||||
self._success = False
|
self._success = False
|
||||||
@ -235,7 +235,7 @@ class EasySlidesImport(SongImport):
|
|||||||
verses[reg].setdefault(vt, {})
|
verses[reg].setdefault(vt, {})
|
||||||
verses[reg][vt].setdefault(vn, {})
|
verses[reg][vt].setdefault(vn, {})
|
||||||
verses[reg][vt][vn].setdefault(inst, [])
|
verses[reg][vt][vn].setdefault(inst, [])
|
||||||
verses[reg][vt][vn][inst].append(self.tidyText(line))
|
verses[reg][vt][vn][inst].append(self.tidy_text(line))
|
||||||
# done parsing
|
# done parsing
|
||||||
|
|
||||||
versetags = []
|
versetags = []
|
||||||
@ -271,7 +271,7 @@ class EasySlidesImport(SongImport):
|
|||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
if tag in versetags:
|
if tag in versetags:
|
||||||
self.verseOrderList.append(tag)
|
self.verse_order_list.append(tag)
|
||||||
else:
|
else:
|
||||||
log.info('Got order item %s, which is not in versetags, dropping item from presentation order',
|
log.info('Got order item %s, which is not in versetags, dropping item from presentation order',
|
||||||
tag)
|
tag)
|
||||||
|
@ -163,7 +163,7 @@ class EasyWorshipSongImport(SongImport):
|
|||||||
break
|
break
|
||||||
raw_record = db_file.read(record_size)
|
raw_record = db_file.read(record_size)
|
||||||
self.fields = self.recordStruct.unpack(raw_record)
|
self.fields = self.recordStruct.unpack(raw_record)
|
||||||
self.setDefaults()
|
self.set_defaults()
|
||||||
self.title = self.getField(fi_title).decode()
|
self.title = self.getField(fi_title).decode()
|
||||||
# Get remaining fields.
|
# Get remaining fields.
|
||||||
copy = self.getField(fi_copy)
|
copy = self.getField(fi_copy)
|
||||||
@ -180,7 +180,7 @@ class EasyWorshipSongImport(SongImport):
|
|||||||
self.copyright += translate('SongsPlugin.EasyWorshipSongImport',
|
self.copyright += translate('SongsPlugin.EasyWorshipSongImport',
|
||||||
'Administered by %s') % admin.decode()
|
'Administered by %s') % admin.decode()
|
||||||
if ccli:
|
if ccli:
|
||||||
self.ccliNumber = ccli.decode()
|
self.ccli_number = ccli.decode()
|
||||||
if authors:
|
if authors:
|
||||||
# Split up the authors
|
# Split up the authors
|
||||||
author_list = authors.split(b'/')
|
author_list = authors.split(b'/')
|
||||||
@ -189,7 +189,7 @@ class EasyWorshipSongImport(SongImport):
|
|||||||
if len(author_list) < 2:
|
if len(author_list) < 2:
|
||||||
author_list = authors.split(b',')
|
author_list = authors.split(b',')
|
||||||
for author_name in author_list:
|
for author_name in author_list:
|
||||||
self.addAuthor(author_name.decode().strip())
|
self.add_author(author_name.decode().strip())
|
||||||
if words:
|
if words:
|
||||||
# Format the lyrics
|
# Format the lyrics
|
||||||
result = strip_rtf(words.decode(), self.encoding)
|
result = strip_rtf(words.decode(), self.encoding)
|
||||||
@ -227,14 +227,14 @@ class EasyWorshipSongImport(SongImport):
|
|||||||
if not number_found:
|
if not number_found:
|
||||||
verse_type += '1'
|
verse_type += '1'
|
||||||
break
|
break
|
||||||
self.addVerse(verse_split[-1].strip() if first_line_is_tag else verse, verse_type)
|
self.add_verse(verse_split[-1].strip() if first_line_is_tag else verse, verse_type)
|
||||||
if len(self.comments) > 5:
|
if len(self.comments) > 5:
|
||||||
self.comments += str(translate('SongsPlugin.EasyWorshipSongImport',
|
self.comments += str(translate('SongsPlugin.EasyWorshipSongImport',
|
||||||
'\n[above are Song Tags with notes imported from EasyWorship]'))
|
'\n[above are Song Tags with notes imported from EasyWorship]'))
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
break
|
break
|
||||||
if not self.finish():
|
if not self.finish():
|
||||||
self.logError(self.import_source)
|
self.log_error(self.import_source)
|
||||||
db_file.close()
|
db_file.close()
|
||||||
self.memoFile.close()
|
self.memoFile.close()
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ class FoilPresenterImport(SongImport):
|
|||||||
xml = etree.tostring(parsed_file).decode()
|
xml = etree.tostring(parsed_file).decode()
|
||||||
self.FoilPresenter.xml_to_song(xml)
|
self.FoilPresenter.xml_to_song(xml)
|
||||||
except etree.XMLSyntaxError:
|
except etree.XMLSyntaxError:
|
||||||
self.logError(file_path, SongStrings.XMLSyntaxError)
|
self.log_error(file_path, SongStrings.XMLSyntaxError)
|
||||||
log.exception('XML syntax error in file %s' % file_path)
|
log.exception('XML syntax error in file %s' % file_path)
|
||||||
|
|
||||||
|
|
||||||
@ -423,7 +423,7 @@ class FoilPresenter(object):
|
|||||||
VerseType.tags[VerseType.PreChorus]: 1
|
VerseType.tags[VerseType.PreChorus]: 1
|
||||||
}
|
}
|
||||||
if not hasattr(foilpresenterfolie.strophen, 'strophe'):
|
if not hasattr(foilpresenterfolie.strophen, 'strophe'):
|
||||||
self.importer.logError(self._child(foilpresenterfolie.titel),
|
self.importer.log_error(self._child(foilpresenterfolie.titel),
|
||||||
str(translate('SongsPlugin.FoilPresenterSongImport',
|
str(translate('SongsPlugin.FoilPresenterSongImport',
|
||||||
'Invalid Foilpresenter song file. No verses found.')))
|
'Invalid Foilpresenter song file. No verses found.')))
|
||||||
self.save_song = False
|
self.save_song = False
|
||||||
|
@ -137,7 +137,7 @@ class SongFormat(object):
|
|||||||
Title for ``QFileDialog`` (default includes the format's ``u'name'``).
|
Title for ``QFileDialog`` (default includes the format's ``u'name'``).
|
||||||
|
|
||||||
``u'invalidSourceMsg'``
|
``u'invalidSourceMsg'``
|
||||||
Message displayed if ``isValidSource()`` returns ``False``.
|
Message displayed if ``is_valid_source()`` returns ``False``.
|
||||||
|
|
||||||
``u'descriptionText'``
|
``u'descriptionText'``
|
||||||
Short description (1-2 lines) about the song format.
|
Short description (1-2 lines) about the song format.
|
||||||
|
@ -57,7 +57,7 @@ class MediaShoutImport(SongImport):
|
|||||||
'DBQ=%s;PWD=6NOZ4eHK7k' % self.import_source)
|
'DBQ=%s;PWD=6NOZ4eHK7k' % self.import_source)
|
||||||
except:
|
except:
|
||||||
# Unfortunately no specific exception type
|
# Unfortunately no specific exception type
|
||||||
self.logError(self.import_source,
|
self.log_error(self.import_source,
|
||||||
translate('SongsPlugin.MediaShoutImport', 'Unable to open the MediaShout database.'))
|
translate('SongsPlugin.MediaShoutImport', 'Unable to open the MediaShout database.'))
|
||||||
return
|
return
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
@ -88,21 +88,21 @@ class MediaShoutImport(SongImport):
|
|||||||
"""
|
"""
|
||||||
Create the song, i.e. title, verse etc.
|
Create the song, i.e. title, verse etc.
|
||||||
"""
|
"""
|
||||||
self.setDefaults()
|
self.set_defaults()
|
||||||
self.title = song.Title
|
self.title = song.Title
|
||||||
self.parse_author(song.Author)
|
self.parse_author(song.Author)
|
||||||
self.addCopyright(song.Copyright)
|
self.add_copyright(song.Copyright)
|
||||||
self.comments = song.Notes
|
self.comments = song.Notes
|
||||||
for topic in topics:
|
for topic in topics:
|
||||||
self.topics.append(topic.Name)
|
self.topics.append(topic.Name)
|
||||||
if '-' in song.SongID:
|
if '-' in song.SongID:
|
||||||
self.songBookName, self.songNumber = song.SongID.split('-', 1)
|
self.song_book_name, self.song_number = song.SongID.split('-', 1)
|
||||||
else:
|
else:
|
||||||
self.songBookName = song.SongID
|
self.song_book_name = song.SongID
|
||||||
for verse in verses:
|
for verse in verses:
|
||||||
tag = VERSE_TAGS[verse.Type] + str(verse.Number) if verse.Type < len(VERSE_TAGS) else 'O'
|
tag = VERSE_TAGS[verse.Type] + str(verse.Number) if verse.Type < len(VERSE_TAGS) else 'O'
|
||||||
self.addVerse(verse.Text, tag)
|
self.add_verse(verse.Text, tag)
|
||||||
for order in verse_order:
|
for order in verse_order:
|
||||||
if order.Type < len(VERSE_TAGS):
|
if order.Type < len(VERSE_TAGS):
|
||||||
self.verseOrderList.append(VERSE_TAGS[order.Type] + str(order.Number))
|
self.verse_order_list.append(VERSE_TAGS[order.Type] + str(order.Number))
|
||||||
self.finish()
|
self.finish()
|
||||||
|
@ -107,7 +107,7 @@ class OpenLPSongImport(SongImport):
|
|||||||
|
|
||||||
# Check the file type
|
# Check the file type
|
||||||
if not self.import_source.endswith('.sqlite'):
|
if not self.import_source.endswith('.sqlite'):
|
||||||
self.logError(self.import_source,
|
self.log_error(self.import_source,
|
||||||
translate('SongsPlugin.OpenLPSongImport', 'Not a valid OpenLP 2.0 song database.'))
|
translate('SongsPlugin.OpenLPSongImport', 'Not a valid OpenLP 2.0 song database.'))
|
||||||
return
|
return
|
||||||
self.import_source = 'sqlite:///%s' % self.import_source
|
self.import_source = 'sqlite:///%s' % self.import_source
|
||||||
|
@ -71,7 +71,7 @@ class OooImport(SongImport):
|
|||||||
try:
|
try:
|
||||||
self.startOoo()
|
self.startOoo()
|
||||||
except NoConnectException as exc:
|
except NoConnectException as exc:
|
||||||
self.logError(
|
self.log_error(
|
||||||
self.import_source[0],
|
self.import_source[0],
|
||||||
translate('SongsPlugin.SongImport', 'Cannot access OpenOffice or LibreOffice'))
|
translate('SongsPlugin.SongImport', 'Cannot access OpenOffice or LibreOffice'))
|
||||||
log.error(exc)
|
log.error(exc)
|
||||||
@ -87,9 +87,9 @@ class OooImport(SongImport):
|
|||||||
self.processOooDocument()
|
self.processOooDocument()
|
||||||
self.closeOooFile()
|
self.closeOooFile()
|
||||||
else:
|
else:
|
||||||
self.logError(self.filepath, translate('SongsPlugin.SongImport', 'Unable to open file'))
|
self.log_error(self.filepath, translate('SongsPlugin.SongImport', 'Unable to open file'))
|
||||||
else:
|
else:
|
||||||
self.logError(self.filepath, translate('SongsPlugin.SongImport', 'File not found'))
|
self.log_error(self.filepath, translate('SongsPlugin.SongImport', 'File not found'))
|
||||||
self.closeOoo()
|
self.closeOoo()
|
||||||
|
|
||||||
def processOooDocument(self):
|
def processOooDocument(self):
|
||||||
@ -228,13 +228,13 @@ class OooImport(SongImport):
|
|||||||
self.processSongsText(text)
|
self.processSongsText(text)
|
||||||
|
|
||||||
def processSongsText(self, text):
|
def processSongsText(self, text):
|
||||||
songtexts = self.tidyText(text).split('\f')
|
songtexts = self.tidy_text(text).split('\f')
|
||||||
self.setDefaults()
|
self.set_defaults()
|
||||||
for songtext in songtexts:
|
for songtext in songtexts:
|
||||||
if songtext.strip():
|
if songtext.strip():
|
||||||
self.processSongText(songtext.strip())
|
self.process_song_text(songtext.strip())
|
||||||
if self.checkComplete():
|
if self.check_complete():
|
||||||
self.finish()
|
self.finish()
|
||||||
self.setDefaults()
|
self.set_defaults()
|
||||||
if self.checkComplete():
|
if self.check_complete():
|
||||||
self.finish()
|
self.finish()
|
||||||
|
@ -74,8 +74,8 @@ class OpenLyricsImport(SongImport):
|
|||||||
self.openLyrics.xml_to_song(xml)
|
self.openLyrics.xml_to_song(xml)
|
||||||
except etree.XMLSyntaxError:
|
except etree.XMLSyntaxError:
|
||||||
log.exception('XML syntax error in file %s' % file_path)
|
log.exception('XML syntax error in file %s' % file_path)
|
||||||
self.logError(file_path, SongStrings.XMLSyntaxError)
|
self.log_error(file_path, SongStrings.XMLSyntaxError)
|
||||||
except OpenLyricsError as exception:
|
except OpenLyricsError as exception:
|
||||||
log.exception('OpenLyricsException %d in file %s: %s'
|
log.exception('OpenLyricsException %d in file %s: %s'
|
||||||
% (exception.type, file_path, exception.log_message))
|
% (exception.type, file_path, exception.log_message))
|
||||||
self.logError(file_path, exception.display_message)
|
self.log_error(file_path, exception.display_message)
|
||||||
|
@ -122,21 +122,21 @@ class OpenSongImport(SongImport):
|
|||||||
"""
|
"""
|
||||||
Process the OpenSong file - pass in a file-like object, not a file path.
|
Process the OpenSong file - pass in a file-like object, not a file path.
|
||||||
"""
|
"""
|
||||||
self.setDefaults()
|
self.set_defaults()
|
||||||
try:
|
try:
|
||||||
tree = objectify.parse(file)
|
tree = objectify.parse(file)
|
||||||
except (Error, LxmlError):
|
except (Error, LxmlError):
|
||||||
self.logError(file.name, SongStrings.XMLSyntaxError)
|
self.log_error(file.name, SongStrings.XMLSyntaxError)
|
||||||
log.exception('Error parsing XML')
|
log.exception('Error parsing XML')
|
||||||
return
|
return
|
||||||
root = tree.getroot()
|
root = tree.getroot()
|
||||||
if root.tag != 'song':
|
if root.tag != 'song':
|
||||||
self.logError(file.name, str(
|
self.log_error(file.name, str(
|
||||||
translate('SongsPlugin.OpenSongImport', ('Invalid OpenSong song file. Missing song tag.'))))
|
translate('SongsPlugin.OpenSongImport', ('Invalid OpenSong song file. Missing song tag.'))))
|
||||||
return
|
return
|
||||||
fields = dir(root)
|
fields = dir(root)
|
||||||
decode = {
|
decode = {
|
||||||
'copyright': self.addCopyright,
|
'copyright': self.add_copyright,
|
||||||
'ccli': 'ccli_number',
|
'ccli': 'ccli_number',
|
||||||
'author': self.parse_author,
|
'author': self.parse_author,
|
||||||
'title': 'title',
|
'title': 'title',
|
||||||
@ -207,7 +207,7 @@ class OpenSongImport(SongImport):
|
|||||||
verses[verse_tag][verse_num][inst] = []
|
verses[verse_tag][verse_num][inst] = []
|
||||||
our_verse_order.append([verse_tag, verse_num, inst])
|
our_verse_order.append([verse_tag, verse_num, inst])
|
||||||
# Tidy text and remove the ____s from extended words
|
# Tidy text and remove the ____s from extended words
|
||||||
this_line = self.tidyText(this_line)
|
this_line = self.tidy_text(this_line)
|
||||||
this_line = this_line.replace('_', '')
|
this_line = this_line.replace('_', '')
|
||||||
this_line = this_line.replace('|', '\n')
|
this_line = this_line.replace('|', '\n')
|
||||||
this_line = this_line.strip()
|
this_line = this_line.strip()
|
||||||
@ -224,9 +224,9 @@ class OpenSongImport(SongImport):
|
|||||||
verse_joints[verse_def] = '%s\n[---]\n%s' % (verse_joints[verse_def], lines) \
|
verse_joints[verse_def] = '%s\n[---]\n%s' % (verse_joints[verse_def], lines) \
|
||||||
if verse_def in verse_joints else lines
|
if verse_def in verse_joints else lines
|
||||||
for verse_def, lines in verse_joints.items():
|
for verse_def, lines in verse_joints.items():
|
||||||
self.addVerse(lines, verse_def)
|
self.add_verse(lines, verse_def)
|
||||||
if not self.verses:
|
if not self.verses:
|
||||||
self.addVerse('')
|
self.add_verse('')
|
||||||
# figure out the presentation order, if present
|
# figure out the presentation order, if present
|
||||||
if 'presentation' in fields and root.presentation:
|
if 'presentation' in fields and root.presentation:
|
||||||
order = str(root.presentation)
|
order = str(root.presentation)
|
||||||
@ -246,9 +246,9 @@ class OpenSongImport(SongImport):
|
|||||||
verse_num = '1'
|
verse_num = '1'
|
||||||
verse_def = '%s%s' % (verse_tag, verse_num)
|
verse_def = '%s%s' % (verse_tag, verse_num)
|
||||||
if verse_num in verses.get(verse_tag, {}):
|
if verse_num in verses.get(verse_tag, {}):
|
||||||
self.verseOrderList.append(verse_def)
|
self.verse_order_list.append(verse_def)
|
||||||
else:
|
else:
|
||||||
log.info('Got order %s but not in verse tags, dropping'
|
log.info('Got order %s but not in verse tags, dropping'
|
||||||
'this item from presentation order', verse_def)
|
'this item from presentation order', verse_def)
|
||||||
if not self.finish():
|
if not self.finish():
|
||||||
self.logError(file.name)
|
self.log_error(file.name)
|
||||||
|
@ -73,7 +73,7 @@ class PowerSongImport(SongImport):
|
|||||||
* .song
|
* .song
|
||||||
"""
|
"""
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def isValidSource(import_source):
|
def is_valid_source(import_source):
|
||||||
"""
|
"""
|
||||||
Checks if source is a PowerSong 1.0 folder:
|
Checks if source is a PowerSong 1.0 folder:
|
||||||
* is a directory
|
* is a directory
|
||||||
@ -101,14 +101,14 @@ class PowerSongImport(SongImport):
|
|||||||
else:
|
else:
|
||||||
self.import_source = ''
|
self.import_source = ''
|
||||||
if not self.import_source or not isinstance(self.import_source, list):
|
if not self.import_source or not isinstance(self.import_source, list):
|
||||||
self.logError(translate('SongsPlugin.PowerSongImport', 'No songs to import.'),
|
self.log_error(translate('SongsPlugin.PowerSongImport', 'No songs to import.'),
|
||||||
translate('SongsPlugin.PowerSongImport', 'No %s files found.') % PS_string)
|
translate('SongsPlugin.PowerSongImport', 'No %s files found.') % PS_string)
|
||||||
return
|
return
|
||||||
self.import_wizard.progress_bar.setMaximum(len(self.import_source))
|
self.import_wizard.progress_bar.setMaximum(len(self.import_source))
|
||||||
for file in self.import_source:
|
for file in self.import_source:
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
return
|
return
|
||||||
self.setDefaults()
|
self.set_defaults()
|
||||||
parse_error = False
|
parse_error = False
|
||||||
with open(file, 'rb') as song_data:
|
with open(file, 'rb') as song_data:
|
||||||
while True:
|
while True:
|
||||||
@ -119,7 +119,7 @@ class PowerSongImport(SongImport):
|
|||||||
field = self._readString(song_data)
|
field = self._readString(song_data)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
parse_error = True
|
parse_error = True
|
||||||
self.logError(os.path.basename(file), str(
|
self.log_error(os.path.basename(file), str(
|
||||||
translate('SongsPlugin.PowerSongImport', 'Invalid %s file. Unexpected byte value.')) %
|
translate('SongsPlugin.PowerSongImport', 'Invalid %s file. Unexpected byte value.')) %
|
||||||
PS_string)
|
PS_string)
|
||||||
break
|
break
|
||||||
@ -132,27 +132,27 @@ class PowerSongImport(SongImport):
|
|||||||
found_copyright = True
|
found_copyright = True
|
||||||
self._parseCopyrightCCLI(field)
|
self._parseCopyrightCCLI(field)
|
||||||
elif label == 'PART':
|
elif label == 'PART':
|
||||||
self.addVerse(field)
|
self.add_verse(field)
|
||||||
if parse_error:
|
if parse_error:
|
||||||
continue
|
continue
|
||||||
# Check that file had TITLE field
|
# Check that file had TITLE field
|
||||||
if not self.title:
|
if not self.title:
|
||||||
self.logError(os.path.basename(file), str(
|
self.log_error(os.path.basename(file), str(
|
||||||
translate('SongsPlugin.PowerSongImport', 'Invalid %s file. Missing "TITLE" header.')) % PS_string)
|
translate('SongsPlugin.PowerSongImport', 'Invalid %s file. Missing "TITLE" header.')) % PS_string)
|
||||||
continue
|
continue
|
||||||
# Check that file had COPYRIGHTLINE label
|
# Check that file had COPYRIGHTLINE label
|
||||||
if not found_copyright:
|
if not found_copyright:
|
||||||
self.logError(self.title, str(
|
self.log_error(self.title, str(
|
||||||
translate('SongsPlugin.PowerSongImport', 'Invalid %s file. Missing "COPYRIGHTLINE" header.')) %
|
translate('SongsPlugin.PowerSongImport', 'Invalid %s file. Missing "COPYRIGHTLINE" header.')) %
|
||||||
PS_string)
|
PS_string)
|
||||||
continue
|
continue
|
||||||
# Check that file had at least one verse
|
# Check that file had at least one verse
|
||||||
if not self.verses:
|
if not self.verses:
|
||||||
self.logError(self.title, str(
|
self.log_error(self.title, str(
|
||||||
translate('SongsPlugin.PowerSongImport', 'Verses not found. Missing "PART" header.')))
|
translate('SongsPlugin.PowerSongImport', 'Verses not found. Missing "PART" header.')))
|
||||||
continue
|
continue
|
||||||
if not self.finish():
|
if not self.finish():
|
||||||
self.logError(self.title)
|
self.log_error(self.title)
|
||||||
|
|
||||||
def _readString(self, file_object):
|
def _readString(self, file_object):
|
||||||
"""
|
"""
|
||||||
@ -211,8 +211,8 @@ class PowerSongImport(SongImport):
|
|||||||
copyright = ccli_no
|
copyright = ccli_no
|
||||||
ccli_no = ''
|
ccli_no = ''
|
||||||
if copyright:
|
if copyright:
|
||||||
self.addCopyright(copyright.rstrip('\n').replace('\n', ' '))
|
self.add_copyright(copyright.rstrip('\n').replace('\n', ' '))
|
||||||
if ccli_no:
|
if ccli_no:
|
||||||
ccli_no = ccli_no.strip(' :')
|
ccli_no = ccli_no.strip(' :')
|
||||||
if ccli_no.isdigit():
|
if ccli_no.isdigit():
|
||||||
self.ccliNumber = ccli_no
|
self.ccli_number = ccli_no
|
||||||
|
@ -108,7 +108,7 @@ class SofImport(OooImport):
|
|||||||
except RuntimeException as exc:
|
except RuntimeException as exc:
|
||||||
log.exception('Error processing file: %s', exc)
|
log.exception('Error processing file: %s', exc)
|
||||||
if not self.finish():
|
if not self.finish():
|
||||||
self.logError(self.filepath)
|
self.log_error(self.filepath)
|
||||||
|
|
||||||
def processParagraph(self, paragraph):
|
def processParagraph(self, paragraph):
|
||||||
"""
|
"""
|
||||||
@ -173,17 +173,17 @@ class SofImport(OooImport):
|
|||||||
self.skipToCloseBracket = True
|
self.skipToCloseBracket = True
|
||||||
return
|
return
|
||||||
if text.startswith('Copyright'):
|
if text.startswith('Copyright'):
|
||||||
self.addCopyright(text)
|
self.add_copyright(text)
|
||||||
return
|
return
|
||||||
if text == '(Repeat)':
|
if text == '(Repeat)':
|
||||||
self.finishVerse()
|
self.finishVerse()
|
||||||
self.repeatVerse()
|
self.repeat_verse()
|
||||||
return
|
return
|
||||||
if self.title == '':
|
if self.title == '':
|
||||||
if self.copyright == '':
|
if self.copyright == '':
|
||||||
self.addSofAuthor(text)
|
self.addSofAuthor(text)
|
||||||
else:
|
else:
|
||||||
self.addCopyright(text)
|
self.add_copyright(text)
|
||||||
return
|
return
|
||||||
self.addVerseLine(text)
|
self.addVerseLine(text)
|
||||||
|
|
||||||
@ -195,12 +195,12 @@ class SofImport(OooImport):
|
|||||||
into line
|
into line
|
||||||
"""
|
"""
|
||||||
text = textportion.getString()
|
text = textportion.getString()
|
||||||
text = self.tidyText(text)
|
text = self.tidy_text(text)
|
||||||
if text.strip() == '':
|
if text.strip() == '':
|
||||||
return text
|
return text
|
||||||
if textportion.CharWeight == BOLD:
|
if textportion.CharWeight == BOLD:
|
||||||
boldtext = text.strip()
|
boldtext = text.strip()
|
||||||
if boldtext.isdigit() and self.songNumber == '':
|
if boldtext.isdigit() and self.song_number == '':
|
||||||
self.addSongNumber(boldtext)
|
self.addSongNumber(boldtext)
|
||||||
return ''
|
return ''
|
||||||
text = self.uncapText(text)
|
text = self.uncapText(text)
|
||||||
@ -219,11 +219,11 @@ class SofImport(OooImport):
|
|||||||
"""
|
"""
|
||||||
if self.song:
|
if self.song:
|
||||||
self.finishVerse()
|
self.finishVerse()
|
||||||
if not self.checkComplete():
|
if not self.check_complete():
|
||||||
return
|
return
|
||||||
self.finish()
|
self.finish()
|
||||||
self.song = True
|
self.song = True
|
||||||
self.setDefaults()
|
self.set_defaults()
|
||||||
self.skipToCloseBracket = False
|
self.skipToCloseBracket = False
|
||||||
self.isChorus = False
|
self.isChorus = False
|
||||||
self.italics = False
|
self.italics = False
|
||||||
@ -234,7 +234,7 @@ class SofImport(OooImport):
|
|||||||
Add a song number, store as alternate title. Also use the song
|
Add a song number, store as alternate title. Also use the song
|
||||||
number to work out which songbook we're in
|
number to work out which songbook we're in
|
||||||
"""
|
"""
|
||||||
self.songNumber = song_no
|
self.song_number = song_no
|
||||||
self.alternateTitle = song_no + '.'
|
self.alternateTitle = song_no + '.'
|
||||||
self.songBook_pub = 'Kingsway Publications'
|
self.songBook_pub = 'Kingsway Publications'
|
||||||
if int(song_no) <= 640:
|
if int(song_no) <= 640:
|
||||||
@ -299,7 +299,7 @@ class SofImport(OooImport):
|
|||||||
splitat = None
|
splitat = None
|
||||||
else:
|
else:
|
||||||
versetag = 'V'
|
versetag = 'V'
|
||||||
splitat = self.verseSplits(self.songNumber)
|
splitat = self.verseSplits(self.song_number)
|
||||||
if splitat:
|
if splitat:
|
||||||
ln = 0
|
ln = 0
|
||||||
verse = ''
|
verse = ''
|
||||||
@ -322,9 +322,9 @@ class SofImport(OooImport):
|
|||||||
self.isChorus = False
|
self.isChorus = False
|
||||||
|
|
||||||
def addSofVerse(self, lyrics, tag):
|
def addSofVerse(self, lyrics, tag):
|
||||||
self.addVerse(lyrics, tag)
|
self.add_verse(lyrics, tag)
|
||||||
if not self.isChorus and 'C1' in self.verseOrderListGenerated:
|
if not self.isChorus and 'C1' in self.verse_order_list_generated:
|
||||||
self.verseOrderListGenerated.append('C1')
|
self.verse_order_list_generated.append('C1')
|
||||||
self.verseOrderListGenerated_useful = True
|
self.verseOrderListGenerated_useful = True
|
||||||
|
|
||||||
def uncapText(self, text):
|
def uncapText(self, text):
|
||||||
|
@ -109,7 +109,7 @@ class SongBeamerImport(SongImport):
|
|||||||
# TODO: check that it is a valid SongBeamer file
|
# TODO: check that it is a valid SongBeamer file
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
return
|
return
|
||||||
self.setDefaults()
|
self.set_defaults()
|
||||||
self.currentVerse = ''
|
self.currentVerse = ''
|
||||||
self.currentVerseType = VerseType.tags[VerseType.Verse]
|
self.currentVerseType = VerseType.tags[VerseType.Verse]
|
||||||
read_verses = False
|
read_verses = False
|
||||||
@ -134,7 +134,7 @@ class SongBeamerImport(SongImport):
|
|||||||
elif line.startswith('---'):
|
elif line.startswith('---'):
|
||||||
if self.currentVerse:
|
if self.currentVerse:
|
||||||
self.replaceHtmlTags()
|
self.replaceHtmlTags()
|
||||||
self.addVerse(self.currentVerse, self.currentVerseType)
|
self.add_verse(self.currentVerse, self.currentVerseType)
|
||||||
self.currentVerse = ''
|
self.currentVerse = ''
|
||||||
self.currentVerseType = VerseType.tags[VerseType.Verse]
|
self.currentVerseType = VerseType.tags[VerseType.Verse]
|
||||||
read_verses = True
|
read_verses = True
|
||||||
@ -148,9 +148,9 @@ class SongBeamerImport(SongImport):
|
|||||||
self.currentVerse += line + '\n'
|
self.currentVerse += line + '\n'
|
||||||
if self.currentVerse:
|
if self.currentVerse:
|
||||||
self.replaceHtmlTags()
|
self.replaceHtmlTags()
|
||||||
self.addVerse(self.currentVerse, self.currentVerseType)
|
self.add_verse(self.currentVerse, self.currentVerseType)
|
||||||
if not self.finish():
|
if not self.finish():
|
||||||
self.logError(import_file)
|
self.log_error(import_file)
|
||||||
|
|
||||||
def replaceHtmlTags(self):
|
def replaceHtmlTags(self):
|
||||||
"""
|
"""
|
||||||
@ -174,7 +174,7 @@ class SongBeamerImport(SongImport):
|
|||||||
if not tag_val[0] or not tag_val[1]:
|
if not tag_val[0] or not tag_val[1]:
|
||||||
return
|
return
|
||||||
if tag_val[0] == '#(c)':
|
if tag_val[0] == '#(c)':
|
||||||
self.addCopyright(tag_val[1])
|
self.add_copyright(tag_val[1])
|
||||||
elif tag_val[0] == '#AddCopyrightInfo':
|
elif tag_val[0] == '#AddCopyrightInfo':
|
||||||
pass
|
pass
|
||||||
elif tag_val[0] == '#Author':
|
elif tag_val[0] == '#Author':
|
||||||
@ -186,7 +186,7 @@ class SongBeamerImport(SongImport):
|
|||||||
elif tag_val[0] == '#Categories':
|
elif tag_val[0] == '#Categories':
|
||||||
self.topics = tag_val[1].split(',')
|
self.topics = tag_val[1].split(',')
|
||||||
elif tag_val[0] == '#CCLI':
|
elif tag_val[0] == '#CCLI':
|
||||||
self.ccliNumber = tag_val[1]
|
self.ccli_number = tag_val[1]
|
||||||
elif tag_val[0] == '#Chords':
|
elif tag_val[0] == '#Chords':
|
||||||
pass
|
pass
|
||||||
elif tag_val[0] == '#ChurchSongID':
|
elif tag_val[0] == '#ChurchSongID':
|
||||||
@ -233,10 +233,10 @@ class SongBeamerImport(SongImport):
|
|||||||
song_book_pub = tag_val[1]
|
song_book_pub = tag_val[1]
|
||||||
elif tag_val[0] == '#Songbook' or tag_val[0] == '#SongBook':
|
elif tag_val[0] == '#Songbook' or tag_val[0] == '#SongBook':
|
||||||
book_data = tag_val[1].split('/')
|
book_data = tag_val[1].split('/')
|
||||||
self.songBookName = book_data[0].strip()
|
self.song_book_name = book_data[0].strip()
|
||||||
if len(book_data) == 2:
|
if len(book_data) == 2:
|
||||||
number = book_data[1].strip()
|
number = book_data[1].strip()
|
||||||
self.songNumber = number if number.isdigit() else ''
|
self.song_number = number if number.isdigit() else ''
|
||||||
elif tag_val[0] == '#Speed':
|
elif tag_val[0] == '#Speed':
|
||||||
pass
|
pass
|
||||||
elif tag_val[0] == 'Tempo':
|
elif tag_val[0] == 'Tempo':
|
||||||
|
@ -53,7 +53,7 @@ class SongImport(QtCore.QObject):
|
|||||||
as necessary
|
as necessary
|
||||||
"""
|
"""
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def isValidSource(import_source):
|
def is_valid_source(import_source):
|
||||||
"""
|
"""
|
||||||
Override this method to validate the source prior to import.
|
Override this method to validate the source prior to import.
|
||||||
"""
|
"""
|
||||||
@ -63,10 +63,8 @@ class SongImport(QtCore.QObject):
|
|||||||
"""
|
"""
|
||||||
Initialise and create defaults for properties
|
Initialise and create defaults for properties
|
||||||
|
|
||||||
``manager``
|
:param manager: An instance of a SongManager, through which all database access is performed.
|
||||||
An instance of a SongManager, through which all database access is
|
:param kwargs:
|
||||||
performed.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
QtCore.QObject.__init__(self)
|
QtCore.QObject.__init__(self)
|
||||||
@ -82,56 +80,51 @@ class SongImport(QtCore.QObject):
|
|||||||
self.import_wizard = None
|
self.import_wizard = None
|
||||||
self.song = None
|
self.song = None
|
||||||
self.stop_import_flag = False
|
self.stop_import_flag = False
|
||||||
self.setDefaults()
|
self.set_defaults()
|
||||||
Registry().register_function('openlp_stop_wizard', self.stop_import)
|
Registry().register_function('openlp_stop_wizard', self.stop_import)
|
||||||
|
|
||||||
def setDefaults(self):
|
def set_defaults(self):
|
||||||
"""
|
"""
|
||||||
Create defaults for properties - call this before each song
|
Create defaults for properties - call this before each song
|
||||||
if importing many songs at once to ensure a clean beginning
|
if importing many songs at once to ensure a clean beginning
|
||||||
"""
|
"""
|
||||||
self.title = ''
|
self.title = ''
|
||||||
self.songNumber = ''
|
self.song_number = ''
|
||||||
self.alternate_title = ''
|
self.alternate_title = ''
|
||||||
self.copyright = ''
|
self.copyright = ''
|
||||||
self.comments = ''
|
self.comments = ''
|
||||||
self.themeName = ''
|
self.theme_name = ''
|
||||||
self.ccliNumber = ''
|
self.ccli_number = ''
|
||||||
self.authors = []
|
self.authors = []
|
||||||
self.topics = []
|
self.topics = []
|
||||||
self.mediaFiles = []
|
self.media_files = []
|
||||||
self.songBookName = ''
|
self.song_book_name = ''
|
||||||
self.songBookPub = ''
|
self.song_book_pub = ''
|
||||||
self.verseOrderListGeneratedUseful = False
|
self.verse_order_list_generated_useful = False
|
||||||
self.verseOrderListGenerated = []
|
self.verse_order_list_generated = []
|
||||||
self.verseOrderList = []
|
self.verse_order_list = []
|
||||||
self.verses = []
|
self.verses = []
|
||||||
self.verseCounts = {}
|
self.verse_counts = {}
|
||||||
self.copyrightString = translate('SongsPlugin.SongImport', 'copyright')
|
self.copyright_string = translate('SongsPlugin.SongImport', 'copyright')
|
||||||
|
|
||||||
def logError(self, filepath, reason=SongStrings.SongIncomplete):
|
def log_error(self, file_path, reason=SongStrings.SongIncomplete):
|
||||||
"""
|
"""
|
||||||
This should be called, when a song could not be imported.
|
This should be called, when a song could not be imported.
|
||||||
|
|
||||||
``filepath``
|
:param file_path: This should be the file path if ``self.import_source`` is a list with different files. If it
|
||||||
This should be the file path if ``self.import_source`` is a list
|
is not a list, but a single file (for instance a database), then this should be the song's title.
|
||||||
with different files. If it is not a list, but a single file (for
|
:param reason: The reason why the import failed. The string should be as informative as possible.
|
||||||
instance a database), then this should be the song's title.
|
|
||||||
|
|
||||||
``reason``
|
|
||||||
The reason why the import failed. The string should be as
|
|
||||||
informative as possible.
|
|
||||||
"""
|
"""
|
||||||
self.setDefaults()
|
self.set_defaults()
|
||||||
if self.import_wizard is None:
|
if self.import_wizard is None:
|
||||||
return
|
return
|
||||||
if self.import_wizard.error_report_text_edit.isHidden():
|
if self.import_wizard.error_report_text_edit.isHidden():
|
||||||
self.import_wizard.error_report_text_edit.setText(translate('SongsPlugin.SongImport',
|
self.import_wizard.error_report_text_edit.setText(
|
||||||
'The following songs could not be imported:'))
|
translate('SongsPlugin.SongImport', 'The following songs could not be imported:'))
|
||||||
self.import_wizard.error_report_text_edit.setVisible(True)
|
self.import_wizard.error_report_text_edit.setVisible(True)
|
||||||
self.import_wizard.error_copy_to_button.setVisible(True)
|
self.import_wizard.error_copy_to_button.setVisible(True)
|
||||||
self.import_wizard.error_save_to_button.setVisible(True)
|
self.import_wizard.error_save_to_button.setVisible(True)
|
||||||
self.import_wizard.error_report_text_edit.append('- %s (%s)' % (filepath, reason))
|
self.import_wizard.error_report_text_edit.append('- %s (%s)' % (file_path, reason))
|
||||||
|
|
||||||
def stop_import(self):
|
def stop_import(self):
|
||||||
"""
|
"""
|
||||||
@ -143,10 +136,9 @@ class SongImport(QtCore.QObject):
|
|||||||
def register(self, import_wizard):
|
def register(self, import_wizard):
|
||||||
self.import_wizard = import_wizard
|
self.import_wizard = import_wizard
|
||||||
|
|
||||||
def tidyText(self, text):
|
def tidy_text(self, text):
|
||||||
"""
|
"""
|
||||||
Get rid of some dodgy unicode and formatting characters we're not
|
Get rid of some dodgy unicode and formatting characters we're not interested in. Some can be converted to ascii.
|
||||||
interested in. Some can be converted to ascii.
|
|
||||||
"""
|
"""
|
||||||
text = text.replace('\u2018', '\'')
|
text = text.replace('\u2018', '\'')
|
||||||
text = text.replace('\u2019', '\'')
|
text = text.replace('\u2019', '\'')
|
||||||
@ -161,21 +153,21 @@ class SongImport(QtCore.QObject):
|
|||||||
text = re.sub(r' ?(\n{5}|\f)+ ?', '\f', text)
|
text = re.sub(r' ?(\n{5}|\f)+ ?', '\f', text)
|
||||||
return text
|
return text
|
||||||
|
|
||||||
def processSongText(self, text):
|
def process_song_text(self, text):
|
||||||
verse_texts = text.split('\n\n')
|
verse_texts = text.split('\n\n')
|
||||||
for verse_text in verse_texts:
|
for verse_text in verse_texts:
|
||||||
if verse_text.strip() != '':
|
if verse_text.strip() != '':
|
||||||
self.processVerseText(verse_text.strip())
|
self.process_verse_text(verse_text.strip())
|
||||||
|
|
||||||
def processVerseText(self, text):
|
def process_verse_text(self, text):
|
||||||
lines = text.split('\n')
|
lines = text.split('\n')
|
||||||
if text.lower().find(self.copyrightString) >= 0 or text.find(str(SongStrings.CopyrightSymbol)) >= 0:
|
if text.lower().find(self.copyright_string) >= 0 or text.find(str(SongStrings.CopyrightSymbol)) >= 0:
|
||||||
copyright_found = False
|
copyright_found = False
|
||||||
for line in lines:
|
for line in lines:
|
||||||
if (copyright_found or line.lower().find(self.copyrightString) >= 0 or
|
if (copyright_found or line.lower().find(self.copyright_string) >= 0 or
|
||||||
line.find(str(SongStrings.CopyrightSymbol)) >= 0):
|
line.find(str(SongStrings.CopyrightSymbol)) >= 0):
|
||||||
copyright_found = True
|
copyright_found = True
|
||||||
self.addCopyright(line)
|
self.add_copyright(line)
|
||||||
else:
|
else:
|
||||||
self.parse_author(line)
|
self.parse_author(line)
|
||||||
return
|
return
|
||||||
@ -184,9 +176,9 @@ class SongImport(QtCore.QObject):
|
|||||||
return
|
return
|
||||||
if not self.title:
|
if not self.title:
|
||||||
self.title = lines[0]
|
self.title = lines[0]
|
||||||
self.addVerse(text)
|
self.add_verse(text)
|
||||||
|
|
||||||
def addCopyright(self, copyright):
|
def add_copyright(self, copyright):
|
||||||
"""
|
"""
|
||||||
Build the copyright field
|
Build the copyright field
|
||||||
"""
|
"""
|
||||||
@ -211,9 +203,9 @@ class SongImport(QtCore.QObject):
|
|||||||
if author2.endswith('.'):
|
if author2.endswith('.'):
|
||||||
author2 = author2[:-1]
|
author2 = author2[:-1]
|
||||||
if author2:
|
if author2:
|
||||||
self.addAuthor(author2)
|
self.add_author(author2)
|
||||||
|
|
||||||
def addAuthor(self, author):
|
def add_author(self, author):
|
||||||
"""
|
"""
|
||||||
Add an author to the list
|
Add an author to the list
|
||||||
"""
|
"""
|
||||||
@ -221,15 +213,15 @@ class SongImport(QtCore.QObject):
|
|||||||
return
|
return
|
||||||
self.authors.append(author)
|
self.authors.append(author)
|
||||||
|
|
||||||
def addMediaFile(self, filename, weight=0):
|
def add_media_file(self, filename, weight=0):
|
||||||
"""
|
"""
|
||||||
Add a media file to the list
|
Add a media file to the list
|
||||||
"""
|
"""
|
||||||
if filename in [x[0] for x in self.mediaFiles]:
|
if filename in [x[0] for x in self.media_files]:
|
||||||
return
|
return
|
||||||
self.mediaFiles.append((filename, weight))
|
self.media_files.append((filename, weight))
|
||||||
|
|
||||||
def addVerse(self, verse_text, verse_def='v', lang=None):
|
def add_verse(self, verse_text, verse_def='v', lang=None):
|
||||||
"""
|
"""
|
||||||
Add a verse. This is the whole verse, lines split by \\n. It will also
|
Add a verse. This is the whole verse, lines split by \\n. It will also
|
||||||
attempt to detect duplicates. In this case it will just add to the verse
|
attempt to detect duplicates. In this case it will just add to the verse
|
||||||
@ -248,32 +240,32 @@ class SongImport(QtCore.QObject):
|
|||||||
"""
|
"""
|
||||||
for (old_verse_def, old_verse, old_lang) in self.verses:
|
for (old_verse_def, old_verse, old_lang) in self.verses:
|
||||||
if old_verse.strip() == verse_text.strip():
|
if old_verse.strip() == verse_text.strip():
|
||||||
self.verseOrderListGenerated.append(old_verse_def)
|
self.verse_order_list_generated.append(old_verse_def)
|
||||||
self.verseOrderListGeneratedUseful = True
|
self.verse_order_list_generated_useful = True
|
||||||
return
|
return
|
||||||
if verse_def[0] in self.verseCounts:
|
if verse_def[0] in self.verse_counts:
|
||||||
self.verseCounts[verse_def[0]] += 1
|
self.verse_counts[verse_def[0]] += 1
|
||||||
else:
|
else:
|
||||||
self.verseCounts[verse_def[0]] = 1
|
self.verse_counts[verse_def[0]] = 1
|
||||||
if len(verse_def) == 1:
|
if len(verse_def) == 1:
|
||||||
verse_def += str(self.verseCounts[verse_def[0]])
|
verse_def += str(self.verse_counts[verse_def[0]])
|
||||||
elif int(verse_def[1:]) > self.verseCounts[verse_def[0]]:
|
elif int(verse_def[1:]) > self.verse_counts[verse_def[0]]:
|
||||||
self.verseCounts[verse_def[0]] = int(verse_def[1:])
|
self.verse_counts[verse_def[0]] = int(verse_def[1:])
|
||||||
self.verses.append([verse_def, verse_text.rstrip(), lang])
|
self.verses.append([verse_def, verse_text.rstrip(), lang])
|
||||||
# A verse_def refers to all verses with that name, adding it once adds every instance, so do not add if already
|
# A verse_def refers to all verses with that name, adding it once adds every instance, so do not add if already
|
||||||
# used.
|
# used.
|
||||||
if verse_def not in self.verseOrderListGenerated:
|
if verse_def not in self.verse_order_list_generated:
|
||||||
self.verseOrderListGenerated.append(verse_def)
|
self.verse_order_list_generated.append(verse_def)
|
||||||
|
|
||||||
def repeatVerse(self):
|
def repeat_verse(self):
|
||||||
"""
|
"""
|
||||||
Repeat the previous verse in the verse order
|
Repeat the previous verse in the verse order
|
||||||
"""
|
"""
|
||||||
if self.verseOrderListGenerated:
|
if self.verse_order_list_generated:
|
||||||
self.verseOrderListGenerated.append(self.verseOrderListGenerated[-1])
|
self.verse_order_list_generated.append(self.verse_order_list_generated[-1])
|
||||||
self.verseOrderListGeneratedUseful = True
|
self.verse_order_list_generated_useful = True
|
||||||
|
|
||||||
def checkComplete(self):
|
def check_complete(self):
|
||||||
"""
|
"""
|
||||||
Check the mandatory fields are entered (i.e. title and a verse)
|
Check the mandatory fields are entered (i.e. title and a verse)
|
||||||
Author not checked here, if no author then "Author unknown" is
|
Author not checked here, if no author then "Author unknown" is
|
||||||
@ -288,8 +280,8 @@ class SongImport(QtCore.QObject):
|
|||||||
"""
|
"""
|
||||||
All fields have been set to this song. Write the song to disk.
|
All fields have been set to this song. Write the song to disk.
|
||||||
"""
|
"""
|
||||||
if not self.checkComplete():
|
if not self.check_complete():
|
||||||
self.setDefaults()
|
self.set_defaults()
|
||||||
return False
|
return False
|
||||||
log.info('committing song %s to database', self.title)
|
log.info('committing song %s to database', self.title)
|
||||||
song = Song()
|
song = Song()
|
||||||
@ -301,7 +293,7 @@ class SongImport(QtCore.QObject):
|
|||||||
song.search_title = ''
|
song.search_title = ''
|
||||||
song.search_lyrics = ''
|
song.search_lyrics = ''
|
||||||
song.verse_order = ''
|
song.verse_order = ''
|
||||||
song.song_number = self.songNumber
|
song.song_number = self.song_number
|
||||||
verses_changed_to_other = {}
|
verses_changed_to_other = {}
|
||||||
sxml = SongXML()
|
sxml = SongXML()
|
||||||
other_count = 1
|
other_count = 1
|
||||||
@ -317,14 +309,14 @@ class SongImport(QtCore.QObject):
|
|||||||
verse_def = new_verse_def
|
verse_def = new_verse_def
|
||||||
sxml.add_verse_to_lyrics(verse_tag, verse_def[1:], verse_text, lang)
|
sxml.add_verse_to_lyrics(verse_tag, verse_def[1:], verse_text, lang)
|
||||||
song.lyrics = str(sxml.extract_xml(), 'utf-8')
|
song.lyrics = str(sxml.extract_xml(), 'utf-8')
|
||||||
if not self.verseOrderList and self.verseOrderListGeneratedUseful:
|
if not self.verse_order_list and self.verse_order_list_generated_useful:
|
||||||
self.verseOrderList = self.verseOrderListGenerated
|
self.verse_order_list = self.verse_order_list_generated
|
||||||
self.verseOrderList = [verses_changed_to_other.get(v, v) for v in self.verseOrderList]
|
self.verse_order_list = [verses_changed_to_other.get(v, v) for v in self.verse_order_list]
|
||||||
song.verse_order = ' '.join(self.verseOrderList)
|
song.verse_order = ' '.join(self.verse_order_list)
|
||||||
song.copyright = self.copyright
|
song.copyright = self.copyright
|
||||||
song.comments = self.comments
|
song.comments = self.comments
|
||||||
song.theme_name = self.themeName
|
song.theme_name = self.theme_name
|
||||||
song.ccli_number = self.ccliNumber
|
song.ccli_number = self.ccli_number
|
||||||
for authortext in self.authors:
|
for authortext in self.authors:
|
||||||
author = self.manager.get_object_filtered(Author, Author.display_name == authortext)
|
author = self.manager.get_object_filtered(Author, Author.display_name == authortext)
|
||||||
if not author:
|
if not author:
|
||||||
@ -332,10 +324,10 @@ class SongImport(QtCore.QObject):
|
|||||||
last_name=authortext.split(' ')[-1],
|
last_name=authortext.split(' ')[-1],
|
||||||
first_name=' '.join(authortext.split(' ')[:-1]))
|
first_name=' '.join(authortext.split(' ')[:-1]))
|
||||||
song.authors.append(author)
|
song.authors.append(author)
|
||||||
if self.songBookName:
|
if self.song_book_name:
|
||||||
song_book = self.manager.get_object_filtered(Book, Book.name == self.songBookName)
|
song_book = self.manager.get_object_filtered(Book, Book.name == self.song_book_name)
|
||||||
if song_book is None:
|
if song_book is None:
|
||||||
song_book = Book.populate(name=self.songBookName, publisher=self.songBookPub)
|
song_book = Book.populate(name=self.song_book_name, publisher=self.song_book_pub)
|
||||||
song.book = song_book
|
song.book = song_book
|
||||||
for topictext in self.topics:
|
for topictext in self.topics:
|
||||||
if not topictext:
|
if not topictext:
|
||||||
@ -350,17 +342,17 @@ class SongImport(QtCore.QObject):
|
|||||||
self.manager.save_object(song)
|
self.manager.save_object(song)
|
||||||
# Now loop through the media files, copy them to the correct location,
|
# Now loop through the media files, copy them to the correct location,
|
||||||
# and save the song again.
|
# and save the song again.
|
||||||
for filename, weight in self.mediaFiles:
|
for filename, weight in self.media_files:
|
||||||
media_file = self.manager.get_object_filtered(MediaFile, MediaFile.file_name == filename)
|
media_file = self.manager.get_object_filtered(MediaFile, MediaFile.file_name == filename)
|
||||||
if not media_file:
|
if not media_file:
|
||||||
if os.path.dirname(filename):
|
if os.path.dirname(filename):
|
||||||
filename = self.copyMediaFile(song.id, filename)
|
filename = self.copy_media_file(song.id, filename)
|
||||||
song.media_files.append(MediaFile.populate(file_name=filename, weight=weight))
|
song.media_files.append(MediaFile.populate(file_name=filename, weight=weight))
|
||||||
self.manager.save_object(song)
|
self.manager.save_object(song)
|
||||||
self.setDefaults()
|
self.set_defaults()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def copyMediaFile(self, song_id, filename):
|
def copy_media_file(self, song_id, filename):
|
||||||
"""
|
"""
|
||||||
This method copies the media file to the correct location and returns
|
This method copies the media file to the correct location and returns
|
||||||
the new file location.
|
the new file location.
|
||||||
|
@ -100,7 +100,7 @@ class SongProImport(SongImport):
|
|||||||
Process a section of the song, i.e. title, verse etc.
|
Process a section of the song, i.e. title, verse etc.
|
||||||
"""
|
"""
|
||||||
if tag == 'T':
|
if tag == 'T':
|
||||||
self.setDefaults()
|
self.set_defaults()
|
||||||
if text:
|
if text:
|
||||||
self.title = text
|
self.title = text
|
||||||
return
|
return
|
||||||
@ -118,29 +118,29 @@ class SongProImport(SongImport):
|
|||||||
if tag == 'A':
|
if tag == 'A':
|
||||||
self.parse_author(text)
|
self.parse_author(text)
|
||||||
elif tag in ['B', 'C']:
|
elif tag in ['B', 'C']:
|
||||||
self.addVerse(text, tag)
|
self.add_verse(text, tag)
|
||||||
elif tag == 'D':
|
elif tag == 'D':
|
||||||
self.addVerse(text, 'E')
|
self.add_verse(text, 'E')
|
||||||
elif tag == 'G':
|
elif tag == 'G':
|
||||||
self.topics.append(text)
|
self.topics.append(text)
|
||||||
elif tag == 'M':
|
elif tag == 'M':
|
||||||
matches = re.findall(r'\d+', text)
|
matches = re.findall(r'\d+', text)
|
||||||
if matches:
|
if matches:
|
||||||
self.songNumber = matches[-1]
|
self.song_number = matches[-1]
|
||||||
self.songBookName = text[:text.rfind(self.songNumber)]
|
self.song_book_name = text[:text.rfind(self.song_number)]
|
||||||
elif tag == 'N':
|
elif tag == 'N':
|
||||||
self.comments = text
|
self.comments = text
|
||||||
elif tag == 'O':
|
elif tag == 'O':
|
||||||
for char in text:
|
for char in text:
|
||||||
if char == 'C':
|
if char == 'C':
|
||||||
self.verseOrderList.append('C1')
|
self.verse_order_list.append('C1')
|
||||||
elif char == 'B':
|
elif char == 'B':
|
||||||
self.verseOrderList.append('B1')
|
self.verse_order_list.append('B1')
|
||||||
elif char == 'D':
|
elif char == 'D':
|
||||||
self.verseOrderList.append('E1')
|
self.verse_order_list.append('E1')
|
||||||
elif '1' <= char <= '7':
|
elif '1' <= char <= '7':
|
||||||
self.verseOrderList.append('V' + char)
|
self.verse_order_list.append('V' + char)
|
||||||
elif tag == 'R':
|
elif tag == 'R':
|
||||||
self.addCopyright(text)
|
self.add_copyright(text)
|
||||||
elif '1' <= tag <= '7':
|
elif '1' <= tag <= '7':
|
||||||
self.addVerse(text, 'V' + tag[1:])
|
self.add_verse(text, 'V' + tag[1:])
|
||||||
|
@ -145,15 +145,15 @@ class SongShowPlusImport(SongImport):
|
|||||||
author = authorParts[1] + " " + authorParts[0]
|
author = authorParts[1] + " " + authorParts[0]
|
||||||
self.parse_author(author)
|
self.parse_author(author)
|
||||||
elif block_key == COPYRIGHT:
|
elif block_key == COPYRIGHT:
|
||||||
self.addCopyright(self.decode(data))
|
self.add_copyright(self.decode(data))
|
||||||
elif block_key == CCLI_NO:
|
elif block_key == CCLI_NO:
|
||||||
self.ccliNumber = int(data)
|
self.ccli_number = int(data)
|
||||||
elif block_key == VERSE:
|
elif block_key == VERSE:
|
||||||
self.addVerse(self.decode(data), "%s%s" % (VerseType.tags[VerseType.Verse], verse_no))
|
self.add_verse(self.decode(data), "%s%s" % (VerseType.tags[VerseType.Verse], verse_no))
|
||||||
elif block_key == CHORUS:
|
elif block_key == CHORUS:
|
||||||
self.addVerse(self.decode(data), "%s%s" % (VerseType.tags[VerseType.Chorus], verse_no))
|
self.add_verse(self.decode(data), "%s%s" % (VerseType.tags[VerseType.Chorus], verse_no))
|
||||||
elif block_key == BRIDGE:
|
elif block_key == BRIDGE:
|
||||||
self.addVerse(self.decode(data), "%s%s" % (VerseType.tags[VerseType.Bridge], verse_no))
|
self.add_verse(self.decode(data), "%s%s" % (VerseType.tags[VerseType.Bridge], verse_no))
|
||||||
elif block_key == TOPIC:
|
elif block_key == TOPIC:
|
||||||
self.topics.append(self.decode(data))
|
self.topics.append(self.decode(data))
|
||||||
elif block_key == COMMENTS:
|
elif block_key == COMMENTS:
|
||||||
@ -165,19 +165,19 @@ class SongShowPlusImport(SongImport):
|
|||||||
verse_tag = self.decode(verse_tag)
|
verse_tag = self.decode(verse_tag)
|
||||||
self.ssp_verse_order_list.append(verse_tag)
|
self.ssp_verse_order_list.append(verse_tag)
|
||||||
elif block_key == SONG_BOOK:
|
elif block_key == SONG_BOOK:
|
||||||
self.songBookName = self.decode(data)
|
self.song_book_name = self.decode(data)
|
||||||
elif block_key == SONG_NUMBER:
|
elif block_key == SONG_NUMBER:
|
||||||
self.songNumber = ord(data)
|
self.song_number = ord(data)
|
||||||
elif block_key == CUSTOM_VERSE:
|
elif block_key == CUSTOM_VERSE:
|
||||||
verse_tag = self.to_openlp_verse_tag(verse_name)
|
verse_tag = self.to_openlp_verse_tag(verse_name)
|
||||||
self.addVerse(self.decode(data), verse_tag)
|
self.add_verse(self.decode(data), verse_tag)
|
||||||
else:
|
else:
|
||||||
log.debug("Unrecognised blockKey: %s, data: %s" % (block_key, data))
|
log.debug("Unrecognised blockKey: %s, data: %s" % (block_key, data))
|
||||||
song_data.seek(next_block_starts)
|
song_data.seek(next_block_starts)
|
||||||
self.verseOrderList = self.ssp_verse_order_list
|
self.verse_order_list = self.ssp_verse_order_list
|
||||||
song_data.close()
|
song_data.close()
|
||||||
if not self.finish():
|
if not self.finish():
|
||||||
self.logError(file)
|
self.log_error(file)
|
||||||
|
|
||||||
def to_openlp_verse_tag(self, verse_name, ignore_unique=False):
|
def to_openlp_verse_tag(self, verse_name, ignore_unique=False):
|
||||||
# Have we got any digits? If so, verse number is everything from the digits to the end (OpenLP does not have
|
# Have we got any digits? If so, verse number is everything from the digits to the end (OpenLP does not have
|
||||||
|
@ -75,18 +75,18 @@ class SundayPlusImport(SongImport):
|
|||||||
"""
|
"""
|
||||||
Process the Sunday Plus file object.
|
Process the Sunday Plus file object.
|
||||||
"""
|
"""
|
||||||
self.setDefaults()
|
self.set_defaults()
|
||||||
if not self.parse(file.read()):
|
if not self.parse(file.read()):
|
||||||
self.logError(file.name)
|
self.log_error(file.name)
|
||||||
return
|
return
|
||||||
if not self.title:
|
if not self.title:
|
||||||
self.title = self.titleFromFilename(file.name)
|
self.title = self.titleFromFilename(file.name)
|
||||||
if not self.finish():
|
if not self.finish():
|
||||||
self.logError(file.name)
|
self.log_error(file.name)
|
||||||
|
|
||||||
def parse(self, data, cell=False):
|
def parse(self, data, cell=False):
|
||||||
if len(data) == 0 or data[0:1] != '[' or data[-1] != ']':
|
if len(data) == 0 or data[0:1] != '[' or data[-1] != ']':
|
||||||
self.logError('File is malformed')
|
self.log_error('File is malformed')
|
||||||
return False
|
return False
|
||||||
i = 1
|
i = 1
|
||||||
verse_type = VerseType.tags[VerseType.Verse]
|
verse_type = VerseType.tags[VerseType.Verse]
|
||||||
@ -126,7 +126,7 @@ class SundayPlusImport(SongImport):
|
|||||||
elif name == 'Author':
|
elif name == 'Author':
|
||||||
author = self.decode(self.unescape(value))
|
author = self.decode(self.unescape(value))
|
||||||
if len(author):
|
if len(author):
|
||||||
self.addAuthor(author)
|
self.add_author(author)
|
||||||
elif name == 'Copyright':
|
elif name == 'Copyright':
|
||||||
self.copyright = self.decode(self.unescape(value))
|
self.copyright = self.decode(self.unescape(value))
|
||||||
elif name[0:4] == 'CELL':
|
elif name[0:4] == 'CELL':
|
||||||
@ -160,13 +160,13 @@ class SundayPlusImport(SongImport):
|
|||||||
if line[:3].lower() == 'ccl':
|
if line[:3].lower() == 'ccl':
|
||||||
m = re.search(r'[0-9]+', line)
|
m = re.search(r'[0-9]+', line)
|
||||||
if m:
|
if m:
|
||||||
self.ccliNumber = int(m.group(0))
|
self.ccli_number = int(m.group(0))
|
||||||
continue
|
continue
|
||||||
elif line.lower() == 'public domain':
|
elif line.lower() == 'public domain':
|
||||||
self.copyright = 'Public Domain'
|
self.copyright = 'Public Domain'
|
||||||
continue
|
continue
|
||||||
processed_lines.append(line)
|
processed_lines.append(line)
|
||||||
self.addVerse('\n'.join(processed_lines).strip(), verse_type)
|
self.add_verse('\n'.join(processed_lines).strip(), verse_type)
|
||||||
if end == -1:
|
if end == -1:
|
||||||
break
|
break
|
||||||
i = end + 1
|
i = end + 1
|
||||||
|
@ -60,7 +60,7 @@ class WorshipCenterProImport(SongImport):
|
|||||||
except (pyodbc.DatabaseError, pyodbc.IntegrityError, pyodbc.InternalError, pyodbc.OperationalError) as e:
|
except (pyodbc.DatabaseError, pyodbc.IntegrityError, pyodbc.InternalError, pyodbc.OperationalError) as e:
|
||||||
log.warn('Unable to connect the WorshipCenter Pro database %s. %s', self.import_source, str(e))
|
log.warn('Unable to connect the WorshipCenter Pro database %s. %s', self.import_source, str(e))
|
||||||
# Unfortunately no specific exception type
|
# Unfortunately no specific exception type
|
||||||
self.logError(self.import_source,
|
self.log_error(self.import_source,
|
||||||
translate('SongsPlugin.WorshipCenterProImport', 'Unable to connect the WorshipCenter Pro database.'))
|
translate('SongsPlugin.WorshipCenterProImport', 'Unable to connect the WorshipCenter Pro database.'))
|
||||||
return
|
return
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
@ -76,10 +76,10 @@ class WorshipCenterProImport(SongImport):
|
|||||||
for song in songs:
|
for song in songs:
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
break
|
break
|
||||||
self.setDefaults()
|
self.set_defaults()
|
||||||
self.title = songs[song]['TITLE']
|
self.title = songs[song]['TITLE']
|
||||||
lyrics = songs[song]['LYRICS'].strip('&crlf;&crlf;')
|
lyrics = songs[song]['LYRICS'].strip('&crlf;&crlf;')
|
||||||
for verse in lyrics.split('&crlf;&crlf;'):
|
for verse in lyrics.split('&crlf;&crlf;'):
|
||||||
verse = verse.replace('&crlf;', '\n')
|
verse = verse.replace('&crlf;', '\n')
|
||||||
self.addVerse(verse)
|
self.add_verse(verse)
|
||||||
self.finish()
|
self.finish()
|
||||||
|
@ -110,10 +110,10 @@ class WowImport(SongImport):
|
|||||||
for source in self.import_source:
|
for source in self.import_source:
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
return
|
return
|
||||||
self.setDefaults()
|
self.set_defaults()
|
||||||
song_data = open(source, 'rb')
|
song_data = open(source, 'rb')
|
||||||
if song_data.read(19) != 'WoW File\nSong Words':
|
if song_data.read(19) != 'WoW File\nSong Words':
|
||||||
self.logError(source, str(translate('SongsPlugin.WordsofWorshipSongImport',
|
self.log_error(source, str(translate('SongsPlugin.WordsofWorshipSongImport',
|
||||||
('Invalid Words of Worship song file. Missing "Wow File\\nSong Words" header.'))))
|
('Invalid Words of Worship song file. Missing "Wow File\\nSong Words" header.'))))
|
||||||
continue
|
continue
|
||||||
# Seek to byte which stores number of blocks in the song
|
# Seek to byte which stores number of blocks in the song
|
||||||
@ -121,7 +121,7 @@ class WowImport(SongImport):
|
|||||||
no_of_blocks = ord(song_data.read(1))
|
no_of_blocks = ord(song_data.read(1))
|
||||||
song_data.seek(66)
|
song_data.seek(66)
|
||||||
if song_data.read(16) != 'CSongDoc::CBlock':
|
if song_data.read(16) != 'CSongDoc::CBlock':
|
||||||
self.logError(source, str(translate('SongsPlugin.WordsofWorshipSongImport',
|
self.log_error(source, str(translate('SongsPlugin.WordsofWorshipSongImport',
|
||||||
('Invalid Words of Worship song file. Missing "CSongDoc::CBlock" string.'))))
|
('Invalid Words of Worship song file. Missing "CSongDoc::CBlock" string.'))))
|
||||||
continue
|
continue
|
||||||
# Seek to the beginning of the first block
|
# Seek to the beginning of the first block
|
||||||
@ -141,7 +141,7 @@ class WowImport(SongImport):
|
|||||||
# this is the last block!
|
# this is the last block!
|
||||||
if block + 1 < no_of_blocks:
|
if block + 1 < no_of_blocks:
|
||||||
song_data.seek(2, os.SEEK_CUR)
|
song_data.seek(2, os.SEEK_CUR)
|
||||||
self.addVerse(block_text, block_type)
|
self.add_verse(block_text, block_type)
|
||||||
# Now to extract the author
|
# Now to extract the author
|
||||||
author_length = ord(song_data.read(1))
|
author_length = ord(song_data.read(1))
|
||||||
if author_length:
|
if author_length:
|
||||||
@ -149,10 +149,10 @@ class WowImport(SongImport):
|
|||||||
# Finally the copyright
|
# Finally the copyright
|
||||||
copyright_length = ord(song_data.read(1))
|
copyright_length = ord(song_data.read(1))
|
||||||
if copyright_length:
|
if copyright_length:
|
||||||
self.addCopyright(str(song_data.read(copyright_length), 'cp1252'))
|
self.add_copyright(str(song_data.read(copyright_length), 'cp1252'))
|
||||||
file_name = os.path.split(source)[1]
|
file_name = os.path.split(source)[1]
|
||||||
# Get the song title
|
# Get the song title
|
||||||
self.title = file_name.rpartition('.')[0]
|
self.title = file_name.rpartition('.')[0]
|
||||||
song_data.close()
|
song_data.close()
|
||||||
if not self.finish():
|
if not self.finish():
|
||||||
self.logError(source)
|
self.log_error(source)
|
||||||
|
@ -89,7 +89,7 @@ class ZionWorxImport(SongImport):
|
|||||||
try:
|
try:
|
||||||
records = list(songs_reader)
|
records = list(songs_reader)
|
||||||
except csv.Error as e:
|
except csv.Error as e:
|
||||||
self.logError(translate('SongsPlugin.ZionWorxImport', 'Error reading CSV file.'),
|
self.log_error(translate('SongsPlugin.ZionWorxImport', 'Error reading CSV file.'),
|
||||||
translate('SongsPlugin.ZionWorxImport', 'Line %d: %s') % (songs_reader.line_num, e))
|
translate('SongsPlugin.ZionWorxImport', 'Line %d: %s') % (songs_reader.line_num, e))
|
||||||
return
|
return
|
||||||
num_records = len(records)
|
num_records = len(records)
|
||||||
@ -98,20 +98,20 @@ class ZionWorxImport(SongImport):
|
|||||||
for index, record in enumerate(records, 1):
|
for index, record in enumerate(records, 1):
|
||||||
if self.stop_import_flag:
|
if self.stop_import_flag:
|
||||||
return
|
return
|
||||||
self.setDefaults()
|
self.set_defaults()
|
||||||
try:
|
try:
|
||||||
self.title = self._decode(record['Title1'])
|
self.title = self._decode(record['Title1'])
|
||||||
if record['Title2']:
|
if record['Title2']:
|
||||||
self.alternate_title = self._decode(record['Title2'])
|
self.alternate_title = self._decode(record['Title2'])
|
||||||
self.parse_author(self._decode(record['Writer']))
|
self.parse_author(self._decode(record['Writer']))
|
||||||
self.addCopyright(self._decode(record['Copyright']))
|
self.add_copyright(self._decode(record['Copyright']))
|
||||||
lyrics = self._decode(record['Lyrics'])
|
lyrics = self._decode(record['Lyrics'])
|
||||||
except UnicodeDecodeError as e:
|
except UnicodeDecodeError as e:
|
||||||
self.logError(translate('SongsPlugin.ZionWorxImport', 'Record %d' % index),
|
self.log_error(translate('SongsPlugin.ZionWorxImport', 'Record %d' % index),
|
||||||
translate('SongsPlugin.ZionWorxImport', 'Decoding error: %s') % e)
|
translate('SongsPlugin.ZionWorxImport', 'Decoding error: %s') % e)
|
||||||
continue
|
continue
|
||||||
except TypeError as e:
|
except TypeError as e:
|
||||||
self.logError(translate(
|
self.log_error(translate(
|
||||||
'SongsPlugin.ZionWorxImport', 'File not valid ZionWorx CSV format.'), 'TypeError: %s' % e)
|
'SongsPlugin.ZionWorxImport', 'File not valid ZionWorx CSV format.'), 'TypeError: %s' % e)
|
||||||
return
|
return
|
||||||
verse = ''
|
verse = ''
|
||||||
@ -119,13 +119,13 @@ class ZionWorxImport(SongImport):
|
|||||||
if line and not line.isspace():
|
if line and not line.isspace():
|
||||||
verse += line + '\n'
|
verse += line + '\n'
|
||||||
elif verse:
|
elif verse:
|
||||||
self.addVerse(verse)
|
self.add_verse(verse)
|
||||||
verse = ''
|
verse = ''
|
||||||
if verse:
|
if verse:
|
||||||
self.addVerse(verse)
|
self.add_verse(verse)
|
||||||
title = self.title
|
title = self.title
|
||||||
if not self.finish():
|
if not self.finish():
|
||||||
self.logError(translate('SongsPlugin.ZionWorxImport', 'Record %d') % index
|
self.log_error(translate('SongsPlugin.ZionWorxImport', 'Record %d') % index
|
||||||
+ (': "' + title + '"' if title else ''))
|
+ (': "' + title + '"' if title else ''))
|
||||||
|
|
||||||
def _decode(self, str):
|
def _decode(self, str):
|
||||||
|
@ -369,8 +369,8 @@ class TestEasyWorshipSongImport(TestCase):
|
|||||||
importer = EasyWorshipSongImportLogger(mocked_manager)
|
importer = EasyWorshipSongImportLogger(mocked_manager)
|
||||||
importer.import_wizard = mocked_import_wizard
|
importer.import_wizard = mocked_import_wizard
|
||||||
importer.stop_import_flag = False
|
importer.stop_import_flag = False
|
||||||
importer.addAuthor = mocked_add_author
|
importer.add_author = mocked_add_author
|
||||||
importer.addVerse = mocked_add_verse
|
importer.add_verse = mocked_add_verse
|
||||||
importer.title = mocked_title
|
importer.title = mocked_title
|
||||||
importer.finish = mocked_finish
|
importer.finish = mocked_finish
|
||||||
importer.topics = []
|
importer.topics = []
|
||||||
@ -394,11 +394,11 @@ class TestEasyWorshipSongImport(TestCase):
|
|||||||
if song_copyright:
|
if song_copyright:
|
||||||
self.assertEqual(importer.copyright, song_copyright)
|
self.assertEqual(importer.copyright, song_copyright)
|
||||||
if ccli_number:
|
if ccli_number:
|
||||||
self.assertEquals(importer.ccliNumber, ccli_number, 'ccliNumber for %s should be %s'
|
self.assertEquals(importer.ccli_number, ccli_number, 'ccli_number for %s should be %s'
|
||||||
% (title, ccli_number))
|
% (title, ccli_number))
|
||||||
for verse_text, verse_tag in add_verse_calls:
|
for verse_text, verse_tag in add_verse_calls:
|
||||||
mocked_add_verse.assert_any_call(verse_text, verse_tag)
|
mocked_add_verse.assert_any_call(verse_text, verse_tag)
|
||||||
if verse_order_list:
|
if verse_order_list:
|
||||||
self.assertEquals(importer.verseOrderList, verse_order_list, 'verseOrderList for %s should be %s'
|
self.assertEquals(importer.verse_order_list, verse_order_list, 'verse_order_list for %s should be %s'
|
||||||
% (title, verse_order_list))
|
% (title, verse_order_list))
|
||||||
mocked_finish.assert_called_with()
|
mocked_finish.assert_called_with()
|
||||||
|
@ -169,7 +169,7 @@ class TestFoilPresenter(TestCase):
|
|||||||
# WHEN: xml_to_song is called with a string without an xml encoding declaration
|
# WHEN: xml_to_song is called with a string without an xml encoding declaration
|
||||||
foil_presenter_instance.xml_to_song('<foilpresenterfolie>')
|
foil_presenter_instance.xml_to_song('<foilpresenterfolie>')
|
||||||
|
|
||||||
# THEN: the string shiuld have been left intact
|
# THEN: the string should have been left intact
|
||||||
self.mocked_re.compile.sub.called_with('<foilpresenterfolie>')
|
self.mocked_re.compile.sub.called_with('<foilpresenterfolie>')
|
||||||
|
|
||||||
def process_lyrics_no_verses_test(self):
|
def process_lyrics_no_verses_test(self):
|
||||||
@ -188,7 +188,7 @@ class TestFoilPresenter(TestCase):
|
|||||||
# WHEN: _process_lyrics is called
|
# WHEN: _process_lyrics is called
|
||||||
result = foil_presenter_instance._process_lyrics(mock_foilpresenterfolie, mocked_song)
|
result = foil_presenter_instance._process_lyrics(mock_foilpresenterfolie, mocked_song)
|
||||||
|
|
||||||
# THEN: _process_lyrics should return None and the song_import logError method should have been called once
|
# THEN: _process_lyrics should return None and the song_import log_error method should have been called once
|
||||||
self.assertIsNone(result)
|
self.assertIsNone(result)
|
||||||
self.mocked_song_import.logError.assert_called_once_with('Element Text', 'Translated String')
|
self.mocked_song_import.log_error.assert_called_once_with('Element Text', 'Translated String')
|
||||||
self.process_lyrics_patcher.start()
|
self.process_lyrics_patcher.start()
|
||||||
|
@ -130,7 +130,7 @@ class TestSongBeamerImport(TestCase):
|
|||||||
importer = SongBeamerImport(mocked_manager)
|
importer = SongBeamerImport(mocked_manager)
|
||||||
importer.import_wizard = mocked_import_wizard
|
importer.import_wizard = mocked_import_wizard
|
||||||
importer.stop_import_flag = False
|
importer.stop_import_flag = False
|
||||||
importer.addVerse = mocked_add_verse
|
importer.add_verse = mocked_add_verse
|
||||||
importer.finish = mocked_finish
|
importer.finish = mocked_finish
|
||||||
|
|
||||||
# WHEN: Importing each file
|
# WHEN: Importing each file
|
||||||
@ -147,9 +147,9 @@ class TestSongBeamerImport(TestCase):
|
|||||||
for verse_text, verse_tag in add_verse_calls:
|
for verse_text, verse_tag in add_verse_calls:
|
||||||
mocked_add_verse.assert_any_call(verse_text, verse_tag)
|
mocked_add_verse.assert_any_call(verse_text, verse_tag)
|
||||||
if song_book_name:
|
if song_book_name:
|
||||||
self.assertEquals(importer.songBookName, song_book_name, 'songBookName for %s should be "%s"'
|
self.assertEquals(importer.song_book_name, song_book_name, 'song_book_name for %s should be "%s"'
|
||||||
% (song_file, song_book_name))
|
% (song_file, song_book_name))
|
||||||
if song_number:
|
if song_number:
|
||||||
self.assertEquals(importer.songNumber, song_number, 'songNumber for %s should be %s'
|
self.assertEquals(importer.song_number, song_number, 'song_number for %s should be %s'
|
||||||
% (song_file, song_number))
|
% (song_file, song_number))
|
||||||
mocked_finish.assert_called_with()
|
mocked_finish.assert_called_with()
|
||||||
|
@ -41,6 +41,7 @@ from tests.functional import patch, MagicMock
|
|||||||
TEST_PATH = os.path.abspath(
|
TEST_PATH = os.path.abspath(
|
||||||
os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'songshowplussongs'))
|
os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'songshowplussongs'))
|
||||||
|
|
||||||
|
|
||||||
class TestSongShowPlusFileImport(SongImportTestHelper):
|
class TestSongShowPlusFileImport(SongImportTestHelper):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.importer_class_name = 'SongShowPlusImport'
|
self.importer_class_name = 'SongShowPlusImport'
|
||||||
|
@ -152,7 +152,7 @@ class TestWorshipCenterProSongImport(TestCase):
|
|||||||
Test that exceptions raised by pyodbc are handled
|
Test that exceptions raised by pyodbc are handled
|
||||||
"""
|
"""
|
||||||
# GIVEN: A mocked out SongImport class, a mocked out pyodbc module, a mocked out translate method,
|
# GIVEN: A mocked out SongImport class, a mocked out pyodbc module, a mocked out translate method,
|
||||||
# a mocked "manager" and a mocked out logError method.
|
# a mocked "manager" and a mocked out log_error method.
|
||||||
with patch('openlp.plugins.songs.lib.worshipcenterproimport.SongImport'), \
|
with patch('openlp.plugins.songs.lib.worshipcenterproimport.SongImport'), \
|
||||||
patch('openlp.plugins.songs.lib.worshipcenterproimport.pyodbc.connect') as mocked_pyodbc_connect, \
|
patch('openlp.plugins.songs.lib.worshipcenterproimport.pyodbc.connect') as mocked_pyodbc_connect, \
|
||||||
patch('openlp.plugins.songs.lib.worshipcenterproimport.translate') as mocked_translate:
|
patch('openlp.plugins.songs.lib.worshipcenterproimport.translate') as mocked_translate:
|
||||||
@ -160,7 +160,7 @@ class TestWorshipCenterProSongImport(TestCase):
|
|||||||
mocked_log_error = MagicMock()
|
mocked_log_error = MagicMock()
|
||||||
mocked_translate.return_value = 'Translated Text'
|
mocked_translate.return_value = 'Translated Text'
|
||||||
importer = WorshipCenterProImport(mocked_manager)
|
importer = WorshipCenterProImport(mocked_manager)
|
||||||
importer.logError = mocked_log_error
|
importer.log_error = mocked_log_error
|
||||||
importer.import_source = 'import_source'
|
importer.import_source = 'import_source'
|
||||||
pyodbc_errors = [pyodbc.DatabaseError, pyodbc.IntegrityError, pyodbc.InternalError, pyodbc.OperationalError]
|
pyodbc_errors = [pyodbc.DatabaseError, pyodbc.IntegrityError, pyodbc.InternalError, pyodbc.OperationalError]
|
||||||
mocked_pyodbc_connect.side_effect = pyodbc_errors
|
mocked_pyodbc_connect.side_effect = pyodbc_errors
|
||||||
@ -169,7 +169,7 @@ class TestWorshipCenterProSongImport(TestCase):
|
|||||||
for effect in pyodbc_errors:
|
for effect in pyodbc_errors:
|
||||||
return_value = importer.doImport()
|
return_value = importer.doImport()
|
||||||
|
|
||||||
# THEN: doImport should return None, and pyodbc, translate & logError are called with known calls
|
# THEN: doImport should return None, and pyodbc, translate & log_error are called with known calls
|
||||||
self.assertIsNone(return_value, 'doImport should return None when pyodbc raises an exception.')
|
self.assertIsNone(return_value, 'doImport should return None when pyodbc raises an exception.')
|
||||||
mocked_pyodbc_connect.assert_called_with( 'DRIVER={Microsoft Access Driver (*.mdb)};DBQ=import_source')
|
mocked_pyodbc_connect.assert_called_with( 'DRIVER={Microsoft Access Driver (*.mdb)};DBQ=import_source')
|
||||||
mocked_translate.assert_called_with('SongsPlugin.WorshipCenterProImport',
|
mocked_translate.assert_called_with('SongsPlugin.WorshipCenterProImport',
|
||||||
@ -181,7 +181,7 @@ class TestWorshipCenterProSongImport(TestCase):
|
|||||||
Test that a simulated WorshipCenter Pro recordset is imported correctly
|
Test that a simulated WorshipCenter Pro recordset is imported correctly
|
||||||
"""
|
"""
|
||||||
# GIVEN: A mocked out SongImport class, a mocked out pyodbc module with a simulated recordset, a mocked out
|
# GIVEN: A mocked out SongImport class, a mocked out pyodbc module with a simulated recordset, a mocked out
|
||||||
# translate method, a mocked "manager", addVerse method & mocked_finish method.
|
# translate method, a mocked "manager", add_verse method & mocked_finish method.
|
||||||
with patch('openlp.plugins.songs.lib.worshipcenterproimport.SongImport'), \
|
with patch('openlp.plugins.songs.lib.worshipcenterproimport.SongImport'), \
|
||||||
patch('openlp.plugins.songs.lib.worshipcenterproimport.pyodbc') as mocked_pyodbc, \
|
patch('openlp.plugins.songs.lib.worshipcenterproimport.pyodbc') as mocked_pyodbc, \
|
||||||
patch('openlp.plugins.songs.lib.worshipcenterproimport.translate') as mocked_translate:
|
patch('openlp.plugins.songs.lib.worshipcenterproimport.translate') as mocked_translate:
|
||||||
@ -194,7 +194,7 @@ class TestWorshipCenterProSongImport(TestCase):
|
|||||||
importer = WorshipCenterProImportLogger(mocked_manager)
|
importer = WorshipCenterProImportLogger(mocked_manager)
|
||||||
importer.import_source = 'import_source'
|
importer.import_source = 'import_source'
|
||||||
importer.import_wizard = mocked_import_wizard
|
importer.import_wizard = mocked_import_wizard
|
||||||
importer.addVerse = mocked_add_verse
|
importer.add_verse = mocked_add_verse
|
||||||
importer.stop_import_flag = False
|
importer.stop_import_flag = False
|
||||||
importer.finish = mocked_finish
|
importer.finish = mocked_finish
|
||||||
|
|
||||||
@ -202,7 +202,7 @@ class TestWorshipCenterProSongImport(TestCase):
|
|||||||
return_value = importer.doImport()
|
return_value = importer.doImport()
|
||||||
|
|
||||||
|
|
||||||
# THEN: doImport should return None, and pyodbc, import_wizard, importer.title and addVerse are called with
|
# THEN: doImport should return None, and pyodbc, import_wizard, importer.title and add_verse are called with
|
||||||
# known calls
|
# known calls
|
||||||
self.assertIsNone(return_value, 'doImport should return None when pyodbc raises an exception.')
|
self.assertIsNone(return_value, 'doImport should return None when pyodbc raises an exception.')
|
||||||
mocked_pyodbc.connect.assert_called_with('DRIVER={Microsoft Access Driver (*.mdb)};DBQ=import_source')
|
mocked_pyodbc.connect.assert_called_with('DRIVER={Microsoft Access Driver (*.mdb)};DBQ=import_source')
|
||||||
@ -220,4 +220,4 @@ class TestWorshipCenterProSongImport(TestCase):
|
|||||||
for call in verse_calls:
|
for call in verse_calls:
|
||||||
mocked_add_verse.assert_any_call(call)
|
mocked_add_verse.assert_any_call(call)
|
||||||
self.assertEqual(mocked_add_verse.call_count, add_verse_call_count,
|
self.assertEqual(mocked_add_verse.call_count, add_verse_call_count,
|
||||||
'Incorrect number of calls made to addVerse')
|
'Incorrect number of calls made to add_verse')
|
||||||
|
@ -35,6 +35,7 @@ from unittest import TestCase
|
|||||||
|
|
||||||
from tests.functional import patch, MagicMock
|
from tests.functional import patch, MagicMock
|
||||||
|
|
||||||
|
|
||||||
class SongImportTestHelper(TestCase):
|
class SongImportTestHelper(TestCase):
|
||||||
"""
|
"""
|
||||||
This class is designed to be a helper class to reduce repition when testing the import of song files.
|
This class is designed to be a helper class to reduce repition when testing the import of song files.
|
||||||
@ -50,9 +51,9 @@ class SongImportTestHelper(TestCase):
|
|||||||
Patch and set up the mocks required.
|
Patch and set up the mocks required.
|
||||||
"""
|
"""
|
||||||
self.add_copyright_patcher = patch(
|
self.add_copyright_patcher = patch(
|
||||||
'openlp.plugins.songs.lib.%s.%s.addCopyright' % (self.importer_module_name, self.importer_class_name))
|
'openlp.plugins.songs.lib.%s.%s.add_copyright' % (self.importer_module_name, self.importer_class_name))
|
||||||
self.add_verse_patcher = patch(
|
self.add_verse_patcher = patch(
|
||||||
'openlp.plugins.songs.lib.%s.%s.addVerse' % (self.importer_module_name, self.importer_class_name))
|
'openlp.plugins.songs.lib.%s.%s.add_verse' % (self.importer_module_name, self.importer_class_name))
|
||||||
self.finish_patcher = patch(
|
self.finish_patcher = patch(
|
||||||
'openlp.plugins.songs.lib.%s.%s.finish' % (self.importer_module_name, self.importer_class_name))
|
'openlp.plugins.songs.lib.%s.%s.finish' % (self.importer_module_name, self.importer_class_name))
|
||||||
self.parse_author_patcher = patch(
|
self.parse_author_patcher = patch(
|
||||||
@ -115,7 +116,7 @@ class SongImportTestHelper(TestCase):
|
|||||||
if song_copyright:
|
if song_copyright:
|
||||||
self.mocked_add_copyright.assert_called_with(song_copyright)
|
self.mocked_add_copyright.assert_called_with(song_copyright)
|
||||||
if ccli_number:
|
if ccli_number:
|
||||||
self.assertEquals(importer.ccliNumber, ccli_number, 'ccliNumber for %s should be %s'
|
self.assertEquals(importer.ccli_number, ccli_number, 'ccli_number for %s should be %s'
|
||||||
% (source_file_name, ccli_number))
|
% (source_file_name, ccli_number))
|
||||||
for verse_text, verse_tag in add_verse_calls:
|
for verse_text, verse_tag in add_verse_calls:
|
||||||
self.mocked_add_verse.assert_any_call(verse_text, verse_tag)
|
self.mocked_add_verse.assert_any_call(verse_text, verse_tag)
|
||||||
@ -125,13 +126,13 @@ class SongImportTestHelper(TestCase):
|
|||||||
self.assertEquals(importer.comments, comments, 'comments for %s should be "%s"'
|
self.assertEquals(importer.comments, comments, 'comments for %s should be "%s"'
|
||||||
% (source_file_name, comments))
|
% (source_file_name, comments))
|
||||||
if song_book_name:
|
if song_book_name:
|
||||||
self.assertEquals(importer.songBookName, song_book_name, 'songBookName for %s should be "%s"'
|
self.assertEquals(importer.song_book_name, song_book_name, 'song_book_name for %s should be "%s"'
|
||||||
% (source_file_name, song_book_name))
|
% (source_file_name, song_book_name))
|
||||||
if song_number:
|
if song_number:
|
||||||
self.assertEquals(importer.songNumber, song_number, 'songNumber for %s should be %s'
|
self.assertEquals(importer.song_number, song_number, 'song_number for %s should be %s'
|
||||||
% (source_file_name, song_number))
|
% (source_file_name, song_number))
|
||||||
if verse_order_list:
|
if verse_order_list:
|
||||||
self.assertEquals(importer.verseOrderList, [], 'verseOrderList for %s should be %s'
|
self.assertEquals(importer.verse_order_list, [], 'verse_order_list for %s should be %s'
|
||||||
% (source_file_name, verse_order_list))
|
% (source_file_name, verse_order_list))
|
||||||
self.mocked_finish.assert_called_with()
|
self.mocked_finish.assert_called_with()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user