← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~raoul-snyman/openlp/permission-error into lp:openlp

 

Raoul Snyman has proposed merging lp:~raoul-snyman/openlp/permission-error into lp:openlp.

Requested reviews:
  OpenLP Core (openlp-core)

For more details, see:
https://code.launchpad.net/~raoul-snyman/openlp/permission-error/+merge/300279

Fix a permission error that people keep on getting but we never actually log and fix.

Add this to your merge proposal:
--------------------------------
lp:~raoul-snyman/openlp/permission-error (revision 2682)
[SUCCESS] https://ci.openlp.io/job/Branch-01-Pull/1656/
[SUCCESS] https://ci.openlp.io/job/Branch-02-Functional-Tests/1567/
[SUCCESS] https://ci.openlp.io/job/Branch-03-Interface-Tests/1505/
[SUCCESS] https://ci.openlp.io/job/Branch-04a-Windows_Functional_Tests/1271/
[SUCCESS] https://ci.openlp.io/job/Branch-04b-Windows_Interface_Tests/861/
[SUCCESS] https://ci.openlp.io/job/Branch-05a-Code_Analysis/929/
[SUCCESS] https://ci.openlp.io/job/Branch-05b-Test_Coverage/797/
-- 
Your team OpenLP Core is requested to review the proposed merge of lp:~raoul-snyman/openlp/permission-error into lp:openlp.
=== modified file 'openlp/core/ui/servicemanager.py'
--- openlp/core/ui/servicemanager.py	2016-05-20 16:22:06 +0000
+++ openlp/core/ui/servicemanager.py	2016-07-17 19:59:02 +0000
@@ -480,9 +480,10 @@
         :return: service array
         """
         service = []
-        core = {'lite-service': self._save_lite,
-                'service-theme': self.service_theme
-                }
+        core = {
+            'lite-service': self._save_lite,
+            'service-theme': self.service_theme
+        }
         service.append({'openlp_core': core})
         return service
 
@@ -597,7 +598,7 @@
         if success:
             try:
                 shutil.copy(temp_file_name, path_file_name)
-            except shutil.Error:
+            except (shutil.Error, PermissionError):
                 return self.save_file_as()
             except OSError as ose:
                 QtWidgets.QMessageBox.critical(self, translate('OpenLP.ServiceManager', 'Error Saving File'),
@@ -658,7 +659,7 @@
         if success:
             try:
                 shutil.copy(temp_file_name, path_file_name)
-            except shutil.Error:
+            except (shutil.Error, PermissionError):
                 return self.save_file_as()
             self.main_window.add_recent_file(path_file_name)
             self.set_modified(False)

=== modified file 'tests/functional/openlp_core_ui/test_servicemanager.py'
--- tests/functional/openlp_core_ui/test_servicemanager.py	2016-06-01 21:42:54 +0000
+++ tests/functional/openlp_core_ui/test_servicemanager.py	2016-07-17 19:59:02 +0000
@@ -22,10 +22,12 @@
 """
 Package to test the openlp.core.ui.slidecontroller package.
 """
+import os
+from unittest import TestCase
+
 import PyQt5
-from unittest import TestCase
 
-from openlp.core.common import Registry, ThemeLevel, Settings
+from openlp.core.common import Registry, ThemeLevel
 from openlp.core.lib import ServiceItem, ServiceItemType, ItemCapabilities
 from openlp.core.ui import ServiceManager
 
@@ -33,6 +35,9 @@
 
 
 class TestServiceManager(TestCase):
+    """
+    Test the service manager
+    """
 
     def setUp(self):
         """
@@ -108,20 +113,20 @@
         # WHEN I define a context menu
         service_manager.context_menu(1)
         # THEN the following calls should have occurred.
-        self.assertEquals(service_manager.edit_action.setVisible.call_count, 1, 'Should have been called once')
-        self.assertEquals(service_manager.rename_action.setVisible.call_count, 1, 'Should have been called once')
-        self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have been called once')
-        self.assertEquals(service_manager.maintain_action.setVisible.call_count, 1, 'Should have been called once')
-        self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have been called once')
-        self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have been called once')
-        self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have been called once')
-        self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
-                          'Should have been called once')
-        self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 1,
-                          'Should have been called once')
+        self.assertEqual(service_manager.edit_action.setVisible.call_count, 1, 'Should have been called once')
+        self.assertEqual(service_manager.rename_action.setVisible.call_count, 1, 'Should have been called once')
+        self.assertEqual(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have been called once')
+        self.assertEqual(service_manager.maintain_action.setVisible.call_count, 1, 'Should have been called once')
+        self.assertEqual(service_manager.notes_action.setVisible.call_count, 1, 'Should have been called once')
+        self.assertEqual(service_manager.time_action.setVisible.call_count, 1, 'Should have been called once')
+        self.assertEqual(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have been called once')
+        self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
+                         'Should have been called once')
+        self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.theme_menu.menuAction().setVisible.call_count, 1,
+                         'Should have been called once')
 
     def test_build_song_context_menu(self):
         """
@@ -139,12 +144,10 @@
         service_manager.service_manager_list = MagicMock()
         service_manager.service_manager_list.itemAt.return_value = item
         service_item = ServiceItem(None)
-        service_item.add_capability(ItemCapabilities.CanEdit)
-        service_item.add_capability(ItemCapabilities.CanPreview)
-        service_item.add_capability(ItemCapabilities.CanLoop)
-        service_item.add_capability(ItemCapabilities.OnLoadUpdate)
-        service_item.add_capability(ItemCapabilities.AddIfNewItem)
-        service_item.add_capability(ItemCapabilities.CanSoftBreak)
+        for capability in [ItemCapabilities.CanEdit, ItemCapabilities.CanPreview, ItemCapabilities.CanLoop,
+                           ItemCapabilities.OnLoadUpdate, ItemCapabilities.AddIfNewItem,
+                           ItemCapabilities.CanSoftBreak]:
+            service_item.add_capability(capability)
         service_item.service_item_type = ServiceItemType.Text
         service_item.edit_id = 1
         service_item._display_frames.append(MagicMock())
@@ -165,29 +168,29 @@
         # WHEN I define a context menu
         service_manager.context_menu(1)
         # THEN the following calls should have occurred.
-        self.assertEquals(service_manager.edit_action.setVisible.call_count, 2, 'Should have be called twice')
-        self.assertEquals(service_manager.rename_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
-                          'Should have be called once')
-        self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 2,
-                          'Should have be called twice')
+        self.assertEqual(service_manager.edit_action.setVisible.call_count, 2, 'Should have be called twice')
+        self.assertEqual(service_manager.rename_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
+                         'Should have be called once')
+        self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.theme_menu.menuAction().setVisible.call_count, 2,
+                         'Should have be called twice')
         # THEN we add a 2nd display frame
         service_item._display_frames.append(MagicMock())
         service_manager.context_menu(1)
         # THEN the following additional calls should have occurred.
-        self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 2,
-                          'Should have be called twice')
-        self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 2,
+                         'Should have be called twice')
+        self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 1, 'Should have be called once')
 
     def test_build_bible_context_menu(self):
         """
@@ -205,11 +208,10 @@
         service_manager.service_manager_list = MagicMock()
         service_manager.service_manager_list.itemAt.return_value = item
         service_item = ServiceItem(None)
-        service_item.add_capability(ItemCapabilities.NoLineBreaks)
-        service_item.add_capability(ItemCapabilities.CanPreview)
-        service_item.add_capability(ItemCapabilities.CanLoop)
-        service_item.add_capability(ItemCapabilities.CanWordSplit)
-        service_item.add_capability(ItemCapabilities.CanEditTitle)
+        for capability in [ItemCapabilities.NoLineBreaks, ItemCapabilities.CanPreview,
+                           ItemCapabilities.CanLoop, ItemCapabilities.CanWordSplit,
+                           ItemCapabilities.CanEditTitle]:
+            service_item.add_capability(capability)
         service_item.service_item_type = ServiceItemType.Text
         service_item.edit_id = 1
         service_item._display_frames.append(MagicMock())
@@ -230,29 +232,29 @@
         # WHEN I define a context menu
         service_manager.context_menu(1)
         # THEN the following calls should have occurred.
-        self.assertEquals(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.rename_action.setVisible.call_count, 2, 'Should have be called twice')
-        self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
-                          'Should have be called once')
-        self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 2,
-                          'Should have be called twice')
+        self.assertEqual(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.rename_action.setVisible.call_count, 2, 'Should have be called twice')
+        self.assertEqual(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
+                         'Should have be called once')
+        self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.theme_menu.menuAction().setVisible.call_count, 2,
+                         'Should have be called twice')
         # THEN we add a 2nd display frame
         service_item._display_frames.append(MagicMock())
         service_manager.context_menu(1)
         # THEN the following additional calls should have occurred.
-        self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 2,
-                          'Should have be called twice')
-        self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 2,
+                         'Should have be called twice')
+        self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 1, 'Should have be called once')
 
     def test_build_custom_context_menu(self):
         """
@@ -295,29 +297,29 @@
         # WHEN I define a context menu
         service_manager.context_menu(1)
         # THEN the following calls should have occurred.
-        self.assertEquals(service_manager.edit_action.setVisible.call_count, 2, 'Should have be called twice')
-        self.assertEquals(service_manager.rename_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
-                          'Should have be called once')
-        self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 2,
-                          'Should have be called twice')
+        self.assertEqual(service_manager.edit_action.setVisible.call_count, 2, 'Should have be called twice')
+        self.assertEqual(service_manager.rename_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
+                         'Should have be called once')
+        self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.theme_menu.menuAction().setVisible.call_count, 2,
+                         'Should have be called twice')
         # THEN we add a 2nd display frame
         service_item._display_frames.append(MagicMock())
         service_manager.context_menu(1)
         # THEN the following additional calls should have occurred.
-        self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 2,
-                          'Should have be called twice')
-        self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 2,
+                         'Should have be called twice')
+        self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 1, 'Should have be called once')
 
     def test_build_image_context_menu(self):
         """
@@ -358,29 +360,29 @@
         # WHEN I define a context menu
         service_manager.context_menu(1)
         # THEN the following calls should have occurred.
-        self.assertEquals(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.rename_action.setVisible.call_count, 2, 'Should have be called twice')
-        self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.maintain_action.setVisible.call_count, 2, 'Should have be called twice')
-        self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
-                          'Should have be called once')
-        self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 1,
-                          'Should have be called once')
+        self.assertEqual(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.rename_action.setVisible.call_count, 2, 'Should have be called twice')
+        self.assertEqual(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.maintain_action.setVisible.call_count, 2, 'Should have be called twice')
+        self.assertEqual(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
+                         'Should have be called once')
+        self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.theme_menu.menuAction().setVisible.call_count, 1,
+                         'Should have be called once')
         # THEN we add a 2nd display frame and regenerate the menu.
         service_item._raw_frames.append(MagicMock())
         service_manager.context_menu(1)
         # THEN the following additional calls should have occurred.
-        self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 2,
-                          'Should have be called twice')
-        self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 2,
+                         'Should have be called twice')
+        self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 1, 'Should have be called once')
 
     def test_build_media_context_menu(self):
         """
@@ -419,25 +421,25 @@
         # WHEN I define a context menu
         service_manager.context_menu(1)
         # THEN the following calls should have occurred.
-        self.assertEquals(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.rename_action.setVisible.call_count, 2, 'Should have be called twice')
-        self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 2, 'Should have be called twice')
-        self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
-                          'Should have be called once')
-        self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 1,
-                          'Should have be called once')
+        self.assertEqual(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.rename_action.setVisible.call_count, 2, 'Should have be called twice')
+        self.assertEqual(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.auto_start_action.setVisible.call_count, 2, 'Should have be called twice')
+        self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
+                         'Should have be called once')
+        self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.theme_menu.menuAction().setVisible.call_count, 1,
+                         'Should have be called once')
         # THEN I change the length of the media and regenerate the menu.
         service_item.set_media_length(5)
         service_manager.context_menu(1)
         # THEN the following additional calls should have occurred.
-        self.assertEquals(service_manager.time_action.setVisible.call_count, 3, 'Should have be called three times')
+        self.assertEqual(service_manager.time_action.setVisible.call_count, 3, 'Should have be called three times')
 
     def test_build_presentation_pdf_context_menu(self):
         """
@@ -477,20 +479,20 @@
         # WHEN I define a context menu
         service_manager.context_menu(1)
         # THEN the following calls should have occurred.
-        self.assertEquals(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.rename_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.maintain_action.setVisible.call_count, 2, 'Should have be called twice')
-        self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
-                          'Should have be called once')
-        self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 1,
-                          'Should have be called once')
+        self.assertEqual(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.rename_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.maintain_action.setVisible.call_count, 2, 'Should have be called twice')
+        self.assertEqual(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
+                         'Should have be called once')
+        self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.theme_menu.menuAction().setVisible.call_count, 1,
+                         'Should have be called once')
 
     def test_build_presentation_non_pdf_context_menu(self):
         """
@@ -527,20 +529,20 @@
         # WHEN I define a context menu
         service_manager.context_menu(1)
         # THEN the following calls should have occurred.
-        self.assertEquals(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.rename_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once')
-        self.assertEquals(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
-                          'Should have be called once')
-        self.assertEquals(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
-        self.assertEquals(service_manager.theme_menu.menuAction().setVisible.call_count, 1,
-                          'Should have be called once')
+        self.assertEqual(service_manager.edit_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.rename_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.create_custom_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.maintain_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.notes_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.time_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.auto_start_action.setVisible.call_count, 1, 'Should have be called once')
+        self.assertEqual(service_manager.auto_play_slides_menu.menuAction().setVisible.call_count, 1,
+                         'Should have be called once')
+        self.assertEqual(service_manager.auto_play_slides_once.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.auto_play_slides_loop.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.timed_slide_interval.setChecked.call_count, 0, 'Should not be called')
+        self.assertEqual(service_manager.theme_menu.menuAction().setVisible.call_count, 1,
+                         'Should have be called once')
 
     @patch(u'openlp.core.ui.servicemanager.Settings')
     @patch(u'PyQt5.QtCore.QTimer.singleShot')
@@ -573,7 +575,7 @@
         # WHEN: on_single_click_preview() is called
         service_manager.on_single_click_preview()
         # THEN: timer should not be started
-        self.assertEquals(mocked_singleShot.call_count, 0, 'Should not be called')
+        self.assertEqual(mocked_singleShot.call_count, 0, 'Should not be called')
 
     @patch(u'openlp.core.ui.servicemanager.Settings')
     @patch(u'PyQt5.QtCore.QTimer.singleShot')
@@ -591,7 +593,8 @@
         service_manager.on_double_click_live()
         service_manager.on_single_click_preview()
         # THEN: timer should not be started
-        self.assertEquals(mocked_singleShot.call_count, 0, 'Should not be called')
+        mocked_make_live.assert_called_with()
+        self.assertEqual(mocked_singleShot.call_count, 0, 'Should not be called')
 
     @patch(u'openlp.core.ui.servicemanager.ServiceManager.make_preview')
     def test_single_click_timeout_single(self, mocked_make_preview):
@@ -603,7 +606,8 @@
         # WHEN: on_single_click_preview() is called
         service_manager.on_single_click_preview_timeout()
         # THEN: make_preview() should have been called
-        self.assertEquals(mocked_make_preview.call_count, 1, 'Should have been called once')
+        self.assertEqual(mocked_make_preview.call_count, 1,
+                         'ServiceManager.make_preview() should have been called once')
 
     @patch(u'openlp.core.ui.servicemanager.ServiceManager.make_preview')
     @patch(u'openlp.core.ui.servicemanager.ServiceManager.make_live')
@@ -616,5 +620,62 @@
         # WHEN: on_single_click_preview() is called after a double click
         service_manager.on_double_click_live()
         service_manager.on_single_click_preview_timeout()
-        # THEN: make_preview() should have been called
-        self.assertEquals(mocked_make_preview.call_count, 0, 'Should not be called')
+        # THEN: make_preview() should not have been called
+        self.assertEqual(mocked_make_preview.call_count, 0, 'ServiceManager.make_preview() should not be called')
+
+    @patch(u'openlp.core.ui.servicemanager.shutil.copy')
+    @patch(u'openlp.core.ui.servicemanager.zipfile')
+    @patch(u'openlp.core.ui.servicemanager.ServiceManager.save_file_as')
+    def test_save_file_raises_permission_error(self, mocked_save_file_as, mocked_zipfile, mocked_shutil_copy):
+        """
+        Test that when a PermissionError is raised when trying to save a file, it is handled correctly
+        """
+        # GIVEN: A service manager, a service to save
+        mocked_main_window = MagicMock()
+        mocked_main_window.service_manager_settings_section = 'servicemanager'
+        Registry().register('main_window', mocked_main_window)
+        Registry().register('application', MagicMock())
+        service_manager = ServiceManager(None)
+        service_manager._file_name = os.path.join('temp', 'filename.osz')
+        service_manager._save_lite = False
+        service_manager.service_items = []
+        service_manager.service_theme = 'Default'
+        service_manager.service_manager_list = MagicMock()
+        mocked_save_file_as.return_value = True
+        mocked_zipfile.ZipFile.return_value = MagicMock()
+        mocked_shutil_copy.side_effect = PermissionError
+
+        # WHEN: The service is saved and a PermissionError is thrown
+        result = service_manager.save_file()
+
+        # THEN: The "save_as" method is called to save the service
+        self.assertTrue(result)
+        mocked_save_file_as.assert_called_with()
+
+    @patch(u'openlp.core.ui.servicemanager.shutil.copy')
+    @patch(u'openlp.core.ui.servicemanager.zipfile')
+    @patch(u'openlp.core.ui.servicemanager.ServiceManager.save_file_as')
+    def test_save_local_file_raises_permission_error(self, mocked_save_file_as, mocked_zipfile, mocked_shutil_copy):
+        """
+        Test that when a PermissionError is raised when trying to save a local file, it is handled correctly
+        """
+        # GIVEN: A service manager, a service to save
+        mocked_main_window = MagicMock()
+        mocked_main_window.service_manager_settings_section = 'servicemanager'
+        Registry().register('main_window', mocked_main_window)
+        Registry().register('application', MagicMock())
+        service_manager = ServiceManager(None)
+        service_manager._file_name = os.path.join('temp', 'filename.osz')
+        service_manager._save_lite = False
+        service_manager.service_items = []
+        service_manager.service_theme = 'Default'
+        mocked_save_file_as.return_value = True
+        mocked_zipfile.ZipFile.return_value = MagicMock()
+        mocked_shutil_copy.side_effect = PermissionError
+
+        # WHEN: The service is saved and a PermissionError is thrown
+        result = service_manager.save_local_file()
+
+        # THEN: The "save_as" method is called to save the service
+        self.assertTrue(result)
+        mocked_save_file_as.assert_called_with()


Follow ups