This commit is contained in:
Andreas Preikschat 2013-07-09 21:47:12 +02:00
commit 3a021b6804
6 changed files with 1311 additions and 6 deletions

View File

@ -35,6 +35,7 @@ import logging
import os
import shutil
import zipfile
import json
from tempfile import mkstemp
from datetime import datetime, timedelta
@ -458,7 +459,7 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog):
path_file_name = unicode(self.file_name())
path, file_name = os.path.split(path_file_name)
base_name = os.path.splitext(file_name)[0]
service_file_name = '%s.osd' % base_name
service_file_name = '%s.osj' % base_name
log.debug(u'ServiceManager.save_file - %s', path_file_name)
Settings().setValue(self.main_window.service_manager_settings_section + u'/last directory', path)
service = []
@ -512,7 +513,7 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog):
file_size = os.path.getsize(file_item)
total_size += file_size
log.debug(u'ServiceManager.save_file - ZIP contents size is %i bytes' % total_size)
service_content = pickle.dumps(service)
service_content = json.dumps(service)
# Usual Zip file cannot exceed 2GiB, file with Zip64 cannot be extracted using unzip in UNIX.
allow_zip_64 = (total_size > 2147483648 + len(service_content))
log.debug(u'ServiceManager.save_file - allowZip64 is %s' % allow_zip_64)
@ -572,7 +573,7 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog):
path_file_name = unicode(self.file_name())
path, file_name = os.path.split(path_file_name)
base_name = os.path.splitext(file_name)[0]
service_file_name = '%s.osd' % base_name
service_file_name = '%s.osj' % base_name
log.debug(u'ServiceManager.save_file - %s', path_file_name)
Settings().setValue(self.main_window.service_manager_settings_section + u'/last directory', path)
service = []
@ -585,7 +586,7 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog):
#TODO: check for file item on save.
service.append({u'serviceitem': service_item})
self.main_window.increment_progress_bar()
service_content = pickle.dumps(service)
service_content = json.dumps(service)
zip_file = None
success = True
self.main_window.increment_progress_bar()
@ -698,11 +699,14 @@ class ServiceManager(QtGui.QWidget, ServiceManagerDialog):
log.debug(u'Extract file: %s', osfile)
zip_info.filename = osfile
zip_file.extract(zip_info, self.servicePath)
if osfile.endswith(u'osd'):
if osfile.endswith(u'osj') or osfile.endswith(u'osd'):
p_file = os.path.join(self.servicePath, osfile)
if 'p_file' in locals():
file_to = open(p_file, u'r')
items = pickle.load(file_to)
if p_file.endswith(u'osj'):
items = json.load(file_to)
else:
items = cPickle.load(file_to)
file_to.close()
self.new_file()
self.set_file_name(file_name)

View File

@ -0,0 +1,261 @@
# -*- coding: utf-8 -*-
"""
Package to test the openlp.core.lib package.
"""
import os
import io
import cPickle
import json
import tempfile
from unittest import TestCase
from mock import MagicMock, patch
from openlp.core.lib import ItemCapabilities, ServiceItem, Registry
from lxml import objectify, etree
VERSE = u'The Lord said to {r}Noah{/r}: \n'\
'There\'s gonna be a {su}floody{/su}, {sb}floody{/sb}\n'\
'The Lord said to {g}Noah{/g}:\n'\
'There\'s gonna be a {st}floody{/st}, {it}floody{/it}\n'\
'Get those children out of the muddy, muddy \n'\
'{r}C{/r}{b}h{/b}{bl}i{/bl}{y}l{/y}{g}d{/g}{pk}'\
'r{/pk}{o}e{/o}{pp}n{/pp} of the Lord\n'
FOOTER = [u'Arky Arky (Unknown)', u'Public Domain', u'CCLI 123456']
TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), u'..', u'..', u'resources'))
class TestServiceItem(TestCase):
def setUp(self):
"""
Set up the Registry
"""
Registry.create()
mocked_renderer = MagicMock()
mocked_renderer.format_slide.return_value = [VERSE]
Registry().register(u'renderer', mocked_renderer)
Registry().register(u'image_manager', MagicMock())
def serviceitem_basic_test(self):
"""
Test the Service Item - basic test
"""
# GIVEN: A new service item
# WHEN: A service item is created (without a plugin)
service_item = ServiceItem(None)
# THEN: We should get back a valid service item
assert service_item.is_valid is True, u'The new service item should be valid'
assert service_item.missing_frames() is True, u'There should not be any frames in the service item'
def serviceitem_load_custom_from_service_test(self):
"""
Test the Service Item - adding a custom slide from a saved service
"""
# GIVEN: A new service item and a mocked add icon function
service_item = ServiceItem(None)
service_item.add_icon = MagicMock()
# WHEN: adding a custom from a saved Service
line = self.convert_file_service_item(u'serviceitem_custom_1.osj')
service_item.set_from_service(line)
# THEN: We should get back a valid service item
assert service_item.is_valid is True, u'The new service item should be valid'
assert len(service_item._display_frames) == 0, u'The service item should have no display frames'
assert len(service_item.capabilities) == 5, u'There should be 5 default custom item capabilities'
service_item.render(True)
assert service_item.get_display_title() == u'Test Custom', u'The title should be "Test Custom"'
assert service_item.get_frames()[0][u'text'] == VERSE[:-1], \
u'The returned text matches the input, except the last line feed'
assert service_item.get_rendered_frame(1) == VERSE.split(u'\n', 1)[0], u'The first line has been returned'
assert service_item.get_frame_title(0) == u'Slide 1', u'"Slide 1" has been returned as the title'
assert service_item.get_frame_title(1) == u'Slide 2', u'"Slide 2" has been returned as the title'
assert service_item.get_frame_title(2) == u'', u'Blank has been returned as the title of slide 3'
def serviceitem_load_image_from_service_test(self):
"""
Test the Service Item - adding an image from a saved service
"""
# GIVEN: A new service item and a mocked add icon function
image_name = u'image_1.jpg'
test_file = os.path.join(TEST_PATH, image_name)
frame_array = {u'path': test_file, u'title': image_name}
service_item = ServiceItem(None)
service_item.add_icon = MagicMock()
# WHEN: adding an image from a saved Service and mocked exists
line = self.convert_file_service_item(u'serviceitem_image_1.osj')
with patch(u'openlp.core.ui.servicemanager.os.path.exists') as mocked_exists:
mocked_exists.return_value = True
service_item.set_from_service(line, TEST_PATH)
# THEN: We should get back a valid service item
assert service_item.is_valid is True, u'The new service item should be valid'
assert service_item.get_rendered_frame(0) == test_file, u'The first frame should match the path to the image'
assert service_item.get_frames()[0] == frame_array, u'The return should match frame array1'
assert service_item.get_frame_path(0) == test_file, u'The frame path should match the full path to the image'
assert service_item.get_frame_title(0) == image_name, u'The frame title should match the image name'
assert service_item.get_display_title() == image_name, u'The display title should match the first image name'
assert service_item.is_image() is True, u'This service item should be of an "image" type'
assert service_item.is_capable(ItemCapabilities.CanMaintain) is True, \
u'This service item should be able to be Maintained'
assert service_item.is_capable(ItemCapabilities.CanPreview) is True, \
u'This service item should be able to be be Previewed'
assert service_item.is_capable(ItemCapabilities.CanLoop) is True, \
u'This service item should be able to be run in a can be made to Loop'
assert service_item.is_capable(ItemCapabilities.CanAppend) is True, \
u'This service item should be able to have new items added to it'
def serviceitem_load_image_from_local_service_test(self):
"""
Test the Service Item - adding an image from a saved local service
"""
# GIVEN: A new service item and a mocked add icon function
image_name1 = u'image_1.jpg'
image_name2 = u'image_2.jpg'
test_file1 = os.path.join(u'/home/openlp', image_name1)
test_file2 = os.path.join(u'/home/openlp', image_name2)
frame_array1 = {u'path': test_file1, u'title': image_name1}
frame_array2 = {u'path': test_file2, u'title': image_name2}
service_item = ServiceItem(None)
service_item.add_icon = MagicMock()
service_item2 = ServiceItem(None)
service_item2.add_icon = MagicMock()
# WHEN: adding an image from a saved Service and mocked exists
line = self.convert_file_service_item(u'serviceitem_image_2.osj')
line2 = self.convert_file_service_item(u'serviceitem_image_2.osj', 1)
with patch(u'openlp.core.ui.servicemanager.os.path.exists') as mocked_exists:
mocked_exists.return_value = True
service_item2.set_from_service(line2)
service_item.set_from_service(line)
# THEN: We should get back a valid service item
# This test is copied from service_item.py, but is changed since to conform to
# new layout of service item. The layout use in serviceitem_image_2.osd is actually invalid now.
assert service_item.is_valid is True, u'The first service item should be valid'
assert service_item2.is_valid is True, u'The second service item should be valid'
assert service_item.get_rendered_frame(0) == test_file1, u'The first frame should match the path to the image'
assert service_item2.get_rendered_frame(0) == test_file2, u'The Second frame should match the path to the image'
assert service_item.get_frames()[0] == frame_array1, u'The return should match the frame array1'
assert service_item2.get_frames()[0] == frame_array2, u'The return should match the frame array2'
assert service_item.get_frame_path(0) == test_file1, u'The frame path should match the full path to the image'
assert service_item2.get_frame_path(0) == test_file2, u'The frame path should match the full path to the image'
assert service_item.get_frame_title(0) == image_name1, u'The 1st frame title should match the image name'
assert service_item2.get_frame_title(0) == image_name2, u'The 2nd frame title should match the image name'
assert service_item.title.lower() == service_item.name, \
u'The plugin name should match the display title, as there are > 1 Images'
assert service_item.is_image() is True, u'This service item should be of an "image" type'
assert service_item.is_capable(ItemCapabilities.CanMaintain) is True, \
u'This service item should be able to be Maintained'
assert service_item.is_capable(ItemCapabilities.CanPreview) is True, \
u'This service item should be able to be be Previewed'
assert service_item.is_capable(ItemCapabilities.CanLoop) is True, \
u'This service item should be able to be run in a can be made to Loop'
assert service_item.is_capable(ItemCapabilities.CanAppend) is True, \
u'This service item should be able to have new items added to it'
def serviceitem_convert_osd2osj_test(self):
"""
Test the Service Item - load a osd to service_item, convert to json,
load again to service_item and compare the old and new service_item.
"""
# GIVEN: A valid osd (python pickle format) service in file
service_file = os.path.join(TEST_PATH, u'serviceitem_osd2osj.osd')
osd_service_items = []
try:
open_file = open(service_file, u'r')
osd_service_items = cPickle.load(open_file)
except IOError:
osd_service_items = []
finally:
open_file.close()
# WHEN: Dumping loaded osd service to json format, and save to file and reloading to service
json_service_content = json.dumps(osd_service_items)
open_file = None
open_filename = u''
try:
(open_filep, open_filename) = tempfile.mkstemp()
open_file = open(open_filename, u'w')
open_file.write(json_service_content)
open_file.close()
open_file = open(open_filename, u'r')
json_service_content = open_file.read()
except IOError:
json_service_content = u''
finally:
open_file.close()
os.remove(open_filename)
osj_service_items = json.loads(json_service_content)
# THEN: The service loaded from osj (json format) should be the same as the service loaded from the original osd (python pickle format)
# Loop over every item and compare the osj with osd version
for osd_item, osj_item in zip(osd_service_items, osj_service_items):
# Create service item objects
service_item_osd = ServiceItem()
service_item_osd.add_icon = MagicMock()
service_item_osj = ServiceItem()
service_item_osj.add_icon = MagicMock()
with patch(u'openlp.core.ui.servicemanager.os.path.exists') as mocked_exists:
mocked_exists.return_value = True
service_item_osd.set_from_service(osd_item, TEST_PATH)
service_item_osj.set_from_service(osj_item, TEST_PATH)
# Check that the exported/imported attributes are the same
assert service_item_osj.is_valid is True, u'The osj service item should be valid'
assert service_item_osd.is_valid is True, u'The osd service item should be valid'
assert service_item_osj.name == service_item_osd.name , u'The osd and the osj attribute name should be the same!'
assert service_item_osj.theme == service_item_osd.theme , u'The osd and the osj attribute theme should be the same!'
assert service_item_osj.title == service_item_osd.title , u'The osd and the osj attribute title should be the same!'
assert service_item_osj.icon == service_item_osd.icon , u'The osd and the osj attribute icon should be the same!'
assert service_item_osj.raw_footer == service_item_osd.raw_footer , u'The osd and the osj attribute raw_footer should be the same!'
assert service_item_osj.service_item_type == service_item_osd.service_item_type , u'The osd and the osj attribute service_item_type should be the same!'
assert service_item_osj.audit == service_item_osd.audit , u'The osd and the osj attribute audit should be the same!'
assert service_item_osj.notes == service_item_osd.notes , u'The osd and the osj attribute notes should be the same!'
assert service_item_osj.from_plugin == service_item_osd.from_plugin , u'The osd and the osj attribute from_plugin should be the same!'
assert service_item_osj.capabilities == service_item_osd.capabilities , u'The osd and the osj attribute capabilities should be the same!'
assert service_item_osj.search_string == service_item_osd.search_string , u'The osd and the osj attribute search_string should be the same!'
assert service_item_osj.data_string == service_item_osd.data_string , u'The osd and the osj attribute data_string should be the same!'
# Notice that xml_version from osd needs to be utf-8 decoded, since unicode-characters
# is written as byte-codes by pickle, while json can escape unicode-characters
if service_item_osd.xml_version:
assert service_item_osj.xml_version == service_item_osd.xml_version.decode(u'utf-8') , u'The osd and the osj attribute xml_version should be the same!'
assert service_item_osj.auto_play_slides_once == service_item_osd.auto_play_slides_once , u'The osd and the osj attribute auto_play_slides_once should be the same!'
assert service_item_osj.auto_play_slides_loop == service_item_osd.auto_play_slides_loop , u'The osd and the osj attribute auto_play_slides_loop should be the same!'
assert service_item_osj.timed_slide_interval == service_item_osd.timed_slide_interval , u'The osd and the osj attribute timed_slide_interval should be the same!'
assert service_item_osj.start_time == service_item_osd.start_time , u'The osd and the osj attribute start_time should be the same!'
assert service_item_osj.end_time == service_item_osd.end_time , u'The osd and the osj attribute end_time should be the same!'
assert service_item_osj.media_length == service_item_osd.media_length , u'The osd and the osj attribute media_length should be the same!'
assert service_item_osj.background_audio == service_item_osd.background_audio , u'The osd and the osj attribute background_audio should be the same!'
assert service_item_osj.theme_overwritten == service_item_osd.theme_overwritten , u'The osd and the osj attribute theme_overwritten should be the same!'
assert service_item_osj.will_auto_start == service_item_osd.will_auto_start , u'The osd and the osj attribute will_auto_start should be the same!'
assert service_item_osj.processor == service_item_osd.processor , u'The osd and the osj attribute processor should be the same!'
def convert_file_service_item(self, name, row=0):
service_file = os.path.join(TEST_PATH, name)
try:
open_file = open(service_file, u'r')
items = json.load(open_file)
first_line = items[row]
except IOError:
first_line = u''
finally:
open_file.close()
return first_line

View File

@ -0,0 +1 @@
[{"serviceitem": {"header": {"xml_version": null, "auto_play_slides_loop": false, "auto_play_slides_once": false, "will_auto_start": false, "title": "Test Custom", "capabilities": [2, 1, 5, 13, 8], "theme": null, "background_audio": [], "icon": ":/plugins/plugin_custom.png", "type": 1, "start_time": 0, "from_plugin": false, "media_length": 0, "data": "", "timed_slide_interval": 0, "audit": "", "search": "", "name": "custom", "footer": ["Test Custom Credits"], "notes": "", "plugin": "custom", "theme_overwritten": false, "end_time": 0, "processor": null}, "data": [{"verseTag": null, "raw_slide": "Slide 1", "title": "Slide 1"}, {"verseTag": null, "raw_slide": "Slide 2", "title": "Slide 2"}]}}]

View File

@ -0,0 +1 @@
[{"serviceitem": {"header": {"xml_version": null, "auto_play_slides_loop": false, "auto_play_slides_once": false, "will_auto_start": false, "title": "Images", "capabilities": [3, 1, 5, 6], "theme": -1, "background_audio": [], "icon": ":/plugins/plugin_images.png", "type": 2, "start_time": 0, "from_plugin": false, "media_length": 0, "data": "", "timed_slide_interval": 0, "audit": "", "search": "", "name": "images", "footer": [], "notes": "", "plugin": "images", "theme_overwritten": false, "end_time": 0, "processor": null}, "data": ["image_1.jpg"]}}]

View File

@ -0,0 +1 @@
[{"serviceitem": {"header": {"xml_version": null, "auto_play_slides_loop": false, "auto_play_slides_once": false, "will_auto_start": false, "title": "Images", "capabilities": [3, 1, 5, 6], "theme": -1, "background_audio": [], "icon": ":/plugins/plugin_images.png", "type": 2, "start_time": 0, "from_plugin": false, "media_length": 0, "data": "", "timed_slide_interval": 0, "audit": "", "search": "", "name": "images", "footer": [], "notes": "", "plugin": "images", "theme_overwritten": false, "end_time": 0, "processor": null}, "data": [{"path": "/home/openlp/image_1.jpg", "title": "image_1.jpg"}]}}, {"serviceitem": {"header": {"xml_version": null, "auto_play_slides_loop": false, "auto_play_slides_once": false, "will_auto_start": false, "title": "Images", "capabilities": [3, 1, 5, 6], "theme": -1, "background_audio": [], "icon": ":/plugins/plugin_images.png", "type": 2, "start_time": 0, "from_plugin": false, "media_length": 0, "data": "", "timed_slide_interval": 0, "audit": "", "search": "", "name": "images", "footer": [], "notes": "", "plugin": "images", "theme_overwritten": false, "end_time": 0, "processor": null}, "data": [{"path": "/home/openlp/image_2.jpg", "title": "image_2.jpg"}]}}]

File diff suppressed because it is too large Load Diff