← Back to team overview

openlp-core team mailing list archive

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

 

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

Requested reviews:
  OpenLP Core (openlp-core)
Related bugs:
  Bug #1514545 in OpenLP: "DVD audio/subtitle track selection is broken"
  https://bugs.launchpad.net/openlp/+bug/1514545
  Bug #1735765 in OpenLP: "Launching OpenLP in portable mode results in a traceback"
  https://bugs.launchpad.net/openlp/+bug/1735765

For more details, see:
https://code.launchpad.net/~phill-ridout/openlp/fixes-mkIV/+merge/334708

A few various fixes, including some affecting the creation / saving of services.

Add this to your merge proposal:
--------------------------------------------------------------------------------
lp:~phill-ridout/openlp/fixes-mkIV (revision 2798)
https://ci.openlp.io/job/Branch-01-Pull/2337/                          [WAITING]
[RUNNING]
[SUCCESS]
https://ci.openlp.io/job/Branch-02-Functional-Tests/2238/              [WAITING]
[RUNNING]
[SUCCESS]
https://ci.openlp.io/job/Branch-03-Interface-Tests/2108/               [WAITING]
[RUNNING]
[SUCCESS]
https://ci.openlp.io/job/Branch-04a-Code_Analysis/1434/                [WAITING]
[RUNNING]
[SUCCESS]
https://ci.openlp.io/job/Branch-04b-Test_Coverage/1253/                [WAITING]
[RUNNING]
[SUCCESS]
https://ci.openlp.io/job/Branch-04c-Code_Analysis2/383/                [WAITING]
[RUNNING]
[SUCCESS]
https://ci.openlp.io/job/Branch-05-AppVeyor-Tests/212/                 [WAITING]
[RUNNING]
[FAILURE]
Stopping after failure

Failed builds:
 - Branch-05-AppVeyor-Tests #212: https://ci.openlp.io/job/Branch-05-AppVeyor-Tests/212/console
-- 
Your team OpenLP Core is requested to review the proposed merge of lp:~phill-ridout/openlp/fixes-mkIV into lp:openlp.
=== modified file 'openlp/core/api/deploy.py'
--- openlp/core/api/deploy.py	2017-11-18 11:23:15 +0000
+++ openlp/core/api/deploy.py	2017-12-04 21:51:22 +0000
@@ -52,6 +52,8 @@
         web_config = get_web_page('https://get.openlp.org/webclient/download.cfg', headers={'User-Agent': user_agent})
     except ConnectionError:
         return False
+    if not web_config:
+        return None
     file_bits = web_config.split()
     return file_bits[0], file_bits[2]
 

=== modified file 'openlp/core/api/http/server.py'
--- openlp/core/api/http/server.py	2017-12-02 09:11:22 +0000
+++ openlp/core/api/http/server.py	2017-12-04 21:51:22 +0000
@@ -67,7 +67,10 @@
         address = Settings().value('api/ip address')
         port = Settings().value('api/port')
         Registry().execute('get_website_version')
-        serve(application, host=address, port=port)
+        try:
+            serve(application, host=address, port=port)
+        except OSError:
+            log.exception('An error occurred when serving the application.')
 
     def stop(self):
         pass

=== modified file 'openlp/core/app.py'
--- openlp/core/app.py	2017-10-23 22:09:57 +0000
+++ openlp/core/app.py	2017-12-04 21:51:22 +0000
@@ -403,8 +403,8 @@
                      .format(back_up_path=back_up_path))
             QtWidgets.QMessageBox.information(
                 None, translate('OpenLP', 'Settings Upgrade'),
-                translate('OpenLP', 'Your settings are about to upgraded. A backup will be created at {back_up_path}')
-                     .format(back_up_path=back_up_path))
+                translate('OpenLP', 'Your settings are about to be upgraded. A backup will be created at '
+                                    '{back_up_path}').format(back_up_path=back_up_path))
             settings.export(back_up_path)
         settings.upgrade_settings()
     # First time checks in settings

=== modified file 'openlp/core/common/settings.py'
--- openlp/core/common/settings.py	2017-11-16 00:19:26 +0000
+++ openlp/core/common/settings.py	2017-12-04 21:51:22 +0000
@@ -236,7 +236,7 @@
         ('bibles/last search type', '', []),
         ('custom/last search type', 'custom/last used search type', []),
         # The following changes are being made for the conversion to using Path objects made in 2.6 development
-        ('advanced/data path', 'advanced/data path', [(str_to_path, None)]),
+        ('advanced/data path', 'advanced/data path', [(lambda p: Path(p) if p is not None else None, None)]),
         ('crashreport/last directory', 'crashreport/last directory', [(str_to_path, None)]),
         ('servicemanager/last directory', 'servicemanager/last directory', [(str_to_path, None)]),
         ('servicemanager/last file', 'servicemanager/last file', [(str_to_path, None)]),

=== modified file 'openlp/core/ui/media/mediacontroller.py'
--- openlp/core/ui/media/mediacontroller.py	2017-10-23 22:09:57 +0000
+++ openlp/core/ui/media/mediacontroller.py	2017-12-04 21:51:22 +0000
@@ -498,8 +498,6 @@
         :param controller: The media controller.
         :return: True if setup succeeded else False.
         """
-        if controller is None:
-            controller = self.display_controllers[DisplayControllerType.Plugin]
         # stop running videos
         self.media_reset(controller)
         # Setup media info
@@ -509,9 +507,9 @@
             controller.media_info.media_type = MediaType.CD
         else:
             controller.media_info.media_type = MediaType.DVD
-        controller.media_info.start_time = start // 1000
-        controller.media_info.end_time = end // 1000
-        controller.media_info.length = (end - start) // 1000
+        controller.media_info.start_time = start
+        controller.media_info.end_time = end
+        controller.media_info.length = (end - start)
         controller.media_info.title_track = title
         controller.media_info.audio_track = audio_track
         controller.media_info.subtitle_track = subtitle_track

=== modified file 'openlp/core/ui/media/vlcplayer.py'
--- openlp/core/ui/media/vlcplayer.py	2017-10-07 07:05:07 +0000
+++ openlp/core/ui/media/vlcplayer.py	2017-12-04 21:51:22 +0000
@@ -280,7 +280,8 @@
                 start_time = controller.media_info.start_time
         log.debug('mediatype: ' + str(controller.media_info.media_type))
         # Set tracks for the optical device
-        if controller.media_info.media_type == MediaType.DVD:
+        if controller.media_info.media_type == MediaType.DVD and \
+                self.get_live_state() != MediaState.Paused and self.get_preview_state() != MediaState.Paused:
             log.debug('vlc play, playing started')
             if controller.media_info.title_track > 0:
                 log.debug('vlc play, title_track set: ' + str(controller.media_info.title_track))
@@ -350,7 +351,7 @@
         """
         if display.controller.media_info.media_type == MediaType.CD \
                 or display.controller.media_info.media_type == MediaType.DVD:
-            seek_value += int(display.controller.media_info.start_time * 1000)
+            seek_value += int(display.controller.media_info.start_time)
         if display.vlc_media_player.is_seekable():
             display.vlc_media_player.set_time(seek_value)
 
@@ -386,15 +387,15 @@
             self.stop(display)
         controller = display.controller
         if controller.media_info.end_time > 0:
-            if display.vlc_media_player.get_time() > controller.media_info.end_time * 1000:
+            if display.vlc_media_player.get_time() > controller.media_info.end_time:
                 self.stop(display)
                 self.set_visible(display, False)
         if not controller.seek_slider.isSliderDown():
             controller.seek_slider.blockSignals(True)
             if display.controller.media_info.media_type == MediaType.CD \
                     or display.controller.media_info.media_type == MediaType.DVD:
-                controller.seek_slider.setSliderPosition(display.vlc_media_player.get_time() -
-                                                         int(display.controller.media_info.start_time * 1000))
+                controller.seek_slider.setSliderPosition(
+                    display.vlc_media_player.get_time() - int(display.controller.media_info.start_time))
             else:
                 controller.seek_slider.setSliderPosition(display.vlc_media_player.get_time())
             controller.seek_slider.blockSignals(False)

=== modified file 'openlp/core/ui/servicemanager.py'
--- openlp/core/ui/servicemanager.py	2017-11-19 21:57:38 +0000
+++ openlp/core/ui/servicemanager.py	2017-12-04 21:51:22 +0000
@@ -350,7 +350,10 @@
         if modified:
             self.service_id += 1
         self._modified = modified
-        service_file = self.short_file_name() or translate('OpenLP.ServiceManager', 'Untitled Service')
+        if self._service_path:
+            service_file = self._service_path.name
+        else:
+            service_file = translate('OpenLP.ServiceManager', 'Untitled Service')
         self.main_window.set_service_modified(modified, service_file)
 
     def is_modified(self):
@@ -367,7 +370,7 @@
         :rtype: None
         """
         self._service_path = file_path
-        self.main_window.set_service_modified(self.is_modified(), self.short_file_name())
+        self.main_window.set_service_modified(self.is_modified(), file_path.name)
         Settings().setValue('servicemanager/last file', file_path)
         if file_path and file_path.suffix == '.oszl':
             self._save_lite = True
@@ -386,7 +389,8 @@
         """
         Return the current file name, excluding the path.
         """
-        return self._service_path.name
+        if self._service_path:
+            return self._service_path.name
 
     def reset_supported_suffixes(self):
         """

=== modified file 'openlp/plugins/media/forms/mediaclipselectorform.py'
--- openlp/plugins/media/forms/mediaclipselectorform.py	2017-10-23 22:09:57 +0000
+++ openlp/plugins/media/forms/mediaclipselectorform.py	2017-12-04 21:51:22 +0000
@@ -28,6 +28,7 @@
 from PyQt5 import QtCore, QtGui, QtWidgets
 
 from openlp.core.common import is_win, is_linux, is_macosx
+from openlp.core.common.path import Path
 from openlp.core.common.i18n import translate
 from openlp.core.common.mixins import RegistryProperties
 from openlp.plugins.media.forms.mediaclipselectordialog import Ui_MediaClipSelector
@@ -109,7 +110,7 @@
         self.subtitle_tracks_combobox.clear()
         self.audio_tracks_combobox.clear()
         self.titles_combo_box.clear()
-        time = QtCore.QTime()
+        time = QtCore.QTime(0, 0, 0)
         self.start_position_edit.setTime(time)
         self.end_timeedit.setTime(time)
         self.position_timeedit.setTime(time)
@@ -294,7 +295,7 @@
         :param clicked: Given from signal, not used.
         """
         vlc_ms_pos = self.vlc_media_player.get_time()
-        time = QtCore.QTime()
+        time = QtCore.QTime(0, 0, 0)
         new_pos_time = time.addMSecs(vlc_ms_pos)
         self.start_position_edit.setTime(new_pos_time)
         # If start time is after end time, update end time.
@@ -310,7 +311,7 @@
         :param clicked: Given from signal, not used.
         """
         vlc_ms_pos = self.vlc_media_player.get_time()
-        time = QtCore.QTime()
+        time = QtCore.QTime(0, 0, 0)
         new_pos_time = time.addMSecs(vlc_ms_pos)
         self.end_timeedit.setTime(new_pos_time)
         # If start time is after end time, update start time.
@@ -447,7 +448,7 @@
         self.position_slider.setMaximum(self.playback_length)
         # setup start and end time
         rounded_vlc_ms_length = int(round(self.playback_length / 100.0) * 100.0)
-        time = QtCore.QTime()
+        time = QtCore.QTime(0, 0, 0)
         playback_length_time = time.addMSecs(rounded_vlc_ms_length)
         self.start_position_edit.setMaximumTime(playback_length_time)
         self.end_timeedit.setMaximumTime(playback_length_time)
@@ -505,7 +506,7 @@
         if self.vlc_media_player:
             vlc_ms_pos = self.vlc_media_player.get_time()
             rounded_vlc_ms_pos = int(round(vlc_ms_pos / 100.0) * 100.0)
-            time = QtCore.QTime()
+            time = QtCore.QTime(0, 0, 0)
             new_pos_time = time.addMSecs(rounded_vlc_ms_pos)
             self.position_timeedit.setTime(new_pos_time)
             self.position_slider.setSliderPosition(vlc_ms_pos)
@@ -615,7 +616,7 @@
                 break
         # Append the new name to the optical string and the path
         optical += new_optical_name + ':' + path
-        self.media_item.add_optical_clip(optical)
+        self.media_item.add_optical_clip(Path(optical))
 
     def media_state_wait(self, media_state):
         """

=== modified file 'openlp/plugins/media/lib/mediaitem.py'
--- openlp/plugins/media/lib/mediaitem.py	2017-11-14 17:35:37 +0000
+++ openlp/plugins/media/lib/mediaitem.py	2017-12-04 21:51:22 +0000
@@ -269,10 +269,9 @@
             service_item.add_from_command(filename, name, CLAPPERBOARD)
             service_item.title = clip_name
             # Set the length
-            self.media_controller.media_setup_optical(name, title, audio_track, subtitle_track, start, end, None, None)
-            service_item.set_media_length((end - start) / 1000)
-            service_item.start_time = start / 1000
-            service_item.end_time = end / 1000
+            service_item.set_media_length(end - start)
+            service_item.start_time = start
+            service_item.end_time = end
             service_item.add_capability(ItemCapabilities.IsOptical)
         else:
             if not os.path.exists(filename):
@@ -455,5 +454,5 @@
             return
         # Append the optical string to the media list
         file_paths.append(optical)
-        self.load_list([optical])
+        self.load_list([str(optical)])
         Settings().setValue(self.settings_section + '/media files', file_paths)

=== added file 'tests/functional/openlp_core/lib/test_exceptions.py'
--- tests/functional/openlp_core/lib/test_exceptions.py	1970-01-01 00:00:00 +0000
+++ tests/functional/openlp_core/lib/test_exceptions.py	2017-12-04 21:51:22 +0000
@@ -0,0 +1,45 @@
+# -*- 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                          #
+###############################################################################
+"""
+Package to test the openlp.core.lib.exceptions package.
+"""
+from unittest import TestCase
+
+from openlp.core.lib.exceptions import ValidationError
+
+
+class TestValidationError(TestCase):
+    """
+    Test the ValidationError Class
+    """
+    def test_validation_error(self):
+        """
+        Test the creation of a ValidationError
+        """
+        # GIVEN: The ValidationError class
+
+        # WHEN: Creating an instance of ValidationError
+        error = ValidationError('Test ValidationError')
+
+        # THEN: Then calling str on the error should return the correct text and it should be an instance of `Exception`
+        assert str(error) == 'Test ValidationError'
+        assert isinstance(error, Exception)

=== modified file 'tests/functional/openlp_core/lib/test_mediamanageritem.py'
--- tests/functional/openlp_core/lib/test_mediamanageritem.py	2017-04-24 05:17:55 +0000
+++ tests/functional/openlp_core/lib/test_mediamanageritem.py	2017-12-04 21:51:22 +0000
@@ -42,8 +42,8 @@
         self.mocked_setup = self.setup_patcher.start()
         self.addCleanup(self.setup_patcher.stop)
 
-    @patch(u'openlp.core.lib.mediamanageritem.Settings')
-    @patch(u'openlp.core.lib.mediamanageritem.MediaManagerItem.on_preview_click')
+    @patch('openlp.core.lib.mediamanageritem.Settings')
+    @patch('openlp.core.lib.mediamanageritem.MediaManagerItem.on_preview_click')
     def test_on_double_clicked(self, mocked_on_preview_click, MockedSettings):
         """
         Test that when an item is double-clicked then the item is previewed
@@ -75,8 +75,8 @@
         self.assertTrue(mmi.has_delete_icon, 'By default a delete icon should be present')
         self.assertFalse(mmi.add_to_service_item, 'There should be no add_to_service icon by default')
 
-    @patch(u'openlp.core.lib.mediamanageritem.Settings')
-    @patch(u'openlp.core.lib.mediamanageritem.MediaManagerItem.on_live_click')
+    @patch('openlp.core.lib.mediamanageritem.Settings')
+    @patch('openlp.core.lib.mediamanageritem.MediaManagerItem.on_live_click')
     def test_on_double_clicked_go_live(self, mocked_on_live_click, MockedSettings):
         """
         Test that when "Double-click to go live" is enabled that the item goes live
@@ -93,9 +93,9 @@
         # THEN: on_live_click() should have been called
         mocked_on_live_click.assert_called_with()
 
-    @patch(u'openlp.core.lib.mediamanageritem.Settings')
-    @patch(u'openlp.core.lib.mediamanageritem.MediaManagerItem.on_live_click')
-    @patch(u'openlp.core.lib.mediamanageritem.MediaManagerItem.on_preview_click')
+    @patch('openlp.core.lib.mediamanageritem.Settings')
+    @patch('openlp.core.lib.mediamanageritem.MediaManagerItem.on_live_click')
+    @patch('openlp.core.lib.mediamanageritem.MediaManagerItem.on_preview_click')
     def test_on_double_clicked_single_click_preview(self, mocked_on_preview_click, mocked_on_live_click,
                                                     MockedSettings):
         """
@@ -111,5 +111,5 @@
         mmi.on_double_clicked()
 
         # THEN: on_live_click() should have been called
-        self.assertEqual(0, mocked_on_live_click.call_count, u'on_live_click() should not have been called')
-        self.assertEqual(0, mocked_on_preview_click.call_count, u'on_preview_click() should not have been called')
+        self.assertEqual(0, mocked_on_live_click.call_count, 'on_live_click() should not have been called')
+        self.assertEqual(0, mocked_on_preview_click.call_count, 'on_preview_click() should not have been called')

=== modified file 'tests/functional/openlp_core/ui/media/test_vlcplayer.py'
--- tests/functional/openlp_core/ui/media/test_vlcplayer.py	2017-10-07 07:05:07 +0000
+++ tests/functional/openlp_core/ui/media/test_vlcplayer.py	2017-12-04 21:51:22 +0000
@@ -693,9 +693,9 @@
         vlc_player.set_state(MediaState.Paused, mocked_display)
 
         # WHEN: play() is called
-        with patch.object(vlc_player, 'media_state_wait') as mocked_media_state_wait, \
-                patch.object(vlc_player, 'volume') as mocked_volume:
-            mocked_media_state_wait.return_value = True
+        with patch.object(vlc_player, 'media_state_wait', return_value=True) as mocked_media_state_wait, \
+                patch.object(vlc_player, 'volume') as mocked_volume, \
+                patch.object(vlc_player, 'get_live_state', return_value=MediaState.Loaded):
             result = vlc_player.play(mocked_display)
 
         # THEN: A bunch of things should happen to play the media
@@ -872,7 +872,7 @@
         mocked_display = MagicMock()
         mocked_display.controller.media_info.media_type = MediaType.DVD
         mocked_display.vlc_media_player.is_seekable.return_value = True
-        mocked_display.controller.media_info.start_time = 3
+        mocked_display.controller.media_info.start_time = 3000
         vlc_player = VlcPlayer(None)
 
         # WHEN: seek() is called
@@ -976,7 +976,7 @@
         mocked_display = MagicMock()
         mocked_display.controller = mocked_controller
         mocked_display.vlc_media.get_state.return_value = 1
-        mocked_display.vlc_media_player.get_time.return_value = 400000
+        mocked_display.vlc_media_player.get_time.return_value = 400
         mocked_display.controller.media_info.media_type = MediaType.DVD
         vlc_player = VlcPlayer(None)
 
@@ -990,7 +990,7 @@
         self.assertEqual(2, mocked_stop.call_count)
         mocked_display.vlc_media_player.get_time.assert_called_with()
         mocked_set_visible.assert_called_with(mocked_display, False)
-        mocked_controller.seek_slider.setSliderPosition.assert_called_with(300000)
+        mocked_controller.seek_slider.setSliderPosition.assert_called_with(300)
         expected_calls = [call(True), call(False)]
         self.assertEqual(expected_calls, mocked_controller.seek_slider.blockSignals.call_args_list)
 


Follow ups