Merge lp:~phill-ridout/openlp/even-more-refactors into lp:openlp

Proposed by Phill
Status: Merged
Approved by: Tim Bentley
Approved revision: 2707
Merged at revision: 2696
Proposed branch: lp:~phill-ridout/openlp/even-more-refactors
Merge into: lp:openlp
Diff against target: 3154 lines (+1623/-771)
24 files modified
openlp/core/common/openlpmixin.py (+6/-0)
openlp/plugins/bibles/bibleplugin.py (+4/-4)
openlp/plugins/bibles/forms/bibleimportform.py (+24/-16)
openlp/plugins/bibles/lib/__init__.py (+2/-2)
openlp/plugins/bibles/lib/bibleimport.py (+150/-29)
openlp/plugins/bibles/lib/db.py (+2/-62)
openlp/plugins/bibles/lib/importers/csvbible.py (+15/-31)
openlp/plugins/bibles/lib/importers/opensong.py (+112/-95)
openlp/plugins/bibles/lib/importers/osis.py (+93/-97)
openlp/plugins/bibles/lib/importers/zefania.py (+4/-3)
openlp/plugins/bibles/lib/manager.py (+3/-3)
openlp/plugins/bibles/lib/upgrade.py (+2/-164)
tests/functional/openlp_core_ui/test_exceptionform.py (+1/-6)
tests/functional/openlp_plugins/bibles/test_bibleimport.py (+437/-34)
tests/functional/openlp_plugins/bibles/test_csvimport.py (+11/-77)
tests/functional/openlp_plugins/bibles/test_db.py (+1/-55)
tests/functional/openlp_plugins/bibles/test_opensongimport.py (+343/-31)
tests/functional/openlp_plugins/bibles/test_osisimport.py (+367/-14)
tests/functional/openlp_plugins/bibles/test_swordimport.py (+1/-1)
tests/functional/openlp_plugins/bibles/test_zefaniaimport.py (+5/-7)
tests/resources/bibles/dk1933.json (+10/-10)
tests/resources/bibles/kjv.json (+10/-10)
tests/resources/bibles/rst.json (+10/-10)
tests/resources/bibles/web.json (+10/-10)
To merge this branch: bzr merge lp:~phill-ridout/openlp/even-more-refactors
Reviewer Review Type Date Requested Status
Tim Bentley Approve
Tomas Groth Approve
Review via email: mp+305388@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Tim Bentley (trb143) wrote :

Sorry one small change needed.

review: Needs Fixing
Revision history for this message
Phill (phill-ridout) wrote :

> Sorry one small change needed.

Any chance you can let this one slide? I'm not going to be in a position to correct this for a week. I'll sort it in my next round of Bible refractors if that's ok with you? Unless tgc or superfly pick up on something else!

Revision history for this message
Tim Bentley (trb143) wrote :

Ok it was a real nit pick!

Revision history for this message
Tomas Groth (tomasgroth) :
review: Approve
Revision history for this message
Tim Bentley (trb143) wrote :

Adding approval

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'openlp/core/common/openlpmixin.py'
--- openlp/core/common/openlpmixin.py 2016-05-14 04:24:46 +0000
+++ openlp/core/common/openlpmixin.py 2016-09-09 21:59:44 +0000
@@ -71,6 +71,12 @@
71 """71 """
72 self.logger.info(message)72 self.logger.info(message)
7373
74 def log_warning(self, message):
75 """
76 Common log warning handler
77 """
78 self.logger.warning(message)
79
74 def log_error(self, message):80 def log_error(self, message):
75 """81 """
76 Common log error handler which prints the calling path82 Common log error handler which prints the calling path
7783
=== modified file 'openlp/plugins/bibles/bibleplugin.py'
--- openlp/plugins/bibles/bibleplugin.py 2016-08-08 18:11:32 +0000
+++ openlp/plugins/bibles/bibleplugin.py 2016-09-09 21:59:44 +0000
@@ -140,10 +140,10 @@
140140
141 def uses_theme(self, theme):141 def uses_theme(self, theme):
142 """142 """
143 Called to find out if the bible plugin is currently using a theme. Returns ``1`` if the theme is being used,143 Called to find out if the bible plugin is currently using a theme.
144 otherwise returns ``0``.
145144
146 :param theme: The theme145 :param theme: The theme
146 :return: 1 if the theme is being used, otherwise returns 0
147 """147 """
148 if str(self.settings_tab.bible_theme) == theme:148 if str(self.settings_tab.bible_theme) == theme:
149 return 1149 return 1
@@ -151,11 +151,11 @@
151151
152 def rename_theme(self, old_theme, new_theme):152 def rename_theme(self, old_theme, new_theme):
153 """153 """
154 Rename the theme the bible plugin is using making the plugin use the154 Rename the theme the bible plugin is using, making the plugin use the new name.
155 new name.
156155
157 :param old_theme: The name of the theme the plugin should stop using. Unused for this particular plugin.156 :param old_theme: The name of the theme the plugin should stop using. Unused for this particular plugin.
158 :param new_theme: The new name the plugin should now use.157 :param new_theme: The new name the plugin should now use.
158 :return: None
159 """159 """
160 self.settings_tab.bible_theme = new_theme160 self.settings_tab.bible_theme = new_theme
161 self.settings_tab.save()161 self.settings_tab.save()
162162
=== modified file 'openlp/plugins/bibles/forms/bibleimportform.py'
--- openlp/plugins/bibles/forms/bibleimportform.py 2016-08-09 20:45:25 +0000
+++ openlp/plugins/bibles/forms/bibleimportform.py 2016-09-09 21:59:44 +0000
@@ -25,6 +25,7 @@
25import logging25import logging
26import os26import os
27import urllib.error27import urllib.error
28from lxml import etree
2829
29from PyQt5 import QtWidgets30from PyQt5 import QtWidgets
30try:31try:
@@ -33,14 +34,15 @@
33except:34except:
34 PYSWORD_AVAILABLE = False35 PYSWORD_AVAILABLE = False
3536
36from openlp.core.common import AppLocation, Settings, UiStrings, translate, clean_filename37from openlp.core.common import AppLocation, Settings, UiStrings, trace_error_handler, translate
38from openlp.core.common.languagemanager import get_locale_key
37from openlp.core.lib.db import delete_database39from openlp.core.lib.db import delete_database
40from openlp.core.lib.exceptions import ValidationError
38from openlp.core.lib.ui import critical_error_message_box41from openlp.core.lib.ui import critical_error_message_box
39from openlp.core.ui.lib.wizard import OpenLPWizard, WizardStrings42from openlp.core.ui.lib.wizard import OpenLPWizard, WizardStrings
40from openlp.core.common.languagemanager import get_locale_key
41from openlp.plugins.bibles.lib.manager import BibleFormat
42from openlp.plugins.bibles.lib.db import clean_filename43from openlp.plugins.bibles.lib.db import clean_filename
43from openlp.plugins.bibles.lib.importers.http import CWExtract, BGExtract, BSExtract44from openlp.plugins.bibles.lib.importers.http import CWExtract, BGExtract, BSExtract
45from openlp.plugins.bibles.lib.manager import BibleFormat
4446
45log = logging.getLogger(__name__)47log = logging.getLogger(__name__)
4648
@@ -809,16 +811,22 @@
809 sword_path=self.field('sword_zip_path'),811 sword_path=self.field('sword_zip_path'),
810 sword_key=self.sword_zipbible_combo_box.itemData(812 sword_key=self.sword_zipbible_combo_box.itemData(
811 self.sword_zipbible_combo_box.currentIndex()))813 self.sword_zipbible_combo_box.currentIndex()))
812 if importer.do_import(license_version):814
813 self.manager.save_meta_data(license_version, license_version, license_copyright, license_permissions)815 try:
814 self.manager.reload_bibles()816 if importer.do_import(license_version) and not importer.stop_import_flag:
815 if bible_type == BibleFormat.WebDownload:817 self.manager.save_meta_data(license_version, license_version, license_copyright, license_permissions)
816 self.progress_label.setText(818 self.manager.reload_bibles()
817 translate('BiblesPlugin.ImportWizardForm', 'Registered Bible. Please note, that verses will be '819 if bible_type == BibleFormat.WebDownload:
818 'downloaded on demand and thus an internet connection is required.'))820 self.progress_label.setText(
819 else:821 translate('BiblesPlugin.ImportWizardForm', 'Registered Bible. Please note, that verses will be '
820 self.progress_label.setText(WizardStrings.FinishedImport)822 'downloaded on demand and thus an internet connection is required.'))
821 else:823 else:
822 self.progress_label.setText(translate('BiblesPlugin.ImportWizardForm', 'Your Bible import failed.'))824 self.progress_label.setText(WizardStrings.FinishedImport)
823 del self.manager.db_cache[importer.name]825 return
824 delete_database(self.plugin.settings_section, importer.file)826 except (AttributeError, ValidationError, etree.XMLSyntaxError):
827 log.exception('Importing bible failed')
828 trace_error_handler(log)
829
830 self.progress_label.setText(translate('BiblesPlugin.ImportWizardForm', 'Your Bible import failed.'))
831 del self.manager.db_cache[importer.name]
832 delete_database(self.plugin.settings_section, importer.file)
825833
=== modified file 'openlp/plugins/bibles/lib/__init__.py'
--- openlp/plugins/bibles/lib/__init__.py 2016-05-05 15:41:48 +0000
+++ openlp/plugins/bibles/lib/__init__.py 2016-09-09 21:59:44 +0000
@@ -173,7 +173,7 @@
173173
174def update_reference_separators():174def update_reference_separators():
175 """175 """
176 Updates separators and matches for parsing and formating scripture references.176 Updates separators and matches for parsing and formatting scripture references.
177 """177 """
178 default_separators = [178 default_separators = [
179 '|'.join([179 '|'.join([
@@ -215,7 +215,7 @@
215 # escape reserved characters215 # escape reserved characters
216 for character in '\\.^$*+?{}[]()':216 for character in '\\.^$*+?{}[]()':
217 source_string = source_string.replace(character, '\\' + character)217 source_string = source_string.replace(character, '\\' + character)
218 # add various unicode alternatives218 # add various Unicode alternatives
219 source_string = source_string.replace('-', '(?:[-\u00AD\u2010\u2011\u2012\u2014\u2014\u2212\uFE63\uFF0D])')219 source_string = source_string.replace('-', '(?:[-\u00AD\u2010\u2011\u2012\u2014\u2014\u2212\uFE63\uFF0D])')
220 source_string = source_string.replace(',', '(?:[,\u201A])')220 source_string = source_string.replace(',', '(?:[,\u201A])')
221 REFERENCE_SEPARATORS['sep_{role}'.format(role=role)] = '\s*(?:{source})\s*'.format(source=source_string)221 REFERENCE_SEPARATORS['sep_{role}'.format(role=role)] = '\s*(?:{source})\s*'.format(source=source_string)
222222
=== modified file 'openlp/plugins/bibles/lib/bibleimport.py'
--- openlp/plugins/bibles/lib/bibleimport.py 2016-08-09 19:32:29 +0000
+++ openlp/plugins/bibles/lib/bibleimport.py 2016-09-09 21:59:44 +0000
@@ -20,25 +20,84 @@
20# Temple Place, Suite 330, Boston, MA 02111-1307 USA #20# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
21###############################################################################21###############################################################################
2222
23import logging
24
25from lxml import etree, objectify23from lxml import etree, objectify
24from zipfile import is_zipfile
2625
27from openlp.core.common import OpenLPMixin, languages26from openlp.core.common import OpenLPMixin, Registry, RegistryProperties, languages, translate
28from openlp.core.lib import ValidationError27from openlp.core.lib import ValidationError
29from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB28from openlp.core.lib.ui import critical_error_message_box
3029from openlp.plugins.bibles.lib.db import AlternativeBookNamesDB, BibleDB, BiblesResourcesDB
31log = logging.getLogger(__name__)30
3231
3332class BibleImport(OpenLPMixin, RegistryProperties, BibleDB):
34class BibleImport(OpenLPMixin, BibleDB):
35 """33 """
36 Helper class to import bibles from a third party source into OpenLP34 Helper class to import bibles from a third party source into OpenLP
37 """35 """
38 # TODO: Test
39 def __init__(self, *args, **kwargs):36 def __init__(self, *args, **kwargs):
40 super().__init__(*args, **kwargs)37 super().__init__(*args, **kwargs)
41 self.filename = kwargs['filename'] if 'filename' in kwargs else None38 self.filename = kwargs['filename'] if 'filename' in kwargs else None
39 self.wizard = None
40 self.stop_import_flag = False
41 Registry().register_function('openlp_stop_wizard', self.stop_import)
42
43 @staticmethod
44 def is_compressed(file):
45 """
46 Check if the supplied file is compressed
47
48 :param file: A path to the file to check
49 """
50 if is_zipfile(file):
51 critical_error_message_box(
52 message=translate('BiblesPlugin.BibleImport',
53 'The file "{file}" you supplied is compressed. You must decompress it before import.'
54 ).format(file=file))
55 return True
56 return False
57
58 def get_book_ref_id_by_name(self, book, maxbooks=66, language_id=None):
59 """
60 Find the book id from the name or abbreviation of the book. If it doesn't currently exist, ask the user.
61
62 :param book: The name or abbreviation of the book
63 :param maxbooks: The number of books in the bible
64 :param language_id: The language_id of the bible
65 :return: The id of the bible, or None
66 """
67 self.log_debug('BibleDB.get_book_ref_id_by_name:("{book}", "{lang}")'.format(book=book, lang=language_id))
68 book_temp = BiblesResourcesDB.get_book(book, True)
69 if book_temp:
70 return book_temp['id']
71 book_id = BiblesResourcesDB.get_alternative_book_name(book)
72 if book_id:
73 return book_id
74 book_id = AlternativeBookNamesDB.get_book_reference_id(book)
75 if book_id:
76 return book_id
77 from openlp.plugins.bibles.forms import BookNameForm
78 book_name = BookNameForm(self.wizard)
79 if book_name.exec(book, self.get_books(), maxbooks) and book_name.book_id:
80 AlternativeBookNamesDB.create_alternative_book_name(book, book_name.book_id, language_id)
81 return book_name.book_id
82
83 def get_language(self, bible_name=None):
84 """
85 If no language is given it calls a dialog window where the user could select the bible language.
86 Return the language id of a bible.
87
88 :param bible_name: The language the bible is.
89 """
90 self.log_debug('BibleImpoer.get_language()')
91 from openlp.plugins.bibles.forms import LanguageForm
92 language_id = None
93 language_form = LanguageForm(self.wizard)
94 if language_form.exec(bible_name):
95 combo_box = language_form.language_combo_box
96 language_id = combo_box.itemData(combo_box.currentIndex())
97 if not language_id:
98 return None
99 self.save_meta('language_id', language_id)
100 return language_id
42101
43 def get_language_id(self, file_language=None, bible_name=None):102 def get_language_id(self, file_language=None, bible_name=None):
44 """103 """
@@ -58,8 +117,8 @@
58 language_id = self.get_language(bible_name)117 language_id = self.get_language(bible_name)
59 if not language_id:118 if not language_id:
60 # User cancelled get_language dialog119 # User cancelled get_language dialog
61 log.error('Language detection failed when importing from "{name}". User aborted language selection.'120 self.log_error('Language detection failed when importing from "{name}". User aborted language selection.'
62 .format(name=bible_name))121 .format(name=bible_name))
63 return None122 return None
64 self.save_meta('language_id', language_id)123 self.save_meta('language_id', language_id)
65 return language_id124 return language_id
@@ -77,7 +136,7 @@
77 if name:136 if name:
78 book_ref_id = self.get_book_ref_id_by_name(name, no_of_books, language_id)137 book_ref_id = self.get_book_ref_id_by_name(name, no_of_books, language_id)
79 else:138 else:
80 log.debug('No book name supplied. Falling back to guess_id')139 self.log_debug('No book name supplied. Falling back to guess_id')
81 book_ref_id = guess_id140 book_ref_id = guess_id
82 if not book_ref_id:141 if not book_ref_id:
83 raise ValidationError(msg='Could not resolve book_ref_id in "{}"'.format(self.filename))142 raise ValidationError(msg='Could not resolve book_ref_id in "{}"'.format(self.filename))
@@ -87,8 +146,7 @@
87 'importing {file}'.format(book_ref=book_ref_id, file=self.filename))146 'importing {file}'.format(book_ref=book_ref_id, file=self.filename))
88 return self.create_book(name, book_ref_id, book_details['testament_id'])147 return self.create_book(name, book_ref_id, book_details['testament_id'])
89148
90 @staticmethod149 def parse_xml(self, filename, use_objectify=False, elements=None, tags=None):
91 def parse_xml(filename, use_objectify=False, elements=None, tags=None):
92 """150 """
93 Parse and clean the supplied file by removing any elements or tags we don't use.151 Parse and clean the supplied file by removing any elements or tags we don't use.
94 :param filename: The filename of the xml file to parse. Str152 :param filename: The filename of the xml file to parse. Str
@@ -97,17 +155,80 @@
97 :param tags: A tuple of element names (Str) to remove, preserving their content.155 :param tags: A tuple of element names (Str) to remove, preserving their content.
98 :return: The root element of the xml document156 :return: The root element of the xml document
99 """157 """
100 with open(filename, 'rb') as import_file:158 try:
101 # NOTE: We don't need to do any of the normal encoding detection here, because lxml does it's own encoding159 with open(filename, 'rb') as import_file:
102 # detection, and the two mechanisms together interfere with each other.160 # NOTE: We don't need to do any of the normal encoding detection here, because lxml does it's own
103 if not use_objectify:161 # encoding detection, and the two mechanisms together interfere with each other.
104 tree = etree.parse(import_file, parser=etree.XMLParser(recover=True))162 if not use_objectify:
105 else:163 tree = etree.parse(import_file, parser=etree.XMLParser(recover=True))
106 tree = objectify.parse(import_file, parser=objectify.makeparser(recover=True))164 else:
107 if elements:165 tree = objectify.parse(import_file, parser=objectify.makeparser(recover=True))
108 # Strip tags we don't use - remove content166 if elements or tags:
109 etree.strip_elements(tree, elements, with_tail=False)167 self.wizard.increment_progress_bar(
110 if tags:168 translate('BiblesPlugin.OsisImport', 'Removing unused tags (this may take a few minutes)...'))
111 # Strip tags we don't use - keep content169 if elements:
112 etree.strip_tags(tree, tags)170 # Strip tags we don't use - remove content
113 return tree.getroot()171 etree.strip_elements(tree, elements, with_tail=False)
172 if tags:
173 # Strip tags we don't use - keep content
174 etree.strip_tags(tree, tags)
175 return tree.getroot()
176 except OSError as e:
177 self.log_exception('Opening {file_name} failed.'.format(file_name=e.filename))
178 critical_error_message_box(
179 title='An Error Occured When Opening A File',
180 message='The following error occurred when trying to open\n{file_name}:\n\n{error}'
181 .format(file_name=e.filename, error=e.strerror))
182 return None
183
184 def register(self, wizard):
185 """
186 This method basically just initialises the database. It is called from the Bible Manager when a Bible is
187 imported. Descendant classes may want to override this method to supply their own custom
188 initialisation as well.
189
190 :param wizard: The actual Qt wizard form.
191 """
192 self.wizard = wizard
193 return self.name
194
195 def set_current_chapter(self, book_name, chapter_name):
196 self.wizard.increment_progress_bar(translate('BiblesPlugin.OsisImport', 'Importing {book} {chapter}...')
197 .format(book=book_name, chapter=chapter_name))
198
199 def stop_import(self):
200 """
201 Stops the import of the Bible.
202 """
203 self.log_debug('Stopping import')
204 self.stop_import_flag = True
205
206 def validate_xml_file(self, filename, tag):
207 """
208 Validate the supplied file
209
210 :param filename: The supplied file
211 :param tag: The expected root tag type
212 :return: True if valid. ValidationError is raised otherwise.
213 """
214 if BibleImport.is_compressed(filename):
215 raise ValidationError(msg='Compressed file')
216 bible = self.parse_xml(filename, use_objectify=True)
217 if bible is None:
218 raise ValidationError(msg='Error when opening file')
219 root_tag = bible.tag.lower()
220 bible_type = translate('BiblesPlugin.BibleImport', 'unknown type of',
221 'This looks like an unknown type of XML bible.')
222 if root_tag == tag:
223 return True
224 elif root_tag == 'bible':
225 bible_type = "OpenSong"
226 elif root_tag == '{http://www.bibletechnologies.net/2003/osis/namespace}osis':
227 bible_type = 'OSIS'
228 elif root_tag == 'xmlbible':
229 bible_type = 'Zefania'
230 critical_error_message_box(
231 message=translate('BiblesPlugin.BibleImport',
232 'Incorrect Bible file type supplied. This looks like an {bible_type} XML bible.'
233 .format(bible_type=bible_type)))
234 raise ValidationError(msg='Invalid xml.')
114235
=== modified file 'openlp/plugins/bibles/lib/db.py'
--- openlp/plugins/bibles/lib/db.py 2016-08-07 10:15:43 +0000
+++ openlp/plugins/bibles/lib/db.py 2016-09-09 21:59:44 +0000
@@ -33,7 +33,7 @@
33from sqlalchemy.orm import class_mapper, mapper, relation33from sqlalchemy.orm import class_mapper, mapper, relation
34from sqlalchemy.orm.exc import UnmappedClassError34from sqlalchemy.orm.exc import UnmappedClassError
3535
36from openlp.core.common import Registry, RegistryProperties, AppLocation, translate, clean_filename36from openlp.core.common import AppLocation, translate, clean_filename
37from openlp.core.lib.db import BaseModel, init_db, Manager37from openlp.core.lib.db import BaseModel, init_db, Manager
38from openlp.core.lib.ui import critical_error_message_box38from openlp.core.lib.ui import critical_error_message_box
39from openlp.plugins.bibles.lib import upgrade39from openlp.plugins.bibles.lib import upgrade
@@ -106,7 +106,7 @@
106 return session106 return session
107107
108108
109class BibleDB(Manager, RegistryProperties):109class BibleDB(Manager):
110 """110 """
111 This class represents a database-bound Bible. It is used as a base class for all the custom importers, so that111 This class represents a database-bound Bible. It is used as a base class for all the custom importers, so that
112 the can implement their own import methods, but benefit from the database methods in here via inheritance,112 the can implement their own import methods, but benefit from the database methods in here via inheritance,
@@ -140,7 +140,6 @@
140 raise KeyError('Missing keyword argument "path".')140 raise KeyError('Missing keyword argument "path".')
141 if 'name' not in kwargs and 'file' not in kwargs:141 if 'name' not in kwargs and 'file' not in kwargs:
142 raise KeyError('Missing keyword argument "name" or "file".')142 raise KeyError('Missing keyword argument "name" or "file".')
143 self.stop_import_flag = False
144 if 'name' in kwargs:143 if 'name' in kwargs:
145 self.name = kwargs['name']144 self.name = kwargs['name']
146 if not isinstance(self.name, str):145 if not isinstance(self.name, str):
@@ -153,15 +152,6 @@
153 self.get_name()152 self.get_name()
154 if 'path' in kwargs:153 if 'path' in kwargs:
155 self.path = kwargs['path']154 self.path = kwargs['path']
156 self.wizard = None
157 Registry().register_function('openlp_stop_wizard', self.stop_import)
158
159 def stop_import(self):
160 """
161 Stops the import of the Bible.
162 """
163 log.debug('Stopping import')
164 self.stop_import_flag = True
165155
166 def get_name(self):156 def get_name(self):
167 """157 """
@@ -171,17 +161,6 @@
171 self.name = version_name.value if version_name else None161 self.name = version_name.value if version_name else None
172 return self.name162 return self.name
173163
174 def register(self, wizard):
175 """
176 This method basically just initialises the database. It is called from the Bible Manager when a Bible is
177 imported. Descendant classes may want to override this method to supply their own custom
178 initialisation as well.
179
180 :param wizard: The actual Qt wizard form.
181 """
182 self.wizard = wizard
183 return self.name
184
185 def create_book(self, name, bk_ref_id, testament=1):164 def create_book(self, name, bk_ref_id, testament=1):
186 """165 """
187 Add a book to the database.166 Add a book to the database.
@@ -306,26 +285,6 @@
306 log.debug('BibleDB.get_book_by_book_ref_id("{ref}")'.format(ref=ref_id))285 log.debug('BibleDB.get_book_by_book_ref_id("{ref}")'.format(ref=ref_id))
307 return self.get_object_filtered(Book, Book.book_reference_id.like(ref_id))286 return self.get_object_filtered(Book, Book.book_reference_id.like(ref_id))
308287
309 def get_book_ref_id_by_name(self, book, maxbooks, language_id=None):
310 log.debug('BibleDB.get_book_ref_id_by_name:("{book}", "{lang}")'.format(book=book, lang=language_id))
311 book_id = None
312 if BiblesResourcesDB.get_book(book, True):
313 book_temp = BiblesResourcesDB.get_book(book, True)
314 book_id = book_temp['id']
315 elif BiblesResourcesDB.get_alternative_book_name(book):
316 book_id = BiblesResourcesDB.get_alternative_book_name(book)
317 elif AlternativeBookNamesDB.get_book_reference_id(book):
318 book_id = AlternativeBookNamesDB.get_book_reference_id(book)
319 else:
320 from openlp.plugins.bibles.forms import BookNameForm
321 book_name = BookNameForm(self.wizard)
322 if book_name.exec(book, self.get_books(), maxbooks):
323 book_id = book_name.book_id
324 if book_id:
325 AlternativeBookNamesDB.create_alternative_book_name(
326 book, book_id, language_id)
327 return book_id
328
329 def get_book_ref_id_by_localised_name(self, book, language_selection):288 def get_book_ref_id_by_localised_name(self, book, language_selection):
330 """289 """
331 Return the id of a named book.290 Return the id of a named book.
@@ -462,25 +421,6 @@
462 return 0421 return 0
463 return count422 return count
464423
465 def get_language(self, bible_name=None):
466 """
467 If no language is given it calls a dialog window where the user could select the bible language.
468 Return the language id of a bible.
469
470 :param bible_name: The language the bible is.
471 """
472 log.debug('BibleDB.get_language()')
473 from openlp.plugins.bibles.forms import LanguageForm
474 language_id = None
475 language_form = LanguageForm(self.wizard)
476 if language_form.exec(bible_name):
477 combo_box = language_form.language_combo_box
478 language_id = combo_box.itemData(combo_box.currentIndex())
479 if not language_id:
480 return None
481 self.save_meta('language_id', language_id)
482 return language_id
483
484 def dump_bible(self):424 def dump_bible(self):
485 """425 """
486 Utility debugging method to dump the contents of a bible.426 Utility debugging method to dump the contents of a bible.
487427
=== modified file 'openlp/plugins/bibles/lib/importers/csvbible.py'
--- openlp/plugins/bibles/lib/importers/csvbible.py 2016-08-09 20:45:25 +0000
+++ openlp/plugins/bibles/lib/importers/csvbible.py 2016-09-09 21:59:44 +0000
@@ -50,7 +50,6 @@
50All CSV files are expected to use a comma (',') as the delimiter and double quotes ('"') as the quote symbol.50All CSV files are expected to use a comma (',') as the delimiter and double quotes ('"') as the quote symbol.
51"""51"""
52import csv52import csv
53import logging
54from collections import namedtuple53from collections import namedtuple
5554
56from openlp.core.common import get_file_encoding, translate55from openlp.core.common import get_file_encoding, translate
@@ -58,8 +57,6 @@
58from openlp.plugins.bibles.lib.bibleimport import BibleImport57from openlp.plugins.bibles.lib.bibleimport import BibleImport
5958
6059
61log = logging.getLogger(__name__)
62
63Book = namedtuple('Book', 'id, testament_id, name, abbreviation')60Book = namedtuple('Book', 'id, testament_id, name, abbreviation')
64Verse = namedtuple('Verse', 'book_id_name, chapter_number, number, text')61Verse = namedtuple('Verse', 'book_id_name, chapter_number, number, text')
6562
@@ -68,15 +65,13 @@
68 """65 """
69 This class provides a specialisation for importing of CSV Bibles.66 This class provides a specialisation for importing of CSV Bibles.
70 """67 """
71 log.info('CSVBible loaded')
72
73 def __init__(self, *args, **kwargs):68 def __init__(self, *args, **kwargs):
74 """69 """
75 Loads a Bible from a set of CSV files. This class assumes the files contain all the information and a clean70 Loads a Bible from a set of CSV files. This class assumes the files contain all the information and a clean
76 bible is being loaded.71 bible is being loaded.
77 """72 """
78 log.info(self.__class__.__name__)
79 super().__init__(*args, **kwargs)73 super().__init__(*args, **kwargs)
74 self.log_info(self.__class__.__name__)
80 self.books_file = kwargs['booksfile']75 self.books_file = kwargs['booksfile']
81 self.verses_file = kwargs['versefile']76 self.verses_file = kwargs['versefile']
8277
@@ -123,12 +118,11 @@
123 number_of_books = len(books)118 number_of_books = len(books)
124 for book in books:119 for book in books:
125 if self.stop_import_flag:120 if self.stop_import_flag:
126 return None121 break
127 self.wizard.increment_progress_bar(122 self.wizard.increment_progress_bar(
128 translate('BiblesPlugin.CSVBible', 'Importing books... {book}').format(book=book.name))123 translate('BiblesPlugin.CSVBible', 'Importing books... {book}').format(book=book.name))
129 self.find_and_create_book(book.name, number_of_books, self.language_id)124 self.find_and_create_book(book.name, number_of_books, self.language_id)
130 book_list.update({int(book.id): book.name})125 book_list.update({int(book.id): book.name})
131 self.application.process_events()
132 return book_list126 return book_list
133127
134 def process_verses(self, verses, books):128 def process_verses(self, verses, books):
@@ -142,7 +136,7 @@
142 book_ptr = None136 book_ptr = None
143 for verse in verses:137 for verse in verses:
144 if self.stop_import_flag:138 if self.stop_import_flag:
145 return None139 break
146 verse_book = self.get_book_name(verse.book_id_name, books)140 verse_book = self.get_book_name(verse.book_id_name, books)
147 if book_ptr != verse_book:141 if book_ptr != verse_book:
148 book = self.get_book(verse_book)142 book = self.get_book(verse_book)
@@ -151,9 +145,7 @@
151 translate('BiblesPlugin.CSVBible', 'Importing verses from {book}...',145 translate('BiblesPlugin.CSVBible', 'Importing verses from {book}...',
152 'Importing verses from <book name>...').format(book=book.name))146 'Importing verses from <book name>...').format(book=book.name))
153 self.session.commit()147 self.session.commit()
154 self.create_verse(book.id, verse.chapter_number, verse.number, verse.text)148 self.create_verse(book.id, int(verse.chapter_number), int(verse.number), verse.text)
155 self.wizard.increment_progress_bar(translate('BiblesPlugin.CSVBible', 'Importing verses... done.'))
156 self.application.process_events()
157 self.session.commit()149 self.session.commit()
158150
159 def do_import(self, bible_name=None):151 def do_import(self, bible_name=None):
@@ -163,24 +155,16 @@
163 :param bible_name: Optional name of the bible being imported. Str or None155 :param bible_name: Optional name of the bible being imported. Str or None
164 :return: True if the import was successful, False if it failed or was cancelled156 :return: True if the import was successful, False if it failed or was cancelled
165 """157 """
166 try:158 self.language_id = self.get_language(bible_name)
167 self.language_id = self.get_language(bible_name)159 if not self.language_id:
168 if not self.language_id:
169 raise ValidationError(msg='Invalid language selected')
170 books = self.parse_csv_file(self.books_file, Book)
171 self.wizard.progress_bar.setValue(0)
172 self.wizard.progress_bar.setMinimum(0)
173 self.wizard.progress_bar.setMaximum(len(books))
174 book_list = self.process_books(books)
175 if self.stop_import_flag:
176 return False
177 verses = self.parse_csv_file(self.verses_file, Verse)
178 self.wizard.progress_bar.setValue(0)
179 self.wizard.progress_bar.setMaximum(len(books) + 1)
180 self.process_verses(verses, book_list)
181 if self.stop_import_flag:
182 return False
183 except ValidationError:
184 log.exception('Could not import CSV bible')
185 return False160 return False
161 books = self.parse_csv_file(self.books_file, Book)
162 self.wizard.progress_bar.setValue(0)
163 self.wizard.progress_bar.setMinimum(0)
164 self.wizard.progress_bar.setMaximum(len(books))
165 book_list = self.process_books(books)
166 verses = self.parse_csv_file(self.verses_file, Verse)
167 self.wizard.progress_bar.setValue(0)
168 self.wizard.progress_bar.setMaximum(len(books) + 1)
169 self.process_verses(verses, book_list)
186 return True170 return True
187171
=== modified file 'openlp/plugins/bibles/lib/importers/opensong.py'
--- openlp/plugins/bibles/lib/importers/opensong.py 2016-08-09 20:45:25 +0000
+++ openlp/plugins/bibles/lib/importers/opensong.py 2016-09-09 21:59:44 +0000
@@ -20,109 +20,126 @@
20# Temple Place, Suite 330, Boston, MA 02111-1307 USA #20# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
21###############################################################################21###############################################################################
2222
23import logging
24from lxml import etree, objectify
25
26from openlp.core.common import translate, trace_error_handler
27from openlp.core.lib.ui import critical_error_message_box
28from openlp.plugins.bibles.lib.bibleimport import BibleImport23from openlp.plugins.bibles.lib.bibleimport import BibleImport
29from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB24
3025
3126def get_text(element):
32log = logging.getLogger(__name__)27 """
28 Recursively get all text in an objectify element and its child elements.
29
30 :param element: An objectify element to get the text from
31 :return: The text content of the element (str)
32 """
33 verse_text = ''
34 if element.text:
35 verse_text = element.text
36 for sub_element in element.iterchildren():
37 verse_text += get_text(sub_element)
38 if element.tail:
39 verse_text += element.tail
40 return verse_text
41
42
43def parse_chapter_number(number, previous_number):
44 """
45 Parse the chapter number
46
47 :param number: The raw data from the xml
48 :param previous_number: The previous chapter number
49 :return: Number of current chapter. (Int)
50 """
51 if number:
52 return int(number.split()[-1])
53 return previous_number + 1
3354
3455
35class OpenSongBible(BibleImport):56class OpenSongBible(BibleImport):
36 """57 """
37 OpenSong Bible format importer class. This class is used to import Bibles from OpenSong's XML format.58 OpenSong Bible format importer class. This class is used to import Bibles from OpenSong's XML format.
38 """59 """
39 def get_text(self, element):60
40 """61 def parse_verse_number(self, number, previous_number):
41 Recursively get all text in an objectify element and its child elements.62 """
4263 Parse the verse number retrieved from the xml
43 :param element: An objectify element to get the text from64
44 """65 :param number: The raw data from the xml
45 verse_text = ''66 :param previous_number: The previous verse number
46 if element.text:67 :return: Number of current verse. (Int)
47 verse_text = element.text68 """
48 for sub_element in element.iterchildren():69 if not number:
49 verse_text += self.get_text(sub_element)70 return previous_number + 1
50 if element.tail:71 try:
51 verse_text += element.tail72 return int(number)
52 return verse_text73 except ValueError:
74 verse_parts = number.split('-')
75 if len(verse_parts) > 1:
76 number = int(verse_parts[0])
77 return number
78 except TypeError:
79 self.log_warning('Illegal verse number: {verse_no}'.format(verse_no=str(number)))
80 return previous_number + 1
81
82 def process_books(self, books):
83 """
84 Extract and create the books from the objectified xml
85
86 :param books: Objectified xml
87 :return: None
88 """
89 for book in books:
90 if self.stop_import_flag:
91 break
92 db_book = self.find_and_create_book(str(book.attrib['n']), len(books), self.language_id)
93 self.process_chapters(db_book, book.c)
94 self.session.commit()
95
96 def process_chapters(self, book, chapters):
97 """
98 Extract and create the chapters from the objectified xml for the book `book`
99
100 :param book: A database Book object to add the chapters to
101 :param chapters: Objectified xml containing chapters
102 :return: None
103 """
104 chapter_number = 0
105 for chapter in chapters:
106 if self.stop_import_flag:
107 break
108 chapter_number = parse_chapter_number(chapter.attrib['n'], chapter_number)
109 self.set_current_chapter(book.name, chapter_number)
110 self.process_verses(book, chapter_number, chapter.v)
111
112 def process_verses(self, book, chapter_number, verses):
113 """
114 Extract and create the verses from the objectified xml
115
116 :param book: A database Book object
117 :param chapter_number: The chapter number to add the verses to (int)
118 :param verses: Objectified xml containing verses
119 :return: None
120 """
121 verse_number = 0
122 for verse in verses:
123 if self.stop_import_flag:
124 break
125 verse_number = self.parse_verse_number(verse.attrib['n'], verse_number)
126 self.create_verse(book.id, chapter_number, verse_number, get_text(verse))
53127
54 def do_import(self, bible_name=None):128 def do_import(self, bible_name=None):
55 """129 """
56 Loads a Bible from file.130 Loads an Open Song Bible from a file.
131
132 :param bible_name: The name of the bible being imported
133 :return: True if import completed, False if import was unsuccessful
57 """134 """
58 log.debug('Starting OpenSong import from "{name}"'.format(name=self.filename))135 self.log_debug('Starting OpenSong import from "{name}"'.format(name=self.filename))
59 success = True136 self.validate_xml_file(self.filename, 'bible')
60 try:137 bible = self.parse_xml(self.filename, use_objectify=True)
61 bible = self.parse_xml(self.filename, use_objectify=True)138 if bible is None:
62 # Check that we're not trying to import a Zefania XML bible, it is sometimes refered to as 'OpenSong'139 return False
63 if bible.tag.upper() == 'XMLBIBLE':140 # No language info in the opensong format, so ask the user
64 critical_error_message_box(141 self.language_id = self.get_language_id(bible_name=self.filename)
65 message=translate('BiblesPlugin.OpenSongImport',142 if not self.language_id:
66 'Incorrect Bible file type supplied. This looks like a Zefania XML bible, '143 return False
67 'please use the Zefania import option.'))144 self.process_books(bible.b)
68 return False145 return True
69 # No language info in the opensong format, so ask the user
70 language_id = self.get_language_id(bible_name=self.filename)
71 if not language_id:
72 return False
73 for book in bible.b:
74 if self.stop_import_flag:
75 break
76 book_ref_id = self.get_book_ref_id_by_name(str(book.attrib['n']), len(bible.b), language_id)
77 if not book_ref_id:
78 log.error('Importing books from "{name}" failed'.format(name=self.filename))
79 return False
80 book_details = BiblesResourcesDB.get_book_by_id(book_ref_id)
81 db_book = self.create_book(book.attrib['n'], book_ref_id, book_details['testament_id'])
82 chapter_number = 0
83 for chapter in book.c:
84 if self.stop_import_flag:
85 break
86 number = chapter.attrib['n']
87 if number:
88 chapter_number = int(number.split()[-1])
89 else:
90 chapter_number += 1
91 verse_number = 0
92 for verse in chapter.v:
93 if self.stop_import_flag:
94 break
95 number = verse.attrib['n']
96 if number:
97 try:
98 number = int(number)
99 except ValueError:
100 verse_parts = number.split('-')
101 if len(verse_parts) > 1:
102 number = int(verse_parts[0])
103 except TypeError:
104 log.warning('Illegal verse number: {verse:d}'.format(verse=verse.attrib['n']))
105 verse_number = number
106 else:
107 verse_number += 1
108 self.create_verse(db_book.id, chapter_number, verse_number, self.get_text(verse))
109 self.wizard.increment_progress_bar(translate('BiblesPlugin.Opensong',
110 'Importing {name} {chapter}...'
111 ).format(name=db_book.name, chapter=chapter_number))
112 self.session.commit()
113 self.application.process_events()
114 except etree.XMLSyntaxError as inst:
115 trace_error_handler(log)
116 critical_error_message_box(
117 message=translate('BiblesPlugin.OpenSongImport',
118 'Incorrect Bible file type supplied. OpenSong Bibles may be '
119 'compressed. You must decompress them before import.'))
120 log.exception(inst)
121 success = False
122 except (IOError, AttributeError):
123 log.exception('Loading Bible from OpenSong file failed')
124 success = False
125 if self.stop_import_flag:
126 return False
127 else:
128 return success
129146
=== modified file 'openlp/plugins/bibles/lib/importers/osis.py'
--- openlp/plugins/bibles/lib/importers/osis.py 2016-08-10 19:08:09 +0000
+++ openlp/plugins/bibles/lib/importers/osis.py 2016-09-09 21:59:44 +0000
@@ -20,15 +20,9 @@
20# Temple Place, Suite 330, Boston, MA 02111-1307 USA #20# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
21###############################################################################21###############################################################################
2222
23import logging
24from lxml import etree23from lxml import etree
2524
26from openlp.core.common import translate, trace_error_handler
27from openlp.core.lib.ui import critical_error_message_box
28from openlp.plugins.bibles.lib.bibleimport import BibleImport25from openlp.plugins.bibles.lib.bibleimport import BibleImport
29from openlp.plugins.bibles.lib.db import BiblesResourcesDB
30
31log = logging.getLogger(__name__)
3226
33NS = {'ns': 'http://www.bibletechnologies.net/2003/OSIS/namespace'}27NS = {'ns': 'http://www.bibletechnologies.net/2003/OSIS/namespace'}
34# Tags we don't use and can remove the content28# Tags we don't use and can remove the content
@@ -74,104 +68,106 @@
74 '{http://www.bibletechnologies.net/2003/OSIS/namespace}caption'68 '{http://www.bibletechnologies.net/2003/OSIS/namespace}caption'
75)69)
7670
7771# Precompile a few xpath-querys
78def replacement(match):72verse_in_chapter = etree.XPath('//ns:chapter[1]/ns:verse', namespaces=NS)
79 return match.group(2).upper()73text_in_verse = etree.XPath('//ns:verse[1]/text()', namespaces=NS)
8074
8175
82class OSISBible(BibleImport):76class OSISBible(BibleImport):
83 """77 """
84 `OSIS <http://www.bibletechnologies.net/>`_ Bible format importer class.78 `OSIS <http://www.bibletechnologies.net/>`_ Bible format importer class.
85 """79 """
80 def process_books(self, bible_data):
81 """
82 Extract and create the bible books from the parsed xml
83
84 :param bible_data: parsed xml
85 :return: None
86 """
87 # Find books in the bible
88 bible_books = bible_data.xpath("//ns:div[@type='book']", namespaces=NS)
89 no_of_books = len(bible_books)
90 for book in bible_books:
91 if self.stop_import_flag:
92 break
93 # Remove div-tags in the book
94 etree.strip_tags(book, '{http://www.bibletechnologies.net/2003/OSIS/namespace}div')
95 db_book = self.find_and_create_book(book.get('osisID'), no_of_books, self.language_id)
96 self.process_chapters(db_book, book)
97 self.session.commit()
98
99 def process_chapters(self, book, chapters):
100 """
101 Extract the chapters, and do some initial processing of the verses
102
103 :param book: An OpenLP bible database book object
104 :param chapters: parsed chapters
105 :return: None
106 """
107 # Find out if chapter-tags contains the verses, or if it is used as milestone/anchor
108 if verse_in_chapter(chapters):
109 # The chapter tags contains the verses
110 for chapter in chapters:
111 chapter_number = int(chapter.get("osisID").split('.')[1])
112 self.set_current_chapter(book.name, chapter_number)
113 # Find out if verse-tags contains the text, or if it is used as milestone/anchor
114 if not text_in_verse(chapter):
115 # verse-tags are used as milestone
116 for verse in chapter:
117 # If this tag marks the start of a verse, the verse text is between this tag and
118 # the next tag, which the "tail" attribute gives us.
119 self.process_verse(book, chapter_number, verse, use_milestones=True)
120 else:
121 # Verse-tags contains the text
122 for verse in chapter:
123 self.process_verse(book, chapter_number, verse)
124 else:
125 # The chapter tags is used as milestones. For now we assume verses is also milestones
126 chapter_number = 0
127 for element in chapters:
128 if element.tag == '{http://www.bibletechnologies.net/2003/OSIS/namespace}chapter' \
129 and element.get('sID'):
130 chapter_number = int(element.get("osisID").split('.')[1])
131 self.set_current_chapter(book.name, chapter_number)
132 elif element.tag == '{http://www.bibletechnologies.net/2003/OSIS/namespace}verse':
133 # If this tag marks the start of a verse, the verse text is between this tag and
134 # the next tag, which the "tail" attribute gives us.
135 self.process_verse(book, chapter_number, element, use_milestones=True)
136
137 def process_verse(self, book, chapter_number, element, use_milestones=False):
138 """
139 Process a verse element
140 :param book: A database Book object
141 :param chapter_number: The chapter number to add the verses to (int)
142 :param element: The verse element to process. (etree element type)
143 :param use_milestones: set to True to process a 'milestone' verse. Defaults to False
144 :return: None
145 """
146 osis_id = element.get("osisID")
147 if not osis_id:
148 return None
149 verse_number = int(osis_id.split('.')[2])
150 verse_text = ''
151 if use_milestones and element.get('sID'):
152 verse_text = element.tail
153 elif not use_milestones:
154 verse_text = element.text
155 if verse_text:
156 self.create_verse(book.id, chapter_number, verse_number, verse_text.strip())
157
86 def do_import(self, bible_name=None):158 def do_import(self, bible_name=None):
87 """159 """
88 Loads a Bible from file.160 Loads a Bible from file.
89 """161 """
90 log.debug('Starting OSIS import from "{name}"'.format(name=self.filename))162 self.log_debug('Starting OSIS import from "{name}"'.format(name=self.filename))
91 success = True163 self.validate_xml_file(self.filename, '{http://www.bibletechnologies.net/2003/osis/namespace}osis')
92 try:164 bible = self.parse_xml(self.filename, elements=REMOVABLE_ELEMENTS, tags=REMOVABLE_TAGS)
93 self.wizard.increment_progress_bar(translate('BiblesPlugin.OsisImport',165 if bible is None:
94 'Removing unused tags (this may take a few minutes)...'))166 return False
95 osis_bible_tree = self.parse_xml(self.filename, elements=REMOVABLE_ELEMENTS, tags=REMOVABLE_TAGS)167 # Find bible language
96 # Find bible language]168 language = bible.xpath("//ns:osisText/@xml:lang", namespaces=NS)
97 language = osis_bible_tree.xpath("//ns:osisText/@xml:lang", namespaces=NS)169 self.language_id = self.get_language_id(language[0] if language else None, bible_name=self.filename)
98 language_id = self.get_language_id(language[0] if language else None, bible_name=self.filename)170 if not self.language_id:
99 if not language_id:171 return False
100 return False172 self.process_books(bible)
101 num_books = int(osis_bible_tree.xpath("count(//ns:div[@type='book'])", namespaces=NS))173 return True
102 # Precompile a few xpath-querys
103 verse_in_chapter = etree.XPath('count(//ns:chapter[1]/ns:verse)', namespaces=NS)
104 text_in_verse = etree.XPath('count(//ns:verse[1]/text())', namespaces=NS)
105 # Find books in the bible
106 bible_books = osis_bible_tree.xpath("//ns:div[@type='book']", namespaces=NS)
107 for book in bible_books:
108 if self.stop_import_flag:
109 break
110 # Remove div-tags in the book
111 etree.strip_tags(book, ('{http://www.bibletechnologies.net/2003/OSIS/namespace}div'))
112 book_ref_id = self.get_book_ref_id_by_name(book.get('osisID'), num_books, language_id)
113 if not book_ref_id:
114 log.error('Importing books from "{name}" failed'.format(name=self.filename))
115 return False
116 book_details = BiblesResourcesDB.get_book_by_id(book_ref_id)
117 db_book = self.create_book(book_details['name'], book_ref_id, book_details['testament_id'])
118 # Find out if chapter-tags contains the verses, or if it is used as milestone/anchor
119 if int(verse_in_chapter(book)) > 0:
120 # The chapter tags contains the verses
121 for chapter in book:
122 chapter_number = chapter.get("osisID").split('.')[1]
123 # Find out if verse-tags contains the text, or if it is used as milestone/anchor
124 if int(text_in_verse(chapter)) == 0:
125 # verse-tags are used as milestone
126 for verse in chapter:
127 # If this tag marks the start of a verse, the verse text is between this tag and
128 # the next tag, which the "tail" attribute gives us.
129 if verse.get('sID'):
130 verse_number = verse.get("osisID").split('.')[2]
131 verse_text = verse.tail
132 if verse_text:
133 self.create_verse(db_book.id, chapter_number, verse_number, verse_text.strip())
134 else:
135 # Verse-tags contains the text
136 for verse in chapter:
137 verse_number = verse.get("osisID").split('.')[2]
138 if verse.text:
139 self.create_verse(db_book.id, chapter_number, verse_number, verse.text.strip())
140 self.wizard.increment_progress_bar(
141 translate('BiblesPlugin.OsisImport', 'Importing %(bookname)s %(chapter)s...') %
142 {'bookname': db_book.name, 'chapter': chapter_number})
143 else:
144 # The chapter tags is used as milestones. For now we assume verses is also milestones
145 chapter_number = 0
146 for element in book:
147 if element.tag == '{http://www.bibletechnologies.net/2003/OSIS/namespace}chapter' \
148 and element.get('sID'):
149 chapter_number = element.get("osisID").split('.')[1]
150 self.wizard.increment_progress_bar(
151 translate('BiblesPlugin.OsisImport', 'Importing %(bookname)s %(chapter)s...') %
152 {'bookname': db_book.name, 'chapter': chapter_number})
153 elif element.tag == '{http://www.bibletechnologies.net/2003/OSIS/namespace}verse' \
154 and element.get('sID'):
155 # If this tag marks the start of a verse, the verse text is between this tag and
156 # the next tag, which the "tail" attribute gives us.
157 verse_number = element.get("osisID").split('.')[2]
158 verse_text = element.tail
159 if verse_text:
160 self.create_verse(db_book.id, chapter_number, verse_number, verse_text.strip())
161 self.session.commit()
162 self.application.process_events()
163 except (ValueError, IOError):
164 log.exception('Loading bible from OSIS file failed')
165 trace_error_handler(log)
166 success = False
167 except etree.XMLSyntaxError as e:
168 log.exception('Loading bible from OSIS file failed')
169 trace_error_handler(log)
170 success = False
171 critical_error_message_box(message=translate('BiblesPlugin.OsisImport',
172 'The file is not a valid OSIS-XML file:'
173 '\n{text}').format(text=e.msg))
174 if self.stop_import_flag:
175 return False
176 else:
177 return success
178174
=== modified file 'openlp/plugins/bibles/lib/importers/zefania.py'
--- openlp/plugins/bibles/lib/importers/zefania.py 2016-08-09 20:45:25 +0000
+++ openlp/plugins/bibles/lib/importers/zefania.py 2016-09-09 21:59:44 +0000
@@ -54,7 +54,7 @@
54 language_id = self.get_language_id(language[0] if language else None, bible_name=self.filename)54 language_id = self.get_language_id(language[0] if language else None, bible_name=self.filename)
55 if not language_id:55 if not language_id:
56 return False56 return False
57 num_books = int(xmlbible.xpath('count(//BIBLEBOOK)'))57 no_of_books = int(xmlbible.xpath('count(//BIBLEBOOK)'))
58 self.wizard.progress_bar.setMaximum(int(xmlbible.xpath('count(//CHAPTER)')))58 self.wizard.progress_bar.setMaximum(int(xmlbible.xpath('count(//CHAPTER)')))
59 for BIBLEBOOK in xmlbible:59 for BIBLEBOOK in xmlbible:
60 if self.stop_import_flag:60 if self.stop_import_flag:
@@ -64,7 +64,7 @@
64 if not bname and not bnumber:64 if not bname and not bnumber:
65 continue65 continue
66 if bname:66 if bname:
67 book_ref_id = self.get_book_ref_id_by_name(bname, num_books, language_id)67 book_ref_id = self.get_book_ref_id_by_name(bname, no_of_books, language_id)
68 else:68 else:
69 log.debug('Could not find a name, will use number, basically a guess.')69 log.debug('Could not find a name, will use number, basically a guess.')
70 book_ref_id = int(bnumber)70 book_ref_id = int(bnumber)
@@ -79,7 +79,8 @@
79 chapter_number = CHAPTER.get("cnumber")79 chapter_number = CHAPTER.get("cnumber")
80 for VERS in CHAPTER:80 for VERS in CHAPTER:
81 verse_number = VERS.get("vnumber")81 verse_number = VERS.get("vnumber")
82 self.create_verse(db_book.id, chapter_number, verse_number, VERS.text.replace('<BR/>', '\n'))82 self.create_verse(
83 db_book.id, int(chapter_number), int(verse_number), VERS.text.replace('<BR/>', '\n'))
83 self.wizard.increment_progress_bar(84 self.wizard.increment_progress_bar(
84 translate('BiblesPlugin.Zefnia',85 translate('BiblesPlugin.Zefnia',
85 'Importing {book} {chapter}...').format(book=db_book.name,86 'Importing {book} {chapter}...').format(book=db_book.name,
8687
=== modified file 'openlp/plugins/bibles/lib/manager.py'
--- openlp/plugins/bibles/lib/manager.py 2016-08-12 17:26:54 +0000
+++ openlp/plugins/bibles/lib/manager.py 2016-09-09 21:59:44 +0000
@@ -23,8 +23,8 @@
23import logging23import logging
24import os24import os
2525
26from openlp.core.common import RegistryProperties, AppLocation, Settings, translate, delete_file, UiStrings26from openlp.core.common import AppLocation, OpenLPMixin, RegistryProperties, Settings, translate, delete_file, UiStrings
27from openlp.plugins.bibles.lib import parse_reference, LanguageSelection27from openlp.plugins.bibles.lib import LanguageSelection, parse_reference
28from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta28from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta
29from .importers.csvbible import CSVBible29from .importers.csvbible import CSVBible
30from .importers.http import HTTPBible30from .importers.http import HTTPBible
@@ -88,7 +88,7 @@
88 ]88 ]
8989
9090
91class BibleManager(RegistryProperties):91class BibleManager(OpenLPMixin, RegistryProperties):
92 """92 """
93 The Bible manager which holds and manages all the Bibles.93 The Bible manager which holds and manages all the Bibles.
94 """94 """
9595
=== modified file 'openlp/plugins/bibles/lib/upgrade.py'
--- openlp/plugins/bibles/lib/upgrade.py 2016-05-21 08:31:24 +0000
+++ openlp/plugins/bibles/lib/upgrade.py 2016-09-09 21:59:44 +0000
@@ -24,8 +24,6 @@
24"""24"""
25import logging25import logging
2626
27from sqlalchemy import delete, func, insert, select
28
29log = logging.getLogger(__name__)27log = logging.getLogger(__name__)
30__version__ = 128__version__ = 1
3129
@@ -35,166 +33,6 @@
35 """33 """
36 Version 1 upgrade.34 Version 1 upgrade.
3735
38 This upgrade renames a number of keys to a single naming convention.36 This upgrade renamed a number of keys to a single naming convention.
39 """37 """
40 metadata_table = metadata.tables['metadata']38 log.info('No upgrades to perform')
41 # Copy "Version" to "name" ("version" used by upgrade system)
42 try:
43 session.execute(insert(metadata_table).values(
44 key='name',
45 value=select(
46 [metadata_table.c.value],
47 metadata_table.c.key == 'Version'
48 ).as_scalar()
49 ))
50 session.execute(delete(metadata_table).where(metadata_table.c.key == 'Version'))
51 except:
52 log.exception('Exception when upgrading Version')
53 # Copy "Copyright" to "copyright"
54 try:
55 session.execute(insert(metadata_table).values(
56 key='copyright',
57 value=select(
58 [metadata_table.c.value],
59 metadata_table.c.key == 'Copyright'
60 ).as_scalar()
61 ))
62 session.execute(delete(metadata_table).where(metadata_table.c.key == 'Copyright'))
63 except:
64 log.exception('Exception when upgrading Copyright')
65 # Copy "Permissions" to "permissions"
66 try:
67 session.execute(insert(metadata_table).values(
68 key='permissions',
69 value=select(
70 [metadata_table.c.value],
71 metadata_table.c.key == 'Permissions'
72 ).as_scalar()
73 ))
74 session.execute(delete(metadata_table).where(metadata_table.c.key == 'Permissions'))
75 except:
76 log.exception('Exception when upgrading Permissions')
77 # Copy "Bookname language" to "book_name_language"
78 try:
79 value_count = session.execute(
80 select(
81 [func.count(metadata_table.c.value)],
82 metadata_table.c.key == 'Bookname language'
83 )
84 ).scalar()
85 if value_count > 0:
86 session.execute(insert(metadata_table).values(
87 key='book_name_language',
88 value=select(
89 [metadata_table.c.value],
90 metadata_table.c.key == 'Bookname language'
91 ).as_scalar()
92 ))
93 session.execute(delete(metadata_table).where(metadata_table.c.key == 'Bookname language'))
94 except:
95 log.exception('Exception when upgrading Bookname language')
96 # Copy "download source" to "download_source"
97 try:
98 value_count = session.execute(
99 select(
100 [func.count(metadata_table.c.value)],
101 metadata_table.c.key == 'download source'
102 )
103 ).scalar()
104 log.debug('download source: {count}'.format(count=value_count))
105 if value_count > 0:
106 session.execute(insert(metadata_table).values(
107 key='download_source',
108 value=select(
109 [metadata_table.c.value],
110 metadata_table.c.key == 'download source'
111 ).as_scalar()
112 ))
113 session.execute(delete(metadata_table).where(metadata_table.c.key == 'download source'))
114 except:
115 log.exception('Exception when upgrading download source')
116 # Copy "download name" to "download_name"
117 try:
118 value_count = session.execute(
119 select(
120 [func.count(metadata_table.c.value)],
121 metadata_table.c.key == 'download name'
122 )
123 ).scalar()
124 log.debug('download name: {count}'.format(count=value_count))
125 if value_count > 0:
126 session.execute(insert(metadata_table).values(
127 key='download_name',
128 value=select(
129 [metadata_table.c.value],
130 metadata_table.c.key == 'download name'
131 ).as_scalar()
132 ))
133 session.execute(delete(metadata_table).where(metadata_table.c.key == 'download name'))
134 except:
135 log.exception('Exception when upgrading download name')
136 # Copy "proxy server" to "proxy_server"
137 try:
138 value_count = session.execute(
139 select(
140 [func.count(metadata_table.c.value)],
141 metadata_table.c.key == 'proxy server'
142 )
143 ).scalar()
144 log.debug('proxy server: {count}'.format(count=value_count))
145 if value_count > 0:
146 session.execute(insert(metadata_table).values(
147 key='proxy_server',
148 value=select(
149 [metadata_table.c.value],
150 metadata_table.c.key == 'proxy server'
151 ).as_scalar()
152 ))
153 session.execute(delete(metadata_table).where(metadata_table.c.key == 'proxy server'))
154 except:
155 log.exception('Exception when upgrading proxy server')
156 # Copy "proxy username" to "proxy_username"
157 try:
158 value_count = session.execute(
159 select(
160 [func.count(metadata_table.c.value)],
161 metadata_table.c.key == 'proxy username'
162 )
163 ).scalar()
164 log.debug('proxy username: {count}'.format(count=value_count))
165 if value_count > 0:
166 session.execute(insert(metadata_table).values(
167 key='proxy_username',
168 value=select(
169 [metadata_table.c.value],
170 metadata_table.c.key == 'proxy username'
171 ).as_scalar()
172 ))
173 session.execute(delete(metadata_table).where(metadata_table.c.key == 'proxy username'))
174 except:
175 log.exception('Exception when upgrading proxy username')
176 # Copy "proxy password" to "proxy_password"
177 try:
178 value_count = session.execute(
179 select(
180 [func.count(metadata_table.c.value)],
181 metadata_table.c.key == 'proxy password'
182 )
183 ).scalar()
184 log.debug('proxy password: {count}'.format(count=value_count))
185 if value_count > 0:
186 session.execute(insert(metadata_table).values(
187 key='proxy_password',
188 value=select(
189 [metadata_table.c.value],
190 metadata_table.c.key == 'proxy password'
191 ).as_scalar()
192 ))
193 session.execute(delete(metadata_table).where(metadata_table.c.key == 'proxy password'))
194 except:
195 log.exception('Exception when upgrading proxy password')
196 try:
197 session.execute(delete(metadata_table).where(metadata_table.c.key == 'dbversion'))
198 except:
199 log.exception('Exception when deleting dbversion')
200 session.commit()
20139
=== modified file 'tests/functional/openlp_core_ui/test_exceptionform.py'
--- tests/functional/openlp_core_ui/test_exceptionform.py 2016-06-25 14:41:06 +0000
+++ tests/functional/openlp_core_ui/test_exceptionform.py 2016-09-09 21:59:44 +0000
@@ -24,18 +24,13 @@
24"""24"""
2525
26import os26import os
27import socket
28import tempfile27import tempfile
29import urllib
30from unittest import TestCase28from unittest import TestCase
31from unittest.mock import mock_open29from unittest.mock import mock_open
3230
33from PyQt5.QtCore import QUrlQuery
34
35from openlp.core.common import Registry31from openlp.core.common import Registry
36from openlp.core.ui.firsttimeform import FirstTimeForm
3732
38from tests.functional import MagicMock, patch33from tests.functional import patch
39from tests.helpers.testmixin import TestMixin34from tests.helpers.testmixin import TestMixin
4035
41from openlp.core.ui import exceptionform36from openlp.core.ui import exceptionform
4237
=== modified file 'tests/functional/openlp_plugins/bibles/test_bibleimport.py'
--- tests/functional/openlp_plugins/bibles/test_bibleimport.py 2016-08-07 11:20:53 +0000
+++ tests/functional/openlp_plugins/bibles/test_bibleimport.py 2016-09-09 21:59:44 +0000
@@ -27,9 +27,12 @@
27from lxml import etree, objectify27from lxml import etree, objectify
2828
29from unittest import TestCase29from unittest import TestCase
30from PyQt5.QtWidgets import QDialog
3031
31from openlp.core.common.languages import Language32from openlp.core.common.languages import Language
33from openlp.core.lib.exceptions import ValidationError
32from openlp.plugins.bibles.lib.bibleimport import BibleImport34from openlp.plugins.bibles.lib.bibleimport import BibleImport
35from openlp.plugins.bibles.lib.db import BibleDB
33from tests.functional import MagicMock, patch36from tests.functional import MagicMock, patch
3437
3538
@@ -39,22 +42,103 @@
39 """42 """
4043
41 def setUp(self):44 def setUp(self):
42 test_file = BytesIO(b'<?xml version="1.0" encoding="UTF-8" ?>\n'45 self.test_file = BytesIO(
43 b'<root>\n'46 b'<?xml version="1.0" encoding="UTF-8" ?>\n'
44 b' <data><div>Test<p>data</p><a>to</a>keep</div></data>\n'47 b'<root>\n'
45 b' <data><unsupported>Test<x>data</x><y>to</y>discard</unsupported></data>\n'48 b' <data><div>Test<p>data</p><a>to</a>keep</div></data>\n'
46 b'</root>')49 b' <data><unsupported>Test<x>data</x><y>to</y>discard</unsupported></data>\n'
47 self.file_patcher = patch('builtins.open', return_value=test_file)50 b'</root>'
48 self.log_patcher = patch('openlp.plugins.bibles.lib.bibleimport.log')51 )
52 self.open_patcher = patch('builtins.open')
53 self.addCleanup(self.open_patcher.stop)
54 self.mocked_open = self.open_patcher.start()
55 self.critical_error_message_box_patcher = \
56 patch('openlp.plugins.bibles.lib.bibleimport.critical_error_message_box')
57 self.addCleanup(self.critical_error_message_box_patcher.stop)
58 self.mocked_critical_error_message_box = self.critical_error_message_box_patcher.start()
49 self.setup_patcher = patch('openlp.plugins.bibles.lib.db.BibleDB._setup')59 self.setup_patcher = patch('openlp.plugins.bibles.lib.db.BibleDB._setup')
50
51 self.addCleanup(self.file_patcher.stop)
52 self.addCleanup(self.log_patcher.stop)
53 self.addCleanup(self.setup_patcher.stop)60 self.addCleanup(self.setup_patcher.stop)
54
55 self.file_patcher.start()
56 self.mock_log = self.log_patcher.start()
57 self.setup_patcher.start()61 self.setup_patcher.start()
62 self.translate_patcher = patch('openlp.plugins.bibles.lib.bibleimport.translate',
63 side_effect=lambda module, string_to_translate, *args: string_to_translate)
64 self.addCleanup(self.translate_patcher.stop)
65 self.mocked_translate = self.translate_patcher.start()
66 self.registry_patcher = patch('openlp.plugins.bibles.lib.bibleimport.Registry')
67 self.addCleanup(self.registry_patcher.stop)
68 self.registry_patcher.start()
69
70 def init_kwargs_none_test(self):
71 """
72 Test the initialisation of the BibleImport Class when no key word arguments are supplied
73 """
74 # GIVEN: A patched BibleDB._setup, BibleImport class and mocked parent
75 # WHEN: Creating an instance of BibleImport with no key word arguments
76 instance = BibleImport(MagicMock())
77
78 # THEN: The filename attribute should be None
79 self.assertIsNone(instance.filename)
80 self.assertIsInstance(instance, BibleDB)
81
82 def init_kwargs_set_test(self):
83 """
84 Test the initialisation of the BibleImport Class when supplied with select keyword arguments
85 """
86 # GIVEN: A patched BibleDB._setup, BibleImport class and mocked parent
87 # WHEN: Creating an instance of BibleImport with selected key word arguments
88 kwargs = {'filename': 'bible.xml'}
89 instance = BibleImport(MagicMock(), **kwargs)
90
91 # THEN: The filename keyword should be set to bible.xml
92 self.assertEqual(instance.filename, 'bible.xml')
93 self.assertIsInstance(instance, BibleDB)
94
95 def get_language_canceled_test(self):
96 """
97 Test the BibleImport.get_language method when the user rejects the dialog box
98 """
99 # GIVEN: A mocked LanguageForm with an exec method which returns QtDialog.Rejected and an instance of BibleDB
100 with patch.object(BibleDB, '_setup'), patch('openlp.plugins.bibles.forms.LanguageForm') as mocked_language_form:
101
102 # The integer value of QtDialog.Rejected is 0. Using the enumeration causes a seg fault for some reason
103 mocked_language_form_instance = MagicMock(**{'exec.return_value': 0})
104 mocked_language_form.return_value = mocked_language_form_instance
105 instance = BibleImport(MagicMock())
106 mocked_wizard = MagicMock()
107 instance.wizard = mocked_wizard
108
109 # WHEN: Calling get_language()
110 result = instance.get_language()
111
112 # THEN: get_language() should return False
113 mocked_language_form.assert_called_once_with(mocked_wizard)
114 mocked_language_form_instance.exec.assert_called_once_with(None)
115 self.assertFalse(result, 'get_language() should return False if the user rejects the dialog box')
116
117 def get_language_accepted_test(self):
118 """
119 Test the BibleImport.get_language method when the user accepts the dialog box
120 """
121 # GIVEN: A mocked LanguageForm with an exec method which returns QtDialog.Accepted an instance of BibleDB and
122 # a combobox with the selected item data as 10
123 with patch.object(BibleDB, 'save_meta'), patch.object(BibleDB, '_setup'), \
124 patch('openlp.plugins.bibles.forms.LanguageForm') as mocked_language_form:
125
126 # The integer value of QtDialog.Accepted is 1. Using the enumeration causes a seg fault for some reason
127 mocked_language_form_instance = MagicMock(**{'exec.return_value': 1,
128 'language_combo_box.itemData.return_value': 10})
129 mocked_language_form.return_value = mocked_language_form_instance
130 instance = BibleImport(MagicMock())
131 mocked_wizard = MagicMock()
132 instance.wizard = mocked_wizard
133
134 # WHEN: Calling get_language()
135 result = instance.get_language('Bible Name')
136
137 # THEN: get_language() should return the id of the selected language in the combo box
138 mocked_language_form.assert_called_once_with(mocked_wizard)
139 mocked_language_form_instance.exec.assert_called_once_with('Bible Name')
140 self.assertEqual(result, 10, 'get_language() should return the id of the language the user has chosen when '
141 'they accept the dialog box')
58142
59 def get_language_id_language_found_test(self):143 def get_language_id_language_found_test(self):
60 """144 """
@@ -63,7 +147,7 @@
63 # GIVEN: A mocked languages.get_language which returns language and an instance of BibleImport147 # GIVEN: A mocked languages.get_language which returns language and an instance of BibleImport
64 with patch('openlp.core.common.languages.get_language', return_value=Language(30, 'English', 'en')) \148 with patch('openlp.core.common.languages.get_language', return_value=Language(30, 'English', 'en')) \
65 as mocked_languages_get_language, \149 as mocked_languages_get_language, \
66 patch('openlp.plugins.bibles.lib.db.BibleDB.get_language') as mocked_db_get_language:150 patch.object(BibleImport, 'get_language') as mocked_db_get_language:
67 instance = BibleImport(MagicMock())151 instance = BibleImport(MagicMock())
68 instance.save_meta = MagicMock()152 instance.save_meta = MagicMock()
69153
@@ -81,9 +165,8 @@
81 Test get_language_id() when called with a name not found in the languages list165 Test get_language_id() when called with a name not found in the languages list
82 """166 """
83 # GIVEN: A mocked languages.get_language which returns language and an instance of BibleImport167 # GIVEN: A mocked languages.get_language which returns language and an instance of BibleImport
84 with patch('openlp.core.common.languages.get_language', return_value=None) \168 with patch('openlp.core.common.languages.get_language', return_value=None) as mocked_languages_get_language, \
85 as mocked_languages_get_language, \169 patch.object(BibleImport, 'get_language', return_value=20) as mocked_db_get_language:
86 patch('openlp.plugins.bibles.lib.db.BibleDB.get_language', return_value=20) as mocked_db_get_language:
87 instance = BibleImport(MagicMock())170 instance = BibleImport(MagicMock())
88 instance.save_meta = MagicMock()171 instance.save_meta = MagicMock()
89172
@@ -103,8 +186,8 @@
103 # GIVEN: A mocked languages.get_language which returns None a mocked BibleDB.get_language which returns a186 # GIVEN: A mocked languages.get_language which returns None a mocked BibleDB.get_language which returns a
104 # language id.187 # language id.
105 with patch('openlp.core.common.languages.get_language', return_value=None) as mocked_languages_get_language, \188 with patch('openlp.core.common.languages.get_language', return_value=None) as mocked_languages_get_language, \
106 patch('openlp.plugins.bibles.lib.db.BibleDB.get_language', return_value=40) as mocked_db_get_language:189 patch.object(BibleImport, 'get_language', return_value=40) as mocked_db_get_language, \
107 self.mock_log.error.reset_mock()190 patch.object(BibleImport, 'log_error') as mocked_log_error:
108 instance = BibleImport(MagicMock())191 instance = BibleImport(MagicMock())
109 instance.save_meta = MagicMock()192 instance.save_meta = MagicMock()
110193
@@ -114,7 +197,7 @@
114 # THEN: The id of the language returned from BibleDB.get_language should be returned197 # THEN: The id of the language returned from BibleDB.get_language should be returned
115 mocked_languages_get_language.assert_called_once_with('English')198 mocked_languages_get_language.assert_called_once_with('English')
116 mocked_db_get_language.assert_called_once_with('KJV')199 mocked_db_get_language.assert_called_once_with('KJV')
117 self.assertFalse(self.mock_log.error.called)200 self.assertFalse(mocked_log_error.error.called)
118 instance.save_meta.assert_called_once_with('language_id', 40)201 instance.save_meta.assert_called_once_with('language_id', 40)
119 self.assertEqual(result, 40)202 self.assertEqual(result, 40)
120203
@@ -125,8 +208,8 @@
125 # GIVEN: A mocked languages.get_language which returns None a mocked BibleDB.get_language which returns a208 # GIVEN: A mocked languages.get_language which returns None a mocked BibleDB.get_language which returns a
126 # language id.209 # language id.
127 with patch('openlp.core.common.languages.get_language', return_value=None) as mocked_languages_get_language, \210 with patch('openlp.core.common.languages.get_language', return_value=None) as mocked_languages_get_language, \
128 patch('openlp.plugins.bibles.lib.db.BibleDB.get_language', return_value=None) as mocked_db_get_language:211 patch.object(BibleImport, 'get_language', return_value=None) as mocked_db_get_language, \
129 self.mock_log.error.reset_mock()212 patch.object(BibleImport, 'log_error') as mocked_log_error:
130 instance = BibleImport(MagicMock())213 instance = BibleImport(MagicMock())
131 instance.save_meta = MagicMock()214 instance.save_meta = MagicMock()
132215
@@ -136,18 +219,148 @@
136 # THEN: None should be returned and an error should be logged219 # THEN: None should be returned and an error should be logged
137 mocked_languages_get_language.assert_called_once_with('Qwerty')220 mocked_languages_get_language.assert_called_once_with('Qwerty')
138 mocked_db_get_language.assert_called_once_with('KJV')221 mocked_db_get_language.assert_called_once_with('KJV')
139 self.mock_log.error.assert_called_once_with('Language detection failed when importing from "KJV". '222 mocked_log_error.assert_called_once_with(
140 'User aborted language selection.')223 'Language detection failed when importing from "KJV". User aborted language selection.')
141 self.assertFalse(instance.save_meta.called)224 self.assertFalse(instance.save_meta.called)
142 self.assertIsNone(result)225 self.assertIsNone(result)
143226
227 def get_book_ref_id_by_name_get_book_test(self):
228 """
229 Test get_book_ref_id_by_name when the book is found as a book in BiblesResourcesDB
230 """
231 # GIVEN: An instance of BibleImport and a mocked BiblesResourcesDB which returns a book id when get_book is
232 # called
233 with patch.object(BibleImport, 'log_debug'), \
234 patch('openlp.plugins.bibles.lib.bibleimport.BiblesResourcesDB',
235 **{'get_book.return_value': {'id': 20}}):
236 instance = BibleImport(MagicMock())
237
238 # WHEN: Calling get_book_ref_id_by_name
239 result = instance.get_book_ref_id_by_name('Gen', 66, 4)
240
241 # THEN: The bible id should be returned
242 self.assertEqual(result, 20)
243
244 def get_book_ref_id_by_name_get_alternative_book_name_test(self):
245 """
246 Test get_book_ref_id_by_name when the book is found as an alternative book in BiblesResourcesDB
247 """
248 # GIVEN: An instance of BibleImport and a mocked BiblesResourcesDB which returns a book id when
249 # get_alternative_book_name is called
250 with patch.object(BibleImport, 'log_debug'), \
251 patch('openlp.plugins.bibles.lib.bibleimport.BiblesResourcesDB',
252 **{'get_book.return_value': None, 'get_alternative_book_name.return_value': 30}):
253 instance = BibleImport(MagicMock())
254
255 # WHEN: Calling get_book_ref_id_by_name
256 result = instance.get_book_ref_id_by_name('Gen', 66, 4)
257
258 # THEN: The bible id should be returned
259 self.assertEqual(result, 30)
260
261 def get_book_ref_id_by_name_get_book_reference_id_test(self):
262 """
263 Test get_book_ref_id_by_name when the book is found as a book in AlternativeBookNamesDB
264 """
265 # GIVEN: An instance of BibleImport and a mocked AlternativeBookNamesDB which returns a book id when
266 # get_book_reference_id is called
267 with patch.object(BibleImport, 'log_debug'), \
268 patch('openlp.plugins.bibles.lib.bibleimport.BiblesResourcesDB',
269 **{'get_book.return_value': None, 'get_alternative_book_name.return_value': None}), \
270 patch('openlp.plugins.bibles.lib.bibleimport.AlternativeBookNamesDB',
271 **{'get_book_reference_id.return_value': 40}):
272 instance = BibleImport(MagicMock())
273
274 # WHEN: Calling get_book_ref_id_by_name
275 result = instance.get_book_ref_id_by_name('Gen', 66, 4)
276
277 # THEN: The bible id should be returned
278 self.assertEqual(result, 40)
279
280 def get_book_ref_id_by_name_book_name_form_rejected_test(self):
281 """
282 Test get_book_ref_id_by_name when the user rejects the BookNameForm
283 """
284 # GIVEN: An instance of BibleImport and a mocked BookNameForm which simulates a user rejecting the dialog
285 with patch.object(BibleImport, 'log_debug'), patch.object(BibleImport, 'get_books'), \
286 patch('openlp.plugins.bibles.lib.bibleimport.BiblesResourcesDB',
287 **{'get_book.return_value': None, 'get_alternative_book_name.return_value': None}), \
288 patch('openlp.plugins.bibles.lib.bibleimport.AlternativeBookNamesDB',
289 **{'get_book_reference_id.return_value': None}), \
290 patch('openlp.plugins.bibles.forms.BookNameForm',
291 return_value=MagicMock(**{'exec.return_value': QDialog.Rejected})):
292 instance = BibleImport(MagicMock())
293
294 # WHEN: Calling get_book_ref_id_by_name
295 result = instance.get_book_ref_id_by_name('Gen', 66, 4)
296
297 # THEN: None should be returned
298 self.assertIsNone(result)
299
300 def get_book_ref_id_by_name_book_name_form_accepted_test(self):
301 """
302 Test get_book_ref_id_by_name when the user accepts the BookNameForm
303 """
304 # GIVEN: An instance of BibleImport and a mocked BookNameForm which simulates a user accepting the dialog
305 with patch.object(BibleImport, 'log_debug'), patch.object(BibleImport, 'get_books'), \
306 patch('openlp.plugins.bibles.lib.bibleimport.BiblesResourcesDB',
307 **{'get_book.return_value': None, 'get_alternative_book_name.return_value': None}), \
308 patch('openlp.plugins.bibles.lib.bibleimport.AlternativeBookNamesDB',
309 **{'get_book_reference_id.return_value': None}) as mocked_alternative_book_names_db, \
310 patch('openlp.plugins.bibles.forms.BookNameForm',
311 return_value=MagicMock(**{'exec.return_value': QDialog.Accepted, 'book_id': 50})):
312 instance = BibleImport(MagicMock())
313
314 # WHEN: Calling get_book_ref_id_by_name
315 result = instance.get_book_ref_id_by_name('Gen', 66, 4)
316
317 # THEN: An alternative book name should be created and a bible id should be returned
318 mocked_alternative_book_names_db.create_alternative_book_name.assert_called_once_with('Gen', 50, 4)
319 self.assertEqual(result, 50)
320
321 def is_compressed_compressed_test(self):
322 """
323 Test is_compressed when the 'file' being tested is compressed
324 """
325 # GIVEN: An instance of BibleImport and a mocked is_zipfile which returns True
326 with patch('openlp.plugins.bibles.lib.bibleimport.is_zipfile', return_value=True):
327 instance = BibleImport(MagicMock())
328
329 # WHEN: Calling is_compressed
330 result = instance.is_compressed('file.ext')
331
332 # THEN: Then critical_error_message_box should be called informing the user that the file is compressed and
333 # True should be returned
334 self.mocked_critical_error_message_box.assert_called_once_with(
335 message='The file "file.ext" you supplied is compressed. You must decompress it before import.')
336 self.assertTrue(result)
337
338 def is_compressed_not_compressed_test(self):
339 """
340 Test is_compressed when the 'file' being tested is not compressed
341 """
342 # GIVEN: An instance of BibleImport and a mocked is_zipfile which returns False
343 with patch('openlp.plugins.bibles.lib.bibleimport.is_zipfile', return_value=False):
344 instance = BibleImport(MagicMock())
345
346 # WHEN: Calling is_compressed
347 result = instance.is_compressed('file.ext')
348
349 # THEN: False should be returned and critical_error_message_box should not have been called
350 self.assertFalse(result)
351 self.assertFalse(self.mocked_critical_error_message_box.called)
352
144 def parse_xml_etree_test(self):353 def parse_xml_etree_test(self):
145 """354 """
146 Test BibleImport.parse_xml() when called with the use_objectify default value355 Test BibleImport.parse_xml() when called with the use_objectify default value
147 """356 """
148 # GIVEN: A sample "file" to parse357 # GIVEN: A sample "file" to parse and an instance of BibleImport
358 self.mocked_open.return_value = self.test_file
359 instance = BibleImport(MagicMock())
360 instance.wizard = MagicMock()
361
149 # WHEN: Calling parse_xml362 # WHEN: Calling parse_xml
150 result = BibleImport.parse_xml('file.tst')363 result = instance.parse_xml('file.tst')
151364
152 # THEN: The result returned should contain the correct data, and should be an instance of eetree_Element365 # THEN: The result returned should contain the correct data, and should be an instance of eetree_Element
153 self.assertEqual(etree.tostring(result),366 self.assertEqual(etree.tostring(result),
@@ -159,9 +372,13 @@
159 """372 """
160 Test BibleImport.parse_xml() when called with use_objectify set to True373 Test BibleImport.parse_xml() when called with use_objectify set to True
161 """374 """
162 # GIVEN: A sample "file" to parse375 # GIVEN: A sample "file" to parse and an instance of BibleImport
376 self.mocked_open.return_value = self.test_file
377 instance = BibleImport(MagicMock())
378 instance.wizard = MagicMock()
379
163 # WHEN: Calling parse_xml380 # WHEN: Calling parse_xml
164 result = BibleImport.parse_xml('file.tst', use_objectify=True)381 result = instance.parse_xml('file.tst', use_objectify=True)
165382
166 # THEN: The result returned should contain the correct data, and should be an instance of ObjectifiedElement383 # THEN: The result returned should contain the correct data, and should be an instance of ObjectifiedElement
167 self.assertEqual(etree.tostring(result),384 self.assertEqual(etree.tostring(result),
@@ -173,11 +390,14 @@
173 """390 """
174 Test BibleImport.parse_xml() when given a tuple of elements to remove391 Test BibleImport.parse_xml() when given a tuple of elements to remove
175 """392 """
176 # GIVEN: A tuple of elements to remove393 # GIVEN: A tuple of elements to remove and an instance of BibleImport
394 self.mocked_open.return_value = self.test_file
177 elements = ('unsupported', 'x', 'y')395 elements = ('unsupported', 'x', 'y')
396 instance = BibleImport(MagicMock())
397 instance.wizard = MagicMock()
178398
179 # WHEN: Calling parse_xml, with a test file399 # WHEN: Calling parse_xml, with a test file
180 result = BibleImport.parse_xml('file.tst', elements=elements)400 result = instance.parse_xml('file.tst', elements=elements)
181401
182 # THEN: The result returned should contain the correct data402 # THEN: The result returned should contain the correct data
183 self.assertEqual(etree.tostring(result),403 self.assertEqual(etree.tostring(result),
@@ -187,11 +407,14 @@
187 """407 """
188 Test BibleImport.parse_xml() when given a tuple of tags to remove408 Test BibleImport.parse_xml() when given a tuple of tags to remove
189 """409 """
190 # GIVEN: A tuple of tags to remove410 # GIVEN: A tuple of tags to remove and an instance of BibleImport
411 self.mocked_open.return_value = self.test_file
191 tags = ('div', 'p', 'a')412 tags = ('div', 'p', 'a')
413 instance = BibleImport(MagicMock())
414 instance.wizard = MagicMock()
192415
193 # WHEN: Calling parse_xml, with a test file416 # WHEN: Calling parse_xml, with a test file
194 result = BibleImport.parse_xml('file.tst', tags=tags)417 result = instance.parse_xml('file.tst', tags=tags)
195418
196 # THEN: The result returned should contain the correct data419 # THEN: The result returned should contain the correct data
197 self.assertEqual(etree.tostring(result), b'<root>\n <data>Testdatatokeep</data>\n <data><unsupported>Test'420 self.assertEqual(etree.tostring(result), b'<root>\n <data>Testdatatokeep</data>\n <data><unsupported>Test'
@@ -201,12 +424,192 @@
201 """424 """
202 Test BibleImport.parse_xml() when given a tuple of elements and of tags to remove425 Test BibleImport.parse_xml() when given a tuple of elements and of tags to remove
203 """426 """
204 # GIVEN: A tuple of elements and of tags to remove427 # GIVEN: A tuple of elements and of tags to remove and an instacne of BibleImport
428 self.mocked_open.return_value = self.test_file
205 elements = ('unsupported', 'x', 'y')429 elements = ('unsupported', 'x', 'y')
206 tags = ('div', 'p', 'a')430 tags = ('div', 'p', 'a')
431 instance = BibleImport(MagicMock())
432 instance.wizard = MagicMock()
207433
208 # WHEN: Calling parse_xml, with a test file434 # WHEN: Calling parse_xml, with a test file
209 result = BibleImport.parse_xml('file.tst', elements=elements, tags=tags)435 result = instance.parse_xml('file.tst', elements=elements, tags=tags)
210436
211 # THEN: The result returned should contain the correct data437 # THEN: The result returned should contain the correct data
212 self.assertEqual(etree.tostring(result), b'<root>\n <data>Testdatatokeep</data>\n <data/>\n</root>')438 self.assertEqual(etree.tostring(result), b'<root>\n <data>Testdatatokeep</data>\n <data/>\n</root>')
439
440 def parse_xml_file_file_not_found_exception_test(self):
441 """
442 Test that parse_xml handles a FileNotFoundError exception correctly
443 """
444 with patch.object(BibleImport, 'log_exception') as mocked_log_exception:
445 # GIVEN: A mocked open which raises a FileNotFoundError and an instance of BibleImporter
446 exception = FileNotFoundError()
447 exception.filename = 'file.tst'
448 exception.strerror = 'No such file or directory'
449 self.mocked_open.side_effect = exception
450 importer = BibleImport(MagicMock(), path='.', name='.', filename='')
451
452 # WHEN: Calling parse_xml
453 result = importer.parse_xml('file.tst')
454
455 # THEN: parse_xml should have caught the error, informed the user and returned None
456 mocked_log_exception.assert_called_once_with('Opening file.tst failed.')
457 self.mocked_critical_error_message_box.assert_called_once_with(
458 title='An Error Occured When Opening A File',
459 message='The following error occurred when trying to open\nfile.tst:\n\nNo such file or directory')
460 self.assertIsNone(result)
461
462 def parse_xml_file_permission_error_exception_test(self):
463 """
464 Test that parse_xml handles a PermissionError exception correctly
465 """
466 with patch.object(BibleImport, 'log_exception') as mocked_log_exception:
467 # GIVEN: A mocked open which raises a PermissionError and an instance of BibleImporter
468 exception = PermissionError()
469 exception.filename = 'file.tst'
470 exception.strerror = 'Permission denied'
471 self.mocked_open.side_effect = exception
472 importer = BibleImport(MagicMock(), path='.', name='.', filename='')
473
474 # WHEN: Calling parse_xml
475 result = importer.parse_xml('file.tst')
476
477 # THEN: parse_xml should have caught the error, informed the user and returned None
478 mocked_log_exception.assert_called_once_with('Opening file.tst failed.')
479 self.mocked_critical_error_message_box.assert_called_once_with(
480 title='An Error Occured When Opening A File',
481 message='The following error occurred when trying to open\nfile.tst:\n\nPermission denied')
482 self.assertIsNone(result)
483
484 def set_current_chapter_test(self):
485 """
486 Test set_current_chapter
487 """
488 # GIVEN: An instance of BibleImport and a mocked wizard
489 importer = BibleImport(MagicMock(), path='.', name='.', filename='')
490 importer.wizard = MagicMock()
491
492 # WHEN: Calling set_current_chapter
493 importer.set_current_chapter('Book_Name', 'Chapter')
494
495 # THEN: Increment_progress_bar should have been called with a text string
496 importer.wizard.increment_progress_bar.assert_called_once_with('Importing Book_Name Chapter...')
497
498 def validate_xml_file_compressed_file_test(self):
499 """
500 Test that validate_xml_file raises a ValidationError when is_compressed returns True
501 """
502 # GIVEN: A mocked parse_xml which returns None
503 with patch.object(BibleImport, 'is_compressed', return_value=True):
504 importer = BibleImport(MagicMock(), path='.', name='.', filename='')
505
506 # WHEN: Calling is_compressed
507 # THEN: ValidationError should be raised, with the message 'Compressed file'
508 with self.assertRaises(ValidationError) as context:
509 importer.validate_xml_file('file.name', 'xbible')
510 self.assertEqual(context.exception.msg, 'Compressed file')
511
512 def validate_xml_file_parse_xml_fails_test(self):
513 """
514 Test that validate_xml_file raises a ValidationError when parse_xml returns None
515 """
516 # GIVEN: A mocked parse_xml which returns None
517 with patch.object(BibleImport, 'parse_xml', return_value=None), \
518 patch.object(BibleImport, 'is_compressed', return_value=False):
519 importer = BibleImport(MagicMock(), path='.', name='.', filename='')
520
521 # WHEN: Calling validate_xml_file
522 # THEN: ValidationError should be raised, with the message 'Error when opening file'
523 # the user that an OpenSong bible was found
524 with self.assertRaises(ValidationError) as context:
525 importer.validate_xml_file('file.name', 'xbible')
526 self.assertEqual(context.exception.msg, 'Error when opening file')
527
528 def validate_xml_file_success_test(self):
529 """
530 Test that validate_xml_file returns True with valid XML
531 """
532 # GIVEN: Some test data with an OpenSong Bible "bible" root tag
533 with patch.object(BibleImport, 'parse_xml', return_value=objectify.fromstring('<bible></bible>')), \
534 patch.object(BibleImport, 'is_compressed', return_value=False):
535 importer = BibleImport(MagicMock(), path='.', name='.', filename='')
536
537 # WHEN: Calling validate_xml_file
538 result = importer.validate_xml_file('file.name', 'bible')
539
540 # THEN: True should be returned
541 self.assertTrue(result)
542
543 def validate_xml_file_opensong_root_test(self):
544 """
545 Test that validate_xml_file raises a ValidationError with an OpenSong root tag
546 """
547 # GIVEN: Some test data with an Zefania root tag and an instance of BibleImport
548 with patch.object(BibleImport, 'parse_xml', return_value=objectify.fromstring('<bible></bible>')), \
549 patch.object(BibleImport, 'is_compressed', return_value=False):
550 importer = BibleImport(MagicMock(), path='.', name='.', filename='')
551
552 # WHEN: Calling validate_xml_file
553 # THEN: ValidationError should be raised, and the critical error message box should was called informing
554 # the user that an OpenSong bible was found
555 with self.assertRaises(ValidationError) as context:
556 importer.validate_xml_file('file.name', 'xbible')
557 self.assertEqual(context.exception.msg, 'Invalid xml.')
558 self.mocked_critical_error_message_box.assert_called_once_with(
559 message='Incorrect Bible file type supplied. This looks like an OpenSong XML bible.')
560
561 def validate_xml_file_osis_root_test(self):
562 """
563 Test that validate_xml_file raises a ValidationError with an OSIS root tag
564 """
565 # GIVEN: Some test data with an Zefania root tag and an instance of BibleImport
566 with patch.object(BibleImport, 'parse_xml', return_value=objectify.fromstring(
567 '<osis xmlns=\'http://www.bibletechnologies.net/2003/OSIS/namespace\'></osis>')), \
568 patch.object(BibleImport, 'is_compressed', return_value=False):
569 importer = BibleImport(MagicMock(), path='.', name='.', filename='')
570
571 # WHEN: Calling validate_xml_file
572 # THEN: ValidationError should be raised, and the critical error message box should was called informing
573 # the user that an OSIS bible was found
574 with self.assertRaises(ValidationError) as context:
575 importer.validate_xml_file('file.name', 'xbible')
576 self.assertEqual(context.exception.msg, 'Invalid xml.')
577 self.mocked_critical_error_message_box.assert_called_once_with(
578 message='Incorrect Bible file type supplied. This looks like an OSIS XML bible.')
579
580 def validate_xml_file_zefania_root_test(self):
581 """
582 Test that validate_xml_file raises a ValidationError with an Zefania root tag
583 """
584 # GIVEN: Some test data with an Zefania root tag and an instance of BibleImport
585 with patch.object(BibleImport, 'parse_xml', return_value=objectify.fromstring('<xmlbible></xmlbible>')), \
586 patch.object(BibleImport, 'is_compressed', return_value=False):
587 importer = BibleImport(MagicMock(), path='.', name='.', filename='')
588
589 # WHEN: Calling validate_xml_file
590 # THEN: ValidationError should be raised, and the critical error message box should was called informing
591 # the user that an Zefania bible was found
592 with self.assertRaises(ValidationError) as context:
593 importer.validate_xml_file('file.name', 'xbible')
594 self.assertEqual(context.exception.msg, 'Invalid xml.')
595 self.mocked_critical_error_message_box.assert_called_once_with(
596 message='Incorrect Bible file type supplied. This looks like an Zefania XML bible.')
597
598 def validate_xml_file_unknown_root_test(self):
599 """
600 Test that validate_xml_file raises a ValidationError with an unknown root tag
601 """
602 # GIVEN: Some test data with an unknown root tag and an instance of BibleImport
603 with patch.object(
604 BibleImport, 'parse_xml', return_value=objectify.fromstring('<unknownbible></unknownbible>')), \
605 patch.object(BibleImport, 'is_compressed', return_value=False):
606 importer = BibleImport(MagicMock(), path='.', name='.', filename='')
607
608 # WHEN: Calling validate_xml_file
609 # THEN: ValidationError should be raised, and the critical error message box should was called informing
610 # the user that a unknown xml bible was found
611 with self.assertRaises(ValidationError) as context:
612 importer.validate_xml_file('file.name', 'xbible')
613 self.assertEqual(context.exception.msg, 'Invalid xml.')
614 self.mocked_critical_error_message_box.assert_called_once_with(
615 message='Incorrect Bible file type supplied. This looks like an unknown type of XML bible.')
213616
=== renamed file 'tests/functional/openlp_plugins/bibles/test_http.py' => 'tests/functional/openlp_plugins/bibles/test_bibleserver.py'
=== modified file 'tests/functional/openlp_plugins/bibles/test_csvimport.py'
--- tests/functional/openlp_plugins/bibles/test_csvimport.py 2016-08-09 20:56:04 +0000
+++ tests/functional/openlp_plugins/bibles/test_csvimport.py 2016-09-09 21:59:44 +0000
@@ -46,10 +46,10 @@
4646
47 def setUp(self):47 def setUp(self):
48 self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager')48 self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager')
49 self.registry_patcher = patch('openlp.plugins.bibles.lib.db.Registry')
50 self.addCleanup(self.manager_patcher.stop)49 self.addCleanup(self.manager_patcher.stop)
50 self.manager_patcher.start()
51 self.registry_patcher = patch('openlp.plugins.bibles.lib.bibleimport.Registry')
51 self.addCleanup(self.registry_patcher.stop)52 self.addCleanup(self.registry_patcher.stop)
52 self.manager_patcher.start()
53 self.registry_patcher.start()53 self.registry_patcher.start()
5454
55 def test_create_importer(self):55 def test_create_importer(self):
@@ -194,9 +194,9 @@
194 # WHEN: Calling process_books194 # WHEN: Calling process_books
195 result = importer.process_books(['Book 1'])195 result = importer.process_books(['Book 1'])
196196
197 # THEN: increment_progress_bar should not be called and the return value should be None197 # THEN: increment_progress_bar should not be called and the return value should be an empty dictionary
198 self.assertFalse(importer.wizard.increment_progress_bar.called)198 self.assertFalse(importer.wizard.increment_progress_bar.called)
199 self.assertIsNone(result)199 self.assertEqual(result, {})
200200
201 def process_books_test(self):201 def process_books_test(self):
202 """202 """
@@ -207,7 +207,6 @@
207 with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'),\207 with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'),\
208 patch('openlp.plugins.bibles.lib.importers.csvbible.translate'):208 patch('openlp.plugins.bibles.lib.importers.csvbible.translate'):
209 importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verse.csv')209 importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verse.csv')
210 type(importer).application = PropertyMock()
211 importer.find_and_create_book = MagicMock()210 importer.find_and_create_book = MagicMock()
212 importer.language_id = 10211 importer.language_id = 10
213 importer.stop_import_flag = False212 importer.stop_import_flag = False
@@ -222,7 +221,6 @@
222 # The returned data should be a dictionary with both song's id and names.221 # The returned data should be a dictionary with both song's id and names.
223 self.assertEqual(importer.find_and_create_book.mock_calls,222 self.assertEqual(importer.find_and_create_book.mock_calls,
224 [call('1. Mosebog', 2, 10), call('2. Mosebog', 2, 10)])223 [call('1. Mosebog', 2, 10), call('2. Mosebog', 2, 10)])
225 importer.application.process_events.assert_called_once_with()
226 self.assertDictEqual(result, {1: '1. Mosebog', 2: '2. Mosebog'})224 self.assertDictEqual(result, {1: '1. Mosebog', 2: '2. Mosebog'})
227225
228 def process_verses_stopped_import_test(self):226 def process_verses_stopped_import_test(self):
@@ -233,19 +231,16 @@
233 mocked_manager = MagicMock()231 mocked_manager = MagicMock()
234 with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'):232 with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'):
235 importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verse.csv')233 importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verse.csv')
236 type(importer).application = PropertyMock()
237 importer.get_book_name = MagicMock()234 importer.get_book_name = MagicMock()
238 importer.session = MagicMock()235 importer.session = MagicMock()
239 importer.stop_import_flag = True236 importer.stop_import_flag = True
240 importer.wizard = MagicMock()237 importer.wizard = MagicMock()
241238
242 # WHEN: Calling process_verses239 # WHEN: Calling process_verses
243 result = importer.process_verses([], [])240 result = importer.process_verses(['Dummy Verse'], [])
244241
245 # THEN: get_book_name should not be called and the return value should be None242 # THEN: get_book_name should not be called and the return value should be None
246 self.assertFalse(importer.get_book_name.called)243 self.assertFalse(importer.get_book_name.called)
247 importer.wizard.increment_progress_bar.assert_called_once_with('Importing verses... done.')
248 importer.application.process_events.assert_called_once_with()
249 self.assertIsNone(result)244 self.assertIsNone(result)
250245
251 def process_verses_successful_test(self):246 def process_verses_successful_test(self):
@@ -257,7 +252,6 @@
257 with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'),\252 with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'),\
258 patch('openlp.plugins.bibles.lib.importers.csvbible.translate'):253 patch('openlp.plugins.bibles.lib.importers.csvbible.translate'):
259 importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verse.csv')254 importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verse.csv')
260 type(importer).application = PropertyMock()
261 importer.create_verse = MagicMock()255 importer.create_verse = MagicMock()
262 importer.get_book = MagicMock(return_value=Book('1', '1', '1. Mosebog', '1Mos'))256 importer.get_book = MagicMock(return_value=Book('1', '1', '1. Mosebog', '1Mos'))
263 importer.get_book_name = MagicMock(return_value='1. Mosebog')257 importer.get_book_name = MagicMock(return_value='1. Mosebog')
@@ -280,7 +274,6 @@
280 [call('1', 1, 1, 'I Begyndelsen skabte Gud Himmelen og Jorden.'),274 [call('1', 1, 1, 'I Begyndelsen skabte Gud Himmelen og Jorden.'),
281 call('1', 1, 2, 'Og Jorden var øde og tom, og der var Mørke over Verdensdybet. '275 call('1', 1, 2, 'Og Jorden var øde og tom, og der var Mørke over Verdensdybet. '
282 'Men Guds Ånd svævede over Vandene.')])276 'Men Guds Ånd svævede over Vandene.')])
283 importer.application.process_events.assert_called_once_with()
284277
285 def do_import_invalid_language_id_test(self):278 def do_import_invalid_language_id_test(self):
286 """279 """
@@ -288,73 +281,16 @@
288 """281 """
289 # GIVEN: An instance of CSVBible and a mocked get_language which simulates the user cancelling the language box282 # GIVEN: An instance of CSVBible and a mocked get_language which simulates the user cancelling the language box
290 mocked_manager = MagicMock()283 mocked_manager = MagicMock()
291 with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'),\284 with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'):
292 patch('openlp.plugins.bibles.lib.importers.csvbible.log') as mocked_log:
293 importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verse.csv')285 importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verse.csv')
294 importer.get_language = MagicMock(return_value=None)286 importer.get_language = MagicMock(return_value=None)
295287
296 # WHEN: Calling do_import288 # WHEN: Calling do_import
297 result = importer.do_import('Bible Name')289 result = importer.do_import('Bible Name')
298290
299 # THEN: The log.exception method should have been called to show that it reached the except clause.291 # THEN: The False should be returned.
300 # False should be returned.
301 importer.get_language.assert_called_once_with('Bible Name')292 importer.get_language.assert_called_once_with('Bible Name')
302 mocked_log.exception.assert_called_once_with('Could not import CSV bible')293 self.assertFalse(result)
303 self.assertFalse(result)
304
305 def do_import_stop_import_test(self):
306 """
307 Test do_import when the import is stopped
308 """
309 # GIVEN: An instance of CSVBible with stop_import set to True
310 mocked_manager = MagicMock()
311 with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'),\
312 patch('openlp.plugins.bibles.lib.importers.csvbible.log') as mocked_log:
313 importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verse.csv')
314 importer.get_language = MagicMock(return_value=10)
315 importer.parse_csv_file = MagicMock(return_value=['Book 1', 'Book 2', 'Book 3'])
316 importer.process_books = MagicMock()
317 importer.stop_import_flag = True
318 importer.wizard = MagicMock()
319
320 # WHEN: Calling do_import
321 result = importer.do_import('Bible Name')
322
323 # THEN: log.exception should not be called, parse_csv_file should only be called once,
324 # and False should be returned.
325 self.assertFalse(mocked_log.exception.called)
326 importer.parse_csv_file.assert_called_once_with('books.csv', Book)
327 importer.process_books.assert_called_once_with(['Book 1', 'Book 2', 'Book 3'])
328 self.assertFalse(result)
329
330 def do_import_stop_import_2_test(self):
331 """
332 Test do_import when the import is stopped
333 """
334 # GIVEN: An instance of CSVBible with stop_import which is True the second time of calling
335 mocked_manager = MagicMock()
336 with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'),\
337 patch('openlp.plugins.bibles.lib.importers.csvbible.log') as mocked_log:
338 CSVBible.stop_import_flag = PropertyMock(side_effect=[False, True])
339 importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verses.csv')
340 importer.get_language = MagicMock(return_value=10)
341 importer.parse_csv_file = MagicMock(side_effect=[['Book 1'], ['Verse 1']])
342 importer.process_books = MagicMock(return_value=['Book 1'])
343 importer.process_verses = MagicMock(return_value=['Verse 1'])
344 importer.wizard = MagicMock()
345
346 # WHEN: Calling do_import
347 result = importer.do_import('Bible Name')
348
349 # THEN: log.exception should not be called, parse_csv_file should be called twice,
350 # and False should be returned.
351 self.assertFalse(mocked_log.exception.called)
352 self.assertEqual(importer.parse_csv_file.mock_calls, [call('books.csv', Book), call('verses.csv', Verse)])
353 importer.process_verses.assert_called_once_with(['Verse 1'], ['Book 1'])
354 self.assertFalse(result)
355
356 # Cleanup
357 del CSVBible.stop_import_flag
358294
359 def do_import_success_test(self):295 def do_import_success_test(self):
360 """296 """
@@ -362,8 +298,7 @@
362 """298 """
363 # GIVEN: An instance of CSVBible299 # GIVEN: An instance of CSVBible
364 mocked_manager = MagicMock()300 mocked_manager = MagicMock()
365 with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'),\301 with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'):
366 patch('openlp.plugins.bibles.lib.importers.csvbible.log') as mocked_log:
367 importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verses.csv')302 importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verses.csv')
368 importer.get_language = MagicMock(return_value=10)303 importer.get_language = MagicMock(return_value=10)
369 importer.parse_csv_file = MagicMock(side_effect=[['Book 1'], ['Verse 1']])304 importer.parse_csv_file = MagicMock(side_effect=[['Book 1'], ['Verse 1']])
@@ -376,9 +311,8 @@
376 # WHEN: Calling do_import311 # WHEN: Calling do_import
377 result = importer.do_import('Bible Name')312 result = importer.do_import('Bible Name')
378313
379 # THEN: log.exception should not be called, parse_csv_file should be called twice,314 # THEN: parse_csv_file should be called twice,
380 # and True should be returned.315 # and True should be returned.
381 self.assertFalse(mocked_log.exception.called)
382 self.assertEqual(importer.parse_csv_file.mock_calls, [call('books.csv', Book), call('verses.csv', Verse)])316 self.assertEqual(importer.parse_csv_file.mock_calls, [call('books.csv', Book), call('verses.csv', Verse)])
383 importer.process_books.assert_called_once_with(['Book 1'])317 importer.process_books.assert_called_once_with(['Book 1'])
384 importer.process_verses.assert_called_once_with(['Verse 1'], ['Book 1'])318 importer.process_verses.assert_called_once_with(['Verse 1'], ['Book 1'])
@@ -413,6 +347,6 @@
413 # THEN: The create_verse() method should have been called with each verse in the file.347 # THEN: The create_verse() method should have been called with each verse in the file.
414 self.assertTrue(importer.create_verse.called)348 self.assertTrue(importer.create_verse.called)
415 for verse_tag, verse_text in test_data['verses']:349 for verse_tag, verse_text in test_data['verses']:
416 importer.create_verse.assert_any_call(importer.get_book().id, '1', verse_tag, verse_text)350 importer.create_verse.assert_any_call(importer.get_book().id, 1, verse_tag, verse_text)
417 importer.create_book.assert_any_call('1. Mosebog', importer.get_book_ref_id_by_name(), 1)351 importer.create_book.assert_any_call('1. Mosebog', importer.get_book_ref_id_by_name(), 1)
418 importer.create_book.assert_any_call('1. Krønikebog', importer.get_book_ref_id_by_name(), 1)352 importer.create_book.assert_any_call('1. Krønikebog', importer.get_book_ref_id_by_name(), 1)
419353
=== modified file 'tests/functional/openlp_plugins/bibles/test_db.py'
--- tests/functional/openlp_plugins/bibles/test_db.py 2016-08-03 20:10:41 +0000
+++ tests/functional/openlp_plugins/bibles/test_db.py 2016-09-09 21:59:44 +0000
@@ -25,63 +25,9 @@
2525
26from unittest import TestCase26from unittest import TestCase
2727
28from openlp.plugins.bibles.lib.db import BibleDB
29from tests.functional import MagicMock, patch
30
3128
32class TestBibleDB(TestCase):29class TestBibleDB(TestCase):
33 """30 """
34 Test the functions in the BibleDB class.31 Test the functions in the BibleDB class.
35 """32 """
3633 pass
37 def test_get_language_canceled(self):
38 """
39 Test the BibleDB.get_language method when the user rejects the dialog box
40 """
41 # GIVEN: A mocked LanguageForm with an exec method which returns QtDialog.Rejected and an instance of BibleDB
42 with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'),\
43 patch('openlp.plugins.bibles.forms.LanguageForm') as mocked_language_form:
44
45 # The integer value of QtDialog.Rejected is 0. Using the enumeration causes a seg fault for some reason
46 mocked_language_form_instance = MagicMock(**{'exec.return_value': 0})
47 mocked_language_form.return_value = mocked_language_form_instance
48 mocked_parent = MagicMock()
49 instance = BibleDB(mocked_parent)
50 mocked_wizard = MagicMock()
51 instance.wizard = mocked_wizard
52
53 # WHEN: Calling get_language()
54 result = instance.get_language()
55
56 # THEN: get_language() should return False
57 mocked_language_form.assert_called_once_with(mocked_wizard)
58 mocked_language_form_instance.exec.assert_called_once_with(None)
59 self.assertFalse(result, 'get_language() should return False if the user rejects the dialog box')
60
61 def test_get_language_accepted(self):
62 """
63 Test the BibleDB.get_language method when the user accepts the dialog box
64 """
65 # GIVEN: A mocked LanguageForm with an exec method which returns QtDialog.Accepted an instance of BibleDB and
66 # a combobox with the selected item data as 10
67 with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'), \
68 patch('openlp.plugins.bibles.lib.db.BibleDB.save_meta'), \
69 patch('openlp.plugins.bibles.forms.LanguageForm') as mocked_language_form:
70
71 # The integer value of QtDialog.Accepted is 1. Using the enumeration causes a seg fault for some reason
72 mocked_language_form_instance = MagicMock(**{'exec.return_value': 1,
73 'language_combo_box.itemData.return_value': 10})
74 mocked_language_form.return_value = mocked_language_form_instance
75 mocked_parent = MagicMock()
76 instance = BibleDB(mocked_parent)
77 mocked_wizard = MagicMock()
78 instance.wizard = mocked_wizard
79
80 # WHEN: Calling get_language()
81 result = instance.get_language('Bible Name')
82
83 # THEN: get_language() should return the id of the selected language in the combo box
84 mocked_language_form.assert_called_once_with(mocked_wizard)
85 mocked_language_form_instance.exec.assert_called_once_with('Bible Name')
86 self.assertEqual(result, 10, 'get_language() should return the id of the language the user has chosen when '
87 'they accept the dialog box')
8834
=== modified file 'tests/functional/openlp_plugins/bibles/test_opensongimport.py'
--- tests/functional/openlp_plugins/bibles/test_opensongimport.py 2016-08-09 20:45:25 +0000
+++ tests/functional/openlp_plugins/bibles/test_opensongimport.py 2016-09-09 21:59:44 +0000
@@ -23,32 +23,38 @@
23This module contains tests for the OpenSong Bible importer.23This module contains tests for the OpenSong Bible importer.
24"""24"""
2525
26import json
26import os27import os
27import json
28from unittest import TestCase28from unittest import TestCase
2929
30from tests.functional import MagicMock, patch30from lxml import objectify
31from openlp.plugins.bibles.lib.importers.opensong import OpenSongBible31
32from openlp.plugins.bibles.lib.db import BibleDB32from tests.functional import MagicMock, patch, call
33from tests.helpers.testmixin import TestMixin
34from openlp.core.common import Registry
35from openlp.plugins.bibles.lib.importers.opensong import OpenSongBible, get_text, parse_chapter_number
36from openlp.plugins.bibles.lib.bibleimport import BibleImport
3337
34TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__),38TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__),
35 '..', '..', '..', 'resources', 'bibles'))39 '..', '..', '..', 'resources', 'bibles'))
3640
3741
38class TestOpenSongImport(TestCase):42class TestOpenSongImport(TestCase, TestMixin):
39 """43 """
40 Test the functions in the :mod:`opensongimport` module.44 Test the functions in the :mod:`opensongimport` module.
41 """45 """
4246
43 def setUp(self):47 def setUp(self):
44 self.registry_patcher = patch('openlp.plugins.bibles.lib.db.Registry')48 self.find_and_create_book_patch = patch.object(BibleImport, 'find_and_create_book')
45 self.registry_patcher.start()49 self.addCleanup(self.find_and_create_book_patch.stop)
50 self.mocked_find_and_create_book = self.find_and_create_book_patch.start()
46 self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager')51 self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager')
52 self.addCleanup(self.manager_patcher.stop)
47 self.manager_patcher.start()53 self.manager_patcher.start()
4854 self.setup_application()
49 def tearDown(self):55 self.app.process_events = MagicMock()
50 self.registry_patcher.stop()56 Registry.create()
51 self.manager_patcher.stop()57 Registry().register('application', self.app)
5258
53 def test_create_importer(self):59 def test_create_importer(self):
54 """60 """
@@ -61,7 +67,332 @@
61 importer = OpenSongBible(mocked_manager, path='.', name='.', filename='')67 importer = OpenSongBible(mocked_manager, path='.', name='.', filename='')
6268
63 # THEN: The importer should be an instance of BibleDB69 # THEN: The importer should be an instance of BibleDB
64 self.assertIsInstance(importer, BibleDB)70 self.assertIsInstance(importer, BibleImport)
71
72 def get_text_no_text_test(self):
73 """
74 Test that get_text handles elements containing text in a combination of text and tail attributes
75 """
76 # GIVEN: Some test data which contains an empty element and an instance of OpenSongBible
77 test_data = objectify.fromstring('<element></element>')
78
79 # WHEN: Calling get_text
80 result = get_text(test_data)
81
82 # THEN: A blank string should be returned
83 self.assertEqual(result, '')
84
85 def get_text_text_test(self):
86 """
87 Test that get_text handles elements containing text in a combination of text and tail attributes
88 """
89 # GIVEN: Some test data which contains all possible permutation of text and tail text possible and an instance
90 # of OpenSongBible
91 test_data = objectify.fromstring('<element>Element text '
92 '<sub_text_tail>sub_text_tail text </sub_text_tail>sub_text_tail tail '
93 '<sub_text>sub_text text </sub_text>'
94 '<sub_tail></sub_tail>sub_tail tail</element>')
95
96 # WHEN: Calling get_text
97 result = get_text(test_data)
98
99 # THEN: The text returned should be as expected
100 self.assertEqual(result, 'Element text sub_text_tail text sub_text_tail tail sub_text text sub_tail tail')
101
102 def parse_chapter_number_test(self):
103 """
104 Test parse_chapter_number when supplied with chapter number and an instance of OpenSongBible
105 """
106 # GIVEN: The number 10 represented as a string
107 # WHEN: Calling parse_chapter_nnumber
108 result = parse_chapter_number('10', 0)
109
110 # THEN: The 10 should be returned as an Int
111 self.assertEqual(result, 10)
112
113 def parse_chapter_number_empty_attribute_test(self):
114 """
115 Testparse_chapter_number when the chapter number is an empty string. (Bug #1074727)
116 """
117 # GIVEN: An empty string, and the previous chapter number set as 12 and an instance of OpenSongBible
118 # WHEN: Calling parse_chapter_number
119 result = parse_chapter_number('', 12)
120
121 # THEN: parse_chapter_number should increment the previous verse number
122 self.assertEqual(result, 13)
123
124 def parse_verse_number_valid_verse_no_test(self):
125 """
126 Test parse_verse_number when supplied with a valid verse number
127 """
128 # GIVEN: An instance of OpenSongBible, the number 15 represented as a string and an instance of OpenSongBible
129 importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
130
131 # WHEN: Calling parse_verse_number
132 result = importer.parse_verse_number('15', 0)
133
134 # THEN: parse_verse_number should return the verse number
135 self.assertEqual(result, 15)
136
137 def parse_verse_number_verse_range_test(self):
138 """
139 Test parse_verse_number when supplied with a verse range
140 """
141 # GIVEN: An instance of OpenSongBible, and the range 24-26 represented as a string
142 importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
143
144 # WHEN: Calling parse_verse_number
145 result = importer.parse_verse_number('24-26', 0)
146
147 # THEN: parse_verse_number should return the first verse number in the range
148 self.assertEqual(result, 24)
149
150 def parse_verse_number_invalid_verse_no_test(self):
151 """
152 Test parse_verse_number when supplied with a invalid verse number
153 """
154 # GIVEN: An instance of OpenSongBible, a non numeric string represented as a string
155 importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
156
157 # WHEN: Calling parse_verse_number
158 result = importer.parse_verse_number('invalid', 41)
159
160 # THEN: parse_verse_number should increment the previous verse number
161 self.assertEqual(result, 42)
162
163 def parse_verse_number_empty_attribute_test(self):
164 """
165 Test parse_verse_number when the verse number is an empty string. (Bug #1074727)
166 """
167 # GIVEN: An instance of OpenSongBible, an empty string, and the previous verse number set as 14
168 importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
169 # WHEN: Calling parse_verse_number
170 result = importer.parse_verse_number('', 14)
171
172 # THEN: parse_verse_number should increment the previous verse number
173 self.assertEqual(result, 15)
174
175 def parse_verse_number_invalid_type_test(self):
176 """
177 Test parse_verse_number when the verse number is an invalid type)
178 """
179 with patch.object(OpenSongBible, 'log_warning')as mocked_log_warning:
180 # GIVEN: An instanceofOpenSongBible, a Tuple, and the previous verse number set as 12
181 importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
182
183 # WHEN: Calling parse_verse_number
184 result = importer.parse_verse_number((1, 2, 3), 12)
185
186 # THEN: parse_verse_number should log the verse number it was called with increment the previous verse
187 # number
188 mocked_log_warning.assert_called_once_with('Illegal verse number: (1, 2, 3)')
189 self.assertEqual(result, 13)
190
191 def process_books_stop_import_test(self):
192 """
193 Test process_books when stop_import is set to True
194 """
195 # GIVEN: An instance of OpenSongBible
196 importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
197
198 # WHEN: stop_import_flag is set to True
199 importer.stop_import_flag = True
200 importer.process_books(['Book'])
201
202 # THEN: find_and_create_book should not have been called
203 self.assertFalse(self.mocked_find_and_create_book.called)
204
205 def process_books_completes_test(self):
206 """
207 Test process_books when it processes all books
208 """
209 # GIVEN: An instance of OpenSongBible Importer and two mocked books
210 self.mocked_find_and_create_book.side_effect = ['db_book1', 'db_book2']
211 with patch.object(OpenSongBible, 'process_chapters') as mocked_process_chapters:
212 importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
213
214 book1 = MagicMock()
215 book1.attrib = {'n': 'Name1'}
216 book1.c = 'Chapter1'
217 book2 = MagicMock()
218 book2.attrib = {'n': 'Name2'}
219 book2.c = 'Chapter2'
220 importer.language_id = 10
221 importer.session = MagicMock()
222 importer.stop_import_flag = False
223
224 # WHEN: Calling process_books with the two books
225 importer.process_books([book1, book2])
226
227 # THEN: find_and_create_book and process_books should be called with the details from the mocked books
228 self.assertEqual(self.mocked_find_and_create_book.call_args_list,
229 [call('Name1', 2, 10), call('Name2', 2, 10)])
230 self.assertEqual(mocked_process_chapters.call_args_list,
231 [call('db_book1', 'Chapter1'), call('db_book2', 'Chapter2')])
232 self.assertEqual(importer.session.commit.call_count, 2)
233
234 def process_chapters_stop_import_test(self):
235 """
236 Test process_chapters when stop_import is set to True
237 """
238 # GIVEN: An isntance of OpenSongBible
239 importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
240 importer.parse_chapter_number = MagicMock()
241
242 # WHEN: stop_import_flag is set to True
243 importer.stop_import_flag = True
244 importer.process_chapters('Book', ['Chapter1'])
245
246 # THEN: importer.parse_chapter_number not have been called
247 self.assertFalse(importer.parse_chapter_number.called)
248
249 @patch('openlp.plugins.bibles.lib.importers.opensong.parse_chapter_number', **{'side_effect': [1, 2]})
250 def process_chapters_completes_test(self, mocked_parse_chapter_number):
251 """
252 Test process_chapters when it completes
253 """
254 # GIVEN: An instance of OpenSongBible
255 importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
256 importer.wizard = MagicMock()
257
258 # WHEN: called with some valid data
259 book = MagicMock()
260 book.name = "Book"
261 chapter1 = MagicMock()
262 chapter1.attrib = {'n': '1'}
263 chapter1.c = 'Chapter1'
264 chapter1.v = ['Chapter1 Verses']
265 chapter2 = MagicMock()
266 chapter2.attrib = {'n': '2'}
267 chapter2.c = 'Chapter2'
268 chapter2.v = ['Chapter2 Verses']
269
270 importer.process_verses = MagicMock()
271 importer.stop_import_flag = False
272 importer.process_chapters(book, [chapter1, chapter2])
273
274 # THEN: parse_chapter_number, process_verses and increment_process_bar should have been called
275 self.assertEqual(mocked_parse_chapter_number.call_args_list, [call('1', 0), call('2', 1)])
276 self.assertEqual(
277 importer.process_verses.call_args_list,
278 [call(book, 1, ['Chapter1 Verses']), call(book, 2, ['Chapter2 Verses'])])
279 self.assertEqual(importer.wizard.increment_progress_bar.call_args_list,
280 [call('Importing Book 1...'), call('Importing Book 2...')])
281
282 def process_verses_stop_import_test(self):
283 """
284 Test process_verses when stop_import is set to True
285 """
286 # GIVEN: An isntance of OpenSongBible
287 importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
288 importer.parse_verse_number = MagicMock()
289
290 # WHEN: stop_import_flag is set to True
291 importer.stop_import_flag = True
292 importer.process_verses('Book', 1, 'Verses')
293
294 # THEN: importer.parse_verse_number not have been called
295 self.assertFalse(importer.parse_verse_number.called)
296
297 def process_verses_completes_test(self):
298 """
299 Test process_verses when it completes
300 """
301 with patch('openlp.plugins.bibles.lib.importers.opensong.get_text',
302 **{'side_effect': ['Verse1 Text', 'Verse2 Text']}) as mocked_get_text, \
303 patch.object(OpenSongBible, 'parse_verse_number',
304 **{'side_effect': [1, 2]}) as mocked_parse_verse_number:
305 # GIVEN: An instance of OpenSongBible
306 importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
307 importer.wizard = MagicMock()
308
309 # WHEN: called with some valid data
310 book = MagicMock()
311 book.id = 1
312 verse1 = MagicMock()
313 verse1.attrib = {'n': '1'}
314 verse1.c = 'Chapter1'
315 verse1.v = ['Chapter1 Verses']
316 verse2 = MagicMock()
317 verse2.attrib = {'n': '2'}
318 verse2.c = 'Chapter2'
319 verse2.v = ['Chapter2 Verses']
320
321 importer.create_verse = MagicMock()
322 importer.stop_import_flag = False
323 importer.process_verses(book, 1, [verse1, verse2])
324
325 # THEN: parse_chapter_number, process_verses and increment_process_bar should have been called
326 self.assertEqual(mocked_parse_verse_number.call_args_list, [call('1', 0), call('2', 1)])
327 self.assertEqual(mocked_get_text.call_args_list, [call(verse1), call(verse2)])
328 self.assertEqual(
329 importer.create_verse.call_args_list,
330 [call(1, 1, 1, 'Verse1 Text'), call(1, 1, 2, 'Verse2 Text')])
331
332 def do_import_parse_xml_fails_test(self):
333 """
334 Test do_import when parse_xml fails (returns None)
335 """
336 # GIVEN: An instance of OpenSongBible and a mocked parse_xml which returns False
337 with patch.object(OpenSongBible, 'log_debug'), \
338 patch.object(OpenSongBible, 'validate_xml_file'), \
339 patch.object(OpenSongBible, 'parse_xml', return_value=None), \
340 patch.object(OpenSongBible, 'get_language_id') as mocked_language_id:
341 importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
342
343 # WHEN: Calling do_import
344 result = importer.do_import()
345
346 # THEN: do_import should return False and get_language_id should have not been called
347 self.assertFalse(result)
348 self.assertFalse(mocked_language_id.called)
349
350 def do_import_no_language_test(self):
351 """
352 Test do_import when the user cancels the language selection dialog
353 """
354 # GIVEN: An instance of OpenSongBible and a mocked get_language which returns False
355 with patch.object(OpenSongBible, 'log_debug'), \
356 patch.object(OpenSongBible, 'validate_xml_file'), \
357 patch.object(OpenSongBible, 'parse_xml'), \
358 patch.object(OpenSongBible, 'get_language_id', return_value=False), \
359 patch.object(OpenSongBible, 'process_books') as mocked_process_books:
360 importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
361
362 # WHEN: Calling do_import
363 result = importer.do_import()
364
365 # THEN: do_import should return False and process_books should have not been called
366 self.assertFalse(result)
367 self.assertFalse(mocked_process_books.called)
368
369 def do_import_completes_test(self):
370 """
371 Test do_import when it completes successfully
372 """
373 # GIVEN: An instance of OpenSongBible
374 with patch.object(OpenSongBible, 'log_debug'), \
375 patch.object(OpenSongBible, 'validate_xml_file'), \
376 patch.object(OpenSongBible, 'parse_xml'), \
377 patch.object(OpenSongBible, 'get_language_id', return_value=10), \
378 patch.object(OpenSongBible, 'process_books'):
379 importer = OpenSongBible(MagicMock(), path='.', name='.', filename='')
380
381 # WHEN: Calling do_import
382 result = importer.do_import()
383
384 # THEN: do_import should return True
385 self.assertTrue(result)
386
387
388class TestOpenSongImportFileImports(TestCase, TestMixin):
389 """
390 Test the functions in the :mod:`opensongimport` module.
391 """
392 def setUp(self):
393 self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager')
394 self.addCleanup(self.manager_patcher.stop)
395 self.manager_patcher.start()
65396
66 def test_file_import(self):397 def test_file_import(self):
67 """398 """
@@ -92,22 +423,3 @@
92 self.assertTrue(importer.create_verse.called)423 self.assertTrue(importer.create_verse.called)
93 for verse_tag, verse_text in test_data['verses']:424 for verse_tag, verse_text in test_data['verses']:
94 importer.create_verse.assert_any_call(importer.create_book().id, 1, int(verse_tag), verse_text)425 importer.create_verse.assert_any_call(importer.create_book().id, 1, int(verse_tag), verse_text)
95
96 def test_zefania_import_error(self):
97 """
98 Test that we give an error message if trying to import a zefania bible
99 """
100 # GIVEN: A mocked out "manager" and mocked out critical_error_message_box and an import
101 with patch('openlp.plugins.bibles.lib.importers.opensong.critical_error_message_box') as \
102 mocked_critical_error_message_box:
103 mocked_manager = MagicMock()
104 importer = OpenSongBible(mocked_manager, path='.', name='.', filename='')
105
106 # WHEN: An trying to import a zefania bible
107 importer.filename = os.path.join(TEST_PATH, 'zefania-dk1933.xml')
108 importer.do_import()
109
110 # THEN: The importer should have "shown" an error message
111 mocked_critical_error_message_box.assert_called_with(message='Incorrect Bible file type supplied. '
112 'This looks like a Zefania XML bible, '
113 'please use the Zefania import option.')
114426
=== modified file 'tests/functional/openlp_plugins/bibles/test_osisimport.py'
--- tests/functional/openlp_plugins/bibles/test_osisimport.py 2016-08-09 20:45:25 +0000
+++ tests/functional/openlp_plugins/bibles/test_osisimport.py 2016-09-09 21:59:44 +0000
@@ -27,29 +27,35 @@
27import json27import json
28from unittest import TestCase28from unittest import TestCase
2929
30from tests.functional import MagicMock, patch30from tests.functional import MagicMock, call, patch
31from openlp.plugins.bibles.lib.bibleimport import BibleImport
32from openlp.plugins.bibles.lib.db import BibleDB
31from openlp.plugins.bibles.lib.importers.osis import OSISBible33from openlp.plugins.bibles.lib.importers.osis import OSISBible
32from openlp.plugins.bibles.lib.db import BibleDB
3334
34TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__),35TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'bibles'))
35 '..', '..', '..', 'resources', 'bibles'))
3636
3737
38class TestOsisImport(TestCase):38class TestOsisImport(TestCase):
39 """39 """
40 Test the functions in the :mod:`osisimport` module.40 Test the functions in the :mod:`osisimport` module.
41 """41 """
42
43 def setUp(self):42 def setUp(self):
44 self.registry_patcher = patch('openlp.plugins.bibles.lib.db.Registry')43 self.etree_patcher = patch('openlp.plugins.bibles.lib.importers.osis.etree')
44 self.addCleanup(self.etree_patcher.stop)
45 self.mocked_etree = self.etree_patcher.start()
46 self.create_verse_patcher = patch('openlp.plugins.bibles.lib.db.BibleDB.create_verse')
47 self.addCleanup(self.create_verse_patcher.stop)
48 self.mocked_create_verse = self.create_verse_patcher.start()
49 self.find_and_create_book_patch = patch.object(BibleImport, 'find_and_create_book')
50 self.addCleanup(self.find_and_create_book_patch.stop)
51 self.mocked_find_and_create_book = self.find_and_create_book_patch.start()
52 self.registry_patcher = patch('openlp.plugins.bibles.lib.bibleimport.Registry')
53 self.addCleanup(self.registry_patcher.stop)
45 self.registry_patcher.start()54 self.registry_patcher.start()
46 self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager')55 self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager')
56 self.addCleanup(self.manager_patcher.stop)
47 self.manager_patcher.start()57 self.manager_patcher.start()
4858
49 def tearDown(self):
50 self.registry_patcher.stop()
51 self.manager_patcher.stop()
52
53 def test_create_importer(self):59 def test_create_importer(self):
54 """60 """
55 Test creating an instance of the OSIS file importer61 Test creating an instance of the OSIS file importer
@@ -63,6 +69,353 @@
63 # THEN: The importer should be an instance of BibleDB69 # THEN: The importer should be an instance of BibleDB
64 self.assertIsInstance(importer, BibleDB)70 self.assertIsInstance(importer, BibleDB)
6571
72 def process_books_stop_import_test(self):
73 """
74 Test process_books when stop_import is set to True
75 """
76 # GIVEN: An instance of OSISBible adn some mocked data
77 importer = OSISBible(MagicMock(), path='.', name='.', filename='')
78 mocked_data = MagicMock(**{'xpath.return_value': ['Book']})
79
80 # WHEN: stop_import_flag is set to True and process_books is called
81 importer.stop_import_flag = True
82 importer.process_books(mocked_data)
83
84 # THEN: find_and_create_book should not have been called
85 self.assertFalse(self.mocked_find_and_create_book.called)
86
87 def process_books_completes_test(self):
88 """
89 Test process_books when it processes all books
90 """
91 # GIVEN: An instance of OSISBible Importer and two mocked books
92 self.mocked_find_and_create_book.side_effect = ['db_book1', 'db_book2']
93 with patch.object(OSISBible, 'process_chapters') as mocked_process_chapters:
94 importer = OSISBible(MagicMock(), path='.', name='.', filename='')
95
96 book1 = MagicMock()
97 book1.get.return_value = 'Name1'
98 book2 = MagicMock()
99 book2.get.return_value = 'Name2'
100 mocked_data = MagicMock(**{'xpath.return_value': [book1, book2]})
101 importer.language_id = 10
102 importer.session = MagicMock()
103 importer.stop_import_flag = False
104
105 # WHEN: Calling process_books with the two books
106 importer.process_books(mocked_data)
107
108 # THEN: find_and_create_book and process_books should be called with the details from the mocked books
109 self.assertEqual(self.mocked_find_and_create_book.call_args_list,
110 [call('Name1', 2, 10), call('Name2', 2, 10)])
111 self.assertEqual(mocked_process_chapters.call_args_list,
112 [call('db_book1', book1), call('db_book2', book2)])
113 self.assertEqual(importer.session.commit.call_count, 2)
114
115 def process_chapters_verse_in_chapter_verse_text_test(self):
116 """
117 Test process_chapters when supplied with an etree element with a verse element nested in it
118 """
119 with patch('openlp.plugins.bibles.lib.importers.osis.verse_in_chapter', return_value=True), \
120 patch('openlp.plugins.bibles.lib.importers.osis.text_in_verse', return_value=True), \
121 patch.object(OSISBible, 'set_current_chapter') as mocked_set_current_chapter, \
122 patch.object(OSISBible, 'process_verse') as mocked_process_verse:
123
124 # GIVEN: Some test data and an instance of OSISBible
125 test_book = MagicMock()
126 test_verse = MagicMock()
127 test_verse.tail = '\n ' # Whitespace
128 test_verse.text = 'Verse Text'
129 test_chapter = MagicMock()
130 test_chapter.__iter__.return_value = [test_verse]
131 test_chapter.get.side_effect = lambda x: {'osisID': '1.2.4', 'sID': '999'}.get(x)
132 importer = OSISBible(MagicMock(), path='.', name='.', filename='')
133
134 # WHEN: Calling process_chapters
135 importer.process_chapters(test_book, [test_chapter])
136
137 # THEN: set_current_chapter and process_verse should have been called with the test data
138 mocked_set_current_chapter.assert_called_once_with(test_book.name, 2)
139 mocked_process_verse.assert_called_once_with(test_book, 2, test_verse)
140
141 def process_chapters_verse_in_chapter_verse_milestone_test(self):
142 """
143 Test process_chapters when supplied with an etree element with a verse element nested, when the verse system is
144 based on milestones
145 """
146 with patch('openlp.plugins.bibles.lib.importers.osis.verse_in_chapter', return_value=True), \
147 patch('openlp.plugins.bibles.lib.importers.osis.text_in_verse', return_value=False), \
148 patch.object(OSISBible, 'set_current_chapter') as mocked_set_current_chapter, \
149 patch.object(OSISBible, 'process_verse') as mocked_process_verse:
150
151 # GIVEN: Some test data and an instance of OSISBible
152 test_book = MagicMock()
153 test_verse = MagicMock()
154 test_verse.tail = '\n ' # Whitespace
155 test_verse.text = 'Verse Text'
156 test_chapter = MagicMock()
157 test_chapter.__iter__.return_value = [test_verse]
158 test_chapter.get.side_effect = lambda x: {'osisID': '1.2.4', 'sID': '999'}.get(x)
159 importer = OSISBible(MagicMock(), path='.', name='.', filename='')
160
161 # WHEN: Calling process_chapters
162 importer.process_chapters(test_book, [test_chapter])
163
164 # THEN: set_current_chapter and process_verse should have been called with the test data
165 mocked_set_current_chapter.assert_called_once_with(test_book.name, 2)
166 mocked_process_verse.assert_called_once_with(test_book, 2, test_verse, use_milestones=True)
167
168 def process_chapters_milestones_chapter_no_sid_test(self):
169 """
170 Test process_chapters when supplied with an etree element with a chapter and verse element in the milestone
171 configuration, where the chapter is the "closing" milestone. (Missing the sID attribute)
172 """
173 with patch('openlp.plugins.bibles.lib.importers.osis.verse_in_chapter', return_value=False), \
174 patch.object(OSISBible, 'set_current_chapter') as mocked_set_current_chapter, \
175 patch.object(OSISBible, 'process_verse') as mocked_process_verse:
176
177 # GIVEN: Some test data and an instance of OSISBible
178 test_book = MagicMock()
179 test_chapter = MagicMock()
180 test_chapter.tag = '{http://www.bibletechnologies.net/2003/OSIS/namespace}chapter'
181 test_chapter.get.side_effect = lambda x: {'osisID': '1.2.4'}.get(x)
182
183 # WHEN: Calling process_chapters
184 importer = OSISBible(MagicMock(), path='.', name='.', filename='')
185 importer.process_chapters(test_book, [test_chapter])
186
187 # THEN: neither set_current_chapter or process_verse should have been called
188 self.assertFalse(mocked_set_current_chapter.called)
189 self.assertFalse(mocked_process_verse.called)
190
191 def process_chapters_milestones_chapter_sid_test(self):
192 """
193 Test process_chapters when supplied with an etree element with a chapter and verse element in the milestone
194 configuration, where the chapter is the "opening" milestone. (Has the sID attribute)
195 """
196 with patch('openlp.plugins.bibles.lib.importers.osis.verse_in_chapter', return_value=False), \
197 patch.object(OSISBible, 'set_current_chapter') as mocked_set_current_chapter, \
198 patch.object(OSISBible, 'process_verse') as mocked_process_verse:
199
200 # GIVEN: Some test data and an instance of OSISBible
201 test_book = MagicMock()
202 test_chapter = MagicMock()
203 test_chapter.tag = '{http://www.bibletechnologies.net/2003/OSIS/namespace}chapter'
204 test_chapter.get.side_effect = lambda x: {'osisID': '1.2.4', 'sID': '999'}.get(x)
205 importer = OSISBible(MagicMock(), path='.', name='.', filename='')
206
207 # WHEN: Calling process_chapters
208 importer.process_chapters(test_book, [test_chapter])
209
210 # THEN: set_current_chapter should have been called with the test data
211 mocked_set_current_chapter.assert_called_once_with(test_book.name, 2)
212 self.assertFalse(mocked_process_verse.called)
213
214 def process_chapters_milestones_verse_tag_test(self):
215 """
216 Test process_chapters when supplied with an etree element with a chapter and verse element in the milestone
217 configuration, where the verse is the "opening" milestone. (Has the sID attribute)
218 """
219 with patch('openlp.plugins.bibles.lib.importers.osis.verse_in_chapter', return_value=False), \
220 patch.object(OSISBible, 'set_current_chapter') as mocked_set_current_chapter, \
221 patch.object(OSISBible, 'process_verse') as mocked_process_verse:
222
223 # GIVEN: Some test data and an instance of OSISBible
224 test_book = MagicMock()
225 test_verse = MagicMock()
226 test_verse.get.side_effect = lambda x: {'osisID': '1.2.4', 'sID': '999'}.get(x)
227 test_verse.tag = '{http://www.bibletechnologies.net/2003/OSIS/namespace}verse'
228 test_verse.tail = '\n ' # Whitespace
229 test_verse.text = 'Verse Text'
230
231 # WHEN: Calling process_chapters
232 importer = OSISBible(MagicMock(), path='.', name='.', filename='')
233 importer.process_chapters(test_book, [test_verse])
234
235 # THEN: process_verse should have been called with the test data
236 self.assertFalse(mocked_set_current_chapter.called)
237 mocked_process_verse.assert_called_once_with(test_book, 0, test_verse, use_milestones=True)
238
239 def process_verse_no_osis_id_test(self):
240 """
241 Test process_verse when the element supplied does not have and osisID attribute
242 """
243 # GIVEN: An instance of OSISBible, and some mocked test data
244 test_book = MagicMock()
245 test_verse = MagicMock()
246 test_verse.get.side_effect = lambda x: {}.get(x)
247 test_verse.tail = 'Verse Text'
248 test_verse.text = None
249 importer = OSISBible(MagicMock(), path='.', name='.', filename='')
250
251 # WHEN: Calling process_verse with the test data
252 importer.process_verse(test_book, 2, test_verse)
253
254 # THEN: create_verse should not have been called
255 self.assertFalse(self.mocked_create_verse.called)
256
257 def process_verse_use_milestones_no_s_id_test(self):
258 """
259 Test process_verse when called with use_milestones set to True, but the element supplied does not have and sID
260 attribute
261 """
262 # GIVEN: An instance of OSISBible, and some mocked test data
263 test_book = MagicMock()
264 test_verse = MagicMock()
265 test_verse.get.side_effect = lambda x: {}.get(x)
266 test_verse.tail = 'Verse Text'
267 test_verse.text = None
268 importer = OSISBible(MagicMock(), path='.', name='.', filename='')
269
270 # WHEN: Calling process_verse with the test data
271 importer.process_verse(test_book, 2, test_verse)
272
273 # THEN: create_verse should not have been called
274 self.assertFalse(self.mocked_create_verse.called)
275
276 def process_verse_use_milestones_no_tail_test(self):
277 """
278 Test process_verse when called with use_milestones set to True, but the element supplied does not have a 'tail'
279 """
280 # GIVEN: An instance of OSISBible, and some mocked test data
281 test_book = MagicMock()
282 test_verse = MagicMock()
283 test_verse.tail = None
284 test_verse.text = None
285 test_verse.get.side_effect = lambda x: {'osisID': '1.2.4', 'sID': '999'}.get(x)
286 importer = OSISBible(MagicMock(), path='.', name='.', filename='')
287
288 # WHEN: Calling process_verse with the test data
289 importer.process_verse(test_book, 2, test_verse, use_milestones=True)
290
291 # THEN: create_verse should not have been called
292 self.assertFalse(self.mocked_create_verse.called)
293
294 def process_verse_use_milestones_success_test(self):
295 """
296 Test process_verse when called with use_milestones set to True, and the verse element successfully imports
297 """
298 # GIVEN: An instance of OSISBible, and some mocked test data
299 test_book = MagicMock()
300 test_book.id = 1
301 test_verse = MagicMock()
302 test_verse.tail = 'Verse Text'
303 test_verse.text = None
304 test_verse.get.side_effect = lambda x: {'osisID': '1.2.4', 'sID': '999'}.get(x)
305 importer = OSISBible(MagicMock(), path='.', name='.', filename='')
306
307 # WHEN: Calling process_verse with the test data
308 importer.process_verse(test_book, 2, test_verse, use_milestones=True)
309
310 # THEN: create_verse should have been called with the test data
311 self.mocked_create_verse.assert_called_once_with(1, 2, 4, 'Verse Text')
312
313 def process_verse_no_text_test(self):
314 """
315 Test process_verse when called with an empty verse element
316 """
317 # GIVEN: An instance of OSISBible, and some mocked test data
318 test_book = MagicMock()
319 test_book.id = 1
320 test_verse = MagicMock()
321 test_verse.tail = '\n ' # Whitespace
322 test_verse.text = None
323 test_verse.get.side_effect = lambda x: {'osisID': '1.2.4', 'sID': '999'}.get(x)
324 importer = OSISBible(MagicMock(), path='.', name='.', filename='')
325
326 # WHEN: Calling process_verse with the test data
327 importer.process_verse(test_book, 2, test_verse)
328
329 # THEN: create_verse should not have been called
330 self.assertFalse(self.mocked_create_verse.called)
331
332 def process_verse_success_test(self):
333 """
334 Test process_verse when called with an element with text set
335 """
336 # GIVEN: An instance of OSISBible, and some mocked test data
337 test_book = MagicMock()
338 test_book.id = 1
339 test_verse = MagicMock()
340 test_verse.tail = '\n ' # Whitespace
341 test_verse.text = 'Verse Text'
342 test_verse.get.side_effect = lambda x: {'osisID': '1.2.4', 'sID': '999'}.get(x)
343 importer = OSISBible(MagicMock(), path='.', name='.', filename='')
344
345 # WHEN: Calling process_verse with the test data
346 importer.process_verse(test_book, 2, test_verse)
347
348 # THEN: create_verse should have been called with the test data
349 self.mocked_create_verse.assert_called_once_with(1, 2, 4, 'Verse Text')
350
351 def do_import_parse_xml_fails_test(self):
352 """
353 Test do_import when parse_xml fails (returns None)
354 """
355 # GIVEN: An instance of OpenSongBible and a mocked parse_xml which returns False
356 with patch.object(OSISBible, 'log_debug'), \
357 patch.object(OSISBible, 'validate_xml_file'), \
358 patch.object(OSISBible, 'parse_xml', return_value=None), \
359 patch.object(OSISBible, 'get_language_id') as mocked_language_id:
360 importer = OSISBible(MagicMock(), path='.', name='.', filename='')
361
362 # WHEN: Calling do_import
363 result = importer.do_import()
364
365 # THEN: do_import should return False and get_language_id should have not been called
366 self.assertFalse(result)
367 self.assertFalse(mocked_language_id.called)
368
369 def do_import_no_language_test(self):
370 """
371 Test do_import when the user cancels the language selection dialog
372 """
373 # GIVEN: An instance of OpenSongBible and a mocked get_language which returns False
374 with patch.object(OSISBible, 'log_debug'), \
375 patch.object(OSISBible, 'validate_xml_file'), \
376 patch.object(OSISBible, 'parse_xml'), \
377 patch.object(OSISBible, 'get_language_id', **{'return_value': False}), \
378 patch.object(OSISBible, 'process_books') as mocked_process_books:
379 importer = OSISBible(MagicMock(), path='.', name='.', filename='')
380
381 # WHEN: Calling do_import
382 result = importer.do_import()
383
384 # THEN: do_import should return False and process_books should have not been called
385 self.assertFalse(result)
386 self.assertFalse(mocked_process_books.called)
387
388 def do_import_completes_test(self):
389 """
390 Test do_import when it completes successfully
391 """
392 # GIVEN: An instance of OpenSongBible
393 with patch.object(OSISBible, 'log_debug'), \
394 patch.object(OSISBible, 'validate_xml_file'), \
395 patch.object(OSISBible, 'parse_xml'), \
396 patch.object(OSISBible, 'get_language_id', **{'return_value': 10}), \
397 patch.object(OSISBible, 'process_books'):
398 importer = OSISBible(MagicMock(), path='.', name='.', filename='')
399
400 # WHEN: Calling do_import
401 result = importer.do_import()
402
403 # THEN: do_import should return True
404 self.assertTrue(result)
405
406
407class TestOsisImportFileImports(TestCase):
408 """
409 Test the functions in the :mod:`osisimport` module.
410 """
411 def setUp(self):
412 self.registry_patcher = patch('openlp.plugins.bibles.lib.bibleimport.Registry')
413 self.addCleanup(self.registry_patcher.stop)
414 self.registry_patcher.start()
415 self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager')
416 self.addCleanup(self.manager_patcher.stop)
417 self.manager_patcher.start()
418
66 def test_file_import_nested_tags(self):419 def test_file_import_nested_tags(self):
67 """420 """
68 Test the actual import of OSIS Bible file, with nested chapter and verse tags421 Test the actual import of OSIS Bible file, with nested chapter and verse tags
@@ -91,7 +444,7 @@
91 # THEN: The create_verse() method should have been called with each verse in the file.444 # THEN: The create_verse() method should have been called with each verse in the file.
92 self.assertTrue(importer.create_verse.called)445 self.assertTrue(importer.create_verse.called)
93 for verse_tag, verse_text in test_data['verses']:446 for verse_tag, verse_text in test_data['verses']:
94 importer.create_verse.assert_any_call(importer.create_book().id, '1', verse_tag, verse_text)447 importer.create_verse.assert_any_call(importer.create_book().id, 1, verse_tag, verse_text)
95448
96 def test_file_import_mixed_tags(self):449 def test_file_import_mixed_tags(self):
97 """450 """
@@ -121,7 +474,7 @@
121 # THEN: The create_verse() method should have been called with each verse in the file.474 # THEN: The create_verse() method should have been called with each verse in the file.
122 self.assertTrue(importer.create_verse.called)475 self.assertTrue(importer.create_verse.called)
123 for verse_tag, verse_text in test_data['verses']:476 for verse_tag, verse_text in test_data['verses']:
124 importer.create_verse.assert_any_call(importer.create_book().id, '1', verse_tag, verse_text)477 importer.create_verse.assert_any_call(importer.create_book().id, 1, verse_tag, verse_text)
125478
126 def test_file_import_milestone_tags(self):479 def test_file_import_milestone_tags(self):
127 """480 """
@@ -151,7 +504,7 @@
151 # THEN: The create_verse() method should have been called with each verse in the file.504 # THEN: The create_verse() method should have been called with each verse in the file.
152 self.assertTrue(importer.create_verse.called)505 self.assertTrue(importer.create_verse.called)
153 for verse_tag, verse_text in test_data['verses']:506 for verse_tag, verse_text in test_data['verses']:
154 importer.create_verse.assert_any_call(importer.create_book().id, '1', verse_tag, verse_text)507 importer.create_verse.assert_any_call(importer.create_book().id, 1, verse_tag, verse_text)
155508
156 def test_file_import_empty_verse_tags(self):509 def test_file_import_empty_verse_tags(self):
157 """510 """
@@ -181,4 +534,4 @@
181 # THEN: The create_verse() method should have been called with each verse in the file.534 # THEN: The create_verse() method should have been called with each verse in the file.
182 self.assertTrue(importer.create_verse.called)535 self.assertTrue(importer.create_verse.called)
183 for verse_tag, verse_text in test_data['verses']:536 for verse_tag, verse_text in test_data['verses']:
184 importer.create_verse.assert_any_call(importer.create_book().id, '1', verse_tag, verse_text)537 importer.create_verse.assert_any_call(importer.create_book().id, 1, verse_tag, verse_text)
185538
=== modified file 'tests/functional/openlp_plugins/bibles/test_swordimport.py'
--- tests/functional/openlp_plugins/bibles/test_swordimport.py 2016-08-09 20:45:25 +0000
+++ tests/functional/openlp_plugins/bibles/test_swordimport.py 2016-09-09 21:59:44 +0000
@@ -46,7 +46,7 @@
46 """46 """
4747
48 def setUp(self):48 def setUp(self):
49 self.registry_patcher = patch('openlp.plugins.bibles.lib.db.Registry')49 self.registry_patcher = patch('openlp.plugins.bibles.lib.bibleimport.Registry')
50 self.registry_patcher.start()50 self.registry_patcher.start()
51 self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager')51 self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager')
52 self.manager_patcher.start()52 self.manager_patcher.start()
5353
=== modified file 'tests/functional/openlp_plugins/bibles/test_zefaniaimport.py'
--- tests/functional/openlp_plugins/bibles/test_zefaniaimport.py 2016-08-09 20:45:25 +0000
+++ tests/functional/openlp_plugins/bibles/test_zefaniaimport.py 2016-09-09 21:59:44 +0000
@@ -41,15 +41,13 @@
41 """41 """
4242
43 def setUp(self):43 def setUp(self):
44 self.registry_patcher = patch('openlp.plugins.bibles.lib.db.Registry')44 self.registry_patcher = patch('openlp.plugins.bibles.lib.bibleimport.Registry')
45 self.addCleanup(self.registry_patcher.stop)
45 self.registry_patcher.start()46 self.registry_patcher.start()
46 self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager')47 self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager')
48 self.addCleanup(self.manager_patcher.stop)
47 self.manager_patcher.start()49 self.manager_patcher.start()
4850
49 def tearDown(self):
50 self.registry_patcher.stop()
51 self.manager_patcher.stop()
52
53 def test_create_importer(self):51 def test_create_importer(self):
54 """52 """
55 Test creating an instance of the Zefania file importer53 Test creating an instance of the Zefania file importer
@@ -90,7 +88,7 @@
90 # THEN: The create_verse() method should have been called with each verse in the file.88 # THEN: The create_verse() method should have been called with each verse in the file.
91 self.assertTrue(importer.create_verse.called)89 self.assertTrue(importer.create_verse.called)
92 for verse_tag, verse_text in test_data['verses']:90 for verse_tag, verse_text in test_data['verses']:
93 importer.create_verse.assert_any_call(importer.create_book().id, '1', verse_tag, verse_text)91 importer.create_verse.assert_any_call(importer.create_book().id, 1, verse_tag, verse_text)
94 importer.create_book.assert_any_call('Genesis', 1, 1)92 importer.create_book.assert_any_call('Genesis', 1, 1)
9593
96 def test_file_import_no_book_name(self):94 def test_file_import_no_book_name(self):
@@ -120,5 +118,5 @@
120 # THEN: The create_verse() method should have been called with each verse in the file.118 # THEN: The create_verse() method should have been called with each verse in the file.
121 self.assertTrue(importer.create_verse.called)119 self.assertTrue(importer.create_verse.called)
122 for verse_tag, verse_text in test_data['verses']:120 for verse_tag, verse_text in test_data['verses']:
123 importer.create_verse.assert_any_call(importer.create_book().id, '1', verse_tag, verse_text)121 importer.create_verse.assert_any_call(importer.create_book().id, 1, verse_tag, verse_text)
124 importer.create_book.assert_any_call('Exodus', 2, 1)122 importer.create_book.assert_any_call('Exodus', 2, 1)
125123
=== modified file 'tests/resources/bibles/dk1933.json'
--- tests/resources/bibles/dk1933.json 2014-08-24 14:40:45 +0000
+++ tests/resources/bibles/dk1933.json 2016-09-09 21:59:44 +0000
@@ -2,15 +2,15 @@
2 "book": "Genesis",2 "book": "Genesis",
3 "chapter": 1,3 "chapter": 1,
4 "verses": [4 "verses": [
5 [ "1", "I Begyndelsen skabte Gud Himmelen og Jorden."],5 [ 1, "I Begyndelsen skabte Gud Himmelen og Jorden."],
6 [ "2", "Og Jorden var øde og tom, og der var Mørke over Verdensdybet. Men Guds Ånd svævede over Vandene." ],6 [ 2, "Og Jorden var øde og tom, og der var Mørke over Verdensdybet. Men Guds Ånd svævede over Vandene." ],
7 [ "3", "Og Gud sagde: \"Der blive Lys!\" Og der blev Lys." ],7 [ 3, "Og Gud sagde: \"Der blive Lys!\" Og der blev Lys." ],
8 [ "4", "Og Gud så, at Lyset var godt, og Gud satte Skel mellem Lyset og Mørket," ],8 [ 4, "Og Gud så, at Lyset var godt, og Gud satte Skel mellem Lyset og Mørket," ],
9 [ "5", "og Gud kaldte Lyset Dag, og Mørket kaldte han Nat. Og det blev Aften, og det blev Morgen, første Dag." ],9 [ 5, "og Gud kaldte Lyset Dag, og Mørket kaldte han Nat. Og det blev Aften, og det blev Morgen, første Dag." ],
10 [ "6", "Derpå sagde Gud: \"Der blive en Hvælving midt i Vandene til at skille Vandene ad!\"" ],10 [ 6, "Derpå sagde Gud: \"Der blive en Hvælving midt i Vandene til at skille Vandene ad!\"" ],
11 [ "7", "Og således skete det: Gud gjorde Hvælvingen og skilte Vandet under Hvælvingen fra Vandet over Hvælvingen;" ],11 [ 7, "Og således skete det: Gud gjorde Hvælvingen og skilte Vandet under Hvælvingen fra Vandet over Hvælvingen;" ],
12 [ "8", "og Gud kaldte Hvælvingen Himmel. Og det blev Aften, og det blev Morgen, anden Dag." ],12 [ 8, "og Gud kaldte Hvælvingen Himmel. Og det blev Aften, og det blev Morgen, anden Dag." ],
13 [ "9", "Derpå sagde Gud: \"Vandet under Himmelen samle sig på eet Sted, så det faste Land kommer til Syne!\" Og således skete det;" ],13 [ 9, "Derpå sagde Gud: \"Vandet under Himmelen samle sig på eet Sted, så det faste Land kommer til Syne!\" Og således skete det;" ],
14 [ "10", "og Gud kaldte det faste Land Jord, og Stedet, hvor Vandet samlede sig, kaldte han Hav. Og Gud så, at det var godt." ]14 [ 10, "og Gud kaldte det faste Land Jord, og Stedet, hvor Vandet samlede sig, kaldte han Hav. Og Gud så, at det var godt." ]
15 ]15 ]
16}16}
17\ No newline at end of file17\ No newline at end of file
1818
=== modified file 'tests/resources/bibles/kjv.json'
--- tests/resources/bibles/kjv.json 2014-08-24 14:40:45 +0000
+++ tests/resources/bibles/kjv.json 2016-09-09 21:59:44 +0000
@@ -2,15 +2,15 @@
2 "book": "Genesis",2 "book": "Genesis",
3 "chapter": 1,3 "chapter": 1,
4 "verses": [4 "verses": [
5 [ "1", "In the beginning God created the heaven and the earth."],5 [ 1, "In the beginning God created the heaven and the earth."],
6 [ "2", "And the earth was without form, and void; and darkness was upon the face of the deep. And the Spirit of God moved upon the face of the waters." ],6 [ 2, "And the earth was without form, and void; and darkness was upon the face of the deep. And the Spirit of God moved upon the face of the waters." ],
7 [ "3", "And God said, Let there be light: and there was light." ],7 [ 3, "And God said, Let there be light: and there was light." ],
8 [ "4", "And God saw the light, that it was good: and God divided the light from the darkness." ],8 [ 4, "And God saw the light, that it was good: and God divided the light from the darkness." ],
9 [ "5", "And God called the light Day, and the darkness he called Night. And the evening and the morning were the first day." ],9 [ 5, "And God called the light Day, and the darkness he called Night. And the evening and the morning were the first day." ],
10 [ "6", "And God said, Let there be a firmament in the midst of the waters, and let it divide the waters from the waters." ],10 [ 6, "And God said, Let there be a firmament in the midst of the waters, and let it divide the waters from the waters." ],
11 [ "7", "And God made the firmament, and divided the waters which were under the firmament from the waters which were above the firmament: and it was so." ],11 [ 7, "And God made the firmament, and divided the waters which were under the firmament from the waters which were above the firmament: and it was so." ],
12 [ "8", "And God called the firmament Heaven. And the evening and the morning were the second day." ],12 [ 8, "And God called the firmament Heaven. And the evening and the morning were the second day." ],
13 [ "9", "And God said, Let the waters under the heaven be gathered together unto one place, and let the dry land appear: and it was so." ],13 [ 9, "And God said, Let the waters under the heaven be gathered together unto one place, and let the dry land appear: and it was so." ],
14 [ "10", "And God called the dry land Earth; and the gathering together of the waters called he Seas: and God saw that it was good." ]14 [ 10, "And God called the dry land Earth; and the gathering together of the waters called he Seas: and God saw that it was good." ]
15 ]15 ]
16}16}
1717
=== modified file 'tests/resources/bibles/rst.json'
--- tests/resources/bibles/rst.json 2015-02-02 20:40:31 +0000
+++ tests/resources/bibles/rst.json 2016-09-09 21:59:44 +0000
@@ -2,15 +2,15 @@
2 "book": "Exodus",2 "book": "Exodus",
3 "chapter": 1,3 "chapter": 1,
4 "verses": [4 "verses": [
5 [ "1", "Вот имена сынов Израилевых, которые вошли в Египет с Иаковом, вошли каждый с домом своим:" ],5 [ 1, "Вот имена сынов Израилевых, которые вошли в Египет с Иаковом, вошли каждый с домом своим:" ],
6 [ "2", "Рувим, Симеон, Левий и Иуда," ],6 [ 2, "Рувим, Симеон, Левий и Иуда," ],
7 [ "3", "Иссахар, Завулон и Вениамин," ],7 [ 3, "Иссахар, Завулон и Вениамин," ],
8 [ "4", "Дан и Неффалим, Гад и Асир." ],8 [ 4, "Дан и Неффалим, Гад и Асир." ],
9 [ "5", "Всех же душ, происшедших от чресл Иакова, было семьдесят, а Иосиф был [уже] в Египте." ],9 [ 5, "Всех же душ, происшедших от чресл Иакова, было семьдесят, а Иосиф был [уже] в Египте." ],
10 [ "6", "И умер Иосиф и все братья его и весь род их;" ],10 [ 6, "И умер Иосиф и все братья его и весь род их;" ],
11 [ "7", "а сыны Израилевы расплодились и размножились, и возросли и усилились чрезвычайно, и наполнилась ими земля та." ],11 [ 7, "а сыны Израилевы расплодились и размножились, и возросли и усилились чрезвычайно, и наполнилась ими земля та." ],
12 [ "8", "И восстал в Египте новый царь, который не знал Иосифа," ],12 [ 8, "И восстал в Египте новый царь, который не знал Иосифа," ],
13 [ "9", "и сказал народу своему: вот, народ сынов Израилевых многочислен и сильнее нас;" ],13 [ 9, "и сказал народу своему: вот, народ сынов Израилевых многочислен и сильнее нас;" ],
14 [ "10", "перехитрим же его, чтобы он не размножался; иначе, когда случится война, соединится и он с нашими неприятелями, и вооружится против нас, и выйдет из земли [нашей]." ]14 [ 10, "перехитрим же его, чтобы он не размножался; иначе, когда случится война, соединится и он с нашими неприятелями, и вооружится против нас, и выйдет из земли [нашей]." ]
15 ]15 ]
16}16}
1717
=== modified file 'tests/resources/bibles/web.json'
--- tests/resources/bibles/web.json 2014-08-24 14:40:45 +0000
+++ tests/resources/bibles/web.json 2016-09-09 21:59:44 +0000
@@ -2,15 +2,15 @@
2 "book": "Genesis",2 "book": "Genesis",
3 "chapter": "1",3 "chapter": "1",
4 "verses": [4 "verses": [
5 [ "1", "In the beginning God created the heavens and the earth."],5 [ 1, "In the beginning God created the heavens and the earth."],
6 [ "2", "Now the earth was formless and empty. Darkness was on the surface of the deep. God’s Spirit was hovering over the surface of the waters." ],6 [ 2, "Now the earth was formless and empty. Darkness was on the surface of the deep. God’s Spirit was hovering over the surface of the waters." ],
7 [ "3", "God said, “Let there be light,” and there was light." ],7 [ 3, "God said, “Let there be light,” and there was light." ],
8 [ "4", "God saw the light, and saw that it was good. God divided the light from the darkness." ],8 [ 4, "God saw the light, and saw that it was good. God divided the light from the darkness." ],
9 [ "5", "God called the light “day,” and the darkness he called “night.” There was evening and there was morning, one day." ],9 [ 5, "God called the light “day,” and the darkness he called “night.” There was evening and there was morning, one day." ],
10 [ "6", "God said, “Let there be an expanse in the middle of the waters, and let it divide the waters from the waters.”" ],10 [ 6, "God said, “Let there be an expanse in the middle of the waters, and let it divide the waters from the waters.”" ],
11 [ "7", "God made the expanse, and divided the waters which were under the expanse from the waters which were above the expanse; and it was so." ],11 [ 7, "God made the expanse, and divided the waters which were under the expanse from the waters which were above the expanse; and it was so." ],
12 [ "8", "God called the expanse “sky.” There was evening and there was morning, a second day." ],12 [ 8, "God called the expanse “sky.” There was evening and there was morning, a second day." ],
13 [ "9", "God said, “Let the waters under the sky be gathered together to one place, and let the dry land appear;” and it was so." ],13 [ 9, "God said, “Let the waters under the sky be gathered together to one place, and let the dry land appear;” and it was so." ],
14 [ "10", "God called the dry land “earth,” and the gathering together of the waters he called “seas.” God saw that it was good." ]14 [ 10, "God called the dry land “earth,” and the gathering together of the waters he called “seas.” God saw that it was good." ]
15 ]15 ]
16}16}