This commit is contained in:
Tomas Groth 2014-04-04 19:57:28 +02:00
commit 7be9613bf0
21 changed files with 364 additions and 196 deletions

View File

@ -62,11 +62,9 @@ class Registry(object):
registry = cls() registry = cls()
registry.service_list = {} registry.service_list = {}
registry.functions_list = {} registry.functions_list = {}
registry.running_under_test = False
registry.initialising = True
# Allow the tests to remove Registry entries but not the live system # Allow the tests to remove Registry entries but not the live system
if 'nose' in sys.argv[0]: registry.running_under_test = 'nose' in sys.argv[0]
registry.running_under_test = True registry.initialising = True
return registry return registry
def get(self, key): def get(self, key):
@ -128,7 +126,7 @@ class Registry(object):
:param event: The function description.. :param event: The function description..
:param function: The function to be called when the event happens. :param function: The function to be called when the event happens.
""" """
if self.running_under_test is False: if not self.running_under_test:
trace_error_handler(log) trace_error_handler(log)
log.error('Invalid Method call for key %s' % event) log.error('Invalid Method call for key %s' % event)
raise KeyError('Invalid Method call for key %s' % event) raise KeyError('Invalid Method call for key %s' % event)

View File

@ -87,10 +87,11 @@ def upgrade_db(url, upgrade):
""" """
pass pass
metadata_table = Table('metadata', metadata, metadata_table = Table(
Column('key', types.Unicode(64), primary_key=True), 'metadata', metadata,
Column('value', types.UnicodeText(), default=None) Column('key', types.Unicode(64), primary_key=True),
) Column('value', types.UnicodeText(), default=None)
)
metadata_table.create(checkfirst=True) metadata_table.create(checkfirst=True)
mapper(Metadata, metadata_table) mapper(Metadata, metadata_table)
version_meta = session.query(Metadata).get('version') version_meta = session.query(Metadata).get('version')
@ -131,7 +132,6 @@ def delete_database(plugin_name, db_file_name=None):
:param plugin_name: The name of the plugin to remove the database for :param plugin_name: The name of the plugin to remove the database for
:param db_file_name: The database file name. Defaults to None resulting in the plugin_name being used. :param db_file_name: The database file name. Defaults to None resulting in the plugin_name being used.
""" """
db_file_path = None
if db_file_name: if db_file_name:
db_file_path = os.path.join(AppLocation.get_section_data_path(plugin_name), db_file_name) db_file_path = os.path.join(AppLocation.get_section_data_path(plugin_name), db_file_name)
else: else:

View File

@ -74,11 +74,13 @@ def create_button_box(dialog, name, standard_buttons, custom_buttons=None):
:param name: A string which is set as object name. :param name: A string which is set as object name.
:param standard_buttons: A list of strings for the used buttons. It might contain: ``ok``, ``save``, ``cancel``, :param standard_buttons: A list of strings for the used buttons. It might contain: ``ok``, ``save``, ``cancel``,
``close``, and ``defaults``. ``close``, and ``defaults``.
:param custom_buttons: A list of additional buttons. If a item is a instance of QtGui.QAbstractButton it is added :param custom_buttons: A list of additional buttons. If an item is an instance of QtGui.QAbstractButton it is added
with QDialogButtonBox.ActionRole. Other wise the item has to be a tuple of a button and a ButtonRole. with QDialogButtonBox.ActionRole. Otherwise the item has to be a tuple of a Button and a ButtonRole.
""" """
if custom_buttons is None: if custom_buttons is None:
custom_buttons = [] custom_buttons = []
if standard_buttons is None:
standard_buttons = []
buttons = QtGui.QDialogButtonBox.NoButton buttons = QtGui.QDialogButtonBox.NoButton
if 'ok' in standard_buttons: if 'ok' in standard_buttons:
buttons |= QtGui.QDialogButtonBox.Ok buttons |= QtGui.QDialogButtonBox.Ok

View File

@ -471,7 +471,7 @@ class SlideController(DisplayController, RegistryProperties):
category=self.category, category=self.category,
triggers=self.live_escape) triggers=self.live_escape)
def live_escape(self): def live_escape(self, field=None):
""" """
If you press ESC on the live screen it should close the display temporarily. If you press ESC on the live screen it should close the display temporarily.
""" """
@ -1243,7 +1243,7 @@ class SlideController(DisplayController, RegistryProperties):
if self.service_item: if self.service_item:
self.service_manager.add_service_item(self.service_item) self.service_manager.add_service_item(self.service_item)
def on_go_live_click(self): def on_go_live_click(self, field=None):
""" """
triggered by clicking the Preview slide items triggered by clicking the Preview slide items
""" """
@ -1256,7 +1256,7 @@ class SlideController(DisplayController, RegistryProperties):
self.on_media_close() self.on_media_close()
self.on_go_live() self.on_go_live()
def on_go_live(self): def on_go_live(self, field=None):
""" """
If preview copy slide item to live controller from Preview Controller If preview copy slide item to live controller from Preview Controller
""" """

View File

@ -31,10 +31,8 @@ The :mod:`upgrade` module provides a way for the database and schema that is the
""" """
import logging import logging
from sqlalchemy import Table, func, select, insert
__version__ = 1
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
__version__ = 1
def upgrade_1(session, metadata): def upgrade_1(session, metadata):
@ -43,136 +41,4 @@ def upgrade_1(session, metadata):
This upgrade renames a number of keys to a single naming convention. This upgrade renames a number of keys to a single naming convention.
""" """
metadata_table = Table('metadata', metadata, autoload=True) log.info('No upgrades to perform')
# Copy "Version" to "name" ("version" used by upgrade system)
# TODO: Clean up in a subsequent release of OpenLP (like 2.0 final)
session.execute(insert(metadata_table).values(
key='name',
value=select(
[metadata_table.c.value],
metadata_table.c.key == 'Version'
).as_scalar()
))
# Copy "Copyright" to "copyright"
# TODO: Clean up in a subsequent release of OpenLP (like 2.0 final)
session.execute(insert(metadata_table).values(
key='copyright',
value=select(
[metadata_table.c.value],
metadata_table.c.key == 'Copyright'
).as_scalar()
))
# Copy "Permissions" to "permissions"
# TODO: Clean up in a subsequent release of OpenLP (like 2.0 final)
session.execute(insert(metadata_table).values(
key='permissions',
value=select(
[metadata_table.c.value],
metadata_table.c.key == 'Permissions'
).as_scalar()
))
# Copy "Bookname language" to "book_name_language"
# TODO: Clean up in a subsequent release of OpenLP (like 2.0 final)
value_count = session.execute(
select(
[func.count(metadata_table.c.value)],
metadata_table.c.key == 'Bookname language'
)
).scalar()
if value_count > 0:
session.execute(insert(metadata_table).values(
key='book_name_language',
value=select(
[metadata_table.c.value],
metadata_table.c.key == 'Bookname language'
).as_scalar()
))
# Copy "download source" to "download_source"
# TODO: Clean up in a subsequent release of OpenLP (like 2.0 final)
value_count = session.execute(
select(
[func.count(metadata_table.c.value)],
metadata_table.c.key == 'download source'
)
).scalar()
log.debug('download source: %s', value_count)
if value_count > 0:
session.execute(insert(metadata_table).values(
key='download_source',
value=select(
[metadata_table.c.value],
metadata_table.c.key == 'download source'
).as_scalar()
))
# Copy "download name" to "download_name"
# TODO: Clean up in a subsequent release of OpenLP (like 2.0 final)
value_count = session.execute(
select(
[func.count(metadata_table.c.value)],
metadata_table.c.key == 'download name'
)
).scalar()
log.debug('download name: %s', value_count)
if value_count > 0:
session.execute(insert(metadata_table).values(
key='download_name',
value=select(
[metadata_table.c.value],
metadata_table.c.key == 'download name'
).as_scalar()
))
# Copy "proxy server" to "proxy_server"
# TODO: Clean up in a subsequent release of OpenLP (like 2.0 final)
value_count = session.execute(
select(
[func.count(metadata_table.c.value)],
metadata_table.c.key == 'proxy server'
)
).scalar()
log.debug('proxy server: %s', value_count)
if value_count > 0:
session.execute(insert(metadata_table).values(
key='proxy_server',
value=select(
[metadata_table.c.value],
metadata_table.c.key == 'proxy server'
).as_scalar()
))
# Copy "proxy username" to "proxy_username"
# TODO: Clean up in a subsequent release of OpenLP (like 2.0 final)
value_count = session.execute(
select(
[func.count(metadata_table.c.value)],
metadata_table.c.key == 'proxy username'
)
).scalar()
log.debug('proxy username: %s', value_count)
if value_count > 0:
session.execute(insert(metadata_table).values(
key='proxy_username',
value=select(
[metadata_table.c.value],
metadata_table.c.key == 'proxy username'
).as_scalar()
))
# Copy "proxy password" to "proxy_password"
# TODO: Clean up in a subsequent release of OpenLP (like 2.0 final)
value_count = session.execute(
select(
[func.count(metadata_table.c.value)],
metadata_table.c.key == 'proxy password'
)
).scalar()
log.debug('proxy password: %s', value_count)
if value_count > 0:
session.execute(insert(metadata_table).values(
key='proxy_password',
value=select(
[metadata_table.c.value],
metadata_table.c.key == 'proxy password'
).as_scalar()
))
# TODO: Clean up in a subsequent release of OpenLP (like 2.0 final)
#session.execute(delete(metadata_table)\
# .where(metadata_table.c.key == u'dbversion'))
session.commit()

View File

@ -49,7 +49,7 @@ class EasySlidesImport(SongImport):
""" """
Initialise the class. Initialise the class.
""" """
SongImport.__init__(self, manager, **kwargs) super(EasySlidesImport, self).__init__(manager, **kwargs)
def do_import(self): def do_import(self):
log.info('Importing EasySlides XML file %s', self.import_source) log.info('Importing EasySlides XML file %s', self.import_source)

View File

@ -73,7 +73,7 @@ class EasyWorshipSongImport(SongImport):
ability to import EasyWorship song files. ability to import EasyWorship song files.
""" """
def __init__(self, manager, **kwargs): def __init__(self, manager, **kwargs):
SongImport.__init__(self, manager, **kwargs) super(EasyWorshipSongImport, self).__init__(manager, **kwargs)
def do_import(self): def do_import(self):
""" """

View File

@ -97,7 +97,7 @@ class SongBeamerImport(SongImport):
""" """
Initialise the Song Beamer importer. Initialise the Song Beamer importer.
""" """
SongImport.__init__(self, manager, **kwargs) super(SongBeamerImport, self).__init__(manager, **kwargs)
def do_import(self): def do_import(self):
""" """

View File

@ -92,7 +92,7 @@ class SongShowPlusImport(SongImport):
""" """
Initialise the SongShow Plus importer. Initialise the SongShow Plus importer.
""" """
SongImport.__init__(self, manager, **kwargs) super(SongShowPlusImport, self).__init__(manager, **kwargs)
def do_import(self): def do_import(self):
""" """

View File

@ -30,12 +30,15 @@
The :mod:`upgrade` module provides a way for the database and schema that is the The :mod:`upgrade` module provides a way for the database and schema that is the
backend for the Songs plugin backend for the Songs plugin
""" """
import logging
from sqlalchemy import Column, types from sqlalchemy import Column, types
from sqlalchemy.exc import OperationalError
from sqlalchemy.sql.expression import func, false, null, text from sqlalchemy.sql.expression import func, false, null, text
from openlp.core.lib.db import get_upgrade_op from openlp.core.lib.db import get_upgrade_op
log = logging.getLogger(__name__)
__version__ = 3 __version__ = 3
@ -50,14 +53,20 @@ def upgrade_1(session, metadata):
In order to facilitate this one-to-many relationship, a song_id column is In order to facilitate this one-to-many relationship, a song_id column is
added to the media_files table, and a weight column so that the media added to the media_files table, and a weight column so that the media
files can be ordered. files can be ordered.
:param session:
:param metadata:
""" """
op = get_upgrade_op(session) try:
op.drop_table('media_files_songs') op = get_upgrade_op(session)
op.add_column('media_files', Column('song_id', types.Integer(), server_default=null())) op.drop_table('media_files_songs')
op.add_column('media_files', Column('weight', types.Integer(), server_default=text('0'))) op.add_column('media_files', Column('song_id', types.Integer(), server_default=null()))
if metadata.bind.url.get_dialect().name != 'sqlite': op.add_column('media_files', Column('weight', types.Integer(), server_default=text('0')))
# SQLite doesn't support ALTER TABLE ADD CONSTRAINT if metadata.bind.url.get_dialect().name != 'sqlite':
op.create_foreign_key('fk_media_files_song_id', 'media_files', 'songs', ['song_id', 'id']) # SQLite doesn't support ALTER TABLE ADD CONSTRAINT
op.create_foreign_key('fk_media_files_song_id', 'media_files', 'songs', ['song_id', 'id'])
except OperationalError:
log.info('Upgrade 1 has already been run')
def upgrade_2(session, metadata): def upgrade_2(session, metadata):
@ -66,9 +75,12 @@ def upgrade_2(session, metadata):
This upgrade adds a create_date and last_modified date to the songs table This upgrade adds a create_date and last_modified date to the songs table
""" """
op = get_upgrade_op(session) try:
op.add_column('songs', Column('create_date', types.DateTime(), default=func.now())) op = get_upgrade_op(session)
op.add_column('songs', Column('last_modified', types.DateTime(), default=func.now())) op.add_column('songs', Column('create_date', types.DateTime(), default=func.now()))
op.add_column('songs', Column('last_modified', types.DateTime(), default=func.now()))
except OperationalError:
log.info('Upgrade 2 has already been run')
def upgrade_3(session, metadata): def upgrade_3(session, metadata):
@ -77,8 +89,11 @@ def upgrade_3(session, metadata):
This upgrade adds a temporary song flag to the songs table This upgrade adds a temporary song flag to the songs table
""" """
op = get_upgrade_op(session) try:
if metadata.bind.url.get_dialect().name == 'sqlite': op = get_upgrade_op(session)
op.add_column('songs', Column('temporary', types.Boolean(create_constraint=False), server_default=false())) if metadata.bind.url.get_dialect().name == 'sqlite':
else: op.add_column('songs', Column('temporary', types.Boolean(create_constraint=False), server_default=false()))
op.add_column('songs', Column('temporary', types.Boolean(), server_default=false())) else:
op.add_column('songs', Column('temporary', types.Boolean(), server_default=false()))
except OperationalError:
log.info('Upgrade 3 has already been run')

View File

@ -30,10 +30,14 @@
The :mod:`upgrade` module provides a way for the database and schema that is the The :mod:`upgrade` module provides a way for the database and schema that is the
backend for the SongsUsage plugin backend for the SongsUsage plugin
""" """
from openlp.core.lib.db import get_upgrade_op import logging
from sqlalchemy.exc import OperationalError
from sqlalchemy import Column, types from sqlalchemy import Column, types
from openlp.core.lib.db import get_upgrade_op
log = logging.getLogger(__name__)
__version__ = 1 __version__ = 1
@ -42,7 +46,13 @@ def upgrade_1(session, metadata):
Version 1 upgrade. Version 1 upgrade.
This upgrade adds two new fields to the songusage database This upgrade adds two new fields to the songusage database
:param session: SQLAlchemy Session object
:param metadata: SQLAlchemy MetaData object
""" """
op = get_upgrade_op(session) try:
op.add_column('songusage_data', Column('plugin_name', types.Unicode(20), server_default='')) op = get_upgrade_op(session)
op.add_column('songusage_data', Column('source', types.Unicode(10), server_default='')) op.add_column('songusage_data', Column('plugin_name', types.Unicode(20), server_default=''))
op.add_column('songusage_data', Column('source', types.Unicode(10), server_default=''))
except OperationalError:
log.info('Upgrade 1 has already taken place')

View File

@ -94,6 +94,7 @@ OPTIONAL_MODULES = [
('psycopg2', '(PostgreSQL support)', True), ('psycopg2', '(PostgreSQL support)', True),
('nose', '(testing framework)', True), ('nose', '(testing framework)', True),
('mock', '(testing module)', sys.version_info[1] < 3), ('mock', '(testing module)', sys.version_info[1] < 3),
('jenkins', '(access jenkins api - package name: jenkins-webapi)', True),
] ]
w = sys.stdout.write w = sys.stdout.write

192
scripts/jenkins_script.py Normal file
View File

@ -0,0 +1,192 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2014 Raoul Snyman #
# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
# --------------------------------------------------------------------------- #
# 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 #
###############################################################################
"""
This script helps to trigger builds of branches. To use it you have to install the jenkins-webapi package:
pip3 install jenkins-webapi
You probably want to create an alias. Add this to your ~/.bashrc file and then logout and login (to apply the alias):
alias ci="python3 ./scripts/jenkins_script.py TOKEN"
You can look up the token in the Branch-01-Pull job configuration or ask in IRC.
"""
from optparse import OptionParser
from requests.exceptions import HTTPError
from subprocess import Popen, PIPE
import sys
import time
from jenkins import Jenkins
JENKINS_URL = 'http://ci.openlp.org/'
class OpenLPJobs(object):
"""
This class holds any jobs we have on jenkins and we actually need in this script.
"""
Branch_Pull = 'Branch-01-Pull'
Branch_Functional = 'Branch-02-Functional-Tests'
Branch_Interface = 'Branch-03-Interface-Tests'
Branch_Windows = 'Branch-04-Windows_Tests'
Branch_PEP = 'Branch-05-Code-Analysis'
Jobs = [Branch_Pull, Branch_Functional, Branch_Interface, Branch_Windows, Branch_PEP]
class JenkinsTrigger(object):
def __init__(self, token):
"""
Create the JenkinsTrigger instance.
:param token: The token we need to trigger the build. If you do not have this token, ask in IRC.
"""
self.token = token
self.repo_name = get_repo_name()
self.jenkins_instance = Jenkins(JENKINS_URL)
def trigger_build(self):
"""
Ask our jenkins server to build the "Branch-01-Pull" job.
"""
self.jenkins_instance.job(OpenLPJobs.Branch_Pull).build({'BRANCH_NAME': self.repo_name}, token=self.token)
def print_output(self):
"""
Print the status information of the build tirggered.
"""
print("Add this to your merge proposal:")
print("--------------------------------")
for job in OpenLPJobs.Jobs:
self.__print_build_info(job)
def open_browser(self):
"""
Opens the browser.
"""
url = self.jenkins_instance.job(OpenLPJobs.Branch_Pull).info['url']
# Open the url
Popen(('xdg-open', url), stderr=PIPE)
def __print_build_info(self, job_name):
"""
This helper method prints the job information of the given ``job_name``
:param job_name: The name of the job we want the information from. For example *Branch-01-Pull*. Use the class
variables from the :class:`OpenLPJobs` class.
"""
job = self.jenkins_instance.job(job_name)
while job.info['inQueue']:
# Give other processes the possibility to take over. Like Thread.yield().
time.sleep(0)
build = job.last_build
build.wait()
result_string = build.info['result']
url = build.info['url']
print('[%s] %s' % (result_string, url))
# On failure open the browser.
#if result_string == "FAILURE":
# url += 'console'
# Popen(('xdg-open', url), stderr=PIPE)
def get_repo_name():
"""
This returns the name of branch of the wokring directory. For example it returns *lp:~googol/openlp/render*.
"""
# Run the bzr command.
bzr = Popen(('bzr', 'info'), stdout=PIPE, stderr=PIPE)
raw_output, error = bzr.communicate()
# Detect any errors
if error:
print('This is not a branch.')
return
# Clean the output.
raw_output = raw_output.decode()
output_list = list(map(str.strip, raw_output.split('\n')))
# Determine the branch's name
repo_name = ''
for line in output_list:
# Check if it is remote branch.
if 'push branch' in line:
repo_name = line.replace('push branch: bzr+ssh://bazaar.launchpad.net/', 'lp:')
break
elif 'checkout of branch' in line:
repo_name = line.replace('checkout of branch: bzr+ssh://bazaar.launchpad.net/', 'lp:')
break
repo_name = repo_name.strip('/')
# Did we find the branch name?
if not repo_name:
for line in output_list:
# Check if the branch was pushed.
if 'Shared repository with trees (format: 2a)' in line:
print('Not a branch. cd to a branch.')
return
print('Not a branch. Have you pushed it to launchpad?')
return
return repo_name
def main():
usage = 'Usage: python %prog TOKEN [options]'
parser = OptionParser(usage=usage)
parser.add_option('-d', '--disable-output', dest='enable_output', action="store_false", default=True,
help='Disable output.')
parser.add_option('-b', '--open-browser', dest='open_browser', action="store_true", default=False,
help='Opens the jenkins page in your browser.')
#parser.add_option('-e', '--open-browser-on-error', dest='open_browser_on_error', action="store_true",
# default=False, help='Opens the jenkins page in your browser in case a test fails.')
options, args = parser.parse_args(sys.argv)
if len(args) == 2:
if not get_repo_name():
return
token = args[-1]
jenkins_trigger = JenkinsTrigger(token)
try:
jenkins_trigger.trigger_build()
except HTTPError as e:
print("Wrong token.")
return
# Open the browser before printing the output.
if options.open_browser:
jenkins_trigger.open_browser()
if options.enable_output:
jenkins_trigger.print_output()
else:
parser.print_help()
if __name__ == '__main__':
main()

View File

@ -100,6 +100,20 @@ class TestRegistry(TestCase):
# THEN: I expect then function to have been called and a return given # THEN: I expect then function to have been called and a return given
self.assertEqual(return_value[0], 'function_2', 'A return value is provided and matches') self.assertEqual(return_value[0], 'function_2', 'A return value is provided and matches')
def remove_function_test(self):
"""
Test the remove_function() method
"""
# GIVEN: An existing registry register a function
Registry.create()
Registry().register_function('test1', self.dummy_function_1)
# WHEN: Remove the function.
Registry().remove_function('test1', self.dummy_function_1)
# THEN: The method should not be available.
assert not Registry().functions_list['test1'], 'The function should not be in the dict anymore.'
def dummy_function_1(self): def dummy_function_1(self):
return "function_1" return "function_1"

View File

@ -29,13 +29,14 @@
""" """
Package to test the openlp.core.lib package. Package to test the openlp.core.lib package.
""" """
import os
from unittest import TestCase from unittest import TestCase
from sqlalchemy.pool import NullPool from sqlalchemy.pool import NullPool
from sqlalchemy.orm.scoping import ScopedSession from sqlalchemy.orm.scoping import ScopedSession
from sqlalchemy import MetaData from sqlalchemy import MetaData
from openlp.core.lib.db import init_db, get_upgrade_op from openlp.core.lib.db import init_db, get_upgrade_op, delete_database
from tests.functional import patch, MagicMock from tests.functional import patch, MagicMock
@ -110,3 +111,44 @@ class TestDB(TestCase):
mocked_session.bind.connect.assert_called_with() mocked_session.bind.connect.assert_called_with()
MockedMigrationContext.configure.assert_called_with(mocked_connection) MockedMigrationContext.configure.assert_called_with(mocked_connection)
MockedOperations.assert_called_with(mocked_context) MockedOperations.assert_called_with(mocked_context)
def delete_database_without_db_file_name_test(self):
"""
Test that the ``delete_database`` function removes a database file, without the file name parameter
"""
# GIVEN: Mocked out AppLocation class and delete_file method, a test plugin name and a db location
with patch('openlp.core.lib.db.AppLocation') as MockedAppLocation, \
patch('openlp.core.lib.db.delete_file') as mocked_delete_file:
MockedAppLocation.get_section_data_path.return_value = 'test-dir'
mocked_delete_file.return_value = True
test_plugin = 'test'
test_location = os.path.join('test-dir', test_plugin)
# WHEN: delete_database is run without a database file
result = delete_database(test_plugin)
# THEN: The AppLocation.get_section_data_path and delete_file methods should have been called
MockedAppLocation.get_section_data_path.assert_called_with(test_plugin)
mocked_delete_file.assert_called_with(test_location)
self.assertTrue(result, 'The result of delete_file should be True (was rigged that way)')
def delete_database_with_db_file_name_test(self):
"""
Test that the ``delete_database`` function removes a database file, with the file name supplied
"""
# GIVEN: Mocked out AppLocation class and delete_file method, a test plugin name and a db location
with patch('openlp.core.lib.db.AppLocation') as MockedAppLocation, \
patch('openlp.core.lib.db.delete_file') as mocked_delete_file:
MockedAppLocation.get_section_data_path.return_value = 'test-dir'
mocked_delete_file.return_value = False
test_plugin = 'test'
test_db_file = 'mydb.sqlite'
test_location = os.path.join('test-dir', test_db_file)
# WHEN: delete_database is run without a database file
result = delete_database(test_plugin, test_db_file)
# THEN: The AppLocation.get_section_data_path and delete_file methods should have been called
MockedAppLocation.get_section_data_path.assert_called_with(test_plugin)
mocked_delete_file.assert_called_with(test_location)
self.assertFalse(result, 'The result of delete_file should be False (was rigged that way)')

View File

@ -53,3 +53,31 @@ class TestUi(TestCase):
# THEN: The wizard should have one page with a pixmap. # THEN: The wizard should have one page with a pixmap.
self.assertEqual(1, len(wizard.pageIds()), 'The wizard should have one page.') self.assertEqual(1, len(wizard.pageIds()), 'The wizard should have one page.')
self.assertIsInstance(wizard.page(0).pixmap(QtGui.QWizard.WatermarkPixmap), QtGui.QPixmap) self.assertIsInstance(wizard.page(0).pixmap(QtGui.QWizard.WatermarkPixmap), QtGui.QPixmap)
def test_create_button_box(self):
"""
Test creating a button box for a dialog
"""
# GIVEN: A dialog
dialog = QtGui.QDialog()
# WHEN: We create the button box with five buttons
btnbox = create_button_box(dialog, 'my_btns', ['ok', 'save', 'cancel', 'close', 'defaults'])
# THEN: We should get a QDialogButtonBox with five buttons
self.assertIsInstance(btnbox, QtGui.QDialogButtonBox)
self.assertEqual(5, len(btnbox.buttons()))
# WHEN: We create the button box with a custom button
btnbox = create_button_box(dialog, 'my_btns', None, [QtGui.QPushButton('Custom')])
# THEN: We should get a QDialogButtonBox with one button
self.assertIsInstance(btnbox, QtGui.QDialogButtonBox)
self.assertEqual(1, len(btnbox.buttons()))
# WHEN: We create the button box with a custom button and a custom role
btnbox = create_button_box(dialog, 'my_btns', None,
[(QtGui.QPushButton('Help'), QtGui.QDialogButtonBox.HelpRole)])
# THEN: We should get a QDialogButtonBox with one button with a certain role
self.assertIsInstance(btnbox, QtGui.QDialogButtonBox)
self.assertEqual(1, len(btnbox.buttons()))
self.assertEqual(QtGui.QDialogButtonBox.HelpRole, btnbox.buttonRole(btnbox.buttons()[0]))

View File

@ -92,7 +92,7 @@ class EasyWorshipSongImportLogger(EasyWorshipSongImport):
_title_assignment_list = [] _title_assignment_list = []
def __init__(self, manager): def __init__(self, manager):
EasyWorshipSongImport.__init__(self, manager) EasyWorshipSongImport.__init__(self, manager, filenames=[])
@property @property
def title(self): def title(self):
@ -162,7 +162,7 @@ class TestEasyWorshipSongImport(TestCase):
mocked_manager = MagicMock() mocked_manager = MagicMock()
# WHEN: An importer object is created # WHEN: An importer object is created
importer = EasyWorshipSongImport(mocked_manager) importer = EasyWorshipSongImport(mocked_manager, filenames=[])
# THEN: The importer object should not be None # THEN: The importer object should not be None
self.assertIsNotNone(importer, 'Import should not be none') self.assertIsNotNone(importer, 'Import should not be none')
@ -174,7 +174,7 @@ class TestEasyWorshipSongImport(TestCase):
# GIVEN: A mocked out SongImport class, a mocked out "manager" and a list of field descriptions. # GIVEN: A mocked out SongImport class, a mocked out "manager" and a list of field descriptions.
with patch('openlp.plugins.songs.lib.ewimport.SongImport'): with patch('openlp.plugins.songs.lib.ewimport.SongImport'):
mocked_manager = MagicMock() mocked_manager = MagicMock()
importer = EasyWorshipSongImport(mocked_manager) importer = EasyWorshipSongImport(mocked_manager, filenames=[])
importer.field_descriptions = TEST_FIELD_DESCS importer.field_descriptions = TEST_FIELD_DESCS
# WHEN: Called with a field name that exists # WHEN: Called with a field name that exists
@ -192,7 +192,7 @@ class TestEasyWorshipSongImport(TestCase):
# GIVEN: A mocked out SongImport class, a mocked out "manager" and a list of field descriptions # GIVEN: A mocked out SongImport class, a mocked out "manager" and a list of field descriptions
with patch('openlp.plugins.songs.lib.ewimport.SongImport'): with patch('openlp.plugins.songs.lib.ewimport.SongImport'):
mocked_manager = MagicMock() mocked_manager = MagicMock()
importer = EasyWorshipSongImport(mocked_manager) importer = EasyWorshipSongImport(mocked_manager, filenames=[])
importer.field_descriptions = TEST_FIELD_DESCS importer.field_descriptions = TEST_FIELD_DESCS
# WHEN: Called with a field name that does not exist # WHEN: Called with a field name that does not exist
@ -211,7 +211,7 @@ class TestEasyWorshipSongImport(TestCase):
with patch('openlp.plugins.songs.lib.ewimport.SongImport'), \ with patch('openlp.plugins.songs.lib.ewimport.SongImport'), \
patch('openlp.plugins.songs.lib.ewimport.struct') as mocked_struct: patch('openlp.plugins.songs.lib.ewimport.struct') as mocked_struct:
mocked_manager = MagicMock() mocked_manager = MagicMock()
importer = EasyWorshipSongImport(mocked_manager) importer = EasyWorshipSongImport(mocked_manager, filenames=[])
# WHEN: set_record_struct is called with a list of field descriptions # WHEN: set_record_struct is called with a list of field descriptions
return_value = importer.set_record_struct(TEST_FIELD_DESCS) return_value = importer.set_record_struct(TEST_FIELD_DESCS)
@ -228,7 +228,7 @@ class TestEasyWorshipSongImport(TestCase):
# GIVEN: A mocked out SongImport class, a mocked out "manager", an encoding and some test data and known results # GIVEN: A mocked out SongImport class, a mocked out "manager", an encoding and some test data and known results
with patch('openlp.plugins.songs.lib.ewimport.SongImport'): with patch('openlp.plugins.songs.lib.ewimport.SongImport'):
mocked_manager = MagicMock() mocked_manager = MagicMock()
importer = EasyWorshipSongImport(mocked_manager) importer = EasyWorshipSongImport(mocked_manager, filenames=[])
importer.encoding = TEST_DATA_ENCODING importer.encoding = TEST_DATA_ENCODING
importer.fields = TEST_FIELDS importer.fields = TEST_FIELDS
importer.field_descriptions = TEST_FIELD_DESCS importer.field_descriptions = TEST_FIELD_DESCS
@ -251,7 +251,7 @@ class TestEasyWorshipSongImport(TestCase):
with patch('openlp.plugins.songs.lib.ewimport.SongImport'): with patch('openlp.plugins.songs.lib.ewimport.SongImport'):
mocked_manager = MagicMock() mocked_manager = MagicMock()
mocked_memo_file = MagicMock() mocked_memo_file = MagicMock()
importer = EasyWorshipSongImport(mocked_manager) importer = EasyWorshipSongImport(mocked_manager, filenames=[])
importer.memo_file = mocked_memo_file importer.memo_file = mocked_memo_file
importer.encoding = TEST_DATA_ENCODING importer.encoding = TEST_DATA_ENCODING
@ -282,7 +282,7 @@ class TestEasyWorshipSongImport(TestCase):
with patch('openlp.plugins.songs.lib.ewimport.SongImport'), \ with patch('openlp.plugins.songs.lib.ewimport.SongImport'), \
patch('openlp.plugins.songs.lib.ewimport.os.path') as mocked_os_path: patch('openlp.plugins.songs.lib.ewimport.os.path') as mocked_os_path:
mocked_manager = MagicMock() mocked_manager = MagicMock()
importer = EasyWorshipSongImport(mocked_manager) importer = EasyWorshipSongImport(mocked_manager, filenames=[])
mocked_os_path.isfile.side_effect = [True, False] mocked_os_path.isfile.side_effect = [True, False]
# WHEN: Supplied with an import source # WHEN: Supplied with an import source
@ -301,7 +301,7 @@ class TestEasyWorshipSongImport(TestCase):
with patch('openlp.plugins.songs.lib.ewimport.SongImport'), \ with patch('openlp.plugins.songs.lib.ewimport.SongImport'), \
patch('openlp.plugins.songs.lib.ewimport.os.path') as mocked_os_path: patch('openlp.plugins.songs.lib.ewimport.os.path') as mocked_os_path:
mocked_manager = MagicMock() mocked_manager = MagicMock()
importer = EasyWorshipSongImport(mocked_manager) importer = EasyWorshipSongImport(mocked_manager, filenames=[])
mocked_os_path.isfile.return_value = True mocked_os_path.isfile.return_value = True
importer.import_source = 'Songs.DB' importer.import_source = 'Songs.DB'
@ -322,7 +322,7 @@ class TestEasyWorshipSongImport(TestCase):
patch('builtins.open') as mocked_open, \ patch('builtins.open') as mocked_open, \
patch('openlp.plugins.songs.lib.ewimport.struct') as mocked_struct: patch('openlp.plugins.songs.lib.ewimport.struct') as mocked_struct:
mocked_manager = MagicMock() mocked_manager = MagicMock()
importer = EasyWorshipSongImport(mocked_manager) importer = EasyWorshipSongImport(mocked_manager, filenames=[])
mocked_os_path.isfile.return_value = True mocked_os_path.isfile.return_value = True
mocked_os_path.getsize.return_value = 0x800 mocked_os_path.getsize.return_value = 0x800
importer.import_source = 'Songs.DB' importer.import_source = 'Songs.DB'
@ -349,7 +349,7 @@ class TestEasyWorshipSongImport(TestCase):
patch('builtins.open'), patch('openlp.plugins.songs.lib.ewimport.struct') as mocked_struct, \ patch('builtins.open'), patch('openlp.plugins.songs.lib.ewimport.struct') as mocked_struct, \
patch('openlp.plugins.songs.lib.ewimport.retrieve_windows_encoding') as mocked_retrieve_windows_encoding: patch('openlp.plugins.songs.lib.ewimport.retrieve_windows_encoding') as mocked_retrieve_windows_encoding:
mocked_manager = MagicMock() mocked_manager = MagicMock()
importer = EasyWorshipSongImport(mocked_manager) importer = EasyWorshipSongImport(mocked_manager, filenames=[])
mocked_os_path.isfile.return_value = True mocked_os_path.isfile.return_value = True
mocked_os_path.getsize.return_value = 0x800 mocked_os_path.getsize.return_value = 0x800
importer.import_source = 'Songs.DB' importer.import_source = 'Songs.DB'

View File

@ -66,7 +66,7 @@ class TestSongBeamerImport(TestCase):
mocked_manager = MagicMock() mocked_manager = MagicMock()
# WHEN: An importer object is created # WHEN: An importer object is created
importer = SongBeamerImport(mocked_manager) importer = SongBeamerImport(mocked_manager, filenames=[])
# THEN: The importer object should not be None # THEN: The importer object should not be None
self.assertIsNotNone(importer, 'Import should not be none') self.assertIsNotNone(importer, 'Import should not be none')
@ -79,7 +79,7 @@ class TestSongBeamerImport(TestCase):
with patch('openlp.plugins.songs.lib.songbeamerimport.SongImport'): with patch('openlp.plugins.songs.lib.songbeamerimport.SongImport'):
mocked_manager = MagicMock() mocked_manager = MagicMock()
mocked_import_wizard = MagicMock() mocked_import_wizard = MagicMock()
importer = SongBeamerImport(mocked_manager) importer = SongBeamerImport(mocked_manager, filenames=[])
importer.import_wizard = mocked_import_wizard importer.import_wizard = mocked_import_wizard
importer.stop_import_flag = True importer.stop_import_flag = True
@ -100,7 +100,7 @@ class TestSongBeamerImport(TestCase):
with patch('openlp.plugins.songs.lib.songbeamerimport.SongImport'): with patch('openlp.plugins.songs.lib.songbeamerimport.SongImport'):
mocked_manager = MagicMock() mocked_manager = MagicMock()
mocked_import_wizard = MagicMock() mocked_import_wizard = MagicMock()
importer = SongBeamerImport(mocked_manager) importer = SongBeamerImport(mocked_manager, filenames=[])
importer.import_wizard = mocked_import_wizard importer.import_wizard = mocked_import_wizard
importer.stop_import_flag = True importer.stop_import_flag = True
@ -127,7 +127,7 @@ class TestSongBeamerImport(TestCase):
mocked_add_verse = MagicMock() mocked_add_verse = MagicMock()
mocked_finish = MagicMock() mocked_finish = MagicMock()
mocked_finish.return_value = True mocked_finish.return_value = True
importer = SongBeamerImport(mocked_manager) importer = SongBeamerImport(mocked_manager, filenames=[])
importer.import_wizard = mocked_import_wizard importer.import_wizard = mocked_import_wizard
importer.stop_import_flag = False importer.stop_import_flag = False
importer.add_verse = mocked_add_verse importer.add_verse = mocked_add_verse

View File

@ -72,7 +72,7 @@ class TestSongShowPlusImport(TestCase):
mocked_manager = MagicMock() mocked_manager = MagicMock()
# WHEN: An importer object is created # WHEN: An importer object is created
importer = SongShowPlusImport(mocked_manager) importer = SongShowPlusImport(mocked_manager, filenames=[])
# THEN: The importer object should not be None # THEN: The importer object should not be None
self.assertIsNotNone(importer, 'Import should not be none') self.assertIsNotNone(importer, 'Import should not be none')
@ -85,7 +85,7 @@ class TestSongShowPlusImport(TestCase):
with patch('openlp.plugins.songs.lib.songshowplusimport.SongImport'): with patch('openlp.plugins.songs.lib.songshowplusimport.SongImport'):
mocked_manager = MagicMock() mocked_manager = MagicMock()
mocked_import_wizard = MagicMock() mocked_import_wizard = MagicMock()
importer = SongShowPlusImport(mocked_manager) importer = SongShowPlusImport(mocked_manager, filenames=[])
importer.import_wizard = mocked_import_wizard importer.import_wizard = mocked_import_wizard
importer.stop_import_flag = True importer.stop_import_flag = True
@ -106,7 +106,7 @@ class TestSongShowPlusImport(TestCase):
with patch('openlp.plugins.songs.lib.songshowplusimport.SongImport'): with patch('openlp.plugins.songs.lib.songshowplusimport.SongImport'):
mocked_manager = MagicMock() mocked_manager = MagicMock()
mocked_import_wizard = MagicMock() mocked_import_wizard = MagicMock()
importer = SongShowPlusImport(mocked_manager) importer = SongShowPlusImport(mocked_manager, filenames=[])
importer.import_wizard = mocked_import_wizard importer.import_wizard = mocked_import_wizard
importer.stop_import_flag = True importer.stop_import_flag = True
@ -126,7 +126,7 @@ class TestSongShowPlusImport(TestCase):
# GIVEN: A mocked out SongImport class, and a mocked out "manager" # GIVEN: A mocked out SongImport class, and a mocked out "manager"
with patch('openlp.plugins.songs.lib.songshowplusimport.SongImport'): with patch('openlp.plugins.songs.lib.songshowplusimport.SongImport'):
mocked_manager = MagicMock() mocked_manager = MagicMock()
importer = SongShowPlusImport(mocked_manager) importer = SongShowPlusImport(mocked_manager, filenames=[])
# WHEN: Supplied with the following arguments replicating verses being added # WHEN: Supplied with the following arguments replicating verses being added
test_values = [('Verse 1', VerseType.tags[VerseType.Verse] + '1'), test_values = [('Verse 1', VerseType.tags[VerseType.Verse] + '1'),
@ -153,7 +153,7 @@ class TestSongShowPlusImport(TestCase):
# GIVEN: A mocked out SongImport class, and a mocked out "manager" # GIVEN: A mocked out SongImport class, and a mocked out "manager"
with patch('openlp.plugins.songs.lib.songshowplusimport.SongImport'): with patch('openlp.plugins.songs.lib.songshowplusimport.SongImport'):
mocked_manager = MagicMock() mocked_manager = MagicMock()
importer = SongShowPlusImport(mocked_manager) importer = SongShowPlusImport(mocked_manager, filenames=[])
# WHEN: Supplied with the following arguments replicating a verse order being added # WHEN: Supplied with the following arguments replicating a verse order being added
test_values = [('Verse 1', VerseType.tags[VerseType.Verse] + '1'), test_values = [('Verse 1', VerseType.tags[VerseType.Verse] + '1'),

View File

@ -89,7 +89,7 @@ class SongImportTestHelper(TestCase):
""" """
Import the given file and check that it has imported correctly Import the given file and check that it has imported correctly
""" """
importer = self.importer_class(self.mocked_manager) importer = self.importer_class(self.mocked_manager, filenames=[source_file_name])
importer.import_wizard = self.mocked_import_wizard importer.import_wizard = self.mocked_import_wizard
importer.stop_import_flag = False importer.stop_import_flag = False
importer.topics = [] importer.topics = []