First go at an importer for Worship Assistant

This commit is contained in:
Samuel Mehrbrodt 2014-06-25 14:23:31 +02:00
parent d61111ab89
commit f92afc296b
2 changed files with 166 additions and 9 deletions

View File

@ -50,6 +50,7 @@ from .sundayplusimport import SundayPlusImport
from .foilpresenterimport import FoilPresenterImport from .foilpresenterimport import FoilPresenterImport
from .zionworximport import ZionWorxImport from .zionworximport import ZionWorxImport
from .propresenterimport import ProPresenterImport from .propresenterimport import ProPresenterImport
from .worshipassistantimport import WorshipAssistantImport
# Imports that might fail # Imports that might fail
@ -167,8 +168,9 @@ class SongFormat(object):
SongsOfFellowship = 16 SongsOfFellowship = 16
SundayPlus = 17 SundayPlus = 17
WordsOfWorship = 18 WordsOfWorship = 18
WorshipCenterPro = 19 WorshipAssistant = 19
ZionWorx = 20 WorshipCenterPro = 20
ZionWorx = 21
# Set optional attribute defaults # Set optional attribute defaults
__defaults__ = { __defaults__ = {
@ -321,6 +323,16 @@ class SongFormat(object):
'prefix': 'wordsOfWorship', 'prefix': 'wordsOfWorship',
'filter': '%s (*.wsg *.wow-song)' % translate('SongsPlugin.ImportWizardForm', 'Words Of Worship Song Files') 'filter': '%s (*.wsg *.wow-song)' % translate('SongsPlugin.ImportWizardForm', 'Words Of Worship Song Files')
}, },
WorshipAssistant: {
'class': WorshipAssistantImport,
'name': 'Worship Assistant 0',
'prefix': 'worshipAssistant',
'selectMode': SongFormatSelect.SingleFile,
'filter': '%s (*.csv)' % translate('SongsPlugin.ImportWizardForm', 'Worship Assistant Files'),
'comboBoxText': translate('SongsPlugin.ImportWizardForm', 'Worship Assistant (CSV)'),
'descriptionText': translate('SongsPlugin.ImportWizardForm',
'In Worship Assistant, export your Database to a CSV file.')
},
WorshipCenterPro: { WorshipCenterPro: {
'name': 'WorshipCenter Pro', 'name': 'WorshipCenter Pro',
'prefix': 'worshipCenterPro', 'prefix': 'worshipCenterPro',
@ -370,16 +382,17 @@ class SongFormat(object):
SongFormat.SongsOfFellowship, SongFormat.SongsOfFellowship,
SongFormat.SundayPlus, SongFormat.SundayPlus,
SongFormat.WordsOfWorship, SongFormat.WordsOfWorship,
SongFormat.WorshipAssistant,
SongFormat.WorshipCenterPro, SongFormat.WorshipCenterPro,
SongFormat.ZionWorx SongFormat.ZionWorx
] ]
@staticmethod @staticmethod
def get(format, *attributes): def get(song_format, *attributes):
""" """
Return requested song format attribute(s). Return requested song format attribute(s).
:param format: A song format from SongFormat. :param song_format: A song format from SongFormat.
:param attributes: Zero or more song format attributes from SongFormat. :param attributes: Zero or more song format attributes from SongFormat.
Return type depends on number of supplied attributes: Return type depends on number of supplied attributes:
@ -389,23 +402,23 @@ class SongFormat(object):
:>1: Return tuple of requested attribute values. :>1: Return tuple of requested attribute values.
""" """
if not attributes: if not attributes:
return SongFormat.__attributes__.get(format) return SongFormat.__attributes__.get(song_format)
elif len(attributes) == 1: elif len(attributes) == 1:
default = SongFormat.__defaults__.get(attributes[0]) default = SongFormat.__defaults__.get(attributes[0])
return SongFormat.__attributes__[format].get(attributes[0], default) return SongFormat.__attributes__[song_format].get(attributes[0], default)
else: else:
values = [] values = []
for attr in attributes: for attr in attributes:
default = SongFormat.__defaults__.get(attr) default = SongFormat.__defaults__.get(attr)
values.append(SongFormat.__attributes__[format].get(attr, default)) values.append(SongFormat.__attributes__[song_format].get(attr, default))
return tuple(values) return tuple(values)
@staticmethod @staticmethod
def set(format, attribute, value): def set(song_format, attribute, value):
""" """
Set specified song format attribute to the supplied value. Set specified song format attribute to the supplied value.
""" """
SongFormat.__attributes__[format][attribute] = value SongFormat.__attributes__[song_format][attribute] = value
SongFormat.set(SongFormat.SongsOfFellowship, 'availability', HAS_SOF) SongFormat.set(SongFormat.SongsOfFellowship, 'availability', HAS_SOF)

View File

@ -0,0 +1,144 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2014 Raoul Snyman #
# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
# --------------------------------------------------------------------------- #
# 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 2 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:`worshipassistantimport` module provides the functionality for importing
Worship Assistant songs into the OpenLP database.
"""
import csv
import logging
from openlp.core.common import translate
from openlp.plugins.songs.lib.songimport import SongImport
log = logging.getLogger(__name__)
# Used to strip control chars (except 10=LF, 13=CR)
CONTROL_CHARS_MAP = dict.fromkeys(list(range(10)) + [11, 12] + list(range(14, 32)) + [127])
class WorshipAssistantImport(SongImport):
"""
The :class:`WorshipAssistantImport` class provides the ability to import songs
from Worship Assistant, via a dump of the database to a CSV file.
The following fields are in the exported CSV file:
* ``SONGNR`` Song ID (Discarded by importer)
* ``TITLE`` Song title
* ``AUTHOR`` Song author. May containt multiple authors.
* ``COPYRIGHT`` Copyright information
* ``FIRSTLINE`` Unknown (Discarded by importer)
* ``PRIKEY`` Primary chord key
* ``ALTKEY`` Alternate chord key
* ``TEMPO`` Tempo
* ``FOCUS`` Unknown (Discarded by importer)
* ``THEME`` Theme (Discarded by importer)
* ``SCRIPTURE`` Associated scripture (Discarded by importer)
* ``ACTIVE`` Boolean value (Discarded by importer)
* ``SONGBOOK`` Boolean value (Discarded by importer)
* ``TIMESIG`` Unknown (Discarded by importer)
* ``INTRODUCED`` Date the song was created (Discarded by importer)
* ``LASTUSED`` Date the song was last used (Discarded by importer)
* ``TIMESUSED`` How many times the song was used (Discarded by importer)
* ``TIMESUSED`` How many times the song was used (Discarded by importer)
* ``CCLINR`` CCLI Number
* ``USER1`` User Field 1 (Discarded by importer)
* ``USER2`` User Field 2 (Discarded by importer)
* ``USER3`` User Field 3 (Discarded by importer)
* ``USER4`` User Field 4 (Discarded by importer)
* ``USER5`` User Field 5 (Discarded by importer)
* ``ROADMAP`` Verse order
* ``FILELINK1`` Associated file 1 (Discarded by importer)
* ``OVERMAP`` Unknown (Discarded by importer)
* ``FILELINK2`` Associated file 2 (Discarded by importer)
* ``LYRICS`` The song lyrics as plain text (Discarded by importer)
* ``INFO`` Unknown (Discarded by importer)
* ``LYRICS2`` The song lyrics with verse numbers
* ``BACKGROUND`` Unknown (Discarded by importer)
"""
def do_import(self):
"""
Receive a CSV file to import.
"""
with open(self.import_source, 'r', encoding='latin-1') as songs_file:
field_names = ['SongNum', 'Title1', 'Title2', 'Lyrics', 'Writer', 'Copyright', 'Keywords',
'DefaultStyle']
songs_reader = csv.DictReader(songs_file)#, field_names)
try:
records = list(songs_reader)
except csv.Error as e:
self.log_error(translate('SongsPlugin.WorshipAssistantImport', 'Error reading CSV file.'),
translate('SongsPlugin.WorshipAssistantImport', 'Line %d: %s') %
(songs_reader.line_num, e))
return
num_records = len(records)
log.info('%s records found in CSV file' % num_records)
self.import_wizard.progress_bar.setMaximum(num_records)
for index, record in enumerate(records, 1):
if self.stop_import_flag:
return
# The CSV file has a line in the middle of the file where the headers are repeated.
# We need to skip this line.
if record['TITLE'] == "TITLE" and record['COPYRIGHT'] == 'COPYRIGHT' and record['AUTHOR'] == 'AUTHOR':
continue
self.set_defaults()
try:
self.title = self._decode(record['TITLE'])
self.parse_author(self._decode(record['AUTHOR']))
self.add_copyright(self._decode(record['COPYRIGHT']))
lyrics = self._decode(record['LYRICS2'])
except UnicodeDecodeError as e:
self.log_error(translate('SongsPlugin.WorshipAssistantImport', 'Record %d' % index),
translate('SongsPlugin.WorshipAssistantImport', 'Decoding error: %s') % e)
continue
except TypeError as e:
self.log_error(translate('SongsPlugin.WorshipAssistantImport',
'File not valid WorshipAssistant CSV format.'), 'TypeError: %s' % e)
return
verse = ''
for line in lyrics.splitlines():
if line and not line.isspace():
verse += line + '\n'
elif verse:
self.add_verse(verse)
verse = ''
if verse:
self.add_verse(verse)
if not self.finish():
self.log_error(translate('SongsPlugin.ZionWorxImport', 'Record %d') % index
+ (': "' + self.title + '"' if self.title else ''))
def _decode(self, str):
"""
Decodes CSV input to unicode, stripping all control characters (except new lines).
"""
# This encoding choice seems OK. ZionWorx has no option for setting the
# encoding for its songs, so we assume encoding is always the same.
return str
#return str(str, 'cp1252').translate(CONTROL_CHARS_MAP)