Merge lp:~phill-ridout/openlp/pathlib8 into lp:openlp

Proposed by Phill
Status: Merged
Merged at revision: 2774
Proposed branch: lp:~phill-ridout/openlp/pathlib8
Merge into: lp:openlp
Diff against target: 3277 lines (+662/-713)
66 files modified
openlp/core/lib/serviceitem.py (+2/-2)
openlp/core/ui/maindisplay.py (+1/-1)
openlp/core/ui/servicemanager.py (+3/-1)
openlp/core/ui/slidecontroller.py (+1/-1)
openlp/plugins/songs/forms/editsongform.py (+34/-38)
openlp/plugins/songs/forms/mediafilesform.py (+11/-4)
openlp/plugins/songs/forms/songexportform.py (+13/-29)
openlp/plugins/songs/forms/songimportform.py (+43/-68)
openlp/plugins/songs/lib/__init__.py (+5/-5)
openlp/plugins/songs/lib/db.py (+5/-4)
openlp/plugins/songs/lib/importers/cclifile.py (+27/-31)
openlp/plugins/songs/lib/importers/chordpro.py (+3/-4)
openlp/plugins/songs/lib/importers/dreambeam.py (+10/-8)
openlp/plugins/songs/lib/importers/easyslides.py (+1/-1)
openlp/plugins/songs/lib/importers/easyworship.py (+30/-46)
openlp/plugins/songs/lib/importers/foilpresenter.py (+2/-5)
openlp/plugins/songs/lib/importers/lyrix.py (+3/-4)
openlp/plugins/songs/lib/importers/openlp.py (+1/-1)
openlp/plugins/songs/lib/importers/openlyrics.py (+2/-5)
openlp/plugins/songs/lib/importers/openoffice.py (+5/-12)
openlp/plugins/songs/lib/importers/opensong.py (+3/-5)
openlp/plugins/songs/lib/importers/opspro.py (+9/-10)
openlp/plugins/songs/lib/importers/powerpraise.py (+4/-6)
openlp/plugins/songs/lib/importers/powersong.py (+7/-3)
openlp/plugins/songs/lib/importers/presentationmanager.py (+11/-11)
openlp/plugins/songs/lib/importers/propresenter.py (+11/-9)
openlp/plugins/songs/lib/importers/songbeamer.py (+14/-14)
openlp/plugins/songs/lib/importers/songimport.py (+26/-27)
openlp/plugins/songs/lib/importers/songpro.py (+3/-1)
openlp/plugins/songs/lib/importers/songshowplus.py (+84/-87)
openlp/plugins/songs/lib/importers/sundayplus.py (+3/-7)
openlp/plugins/songs/lib/importers/videopsalm.py (+8/-9)
openlp/plugins/songs/lib/importers/wordsofworship.py (+55/-56)
openlp/plugins/songs/lib/importers/worshipassistant.py (+11/-15)
openlp/plugins/songs/lib/importers/zionworx.py (+1/-1)
openlp/plugins/songs/lib/mediaitem.py (+16/-18)
openlp/plugins/songs/lib/openlyricsexport.py (+10/-9)
openlp/plugins/songs/lib/upgrade.py (+31/-2)
openlp/plugins/songs/reporting.py (+2/-3)
openlp/plugins/songs/songsplugin.py (+1/-3)
tests/functional/openlp_plugins/images/test_upgrade.py (+1/-0)
tests/functional/openlp_plugins/songs/test_chordproimport.py (+3/-1)
tests/functional/openlp_plugins/songs/test_easyslidesimport.py (+4/-3)
tests/functional/openlp_plugins/songs/test_ewimport.py (+35/-54)
tests/functional/openlp_plugins/songs/test_lyriximport.py (+5/-4)
tests/functional/openlp_plugins/songs/test_mediashout.py (+6/-6)
tests/functional/openlp_plugins/songs/test_openlpimporter.py (+2/-2)
tests/functional/openlp_plugins/songs/test_openlyricsexport.py (+10/-8)
tests/functional/openlp_plugins/songs/test_openlyricsimport.py (+5/-4)
tests/functional/openlp_plugins/songs/test_openoffice.py (+2/-2)
tests/functional/openlp_plugins/songs/test_opensongimport.py (+9/-8)
tests/functional/openlp_plugins/songs/test_opsproimport.py (+5/-5)
tests/functional/openlp_plugins/songs/test_powerpraiseimport.py (+4/-3)
tests/functional/openlp_plugins/songs/test_presentationmanagerimport.py (+4/-3)
tests/functional/openlp_plugins/songs/test_propresenterimport.py (+5/-4)
tests/functional/openlp_plugins/songs/test_songbeamerimport.py (+8/-7)
tests/functional/openlp_plugins/songs/test_songproimport.py (+3/-2)
tests/functional/openlp_plugins/songs/test_songselect.py (+4/-3)
tests/functional/openlp_plugins/songs/test_songshowplusimport.py (+10/-9)
tests/functional/openlp_plugins/songs/test_sundayplusimport.py (+3/-1)
tests/functional/openlp_plugins/songs/test_videopsalm.py (+4/-3)
tests/functional/openlp_plugins/songs/test_wordsofworshipimport.py (+5/-4)
tests/functional/openlp_plugins/songs/test_worshipassistantimport.py (+5/-4)
tests/functional/openlp_plugins/songs/test_worshipcenterproimport.py (+3/-3)
tests/functional/openlp_plugins/songs/test_zionworximport.py (+4/-3)
tests/helpers/songfileimport.py (+1/-1)
To merge this branch: bzr merge lp:~phill-ridout/openlp/pathlib8
Reviewer Review Type Date Requested Status
Tomas Groth Approve
Tim Bentley Approve
Review via email: mp+331621@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Tim Bentley (trb143) :
review: Approve
Revision history for this message
Tomas Groth (tomasgroth) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'openlp/core/lib/serviceitem.py'
--- openlp/core/lib/serviceitem.py 2017-08-03 17:54:40 +0000
+++ openlp/core/lib/serviceitem.py 2017-09-30 23:24:21 +0000
@@ -426,10 +426,10 @@
426 self.background_audio = []426 self.background_audio = []
427 for filename in header['background_audio']:427 for filename in header['background_audio']:
428 # Give them real file paths.428 # Give them real file paths.
429 filepath = filename429 filepath = str(filename)
430 if path:430 if path:
431 # Windows can handle both forward and backward slashes, so we use ntpath to get the basename431 # Windows can handle both forward and backward slashes, so we use ntpath to get the basename
432 filepath = os.path.join(path, ntpath.basename(filename))432 filepath = os.path.join(path, ntpath.basename(str(filename)))
433 self.background_audio.append(filepath)433 self.background_audio.append(filepath)
434 self.theme_overwritten = header.get('theme_overwritten', False)434 self.theme_overwritten = header.get('theme_overwritten', False)
435 if self.service_item_type == ServiceItemType.Text:435 if self.service_item_type == ServiceItemType.Text:
436436
=== modified file 'openlp/core/ui/maindisplay.py'
--- openlp/core/ui/maindisplay.py 2017-09-26 16:39:13 +0000
+++ openlp/core/ui/maindisplay.py 2017-09-30 23:24:21 +0000
@@ -684,7 +684,7 @@
684 if not isinstance(file_names, list):684 if not isinstance(file_names, list):
685 file_names = [file_names]685 file_names = [file_names]
686 for file_name in file_names:686 for file_name in file_names:
687 self.playlist.addMedia(QtMultimedia.QMediaContent(QtCore.QUrl.fromLocalFile(file_name)))687 self.playlist.addMedia(QtMultimedia.QMediaContent(QtCore.QUrl.fromLocalFile(str(file_name))))
688688
689 def next(self):689 def next(self):
690 """690 """
691691
=== modified file 'openlp/core/ui/servicemanager.py'
--- openlp/core/ui/servicemanager.py 2017-09-23 13:06:42 +0000
+++ openlp/core/ui/servicemanager.py 2017-09-30 23:24:21 +0000
@@ -561,7 +561,7 @@
561 service_item = item['service_item'].get_service_repr(self._save_lite)561 service_item = item['service_item'].get_service_repr(self._save_lite)
562 if service_item['header']['background_audio']:562 if service_item['header']['background_audio']:
563 for i, file_name in enumerate(service_item['header']['background_audio']):563 for i, file_name in enumerate(service_item['header']['background_audio']):
564 new_file = os.path.join('audio', item['service_item'].unique_identifier, file_name)564 new_file = os.path.join('audio', item['service_item'].unique_identifier, str(file_name))
565 audio_files.append((file_name, new_file))565 audio_files.append((file_name, new_file))
566 service_item['header']['background_audio'][i] = new_file566 service_item['header']['background_audio'][i] = new_file
567 # Add the service item to the service.567 # Add the service item to the service.
@@ -586,6 +586,8 @@
586 for write_from in write_list:586 for write_from in write_list:
587 zip_file.write(write_from, write_from)587 zip_file.write(write_from, write_from)
588 for audio_from, audio_to in audio_files:588 for audio_from, audio_to in audio_files:
589 audio_from = str(audio_from)
590 audio_to = str(audio_to)
589 if audio_from.startswith('audio'):591 if audio_from.startswith('audio'):
590 # When items are saved, they get new unique_identifier. Let's copy the file to the new location.592 # When items are saved, they get new unique_identifier. Let's copy the file to the new location.
591 # Unused files can be ignored, OpenLP automatically cleans up the service manager dir on exit.593 # Unused files can be ignored, OpenLP automatically cleans up the service manager dir on exit.
592594
=== modified file 'openlp/core/ui/slidecontroller.py'
--- openlp/core/ui/slidecontroller.py 2017-06-06 20:58:12 +0000
+++ openlp/core/ui/slidecontroller.py 2017-09-30 23:24:21 +0000
@@ -868,7 +868,7 @@
868 self.track_menu.clear()868 self.track_menu.clear()
869 for counter in range(len(self.service_item.background_audio)):869 for counter in range(len(self.service_item.background_audio)):
870 action = self.track_menu.addAction(870 action = self.track_menu.addAction(
871 os.path.basename(self.service_item.background_audio[counter]))871 os.path.basename(str(self.service_item.background_audio[counter])))
872 action.setData(counter)872 action.setData(counter)
873 action.triggered.connect(self.on_track_triggered)873 action.triggered.connect(self.on_track_triggered)
874 self.display.audio_player.repeat = \874 self.display.audio_player.repeat = \
875875
=== modified file 'openlp/plugins/songs/forms/editsongform.py'
--- openlp/plugins/songs/forms/editsongform.py 2017-08-25 20:03:25 +0000
+++ openlp/plugins/songs/forms/editsongform.py 2017-09-30 23:24:21 +0000
@@ -23,27 +23,25 @@
23The :mod:`~openlp.plugins.songs.forms.editsongform` module contains the form23The :mod:`~openlp.plugins.songs.forms.editsongform` module contains the form
24used to edit songs.24used to edit songs.
25"""25"""
26
27import logging26import logging
27import os
28import re28import re
29import os
30import shutil
3129
32from PyQt5 import QtCore, QtWidgets30from PyQt5 import QtCore, QtWidgets
3331
34from openlp.core.common import Registry, RegistryProperties, AppLocation, UiStrings, check_directory_exists, translate32from openlp.core.common import Registry, RegistryProperties, AppLocation, UiStrings, check_directory_exists, translate
35from openlp.core.common.path import Path, path_to_str33from openlp.core.common.languagemanager import get_natural_key
34from openlp.core.common.path import copyfile
36from openlp.core.lib import PluginStatus, MediaType, create_separated_list35from openlp.core.lib import PluginStatus, MediaType, create_separated_list
37from openlp.core.lib.ui import set_case_insensitive_completer, critical_error_message_box, find_and_set_in_combo_box36from openlp.core.lib.ui import set_case_insensitive_completer, critical_error_message_box, find_and_set_in_combo_box
38from openlp.core.ui.lib.filedialog import FileDialog37from openlp.core.ui.lib.filedialog import FileDialog
39from openlp.core.common.languagemanager import get_natural_key38from openlp.plugins.songs.forms.editsongdialog import Ui_EditSongDialog
39from openlp.plugins.songs.forms.editverseform import EditVerseForm
40from openlp.plugins.songs.forms.mediafilesform import MediaFilesForm
40from openlp.plugins.songs.lib import VerseType, clean_song41from openlp.plugins.songs.lib import VerseType, clean_song
41from openlp.plugins.songs.lib.db import Book, Song, Author, AuthorType, Topic, MediaFile, SongBookEntry42from openlp.plugins.songs.lib.db import Book, Song, Author, AuthorType, Topic, MediaFile, SongBookEntry
43from openlp.plugins.songs.lib.openlyricsxml import SongXML
42from openlp.plugins.songs.lib.ui import SongStrings44from openlp.plugins.songs.lib.ui import SongStrings
43from openlp.plugins.songs.lib.openlyricsxml import SongXML
44from openlp.plugins.songs.forms.editsongdialog import Ui_EditSongDialog
45from openlp.plugins.songs.forms.editverseform import EditVerseForm
46from openlp.plugins.songs.forms.mediafilesform import MediaFilesForm
4745
48log = logging.getLogger(__name__)46log = logging.getLogger(__name__)
4947
@@ -545,9 +543,9 @@
545 songbook_entry.entry)543 songbook_entry.entry)
546 self.audio_list_widget.clear()544 self.audio_list_widget.clear()
547 for media in self.song.media_files:545 for media in self.song.media_files:
548 media_file = QtWidgets.QListWidgetItem(os.path.split(media.file_name)[1])546 item = QtWidgets.QListWidgetItem(media.file_path.name)
549 media_file.setData(QtCore.Qt.UserRole, media.file_name)547 item.setData(QtCore.Qt.UserRole, media.file_path)
550 self.audio_list_widget.addItem(media_file)548 self.audio_list_widget.addItem(item)
551 self.title_edit.setFocus()549 self.title_edit.setFocus()
552 # Hide or show the preview button.550 # Hide or show the preview button.
553 self.preview_button.setVisible(preview)551 self.preview_button.setVisible(preview)
@@ -927,12 +925,11 @@
927 Loads file(s) from the filesystem.925 Loads file(s) from the filesystem.
928 """926 """
929 filters = '{text} (*)'.format(text=UiStrings().AllFiles)927 filters = '{text} (*)'.format(text=UiStrings().AllFiles)
930 file_paths, selected_filter = FileDialog.getOpenFileNames(928 file_paths, filter_used = FileDialog.getOpenFileNames(
931 self, translate('SongsPlugin.EditSongForm', 'Open File(s)'), Path(), filters)929 parent=self, caption=translate('SongsPlugin.EditSongForm', 'Open File(s)'), filter=filters)
932 for file_path in file_paths:930 for file_path in file_paths:
933 filename = path_to_str(file_path)931 item = QtWidgets.QListWidgetItem(file_path.name)
934 item = QtWidgets.QListWidgetItem(os.path.split(str(filename))[1])932 item.setData(QtCore.Qt.UserRole, file_path)
935 item.setData(QtCore.Qt.UserRole, filename)
936 self.audio_list_widget.addItem(item)933 self.audio_list_widget.addItem(item)
937934
938 def on_audio_add_from_media_button_clicked(self):935 def on_audio_add_from_media_button_clicked(self):
@@ -940,9 +937,9 @@
940 Loads file(s) from the media plugin.937 Loads file(s) from the media plugin.
941 """938 """
942 if self.media_form.exec():939 if self.media_form.exec():
943 for filename in self.media_form.get_selected_files():940 for file_path in self.media_form.get_selected_files():
944 item = QtWidgets.QListWidgetItem(os.path.split(str(filename))[1])941 item = QtWidgets.QListWidgetItem(file_path.name)
945 item.setData(QtCore.Qt.UserRole, filename)942 item.setData(QtCore.Qt.UserRole, file_path)
946 self.audio_list_widget.addItem(item)943 self.audio_list_widget.addItem(item)
947944
948 def on_audio_remove_button_clicked(self):945 def on_audio_remove_button_clicked(self):
@@ -1066,34 +1063,33 @@
1066 # Save the song here because we need a valid id for the audio files.1063 # Save the song here because we need a valid id for the audio files.
1067 clean_song(self.manager, self.song)1064 clean_song(self.manager, self.song)
1068 self.manager.save_object(self.song)1065 self.manager.save_object(self.song)
1069 audio_files = [a.file_name for a in self.song.media_files]1066 audio_paths = [a.file_path for a in self.song.media_files]
1070 log.debug(audio_files)1067 log.debug(audio_paths)
1071 save_path = os.path.join(str(AppLocation.get_section_data_path(self.media_item.plugin.name)), 'audio',1068 save_path = AppLocation.get_section_data_path(self.media_item.plugin.name) / 'audio' / str(self.song.id)
1072 str(self.song.id))1069 check_directory_exists(save_path)
1073 check_directory_exists(Path(save_path))
1074 self.song.media_files = []1070 self.song.media_files = []
1075 files = []1071 file_paths = []
1076 for row in range(self.audio_list_widget.count()):1072 for row in range(self.audio_list_widget.count()):
1077 item = self.audio_list_widget.item(row)1073 item = self.audio_list_widget.item(row)
1078 filename = item.data(QtCore.Qt.UserRole)1074 file_path = item.data(QtCore.Qt.UserRole)
1079 if not filename.startswith(save_path):1075 if save_path not in file_path.parents:
1080 old_file, filename = filename, os.path.join(save_path, os.path.split(filename)[1])1076 old_file_path, file_path = file_path, save_path / file_path.name
1081 shutil.copyfile(old_file, filename)1077 copyfile(old_file_path, file_path)
1082 files.append(filename)1078 file_paths.append(file_path)
1083 media_file = MediaFile()1079 media_file = MediaFile()
1084 media_file.file_name = filename1080 media_file.file_path = file_path
1085 media_file.type = 'audio'1081 media_file.type = 'audio'
1086 media_file.weight = row1082 media_file.weight = row
1087 self.song.media_files.append(media_file)1083 self.song.media_files.append(media_file)
1088 for audio in audio_files:1084 for audio_path in audio_paths:
1089 if audio not in files:1085 if audio_path not in file_paths:
1090 try:1086 try:
1091 os.remove(audio)1087 audio_path.unlink()
1092 except:1088 except:
1093 log.exception('Could not remove file: {audio}'.format(audio=audio))1089 log.exception('Could not remove file: {audio}'.format(audio=audio_path))
1094 if not files:1090 if not file_paths:
1095 try:1091 try:
1096 os.rmdir(save_path)1092 save_path.rmdir()
1097 except OSError:1093 except OSError:
1098 log.exception('Could not remove directory: {path}'.format(path=save_path))1094 log.exception('Could not remove directory: {path}'.format(path=save_path))
1099 clean_song(self.manager, self.song)1095 clean_song(self.manager, self.song)
11001096
=== modified file 'openlp/plugins/songs/forms/mediafilesform.py'
--- openlp/plugins/songs/forms/mediafilesform.py 2017-06-04 12:14:23 +0000
+++ openlp/plugins/songs/forms/mediafilesform.py 2017-09-30 23:24:21 +0000
@@ -41,12 +41,19 @@
41 QtCore.Qt.WindowCloseButtonHint)41 QtCore.Qt.WindowCloseButtonHint)
42 self.setupUi(self)42 self.setupUi(self)
4343
44 def populate_files(self, files):44 def populate_files(self, file_paths):
45 """
46 :param list[openlp.core.common.path.Path] file_paths:
47 :return:
48 """
45 self.file_list_widget.clear()49 self.file_list_widget.clear()
46 for file in files:50 for file_path in file_paths:
47 item = QtWidgets.QListWidgetItem(os.path.split(file)[1])51 item = QtWidgets.QListWidgetItem(file_path.name)
48 item.setData(QtCore.Qt.UserRole, file)52 item.setData(QtCore.Qt.UserRole, file_path)
49 self.file_list_widget.addItem(item)53 self.file_list_widget.addItem(item)
5054
51 def get_selected_files(self):55 def get_selected_files(self):
56 """
57 :rtype: list[openlp.core.common.path.Path]
58 """
52 return [item.data(QtCore.Qt.UserRole) for item in self.file_list_widget.selectedItems()]59 return [item.data(QtCore.Qt.UserRole) for item in self.file_list_widget.selectedItems()]
5360
=== modified file 'openlp/plugins/songs/forms/songexportform.py'
--- openlp/plugins/songs/forms/songexportform.py 2017-05-30 18:42:35 +0000
+++ openlp/plugins/songs/forms/songexportform.py 2017-09-30 23:24:21 +0000
@@ -27,9 +27,10 @@
2727
28from PyQt5 import QtCore, QtWidgets28from PyQt5 import QtCore, QtWidgets
2929
30from openlp.core.common import Registry, UiStrings, translate30from openlp.core.common import Registry, Settings, UiStrings, translate
31from openlp.core.lib import create_separated_list, build_icon31from openlp.core.lib import create_separated_list
32from openlp.core.lib.ui import critical_error_message_box32from openlp.core.lib.ui import critical_error_message_box
33from openlp.core.ui.lib import PathEdit, PathType
33from openlp.core.ui.lib.wizard import OpenLPWizard, WizardStrings34from openlp.core.ui.lib.wizard import OpenLPWizard, WizardStrings
34from openlp.plugins.songs.lib.db import Song35from openlp.plugins.songs.lib.db import Song
35from openlp.plugins.songs.lib.openlyricsexport import OpenLyricsExport36from openlp.plugins.songs.lib.openlyricsexport import OpenLyricsExport
@@ -76,7 +77,6 @@
76 self.search_line_edit.textEdited.connect(self.on_search_line_edit_changed)77 self.search_line_edit.textEdited.connect(self.on_search_line_edit_changed)
77 self.uncheck_button.clicked.connect(self.on_uncheck_button_clicked)78 self.uncheck_button.clicked.connect(self.on_uncheck_button_clicked)
78 self.check_button.clicked.connect(self.on_check_button_clicked)79 self.check_button.clicked.connect(self.on_check_button_clicked)
79 self.directory_button.clicked.connect(self.on_directory_button_clicked)
8080
81 def add_custom_pages(self):81 def add_custom_pages(self):
82 """82 """
@@ -120,21 +120,15 @@
120 self.grid_layout.setObjectName('range_layout')120 self.grid_layout.setObjectName('range_layout')
121 self.selected_list_widget = QtWidgets.QListWidget(self.export_song_page)121 self.selected_list_widget = QtWidgets.QListWidget(self.export_song_page)
122 self.selected_list_widget.setObjectName('selected_list_widget')122 self.selected_list_widget.setObjectName('selected_list_widget')
123 self.grid_layout.addWidget(self.selected_list_widget, 1, 0, 1, 1)123 self.grid_layout.addWidget(self.selected_list_widget, 1, 0, 1, 2)
124 # FIXME: self.horizontal_layout is already defined above?!?!? Replace with Path Eidt!124 self.output_directory_path_edit = PathEdit(
125 self.horizontal_layout = QtWidgets.QHBoxLayout()125 self.export_song_page, PathType.Directories,
126 self.horizontal_layout.setObjectName('horizontal_layout')126 dialog_caption=translate('SongsPlugin.ExportWizardForm', 'Select Destination Folder'), show_revert=False)
127 self.output_directory_path_edit.path = Settings().value('songs/last directory export')
127 self.directory_label = QtWidgets.QLabel(self.export_song_page)128 self.directory_label = QtWidgets.QLabel(self.export_song_page)
128 self.directory_label.setObjectName('directory_label')129 self.directory_label.setObjectName('directory_label')
129 self.horizontal_layout.addWidget(self.directory_label)130 self.grid_layout.addWidget(self.directory_label, 0, 0)
130 self.directory_line_edit = QtWidgets.QLineEdit(self.export_song_page)131 self.grid_layout.addWidget(self.output_directory_path_edit, 0, 1)
131 self.directory_line_edit.setObjectName('directory_line_edit')
132 self.horizontal_layout.addWidget(self.directory_line_edit)
133 self.directory_button = QtWidgets.QToolButton(self.export_song_page)
134 self.directory_button.setIcon(build_icon(':/exports/export_load.png'))
135 self.directory_button.setObjectName('directory_button')
136 self.horizontal_layout.addWidget(self.directory_button)
137 self.grid_layout.addLayout(self.horizontal_layout, 0, 0, 1, 1)
138 self.export_song_layout.addLayout(self.grid_layout)132 self.export_song_layout.addLayout(self.grid_layout)
139 self.addPage(self.export_song_page)133 self.addPage(self.export_song_page)
140134
@@ -188,11 +182,12 @@
188 self.selected_list_widget.addItem(song)182 self.selected_list_widget.addItem(song)
189 return True183 return True
190 elif self.currentPage() == self.export_song_page:184 elif self.currentPage() == self.export_song_page:
191 if not self.directory_line_edit.text():185 if not self.output_directory_path_edit.path:
192 critical_error_message_box(186 critical_error_message_box(
193 translate('SongsPlugin.ExportWizardForm', 'No Save Location specified'),187 translate('SongsPlugin.ExportWizardForm', 'No Save Location specified'),
194 translate('SongsPlugin.ExportWizardForm', 'You need to specify a directory.'))188 translate('SongsPlugin.ExportWizardForm', 'You need to specify a directory.'))
195 return False189 return False
190 Settings().setValue('songs/last directory export', self.output_directory_path_edit.path)
196 return True191 return True
197 elif self.currentPage() == self.progress_page:192 elif self.currentPage() == self.progress_page:
198 self.available_list_widget.clear()193 self.available_list_widget.clear()
@@ -211,8 +206,6 @@
211 self.finish_button.setVisible(False)206 self.finish_button.setVisible(False)
212 self.cancel_button.setVisible(True)207 self.cancel_button.setVisible(True)
213 self.available_list_widget.clear()208 self.available_list_widget.clear()
214 self.selected_list_widget.clear()
215 self.directory_line_edit.clear()
216 self.search_line_edit.clear()209 self.search_line_edit.clear()
217 # Load the list of songs.210 # Load the list of songs.
218 self.application.set_busy_cursor()211 self.application.set_busy_cursor()
@@ -247,7 +240,7 @@
247 song.data(QtCore.Qt.UserRole)240 song.data(QtCore.Qt.UserRole)
248 for song in find_list_widget_items(self.selected_list_widget)241 for song in find_list_widget_items(self.selected_list_widget)
249 ]242 ]
250 exporter = OpenLyricsExport(self, songs, self.directory_line_edit.text())243 exporter = OpenLyricsExport(self, songs, self.output_directory_path_edit.path)
251 try:244 try:
252 if exporter.do_export():245 if exporter.do_export():
253 self.progress_label.setText(246 self.progress_label.setText(
@@ -291,15 +284,6 @@
291 if not item.isHidden():284 if not item.isHidden():
292 item.setCheckState(QtCore.Qt.Checked)285 item.setCheckState(QtCore.Qt.Checked)
293286
294 def on_directory_button_clicked(self):
295 """
296 Called when the *directory_button* was clicked. Opens a dialog and writes
297 the path to *directory_line_edit*.
298 """
299 self.get_folder(
300 translate('SongsPlugin.ExportWizardForm', 'Select Destination Folder'),
301 self.directory_line_edit, 'last directory export')
302
303287
304def find_list_widget_items(list_widget, text=''):288def find_list_widget_items(list_widget, text=''):
305 """289 """
306290
=== modified file 'openlp/plugins/songs/forms/songimportform.py'
--- openlp/plugins/songs/forms/songimportform.py 2017-08-26 15:06:11 +0000
+++ openlp/plugins/songs/forms/songimportform.py 2017-09-30 23:24:21 +0000
@@ -22,15 +22,13 @@
22"""22"""
23The song import functions for OpenLP.23The song import functions for OpenLP.
24"""24"""
25import codecs
26import logging25import logging
27import os
2826
29from PyQt5 import QtCore, QtWidgets27from PyQt5 import QtCore, QtWidgets
3028
31from openlp.core.common import RegistryProperties, Settings, UiStrings, translate29from openlp.core.common import RegistryProperties, Settings, UiStrings, translate
32from openlp.core.common.path import path_to_str, str_to_path
33from openlp.core.lib.ui import critical_error_message_box30from openlp.core.lib.ui import critical_error_message_box
31from openlp.core.ui.lib import PathEdit, PathType
34from openlp.core.ui.lib.filedialog import FileDialog32from openlp.core.ui.lib.filedialog import FileDialog
35from openlp.core.ui.lib.wizard import OpenLPWizard, WizardStrings33from openlp.core.ui.lib.wizard import OpenLPWizard, WizardStrings
36from openlp.plugins.songs.lib.importer import SongFormat, SongFormatSelect34from openlp.plugins.songs.lib.importer import SongFormat, SongFormatSelect
@@ -93,9 +91,7 @@
93 self.format_widgets[song_format]['addButton'].clicked.connect(self.on_add_button_clicked)91 self.format_widgets[song_format]['addButton'].clicked.connect(self.on_add_button_clicked)
94 self.format_widgets[song_format]['removeButton'].clicked.connect(self.on_remove_button_clicked)92 self.format_widgets[song_format]['removeButton'].clicked.connect(self.on_remove_button_clicked)
95 else:93 else:
96 self.format_widgets[song_format]['browseButton'].clicked.connect(self.on_browse_button_clicked)94 self.format_widgets[song_format]['path_edit'].pathChanged.connect(self.on_path_edit_path_changed)
97 self.format_widgets[song_format]['file_path_edit'].textChanged.\
98 connect(self.on_filepath_edit_text_changed)
9995
100 def add_custom_pages(self):96 def add_custom_pages(self):
101 """97 """
@@ -155,7 +151,6 @@
155 self.format_widgets[format_list]['removeButton'].setText(151 self.format_widgets[format_list]['removeButton'].setText(
156 translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))152 translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
157 else:153 else:
158 self.format_widgets[format_list]['browseButton'].setText(UiStrings().Browse)
159 f_label = 'Filename:'154 f_label = 'Filename:'
160 if select_mode == SongFormatSelect.SingleFolder:155 if select_mode == SongFormatSelect.SingleFolder:
161 f_label = 'Folder:'156 f_label = 'Folder:'
@@ -172,16 +167,11 @@
172 self.error_save_to_button.setText(translate('SongsPlugin.ImportWizardForm', 'Save to File'))167 self.error_save_to_button.setText(translate('SongsPlugin.ImportWizardForm', 'Save to File'))
173 # Align all QFormLayouts towards each other.168 # Align all QFormLayouts towards each other.
174 formats = [f for f in SongFormat.get_format_list() if 'filepathLabel' in self.format_widgets[f]]169 formats = [f for f in SongFormat.get_format_list() if 'filepathLabel' in self.format_widgets[f]]
175 labels = [self.format_widgets[f]['filepathLabel'] for f in formats]170 labels = [self.format_widgets[f]['filepathLabel'] for f in formats] + [self.format_label]
176 # Get max width of all labels171 # Get max width of all labels
177 max_label_width = max(self.format_label.minimumSizeHint().width(),172 max_label_width = max(labels, key=lambda label: label.minimumSizeHint().width()).minimumSizeHint().width()
178 max([label.minimumSizeHint().width() for label in labels]))173 for label in labels:
179 self.format_spacer.changeSize(max_label_width, 0, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)174 label.setFixedWidth(max_label_width)
180 spacers = [self.format_widgets[f]['filepathSpacer'] for f in formats]
181 for index, spacer in enumerate(spacers):
182 spacer.changeSize(
183 max_label_width - labels[index].minimumSizeHint().width(), 0,
184 QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
185 # Align descriptionLabels with rest of layout175 # Align descriptionLabels with rest of layout
186 for format_list in SongFormat.get_format_list():176 for format_list in SongFormat.get_format_list():
187 if SongFormat.get(format_list, 'descriptionText') is not None:177 if SongFormat.get(format_list, 'descriptionText') is not None:
@@ -209,13 +199,13 @@
209 Settings().setValue('songs/last import type', this_format)199 Settings().setValue('songs/last import type', this_format)
210 select_mode, class_, error_msg = SongFormat.get(this_format, 'selectMode', 'class', 'invalidSourceMsg')200 select_mode, class_, error_msg = SongFormat.get(this_format, 'selectMode', 'class', 'invalidSourceMsg')
211 if select_mode == SongFormatSelect.MultipleFiles:201 if select_mode == SongFormatSelect.MultipleFiles:
212 import_source = self.get_list_of_files(self.format_widgets[this_format]['file_list_widget'])202 import_source = self.get_list_of_paths(self.format_widgets[this_format]['file_list_widget'])
213 error_title = UiStrings().IFSp203 error_title = UiStrings().IFSp
214 focus_button = self.format_widgets[this_format]['addButton']204 focus_button = self.format_widgets[this_format]['addButton']
215 else:205 else:
216 import_source = self.format_widgets[this_format]['file_path_edit'].text()206 import_source = self.format_widgets[this_format]['path_edit'].path
217 error_title = (UiStrings().IFSs if select_mode == SongFormatSelect.SingleFile else UiStrings().IFdSs)207 error_title = (UiStrings().IFSs if select_mode == SongFormatSelect.SingleFile else UiStrings().IFdSs)
218 focus_button = self.format_widgets[this_format]['browseButton']208 focus_button = self.format_widgets[this_format]['path_edit']
219 if not class_.is_valid_source(import_source):209 if not class_.is_valid_source(import_source):
220 critical_error_message_box(error_title, error_msg)210 critical_error_message_box(error_title, error_msg)
221 focus_button.setFocus()211 focus_button.setFocus()
@@ -238,20 +228,23 @@
238 if filters:228 if filters:
239 filters += ';;'229 filters += ';;'
240 filters += '{text} (*)'.format(text=UiStrings().AllFiles)230 filters += '{text} (*)'.format(text=UiStrings().AllFiles)
241 file_paths, selected_filter = FileDialog.getOpenFileNames(231 file_paths, filter_used = FileDialog.getOpenFileNames(
242 self, title, Settings().value(self.plugin.settings_section + '/last directory import'), filters)232 self, title,
233 Settings().value(self.plugin.settings_section + '/last directory import'), filters)
234 for file_path in file_paths:
235 list_item = QtWidgets.QListWidgetItem(str(file_path))
236 list_item.setData(QtCore.Qt.UserRole, file_path)
237 listbox.addItem(list_item)
243 if file_paths:238 if file_paths:
244 file_names = [path_to_str(file_path) for file_path in file_paths]
245 listbox.addItems(file_names)
246 Settings().setValue(self.plugin.settings_section + '/last directory import', file_paths[0].parent)239 Settings().setValue(self.plugin.settings_section + '/last directory import', file_paths[0].parent)
247240
248 def get_list_of_files(self, list_box):241 def get_list_of_paths(self, list_box):
249 """242 """
250 Return a list of file from the list_box243 Return a list of file from the list_box
251244
252 :param list_box: The source list box245 :param list_box: The source list box
253 """246 """
254 return [list_box.item(i).text() for i in range(list_box.count())]247 return [list_box.item(i).data(QtCore.Qt.UserRole) for i in range(list_box.count())]
255248
256 def remove_selected_items(self, list_box):249 def remove_selected_items(self, list_box):
257 """250 """
@@ -263,20 +256,6 @@
263 item = list_box.takeItem(list_box.row(item))256 item = list_box.takeItem(list_box.row(item))
264 del item257 del item
265258
266 def on_browse_button_clicked(self):
267 """
268 Browse for files or a directory.
269 """
270 this_format = self.current_format
271 select_mode, format_name, ext_filter = SongFormat.get(this_format, 'selectMode', 'name', 'filter')
272 file_path_edit = self.format_widgets[this_format]['file_path_edit']
273 if select_mode == SongFormatSelect.SingleFile:
274 self.get_file_name(WizardStrings.OpenTypeFile.format(file_type=format_name),
275 file_path_edit, 'last directory import', ext_filter)
276 elif select_mode == SongFormatSelect.SingleFolder:
277 self.get_folder(
278 WizardStrings.OpenTypeFolder.format(folder_name=format_name), file_path_edit, 'last directory import')
279
280 def on_add_button_clicked(self):259 def on_add_button_clicked(self):
281 """260 """
282 Add a file or directory.261 Add a file or directory.
@@ -296,7 +275,7 @@
296 self.remove_selected_items(self.format_widgets[self.current_format]['file_list_widget'])275 self.remove_selected_items(self.format_widgets[self.current_format]['file_list_widget'])
297 self.source_page.completeChanged.emit()276 self.source_page.completeChanged.emit()
298277
299 def on_filepath_edit_text_changed(self):278 def on_path_edit_path_changed(self):
300 """279 """
301 Called when the content of the Filename/Folder edit box changes.280 Called when the content of the Filename/Folder edit box changes.
302 """281 """
@@ -317,8 +296,6 @@
317 select_mode = SongFormat.get(format_list, 'selectMode')296 select_mode = SongFormat.get(format_list, 'selectMode')
318 if select_mode == SongFormatSelect.MultipleFiles:297 if select_mode == SongFormatSelect.MultipleFiles:
319 self.format_widgets[format_list]['file_list_widget'].clear()298 self.format_widgets[format_list]['file_list_widget'].clear()
320 else:
321 self.format_widgets[format_list]['file_path_edit'].setText('')
322 self.error_report_text_edit.clear()299 self.error_report_text_edit.clear()
323 self.error_report_text_edit.setHidden(True)300 self.error_report_text_edit.setHidden(True)
324 self.error_copy_to_button.setHidden(True)301 self.error_copy_to_button.setHidden(True)
@@ -341,14 +318,14 @@
341 select_mode = SongFormat.get(source_format, 'selectMode')318 select_mode = SongFormat.get(source_format, 'selectMode')
342 if select_mode == SongFormatSelect.SingleFile:319 if select_mode == SongFormatSelect.SingleFile:
343 importer = self.plugin.import_songs(source_format,320 importer = self.plugin.import_songs(source_format,
344 filename=self.format_widgets[source_format]['file_path_edit'].text())321 file_path=self.format_widgets[source_format]['path_edit'].path)
345 elif select_mode == SongFormatSelect.SingleFolder:322 elif select_mode == SongFormatSelect.SingleFolder:
346 importer = self.plugin.import_songs(source_format,323 importer = self.plugin.import_songs(source_format,
347 folder=self.format_widgets[source_format]['file_path_edit'].text())324 folder_path=self.format_widgets[source_format]['path_edit'].path)
348 else:325 else:
349 importer = self.plugin.import_songs(326 importer = self.plugin.import_songs(
350 source_format,327 source_format,
351 filenames=self.get_list_of_files(self.format_widgets[source_format]['file_list_widget']))328 file_paths=self.get_list_of_paths(self.format_widgets[source_format]['file_list_widget']))
352 importer.do_import()329 importer.do_import()
353 self.progress_label.setText(WizardStrings.FinishedImport)330 self.progress_label.setText(WizardStrings.FinishedImport)
354331
@@ -366,18 +343,17 @@
366 """343 """
367 file_path, filter_used = FileDialog.getSaveFileName(344 file_path, filter_used = FileDialog.getSaveFileName(
368 self, Settings().value(self.plugin.settings_section + '/last directory import'))345 self, Settings().value(self.plugin.settings_section + '/last directory import'))
369 if not file_path:346 if file_path is None:
370 return347 return
371 with file_path.open('w', encoding='utf-8') as report_file:348 file_path.write_text(self.error_report_text_edit.toPlainText(), encoding='utf-8')
372 report_file.write(self.error_report_text_edit.toPlainText())
373349
374 def add_file_select_item(self):350 def add_file_select_item(self):
375 """351 """
376 Add a file selection page.352 Add a file selection page.
377 """353 """
378 this_format = self.current_format354 this_format = self.current_format
379 prefix, can_disable, description_text, select_mode = \355 format_name, prefix, can_disable, description_text, select_mode, filters = \
380 SongFormat.get(this_format, 'prefix', 'canDisable', 'descriptionText', 'selectMode')356 SongFormat.get(this_format, 'name', 'prefix', 'canDisable', 'descriptionText', 'selectMode', 'filter')
381 page = QtWidgets.QWidget()357 page = QtWidgets.QWidget()
382 page.setObjectName(prefix + 'Page')358 page.setObjectName(prefix + 'Page')
383 if can_disable:359 if can_disable:
@@ -403,26 +379,23 @@
403 if select_mode == SongFormatSelect.SingleFile or select_mode == SongFormatSelect.SingleFolder:379 if select_mode == SongFormatSelect.SingleFile or select_mode == SongFormatSelect.SingleFolder:
404 file_path_layout = QtWidgets.QHBoxLayout()380 file_path_layout = QtWidgets.QHBoxLayout()
405 file_path_layout.setObjectName(prefix + '_file_path_layout')381 file_path_layout.setObjectName(prefix + '_file_path_layout')
406 file_path_layout.setContentsMargins(0, self.format_v_spacing, 0, 0)
407 file_path_label = QtWidgets.QLabel(import_widget)382 file_path_label = QtWidgets.QLabel(import_widget)
408 file_path_label.setObjectName(prefix + 'FilepathLabel')
409 file_path_layout.addWidget(file_path_label)383 file_path_layout.addWidget(file_path_label)
410 file_path_spacer = QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)384 if select_mode == SongFormatSelect.SingleFile:
411 file_path_layout.addSpacerItem(file_path_spacer)385 path_type = PathType.Files
412 file_path_edit = QtWidgets.QLineEdit(import_widget)386 dialog_caption = WizardStrings.OpenTypeFile.format(file_type=format_name)
413 file_path_edit.setObjectName(prefix + '_file_path_edit')387 else:
414 file_path_layout.addWidget(file_path_edit)388 path_type = PathType.Directories
415 browse_button = QtWidgets.QToolButton(import_widget)389 dialog_caption = WizardStrings.OpenTypeFolder.format(folder_name=format_name)
416 browse_button.setIcon(self.open_icon)390 path_edit = PathEdit(
417 browse_button.setObjectName(prefix + 'BrowseButton')391 parent=import_widget, path_type=path_type, dialog_caption=dialog_caption, show_revert=False)
418 file_path_layout.addWidget(browse_button)392 path_edit.filters = path_edit.filters + filters
393 path_edit.path = Settings().value(self.plugin.settings_section + '/last directory import')
394 file_path_layout.addWidget(path_edit)
419 import_layout.addLayout(file_path_layout)395 import_layout.addLayout(file_path_layout)
420 import_layout.addSpacerItem(self.stack_spacer)396 import_layout.addSpacerItem(self.stack_spacer)
421 self.format_widgets[this_format]['filepathLabel'] = file_path_label397 self.format_widgets[this_format]['filepathLabel'] = file_path_label
422 self.format_widgets[this_format]['filepathSpacer'] = file_path_spacer398 self.format_widgets[this_format]['path_edit'] = path_edit
423 self.format_widgets[this_format]['file_path_layout'] = file_path_layout
424 self.format_widgets[this_format]['file_path_edit'] = file_path_edit
425 self.format_widgets[this_format]['browseButton'] = browse_button
426 elif select_mode == SongFormatSelect.MultipleFiles:399 elif select_mode == SongFormatSelect.MultipleFiles:
427 file_list_widget = QtWidgets.QListWidget(import_widget)400 file_list_widget = QtWidgets.QListWidget(import_widget)
428 file_list_widget.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)401 file_list_widget.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
@@ -496,6 +469,8 @@
496 * or if SingleFolder mode, the specified folder exists469 * or if SingleFolder mode, the specified folder exists
497470
498 When this method returns True, the wizard's Next button is enabled.471 When this method returns True, the wizard's Next button is enabled.
472
473 :rtype: bool
499 """474 """
500 wizard = self.wizard()475 wizard = self.wizard()
501 this_format = wizard.current_format476 this_format = wizard.current_format
@@ -505,10 +480,10 @@
505 if wizard.format_widgets[this_format]['file_list_widget'].count() > 0:480 if wizard.format_widgets[this_format]['file_list_widget'].count() > 0:
506 return True481 return True
507 else:482 else:
508 file_path = str(wizard.format_widgets[this_format]['file_path_edit'].text())483 file_path = wizard.format_widgets[this_format]['path_edit'].path
509 if file_path:484 if file_path:
510 if select_mode == SongFormatSelect.SingleFile and os.path.isfile(file_path):485 if select_mode == SongFormatSelect.SingleFile and file_path.is_file():
511 return True486 return True
512 elif select_mode == SongFormatSelect.SingleFolder and os.path.isdir(file_path):487 elif select_mode == SongFormatSelect.SingleFolder and file_path.is_dir():
513 return True488 return True
514 return False489 return False
515490
=== modified file 'openlp/plugins/songs/lib/__init__.py'
--- openlp/plugins/songs/lib/__init__.py 2017-08-03 17:54:40 +0000
+++ openlp/plugins/songs/lib/__init__.py 2017-09-30 23:24:21 +0000
@@ -534,13 +534,13 @@
534 media_files = song_plugin.manager.get_all_objects(MediaFile, MediaFile.song_id == song_id)534 media_files = song_plugin.manager.get_all_objects(MediaFile, MediaFile.song_id == song_id)
535 for media_file in media_files:535 for media_file in media_files:
536 try:536 try:
537 os.remove(media_file.file_name)537 media_file.file_path.unlink()
538 except OSError:538 except OSError:
539 log.exception('Could not remove file: {name}'.format(name=media_file.file_name))539 log.exception('Could not remove file: {name}'.format(name=media_file.file_path))
540 try:540 try:
541 save_path = os.path.join(str(AppLocation.get_section_data_path(song_plugin.name)), 'audio', str(song_id))541 save_path = AppLocation.get_section_data_path(song_plugin.name) / 'audio' / str(song_id)
542 if os.path.exists(save_path):542 if save_path.exists():
543 os.rmdir(save_path)543 save_path.rmdir()
544 except OSError:544 except OSError:
545 log.exception('Could not remove directory: {path}'.format(path=save_path))545 log.exception('Could not remove directory: {path}'.format(path=save_path))
546 song_plugin.manager.delete_object(Song, song_id)546 song_plugin.manager.delete_object(Song, song_id)
547547
=== modified file 'openlp/plugins/songs/lib/db.py'
--- openlp/plugins/songs/lib/db.py 2016-12-31 11:01:36 +0000
+++ openlp/plugins/songs/lib/db.py 2017-09-30 23:24:21 +0000
@@ -23,14 +23,15 @@
23The :mod:`db` module provides the database and schema that is the backend for23The :mod:`db` module provides the database and schema that is the backend for
24the Songs plugin24the Songs plugin
25"""25"""
2626from contextlib import suppress
27from sqlalchemy import Column, ForeignKey, Table, types27from sqlalchemy import Column, ForeignKey, Table, types
28from sqlalchemy.orm import mapper, relation, reconstructor28from sqlalchemy.orm import mapper, relation, reconstructor
29from sqlalchemy.sql.expression import func, text29from sqlalchemy.sql.expression import func, text
3030
31from openlp.core.lib.db import BaseModel, init_db31from openlp.core.common.applocation import AppLocation
32from openlp.core.common.languagemanager import get_natural_key32from openlp.core.common.languagemanager import get_natural_key
33from openlp.core.lib import translate33from openlp.core.lib import translate
34from openlp.core.lib.db import BaseModel, PathType, init_db
3435
3536
36class Author(BaseModel):37class Author(BaseModel):
@@ -238,7 +239,7 @@
238239
239 **media_files Table**240 **media_files Table**
240 * id241 * id
241 * file_name242 * _file_path
242 * type243 * type
243244
244 **song_books Table**245 **song_books Table**
@@ -305,7 +306,7 @@
305 'media_files', metadata,306 'media_files', metadata,
306 Column('id', types.Integer(), primary_key=True),307 Column('id', types.Integer(), primary_key=True),
307 Column('song_id', types.Integer(), ForeignKey('songs.id'), default=None),308 Column('song_id', types.Integer(), ForeignKey('songs.id'), default=None),
308 Column('file_name', types.Unicode(255), nullable=False),309 Column('file_path', PathType, nullable=False),
309 Column('type', types.Unicode(64), nullable=False, default='audio'),310 Column('type', types.Unicode(64), nullable=False, default='audio'),
310 Column('weight', types.Integer(), default=0)311 Column('weight', types.Integer(), default=0)
311 )312 )
312313
=== modified file 'openlp/plugins/songs/lib/importers/cclifile.py'
--- openlp/plugins/songs/lib/importers/cclifile.py 2016-12-31 11:01:36 +0000
+++ openlp/plugins/songs/lib/importers/cclifile.py 2017-09-30 23:24:21 +0000
@@ -19,11 +19,9 @@
19# with this program; if not, write to the Free Software Foundation, Inc., 59 #19# with this program; if not, write to the Free Software Foundation, Inc., 59 #
20# Temple Place, Suite 330, Boston, MA 02111-1307 USA #20# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
21###############################################################################21###############################################################################
22
23import logging
24import os
25import chardet22import chardet
26import codecs23import codecs
24import logging
2725
28from openlp.core.lib import translate26from openlp.core.lib import translate
29from openlp.plugins.songs.lib import VerseType27from openlp.plugins.songs.lib import VerseType
@@ -48,7 +46,7 @@
48 :param manager: The song manager for the running OpenLP installation.46 :param manager: The song manager for the running OpenLP installation.
49 :param kwargs: The files to be imported.47 :param kwargs: The files to be imported.
50 """48 """
51 super(CCLIFileImport, self).__init__(manager, **kwargs)49 super().__init__(manager, **kwargs)
5250
53 def do_import(self):51 def do_import(self):
54 """52 """
@@ -56,37 +54,35 @@
56 """54 """
57 log.debug('Starting CCLI File Import')55 log.debug('Starting CCLI File Import')
58 self.import_wizard.progress_bar.setMaximum(len(self.import_source))56 self.import_wizard.progress_bar.setMaximum(len(self.import_source))
59 for filename in self.import_source:57 for file_path in self.import_source:
60 filename = str(filename)58 log.debug('Importing CCLI File: {name}'.format(name=file_path))
61 log.debug('Importing CCLI File: {name}'.format(name=filename))59 if file_path.is_file():
62 if os.path.isfile(filename):60 with file_path.open('rb') as detect_file:
63 detect_file = open(filename, 'rb')61 detect_content = detect_file.read(2048)
64 detect_content = detect_file.read(2048)62 try:
65 try:63 str(detect_content, 'utf-8')
66 str(detect_content, 'utf-8')64 details = {'confidence': 1, 'encoding': 'utf-8'}
67 details = {'confidence': 1, 'encoding': 'utf-8'}65 except UnicodeDecodeError:
68 except UnicodeDecodeError:66 details = chardet.detect(detect_content)
69 details = chardet.detect(detect_content)67 in_file = codecs.open(str(file_path), 'r', details['encoding'])
70 detect_file.close()68 if not in_file.read(1) == '\ufeff':
71 infile = codecs.open(filename, 'r', details['encoding'])
72 if not infile.read(1) == '\ufeff':
73 # not UTF or no BOM was found69 # not UTF or no BOM was found
74 infile.seek(0)70 in_file.seek(0)
75 lines = infile.readlines()71 lines = in_file.readlines()
76 infile.close()72 in_file.close()
77 ext = os.path.splitext(filename)[1]73 ext = file_path.suffix.lower()
78 if ext.lower() == '.usr' or ext.lower() == '.bin':74 if ext == '.usr' or ext == '.bin':
79 log.info('SongSelect USR format file found: {name}'.format(name=filename))75 log.info('SongSelect USR format file found: {name}'.format(name=file_path))
80 if not self.do_import_usr_file(lines):76 if not self.do_import_usr_file(lines):
81 self.log_error(filename)77 self.log_error(file_path)
82 elif ext.lower() == '.txt':78 elif ext == '.txt':
83 log.info('SongSelect TEXT format file found: {name}'.format(name=filename))79 log.info('SongSelect TEXT format file found: {name}'.format(name=file_path))
84 if not self.do_import_txt_file(lines):80 if not self.do_import_txt_file(lines):
85 self.log_error(filename)81 self.log_error(file_path)
86 else:82 else:
87 self.log_error(filename, translate('SongsPlugin.CCLIFileImport', 'The file does not have a valid '83 self.log_error(file_path, translate('SongsPlugin.CCLIFileImport',
88 'extension.'))84 'The file does not have a valid extension.'))
89 log.info('Extension {name} is not valid'.format(name=filename))85 log.info('Extension {name} is not valid'.format(name=file_path))
90 if self.stop_import_flag:86 if self.stop_import_flag:
91 return87 return
9288
9389
=== modified file 'openlp/plugins/songs/lib/importers/chordpro.py'
--- openlp/plugins/songs/lib/importers/chordpro.py 2017-02-26 21:14:49 +0000
+++ openlp/plugins/songs/lib/importers/chordpro.py 2017-09-30 23:24:21 +0000
@@ -47,12 +47,11 @@
47 """47 """
48 def do_import(self):48 def do_import(self):
49 self.import_wizard.progress_bar.setMaximum(len(self.import_source))49 self.import_wizard.progress_bar.setMaximum(len(self.import_source))
50 for filename in self.import_source:50 for file_path in self.import_source:
51 if self.stop_import_flag:51 if self.stop_import_flag:
52 return52 return
53 song_file = open(filename, 'rt')53 with file_path.open('rt') as song_file:
54 self.do_import_file(song_file)54 self.do_import_file(song_file)
55 song_file.close()
5655
57 def do_import_file(self, song_file):56 def do_import_file(self, song_file):
58 """57 """
5958
=== modified file 'openlp/plugins/songs/lib/importers/dreambeam.py'
--- openlp/plugins/songs/lib/importers/dreambeam.py 2016-12-31 11:01:36 +0000
+++ openlp/plugins/songs/lib/importers/dreambeam.py 2017-09-30 23:24:21 +0000
@@ -78,27 +78,29 @@
7878
79 def do_import(self):79 def do_import(self):
80 """80 """
81 Receive a single file or a list of files to import.81 Receive a single file_path or a list of files to import.
82 """82 """
83 if isinstance(self.import_source, list):83 if isinstance(self.import_source, list):
84 self.import_wizard.progress_bar.setMaximum(len(self.import_source))84 self.import_wizard.progress_bar.setMaximum(len(self.import_source))
85 for file in self.import_source:85 for file_path in self.import_source:
86 if self.stop_import_flag:86 if self.stop_import_flag:
87 return87 return
88 self.set_defaults()88 self.set_defaults()
89 parser = etree.XMLParser(remove_blank_text=True)89 parser = etree.XMLParser(remove_blank_text=True)
90 try:90 try:
91 parsed_file = etree.parse(open(file, 'r'), parser)91 with file_path.open('r') as xml_file:
92 parsed_file = etree.parse(xml_file, parser)
92 except etree.XMLSyntaxError:93 except etree.XMLSyntaxError:
93 log.exception('XML syntax error in file {name}'.format(name=file))94 log.exception('XML syntax error in file_path {name}'.format(name=file_path))
94 self.log_error(file, SongStrings.XMLSyntaxError)95 self.log_error(file_path, SongStrings.XMLSyntaxError)
95 continue96 continue
96 xml = etree.tostring(parsed_file).decode()97 xml = etree.tostring(parsed_file).decode()
97 song_xml = objectify.fromstring(xml)98 song_xml = objectify.fromstring(xml)
98 if song_xml.tag != 'DreamSong':99 if song_xml.tag != 'DreamSong':
99 self.log_error(100 self.log_error(
100 file,101 file_path,
101 translate('SongsPlugin.DreamBeamImport', 'Invalid DreamBeam song file. Missing DreamSong tag.'))102 translate('SongsPlugin.DreamBeamImport',
103 'Invalid DreamBeam song file_path. Missing DreamSong tag.'))
102 continue104 continue
103 if hasattr(song_xml, 'Version'):105 if hasattr(song_xml, 'Version'):
104 self.version = float(song_xml.Version.text)106 self.version = float(song_xml.Version.text)
@@ -144,4 +146,4 @@
144 else:146 else:
145 self.parse_author(author_copyright)147 self.parse_author(author_copyright)
146 if not self.finish():148 if not self.finish():
147 self.log_error(file)149 self.log_error(file_path)
148150
=== modified file 'openlp/plugins/songs/lib/importers/easyslides.py'
--- openlp/plugins/songs/lib/importers/easyslides.py 2017-01-12 21:31:01 +0000
+++ openlp/plugins/songs/lib/importers/easyslides.py 2017-09-30 23:24:21 +0000
@@ -47,7 +47,7 @@
47 def do_import(self):47 def do_import(self):
48 log.info('Importing EasySlides XML file {source}'.format(source=self.import_source))48 log.info('Importing EasySlides XML file {source}'.format(source=self.import_source))
49 parser = etree.XMLParser(remove_blank_text=True, recover=True)49 parser = etree.XMLParser(remove_blank_text=True, recover=True)
50 parsed_file = etree.parse(self.import_source, parser)50 parsed_file = etree.parse(str(self.import_source), parser)
51 xml = etree.tostring(parsed_file).decode()51 xml = etree.tostring(parsed_file).decode()
52 song_xml = objectify.fromstring(xml)52 song_xml = objectify.fromstring(xml)
53 self.import_wizard.progress_bar.setMaximum(len(song_xml.Item))53 self.import_wizard.progress_bar.setMaximum(len(song_xml.Item))
5454
=== modified file 'openlp/plugins/songs/lib/importers/easyworship.py'
--- openlp/plugins/songs/lib/importers/easyworship.py 2017-04-01 04:45:12 +0000
+++ openlp/plugins/songs/lib/importers/easyworship.py 2017-09-30 23:24:21 +0000
@@ -22,14 +22,15 @@
22"""22"""
23The :mod:`easyworship` module provides the functionality for importing EasyWorship song databases into OpenLP.23The :mod:`easyworship` module provides the functionality for importing EasyWorship song databases into OpenLP.
24"""24"""
2525import logging
26import os26import os
27import re
27import struct28import struct
28import re
29import zlib29import zlib
30import logging30
31import sqlite331import sqlite3
3232
33from openlp.core.common.path import Path
33from openlp.core.lib import translate34from openlp.core.lib import translate
34from openlp.plugins.songs.lib import VerseType35from openlp.plugins.songs.lib import VerseType
35from openlp.plugins.songs.lib import retrieve_windows_encoding, strip_rtf36from openlp.plugins.songs.lib import retrieve_windows_encoding, strip_rtf
@@ -76,9 +77,11 @@
76 """77 """
77 Determines the type of file to import and calls the appropiate method78 Determines the type of file to import and calls the appropiate method
78 """79 """
79 if self.import_source.lower().endswith('ews'):80 self.import_source = Path(self.import_source)
81 ext = self.import_source.suffix.lower()
82 if ext == '.ews':
80 self.import_ews()83 self.import_ews()
81 elif self.import_source.endswith('DB'):84 elif ext == '.db':
82 self.import_db()85 self.import_db()
83 else:86 else:
84 self.import_sqlite_db()87 self.import_sqlite_db()
@@ -91,11 +94,11 @@
91 or here: http://wiki.openlp.org/Development:EasyWorship_EWS_Format94 or here: http://wiki.openlp.org/Development:EasyWorship_EWS_Format
92 """95 """
93 # Open ews file if it exists96 # Open ews file if it exists
94 if not os.path.isfile(self.import_source):97 if not self.import_source.is_file():
95 log.debug('Given ews file does not exists.')98 log.debug('Given ews file does not exists.')
96 return99 return
97 # Make sure there is room for at least a header and one entry100 # Make sure there is room for at least a header and one entry
98 if os.path.getsize(self.import_source) < 892:101 if self.import_source.stat().st_size < 892:
99 log.debug('Given ews file is to small to contain valid data.')102 log.debug('Given ews file is to small to contain valid data.')
100 return103 return
101 # Take a stab at how text is encoded104 # Take a stab at how text is encoded
@@ -104,7 +107,7 @@
104 if not self.encoding:107 if not self.encoding:
105 log.debug('No encoding set.')108 log.debug('No encoding set.')
106 return109 return
107 self.ews_file = open(self.import_source, 'rb')110 self.ews_file = self.import_source.open('rb')
108 # EWS header, version '1.6'/' 3'/' 5':111 # EWS header, version '1.6'/' 3'/' 5':
109 # Offset Field Data type Length Details112 # Offset Field Data type Length Details
110 # --------------------------------------------------------------------------------------------------113 # --------------------------------------------------------------------------------------------------
@@ -199,23 +202,22 @@
199 Import the songs from the database202 Import the songs from the database
200 """203 """
201 # Open the DB and MB files if they exist204 # Open the DB and MB files if they exist
202 import_source_mb = self.import_source.replace('.DB', '.MB')205 import_source_mb = self.import_source.with_suffix('.MB')
203 if not os.path.isfile(self.import_source):206 if not self.import_source.is_file():
204 self.log_error(self.import_source, translate('SongsPlugin.EasyWorshipSongImport',207 self.log_error(self.import_source, translate('SongsPlugin.EasyWorshipSongImport',
205 'This file does not exist.'))208 'This file does not exist.'))
206 return209 return
207 if not os.path.isfile(import_source_mb):210 if not import_source_mb.is_file():
208 self.log_error(self.import_source, translate('SongsPlugin.EasyWorshipSongImport',211 self.log_error(self.import_source, translate('SongsPlugin.EasyWorshipSongImport',
209 'Could not find the "Songs.MB" file. It must be in the same '212 'Could not find the "Songs.MB" file. It must be in the same '
210 'folder as the "Songs.DB" file.'))213 'folder as the "Songs.DB" file.'))
211 return214 return
212 db_size = os.path.getsize(self.import_source)215 if self.import_source.stat().st_size < 0x800:
213 if db_size < 0x800:
214 self.log_error(self.import_source, translate('SongsPlugin.EasyWorshipSongImport',216 self.log_error(self.import_source, translate('SongsPlugin.EasyWorshipSongImport',
215 'This file is not a valid EasyWorship database.'))217 'This file is not a valid EasyWorship database.'))
216 return218 return
217 db_file = open(self.import_source, 'rb')219 db_file = self.import_source.open('rb')
218 self.memo_file = open(import_source_mb, 'rb')220 self.memo_file = import_source_mb.open('rb')
219 # Don't accept files that are clearly not paradox files221 # Don't accept files that are clearly not paradox files
220 record_size, header_size, block_size, first_block, num_fields = struct.unpack('<hhxb8xh17xh', db_file.read(35))222 record_size, header_size, block_size, first_block, num_fields = struct.unpack('<hhxb8xh17xh', db_file.read(35))
221 if header_size != 0x800 or block_size < 1 or block_size > 4:223 if header_size != 0x800 or block_size < 1 or block_size > 4:
@@ -340,52 +342,34 @@
340 db_file.close()342 db_file.close()
341 self.memo_file.close()343 self.memo_file.close()
342344
343 def _find_file(self, base_path, path_list):
344 """
345 Find the specified file, with the option of the file being at any level in the specified directory structure.
346
347 :param base_path: the location search in
348 :param path_list: the targeted file, preceded by directories that may be their parents relative to the base_path
349 :return: path for targeted file
350 """
351 target_file = ''
352 while len(path_list) > 0:
353 target_file = os.path.join(path_list[-1], target_file)
354 path_list = path_list[:len(path_list) - 1]
355 full_path = os.path.join(base_path, target_file)
356 full_path = full_path[:len(full_path) - 1]
357 if os.path.isfile(full_path):
358 return full_path
359 return ''
360
361 def import_sqlite_db(self):345 def import_sqlite_db(self):
362 """346 """
363 Import the songs from an EasyWorship 6 SQLite database347 Import the songs from an EasyWorship 6 SQLite database
364 """348 """
365 songs_db_path = self._find_file(self.import_source, ["Databases", "Data", "Songs.db"])349 songs_db_path = next(self.import_source.rglob('Songs.db'), None)
366 song_words_db_path = self._find_file(self.import_source, ["Databases", "Data", "SongWords.db"])350 song_words_db_path = next(self.import_source.rglob('SongWords.db'), None)
367 invalid_dir_msg = 'This does not appear to be a valid Easy Worship 6 database directory.'351 invalid_dir_msg = translate('SongsPlugin.EasyWorshipSongImport',
352 'This does not appear to be a valid Easy Worship 6 database directory.')
353 invalid_db_msg = translate('SongsPlugin.EasyWorshipSongImport', 'This is not a valid Easy Worship 6 database.')
368 # check to see if needed files are there354 # check to see if needed files are there
369 if not os.path.isfile(songs_db_path):355 if not (songs_db_path and songs_db_path.is_file()):
370 self.log_error(songs_db_path, translate('SongsPlugin.EasyWorshipSongImport', invalid_dir_msg))356 self.log_error(self.import_source, invalid_dir_msg)
371 return357 return
372 if not os.path.isfile(song_words_db_path):358 if not (song_words_db_path and song_words_db_path.is_file()):
373 self.log_error(song_words_db_path, translate('SongsPlugin.EasyWorshipSongImport', invalid_dir_msg))359 self.log_error(self.import_source, invalid_dir_msg)
374 return360 return
375 # get database handles361 # get database handles
376 songs_conn = sqlite3.connect(songs_db_path)362 songs_conn = sqlite3.connect(str(songs_db_path))
377 words_conn = sqlite3.connect(song_words_db_path)363 words_conn = sqlite3.connect(str(song_words_db_path))
378 if songs_conn is None or words_conn is None:364 if songs_conn is None or words_conn is None:
379 self.log_error(self.import_source, translate('SongsPlugin.EasyWorshipSongImport',365 self.log_error(self.import_source, invalid_db_msg)
380 'This is not a valid Easy Worship 6 database.'))
381 songs_conn.close()366 songs_conn.close()
382 words_conn.close()367 words_conn.close()
383 return368 return
384 songs_db = songs_conn.cursor()369 songs_db = songs_conn.cursor()
385 words_db = words_conn.cursor()370 words_db = words_conn.cursor()
386 if songs_conn is None or words_conn is None:371 if songs_conn is None or words_conn is None:
387 self.log_error(self.import_source, translate('SongsPlugin.EasyWorshipSongImport',372 self.log_error(self.import_source, invalid_db_msg)
388 'This is not a valid Easy Worship 6 database.'))
389 songs_conn.close()373 songs_conn.close()
390 words_conn.close()374 words_conn.close()
391 return375 return
392376
=== modified file 'openlp/plugins/songs/lib/importers/foilpresenter.py'
--- openlp/plugins/songs/lib/importers/foilpresenter.py 2017-05-30 18:42:35 +0000
+++ openlp/plugins/songs/lib/importers/foilpresenter.py 2017-09-30 23:24:21 +0000
@@ -82,10 +82,8 @@
82 </kategorien>82 </kategorien>
83 </foilpresenterfolie>83 </foilpresenterfolie>
84"""84"""
85
86import logging85import logging
87import re86import re
88import os
8987
90from lxml import etree, objectify88from lxml import etree, objectify
9189
@@ -121,10 +119,9 @@
121 for file_path in self.import_source:119 for file_path in self.import_source:
122 if self.stop_import_flag:120 if self.stop_import_flag:
123 return121 return
124 self.import_wizard.increment_progress_bar(122 self.import_wizard.increment_progress_bar(WizardStrings.ImportingType.format(source=file_path.name))
125 WizardStrings.ImportingType.format(source=os.path.basename(file_path)))
126 try:123 try:
127 parsed_file = etree.parse(file_path, parser)124 parsed_file = etree.parse(str(file_path), parser)
128 xml = etree.tostring(parsed_file).decode()125 xml = etree.tostring(parsed_file).decode()
129 self.foil_presenter.xml_to_song(xml)126 self.foil_presenter.xml_to_song(xml)
130 except etree.XMLSyntaxError:127 except etree.XMLSyntaxError:
131128
=== modified file 'openlp/plugins/songs/lib/importers/lyrix.py'
--- openlp/plugins/songs/lib/importers/lyrix.py 2016-12-31 11:01:36 +0000
+++ openlp/plugins/songs/lib/importers/lyrix.py 2017-09-30 23:24:21 +0000
@@ -50,12 +50,11 @@
50 if not isinstance(self.import_source, list):50 if not isinstance(self.import_source, list):
51 return51 return
52 self.import_wizard.progress_bar.setMaximum(len(self.import_source))52 self.import_wizard.progress_bar.setMaximum(len(self.import_source))
53 for filename in self.import_source:53 for file_path in self.import_source:
54 if self.stop_import_flag:54 if self.stop_import_flag:
55 return55 return
56 song_file = open(filename, 'rt', encoding='cp1251')56 with file_path.open('rt', encoding='cp1251') as song_file:
57 self.do_import_file(song_file)57 self.do_import_file(song_file)
58 song_file.close()
5958
60 def do_import_file(self, file):59 def do_import_file(self, file):
61 """60 """
6261
=== modified file 'openlp/plugins/songs/lib/importers/openlp.py'
--- openlp/plugins/songs/lib/importers/openlp.py 2017-05-30 18:42:35 +0000
+++ openlp/plugins/songs/lib/importers/openlp.py 2017-09-30 23:24:21 +0000
@@ -266,7 +266,7 @@
266 if has_media_files and song.media_files:266 if has_media_files and song.media_files:
267 for media_file in song.media_files:267 for media_file in song.media_files:
268 existing_media_file = self.manager.get_object_filtered(268 existing_media_file = self.manager.get_object_filtered(
269 MediaFile, MediaFile.file_name == media_file.file_name)269 MediaFile, MediaFile.file_path == media_file.file_path)
270 if existing_media_file:270 if existing_media_file:
271 new_song.media_files.append(existing_media_file)271 new_song.media_files.append(existing_media_file)
272 else:272 else:
273273
=== modified file 'openlp/plugins/songs/lib/importers/openlyrics.py'
--- openlp/plugins/songs/lib/importers/openlyrics.py 2017-05-30 18:42:35 +0000
+++ openlp/plugins/songs/lib/importers/openlyrics.py 2017-09-30 23:24:21 +0000
@@ -23,9 +23,7 @@
23The :mod:`openlyrics` module provides the functionality for importing23The :mod:`openlyrics` module provides the functionality for importing
24songs which are saved as OpenLyrics files.24songs which are saved as OpenLyrics files.
25"""25"""
26
27import logging26import logging
28import os
2927
30from lxml import etree28from lxml import etree
3129
@@ -58,12 +56,11 @@
58 for file_path in self.import_source:56 for file_path in self.import_source:
59 if self.stop_import_flag:57 if self.stop_import_flag:
60 return58 return
61 self.import_wizard.increment_progress_bar(59 self.import_wizard.increment_progress_bar(WizardStrings.ImportingType.format(source=file_path.name))
62 WizardStrings.ImportingType.format(source=os.path.basename(file_path)))
63 try:60 try:
64 # Pass a file object, because lxml does not cope with some61 # Pass a file object, because lxml does not cope with some
65 # special characters in the path (see lp:757673 and lp:744337).62 # special characters in the path (see lp:757673 and lp:744337).
66 parsed_file = etree.parse(open(file_path, 'rb'), parser)63 parsed_file = etree.parse(file_path.open('rb'), parser)
67 xml = etree.tostring(parsed_file).decode()64 xml = etree.tostring(parsed_file).decode()
68 self.open_lyrics.xml_to_song(xml)65 self.open_lyrics.xml_to_song(xml)
69 except etree.XMLSyntaxError:66 except etree.XMLSyntaxError:
7067
=== modified file 'openlp/plugins/songs/lib/importers/openoffice.py'
--- openlp/plugins/songs/lib/importers/openoffice.py 2016-12-31 11:01:36 +0000
+++ openlp/plugins/songs/lib/importers/openoffice.py 2017-09-30 23:24:21 +0000
@@ -20,7 +20,6 @@
20# Temple Place, Suite 330, Boston, MA 02111-1307 USA #20# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
21###############################################################################21###############################################################################
22import logging22import logging
23import os
24import time23import time
2524
26from PyQt5 import QtCore25from PyQt5 import QtCore
@@ -70,12 +69,11 @@
70 log.error(exc)69 log.error(exc)
71 return70 return
72 self.import_wizard.progress_bar.setMaximum(len(self.import_source))71 self.import_wizard.progress_bar.setMaximum(len(self.import_source))
73 for filename in self.import_source:72 for file_path in self.import_source:
74 if self.stop_import_flag:73 if self.stop_import_flag:
75 break74 break
76 filename = str(filename)75 if file_path.is_file():
77 if os.path.isfile(filename):76 self.open_ooo_file(file_path)
78 self.open_ooo_file(filename)
79 if self.document:77 if self.document:
80 self.process_ooo_document()78 self.process_ooo_document()
81 self.close_ooo_file()79 self.close_ooo_file()
@@ -144,12 +142,7 @@
144 Open the passed file in OpenOffice.org Impress142 Open the passed file in OpenOffice.org Impress
145 """143 """
146 self.file_path = file_path144 self.file_path = file_path
147 if is_win():145 url = file_path.as_uri()
148 url = file_path.replace('\\', '/')
149 url = url.replace(':', '|').replace(' ', '%20')
150 url = 'file:///' + url
151 else:
152 url = uno.systemPathToFileUrl(file_path)
153 properties = []146 properties = []
154 properties.append(self.create_property('Hidden', True))147 properties.append(self.create_property('Hidden', True))
155 properties = tuple(properties)148 properties = tuple(properties)
@@ -159,7 +152,7 @@
159 self.document.supportsService("com.sun.star.text.TextDocument"):152 self.document.supportsService("com.sun.star.text.TextDocument"):
160 self.close_ooo_file()153 self.close_ooo_file()
161 else:154 else:
162 self.import_wizard.increment_progress_bar('Processing file ' + file_path, 0)155 self.import_wizard.increment_progress_bar('Processing file {file_path}'.format(file_path=file_path), 0)
163 except AttributeError:156 except AttributeError:
164 log.exception("open_ooo_file failed: {url}".format(url=url))157 log.exception("open_ooo_file failed: {url}".format(url=url))
165 return158 return
166159
=== modified file 'openlp/plugins/songs/lib/importers/opensong.py'
--- openlp/plugins/songs/lib/importers/opensong.py 2017-02-26 21:14:49 +0000
+++ openlp/plugins/songs/lib/importers/opensong.py 2017-09-30 23:24:21 +0000
@@ -19,7 +19,6 @@
19# with this program; if not, write to the Free Software Foundation, Inc., 59 #19# with this program; if not, write to the Free Software Foundation, Inc., 59 #
20# Temple Place, Suite 330, Boston, MA 02111-1307 USA #20# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
21###############################################################################21###############################################################################
22
23import logging22import logging
24import re23import re
2524
@@ -116,12 +115,11 @@
116 if not isinstance(self.import_source, list):115 if not isinstance(self.import_source, list):
117 return116 return
118 self.import_wizard.progress_bar.setMaximum(len(self.import_source))117 self.import_wizard.progress_bar.setMaximum(len(self.import_source))
119 for filename in self.import_source:118 for file_path in self.import_source:
120 if self.stop_import_flag:119 if self.stop_import_flag:
121 return120 return
122 song_file = open(filename, 'rb')121 with file_path.open('rb') as song_file:
123 self.do_import_file(song_file)122 self.do_import_file(song_file)
124 song_file.close()
125123
126 def do_import_file(self, file):124 def do_import_file(self, file):
127 """125 """
128126
=== modified file 'openlp/plugins/songs/lib/importers/opspro.py'
--- openlp/plugins/songs/lib/importers/opspro.py 2016-12-31 11:01:36 +0000
+++ openlp/plugins/songs/lib/importers/opspro.py 2017-09-30 23:24:21 +0000
@@ -231,16 +231,15 @@
231 xor_pattern_2k = (0xa1, 0xec, 0x7a, 0x9c, 0xe1, 0x28, 0x34, 0x8a, 0x73, 0x7b, 0xd2, 0xdf, 0x50)231 xor_pattern_2k = (0xa1, 0xec, 0x7a, 0x9c, 0xe1, 0x28, 0x34, 0x8a, 0x73, 0x7b, 0xd2, 0xdf, 0x50)
232 # Access97 XOR of the source232 # Access97 XOR of the source
233 xor_pattern_97 = (0x86, 0xfb, 0xec, 0x37, 0x5d, 0x44, 0x9c, 0xfa, 0xc6, 0x5e, 0x28, 0xe6, 0x13)233 xor_pattern_97 = (0x86, 0xfb, 0xec, 0x37, 0x5d, 0x44, 0x9c, 0xfa, 0xc6, 0x5e, 0x28, 0xe6, 0x13)
234 mdb = open(self.import_source, 'rb')234 with self.import_source.open('rb') as mdb_file:
235 mdb.seek(0x14)235 mdb_file.seek(0x14)
236 version = struct.unpack('B', mdb.read(1))[0]236 version = struct.unpack('B', mdb_file.read(1))[0]
237 # Get encrypted logo237 # Get encrypted logo
238 mdb.seek(0x62)238 mdb_file.seek(0x62)
239 EncrypFlag = struct.unpack('B', mdb.read(1))[0]239 EncrypFlag = struct.unpack('B', mdb_file.read(1))[0]
240 # Get encrypted password240 # Get encrypted password
241 mdb.seek(0x42)241 mdb_file.seek(0x42)
242 encrypted_password = mdb.read(26)242 encrypted_password = mdb_file.read(26)
243 mdb.close()
244 # "Decrypt" the password based on the version243 # "Decrypt" the password based on the version
245 decrypted_password = ''244 decrypted_password = ''
246 if version < 0x01:245 if version < 0x01:
247246
=== modified file 'openlp/plugins/songs/lib/importers/powerpraise.py'
--- openlp/plugins/songs/lib/importers/powerpraise.py 2017-05-30 18:42:35 +0000
+++ openlp/plugins/songs/lib/importers/powerpraise.py 2017-09-30 23:24:21 +0000
@@ -23,8 +23,6 @@
23The :mod:`powerpraiseimport` module provides the functionality for importing23The :mod:`powerpraiseimport` module provides the functionality for importing
24Powerpraise song files into the current database.24Powerpraise song files into the current database.
25"""25"""
26
27import os
28from lxml import objectify26from lxml import objectify
2927
30from openlp.core.ui.lib.wizard import WizardStrings28from openlp.core.ui.lib.wizard import WizardStrings
@@ -41,10 +39,10 @@
41 for file_path in self.import_source:39 for file_path in self.import_source:
42 if self.stop_import_flag:40 if self.stop_import_flag:
43 return41 return
44 self.import_wizard.increment_progress_bar(42 self.import_wizard.increment_progress_bar(WizardStrings.ImportingType.format(source=file_path.name))
45 WizardStrings.ImportingType.format(source=os.path.basename(file_path)))43 with file_path.open('rb') as xml_file:
46 root = objectify.parse(open(file_path, 'rb')).getroot()44 root = objectify.parse(xml_file).getroot()
47 self.process_song(root)45 self.process_song(root)
4846
49 def process_song(self, root):47 def process_song(self, root):
50 self.set_defaults()48 self.set_defaults()
5149
=== modified file 'openlp/plugins/songs/lib/importers/powersong.py'
--- openlp/plugins/songs/lib/importers/powersong.py 2016-12-31 11:01:36 +0000
+++ openlp/plugins/songs/lib/importers/powersong.py 2017-09-30 23:24:21 +0000
@@ -72,10 +72,14 @@
72 Checks if source is a PowerSong 1.0 folder:72 Checks if source is a PowerSong 1.0 folder:
73 * is a directory73 * is a directory
74 * contains at least one \*.song file74 * contains at least one \*.song file
75
76 :param openlp.core.common.path.Path import_source: Should be a Path object that fulfills the above criteria
77 :return: If the source is valid
78 :rtype: bool
75 """79 """
76 if os.path.isdir(import_source):80 if import_source.is_dir():
77 for file in os.listdir(import_source):81 for file_path in import_source.iterdir():
78 if fnmatch.fnmatch(file, '*.song'):82 if file_path.suffix == '.song':
79 return True83 return True
80 return False84 return False
8185
8286
=== modified file 'openlp/plugins/songs/lib/importers/presentationmanager.py'
--- openlp/plugins/songs/lib/importers/presentationmanager.py 2017-05-30 18:42:35 +0000
+++ openlp/plugins/songs/lib/importers/presentationmanager.py 2017-09-30 23:24:21 +0000
@@ -23,13 +23,11 @@
23The :mod:`presentationmanager` module provides the functionality for importing23The :mod:`presentationmanager` module provides the functionality for importing
24Presentationmanager song files into the current database.24Presentationmanager song files into the current database.
25"""25"""
26import os
27import re26import re
2827
29import chardet
30from lxml import objectify, etree28from lxml import objectify, etree
3129
32from openlp.core.common import translate30from openlp.core.common import get_file_encoding, translate
33from openlp.core.ui.lib.wizard import WizardStrings31from openlp.core.ui.lib.wizard import WizardStrings
34from .songimport import SongImport32from .songimport import SongImport
3533
@@ -44,17 +42,14 @@
44 for file_path in self.import_source:42 for file_path in self.import_source:
45 if self.stop_import_flag:43 if self.stop_import_flag:
46 return44 return
47 self.import_wizard.increment_progress_bar(45 self.import_wizard.increment_progress_bar(WizardStrings.ImportingType.format(source=file_path.name))
48 WizardStrings.ImportingType.format(source=os.path.basename(file_path)))
49 try:46 try:
50 tree = etree.parse(file_path, parser=etree.XMLParser(recover=True))47 tree = etree.parse(str(file_path), parser=etree.XMLParser(recover=True))
51 except etree.XMLSyntaxError:48 except etree.XMLSyntaxError:
52 # Try to detect encoding and use it49 # Try to detect encoding and use it
53 file = open(file_path, mode='rb')50 encoding = get_file_encoding(file_path)['encoding']
54 encoding = chardet.detect(file.read())['encoding']
55 file.close()
56 # Open file with detected encoding and remove encoding declaration51 # Open file with detected encoding and remove encoding declaration
57 text = open(file_path, mode='r', encoding=encoding).read()52 text = file_path.read_text(encoding=encoding)
58 text = re.sub('.+\?>\n', '', text)53 text = re.sub('.+\?>\n', '', text)
59 try:54 try:
60 tree = etree.fromstring(text, parser=etree.XMLParser(recover=True))55 tree = etree.fromstring(text, parser=etree.XMLParser(recover=True))
@@ -80,6 +75,11 @@
80 return ''75 return ''
8176
82 def process_song(self, root, file_path):77 def process_song(self, root, file_path):
78 """
79 :param root:
80 :param openlp.core.common.path.Path file_path: Path to the file to process
81 :rtype: None
82 """
83 self.set_defaults()83 self.set_defaults()
84 attrs = None84 attrs = None
85 if hasattr(root, 'attributes'):85 if hasattr(root, 'attributes'):
@@ -123,4 +123,4 @@
123123
124 self.verse_order_list = verse_order_list124 self.verse_order_list = verse_order_list
125 if not self.finish():125 if not self.finish():
126 self.log_error(os.path.basename(file_path))126 self.log_error(file_path.name)
127127
=== modified file 'openlp/plugins/songs/lib/importers/propresenter.py'
--- openlp/plugins/songs/lib/importers/propresenter.py 2017-05-30 18:42:35 +0000
+++ openlp/plugins/songs/lib/importers/propresenter.py 2017-09-30 23:24:21 +0000
@@ -23,8 +23,6 @@
23The :mod:`propresenter` module provides the functionality for importing23The :mod:`propresenter` module provides the functionality for importing
24ProPresenter song files into the current installation database.24ProPresenter song files into the current installation database.
25"""25"""
26
27import os
28import base6426import base64
29import logging27import logging
30from lxml import objectify28from lxml import objectify
@@ -47,11 +45,17 @@
47 if self.stop_import_flag:45 if self.stop_import_flag:
48 return46 return
49 self.import_wizard.increment_progress_bar(47 self.import_wizard.increment_progress_bar(
50 WizardStrings.ImportingType.format(source=os.path.basename(file_path)))48 WizardStrings.ImportingType.format(source=file_path.name))
51 root = objectify.parse(open(file_path, 'rb')).getroot()49 with file_path.open('rb') as xml_file:
52 self.process_song(root, file_path)50 root = objectify.parse(xml_file).getroot()
51 self.process_song(root, file_path)
5352
54 def process_song(self, root, filename):53 def process_song(self, root, file_path):
54 """
55 :param root:
56 :param openlp.core.common.path.Path file_path: Path to the file thats being imported
57 :rtype: None
58 """
55 self.set_defaults()59 self.set_defaults()
5660
57 # Extract ProPresenter versionNumber61 # Extract ProPresenter versionNumber
@@ -64,9 +68,7 @@
64 # Title68 # Title
65 self.title = root.get('CCLISongTitle')69 self.title = root.get('CCLISongTitle')
66 if not self.title or self.title == '':70 if not self.title or self.title == '':
67 self.title = os.path.basename(filename)71 self.title = file_path.stem
68 if self.title[-5:-1] == '.pro':
69 self.title = self.title[:-5]
70 # Notes72 # Notes
71 self.comments = root.get('notes')73 self.comments = root.get('notes')
72 # Author74 # Author
7375
=== modified file 'openlp/plugins/songs/lib/importers/songbeamer.py'
--- openlp/plugins/songs/lib/importers/songbeamer.py 2017-08-25 20:03:25 +0000
+++ openlp/plugins/songs/lib/importers/songbeamer.py 2017-09-30 23:24:21 +0000
@@ -112,7 +112,7 @@
112 if not isinstance(self.import_source, list):112 if not isinstance(self.import_source, list):
113 return113 return
114 self.import_wizard.progress_bar.setMaximum(len(self.import_source))114 self.import_wizard.progress_bar.setMaximum(len(self.import_source))
115 for import_file in self.import_source:115 for file_path in self.import_source:
116 # TODO: check that it is a valid SongBeamer file116 # TODO: check that it is a valid SongBeamer file
117 if self.stop_import_flag:117 if self.stop_import_flag:
118 return118 return
@@ -120,20 +120,19 @@
120 self.current_verse = ''120 self.current_verse = ''
121 self.current_verse_type = VerseType.tags[VerseType.Verse]121 self.current_verse_type = VerseType.tags[VerseType.Verse]
122 self.chord_table = None122 self.chord_table = None
123 file_name = os.path.split(import_file)[1]123 if file_path.is_file():
124 if os.path.isfile(import_file):
125 # Detect the encoding124 # Detect the encoding
126 self.input_file_encoding = get_file_encoding(Path(import_file))['encoding']125 self.input_file_encoding = get_file_encoding(file_path)['encoding']
127 # The encoding should only be ANSI (cp1252), UTF-8, Unicode, Big-Endian-Unicode.126 # The encoding should only be ANSI (cp1252), UTF-8, Unicode, Big-Endian-Unicode.
128 # So if it doesn't start with 'u' we default to cp1252. See:127 # So if it doesn't start with 'u' we default to cp1252. See:
129 # https://forum.songbeamer.com/viewtopic.php?p=419&sid=ca4814924e37c11e4438b7272a98b6f2128 # https://forum.songbeamer.com/viewtopic.php?p=419&sid=ca4814924e37c11e4438b7272a98b6f2
130 if not self.input_file_encoding.lower().startswith('u'):129 if not self.input_file_encoding.lower().startswith('u'):
131 self.input_file_encoding = 'cp1252'130 self.input_file_encoding = 'cp1252'
132 infile = open(import_file, 'rt', encoding=self.input_file_encoding)131 with file_path.open(encoding=self.input_file_encoding) as song_file:
133 song_data = infile.readlines()132 song_data = song_file.readlines()
134 else:133 else:
135 continue134 continue
136 self.title = file_name.split('.sng')[0]135 self.title = file_path.stem
137 read_verses = False136 read_verses = False
138 # The first verse separator doesn't count, but the others does, so line count starts at -1137 # The first verse separator doesn't count, but the others does, so line count starts at -1
139 line_number = -1138 line_number = -1
@@ -185,7 +184,7 @@
185 # inserted by songbeamer, but are manually added headings. So restart the loop, and184 # inserted by songbeamer, but are manually added headings. So restart the loop, and
186 # count tags as lines.185 # count tags as lines.
187 self.set_defaults()186 self.set_defaults()
188 self.title = file_name.split('.sng')[0]187 self.title = file_path.stem
189 verse_tags_mode = VerseTagMode.ContainsNoTagsRestart188 verse_tags_mode = VerseTagMode.ContainsNoTagsRestart
190 read_verses = False189 read_verses = False
191 # The first verseseparator doesn't count, but the others does, so linecount starts at -1190 # The first verseseparator doesn't count, but the others does, so linecount starts at -1
@@ -207,7 +206,7 @@
207 self.replace_html_tags()206 self.replace_html_tags()
208 self.add_verse(self.current_verse, self.current_verse_type)207 self.add_verse(self.current_verse, self.current_verse_type)
209 if not self.finish():208 if not self.finish():
210 self.log_error(import_file)209 self.log_error(file_path)
211210
212 def insert_chords(self, line_number, line):211 def insert_chords(self, line_number, line):
213 """212 """
@@ -414,14 +413,15 @@
414 """413 """
415 # The path is relative to SongBeamers Song folder414 # The path is relative to SongBeamers Song folder
416 if is_win():415 if is_win():
417 user_doc_folder = os.path.expandvars('$DOCUMENTS')416 user_doc_path = Path(os.path.expandvars('$DOCUMENTS'))
418 elif is_macosx():417 elif is_macosx():
419 user_doc_folder = os.path.join(os.path.expanduser('~'), 'Documents')418 user_doc_path = Path.home() / 'Documents'
420 else:419 else:
421 # SongBeamer only runs on mac and win...420 # SongBeamer only runs on mac and win...
422 return421 return
423 audio_file_path = os.path.normpath(os.path.join(user_doc_folder, 'SongBeamer', 'Songs', audio_file_path))422 audio_file_path = user_doc_path / 'SongBeamer' / 'Songs' / audio_file_path
424 if os.path.isfile(audio_file_path):423 if audio_file_path.is_file():
425 self.add_media_file(audio_file_path)424 self.add_media_file(audio_file_path)
426 else:425 else:
427 log.debug('Could not import mediafile "%s" since it does not exists!' % audio_file_path)426 log.debug('Could not import mediafile "{audio_file_path}" since it does not exists!'
427 .format(audio_file_path=audio_file_path))
428428
=== modified file 'openlp/plugins/songs/lib/importers/songimport.py'
--- openlp/plugins/songs/lib/importers/songimport.py 2017-08-25 20:03:25 +0000
+++ openlp/plugins/songs/lib/importers/songimport.py 2017-09-30 23:24:21 +0000
@@ -22,13 +22,11 @@
2222
23import logging23import logging
24import re24import re
25import shutil
26import os
2725
28from PyQt5 import QtCore26from PyQt5 import QtCore
2927
30from openlp.core.common import Registry, AppLocation, check_directory_exists, translate28from openlp.core.common import Registry, AppLocation, check_directory_exists, translate
31from openlp.core.common.path import Path29from openlp.core.common.path import copyfile
32from openlp.core.ui.lib.wizard import WizardStrings30from openlp.core.ui.lib.wizard import WizardStrings
33from openlp.plugins.songs.lib import clean_song, VerseType31from openlp.plugins.songs.lib import clean_song, VerseType
34from openlp.plugins.songs.lib.db import Song, Author, Topic, Book, MediaFile32from openlp.plugins.songs.lib.db import Song, Author, Topic, Book, MediaFile
@@ -62,14 +60,14 @@
62 """60 """
63 self.manager = manager61 self.manager = manager
64 QtCore.QObject.__init__(self)62 QtCore.QObject.__init__(self)
65 if 'filename' in kwargs:63 if 'file_path' in kwargs:
66 self.import_source = kwargs['filename']64 self.import_source = kwargs['file_path']
67 elif 'filenames' in kwargs:65 elif 'file_paths' in kwargs:
68 self.import_source = kwargs['filenames']66 self.import_source = kwargs['file_paths']
69 elif 'folder' in kwargs:67 elif 'folder_path' in kwargs:
70 self.import_source = kwargs['folder']68 self.import_source = kwargs['folder_path']
71 else:69 else:
72 raise KeyError('Keyword arguments "filename[s]" or "folder" not supplied.')70 raise KeyError('Keyword arguments "file_path[s]" or "folder_path" not supplied.')
73 log.debug(self.import_source)71 log.debug(self.import_source)
74 self.import_wizard = None72 self.import_wizard = None
75 self.song = None73 self.song = None
@@ -270,13 +268,13 @@
270 return268 return
271 self.authors.append((author, type))269 self.authors.append((author, type))
272270
273 def add_media_file(self, filename, weight=0):271 def add_media_file(self, file_path, weight=0):
274 """272 """
275 Add a media file to the list273 Add a media file to the list
276 """274 """
277 if filename in [x[0] for x in self.media_files]:275 if file_path in [x[0] for x in self.media_files]:
278 return276 return
279 self.media_files.append((filename, weight))277 self.media_files.append((file_path, weight))
280278
281 def add_verse(self, verse_text, verse_def='v', lang=None):279 def add_verse(self, verse_text, verse_def='v', lang=None):
282 """280 """
@@ -403,29 +401,30 @@
403 self.manager.save_object(song)401 self.manager.save_object(song)
404 # Now loop through the media files, copy them to the correct location,402 # Now loop through the media files, copy them to the correct location,
405 # and save the song again.403 # and save the song again.
406 for filename, weight in self.media_files:404 for file_path, weight in self.media_files:
407 media_file = self.manager.get_object_filtered(MediaFile, MediaFile.file_name == filename)405 media_file = self.manager.get_object_filtered(MediaFile, MediaFile.file_path == file_path)
408 if not media_file:406 if not media_file:
409 if os.path.dirname(filename):407 if file_path.parent:
410 filename = self.copy_media_file(song.id, filename)408 file_path = self.copy_media_file(song.id, file_path)
411 song.media_files.append(MediaFile.populate(file_name=filename, weight=weight))409 song.media_files.append(MediaFile.populate(file_path=file_path, weight=weight))
412 self.manager.save_object(song)410 self.manager.save_object(song)
413 self.set_defaults()411 self.set_defaults()
414 return True412 return True
415413
416 def copy_media_file(self, song_id, filename):414 def copy_media_file(self, song_id, file_path):
417 """415 """
418 This method copies the media file to the correct location and returns416 This method copies the media file to the correct location and returns
419 the new file location.417 the new file location.
420418
421 :param song_id:419 :param song_id:
422 :param filename: The file to copy.420 :param openlp.core.common.path.Path file_path: The file to copy.
421 :return: The new location of the file
422 :rtype: openlp.core.common.path.Path
423 """423 """
424 if not hasattr(self, 'save_path'):424 if not hasattr(self, 'save_path'):
425 self.save_path = os.path.join(str(AppLocation.get_section_data_path(self.import_wizard.plugin.name)),425 self.save_path = AppLocation.get_section_data_path(self.import_wizard.plugin.name) / 'audio' / str(song_id)
426 'audio', str(song_id))426 check_directory_exists(self.save_path)
427 check_directory_exists(Path(self.save_path))427 if self.save_path not in file_path.parents:
428 if not filename.startswith(self.save_path):428 old_path, file_path = file_path, self.save_path / file_path.name
429 old_file, filename = filename, os.path.join(self.save_path, os.path.split(filename)[1])429 copyfile(old_path, file_path)
430 shutil.copyfile(old_file, filename)430 return file_path
431 return filename
432431
=== modified file 'openlp/plugins/songs/lib/importers/songpro.py'
--- openlp/plugins/songs/lib/importers/songpro.py 2016-12-31 11:01:36 +0000
+++ openlp/plugins/songs/lib/importers/songpro.py 2017-09-30 23:24:21 +0000
@@ -25,6 +25,7 @@
25"""25"""
26import re26import re
2727
28from openlp.core.common.path import Path
28from openlp.plugins.songs.lib import strip_rtf29from openlp.plugins.songs.lib import strip_rtf
29from openlp.plugins.songs.lib.importers.songimport import SongImport30from openlp.plugins.songs.lib.importers.songimport import SongImport
3031
@@ -72,7 +73,8 @@
72 Receive a single file or a list of files to import.73 Receive a single file or a list of files to import.
73 """74 """
74 self.encoding = None75 self.encoding = None
75 with open(self.import_source, 'rt', errors='ignore') as songs_file:76 self.import_source = Path(self.import_source)
77 with self.import_source.open('rt', errors='ignore') as songs_file:
76 self.import_wizard.progress_bar.setMaximum(0)78 self.import_wizard.progress_bar.setMaximum(0)
77 tag = ''79 tag = ''
78 text = ''80 text = ''
7981
=== modified file 'openlp/plugins/songs/lib/importers/songshowplus.py'
--- openlp/plugins/songs/lib/importers/songshowplus.py 2017-06-01 06:18:47 +0000
+++ openlp/plugins/songs/lib/importers/songshowplus.py 2017-09-30 23:24:21 +0000
@@ -23,7 +23,6 @@
23The :mod:`songshowplus` module provides the functionality for importing SongShow Plus songs into the OpenLP23The :mod:`songshowplus` module provides the functionality for importing SongShow Plus songs into the OpenLP
24database.24database.
25"""25"""
26import os
27import logging26import logging
28import re27import re
29import struct28import struct
@@ -93,97 +92,95 @@
93 if not isinstance(self.import_source, list):92 if not isinstance(self.import_source, list):
94 return93 return
95 self.import_wizard.progress_bar.setMaximum(len(self.import_source))94 self.import_wizard.progress_bar.setMaximum(len(self.import_source))
96 for file in self.import_source:95 for file_path in self.import_source:
97 if self.stop_import_flag:96 if self.stop_import_flag:
98 return97 return
99 self.ssp_verse_order_list = []98 self.ssp_verse_order_list = []
100 self.other_count = 099 self.other_count = 0
101 self.other_list = {}100 self.other_list = {}
102 file_name = os.path.split(file)[1]101 self.import_wizard.increment_progress_bar(WizardStrings.ImportingType.format(source=file_path.name), 0)
103 self.import_wizard.increment_progress_bar(WizardStrings.ImportingType.format(source=file_name), 0)102 with file_path.open('rb') as song_file:
104 song_data = open(file, 'rb')103 while True:
105 while True:104 block_key, = struct.unpack("I", song_file.read(4))
106 block_key, = struct.unpack("I", song_data.read(4))105 log.debug('block_key: %d' % block_key)
107 log.debug('block_key: %d' % block_key)106 # The file ends with 4 NULL's
108 # The file ends with 4 NULL's107 if block_key == 0:
109 if block_key == 0:108 break
110 break109 next_block_starts, = struct.unpack("I", song_file.read(4))
111 next_block_starts, = struct.unpack("I", song_data.read(4))110 next_block_starts += song_file.tell()
112 next_block_starts += song_data.tell()111 if block_key in (VERSE, CHORUS, BRIDGE):
113 if block_key in (VERSE, CHORUS, BRIDGE):112 null, verse_no, = struct.unpack("BB", song_file.read(2))
114 null, verse_no, = struct.unpack("BB", song_data.read(2))113 elif block_key == CUSTOM_VERSE:
115 elif block_key == CUSTOM_VERSE:114 null, verse_name_length, = struct.unpack("BB", song_file.read(2))
116 null, verse_name_length, = struct.unpack("BB", song_data.read(2))115 verse_name = self.decode(song_file.read(verse_name_length))
117 verse_name = self.decode(song_data.read(verse_name_length))116 length_descriptor_size, = struct.unpack("B", song_file.read(1))
118 length_descriptor_size, = struct.unpack("B", song_data.read(1))117 log.debug('length_descriptor_size: %d' % length_descriptor_size)
119 log.debug('length_descriptor_size: %d' % length_descriptor_size)118 # In the case of song_numbers the number is in the data from the
120 # In the case of song_numbers the number is in the data from the119 # current position to the next block starts
121 # current position to the next block starts120 if block_key == SONG_NUMBER:
122 if block_key == SONG_NUMBER:121 sn_bytes = song_file.read(length_descriptor_size - 1)
123 sn_bytes = song_data.read(length_descriptor_size - 1)122 self.song_number = int.from_bytes(sn_bytes, byteorder='little')
124 self.song_number = int.from_bytes(sn_bytes, byteorder='little')123 continue
125 continue124 # Detect if/how long the length descriptor is
126 # Detect if/how long the length descriptor is125 if length_descriptor_size == 12 or length_descriptor_size == 20:
127 if length_descriptor_size == 12 or length_descriptor_size == 20:126 length_descriptor, = struct.unpack("I", song_file.read(4))
128 length_descriptor, = struct.unpack("I", song_data.read(4))127 elif length_descriptor_size == 2:
129 elif length_descriptor_size == 2:128 length_descriptor = 1
130 length_descriptor = 1129 elif length_descriptor_size == 9:
131 elif length_descriptor_size == 9:130 length_descriptor = 0
132 length_descriptor = 0131 else:
133 else:132 length_descriptor, = struct.unpack("B", song_file.read(1))
134 length_descriptor, = struct.unpack("B", song_data.read(1))133 log.debug('length_descriptor: %d' % length_descriptor)
135 log.debug('length_descriptor: %d' % length_descriptor)134 data = song_file.read(length_descriptor)
136 data = song_data.read(length_descriptor)135 log.debug(data)
137 log.debug(data)136 if block_key == TITLE:
138 if block_key == TITLE:137 self.title = self.decode(data)
139 self.title = self.decode(data)138 elif block_key == AUTHOR:
140 elif block_key == AUTHOR:139 authors = self.decode(data).split(" / ")
141 authors = self.decode(data).split(" / ")140 for author in authors:
142 for author in authors:141 if author.find(",") != -1:
143 if author.find(",") != -1:142 author_parts = author.split(", ")
144 author_parts = author.split(", ")143 author = author_parts[1] + " " + author_parts[0]
145 author = author_parts[1] + " " + author_parts[0]144 self.parse_author(author)
146 self.parse_author(author)145 elif block_key == COPYRIGHT:
147 elif block_key == COPYRIGHT:146 self.add_copyright(self.decode(data))
148 self.add_copyright(self.decode(data))147 elif block_key == CCLI_NO:
149 elif block_key == CCLI_NO:148 # Try to get the CCLI number even if the field contains additional text
150 # Try to get the CCLI number even if the field contains additional text149 match = re.search(r'\d+', self.decode(data))
151 match = re.search(r'\d+', self.decode(data))150 if match:
152 if match:151 self.ccli_number = int(match.group())
153 self.ccli_number = int(match.group())152 else:
154 else:153 log.warning("Can't parse CCLI Number from string: {text}".format(text=self.decode(data)))
155 log.warning("Can't parse CCLI Number from string: {text}".format(text=self.decode(data)))154 elif block_key == VERSE:
156 elif block_key == VERSE:155 self.add_verse(self.decode(data), "{tag}{number}".format(tag=VerseType.tags[VerseType.Verse],
157 self.add_verse(self.decode(data), "{tag}{number}".format(tag=VerseType.tags[VerseType.Verse],156 number=verse_no))
158 number=verse_no))157 elif block_key == CHORUS:
159 elif block_key == CHORUS:158 self.add_verse(self.decode(data), "{tag}{number}".format(tag=VerseType.tags[VerseType.Chorus],
160 self.add_verse(self.decode(data), "{tag}{number}".format(tag=VerseType.tags[VerseType.Chorus],159 number=verse_no))
161 number=verse_no))160 elif block_key == BRIDGE:
162 elif block_key == BRIDGE:161 self.add_verse(self.decode(data), "{tag}{number}".format(tag=VerseType.tags[VerseType.Bridge],
163 self.add_verse(self.decode(data), "{tag}{number}".format(tag=VerseType.tags[VerseType.Bridge],162 number=verse_no))
164 number=verse_no))163 elif block_key == TOPIC:
165 elif block_key == TOPIC:164 self.topics.append(self.decode(data))
166 self.topics.append(self.decode(data))165 elif block_key == COMMENTS:
167 elif block_key == COMMENTS:166 self.comments = self.decode(data)
168 self.comments = self.decode(data)167 elif block_key == VERSE_ORDER:
169 elif block_key == VERSE_ORDER:168 verse_tag = self.to_openlp_verse_tag(self.decode(data), True)
170 verse_tag = self.to_openlp_verse_tag(self.decode(data), True)169 if verse_tag:
171 if verse_tag:170 if not isinstance(verse_tag, str):
172 if not isinstance(verse_tag, str):171 verse_tag = self.decode(verse_tag)
173 verse_tag = self.decode(verse_tag)172 self.ssp_verse_order_list.append(verse_tag)
174 self.ssp_verse_order_list.append(verse_tag)173 elif block_key == SONG_BOOK:
175 elif block_key == SONG_BOOK:174 self.song_book_name = self.decode(data)
176 self.song_book_name = self.decode(data)175 elif block_key == CUSTOM_VERSE:
177 elif block_key == CUSTOM_VERSE:176 verse_tag = self.to_openlp_verse_tag(verse_name)
178 verse_tag = self.to_openlp_verse_tag(verse_name)177 self.add_verse(self.decode(data), verse_tag)
179 self.add_verse(self.decode(data), verse_tag)178 else:
180 else:179 log.debug("Unrecognised blockKey: {key}, data: {data}".format(key=block_key, data=data))
181 log.debug("Unrecognised blockKey: {key}, data: {data}".format(key=block_key, data=data))180 song_file.seek(next_block_starts)
182 song_data.seek(next_block_starts)181 self.verse_order_list = self.ssp_verse_order_list
183 self.verse_order_list = self.ssp_verse_order_list182 if not self.finish():
184 song_data.close()183 self.log_error(file_path)
185 if not self.finish():
186 self.log_error(file)
187184
188 def to_openlp_verse_tag(self, verse_name, ignore_unique=False):185 def to_openlp_verse_tag(self, verse_name, ignore_unique=False):
189 """186 """
190187
=== modified file 'openlp/plugins/songs/lib/importers/sundayplus.py'
--- openlp/plugins/songs/lib/importers/sundayplus.py 2016-12-31 11:01:36 +0000
+++ openlp/plugins/songs/lib/importers/sundayplus.py 2017-09-30 23:24:21 +0000
@@ -19,11 +19,8 @@
19# with this program; if not, write to the Free Software Foundation, Inc., 59 #19# with this program; if not, write to the Free Software Foundation, Inc., 59 #
20# Temple Place, Suite 330, Boston, MA 02111-1307 USA #20# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
21###############################################################################21###############################################################################
22
23import os22import os
24import re23import re
25import logging
26
2724
28from openlp.plugins.songs.lib import VerseType, retrieve_windows_encoding25from openlp.plugins.songs.lib import VerseType, retrieve_windows_encoding
29from openlp.plugins.songs.lib import strip_rtf26from openlp.plugins.songs.lib import strip_rtf
@@ -60,12 +57,11 @@
6057
61 def do_import(self):58 def do_import(self):
62 self.import_wizard.progress_bar.setMaximum(len(self.import_source))59 self.import_wizard.progress_bar.setMaximum(len(self.import_source))
63 for filename in self.import_source:60 for file_path in self.import_source:
64 if self.stop_import_flag:61 if self.stop_import_flag:
65 return62 return
66 song_file = open(filename, 'rb')63 with file_path.open('rb') as song_file:
67 self.do_import_file(song_file)64 self.do_import_file(song_file)
68 song_file.close()
6965
70 def do_import_file(self, file):66 def do_import_file(self, file):
71 """67 """
7268
=== modified file 'openlp/plugins/songs/lib/importers/videopsalm.py'
--- openlp/plugins/songs/lib/importers/videopsalm.py 2017-02-26 21:14:49 +0000
+++ openlp/plugins/songs/lib/importers/videopsalm.py 2017-09-30 23:24:21 +0000
@@ -22,13 +22,12 @@
22"""22"""
23The :mod:`lyrix` module provides the functionality for importing songs which are23The :mod:`lyrix` module provides the functionality for importing songs which are
24exproted from Lyrix."""24exproted from Lyrix."""
2525import json
26import logging26import logging
27import json
28import os
29import re27import re
3028
31from openlp.core.common import translate, Settings29from openlp.core.common import translate, Settings
30from openlp.core.common.path import Path
32from openlp.plugins.songs.lib.importers.songimport import SongImport31from openlp.plugins.songs.lib.importers.songimport import SongImport
33from openlp.plugins.songs.lib.db import AuthorType32from openlp.plugins.songs.lib.db import AuthorType
3433
@@ -50,11 +49,10 @@
50 """49 """
51 Process the VideoPsalm file - pass in a file-like object, not a file path.50 Process the VideoPsalm file - pass in a file-like object, not a file path.
52 """51 """
52 self.import_source = Path(self.import_source)
53 self.set_defaults()53 self.set_defaults()
54 # Open SongBook file
55 song_file = open(self.import_source, 'rt', encoding='utf-8-sig')
56 try:54 try:
57 file_content = song_file.read()55 file_content = self.import_source.read_text(encoding='utf-8-sig')
58 processed_content = ''56 processed_content = ''
59 inside_quotes = False57 inside_quotes = False
60 # The VideoPsalm format is not valid json, it uses illegal line breaks and unquoted keys, this must be fixed58 # The VideoPsalm format is not valid json, it uses illegal line breaks and unquoted keys, this must be fixed
@@ -89,7 +87,7 @@
89 songs = songbook['Songs']87 songs = songbook['Songs']
90 self.import_wizard.progress_bar.setMaximum(len(songs))88 self.import_wizard.progress_bar.setMaximum(len(songs))
91 songbook_name = songbook['Text']89 songbook_name = songbook['Text']
92 media_folder = os.path.normpath(os.path.join(os.path.dirname(song_file.name), '..', 'Audio'))90 media_path = Path('..', 'Audio')
93 for song in songs:91 for song in songs:
94 self.song_book_name = songbook_name92 self.song_book_name = songbook_name
95 if 'Text' in song:93 if 'Text' in song:
@@ -114,7 +112,7 @@
114 if 'Theme' in song:112 if 'Theme' in song:
115 self.topics = song['Theme'].splitlines()113 self.topics = song['Theme'].splitlines()
116 if 'AudioFile' in song:114 if 'AudioFile' in song:
117 self.add_media_file(os.path.join(media_folder, song['AudioFile']))115 self.add_media_file(media_path / song['AudioFile'])
118 if 'Memo1' in song:116 if 'Memo1' in song:
119 self.add_comment(song['Memo1'])117 self.add_comment(song['Memo1'])
120 if 'Memo2' in song:118 if 'Memo2' in song:
@@ -132,4 +130,5 @@
132 if not self.finish():130 if not self.finish():
133 self.log_error('Could not import {title}'.format(title=self.title))131 self.log_error('Could not import {title}'.format(title=self.title))
134 except Exception as e:132 except Exception as e:
135 self.log_error(song_file.name, translate('SongsPlugin.VideoPsalmImport', 'Error: {error}').format(error=e))133 self.log_error(self.import_source.name,
134 translate('SongsPlugin.VideoPsalmImport', 'Error: {error}').format(error=e))
136135
=== modified file 'openlp/plugins/songs/lib/importers/wordsofworship.py'
--- openlp/plugins/songs/lib/importers/wordsofworship.py 2016-12-31 11:01:36 +0000
+++ openlp/plugins/songs/lib/importers/wordsofworship.py 2017-09-30 23:24:21 +0000
@@ -25,6 +25,7 @@
25"""25"""
26import os26import os
27import logging27import logging
28from openlp.core.common.path import Path
2829
29from openlp.core.common import translate30from openlp.core.common import translate
30from openlp.plugins.songs.lib.importers.songimport import SongImport31from openlp.plugins.songs.lib.importers.songimport import SongImport
@@ -100,62 +101,60 @@
100 """101 """
101 if isinstance(self.import_source, list):102 if isinstance(self.import_source, list):
102 self.import_wizard.progress_bar.setMaximum(len(self.import_source))103 self.import_wizard.progress_bar.setMaximum(len(self.import_source))
103 for source in self.import_source:104 for file_path in self.import_source:
104 if self.stop_import_flag:105 if self.stop_import_flag:
105 return106 return
106 self.set_defaults()107 self.set_defaults()
107 song_data = open(source, 'rb')108 with file_path.open('rb') as song_data:
108 if song_data.read(19).decode() != 'WoW File\nSong Words':109 if song_data.read(19).decode() != 'WoW File\nSong Words':
109 self.log_error(source,110 self.log_error(file_path,
110 translate('SongsPlugin.WordsofWorshipSongImport',111 translate('SongsPlugin.WordsofWorshipSongImport',
111 'Invalid Words of Worship song file. Missing "{text}" '112 'Invalid Words of Worship song file. Missing "{text}" '
112 'header.').format(text='WoW File\\nSong Words'))113 'header.').format(text='WoW File\\nSong Words'))
113 continue114 continue
114 # Seek to byte which stores number of blocks in the song115 # Seek to byte which stores number of blocks in the song
115 song_data.seek(56)116 song_data.seek(56)
116 no_of_blocks = ord(song_data.read(1))117 no_of_blocks = ord(song_data.read(1))
117 song_data.seek(66)118 song_data.seek(66)
118 if song_data.read(16).decode() != 'CSongDoc::CBlock':119 if song_data.read(16).decode() != 'CSongDoc::CBlock':
119 self.log_error(source,120 self.log_error(file_path,
120 translate('SongsPlugin.WordsofWorshipSongImport',121 translate('SongsPlugin.WordsofWorshipSongImport',
121 'Invalid Words of Worship song file. Missing "{text}" '122 'Invalid Words of Worship song file. Missing "{text}" '
122 'string.').format(text='CSongDoc::CBlock'))123 'string.').format(text='CSongDoc::CBlock'))
123 continue124 continue
124 # Seek to the beginning of the first block125 # Seek to the beginning of the first block
125 song_data.seek(82)126 song_data.seek(82)
126 for block in range(no_of_blocks):127 for block in range(no_of_blocks):
127 skip_char_at_end = True128 skip_char_at_end = True
128 self.lines_to_read = ord(song_data.read(4)[:1])129 self.lines_to_read = ord(song_data.read(4)[:1])
129 block_text = ''130 block_text = ''
130 while self.lines_to_read:131 while self.lines_to_read:
131 self.line_text = str(song_data.read(ord(song_data.read(1))), 'cp1252')132 self.line_text = str(song_data.read(ord(song_data.read(1))), 'cp1252')
132 if skip_char_at_end:133 if skip_char_at_end:
133 skip_char = ord(song_data.read(1))134 skip_char = ord(song_data.read(1))
134 # Check if we really should skip a char. In some wsg files we shouldn't135 # Check if we really should skip a char. In some wsg files we shouldn't
135 if skip_char != 0:136 if skip_char != 0:
136 song_data.seek(-1, os.SEEK_CUR)137 song_data.seek(-1, os.SEEK_CUR)
137 skip_char_at_end = False138 skip_char_at_end = False
138 if block_text:139 if block_text:
139 block_text += '\n'140 block_text += '\n'
140 block_text += self.line_text141 block_text += self.line_text
141 self.lines_to_read -= 1142 self.lines_to_read -= 1
142 block_type = BLOCK_TYPES[ord(song_data.read(4)[:1])]143 block_type = BLOCK_TYPES[ord(song_data.read(4)[:1])]
143 # Blocks are separated by 2 bytes, skip them, but not if144 # Blocks are separated by 2 bytes, skip them, but not if
144 # this is the last block!145 # this is the last block!
145 if block + 1 < no_of_blocks:146 if block + 1 < no_of_blocks:
146 song_data.seek(2, os.SEEK_CUR)147 song_data.seek(2, os.SEEK_CUR)
147 self.add_verse(block_text, block_type)148 self.add_verse(block_text, block_type)
148 # Now to extract the author149 # Now to extract the author
149 author_length = ord(song_data.read(1))150 author_length = ord(song_data.read(1))
150 if author_length:151 if author_length:
151 self.parse_author(str(song_data.read(author_length), 'cp1252'))152 self.parse_author(str(song_data.read(author_length), 'cp1252'))
152 # Finally the copyright153 # Finally the copyright
153 copyright_length = ord(song_data.read(1))154 copyright_length = ord(song_data.read(1))
154 if copyright_length:155 if copyright_length:
155 self.add_copyright(str(song_data.read(copyright_length), 'cp1252'))156 self.add_copyright(str(song_data.read(copyright_length), 'cp1252'))
156 file_name = os.path.split(source)[1]157 # Get the song title
157 # Get the song title158 self.title = file_path.stem
158 self.title = file_name.rpartition('.')[0]159 if not self.finish():
159 song_data.close()160 self.log_error(file_path)
160 if not self.finish():
161 self.log_error(source)
162161
=== modified file 'openlp/plugins/songs/lib/importers/worshipassistant.py'
--- openlp/plugins/songs/lib/importers/worshipassistant.py 2016-12-31 11:01:36 +0000
+++ openlp/plugins/songs/lib/importers/worshipassistant.py 2017-09-30 23:24:21 +0000
@@ -28,7 +28,7 @@
28import logging28import logging
29import re29import re
3030
31from openlp.core.common import translate31from openlp.core.common import get_file_encoding, translate
32from openlp.plugins.songs.lib import VerseType32from openlp.plugins.songs.lib import VerseType
33from openlp.plugins.songs.lib.importers.songimport import SongImport33from openlp.plugins.songs.lib.importers.songimport import SongImport
3434
@@ -81,19 +81,16 @@
81 Receive a CSV file to import.81 Receive a CSV file to import.
82 """82 """
83 # Get encoding83 # Get encoding
84 detect_file = open(self.import_source, 'rb')84 encoding = get_file_encoding(self.import_source)['encoding']
85 detect_content = detect_file.read()85 with self.import_source.open('r', encoding=encoding) as songs_file:
86 details = chardet.detect(detect_content)86 songs_reader = csv.DictReader(songs_file, escapechar='\\')
87 detect_file.close()87 try:
88 songs_file = open(self.import_source, 'r', encoding=details['encoding'])88 records = list(songs_reader)
89 songs_reader = csv.DictReader(songs_file, escapechar='\\')89 except csv.Error as e:
90 try:90 self.log_error(translate('SongsPlugin.WorshipAssistantImport', 'Error reading CSV file.'),
91 records = list(songs_reader)91 translate('SongsPlugin.WorshipAssistantImport',
92 except csv.Error as e:92 'Line {number:d}: {error}').format(number=songs_reader.line_num, error=e))
93 self.log_error(translate('SongsPlugin.WorshipAssistantImport', 'Error reading CSV file.'),93 return
94 translate('SongsPlugin.WorshipAssistantImport',
95 'Line {number:d}: {error}').format(number=songs_reader.line_num, error=e))
96 return
97 num_records = len(records)94 num_records = len(records)
98 log.info('{count} records found in CSV file'.format(count=num_records))95 log.info('{count} records found in CSV file'.format(count=num_records))
99 self.import_wizard.progress_bar.setMaximum(num_records)96 self.import_wizard.progress_bar.setMaximum(num_records)
@@ -185,4 +182,3 @@
185 self.log_error(translate('SongsPlugin.WorshipAssistantImport',182 self.log_error(translate('SongsPlugin.WorshipAssistantImport',
186 'Record {count:d}').format(count=index) +183 'Record {count:d}').format(count=index) +
187 (': "' + self.title + '"' if self.title else ''))184 (': "' + self.title + '"' if self.title else ''))
188 songs_file.close()
189185
=== modified file 'openlp/plugins/songs/lib/importers/zionworx.py'
--- openlp/plugins/songs/lib/importers/zionworx.py 2016-12-31 11:01:36 +0000
+++ openlp/plugins/songs/lib/importers/zionworx.py 2017-09-30 23:24:21 +0000
@@ -76,7 +76,7 @@
76 Receive a CSV file (from a ZionWorx database dump) to import.76 Receive a CSV file (from a ZionWorx database dump) to import.
77 """77 """
78 # Encoding should always be ISO-8859-178 # Encoding should always be ISO-8859-1
79 with open(self.import_source, 'rt', encoding='ISO-8859-1') as songs_file:79 with self.import_source.open('rt', encoding='ISO-8859-1') as songs_file:
80 field_names = ['SongNum', 'Title1', 'Title2', 'Lyrics', 'Writer', 'Copyright', 'Keywords',80 field_names = ['SongNum', 'Title1', 'Title2', 'Lyrics', 'Writer', 'Copyright', 'Keywords',
81 'DefaultStyle']81 'DefaultStyle']
82 songs_reader = csv.DictReader(songs_file, field_names)82 songs_reader = csv.DictReader(songs_file, field_names)
8383
=== modified file 'openlp/plugins/songs/lib/mediaitem.py'
--- openlp/plugins/songs/lib/mediaitem.py 2017-08-25 20:03:25 +0000
+++ openlp/plugins/songs/lib/mediaitem.py 2017-09-30 23:24:21 +0000
@@ -22,25 +22,24 @@
2222
23import logging23import logging
24import os24import os
25import shutil
2625
27from PyQt5 import QtCore, QtWidgets26from PyQt5 import QtCore, QtWidgets
28from sqlalchemy.sql import and_, or_27from sqlalchemy.sql import and_, or_
2928
30from openlp.core.common import Registry, AppLocation, Settings, check_directory_exists, UiStrings, translate29from openlp.core.common import Registry, AppLocation, Settings, check_directory_exists, UiStrings, translate
31from openlp.core.common.path import Path30from openlp.core.common.languagemanager import get_natural_key
31from openlp.core.common.path import copyfile
32from openlp.core.lib import MediaManagerItem, ItemCapabilities, PluginStatus, ServiceItemContext, \32from openlp.core.lib import MediaManagerItem, ItemCapabilities, PluginStatus, ServiceItemContext, \
33 check_item_selected, create_separated_list33 check_item_selected, create_separated_list
34from openlp.core.lib.ui import create_widget_action34from openlp.core.lib.ui import create_widget_action
35from openlp.core.common.languagemanager import get_natural_key
36from openlp.plugins.songs.forms.editsongform import EditSongForm35from openlp.plugins.songs.forms.editsongform import EditSongForm
36from openlp.plugins.songs.forms.songexportform import SongExportForm
37from openlp.plugins.songs.forms.songimportform import SongImportForm
37from openlp.plugins.songs.forms.songmaintenanceform import SongMaintenanceForm38from openlp.plugins.songs.forms.songmaintenanceform import SongMaintenanceForm
38from openlp.plugins.songs.forms.songimportform import SongImportForm
39from openlp.plugins.songs.forms.songexportform import SongExportForm
40from openlp.plugins.songs.lib import VerseType, clean_string, delete_song39from openlp.plugins.songs.lib import VerseType, clean_string, delete_song
41from openlp.plugins.songs.lib.db import Author, AuthorType, Song, Book, MediaFile, SongBookEntry, Topic40from openlp.plugins.songs.lib.db import Author, AuthorType, Song, Book, MediaFile, SongBookEntry, Topic
41from openlp.plugins.songs.lib.openlyricsxml import OpenLyrics, SongXML
42from openlp.plugins.songs.lib.ui import SongStrings42from openlp.plugins.songs.lib.ui import SongStrings
43from openlp.plugins.songs.lib.openlyricsxml import OpenLyrics, SongXML
4443
45log = logging.getLogger(__name__)44log = logging.getLogger(__name__)
4645
@@ -88,11 +87,11 @@
88 def _update_background_audio(self, song, item):87 def _update_background_audio(self, song, item):
89 song.media_files = []88 song.media_files = []
90 for i, bga in enumerate(item.background_audio):89 for i, bga in enumerate(item.background_audio):
91 dest_file = os.path.join(90 dest_path =\
92 str(AppLocation.get_section_data_path(self.plugin.name)), 'audio', str(song.id), os.path.split(bga)[1])91 AppLocation.get_section_data_path(self.plugin.name) / 'audio' / str(song.id) / os.path.split(bga)[1]
93 check_directory_exists(Path(os.path.split(dest_file)[0]))92 check_directory_exists(dest_path.parent)
94 shutil.copyfile(os.path.join(str(AppLocation.get_section_data_path('servicemanager')), bga), dest_file)93 copyfile(AppLocation.get_section_data_path('servicemanager') / bga, dest_path)
95 song.media_files.append(MediaFile.populate(weight=i, file_name=dest_file))94 song.media_files.append(MediaFile.populate(weight=i, file_path=dest_path))
96 self.plugin.manager.save_object(song, True)95 self.plugin.manager.save_object(song, True)
9796
98 def add_end_header_bar(self):97 def add_end_header_bar(self):
@@ -534,14 +533,13 @@
534 'copy', 'For song cloning'))533 'copy', 'For song cloning'))
535 # Copy audio files from the old to the new song534 # Copy audio files from the old to the new song
536 if len(old_song.media_files) > 0:535 if len(old_song.media_files) > 0:
537 save_path = os.path.join(536 save_path = AppLocation.get_section_data_path(self.plugin.name) / 'audio' / str(new_song.id)
538 str(AppLocation.get_section_data_path(self.plugin.name)), 'audio', str(new_song.id))537 check_directory_exists(save_path)
539 check_directory_exists(Path(save_path))
540 for media_file in old_song.media_files:538 for media_file in old_song.media_files:
541 new_media_file_name = os.path.join(save_path, os.path.basename(media_file.file_name))539 new_media_file_path = save_path / media_file.file_path.name
542 shutil.copyfile(media_file.file_name, new_media_file_name)540 copyfile(media_file.file_path, new_media_file_path)
543 new_media_file = MediaFile()541 new_media_file = MediaFile()
544 new_media_file.file_name = new_media_file_name542 new_media_file.file_path = new_media_file_path
545 new_media_file.type = media_file.type543 new_media_file.type = media_file.type
546 new_media_file.weight = media_file.weight544 new_media_file.weight = media_file.weight
547 new_song.media_files.append(new_media_file)545 new_song.media_files.append(new_media_file)
@@ -613,7 +611,7 @@
613 # Add the audio file to the service item.611 # Add the audio file to the service item.
614 if song.media_files:612 if song.media_files:
615 service_item.add_capability(ItemCapabilities.HasBackgroundAudio)613 service_item.add_capability(ItemCapabilities.HasBackgroundAudio)
616 service_item.background_audio = [m.file_name for m in song.media_files]614 service_item.background_audio = [m.file_path for m in song.media_files]
617 return True615 return True
618616
619 def generate_footer(self, item, song):617 def generate_footer(self, item, song):
620618
=== modified file 'openlp/plugins/songs/lib/openlyricsexport.py'
--- openlp/plugins/songs/lib/openlyricsexport.py 2017-08-25 20:03:25 +0000
+++ openlp/plugins/songs/lib/openlyricsexport.py 2017-09-30 23:24:21 +0000
@@ -24,12 +24,10 @@
24format.24format.
25"""25"""
26import logging26import logging
27import os
2827
29from lxml import etree28from lxml import etree
3029
31from openlp.core.common import RegistryProperties, check_directory_exists, translate, clean_filename30from openlp.core.common import RegistryProperties, check_directory_exists, translate, clean_filename
32from openlp.core.common.path import Path
33from openlp.plugins.songs.lib.openlyricsxml import OpenLyrics31from openlp.plugins.songs.lib.openlyricsxml import OpenLyrics
3432
35log = logging.getLogger(__name__)33log = logging.getLogger(__name__)
@@ -42,13 +40,16 @@
42 def __init__(self, parent, songs, save_path):40 def __init__(self, parent, songs, save_path):
43 """41 """
44 Initialise the export.42 Initialise the export.
43
44 :param openlp.core.common.path.Path save_path: The directory to save the exported songs in
45 :rtype: None
45 """46 """
46 log.debug('initialise OpenLyricsExport')47 log.debug('initialise OpenLyricsExport')
47 self.parent = parent48 self.parent = parent
48 self.manager = parent.plugin.manager49 self.manager = parent.plugin.manager
49 self.songs = songs50 self.songs = songs
50 self.save_path = save_path51 self.save_path = save_path
51 check_directory_exists(Path(self.save_path))52 check_directory_exists(self.save_path)
5253
53 def do_export(self):54 def do_export(self):
54 """55 """
@@ -69,15 +70,15 @@
69 author=', '.join([author.display_name for author in song.authors]))70 author=', '.join([author.display_name for author in song.authors]))
70 filename = clean_filename(filename)71 filename = clean_filename(filename)
71 # Ensure the filename isn't too long for some filesystems72 # Ensure the filename isn't too long for some filesystems
72 filename_with_ext = '{name}.xml'.format(name=filename[0:250 - len(self.save_path)])73 path_length = len(str(self.save_path))
74 filename_with_ext = '{name}.xml'.format(name=filename[0:250 - path_length])
73 # Make sure we're not overwriting an existing file75 # Make sure we're not overwriting an existing file
74 conflicts = 076 conflicts = 0
75 while os.path.exists(os.path.join(self.save_path, filename_with_ext)):77 while (self.save_path / filename_with_ext).exists():
76 conflicts += 178 conflicts += 1
77 filename_with_ext = '{name}-{extra}.xml'.format(name=filename[0:247 - len(self.save_path)],79 filename_with_ext = '{name}-{extra}.xml'.format(name=filename[0:247 - path_length], extra=conflicts)
78 extra=conflicts)
79 # Pass a file object, because lxml does not cope with some special80 # Pass a file object, because lxml does not cope with some special
80 # characters in the path (see lp:757673 and lp:744337).81 # characters in the path (see lp:757673 and lp:744337).
81 tree.write(open(os.path.join(self.save_path, filename_with_ext), 'wb'), encoding='utf-8',82 with (self.save_path / filename_with_ext).open('wb') as out_file:
82 xml_declaration=True, pretty_print=True)83 tree.write(out_file, encoding='utf-8', xml_declaration=True, pretty_print=True)
83 return True84 return True
8485
=== modified file 'openlp/plugins/songs/lib/upgrade.py'
--- openlp/plugins/songs/lib/upgrade.py 2017-06-10 05:57:00 +0000
+++ openlp/plugins/songs/lib/upgrade.py 2017-09-30 23:24:21 +0000
@@ -23,16 +23,20 @@
23The :mod:`upgrade` module provides a way for the database and schema that is the23The :mod:`upgrade` module provides a way for the database and schema that is the
24backend for the Songs plugin24backend for the Songs plugin
25"""25"""
26import json
26import logging27import logging
2728
28from sqlalchemy import Table, Column, ForeignKey, types29from sqlalchemy import Table, Column, ForeignKey, types
29from sqlalchemy.sql.expression import func, false, null, text30from sqlalchemy.sql.expression import func, false, null, text
3031
32from openlp.core.common import AppLocation
31from openlp.core.common.db import drop_columns33from openlp.core.common.db import drop_columns
32from openlp.core.lib.db import get_upgrade_op34from openlp.core.common.json import OpenLPJsonEncoder
35from openlp.core.common.path import Path
36from openlp.core.lib.db import PathType, get_upgrade_op
3337
34log = logging.getLogger(__name__)38log = logging.getLogger(__name__)
35__version__ = 639__version__ = 7
3640
3741
38# TODO: When removing an upgrade path the ftw-data needs updating to the minimum supported version42# TODO: When removing an upgrade path the ftw-data needs updating to the minimum supported version
@@ -162,3 +166,28 @@
162 op.drop_column('songs', 'song_number')166 op.drop_column('songs', 'song_number')
163 # Finally, clean up our mess in people's databases167 # Finally, clean up our mess in people's databases
164 op.execute('DELETE FROM songs_songbooks WHERE songbook_id = 0')168 op.execute('DELETE FROM songs_songbooks WHERE songbook_id = 0')
169
170
171def upgrade_7(session, metadata):
172 """
173 Version 7 upgrade - Move file path from old db to JSON encoded path to new db. Upgrade added in 2.5 dev
174 """
175 log.debug('Starting upgrade_7 for file_path to JSON')
176 old_table = Table('media_files', metadata, autoload=True)
177 if 'file_path' not in [col.name for col in old_table.c.values()]:
178 op = get_upgrade_op(session)
179 op.add_column('media_files', Column('file_path', PathType()))
180 conn = op.get_bind()
181 results = conn.execute('SELECT * FROM media_files')
182 data_path = AppLocation.get_data_path()
183 for row in results.fetchall():
184 file_path_json = json.dumps(Path(row.file_name), cls=OpenLPJsonEncoder, base_path=data_path)
185 sql = 'UPDATE media_files SET file_path = \'{file_path_json}\' WHERE id = {id}'.format(
186 file_path_json=file_path_json, id=row.id)
187 conn.execute(sql)
188 # Drop old columns
189 if metadata.bind.url.get_dialect().name == 'sqlite':
190 drop_columns(op, 'media_files', ['file_name', ])
191 else:
192 op.drop_constraint('media_files', 'foreignkey')
193 op.drop_column('media_files', 'filenames')
165194
=== modified file 'openlp/plugins/songs/reporting.py'
--- openlp/plugins/songs/reporting.py 2017-09-07 21:52:39 +0000
+++ openlp/plugins/songs/reporting.py 2017-09-30 23:24:21 +0000
@@ -31,7 +31,6 @@
31from openlp.core.ui.lib.filedialog import FileDialog31from openlp.core.ui.lib.filedialog import FileDialog
32from openlp.plugins.songs.lib.db import Song32from openlp.plugins.songs.lib.db import Song
3333
34
35log = logging.getLogger(__name__)34log = logging.getLogger(__name__)
3635
3736
@@ -58,9 +57,9 @@
58 report_file_path.with_suffix('.csv')57 report_file_path.with_suffix('.csv')
59 Registry().get('application').set_busy_cursor()58 Registry().get('application').set_busy_cursor()
60 try:59 try:
61 with report_file_path.open('wt') as file_handle:60 with report_file_path.open('wt') as export_file:
62 fieldnames = ('Title', 'Alternative Title', 'Copyright', 'Author(s)', 'Song Book', 'Topic')61 fieldnames = ('Title', 'Alternative Title', 'Copyright', 'Author(s)', 'Song Book', 'Topic')
63 writer = csv.DictWriter(file_handle, fieldnames=fieldnames, quoting=csv.QUOTE_ALL)62 writer = csv.DictWriter(export_file, fieldnames=fieldnames, quoting=csv.QUOTE_ALL)
64 headers = dict((n, n) for n in fieldnames)63 headers = dict((n, n) for n in fieldnames)
65 writer.writerow(headers)64 writer.writerow(headers)
66 song_list = plugin.manager.get_all_objects(Song)65 song_list = plugin.manager.get_all_objects(Song)
6766
=== modified file 'openlp/plugins/songs/songsplugin.py'
--- openlp/plugins/songs/songsplugin.py 2017-08-26 15:06:11 +0000
+++ openlp/plugins/songs/songsplugin.py 2017-09-30 23:24:21 +0000
@@ -37,7 +37,6 @@
37from openlp.core.lib import Plugin, StringContent, build_icon37from openlp.core.lib import Plugin, StringContent, build_icon
38from openlp.core.lib.db import Manager38from openlp.core.lib.db import Manager
39from openlp.core.lib.ui import create_action39from openlp.core.lib.ui import create_action
40
41from openlp.plugins.songs import reporting40from openlp.plugins.songs import reporting
42from openlp.plugins.songs.endpoint import api_songs_endpoint, songs_endpoint41from openlp.plugins.songs.endpoint import api_songs_endpoint, songs_endpoint
43from openlp.plugins.songs.forms.duplicatesongremovalform import DuplicateSongRemovalForm42from openlp.plugins.songs.forms.duplicatesongremovalform import DuplicateSongRemovalForm
@@ -50,7 +49,6 @@
50from openlp.plugins.songs.lib.mediaitem import SongSearch49from openlp.plugins.songs.lib.mediaitem import SongSearch
51from openlp.plugins.songs.lib.songstab import SongsTab50from openlp.plugins.songs.lib.songstab import SongsTab
5251
53
54log = logging.getLogger(__name__)52log = logging.getLogger(__name__)
55__default_settings__ = {53__default_settings__ = {
56 'songs/db type': 'sqlite',54 'songs/db type': 'sqlite',
@@ -340,7 +338,7 @@
340 progress.forceShow()338 progress.forceShow()
341 self.application.process_events()339 self.application.process_events()
342 for db in song_dbs:340 for db in song_dbs:
343 importer = OpenLPSongImport(self.manager, filename=db)341 importer = OpenLPSongImport(self.manager, file_path=db)
344 importer.do_import(progress)342 importer.do_import(progress)
345 self.application.process_events()343 self.application.process_events()
346 progress.setValue(song_count)344 progress.setValue(song_count)
347345
=== modified file 'tests/functional/openlp_plugins/images/test_upgrade.py'
--- tests/functional/openlp_plugins/images/test_upgrade.py 2017-09-24 19:33:07 +0000
+++ tests/functional/openlp_plugins/images/test_upgrade.py 2017-09-30 23:24:21 +0000
@@ -79,5 +79,6 @@
79 2: Path('/', 'test', 'dir', 'image2.jpg'),79 2: Path('/', 'test', 'dir', 'image2.jpg'),
80 3: Path('/', 'test', 'dir', 'subdir', 'image3.jpg')}80 3: Path('/', 'test', 'dir', 'subdir', 'image3.jpg')}
8181
82 self.assertEqual(len(upgraded_results), 3)
82 for result in upgraded_results:83 for result in upgraded_results:
83 self.assertEqual(expected_result_data[result.id], result.file_path)84 self.assertEqual(expected_result_data[result.id], result.file_path)
8485
=== modified file 'tests/functional/openlp_plugins/songs/test_chordproimport.py'
--- tests/functional/openlp_plugins/songs/test_chordproimport.py 2017-05-11 20:24:20 +0000
+++ tests/functional/openlp_plugins/songs/test_chordproimport.py 2017-09-30 23:24:21 +0000
@@ -24,6 +24,8 @@
24"""24"""
25import os25import os
2626
27from openlp.core.common.path import Path
28
27from tests.helpers.songfileimport import SongImportTestHelper29from tests.helpers.songfileimport import SongImportTestHelper
28from unittest.mock import patch, MagicMock30from unittest.mock import patch, MagicMock
2931
@@ -48,5 +50,5 @@
48 mocked_returned_settings.value.side_effect = lambda value: True if value == 'songs/enable chords' else False50 mocked_returned_settings.value.side_effect = lambda value: True if value == 'songs/enable chords' else False
49 mocked_settings.return_value = mocked_returned_settings51 mocked_settings.return_value = mocked_returned_settings
50 # Do the test import52 # Do the test import
51 self.file_import([os.path.join(TEST_PATH, 'swing-low.chordpro')],53 self.file_import([Path(TEST_PATH, 'swing-low.chordpro')],
52 self.load_external_result_data(os.path.join(TEST_PATH, 'swing-low.json')))54 self.load_external_result_data(os.path.join(TEST_PATH, 'swing-low.json')))
5355
=== modified file 'tests/functional/openlp_plugins/songs/test_easyslidesimport.py'
--- tests/functional/openlp_plugins/songs/test_easyslidesimport.py 2017-01-12 21:31:01 +0000
+++ tests/functional/openlp_plugins/songs/test_easyslidesimport.py 2017-09-30 23:24:21 +0000
@@ -21,9 +21,10 @@
21"""21"""
22This module contains tests for the EasySlides song importer.22This module contains tests for the EasySlides song importer.
23"""23"""
24
25import os24import os
2625
26from openlp.core.common.path import Path
27
27from tests.helpers.songfileimport import SongImportTestHelper28from tests.helpers.songfileimport import SongImportTestHelper
2829
29TEST_PATH = os.path.abspath(30TEST_PATH = os.path.abspath(
@@ -41,7 +42,7 @@
41 """42 """
42 Test that loading an EasySlides file works correctly on various files43 Test that loading an EasySlides file works correctly on various files
43 """44 """
44 self.file_import(os.path.join(TEST_PATH, 'amazing-grace.xml'),45 self.file_import(Path(TEST_PATH, 'amazing-grace.xml'),
45 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))46 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
46 self.file_import(os.path.join(TEST_PATH, 'Export_2017-01-12_BB.xml'),47 self.file_import(Path(TEST_PATH, 'Export_2017-01-12_BB.xml'),
47 self.load_external_result_data(os.path.join(TEST_PATH, 'Export_2017-01-12_BB.json')))48 self.load_external_result_data(os.path.join(TEST_PATH, 'Export_2017-01-12_BB.json')))
4849
=== modified file 'tests/functional/openlp_plugins/songs/test_ewimport.py'
--- tests/functional/openlp_plugins/songs/test_ewimport.py 2017-05-22 19:07:07 +0000
+++ tests/functional/openlp_plugins/songs/test_ewimport.py 2017-09-30 23:24:21 +0000
@@ -97,7 +97,7 @@
97 _title_assignment_list = []97 _title_assignment_list = []
9898
99 def __init__(self, manager):99 def __init__(self, manager):
100 EasyWorshipSongImport.__init__(self, manager, filenames=[])100 EasyWorshipSongImport.__init__(self, manager, file_paths=[])
101101
102 @property102 @property
103 def title(self):103 def title(self):
@@ -180,7 +180,7 @@
180 mocked_manager = MagicMock()180 mocked_manager = MagicMock()
181181
182 # WHEN: An importer object is created182 # WHEN: An importer object is created
183 importer = EasyWorshipSongImport(mocked_manager, filenames=[])183 importer = EasyWorshipSongImport(mocked_manager, file_paths=[])
184184
185 # THEN: The importer object should not be None185 # THEN: The importer object should not be None
186 self.assertIsNotNone(importer, 'Import should not be none')186 self.assertIsNotNone(importer, 'Import should not be none')
@@ -192,7 +192,7 @@
192 # GIVEN: A mocked out SongImport class, a mocked out "manager" and a list of field descriptions.192 # GIVEN: A mocked out SongImport class, a mocked out "manager" and a list of field descriptions.
193 with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'):193 with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'):
194 mocked_manager = MagicMock()194 mocked_manager = MagicMock()
195 importer = EasyWorshipSongImport(mocked_manager, filenames=[])195 importer = EasyWorshipSongImport(mocked_manager, file_paths=[])
196 importer.field_descriptions = TEST_FIELD_DESCS196 importer.field_descriptions = TEST_FIELD_DESCS
197197
198 # WHEN: Called with a field name that exists198 # WHEN: Called with a field name that exists
@@ -210,7 +210,7 @@
210 # GIVEN: A mocked out SongImport class, a mocked out "manager" and a list of field descriptions210 # GIVEN: A mocked out SongImport class, a mocked out "manager" and a list of field descriptions
211 with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'):211 with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'):
212 mocked_manager = MagicMock()212 mocked_manager = MagicMock()
213 importer = EasyWorshipSongImport(mocked_manager, filenames=[])213 importer = EasyWorshipSongImport(mocked_manager, file_paths=[])
214 importer.field_descriptions = TEST_FIELD_DESCS214 importer.field_descriptions = TEST_FIELD_DESCS
215215
216 # WHEN: Called with a field name that does not exist216 # WHEN: Called with a field name that does not exist
@@ -229,7 +229,7 @@
229 with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'), \229 with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'), \
230 patch('openlp.plugins.songs.lib.importers.easyworship.struct') as mocked_struct:230 patch('openlp.plugins.songs.lib.importers.easyworship.struct') as mocked_struct:
231 mocked_manager = MagicMock()231 mocked_manager = MagicMock()
232 importer = EasyWorshipSongImport(mocked_manager, filenames=[])232 importer = EasyWorshipSongImport(mocked_manager, file_paths=[])
233233
234 # WHEN: db_set_record_struct is called with a list of field descriptions234 # WHEN: db_set_record_struct is called with a list of field descriptions
235 return_value = importer.db_set_record_struct(TEST_FIELD_DESCS)235 return_value = importer.db_set_record_struct(TEST_FIELD_DESCS)
@@ -246,7 +246,7 @@
246 # GIVEN: A mocked out SongImport class, a mocked out "manager", an encoding and some test data and known results246 # GIVEN: A mocked out SongImport class, a mocked out "manager", an encoding and some test data and known results
247 with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'):247 with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'):
248 mocked_manager = MagicMock()248 mocked_manager = MagicMock()
249 importer = EasyWorshipSongImport(mocked_manager, filenames=[])249 importer = EasyWorshipSongImport(mocked_manager, file_paths=[])
250 importer.encoding = TEST_DATA_ENCODING250 importer.encoding = TEST_DATA_ENCODING
251 importer.fields = TEST_FIELDS251 importer.fields = TEST_FIELDS
252 importer.field_descriptions = TEST_FIELD_DESCS252 importer.field_descriptions = TEST_FIELD_DESCS
@@ -270,7 +270,7 @@
270 with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'):270 with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'):
271 mocked_manager = MagicMock()271 mocked_manager = MagicMock()
272 mocked_memo_file = MagicMock()272 mocked_memo_file = MagicMock()
273 importer = EasyWorshipSongImport(mocked_manager, filenames=[])273 importer = EasyWorshipSongImport(mocked_manager, file_paths=[])
274 importer.memo_file = mocked_memo_file274 importer.memo_file = mocked_memo_file
275 importer.encoding = TEST_DATA_ENCODING275 importer.encoding = TEST_DATA_ENCODING
276276
@@ -294,44 +294,25 @@
294 else:294 else:
295 mocked_memo_file.seek.assert_any_call(call[0], call[1])295 mocked_memo_file.seek.assert_any_call(call[0], call[1])
296296
297 def test_do_import_source(self):
298 """
299 Test the :mod:`do_import` module opens the correct files
300 """
301 # GIVEN: A mocked out SongImport class, a mocked out "manager"
302 with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'), \
303 patch('openlp.plugins.songs.lib.importers.easyworship.os.path') as mocked_os_path:
304 mocked_manager = MagicMock()
305 importer = EasyWorshipSongImport(mocked_manager, filenames=[])
306 mocked_os_path.isfile.side_effect = [True, False]
307
308 # WHEN: Supplied with an import source
309 importer.import_source = 'Songs.DB'
310
311 # THEN: do_import should return None having called os.path.isfile
312 self.assertIsNone(importer.do_import(), 'do_import should return None')
313 mocked_os_path.isfile.assert_any_call('Songs.DB')
314 mocked_os_path.isfile.assert_any_call('Songs.MB')
315
316 def test_do_import_source_invalid(self):297 def test_do_import_source_invalid(self):
317 """298 """
318 Test the :mod:`do_import` module produces an error when Songs.MB not found.299 Test the :mod:`do_import` module produces an error when Songs.MB not found.
319 """300 """
320 # GIVEN: A mocked out SongImport class, a mocked out "manager"301 # GIVEN: A mocked out SongImport class, a mocked out "manager"
321 with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'), \302 with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'), \
322 patch('openlp.plugins.songs.lib.importers.easyworship.os.path') as mocked_os_path:303 patch('openlp.plugins.songs.lib.importers.easyworship.Path.is_file', side_effect=[True, False]):
323 mocked_manager = MagicMock()304 mocked_manager = MagicMock()
324 importer = EasyWorshipSongImport(mocked_manager, filenames=[])305 importer = EasyWorshipSongImport(mocked_manager, file_paths=[])
325 importer.log_error = MagicMock()306 with patch.object(importer, 'log_error') as mocked_log_error:
326 mocked_os_path.isfile.side_effect = [True, False]307
327308 # WHEN: do_import is supplied with an import source (Songs.MB missing)
328 # WHEN: do_import is supplied with an import source (Songs.MB missing)309 importer.import_source = 'Songs.DB'
329 importer.import_source = 'Songs.DB'310 importer.do_import()
330 importer.do_import()311
331312 # THEN: do_import should have logged an error that the Songs.MB file could not be found.
332 # THEN: do_import should have logged an error that the Songs.MB file could not be found.313 mocked_log_error.assert_any_call(importer.import_source,
333 importer.log_error.assert_any_call(importer.import_source, 'Could not find the "Songs.MB" file. It must be '314 'Could not find the "Songs.MB" file. It must be in the same folder as '
334 'in the same folder as the "Songs.DB" file.')315 'the "Songs.DB" file.')
335316
336 def test_do_import_database_validity(self):317 def test_do_import_database_validity(self):
337 """318 """
@@ -339,18 +320,19 @@
339 """320 """
340 # GIVEN: A mocked out SongImport class, os.path and a mocked out "manager"321 # GIVEN: A mocked out SongImport class, os.path and a mocked out "manager"
341 with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'), \322 with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'), \
342 patch('openlp.plugins.songs.lib.importers.easyworship.os.path') as mocked_os_path:323 patch('openlp.plugins.songs.lib.importers.easyworship.Path.is_file', return_value=True), \
324 patch('openlp.plugins.songs.lib.importers.easyworship.Path.stat') as mocked_stat:
325
343 mocked_manager = MagicMock()326 mocked_manager = MagicMock()
344 importer = EasyWorshipSongImport(mocked_manager, filenames=[])327 importer = EasyWorshipSongImport(mocked_manager, file_paths=[])
345 mocked_os_path.isfile.return_value = True
346 importer.import_source = 'Songs.DB'328 importer.import_source = 'Songs.DB'
347329
348 # WHEN: DB file size is less than 0x800330 # WHEN: DB file size is less than 0x800
349 mocked_os_path.getsize.return_value = 0x7FF331 mocked_stat.return_value.st_size = 0x7FF
350332
351 # THEN: do_import should return None having called os.path.isfile333 # THEN: do_import should return None having called Path.stat()
352 self.assertIsNone(importer.do_import(), 'do_import should return None when db_size is less than 0x800')334 self.assertIsNone(importer.do_import(), 'do_import should return None when db_size is less than 0x800')
353 mocked_os_path.getsize.assert_any_call('Songs.DB')335 mocked_stat.assert_called_once_with()
354336
355 def test_do_import_memo_validty(self):337 def test_do_import_memo_validty(self):
356 """338 """
@@ -358,13 +340,12 @@
358 """340 """
359 # GIVEN: A mocked out SongImport class, a mocked out "manager"341 # GIVEN: A mocked out SongImport class, a mocked out "manager"
360 with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'), \342 with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'), \
361 patch('openlp.plugins.songs.lib.importers.easyworship.os.path') as mocked_os_path, \343 patch('openlp.plugins.songs.lib.importers.easyworship.Path.is_file', return_value=True), \
362 patch('builtins.open') as mocked_open, \344 patch('openlp.plugins.songs.lib.importers.easyworship.Path.stat', **{'return_value.st_size': 0x800}), \
345 patch('openlp.plugins.songs.lib.importers.easyworship.Path.open') as mocked_open, \
363 patch('openlp.plugins.songs.lib.importers.easyworship.struct') as mocked_struct:346 patch('openlp.plugins.songs.lib.importers.easyworship.struct') as mocked_struct:
364 mocked_manager = MagicMock()347 mocked_manager = MagicMock()
365 importer = EasyWorshipSongImport(mocked_manager, filenames=[])348 importer = EasyWorshipSongImport(mocked_manager, file_paths=[])
366 mocked_os_path.isfile.return_value = True
367 mocked_os_path.getsize.return_value = 0x800
368 importer.import_source = 'Songs.DB'349 importer.import_source = 'Songs.DB'
369350
370 # WHEN: Unpacking first 35 bytes of Memo file351 # WHEN: Unpacking first 35 bytes of Memo file
@@ -385,14 +366,14 @@
385 """366 """
386 # GIVEN: A mocked out SongImport class, a mocked out "manager"367 # GIVEN: A mocked out SongImport class, a mocked out "manager"
387 with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'), \368 with patch('openlp.plugins.songs.lib.importers.easyworship.SongImport'), \
388 patch('openlp.plugins.songs.lib.importers.easyworship.os.path') as mocked_os_path, \369 patch('openlp.plugins.songs.lib.importers.easyworship.Path.is_file', return_value=True), \
370 patch('openlp.plugins.songs.lib.importers.easyworship.Path.stat', **{'return_value.st_size': 0x800}), \
371 patch('openlp.plugins.songs.lib.importers.easyworship.Path.open'), \
389 patch('builtins.open'), patch('openlp.plugins.songs.lib.importers.easyworship.struct') as mocked_struct, \372 patch('builtins.open'), patch('openlp.plugins.songs.lib.importers.easyworship.struct') as mocked_struct, \
390 patch('openlp.plugins.songs.lib.importers.easyworship.retrieve_windows_encoding') as \373 patch('openlp.plugins.songs.lib.importers.easyworship.retrieve_windows_encoding') as \
391 mocked_retrieve_windows_encoding:374 mocked_retrieve_windows_encoding:
392 mocked_manager = MagicMock()375 mocked_manager = MagicMock()
393 importer = EasyWorshipSongImport(mocked_manager, filenames=[])376 importer = EasyWorshipSongImport(mocked_manager, file_paths=[])
394 mocked_os_path.isfile.return_value = True
395 mocked_os_path.getsize.return_value = 0x800
396 importer.import_source = 'Songs.DB'377 importer.import_source = 'Songs.DB'
397378
398 # WHEN: Unpacking the code page379 # WHEN: Unpacking the code page
399380
=== modified file 'tests/functional/openlp_plugins/songs/test_lyriximport.py'
--- tests/functional/openlp_plugins/songs/test_lyriximport.py 2017-04-24 05:17:55 +0000
+++ tests/functional/openlp_plugins/songs/test_lyriximport.py 2017-09-30 23:24:21 +0000
@@ -22,7 +22,8 @@
22This module contains tests for the LyriX song importer.22This module contains tests for the LyriX song importer.
23"""23"""
24import os24import os
25from unittest.mock import patch25
26from openlp.core.common.path import Path
2627
27from tests.helpers.songfileimport import SongImportTestHelper28from tests.helpers.songfileimport import SongImportTestHelper
2829
@@ -41,9 +42,9 @@
41 """42 """
42 Test that loading an LyriX file works correctly on various files43 Test that loading an LyriX file works correctly on various files
43 """44 """
44 self.file_import([os.path.join(TEST_PATH, 'A06.TXT')],45 self.file_import([Path(TEST_PATH, 'A06.TXT')],
45 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))46 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
46 self.file_import([os.path.join(TEST_PATH, 'A002.TXT')],47 self.file_import([Path(TEST_PATH, 'A002.TXT')],
47 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace2.json')))48 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace2.json')))
48 self.file_import([os.path.join(TEST_PATH, 'AO05.TXT')],49 self.file_import([Path(TEST_PATH, 'AO05.TXT')],
49 self.load_external_result_data(os.path.join(TEST_PATH, 'in die regterhand.json')))50 self.load_external_result_data(os.path.join(TEST_PATH, 'in die regterhand.json')))
5051
=== modified file 'tests/functional/openlp_plugins/songs/test_mediashout.py'
--- tests/functional/openlp_plugins/songs/test_mediashout.py 2017-04-24 05:17:55 +0000
+++ tests/functional/openlp_plugins/songs/test_mediashout.py 2017-09-30 23:24:21 +0000
@@ -51,7 +51,7 @@
51 """51 """
52 # GIVEN: A MediaShoutImport class52 # GIVEN: A MediaShoutImport class
53 # WHEN: It is created53 # WHEN: It is created
54 importer = MediaShoutImport(MagicMock(), filename='mediashout.db')54 importer = MediaShoutImport(MagicMock(), file_path='mediashout.db')
5555
56 # THEN: It should not be None56 # THEN: It should not be None
57 self.assertIsNotNone(importer)57 self.assertIsNotNone(importer)
@@ -62,7 +62,7 @@
62 Test that do_import exits early when unable to connect to the database62 Test that do_import exits early when unable to connect to the database
63 """63 """
64 # GIVEN: A MediaShoutImport instance64 # GIVEN: A MediaShoutImport instance
65 importer = MediaShoutImport(MagicMock(), filename='mediashout.db')65 importer = MediaShoutImport(MagicMock(), file_path='mediashout.db')
66 mocked_pyodbc.connect.side_effect = Exception('Unable to connect')66 mocked_pyodbc.connect.side_effect = Exception('Unable to connect')
6767
68 # WHEN: do_import is called68 # WHEN: do_import is called
@@ -89,7 +89,7 @@
89 group = GroupRecord('Hymns')89 group = GroupRecord('Hymns')
9090
91 # GIVEN: A MediaShoutImport instance and a bunch of stuff mocked out91 # GIVEN: A MediaShoutImport instance and a bunch of stuff mocked out
92 importer = MediaShoutImport(MagicMock(), filename='mediashout.db')92 importer = MediaShoutImport(MagicMock(), file_path='mediashout.db')
93 mocked_cursor = MagicMock()93 mocked_cursor = MagicMock()
94 mocked_cursor.fetchall.side_effect = [[song], [verse], [play_order], [theme], [group]]94 mocked_cursor.fetchall.side_effect = [[song], [verse], [play_order], [theme], [group]]
95 mocked_cursor.tables.fetchone.return_value = True95 mocked_cursor.tables.fetchone.return_value = True
@@ -124,7 +124,7 @@
124 song = SongRecord(1, 'Amazing Grace', 'William Wilberforce', 'Public Domain', 1, '654321', '')124 song = SongRecord(1, 'Amazing Grace', 'William Wilberforce', 'Public Domain', 1, '654321', '')
125125
126 # GIVEN: A MediaShoutImport instance and a bunch of stuff mocked out126 # GIVEN: A MediaShoutImport instance and a bunch of stuff mocked out
127 importer = MediaShoutImport(MagicMock(), filename='mediashout.db')127 importer = MediaShoutImport(MagicMock(), file_path='mediashout.db')
128 mocked_cursor = MagicMock()128 mocked_cursor = MagicMock()
129 mocked_cursor.fetchall.return_value = [song]129 mocked_cursor.fetchall.return_value = [song]
130 mocked_connection = MagicMock()130 mocked_connection = MagicMock()
@@ -158,7 +158,7 @@
158 play_order = PlayOrderRecord(0, 1, 1)158 play_order = PlayOrderRecord(0, 1, 1)
159 theme = ThemeRecord('Grace')159 theme = ThemeRecord('Grace')
160 group = GroupRecord('Hymns')160 group = GroupRecord('Hymns')
161 importer = MediaShoutImport(MagicMock(), filename='mediashout.db')161 importer = MediaShoutImport(MagicMock(), file_path='mediashout.db')
162162
163 # WHEN: A song is processed163 # WHEN: A song is processed
164 with patch.object(importer, 'set_defaults') as mocked_set_defaults, \164 with patch.object(importer, 'set_defaults') as mocked_set_defaults, \
@@ -200,7 +200,7 @@
200 play_order = PlayOrderRecord(0, 1, 1)200 play_order = PlayOrderRecord(0, 1, 1)
201 theme = ThemeRecord('Grace')201 theme = ThemeRecord('Grace')
202 group = GroupRecord('Hymns')202 group = GroupRecord('Hymns')
203 importer = MediaShoutImport(MagicMock(), filename='mediashout.db')203 importer = MediaShoutImport(MagicMock(), file_path='mediashout.db')
204204
205 # WHEN: A song is processed205 # WHEN: A song is processed
206 with patch.object(importer, 'set_defaults') as mocked_set_defaults, \206 with patch.object(importer, 'set_defaults') as mocked_set_defaults, \
207207
=== modified file 'tests/functional/openlp_plugins/songs/test_openlpimporter.py'
--- tests/functional/openlp_plugins/songs/test_openlpimporter.py 2017-04-24 05:17:55 +0000
+++ tests/functional/openlp_plugins/songs/test_openlpimporter.py 2017-09-30 23:24:21 +0000
@@ -48,7 +48,7 @@
48 mocked_manager = MagicMock()48 mocked_manager = MagicMock()
4949
50 # WHEN: An importer object is created50 # WHEN: An importer object is created
51 importer = OpenLPSongImport(mocked_manager, filenames=[])51 importer = OpenLPSongImport(mocked_manager, file_paths=[])
5252
53 # THEN: The importer object should not be None53 # THEN: The importer object should not be None
54 self.assertIsNotNone(importer, 'Import should not be none')54 self.assertIsNotNone(importer, 'Import should not be none')
@@ -61,7 +61,7 @@
61 with patch('openlp.plugins.songs.lib.importers.openlp.SongImport'):61 with patch('openlp.plugins.songs.lib.importers.openlp.SongImport'):
62 mocked_manager = MagicMock()62 mocked_manager = MagicMock()
63 mocked_import_wizard = MagicMock()63 mocked_import_wizard = MagicMock()
64 importer = OpenLPSongImport(mocked_manager, filenames=[])64 importer = OpenLPSongImport(mocked_manager, file_paths=[])
65 importer.import_wizard = mocked_import_wizard65 importer.import_wizard = mocked_import_wizard
66 importer.stop_import_flag = True66 importer.stop_import_flag = True
6767
6868
=== modified file 'tests/functional/openlp_plugins/songs/test_openlyricsexport.py'
--- tests/functional/openlp_plugins/songs/test_openlyricsexport.py 2017-04-24 05:17:55 +0000
+++ tests/functional/openlp_plugins/songs/test_openlyricsexport.py 2017-09-30 23:24:21 +0000
@@ -22,14 +22,14 @@
22"""22"""
23This module contains tests for the OpenLyrics song importer.23This module contains tests for the OpenLyrics song importer.
24"""24"""
25import os
26import shutil25import shutil
27from tempfile import mkdtemp26from tempfile import mkdtemp
28from unittest import TestCase27from unittest import TestCase
29from unittest.mock import MagicMock, patch28from unittest.mock import MagicMock, patch
3029
30from openlp.core.common import Registry
31from openlp.core.common.path import Path, rmtree
31from openlp.plugins.songs.lib.openlyricsexport import OpenLyricsExport32from openlp.plugins.songs.lib.openlyricsexport import OpenLyricsExport
32from openlp.core.common import Registry
3333
34from tests.helpers.testmixin import TestMixin34from tests.helpers.testmixin import TestMixin
3535
@@ -43,13 +43,13 @@
43 Create the registry43 Create the registry
44 """44 """
45 Registry.create()45 Registry.create()
46 self.temp_folder = mkdtemp()46 self.temp_folder = Path(mkdtemp())
4747
48 def tearDown(self):48 def tearDown(self):
49 """49 """
50 Cleanup50 Cleanup
51 """51 """
52 shutil.rmtree(self.temp_folder)52 rmtree(self.temp_folder)
5353
54 def test_export_same_filename(self):54 def test_export_same_filename(self):
55 """55 """
@@ -73,7 +73,9 @@
73 ol_export.do_export()73 ol_export.do_export()
7474
75 # THEN: The exporter should have created 2 files75 # THEN: The exporter should have created 2 files
76 self.assertTrue(os.path.exists(os.path.join(self.temp_folder,76 self.assertTrue((self.temp_folder /
77 '%s (%s).xml' % (song.title, author.display_name))))77 '{title} ({display_name}).xml'.format(
78 self.assertTrue(os.path.exists(os.path.join(self.temp_folder,78 title=song.title, display_name=author.display_name)).exists())
79 '%s (%s)-1.xml' % (song.title, author.display_name))))79 self.assertTrue((self.temp_folder /
80 '{title} ({display_name})-1.xml'.format(
81 title=song.title, display_name=author.display_name)).exists())
8082
=== modified file 'tests/functional/openlp_plugins/songs/test_openlyricsimport.py'
--- tests/functional/openlp_plugins/songs/test_openlyricsimport.py 2017-06-06 20:58:12 +0000
+++ tests/functional/openlp_plugins/songs/test_openlyricsimport.py 2017-09-30 23:24:21 +0000
@@ -29,10 +29,11 @@
2929
30from lxml import etree, objectify30from lxml import etree, objectify
3131
32from openlp.core.common import Registry, Settings
33from openlp.core.common.path import Path
32from openlp.plugins.songs.lib.importers.openlyrics import OpenLyricsImport34from openlp.plugins.songs.lib.importers.openlyrics import OpenLyricsImport
33from openlp.plugins.songs.lib.importers.songimport import SongImport35from openlp.plugins.songs.lib.importers.songimport import SongImport
34from openlp.plugins.songs.lib.openlyricsxml import OpenLyrics36from openlp.plugins.songs.lib.openlyricsxml import OpenLyrics
35from openlp.core.common import Registry, Settings
3637
37from tests.helpers.testmixin import TestMixin38from tests.helpers.testmixin import TestMixin
3839
@@ -109,7 +110,7 @@
109 mocked_manager = MagicMock()110 mocked_manager = MagicMock()
110111
111 # WHEN: An importer object is created112 # WHEN: An importer object is created
112 importer = OpenLyricsImport(mocked_manager, filenames=[])113 importer = OpenLyricsImport(mocked_manager, file_paths=[])
113114
114 # THEN: The importer should be an instance of SongImport115 # THEN: The importer should be an instance of SongImport
115 self.assertIsInstance(importer, SongImport)116 self.assertIsInstance(importer, SongImport)
@@ -122,13 +123,13 @@
122 for song_file in SONG_TEST_DATA:123 for song_file in SONG_TEST_DATA:
123 mocked_manager = MagicMock()124 mocked_manager = MagicMock()
124 mocked_import_wizard = MagicMock()125 mocked_import_wizard = MagicMock()
125 importer = OpenLyricsImport(mocked_manager, filenames=[])126 importer = OpenLyricsImport(mocked_manager, file_paths=[])
126 importer.import_wizard = mocked_import_wizard127 importer.import_wizard = mocked_import_wizard
127 importer.open_lyrics = MagicMock()128 importer.open_lyrics = MagicMock()
128 importer.open_lyrics.xml_to_song = MagicMock()129 importer.open_lyrics.xml_to_song = MagicMock()
129130
130 # WHEN: Importing each file131 # WHEN: Importing each file
131 importer.import_source = [os.path.join(TEST_PATH, song_file)]132 importer.import_source = [Path(TEST_PATH, song_file)]
132 importer.do_import()133 importer.do_import()
133134
134 # THEN: The xml_to_song() method should have been called135 # THEN: The xml_to_song() method should have been called
135136
=== modified file 'tests/functional/openlp_plugins/songs/test_openoffice.py'
--- tests/functional/openlp_plugins/songs/test_openoffice.py 2017-04-24 05:17:55 +0000
+++ tests/functional/openlp_plugins/songs/test_openoffice.py 2017-09-30 23:24:21 +0000
@@ -54,7 +54,7 @@
54 mocked_manager = MagicMock()54 mocked_manager = MagicMock()
5555
56 # WHEN: An importer object is created56 # WHEN: An importer object is created
57 importer = OpenOfficeImport(mocked_manager, filenames=[])57 importer = OpenOfficeImport(mocked_manager, file_paths=[])
5858
59 # THEN: The importer object should not be None59 # THEN: The importer object should not be None
60 self.assertIsNotNone(importer, 'Import should not be none')60 self.assertIsNotNone(importer, 'Import should not be none')
@@ -66,7 +66,7 @@
66 """66 """
67 # GIVEN: A mocked out SongImport class, a mocked out "manager" and a document that raises an exception67 # GIVEN: A mocked out SongImport class, a mocked out "manager" and a document that raises an exception
68 mocked_manager = MagicMock()68 mocked_manager = MagicMock()
69 importer = OpenOfficeImport(mocked_manager, filenames=[])69 importer = OpenOfficeImport(mocked_manager, file_paths=[])
70 importer.document = MagicMock()70 importer.document = MagicMock()
71 importer.document.close = MagicMock(side_effect=Exception())71 importer.document.close = MagicMock(side_effect=Exception())
7272
7373
=== modified file 'tests/functional/openlp_plugins/songs/test_opensongimport.py'
--- tests/functional/openlp_plugins/songs/test_opensongimport.py 2017-05-11 20:24:20 +0000
+++ tests/functional/openlp_plugins/songs/test_opensongimport.py 2017-09-30 23:24:21 +0000
@@ -27,6 +27,7 @@
27from unittest.mock import patch, MagicMock27from unittest.mock import patch, MagicMock
2828
29from openlp.core.common import Registry29from openlp.core.common import Registry
30from openlp.core.common.path import Path
30from openlp.plugins.songs.lib.importers.opensong import OpenSongImport31from openlp.plugins.songs.lib.importers.opensong import OpenSongImport
3132
32from tests.helpers.songfileimport import SongImportTestHelper33from tests.helpers.songfileimport import SongImportTestHelper
@@ -52,15 +53,15 @@
52 mocked_returned_settings.value.side_effect = lambda value: True if value == 'songs/enable chords' else False53 mocked_returned_settings.value.side_effect = lambda value: True if value == 'songs/enable chords' else False
53 mocked_settings.return_value = mocked_returned_settings54 mocked_settings.return_value = mocked_returned_settings
54 # Do the test import55 # Do the test import
55 self.file_import([os.path.join(TEST_PATH, 'Amazing Grace')],56 self.file_import([Path(TEST_PATH, 'Amazing Grace')],
56 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))57 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
57 self.file_import([os.path.join(TEST_PATH, 'Beautiful Garden Of Prayer')],58 self.file_import([Path(TEST_PATH, 'Beautiful Garden Of Prayer')],
58 self.load_external_result_data(os.path.join(TEST_PATH, 'Beautiful Garden Of Prayer.json')))59 self.load_external_result_data(os.path.join(TEST_PATH, 'Beautiful Garden Of Prayer.json')))
59 self.file_import([os.path.join(TEST_PATH, 'One, Two, Three, Four, Five')],60 self.file_import([Path(TEST_PATH, 'One, Two, Three, Four, Five')],
60 self.load_external_result_data(os.path.join(TEST_PATH, 'One, Two, Three, Four, Five.json')))61 self.load_external_result_data(os.path.join(TEST_PATH, 'One, Two, Three, Four, Five.json')))
61 self.file_import([os.path.join(TEST_PATH, 'Amazing Grace2')],62 self.file_import([Path(TEST_PATH, 'Amazing Grace2')],
62 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))63 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
63 self.file_import([os.path.join(TEST_PATH, 'Amazing Grace with bad CCLI')],64 self.file_import([Path(TEST_PATH, 'Amazing Grace with bad CCLI')],
64 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace without CCLI.json')))65 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace without CCLI.json')))
6566
6667
@@ -83,7 +84,7 @@
83 mocked_manager = MagicMock()84 mocked_manager = MagicMock()
8485
85 # WHEN: An importer object is created86 # WHEN: An importer object is created
86 importer = OpenSongImport(mocked_manager, filenames=[])87 importer = OpenSongImport(mocked_manager, file_paths=[])
8788
88 # THEN: The importer object should not be None89 # THEN: The importer object should not be None
89 self.assertIsNotNone(importer, 'Import should not be none')90 self.assertIsNotNone(importer, 'Import should not be none')
@@ -96,7 +97,7 @@
96 with patch('openlp.plugins.songs.lib.importers.opensong.SongImport'):97 with patch('openlp.plugins.songs.lib.importers.opensong.SongImport'):
97 mocked_manager = MagicMock()98 mocked_manager = MagicMock()
98 mocked_import_wizard = MagicMock()99 mocked_import_wizard = MagicMock()
99 importer = OpenSongImport(mocked_manager, filenames=[])100 importer = OpenSongImport(mocked_manager, file_paths=[])
100 importer.import_wizard = mocked_import_wizard101 importer.import_wizard = mocked_import_wizard
101 importer.stop_import_flag = True102 importer.stop_import_flag = True
102103
@@ -117,7 +118,7 @@
117 with patch('openlp.plugins.songs.lib.importers.opensong.SongImport'):118 with patch('openlp.plugins.songs.lib.importers.opensong.SongImport'):
118 mocked_manager = MagicMock()119 mocked_manager = MagicMock()
119 mocked_import_wizard = MagicMock()120 mocked_import_wizard = MagicMock()
120 importer = OpenSongImport(mocked_manager, filenames=[])121 importer = OpenSongImport(mocked_manager, file_paths=[])
121 importer.import_wizard = mocked_import_wizard122 importer.import_wizard = mocked_import_wizard
122 importer.stop_import_flag = True123 importer.stop_import_flag = True
123124
124125
=== modified file 'tests/functional/openlp_plugins/songs/test_opsproimport.py'
--- tests/functional/openlp_plugins/songs/test_opsproimport.py 2017-04-24 05:17:55 +0000
+++ tests/functional/openlp_plugins/songs/test_opsproimport.py 2017-09-30 23:24:21 +0000
@@ -86,7 +86,7 @@
86 mocked_manager = MagicMock()86 mocked_manager = MagicMock()
8787
88 # WHEN: An importer object is created88 # WHEN: An importer object is created
89 importer = OPSProImport(mocked_manager, filenames=[])89 importer = OPSProImport(mocked_manager, file_paths=[])
9090
91 # THEN: The importer object should not be None91 # THEN: The importer object should not be None
92 self.assertIsNotNone(importer, 'Import should not be none')92 self.assertIsNotNone(importer, 'Import should not be none')
@@ -98,7 +98,7 @@
98 """98 """
99 # GIVEN: A mocked out SongImport class, a mocked out "manager" and a mocked song and lyrics entry99 # GIVEN: A mocked out SongImport class, a mocked out "manager" and a mocked song and lyrics entry
100 mocked_manager = MagicMock()100 mocked_manager = MagicMock()
101 importer = OPSProImport(mocked_manager, filenames=[])101 importer = OPSProImport(mocked_manager, file_paths=[])
102 importer.finish = MagicMock()102 importer.finish = MagicMock()
103 song, lyrics = _build_data('you are so faithfull.txt', False)103 song, lyrics = _build_data('you are so faithfull.txt', False)
104104
@@ -118,7 +118,7 @@
118 """118 """
119 # GIVEN: A mocked out SongImport class, a mocked out "manager" and a mocked song and lyrics entry119 # GIVEN: A mocked out SongImport class, a mocked out "manager" and a mocked song and lyrics entry
120 mocked_manager = MagicMock()120 mocked_manager = MagicMock()
121 importer = OPSProImport(mocked_manager, filenames=[])121 importer = OPSProImport(mocked_manager, file_paths=[])
122 importer.finish = MagicMock()122 importer.finish = MagicMock()
123 song, lyrics = _build_data('amazing grace.txt', False)123 song, lyrics = _build_data('amazing grace.txt', False)
124124
@@ -138,7 +138,7 @@
138 """138 """
139 # GIVEN: A mocked out SongImport class, a mocked out "manager" and a mocked song and lyrics entry139 # GIVEN: A mocked out SongImport class, a mocked out "manager" and a mocked song and lyrics entry
140 mocked_manager = MagicMock()140 mocked_manager = MagicMock()
141 importer = OPSProImport(mocked_manager, filenames=[])141 importer = OPSProImport(mocked_manager, file_paths=[])
142 importer.finish = MagicMock()142 importer.finish = MagicMock()
143 song, lyrics = _build_data('amazing grace2.txt', True)143 song, lyrics = _build_data('amazing grace2.txt', True)
144144
@@ -158,7 +158,7 @@
158 """158 """
159 # GIVEN: A mocked out SongImport class, a mocked out "manager" and a mocked song and lyrics entry159 # GIVEN: A mocked out SongImport class, a mocked out "manager" and a mocked song and lyrics entry
160 mocked_manager = MagicMock()160 mocked_manager = MagicMock()
161 importer = OPSProImport(mocked_manager, filenames=[])161 importer = OPSProImport(mocked_manager, file_paths=[])
162 importer.finish = MagicMock()162 importer.finish = MagicMock()
163 song, lyrics = _build_data('amazing grace3.txt', True)163 song, lyrics = _build_data('amazing grace3.txt', True)
164164
165165
=== modified file 'tests/functional/openlp_plugins/songs/test_powerpraiseimport.py'
--- tests/functional/openlp_plugins/songs/test_powerpraiseimport.py 2016-12-31 11:01:36 +0000
+++ tests/functional/openlp_plugins/songs/test_powerpraiseimport.py 2017-09-30 23:24:21 +0000
@@ -26,8 +26,9 @@
2626
27import os27import os
2828
29from openlp.core.common.path import Path
30
29from tests.helpers.songfileimport import SongImportTestHelper31from tests.helpers.songfileimport import SongImportTestHelper
30from openlp.core.common import Registry
3132
32TEST_PATH = os.path.abspath(33TEST_PATH = os.path.abspath(
33 os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'powerpraisesongs'))34 os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'powerpraisesongs'))
@@ -44,7 +45,7 @@
44 """45 """
45 Test that loading a PowerPraise file works correctly46 Test that loading a PowerPraise file works correctly
46 """47 """
47 self.file_import([os.path.join(TEST_PATH, 'Naher, mein Gott zu Dir.ppl')],48 self.file_import([Path(TEST_PATH, 'Naher, mein Gott zu Dir.ppl')],
48 self.load_external_result_data(os.path.join(TEST_PATH, 'Naher, mein Gott zu Dir.json')))49 self.load_external_result_data(os.path.join(TEST_PATH, 'Naher, mein Gott zu Dir.json')))
49 self.file_import([os.path.join(TEST_PATH, 'You are so faithful.ppl')],50 self.file_import([Path(TEST_PATH, 'You are so faithful.ppl')],
50 self.load_external_result_data(os.path.join(TEST_PATH, 'You are so faithful.json')))51 self.load_external_result_data(os.path.join(TEST_PATH, 'You are so faithful.json')))
5152
=== modified file 'tests/functional/openlp_plugins/songs/test_presentationmanagerimport.py'
--- tests/functional/openlp_plugins/songs/test_presentationmanagerimport.py 2016-12-31 11:01:36 +0000
+++ tests/functional/openlp_plugins/songs/test_presentationmanagerimport.py 2017-09-30 23:24:21 +0000
@@ -22,9 +22,10 @@
22"""22"""
23This module contains tests for the PresentationManager song importer.23This module contains tests for the PresentationManager song importer.
24"""24"""
25
26import os25import os
2726
27from openlp.core.common.path import Path
28
28from tests.helpers.songfileimport import SongImportTestHelper29from tests.helpers.songfileimport import SongImportTestHelper
2930
30TEST_PATH = os.path.abspath(31TEST_PATH = os.path.abspath(
@@ -42,7 +43,7 @@
42 """43 """
43 Test that loading a PresentationManager file works correctly44 Test that loading a PresentationManager file works correctly
44 """45 """
45 self.file_import([os.path.join(TEST_PATH, 'Great Is Thy Faithfulness.sng')],46 self.file_import([Path(TEST_PATH, 'Great Is Thy Faithfulness.sng')],
46 self.load_external_result_data(os.path.join(TEST_PATH, 'Great Is Thy Faithfulness.json')))47 self.load_external_result_data(os.path.join(TEST_PATH, 'Great Is Thy Faithfulness.json')))
47 self.file_import([os.path.join(TEST_PATH, 'Amazing Grace.sng')],48 self.file_import([Path(TEST_PATH, 'Amazing Grace.sng')],
48 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))49 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
4950
=== modified file 'tests/functional/openlp_plugins/songs/test_propresenterimport.py'
--- tests/functional/openlp_plugins/songs/test_propresenterimport.py 2016-12-31 11:01:36 +0000
+++ tests/functional/openlp_plugins/songs/test_propresenterimport.py 2017-09-30 23:24:21 +0000
@@ -23,9 +23,10 @@
23The :mod:`propresenterimport` module provides the functionality for importing23The :mod:`propresenterimport` module provides the functionality for importing
24ProPresenter song files into the current installation database.24ProPresenter song files into the current installation database.
25"""25"""
26
27import os26import os
2827
28from openlp.core.common.path import Path
29
29from tests.helpers.songfileimport import SongImportTestHelper30from tests.helpers.songfileimport import SongImportTestHelper
3031
31TEST_PATH = os.path.abspath(32TEST_PATH = os.path.abspath(
@@ -43,19 +44,19 @@
43 """44 """
44 Test that loading a ProPresenter 4 file works correctly45 Test that loading a ProPresenter 4 file works correctly
45 """46 """
46 self.file_import([os.path.join(TEST_PATH, 'Amazing Grace.pro4')],47 self.file_import([Path(TEST_PATH, 'Amazing Grace.pro4')],
47 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))48 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
4849
49 def test_pro5_song_import(self):50 def test_pro5_song_import(self):
50 """51 """
51 Test that loading a ProPresenter 5 file works correctly52 Test that loading a ProPresenter 5 file works correctly
52 """53 """
53 self.file_import([os.path.join(TEST_PATH, 'Amazing Grace.pro5')],54 self.file_import([Path(TEST_PATH, 'Amazing Grace.pro5')],
54 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))55 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
5556
56 def test_pro6_song_import(self):57 def test_pro6_song_import(self):
57 """58 """
58 Test that loading a ProPresenter 6 file works correctly59 Test that loading a ProPresenter 6 file works correctly
59 """60 """
60 self.file_import([os.path.join(TEST_PATH, 'Amazing Grace.pro6')],61 self.file_import([Path(TEST_PATH, 'Amazing Grace.pro6')],
61 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))62 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
6263
=== modified file 'tests/functional/openlp_plugins/songs/test_songbeamerimport.py'
--- tests/functional/openlp_plugins/songs/test_songbeamerimport.py 2017-05-11 20:24:20 +0000
+++ tests/functional/openlp_plugins/songs/test_songbeamerimport.py 2017-09-30 23:24:21 +0000
@@ -26,8 +26,9 @@
26from unittest import TestCase26from unittest import TestCase
27from unittest.mock import MagicMock, patch27from unittest.mock import MagicMock, patch
2828
29from openlp.core.common import Registry
30from openlp.core.common.path import Path
29from openlp.plugins.songs.lib.importers.songbeamer import SongBeamerImport, SongBeamerTypes31from openlp.plugins.songs.lib.importers.songbeamer import SongBeamerImport, SongBeamerTypes
30from openlp.core.common import Registry
3132
32from tests.helpers.songfileimport import SongImportTestHelper33from tests.helpers.songfileimport import SongImportTestHelper
3334
@@ -51,18 +52,18 @@
51 mocked_returned_settings = MagicMock()52 mocked_returned_settings = MagicMock()
52 mocked_returned_settings.value.side_effect = lambda value: True if value == 'songs/enable chords' else False53 mocked_returned_settings.value.side_effect = lambda value: True if value == 'songs/enable chords' else False
53 mocked_settings.return_value = mocked_returned_settings54 mocked_settings.return_value = mocked_returned_settings
54 self.file_import([os.path.join(TEST_PATH, 'Amazing Grace.sng')],55 self.file_import([Path(TEST_PATH, 'Amazing Grace.sng')],
55 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))56 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
56 self.file_import([os.path.join(TEST_PATH, 'Lobsinget dem Herrn.sng')],57 self.file_import([Path(TEST_PATH, 'Lobsinget dem Herrn.sng')],
57 self.load_external_result_data(os.path.join(TEST_PATH, 'Lobsinget dem Herrn.json')))58 self.load_external_result_data(os.path.join(TEST_PATH, 'Lobsinget dem Herrn.json')))
58 self.file_import([os.path.join(TEST_PATH, 'When I Call On You.sng')],59 self.file_import([Path(TEST_PATH, 'When I Call On You.sng')],
59 self.load_external_result_data(os.path.join(TEST_PATH, 'When I Call On You.json')))60 self.load_external_result_data(os.path.join(TEST_PATH, 'When I Call On You.json')))
6061
61 def test_cp1252_encoded_file(self):62 def test_cp1252_encoded_file(self):
62 """63 """
63 Test that a CP1252 encoded file get's decoded properly.64 Test that a CP1252 encoded file get's decoded properly.
64 """65 """
65 self.file_import([os.path.join(TEST_PATH, 'cp1252song.sng')],66 self.file_import([Path(TEST_PATH, 'cp1252song.sng')],
66 self.load_external_result_data(os.path.join(TEST_PATH, 'cp1252song.json')))67 self.load_external_result_data(os.path.join(TEST_PATH, 'cp1252song.json')))
6768
6869
@@ -78,7 +79,7 @@
78 self.song_import_patcher = patch('openlp.plugins.songs.lib.importers.songbeamer.SongImport')79 self.song_import_patcher = patch('openlp.plugins.songs.lib.importers.songbeamer.SongImport')
79 self.song_import_patcher.start()80 self.song_import_patcher.start()
80 mocked_manager = MagicMock()81 mocked_manager = MagicMock()
81 self.importer = SongBeamerImport(mocked_manager, filenames=[])82 self.importer = SongBeamerImport(mocked_manager, file_paths=[])
8283
83 def tearDown(self):84 def tearDown(self):
84 """85 """
@@ -95,7 +96,7 @@
95 mocked_manager = MagicMock()96 mocked_manager = MagicMock()
9697
97 # WHEN: An importer object is created98 # WHEN: An importer object is created
98 importer = SongBeamerImport(mocked_manager, filenames=[])99 importer = SongBeamerImport(mocked_manager, file_paths=[])
99100
100 # THEN: The importer object should not be None101 # THEN: The importer object should not be None
101 self.assertIsNotNone(importer, 'Import should not be none')102 self.assertIsNotNone(importer, 'Import should not be none')
102103
=== modified file 'tests/functional/openlp_plugins/songs/test_songproimport.py'
--- tests/functional/openlp_plugins/songs/test_songproimport.py 2016-12-31 11:01:36 +0000
+++ tests/functional/openlp_plugins/songs/test_songproimport.py 2017-09-30 23:24:21 +0000
@@ -23,9 +23,10 @@
23The :mod:`songproimport` module provides the functionality for importing23The :mod:`songproimport` module provides the functionality for importing
24SongPro song files into the current installation database.24SongPro song files into the current installation database.
25"""25"""
26
27import os26import os
2827
28from openlp.core.common.path import Path
29
29from tests.helpers.songfileimport import SongImportTestHelper30from tests.helpers.songfileimport import SongImportTestHelper
3031
31TEST_PATH = os.path.abspath(32TEST_PATH = os.path.abspath(
@@ -43,5 +44,5 @@
43 """44 """
44 Test that loading an SongPro file works correctly45 Test that loading an SongPro file works correctly
45 """46 """
46 self.file_import(os.path.join(TEST_PATH, 'amazing-grace.txt'),47 self.file_import(Path(TEST_PATH, 'amazing-grace.txt'),
47 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))48 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
4849
=== modified file 'tests/functional/openlp_plugins/songs/test_songselect.py'
--- tests/functional/openlp_plugins/songs/test_songselect.py 2017-05-30 19:40:01 +0000
+++ tests/functional/openlp_plugins/songs/test_songselect.py 2017-09-30 23:24:21 +0000
@@ -31,6 +31,7 @@
31from PyQt5 import QtWidgets31from PyQt5 import QtWidgets
3232
33from openlp.core import Registry33from openlp.core import Registry
34from openlp.core.common.path import Path
34from openlp.plugins.songs.forms.songselectform import SongSelectForm, SearchWorker35from openlp.plugins.songs.forms.songselectform import SongSelectForm, SearchWorker
35from openlp.plugins.songs.lib import Song36from openlp.plugins.songs.lib import Song
36from openlp.plugins.songs.lib.songselect import SongSelectImport, LOGIN_PAGE, LOGOUT_URL, BASE_URL37from openlp.plugins.songs.lib.songselect import SongSelectImport, LOGIN_PAGE, LOGOUT_URL, BASE_URL
@@ -810,15 +811,15 @@
810 def __init__(self, *args, **kwargs):811 def __init__(self, *args, **kwargs):
811 self.importer_class_name = 'CCLIFileImport'812 self.importer_class_name = 'CCLIFileImport'
812 self.importer_module_name = 'cclifile'813 self.importer_module_name = 'cclifile'
813 super(TestSongSelectFileImport, self).__init__(*args, **kwargs)814 super().__init__(*args, **kwargs)
814815
815 def test_song_import(self):816 def test_song_import(self):
816 """817 """
817 Test that loading an OpenSong file works correctly on various files818 Test that loading an OpenSong file works correctly on various files
818 """819 """
819 self.file_import([os.path.join(TEST_PATH, 'TestSong.bin')],820 self.file_import([Path(TEST_PATH, 'TestSong.bin')],
820 self.load_external_result_data(os.path.join(TEST_PATH, 'TestSong-bin.json')))821 self.load_external_result_data(os.path.join(TEST_PATH, 'TestSong-bin.json')))
821 self.file_import([os.path.join(TEST_PATH, 'TestSong.txt')],822 self.file_import([Path(TEST_PATH, 'TestSong.txt')],
822 self.load_external_result_data(os.path.join(TEST_PATH, 'TestSong-txt.json')))823 self.load_external_result_data(os.path.join(TEST_PATH, 'TestSong-txt.json')))
823824
824825
825826
=== modified file 'tests/functional/openlp_plugins/songs/test_songshowplusimport.py'
--- tests/functional/openlp_plugins/songs/test_songshowplusimport.py 2017-04-24 05:17:55 +0000
+++ tests/functional/openlp_plugins/songs/test_songshowplusimport.py 2017-09-30 23:24:21 +0000
@@ -26,6 +26,7 @@
26from unittest import TestCase26from unittest import TestCase
27from unittest.mock import patch, MagicMock27from unittest.mock import patch, MagicMock
2828
29from openlp.core.common.path import Path
29from openlp.plugins.songs.lib import VerseType30from openlp.plugins.songs.lib import VerseType
30from openlp.plugins.songs.lib.importers.songshowplus import SongShowPlusImport31from openlp.plugins.songs.lib.importers.songshowplus import SongShowPlusImport
3132
@@ -46,13 +47,13 @@
46 """47 """
47 Test that loading a SongShow Plus file works correctly on various files48 Test that loading a SongShow Plus file works correctly on various files
48 """49 """
49 self.file_import([os.path.join(TEST_PATH, 'Amazing Grace.sbsong')],50 self.file_import([Path(TEST_PATH, 'Amazing Grace.sbsong')],
50 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))51 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
51 self.file_import([os.path.join(TEST_PATH, 'Beautiful Garden Of Prayer.sbsong')],52 self.file_import([Path(TEST_PATH, 'Beautiful Garden Of Prayer.sbsong')],
52 self.load_external_result_data(os.path.join(TEST_PATH, 'Beautiful Garden Of Prayer.json')))53 self.load_external_result_data(os.path.join(TEST_PATH, 'Beautiful Garden Of Prayer.json')))
53 self.file_import([os.path.join(TEST_PATH, 'a mighty fortress is our god.sbsong')],54 self.file_import([Path(TEST_PATH, 'a mighty fortress is our god.sbsong')],
54 self.load_external_result_data(os.path.join(TEST_PATH, 'a mighty fortress is our god.json')))55 self.load_external_result_data(os.path.join(TEST_PATH, 'a mighty fortress is our god.json')))
55 self.file_import([os.path.join(TEST_PATH, 'cleanse-me.sbsong')],56 self.file_import([Path(TEST_PATH, 'cleanse-me.sbsong')],
56 self.load_external_result_data(os.path.join(TEST_PATH, 'cleanse-me.json')))57 self.load_external_result_data(os.path.join(TEST_PATH, 'cleanse-me.json')))
5758
5859
@@ -69,7 +70,7 @@
69 mocked_manager = MagicMock()70 mocked_manager = MagicMock()
7071
71 # WHEN: An importer object is created72 # WHEN: An importer object is created
72 importer = SongShowPlusImport(mocked_manager, filenames=[])73 importer = SongShowPlusImport(mocked_manager, file_paths=[])
7374
74 # THEN: The importer object should not be None75 # THEN: The importer object should not be None
75 self.assertIsNotNone(importer, 'Import should not be none')76 self.assertIsNotNone(importer, 'Import should not be none')
@@ -82,7 +83,7 @@
82 with patch('openlp.plugins.songs.lib.importers.songshowplus.SongImport'):83 with patch('openlp.plugins.songs.lib.importers.songshowplus.SongImport'):
83 mocked_manager = MagicMock()84 mocked_manager = MagicMock()
84 mocked_import_wizard = MagicMock()85 mocked_import_wizard = MagicMock()
85 importer = SongShowPlusImport(mocked_manager, filenames=[])86 importer = SongShowPlusImport(mocked_manager, file_paths=[])
86 importer.import_wizard = mocked_import_wizard87 importer.import_wizard = mocked_import_wizard
87 importer.stop_import_flag = True88 importer.stop_import_flag = True
8889
@@ -103,7 +104,7 @@
103 with patch('openlp.plugins.songs.lib.importers.songshowplus.SongImport'):104 with patch('openlp.plugins.songs.lib.importers.songshowplus.SongImport'):
104 mocked_manager = MagicMock()105 mocked_manager = MagicMock()
105 mocked_import_wizard = MagicMock()106 mocked_import_wizard = MagicMock()
106 importer = SongShowPlusImport(mocked_manager, filenames=[])107 importer = SongShowPlusImport(mocked_manager, file_paths=[])
107 importer.import_wizard = mocked_import_wizard108 importer.import_wizard = mocked_import_wizard
108 importer.stop_import_flag = True109 importer.stop_import_flag = True
109110
@@ -123,7 +124,7 @@
123 # GIVEN: A mocked out SongImport class, and a mocked out "manager"124 # GIVEN: A mocked out SongImport class, and a mocked out "manager"
124 with patch('openlp.plugins.songs.lib.importers.songshowplus.SongImport'):125 with patch('openlp.plugins.songs.lib.importers.songshowplus.SongImport'):
125 mocked_manager = MagicMock()126 mocked_manager = MagicMock()
126 importer = SongShowPlusImport(mocked_manager, filenames=[])127 importer = SongShowPlusImport(mocked_manager, file_paths=[])
127128
128 # WHEN: Supplied with the following arguments replicating verses being added129 # WHEN: Supplied with the following arguments replicating verses being added
129 test_values = [130 test_values = [
@@ -151,7 +152,7 @@
151 # GIVEN: A mocked out SongImport class, and a mocked out "manager"152 # GIVEN: A mocked out SongImport class, and a mocked out "manager"
152 with patch('openlp.plugins.songs.lib.importers.songshowplus.SongImport'):153 with patch('openlp.plugins.songs.lib.importers.songshowplus.SongImport'):
153 mocked_manager = MagicMock()154 mocked_manager = MagicMock()
154 importer = SongShowPlusImport(mocked_manager, filenames=[])155 importer = SongShowPlusImport(mocked_manager, file_paths=[])
155156
156 # WHEN: Supplied with the following arguments replicating a verse order being added157 # WHEN: Supplied with the following arguments replicating a verse order being added
157 test_values = [158 test_values = [
158159
=== modified file 'tests/functional/openlp_plugins/songs/test_sundayplusimport.py'
--- tests/functional/openlp_plugins/songs/test_sundayplusimport.py 2017-04-24 05:17:55 +0000
+++ tests/functional/openlp_plugins/songs/test_sundayplusimport.py 2017-09-30 23:24:21 +0000
@@ -24,6 +24,8 @@
24import os24import os
25from unittest.mock import patch25from unittest.mock import patch
2626
27from openlp.core.common.path import Path
28
27from tests.helpers.songfileimport import SongImportTestHelper29from tests.helpers.songfileimport import SongImportTestHelper
2830
29TEST_PATH = os.path.abspath(31TEST_PATH = os.path.abspath(
@@ -44,5 +46,5 @@
44 with patch('openlp.plugins.songs.lib.importers.sundayplus.retrieve_windows_encoding') as \46 with patch('openlp.plugins.songs.lib.importers.sundayplus.retrieve_windows_encoding') as \
45 mocked_retrieve_windows_encoding:47 mocked_retrieve_windows_encoding:
46 mocked_retrieve_windows_encoding.return_value = 'cp1252'48 mocked_retrieve_windows_encoding.return_value = 'cp1252'
47 self.file_import([os.path.join(TEST_PATH, 'Amazing Grace.ptf')],49 self.file_import([Path(TEST_PATH, 'Amazing Grace.ptf')],
48 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))50 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
4951
=== modified file 'tests/functional/openlp_plugins/songs/test_videopsalm.py'
--- tests/functional/openlp_plugins/songs/test_videopsalm.py 2017-05-11 20:24:20 +0000
+++ tests/functional/openlp_plugins/songs/test_videopsalm.py 2017-09-30 23:24:21 +0000
@@ -21,9 +21,10 @@
21"""21"""
22This module contains tests for the VideoPsalm song importer.22This module contains tests for the VideoPsalm song importer.
23"""23"""
24
25import os24import os
2625
26from openlp.core.common.path import Path
27
27from tests.helpers.songfileimport import SongImportTestHelper28from tests.helpers.songfileimport import SongImportTestHelper
28from unittest.mock import patch, MagicMock29from unittest.mock import patch, MagicMock
2930
@@ -48,7 +49,7 @@
48 mocked_returned_settings.value.side_effect = lambda value: True if value == 'songs/enable chords' else False49 mocked_returned_settings.value.side_effect = lambda value: True if value == 'songs/enable chords' else False
49 mocked_settings.return_value = mocked_returned_settings50 mocked_settings.return_value = mocked_returned_settings
50 # Do the test import51 # Do the test import
51 self.file_import(os.path.join(TEST_PATH, 'videopsalm-as-safe-a-stronghold.json'),52 self.file_import(Path(TEST_PATH, 'videopsalm-as-safe-a-stronghold.json'),
52 self.load_external_result_data(os.path.join(TEST_PATH, 'as-safe-a-stronghold.json')))53 self.load_external_result_data(os.path.join(TEST_PATH, 'as-safe-a-stronghold.json')))
53 self.file_import(os.path.join(TEST_PATH, 'videopsalm-as-safe-a-stronghold2.json'),54 self.file_import(Path(TEST_PATH, 'videopsalm-as-safe-a-stronghold2.json'),
54 self.load_external_result_data(os.path.join(TEST_PATH, 'as-safe-a-stronghold2.json')))55 self.load_external_result_data(os.path.join(TEST_PATH, 'as-safe-a-stronghold2.json')))
5556
=== modified file 'tests/functional/openlp_plugins/songs/test_wordsofworshipimport.py'
--- tests/functional/openlp_plugins/songs/test_wordsofworshipimport.py 2016-12-31 11:01:36 +0000
+++ tests/functional/openlp_plugins/songs/test_wordsofworshipimport.py 2017-09-30 23:24:21 +0000
@@ -22,9 +22,10 @@
22"""22"""
23This module contains tests for the Words of Worship song importer.23This module contains tests for the Words of Worship song importer.
24"""24"""
25
26import os25import os
2726
27from openlp.core.common.path import Path
28
28from tests.helpers.songfileimport import SongImportTestHelper29from tests.helpers.songfileimport import SongImportTestHelper
29from openlp.plugins.songs.lib.importers.wordsofworship import WordsOfWorshipImport30from openlp.plugins.songs.lib.importers.wordsofworship import WordsOfWorshipImport
3031
@@ -43,10 +44,10 @@
43 """44 """
44 Test that loading a Words of Worship file works correctly45 Test that loading a Words of Worship file works correctly
45 """46 """
46 self.file_import([os.path.join(TEST_PATH, 'Amazing Grace (6 Verses).wow-song')],47 self.file_import([Path(TEST_PATH, 'Amazing Grace (6 Verses).wow-song')],
47 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace (6 Verses).json')))48 self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace (6 Verses).json')))
48 self.file_import([os.path.join(TEST_PATH, 'When morning gilds the skies.wsg')],49 self.file_import([Path(TEST_PATH, 'When morning gilds the skies.wsg')],
49 self.load_external_result_data(os.path.join(TEST_PATH, 'When morning gilds the skies.json')))50 self.load_external_result_data(os.path.join(TEST_PATH, 'When morning gilds the skies.json')))
50 self.file_import([os.path.join(TEST_PATH, 'Holy Holy Holy Lord God Almighty.wow-song')],51 self.file_import([Path(TEST_PATH, 'Holy Holy Holy Lord God Almighty.wow-song')],
51 self.load_external_result_data(os.path.join(TEST_PATH,52 self.load_external_result_data(os.path.join(TEST_PATH,
52 'Holy Holy Holy Lord God Almighty.json')))53 'Holy Holy Holy Lord God Almighty.json')))
5354
=== modified file 'tests/functional/openlp_plugins/songs/test_worshipassistantimport.py'
--- tests/functional/openlp_plugins/songs/test_worshipassistantimport.py 2016-12-31 11:01:36 +0000
+++ tests/functional/openlp_plugins/songs/test_worshipassistantimport.py 2017-09-30 23:24:21 +0000
@@ -23,9 +23,10 @@
23The :mod:`worshipassistantimport` module provides the functionality for importing23The :mod:`worshipassistantimport` module provides the functionality for importing
24WorshipAssistant song files into the current installation database.24WorshipAssistant song files into the current installation database.
25"""25"""
26
27import os26import os
2827
28from openlp.core.common.path import Path
29
29from tests.helpers.songfileimport import SongImportTestHelper30from tests.helpers.songfileimport import SongImportTestHelper
3031
31TEST_PATH = os.path.abspath(32TEST_PATH = os.path.abspath(
@@ -43,9 +44,9 @@
43 """44 """
44 Test that loading an Worship Assistant file works correctly45 Test that loading an Worship Assistant file works correctly
45 """46 """
46 self.file_import(os.path.join(TEST_PATH, 'du_herr.csv'),47 self.file_import(Path(TEST_PATH, 'du_herr.csv'),
47 self.load_external_result_data(os.path.join(TEST_PATH, 'du_herr.json')))48 self.load_external_result_data(os.path.join(TEST_PATH, 'du_herr.json')))
48 self.file_import(os.path.join(TEST_PATH, 'would_you_be_free.csv'),49 self.file_import(Path(TEST_PATH, 'would_you_be_free.csv'),
49 self.load_external_result_data(os.path.join(TEST_PATH, 'would_you_be_free.json')))50 self.load_external_result_data(os.path.join(TEST_PATH, 'would_you_be_free.json')))
50 self.file_import(os.path.join(TEST_PATH, 'would_you_be_free2.csv'),51 self.file_import(Path(TEST_PATH, 'would_you_be_free2.csv'),
51 self.load_external_result_data(os.path.join(TEST_PATH, 'would_you_be_free.json')))52 self.load_external_result_data(os.path.join(TEST_PATH, 'would_you_be_free.json')))
5253
=== modified file 'tests/functional/openlp_plugins/songs/test_worshipcenterproimport.py'
--- tests/functional/openlp_plugins/songs/test_worshipcenterproimport.py 2017-04-24 05:17:55 +0000
+++ tests/functional/openlp_plugins/songs/test_worshipcenterproimport.py 2017-09-30 23:24:21 +0000
@@ -55,7 +55,7 @@
55 _title_assignment_list = []55 _title_assignment_list = []
5656
57 def __init__(self, manager):57 def __init__(self, manager):
58 WorshipCenterProImport.__init__(self, manager, filenames=[])58 WorshipCenterProImport.__init__(self, manager, file_paths=[])
5959
60 @property60 @property
61 def title(self):61 def title(self):
@@ -153,7 +153,7 @@
153 mocked_manager = MagicMock()153 mocked_manager = MagicMock()
154154
155 # WHEN: An importer object is created155 # WHEN: An importer object is created
156 importer = WorshipCenterProImport(mocked_manager, filenames=[])156 importer = WorshipCenterProImport(mocked_manager, file_paths=[])
157157
158 # THEN: The importer object should not be None158 # THEN: The importer object should not be None
159 self.assertIsNotNone(importer, 'Import should not be none')159 self.assertIsNotNone(importer, 'Import should not be none')
@@ -170,7 +170,7 @@
170 mocked_manager = MagicMock()170 mocked_manager = MagicMock()
171 mocked_log_error = MagicMock()171 mocked_log_error = MagicMock()
172 mocked_translate.return_value = 'Translated Text'172 mocked_translate.return_value = 'Translated Text'
173 importer = WorshipCenterProImport(mocked_manager, filenames=[])173 importer = WorshipCenterProImport(mocked_manager, file_paths=[])
174 importer.log_error = mocked_log_error174 importer.log_error = mocked_log_error
175 importer.import_source = 'import_source'175 importer.import_source = 'import_source'
176 pyodbc_errors = [pyodbc.DatabaseError, pyodbc.IntegrityError, pyodbc.InternalError, pyodbc.OperationalError]176 pyodbc_errors = [pyodbc.DatabaseError, pyodbc.IntegrityError, pyodbc.InternalError, pyodbc.OperationalError]
177177
=== modified file 'tests/functional/openlp_plugins/songs/test_zionworximport.py'
--- tests/functional/openlp_plugins/songs/test_zionworximport.py 2017-04-24 05:17:55 +0000
+++ tests/functional/openlp_plugins/songs/test_zionworximport.py 2017-09-30 23:24:21 +0000
@@ -26,9 +26,10 @@
26from unittest import TestCase26from unittest import TestCase
27from unittest.mock import MagicMock, patch27from unittest.mock import MagicMock, patch
2828
29from openlp.core.common import Registry
30from openlp.core.common.path import Path
29from openlp.plugins.songs.lib.importers.zionworx import ZionWorxImport31from openlp.plugins.songs.lib.importers.zionworx import ZionWorxImport
30from openlp.plugins.songs.lib.importers.songimport import SongImport32from openlp.plugins.songs.lib.importers.songimport import SongImport
31from openlp.core.common import Registry
3233
33from tests.helpers.songfileimport import SongImportTestHelper34from tests.helpers.songfileimport import SongImportTestHelper
3435
@@ -55,7 +56,7 @@
55 mocked_manager = MagicMock()56 mocked_manager = MagicMock()
5657
57 # WHEN: An importer object is created58 # WHEN: An importer object is created
58 importer = ZionWorxImport(mocked_manager, filenames=[])59 importer = ZionWorxImport(mocked_manager, file_paths=[])
5960
60 # THEN: The importer should be an instance of SongImport61 # THEN: The importer should be an instance of SongImport
61 self.assertIsInstance(importer, SongImport)62 self.assertIsInstance(importer, SongImport)
@@ -72,5 +73,5 @@
72 """73 """
73 Test that loading an ZionWorx file works correctly on various files74 Test that loading an ZionWorx file works correctly on various files
74 """75 """
75 self.file_import(os.path.join(TEST_PATH, 'zionworx.csv'),76 self.file_import(Path(TEST_PATH, 'zionworx.csv'),
76 self.load_external_result_data(os.path.join(TEST_PATH, 'zionworx.json')))77 self.load_external_result_data(os.path.join(TEST_PATH, 'zionworx.json')))
7778
=== modified file 'tests/helpers/songfileimport.py'
--- tests/helpers/songfileimport.py 2017-04-24 05:17:55 +0000
+++ tests/helpers/songfileimport.py 2017-09-30 23:24:21 +0000
@@ -89,7 +89,7 @@
89 """89 """
90 Import the given file and check that it has imported correctly90 Import the given file and check that it has imported correctly
91 """91 """
92 importer = self.importer_class(self.mocked_manager, filenames=[source_file_name])92 importer = self.importer_class(self.mocked_manager, file_paths=[source_file_name])
93 importer.import_wizard = self.mocked_import_wizard93 importer.import_wizard = self.mocked_import_wizard
94 importer.stop_import_flag = False94 importer.stop_import_flag = False
95 importer.topics = []95 importer.topics = []