← Back to team overview

openlp-core team mailing list archive

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

 

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

Requested reviews:
  Raoul Snyman (raoul-snyman)
  Tim Bentley (trb143)

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

Add this to your merge proposal:
--------------------------------------------------------------------------------
lp:~phill-ridout/openlp/pathlib9 (revision 2783)
https://ci.openlp.io/job/Branch-01-Pull/2286/                          [WAITING]
[RUNNING]
[SUCCESS]
https://ci.openlp.io/job/Branch-02-Functional-Tests/2187/              [WAITING]
[RUNNING]
[SUCCESS]
https://ci.openlp.io/job/Branch-03-Interface-Tests/2068/               [WAITING]
[RUNNING]
[SUCCESS]
https://ci.openlp.io/job/Branch-04a-Code_Analysis/1396/                [WAITING]
[RUNNING]
[SUCCESS]
https://ci.openlp.io/job/Branch-04b-Test_Coverage/1221/                [WAITING]
[RUNNING]
[SUCCESS]
https://ci.openlp.io/job/Branch-04c-Code_Analysis2/351/                [WAITING]
[RUNNING]
[SUCCESS]
https://ci.openlp.io/job/Branch-05-AppVeyor-Tests/183/                 [WAITING]
[RUNNING]
[FAILURE]
Stopping after failure, see https://ci.openlp.io/job/Branch-05-AppVeyor-Tests/183/console for more details
-- 
Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/plugins/bibles/forms/bibleimportform.py'
--- openlp/plugins/bibles/forms/bibleimportform.py	2017-10-23 22:09:57 +0000
+++ openlp/plugins/bibles/forms/bibleimportform.py	2017-11-14 23:03:10 +0000
@@ -23,7 +23,6 @@
 The bible import functions for OpenLP
 """
 import logging
-import os
 import urllib.error
 from lxml import etree
 
@@ -41,6 +40,7 @@
 from openlp.core.lib.db import delete_database
 from openlp.core.lib.exceptions import ValidationError
 from openlp.core.lib.ui import critical_error_message_box
+from openlp.core.widgets.edits import PathEdit
 from openlp.core.widgets.wizard import OpenLPWizard, WizardStrings
 from openlp.plugins.bibles.lib.db import clean_filename
 from openlp.plugins.bibles.lib.importers.http import CWExtract, BGExtract, BSExtract
@@ -122,15 +122,9 @@
         Set up the signals used in the bible importer.
         """
         self.web_source_combo_box.currentIndexChanged.connect(self.on_web_source_combo_box_index_changed)
-        self.osis_browse_button.clicked.connect(self.on_osis_browse_button_clicked)
-        self.csv_books_button.clicked.connect(self.on_csv_books_browse_button_clicked)
-        self.csv_verses_button.clicked.connect(self.on_csv_verses_browse_button_clicked)
-        self.open_song_browse_button.clicked.connect(self.on_open_song_browse_button_clicked)
-        self.zefania_browse_button.clicked.connect(self.on_zefania_browse_button_clicked)
-        self.wordproject_browse_button.clicked.connect(self.on_wordproject_browse_button_clicked)
         self.web_update_button.clicked.connect(self.on_web_update_button_clicked)
-        self.sword_browse_button.clicked.connect(self.on_sword_browse_button_clicked)
-        self.sword_zipbrowse_button.clicked.connect(self.on_sword_zipbrowse_button_clicked)
+        self.sword_folder_path_edit.pathChanged.connect(self.on_sword_folder_path_edit_path_changed)
+        self.sword_zipfile_path_edit.pathChanged.connect(self.on_sword_zipfile_path_edit_path_changed)
 
     def add_custom_pages(self):
         """
@@ -161,17 +155,12 @@
         self.osis_layout.setObjectName('OsisLayout')
         self.osis_file_label = QtWidgets.QLabel(self.osis_widget)
         self.osis_file_label.setObjectName('OsisFileLabel')
-        self.osis_file_layout = QtWidgets.QHBoxLayout()
-        self.osis_file_layout.setObjectName('OsisFileLayout')
-        self.osis_file_edit = QtWidgets.QLineEdit(self.osis_widget)
-        self.osis_file_edit.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
-        self.osis_file_edit.setObjectName('OsisFileEdit')
-        self.osis_file_layout.addWidget(self.osis_file_edit)
-        self.osis_browse_button = QtWidgets.QToolButton(self.osis_widget)
-        self.osis_browse_button.setIcon(self.open_icon)
-        self.osis_browse_button.setObjectName('OsisBrowseButton')
-        self.osis_file_layout.addWidget(self.osis_browse_button)
-        self.osis_layout.addRow(self.osis_file_label, self.osis_file_layout)
+        self.osis_path_edit = PathEdit(
+            self.osis_widget,
+            default_path=Settings().value('bibles/last directory import'),
+            dialog_caption=WizardStrings.OpenTypeFile.format(file_type=WizardStrings.OSIS),
+            show_revert=False)
+        self.osis_layout.addRow(self.osis_file_label, self.osis_path_edit)
         self.osis_layout.setItem(1, QtWidgets.QFormLayout.LabelRole, self.spacer)
         self.select_stack.addWidget(self.osis_widget)
         self.csv_widget = QtWidgets.QWidget(self.select_page)
@@ -181,30 +170,27 @@
         self.csv_layout.setObjectName('CsvLayout')
         self.csv_books_label = QtWidgets.QLabel(self.csv_widget)
         self.csv_books_label.setObjectName('CsvBooksLabel')
-        self.csv_books_layout = QtWidgets.QHBoxLayout()
-        self.csv_books_layout.setObjectName('CsvBooksLayout')
-        self.csv_books_edit = QtWidgets.QLineEdit(self.csv_widget)
-        self.csv_books_edit.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
-        self.csv_books_edit.setObjectName('CsvBooksEdit')
-        self.csv_books_layout.addWidget(self.csv_books_edit)
-        self.csv_books_button = QtWidgets.QToolButton(self.csv_widget)
-        self.csv_books_button.setIcon(self.open_icon)
-        self.csv_books_button.setObjectName('CsvBooksButton')
-        self.csv_books_layout.addWidget(self.csv_books_button)
-        self.csv_layout.addRow(self.csv_books_label, self.csv_books_layout)
+        self.csv_books_path_edit = PathEdit(
+            self.csv_widget,
+            default_path=Settings().value('bibles/last directory import'),
+            dialog_caption=WizardStrings.OpenTypeFile.format(file_type=WizardStrings.CSV),
+            show_revert=False,
+        )
+        self.csv_books_path_edit.filters = \
+            '{name} (*.csv)'.format(name=translate('BiblesPlugin.ImportWizardForm', 'CSV File'))
+        self.csv_layout.addRow(self.csv_books_label, self.csv_books_path_edit)
         self.csv_verses_label = QtWidgets.QLabel(self.csv_widget)
         self.csv_verses_label.setObjectName('CsvVersesLabel')
-        self.csv_verses_layout = QtWidgets.QHBoxLayout()
-        self.csv_verses_layout.setObjectName('CsvVersesLayout')
-        self.csv_verses_edit = QtWidgets.QLineEdit(self.csv_widget)
-        self.csv_verses_edit.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
-        self.csv_verses_edit.setObjectName('CsvVersesEdit')
-        self.csv_verses_layout.addWidget(self.csv_verses_edit)
-        self.csv_verses_button = QtWidgets.QToolButton(self.csv_widget)
-        self.csv_verses_button.setIcon(self.open_icon)
-        self.csv_verses_button.setObjectName('CsvVersesButton')
-        self.csv_verses_layout.addWidget(self.csv_verses_button)
-        self.csv_layout.addRow(self.csv_verses_label, self.csv_verses_layout)
+        self.csv_verses_path_edit = PathEdit(
+            self.csv_widget,
+            default_path=Settings().value('bibles/last directory import'),
+            dialog_caption=WizardStrings.OpenTypeFile.format(file_type=WizardStrings.CSV),
+            show_revert=False,
+        )
+        self.csv_verses_path_edit.filters = \
+            '{name} (*.csv)'.format(name=translate('BiblesPlugin.ImportWizardForm', 'CSV File'))
+        self.csv_layout.addRow(self.csv_books_label, self.csv_books_path_edit)
+        self.csv_layout.addRow(self.csv_verses_label, self.csv_verses_path_edit)
         self.csv_layout.setItem(3, QtWidgets.QFormLayout.LabelRole, self.spacer)
         self.select_stack.addWidget(self.csv_widget)
         self.open_song_widget = QtWidgets.QWidget(self.select_page)
@@ -214,17 +200,13 @@
         self.open_song_layout.setObjectName('OpenSongLayout')
         self.open_song_file_label = QtWidgets.QLabel(self.open_song_widget)
         self.open_song_file_label.setObjectName('OpenSongFileLabel')
-        self.open_song_file_layout = QtWidgets.QHBoxLayout()
-        self.open_song_file_layout.setObjectName('OpenSongFileLayout')
-        self.open_song_file_edit = QtWidgets.QLineEdit(self.open_song_widget)
-        self.open_song_file_edit.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
-        self.open_song_file_edit.setObjectName('OpenSongFileEdit')
-        self.open_song_file_layout.addWidget(self.open_song_file_edit)
-        self.open_song_browse_button = QtWidgets.QToolButton(self.open_song_widget)
-        self.open_song_browse_button.setIcon(self.open_icon)
-        self.open_song_browse_button.setObjectName('OpenSongBrowseButton')
-        self.open_song_file_layout.addWidget(self.open_song_browse_button)
-        self.open_song_layout.addRow(self.open_song_file_label, self.open_song_file_layout)
+        self.open_song_path_edit = PathEdit(
+            self.open_song_widget,
+            default_path=Settings().value('bibles/last directory import'),
+            dialog_caption=WizardStrings.OpenTypeFile.format(file_type=WizardStrings.OS),
+            show_revert=False,
+        )
+        self.open_song_layout.addRow(self.open_song_file_label, self.open_song_path_edit)
         self.open_song_layout.setItem(1, QtWidgets.QFormLayout.LabelRole, self.spacer)
         self.select_stack.addWidget(self.open_song_widget)
         self.web_tab_widget = QtWidgets.QTabWidget(self.select_page)
@@ -292,17 +274,14 @@
         self.zefania_layout.setObjectName('ZefaniaLayout')
         self.zefania_file_label = QtWidgets.QLabel(self.zefania_widget)
         self.zefania_file_label.setObjectName('ZefaniaFileLabel')
-        self.zefania_file_layout = QtWidgets.QHBoxLayout()
-        self.zefania_file_layout.setObjectName('ZefaniaFileLayout')
-        self.zefania_file_edit = QtWidgets.QLineEdit(self.zefania_widget)
-        self.zefania_file_edit.setObjectName('ZefaniaFileEdit')
-        self.zefania_file_layout.addWidget(self.zefania_file_edit)
-        self.zefania_browse_button = QtWidgets.QToolButton(self.zefania_widget)
-        self.zefania_browse_button.setIcon(self.open_icon)
-        self.zefania_browse_button.setObjectName('ZefaniaBrowseButton')
-        self.zefania_file_layout.addWidget(self.zefania_browse_button)
-        self.zefania_layout.addRow(self.zefania_file_label, self.zefania_file_layout)
-        self.zefania_layout.setItem(5, QtWidgets.QFormLayout.LabelRole, self.spacer)
+        self.zefania_path_edit = PathEdit(
+            self.zefania_widget,
+            default_path=Settings().value('bibles/last directory import'),
+            dialog_caption=WizardStrings.OpenTypeFile.format(file_type=WizardStrings.ZEF),
+            show_revert=False,
+        )
+        self.zefania_layout.addRow(self.zefania_file_label, self.zefania_path_edit)
+        self.zefania_layout.setItem(2, QtWidgets.QFormLayout.LabelRole, self.spacer)
         self.select_stack.addWidget(self.zefania_widget)
         self.sword_widget = QtWidgets.QWidget(self.select_page)
         self.sword_widget.setObjectName('SwordWidget')
@@ -318,16 +297,13 @@
         self.sword_folder_label = QtWidgets.QLabel(self.sword_folder_tab)
         self.sword_folder_label.setObjectName('SwordSourceLabel')
         self.sword_folder_label.setObjectName('SwordFolderLabel')
-        self.sword_folder_edit = QtWidgets.QLineEdit(self.sword_folder_tab)
-        self.sword_folder_edit.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
-        self.sword_folder_edit.setObjectName('SwordFolderEdit')
-        self.sword_browse_button = QtWidgets.QToolButton(self.sword_folder_tab)
-        self.sword_browse_button.setIcon(self.open_icon)
-        self.sword_browse_button.setObjectName('SwordBrowseButton')
-        self.sword_folder_layout = QtWidgets.QHBoxLayout()
-        self.sword_folder_layout.addWidget(self.sword_folder_edit)
-        self.sword_folder_layout.addWidget(self.sword_browse_button)
-        self.sword_folder_tab_layout.addRow(self.sword_folder_label, self.sword_folder_layout)
+        self.sword_folder_path_edit = PathEdit(
+            self.sword_folder_tab,
+            default_path=Settings().value('bibles/last directory import'),
+            dialog_caption=WizardStrings.OpenTypeFile.format(file_type=WizardStrings.SWORD),
+            show_revert=False,
+        )
+        self.sword_folder_tab_layout.addRow(self.sword_folder_label, self.sword_folder_path_edit)
         self.sword_bible_label = QtWidgets.QLabel(self.sword_folder_tab)
         self.sword_bible_label.setObjectName('SwordBibleLabel')
         self.sword_bible_combo_box = QtWidgets.QComboBox(self.sword_folder_tab)
@@ -342,16 +318,13 @@
         self.sword_zip_layout.setObjectName('SwordZipLayout')
         self.sword_zipfile_label = QtWidgets.QLabel(self.sword_zip_tab)
         self.sword_zipfile_label.setObjectName('SwordZipFileLabel')
-        self.sword_zipfile_edit = QtWidgets.QLineEdit(self.sword_zip_tab)
-        self.sword_zipfile_edit.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
-        self.sword_zipfile_edit.setObjectName('SwordZipFileEdit')
-        self.sword_zipbrowse_button = QtWidgets.QToolButton(self.sword_zip_tab)
-        self.sword_zipbrowse_button.setIcon(self.open_icon)
-        self.sword_zipbrowse_button.setObjectName('SwordZipBrowseButton')
-        self.sword_zipfile_layout = QtWidgets.QHBoxLayout()
-        self.sword_zipfile_layout.addWidget(self.sword_zipfile_edit)
-        self.sword_zipfile_layout.addWidget(self.sword_zipbrowse_button)
-        self.sword_zip_layout.addRow(self.sword_zipfile_label, self.sword_zipfile_layout)
+        self.sword_zipfile_path_edit = PathEdit(
+            self.sword_zip_tab,
+            default_path=Settings().value('bibles/last directory import'),
+            dialog_caption=WizardStrings.OpenTypeFile.format(file_type=WizardStrings.SWORD),
+            show_revert=False,
+        )
+        self.sword_zip_layout.addRow(self.sword_zipfile_label, self.sword_zipfile_path_edit)
         self.sword_zipbible_label = QtWidgets.QLabel(self.sword_folder_tab)
         self.sword_zipbible_label.setObjectName('SwordZipBibleLabel')
         self.sword_zipbible_combo_box = QtWidgets.QComboBox(self.sword_zip_tab)
@@ -372,18 +345,13 @@
         self.wordproject_layout.setObjectName('WordProjectLayout')
         self.wordproject_file_label = QtWidgets.QLabel(self.wordproject_widget)
         self.wordproject_file_label.setObjectName('WordProjectFileLabel')
-        self.wordproject_file_layout = QtWidgets.QHBoxLayout()
-        self.wordproject_file_layout.setObjectName('WordProjectFileLayout')
-        self.wordproject_file_edit = QtWidgets.QLineEdit(self.wordproject_widget)
-        self.wordproject_file_edit.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
-        self.wordproject_file_edit.setObjectName('WordProjectFileEdit')
-        self.wordproject_file_layout.addWidget(self.wordproject_file_edit)
-        self.wordproject_browse_button = QtWidgets.QToolButton(self.wordproject_widget)
-        self.wordproject_browse_button.setIcon(self.open_icon)
-        self.wordproject_browse_button.setObjectName('WordProjectBrowseButton')
-        self.wordproject_file_layout.addWidget(self.wordproject_browse_button)
-        self.wordproject_layout.addRow(self.wordproject_file_label, self.wordproject_file_layout)
-        self.wordproject_layout.setItem(5, QtWidgets.QFormLayout.LabelRole, self.spacer)
+        self.wordproject_path_edit = PathEdit(
+            self.wordproject_widget,
+            default_path=Settings().value('bibles/last directory import'),
+            dialog_caption=WizardStrings.OpenTypeFile.format(file_type=WizardStrings.WordProject),
+            show_revert=False)
+        self.wordproject_layout.addRow(self.wordproject_file_label, self.wordproject_path_edit)
+        self.wordproject_layout.setItem(1, QtWidgets.QFormLayout.LabelRole, self.spacer)
         self.select_stack.addWidget(self.wordproject_widget)
         self.select_page_layout.addLayout(self.select_stack)
         self.addPage(self.select_page)
@@ -468,8 +436,6 @@
         self.sword_bible_label.setText(translate('BiblesPlugin.ImportWizardForm', 'Bibles:'))
         self.sword_folder_label.setText(translate('BiblesPlugin.ImportWizardForm', 'SWORD data folder:'))
         self.sword_zipfile_label.setText(translate('BiblesPlugin.ImportWizardForm', 'SWORD zip-file:'))
-        self.sword_folder_edit.setPlaceholderText(translate('BiblesPlugin.ImportWizardForm',
-                                                            'Defaults to the standard SWORD data folder'))
         self.sword_zipbible_label.setText(translate('BiblesPlugin.ImportWizardForm', 'Bibles:'))
         self.sword_tab_widget.setTabText(self.sword_tab_widget.indexOf(self.sword_folder_tab),
                                          translate('BiblesPlugin.ImportWizardForm', 'Import from folder'))
@@ -518,7 +484,7 @@
             if self.field('source_format') == BibleFormat.OSIS:
                 if not self.field('osis_location'):
                     critical_error_message_box(UiStrings().NFSs, WizardStrings.YouSpecifyFile % WizardStrings.OSIS)
-                    self.osis_file_edit.setFocus()
+                    self.osis_path_edit.setFocus()
                     return False
             elif self.field('source_format') == BibleFormat.CSV:
                 if not self.field('csv_booksfile'):
@@ -538,18 +504,18 @@
             elif self.field('source_format') == BibleFormat.OpenSong:
                 if not self.field('opensong_file'):
                     critical_error_message_box(UiStrings().NFSs, WizardStrings.YouSpecifyFile % WizardStrings.OS)
-                    self.open_song_file_edit.setFocus()
+                    self.open_song_path_edit.setFocus()
                     return False
             elif self.field('source_format') == BibleFormat.Zefania:
                 if not self.field('zefania_file'):
                     critical_error_message_box(UiStrings().NFSs, WizardStrings.YouSpecifyFile % WizardStrings.ZEF)
-                    self.zefania_file_edit.setFocus()
+                    self.zefania_path_edit.setFocus()
                     return False
             elif self.field('source_format') == BibleFormat.WordProject:
                 if not self.field('wordproject_file'):
                     critical_error_message_box(UiStrings().NFSs,
                                                WizardStrings.YouSpecifyFile % WizardStrings.WordProject)
-                    self.wordproject_file_edit.setFocus()
+                    self.wordproject_path_edit.setFocus()
                     return False
             elif self.field('source_format') == BibleFormat.WebDownload:
                 # If count is 0 the bible list has not yet been downloaded
@@ -563,7 +529,7 @@
                     if not self.field('sword_folder_path') and self.sword_bible_combo_box.count() == 0:
                         critical_error_message_box(UiStrings().NFSs,
                                                    WizardStrings.YouSpecifyFolder % WizardStrings.SWORD)
-                        self.sword_folder_edit.setFocus()
+                        self.sword_folder_path_edit.setFocus()
                         return False
                     key = self.sword_bible_combo_box.itemData(self.sword_bible_combo_box.currentIndex())
                     if 'description' in self.pysword_folder_modules_json[key]:
@@ -575,7 +541,7 @@
                 elif self.sword_tab_widget.currentIndex() == self.sword_tab_widget.indexOf(self.sword_zip_tab):
                     if not self.field('sword_zip_path'):
                         critical_error_message_box(UiStrings().NFSs, WizardStrings.YouSpecifyFile % WizardStrings.SWORD)
-                        self.sword_zipfile_edit.setFocus()
+                        self.sword_zipfile_path_edit.setFocus()
                         return False
                     key = self.sword_zipbible_combo_box.itemData(self.sword_zipbible_combo_box.currentIndex())
                     if 'description' in self.pysword_zip_modules_json[key]:
@@ -586,7 +552,6 @@
         elif self.currentPage() == self.license_details_page:
             license_version = self.field('license_version')
             license_copyright = self.field('license_copyright')
-            path = str(AppLocation.get_section_data_path('bibles'))
             if not license_version:
                 critical_error_message_box(
                     UiStrings().EmptyField,
@@ -608,7 +573,7 @@
                               'existing one.'))
                 self.version_name_edit.setFocus()
                 return False
-            elif os.path.exists(os.path.join(path, clean_filename(license_version))):
+            elif (AppLocation.get_section_data_path('bibles') / clean_filename(license_version)).exists():
                 critical_error_message_box(
                     translate('BiblesPlugin.ImportWizardForm', 'Bible Exists'),
                     translate('BiblesPlugin.ImportWizardForm', 'This Bible already exists. Please import '
@@ -631,57 +596,6 @@
             bibles.sort(key=get_locale_key)
             self.web_translation_combo_box.addItems(bibles)
 
-    def on_osis_browse_button_clicked(self):
-        """
-        Show the file open dialog for the OSIS file.
-        """
-        self.get_file_name(WizardStrings.OpenTypeFile % WizardStrings.OSIS, self.osis_file_edit,
-                           'last directory import')
-
-    def on_csv_books_browse_button_clicked(self):
-        """
-        Show the file open dialog for the books CSV file.
-        """
-        # TODO: Verify format() with varible template
-        self.get_file_name(
-            WizardStrings.OpenTypeFile % WizardStrings.CSV,
-            self.csv_books_edit,
-            'last directory import',
-            '{name} (*.csv)'.format(name=translate('BiblesPlugin.ImportWizardForm', 'CSV File')))
-
-    def on_csv_verses_browse_button_clicked(self):
-        """
-        Show the file open dialog for the verses CSV file.
-        """
-        # TODO: Verify format() with variable template
-        self.get_file_name(WizardStrings.OpenTypeFile % WizardStrings.CSV, self.csv_verses_edit,
-                           'last directory import',
-                           '{name} (*.csv)'.format(name=translate('BiblesPlugin.ImportWizardForm', 'CSV File')))
-
-    def on_open_song_browse_button_clicked(self):
-        """
-        Show the file open dialog for the OpenSong file.
-        """
-        # TODO: Verify format() with variable template
-        self.get_file_name(WizardStrings.OpenTypeFile % WizardStrings.OS, self.open_song_file_edit,
-                           'last directory import')
-
-    def on_zefania_browse_button_clicked(self):
-        """
-        Show the file open dialog for the Zefania file.
-        """
-        # TODO: Verify format() with variable template
-        self.get_file_name(WizardStrings.OpenTypeFile % WizardStrings.ZEF, self.zefania_file_edit,
-                           'last directory import')
-
-    def on_wordproject_browse_button_clicked(self):
-        """
-        Show the file open dialog for the WordProject file.
-        """
-        # TODO: Verify format() with variable template
-        self.get_file_name(WizardStrings.OpenTypeFile % WizardStrings.WordProject, self.wordproject_file_edit,
-                           'last directory import')
-
     def on_web_update_button_clicked(self):
         """
         Download list of bibles from Crosswalk, BibleServer and BibleGateway.
@@ -718,15 +632,13 @@
         self.web_update_button.setEnabled(True)
         self.web_progress_bar.setVisible(False)
 
-    def on_sword_browse_button_clicked(self):
+    def on_sword_folder_path_edit_path_changed(self, new_path):
         """
         Show the file open dialog for the SWORD folder.
         """
-        self.get_folder(WizardStrings.OpenTypeFolder % WizardStrings.SWORD, self.sword_folder_edit,
-                        'last directory import')
-        if self.sword_folder_edit.text():
+        if new_path:
             try:
-                self.pysword_folder_modules = modules.SwordModules(self.sword_folder_edit.text())
+                self.pysword_folder_modules = modules.SwordModules(str(new_path))
                 self.pysword_folder_modules_json = self.pysword_folder_modules.parse_modules()
                 bible_keys = self.pysword_folder_modules_json.keys()
                 self.sword_bible_combo_box.clear()
@@ -735,15 +647,13 @@
             except:
                 self.sword_bible_combo_box.clear()
 
-    def on_sword_zipbrowse_button_clicked(self):
+    def on_sword_zipfile_path_edit_path_changed(self, new_path):
         """
         Show the file open dialog for a SWORD zip-file.
         """
-        self.get_file_name(WizardStrings.OpenTypeFile % WizardStrings.SWORD, self.sword_zipfile_edit,
-                           'last directory import')
-        if self.sword_zipfile_edit.text():
+        if new_path:
             try:
-                self.pysword_zip_modules = modules.SwordModules(self.sword_zipfile_edit.text())
+                self.pysword_zip_modules = modules.SwordModules(str(new_path))
                 self.pysword_zip_modules_json = self.pysword_zip_modules.parse_modules()
                 bible_keys = self.pysword_zip_modules_json.keys()
                 self.sword_zipbible_combo_box.clear()
@@ -757,16 +667,16 @@
         Register the bible import wizard fields.
         """
         self.select_page.registerField('source_format', self.format_combo_box)
-        self.select_page.registerField('osis_location', self.osis_file_edit)
-        self.select_page.registerField('csv_booksfile', self.csv_books_edit)
-        self.select_page.registerField('csv_versefile', self.csv_verses_edit)
-        self.select_page.registerField('opensong_file', self.open_song_file_edit)
-        self.select_page.registerField('zefania_file', self.zefania_file_edit)
-        self.select_page.registerField('wordproject_file', self.wordproject_file_edit)
+        self.select_page.registerField('osis_location', self.osis_path_edit, 'path', PathEdit.pathChanged)
+        self.select_page.registerField('csv_booksfile', self.csv_books_path_edit, 'path', PathEdit.pathChanged)
+        self.select_page.registerField('csv_versefile', self.csv_verses_path_edit, 'path', PathEdit.pathChanged)
+        self.select_page.registerField('opensong_file', self.open_song_path_edit, 'path', PathEdit.pathChanged)
+        self.select_page.registerField('zefania_file', self.zefania_path_edit, 'path', PathEdit.pathChanged)
+        self.select_page.registerField('wordproject_file', self.wordproject_path_edit, 'path', PathEdit.pathChanged)
         self.select_page.registerField('web_location', self.web_source_combo_box)
         self.select_page.registerField('web_biblename', self.web_translation_combo_box)
-        self.select_page.registerField('sword_folder_path', self.sword_folder_edit)
-        self.select_page.registerField('sword_zip_path', self.sword_zipfile_edit)
+        self.select_page.registerField('sword_folder_path', self.sword_folder_path_edit, 'path', PathEdit.pathChanged)
+        self.select_page.registerField('sword_zip_path', self.sword_zipfile_path_edit, 'path', PathEdit.pathChanged)
         self.select_page.registerField('proxy_server', self.web_server_edit)
         self.select_page.registerField('proxy_username', self.web_user_edit)
         self.select_page.registerField('proxy_password', self.web_password_edit)
@@ -785,13 +695,13 @@
         self.finish_button.setVisible(False)
         self.cancel_button.setVisible(True)
         self.setField('source_format', 0)
-        self.setField('osis_location', '')
-        self.setField('csv_booksfile', '')
-        self.setField('csv_versefile', '')
-        self.setField('opensong_file', '')
-        self.setField('zefania_file', '')
-        self.setField('sword_folder_path', '')
-        self.setField('sword_zip_path', '')
+        self.setField('osis_location', None)
+        self.setField('csv_booksfile', None)
+        self.setField('csv_versefile', None)
+        self.setField('opensong_file', None)
+        self.setField('zefania_file', None)
+        self.setField('sword_folder_path', None)
+        self.setField('sword_zip_path', None)
         self.setField('web_location', WebDownload.Crosswalk)
         self.setField('web_biblename', self.web_translation_combo_box.currentIndex())
         self.setField('proxy_server', settings.value('proxy address'))
@@ -833,16 +743,16 @@
         if bible_type == BibleFormat.OSIS:
             # Import an OSIS bible.
             importer = self.manager.import_bible(BibleFormat.OSIS, name=license_version,
-                                                 filename=self.field('osis_location'))
+                                                 file_path=self.field('osis_location'))
         elif bible_type == BibleFormat.CSV:
             # Import a CSV bible.
             importer = self.manager.import_bible(BibleFormat.CSV, name=license_version,
-                                                 booksfile=self.field('csv_booksfile'),
-                                                 versefile=self.field('csv_versefile'))
+                                                 books_path=self.field('csv_booksfile'),
+                                                 verse_path=self.field('csv_versefile'))
         elif bible_type == BibleFormat.OpenSong:
             # Import an OpenSong bible.
             importer = self.manager.import_bible(BibleFormat.OpenSong, name=license_version,
-                                                 filename=self.field('opensong_file'))
+                                                 file_path=self.field('opensong_file'))
         elif bible_type == BibleFormat.WebDownload:
             # Import a bible from the web.
             self.progress_bar.setMaximum(1)
@@ -861,11 +771,11 @@
         elif bible_type == BibleFormat.Zefania:
             # Import a Zefania bible.
             importer = self.manager.import_bible(BibleFormat.Zefania, name=license_version,
-                                                 filename=self.field('zefania_file'))
+                                                 file_path=self.field('zefania_file'))
         elif bible_type == BibleFormat.WordProject:
             # Import a WordProject bible.
             importer = self.manager.import_bible(BibleFormat.WordProject, name=license_version,
-                                                 filename=self.field('wordproject_file'))
+                                                 file_path=self.field('wordproject_file'))
         elif bible_type == BibleFormat.SWORD:
             # Import a SWORD bible.
             if self.sword_tab_widget.currentIndex() == self.sword_tab_widget.indexOf(self.sword_folder_tab):

=== modified file 'openlp/plugins/bibles/lib/bibleimport.py'
--- openlp/plugins/bibles/lib/bibleimport.py	2017-10-29 06:01:25 +0000
+++ openlp/plugins/bibles/lib/bibleimport.py	2017-11-14 23:03:10 +0000
@@ -37,23 +37,23 @@
     """
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
-        self.filename = kwargs['filename'] if 'filename' in kwargs else None
+        self.file_path = kwargs.get('file_path')
         self.wizard = None
         self.stop_import_flag = False
         Registry().register_function('openlp_stop_wizard', self.stop_import)
 
     @staticmethod
-    def is_compressed(file):
+    def is_compressed(file_path):
         """
         Check if the supplied file is compressed
 
-        :param file: A path to the file to check
+        :param file_path: A path to the file to check
         """
-        if is_zipfile(file):
+        if is_zipfile(str(file_path)):
             critical_error_message_box(
                 message=translate('BiblesPlugin.BibleImport',
                                   'The file "{file}" you supplied is compressed. You must decompress it before import.'
-                                  ).format(file=file))
+                                  ).format(file=file_path))
             return True
         return False
 
@@ -143,24 +143,24 @@
             self.log_debug('No book name supplied. Falling back to guess_id')
             book_ref_id = guess_id
         if not book_ref_id:
-            raise ValidationError(msg='Could not resolve book_ref_id in "{}"'.format(self.filename))
+            raise ValidationError(msg='Could not resolve book_ref_id in "{}"'.format(self.file_path))
         book_details = BiblesResourcesDB.get_book_by_id(book_ref_id)
         if book_details is None:
             raise ValidationError(msg='book_ref_id: {book_ref} Could not be found in the BibleResourcesDB while '
-                                      'importing {file}'.format(book_ref=book_ref_id, file=self.filename))
+                                      'importing {file}'.format(book_ref=book_ref_id, file=self.file_path))
         return self.create_book(name, book_ref_id, book_details['testament_id'])
 
-    def parse_xml(self, filename, use_objectify=False, elements=None, tags=None):
+    def parse_xml(self, file_path, use_objectify=False, elements=None, tags=None):
         """
         Parse and clean the supplied file by removing any elements or tags we don't use.
-        :param filename: The filename of the xml file to parse. Str
+        :param file_path: The filename of the xml file to parse. Str
         :param use_objectify: Use the objectify parser rather than the etree parser. (Bool)
         :param elements: A tuple of element names (Str) to remove along with their content.
         :param tags: A tuple of element names (Str) to remove, preserving their content.
         :return: The root element of the xml document
         """
         try:
-            with open(filename, 'rb') as import_file:
+            with file_path.open('rb') as import_file:
                 # NOTE: We don't need to do any of the normal encoding detection here, because lxml does it's own
                 # encoding detection, and the two mechanisms together interfere with each other.
                 if not use_objectify:
@@ -207,17 +207,17 @@
         self.log_debug('Stopping import')
         self.stop_import_flag = True
 
-    def validate_xml_file(self, filename, tag):
+    def validate_xml_file(self, file_path, tag):
         """
         Validate the supplied file
 
-        :param filename: The supplied file
+        :param file_path: The supplied file
         :param tag: The expected root tag type
         :return: True if valid. ValidationError is raised otherwise.
         """
-        if BibleImport.is_compressed(filename):
+        if BibleImport.is_compressed(file_path):
             raise ValidationError(msg='Compressed file')
-        bible = self.parse_xml(filename, use_objectify=True)
+        bible = self.parse_xml(file_path, use_objectify=True)
         if bible is None:
             raise ValidationError(msg='Error when opening file')
         root_tag = bible.tag.lower()

=== modified file 'openlp/plugins/bibles/lib/biblestab.py'
--- openlp/plugins/bibles/lib/biblestab.py	2017-10-07 07:05:07 +0000
+++ openlp/plugins/bibles/lib/biblestab.py	2017-11-14 23:03:10 +0000
@@ -41,11 +41,11 @@
     """
     log.info('Bible Tab loaded')
 
-    def _init_(self, parent, title, visible_title, icon_path):
+    def _init_(self, *args, **kwargs):
         self.paragraph_style = True
         self.show_new_chapters = False
         self.display_style = 0
-        super(BiblesTab, self).__init__(parent, title, visible_title, icon_path)
+        super().__init__(*args, **kwargs)
 
     def setupUi(self):
         self.setObjectName('BiblesTab')

=== modified file 'openlp/plugins/bibles/lib/db.py'
--- openlp/plugins/bibles/lib/db.py	2017-10-28 10:04:09 +0000
+++ openlp/plugins/bibles/lib/db.py	2017-11-14 23:03:10 +0000
@@ -35,6 +35,7 @@
 from openlp.core.common import clean_filename
 from openlp.core.common.applocation import AppLocation
 from openlp.core.common.i18n import translate
+from openlp.core.common.path import Path
 from openlp.core.lib.db import BaseModel, init_db, Manager
 from openlp.core.lib.ui import critical_error_message_box
 from openlp.plugins.bibles.lib import BibleStrings, LanguageSelection, upgrade
@@ -129,10 +130,15 @@
         :param parent:
         :param kwargs:
             ``path``
-                The path to the bible database file.
+                The path to the bible database file. Type: openlp.core.common.path.Path
 
             ``name``
                 The name of the database. This is also used as the file name for SQLite databases.
+
+            ``file``
+                Type: openlp.core.common.path.Path
+
+        :rtype: None
         """
         log.info('BibleDB loaded')
         self._setup(parent, **kwargs)
@@ -145,20 +151,20 @@
         self.session = None
         if 'path' not in kwargs:
             raise KeyError('Missing keyword argument "path".')
+        self.path = kwargs['path']
         if 'name' not in kwargs and 'file' not in kwargs:
             raise KeyError('Missing keyword argument "name" or "file".')
         if 'name' in kwargs:
             self.name = kwargs['name']
             if not isinstance(self.name, str):
                 self.name = str(self.name, 'utf-8')
-            self.file = clean_filename(self.name) + '.sqlite'
+            # TODO: To path object
+            file_path = Path(clean_filename(self.name) + '.sqlite')
         if 'file' in kwargs:
-            self.file = kwargs['file']
-        Manager.__init__(self, 'bibles', init_schema, self.file, upgrade)
+            file_path = kwargs['file']
+        Manager.__init__(self, 'bibles', init_schema, file_path, upgrade)
         if self.session and 'file' in kwargs:
                 self.get_name()
-        if 'path' in kwargs:
-            self.path = kwargs['path']
         self._is_web_bible = None
 
     def get_name(self):
@@ -470,9 +476,9 @@
         Return the cursor object. Instantiate one if it doesn't exist yet.
         """
         if BiblesResourcesDB.cursor is None:
-            file_path = os.path.join(str(AppLocation.get_directory(AppLocation.PluginsDir)),
-                                     'bibles', 'resources', 'bibles_resources.sqlite')
-            conn = sqlite3.connect(file_path)
+            file_path = \
+                AppLocation.get_directory(AppLocation.PluginsDir) / 'bibles' / 'resources' / 'bibles_resources.sqlite'
+            conn = sqlite3.connect(str(file_path))
             BiblesResourcesDB.cursor = conn.cursor()
         return BiblesResourcesDB.cursor
 
@@ -758,17 +764,13 @@
         If necessary loads up the database and creates the tables if the database doesn't exist.
         """
         if AlternativeBookNamesDB.cursor is None:
-            file_path = os.path.join(
-                str(AppLocation.get_directory(AppLocation.DataDir)), 'bibles', 'alternative_book_names.sqlite')
-            if not os.path.exists(file_path):
+            file_path = AppLocation.get_directory(AppLocation.DataDir) / 'bibles' / 'alternative_book_names.sqlite'
+            AlternativeBookNamesDB.conn = sqlite3.connect(str(file_path))
+            if not file_path.exists():
                 # create new DB, create table alternative_book_names
-                AlternativeBookNamesDB.conn = sqlite3.connect(file_path)
                 AlternativeBookNamesDB.conn.execute(
                     'CREATE TABLE alternative_book_names(id INTEGER NOT NULL, '
                     'book_reference_id INTEGER, language_id INTEGER, name VARCHAR(50), PRIMARY KEY (id))')
-            else:
-                # use existing DB
-                AlternativeBookNamesDB.conn = sqlite3.connect(file_path)
             AlternativeBookNamesDB.cursor = AlternativeBookNamesDB.conn.cursor()
         return AlternativeBookNamesDB.cursor
 

=== added file 'openlp/plugins/bibles/lib/importers/__init__.py'
--- openlp/plugins/bibles/lib/importers/__init__.py	1970-01-01 00:00:00 +0000
+++ openlp/plugins/bibles/lib/importers/__init__.py	2017-11-14 23:03:10 +0000
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection                                      #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2017 OpenLP Developers                                   #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it     #
+# under the terms of the GNU General Public License as published by the Free  #
+# Software Foundation; version 2 of the License.                              #
+#                                                                             #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    #
+# more details.                                                               #
+#                                                                             #
+# You should have received a copy of the GNU General Public License along     #
+# with this program; if not, write to the Free Software Foundation, Inc., 59  #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
+###############################################################################
+"""
+The :mod:`~openlp.plugins.bibles.lib.importers` module contains importers for the Bibles plugin.
+"""

=== removed file 'openlp/plugins/bibles/lib/importers/__init__.py'
--- openlp/plugins/bibles/lib/importers/__init__.py	2017-10-23 22:09:57 +0000
+++ openlp/plugins/bibles/lib/importers/__init__.py	1970-01-01 00:00:00 +0000
@@ -1,21 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection                                      #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2017 OpenLP Developers                                   #
-# --------------------------------------------------------------------------- #
-# This program is free software; you can redistribute it and/or modify it     #
-# under the terms of the GNU General Public License as published by the Free  #
-# Software Foundation; version 2 of the License.                              #
-#                                                                             #
-# This program is distributed in the hope that it will be useful, but WITHOUT #
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       #
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    #
-# more details.                                                               #
-#                                                                             #
-# You should have received a copy of the GNU General Public License along     #
-# with this program; if not, write to the Free Software Foundation, Inc., 59  #
-# Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
-###############################################################################

=== modified file 'openlp/plugins/bibles/lib/importers/csvbible.py'
--- openlp/plugins/bibles/lib/importers/csvbible.py	2017-10-07 07:05:07 +0000
+++ openlp/plugins/bibles/lib/importers/csvbible.py	2017-11-14 23:03:10 +0000
@@ -73,8 +73,8 @@
         """
         super().__init__(*args, **kwargs)
         self.log_info(self.__class__.__name__)
-        self.books_file = kwargs['booksfile']
-        self.verses_file = kwargs['versefile']
+        self.books_path = kwargs['books_path']
+        self.verses_path = kwargs['verse_path']
 
     @staticmethod
     def get_book_name(name, books):
@@ -92,21 +92,22 @@
         return book_name
 
     @staticmethod
-    def parse_csv_file(filename, results_tuple):
+    def parse_csv_file(file_path, results_tuple):
         """
         Parse the supplied CSV file.
 
-        :param filename: The name of the file to parse. Str
-        :param results_tuple: The namedtuple to use to store the results. namedtuple
-        :return: An iterable yielding namedtuples of type results_tuple
+        :param openlp.core.common.path.Path file_path: The name of the file to parse.
+        :param namedtuple results_tuple: The namedtuple to use to store the results.
+        :return: An list of namedtuples of type results_tuple
+        :rtype: list[namedtuple]
         """
         try:
-            encoding = get_file_encoding(Path(filename))['encoding']
-            with open(filename, 'r', encoding=encoding, newline='') as csv_file:
+            encoding = get_file_encoding(file_path)['encoding']
+            with file_path.open('r', encoding=encoding, newline='') as csv_file:
                 csv_reader = csv.reader(csv_file, delimiter=',', quotechar='"')
                 return [results_tuple(*line) for line in csv_reader]
         except (OSError, csv.Error):
-            raise ValidationError(msg='Parsing "{file}" failed'.format(file=filename))
+            raise ValidationError(msg='Parsing "{file}" failed'.format(file=file_path))
 
     def process_books(self, books):
         """
@@ -159,12 +160,12 @@
         self.language_id = self.get_language(bible_name)
         if not self.language_id:
             return False
-        books = self.parse_csv_file(self.books_file, Book)
+        books = self.parse_csv_file(self.books_path, Book)
         self.wizard.progress_bar.setValue(0)
         self.wizard.progress_bar.setMinimum(0)
         self.wizard.progress_bar.setMaximum(len(books))
         book_list = self.process_books(books)
-        verses = self.parse_csv_file(self.verses_file, Verse)
+        verses = self.parse_csv_file(self.verses_path, Verse)
         self.wizard.progress_bar.setValue(0)
         self.wizard.progress_bar.setMaximum(len(books) + 1)
         self.process_verses(verses, book_list)

=== modified file 'openlp/plugins/bibles/lib/importers/opensong.py'
--- openlp/plugins/bibles/lib/importers/opensong.py	2016-12-31 11:01:36 +0000
+++ openlp/plugins/bibles/lib/importers/opensong.py	2017-11-14 23:03:10 +0000
@@ -46,7 +46,8 @@
 
     :param number: The raw data from the xml
     :param previous_number: The previous chapter number
-    :return: Number of current chapter. (Int)
+    :return: Number of current chapter.
+    :rtype: int
     """
     if number:
         return int(number.split()[-1])
@@ -132,13 +133,13 @@
         :param bible_name: The name of the bible being imported
         :return: True if import completed, False if import was unsuccessful
         """
-        self.log_debug('Starting OpenSong import from "{name}"'.format(name=self.filename))
-        self.validate_xml_file(self.filename, 'bible')
-        bible = self.parse_xml(self.filename, use_objectify=True)
+        self.log_debug('Starting OpenSong import from "{name}"'.format(name=self.file_path))
+        self.validate_xml_file(self.file_path, 'bible')
+        bible = self.parse_xml(self.file_path, use_objectify=True)
         if bible is None:
             return False
         # No language info in the opensong format, so ask the user
-        self.language_id = self.get_language_id(bible_name=self.filename)
+        self.language_id = self.get_language_id(bible_name=str(self.file_path))
         if not self.language_id:
             return False
         self.process_books(bible.b)

=== modified file 'openlp/plugins/bibles/lib/importers/osis.py'
--- openlp/plugins/bibles/lib/importers/osis.py	2016-12-31 11:01:36 +0000
+++ openlp/plugins/bibles/lib/importers/osis.py	2017-11-14 23:03:10 +0000
@@ -159,14 +159,14 @@
         """
         Loads a Bible from file.
         """
-        self.log_debug('Starting OSIS import from "{name}"'.format(name=self.filename))
-        self.validate_xml_file(self.filename, '{http://www.bibletechnologies.net/2003/osis/namespace}osis')
-        bible = self.parse_xml(self.filename, elements=REMOVABLE_ELEMENTS, tags=REMOVABLE_TAGS)
+        self.log_debug('Starting OSIS import from "{name}"'.format(name=self.file_path))
+        self.validate_xml_file(self.file_path, '{http://www.bibletechnologies.net/2003/osis/namespace}osis')
+        bible = self.parse_xml(self.file_path, elements=REMOVABLE_ELEMENTS, tags=REMOVABLE_TAGS)
         if bible is None:
             return False
         # Find bible language
         language = bible.xpath("//ns:osisText/@xml:lang", namespaces=NS)
-        self.language_id = self.get_language_id(language[0] if language else None, bible_name=self.filename)
+        self.language_id = self.get_language_id(language[0] if language else None, bible_name=str(self.file_path))
         if not self.language_id:
             return False
         self.process_books(bible)

=== modified file 'openlp/plugins/bibles/lib/importers/sword.py'
--- openlp/plugins/bibles/lib/importers/sword.py	2017-10-07 07:05:07 +0000
+++ openlp/plugins/bibles/lib/importers/sword.py	2017-11-14 23:03:10 +0000
@@ -60,7 +60,7 @@
             bible = pysword_modules.get_bible_from_module(self.sword_key)
             language = pysword_module_json['lang']
             language = language[language.find('.') + 1:]
-            language_id = self.get_language_id(language, bible_name=self.filename)
+            language_id = self.get_language_id(language, bible_name=str(self.file_path))
             if not language_id:
                 return False
             books = bible.get_structure().get_books()

=== modified file 'openlp/plugins/bibles/lib/importers/wordproject.py'
--- openlp/plugins/bibles/lib/importers/wordproject.py	2016-12-31 11:01:36 +0000
+++ openlp/plugins/bibles/lib/importers/wordproject.py	2017-11-14 23:03:10 +0000
@@ -19,15 +19,14 @@
 # with this program; if not, write to the Free Software Foundation, Inc., 59  #
 # Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
 ###############################################################################
-import os
+import logging
 import re
-import logging
-from codecs import open as copen
 from tempfile import TemporaryDirectory
 from zipfile import ZipFile
 
 from bs4 import BeautifulSoup, Tag, NavigableString
 
+from openlp.core.common.path import Path
 from openlp.plugins.bibles.lib.bibleimport import BibleImport
 
 BOOK_NUMBER_PATTERN = re.compile(r'\[(\d+)\]')
@@ -51,9 +50,9 @@
         Unzip the file to a temporary directory
         """
         self.tmp = TemporaryDirectory()
-        zip_file = ZipFile(os.path.abspath(self.filename))
-        zip_file.extractall(self.tmp.name)
-        self.base_dir = os.path.join(self.tmp.name, os.path.splitext(os.path.basename(self.filename))[0])
+        with ZipFile(str(self.file_path)) as zip_file:
+            zip_file.extractall(self.tmp.name)
+        self.base_path = Path(self.tmp.name, self.file_path.stem)
 
     def process_books(self):
         """
@@ -62,8 +61,7 @@
         :param bible_data: parsed xml
         :return: None
         """
-        with copen(os.path.join(self.base_dir, 'index.htm'), encoding='utf-8', errors='ignore') as index_file:
-            page = index_file.read()
+        page = (self.base_path / 'index.htm').read_text(encoding='utf-8', errors='ignore')
         soup = BeautifulSoup(page, 'lxml')
         bible_books = soup.find('div', 'textOptions').find_all('li')
         book_count = len(bible_books)
@@ -93,9 +91,7 @@
         :return: None
         """
         log.debug(book_link)
-        book_file = os.path.join(self.base_dir, os.path.normpath(book_link))
-        with copen(book_file, encoding='utf-8', errors='ignore') as f:
-            page = f.read()
+        page = (self.base_path / book_link).read_text(encoding='utf-8', errors='ignore')
         soup = BeautifulSoup(page, 'lxml')
         header_div = soup.find('div', 'textHeader')
         chapters_p = header_div.find('p')
@@ -114,9 +110,8 @@
         """
         Get the verses for a particular book
         """
-        chapter_file_name = os.path.join(self.base_dir, '{:02d}'.format(book_number), '{}.htm'.format(chapter_number))
-        with copen(chapter_file_name, encoding='utf-8', errors='ignore') as chapter_file:
-            page = chapter_file.read()
+        chapter_file_path = self.base_path / '{:02d}'.format(book_number) / '{}.htm'.format(chapter_number)
+        page = chapter_file_path.read_text(encoding='utf-8', errors='ignore')
         soup = BeautifulSoup(page, 'lxml')
         text_body = soup.find('div', 'textBody')
         if text_body:
@@ -158,9 +153,9 @@
         """
         Loads a Bible from file.
         """
-        self.log_debug('Starting WordProject import from "{name}"'.format(name=self.filename))
+        self.log_debug('Starting WordProject import from "{name}"'.format(name=self.file_path))
         self._unzip_file()
-        self.language_id = self.get_language_id(None, bible_name=self.filename)
+        self.language_id = self.get_language_id(None, bible_name=str(self.file_path))
         result = False
         if self.language_id:
             self.process_books()

=== modified file 'openlp/plugins/bibles/lib/importers/zefania.py'
--- openlp/plugins/bibles/lib/importers/zefania.py	2017-10-07 07:05:07 +0000
+++ openlp/plugins/bibles/lib/importers/zefania.py	2017-11-14 23:03:10 +0000
@@ -45,13 +45,13 @@
         """
         Loads a Bible from file.
         """
-        log.debug('Starting Zefania import from "{name}"'.format(name=self.filename))
+        log.debug('Starting Zefania import from "{name}"'.format(name=self.file_path))
         success = True
         try:
-            xmlbible = self.parse_xml(self.filename, elements=REMOVABLE_ELEMENTS, tags=REMOVABLE_TAGS)
+            xmlbible = self.parse_xml(self.file_path, elements=REMOVABLE_ELEMENTS, tags=REMOVABLE_TAGS)
             # Find bible language
             language = xmlbible.xpath("/XMLBIBLE/INFORMATION/language/text()")
-            language_id = self.get_language_id(language[0] if language else None, bible_name=self.filename)
+            language_id = self.get_language_id(language[0] if language else None, bible_name=str(self.file_path))
             if not language_id:
                 return False
             no_of_books = int(xmlbible.xpath('count(//BIBLEBOOK)'))
@@ -69,7 +69,7 @@
                     log.debug('Could not find a name, will use number, basically a guess.')
                     book_ref_id = int(bnumber)
                 if not book_ref_id:
-                    log.error('Importing books from "{name}" failed'.format(name=self.filename))
+                    log.error('Importing books from "{name}" failed'.format(name=self.file_path))
                     return False
                 book_details = BiblesResourcesDB.get_book_by_id(book_ref_id)
                 db_book = self.create_book(book_details['name'], book_ref_id, book_details['testament_id'])

=== modified file 'openlp/plugins/bibles/lib/manager.py'
--- openlp/plugins/bibles/lib/manager.py	2017-10-23 22:09:57 +0000
+++ openlp/plugins/bibles/lib/manager.py	2017-11-14 23:03:10 +0000
@@ -19,7 +19,6 @@
 # with this program; if not, write to the Free Software Foundation, Inc., 59  #
 # Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
 ###############################################################################
-
 import logging
 
 from openlp.core.common import delete_file
@@ -115,7 +114,7 @@
         self.settings_section = 'bibles'
         self.web = 'Web'
         self.db_cache = None
-        self.path = str(AppLocation.get_section_data_path(self.settings_section))
+        self.path = AppLocation.get_section_data_path(self.settings_section)
         self.proxy_name = Settings().value(self.settings_section + '/proxy name')
         self.suffix = '.sqlite'
         self.import_wizard = None
@@ -128,20 +127,20 @@
         of HTTPBible is loaded instead of the BibleDB class.
         """
         log.debug('Reload bibles')
-        files = [str(file) for file in AppLocation.get_files(self.settings_section, self.suffix)]
-        if 'alternative_book_names.sqlite' in files:
-            files.remove('alternative_book_names.sqlite')
-        log.debug('Bible Files {text}'.format(text=files))
+        file_paths = AppLocation.get_files(self.settings_section, self.suffix)
+        if Path('alternative_book_names.sqlite') in file_paths:
+            file_paths.remove(Path('alternative_book_names.sqlite'))
+        log.debug('Bible Files {text}'.format(text=file_paths))
         self.db_cache = {}
-        for filename in files:
-            bible = BibleDB(self.parent, path=self.path, file=filename)
+        for file_path in file_paths:
+            bible = BibleDB(self.parent, path=self.path, file=file_path)
             if not bible.session:
                 continue
             name = bible.get_name()
             # Remove corrupted files.
             if name is None:
                 bible.session.close_all()
-                delete_file(Path(self.path, filename))
+                delete_file(self.path / file_path)
                 continue
             log.debug('Bible Name: "{name}"'.format(name=name))
             self.db_cache[name] = bible
@@ -150,7 +149,7 @@
                 source = self.db_cache[name].get_object(BibleMeta, 'download_source')
                 download_name = self.db_cache[name].get_object(BibleMeta, 'download_name').value
                 meta_proxy = self.db_cache[name].get_object(BibleMeta, 'proxy_server')
-                web_bible = HTTPBible(self.parent, path=self.path, file=filename, download_source=source.value,
+                web_bible = HTTPBible(self.parent, path=self.path, file=file_path, download_source=source.value,
                                       download_name=download_name)
                 if meta_proxy:
                     web_bible.proxy_server = meta_proxy.value

=== modified file 'tests/functional/openlp_plugins/bibles/test_bibleimport.py'
--- tests/functional/openlp_plugins/bibles/test_bibleimport.py	2017-10-29 06:01:25 +0000
+++ tests/functional/openlp_plugins/bibles/test_bibleimport.py	2017-11-14 23:03:10 +0000
@@ -30,6 +30,7 @@
 from PyQt5.QtWidgets import QDialog
 
 from openlp.core.common.i18n import Language
+from openlp.core.common.path import Path
 from openlp.core.lib.exceptions import ValidationError
 from openlp.plugins.bibles.lib.bibleimport import BibleImport
 from openlp.plugins.bibles.lib.db import BibleDB
@@ -48,7 +49,7 @@
             b'    <data><unsupported>Test<x>data</x><y>to</y>discard</unsupported></data>\n'
             b'</root>'
         )
-        self.open_patcher = patch('builtins.open')
+        self.open_patcher = patch.object(Path, 'open')
         self.addCleanup(self.open_patcher.stop)
         self.mocked_open = self.open_patcher.start()
         self.critical_error_message_box_patcher = \
@@ -74,8 +75,8 @@
         # WHEN: Creating an instance of BibleImport with no key word arguments
         instance = BibleImport(MagicMock())
 
-        # THEN: The filename attribute should be None
-        assert instance.filename is None
+        # THEN: The file_path attribute should be None
+        assert instance.file_path is None
         assert isinstance(instance, BibleDB)
 
     def test_init_kwargs_set(self):
@@ -84,11 +85,11 @@
         """
         # GIVEN: A patched BibleDB._setup, BibleImport class and mocked parent
         # WHEN: Creating an instance of BibleImport with selected key word arguments
-        kwargs = {'filename': 'bible.xml'}
+        kwargs = {'file_path': 'bible.xml'}
         instance = BibleImport(MagicMock(), **kwargs)
 
-        # THEN: The filename keyword should be set to bible.xml
-        assert instance.filename == 'bible.xml'
+        # THEN: The file_path keyword should be set to bible.xml
+        assert instance.file_path == 'bible.xml'
         assert isinstance(instance, BibleDB)
 
     @patch.object(BibleDB, '_setup')
@@ -361,7 +362,7 @@
         instance.wizard = MagicMock()
 
         # WHEN: Calling parse_xml
-        result = instance.parse_xml('file.tst')
+        result = instance.parse_xml(Path('file.tst'))
 
         # THEN: The result returned should contain the correct data, and should be an instance of eetree_Element
         assert etree.tostring(result) == b'<root>\n    <data><div>Test<p>data</p><a>to</a>keep</div></data>\n' \
@@ -378,7 +379,7 @@
         instance.wizard = MagicMock()
 
         # WHEN: Calling parse_xml
-        result = instance.parse_xml('file.tst', use_objectify=True)
+        result = instance.parse_xml(Path('file.tst'), use_objectify=True)
 
         # THEN: The result returned should contain the correct data, and should be an instance of ObjectifiedElement
         assert etree.tostring(result) == b'<root><data><div>Test<p>data</p><a>to</a>keep</div></data>' \
@@ -396,7 +397,7 @@
         instance.wizard = MagicMock()
 
         # WHEN: Calling parse_xml, with a test file
-        result = instance.parse_xml('file.tst', elements=elements)
+        result = instance.parse_xml(Path('file.tst'), elements=elements)
 
         # THEN: The result returned should contain the correct data
         assert etree.tostring(result) == \
@@ -413,7 +414,7 @@
         instance.wizard = MagicMock()
 
         # WHEN: Calling parse_xml, with a test file
-        result = instance.parse_xml('file.tst', tags=tags)
+        result = instance.parse_xml(Path('file.tst'), tags=tags)
 
         # THEN: The result returned should contain the correct data
         assert etree.tostring(result) == b'<root>\n    <data>Testdatatokeep</data>\n    <data><unsupported>Test' \
@@ -431,7 +432,7 @@
         instance.wizard = MagicMock()
 
         # WHEN: Calling parse_xml, with a test file
-        result = instance.parse_xml('file.tst', elements=elements, tags=tags)
+        result = instance.parse_xml(Path('file.tst'), elements=elements, tags=tags)
 
         # THEN: The result returned should contain the correct data
         assert etree.tostring(result) == b'<root>\n    <data>Testdatatokeep</data>\n    <data/>\n</root>'
@@ -446,10 +447,10 @@
         exception.filename = 'file.tst'
         exception.strerror = 'No such file or directory'
         self.mocked_open.side_effect = exception
-        importer = BibleImport(MagicMock(), path='.', name='.', filename='')
+        importer = BibleImport(MagicMock(), path='.', name='.', file_path=None)
 
         # WHEN: Calling parse_xml
-        result = importer.parse_xml('file.tst')
+        result = importer.parse_xml(Path('file.tst'))
 
         # THEN: parse_xml should have caught the error, informed the user and returned None
         mocked_log_exception.assert_called_once_with('Opening file.tst failed.')
@@ -468,10 +469,10 @@
         exception.filename = 'file.tst'
         exception.strerror = 'Permission denied'
         self.mocked_open.side_effect = exception
-        importer = BibleImport(MagicMock(), path='.', name='.', filename='')
+        importer = BibleImport(MagicMock(), path='.', name='.', file_path=None)
 
         # WHEN: Calling parse_xml
-        result = importer.parse_xml('file.tst')
+        result = importer.parse_xml(Path('file.tst'))
 
         # THEN: parse_xml should have caught the error, informed the user and returned None
         mocked_log_exception.assert_called_once_with('Opening file.tst failed.')
@@ -485,7 +486,7 @@
         Test set_current_chapter
         """
         # GIVEN: An instance of BibleImport and a mocked wizard
-        importer = BibleImport(MagicMock(), path='.', name='.', filename='')
+        importer = BibleImport(MagicMock(), path='.', name='.', file_path=None)
         importer.wizard = MagicMock()
 
         # WHEN: Calling set_current_chapter
@@ -500,7 +501,7 @@
         Test that validate_xml_file raises a ValidationError when is_compressed returns True
         """
         # GIVEN: A mocked parse_xml which returns None
-        importer = BibleImport(MagicMock(), path='.', name='.', filename='')
+        importer = BibleImport(MagicMock(), path='.', name='.', file_path=None)
 
         # WHEN: Calling is_compressed
         # THEN: ValidationError should be raised, with the message 'Compressed file'
@@ -515,7 +516,7 @@
         Test that validate_xml_file raises a ValidationError when parse_xml returns None
         """
         # GIVEN: A mocked parse_xml which returns None
-        importer = BibleImport(MagicMock(), path='.', name='.', filename='')
+        importer = BibleImport(MagicMock(), path='.', name='.', file_path=None)
 
         # WHEN: Calling validate_xml_file
         # THEN: ValidationError should be raised, with the message 'Error when opening file'
@@ -531,7 +532,7 @@
         Test that validate_xml_file returns True with valid XML
         """
         # GIVEN: Some test data with an OpenSong Bible "bible" root tag
-        importer = BibleImport(MagicMock(), path='.', name='.', filename='')
+        importer = BibleImport(MagicMock(), path='.', name='.', file_path=None)
 
         # WHEN: Calling validate_xml_file
         result = importer.validate_xml_file('file.name', 'bible')
@@ -546,7 +547,7 @@
         Test that validate_xml_file raises a ValidationError with an OpenSong root tag
         """
         # GIVEN: Some test data with an Zefania root tag and an instance of BibleImport
-        importer = BibleImport(MagicMock(), path='.', name='.', filename='')
+        importer = BibleImport(MagicMock(), path='.', name='.', file_path=None)
 
         # WHEN: Calling validate_xml_file
         # THEN: ValidationError should be raised, and the critical error message box should was called informing
@@ -566,7 +567,7 @@
         # GIVEN: Some test data with an Zefania root tag and an instance of BibleImport
         mocked_parse_xml.return_value = objectify.fromstring(
             '<osis xmlns=\'http://www.bibletechnologies.net/2003/OSIS/namespace\'></osis>')
-        importer = BibleImport(MagicMock(), path='.', name='.', filename='')
+        importer = BibleImport(MagicMock(), path='.', name='.', file_path=None)
 
         # WHEN: Calling validate_xml_file
         # THEN: ValidationError should be raised, and the critical error message box should was called informing
@@ -584,7 +585,7 @@
         Test that validate_xml_file raises a ValidationError with an Zefania root tag
         """
         # GIVEN: Some test data with an Zefania root tag and an instance of BibleImport
-        importer = BibleImport(MagicMock(), path='.', name='.', filename='')
+        importer = BibleImport(MagicMock(), path='.', name='.', file_path=None)
 
         # WHEN: Calling validate_xml_file
         # THEN: ValidationError should be raised, and the critical error message box should was called informing
@@ -602,7 +603,7 @@
         Test that validate_xml_file raises a ValidationError with an unknown root tag
         """
         # GIVEN: Some test data with an unknown root tag and an instance of BibleImport
-        importer = BibleImport(MagicMock(), path='.', name='.', filename='')
+        importer = BibleImport(MagicMock(), path='.', name='.', file_path=None)
 
         # WHEN: Calling validate_xml_file
         # THEN: ValidationError should be raised, and the critical error message box should was called informing

=== modified file 'tests/functional/openlp_plugins/bibles/test_csvimport.py'
--- tests/functional/openlp_plugins/bibles/test_csvimport.py	2017-10-29 06:01:25 +0000
+++ tests/functional/openlp_plugins/bibles/test_csvimport.py	2017-11-14 23:03:10 +0000
@@ -29,6 +29,7 @@
 from unittest import TestCase
 from unittest.mock import ANY, MagicMock, PropertyMock, call, patch
 
+from openlp.core.common.path import Path
 from openlp.core.lib.exceptions import ValidationError
 from openlp.plugins.bibles.lib.bibleimport import BibleImport
 from openlp.plugins.bibles.lib.importers.csvbible import Book, CSVBible, Verse
@@ -59,12 +60,13 @@
         mocked_manager = MagicMock()
 
         # WHEN: An importer object is created
-        importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verse.csv')
+        importer = \
+            CSVBible(mocked_manager, path='.', name='.', books_path=Path('books.csv'), verse_path=Path('verse.csv'))
 
         # THEN: The importer should be an instance of BibleImport
         self.assertIsInstance(importer, BibleImport)
-        self.assertEqual(importer.books_file, 'books.csv')
-        self.assertEqual(importer.verses_file, 'verse.csv')
+        self.assertEqual(importer.books_path, Path('books.csv'))
+        self.assertEqual(importer.verses_path, Path('verse.csv'))
 
     def test_book_namedtuple(self):
         """
@@ -134,17 +136,17 @@
 
         with patch('openlp.plugins.bibles.lib.importers.csvbible.get_file_encoding',
                    return_value={'encoding': 'utf-8', 'confidence': 0.99}),\
-                patch('openlp.plugins.bibles.lib.importers.csvbible.open', create=True) as mocked_open,\
+                patch('openlp.plugins.bibles.lib.importers.csvbible.Path.open', create=True) as mocked_open,\
                 patch('openlp.plugins.bibles.lib.importers.csvbible.csv.reader',
                       return_value=iter(test_data)) as mocked_reader:
 
             # WHEN: Calling the CSVBible parse_csv_file method with a file name and TestTuple
-            result = CSVBible.parse_csv_file('file.csv', TestTuple)
+            result = CSVBible.parse_csv_file(Path('file.csv'), TestTuple)
 
             # THEN: A list of TestTuple instances with the parsed data should be returned
             self.assertEqual(result, [TestTuple('1', 'Line 1', 'Data 1'), TestTuple('2', 'Line 2', 'Data 2'),
                                       TestTuple('3', 'Line 3', 'Data 3')])
-            mocked_open.assert_called_once_with('file.csv', 'r', encoding='utf-8', newline='')
+            mocked_open.assert_called_once_with('r', encoding='utf-8', newline='')
             mocked_reader.assert_called_once_with(ANY, delimiter=',', quotechar='"')
 
     def test_parse_csv_file_oserror(self):
@@ -154,12 +156,12 @@
         # GIVEN: Mocked a mocked open object which raises an OSError
         with patch('openlp.plugins.bibles.lib.importers.csvbible.get_file_encoding',
                    return_value={'encoding': 'utf-8', 'confidence': 0.99}),\
-                patch('openlp.plugins.bibles.lib.importers.csvbible.open', side_effect=OSError, create=True):
+                patch('openlp.plugins.bibles.lib.importers.csvbible.Path.open', side_effect=OSError, create=True):
 
             # WHEN: Calling CSVBible.parse_csv_file
             # THEN: A ValidationError should be raised
             with self.assertRaises(ValidationError) as context:
-                CSVBible.parse_csv_file('file.csv', None)
+                CSVBible.parse_csv_file(Path('file.csv'), None)
             self.assertEqual(context.exception.msg, 'Parsing "file.csv" failed')
 
     def test_parse_csv_file_csverror(self):
@@ -169,13 +171,13 @@
         # GIVEN: Mocked a csv.reader which raises an csv.Error
         with patch('openlp.plugins.bibles.lib.importers.csvbible.get_file_encoding',
                    return_value={'encoding': 'utf-8', 'confidence': 0.99}),\
-                patch('openlp.plugins.bibles.lib.importers.csvbible.open', create=True),\
+                patch('openlp.plugins.bibles.lib.importers.csvbible.Path.open', create=True),\
                 patch('openlp.plugins.bibles.lib.importers.csvbible.csv.reader', side_effect=csv.Error):
 
             # WHEN: Calling CSVBible.parse_csv_file
             # THEN: A ValidationError should be raised
             with self.assertRaises(ValidationError) as context:
-                CSVBible.parse_csv_file('file.csv', None)
+                CSVBible.parse_csv_file(Path('file.csv'), None)
             self.assertEqual(context.exception.msg, 'Parsing "file.csv" failed')
 
     def test_process_books_stopped_import(self):
@@ -185,7 +187,8 @@
         # GIVEN: An instance of CSVBible with the stop_import_flag set to True
         mocked_manager = MagicMock()
         with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'):
-            importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verse.csv')
+            importer = CSVBible(mocked_manager, path='.', name='.', books_path=Path('books.csv'),
+                                verse_path=Path('verse.csv'))
             type(importer).application = PropertyMock()
             importer.stop_import_flag = True
             importer.wizard = MagicMock()
@@ -205,7 +208,8 @@
         mocked_manager = MagicMock()
         with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'),\
                 patch('openlp.plugins.bibles.lib.importers.csvbible.translate'):
-            importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verse.csv')
+            importer = CSVBible(mocked_manager, path='.', name='.', books_path=Path('books.csv'),
+                                verse_path=Path('verse.csv'))
             importer.find_and_create_book = MagicMock()
             importer.language_id = 10
             importer.stop_import_flag = False
@@ -229,7 +233,8 @@
         # GIVEN: An instance of CSVBible with the stop_import_flag set to True
         mocked_manager = MagicMock()
         with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'):
-            importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verse.csv')
+            importer = CSVBible(mocked_manager, path='.', name='.', books_path=Path('books.csv'),
+                                verse_path=Path('verse.csv'))
             importer.get_book_name = MagicMock()
             importer.session = MagicMock()
             importer.stop_import_flag = True
@@ -250,7 +255,8 @@
         mocked_manager = MagicMock()
         with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'),\
                 patch('openlp.plugins.bibles.lib.importers.csvbible.translate'):
-            importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verse.csv')
+            importer = CSVBible(mocked_manager, path='.', name='.', books_path=Path('books.csv'),
+                                verse_path=Path('verse.csv'))
             importer.create_verse = MagicMock()
             importer.get_book = MagicMock(return_value=Book('1', '1', '1. Mosebog', '1Mos'))
             importer.get_book_name = MagicMock(return_value='1. Mosebog')
@@ -281,7 +287,8 @@
         # GIVEN: An instance of CSVBible and a mocked get_language which simulates the user cancelling the language box
         mocked_manager = MagicMock()
         with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'):
-            importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verse.csv')
+            importer = CSVBible(mocked_manager, path='.', name='.', books_path=Path('books.csv'),
+                                verse_path=Path('verse.csv'))
             importer.get_language = MagicMock(return_value=None)
 
             # WHEN: Calling do_import
@@ -298,7 +305,8 @@
         # GIVEN: An instance of CSVBible
         mocked_manager = MagicMock()
         with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'):
-            importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verses.csv')
+            importer = CSVBible(mocked_manager, path='.', name='.', books_path=Path('books.csv'),
+                                verse_path=Path('verses.csv'))
             importer.get_language = MagicMock(return_value=10)
             importer.parse_csv_file = MagicMock(side_effect=[['Book 1'], ['Verse 1']])
             importer.process_books = MagicMock(return_value=['Book 1'])
@@ -312,7 +320,8 @@
 
             # THEN: parse_csv_file should be called twice,
             # and True should be returned.
-            self.assertEqual(importer.parse_csv_file.mock_calls, [call('books.csv', Book), call('verses.csv', Verse)])
+            self.assertEqual(importer.parse_csv_file.mock_calls,
+                             [call(Path('books.csv'), Book), call(Path('verses.csv'), Verse)])
             importer.process_books.assert_called_once_with(['Book 1'])
             importer.process_verses.assert_called_once_with(['Verse 1'], ['Book 1'])
             self.assertTrue(result)
@@ -325,12 +334,12 @@
         #        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 = os.path.join(TEST_PATH, 'dk1933-books.csv')
-        verses_file = os.path.join(TEST_PATH, 'dk1933-verses.csv')
+        books_file = Path(TEST_PATH, 'dk1933-books.csv')
+        verses_file = Path(TEST_PATH, 'dk1933-verses.csv')
         with patch('openlp.plugins.bibles.lib.importers.csvbible.CSVBible.application'):
             mocked_manager = MagicMock()
             mocked_import_wizard = MagicMock()
-            importer = CSVBible(mocked_manager, path='.', name='.', booksfile=books_file, versefile=verses_file)
+            importer = CSVBible(mocked_manager, path='.', name='.', books_path=books_file, verse_path=verses_file)
             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_opensongimport.py'
--- tests/functional/openlp_plugins/bibles/test_opensongimport.py	2017-10-29 06:01:25 +0000
+++ tests/functional/openlp_plugins/bibles/test_opensongimport.py	2017-11-14 23:03:10 +0000
@@ -29,6 +29,7 @@
 
 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
@@ -64,7 +65,7 @@
         mocked_manager = MagicMock()
 
         # WHEN: An importer object is created
-        importer = OpenSongBible(mocked_manager, path='.', name='.', filename='')
+        importer = OpenSongBible(mocked_manager, path='.', name='.', file_path=None)
 
         # THEN: The importer should be an instance of BibleDB
         self.assertIsInstance(importer, BibleImport)
@@ -126,7 +127,7 @@
         Test parse_verse_number when supplied with a valid verse number
         """
         # GIVEN: An instance of OpenSongBible, the number 15 represented as a string and an instance of OpenSongBible
-        importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
+        importer = OpenSongBible(MagicMock(), path='.', name='.', file_path=None)
 
         # WHEN: Calling parse_verse_number
         result = importer.parse_verse_number('15', 0)
@@ -139,7 +140,7 @@
         Test parse_verse_number when supplied with a verse range
         """
         # GIVEN: An instance of OpenSongBible, and the range 24-26 represented as a string
-        importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
+        importer = OpenSongBible(MagicMock(), path='.', name='.', file_path=None)
 
         # WHEN: Calling parse_verse_number
         result = importer.parse_verse_number('24-26', 0)
@@ -152,7 +153,7 @@
         Test parse_verse_number when supplied with a invalid verse number
         """
         # GIVEN: An instance of OpenSongBible, a non numeric string represented as a string
-        importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
+        importer = OpenSongBible(MagicMock(), path='.', name='.', file_path=None)
 
         # WHEN: Calling parse_verse_number
         result = importer.parse_verse_number('invalid', 41)
@@ -165,7 +166,7 @@
         Test parse_verse_number when the verse number is an empty string. (Bug #1074727)
         """
         # GIVEN: An instance of OpenSongBible, an empty string, and the previous verse number set as 14
-        importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
+        importer = OpenSongBible(MagicMock(), path='.', name='.', file_path=None)
         # WHEN: Calling parse_verse_number
         result = importer.parse_verse_number('', 14)
 
@@ -178,7 +179,7 @@
         """
         with patch.object(OpenSongBible, 'log_warning')as mocked_log_warning:
             # GIVEN: An instanceofOpenSongBible, a Tuple, and the previous verse number set as 12
-            importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
+            importer = OpenSongBible(MagicMock(), path='.', name='.', file_path=None)
 
             # WHEN: Calling parse_verse_number
             result = importer.parse_verse_number((1, 2, 3), 12)
@@ -193,7 +194,7 @@
         Test process_books when stop_import is set to True
         """
         # GIVEN: An instance of OpenSongBible
-        importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
+        importer = OpenSongBible(MagicMock(), path='.', name='.', file_path=None)
 
         # WHEN: stop_import_flag is set to True
         importer.stop_import_flag = True
@@ -209,7 +210,7 @@
         # GIVEN: An instance of OpenSongBible Importer and two mocked books
         self.mocked_find_and_create_book.side_effect = ['db_book1', 'db_book2']
         with patch.object(OpenSongBible, 'process_chapters') as mocked_process_chapters:
-            importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
+            importer = OpenSongBible(MagicMock(), path='.', name='.', file_path=None)
 
             book1 = MagicMock()
             book1.attrib = {'n': 'Name1'}
@@ -236,7 +237,7 @@
         Test process_chapters when stop_import is set to True
         """
         # GIVEN: An isntance of OpenSongBible
-        importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
+        importer = OpenSongBible(MagicMock(), path='.', name='.', file_path=None)
         importer.parse_chapter_number = MagicMock()
 
         # WHEN: stop_import_flag is set to True
@@ -252,7 +253,7 @@
         Test process_chapters when it completes
         """
         # GIVEN: An instance of OpenSongBible
-        importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
+        importer = OpenSongBible(MagicMock(), path='.', name='.', file_path=None)
         importer.wizard = MagicMock()
 
         # WHEN: called with some valid data
@@ -284,7 +285,7 @@
         Test process_verses when stop_import is set to True
         """
         # GIVEN: An isntance of OpenSongBible
-        importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
+        importer = OpenSongBible(MagicMock(), path='.', name='.', file_path=None)
         importer.parse_verse_number = MagicMock()
 
         # WHEN: stop_import_flag is set to True
@@ -303,7 +304,7 @@
                 patch.object(OpenSongBible, 'parse_verse_number',
                              **{'side_effect': [1, 2]}) as mocked_parse_verse_number:
             # GIVEN: An instance of OpenSongBible
-            importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
+            importer = OpenSongBible(MagicMock(), path='.', name='.', file_path=None)
             importer.wizard = MagicMock()
 
             # WHEN: called with some valid data
@@ -338,7 +339,7 @@
                 patch.object(OpenSongBible, 'validate_xml_file'), \
                 patch.object(OpenSongBible, 'parse_xml', return_value=None), \
                 patch.object(OpenSongBible, 'get_language_id') as mocked_language_id:
-            importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
+            importer = OpenSongBible(MagicMock(), path='.', name='.', file_path=None)
 
             # WHEN: Calling do_import
             result = importer.do_import()
@@ -357,7 +358,7 @@
                 patch.object(OpenSongBible, 'parse_xml'), \
                 patch.object(OpenSongBible, 'get_language_id', return_value=False), \
                 patch.object(OpenSongBible, 'process_books') as mocked_process_books:
-            importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
+            importer = OpenSongBible(MagicMock(), path='.', name='.', file_path=None)
 
             # WHEN: Calling do_import
             result = importer.do_import()
@@ -376,7 +377,7 @@
                 patch.object(OpenSongBible, 'parse_xml'), \
                 patch.object(OpenSongBible, 'get_language_id', return_value=10), \
                 patch.object(OpenSongBible, 'process_books'):
-            importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
+            importer = OpenSongBible(MagicMock(), path='.', name='.', file_path=None)
 
             # WHEN: Calling do_import
             result = importer.do_import()
@@ -406,7 +407,7 @@
         with patch('openlp.plugins.bibles.lib.importers.opensong.OpenSongBible.application'):
             mocked_manager = MagicMock()
             mocked_import_wizard = MagicMock()
-            importer = OpenSongBible(mocked_manager, path='.', name='.', filename='')
+            importer = OpenSongBible(mocked_manager, path='.', name='.', file_path=None)
             importer.wizard = mocked_import_wizard
             importer.get_book_ref_id_by_name = MagicMock()
             importer.create_verse = MagicMock()
@@ -416,7 +417,7 @@
             importer.get_language.return_value = 'Danish'
 
             # WHEN: Importing bible file
-            importer.filename = os.path.join(TEST_PATH, bible_file)
+            importer.file_path = 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-10-29 06:01:25 +0000
+++ tests/functional/openlp_plugins/bibles/test_osisimport.py	2017-11-14 23:03:10 +0000
@@ -27,6 +27,7 @@
 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
@@ -63,7 +64,7 @@
         mocked_manager = MagicMock()
 
         # WHEN: An importer object is created
-        importer = OSISBible(mocked_manager, path='.', name='.', filename='')
+        importer = OSISBible(mocked_manager, path='.', name='.', file_path=None)
 
         # THEN: The importer should be an instance of BibleDB
         self.assertIsInstance(importer, BibleDB)
@@ -73,7 +74,7 @@
         Test process_books when stop_import is set to True
         """
         # GIVEN: An instance of OSISBible adn some mocked data
-        importer = OSISBible(MagicMock(), path='.', name='.', filename='')
+        importer = OSISBible(MagicMock(), path='.', name='.', file_path=None)
         mocked_data = MagicMock(**{'xpath.return_value': ['Book']})
 
         # WHEN: stop_import_flag is set to True and process_books is called
@@ -90,7 +91,7 @@
         # GIVEN: An instance of OSISBible Importer and two mocked books
         self.mocked_find_and_create_book.side_effect = ['db_book1', 'db_book2']
         with patch.object(OSISBible, 'process_chapters') as mocked_process_chapters:
-            importer = OSISBible(MagicMock(), path='.', name='.', filename='')
+            importer = OSISBible(MagicMock(), path='.', name='.', file_path=None)
 
             book1 = MagicMock()
             book1.get.return_value = 'Name1'
@@ -128,7 +129,7 @@
             test_chapter = MagicMock()
             test_chapter.__iter__.return_value = [test_verse]
             test_chapter.get.side_effect = lambda x: {'osisID': '1.2.4', 'sID': '999'}.get(x)
-            importer = OSISBible(MagicMock(), path='.', name='.', filename='')
+            importer = OSISBible(MagicMock(), path='.', name='.', file_path=None)
 
             # WHEN: Calling process_chapters
             importer.process_chapters(test_book, [test_chapter])
@@ -155,7 +156,7 @@
             test_chapter = MagicMock()
             test_chapter.__iter__.return_value = [test_verse]
             test_chapter.get.side_effect = lambda x: {'osisID': '1.2.4', 'sID': '999'}.get(x)
-            importer = OSISBible(MagicMock(), path='.', name='.', filename='')
+            importer = OSISBible(MagicMock(), path='.', name='.', file_path=None)
 
             # WHEN: Calling process_chapters
             importer.process_chapters(test_book, [test_chapter])
@@ -180,7 +181,7 @@
             test_chapter.get.side_effect = lambda x: {'osisID': '1.2.4'}.get(x)
 
             # WHEN: Calling process_chapters
-            importer = OSISBible(MagicMock(), path='.', name='.', filename='')
+            importer = OSISBible(MagicMock(), path='.', name='.', file_path=None)
             importer.process_chapters(test_book, [test_chapter])
 
             # THEN: neither set_current_chapter or process_verse should have been called
@@ -201,7 +202,7 @@
             test_chapter = MagicMock()
             test_chapter.tag = '{http://www.bibletechnologies.net/2003/OSIS/namespace}chapter'
             test_chapter.get.side_effect = lambda x: {'osisID': '1.2.4', 'sID': '999'}.get(x)
-            importer = OSISBible(MagicMock(), path='.', name='.', filename='')
+            importer = OSISBible(MagicMock(), path='.', name='.', file_path=None)
 
             # WHEN: Calling process_chapters
             importer.process_chapters(test_book, [test_chapter])
@@ -228,7 +229,7 @@
             test_verse.text = 'Verse Text'
 
             # WHEN: Calling process_chapters
-            importer = OSISBible(MagicMock(), path='.', name='.', filename='')
+            importer = OSISBible(MagicMock(), path='.', name='.', file_path=None)
             importer.process_chapters(test_book, [test_verse])
 
             # THEN: process_verse should have been called with the test data
@@ -245,7 +246,7 @@
         test_verse.get.side_effect = lambda x: {}.get(x)
         test_verse.tail = 'Verse Text'
         test_verse.text = None
-        importer = OSISBible(MagicMock(), path='.', name='.', filename='')
+        importer = OSISBible(MagicMock(), path='.', name='.', file_path=None)
 
         # WHEN: Calling process_verse with the test data
         importer.process_verse(test_book, 2, test_verse)
@@ -264,7 +265,7 @@
         test_verse.get.side_effect = lambda x: {}.get(x)
         test_verse.tail = 'Verse Text'
         test_verse.text = None
-        importer = OSISBible(MagicMock(), path='.', name='.', filename='')
+        importer = OSISBible(MagicMock(), path='.', name='.', file_path=None)
 
         # WHEN: Calling process_verse with the test data
         importer.process_verse(test_book, 2, test_verse)
@@ -282,7 +283,7 @@
         test_verse.tail = None
         test_verse.text = None
         test_verse.get.side_effect = lambda x: {'osisID': '1.2.4', 'sID': '999'}.get(x)
-        importer = OSISBible(MagicMock(), path='.', name='.', filename='')
+        importer = OSISBible(MagicMock(), path='.', name='.', file_path=None)
 
         # WHEN: Calling process_verse with the test data
         importer.process_verse(test_book, 2, test_verse, use_milestones=True)
@@ -301,7 +302,7 @@
         test_verse.tail = 'Verse Text'
         test_verse.text = None
         test_verse.get.side_effect = lambda x: {'osisID': '1.2.4', 'sID': '999'}.get(x)
-        importer = OSISBible(MagicMock(), path='.', name='.', filename='')
+        importer = OSISBible(MagicMock(), path='.', name='.', file_path=None)
 
         # WHEN: Calling process_verse with the test data
         importer.process_verse(test_book, 2, test_verse, use_milestones=True)
@@ -320,7 +321,7 @@
         test_verse.tail = '\n    '  # Whitespace
         test_verse.text = None
         test_verse.get.side_effect = lambda x: {'osisID': '1.2.4', 'sID': '999'}.get(x)
-        importer = OSISBible(MagicMock(), path='.', name='.', filename='')
+        importer = OSISBible(MagicMock(), path='.', name='.', file_path=None)
 
         # WHEN: Calling process_verse with the test data
         importer.process_verse(test_book, 2, test_verse)
@@ -339,7 +340,7 @@
         test_verse.tail = '\n    '  # Whitespace
         test_verse.text = 'Verse Text'
         test_verse.get.side_effect = lambda x: {'osisID': '1.2.4', 'sID': '999'}.get(x)
-        importer = OSISBible(MagicMock(), path='.', name='.', filename='')
+        importer = OSISBible(MagicMock(), path='.', name='.', file_path=None)
 
         # WHEN: Calling process_verse with the test data
         importer.process_verse(test_book, 2, test_verse)
@@ -356,7 +357,7 @@
                 patch.object(OSISBible, 'validate_xml_file'), \
                 patch.object(OSISBible, 'parse_xml', return_value=None), \
                 patch.object(OSISBible, 'get_language_id') as mocked_language_id:
-            importer = OSISBible(MagicMock(), path='.', name='.', filename='')
+            importer = OSISBible(MagicMock(), path='.', name='.', file_path=None)
 
             # WHEN: Calling do_import
             result = importer.do_import()
@@ -375,7 +376,7 @@
                 patch.object(OSISBible, 'parse_xml'), \
                 patch.object(OSISBible, 'get_language_id', **{'return_value': False}), \
                 patch.object(OSISBible, 'process_books') as mocked_process_books:
-            importer = OSISBible(MagicMock(), path='.', name='.', filename='')
+            importer = OSISBible(MagicMock(), path='.', name='.', file_path=None)
 
             # WHEN: Calling do_import
             result = importer.do_import()
@@ -394,7 +395,7 @@
                 patch.object(OSISBible, 'parse_xml'), \
                 patch.object(OSISBible, 'get_language_id', **{'return_value': 10}), \
                 patch.object(OSISBible, 'process_books'):
-            importer = OSISBible(MagicMock(), path='.', name='.', filename='')
+            importer = OSISBible(MagicMock(), path='.', name='.', file_path=None)
 
             # WHEN: Calling do_import
             result = importer.do_import()
@@ -427,7 +428,7 @@
         with patch('openlp.plugins.bibles.lib.importers.osis.OSISBible.application'):
             mocked_manager = MagicMock()
             mocked_import_wizard = MagicMock()
-            importer = OSISBible(mocked_manager, path='.', name='.', filename='')
+            importer = OSISBible(mocked_manager, path='.', name='.', file_path=None)
             importer.wizard = mocked_import_wizard
             importer.get_book_ref_id_by_name = MagicMock()
             importer.create_verse = MagicMock()
@@ -437,7 +438,7 @@
             importer.get_language.return_value = 'Danish'
 
             # WHEN: Importing bible file
-            importer.filename = os.path.join(TEST_PATH, bible_file)
+            importer.file_path = Path(TEST_PATH, bible_file)
             importer.do_import()
 
             # THEN: The create_verse() method should have been called with each verse in the file.
@@ -457,7 +458,7 @@
         with patch('openlp.plugins.bibles.lib.importers.osis.OSISBible.application'):
             mocked_manager = MagicMock()
             mocked_import_wizard = MagicMock()
-            importer = OSISBible(mocked_manager, path='.', name='.', filename='')
+            importer = OSISBible(mocked_manager, path='.', name='.', file_path=None)
             importer.wizard = mocked_import_wizard
             importer.get_book_ref_id_by_name = MagicMock()
             importer.create_verse = MagicMock()
@@ -467,7 +468,7 @@
             importer.get_language.return_value = 'English'
 
             # WHEN: Importing bible file
-            importer.filename = os.path.join(TEST_PATH, bible_file)
+            importer.file_path = Path(TEST_PATH, bible_file)
             importer.do_import()
 
             # THEN: The create_verse() method should have been called with each verse in the file.
@@ -487,7 +488,7 @@
         with patch('openlp.plugins.bibles.lib.importers.osis.OSISBible.application'):
             mocked_manager = MagicMock()
             mocked_import_wizard = MagicMock()
-            importer = OSISBible(mocked_manager, path='.', name='.', filename='')
+            importer = OSISBible(mocked_manager, path='.', name='.', file_path=None)
             importer.wizard = mocked_import_wizard
             importer.get_book_ref_id_by_name = MagicMock()
             importer.create_verse = MagicMock()
@@ -497,7 +498,7 @@
             importer.get_language.return_value = 'English'
 
             # WHEN: Importing bible file
-            importer.filename = os.path.join(TEST_PATH, bible_file)
+            importer.file_path = Path(TEST_PATH, bible_file)
             importer.do_import()
 
             # THEN: The create_verse() method should have been called with each verse in the file.
@@ -517,7 +518,7 @@
         with patch('openlp.plugins.bibles.lib.importers.osis.OSISBible.application'):
             mocked_manager = MagicMock()
             mocked_import_wizard = MagicMock()
-            importer = OSISBible(mocked_manager, path='.', name='.', filename='')
+            importer = OSISBible(mocked_manager, path='.', name='.', file_path=None)
             importer.wizard = mocked_import_wizard
             importer.get_book_ref_id_by_name = MagicMock()
             importer.create_verse = MagicMock()
@@ -527,7 +528,7 @@
             importer.get_language.return_value = 'Danish'
 
             # WHEN: Importing bible file
-            importer.filename = os.path.join(TEST_PATH, bible_file)
+            importer.file_path = 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-04-24 05:17:55 +0000
+++ tests/functional/openlp_plugins/bibles/test_swordimport.py	2017-11-14 23:03:10 +0000
@@ -64,7 +64,7 @@
         mocked_manager = MagicMock()
 
         # WHEN: An importer object is created
-        importer = SwordBible(mocked_manager, path='.', name='.', filename='', sword_key='', sword_path='')
+        importer = SwordBible(mocked_manager, path='.', name='.', file_path=None, sword_key='', sword_path='')
 
         # THEN: The importer should be an instance of BibleDB
         self.assertIsInstance(importer, BibleDB)
@@ -80,7 +80,7 @@
         #       Also mocked pysword structures
         mocked_manager = MagicMock()
         mocked_import_wizard = MagicMock()
-        importer = SwordBible(mocked_manager, path='.', name='.', filename='', sword_key='', sword_path='')
+        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())
         importer.wizard = mocked_import_wizard

=== modified file 'tests/functional/openlp_plugins/bibles/test_wordprojectimport.py'
--- tests/functional/openlp_plugins/bibles/test_wordprojectimport.py	2017-04-24 05:17:55 +0000
+++ tests/functional/openlp_plugins/bibles/test_wordprojectimport.py	2017-11-14 23:03:10 +0000
@@ -26,6 +26,7 @@
 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
 
 
@@ -48,19 +49,17 @@
         self.addCleanup(self.manager_patcher.stop)
         self.manager_patcher.start()
 
-    @patch('openlp.plugins.bibles.lib.importers.wordproject.os')
-    @patch('openlp.plugins.bibles.lib.importers.wordproject.copen')
-    def test_process_books(self, mocked_open, mocked_os):
+    @patch.object(Path, 'read_text')
+    def test_process_books(self, mocked_read_text):
         """
         Test the process_books() method
         """
         # GIVEN: A WordProject importer and a bunch of mocked things
-        importer = WordProjectBible(MagicMock(), path='.', name='.', filename='kj.zip')
-        importer.base_dir = ''
+        importer = WordProjectBible(MagicMock(), path='.', name='.', file_path=Path('kj.zip'))
+        importer.base_path = Path()
         importer.stop_import_flag = False
         importer.language_id = 'en'
-        mocked_open.return_value.__enter__.return_value.read.return_value = INDEX_PAGE
-        mocked_os.path.join.side_effect = lambda *x: ''.join(x)
+        mocked_read_text.return_value = INDEX_PAGE
 
         # WHEN: process_books() is called
         with patch.object(importer, 'find_and_create_book') as mocked_find_and_create_book, \
@@ -69,26 +68,22 @@
             importer.process_books()
 
         # THEN: The right methods should have been called
-        mocked_os.path.join.assert_called_once_with('', 'index.htm')
-        mocked_open.assert_called_once_with('index.htm', encoding='utf-8', errors='ignore')
+        mocked_read_text.assert_called_once_with(encoding='utf-8', errors='ignore')
         assert mocked_find_and_create_book.call_count == 66, 'There should be 66 books'
         assert mocked_process_chapters.call_count == 66, 'There should be 66 books'
         assert mocked_session.commit.call_count == 66, 'There should be 66 books'
 
-    @patch('openlp.plugins.bibles.lib.importers.wordproject.os')
-    @patch('openlp.plugins.bibles.lib.importers.wordproject.copen')
-    def test_process_chapters(self, mocked_open, mocked_os):
+    @patch.object(Path, 'read_text')
+    def test_process_chapters(self, mocked_read_text):
         """
         Test the process_chapters() method
         """
         # GIVEN: A WordProject importer and a bunch of mocked things
-        importer = WordProjectBible(MagicMock(), path='.', name='.', filename='kj.zip')
-        importer.base_dir = ''
+        importer = WordProjectBible(MagicMock(), path='.', name='.', file_path=Path('kj.zip'))
+        importer.base_path = Path()
         importer.stop_import_flag = False
         importer.language_id = 'en'
-        mocked_open.return_value.__enter__.return_value.read.return_value = CHAPTER_PAGE
-        mocked_os.path.join.side_effect = lambda *x: ''.join(x)
-        mocked_os.path.normpath.side_effect = lambda x: x
+        mocked_read_text.return_value = CHAPTER_PAGE
         mocked_db_book = MagicMock()
         mocked_db_book.name = 'Genesis'
         book_id = 1
@@ -102,24 +97,21 @@
         # THEN: The right methods should have been called
         expected_set_current_chapter_calls = [call('Genesis', ch) for ch in range(1, 51)]
         expected_process_verses_calls = [call(mocked_db_book, 1, ch) for ch in range(1, 51)]
-        mocked_os.path.join.assert_called_once_with('', '01/1.htm')
-        mocked_open.assert_called_once_with('01/1.htm', encoding='utf-8', errors='ignore')
+        mocked_read_text.assert_called_once_with(encoding='utf-8', errors='ignore')
         assert mocked_set_current_chapter.call_args_list == expected_set_current_chapter_calls
         assert mocked_process_verses.call_args_list == expected_process_verses_calls
 
-    @patch('openlp.plugins.bibles.lib.importers.wordproject.os')
-    @patch('openlp.plugins.bibles.lib.importers.wordproject.copen')
-    def test_process_verses(self, mocked_open, mocked_os):
+    @patch.object(Path, 'read_text')
+    def test_process_verses(self, mocked_read_text):
         """
         Test the process_verses() method
         """
         # GIVEN: A WordProject importer and a bunch of mocked things
-        importer = WordProjectBible(MagicMock(), path='.', name='.', filename='kj.zip')
-        importer.base_dir = ''
+        importer = WordProjectBible(MagicMock(), path='.', name='.', file_path=Path('kj.zip'))
+        importer.base_path = Path()
         importer.stop_import_flag = False
         importer.language_id = 'en'
-        mocked_open.return_value.__enter__.return_value.read.return_value = CHAPTER_PAGE
-        mocked_os.path.join.side_effect = lambda *x: '/'.join(x)
+        mocked_read_text.return_value = CHAPTER_PAGE
         mocked_db_book = MagicMock()
         mocked_db_book.name = 'Genesis'
         book_number = 1
@@ -130,8 +122,7 @@
             importer.process_verses(mocked_db_book, book_number, chapter_number)
 
         # THEN: All the right methods should have been called
-        mocked_os.path.join.assert_called_once_with('', '01', '1.htm')
-        mocked_open.assert_called_once_with('/01/1.htm', encoding='utf-8', errors='ignore')
+        mocked_read_text.assert_called_once_with(encoding='utf-8', errors='ignore')
         assert mocked_process_verse.call_count == 31
 
     def test_process_verse(self):
@@ -139,7 +130,7 @@
         Test the process_verse() method
         """
         # GIVEN: An importer and a mocked method
-        importer = WordProjectBible(MagicMock(), path='.', name='.', filename='kj.zip')
+        importer = WordProjectBible(MagicMock(), path='.', name='.', file_path=Path('kj.zip'))
         mocked_db_book = MagicMock()
         mocked_db_book.id = 1
         chapter_number = 1
@@ -158,7 +149,7 @@
         Test the process_verse() method when there's no text
         """
         # GIVEN: An importer and a mocked method
-        importer = WordProjectBible(MagicMock(), path='.', name='.', filename='kj.zip')
+        importer = WordProjectBible(MagicMock(), path='.', name='.', file_path=Path('kj.zip'))
         mocked_db_book = MagicMock()
         mocked_db_book.id = 1
         chapter_number = 1
@@ -177,7 +168,7 @@
         Test the do_import() method
         """
         # GIVEN: An importer and mocked methods
-        importer = WordProjectBible(MagicMock(), path='.', name='.', filename='kj.zip')
+        importer = WordProjectBible(MagicMock(), path='.', name='.', file_path='kj.zip')
 
         # WHEN: do_import() is called
         with patch.object(importer, '_unzip_file') as mocked_unzip_file, \
@@ -199,7 +190,7 @@
         Test the do_import() method when the language is not available
         """
         # GIVEN: An importer and mocked methods
-        importer = WordProjectBible(MagicMock(), path='.', name='.', filename='kj.zip')
+        importer = WordProjectBible(MagicMock(), path='.', name='.', file_path='kj.zip')
 
         # WHEN: do_import() is called
         with patch.object(importer, '_unzip_file') as mocked_unzip_file, \

=== modified file 'tests/functional/openlp_plugins/bibles/test_zefaniaimport.py'
--- tests/functional/openlp_plugins/bibles/test_zefaniaimport.py	2017-04-24 05:17:55 +0000
+++ tests/functional/openlp_plugins/bibles/test_zefaniaimport.py	2017-11-14 23:03:10 +0000
@@ -27,6 +27,7 @@
 from unittest import TestCase
 from unittest.mock import MagicMock, patch
 
+from openlp.core.common.path import Path
 from openlp.plugins.bibles.lib.importers.zefania import ZefaniaBible
 from openlp.plugins.bibles.lib.db import BibleDB
 
@@ -55,7 +56,7 @@
         mocked_manager = MagicMock()
 
         # WHEN: An importer object is created
-        importer = ZefaniaBible(mocked_manager, path='.', name='.', filename='')
+        importer = ZefaniaBible(mocked_manager, path='.', name='.', file_path=None)
 
         # THEN: The importer should be an instance of BibleDB
         self.assertIsInstance(importer, BibleDB)
@@ -72,7 +73,7 @@
         with patch('openlp.plugins.bibles.lib.importers.zefania.ZefaniaBible.application'):
             mocked_manager = MagicMock()
             mocked_import_wizard = MagicMock()
-            importer = ZefaniaBible(mocked_manager, path='.', name='.', filename='')
+            importer = ZefaniaBible(mocked_manager, path='.', name='.', file_path=None)
             importer.wizard = mocked_import_wizard
             importer.create_verse = MagicMock()
             importer.create_book = MagicMock()
@@ -81,7 +82,7 @@
             importer.get_language.return_value = 'Danish'
 
             # WHEN: Importing bible file
-            importer.filename = os.path.join(TEST_PATH, bible_file)
+            importer.file_path = Path(TEST_PATH, bible_file)
             importer.do_import()
 
             # THEN: The create_verse() method should have been called with each verse in the file.
@@ -102,7 +103,7 @@
         with patch('openlp.plugins.bibles.lib.importers.zefania.ZefaniaBible.application'):
             mocked_manager = MagicMock()
             mocked_import_wizard = MagicMock()
-            importer = ZefaniaBible(mocked_manager, path='.', name='.', filename='')
+            importer = ZefaniaBible(mocked_manager, path='.', name='.', file_path=None)
             importer.wizard = mocked_import_wizard
             importer.create_verse = MagicMock()
             importer.create_book = MagicMock()
@@ -111,7 +112,7 @@
             importer.get_language.return_value = 'Russian'
 
             # WHEN: Importing bible file
-            importer.filename = os.path.join(TEST_PATH, bible_file)
+            importer.file_path = Path(TEST_PATH, bible_file)
             importer.do_import()
 
             # THEN: The create_verse() method should have been called with each verse in the file.


Follow ups