← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~phill-ridout/openlp/pathlib11 into lp:openlp

 

Phill has proposed merging lp:~phill-ridout/openlp/pathlib11 into lp:openlp.

Requested reviews:
  OpenLP Core (openlp-core)

For more details, see:
https://code.launchpad.net/~phill-ridout/openlp/pathlib11/+merge/335578

Some more pathlib refactors.
Test tidy ups

lp:~phill-ridout/openlp/pathlib11 (revision 2806)
https://ci.openlp.io/job/Branch-01-Pull/2384/                          [WAITING]
[RUNNING]
[SUCCESS]
https://ci.openlp.io/job/Branch-02a-Linux-Tests/2285/                  [WAITING]
[RUNNING]
[SUCCESS]
https://ci.openlp.io/job/Branch-02b-macOS-Tests/80/                    [WAITING]
[SUCCESS]
https://ci.openlp.io/job/Branch-03a-Build-Source/5/                    [WAITING]
[SUCCESS]
https://ci.openlp.io/job/Branch-03b-Build-macOS/5/                     [WAITING]
[RUNNING]
[SUCCESS]
https://ci.openlp.io/job/Branch-04a-Code-Analysis/1467/                [WAITING]
[SUCCESS]
https://ci.openlp.io/job/Branch-04b-Test-Coverage/1280/                [WAITING]
[SUCCESS]
https://ci.openlp.io/job/Branch-05-AppVeyor-Tests/238/                 [WAITING]
[RUNNING]
[ABORTED]
-- 
Your team OpenLP Core is requested to review the proposed merge of lp:~phill-ridout/openlp/pathlib11 into lp:openlp.
=== modified file 'openlp.py'
--- openlp.py	2017-10-23 22:09:57 +0000
+++ openlp.py	2017-12-24 07:50:03 +0000
@@ -39,7 +39,7 @@
     """
     # Create the cache directory if it doesn't exist, and enable the fault handler to log to an error log file
     create_paths(AppLocation.get_directory(AppLocation.CacheDir))
-    faulthandler.enable(open(str(AppLocation.get_directory(AppLocation.CacheDir) / 'error.log'), 'wb'))
+    faulthandler.enable((AppLocation.get_directory(AppLocation.CacheDir) / 'error.log').open('wb'))
 
 
 if __name__ == '__main__':

=== modified file 'openlp/core/lib/mediamanageritem.py'
--- openlp/core/lib/mediamanageritem.py	2017-12-19 19:47:02 +0000
+++ openlp/core/lib/mediamanageritem.py	2017-12-24 07:50:03 +0000
@@ -331,8 +331,7 @@
         """
         new_file_paths = []
         error_shown = False
-        for file_name in data['files']:
-            file_path = str_to_path(file_name)
+        for file_path in data['file_paths']:
             if file_path.suffix[1:].lower() not in self.on_new_file_masks:
                 if not error_shown:
                     critical_error_message_box(

=== modified file 'openlp/core/ui/firsttimeform.py'
--- openlp/core/ui/firsttimeform.py	2017-10-23 22:09:57 +0000
+++ openlp/core/ui/firsttimeform.py	2017-12-24 07:50:03 +0000
@@ -401,7 +401,7 @@
             screenshot = self.config.get('theme_{theme}'.format(theme=theme), 'screenshot')
             item = self.themes_list_widget.item(index)
             if item:
-                item.setIcon(build_icon(os.path.join(gettempdir(), 'openlp', screenshot)))
+                item.setIcon(build_icon(Path(gettempdir(), 'openlp', screenshot)))
 
     def _download_progress(self, count, block_size):
         """
@@ -550,9 +550,9 @@
         Download selected songs, bibles and themes. Returns False on download error
         """
         # Build directories for downloads
-        songs_destination = os.path.join(gettempdir(), 'openlp')
-        bibles_destination = str(AppLocation.get_section_data_path('bibles'))
-        themes_destination = str(AppLocation.get_section_data_path('themes'))
+        songs_destination_path = Path(gettempdir(), 'openlp')
+        bibles_destination_path = AppLocation.get_section_data_path('bibles')
+        themes_destination_path = AppLocation.get_section_data_path('themes')
         missed_files = []
         # Download songs
         for i in range(self.songs_list_widget.count()):
@@ -561,7 +561,7 @@
                 filename, sha256 = item.data(QtCore.Qt.UserRole)
                 self._increment_progress_bar(self.downloading.format(name=filename), 0)
                 self.previous_size = 0
-                destination = Path(songs_destination, str(filename))
+                destination = songs_destination_path / str(filename)
                 if not url_get_file(self, '{path}{name}'.format(path=self.songs_url, name=filename),
                                     destination, sha256):
                     missed_files.append('Song: {name}'.format(name=filename))
@@ -574,8 +574,7 @@
                 self._increment_progress_bar(self.downloading.format(name=bible), 0)
                 self.previous_size = 0
                 if not url_get_file(self, '{path}{name}'.format(path=self.bibles_url, name=bible),
-                                    Path(bibles_destination, bible),
-                                    sha256):
+                                    bibles_destination_path / bible, sha256):
                     missed_files.append('Bible: {name}'.format(name=bible))
             bibles_iterator += 1
         # Download themes
@@ -586,8 +585,7 @@
                 self._increment_progress_bar(self.downloading.format(name=theme), 0)
                 self.previous_size = 0
                 if not url_get_file(self, '{path}{name}'.format(path=self.themes_url, name=theme),
-                                    Path(themes_destination, theme),
-                                    sha256):
+                                    themes_destination_path / theme, sha256):
                     missed_files.append('Theme: {name}'.format(name=theme))
         if missed_files:
             file_list = ''

=== modified file 'openlp/core/widgets/views.py'
--- openlp/core/widgets/views.py	2017-10-27 21:11:29 +0000
+++ openlp/core/widgets/views.py	2017-12-24 07:50:03 +0000
@@ -23,18 +23,36 @@
 The :mod:`listpreviewwidget` is a widget that lists the slides in the slide controller.
 It is based on a QTableWidget but represents its contents in list form.
 """
-import os
-
 from PyQt5 import QtCore, QtGui, QtWidgets
 
 from openlp.core.common import is_win
 from openlp.core.common.i18n import UiStrings
 from openlp.core.common.mixins import RegistryProperties
+from openlp.core.common.path import Path
 from openlp.core.common.registry import Registry
 from openlp.core.common.settings import Settings
 from openlp.core.lib import ImageSource, ItemCapabilities, ServiceItem
 
 
+def handle_mime_data_urls(mime_data):
+    """
+    Process the data from a drag and drop operation.
+
+    :param PyQt5.QtCore.QMimeData mime_data: The mime data from the drag and drop opperation.
+    :return: A list of file paths that were dropped
+    :rtype: list[openlp.core.common.path.Path]
+    """
+    file_paths = []
+    for url in mime_data.urls():
+        local_path = Path(url.toLocalFile())
+        if local_path.is_file():
+            file_paths.append(local_path)
+        elif local_path.is_dir():
+            for path in local_path.iterdir():
+                file_paths.append(path)
+    return file_paths
+
+
 class ListPreviewWidget(QtWidgets.QTableWidget, RegistryProperties):
     """
     A special type of QTableWidget which lists the slides in the slide controller
@@ -326,17 +344,9 @@
         if event.mimeData().hasUrls():
             event.setDropAction(QtCore.Qt.CopyAction)
             event.accept()
-            files = []
-            for url in event.mimeData().urls():
-                local_file = os.path.normpath(url.toLocalFile())
-                if os.path.isfile(local_file):
-                    files.append(local_file)
-                elif os.path.isdir(local_file):
-                    listing = os.listdir(local_file)
-                    for file in listing:
-                        files.append(os.path.join(local_file, file))
+            file_paths = handle_mime_data_urls(event.mimeData())
             Registry().execute('{mime_data}_dnd'.format(mime_data=self.mime_data_text),
-                               {'files': files})
+                               {'file_paths': file_paths})
         else:
             event.ignore()
 
@@ -454,16 +464,9 @@
         if event.mimeData().hasUrls():
             event.setDropAction(QtCore.Qt.CopyAction)
             event.accept()
-            files = []
-            for url in event.mimeData().urls():
-                local_file = url.toLocalFile()
-                if os.path.isfile(local_file):
-                    files.append(local_file)
-                elif os.path.isdir(local_file):
-                    listing = os.listdir(local_file)
-                    for file_name in listing:
-                        files.append(os.path.join(local_file, file_name))
-            Registry().execute('%s_dnd' % self.mime_data_text, {'files': files, 'target': self.itemAt(event.pos())})
+            file_paths = handle_mime_data_urls(event.mimeData())
+            Registry().execute('%s_dnd' % self.mime_data_text,
+                               {'file_paths': file_paths, 'target': self.itemAt(event.pos())})
         elif self.allow_internal_dnd:
             event.setDropAction(QtCore.Qt.CopyAction)
             event.accept()

=== modified file 'openlp/plugins/media/lib/mediaitem.py'
--- openlp/plugins/media/lib/mediaitem.py	2017-11-22 21:56:56 +0000
+++ openlp/plugins/media/lib/mediaitem.py	2017-12-24 07:50:03 +0000
@@ -302,7 +302,7 @@
         Initialize media item.
         """
         self.list_view.clear()
-        self.service_path = os.path.join(str(AppLocation.get_section_data_path(self.settings_section)), 'thumbnails')
+        self.service_path = str(AppLocation.get_section_data_path(self.settings_section) / 'thumbnails')
         create_paths(Path(self.service_path))
         self.load_list([path_to_str(file) for file in Settings().value(self.settings_section + '/media files')])
         self.rebuild_players()

=== modified file 'openlp/plugins/songs/lib/importers/powersong.py'
--- openlp/plugins/songs/lib/importers/powersong.py	2017-10-10 02:29:56 +0000
+++ openlp/plugins/songs/lib/importers/powersong.py	2017-12-24 07:50:03 +0000
@@ -24,10 +24,9 @@
 PowerSong songs into the OpenLP database.
 """
 import logging
-import fnmatch
-import os
 
 from openlp.core.common.i18n import translate
+from openlp.core.common.path import Path
 from openlp.plugins.songs.lib.importers.songimport import SongImport
 
 log = logging.getLogger(__name__)
@@ -89,26 +88,25 @@
         """
         from openlp.plugins.songs.lib.importer import SongFormat
         ps_string = SongFormat.get(SongFormat.PowerSong, 'name')
-        if isinstance(self.import_source, str):
-            if os.path.isdir(self.import_source):
+        if isinstance(self.import_source, Path):
+            if self.import_source.is_dir():
                 dir = self.import_source
                 self.import_source = []
-                for file in os.listdir(dir):
-                    if fnmatch.fnmatch(file, '*.song'):
-                        self.import_source.append(os.path.join(dir, file))
+                for path in dir.glob('*.song'):
+                    self.import_source.append(path)
             else:
-                self.import_source = ''
+                self.import_source = None
         if not self.import_source or not isinstance(self.import_source, list):
             self.log_error(translate('SongsPlugin.PowerSongImport', 'No songs to import.'),
                            translate('SongsPlugin.PowerSongImport', 'No {text} files found.').format(text=ps_string))
             return
         self.import_wizard.progress_bar.setMaximum(len(self.import_source))
-        for file in self.import_source:
+        for file_path in self.import_source:
             if self.stop_import_flag:
                 return
             self.set_defaults()
             parse_error = False
-            with open(file, 'rb') as song_data:
+            with file_path.open('rb') as song_data:
                 while True:
                     try:
                         label = self._read_string(song_data)
@@ -117,7 +115,7 @@
                         field = self._read_string(song_data)
                     except ValueError:
                         parse_error = True
-                        self.log_error(os.path.basename(file),
+                        self.log_error(file_path.name,
                                        translate('SongsPlugin.PowerSongImport',
                                                  'Invalid {text} file. Unexpected byte value.').format(text=ps_string))
                         break
@@ -135,7 +133,7 @@
                 continue
             # Check that file had TITLE field
             if not self.title:
-                self.log_error(os.path.basename(file),
+                self.log_error(file_path.name,
                                translate('SongsPlugin.PowerSongImport',
                                          'Invalid {text} file. Missing "TITLE" header.').format(text=ps_string))
                 continue

=== modified file 'openlp/plugins/songs/lib/importers/sundayplus.py'
--- openlp/plugins/songs/lib/importers/sundayplus.py	2017-09-30 20:16:30 +0000
+++ openlp/plugins/songs/lib/importers/sundayplus.py	2017-12-24 07:50:03 +0000
@@ -60,21 +60,24 @@
         for file_path in self.import_source:
             if self.stop_import_flag:
                 return
-            with file_path.open('rb') as song_file:
-                self.do_import_file(song_file)
-
-    def do_import_file(self, file):
-        """
-        Process the Sunday Plus file object.
-        """
-        self.set_defaults()
-        if not self.parse(file.read()):
-            self.log_error(file.name)
-            return
-        if self.title == '':
-            self.title = self.title_from_filename(file.name)
-        if not self.finish():
-            self.log_error(file.name)
+            self.do_import_file(file_path)
+
+    def do_import_file(self, file_path):
+        """
+        Process the Sunday Plus song file
+
+        :param openlp.core.common.path.Path file_path: The song file to import
+        :rtype: None
+        """
+        with file_path.open('rb') as song_file:
+            self.set_defaults()
+            if not self.parse(song_file.read()):
+                self.log_error(file_path.name)
+                return
+            if self.title == '':
+                self.title = self.title_from_file_path(file_path)
+            if not self.finish():
+                self.log_error(file_path.name)
 
     def parse(self, data, cell=False):
         """
@@ -174,16 +177,15 @@
             i += 1
         return True
 
-    def title_from_filename(self, filename):
+    def title_from_file_path(self, file_path):
         """
         Extract the title from the filename
 
-        :param filename: File name
-        :return:
+        :param openlp.core.common.path.Path file_path: File being imported
+        :return: The song title
+        :rtype: str
         """
-        title = os.path.split(filename)[1]
-        if title.endswith('.ptf'):
-            title = title[:-4]
+        title = file_path.stem
         # For some strange reason all example files names ended with 1-7.
         if title.endswith('1-7'):
             title = title[:-3]

=== modified file 'openlp/plugins/songs/songsplugin.py'
--- openlp/plugins/songs/songsplugin.py	2017-10-10 02:29:56 +0000
+++ openlp/plugins/songs/songsplugin.py	2017-12-24 07:50:03 +0000
@@ -27,6 +27,7 @@
 import logging
 import os
 import sqlite3
+from pathlib import Path
 from tempfile import gettempdir
 
 from PyQt5 import QtCore, QtWidgets
@@ -316,17 +317,16 @@
         self.application.process_events()
         self.on_tools_reindex_item_triggered()
         self.application.process_events()
-        db_dir = os.path.join(gettempdir(), 'openlp')
-        if not os.path.exists(db_dir):
+        db_dir_path = Path(gettempdir(), 'openlp')
+        if not db_dir_path.exists():
             return
-        song_dbs = []
+        song_db_paths = []
         song_count = 0
-        for sfile in os.listdir(db_dir):
-            if sfile.startswith('songs_') and sfile.endswith('.sqlite'):
-                self.application.process_events()
-                song_dbs.append(os.path.join(db_dir, sfile))
-                song_count += SongsPlugin._count_songs(os.path.join(db_dir, sfile))
-        if not song_dbs:
+        for db_file_path in db_dir_path.glob('songs_*.sqlite'):
+            self.application.process_events()
+            song_db_paths.append(db_file_path)
+            song_count += SongsPlugin._count_songs(db_file_path)
+        if not song_db_paths:
             return
         self.application.process_events()
         progress = QtWidgets.QProgressDialog(self.main_window)
@@ -338,8 +338,8 @@
         progress.setMinimumDuration(0)
         progress.forceShow()
         self.application.process_events()
-        for db in song_dbs:
-            importer = OpenLPSongImport(self.manager, file_path=db)
+        for db_path in song_db_paths:
+            importer = OpenLPSongImport(self.manager, file_path=db_path)
             importer.do_import(progress)
             self.application.process_events()
         progress.setValue(song_count)
@@ -373,13 +373,15 @@
             self.manager.delete_object(Song, song.id)
 
     @staticmethod
-    def _count_songs(db_file):
+    def _count_songs(db_path):
         """
         Provide a count of the songs in the database
 
-        :param db_file: the database name to count
+        :param openlp.core.common.path.Path db_path: The database to use
+        :return: The number of songs in the db.
+        :rtype: int
         """
-        connection = sqlite3.connect(db_file)
+        connection = sqlite3.connect(str(db_path))
         cursor = connection.cursor()
         cursor.execute('SELECT COUNT(id) AS song_count FROM songs')
         song_count = cursor.fetchone()[0]

=== modified file 'tests/functional/openlp_core/api/test_tab.py'
--- tests/functional/openlp_core/api/test_tab.py	2017-12-09 15:39:31 +0000
+++ tests/functional/openlp_core/api/test_tab.py	2017-12-24 07:50:03 +0000
@@ -22,7 +22,6 @@
 """
 This module contains tests for the lib submodule of the Remotes plugin.
 """
-import os
 import re
 from unittest import TestCase
 from unittest.mock import patch
@@ -45,7 +44,6 @@
     'remotes/download version': '0000_00_00'
 }
 ZERO_URL = '0.0.0.0'
-TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources'))
 
 
 class TestApiTab(TestCase, TestMixin):

=== modified file 'tests/functional/openlp_core/common/test_registry.py'
--- tests/functional/openlp_core/common/test_registry.py	2017-12-15 16:30:10 +0000
+++ tests/functional/openlp_core/common/test_registry.py	2017-12-24 07:50:03 +0000
@@ -22,14 +22,11 @@
 """
 Package to test the openlp.core.lib package.
 """
-import os
 from unittest import TestCase
 from unittest.mock import MagicMock
 
 from openlp.core.common.registry import Registry, RegistryBase
 
-TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '../', '..', 'resources'))
-
 
 class TestRegistry(TestCase):
 

=== modified file 'tests/functional/openlp_core/lib/test_image_manager.py'
--- tests/functional/openlp_core/lib/test_image_manager.py	2017-12-23 09:30:02 +0000
+++ tests/functional/openlp_core/lib/test_image_manager.py	2017-12-24 07:50:03 +0000
@@ -35,8 +35,9 @@
 from openlp.core.lib.imagemanager import ImageManager, Priority
 
 from tests.helpers.testmixin import TestMixin
+from tests.utils.constants import RESOURCE_PATH
 
-TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources'))
+TEST_PATH = str(RESOURCE_PATH)
 
 
 class TestImageManager(TestCase, TestMixin):

=== modified file 'tests/functional/openlp_core/lib/test_lib.py'
--- tests/functional/openlp_core/lib/test_lib.py	2017-12-23 09:09:45 +0000
+++ tests/functional/openlp_core/lib/test_lib.py	2017-12-24 07:50:03 +0000
@@ -22,7 +22,6 @@
 """
 Package to test the openlp.core.lib package.
 """
-import os
 from unittest import TestCase
 from unittest.mock import MagicMock, patch
 
@@ -32,8 +31,7 @@
 from openlp.core.lib import FormattingTags, build_icon, check_item_selected, clean_tags, compare_chord_lyric, \
     create_separated_list, create_thumb, expand_chords, expand_chords_for_printing, expand_tags, find_formatting_tags, \
     get_text_file_string, image_to_byte, resize_image, str_to_bool, validate_thumb
-
-TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources'))
+from tests.utils.constants import RESOURCE_PATH
 
 
 class TestLib(TestCase):
@@ -273,8 +271,8 @@
         Test the create_thumb() function with a given size.
         """
         # GIVEN: An image to create a thumb of.
-        image_path = Path(TEST_PATH, 'church.jpg')
-        thumb_path = Path(TEST_PATH, 'church_thumb.jpg')
+        image_path = RESOURCE_PATH / 'church.jpg'
+        thumb_path = RESOURCE_PATH / 'church_thumb.jpg'
         thumb_size = QtCore.QSize(10, 20)
 
         # Remove the thumb so that the test actually tests if the thumb will be created. Maybe it was not deleted in the
@@ -307,8 +305,8 @@
         Test the create_thumb() function with no size specified.
         """
         # GIVEN: An image to create a thumb of.
-        image_path = Path(TEST_PATH, 'church.jpg')
-        thumb_path = Path(TEST_PATH, 'church_thumb.jpg')
+        image_path = RESOURCE_PATH / 'church.jpg'
+        thumb_path = RESOURCE_PATH / 'church_thumb.jpg'
         expected_size = QtCore.QSize(63, 88)
 
         # Remove the thumb so that the test actually tests if the thumb will be created. Maybe it was not deleted in the
@@ -341,8 +339,8 @@
         Test the create_thumb() function with invalid size specified.
         """
         # GIVEN: An image to create a thumb of.
-        image_path = Path(TEST_PATH, 'church.jpg')
-        thumb_path = Path(TEST_PATH, 'church_thumb.jpg')
+        image_path = RESOURCE_PATH / 'church.jpg'
+        thumb_path = RESOURCE_PATH / 'church_thumb.jpg'
         thumb_size = QtCore.QSize(-1, -1)
         expected_size = QtCore.QSize(63, 88)
 
@@ -376,8 +374,8 @@
         Test the create_thumb() function with a size of only width specified.
         """
         # GIVEN: An image to create a thumb of.
-        image_path = Path(TEST_PATH, 'church.jpg')
-        thumb_path = Path(TEST_PATH, 'church_thumb.jpg')
+        image_path = RESOURCE_PATH / 'church.jpg'
+        thumb_path = RESOURCE_PATH / 'church_thumb.jpg'
         thumb_size = QtCore.QSize(100, -1)
         expected_size = QtCore.QSize(100, 137)
 
@@ -411,8 +409,8 @@
         Test the create_thumb() function with a size of only height specified.
         """
         # GIVEN: An image to create a thumb of.
-        image_path = Path(TEST_PATH, 'church.jpg')
-        thumb_path = Path(TEST_PATH, 'church_thumb.jpg')
+        image_path = RESOURCE_PATH / 'church.jpg'
+        thumb_path = RESOURCE_PATH / 'church_thumb.jpg'
         thumb_size = QtCore.QSize(-1, 100)
         expected_size = QtCore.QSize(72, 100)
 
@@ -446,8 +444,8 @@
         Test the create_thumb() function with a size of only height specified.
         """
         # GIVEN: An image to create a thumb of.
-        image_path = Path(TEST_PATH, 'church.jpg')
-        thumb_path = Path(TEST_PATH, 'church_thumb.jpg')
+        image_path = RESOURCE_PATH / 'church.jpg'
+        thumb_path = RESOURCE_PATH / 'church_thumb.jpg'
         thumb_size = QtCore.QSize(-1, 100)
         expected_size_1 = QtCore.QSize(88, 88)
         expected_size_2 = QtCore.QSize(100, 100)
@@ -639,7 +637,7 @@
         Test the resize_thumb() function
         """
         # GIVEN: A path to an image.
-        image_path = os.path.join(TEST_PATH, 'church.jpg')
+        image_path = str(RESOURCE_PATH / 'church.jpg')
         wanted_width = 777
         wanted_height = 72
         # We want the background to be white.
@@ -660,7 +658,7 @@
         Test the resize_thumb() function ignoring aspect ratio
         """
         # GIVEN: A path to an image.
-        image_path = os.path.join(TEST_PATH, 'church.jpg')
+        image_path = str(RESOURCE_PATH / 'church.jpg')
         wanted_width = 1000
         wanted_height = 1000
         # We want the background to be white.

=== modified file 'tests/functional/openlp_core/lib/test_serviceitem.py'
--- tests/functional/openlp_core/lib/test_serviceitem.py	2017-12-18 17:10:04 +0000
+++ tests/functional/openlp_core/lib/test_serviceitem.py	2017-12-24 07:50:03 +0000
@@ -30,9 +30,10 @@
 from openlp.core.common.registry import Registry
 from openlp.core.common.settings import Settings
 from openlp.core.lib import ItemCapabilities, ServiceItem, ServiceItemType, FormattingTags
+
 from tests.helpers.testmixin import TestMixin
-
 from tests.utils import assert_length, convert_file_service_item
+from tests.utils.constants import RESOURCE_PATH
 
 VERSE = 'The Lord said to {r}Noah{/r}: \n'\
         'There\'s gonna be a {su}floody{/su}, {sb}floody{/sb}\n'\
@@ -59,7 +60,7 @@
                  '<span style="-webkit-text-fill-color:#FFA500">e</span><span style="-webkit-text-fill-color:#800080">'\
                  'n</span> of the Lord\n'
 FOOTER = ['Arky Arky (Unknown)', 'Public Domain', 'CCLI 123456']
-TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'service'))
+TEST_PATH = str(RESOURCE_PATH / 'service')
 
 __default_settings__ = {
     'songs/enable chords': True,

=== modified file 'tests/functional/openlp_core/test_app.py'
--- tests/functional/openlp_core/test_app.py	2017-12-22 15:50:45 +0000
+++ tests/functional/openlp_core/test_app.py	2017-12-24 07:50:03 +0000
@@ -29,7 +29,7 @@
 from openlp.core.app import OpenLP, parse_options
 from openlp.core.common.settings import Settings
 
-TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'resources'))
+from tests.utils.constants import RESOURCE_PATH
 
 
 def test_parse_options_basic():
@@ -280,7 +280,7 @@
         Test the reimplemented event method
         """
         # GIVEN: A file path and a QEvent.
-        file_path = os.path.join(TEST_PATH, 'church.jpg')
+        file_path = str(RESOURCE_PATH / 'church.jpg')
         mocked_file_method = MagicMock(return_value=file_path)
         event = QtCore.QEvent(QtCore.QEvent.FileOpen)
         event.file = mocked_file_method

=== modified file 'tests/functional/openlp_core/widgets/test_views.py'
--- tests/functional/openlp_core/widgets/test_views.py	2017-12-23 09:22:53 +0000
+++ tests/functional/openlp_core/widgets/test_views.py	2017-12-24 07:50:03 +0000
@@ -22,6 +22,7 @@
 """
 Package to test the openlp.core.widgets.views package.
 """
+import os
 from types import GeneratorType
 from unittest import TestCase
 from unittest.mock import MagicMock, patch, call
@@ -30,7 +31,59 @@
 
 from openlp.core.common.i18n import UiStrings
 from openlp.core.lib import ImageSource
-from openlp.core.widgets.views import ListPreviewWidget, ListWidgetWithDnD, TreeWidgetWithDnD
+from openlp.core.widgets.views import ListPreviewWidget, ListWidgetWithDnD, TreeWidgetWithDnD, handle_mime_data_urls
+
+
+class TestHandleMimeDataUrls(TestCase):
+    """
+    Test the :func:`openlp.core.widgets.views.handle_mime_data_urls` function.
+    """
+    def test_files(self):
+        """
+        Test handle_mime_data_urls when the data points to some files.
+        """
+        # GIVEN: Some mocked objects that return True when is_file is called, and some mocked mime data
+        mocked_path_instance_1 = MagicMock(**{'is_file.return_value': True})
+        mocked_path_instance_2 = MagicMock(**{'is_file.return_value': True})
+        with patch('openlp.core.widgets.views.Path',
+                   side_effect=[mocked_path_instance_1, mocked_path_instance_2]) as mocked_path:
+            mocked_q_url_1 = MagicMock(**{'toLocalFile.return_value': os.path.join('file', 'test', 'path', '1.ext')})
+            mocked_q_url_2 = MagicMock(**{'toLocalFile.return_value': os.path.join('file', 'test', 'path', '2.ext')})
+            mocked_q_mime_data = MagicMock(**{'urls.return_value': [mocked_q_url_1, mocked_q_url_2]})
+
+            # WHEN: Calling handle_mime_data_urls with the mocked mime data
+            result = handle_mime_data_urls(mocked_q_mime_data)
+
+            # THEN: Both mocked Path objects should be returned in the list
+            mocked_path.assert_has_calls([call(os.path.join('file', 'test', 'path', '1.ext')),
+                                          call(os.path.join('file', 'test', 'path', '2.ext'))])
+            assert result == [mocked_path_instance_1, mocked_path_instance_2]
+
+    def test_directory(self):
+        """
+        Test handle_mime_data_urls when the data points to some directories.
+        """
+        # GIVEN: Some mocked objects that return True when is_dir is called, and some mocked mime data
+        mocked_path_instance_1 = MagicMock()
+        mocked_path_instance_2 = MagicMock()
+        mocked_path_instance_3 = MagicMock()
+        mocked_path_instance_4 = MagicMock(**{'is_file.return_value': False, 'is_directory.return_value': True,
+                                              'iterdir.return_value': [mocked_path_instance_1, mocked_path_instance_2]})
+        mocked_path_instance_5 = MagicMock(**{'is_file.return_value': False, 'is_directory.return_value': True,
+                                              'iterdir.return_value': [mocked_path_instance_3]})
+        with patch('openlp.core.widgets.views.Path',
+                   side_effect=[mocked_path_instance_4, mocked_path_instance_5]) as mocked_path:
+            mocked_q_url_1 = MagicMock(**{'toLocalFile.return_value': os.path.join('file', 'test', 'path')})
+            mocked_q_url_2 = MagicMock(**{'toLocalFile.return_value': os.path.join('file', 'test', 'path')})
+            mocked_q_mime_data = MagicMock(**{'urls.return_value': [mocked_q_url_1, mocked_q_url_2]})
+
+            # WHEN: Calling handle_mime_data_urls with the mocked mime data
+            result = handle_mime_data_urls(mocked_q_mime_data)
+
+            # THEN: The three mocked Path file objects should be returned in the list
+            mocked_path.assert_has_calls([call(os.path.join('file', 'test', 'path')),
+                                          call(os.path.join('file', 'test', 'path'))])
+            assert result == [mocked_path_instance_1, mocked_path_instance_2, mocked_path_instance_3]
 
 
 class TestListPreviewWidget(TestCase):

=== modified file 'tests/functional/openlp_plugins/bibles/test_csvimport.py'
--- tests/functional/openlp_plugins/bibles/test_csvimport.py	2017-12-22 15:50:45 +0000
+++ tests/functional/openlp_plugins/bibles/test_csvimport.py	2017-12-24 07:50:03 +0000
@@ -23,8 +23,6 @@
 This module contains tests for the CSV Bible importer.
 """
 import csv
-import json
-import os
 from collections import namedtuple
 from unittest import TestCase
 from unittest.mock import ANY, MagicMock, PropertyMock, call, patch
@@ -34,9 +32,10 @@
 from openlp.plugins.bibles.lib.bibleimport import BibleImport
 from openlp.plugins.bibles.lib.importers.csvbible import Book, CSVBible, Verse
 
+from tests.utils import load_external_result_data
+from tests.utils.constants import RESOURCE_PATH
 
-TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__),
-                                         '..', '..', '..', 'resources', 'bibles'))
+TEST_PATH = RESOURCE_PATH / 'bibles'
 
 
 class TestCSVImport(TestCase):
@@ -332,10 +331,9 @@
         """
         # GIVEN: Test files with a mocked out "manager", "import_wizard", and mocked functions
         #        get_book_ref_id_by_name, create_verse, create_book, session and get_language.
-        result_file = open(os.path.join(TEST_PATH, 'dk1933.json'), 'rb')
-        test_data = json.loads(result_file.read().decode())
-        books_file = Path(TEST_PATH, 'dk1933-books.csv')
-        verses_file = Path(TEST_PATH, 'dk1933-verses.csv')
+        test_data = load_external_result_data(TEST_PATH / 'dk1933.json')
+        books_file = TEST_PATH / 'dk1933-books.csv'
+        verses_file = TEST_PATH / 'dk1933-verses.csv'
         with patch('openlp.plugins.bibles.lib.importers.csvbible.CSVBible.application'):
             mocked_manager = MagicMock()
             mocked_import_wizard = MagicMock()

=== modified file 'tests/functional/openlp_plugins/bibles/test_opensongimport.py'
--- tests/functional/openlp_plugins/bibles/test_opensongimport.py	2017-12-23 09:30:02 +0000
+++ tests/functional/openlp_plugins/bibles/test_opensongimport.py	2017-12-24 07:50:03 +0000
@@ -22,22 +22,20 @@
 """
 This module contains tests for the OpenSong Bible importer.
 """
-import json
-import os
 from unittest import TestCase
 from unittest.mock import MagicMock, patch, call
 
 from lxml import objectify
 
-from openlp.core.common.path import Path
 from openlp.core.common.registry import Registry
 from openlp.plugins.bibles.lib.importers.opensong import OpenSongBible, get_text, parse_chapter_number
 from openlp.plugins.bibles.lib.bibleimport import BibleImport
 
 from tests.helpers.testmixin import TestMixin
+from tests.utils import load_external_result_data
+from tests.utils.constants import RESOURCE_PATH
 
-TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__),
-                                         '..', '..', '..', 'resources', 'bibles'))
+TEST_PATH = RESOURCE_PATH / 'bibles'
 
 
 class TestOpenSongImport(TestCase, TestMixin):
@@ -398,8 +396,7 @@
         """
         # GIVEN: Test files with a mocked out "manager", "import_wizard", and mocked functions
         #       get_book_ref_id_by_name, create_verse, create_book, session and get_language.
-        result_file = open(os.path.join(TEST_PATH, 'dk1933.json'), 'rb')
-        test_data = json.loads(result_file.read().decode())
+        test_data = load_external_result_data(TEST_PATH / 'dk1933.json')
         bible_file = 'opensong-dk1933.xml'
         with patch('openlp.plugins.bibles.lib.importers.opensong.OpenSongBible.application'):
             mocked_manager = MagicMock()
@@ -414,7 +411,7 @@
             importer.get_language.return_value = 'Danish'
 
             # WHEN: Importing bible file
-            importer.file_path = Path(TEST_PATH, bible_file)
+            importer.file_path = TEST_PATH / bible_file
             importer.do_import()
 
             # THEN: The create_verse() method should have been called with each verse in the file.

=== modified file 'tests/functional/openlp_plugins/bibles/test_osisimport.py'
--- tests/functional/openlp_plugins/bibles/test_osisimport.py	2017-12-22 16:53:40 +0000
+++ tests/functional/openlp_plugins/bibles/test_osisimport.py	2017-12-24 07:50:03 +0000
@@ -22,17 +22,17 @@
 """
 This module contains tests for the OSIS Bible importer.
 """
-import os
-import json
 from unittest import TestCase
 from unittest.mock import MagicMock, call, patch
 
-from openlp.core.common.path import Path
 from openlp.plugins.bibles.lib.bibleimport import BibleImport
 from openlp.plugins.bibles.lib.db import BibleDB
 from openlp.plugins.bibles.lib.importers.osis import OSISBible
 
-TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'bibles'))
+from tests.utils import load_external_result_data
+from tests.utils.constants import RESOURCE_PATH
+
+TEST_PATH = RESOURCE_PATH / 'bibles'
 
 
 class TestOsisImport(TestCase):
@@ -420,8 +420,7 @@
         """
         # GIVEN: Test files with a mocked out "manager", "import_wizard", and mocked functions
         #        get_book_ref_id_by_name, create_verse, create_book, session and get_language.
-        result_file = open(os.path.join(TEST_PATH, 'dk1933.json'), 'rb')
-        test_data = json.loads(result_file.read().decode())
+        test_data = load_external_result_data(TEST_PATH / 'dk1933.json')
         bible_file = 'osis-dk1933.xml'
         with patch('openlp.plugins.bibles.lib.importers.osis.OSISBible.application'):
             mocked_manager = MagicMock()
@@ -436,7 +435,7 @@
             importer.get_language.return_value = 'Danish'
 
             # WHEN: Importing bible file
-            importer.file_path = Path(TEST_PATH, bible_file)
+            importer.file_path = TEST_PATH / bible_file
             importer.do_import()
 
             # THEN: The create_verse() method should have been called with each verse in the file.
@@ -450,8 +449,7 @@
         """
         # GIVEN: Test files with a mocked out "manager", "import_wizard", and mocked functions
         #        get_book_ref_id_by_name, create_verse, create_book, session and get_language.
-        result_file = open(os.path.join(TEST_PATH, 'kjv.json'), 'rb')
-        test_data = json.loads(result_file.read().decode())
+        test_data = load_external_result_data(TEST_PATH / 'kjv.json')
         bible_file = 'osis-kjv.xml'
         with patch('openlp.plugins.bibles.lib.importers.osis.OSISBible.application'):
             mocked_manager = MagicMock()
@@ -466,7 +464,7 @@
             importer.get_language.return_value = 'English'
 
             # WHEN: Importing bible file
-            importer.file_path = Path(TEST_PATH, bible_file)
+            importer.file_path = TEST_PATH / bible_file
             importer.do_import()
 
             # THEN: The create_verse() method should have been called with each verse in the file.
@@ -480,8 +478,7 @@
         """
         # GIVEN: Test files with a mocked out "manager", "import_wizard", and mocked functions
         #        get_book_ref_id_by_name, create_verse, create_book, session and get_language.
-        result_file = open(os.path.join(TEST_PATH, 'web.json'), 'rb')
-        test_data = json.loads(result_file.read().decode())
+        test_data = load_external_result_data(TEST_PATH / 'web.json')
         bible_file = 'osis-web.xml'
         with patch('openlp.plugins.bibles.lib.importers.osis.OSISBible.application'):
             mocked_manager = MagicMock()
@@ -496,7 +493,7 @@
             importer.get_language.return_value = 'English'
 
             # WHEN: Importing bible file
-            importer.file_path = Path(TEST_PATH, bible_file)
+            importer.file_path = TEST_PATH / bible_file
             importer.do_import()
 
             # THEN: The create_verse() method should have been called with each verse in the file.
@@ -510,8 +507,7 @@
         """
         # GIVEN: Test files with a mocked out "manager", "import_wizard", and mocked functions
         #        get_book_ref_id_by_name, create_verse, create_book, session and get_language.
-        result_file = open(os.path.join(TEST_PATH, 'dk1933.json'), 'rb')
-        test_data = json.loads(result_file.read().decode())
+        test_data = load_external_result_data(TEST_PATH / 'dk1933.json')
         bible_file = 'osis-dk1933-empty-verse.xml'
         with patch('openlp.plugins.bibles.lib.importers.osis.OSISBible.application'):
             mocked_manager = MagicMock()
@@ -526,7 +522,7 @@
             importer.get_language.return_value = 'Danish'
 
             # WHEN: Importing bible file
-            importer.file_path = Path(TEST_PATH, bible_file)
+            importer.file_path = TEST_PATH / bible_file
             importer.do_import()
 
             # THEN: The create_verse() method should have been called with each verse in the file.

=== modified file 'tests/functional/openlp_plugins/bibles/test_swordimport.py'
--- tests/functional/openlp_plugins/bibles/test_swordimport.py	2017-12-22 15:50:45 +0000
+++ tests/functional/openlp_plugins/bibles/test_swordimport.py	2017-12-24 07:50:03 +0000
@@ -22,9 +22,6 @@
 """
 This module contains tests for the SWORD Bible importer.
 """
-
-import os
-import json
 from unittest import TestCase, skipUnless
 from unittest.mock import MagicMock, patch
 
@@ -36,8 +33,10 @@
 
 from openlp.plugins.bibles.lib.db import BibleDB
 
-TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__),
-                                         '..', '..', '..', 'resources', 'bibles'))
+from tests.utils import load_external_result_data
+from tests.utils.constants import RESOURCE_PATH
+
+TEST_PATH = RESOURCE_PATH / 'bibles'
 
 
 @skipUnless(HAS_PYSWORD, 'pysword not installed')
@@ -81,8 +80,7 @@
         mocked_manager = MagicMock()
         mocked_import_wizard = MagicMock()
         importer = SwordBible(mocked_manager, path='.', name='.', file_path=None, sword_key='', sword_path='')
-        result_file = open(os.path.join(TEST_PATH, 'dk1933.json'), 'rb')
-        test_data = json.loads(result_file.read().decode())
+        test_data = load_external_result_data(TEST_PATH / 'dk1933.json')
         importer.wizard = mocked_import_wizard
         importer.get_book_ref_id_by_name = MagicMock()
         importer.create_verse = MagicMock()

=== modified file 'tests/functional/openlp_plugins/bibles/test_wordprojectimport.py'
--- tests/functional/openlp_plugins/bibles/test_wordprojectimport.py	2017-10-10 19:09:20 +0000
+++ tests/functional/openlp_plugins/bibles/test_wordprojectimport.py	2017-12-24 07:50:03 +0000
@@ -22,18 +22,17 @@
 """
 This module contains tests for the WordProject Bible importer.
 """
-import os
 from unittest import TestCase
 from unittest.mock import MagicMock, patch, call
 
 from openlp.core.common.path import Path
 from openlp.plugins.bibles.lib.importers.wordproject import WordProjectBible
 
+from tests.utils.constants import RESOURCE_PATH
 
-TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__),
-                                         '..', '..', '..', 'resources', 'bibles'))
-INDEX_PAGE = open(os.path.join(TEST_PATH, 'wordproject_index.htm')).read()
-CHAPTER_PAGE = open(os.path.join(TEST_PATH, 'wordproject_chapter.htm')).read()
+TEST_PATH = RESOURCE_PATH / 'bibles'
+INDEX_PAGE = (TEST_PATH / 'wordproject_index.htm').read_bytes().decode()
+CHAPTER_PAGE = (TEST_PATH / 'wordproject_chapter.htm').read_bytes().decode()
 
 
 class TestWordProjectImport(TestCase):

=== modified file 'tests/functional/openlp_plugins/bibles/test_zefaniaimport.py'
--- tests/functional/openlp_plugins/bibles/test_zefaniaimport.py	2017-12-22 16:53:40 +0000
+++ tests/functional/openlp_plugins/bibles/test_zefaniaimport.py	2017-12-24 07:50:03 +0000
@@ -22,17 +22,16 @@
 """
 This module contains tests for the Zefania Bible importer.
 """
-import os
-import json
 from unittest import TestCase
 from unittest.mock import MagicMock, patch
 
-from openlp.core.common.path import Path
+from openlp.plugins.bibles.lib.db import BibleDB
 from openlp.plugins.bibles.lib.importers.zefania import ZefaniaBible
-from openlp.plugins.bibles.lib.db import BibleDB
-
-TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__),
-                                         '..', '..', '..', 'resources', 'bibles'))
+
+from tests.utils import load_external_result_data
+from tests.utils.constants import RESOURCE_PATH
+
+TEST_PATH = RESOURCE_PATH / 'bibles'
 
 
 class TestZefaniaImport(TestCase):
@@ -67,8 +66,7 @@
         """
         # GIVEN: Test files with a mocked out "manager", "import_wizard", and mocked functions
         #        get_book_ref_id_by_name, create_verse, create_book, session and get_language.
-        result_file = open(os.path.join(TEST_PATH, 'dk1933.json'), 'rb')
-        test_data = json.loads(result_file.read().decode())
+        test_data = load_external_result_data(TEST_PATH / 'dk1933.json')
         bible_file = 'zefania-dk1933.xml'
         with patch('openlp.plugins.bibles.lib.importers.zefania.ZefaniaBible.application'):
             mocked_manager = MagicMock()
@@ -82,7 +80,7 @@
             importer.get_language.return_value = 'Danish'
 
             # WHEN: Importing bible file
-            importer.file_path = Path(TEST_PATH, bible_file)
+            importer.file_path = TEST_PATH / bible_file
             importer.do_import()
 
             # THEN: The create_verse() method should have been called with each verse in the file.
@@ -97,8 +95,7 @@
         """
         # GIVEN: Test files with a mocked out "manager", "import_wizard", and mocked functions
         #        get_book_ref_id_by_name, create_verse, create_book, session and get_language.
-        result_file = open(os.path.join(TEST_PATH, 'rst.json'), 'rb')
-        test_data = json.loads(result_file.read().decode())
+        test_data = load_external_result_data(TEST_PATH / 'rst.json')
         bible_file = 'zefania-rst.xml'
         with patch('openlp.plugins.bibles.lib.importers.zefania.ZefaniaBible.application'):
             mocked_manager = MagicMock()
@@ -112,7 +109,7 @@
             importer.get_language.return_value = 'Russian'
 
             # WHEN: Importing bible file
-            importer.file_path = Path(TEST_PATH, bible_file)
+            importer.file_path = TEST_PATH / bible_file
             importer.do_import()
 
             # THEN: The create_verse() method should have been called with each verse in the file.

=== modified file 'tests/functional/openlp_plugins/songs/test_chordproimport.py'
--- tests/functional/openlp_plugins/songs/test_chordproimport.py	2017-09-30 20:16:30 +0000
+++ tests/functional/openlp_plugins/songs/test_chordproimport.py	2017-12-24 07:50:03 +0000
@@ -22,15 +22,12 @@
 """
 This module contains tests for the OpenSong song importer.
 """
-import os
-
-from openlp.core.common.path import Path
+from unittest.mock import patch, MagicMock
 
 from tests.helpers.songfileimport import SongImportTestHelper
-from unittest.mock import patch, MagicMock
+from tests.utils.constants import RESOURCE_PATH
 
-TEST_PATH = os.path.abspath(
-    os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'chordprosongs'))
+TEST_PATH = RESOURCE_PATH / 'chordprosongs'
 
 
 class TestChordProFileImport(SongImportTestHelper):
@@ -50,5 +47,5 @@
         mocked_returned_settings.value.side_effect = lambda value: True if value == 'songs/enable chords' else False
         mocked_settings.return_value = mocked_returned_settings
         # Do the test import
-        self.file_import([Path(TEST_PATH, 'swing-low.chordpro')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'swing-low.json')))
+        self.file_import([TEST_PATH / 'swing-low.chordpro'],
+                         self.load_external_result_data(TEST_PATH / 'swing-low.json'))

=== modified file 'tests/functional/openlp_plugins/songs/test_easyslidesimport.py'
--- tests/functional/openlp_plugins/songs/test_easyslidesimport.py	2017-09-30 20:16:30 +0000
+++ tests/functional/openlp_plugins/songs/test_easyslidesimport.py	2017-12-24 07:50:03 +0000
@@ -21,14 +21,10 @@
 """
 This module contains tests for the EasySlides song importer.
 """
-import os
-
-from openlp.core.common.path import Path
-
 from tests.helpers.songfileimport import SongImportTestHelper
+from tests.utils.constants import RESOURCE_PATH
 
-TEST_PATH = os.path.abspath(
-    os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'easyslidessongs'))
+TEST_PATH = RESOURCE_PATH / 'easyslidessongs'
 
 
 class TestEasySlidesFileImport(SongImportTestHelper):
@@ -42,7 +38,7 @@
         """
         Test that loading an EasySlides file works correctly on various files
         """
-        self.file_import(Path(TEST_PATH, 'amazing-grace.xml'),
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
-        self.file_import(Path(TEST_PATH, 'Export_2017-01-12_BB.xml'),
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'Export_2017-01-12_BB.json')))
+        self.file_import(TEST_PATH / 'amazing-grace.xml',
+                         self.load_external_result_data(TEST_PATH / 'Amazing Grace.json'))
+        self.file_import(TEST_PATH / 'Export_2017-01-12_BB.xml',
+                         self.load_external_result_data(TEST_PATH / 'Export_2017-01-12_BB.json'))

=== modified file 'tests/functional/openlp_plugins/songs/test_ewimport.py'
--- tests/functional/openlp_plugins/songs/test_ewimport.py	2017-12-24 07:11:30 +0000
+++ tests/functional/openlp_plugins/songs/test_ewimport.py	2017-12-24 07:50:03 +0000
@@ -29,8 +29,9 @@
 from openlp.core.common.registry import Registry
 from openlp.plugins.songs.lib.importers.easyworship import EasyWorshipSongImport, FieldDescEntry, FieldType
 
-TEST_PATH = os.path.abspath(
-    os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'easyworshipsongs'))
+from tests.utils.constants import RESOURCE_PATH
+
+TEST_PATH = RESOURCE_PATH / 'easyworshipsongs'
 SONG_TEST_DATA = [
     {'title': 'Amazing Grace',
      'authors': ['John Newton'],
@@ -384,10 +385,10 @@
             mocked_retrieve_windows_encoding.assert_any_call(encoding)
 
     def test_db_file_import(self):
-        return self._run_db_file_import(os.path.join(TEST_PATH, 'Songs.DB'))
+        return self._run_db_file_import(TEST_PATH / 'Songs.DB')
 
     def test_sqlite_db_file_import(self):
-        return self._run_db_file_import(os.path.join(TEST_PATH, 'ew6'))
+        return self._run_db_file_import(TEST_PATH / 'ew6')
 
     def _run_db_file_import(self, source_path):
         """
@@ -417,7 +418,8 @@
             importer.topics = []
 
             # WHEN: Importing each file
-            importer.import_source = source_path
+            # TODO: To Path object
+            importer.import_source = str(source_path)
             import_result = importer.do_import()
 
             # THEN: do_import should return none, the song data should be as expected, and finish should have been
@@ -471,7 +473,7 @@
         importer.topics = []
 
         # WHEN: Importing ews file
-        importer.import_source = os.path.join(TEST_PATH, 'test1.ews')
+        importer.import_source = str(TEST_PATH / 'test1.ews')
         import_result = importer.do_import()
 
         # THEN: do_import should return none, the song data should be as expected, and finish should have been

=== modified file 'tests/functional/openlp_plugins/songs/test_foilpresenterimport.py'
--- tests/functional/openlp_plugins/songs/test_foilpresenterimport.py	2017-12-22 22:20:04 +0000
+++ tests/functional/openlp_plugins/songs/test_foilpresenterimport.py	2017-12-24 07:50:03 +0000
@@ -22,15 +22,11 @@
 """
 This module contains tests for the SongShow Plus song importer.
 """
-import os
 from unittest import TestCase
 from unittest.mock import patch, MagicMock
 
 from openlp.plugins.songs.lib.importers.foilpresenter import FoilPresenter
 
-TEST_PATH = os.path.abspath(
-    os.path.join(os.path.dirname(__file__), '..', '..', '..', '/resources/foilpresentersongs'))
-
 
 class TestFoilPresenter(TestCase):
     """

=== modified file 'tests/functional/openlp_plugins/songs/test_lyriximport.py'
--- tests/functional/openlp_plugins/songs/test_lyriximport.py	2017-09-30 20:16:30 +0000
+++ tests/functional/openlp_plugins/songs/test_lyriximport.py	2017-12-24 07:50:03 +0000
@@ -21,14 +21,10 @@
 """
 This module contains tests for the LyriX song importer.
 """
-import os
-
-from openlp.core.common.path import Path
-
 from tests.helpers.songfileimport import SongImportTestHelper
+from tests.utils.constants import RESOURCE_PATH
 
-TEST_PATH = os.path.abspath(
-    os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'lyrixsongs'))
+TEST_PATH = RESOURCE_PATH / 'lyrixsongs'
 
 
 class TestLyrixFileImport(SongImportTestHelper):
@@ -42,9 +38,9 @@
         """
         Test that loading an LyriX file works correctly on various files
         """
-        self.file_import([Path(TEST_PATH, 'A06.TXT')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
-        self.file_import([Path(TEST_PATH, 'A002.TXT')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace2.json')))
-        self.file_import([Path(TEST_PATH, 'AO05.TXT')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'in die regterhand.json')))
+        self.file_import([TEST_PATH / 'A06.TXT'],
+                         self.load_external_result_data(TEST_PATH / 'Amazing Grace.json'))
+        self.file_import([TEST_PATH / 'A002.TXT'],
+                         self.load_external_result_data(TEST_PATH / 'Amazing Grace2.json'))
+        self.file_import([TEST_PATH / 'AO05.TXT'],
+                         self.load_external_result_data(TEST_PATH / 'in die regterhand.json'))

=== modified file 'tests/functional/openlp_plugins/songs/test_openlyricsimport.py'
--- tests/functional/openlp_plugins/songs/test_openlyricsimport.py	2017-12-23 09:22:53 +0000
+++ tests/functional/openlp_plugins/songs/test_openlyricsimport.py	2017-12-24 07:50:03 +0000
@@ -22,14 +22,12 @@
 """
 This module contains tests for the OpenLyrics song importer.
 """
-import os
 import json
 from unittest import TestCase
 from unittest.mock import MagicMock, patch
 
 from lxml import etree, objectify
 
-from openlp.core.common.path import Path
 from openlp.core.common.registry import Registry
 from openlp.core.common.settings import Settings
 from openlp.plugins.songs.lib.importers.openlyrics import OpenLyricsImport
@@ -37,9 +35,9 @@
 from openlp.plugins.songs.lib.openlyricsxml import OpenLyrics
 
 from tests.helpers.testmixin import TestMixin
+from tests.utils.constants import RESOURCE_PATH
 
-TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__),
-                                         '..', '..', '..', 'resources', 'openlyricssongs'))
+TEST_PATH = RESOURCE_PATH / 'openlyricssongs'
 SONG_TEST_DATA = {
     'What a friend we have in Jesus.xml': {
         'title': 'What A Friend We Have In Jesus',
@@ -130,7 +128,7 @@
             importer.open_lyrics.xml_to_song = MagicMock()
 
             # WHEN: Importing each file
-            importer.import_source = [Path(TEST_PATH, song_file)]
+            importer.import_source = [TEST_PATH / song_file]
             importer.do_import()
 
             # THEN: The xml_to_song() method should have been called
@@ -145,7 +143,7 @@
         Settings().setValue('formattingTags/html_tags', json.dumps(start_tags))
         ol = OpenLyrics(mocked_manager)
         parser = etree.XMLParser(remove_blank_text=True)
-        parsed_file = etree.parse(open(os.path.join(TEST_PATH, 'duchu-tags.xml'), 'rb'), parser)
+        parsed_file = etree.parse((TEST_PATH / 'duchu-tags.xml').open('rb'), parser)
         xml = etree.tostring(parsed_file).decode()
         song_xml = objectify.fromstring(xml)
 

=== modified file 'tests/functional/openlp_plugins/songs/test_opensongimport.py'
--- tests/functional/openlp_plugins/songs/test_opensongimport.py	2017-12-22 22:20:04 +0000
+++ tests/functional/openlp_plugins/songs/test_opensongimport.py	2017-12-24 07:50:03 +0000
@@ -22,18 +22,16 @@
 """
 This module contains tests for the OpenSong song importer.
 """
-import os
 from unittest import TestCase
 from unittest.mock import patch, MagicMock
 
 from openlp.core.common.registry import Registry
-from openlp.core.common.path import Path
 from openlp.plugins.songs.lib.importers.opensong import OpenSongImport
 
 from tests.helpers.songfileimport import SongImportTestHelper
+from tests.utils.constants import RESOURCE_PATH
 
-TEST_PATH = os.path.abspath(
-    os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'opensongsongs'))
+TEST_PATH = RESOURCE_PATH / 'opensongsongs'
 
 
 class TestOpenSongFileImport(SongImportTestHelper):
@@ -53,16 +51,16 @@
         mocked_returned_settings.value.side_effect = lambda value: True if value == 'songs/enable chords' else False
         mocked_settings.return_value = mocked_returned_settings
         # Do the test import
-        self.file_import([Path(TEST_PATH, 'Amazing Grace')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
-        self.file_import([Path(TEST_PATH, 'Beautiful Garden Of Prayer')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'Beautiful Garden Of Prayer.json')))
-        self.file_import([Path(TEST_PATH, 'One, Two, Three, Four, Five')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'One, Two, Three, Four, Five.json')))
-        self.file_import([Path(TEST_PATH, 'Amazing Grace2')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
-        self.file_import([Path(TEST_PATH, 'Amazing Grace with bad CCLI')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace without CCLI.json')))
+        self.file_import([TEST_PATH / 'Amazing Grace'],
+                         self.load_external_result_data(TEST_PATH / 'Amazing Grace.json'))
+        self.file_import([TEST_PATH / 'Beautiful Garden Of Prayer'],
+                         self.load_external_result_data(TEST_PATH / 'Beautiful Garden Of Prayer.json'))
+        self.file_import([TEST_PATH / 'One, Two, Three, Four, Five'],
+                         self.load_external_result_data(TEST_PATH / 'One, Two, Three, Four, Five.json'))
+        self.file_import([TEST_PATH / 'Amazing Grace2'],
+                         self.load_external_result_data(TEST_PATH / 'Amazing Grace.json'))
+        self.file_import([TEST_PATH / 'Amazing Grace with bad CCLI'],
+                         self.load_external_result_data(TEST_PATH / 'Amazing Grace without CCLI.json'))
 
 
 class TestOpenSongImport(TestCase):

=== modified file 'tests/functional/openlp_plugins/songs/test_opsproimport.py'
--- tests/functional/openlp_plugins/songs/test_opsproimport.py	2017-12-22 21:04:29 +0000
+++ tests/functional/openlp_plugins/songs/test_opsproimport.py	2017-12-24 07:50:03 +0000
@@ -22,8 +22,6 @@
 """
 This module contains tests for the WorshipCenter Pro song importer.
 """
-import os
-import json
 from unittest import TestCase, skipUnless
 from unittest.mock import patch, MagicMock
 
@@ -34,7 +32,10 @@
 except ImportError:
     CAN_RUN_TESTS = False
 
-TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'opsprosongs'))
+from tests.utils import load_external_result_data
+from tests.utils.constants import RESOURCE_PATH
+
+TEST_PATH = RESOURCE_PATH / 'opsprosongs'
 
 
 def _get_item(data, key):
@@ -59,8 +60,7 @@
     song.Version = '1'
     song.Origin = '...'
     lyrics = MagicMock()
-    test_file = open(os.path.join(TEST_PATH, test_file), 'rb')
-    lyrics.Lyrics = test_file.read().decode()
+    lyrics.Lyrics = (TEST_PATH / test_file).read_bytes().decode()
     lyrics.Type = 1
     lyrics.IsDualLanguage = dual_language
     return song, lyrics
@@ -106,8 +106,7 @@
         importer.process_song(song, lyrics, [])
 
         # THEN: The imported data should look like expected
-        result_file = open(os.path.join(TEST_PATH, 'You are so faithful.json'), 'rb')
-        result_data = json.loads(result_file.read().decode())
+        result_data = load_external_result_data(TEST_PATH / 'You are so faithful.json')
         assert importer.verses == _get_item(result_data, 'verses')
         assert importer.verse_order_list_generated == _get_item(result_data, 'verse_order_list')
 
@@ -126,8 +125,7 @@
         importer.process_song(song, lyrics, [])
 
         # THEN: The imported data should look like expected
-        result_file = open(os.path.join(TEST_PATH, 'Amazing Grace.json'), 'rb')
-        result_data = json.loads(result_file.read().decode())
+        result_data = load_external_result_data(TEST_PATH / 'Amazing Grace.json')
         assert importer.verses == _get_item(result_data, 'verses')
         assert importer.verse_order_list_generated == _get_item(result_data, 'verse_order_list')
 
@@ -146,8 +144,7 @@
         importer.process_song(song, lyrics, [])
 
         # THEN: The imported data should look like expected
-        result_file = open(os.path.join(TEST_PATH, 'Amazing Grace.json'), 'rb')
-        result_data = json.loads(result_file.read().decode())
+        result_data = load_external_result_data(TEST_PATH / 'Amazing Grace.json')
         assert importer.verses == _get_item(result_data, 'verses')
         assert importer.verse_order_list_generated == _get_item(result_data, 'verse_order_list')
 
@@ -166,7 +163,6 @@
         importer.process_song(song, lyrics, [])
 
         # THEN: The imported data should look like expected
-        result_file = open(os.path.join(TEST_PATH, 'Amazing Grace3.json'), 'rb')
-        result_data = json.loads(result_file.read().decode())
+        result_data = load_external_result_data(TEST_PATH / 'Amazing Grace3.json')
         assert importer.verses == _get_item(result_data, 'verses')
         assert importer.verse_order_list_generated == _get_item(result_data, 'verse_order_list')

=== modified file 'tests/functional/openlp_plugins/songs/test_powerpraiseimport.py'
--- tests/functional/openlp_plugins/songs/test_powerpraiseimport.py	2017-10-10 02:29:56 +0000
+++ tests/functional/openlp_plugins/songs/test_powerpraiseimport.py	2017-12-24 07:50:03 +0000
@@ -23,14 +23,10 @@
 The :mod:`powerpraiseimport` module provides the functionality for importing
 ProPresenter song files into the current installation database.
 """
-import os
-
-from openlp.core.common.path import Path
-
 from tests.helpers.songfileimport import SongImportTestHelper
+from tests.utils.constants import RESOURCE_PATH
 
-TEST_PATH = os.path.abspath(
-    os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'powerpraisesongs'))
+TEST_PATH = RESOURCE_PATH / 'powerpraisesongs'
 
 
 class TestPowerPraiseFileImport(SongImportTestHelper):
@@ -44,7 +40,7 @@
         """
         Test that loading a PowerPraise file works correctly
         """
-        self.file_import([Path(TEST_PATH, 'Naher, mein Gott zu Dir.ppl')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'Naher, mein Gott zu Dir.json')))
-        self.file_import([Path(TEST_PATH, 'You are so faithful.ppl')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'You are so faithful.json')))
+        self.file_import([TEST_PATH / 'Naher, mein Gott zu Dir.ppl'],
+                         self.load_external_result_data(TEST_PATH / 'Naher, mein Gott zu Dir.json'))
+        self.file_import([TEST_PATH / 'You are so faithful.ppl'],
+                         self.load_external_result_data(TEST_PATH / 'You are so faithful.json'))

=== modified file 'tests/functional/openlp_plugins/songs/test_presentationmanagerimport.py'
--- tests/functional/openlp_plugins/songs/test_presentationmanagerimport.py	2017-09-30 20:16:30 +0000
+++ tests/functional/openlp_plugins/songs/test_presentationmanagerimport.py	2017-12-24 07:50:03 +0000
@@ -22,14 +22,10 @@
 """
 This module contains tests for the PresentationManager song importer.
 """
-import os
-
-from openlp.core.common.path import Path
-
 from tests.helpers.songfileimport import SongImportTestHelper
+from tests.utils.constants import RESOURCE_PATH
 
-TEST_PATH = os.path.abspath(
-    os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'presentationmanagersongs'))
+TEST_PATH = RESOURCE_PATH / 'presentationmanagersongs'
 
 
 class TestPresentationManagerFileImport(SongImportTestHelper):
@@ -43,7 +39,7 @@
         """
         Test that loading a PresentationManager file works correctly
         """
-        self.file_import([Path(TEST_PATH, 'Great Is Thy Faithfulness.sng')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'Great Is Thy Faithfulness.json')))
-        self.file_import([Path(TEST_PATH, 'Amazing Grace.sng')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
+        self.file_import([TEST_PATH / 'Great Is Thy Faithfulness.sng'],
+                         self.load_external_result_data(TEST_PATH / 'Great Is Thy Faithfulness.json'))
+        self.file_import([TEST_PATH / 'Amazing Grace.sng'],
+                         self.load_external_result_data(TEST_PATH / 'Amazing Grace.json'))

=== modified file 'tests/functional/openlp_plugins/songs/test_propresenterimport.py'
--- tests/functional/openlp_plugins/songs/test_propresenterimport.py	2017-09-30 20:16:30 +0000
+++ tests/functional/openlp_plugins/songs/test_propresenterimport.py	2017-12-24 07:50:03 +0000
@@ -23,14 +23,10 @@
 The :mod:`propresenterimport` module provides the functionality for importing
 ProPresenter song files into the current installation database.
 """
-import os
-
-from openlp.core.common.path import Path
-
 from tests.helpers.songfileimport import SongImportTestHelper
+from tests.utils.constants import RESOURCE_PATH
 
-TEST_PATH = os.path.abspath(
-    os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'propresentersongs'))
+TEST_PATH = RESOURCE_PATH / 'propresentersongs'
 
 
 class TestProPresenterFileImport(SongImportTestHelper):
@@ -44,19 +40,19 @@
         """
         Test that loading a ProPresenter 4 file works correctly
         """
-        self.file_import([Path(TEST_PATH, 'Amazing Grace.pro4')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
+        self.file_import([TEST_PATH / 'Amazing Grace.pro4'],
+                         self.load_external_result_data(TEST_PATH / 'Amazing Grace.json'))
 
     def test_pro5_song_import(self):
         """
         Test that loading a ProPresenter 5 file works correctly
         """
-        self.file_import([Path(TEST_PATH, 'Amazing Grace.pro5')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
+        self.file_import([TEST_PATH / 'Amazing Grace.pro5'],
+                         self.load_external_result_data(TEST_PATH / 'Amazing Grace.json'))
 
     def test_pro6_song_import(self):
         """
         Test that loading a ProPresenter 6 file works correctly
         """
-        self.file_import([Path(TEST_PATH, 'Amazing Grace.pro6')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
+        self.file_import([TEST_PATH / 'Amazing Grace.pro6'],
+                         self.load_external_result_data(TEST_PATH / 'Amazing Grace.json'))

=== modified file 'tests/functional/openlp_plugins/songs/test_songbeamerimport.py'
--- tests/functional/openlp_plugins/songs/test_songbeamerimport.py	2017-12-23 07:55:26 +0000
+++ tests/functional/openlp_plugins/songs/test_songbeamerimport.py	2017-12-24 07:50:03 +0000
@@ -22,18 +22,16 @@
 """
 This module contains tests for the Songbeamer song importer.
 """
-import os
 from unittest import TestCase
 from unittest.mock import MagicMock, patch
 
 from openlp.core.common.registry import Registry
-from openlp.core.common.path import Path
 from openlp.plugins.songs.lib.importers.songbeamer import SongBeamerImport, SongBeamerTypes
 
 from tests.helpers.songfileimport import SongImportTestHelper
+from tests.utils.constants import RESOURCE_PATH
 
-TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__),
-                                         '..', '..', '..', 'resources', 'songbeamersongs'))
+TEST_PATH = RESOURCE_PATH / 'songbeamersongs'
 
 
 class TestSongBeamerFileImport(SongImportTestHelper):
@@ -52,19 +50,19 @@
         mocked_returned_settings = MagicMock()
         mocked_returned_settings.value.side_effect = lambda value: True if value == 'songs/enable chords' else False
         mocked_settings.return_value = mocked_returned_settings
-        self.file_import([Path(TEST_PATH, 'Amazing Grace.sng')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
-        self.file_import([Path(TEST_PATH, 'Lobsinget dem Herrn.sng')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'Lobsinget dem Herrn.json')))
-        self.file_import([Path(TEST_PATH, 'When I Call On You.sng')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'When I Call On You.json')))
+        self.file_import([TEST_PATH / 'Amazing Grace.sng'],
+                         self.load_external_result_data(TEST_PATH / 'Amazing Grace.json'))
+        self.file_import([TEST_PATH / 'Lobsinget dem Herrn.sng'],
+                         self.load_external_result_data(TEST_PATH / 'Lobsinget dem Herrn.json'))
+        self.file_import([TEST_PATH / 'When I Call On You.sng'],
+                         self.load_external_result_data(TEST_PATH / 'When I Call On You.json'))
 
     def test_cp1252_encoded_file(self):
         """
         Test that a CP1252 encoded file get's decoded properly.
         """
-        self.file_import([Path(TEST_PATH, 'cp1252song.sng')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'cp1252song.json')))
+        self.file_import([TEST_PATH / 'cp1252song.sng'],
+                         self.load_external_result_data(TEST_PATH / 'cp1252song.json'))
 
 
 class TestSongBeamerImport(TestCase):

=== modified file 'tests/functional/openlp_plugins/songs/test_songproimport.py'
--- tests/functional/openlp_plugins/songs/test_songproimport.py	2017-09-30 20:16:30 +0000
+++ tests/functional/openlp_plugins/songs/test_songproimport.py	2017-12-24 07:50:03 +0000
@@ -23,14 +23,10 @@
 The :mod:`songproimport` module provides the functionality for importing
 SongPro song files into the current installation database.
 """
-import os
-
-from openlp.core.common.path import Path
-
 from tests.helpers.songfileimport import SongImportTestHelper
+from tests.utils.constants import RESOURCE_PATH
 
-TEST_PATH = os.path.abspath(
-    os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'songprosongs'))
+TEST_PATH = RESOURCE_PATH / 'songprosongs'
 
 
 class TestSongProFileImport(SongImportTestHelper):
@@ -44,5 +40,5 @@
         """
         Test that loading an SongPro file works correctly
         """
-        self.file_import(Path(TEST_PATH, 'amazing-grace.txt'),
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
+        self.file_import(TEST_PATH / 'amazing-grace.txt',
+                         self.load_external_result_data(TEST_PATH / 'Amazing Grace.json'))

=== modified file 'tests/functional/openlp_plugins/songs/test_songselect.py'
--- tests/functional/openlp_plugins/songs/test_songselect.py	2017-12-24 07:11:30 +0000
+++ tests/functional/openlp_plugins/songs/test_songselect.py	2017-12-24 07:50:03 +0000
@@ -23,7 +23,6 @@
 """
 This module contains tests for the CCLI SongSelect importer.
 """
-import os
 from unittest import TestCase
 from unittest.mock import MagicMock, patch, call
 from urllib.error import URLError
@@ -31,16 +30,15 @@
 from PyQt5 import QtWidgets
 
 from openlp.core.common.registry import Registry
-from openlp.core.common.path import Path
 from openlp.plugins.songs.forms.songselectform import SongSelectForm, SearchWorker
 from openlp.plugins.songs.lib import Song
 from openlp.plugins.songs.lib.songselect import SongSelectImport, LOGOUT_URL, BASE_URL
 
 from tests.helpers.songfileimport import SongImportTestHelper
 from tests.helpers.testmixin import TestMixin
+from tests.utils.constants import RESOURCE_PATH
 
-TEST_PATH = os.path.abspath(
-    os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'songselect'))
+TEST_PATH = RESOURCE_PATH / 'songselect'
 
 
 class TestSongSelectImport(TestCase, TestMixin):
@@ -812,10 +810,8 @@
         """
         Test that loading an OpenSong file works correctly on various files
         """
-        self.file_import([Path(TEST_PATH, 'TestSong.bin')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'TestSong-bin.json')))
-        self.file_import([Path(TEST_PATH, 'TestSong.txt')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'TestSong-txt.json')))
+        self.file_import([TEST_PATH / 'TestSong.bin'], self.load_external_result_data(TEST_PATH / 'TestSong-bin.json'))
+        self.file_import([TEST_PATH / 'TestSong.txt'], self.load_external_result_data(TEST_PATH / 'TestSong-txt.json'))
 
 
 class TestSearchWorker(TestCase, TestMixin):

=== modified file 'tests/functional/openlp_plugins/songs/test_songshowplusimport.py'
--- tests/functional/openlp_plugins/songs/test_songshowplusimport.py	2017-12-22 22:20:04 +0000
+++ tests/functional/openlp_plugins/songs/test_songshowplusimport.py	2017-12-24 07:50:03 +0000
@@ -22,18 +22,16 @@
 """
 This module contains tests for the SongShow Plus song importer.
 """
-import os
 from unittest import TestCase
 from unittest.mock import patch, MagicMock
 
-from openlp.core.common.path import Path
 from openlp.plugins.songs.lib import VerseType
 from openlp.plugins.songs.lib.importers.songshowplus import SongShowPlusImport
 
 from tests.helpers.songfileimport import SongImportTestHelper
+from tests.utils.constants import RESOURCE_PATH
 
-TEST_PATH = os.path.abspath(
-    os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'songshowplussongs'))
+TEST_PATH = RESOURCE_PATH / 'songshowplussongs'
 
 
 class TestSongShowPlusFileImport(SongImportTestHelper):
@@ -47,14 +45,14 @@
         """
         Test that loading a SongShow Plus file works correctly on various files
         """
-        self.file_import([Path(TEST_PATH, 'Amazing Grace.sbsong')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
-        self.file_import([Path(TEST_PATH, 'Beautiful Garden Of Prayer.sbsong')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'Beautiful Garden Of Prayer.json')))
-        self.file_import([Path(TEST_PATH, 'a mighty fortress is our god.sbsong')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'a mighty fortress is our god.json')))
-        self.file_import([Path(TEST_PATH, 'cleanse-me.sbsong')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'cleanse-me.json')))
+        self.file_import([TEST_PATH / 'Amazing Grace.sbsong'],
+                         self.load_external_result_data(TEST_PATH / 'Amazing Grace.json'))
+        self.file_import([TEST_PATH / 'Beautiful Garden Of Prayer.sbsong'],
+                         self.load_external_result_data(TEST_PATH / 'Beautiful Garden Of Prayer.json'))
+        self.file_import([TEST_PATH / 'a mighty fortress is our god.sbsong'],
+                         self.load_external_result_data(TEST_PATH / 'a mighty fortress is our god.json'))
+        self.file_import([TEST_PATH / 'cleanse-me.sbsong'],
+                         self.load_external_result_data(TEST_PATH / 'cleanse-me.json'))
 
 
 class TestSongShowPlusImport(TestCase):

=== modified file 'tests/functional/openlp_plugins/songs/test_sundayplusimport.py'
--- tests/functional/openlp_plugins/songs/test_sundayplusimport.py	2017-09-30 20:16:30 +0000
+++ tests/functional/openlp_plugins/songs/test_sundayplusimport.py	2017-12-24 07:50:03 +0000
@@ -21,15 +21,12 @@
 """
 This module contains tests for the SundayPlus song importer.
 """
-import os
 from unittest.mock import patch
 
-from openlp.core.common.path import Path
-
 from tests.helpers.songfileimport import SongImportTestHelper
+from tests.utils.constants import RESOURCE_PATH
 
-TEST_PATH = os.path.abspath(
-    os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'sundayplussongs'))
+TEST_PATH = RESOURCE_PATH / 'sundayplussongs'
 
 
 class TestSundayPlusFileImport(SongImportTestHelper):
@@ -46,5 +43,5 @@
         with patch('openlp.plugins.songs.lib.importers.sundayplus.retrieve_windows_encoding') as \
                 mocked_retrieve_windows_encoding:
             mocked_retrieve_windows_encoding.return_value = 'cp1252'
-            self.file_import([Path(TEST_PATH, 'Amazing Grace.ptf')],
-                             self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace.json')))
+            self.file_import([TEST_PATH / 'Amazing Grace.ptf'],
+                             self.load_external_result_data(TEST_PATH / 'Amazing Grace.json'))

=== modified file 'tests/functional/openlp_plugins/songs/test_videopsalm.py'
--- tests/functional/openlp_plugins/songs/test_videopsalm.py	2017-09-30 20:16:30 +0000
+++ tests/functional/openlp_plugins/songs/test_videopsalm.py	2017-12-24 07:50:03 +0000
@@ -21,15 +21,12 @@
 """
 This module contains tests for the VideoPsalm song importer.
 """
-import os
-
-from openlp.core.common.path import Path
+from unittest.mock import patch, MagicMock
 
 from tests.helpers.songfileimport import SongImportTestHelper
-from unittest.mock import patch, MagicMock
+from tests.utils.constants import RESOURCE_PATH
 
-TEST_PATH = os.path.abspath(
-    os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'videopsalmsongs'))
+TEST_PATH = RESOURCE_PATH / 'videopsalmsongs'
 
 
 class TestVideoPsalmFileImport(SongImportTestHelper):
@@ -49,7 +46,7 @@
         mocked_returned_settings.value.side_effect = lambda value: True if value == 'songs/enable chords' else False
         mocked_settings.return_value = mocked_returned_settings
         # Do the test import
-        self.file_import(Path(TEST_PATH, 'videopsalm-as-safe-a-stronghold.json'),
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'as-safe-a-stronghold.json')))
-        self.file_import(Path(TEST_PATH, 'videopsalm-as-safe-a-stronghold2.json'),
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'as-safe-a-stronghold2.json')))
+        self.file_import(TEST_PATH / 'videopsalm-as-safe-a-stronghold.json',
+                         self.load_external_result_data(TEST_PATH / 'as-safe-a-stronghold.json'))
+        self.file_import(TEST_PATH / 'videopsalm-as-safe-a-stronghold2.json',
+                         self.load_external_result_data(TEST_PATH / 'as-safe-a-stronghold2.json'))

=== modified file 'tests/functional/openlp_plugins/songs/test_wordsofworshipimport.py'
--- tests/functional/openlp_plugins/songs/test_wordsofworshipimport.py	2017-09-30 20:16:30 +0000
+++ tests/functional/openlp_plugins/songs/test_wordsofworshipimport.py	2017-12-24 07:50:03 +0000
@@ -22,15 +22,10 @@
 """
 This module contains tests for the Words of Worship song importer.
 """
-import os
-
-from openlp.core.common.path import Path
-
 from tests.helpers.songfileimport import SongImportTestHelper
-from openlp.plugins.songs.lib.importers.wordsofworship import WordsOfWorshipImport
+from tests.utils.constants import RESOURCE_PATH
 
-TEST_PATH = os.path.abspath(
-    os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'wordsofworshipsongs'))
+TEST_PATH = RESOURCE_PATH / 'wordsofworshipsongs'
 
 
 class TestWordsOfWorshipFileImport(SongImportTestHelper):
@@ -44,10 +39,9 @@
         """
         Test that loading a Words of Worship file works correctly
         """
-        self.file_import([Path(TEST_PATH, 'Amazing Grace (6 Verses).wow-song')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'Amazing Grace (6 Verses).json')))
-        self.file_import([Path(TEST_PATH, 'When morning gilds the skies.wsg')],
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'When morning gilds the skies.json')))
-        self.file_import([Path(TEST_PATH, 'Holy Holy Holy Lord God Almighty.wow-song')],
-                         self.load_external_result_data(os.path.join(TEST_PATH,
-                                                                     'Holy Holy Holy Lord God Almighty.json')))
+        self.file_import([TEST_PATH / 'Amazing Grace (6 Verses).wow-song'],
+                         self.load_external_result_data(TEST_PATH / 'Amazing Grace (6 Verses).json'))
+        self.file_import([TEST_PATH / 'When morning gilds the skies.wsg'],
+                         self.load_external_result_data(TEST_PATH / 'When morning gilds the skies.json'))
+        self.file_import([TEST_PATH / 'Holy Holy Holy Lord God Almighty.wow-song'],
+                         self.load_external_result_data(TEST_PATH / 'Holy Holy Holy Lord God Almighty.json'))

=== modified file 'tests/functional/openlp_plugins/songs/test_worshipassistantimport.py'
--- tests/functional/openlp_plugins/songs/test_worshipassistantimport.py	2017-09-30 20:16:30 +0000
+++ tests/functional/openlp_plugins/songs/test_worshipassistantimport.py	2017-12-24 07:50:03 +0000
@@ -23,14 +23,10 @@
 The :mod:`worshipassistantimport` module provides the functionality for importing
 WorshipAssistant song files into the current installation database.
 """
-import os
-
-from openlp.core.common.path import Path
-
 from tests.helpers.songfileimport import SongImportTestHelper
+from tests.utils.constants import RESOURCE_PATH
 
-TEST_PATH = os.path.abspath(
-    os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'worshipassistantsongs'))
+TEST_PATH = RESOURCE_PATH / 'worshipassistantsongs'
 
 
 class TestWorshipAssistantFileImport(SongImportTestHelper):
@@ -44,9 +40,8 @@
         """
         Test that loading an Worship Assistant file works correctly
         """
-        self.file_import(Path(TEST_PATH, 'du_herr.csv'),
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'du_herr.json')))
-        self.file_import(Path(TEST_PATH, 'would_you_be_free.csv'),
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'would_you_be_free.json')))
-        self.file_import(Path(TEST_PATH, 'would_you_be_free2.csv'),
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'would_you_be_free.json')))
+        self.file_import(TEST_PATH / 'du_herr.csv', self.load_external_result_data(TEST_PATH / 'du_herr.json'))
+        self.file_import(TEST_PATH / 'would_you_be_free.csv',
+                         self.load_external_result_data(TEST_PATH / 'would_you_be_free.json'))
+        self.file_import(TEST_PATH / 'would_you_be_free2.csv',
+                         self.load_external_result_data(TEST_PATH / 'would_you_be_free.json'))

=== modified file 'tests/functional/openlp_plugins/songs/test_zionworximport.py'
--- tests/functional/openlp_plugins/songs/test_zionworximport.py	2017-12-22 16:53:40 +0000
+++ tests/functional/openlp_plugins/songs/test_zionworximport.py	2017-12-24 07:50:03 +0000
@@ -22,19 +22,17 @@
 """
 This module contains tests for the ZionWorx song importer.
 """
-import os
 from unittest import TestCase
 from unittest.mock import MagicMock, patch
 
 from openlp.core.common.registry import Registry
-from openlp.core.common.path import Path
+from openlp.plugins.songs.lib.importers.songimport import SongImport
 from openlp.plugins.songs.lib.importers.zionworx import ZionWorxImport
-from openlp.plugins.songs.lib.importers.songimport import SongImport
 
 from tests.helpers.songfileimport import SongImportTestHelper
+from tests.utils.constants import RESOURCE_PATH
 
-TEST_PATH = os.path.abspath(
-    os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'zionworxsongs'))
+TEST_PATH = RESOURCE_PATH / 'zionworxsongs'
 
 
 class TestZionWorxImport(TestCase):
@@ -73,5 +71,4 @@
         """
         Test that loading an ZionWorx file works correctly on various files
         """
-        self.file_import(Path(TEST_PATH, 'zionworx.csv'),
-                         self.load_external_result_data(os.path.join(TEST_PATH, 'zionworx.json')))
+        self.file_import(TEST_PATH / 'zionworx.csv', self.load_external_result_data(TEST_PATH / 'zionworx.json'))

=== modified file 'tests/helpers/songfileimport.py'
--- tests/helpers/songfileimport.py	2017-12-23 09:09:45 +0000
+++ tests/helpers/songfileimport.py	2017-12-24 07:50:03 +0000
@@ -29,7 +29,6 @@
 from unittest.mock import MagicMock, patch, call
 
 from openlp.core.common.registry import Registry
-from openlp.plugins.songs.lib.importers.opensong import OpenSongImport
 
 log = logging.getLogger(__name__)
 
@@ -78,12 +77,13 @@
         self.add_author_patcher.stop()
         self.song_import_patcher.stop()
 
-    def load_external_result_data(self, file_name):
+    def load_external_result_data(self, file_path):
         """
         A method to load and return an object containing the song data from an external file.
+
+        :param openlp.core.common.path.Path file_path: The path of the file to load
         """
-        result_file = open(file_name, 'rb')
-        return json.loads(result_file.read().decode())
+        return json.loads(file_path.read_bytes().decode())
 
     def file_import(self, source_file_name, result_data):
         """

=== modified file 'tests/interfaces/openlp_core/ui/media/vendor/test_mediainfoWrapper.py'
--- tests/interfaces/openlp_core/ui/media/vendor/test_mediainfoWrapper.py	2017-12-23 09:09:45 +0000
+++ tests/interfaces/openlp_core/ui/media/vendor/test_mediainfoWrapper.py	2017-12-24 07:50:03 +0000
@@ -22,13 +22,13 @@
 """
 Package to test the openlp.core.ui.media package.
 """
-
-import os
 from unittest import TestCase
 
 from openlp.core.ui.media.vendor.mediainfoWrapper import MediaInfoWrapper
 
-TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', '..', 'resources', 'media'))
+from tests.utils.constants import RESOURCE_PATH
+
+TEST_PATH = RESOURCE_PATH / 'media'
 TEST_MEDIA = [['avi_file.avi', 61495], ['mp3_file.mp3', 134426], ['mpg_file.mpg', 9404], ['mp4_file.mp4', 188336]]
 
 
@@ -40,7 +40,7 @@
         """
         for test_data in TEST_MEDIA:
             # GIVEN: a media file
-            full_path = os.path.normpath(os.path.join(TEST_PATH, test_data[0]))
+            full_path = str(TEST_PATH / test_data[0])
 
             # WHEN the media data is retrieved
             results = MediaInfoWrapper.parse(full_path)

=== modified file 'tests/utils/__init__.py'
--- tests/utils/__init__.py	2017-11-03 20:55:41 +0000
+++ tests/utils/__init__.py	2017-12-24 07:50:03 +0000
@@ -41,3 +41,12 @@
     finally:
         open_file.close()
     return first_line
+
+
+def load_external_result_data(file_path):
+    """
+    A method to load and return an object containing the song data from an external file.
+
+    :param openlp.core.common.path.Path file_path: The path of the file to load
+    """
+    return json.loads(file_path.read_bytes().decode())

=== modified file 'tests/utils/constants.py'
--- tests/utils/constants.py	2013-08-31 18:17:38 +0000
+++ tests/utils/constants.py	2017-12-24 07:50:03 +0000
@@ -1,5 +1,8 @@
 
 import os
 
+from openlp.core.common.path import Path
+
 OPENLP_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
 TEST_RESOURCES_PATH = os.path.join(OPENLP_PATH, 'tests', 'resources')
+RESOURCE_PATH = Path(TEST_RESOURCES_PATH)


Follow ups