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 .zionworximport import ZionWorxImport
from .propresenterimport import ProPresenterImport
from .worshipassistantimport import WorshipAssistantImport
# Imports that might fail
@ -167,8 +168,9 @@ class SongFormat(object):
SongsOfFellowship = 16
SundayPlus = 17
WordsOfWorship = 18
WorshipCenterPro = 19
ZionWorx = 20
WorshipAssistant = 19
WorshipCenterPro = 20
ZionWorx = 21
# Set optional attribute defaults
__defaults__ = {
@ -321,6 +323,16 @@ class SongFormat(object):
'prefix': 'wordsOfWorship',
'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: {
'name': 'WorshipCenter Pro',
'prefix': 'worshipCenterPro',
@ -370,16 +382,17 @@ class SongFormat(object):
SongFormat.SongsOfFellowship,
SongFormat.SundayPlus,
SongFormat.WordsOfWorship,
SongFormat.WorshipAssistant,
SongFormat.WorshipCenterPro,
SongFormat.ZionWorx
]
@staticmethod
def get(format, *attributes):
def get(song_format, *attributes):
"""
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.
Return type depends on number of supplied attributes:
@ -389,23 +402,23 @@ class SongFormat(object):
:>1: Return tuple of requested attribute values.
"""
if not attributes:
return SongFormat.__attributes__.get(format)
return SongFormat.__attributes__.get(song_format)
elif len(attributes) == 1:
default = SongFormat.__defaults__.get(attributes[0])
return SongFormat.__attributes__[format].get(attributes[0], default)
return SongFormat.__attributes__[song_format].get(attributes[0], default)
else:
values = []
for attr in attributes:
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)
@staticmethod
def set(format, attribute, value):
def set(song_format, attribute, 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)

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)