diff --git a/openlp/core/api/deploy.py b/openlp/core/api/deploy.py index b64cc40d5..a42f83f0c 100644 --- a/openlp/core/api/deploy.py +++ b/openlp/core/api/deploy.py @@ -52,6 +52,8 @@ def download_sha256(): 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] diff --git a/openlp/core/api/http/server.py b/openlp/core/api/http/server.py index b17888ddb..c80275801 100644 --- a/openlp/core/api/http/server.py +++ b/openlp/core/api/http/server.py @@ -67,7 +67,10 @@ class HttpWorker(QtCore.QObject): 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 diff --git a/openlp/core/app.py b/openlp/core/app.py index 19943e3f0..114a62807 100644 --- a/openlp/core/app.py +++ b/openlp/core/app.py @@ -403,8 +403,8 @@ def main(args=None): .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 diff --git a/openlp/core/common/settings.py b/openlp/core/common/settings.py index 225feb4e1..54f1d9b2a 100644 --- a/openlp/core/common/settings.py +++ b/openlp/core/common/settings.py @@ -236,7 +236,7 @@ class Settings(QtCore.QSettings): ('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)]), diff --git a/openlp/core/ui/media/mediacontroller.py b/openlp/core/ui/media/mediacontroller.py index c72d6669d..10c384b0c 100644 --- a/openlp/core/ui/media/mediacontroller.py +++ b/openlp/core/ui/media/mediacontroller.py @@ -498,8 +498,6 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): :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 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties): 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 diff --git a/openlp/core/ui/media/vlcplayer.py b/openlp/core/ui/media/vlcplayer.py index 605f6a8a1..840471cfe 100644 --- a/openlp/core/ui/media/vlcplayer.py +++ b/openlp/core/ui/media/vlcplayer.py @@ -280,7 +280,8 @@ class VlcPlayer(MediaPlayer): 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 @@ class VlcPlayer(MediaPlayer): """ 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 @@ class VlcPlayer(MediaPlayer): 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) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index e6fb34e2f..29718e09a 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -350,7 +350,10 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi 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 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi :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 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi """ 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): """ diff --git a/openlp/plugins/media/forms/mediaclipselectorform.py b/openlp/plugins/media/forms/mediaclipselectorform.py index af08870df..be9e69fbd 100644 --- a/openlp/plugins/media/forms/mediaclipselectorform.py +++ b/openlp/plugins/media/forms/mediaclipselectorform.py @@ -28,6 +28,7 @@ from datetime import datetime 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 @@ class MediaClipSelectorForm(QtWidgets.QDialog, Ui_MediaClipSelector, RegistryPro 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 @@ class MediaClipSelectorForm(QtWidgets.QDialog, Ui_MediaClipSelector, RegistryPro :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 @@ class MediaClipSelectorForm(QtWidgets.QDialog, Ui_MediaClipSelector, RegistryPro :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 @@ class MediaClipSelectorForm(QtWidgets.QDialog, Ui_MediaClipSelector, RegistryPro 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 @@ class MediaClipSelectorForm(QtWidgets.QDialog, Ui_MediaClipSelector, RegistryPro 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 @@ class MediaClipSelectorForm(QtWidgets.QDialog, Ui_MediaClipSelector, RegistryPro 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): """ diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index e47ed70e0..1c7556aa9 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -269,10 +269,9 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties): 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 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties): 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) diff --git a/tests/functional/openlp_core/lib/test_exceptions.py b/tests/functional/openlp_core/lib/test_exceptions.py new file mode 100644 index 000000000..c0de323b7 --- /dev/null +++ b/tests/functional/openlp_core/lib/test_exceptions.py @@ -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) diff --git a/tests/functional/openlp_core/lib/test_mediamanageritem.py b/tests/functional/openlp_core/lib/test_mediamanageritem.py index fba8ce36b..a6152cbdf 100644 --- a/tests/functional/openlp_core/lib/test_mediamanageritem.py +++ b/tests/functional/openlp_core/lib/test_mediamanageritem.py @@ -42,8 +42,8 @@ class TestMediaManagerItem(TestCase, TestMixin): 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 @@ class TestMediaManagerItem(TestCase, TestMixin): 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 @@ class TestMediaManagerItem(TestCase, TestMixin): # 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 @@ class TestMediaManagerItem(TestCase, TestMixin): 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') diff --git a/tests/functional/openlp_core/ui/media/test_vlcplayer.py b/tests/functional/openlp_core/ui/media/test_vlcplayer.py index 6e2fe73c6..96ab629c6 100644 --- a/tests/functional/openlp_core/ui/media/test_vlcplayer.py +++ b/tests/functional/openlp_core/ui/media/test_vlcplayer.py @@ -693,9 +693,9 @@ class TestVLCPlayer(TestCase, TestMixin): 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 @@ class TestVLCPlayer(TestCase, TestMixin): 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 @@ class TestVLCPlayer(TestCase, TestMixin): 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 @@ class TestVLCPlayer(TestCase, TestMixin): 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)