Merge lp:~phill-ridout/openlp/even-more-refactors into lp:openlp
- even-more-refactors
- Merge into trunk
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Tim Bentley | Approve | ||
Tomas Groth | Approve | ||
Review via email:
|
Commit message
Description of the change
Some more bible refactors
lp:~phill-ridout/openlp/even-more-refactors (revision 2707)
[SUCCESS] https:/
[SUCCESS] https:/
[SUCCESS] https:/
[SUCCESS] https:/
[SUCCESS] https:/
[SUCCESS] https:/
[SUCCESS] https:/
[SUCCESS] https:/
Process finished with exit code 0
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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!
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Tim Bentley (trb143) wrote : | # |
Ok it was a real nit pick!
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Tomas Groth (tomasgroth) : | # |
Preview Diff
1 | === modified file 'openlp/core/common/openlpmixin.py' | |||
2 | --- openlp/core/common/openlpmixin.py 2016-05-14 04:24:46 +0000 | |||
3 | +++ openlp/core/common/openlpmixin.py 2016-09-09 21:59:44 +0000 | |||
4 | @@ -71,6 +71,12 @@ | |||
5 | 71 | """ | 71 | """ |
6 | 72 | self.logger.info(message) | 72 | self.logger.info(message) |
7 | 73 | 73 | ||
8 | 74 | def log_warning(self, message): | ||
9 | 75 | """ | ||
10 | 76 | Common log warning handler | ||
11 | 77 | """ | ||
12 | 78 | self.logger.warning(message) | ||
13 | 79 | |||
14 | 74 | def log_error(self, message): | 80 | def log_error(self, message): |
15 | 75 | """ | 81 | """ |
16 | 76 | Common log error handler which prints the calling path | 82 | Common log error handler which prints the calling path |
17 | 77 | 83 | ||
18 | === modified file 'openlp/plugins/bibles/bibleplugin.py' | |||
19 | --- openlp/plugins/bibles/bibleplugin.py 2016-08-08 18:11:32 +0000 | |||
20 | +++ openlp/plugins/bibles/bibleplugin.py 2016-09-09 21:59:44 +0000 | |||
21 | @@ -140,10 +140,10 @@ | |||
22 | 140 | 140 | ||
23 | 141 | def uses_theme(self, theme): | 141 | def uses_theme(self, theme): |
24 | 142 | """ | 142 | """ |
27 | 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. |
26 | 144 | otherwise returns ``0``. | ||
28 | 145 | 144 | ||
29 | 146 | :param theme: The theme | 145 | :param theme: The theme |
30 | 146 | :return: 1 if the theme is being used, otherwise returns 0 | ||
31 | 147 | """ | 147 | """ |
32 | 148 | if str(self.settings_tab.bible_theme) == theme: | 148 | if str(self.settings_tab.bible_theme) == theme: |
33 | 149 | return 1 | 149 | return 1 |
34 | @@ -151,11 +151,11 @@ | |||
35 | 151 | 151 | ||
36 | 152 | def rename_theme(self, old_theme, new_theme): | 152 | def rename_theme(self, old_theme, new_theme): |
37 | 153 | """ | 153 | """ |
40 | 154 | Rename the theme the bible plugin is using making the plugin use the | 154 | Rename the theme the bible plugin is using, making the plugin use the new name. |
39 | 155 | new name. | ||
41 | 156 | 155 | ||
42 | 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. |
43 | 158 | :param new_theme: The new name the plugin should now use. | 157 | :param new_theme: The new name the plugin should now use. |
44 | 158 | :return: None | ||
45 | 159 | """ | 159 | """ |
46 | 160 | self.settings_tab.bible_theme = new_theme | 160 | self.settings_tab.bible_theme = new_theme |
47 | 161 | self.settings_tab.save() | 161 | self.settings_tab.save() |
48 | 162 | 162 | ||
49 | === modified file 'openlp/plugins/bibles/forms/bibleimportform.py' | |||
50 | --- openlp/plugins/bibles/forms/bibleimportform.py 2016-08-09 20:45:25 +0000 | |||
51 | +++ openlp/plugins/bibles/forms/bibleimportform.py 2016-09-09 21:59:44 +0000 | |||
52 | @@ -25,6 +25,7 @@ | |||
53 | 25 | import logging | 25 | import logging |
54 | 26 | import os | 26 | import os |
55 | 27 | import urllib.error | 27 | import urllib.error |
56 | 28 | from lxml import etree | ||
57 | 28 | 29 | ||
58 | 29 | from PyQt5 import QtWidgets | 30 | from PyQt5 import QtWidgets |
59 | 30 | try: | 31 | try: |
60 | @@ -33,14 +34,15 @@ | |||
61 | 33 | except: | 34 | except: |
62 | 34 | PYSWORD_AVAILABLE = False | 35 | PYSWORD_AVAILABLE = False |
63 | 35 | 36 | ||
65 | 36 | from openlp.core.common import AppLocation, Settings, UiStrings, translate, clean_filename | 37 | from openlp.core.common import AppLocation, Settings, UiStrings, trace_error_handler, translate |
66 | 38 | from openlp.core.common.languagemanager import get_locale_key | ||
67 | 37 | from openlp.core.lib.db import delete_database | 39 | from openlp.core.lib.db import delete_database |
68 | 40 | from openlp.core.lib.exceptions import ValidationError | ||
69 | 38 | from openlp.core.lib.ui import critical_error_message_box | 41 | from openlp.core.lib.ui import critical_error_message_box |
70 | 39 | from openlp.core.ui.lib.wizard import OpenLPWizard, WizardStrings | 42 | from openlp.core.ui.lib.wizard import OpenLPWizard, WizardStrings |
71 | 40 | from openlp.core.common.languagemanager import get_locale_key | ||
72 | 41 | from openlp.plugins.bibles.lib.manager import BibleFormat | ||
73 | 42 | from openlp.plugins.bibles.lib.db import clean_filename | 43 | from openlp.plugins.bibles.lib.db import clean_filename |
74 | 43 | from openlp.plugins.bibles.lib.importers.http import CWExtract, BGExtract, BSExtract | 44 | from openlp.plugins.bibles.lib.importers.http import CWExtract, BGExtract, BSExtract |
75 | 45 | from openlp.plugins.bibles.lib.manager import BibleFormat | ||
76 | 44 | 46 | ||
77 | 45 | log = logging.getLogger(__name__) | 47 | log = logging.getLogger(__name__) |
78 | 46 | 48 | ||
79 | @@ -809,16 +811,22 @@ | |||
80 | 809 | sword_path=self.field('sword_zip_path'), | 811 | sword_path=self.field('sword_zip_path'), |
81 | 810 | sword_key=self.sword_zipbible_combo_box.itemData( | 812 | sword_key=self.sword_zipbible_combo_box.itemData( |
82 | 811 | self.sword_zipbible_combo_box.currentIndex())) | 813 | self.sword_zipbible_combo_box.currentIndex())) |
96 | 812 | if importer.do_import(license_version): | 814 | |
97 | 813 | self.manager.save_meta_data(license_version, license_version, license_copyright, license_permissions) | 815 | try: |
98 | 814 | self.manager.reload_bibles() | 816 | if importer.do_import(license_version) and not importer.stop_import_flag: |
99 | 815 | if bible_type == BibleFormat.WebDownload: | 817 | self.manager.save_meta_data(license_version, license_version, license_copyright, license_permissions) |
100 | 816 | self.progress_label.setText( | 818 | self.manager.reload_bibles() |
101 | 817 | translate('BiblesPlugin.ImportWizardForm', 'Registered Bible. Please note, that verses will be ' | 819 | if bible_type == BibleFormat.WebDownload: |
102 | 818 | 'downloaded on demand and thus an internet connection is required.')) | 820 | self.progress_label.setText( |
103 | 819 | else: | 821 | translate('BiblesPlugin.ImportWizardForm', 'Registered Bible. Please note, that verses will be ' |
104 | 820 | self.progress_label.setText(WizardStrings.FinishedImport) | 822 | 'downloaded on demand and thus an internet connection is required.')) |
105 | 821 | else: | 823 | else: |
106 | 822 | self.progress_label.setText(translate('BiblesPlugin.ImportWizardForm', 'Your Bible import failed.')) | 824 | self.progress_label.setText(WizardStrings.FinishedImport) |
107 | 823 | del self.manager.db_cache[importer.name] | 825 | return |
108 | 824 | delete_database(self.plugin.settings_section, importer.file) | 826 | except (AttributeError, ValidationError, etree.XMLSyntaxError): |
109 | 827 | log.exception('Importing bible failed') | ||
110 | 828 | trace_error_handler(log) | ||
111 | 829 | |||
112 | 830 | self.progress_label.setText(translate('BiblesPlugin.ImportWizardForm', 'Your Bible import failed.')) | ||
113 | 831 | del self.manager.db_cache[importer.name] | ||
114 | 832 | delete_database(self.plugin.settings_section, importer.file) | ||
115 | 825 | 833 | ||
116 | === modified file 'openlp/plugins/bibles/lib/__init__.py' | |||
117 | --- openlp/plugins/bibles/lib/__init__.py 2016-05-05 15:41:48 +0000 | |||
118 | +++ openlp/plugins/bibles/lib/__init__.py 2016-09-09 21:59:44 +0000 | |||
119 | @@ -173,7 +173,7 @@ | |||
120 | 173 | 173 | ||
121 | 174 | def update_reference_separators(): | 174 | def update_reference_separators(): |
122 | 175 | """ | 175 | """ |
124 | 176 | Updates separators and matches for parsing and formating scripture references. | 176 | Updates separators and matches for parsing and formatting scripture references. |
125 | 177 | """ | 177 | """ |
126 | 178 | default_separators = [ | 178 | default_separators = [ |
127 | 179 | '|'.join([ | 179 | '|'.join([ |
128 | @@ -215,7 +215,7 @@ | |||
129 | 215 | # escape reserved characters | 215 | # escape reserved characters |
130 | 216 | for character in '\\.^$*+?{}[]()': | 216 | for character in '\\.^$*+?{}[]()': |
131 | 217 | source_string = source_string.replace(character, '\\' + character) | 217 | source_string = source_string.replace(character, '\\' + character) |
133 | 218 | # add various unicode alternatives | 218 | # add various Unicode alternatives |
134 | 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])') |
135 | 220 | source_string = source_string.replace(',', '(?:[,\u201A])') | 220 | source_string = source_string.replace(',', '(?:[,\u201A])') |
136 | 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) |
137 | 222 | 222 | ||
138 | === modified file 'openlp/plugins/bibles/lib/bibleimport.py' | |||
139 | --- openlp/plugins/bibles/lib/bibleimport.py 2016-08-09 19:32:29 +0000 | |||
140 | +++ openlp/plugins/bibles/lib/bibleimport.py 2016-09-09 21:59:44 +0000 | |||
141 | @@ -20,25 +20,84 @@ | |||
142 | 20 | # Temple Place, Suite 330, Boston, MA 02111-1307 USA # | 20 | # Temple Place, Suite 330, Boston, MA 02111-1307 USA # |
143 | 21 | ############################################################################### | 21 | ############################################################################### |
144 | 22 | 22 | ||
145 | 23 | import logging | ||
146 | 24 | |||
147 | 25 | from lxml import etree, objectify | 23 | from lxml import etree, objectify |
148 | 24 | from zipfile import is_zipfile | ||
149 | 26 | 25 | ||
151 | 27 | from openlp.core.common import OpenLPMixin, languages | 26 | from openlp.core.common import OpenLPMixin, Registry, RegistryProperties, languages, translate |
152 | 28 | from openlp.core.lib import ValidationError | 27 | from openlp.core.lib import ValidationError |
159 | 29 | from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB | 28 | from openlp.core.lib.ui import critical_error_message_box |
160 | 30 | 29 | from openlp.plugins.bibles.lib.db import AlternativeBookNamesDB, BibleDB, BiblesResourcesDB | |
161 | 31 | log = logging.getLogger(__name__) | 30 | |
162 | 32 | 31 | ||
163 | 33 | 32 | class BibleImport(OpenLPMixin, RegistryProperties, BibleDB): | |
158 | 34 | class BibleImport(OpenLPMixin, BibleDB): | ||
164 | 35 | """ | 33 | """ |
165 | 36 | Helper class to import bibles from a third party source into OpenLP | 34 | Helper class to import bibles from a third party source into OpenLP |
166 | 37 | """ | 35 | """ |
167 | 38 | # TODO: Test | ||
168 | 39 | def __init__(self, *args, **kwargs): | 36 | def __init__(self, *args, **kwargs): |
169 | 40 | super().__init__(*args, **kwargs) | 37 | super().__init__(*args, **kwargs) |
170 | 41 | self.filename = kwargs['filename'] if 'filename' in kwargs else None | 38 | self.filename = kwargs['filename'] if 'filename' in kwargs else None |
171 | 39 | self.wizard = None | ||
172 | 40 | self.stop_import_flag = False | ||
173 | 41 | Registry().register_function('openlp_stop_wizard', self.stop_import) | ||
174 | 42 | |||
175 | 43 | @staticmethod | ||
176 | 44 | def is_compressed(file): | ||
177 | 45 | """ | ||
178 | 46 | Check if the supplied file is compressed | ||
179 | 47 | |||
180 | 48 | :param file: A path to the file to check | ||
181 | 49 | """ | ||
182 | 50 | if is_zipfile(file): | ||
183 | 51 | critical_error_message_box( | ||
184 | 52 | message=translate('BiblesPlugin.BibleImport', | ||
185 | 53 | 'The file "{file}" you supplied is compressed. You must decompress it before import.' | ||
186 | 54 | ).format(file=file)) | ||
187 | 55 | return True | ||
188 | 56 | return False | ||
189 | 57 | |||
190 | 58 | def get_book_ref_id_by_name(self, book, maxbooks=66, language_id=None): | ||
191 | 59 | """ | ||
192 | 60 | Find the book id from the name or abbreviation of the book. If it doesn't currently exist, ask the user. | ||
193 | 61 | |||
194 | 62 | :param book: The name or abbreviation of the book | ||
195 | 63 | :param maxbooks: The number of books in the bible | ||
196 | 64 | :param language_id: The language_id of the bible | ||
197 | 65 | :return: The id of the bible, or None | ||
198 | 66 | """ | ||
199 | 67 | self.log_debug('BibleDB.get_book_ref_id_by_name:("{book}", "{lang}")'.format(book=book, lang=language_id)) | ||
200 | 68 | book_temp = BiblesResourcesDB.get_book(book, True) | ||
201 | 69 | if book_temp: | ||
202 | 70 | return book_temp['id'] | ||
203 | 71 | book_id = BiblesResourcesDB.get_alternative_book_name(book) | ||
204 | 72 | if book_id: | ||
205 | 73 | return book_id | ||
206 | 74 | book_id = AlternativeBookNamesDB.get_book_reference_id(book) | ||
207 | 75 | if book_id: | ||
208 | 76 | return book_id | ||
209 | 77 | from openlp.plugins.bibles.forms import BookNameForm | ||
210 | 78 | book_name = BookNameForm(self.wizard) | ||
211 | 79 | if book_name.exec(book, self.get_books(), maxbooks) and book_name.book_id: | ||
212 | 80 | AlternativeBookNamesDB.create_alternative_book_name(book, book_name.book_id, language_id) | ||
213 | 81 | return book_name.book_id | ||
214 | 82 | |||
215 | 83 | def get_language(self, bible_name=None): | ||
216 | 84 | """ | ||
217 | 85 | If no language is given it calls a dialog window where the user could select the bible language. | ||
218 | 86 | Return the language id of a bible. | ||
219 | 87 | |||
220 | 88 | :param bible_name: The language the bible is. | ||
221 | 89 | """ | ||
222 | 90 | self.log_debug('BibleImpoer.get_language()') | ||
223 | 91 | from openlp.plugins.bibles.forms import LanguageForm | ||
224 | 92 | language_id = None | ||
225 | 93 | language_form = LanguageForm(self.wizard) | ||
226 | 94 | if language_form.exec(bible_name): | ||
227 | 95 | combo_box = language_form.language_combo_box | ||
228 | 96 | language_id = combo_box.itemData(combo_box.currentIndex()) | ||
229 | 97 | if not language_id: | ||
230 | 98 | return None | ||
231 | 99 | self.save_meta('language_id', language_id) | ||
232 | 100 | return language_id | ||
233 | 42 | 101 | ||
234 | 43 | def get_language_id(self, file_language=None, bible_name=None): | 102 | def get_language_id(self, file_language=None, bible_name=None): |
235 | 44 | """ | 103 | """ |
236 | @@ -58,8 +117,8 @@ | |||
237 | 58 | language_id = self.get_language(bible_name) | 117 | language_id = self.get_language(bible_name) |
238 | 59 | if not language_id: | 118 | if not language_id: |
239 | 60 | # User cancelled get_language dialog | 119 | # User cancelled get_language dialog |
242 | 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.' |
243 | 62 | .format(name=bible_name)) | 121 | .format(name=bible_name)) |
244 | 63 | return None | 122 | return None |
245 | 64 | self.save_meta('language_id', language_id) | 123 | self.save_meta('language_id', language_id) |
246 | 65 | return language_id | 124 | return language_id |
247 | @@ -77,7 +136,7 @@ | |||
248 | 77 | if name: | 136 | if name: |
249 | 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) |
250 | 79 | else: | 138 | else: |
252 | 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') |
253 | 81 | book_ref_id = guess_id | 140 | book_ref_id = guess_id |
254 | 82 | if not book_ref_id: | 141 | if not book_ref_id: |
255 | 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)) |
256 | @@ -87,8 +146,7 @@ | |||
257 | 87 | 'importing {file}'.format(book_ref=book_ref_id, file=self.filename)) | 146 | 'importing {file}'.format(book_ref=book_ref_id, file=self.filename)) |
258 | 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']) |
259 | 89 | 148 | ||
262 | 90 | @staticmethod | 149 | def parse_xml(self, filename, use_objectify=False, elements=None, tags=None): |
261 | 91 | def parse_xml(filename, use_objectify=False, elements=None, tags=None): | ||
263 | 92 | """ | 150 | """ |
264 | 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. |
265 | 94 | :param filename: The filename of the xml file to parse. Str | 152 | :param filename: The filename of the xml file to parse. Str |
266 | @@ -97,17 +155,80 @@ | |||
267 | 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. |
268 | 98 | :return: The root element of the xml document | 156 | :return: The root element of the xml document |
269 | 99 | """ | 157 | """ |
284 | 100 | with open(filename, 'rb') as import_file: | 158 | try: |
285 | 101 | # NOTE: We don't need to do any of the normal encoding detection here, because lxml does it's own encoding | 159 | with open(filename, 'rb') as import_file: |
286 | 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 |
287 | 103 | if not use_objectify: | 161 | # encoding detection, and the two mechanisms together interfere with each other. |
288 | 104 | tree = etree.parse(import_file, parser=etree.XMLParser(recover=True)) | 162 | if not use_objectify: |
289 | 105 | else: | 163 | tree = etree.parse(import_file, parser=etree.XMLParser(recover=True)) |
290 | 106 | tree = objectify.parse(import_file, parser=objectify.makeparser(recover=True)) | 164 | else: |
291 | 107 | if elements: | 165 | tree = objectify.parse(import_file, parser=objectify.makeparser(recover=True)) |
292 | 108 | # Strip tags we don't use - remove content | 166 | if elements or tags: |
293 | 109 | etree.strip_elements(tree, elements, with_tail=False) | 167 | self.wizard.increment_progress_bar( |
294 | 110 | if tags: | 168 | translate('BiblesPlugin.OsisImport', 'Removing unused tags (this may take a few minutes)...')) |
295 | 111 | # Strip tags we don't use - keep content | 169 | if elements: |
296 | 112 | etree.strip_tags(tree, tags) | 170 | # Strip tags we don't use - remove content |
297 | 113 | return tree.getroot() | 171 | etree.strip_elements(tree, elements, with_tail=False) |
298 | 172 | if tags: | ||
299 | 173 | # Strip tags we don't use - keep content | ||
300 | 174 | etree.strip_tags(tree, tags) | ||
301 | 175 | return tree.getroot() | ||
302 | 176 | except OSError as e: | ||
303 | 177 | self.log_exception('Opening {file_name} failed.'.format(file_name=e.filename)) | ||
304 | 178 | critical_error_message_box( | ||
305 | 179 | title='An Error Occured When Opening A File', | ||
306 | 180 | message='The following error occurred when trying to open\n{file_name}:\n\n{error}' | ||
307 | 181 | .format(file_name=e.filename, error=e.strerror)) | ||
308 | 182 | return None | ||
309 | 183 | |||
310 | 184 | def register(self, wizard): | ||
311 | 185 | """ | ||
312 | 186 | This method basically just initialises the database. It is called from the Bible Manager when a Bible is | ||
313 | 187 | imported. Descendant classes may want to override this method to supply their own custom | ||
314 | 188 | initialisation as well. | ||
315 | 189 | |||
316 | 190 | :param wizard: The actual Qt wizard form. | ||
317 | 191 | """ | ||
318 | 192 | self.wizard = wizard | ||
319 | 193 | return self.name | ||
320 | 194 | |||
321 | 195 | def set_current_chapter(self, book_name, chapter_name): | ||
322 | 196 | self.wizard.increment_progress_bar(translate('BiblesPlugin.OsisImport', 'Importing {book} {chapter}...') | ||
323 | 197 | .format(book=book_name, chapter=chapter_name)) | ||
324 | 198 | |||
325 | 199 | def stop_import(self): | ||
326 | 200 | """ | ||
327 | 201 | Stops the import of the Bible. | ||
328 | 202 | """ | ||
329 | 203 | self.log_debug('Stopping import') | ||
330 | 204 | self.stop_import_flag = True | ||
331 | 205 | |||
332 | 206 | def validate_xml_file(self, filename, tag): | ||
333 | 207 | """ | ||
334 | 208 | Validate the supplied file | ||
335 | 209 | |||
336 | 210 | :param filename: The supplied file | ||
337 | 211 | :param tag: The expected root tag type | ||
338 | 212 | :return: True if valid. ValidationError is raised otherwise. | ||
339 | 213 | """ | ||
340 | 214 | if BibleImport.is_compressed(filename): | ||
341 | 215 | raise ValidationError(msg='Compressed file') | ||
342 | 216 | bible = self.parse_xml(filename, use_objectify=True) | ||
343 | 217 | if bible is None: | ||
344 | 218 | raise ValidationError(msg='Error when opening file') | ||
345 | 219 | root_tag = bible.tag.lower() | ||
346 | 220 | bible_type = translate('BiblesPlugin.BibleImport', 'unknown type of', | ||
347 | 221 | 'This looks like an unknown type of XML bible.') | ||
348 | 222 | if root_tag == tag: | ||
349 | 223 | return True | ||
350 | 224 | elif root_tag == 'bible': | ||
351 | 225 | bible_type = "OpenSong" | ||
352 | 226 | elif root_tag == '{http://www.bibletechnologies.net/2003/osis/namespace}osis': | ||
353 | 227 | bible_type = 'OSIS' | ||
354 | 228 | elif root_tag == 'xmlbible': | ||
355 | 229 | bible_type = 'Zefania' | ||
356 | 230 | critical_error_message_box( | ||
357 | 231 | message=translate('BiblesPlugin.BibleImport', | ||
358 | 232 | 'Incorrect Bible file type supplied. This looks like an {bible_type} XML bible.' | ||
359 | 233 | .format(bible_type=bible_type))) | ||
360 | 234 | raise ValidationError(msg='Invalid xml.') | ||
361 | 114 | 235 | ||
362 | === modified file 'openlp/plugins/bibles/lib/db.py' | |||
363 | --- openlp/plugins/bibles/lib/db.py 2016-08-07 10:15:43 +0000 | |||
364 | +++ openlp/plugins/bibles/lib/db.py 2016-09-09 21:59:44 +0000 | |||
365 | @@ -33,7 +33,7 @@ | |||
366 | 33 | from sqlalchemy.orm import class_mapper, mapper, relation | 33 | from sqlalchemy.orm import class_mapper, mapper, relation |
367 | 34 | from sqlalchemy.orm.exc import UnmappedClassError | 34 | from sqlalchemy.orm.exc import UnmappedClassError |
368 | 35 | 35 | ||
370 | 36 | from openlp.core.common import Registry, RegistryProperties, AppLocation, translate, clean_filename | 36 | from openlp.core.common import AppLocation, translate, clean_filename |
371 | 37 | from openlp.core.lib.db import BaseModel, init_db, Manager | 37 | from openlp.core.lib.db import BaseModel, init_db, Manager |
372 | 38 | from openlp.core.lib.ui import critical_error_message_box | 38 | from openlp.core.lib.ui import critical_error_message_box |
373 | 39 | from openlp.plugins.bibles.lib import upgrade | 39 | from openlp.plugins.bibles.lib import upgrade |
374 | @@ -106,7 +106,7 @@ | |||
375 | 106 | return session | 106 | return session |
376 | 107 | 107 | ||
377 | 108 | 108 | ||
379 | 109 | class BibleDB(Manager, RegistryProperties): | 109 | class BibleDB(Manager): |
380 | 110 | """ | 110 | """ |
381 | 111 | This class represents a database-bound Bible. It is used as a base class for all the custom importers, so that | 111 | This class represents a database-bound Bible. It is used as a base class for all the custom importers, so that |
382 | 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, |
383 | @@ -140,7 +140,6 @@ | |||
384 | 140 | raise KeyError('Missing keyword argument "path".') | 140 | raise KeyError('Missing keyword argument "path".') |
385 | 141 | if 'name' not in kwargs and 'file' not in kwargs: | 141 | if 'name' not in kwargs and 'file' not in kwargs: |
386 | 142 | raise KeyError('Missing keyword argument "name" or "file".') | 142 | raise KeyError('Missing keyword argument "name" or "file".') |
387 | 143 | self.stop_import_flag = False | ||
388 | 144 | if 'name' in kwargs: | 143 | if 'name' in kwargs: |
389 | 145 | self.name = kwargs['name'] | 144 | self.name = kwargs['name'] |
390 | 146 | if not isinstance(self.name, str): | 145 | if not isinstance(self.name, str): |
391 | @@ -153,15 +152,6 @@ | |||
392 | 153 | self.get_name() | 152 | self.get_name() |
393 | 154 | if 'path' in kwargs: | 153 | if 'path' in kwargs: |
394 | 155 | self.path = kwargs['path'] | 154 | self.path = kwargs['path'] |
395 | 156 | self.wizard = None | ||
396 | 157 | Registry().register_function('openlp_stop_wizard', self.stop_import) | ||
397 | 158 | |||
398 | 159 | def stop_import(self): | ||
399 | 160 | """ | ||
400 | 161 | Stops the import of the Bible. | ||
401 | 162 | """ | ||
402 | 163 | log.debug('Stopping import') | ||
403 | 164 | self.stop_import_flag = True | ||
404 | 165 | 155 | ||
405 | 166 | def get_name(self): | 156 | def get_name(self): |
406 | 167 | """ | 157 | """ |
407 | @@ -171,17 +161,6 @@ | |||
408 | 171 | self.name = version_name.value if version_name else None | 161 | self.name = version_name.value if version_name else None |
409 | 172 | return self.name | 162 | return self.name |
410 | 173 | 163 | ||
411 | 174 | def register(self, wizard): | ||
412 | 175 | """ | ||
413 | 176 | This method basically just initialises the database. It is called from the Bible Manager when a Bible is | ||
414 | 177 | imported. Descendant classes may want to override this method to supply their own custom | ||
415 | 178 | initialisation as well. | ||
416 | 179 | |||
417 | 180 | :param wizard: The actual Qt wizard form. | ||
418 | 181 | """ | ||
419 | 182 | self.wizard = wizard | ||
420 | 183 | return self.name | ||
421 | 184 | |||
422 | 185 | def create_book(self, name, bk_ref_id, testament=1): | 164 | def create_book(self, name, bk_ref_id, testament=1): |
423 | 186 | """ | 165 | """ |
424 | 187 | Add a book to the database. | 166 | Add a book to the database. |
425 | @@ -306,26 +285,6 @@ | |||
426 | 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)) |
427 | 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)) |
428 | 308 | 287 | ||
429 | 309 | def get_book_ref_id_by_name(self, book, maxbooks, language_id=None): | ||
430 | 310 | log.debug('BibleDB.get_book_ref_id_by_name:("{book}", "{lang}")'.format(book=book, lang=language_id)) | ||
431 | 311 | book_id = None | ||
432 | 312 | if BiblesResourcesDB.get_book(book, True): | ||
433 | 313 | book_temp = BiblesResourcesDB.get_book(book, True) | ||
434 | 314 | book_id = book_temp['id'] | ||
435 | 315 | elif BiblesResourcesDB.get_alternative_book_name(book): | ||
436 | 316 | book_id = BiblesResourcesDB.get_alternative_book_name(book) | ||
437 | 317 | elif AlternativeBookNamesDB.get_book_reference_id(book): | ||
438 | 318 | book_id = AlternativeBookNamesDB.get_book_reference_id(book) | ||
439 | 319 | else: | ||
440 | 320 | from openlp.plugins.bibles.forms import BookNameForm | ||
441 | 321 | book_name = BookNameForm(self.wizard) | ||
442 | 322 | if book_name.exec(book, self.get_books(), maxbooks): | ||
443 | 323 | book_id = book_name.book_id | ||
444 | 324 | if book_id: | ||
445 | 325 | AlternativeBookNamesDB.create_alternative_book_name( | ||
446 | 326 | book, book_id, language_id) | ||
447 | 327 | return book_id | ||
448 | 328 | |||
449 | 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): |
450 | 330 | """ | 289 | """ |
451 | 331 | Return the id of a named book. | 290 | Return the id of a named book. |
452 | @@ -462,25 +421,6 @@ | |||
453 | 462 | return 0 | 421 | return 0 |
454 | 463 | return count | 422 | return count |
455 | 464 | 423 | ||
456 | 465 | def get_language(self, bible_name=None): | ||
457 | 466 | """ | ||
458 | 467 | If no language is given it calls a dialog window where the user could select the bible language. | ||
459 | 468 | Return the language id of a bible. | ||
460 | 469 | |||
461 | 470 | :param bible_name: The language the bible is. | ||
462 | 471 | """ | ||
463 | 472 | log.debug('BibleDB.get_language()') | ||
464 | 473 | from openlp.plugins.bibles.forms import LanguageForm | ||
465 | 474 | language_id = None | ||
466 | 475 | language_form = LanguageForm(self.wizard) | ||
467 | 476 | if language_form.exec(bible_name): | ||
468 | 477 | combo_box = language_form.language_combo_box | ||
469 | 478 | language_id = combo_box.itemData(combo_box.currentIndex()) | ||
470 | 479 | if not language_id: | ||
471 | 480 | return None | ||
472 | 481 | self.save_meta('language_id', language_id) | ||
473 | 482 | return language_id | ||
474 | 483 | |||
475 | 484 | def dump_bible(self): | 424 | def dump_bible(self): |
476 | 485 | """ | 425 | """ |
477 | 486 | Utility debugging method to dump the contents of a bible. | 426 | Utility debugging method to dump the contents of a bible. |
478 | 487 | 427 | ||
479 | === modified file 'openlp/plugins/bibles/lib/importers/csvbible.py' | |||
480 | --- openlp/plugins/bibles/lib/importers/csvbible.py 2016-08-09 20:45:25 +0000 | |||
481 | +++ openlp/plugins/bibles/lib/importers/csvbible.py 2016-09-09 21:59:44 +0000 | |||
482 | @@ -50,7 +50,6 @@ | |||
483 | 50 | All CSV files are expected to use a comma (',') as the delimiter and double quotes ('"') as the quote symbol. | 50 | All CSV files are expected to use a comma (',') as the delimiter and double quotes ('"') as the quote symbol. |
484 | 51 | """ | 51 | """ |
485 | 52 | import csv | 52 | import csv |
486 | 53 | import logging | ||
487 | 54 | from collections import namedtuple | 53 | from collections import namedtuple |
488 | 55 | 54 | ||
489 | 56 | from openlp.core.common import get_file_encoding, translate | 55 | from openlp.core.common import get_file_encoding, translate |
490 | @@ -58,8 +57,6 @@ | |||
491 | 58 | from openlp.plugins.bibles.lib.bibleimport import BibleImport | 57 | from openlp.plugins.bibles.lib.bibleimport import BibleImport |
492 | 59 | 58 | ||
493 | 60 | 59 | ||
494 | 61 | log = logging.getLogger(__name__) | ||
495 | 62 | |||
496 | 63 | Book = namedtuple('Book', 'id, testament_id, name, abbreviation') | 60 | Book = namedtuple('Book', 'id, testament_id, name, abbreviation') |
497 | 64 | Verse = namedtuple('Verse', 'book_id_name, chapter_number, number, text') | 61 | Verse = namedtuple('Verse', 'book_id_name, chapter_number, number, text') |
498 | 65 | 62 | ||
499 | @@ -68,15 +65,13 @@ | |||
500 | 68 | """ | 65 | """ |
501 | 69 | This class provides a specialisation for importing of CSV Bibles. | 66 | This class provides a specialisation for importing of CSV Bibles. |
502 | 70 | """ | 67 | """ |
503 | 71 | log.info('CSVBible loaded') | ||
504 | 72 | |||
505 | 73 | def __init__(self, *args, **kwargs): | 68 | def __init__(self, *args, **kwargs): |
506 | 74 | """ | 69 | """ |
507 | 75 | Loads a Bible from a set of CSV files. This class assumes the files contain all the information and a clean | 70 | Loads a Bible from a set of CSV files. This class assumes the files contain all the information and a clean |
508 | 76 | bible is being loaded. | 71 | bible is being loaded. |
509 | 77 | """ | 72 | """ |
510 | 78 | log.info(self.__class__.__name__) | ||
511 | 79 | super().__init__(*args, **kwargs) | 73 | super().__init__(*args, **kwargs) |
512 | 74 | self.log_info(self.__class__.__name__) | ||
513 | 80 | self.books_file = kwargs['booksfile'] | 75 | self.books_file = kwargs['booksfile'] |
514 | 81 | self.verses_file = kwargs['versefile'] | 76 | self.verses_file = kwargs['versefile'] |
515 | 82 | 77 | ||
516 | @@ -123,12 +118,11 @@ | |||
517 | 123 | number_of_books = len(books) | 118 | number_of_books = len(books) |
518 | 124 | for book in books: | 119 | for book in books: |
519 | 125 | if self.stop_import_flag: | 120 | if self.stop_import_flag: |
521 | 126 | return None | 121 | break |
522 | 127 | self.wizard.increment_progress_bar( | 122 | self.wizard.increment_progress_bar( |
523 | 128 | translate('BiblesPlugin.CSVBible', 'Importing books... {book}').format(book=book.name)) | 123 | translate('BiblesPlugin.CSVBible', 'Importing books... {book}').format(book=book.name)) |
524 | 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) |
525 | 130 | book_list.update({int(book.id): book.name}) | 125 | book_list.update({int(book.id): book.name}) |
526 | 131 | self.application.process_events() | ||
527 | 132 | return book_list | 126 | return book_list |
528 | 133 | 127 | ||
529 | 134 | def process_verses(self, verses, books): | 128 | def process_verses(self, verses, books): |
530 | @@ -142,7 +136,7 @@ | |||
531 | 142 | book_ptr = None | 136 | book_ptr = None |
532 | 143 | for verse in verses: | 137 | for verse in verses: |
533 | 144 | if self.stop_import_flag: | 138 | if self.stop_import_flag: |
535 | 145 | return None | 139 | break |
536 | 146 | verse_book = self.get_book_name(verse.book_id_name, books) | 140 | verse_book = self.get_book_name(verse.book_id_name, books) |
537 | 147 | if book_ptr != verse_book: | 141 | if book_ptr != verse_book: |
538 | 148 | book = self.get_book(verse_book) | 142 | book = self.get_book(verse_book) |
539 | @@ -151,9 +145,7 @@ | |||
540 | 151 | translate('BiblesPlugin.CSVBible', 'Importing verses from {book}...', | 145 | translate('BiblesPlugin.CSVBible', 'Importing verses from {book}...', |
541 | 152 | 'Importing verses from <book name>...').format(book=book.name)) | 146 | 'Importing verses from <book name>...').format(book=book.name)) |
542 | 153 | self.session.commit() | 147 | self.session.commit() |
546 | 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) |
544 | 155 | self.wizard.increment_progress_bar(translate('BiblesPlugin.CSVBible', 'Importing verses... done.')) | ||
545 | 156 | self.application.process_events() | ||
547 | 157 | self.session.commit() | 149 | self.session.commit() |
548 | 158 | 150 | ||
549 | 159 | def do_import(self, bible_name=None): | 151 | def do_import(self, bible_name=None): |
550 | @@ -163,24 +155,16 @@ | |||
551 | 163 | :param bible_name: Optional name of the bible being imported. Str or None | 155 | :param bible_name: Optional name of the bible being imported. Str or None |
552 | 164 | :return: True if the import was successful, False if it failed or was cancelled | 156 | :return: True if the import was successful, False if it failed or was cancelled |
553 | 165 | """ | 157 | """ |
573 | 166 | try: | 158 | self.language_id = self.get_language(bible_name) |
574 | 167 | self.language_id = self.get_language(bible_name) | 159 | if not self.language_id: |
556 | 168 | if not self.language_id: | ||
557 | 169 | raise ValidationError(msg='Invalid language selected') | ||
558 | 170 | books = self.parse_csv_file(self.books_file, Book) | ||
559 | 171 | self.wizard.progress_bar.setValue(0) | ||
560 | 172 | self.wizard.progress_bar.setMinimum(0) | ||
561 | 173 | self.wizard.progress_bar.setMaximum(len(books)) | ||
562 | 174 | book_list = self.process_books(books) | ||
563 | 175 | if self.stop_import_flag: | ||
564 | 176 | return False | ||
565 | 177 | verses = self.parse_csv_file(self.verses_file, Verse) | ||
566 | 178 | self.wizard.progress_bar.setValue(0) | ||
567 | 179 | self.wizard.progress_bar.setMaximum(len(books) + 1) | ||
568 | 180 | self.process_verses(verses, book_list) | ||
569 | 181 | if self.stop_import_flag: | ||
570 | 182 | return False | ||
571 | 183 | except ValidationError: | ||
572 | 184 | log.exception('Could not import CSV bible') | ||
575 | 185 | return False | 160 | return False |
576 | 161 | books = self.parse_csv_file(self.books_file, Book) | ||
577 | 162 | self.wizard.progress_bar.setValue(0) | ||
578 | 163 | self.wizard.progress_bar.setMinimum(0) | ||
579 | 164 | self.wizard.progress_bar.setMaximum(len(books)) | ||
580 | 165 | book_list = self.process_books(books) | ||
581 | 166 | verses = self.parse_csv_file(self.verses_file, Verse) | ||
582 | 167 | self.wizard.progress_bar.setValue(0) | ||
583 | 168 | self.wizard.progress_bar.setMaximum(len(books) + 1) | ||
584 | 169 | self.process_verses(verses, book_list) | ||
585 | 186 | return True | 170 | return True |
586 | 187 | 171 | ||
587 | === modified file 'openlp/plugins/bibles/lib/importers/opensong.py' | |||
588 | --- openlp/plugins/bibles/lib/importers/opensong.py 2016-08-09 20:45:25 +0000 | |||
589 | +++ openlp/plugins/bibles/lib/importers/opensong.py 2016-09-09 21:59:44 +0000 | |||
590 | @@ -20,109 +20,126 @@ | |||
591 | 20 | # Temple Place, Suite 330, Boston, MA 02111-1307 USA # | 20 | # Temple Place, Suite 330, Boston, MA 02111-1307 USA # |
592 | 21 | ############################################################################### | 21 | ############################################################################### |
593 | 22 | 22 | ||
594 | 23 | import logging | ||
595 | 24 | from lxml import etree, objectify | ||
596 | 25 | |||
597 | 26 | from openlp.core.common import translate, trace_error_handler | ||
598 | 27 | from openlp.core.lib.ui import critical_error_message_box | ||
599 | 28 | from openlp.plugins.bibles.lib.bibleimport import BibleImport | 23 | from openlp.plugins.bibles.lib.bibleimport import BibleImport |
604 | 29 | from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB | 24 | |
605 | 30 | 25 | ||
606 | 31 | 26 | def get_text(element): | |
607 | 32 | log = logging.getLogger(__name__) | 27 | """ |
608 | 28 | Recursively get all text in an objectify element and its child elements. | ||
609 | 29 | |||
610 | 30 | :param element: An objectify element to get the text from | ||
611 | 31 | :return: The text content of the element (str) | ||
612 | 32 | """ | ||
613 | 33 | verse_text = '' | ||
614 | 34 | if element.text: | ||
615 | 35 | verse_text = element.text | ||
616 | 36 | for sub_element in element.iterchildren(): | ||
617 | 37 | verse_text += get_text(sub_element) | ||
618 | 38 | if element.tail: | ||
619 | 39 | verse_text += element.tail | ||
620 | 40 | return verse_text | ||
621 | 41 | |||
622 | 42 | |||
623 | 43 | def parse_chapter_number(number, previous_number): | ||
624 | 44 | """ | ||
625 | 45 | Parse the chapter number | ||
626 | 46 | |||
627 | 47 | :param number: The raw data from the xml | ||
628 | 48 | :param previous_number: The previous chapter number | ||
629 | 49 | :return: Number of current chapter. (Int) | ||
630 | 50 | """ | ||
631 | 51 | if number: | ||
632 | 52 | return int(number.split()[-1]) | ||
633 | 53 | return previous_number + 1 | ||
634 | 33 | 54 | ||
635 | 34 | 55 | ||
636 | 35 | class OpenSongBible(BibleImport): | 56 | class OpenSongBible(BibleImport): |
637 | 36 | """ | 57 | """ |
638 | 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. |
639 | 38 | """ | 59 | """ |
654 | 39 | def get_text(self, element): | 60 | |
655 | 40 | """ | 61 | def parse_verse_number(self, number, previous_number): |
656 | 41 | Recursively get all text in an objectify element and its child elements. | 62 | """ |
657 | 42 | 63 | Parse the verse number retrieved from the xml | |
658 | 43 | :param element: An objectify element to get the text from | 64 | |
659 | 44 | """ | 65 | :param number: The raw data from the xml |
660 | 45 | verse_text = '' | 66 | :param previous_number: The previous verse number |
661 | 46 | if element.text: | 67 | :return: Number of current verse. (Int) |
662 | 47 | verse_text = element.text | 68 | """ |
663 | 48 | for sub_element in element.iterchildren(): | 69 | if not number: |
664 | 49 | verse_text += self.get_text(sub_element) | 70 | return previous_number + 1 |
665 | 50 | if element.tail: | 71 | try: |
666 | 51 | verse_text += element.tail | 72 | return int(number) |
667 | 52 | return verse_text | 73 | except ValueError: |
668 | 74 | verse_parts = number.split('-') | ||
669 | 75 | if len(verse_parts) > 1: | ||
670 | 76 | number = int(verse_parts[0]) | ||
671 | 77 | return number | ||
672 | 78 | except TypeError: | ||
673 | 79 | self.log_warning('Illegal verse number: {verse_no}'.format(verse_no=str(number))) | ||
674 | 80 | return previous_number + 1 | ||
675 | 81 | |||
676 | 82 | def process_books(self, books): | ||
677 | 83 | """ | ||
678 | 84 | Extract and create the books from the objectified xml | ||
679 | 85 | |||
680 | 86 | :param books: Objectified xml | ||
681 | 87 | :return: None | ||
682 | 88 | """ | ||
683 | 89 | for book in books: | ||
684 | 90 | if self.stop_import_flag: | ||
685 | 91 | break | ||
686 | 92 | db_book = self.find_and_create_book(str(book.attrib['n']), len(books), self.language_id) | ||
687 | 93 | self.process_chapters(db_book, book.c) | ||
688 | 94 | self.session.commit() | ||
689 | 95 | |||
690 | 96 | def process_chapters(self, book, chapters): | ||
691 | 97 | """ | ||
692 | 98 | Extract and create the chapters from the objectified xml for the book `book` | ||
693 | 99 | |||
694 | 100 | :param book: A database Book object to add the chapters to | ||
695 | 101 | :param chapters: Objectified xml containing chapters | ||
696 | 102 | :return: None | ||
697 | 103 | """ | ||
698 | 104 | chapter_number = 0 | ||
699 | 105 | for chapter in chapters: | ||
700 | 106 | if self.stop_import_flag: | ||
701 | 107 | break | ||
702 | 108 | chapter_number = parse_chapter_number(chapter.attrib['n'], chapter_number) | ||
703 | 109 | self.set_current_chapter(book.name, chapter_number) | ||
704 | 110 | self.process_verses(book, chapter_number, chapter.v) | ||
705 | 111 | |||
706 | 112 | def process_verses(self, book, chapter_number, verses): | ||
707 | 113 | """ | ||
708 | 114 | Extract and create the verses from the objectified xml | ||
709 | 115 | |||
710 | 116 | :param book: A database Book object | ||
711 | 117 | :param chapter_number: The chapter number to add the verses to (int) | ||
712 | 118 | :param verses: Objectified xml containing verses | ||
713 | 119 | :return: None | ||
714 | 120 | """ | ||
715 | 121 | verse_number = 0 | ||
716 | 122 | for verse in verses: | ||
717 | 123 | if self.stop_import_flag: | ||
718 | 124 | break | ||
719 | 125 | verse_number = self.parse_verse_number(verse.attrib['n'], verse_number) | ||
720 | 126 | self.create_verse(book.id, chapter_number, verse_number, get_text(verse)) | ||
721 | 53 | 127 | ||
722 | 54 | def do_import(self, bible_name=None): | 128 | def do_import(self, bible_name=None): |
723 | 55 | """ | 129 | """ |
725 | 56 | Loads a Bible from file. | 130 | Loads an Open Song Bible from a file. |
726 | 131 | |||
727 | 132 | :param bible_name: The name of the bible being imported | ||
728 | 133 | :return: True if import completed, False if import was unsuccessful | ||
729 | 57 | """ | 134 | """ |
801 | 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)) |
802 | 59 | success = True | 136 | self.validate_xml_file(self.filename, 'bible') |
803 | 60 | try: | 137 | bible = self.parse_xml(self.filename, use_objectify=True) |
804 | 61 | bible = self.parse_xml(self.filename, use_objectify=True) | 138 | if bible is None: |
805 | 62 | # Check that we're not trying to import a Zefania XML bible, it is sometimes refered to as 'OpenSong' | 139 | return False |
806 | 63 | if bible.tag.upper() == 'XMLBIBLE': | 140 | # No language info in the opensong format, so ask the user |
807 | 64 | critical_error_message_box( | 141 | self.language_id = self.get_language_id(bible_name=self.filename) |
808 | 65 | message=translate('BiblesPlugin.OpenSongImport', | 142 | if not self.language_id: |
809 | 66 | 'Incorrect Bible file type supplied. This looks like a Zefania XML bible, ' | 143 | return False |
810 | 67 | 'please use the Zefania import option.')) | 144 | self.process_books(bible.b) |
811 | 68 | return False | 145 | return True |
741 | 69 | # No language info in the opensong format, so ask the user | ||
742 | 70 | language_id = self.get_language_id(bible_name=self.filename) | ||
743 | 71 | if not language_id: | ||
744 | 72 | return False | ||
745 | 73 | for book in bible.b: | ||
746 | 74 | if self.stop_import_flag: | ||
747 | 75 | break | ||
748 | 76 | book_ref_id = self.get_book_ref_id_by_name(str(book.attrib['n']), len(bible.b), language_id) | ||
749 | 77 | if not book_ref_id: | ||
750 | 78 | log.error('Importing books from "{name}" failed'.format(name=self.filename)) | ||
751 | 79 | return False | ||
752 | 80 | book_details = BiblesResourcesDB.get_book_by_id(book_ref_id) | ||
753 | 81 | db_book = self.create_book(book.attrib['n'], book_ref_id, book_details['testament_id']) | ||
754 | 82 | chapter_number = 0 | ||
755 | 83 | for chapter in book.c: | ||
756 | 84 | if self.stop_import_flag: | ||
757 | 85 | break | ||
758 | 86 | number = chapter.attrib['n'] | ||
759 | 87 | if number: | ||
760 | 88 | chapter_number = int(number.split()[-1]) | ||
761 | 89 | else: | ||
762 | 90 | chapter_number += 1 | ||
763 | 91 | verse_number = 0 | ||
764 | 92 | for verse in chapter.v: | ||
765 | 93 | if self.stop_import_flag: | ||
766 | 94 | break | ||
767 | 95 | number = verse.attrib['n'] | ||
768 | 96 | if number: | ||
769 | 97 | try: | ||
770 | 98 | number = int(number) | ||
771 | 99 | except ValueError: | ||
772 | 100 | verse_parts = number.split('-') | ||
773 | 101 | if len(verse_parts) > 1: | ||
774 | 102 | number = int(verse_parts[0]) | ||
775 | 103 | except TypeError: | ||
776 | 104 | log.warning('Illegal verse number: {verse:d}'.format(verse=verse.attrib['n'])) | ||
777 | 105 | verse_number = number | ||
778 | 106 | else: | ||
779 | 107 | verse_number += 1 | ||
780 | 108 | self.create_verse(db_book.id, chapter_number, verse_number, self.get_text(verse)) | ||
781 | 109 | self.wizard.increment_progress_bar(translate('BiblesPlugin.Opensong', | ||
782 | 110 | 'Importing {name} {chapter}...' | ||
783 | 111 | ).format(name=db_book.name, chapter=chapter_number)) | ||
784 | 112 | self.session.commit() | ||
785 | 113 | self.application.process_events() | ||
786 | 114 | except etree.XMLSyntaxError as inst: | ||
787 | 115 | trace_error_handler(log) | ||
788 | 116 | critical_error_message_box( | ||
789 | 117 | message=translate('BiblesPlugin.OpenSongImport', | ||
790 | 118 | 'Incorrect Bible file type supplied. OpenSong Bibles may be ' | ||
791 | 119 | 'compressed. You must decompress them before import.')) | ||
792 | 120 | log.exception(inst) | ||
793 | 121 | success = False | ||
794 | 122 | except (IOError, AttributeError): | ||
795 | 123 | log.exception('Loading Bible from OpenSong file failed') | ||
796 | 124 | success = False | ||
797 | 125 | if self.stop_import_flag: | ||
798 | 126 | return False | ||
799 | 127 | else: | ||
800 | 128 | return success | ||
812 | 129 | 146 | ||
813 | === modified file 'openlp/plugins/bibles/lib/importers/osis.py' | |||
814 | --- openlp/plugins/bibles/lib/importers/osis.py 2016-08-10 19:08:09 +0000 | |||
815 | +++ openlp/plugins/bibles/lib/importers/osis.py 2016-09-09 21:59:44 +0000 | |||
816 | @@ -20,15 +20,9 @@ | |||
817 | 20 | # Temple Place, Suite 330, Boston, MA 02111-1307 USA # | 20 | # Temple Place, Suite 330, Boston, MA 02111-1307 USA # |
818 | 21 | ############################################################################### | 21 | ############################################################################### |
819 | 22 | 22 | ||
820 | 23 | import logging | ||
821 | 24 | from lxml import etree | 23 | from lxml import etree |
822 | 25 | 24 | ||
823 | 26 | from openlp.core.common import translate, trace_error_handler | ||
824 | 27 | from openlp.core.lib.ui import critical_error_message_box | ||
825 | 28 | from openlp.plugins.bibles.lib.bibleimport import BibleImport | 25 | from openlp.plugins.bibles.lib.bibleimport import BibleImport |
826 | 29 | from openlp.plugins.bibles.lib.db import BiblesResourcesDB | ||
827 | 30 | |||
828 | 31 | log = logging.getLogger(__name__) | ||
829 | 32 | 26 | ||
830 | 33 | NS = {'ns': 'http://www.bibletechnologies.net/2003/OSIS/namespace'} | 27 | NS = {'ns': 'http://www.bibletechnologies.net/2003/OSIS/namespace'} |
831 | 34 | # Tags we don't use and can remove the content | 28 | # Tags we don't use and can remove the content |
832 | @@ -74,104 +68,106 @@ | |||
833 | 74 | '{http://www.bibletechnologies.net/2003/OSIS/namespace}caption' | 68 | '{http://www.bibletechnologies.net/2003/OSIS/namespace}caption' |
834 | 75 | ) | 69 | ) |
835 | 76 | 70 | ||
839 | 77 | 71 | # Precompile a few xpath-querys | |
840 | 78 | def replacement(match): | 72 | verse_in_chapter = etree.XPath('//ns:chapter[1]/ns:verse', namespaces=NS) |
841 | 79 | return match.group(2).upper() | 73 | text_in_verse = etree.XPath('//ns:verse[1]/text()', namespaces=NS) |
842 | 80 | 74 | ||
843 | 81 | 75 | ||
844 | 82 | class OSISBible(BibleImport): | 76 | class OSISBible(BibleImport): |
845 | 83 | """ | 77 | """ |
846 | 84 | `OSIS <http://www.bibletechnologies.net/>`_ Bible format importer class. | 78 | `OSIS <http://www.bibletechnologies.net/>`_ Bible format importer class. |
847 | 85 | """ | 79 | """ |
848 | 80 | def process_books(self, bible_data): | ||
849 | 81 | """ | ||
850 | 82 | Extract and create the bible books from the parsed xml | ||
851 | 83 | |||
852 | 84 | :param bible_data: parsed xml | ||
853 | 85 | :return: None | ||
854 | 86 | """ | ||
855 | 87 | # Find books in the bible | ||
856 | 88 | bible_books = bible_data.xpath("//ns:div[@type='book']", namespaces=NS) | ||
857 | 89 | no_of_books = len(bible_books) | ||
858 | 90 | for book in bible_books: | ||
859 | 91 | if self.stop_import_flag: | ||
860 | 92 | break | ||
861 | 93 | # Remove div-tags in the book | ||
862 | 94 | etree.strip_tags(book, '{http://www.bibletechnologies.net/2003/OSIS/namespace}div') | ||
863 | 95 | db_book = self.find_and_create_book(book.get('osisID'), no_of_books, self.language_id) | ||
864 | 96 | self.process_chapters(db_book, book) | ||
865 | 97 | self.session.commit() | ||
866 | 98 | |||
867 | 99 | def process_chapters(self, book, chapters): | ||
868 | 100 | """ | ||
869 | 101 | Extract the chapters, and do some initial processing of the verses | ||
870 | 102 | |||
871 | 103 | :param book: An OpenLP bible database book object | ||
872 | 104 | :param chapters: parsed chapters | ||
873 | 105 | :return: None | ||
874 | 106 | """ | ||
875 | 107 | # Find out if chapter-tags contains the verses, or if it is used as milestone/anchor | ||
876 | 108 | if verse_in_chapter(chapters): | ||
877 | 109 | # The chapter tags contains the verses | ||
878 | 110 | for chapter in chapters: | ||
879 | 111 | chapter_number = int(chapter.get("osisID").split('.')[1]) | ||
880 | 112 | self.set_current_chapter(book.name, chapter_number) | ||
881 | 113 | # Find out if verse-tags contains the text, or if it is used as milestone/anchor | ||
882 | 114 | if not text_in_verse(chapter): | ||
883 | 115 | # verse-tags are used as milestone | ||
884 | 116 | for verse in chapter: | ||
885 | 117 | # If this tag marks the start of a verse, the verse text is between this tag and | ||
886 | 118 | # the next tag, which the "tail" attribute gives us. | ||
887 | 119 | self.process_verse(book, chapter_number, verse, use_milestones=True) | ||
888 | 120 | else: | ||
889 | 121 | # Verse-tags contains the text | ||
890 | 122 | for verse in chapter: | ||
891 | 123 | self.process_verse(book, chapter_number, verse) | ||
892 | 124 | else: | ||
893 | 125 | # The chapter tags is used as milestones. For now we assume verses is also milestones | ||
894 | 126 | chapter_number = 0 | ||
895 | 127 | for element in chapters: | ||
896 | 128 | if element.tag == '{http://www.bibletechnologies.net/2003/OSIS/namespace}chapter' \ | ||
897 | 129 | and element.get('sID'): | ||
898 | 130 | chapter_number = int(element.get("osisID").split('.')[1]) | ||
899 | 131 | self.set_current_chapter(book.name, chapter_number) | ||
900 | 132 | elif element.tag == '{http://www.bibletechnologies.net/2003/OSIS/namespace}verse': | ||
901 | 133 | # If this tag marks the start of a verse, the verse text is between this tag and | ||
902 | 134 | # the next tag, which the "tail" attribute gives us. | ||
903 | 135 | self.process_verse(book, chapter_number, element, use_milestones=True) | ||
904 | 136 | |||
905 | 137 | def process_verse(self, book, chapter_number, element, use_milestones=False): | ||
906 | 138 | """ | ||
907 | 139 | Process a verse element | ||
908 | 140 | :param book: A database Book object | ||
909 | 141 | :param chapter_number: The chapter number to add the verses to (int) | ||
910 | 142 | :param element: The verse element to process. (etree element type) | ||
911 | 143 | :param use_milestones: set to True to process a 'milestone' verse. Defaults to False | ||
912 | 144 | :return: None | ||
913 | 145 | """ | ||
914 | 146 | osis_id = element.get("osisID") | ||
915 | 147 | if not osis_id: | ||
916 | 148 | return None | ||
917 | 149 | verse_number = int(osis_id.split('.')[2]) | ||
918 | 150 | verse_text = '' | ||
919 | 151 | if use_milestones and element.get('sID'): | ||
920 | 152 | verse_text = element.tail | ||
921 | 153 | elif not use_milestones: | ||
922 | 154 | verse_text = element.text | ||
923 | 155 | if verse_text: | ||
924 | 156 | self.create_verse(book.id, chapter_number, verse_number, verse_text.strip()) | ||
925 | 157 | |||
926 | 86 | def do_import(self, bible_name=None): | 158 | def do_import(self, bible_name=None): |
927 | 87 | """ | 159 | """ |
928 | 88 | Loads a Bible from file. | 160 | Loads a Bible from file. |
929 | 89 | """ | 161 | """ |
1018 | 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)) |
1019 | 91 | success = True | 163 | self.validate_xml_file(self.filename, '{http://www.bibletechnologies.net/2003/osis/namespace}osis') |
1020 | 92 | try: | 164 | bible = self.parse_xml(self.filename, elements=REMOVABLE_ELEMENTS, tags=REMOVABLE_TAGS) |
1021 | 93 | self.wizard.increment_progress_bar(translate('BiblesPlugin.OsisImport', | 165 | if bible is None: |
1022 | 94 | 'Removing unused tags (this may take a few minutes)...')) | 166 | return False |
1023 | 95 | osis_bible_tree = self.parse_xml(self.filename, elements=REMOVABLE_ELEMENTS, tags=REMOVABLE_TAGS) | 167 | # Find bible language |
1024 | 96 | # Find bible language] | 168 | language = bible.xpath("//ns:osisText/@xml:lang", namespaces=NS) |
1025 | 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) |
1026 | 98 | language_id = self.get_language_id(language[0] if language else None, bible_name=self.filename) | 170 | if not self.language_id: |
1027 | 99 | if not language_id: | 171 | return False |
1028 | 100 | return False | 172 | self.process_books(bible) |
1029 | 101 | num_books = int(osis_bible_tree.xpath("count(//ns:div[@type='book'])", namespaces=NS)) | 173 | return True |
942 | 102 | # Precompile a few xpath-querys | ||
943 | 103 | verse_in_chapter = etree.XPath('count(//ns:chapter[1]/ns:verse)', namespaces=NS) | ||
944 | 104 | text_in_verse = etree.XPath('count(//ns:verse[1]/text())', namespaces=NS) | ||
945 | 105 | # Find books in the bible | ||
946 | 106 | bible_books = osis_bible_tree.xpath("//ns:div[@type='book']", namespaces=NS) | ||
947 | 107 | for book in bible_books: | ||
948 | 108 | if self.stop_import_flag: | ||
949 | 109 | break | ||
950 | 110 | # Remove div-tags in the book | ||
951 | 111 | etree.strip_tags(book, ('{http://www.bibletechnologies.net/2003/OSIS/namespace}div')) | ||
952 | 112 | book_ref_id = self.get_book_ref_id_by_name(book.get('osisID'), num_books, language_id) | ||
953 | 113 | if not book_ref_id: | ||
954 | 114 | log.error('Importing books from "{name}" failed'.format(name=self.filename)) | ||
955 | 115 | return False | ||
956 | 116 | book_details = BiblesResourcesDB.get_book_by_id(book_ref_id) | ||
957 | 117 | db_book = self.create_book(book_details['name'], book_ref_id, book_details['testament_id']) | ||
958 | 118 | # Find out if chapter-tags contains the verses, or if it is used as milestone/anchor | ||
959 | 119 | if int(verse_in_chapter(book)) > 0: | ||
960 | 120 | # The chapter tags contains the verses | ||
961 | 121 | for chapter in book: | ||
962 | 122 | chapter_number = chapter.get("osisID").split('.')[1] | ||
963 | 123 | # Find out if verse-tags contains the text, or if it is used as milestone/anchor | ||
964 | 124 | if int(text_in_verse(chapter)) == 0: | ||
965 | 125 | # verse-tags are used as milestone | ||
966 | 126 | for verse in chapter: | ||
967 | 127 | # If this tag marks the start of a verse, the verse text is between this tag and | ||
968 | 128 | # the next tag, which the "tail" attribute gives us. | ||
969 | 129 | if verse.get('sID'): | ||
970 | 130 | verse_number = verse.get("osisID").split('.')[2] | ||
971 | 131 | verse_text = verse.tail | ||
972 | 132 | if verse_text: | ||
973 | 133 | self.create_verse(db_book.id, chapter_number, verse_number, verse_text.strip()) | ||
974 | 134 | else: | ||
975 | 135 | # Verse-tags contains the text | ||
976 | 136 | for verse in chapter: | ||
977 | 137 | verse_number = verse.get("osisID").split('.')[2] | ||
978 | 138 | if verse.text: | ||
979 | 139 | self.create_verse(db_book.id, chapter_number, verse_number, verse.text.strip()) | ||
980 | 140 | self.wizard.increment_progress_bar( | ||
981 | 141 | translate('BiblesPlugin.OsisImport', 'Importing %(bookname)s %(chapter)s...') % | ||
982 | 142 | {'bookname': db_book.name, 'chapter': chapter_number}) | ||
983 | 143 | else: | ||
984 | 144 | # The chapter tags is used as milestones. For now we assume verses is also milestones | ||
985 | 145 | chapter_number = 0 | ||
986 | 146 | for element in book: | ||
987 | 147 | if element.tag == '{http://www.bibletechnologies.net/2003/OSIS/namespace}chapter' \ | ||
988 | 148 | and element.get('sID'): | ||
989 | 149 | chapter_number = element.get("osisID").split('.')[1] | ||
990 | 150 | self.wizard.increment_progress_bar( | ||
991 | 151 | translate('BiblesPlugin.OsisImport', 'Importing %(bookname)s %(chapter)s...') % | ||
992 | 152 | {'bookname': db_book.name, 'chapter': chapter_number}) | ||
993 | 153 | elif element.tag == '{http://www.bibletechnologies.net/2003/OSIS/namespace}verse' \ | ||
994 | 154 | and element.get('sID'): | ||
995 | 155 | # If this tag marks the start of a verse, the verse text is between this tag and | ||
996 | 156 | # the next tag, which the "tail" attribute gives us. | ||
997 | 157 | verse_number = element.get("osisID").split('.')[2] | ||
998 | 158 | verse_text = element.tail | ||
999 | 159 | if verse_text: | ||
1000 | 160 | self.create_verse(db_book.id, chapter_number, verse_number, verse_text.strip()) | ||
1001 | 161 | self.session.commit() | ||
1002 | 162 | self.application.process_events() | ||
1003 | 163 | except (ValueError, IOError): | ||
1004 | 164 | log.exception('Loading bible from OSIS file failed') | ||
1005 | 165 | trace_error_handler(log) | ||
1006 | 166 | success = False | ||
1007 | 167 | except etree.XMLSyntaxError as e: | ||
1008 | 168 | log.exception('Loading bible from OSIS file failed') | ||
1009 | 169 | trace_error_handler(log) | ||
1010 | 170 | success = False | ||
1011 | 171 | critical_error_message_box(message=translate('BiblesPlugin.OsisImport', | ||
1012 | 172 | 'The file is not a valid OSIS-XML file:' | ||
1013 | 173 | '\n{text}').format(text=e.msg)) | ||
1014 | 174 | if self.stop_import_flag: | ||
1015 | 175 | return False | ||
1016 | 176 | else: | ||
1017 | 177 | return success | ||
1030 | 178 | 174 | ||
1031 | === modified file 'openlp/plugins/bibles/lib/importers/zefania.py' | |||
1032 | --- openlp/plugins/bibles/lib/importers/zefania.py 2016-08-09 20:45:25 +0000 | |||
1033 | +++ openlp/plugins/bibles/lib/importers/zefania.py 2016-09-09 21:59:44 +0000 | |||
1034 | @@ -54,7 +54,7 @@ | |||
1035 | 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) |
1036 | 55 | if not language_id: | 55 | if not language_id: |
1037 | 56 | return False | 56 | return False |
1039 | 57 | num_books = int(xmlbible.xpath('count(//BIBLEBOOK)')) | 57 | no_of_books = int(xmlbible.xpath('count(//BIBLEBOOK)')) |
1040 | 58 | self.wizard.progress_bar.setMaximum(int(xmlbible.xpath('count(//CHAPTER)'))) | 58 | self.wizard.progress_bar.setMaximum(int(xmlbible.xpath('count(//CHAPTER)'))) |
1041 | 59 | for BIBLEBOOK in xmlbible: | 59 | for BIBLEBOOK in xmlbible: |
1042 | 60 | if self.stop_import_flag: | 60 | if self.stop_import_flag: |
1043 | @@ -64,7 +64,7 @@ | |||
1044 | 64 | if not bname and not bnumber: | 64 | if not bname and not bnumber: |
1045 | 65 | continue | 65 | continue |
1046 | 66 | if bname: | 66 | if bname: |
1048 | 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) |
1049 | 68 | else: | 68 | else: |
1050 | 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.') |
1051 | 70 | book_ref_id = int(bnumber) | 70 | book_ref_id = int(bnumber) |
1052 | @@ -79,7 +79,8 @@ | |||
1053 | 79 | chapter_number = CHAPTER.get("cnumber") | 79 | chapter_number = CHAPTER.get("cnumber") |
1054 | 80 | for VERS in CHAPTER: | 80 | for VERS in CHAPTER: |
1055 | 81 | verse_number = VERS.get("vnumber") | 81 | verse_number = VERS.get("vnumber") |
1057 | 82 | self.create_verse(db_book.id, chapter_number, verse_number, VERS.text.replace('<BR/>', '\n')) | 82 | self.create_verse( |
1058 | 83 | db_book.id, int(chapter_number), int(verse_number), VERS.text.replace('<BR/>', '\n')) | ||
1059 | 83 | self.wizard.increment_progress_bar( | 84 | self.wizard.increment_progress_bar( |
1060 | 84 | translate('BiblesPlugin.Zefnia', | 85 | translate('BiblesPlugin.Zefnia', |
1061 | 85 | 'Importing {book} {chapter}...').format(book=db_book.name, | 86 | 'Importing {book} {chapter}...').format(book=db_book.name, |
1062 | 86 | 87 | ||
1063 | === modified file 'openlp/plugins/bibles/lib/manager.py' | |||
1064 | --- openlp/plugins/bibles/lib/manager.py 2016-08-12 17:26:54 +0000 | |||
1065 | +++ openlp/plugins/bibles/lib/manager.py 2016-09-09 21:59:44 +0000 | |||
1066 | @@ -23,8 +23,8 @@ | |||
1067 | 23 | import logging | 23 | import logging |
1068 | 24 | import os | 24 | import os |
1069 | 25 | 25 | ||
1072 | 26 | from openlp.core.common import RegistryProperties, AppLocation, Settings, translate, delete_file, UiStrings | 26 | from openlp.core.common import AppLocation, OpenLPMixin, RegistryProperties, Settings, translate, delete_file, UiStrings |
1073 | 27 | from openlp.plugins.bibles.lib import parse_reference, LanguageSelection | 27 | from openlp.plugins.bibles.lib import LanguageSelection, parse_reference |
1074 | 28 | from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta | 28 | from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta |
1075 | 29 | from .importers.csvbible import CSVBible | 29 | from .importers.csvbible import CSVBible |
1076 | 30 | from .importers.http import HTTPBible | 30 | from .importers.http import HTTPBible |
1077 | @@ -88,7 +88,7 @@ | |||
1078 | 88 | ] | 88 | ] |
1079 | 89 | 89 | ||
1080 | 90 | 90 | ||
1082 | 91 | class BibleManager(RegistryProperties): | 91 | class BibleManager(OpenLPMixin, RegistryProperties): |
1083 | 92 | """ | 92 | """ |
1084 | 93 | The Bible manager which holds and manages all the Bibles. | 93 | The Bible manager which holds and manages all the Bibles. |
1085 | 94 | """ | 94 | """ |
1086 | 95 | 95 | ||
1087 | === modified file 'openlp/plugins/bibles/lib/upgrade.py' | |||
1088 | --- openlp/plugins/bibles/lib/upgrade.py 2016-05-21 08:31:24 +0000 | |||
1089 | +++ openlp/plugins/bibles/lib/upgrade.py 2016-09-09 21:59:44 +0000 | |||
1090 | @@ -24,8 +24,6 @@ | |||
1091 | 24 | """ | 24 | """ |
1092 | 25 | import logging | 25 | import logging |
1093 | 26 | 26 | ||
1094 | 27 | from sqlalchemy import delete, func, insert, select | ||
1095 | 28 | |||
1096 | 29 | log = logging.getLogger(__name__) | 27 | log = logging.getLogger(__name__) |
1097 | 30 | __version__ = 1 | 28 | __version__ = 1 |
1098 | 31 | 29 | ||
1099 | @@ -35,166 +33,6 @@ | |||
1100 | 35 | """ | 33 | """ |
1101 | 36 | Version 1 upgrade. | 34 | Version 1 upgrade. |
1102 | 37 | 35 | ||
1104 | 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. |
1105 | 39 | """ | 37 | """ |
1267 | 40 | metadata_table = metadata.tables['metadata'] | 38 | log.info('No upgrades to perform') |
1107 | 41 | # Copy "Version" to "name" ("version" used by upgrade system) | ||
1108 | 42 | try: | ||
1109 | 43 | session.execute(insert(metadata_table).values( | ||
1110 | 44 | key='name', | ||
1111 | 45 | value=select( | ||
1112 | 46 | [metadata_table.c.value], | ||
1113 | 47 | metadata_table.c.key == 'Version' | ||
1114 | 48 | ).as_scalar() | ||
1115 | 49 | )) | ||
1116 | 50 | session.execute(delete(metadata_table).where(metadata_table.c.key == 'Version')) | ||
1117 | 51 | except: | ||
1118 | 52 | log.exception('Exception when upgrading Version') | ||
1119 | 53 | # Copy "Copyright" to "copyright" | ||
1120 | 54 | try: | ||
1121 | 55 | session.execute(insert(metadata_table).values( | ||
1122 | 56 | key='copyright', | ||
1123 | 57 | value=select( | ||
1124 | 58 | [metadata_table.c.value], | ||
1125 | 59 | metadata_table.c.key == 'Copyright' | ||
1126 | 60 | ).as_scalar() | ||
1127 | 61 | )) | ||
1128 | 62 | session.execute(delete(metadata_table).where(metadata_table.c.key == 'Copyright')) | ||
1129 | 63 | except: | ||
1130 | 64 | log.exception('Exception when upgrading Copyright') | ||
1131 | 65 | # Copy "Permissions" to "permissions" | ||
1132 | 66 | try: | ||
1133 | 67 | session.execute(insert(metadata_table).values( | ||
1134 | 68 | key='permissions', | ||
1135 | 69 | value=select( | ||
1136 | 70 | [metadata_table.c.value], | ||
1137 | 71 | metadata_table.c.key == 'Permissions' | ||
1138 | 72 | ).as_scalar() | ||
1139 | 73 | )) | ||
1140 | 74 | session.execute(delete(metadata_table).where(metadata_table.c.key == 'Permissions')) | ||
1141 | 75 | except: | ||
1142 | 76 | log.exception('Exception when upgrading Permissions') | ||
1143 | 77 | # Copy "Bookname language" to "book_name_language" | ||
1144 | 78 | try: | ||
1145 | 79 | value_count = session.execute( | ||
1146 | 80 | select( | ||
1147 | 81 | [func.count(metadata_table.c.value)], | ||
1148 | 82 | metadata_table.c.key == 'Bookname language' | ||
1149 | 83 | ) | ||
1150 | 84 | ).scalar() | ||
1151 | 85 | if value_count > 0: | ||
1152 | 86 | session.execute(insert(metadata_table).values( | ||
1153 | 87 | key='book_name_language', | ||
1154 | 88 | value=select( | ||
1155 | 89 | [metadata_table.c.value], | ||
1156 | 90 | metadata_table.c.key == 'Bookname language' | ||
1157 | 91 | ).as_scalar() | ||
1158 | 92 | )) | ||
1159 | 93 | session.execute(delete(metadata_table).where(metadata_table.c.key == 'Bookname language')) | ||
1160 | 94 | except: | ||
1161 | 95 | log.exception('Exception when upgrading Bookname language') | ||
1162 | 96 | # Copy "download source" to "download_source" | ||
1163 | 97 | try: | ||
1164 | 98 | value_count = session.execute( | ||
1165 | 99 | select( | ||
1166 | 100 | [func.count(metadata_table.c.value)], | ||
1167 | 101 | metadata_table.c.key == 'download source' | ||
1168 | 102 | ) | ||
1169 | 103 | ).scalar() | ||
1170 | 104 | log.debug('download source: {count}'.format(count=value_count)) | ||
1171 | 105 | if value_count > 0: | ||
1172 | 106 | session.execute(insert(metadata_table).values( | ||
1173 | 107 | key='download_source', | ||
1174 | 108 | value=select( | ||
1175 | 109 | [metadata_table.c.value], | ||
1176 | 110 | metadata_table.c.key == 'download source' | ||
1177 | 111 | ).as_scalar() | ||
1178 | 112 | )) | ||
1179 | 113 | session.execute(delete(metadata_table).where(metadata_table.c.key == 'download source')) | ||
1180 | 114 | except: | ||
1181 | 115 | log.exception('Exception when upgrading download source') | ||
1182 | 116 | # Copy "download name" to "download_name" | ||
1183 | 117 | try: | ||
1184 | 118 | value_count = session.execute( | ||
1185 | 119 | select( | ||
1186 | 120 | [func.count(metadata_table.c.value)], | ||
1187 | 121 | metadata_table.c.key == 'download name' | ||
1188 | 122 | ) | ||
1189 | 123 | ).scalar() | ||
1190 | 124 | log.debug('download name: {count}'.format(count=value_count)) | ||
1191 | 125 | if value_count > 0: | ||
1192 | 126 | session.execute(insert(metadata_table).values( | ||
1193 | 127 | key='download_name', | ||
1194 | 128 | value=select( | ||
1195 | 129 | [metadata_table.c.value], | ||
1196 | 130 | metadata_table.c.key == 'download name' | ||
1197 | 131 | ).as_scalar() | ||
1198 | 132 | )) | ||
1199 | 133 | session.execute(delete(metadata_table).where(metadata_table.c.key == 'download name')) | ||
1200 | 134 | except: | ||
1201 | 135 | log.exception('Exception when upgrading download name') | ||
1202 | 136 | # Copy "proxy server" to "proxy_server" | ||
1203 | 137 | try: | ||
1204 | 138 | value_count = session.execute( | ||
1205 | 139 | select( | ||
1206 | 140 | [func.count(metadata_table.c.value)], | ||
1207 | 141 | metadata_table.c.key == 'proxy server' | ||
1208 | 142 | ) | ||
1209 | 143 | ).scalar() | ||
1210 | 144 | log.debug('proxy server: {count}'.format(count=value_count)) | ||
1211 | 145 | if value_count > 0: | ||
1212 | 146 | session.execute(insert(metadata_table).values( | ||
1213 | 147 | key='proxy_server', | ||
1214 | 148 | value=select( | ||
1215 | 149 | [metadata_table.c.value], | ||
1216 | 150 | metadata_table.c.key == 'proxy server' | ||
1217 | 151 | ).as_scalar() | ||
1218 | 152 | )) | ||
1219 | 153 | session.execute(delete(metadata_table).where(metadata_table.c.key == 'proxy server')) | ||
1220 | 154 | except: | ||
1221 | 155 | log.exception('Exception when upgrading proxy server') | ||
1222 | 156 | # Copy "proxy username" to "proxy_username" | ||
1223 | 157 | try: | ||
1224 | 158 | value_count = session.execute( | ||
1225 | 159 | select( | ||
1226 | 160 | [func.count(metadata_table.c.value)], | ||
1227 | 161 | metadata_table.c.key == 'proxy username' | ||
1228 | 162 | ) | ||
1229 | 163 | ).scalar() | ||
1230 | 164 | log.debug('proxy username: {count}'.format(count=value_count)) | ||
1231 | 165 | if value_count > 0: | ||
1232 | 166 | session.execute(insert(metadata_table).values( | ||
1233 | 167 | key='proxy_username', | ||
1234 | 168 | value=select( | ||
1235 | 169 | [metadata_table.c.value], | ||
1236 | 170 | metadata_table.c.key == 'proxy username' | ||
1237 | 171 | ).as_scalar() | ||
1238 | 172 | )) | ||
1239 | 173 | session.execute(delete(metadata_table).where(metadata_table.c.key == 'proxy username')) | ||
1240 | 174 | except: | ||
1241 | 175 | log.exception('Exception when upgrading proxy username') | ||
1242 | 176 | # Copy "proxy password" to "proxy_password" | ||
1243 | 177 | try: | ||
1244 | 178 | value_count = session.execute( | ||
1245 | 179 | select( | ||
1246 | 180 | [func.count(metadata_table.c.value)], | ||
1247 | 181 | metadata_table.c.key == 'proxy password' | ||
1248 | 182 | ) | ||
1249 | 183 | ).scalar() | ||
1250 | 184 | log.debug('proxy password: {count}'.format(count=value_count)) | ||
1251 | 185 | if value_count > 0: | ||
1252 | 186 | session.execute(insert(metadata_table).values( | ||
1253 | 187 | key='proxy_password', | ||
1254 | 188 | value=select( | ||
1255 | 189 | [metadata_table.c.value], | ||
1256 | 190 | metadata_table.c.key == 'proxy password' | ||
1257 | 191 | ).as_scalar() | ||
1258 | 192 | )) | ||
1259 | 193 | session.execute(delete(metadata_table).where(metadata_table.c.key == 'proxy password')) | ||
1260 | 194 | except: | ||
1261 | 195 | log.exception('Exception when upgrading proxy password') | ||
1262 | 196 | try: | ||
1263 | 197 | session.execute(delete(metadata_table).where(metadata_table.c.key == 'dbversion')) | ||
1264 | 198 | except: | ||
1265 | 199 | log.exception('Exception when deleting dbversion') | ||
1266 | 200 | session.commit() | ||
1268 | 201 | 39 | ||
1269 | === modified file 'tests/functional/openlp_core_ui/test_exceptionform.py' | |||
1270 | --- tests/functional/openlp_core_ui/test_exceptionform.py 2016-06-25 14:41:06 +0000 | |||
1271 | +++ tests/functional/openlp_core_ui/test_exceptionform.py 2016-09-09 21:59:44 +0000 | |||
1272 | @@ -24,18 +24,13 @@ | |||
1273 | 24 | """ | 24 | """ |
1274 | 25 | 25 | ||
1275 | 26 | import os | 26 | import os |
1276 | 27 | import socket | ||
1277 | 28 | import tempfile | 27 | import tempfile |
1278 | 29 | import urllib | ||
1279 | 30 | from unittest import TestCase | 28 | from unittest import TestCase |
1280 | 31 | from unittest.mock import mock_open | 29 | from unittest.mock import mock_open |
1281 | 32 | 30 | ||
1282 | 33 | from PyQt5.QtCore import QUrlQuery | ||
1283 | 34 | |||
1284 | 35 | from openlp.core.common import Registry | 31 | from openlp.core.common import Registry |
1285 | 36 | from openlp.core.ui.firsttimeform import FirstTimeForm | ||
1286 | 37 | 32 | ||
1288 | 38 | from tests.functional import MagicMock, patch | 33 | from tests.functional import patch |
1289 | 39 | from tests.helpers.testmixin import TestMixin | 34 | from tests.helpers.testmixin import TestMixin |
1290 | 40 | 35 | ||
1291 | 41 | from openlp.core.ui import exceptionform | 36 | from openlp.core.ui import exceptionform |
1292 | 42 | 37 | ||
1293 | === modified file 'tests/functional/openlp_plugins/bibles/test_bibleimport.py' | |||
1294 | --- tests/functional/openlp_plugins/bibles/test_bibleimport.py 2016-08-07 11:20:53 +0000 | |||
1295 | +++ tests/functional/openlp_plugins/bibles/test_bibleimport.py 2016-09-09 21:59:44 +0000 | |||
1296 | @@ -27,9 +27,12 @@ | |||
1297 | 27 | from lxml import etree, objectify | 27 | from lxml import etree, objectify |
1298 | 28 | 28 | ||
1299 | 29 | from unittest import TestCase | 29 | from unittest import TestCase |
1300 | 30 | from PyQt5.QtWidgets import QDialog | ||
1301 | 30 | 31 | ||
1302 | 31 | from openlp.core.common.languages import Language | 32 | from openlp.core.common.languages import Language |
1303 | 33 | from openlp.core.lib.exceptions import ValidationError | ||
1304 | 32 | from openlp.plugins.bibles.lib.bibleimport import BibleImport | 34 | from openlp.plugins.bibles.lib.bibleimport import BibleImport |
1305 | 35 | from openlp.plugins.bibles.lib.db import BibleDB | ||
1306 | 33 | from tests.functional import MagicMock, patch | 36 | from tests.functional import MagicMock, patch |
1307 | 34 | 37 | ||
1308 | 35 | 38 | ||
1309 | @@ -39,22 +42,103 @@ | |||
1310 | 39 | """ | 42 | """ |
1311 | 40 | 43 | ||
1312 | 41 | def setUp(self): | 44 | def setUp(self): |
1320 | 42 | test_file = BytesIO(b'<?xml version="1.0" encoding="UTF-8" ?>\n' | 45 | self.test_file = BytesIO( |
1321 | 43 | b'<root>\n' | 46 | b'<?xml version="1.0" encoding="UTF-8" ?>\n' |
1322 | 44 | b' <data><div>Test<p>data</p><a>to</a>keep</div></data>\n' | 47 | b'<root>\n' |
1323 | 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' |
1324 | 46 | b'</root>') | 49 | b' <data><unsupported>Test<x>data</x><y>to</y>discard</unsupported></data>\n' |
1325 | 47 | self.file_patcher = patch('builtins.open', return_value=test_file) | 50 | b'</root>' |
1326 | 48 | self.log_patcher = patch('openlp.plugins.bibles.lib.bibleimport.log') | 51 | ) |
1327 | 52 | self.open_patcher = patch('builtins.open') | ||
1328 | 53 | self.addCleanup(self.open_patcher.stop) | ||
1329 | 54 | self.mocked_open = self.open_patcher.start() | ||
1330 | 55 | self.critical_error_message_box_patcher = \ | ||
1331 | 56 | patch('openlp.plugins.bibles.lib.bibleimport.critical_error_message_box') | ||
1332 | 57 | self.addCleanup(self.critical_error_message_box_patcher.stop) | ||
1333 | 58 | self.mocked_critical_error_message_box = self.critical_error_message_box_patcher.start() | ||
1334 | 49 | self.setup_patcher = patch('openlp.plugins.bibles.lib.db.BibleDB._setup') | 59 | self.setup_patcher = patch('openlp.plugins.bibles.lib.db.BibleDB._setup') |
1335 | 50 | |||
1336 | 51 | self.addCleanup(self.file_patcher.stop) | ||
1337 | 52 | self.addCleanup(self.log_patcher.stop) | ||
1338 | 53 | self.addCleanup(self.setup_patcher.stop) | 60 | self.addCleanup(self.setup_patcher.stop) |
1339 | 54 | |||
1340 | 55 | self.file_patcher.start() | ||
1341 | 56 | self.mock_log = self.log_patcher.start() | ||
1342 | 57 | self.setup_patcher.start() | 61 | self.setup_patcher.start() |
1343 | 62 | self.translate_patcher = patch('openlp.plugins.bibles.lib.bibleimport.translate', | ||
1344 | 63 | side_effect=lambda module, string_to_translate, *args: string_to_translate) | ||
1345 | 64 | self.addCleanup(self.translate_patcher.stop) | ||
1346 | 65 | self.mocked_translate = self.translate_patcher.start() | ||
1347 | 66 | self.registry_patcher = patch('openlp.plugins.bibles.lib.bibleimport.Registry') | ||
1348 | 67 | self.addCleanup(self.registry_patcher.stop) | ||
1349 | 68 | self.registry_patcher.start() | ||
1350 | 69 | |||
1351 | 70 | def init_kwargs_none_test(self): | ||
1352 | 71 | """ | ||
1353 | 72 | Test the initialisation of the BibleImport Class when no key word arguments are supplied | ||
1354 | 73 | """ | ||
1355 | 74 | # GIVEN: A patched BibleDB._setup, BibleImport class and mocked parent | ||
1356 | 75 | # WHEN: Creating an instance of BibleImport with no key word arguments | ||
1357 | 76 | instance = BibleImport(MagicMock()) | ||
1358 | 77 | |||
1359 | 78 | # THEN: The filename attribute should be None | ||
1360 | 79 | self.assertIsNone(instance.filename) | ||
1361 | 80 | self.assertIsInstance(instance, BibleDB) | ||
1362 | 81 | |||
1363 | 82 | def init_kwargs_set_test(self): | ||
1364 | 83 | """ | ||
1365 | 84 | Test the initialisation of the BibleImport Class when supplied with select keyword arguments | ||
1366 | 85 | """ | ||
1367 | 86 | # GIVEN: A patched BibleDB._setup, BibleImport class and mocked parent | ||
1368 | 87 | # WHEN: Creating an instance of BibleImport with selected key word arguments | ||
1369 | 88 | kwargs = {'filename': 'bible.xml'} | ||
1370 | 89 | instance = BibleImport(MagicMock(), **kwargs) | ||
1371 | 90 | |||
1372 | 91 | # THEN: The filename keyword should be set to bible.xml | ||
1373 | 92 | self.assertEqual(instance.filename, 'bible.xml') | ||
1374 | 93 | self.assertIsInstance(instance, BibleDB) | ||
1375 | 94 | |||
1376 | 95 | def get_language_canceled_test(self): | ||
1377 | 96 | """ | ||
1378 | 97 | Test the BibleImport.get_language method when the user rejects the dialog box | ||
1379 | 98 | """ | ||
1380 | 99 | # GIVEN: A mocked LanguageForm with an exec method which returns QtDialog.Rejected and an instance of BibleDB | ||
1381 | 100 | with patch.object(BibleDB, '_setup'), patch('openlp.plugins.bibles.forms.LanguageForm') as mocked_language_form: | ||
1382 | 101 | |||
1383 | 102 | # The integer value of QtDialog.Rejected is 0. Using the enumeration causes a seg fault for some reason | ||
1384 | 103 | mocked_language_form_instance = MagicMock(**{'exec.return_value': 0}) | ||
1385 | 104 | mocked_language_form.return_value = mocked_language_form_instance | ||
1386 | 105 | instance = BibleImport(MagicMock()) | ||
1387 | 106 | mocked_wizard = MagicMock() | ||
1388 | 107 | instance.wizard = mocked_wizard | ||
1389 | 108 | |||
1390 | 109 | # WHEN: Calling get_language() | ||
1391 | 110 | result = instance.get_language() | ||
1392 | 111 | |||
1393 | 112 | # THEN: get_language() should return False | ||
1394 | 113 | mocked_language_form.assert_called_once_with(mocked_wizard) | ||
1395 | 114 | mocked_language_form_instance.exec.assert_called_once_with(None) | ||
1396 | 115 | self.assertFalse(result, 'get_language() should return False if the user rejects the dialog box') | ||
1397 | 116 | |||
1398 | 117 | def get_language_accepted_test(self): | ||
1399 | 118 | """ | ||
1400 | 119 | Test the BibleImport.get_language method when the user accepts the dialog box | ||
1401 | 120 | """ | ||
1402 | 121 | # GIVEN: A mocked LanguageForm with an exec method which returns QtDialog.Accepted an instance of BibleDB and | ||
1403 | 122 | # a combobox with the selected item data as 10 | ||
1404 | 123 | with patch.object(BibleDB, 'save_meta'), patch.object(BibleDB, '_setup'), \ | ||
1405 | 124 | patch('openlp.plugins.bibles.forms.LanguageForm') as mocked_language_form: | ||
1406 | 125 | |||
1407 | 126 | # The integer value of QtDialog.Accepted is 1. Using the enumeration causes a seg fault for some reason | ||
1408 | 127 | mocked_language_form_instance = MagicMock(**{'exec.return_value': 1, | ||
1409 | 128 | 'language_combo_box.itemData.return_value': 10}) | ||
1410 | 129 | mocked_language_form.return_value = mocked_language_form_instance | ||
1411 | 130 | instance = BibleImport(MagicMock()) | ||
1412 | 131 | mocked_wizard = MagicMock() | ||
1413 | 132 | instance.wizard = mocked_wizard | ||
1414 | 133 | |||
1415 | 134 | # WHEN: Calling get_language() | ||
1416 | 135 | result = instance.get_language('Bible Name') | ||
1417 | 136 | |||
1418 | 137 | # THEN: get_language() should return the id of the selected language in the combo box | ||
1419 | 138 | mocked_language_form.assert_called_once_with(mocked_wizard) | ||
1420 | 139 | mocked_language_form_instance.exec.assert_called_once_with('Bible Name') | ||
1421 | 140 | self.assertEqual(result, 10, 'get_language() should return the id of the language the user has chosen when ' | ||
1422 | 141 | 'they accept the dialog box') | ||
1423 | 58 | 142 | ||
1424 | 59 | def get_language_id_language_found_test(self): | 143 | def get_language_id_language_found_test(self): |
1425 | 60 | """ | 144 | """ |
1426 | @@ -63,7 +147,7 @@ | |||
1427 | 63 | # GIVEN: A mocked languages.get_language which returns language and an instance of BibleImport | 147 | # GIVEN: A mocked languages.get_language which returns language and an instance of BibleImport |
1428 | 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')) \ |
1429 | 65 | as mocked_languages_get_language, \ | 149 | as mocked_languages_get_language, \ |
1431 | 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: |
1432 | 67 | instance = BibleImport(MagicMock()) | 151 | instance = BibleImport(MagicMock()) |
1433 | 68 | instance.save_meta = MagicMock() | 152 | instance.save_meta = MagicMock() |
1434 | 69 | 153 | ||
1435 | @@ -81,9 +165,8 @@ | |||
1436 | 81 | Test get_language_id() when called with a name not found in the languages list | 165 | Test get_language_id() when called with a name not found in the languages list |
1437 | 82 | """ | 166 | """ |
1438 | 83 | # GIVEN: A mocked languages.get_language which returns language and an instance of BibleImport | 167 | # GIVEN: A mocked languages.get_language which returns language and an instance of BibleImport |
1442 | 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, \ |
1443 | 85 | as mocked_languages_get_language, \ | 169 | patch.object(BibleImport, 'get_language', return_value=20) as mocked_db_get_language: |
1441 | 86 | patch('openlp.plugins.bibles.lib.db.BibleDB.get_language', return_value=20) as mocked_db_get_language: | ||
1444 | 87 | instance = BibleImport(MagicMock()) | 170 | instance = BibleImport(MagicMock()) |
1445 | 88 | instance.save_meta = MagicMock() | 171 | instance.save_meta = MagicMock() |
1446 | 89 | 172 | ||
1447 | @@ -103,8 +186,8 @@ | |||
1448 | 103 | # GIVEN: A mocked languages.get_language which returns None a mocked BibleDB.get_language which returns a | 186 | # GIVEN: A mocked languages.get_language which returns None a mocked BibleDB.get_language which returns a |
1449 | 104 | # language id. | 187 | # language id. |
1450 | 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, \ |
1453 | 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, \ |
1454 | 107 | self.mock_log.error.reset_mock() | 190 | patch.object(BibleImport, 'log_error') as mocked_log_error: |
1455 | 108 | instance = BibleImport(MagicMock()) | 191 | instance = BibleImport(MagicMock()) |
1456 | 109 | instance.save_meta = MagicMock() | 192 | instance.save_meta = MagicMock() |
1457 | 110 | 193 | ||
1458 | @@ -114,7 +197,7 @@ | |||
1459 | 114 | # THEN: The id of the language returned from BibleDB.get_language should be returned | 197 | # THEN: The id of the language returned from BibleDB.get_language should be returned |
1460 | 115 | mocked_languages_get_language.assert_called_once_with('English') | 198 | mocked_languages_get_language.assert_called_once_with('English') |
1461 | 116 | mocked_db_get_language.assert_called_once_with('KJV') | 199 | mocked_db_get_language.assert_called_once_with('KJV') |
1463 | 117 | self.assertFalse(self.mock_log.error.called) | 200 | self.assertFalse(mocked_log_error.error.called) |
1464 | 118 | instance.save_meta.assert_called_once_with('language_id', 40) | 201 | instance.save_meta.assert_called_once_with('language_id', 40) |
1465 | 119 | self.assertEqual(result, 40) | 202 | self.assertEqual(result, 40) |
1466 | 120 | 203 | ||
1467 | @@ -125,8 +208,8 @@ | |||
1468 | 125 | # GIVEN: A mocked languages.get_language which returns None a mocked BibleDB.get_language which returns a | 208 | # GIVEN: A mocked languages.get_language which returns None a mocked BibleDB.get_language which returns a |
1469 | 126 | # language id. | 209 | # language id. |
1470 | 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, \ |
1473 | 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, \ |
1474 | 129 | self.mock_log.error.reset_mock() | 212 | patch.object(BibleImport, 'log_error') as mocked_log_error: |
1475 | 130 | instance = BibleImport(MagicMock()) | 213 | instance = BibleImport(MagicMock()) |
1476 | 131 | instance.save_meta = MagicMock() | 214 | instance.save_meta = MagicMock() |
1477 | 132 | 215 | ||
1478 | @@ -136,18 +219,148 @@ | |||
1479 | 136 | # THEN: None should be returned and an error should be logged | 219 | # THEN: None should be returned and an error should be logged |
1480 | 137 | mocked_languages_get_language.assert_called_once_with('Qwerty') | 220 | mocked_languages_get_language.assert_called_once_with('Qwerty') |
1481 | 138 | mocked_db_get_language.assert_called_once_with('KJV') | 221 | mocked_db_get_language.assert_called_once_with('KJV') |
1484 | 139 | self.mock_log.error.assert_called_once_with('Language detection failed when importing from "KJV". ' | 222 | mocked_log_error.assert_called_once_with( |
1485 | 140 | 'User aborted language selection.') | 223 | 'Language detection failed when importing from "KJV". User aborted language selection.') |
1486 | 141 | self.assertFalse(instance.save_meta.called) | 224 | self.assertFalse(instance.save_meta.called) |
1487 | 142 | self.assertIsNone(result) | 225 | self.assertIsNone(result) |
1488 | 143 | 226 | ||
1489 | 227 | def get_book_ref_id_by_name_get_book_test(self): | ||
1490 | 228 | """ | ||
1491 | 229 | Test get_book_ref_id_by_name when the book is found as a book in BiblesResourcesDB | ||
1492 | 230 | """ | ||
1493 | 231 | # GIVEN: An instance of BibleImport and a mocked BiblesResourcesDB which returns a book id when get_book is | ||
1494 | 232 | # called | ||
1495 | 233 | with patch.object(BibleImport, 'log_debug'), \ | ||
1496 | 234 | patch('openlp.plugins.bibles.lib.bibleimport.BiblesResourcesDB', | ||
1497 | 235 | **{'get_book.return_value': {'id': 20}}): | ||
1498 | 236 | instance = BibleImport(MagicMock()) | ||
1499 | 237 | |||
1500 | 238 | # WHEN: Calling get_book_ref_id_by_name | ||
1501 | 239 | result = instance.get_book_ref_id_by_name('Gen', 66, 4) | ||
1502 | 240 | |||
1503 | 241 | # THEN: The bible id should be returned | ||
1504 | 242 | self.assertEqual(result, 20) | ||
1505 | 243 | |||
1506 | 244 | def get_book_ref_id_by_name_get_alternative_book_name_test(self): | ||
1507 | 245 | """ | ||
1508 | 246 | Test get_book_ref_id_by_name when the book is found as an alternative book in BiblesResourcesDB | ||
1509 | 247 | """ | ||
1510 | 248 | # GIVEN: An instance of BibleImport and a mocked BiblesResourcesDB which returns a book id when | ||
1511 | 249 | # get_alternative_book_name is called | ||
1512 | 250 | with patch.object(BibleImport, 'log_debug'), \ | ||
1513 | 251 | patch('openlp.plugins.bibles.lib.bibleimport.BiblesResourcesDB', | ||
1514 | 252 | **{'get_book.return_value': None, 'get_alternative_book_name.return_value': 30}): | ||
1515 | 253 | instance = BibleImport(MagicMock()) | ||
1516 | 254 | |||
1517 | 255 | # WHEN: Calling get_book_ref_id_by_name | ||
1518 | 256 | result = instance.get_book_ref_id_by_name('Gen', 66, 4) | ||
1519 | 257 | |||
1520 | 258 | # THEN: The bible id should be returned | ||
1521 | 259 | self.assertEqual(result, 30) | ||
1522 | 260 | |||
1523 | 261 | def get_book_ref_id_by_name_get_book_reference_id_test(self): | ||
1524 | 262 | """ | ||
1525 | 263 | Test get_book_ref_id_by_name when the book is found as a book in AlternativeBookNamesDB | ||
1526 | 264 | """ | ||
1527 | 265 | # GIVEN: An instance of BibleImport and a mocked AlternativeBookNamesDB which returns a book id when | ||
1528 | 266 | # get_book_reference_id is called | ||
1529 | 267 | with patch.object(BibleImport, 'log_debug'), \ | ||
1530 | 268 | patch('openlp.plugins.bibles.lib.bibleimport.BiblesResourcesDB', | ||
1531 | 269 | **{'get_book.return_value': None, 'get_alternative_book_name.return_value': None}), \ | ||
1532 | 270 | patch('openlp.plugins.bibles.lib.bibleimport.AlternativeBookNamesDB', | ||
1533 | 271 | **{'get_book_reference_id.return_value': 40}): | ||
1534 | 272 | instance = BibleImport(MagicMock()) | ||
1535 | 273 | |||
1536 | 274 | # WHEN: Calling get_book_ref_id_by_name | ||
1537 | 275 | result = instance.get_book_ref_id_by_name('Gen', 66, 4) | ||
1538 | 276 | |||
1539 | 277 | # THEN: The bible id should be returned | ||
1540 | 278 | self.assertEqual(result, 40) | ||
1541 | 279 | |||
1542 | 280 | def get_book_ref_id_by_name_book_name_form_rejected_test(self): | ||
1543 | 281 | """ | ||
1544 | 282 | Test get_book_ref_id_by_name when the user rejects the BookNameForm | ||
1545 | 283 | """ | ||
1546 | 284 | # GIVEN: An instance of BibleImport and a mocked BookNameForm which simulates a user rejecting the dialog | ||
1547 | 285 | with patch.object(BibleImport, 'log_debug'), patch.object(BibleImport, 'get_books'), \ | ||
1548 | 286 | patch('openlp.plugins.bibles.lib.bibleimport.BiblesResourcesDB', | ||
1549 | 287 | **{'get_book.return_value': None, 'get_alternative_book_name.return_value': None}), \ | ||
1550 | 288 | patch('openlp.plugins.bibles.lib.bibleimport.AlternativeBookNamesDB', | ||
1551 | 289 | **{'get_book_reference_id.return_value': None}), \ | ||
1552 | 290 | patch('openlp.plugins.bibles.forms.BookNameForm', | ||
1553 | 291 | return_value=MagicMock(**{'exec.return_value': QDialog.Rejected})): | ||
1554 | 292 | instance = BibleImport(MagicMock()) | ||
1555 | 293 | |||
1556 | 294 | # WHEN: Calling get_book_ref_id_by_name | ||
1557 | 295 | result = instance.get_book_ref_id_by_name('Gen', 66, 4) | ||
1558 | 296 | |||
1559 | 297 | # THEN: None should be returned | ||
1560 | 298 | self.assertIsNone(result) | ||
1561 | 299 | |||
1562 | 300 | def get_book_ref_id_by_name_book_name_form_accepted_test(self): | ||
1563 | 301 | """ | ||
1564 | 302 | Test get_book_ref_id_by_name when the user accepts the BookNameForm | ||
1565 | 303 | """ | ||
1566 | 304 | # GIVEN: An instance of BibleImport and a mocked BookNameForm which simulates a user accepting the dialog | ||
1567 | 305 | with patch.object(BibleImport, 'log_debug'), patch.object(BibleImport, 'get_books'), \ | ||
1568 | 306 | patch('openlp.plugins.bibles.lib.bibleimport.BiblesResourcesDB', | ||
1569 | 307 | **{'get_book.return_value': None, 'get_alternative_book_name.return_value': None}), \ | ||
1570 | 308 | patch('openlp.plugins.bibles.lib.bibleimport.AlternativeBookNamesDB', | ||
1571 | 309 | **{'get_book_reference_id.return_value': None}) as mocked_alternative_book_names_db, \ | ||
1572 | 310 | patch('openlp.plugins.bibles.forms.BookNameForm', | ||
1573 | 311 | return_value=MagicMock(**{'exec.return_value': QDialog.Accepted, 'book_id': 50})): | ||
1574 | 312 | instance = BibleImport(MagicMock()) | ||
1575 | 313 | |||
1576 | 314 | # WHEN: Calling get_book_ref_id_by_name | ||
1577 | 315 | result = instance.get_book_ref_id_by_name('Gen', 66, 4) | ||
1578 | 316 | |||
1579 | 317 | # THEN: An alternative book name should be created and a bible id should be returned | ||
1580 | 318 | mocked_alternative_book_names_db.create_alternative_book_name.assert_called_once_with('Gen', 50, 4) | ||
1581 | 319 | self.assertEqual(result, 50) | ||
1582 | 320 | |||
1583 | 321 | def is_compressed_compressed_test(self): | ||
1584 | 322 | """ | ||
1585 | 323 | Test is_compressed when the 'file' being tested is compressed | ||
1586 | 324 | """ | ||
1587 | 325 | # GIVEN: An instance of BibleImport and a mocked is_zipfile which returns True | ||
1588 | 326 | with patch('openlp.plugins.bibles.lib.bibleimport.is_zipfile', return_value=True): | ||
1589 | 327 | instance = BibleImport(MagicMock()) | ||
1590 | 328 | |||
1591 | 329 | # WHEN: Calling is_compressed | ||
1592 | 330 | result = instance.is_compressed('file.ext') | ||
1593 | 331 | |||
1594 | 332 | # THEN: Then critical_error_message_box should be called informing the user that the file is compressed and | ||
1595 | 333 | # True should be returned | ||
1596 | 334 | self.mocked_critical_error_message_box.assert_called_once_with( | ||
1597 | 335 | message='The file "file.ext" you supplied is compressed. You must decompress it before import.') | ||
1598 | 336 | self.assertTrue(result) | ||
1599 | 337 | |||
1600 | 338 | def is_compressed_not_compressed_test(self): | ||
1601 | 339 | """ | ||
1602 | 340 | Test is_compressed when the 'file' being tested is not compressed | ||
1603 | 341 | """ | ||
1604 | 342 | # GIVEN: An instance of BibleImport and a mocked is_zipfile which returns False | ||
1605 | 343 | with patch('openlp.plugins.bibles.lib.bibleimport.is_zipfile', return_value=False): | ||
1606 | 344 | instance = BibleImport(MagicMock()) | ||
1607 | 345 | |||
1608 | 346 | # WHEN: Calling is_compressed | ||
1609 | 347 | result = instance.is_compressed('file.ext') | ||
1610 | 348 | |||
1611 | 349 | # THEN: False should be returned and critical_error_message_box should not have been called | ||
1612 | 350 | self.assertFalse(result) | ||
1613 | 351 | self.assertFalse(self.mocked_critical_error_message_box.called) | ||
1614 | 352 | |||
1615 | 144 | def parse_xml_etree_test(self): | 353 | def parse_xml_etree_test(self): |
1616 | 145 | """ | 354 | """ |
1617 | 146 | Test BibleImport.parse_xml() when called with the use_objectify default value | 355 | Test BibleImport.parse_xml() when called with the use_objectify default value |
1618 | 147 | """ | 356 | """ |
1620 | 148 | # GIVEN: A sample "file" to parse | 357 | # GIVEN: A sample "file" to parse and an instance of BibleImport |
1621 | 358 | self.mocked_open.return_value = self.test_file | ||
1622 | 359 | instance = BibleImport(MagicMock()) | ||
1623 | 360 | instance.wizard = MagicMock() | ||
1624 | 361 | |||
1625 | 149 | # WHEN: Calling parse_xml | 362 | # WHEN: Calling parse_xml |
1627 | 150 | result = BibleImport.parse_xml('file.tst') | 363 | result = instance.parse_xml('file.tst') |
1628 | 151 | 364 | ||
1629 | 152 | # THEN: The result returned should contain the correct data, and should be an instance of eetree_Element | 365 | # THEN: The result returned should contain the correct data, and should be an instance of eetree_Element |
1630 | 153 | self.assertEqual(etree.tostring(result), | 366 | self.assertEqual(etree.tostring(result), |
1631 | @@ -159,9 +372,13 @@ | |||
1632 | 159 | """ | 372 | """ |
1633 | 160 | Test BibleImport.parse_xml() when called with use_objectify set to True | 373 | Test BibleImport.parse_xml() when called with use_objectify set to True |
1634 | 161 | """ | 374 | """ |
1636 | 162 | # GIVEN: A sample "file" to parse | 375 | # GIVEN: A sample "file" to parse and an instance of BibleImport |
1637 | 376 | self.mocked_open.return_value = self.test_file | ||
1638 | 377 | instance = BibleImport(MagicMock()) | ||
1639 | 378 | instance.wizard = MagicMock() | ||
1640 | 379 | |||
1641 | 163 | # WHEN: Calling parse_xml | 380 | # WHEN: Calling parse_xml |
1643 | 164 | result = BibleImport.parse_xml('file.tst', use_objectify=True) | 381 | result = instance.parse_xml('file.tst', use_objectify=True) |
1644 | 165 | 382 | ||
1645 | 166 | # THEN: The result returned should contain the correct data, and should be an instance of ObjectifiedElement | 383 | # THEN: The result returned should contain the correct data, and should be an instance of ObjectifiedElement |
1646 | 167 | self.assertEqual(etree.tostring(result), | 384 | self.assertEqual(etree.tostring(result), |
1647 | @@ -173,11 +390,14 @@ | |||
1648 | 173 | """ | 390 | """ |
1649 | 174 | Test BibleImport.parse_xml() when given a tuple of elements to remove | 391 | Test BibleImport.parse_xml() when given a tuple of elements to remove |
1650 | 175 | """ | 392 | """ |
1652 | 176 | # GIVEN: A tuple of elements to remove | 393 | # GIVEN: A tuple of elements to remove and an instance of BibleImport |
1653 | 394 | self.mocked_open.return_value = self.test_file | ||
1654 | 177 | elements = ('unsupported', 'x', 'y') | 395 | elements = ('unsupported', 'x', 'y') |
1655 | 396 | instance = BibleImport(MagicMock()) | ||
1656 | 397 | instance.wizard = MagicMock() | ||
1657 | 178 | 398 | ||
1658 | 179 | # WHEN: Calling parse_xml, with a test file | 399 | # WHEN: Calling parse_xml, with a test file |
1660 | 180 | result = BibleImport.parse_xml('file.tst', elements=elements) | 400 | result = instance.parse_xml('file.tst', elements=elements) |
1661 | 181 | 401 | ||
1662 | 182 | # THEN: The result returned should contain the correct data | 402 | # THEN: The result returned should contain the correct data |
1663 | 183 | self.assertEqual(etree.tostring(result), | 403 | self.assertEqual(etree.tostring(result), |
1664 | @@ -187,11 +407,14 @@ | |||
1665 | 187 | """ | 407 | """ |
1666 | 188 | Test BibleImport.parse_xml() when given a tuple of tags to remove | 408 | Test BibleImport.parse_xml() when given a tuple of tags to remove |
1667 | 189 | """ | 409 | """ |
1669 | 190 | # GIVEN: A tuple of tags to remove | 410 | # GIVEN: A tuple of tags to remove and an instance of BibleImport |
1670 | 411 | self.mocked_open.return_value = self.test_file | ||
1671 | 191 | tags = ('div', 'p', 'a') | 412 | tags = ('div', 'p', 'a') |
1672 | 413 | instance = BibleImport(MagicMock()) | ||
1673 | 414 | instance.wizard = MagicMock() | ||
1674 | 192 | 415 | ||
1675 | 193 | # WHEN: Calling parse_xml, with a test file | 416 | # WHEN: Calling parse_xml, with a test file |
1677 | 194 | result = BibleImport.parse_xml('file.tst', tags=tags) | 417 | result = instance.parse_xml('file.tst', tags=tags) |
1678 | 195 | 418 | ||
1679 | 196 | # THEN: The result returned should contain the correct data | 419 | # THEN: The result returned should contain the correct data |
1680 | 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' |
1681 | @@ -201,12 +424,192 @@ | |||
1682 | 201 | """ | 424 | """ |
1683 | 202 | Test BibleImport.parse_xml() when given a tuple of elements and of tags to remove | 425 | Test BibleImport.parse_xml() when given a tuple of elements and of tags to remove |
1684 | 203 | """ | 426 | """ |
1686 | 204 | # GIVEN: A tuple of elements and of tags to remove | 427 | # GIVEN: A tuple of elements and of tags to remove and an instacne of BibleImport |
1687 | 428 | self.mocked_open.return_value = self.test_file | ||
1688 | 205 | elements = ('unsupported', 'x', 'y') | 429 | elements = ('unsupported', 'x', 'y') |
1689 | 206 | tags = ('div', 'p', 'a') | 430 | tags = ('div', 'p', 'a') |
1690 | 431 | instance = BibleImport(MagicMock()) | ||
1691 | 432 | instance.wizard = MagicMock() | ||
1692 | 207 | 433 | ||
1693 | 208 | # WHEN: Calling parse_xml, with a test file | 434 | # WHEN: Calling parse_xml, with a test file |
1695 | 209 | result = BibleImport.parse_xml('file.tst', elements=elements, tags=tags) | 435 | result = instance.parse_xml('file.tst', elements=elements, tags=tags) |
1696 | 210 | 436 | ||
1697 | 211 | # THEN: The result returned should contain the correct data | 437 | # THEN: The result returned should contain the correct data |
1698 | 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>') |
1699 | 439 | |||
1700 | 440 | def parse_xml_file_file_not_found_exception_test(self): | ||
1701 | 441 | """ | ||
1702 | 442 | Test that parse_xml handles a FileNotFoundError exception correctly | ||
1703 | 443 | """ | ||
1704 | 444 | with patch.object(BibleImport, 'log_exception') as mocked_log_exception: | ||
1705 | 445 | # GIVEN: A mocked open which raises a FileNotFoundError and an instance of BibleImporter | ||
1706 | 446 | exception = FileNotFoundError() | ||
1707 | 447 | exception.filename = 'file.tst' | ||
1708 | 448 | exception.strerror = 'No such file or directory' | ||
1709 | 449 | self.mocked_open.side_effect = exception | ||
1710 | 450 | importer = BibleImport(MagicMock(), path='.', name='.', filename='') | ||
1711 | 451 | |||
1712 | 452 | # WHEN: Calling parse_xml | ||
1713 | 453 | result = importer.parse_xml('file.tst') | ||
1714 | 454 | |||
1715 | 455 | # THEN: parse_xml should have caught the error, informed the user and returned None | ||
1716 | 456 | mocked_log_exception.assert_called_once_with('Opening file.tst failed.') | ||
1717 | 457 | self.mocked_critical_error_message_box.assert_called_once_with( | ||
1718 | 458 | title='An Error Occured When Opening A File', | ||
1719 | 459 | message='The following error occurred when trying to open\nfile.tst:\n\nNo such file or directory') | ||
1720 | 460 | self.assertIsNone(result) | ||
1721 | 461 | |||
1722 | 462 | def parse_xml_file_permission_error_exception_test(self): | ||
1723 | 463 | """ | ||
1724 | 464 | Test that parse_xml handles a PermissionError exception correctly | ||
1725 | 465 | """ | ||
1726 | 466 | with patch.object(BibleImport, 'log_exception') as mocked_log_exception: | ||
1727 | 467 | # GIVEN: A mocked open which raises a PermissionError and an instance of BibleImporter | ||
1728 | 468 | exception = PermissionError() | ||
1729 | 469 | exception.filename = 'file.tst' | ||
1730 | 470 | exception.strerror = 'Permission denied' | ||
1731 | 471 | self.mocked_open.side_effect = exception | ||
1732 | 472 | importer = BibleImport(MagicMock(), path='.', name='.', filename='') | ||
1733 | 473 | |||
1734 | 474 | # WHEN: Calling parse_xml | ||
1735 | 475 | result = importer.parse_xml('file.tst') | ||
1736 | 476 | |||
1737 | 477 | # THEN: parse_xml should have caught the error, informed the user and returned None | ||
1738 | 478 | mocked_log_exception.assert_called_once_with('Opening file.tst failed.') | ||
1739 | 479 | self.mocked_critical_error_message_box.assert_called_once_with( | ||
1740 | 480 | title='An Error Occured When Opening A File', | ||
1741 | 481 | message='The following error occurred when trying to open\nfile.tst:\n\nPermission denied') | ||
1742 | 482 | self.assertIsNone(result) | ||
1743 | 483 | |||
1744 | 484 | def set_current_chapter_test(self): | ||
1745 | 485 | """ | ||
1746 | 486 | Test set_current_chapter | ||
1747 | 487 | """ | ||
1748 | 488 | # GIVEN: An instance of BibleImport and a mocked wizard | ||
1749 | 489 | importer = BibleImport(MagicMock(), path='.', name='.', filename='') | ||
1750 | 490 | importer.wizard = MagicMock() | ||
1751 | 491 | |||
1752 | 492 | # WHEN: Calling set_current_chapter | ||
1753 | 493 | importer.set_current_chapter('Book_Name', 'Chapter') | ||
1754 | 494 | |||
1755 | 495 | # THEN: Increment_progress_bar should have been called with a text string | ||
1756 | 496 | importer.wizard.increment_progress_bar.assert_called_once_with('Importing Book_Name Chapter...') | ||
1757 | 497 | |||
1758 | 498 | def validate_xml_file_compressed_file_test(self): | ||
1759 | 499 | """ | ||
1760 | 500 | Test that validate_xml_file raises a ValidationError when is_compressed returns True | ||
1761 | 501 | """ | ||
1762 | 502 | # GIVEN: A mocked parse_xml which returns None | ||
1763 | 503 | with patch.object(BibleImport, 'is_compressed', return_value=True): | ||
1764 | 504 | importer = BibleImport(MagicMock(), path='.', name='.', filename='') | ||
1765 | 505 | |||
1766 | 506 | # WHEN: Calling is_compressed | ||
1767 | 507 | # THEN: ValidationError should be raised, with the message 'Compressed file' | ||
1768 | 508 | with self.assertRaises(ValidationError) as context: | ||
1769 | 509 | importer.validate_xml_file('file.name', 'xbible') | ||
1770 | 510 | self.assertEqual(context.exception.msg, 'Compressed file') | ||
1771 | 511 | |||
1772 | 512 | def validate_xml_file_parse_xml_fails_test(self): | ||
1773 | 513 | """ | ||
1774 | 514 | Test that validate_xml_file raises a ValidationError when parse_xml returns None | ||
1775 | 515 | """ | ||
1776 | 516 | # GIVEN: A mocked parse_xml which returns None | ||
1777 | 517 | with patch.object(BibleImport, 'parse_xml', return_value=None), \ | ||
1778 | 518 | patch.object(BibleImport, 'is_compressed', return_value=False): | ||
1779 | 519 | importer = BibleImport(MagicMock(), path='.', name='.', filename='') | ||
1780 | 520 | |||
1781 | 521 | # WHEN: Calling validate_xml_file | ||
1782 | 522 | # THEN: ValidationError should be raised, with the message 'Error when opening file' | ||
1783 | 523 | # the user that an OpenSong bible was found | ||
1784 | 524 | with self.assertRaises(ValidationError) as context: | ||
1785 | 525 | importer.validate_xml_file('file.name', 'xbible') | ||
1786 | 526 | self.assertEqual(context.exception.msg, 'Error when opening file') | ||
1787 | 527 | |||
1788 | 528 | def validate_xml_file_success_test(self): | ||
1789 | 529 | """ | ||
1790 | 530 | Test that validate_xml_file returns True with valid XML | ||
1791 | 531 | """ | ||
1792 | 532 | # GIVEN: Some test data with an OpenSong Bible "bible" root tag | ||
1793 | 533 | with patch.object(BibleImport, 'parse_xml', return_value=objectify.fromstring('<bible></bible>')), \ | ||
1794 | 534 | patch.object(BibleImport, 'is_compressed', return_value=False): | ||
1795 | 535 | importer = BibleImport(MagicMock(), path='.', name='.', filename='') | ||
1796 | 536 | |||
1797 | 537 | # WHEN: Calling validate_xml_file | ||
1798 | 538 | result = importer.validate_xml_file('file.name', 'bible') | ||
1799 | 539 | |||
1800 | 540 | # THEN: True should be returned | ||
1801 | 541 | self.assertTrue(result) | ||
1802 | 542 | |||
1803 | 543 | def validate_xml_file_opensong_root_test(self): | ||
1804 | 544 | """ | ||
1805 | 545 | Test that validate_xml_file raises a ValidationError with an OpenSong root tag | ||
1806 | 546 | """ | ||
1807 | 547 | # GIVEN: Some test data with an Zefania root tag and an instance of BibleImport | ||
1808 | 548 | with patch.object(BibleImport, 'parse_xml', return_value=objectify.fromstring('<bible></bible>')), \ | ||
1809 | 549 | patch.object(BibleImport, 'is_compressed', return_value=False): | ||
1810 | 550 | importer = BibleImport(MagicMock(), path='.', name='.', filename='') | ||
1811 | 551 | |||
1812 | 552 | # WHEN: Calling validate_xml_file | ||
1813 | 553 | # THEN: ValidationError should be raised, and the critical error message box should was called informing | ||
1814 | 554 | # the user that an OpenSong bible was found | ||
1815 | 555 | with self.assertRaises(ValidationError) as context: | ||
1816 | 556 | importer.validate_xml_file('file.name', 'xbible') | ||
1817 | 557 | self.assertEqual(context.exception.msg, 'Invalid xml.') | ||
1818 | 558 | self.mocked_critical_error_message_box.assert_called_once_with( | ||
1819 | 559 | message='Incorrect Bible file type supplied. This looks like an OpenSong XML bible.') | ||
1820 | 560 | |||
1821 | 561 | def validate_xml_file_osis_root_test(self): | ||
1822 | 562 | """ | ||
1823 | 563 | Test that validate_xml_file raises a ValidationError with an OSIS root tag | ||
1824 | 564 | """ | ||
1825 | 565 | # GIVEN: Some test data with an Zefania root tag and an instance of BibleImport | ||
1826 | 566 | with patch.object(BibleImport, 'parse_xml', return_value=objectify.fromstring( | ||
1827 | 567 | '<osis xmlns=\'http://www.bibletechnologies.net/2003/OSIS/namespace\'></osis>')), \ | ||
1828 | 568 | patch.object(BibleImport, 'is_compressed', return_value=False): | ||
1829 | 569 | importer = BibleImport(MagicMock(), path='.', name='.', filename='') | ||
1830 | 570 | |||
1831 | 571 | # WHEN: Calling validate_xml_file | ||
1832 | 572 | # THEN: ValidationError should be raised, and the critical error message box should was called informing | ||
1833 | 573 | # the user that an OSIS bible was found | ||
1834 | 574 | with self.assertRaises(ValidationError) as context: | ||
1835 | 575 | importer.validate_xml_file('file.name', 'xbible') | ||
1836 | 576 | self.assertEqual(context.exception.msg, 'Invalid xml.') | ||
1837 | 577 | self.mocked_critical_error_message_box.assert_called_once_with( | ||
1838 | 578 | message='Incorrect Bible file type supplied. This looks like an OSIS XML bible.') | ||
1839 | 579 | |||
1840 | 580 | def validate_xml_file_zefania_root_test(self): | ||
1841 | 581 | """ | ||
1842 | 582 | Test that validate_xml_file raises a ValidationError with an Zefania root tag | ||
1843 | 583 | """ | ||
1844 | 584 | # GIVEN: Some test data with an Zefania root tag and an instance of BibleImport | ||
1845 | 585 | with patch.object(BibleImport, 'parse_xml', return_value=objectify.fromstring('<xmlbible></xmlbible>')), \ | ||
1846 | 586 | patch.object(BibleImport, 'is_compressed', return_value=False): | ||
1847 | 587 | importer = BibleImport(MagicMock(), path='.', name='.', filename='') | ||
1848 | 588 | |||
1849 | 589 | # WHEN: Calling validate_xml_file | ||
1850 | 590 | # THEN: ValidationError should be raised, and the critical error message box should was called informing | ||
1851 | 591 | # the user that an Zefania bible was found | ||
1852 | 592 | with self.assertRaises(ValidationError) as context: | ||
1853 | 593 | importer.validate_xml_file('file.name', 'xbible') | ||
1854 | 594 | self.assertEqual(context.exception.msg, 'Invalid xml.') | ||
1855 | 595 | self.mocked_critical_error_message_box.assert_called_once_with( | ||
1856 | 596 | message='Incorrect Bible file type supplied. This looks like an Zefania XML bible.') | ||
1857 | 597 | |||
1858 | 598 | def validate_xml_file_unknown_root_test(self): | ||
1859 | 599 | """ | ||
1860 | 600 | Test that validate_xml_file raises a ValidationError with an unknown root tag | ||
1861 | 601 | """ | ||
1862 | 602 | # GIVEN: Some test data with an unknown root tag and an instance of BibleImport | ||
1863 | 603 | with patch.object( | ||
1864 | 604 | BibleImport, 'parse_xml', return_value=objectify.fromstring('<unknownbible></unknownbible>')), \ | ||
1865 | 605 | patch.object(BibleImport, 'is_compressed', return_value=False): | ||
1866 | 606 | importer = BibleImport(MagicMock(), path='.', name='.', filename='') | ||
1867 | 607 | |||
1868 | 608 | # WHEN: Calling validate_xml_file | ||
1869 | 609 | # THEN: ValidationError should be raised, and the critical error message box should was called informing | ||
1870 | 610 | # the user that a unknown xml bible was found | ||
1871 | 611 | with self.assertRaises(ValidationError) as context: | ||
1872 | 612 | importer.validate_xml_file('file.name', 'xbible') | ||
1873 | 613 | self.assertEqual(context.exception.msg, 'Invalid xml.') | ||
1874 | 614 | self.mocked_critical_error_message_box.assert_called_once_with( | ||
1875 | 615 | message='Incorrect Bible file type supplied. This looks like an unknown type of XML bible.') | ||
1876 | 213 | 616 | ||
1877 | === renamed file 'tests/functional/openlp_plugins/bibles/test_http.py' => 'tests/functional/openlp_plugins/bibles/test_bibleserver.py' | |||
1878 | === modified file 'tests/functional/openlp_plugins/bibles/test_csvimport.py' | |||
1879 | --- tests/functional/openlp_plugins/bibles/test_csvimport.py 2016-08-09 20:56:04 +0000 | |||
1880 | +++ tests/functional/openlp_plugins/bibles/test_csvimport.py 2016-09-09 21:59:44 +0000 | |||
1881 | @@ -46,10 +46,10 @@ | |||
1882 | 46 | 46 | ||
1883 | 47 | def setUp(self): | 47 | def setUp(self): |
1884 | 48 | self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager') | 48 | self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager') |
1885 | 49 | self.registry_patcher = patch('openlp.plugins.bibles.lib.db.Registry') | ||
1886 | 50 | self.addCleanup(self.manager_patcher.stop) | 49 | self.addCleanup(self.manager_patcher.stop) |
1887 | 50 | self.manager_patcher.start() | ||
1888 | 51 | self.registry_patcher = patch('openlp.plugins.bibles.lib.bibleimport.Registry') | ||
1889 | 51 | self.addCleanup(self.registry_patcher.stop) | 52 | self.addCleanup(self.registry_patcher.stop) |
1890 | 52 | self.manager_patcher.start() | ||
1891 | 53 | self.registry_patcher.start() | 53 | self.registry_patcher.start() |
1892 | 54 | 54 | ||
1893 | 55 | def test_create_importer(self): | 55 | def test_create_importer(self): |
1894 | @@ -194,9 +194,9 @@ | |||
1895 | 194 | # WHEN: Calling process_books | 194 | # WHEN: Calling process_books |
1896 | 195 | result = importer.process_books(['Book 1']) | 195 | result = importer.process_books(['Book 1']) |
1897 | 196 | 196 | ||
1899 | 197 | # THEN: increment_progress_bar should not be called and the return value should be None | 197 | # THEN: increment_progress_bar should not be called and the return value should be an empty dictionary |
1900 | 198 | self.assertFalse(importer.wizard.increment_progress_bar.called) | 198 | self.assertFalse(importer.wizard.increment_progress_bar.called) |
1902 | 199 | self.assertIsNone(result) | 199 | self.assertEqual(result, {}) |
1903 | 200 | 200 | ||
1904 | 201 | def process_books_test(self): | 201 | def process_books_test(self): |
1905 | 202 | """ | 202 | """ |
1906 | @@ -207,7 +207,6 @@ | |||
1907 | 207 | with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'),\ | 207 | with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'),\ |
1908 | 208 | patch('openlp.plugins.bibles.lib.importers.csvbible.translate'): | 208 | patch('openlp.plugins.bibles.lib.importers.csvbible.translate'): |
1909 | 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') |
1910 | 210 | type(importer).application = PropertyMock() | ||
1911 | 211 | importer.find_and_create_book = MagicMock() | 210 | importer.find_and_create_book = MagicMock() |
1912 | 212 | importer.language_id = 10 | 211 | importer.language_id = 10 |
1913 | 213 | importer.stop_import_flag = False | 212 | importer.stop_import_flag = False |
1914 | @@ -222,7 +221,6 @@ | |||
1915 | 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. |
1916 | 223 | self.assertEqual(importer.find_and_create_book.mock_calls, | 222 | self.assertEqual(importer.find_and_create_book.mock_calls, |
1917 | 224 | [call('1. Mosebog', 2, 10), call('2. Mosebog', 2, 10)]) | 223 | [call('1. Mosebog', 2, 10), call('2. Mosebog', 2, 10)]) |
1918 | 225 | importer.application.process_events.assert_called_once_with() | ||
1919 | 226 | self.assertDictEqual(result, {1: '1. Mosebog', 2: '2. Mosebog'}) | 224 | self.assertDictEqual(result, {1: '1. Mosebog', 2: '2. Mosebog'}) |
1920 | 227 | 225 | ||
1921 | 228 | def process_verses_stopped_import_test(self): | 226 | def process_verses_stopped_import_test(self): |
1922 | @@ -233,19 +231,16 @@ | |||
1923 | 233 | mocked_manager = MagicMock() | 231 | mocked_manager = MagicMock() |
1924 | 234 | with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'): | 232 | with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'): |
1925 | 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') |
1926 | 236 | type(importer).application = PropertyMock() | ||
1927 | 237 | importer.get_book_name = MagicMock() | 234 | importer.get_book_name = MagicMock() |
1928 | 238 | importer.session = MagicMock() | 235 | importer.session = MagicMock() |
1929 | 239 | importer.stop_import_flag = True | 236 | importer.stop_import_flag = True |
1930 | 240 | importer.wizard = MagicMock() | 237 | importer.wizard = MagicMock() |
1931 | 241 | 238 | ||
1932 | 242 | # WHEN: Calling process_verses | 239 | # WHEN: Calling process_verses |
1934 | 243 | result = importer.process_verses([], []) | 240 | result = importer.process_verses(['Dummy Verse'], []) |
1935 | 244 | 241 | ||
1936 | 245 | # THEN: get_book_name should not be called and the return value should be None | 242 | # THEN: get_book_name should not be called and the return value should be None |
1937 | 246 | self.assertFalse(importer.get_book_name.called) | 243 | self.assertFalse(importer.get_book_name.called) |
1938 | 247 | importer.wizard.increment_progress_bar.assert_called_once_with('Importing verses... done.') | ||
1939 | 248 | importer.application.process_events.assert_called_once_with() | ||
1940 | 249 | self.assertIsNone(result) | 244 | self.assertIsNone(result) |
1941 | 250 | 245 | ||
1942 | 251 | def process_verses_successful_test(self): | 246 | def process_verses_successful_test(self): |
1943 | @@ -257,7 +252,6 @@ | |||
1944 | 257 | with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'),\ | 252 | with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'),\ |
1945 | 258 | patch('openlp.plugins.bibles.lib.importers.csvbible.translate'): | 253 | patch('openlp.plugins.bibles.lib.importers.csvbible.translate'): |
1946 | 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') |
1947 | 260 | type(importer).application = PropertyMock() | ||
1948 | 261 | importer.create_verse = MagicMock() | 255 | importer.create_verse = MagicMock() |
1949 | 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')) |
1950 | 263 | importer.get_book_name = MagicMock(return_value='1. Mosebog') | 257 | importer.get_book_name = MagicMock(return_value='1. Mosebog') |
1951 | @@ -280,7 +274,6 @@ | |||
1952 | 280 | [call('1', 1, 1, 'I Begyndelsen skabte Gud Himmelen og Jorden.'), | 274 | [call('1', 1, 1, 'I Begyndelsen skabte Gud Himmelen og Jorden.'), |
1953 | 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. ' |
1954 | 282 | 'Men Guds Ånd svævede over Vandene.')]) | 276 | 'Men Guds Ånd svævede over Vandene.')]) |
1955 | 283 | importer.application.process_events.assert_called_once_with() | ||
1956 | 284 | 277 | ||
1957 | 285 | def do_import_invalid_language_id_test(self): | 278 | def do_import_invalid_language_id_test(self): |
1958 | 286 | """ | 279 | """ |
1959 | @@ -288,73 +281,16 @@ | |||
1960 | 288 | """ | 281 | """ |
1961 | 289 | # GIVEN: An instance of CSVBible and a mocked get_language which simulates the user cancelling the language box | 282 | # GIVEN: An instance of CSVBible and a mocked get_language which simulates the user cancelling the language box |
1962 | 290 | mocked_manager = MagicMock() | 283 | mocked_manager = MagicMock() |
1965 | 291 | with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'),\ | 284 | with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'): |
1964 | 292 | patch('openlp.plugins.bibles.lib.importers.csvbible.log') as mocked_log: | ||
1966 | 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') |
1967 | 294 | importer.get_language = MagicMock(return_value=None) | 286 | importer.get_language = MagicMock(return_value=None) |
1968 | 295 | 287 | ||
1969 | 296 | # WHEN: Calling do_import | 288 | # WHEN: Calling do_import |
1970 | 297 | result = importer.do_import('Bible Name') | 289 | result = importer.do_import('Bible Name') |
1971 | 298 | 290 | ||
1974 | 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. |
1973 | 300 | # False should be returned. | ||
1975 | 301 | importer.get_language.assert_called_once_with('Bible Name') | 292 | importer.get_language.assert_called_once_with('Bible Name') |
2032 | 302 | mocked_log.exception.assert_called_once_with('Could not import CSV bible') | 293 | self.assertFalse(result) |
1977 | 303 | self.assertFalse(result) | ||
1978 | 304 | |||
1979 | 305 | def do_import_stop_import_test(self): | ||
1980 | 306 | """ | ||
1981 | 307 | Test do_import when the import is stopped | ||
1982 | 308 | """ | ||
1983 | 309 | # GIVEN: An instance of CSVBible with stop_import set to True | ||
1984 | 310 | mocked_manager = MagicMock() | ||
1985 | 311 | with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'),\ | ||
1986 | 312 | patch('openlp.plugins.bibles.lib.importers.csvbible.log') as mocked_log: | ||
1987 | 313 | importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verse.csv') | ||
1988 | 314 | importer.get_language = MagicMock(return_value=10) | ||
1989 | 315 | importer.parse_csv_file = MagicMock(return_value=['Book 1', 'Book 2', 'Book 3']) | ||
1990 | 316 | importer.process_books = MagicMock() | ||
1991 | 317 | importer.stop_import_flag = True | ||
1992 | 318 | importer.wizard = MagicMock() | ||
1993 | 319 | |||
1994 | 320 | # WHEN: Calling do_import | ||
1995 | 321 | result = importer.do_import('Bible Name') | ||
1996 | 322 | |||
1997 | 323 | # THEN: log.exception should not be called, parse_csv_file should only be called once, | ||
1998 | 324 | # and False should be returned. | ||
1999 | 325 | self.assertFalse(mocked_log.exception.called) | ||
2000 | 326 | importer.parse_csv_file.assert_called_once_with('books.csv', Book) | ||
2001 | 327 | importer.process_books.assert_called_once_with(['Book 1', 'Book 2', 'Book 3']) | ||
2002 | 328 | self.assertFalse(result) | ||
2003 | 329 | |||
2004 | 330 | def do_import_stop_import_2_test(self): | ||
2005 | 331 | """ | ||
2006 | 332 | Test do_import when the import is stopped | ||
2007 | 333 | """ | ||
2008 | 334 | # GIVEN: An instance of CSVBible with stop_import which is True the second time of calling | ||
2009 | 335 | mocked_manager = MagicMock() | ||
2010 | 336 | with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'),\ | ||
2011 | 337 | patch('openlp.plugins.bibles.lib.importers.csvbible.log') as mocked_log: | ||
2012 | 338 | CSVBible.stop_import_flag = PropertyMock(side_effect=[False, True]) | ||
2013 | 339 | importer = CSVBible(mocked_manager, path='.', name='.', booksfile='books.csv', versefile='verses.csv') | ||
2014 | 340 | importer.get_language = MagicMock(return_value=10) | ||
2015 | 341 | importer.parse_csv_file = MagicMock(side_effect=[['Book 1'], ['Verse 1']]) | ||
2016 | 342 | importer.process_books = MagicMock(return_value=['Book 1']) | ||
2017 | 343 | importer.process_verses = MagicMock(return_value=['Verse 1']) | ||
2018 | 344 | importer.wizard = MagicMock() | ||
2019 | 345 | |||
2020 | 346 | # WHEN: Calling do_import | ||
2021 | 347 | result = importer.do_import('Bible Name') | ||
2022 | 348 | |||
2023 | 349 | # THEN: log.exception should not be called, parse_csv_file should be called twice, | ||
2024 | 350 | # and False should be returned. | ||
2025 | 351 | self.assertFalse(mocked_log.exception.called) | ||
2026 | 352 | self.assertEqual(importer.parse_csv_file.mock_calls, [call('books.csv', Book), call('verses.csv', Verse)]) | ||
2027 | 353 | importer.process_verses.assert_called_once_with(['Verse 1'], ['Book 1']) | ||
2028 | 354 | self.assertFalse(result) | ||
2029 | 355 | |||
2030 | 356 | # Cleanup | ||
2031 | 357 | del CSVBible.stop_import_flag | ||
2033 | 358 | 294 | ||
2034 | 359 | def do_import_success_test(self): | 295 | def do_import_success_test(self): |
2035 | 360 | """ | 296 | """ |
2036 | @@ -362,8 +298,7 @@ | |||
2037 | 362 | """ | 298 | """ |
2038 | 363 | # GIVEN: An instance of CSVBible | 299 | # GIVEN: An instance of CSVBible |
2039 | 364 | mocked_manager = MagicMock() | 300 | mocked_manager = MagicMock() |
2042 | 365 | with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'),\ | 301 | with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'): |
2041 | 366 | patch('openlp.plugins.bibles.lib.importers.csvbible.log') as mocked_log: | ||
2043 | 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') |
2044 | 368 | importer.get_language = MagicMock(return_value=10) | 303 | importer.get_language = MagicMock(return_value=10) |
2045 | 369 | importer.parse_csv_file = MagicMock(side_effect=[['Book 1'], ['Verse 1']]) | 304 | importer.parse_csv_file = MagicMock(side_effect=[['Book 1'], ['Verse 1']]) |
2046 | @@ -376,9 +311,8 @@ | |||
2047 | 376 | # WHEN: Calling do_import | 311 | # WHEN: Calling do_import |
2048 | 377 | result = importer.do_import('Bible Name') | 312 | result = importer.do_import('Bible Name') |
2049 | 378 | 313 | ||
2051 | 379 | # THEN: log.exception should not be called, parse_csv_file should be called twice, | 314 | # THEN: parse_csv_file should be called twice, |
2052 | 380 | # and True should be returned. | 315 | # and True should be returned. |
2053 | 381 | self.assertFalse(mocked_log.exception.called) | ||
2054 | 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)]) |
2055 | 383 | importer.process_books.assert_called_once_with(['Book 1']) | 317 | importer.process_books.assert_called_once_with(['Book 1']) |
2056 | 384 | importer.process_verses.assert_called_once_with(['Verse 1'], ['Book 1']) | 318 | importer.process_verses.assert_called_once_with(['Verse 1'], ['Book 1']) |
2057 | @@ -413,6 +347,6 @@ | |||
2058 | 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. |
2059 | 414 | self.assertTrue(importer.create_verse.called) | 348 | self.assertTrue(importer.create_verse.called) |
2060 | 415 | for verse_tag, verse_text in test_data['verses']: | 349 | for verse_tag, verse_text in test_data['verses']: |
2062 | 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) |
2063 | 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) |
2064 | 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) |
2065 | 419 | 353 | ||
2066 | === modified file 'tests/functional/openlp_plugins/bibles/test_db.py' | |||
2067 | --- tests/functional/openlp_plugins/bibles/test_db.py 2016-08-03 20:10:41 +0000 | |||
2068 | +++ tests/functional/openlp_plugins/bibles/test_db.py 2016-09-09 21:59:44 +0000 | |||
2069 | @@ -25,63 +25,9 @@ | |||
2070 | 25 | 25 | ||
2071 | 26 | from unittest import TestCase | 26 | from unittest import TestCase |
2072 | 27 | 27 | ||
2073 | 28 | from openlp.plugins.bibles.lib.db import BibleDB | ||
2074 | 29 | from tests.functional import MagicMock, patch | ||
2075 | 30 | |||
2076 | 31 | 28 | ||
2077 | 32 | class TestBibleDB(TestCase): | 29 | class TestBibleDB(TestCase): |
2078 | 33 | """ | 30 | """ |
2079 | 34 | Test the functions in the BibleDB class. | 31 | Test the functions in the BibleDB class. |
2080 | 35 | """ | 32 | """ |
2133 | 36 | 33 | pass | |
2082 | 37 | def test_get_language_canceled(self): | ||
2083 | 38 | """ | ||
2084 | 39 | Test the BibleDB.get_language method when the user rejects the dialog box | ||
2085 | 40 | """ | ||
2086 | 41 | # GIVEN: A mocked LanguageForm with an exec method which returns QtDialog.Rejected and an instance of BibleDB | ||
2087 | 42 | with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'),\ | ||
2088 | 43 | patch('openlp.plugins.bibles.forms.LanguageForm') as mocked_language_form: | ||
2089 | 44 | |||
2090 | 45 | # The integer value of QtDialog.Rejected is 0. Using the enumeration causes a seg fault for some reason | ||
2091 | 46 | mocked_language_form_instance = MagicMock(**{'exec.return_value': 0}) | ||
2092 | 47 | mocked_language_form.return_value = mocked_language_form_instance | ||
2093 | 48 | mocked_parent = MagicMock() | ||
2094 | 49 | instance = BibleDB(mocked_parent) | ||
2095 | 50 | mocked_wizard = MagicMock() | ||
2096 | 51 | instance.wizard = mocked_wizard | ||
2097 | 52 | |||
2098 | 53 | # WHEN: Calling get_language() | ||
2099 | 54 | result = instance.get_language() | ||
2100 | 55 | |||
2101 | 56 | # THEN: get_language() should return False | ||
2102 | 57 | mocked_language_form.assert_called_once_with(mocked_wizard) | ||
2103 | 58 | mocked_language_form_instance.exec.assert_called_once_with(None) | ||
2104 | 59 | self.assertFalse(result, 'get_language() should return False if the user rejects the dialog box') | ||
2105 | 60 | |||
2106 | 61 | def test_get_language_accepted(self): | ||
2107 | 62 | """ | ||
2108 | 63 | Test the BibleDB.get_language method when the user accepts the dialog box | ||
2109 | 64 | """ | ||
2110 | 65 | # GIVEN: A mocked LanguageForm with an exec method which returns QtDialog.Accepted an instance of BibleDB and | ||
2111 | 66 | # a combobox with the selected item data as 10 | ||
2112 | 67 | with patch('openlp.plugins.bibles.lib.db.BibleDB._setup'), \ | ||
2113 | 68 | patch('openlp.plugins.bibles.lib.db.BibleDB.save_meta'), \ | ||
2114 | 69 | patch('openlp.plugins.bibles.forms.LanguageForm') as mocked_language_form: | ||
2115 | 70 | |||
2116 | 71 | # The integer value of QtDialog.Accepted is 1. Using the enumeration causes a seg fault for some reason | ||
2117 | 72 | mocked_language_form_instance = MagicMock(**{'exec.return_value': 1, | ||
2118 | 73 | 'language_combo_box.itemData.return_value': 10}) | ||
2119 | 74 | mocked_language_form.return_value = mocked_language_form_instance | ||
2120 | 75 | mocked_parent = MagicMock() | ||
2121 | 76 | instance = BibleDB(mocked_parent) | ||
2122 | 77 | mocked_wizard = MagicMock() | ||
2123 | 78 | instance.wizard = mocked_wizard | ||
2124 | 79 | |||
2125 | 80 | # WHEN: Calling get_language() | ||
2126 | 81 | result = instance.get_language('Bible Name') | ||
2127 | 82 | |||
2128 | 83 | # THEN: get_language() should return the id of the selected language in the combo box | ||
2129 | 84 | mocked_language_form.assert_called_once_with(mocked_wizard) | ||
2130 | 85 | mocked_language_form_instance.exec.assert_called_once_with('Bible Name') | ||
2131 | 86 | self.assertEqual(result, 10, 'get_language() should return the id of the language the user has chosen when ' | ||
2132 | 87 | 'they accept the dialog box') | ||
2134 | 88 | 34 | ||
2135 | === modified file 'tests/functional/openlp_plugins/bibles/test_opensongimport.py' | |||
2136 | --- tests/functional/openlp_plugins/bibles/test_opensongimport.py 2016-08-09 20:45:25 +0000 | |||
2137 | +++ tests/functional/openlp_plugins/bibles/test_opensongimport.py 2016-09-09 21:59:44 +0000 | |||
2138 | @@ -23,32 +23,38 @@ | |||
2139 | 23 | This module contains tests for the OpenSong Bible importer. | 23 | This module contains tests for the OpenSong Bible importer. |
2140 | 24 | """ | 24 | """ |
2141 | 25 | 25 | ||
2142 | 26 | import json | ||
2143 | 26 | import os | 27 | import os |
2144 | 27 | import json | ||
2145 | 28 | from unittest import TestCase | 28 | from unittest import TestCase |
2146 | 29 | 29 | ||
2150 | 30 | from tests.functional import MagicMock, patch | 30 | from lxml import objectify |
2151 | 31 | from openlp.plugins.bibles.lib.importers.opensong import OpenSongBible | 31 | |
2152 | 32 | from openlp.plugins.bibles.lib.db import BibleDB | 32 | from tests.functional import MagicMock, patch, call |
2153 | 33 | from tests.helpers.testmixin import TestMixin | ||
2154 | 34 | from openlp.core.common import Registry | ||
2155 | 35 | from openlp.plugins.bibles.lib.importers.opensong import OpenSongBible, get_text, parse_chapter_number | ||
2156 | 36 | from openlp.plugins.bibles.lib.bibleimport import BibleImport | ||
2157 | 33 | 37 | ||
2158 | 34 | TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), | 38 | TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), |
2159 | 35 | '..', '..', '..', 'resources', 'bibles')) | 39 | '..', '..', '..', 'resources', 'bibles')) |
2160 | 36 | 40 | ||
2161 | 37 | 41 | ||
2163 | 38 | class TestOpenSongImport(TestCase): | 42 | class TestOpenSongImport(TestCase, TestMixin): |
2164 | 39 | """ | 43 | """ |
2165 | 40 | Test the functions in the :mod:`opensongimport` module. | 44 | Test the functions in the :mod:`opensongimport` module. |
2166 | 41 | """ | 45 | """ |
2167 | 42 | 46 | ||
2168 | 43 | def setUp(self): | 47 | def setUp(self): |
2171 | 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') |
2172 | 45 | self.registry_patcher.start() | 49 | self.addCleanup(self.find_and_create_book_patch.stop) |
2173 | 50 | self.mocked_find_and_create_book = self.find_and_create_book_patch.start() | ||
2174 | 46 | self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager') | 51 | self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager') |
2175 | 52 | self.addCleanup(self.manager_patcher.stop) | ||
2176 | 47 | self.manager_patcher.start() | 53 | self.manager_patcher.start() |
2181 | 48 | 54 | self.setup_application() | |
2182 | 49 | def tearDown(self): | 55 | self.app.process_events = MagicMock() |
2183 | 50 | self.registry_patcher.stop() | 56 | Registry.create() |
2184 | 51 | self.manager_patcher.stop() | 57 | Registry().register('application', self.app) |
2185 | 52 | 58 | ||
2186 | 53 | def test_create_importer(self): | 59 | def test_create_importer(self): |
2187 | 54 | """ | 60 | """ |
2188 | @@ -61,7 +67,332 @@ | |||
2189 | 61 | importer = OpenSongBible(mocked_manager, path='.', name='.', filename='') | 67 | importer = OpenSongBible(mocked_manager, path='.', name='.', filename='') |
2190 | 62 | 68 | ||
2191 | 63 | # THEN: The importer should be an instance of BibleDB | 69 | # THEN: The importer should be an instance of BibleDB |
2193 | 64 | self.assertIsInstance(importer, BibleDB) | 70 | self.assertIsInstance(importer, BibleImport) |
2194 | 71 | |||
2195 | 72 | def get_text_no_text_test(self): | ||
2196 | 73 | """ | ||
2197 | 74 | Test that get_text handles elements containing text in a combination of text and tail attributes | ||
2198 | 75 | """ | ||
2199 | 76 | # GIVEN: Some test data which contains an empty element and an instance of OpenSongBible | ||
2200 | 77 | test_data = objectify.fromstring('<element></element>') | ||
2201 | 78 | |||
2202 | 79 | # WHEN: Calling get_text | ||
2203 | 80 | result = get_text(test_data) | ||
2204 | 81 | |||
2205 | 82 | # THEN: A blank string should be returned | ||
2206 | 83 | self.assertEqual(result, '') | ||
2207 | 84 | |||
2208 | 85 | def get_text_text_test(self): | ||
2209 | 86 | """ | ||
2210 | 87 | Test that get_text handles elements containing text in a combination of text and tail attributes | ||
2211 | 88 | """ | ||
2212 | 89 | # GIVEN: Some test data which contains all possible permutation of text and tail text possible and an instance | ||
2213 | 90 | # of OpenSongBible | ||
2214 | 91 | test_data = objectify.fromstring('<element>Element text ' | ||
2215 | 92 | '<sub_text_tail>sub_text_tail text </sub_text_tail>sub_text_tail tail ' | ||
2216 | 93 | '<sub_text>sub_text text </sub_text>' | ||
2217 | 94 | '<sub_tail></sub_tail>sub_tail tail</element>') | ||
2218 | 95 | |||
2219 | 96 | # WHEN: Calling get_text | ||
2220 | 97 | result = get_text(test_data) | ||
2221 | 98 | |||
2222 | 99 | # THEN: The text returned should be as expected | ||
2223 | 100 | self.assertEqual(result, 'Element text sub_text_tail text sub_text_tail tail sub_text text sub_tail tail') | ||
2224 | 101 | |||
2225 | 102 | def parse_chapter_number_test(self): | ||
2226 | 103 | """ | ||
2227 | 104 | Test parse_chapter_number when supplied with chapter number and an instance of OpenSongBible | ||
2228 | 105 | """ | ||
2229 | 106 | # GIVEN: The number 10 represented as a string | ||
2230 | 107 | # WHEN: Calling parse_chapter_nnumber | ||
2231 | 108 | result = parse_chapter_number('10', 0) | ||
2232 | 109 | |||
2233 | 110 | # THEN: The 10 should be returned as an Int | ||
2234 | 111 | self.assertEqual(result, 10) | ||
2235 | 112 | |||
2236 | 113 | def parse_chapter_number_empty_attribute_test(self): | ||
2237 | 114 | """ | ||
2238 | 115 | Testparse_chapter_number when the chapter number is an empty string. (Bug #1074727) | ||
2239 | 116 | """ | ||
2240 | 117 | # GIVEN: An empty string, and the previous chapter number set as 12 and an instance of OpenSongBible | ||
2241 | 118 | # WHEN: Calling parse_chapter_number | ||
2242 | 119 | result = parse_chapter_number('', 12) | ||
2243 | 120 | |||
2244 | 121 | # THEN: parse_chapter_number should increment the previous verse number | ||
2245 | 122 | self.assertEqual(result, 13) | ||
2246 | 123 | |||
2247 | 124 | def parse_verse_number_valid_verse_no_test(self): | ||
2248 | 125 | """ | ||
2249 | 126 | Test parse_verse_number when supplied with a valid verse number | ||
2250 | 127 | """ | ||
2251 | 128 | # GIVEN: An instance of OpenSongBible, the number 15 represented as a string and an instance of OpenSongBible | ||
2252 | 129 | importer = OpenSongBible(MagicMock(), path='.', name='.', filename='') | ||
2253 | 130 | |||
2254 | 131 | # WHEN: Calling parse_verse_number | ||
2255 | 132 | result = importer.parse_verse_number('15', 0) | ||
2256 | 133 | |||
2257 | 134 | # THEN: parse_verse_number should return the verse number | ||
2258 | 135 | self.assertEqual(result, 15) | ||
2259 | 136 | |||
2260 | 137 | def parse_verse_number_verse_range_test(self): | ||
2261 | 138 | """ | ||
2262 | 139 | Test parse_verse_number when supplied with a verse range | ||
2263 | 140 | """ | ||
2264 | 141 | # GIVEN: An instance of OpenSongBible, and the range 24-26 represented as a string | ||
2265 | 142 | importer = OpenSongBible(MagicMock(), path='.', name='.', filename='') | ||
2266 | 143 | |||
2267 | 144 | # WHEN: Calling parse_verse_number | ||
2268 | 145 | result = importer.parse_verse_number('24-26', 0) | ||
2269 | 146 | |||
2270 | 147 | # THEN: parse_verse_number should return the first verse number in the range | ||
2271 | 148 | self.assertEqual(result, 24) | ||
2272 | 149 | |||
2273 | 150 | def parse_verse_number_invalid_verse_no_test(self): | ||
2274 | 151 | """ | ||
2275 | 152 | Test parse_verse_number when supplied with a invalid verse number | ||
2276 | 153 | """ | ||
2277 | 154 | # GIVEN: An instance of OpenSongBible, a non numeric string represented as a string | ||
2278 | 155 | importer = OpenSongBible(MagicMock(), path='.', name='.', filename='') | ||
2279 | 156 | |||
2280 | 157 | # WHEN: Calling parse_verse_number | ||
2281 | 158 | result = importer.parse_verse_number('invalid', 41) | ||
2282 | 159 | |||
2283 | 160 | # THEN: parse_verse_number should increment the previous verse number | ||
2284 | 161 | self.assertEqual(result, 42) | ||
2285 | 162 | |||
2286 | 163 | def parse_verse_number_empty_attribute_test(self): | ||
2287 | 164 | """ | ||
2288 | 165 | Test parse_verse_number when the verse number is an empty string. (Bug #1074727) | ||
2289 | 166 | """ | ||
2290 | 167 | # GIVEN: An instance of OpenSongBible, an empty string, and the previous verse number set as 14 | ||
2291 | 168 | importer = OpenSongBible(MagicMock(), path='.', name='.', filename='') | ||
2292 | 169 | # WHEN: Calling parse_verse_number | ||
2293 | 170 | result = importer.parse_verse_number('', 14) | ||
2294 | 171 | |||
2295 | 172 | # THEN: parse_verse_number should increment the previous verse number | ||
2296 | 173 | self.assertEqual(result, 15) | ||
2297 | 174 | |||
2298 | 175 | def parse_verse_number_invalid_type_test(self): | ||
2299 | 176 | """ | ||
2300 | 177 | Test parse_verse_number when the verse number is an invalid type) | ||
2301 | 178 | """ | ||
2302 | 179 | with patch.object(OpenSongBible, 'log_warning')as mocked_log_warning: | ||
2303 | 180 | # GIVEN: An instanceofOpenSongBible, a Tuple, and the previous verse number set as 12 | ||
2304 | 181 | importer = OpenSongBible(MagicMock(), path='.', name='.', filename='') | ||
2305 | 182 | |||
2306 | 183 | # WHEN: Calling parse_verse_number | ||
2307 | 184 | result = importer.parse_verse_number((1, 2, 3), 12) | ||
2308 | 185 | |||
2309 | 186 | # THEN: parse_verse_number should log the verse number it was called with increment the previous verse | ||
2310 | 187 | # number | ||
2311 | 188 | mocked_log_warning.assert_called_once_with('Illegal verse number: (1, 2, 3)') | ||
2312 | 189 | self.assertEqual(result, 13) | ||
2313 | 190 | |||
2314 | 191 | def process_books_stop_import_test(self): | ||
2315 | 192 | """ | ||
2316 | 193 | Test process_books when stop_import is set to True | ||
2317 | 194 | """ | ||
2318 | 195 | # GIVEN: An instance of OpenSongBible | ||
2319 | 196 | importer = OpenSongBible(MagicMock(), path='.', name='.', filename='') | ||
2320 | 197 | |||
2321 | 198 | # WHEN: stop_import_flag is set to True | ||
2322 | 199 | importer.stop_import_flag = True | ||
2323 | 200 | importer.process_books(['Book']) | ||
2324 | 201 | |||
2325 | 202 | # THEN: find_and_create_book should not have been called | ||
2326 | 203 | self.assertFalse(self.mocked_find_and_create_book.called) | ||
2327 | 204 | |||
2328 | 205 | def process_books_completes_test(self): | ||
2329 | 206 | """ | ||
2330 | 207 | Test process_books when it processes all books | ||
2331 | 208 | """ | ||
2332 | 209 | # GIVEN: An instance of OpenSongBible Importer and two mocked books | ||
2333 | 210 | self.mocked_find_and_create_book.side_effect = ['db_book1', 'db_book2'] | ||
2334 | 211 | with patch.object(OpenSongBible, 'process_chapters') as mocked_process_chapters: | ||
2335 | 212 | importer = OpenSongBible(MagicMock(), path='.', name='.', filename='') | ||
2336 | 213 | |||
2337 | 214 | book1 = MagicMock() | ||
2338 | 215 | book1.attrib = {'n': 'Name1'} | ||
2339 | 216 | book1.c = 'Chapter1' | ||
2340 | 217 | book2 = MagicMock() | ||
2341 | 218 | book2.attrib = {'n': 'Name2'} | ||
2342 | 219 | book2.c = 'Chapter2' | ||
2343 | 220 | importer.language_id = 10 | ||
2344 | 221 | importer.session = MagicMock() | ||
2345 | 222 | importer.stop_import_flag = False | ||
2346 | 223 | |||
2347 | 224 | # WHEN: Calling process_books with the two books | ||
2348 | 225 | importer.process_books([book1, book2]) | ||
2349 | 226 | |||
2350 | 227 | # THEN: find_and_create_book and process_books should be called with the details from the mocked books | ||
2351 | 228 | self.assertEqual(self.mocked_find_and_create_book.call_args_list, | ||
2352 | 229 | [call('Name1', 2, 10), call('Name2', 2, 10)]) | ||
2353 | 230 | self.assertEqual(mocked_process_chapters.call_args_list, | ||
2354 | 231 | [call('db_book1', 'Chapter1'), call('db_book2', 'Chapter2')]) | ||
2355 | 232 | self.assertEqual(importer.session.commit.call_count, 2) | ||
2356 | 233 | |||
2357 | 234 | def process_chapters_stop_import_test(self): | ||
2358 | 235 | """ | ||
2359 | 236 | Test process_chapters when stop_import is set to True | ||
2360 | 237 | """ | ||
2361 | 238 | # GIVEN: An isntance of OpenSongBible | ||
2362 | 239 | importer = OpenSongBible(MagicMock(), path='.', name='.', filename='') | ||
2363 | 240 | importer.parse_chapter_number = MagicMock() | ||
2364 | 241 | |||
2365 | 242 | # WHEN: stop_import_flag is set to True | ||
2366 | 243 | importer.stop_import_flag = True | ||
2367 | 244 | importer.process_chapters('Book', ['Chapter1']) | ||
2368 | 245 | |||
2369 | 246 | # THEN: importer.parse_chapter_number not have been called | ||
2370 | 247 | self.assertFalse(importer.parse_chapter_number.called) | ||
2371 | 248 | |||
2372 | 249 | @patch('openlp.plugins.bibles.lib.importers.opensong.parse_chapter_number', **{'side_effect': [1, 2]}) | ||
2373 | 250 | def process_chapters_completes_test(self, mocked_parse_chapter_number): | ||
2374 | 251 | """ | ||
2375 | 252 | Test process_chapters when it completes | ||
2376 | 253 | """ | ||
2377 | 254 | # GIVEN: An instance of OpenSongBible | ||
2378 | 255 | importer = OpenSongBible(MagicMock(), path='.', name='.', filename='') | ||
2379 | 256 | importer.wizard = MagicMock() | ||
2380 | 257 | |||
2381 | 258 | # WHEN: called with some valid data | ||
2382 | 259 | book = MagicMock() | ||
2383 | 260 | book.name = "Book" | ||
2384 | 261 | chapter1 = MagicMock() | ||
2385 | 262 | chapter1.attrib = {'n': '1'} | ||
2386 | 263 | chapter1.c = 'Chapter1' | ||
2387 | 264 | chapter1.v = ['Chapter1 Verses'] | ||
2388 | 265 | chapter2 = MagicMock() | ||
2389 | 266 | chapter2.attrib = {'n': '2'} | ||
2390 | 267 | chapter2.c = 'Chapter2' | ||
2391 | 268 | chapter2.v = ['Chapter2 Verses'] | ||
2392 | 269 | |||
2393 | 270 | importer.process_verses = MagicMock() | ||
2394 | 271 | importer.stop_import_flag = False | ||
2395 | 272 | importer.process_chapters(book, [chapter1, chapter2]) | ||
2396 | 273 | |||
2397 | 274 | # THEN: parse_chapter_number, process_verses and increment_process_bar should have been called | ||
2398 | 275 | self.assertEqual(mocked_parse_chapter_number.call_args_list, [call('1', 0), call('2', 1)]) | ||
2399 | 276 | self.assertEqual( | ||
2400 | 277 | importer.process_verses.call_args_list, | ||
2401 | 278 | [call(book, 1, ['Chapter1 Verses']), call(book, 2, ['Chapter2 Verses'])]) | ||
2402 | 279 | self.assertEqual(importer.wizard.increment_progress_bar.call_args_list, | ||
2403 | 280 | [call('Importing Book 1...'), call('Importing Book 2...')]) | ||
2404 | 281 | |||
2405 | 282 | def process_verses_stop_import_test(self): | ||
2406 | 283 | """ | ||
2407 | 284 | Test process_verses when stop_import is set to True | ||
2408 | 285 | """ | ||
2409 | 286 | # GIVEN: An isntance of OpenSongBible | ||
2410 | 287 | importer = OpenSongBible(MagicMock(), path='.', name='.', filename='') | ||
2411 | 288 | importer.parse_verse_number = MagicMock() | ||
2412 | 289 | |||
2413 | 290 | # WHEN: stop_import_flag is set to True | ||
2414 | 291 | importer.stop_import_flag = True | ||
2415 | 292 | importer.process_verses('Book', 1, 'Verses') | ||
2416 | 293 | |||
2417 | 294 | # THEN: importer.parse_verse_number not have been called | ||
2418 | 295 | self.assertFalse(importer.parse_verse_number.called) | ||
2419 | 296 | |||
2420 | 297 | def process_verses_completes_test(self): | ||
2421 | 298 | """ | ||
2422 | 299 | Test process_verses when it completes | ||
2423 | 300 | """ | ||
2424 | 301 | with patch('openlp.plugins.bibles.lib.importers.opensong.get_text', | ||
2425 | 302 | **{'side_effect': ['Verse1 Text', 'Verse2 Text']}) as mocked_get_text, \ | ||
2426 | 303 | patch.object(OpenSongBible, 'parse_verse_number', | ||
2427 | 304 | **{'side_effect': [1, 2]}) as mocked_parse_verse_number: | ||
2428 | 305 | # GIVEN: An instance of OpenSongBible | ||
2429 | 306 | importer = OpenSongBible(MagicMock(), path='.', name='.', filename='') | ||
2430 | 307 | importer.wizard = MagicMock() | ||
2431 | 308 | |||
2432 | 309 | # WHEN: called with some valid data | ||
2433 | 310 | book = MagicMock() | ||
2434 | 311 | book.id = 1 | ||
2435 | 312 | verse1 = MagicMock() | ||
2436 | 313 | verse1.attrib = {'n': '1'} | ||
2437 | 314 | verse1.c = 'Chapter1' | ||
2438 | 315 | verse1.v = ['Chapter1 Verses'] | ||
2439 | 316 | verse2 = MagicMock() | ||
2440 | 317 | verse2.attrib = {'n': '2'} | ||
2441 | 318 | verse2.c = 'Chapter2' | ||
2442 | 319 | verse2.v = ['Chapter2 Verses'] | ||
2443 | 320 | |||
2444 | 321 | importer.create_verse = MagicMock() | ||
2445 | 322 | importer.stop_import_flag = False | ||
2446 | 323 | importer.process_verses(book, 1, [verse1, verse2]) | ||
2447 | 324 | |||
2448 | 325 | # THEN: parse_chapter_number, process_verses and increment_process_bar should have been called | ||
2449 | 326 | self.assertEqual(mocked_parse_verse_number.call_args_list, [call('1', 0), call('2', 1)]) | ||
2450 | 327 | self.assertEqual(mocked_get_text.call_args_list, [call(verse1), call(verse2)]) | ||
2451 | 328 | self.assertEqual( | ||
2452 | 329 | importer.create_verse.call_args_list, | ||
2453 | 330 | [call(1, 1, 1, 'Verse1 Text'), call(1, 1, 2, 'Verse2 Text')]) | ||
2454 | 331 | |||
2455 | 332 | def do_import_parse_xml_fails_test(self): | ||
2456 | 333 | """ | ||
2457 | 334 | Test do_import when parse_xml fails (returns None) | ||
2458 | 335 | """ | ||
2459 | 336 | # GIVEN: An instance of OpenSongBible and a mocked parse_xml which returns False | ||
2460 | 337 | with patch.object(OpenSongBible, 'log_debug'), \ | ||
2461 | 338 | patch.object(OpenSongBible, 'validate_xml_file'), \ | ||
2462 | 339 | patch.object(OpenSongBible, 'parse_xml', return_value=None), \ | ||
2463 | 340 | patch.object(OpenSongBible, 'get_language_id') as mocked_language_id: | ||
2464 | 341 | importer = OpenSongBible(MagicMock(), path='.', name='.', filename='') | ||
2465 | 342 | |||
2466 | 343 | # WHEN: Calling do_import | ||
2467 | 344 | result = importer.do_import() | ||
2468 | 345 | |||
2469 | 346 | # THEN: do_import should return False and get_language_id should have not been called | ||
2470 | 347 | self.assertFalse(result) | ||
2471 | 348 | self.assertFalse(mocked_language_id.called) | ||
2472 | 349 | |||
2473 | 350 | def do_import_no_language_test(self): | ||
2474 | 351 | """ | ||
2475 | 352 | Test do_import when the user cancels the language selection dialog | ||
2476 | 353 | """ | ||
2477 | 354 | # GIVEN: An instance of OpenSongBible and a mocked get_language which returns False | ||
2478 | 355 | with patch.object(OpenSongBible, 'log_debug'), \ | ||
2479 | 356 | patch.object(OpenSongBible, 'validate_xml_file'), \ | ||
2480 | 357 | patch.object(OpenSongBible, 'parse_xml'), \ | ||
2481 | 358 | patch.object(OpenSongBible, 'get_language_id', return_value=False), \ | ||
2482 | 359 | patch.object(OpenSongBible, 'process_books') as mocked_process_books: | ||
2483 | 360 | importer = OpenSongBible(MagicMock(), path='.', name='.', filename='') | ||
2484 | 361 | |||
2485 | 362 | # WHEN: Calling do_import | ||
2486 | 363 | result = importer.do_import() | ||
2487 | 364 | |||
2488 | 365 | # THEN: do_import should return False and process_books should have not been called | ||
2489 | 366 | self.assertFalse(result) | ||
2490 | 367 | self.assertFalse(mocked_process_books.called) | ||
2491 | 368 | |||
2492 | 369 | def do_import_completes_test(self): | ||
2493 | 370 | """ | ||
2494 | 371 | Test do_import when it completes successfully | ||
2495 | 372 | """ | ||
2496 | 373 | # GIVEN: An instance of OpenSongBible | ||
2497 | 374 | with patch.object(OpenSongBible, 'log_debug'), \ | ||
2498 | 375 | patch.object(OpenSongBible, 'validate_xml_file'), \ | ||
2499 | 376 | patch.object(OpenSongBible, 'parse_xml'), \ | ||
2500 | 377 | patch.object(OpenSongBible, 'get_language_id', return_value=10), \ | ||
2501 | 378 | patch.object(OpenSongBible, 'process_books'): | ||
2502 | 379 | importer = OpenSongBible(MagicMock(), path='.', name='.', filename='') | ||
2503 | 380 | |||
2504 | 381 | # WHEN: Calling do_import | ||
2505 | 382 | result = importer.do_import() | ||
2506 | 383 | |||
2507 | 384 | # THEN: do_import should return True | ||
2508 | 385 | self.assertTrue(result) | ||
2509 | 386 | |||
2510 | 387 | |||
2511 | 388 | class TestOpenSongImportFileImports(TestCase, TestMixin): | ||
2512 | 389 | """ | ||
2513 | 390 | Test the functions in the :mod:`opensongimport` module. | ||
2514 | 391 | """ | ||
2515 | 392 | def setUp(self): | ||
2516 | 393 | self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager') | ||
2517 | 394 | self.addCleanup(self.manager_patcher.stop) | ||
2518 | 395 | self.manager_patcher.start() | ||
2519 | 65 | 396 | ||
2520 | 66 | def test_file_import(self): | 397 | def test_file_import(self): |
2521 | 67 | """ | 398 | """ |
2522 | @@ -92,22 +423,3 @@ | |||
2523 | 92 | self.assertTrue(importer.create_verse.called) | 423 | self.assertTrue(importer.create_verse.called) |
2524 | 93 | for verse_tag, verse_text in test_data['verses']: | 424 | for verse_tag, verse_text in test_data['verses']: |
2525 | 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) |
2526 | 95 | |||
2527 | 96 | def test_zefania_import_error(self): | ||
2528 | 97 | """ | ||
2529 | 98 | Test that we give an error message if trying to import a zefania bible | ||
2530 | 99 | """ | ||
2531 | 100 | # GIVEN: A mocked out "manager" and mocked out critical_error_message_box and an import | ||
2532 | 101 | with patch('openlp.plugins.bibles.lib.importers.opensong.critical_error_message_box') as \ | ||
2533 | 102 | mocked_critical_error_message_box: | ||
2534 | 103 | mocked_manager = MagicMock() | ||
2535 | 104 | importer = OpenSongBible(mocked_manager, path='.', name='.', filename='') | ||
2536 | 105 | |||
2537 | 106 | # WHEN: An trying to import a zefania bible | ||
2538 | 107 | importer.filename = os.path.join(TEST_PATH, 'zefania-dk1933.xml') | ||
2539 | 108 | importer.do_import() | ||
2540 | 109 | |||
2541 | 110 | # THEN: The importer should have "shown" an error message | ||
2542 | 111 | mocked_critical_error_message_box.assert_called_with(message='Incorrect Bible file type supplied. ' | ||
2543 | 112 | 'This looks like a Zefania XML bible, ' | ||
2544 | 113 | 'please use the Zefania import option.') | ||
2545 | 114 | 426 | ||
2546 | === modified file 'tests/functional/openlp_plugins/bibles/test_osisimport.py' | |||
2547 | --- tests/functional/openlp_plugins/bibles/test_osisimport.py 2016-08-09 20:45:25 +0000 | |||
2548 | +++ tests/functional/openlp_plugins/bibles/test_osisimport.py 2016-09-09 21:59:44 +0000 | |||
2549 | @@ -27,29 +27,35 @@ | |||
2550 | 27 | import json | 27 | import json |
2551 | 28 | from unittest import TestCase | 28 | from unittest import TestCase |
2552 | 29 | 29 | ||
2554 | 30 | from tests.functional import MagicMock, patch | 30 | from tests.functional import MagicMock, call, patch |
2555 | 31 | from openlp.plugins.bibles.lib.bibleimport import BibleImport | ||
2556 | 32 | from openlp.plugins.bibles.lib.db import BibleDB | ||
2557 | 31 | from openlp.plugins.bibles.lib.importers.osis import OSISBible | 33 | from openlp.plugins.bibles.lib.importers.osis import OSISBible |
2558 | 32 | from openlp.plugins.bibles.lib.db import BibleDB | ||
2559 | 33 | 34 | ||
2562 | 34 | TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), | 35 | TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'resources', 'bibles')) |
2561 | 35 | '..', '..', '..', 'resources', 'bibles')) | ||
2563 | 36 | 36 | ||
2564 | 37 | 37 | ||
2565 | 38 | class TestOsisImport(TestCase): | 38 | class TestOsisImport(TestCase): |
2566 | 39 | """ | 39 | """ |
2567 | 40 | Test the functions in the :mod:`osisimport` module. | 40 | Test the functions in the :mod:`osisimport` module. |
2568 | 41 | """ | 41 | """ |
2569 | 42 | |||
2570 | 43 | def setUp(self): | 42 | def setUp(self): |
2572 | 44 | self.registry_patcher = patch('openlp.plugins.bibles.lib.db.Registry') | 43 | self.etree_patcher = patch('openlp.plugins.bibles.lib.importers.osis.etree') |
2573 | 44 | self.addCleanup(self.etree_patcher.stop) | ||
2574 | 45 | self.mocked_etree = self.etree_patcher.start() | ||
2575 | 46 | self.create_verse_patcher = patch('openlp.plugins.bibles.lib.db.BibleDB.create_verse') | ||
2576 | 47 | self.addCleanup(self.create_verse_patcher.stop) | ||
2577 | 48 | self.mocked_create_verse = self.create_verse_patcher.start() | ||
2578 | 49 | self.find_and_create_book_patch = patch.object(BibleImport, 'find_and_create_book') | ||
2579 | 50 | self.addCleanup(self.find_and_create_book_patch.stop) | ||
2580 | 51 | self.mocked_find_and_create_book = self.find_and_create_book_patch.start() | ||
2581 | 52 | self.registry_patcher = patch('openlp.plugins.bibles.lib.bibleimport.Registry') | ||
2582 | 53 | self.addCleanup(self.registry_patcher.stop) | ||
2583 | 45 | self.registry_patcher.start() | 54 | self.registry_patcher.start() |
2584 | 46 | self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager') | 55 | self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager') |
2585 | 56 | self.addCleanup(self.manager_patcher.stop) | ||
2586 | 47 | self.manager_patcher.start() | 57 | self.manager_patcher.start() |
2587 | 48 | 58 | ||
2588 | 49 | def tearDown(self): | ||
2589 | 50 | self.registry_patcher.stop() | ||
2590 | 51 | self.manager_patcher.stop() | ||
2591 | 52 | |||
2592 | 53 | def test_create_importer(self): | 59 | def test_create_importer(self): |
2593 | 54 | """ | 60 | """ |
2594 | 55 | Test creating an instance of the OSIS file importer | 61 | Test creating an instance of the OSIS file importer |
2595 | @@ -63,6 +69,353 @@ | |||
2596 | 63 | # THEN: The importer should be an instance of BibleDB | 69 | # THEN: The importer should be an instance of BibleDB |
2597 | 64 | self.assertIsInstance(importer, BibleDB) | 70 | self.assertIsInstance(importer, BibleDB) |
2598 | 65 | 71 | ||
2599 | 72 | def process_books_stop_import_test(self): | ||
2600 | 73 | """ | ||
2601 | 74 | Test process_books when stop_import is set to True | ||
2602 | 75 | """ | ||
2603 | 76 | # GIVEN: An instance of OSISBible adn some mocked data | ||
2604 | 77 | importer = OSISBible(MagicMock(), path='.', name='.', filename='') | ||
2605 | 78 | mocked_data = MagicMock(**{'xpath.return_value': ['Book']}) | ||
2606 | 79 | |||
2607 | 80 | # WHEN: stop_import_flag is set to True and process_books is called | ||
2608 | 81 | importer.stop_import_flag = True | ||
2609 | 82 | importer.process_books(mocked_data) | ||
2610 | 83 | |||
2611 | 84 | # THEN: find_and_create_book should not have been called | ||
2612 | 85 | self.assertFalse(self.mocked_find_and_create_book.called) | ||
2613 | 86 | |||
2614 | 87 | def process_books_completes_test(self): | ||
2615 | 88 | """ | ||
2616 | 89 | Test process_books when it processes all books | ||
2617 | 90 | """ | ||
2618 | 91 | # GIVEN: An instance of OSISBible Importer and two mocked books | ||
2619 | 92 | self.mocked_find_and_create_book.side_effect = ['db_book1', 'db_book2'] | ||
2620 | 93 | with patch.object(OSISBible, 'process_chapters') as mocked_process_chapters: | ||
2621 | 94 | importer = OSISBible(MagicMock(), path='.', name='.', filename='') | ||
2622 | 95 | |||
2623 | 96 | book1 = MagicMock() | ||
2624 | 97 | book1.get.return_value = 'Name1' | ||
2625 | 98 | book2 = MagicMock() | ||
2626 | 99 | book2.get.return_value = 'Name2' | ||
2627 | 100 | mocked_data = MagicMock(**{'xpath.return_value': [book1, book2]}) | ||
2628 | 101 | importer.language_id = 10 | ||
2629 | 102 | importer.session = MagicMock() | ||
2630 | 103 | importer.stop_import_flag = False | ||
2631 | 104 | |||
2632 | 105 | # WHEN: Calling process_books with the two books | ||
2633 | 106 | importer.process_books(mocked_data) | ||
2634 | 107 | |||
2635 | 108 | # THEN: find_and_create_book and process_books should be called with the details from the mocked books | ||
2636 | 109 | self.assertEqual(self.mocked_find_and_create_book.call_args_list, | ||
2637 | 110 | [call('Name1', 2, 10), call('Name2', 2, 10)]) | ||
2638 | 111 | self.assertEqual(mocked_process_chapters.call_args_list, | ||
2639 | 112 | [call('db_book1', book1), call('db_book2', book2)]) | ||
2640 | 113 | self.assertEqual(importer.session.commit.call_count, 2) | ||
2641 | 114 | |||
2642 | 115 | def process_chapters_verse_in_chapter_verse_text_test(self): | ||
2643 | 116 | """ | ||
2644 | 117 | Test process_chapters when supplied with an etree element with a verse element nested in it | ||
2645 | 118 | """ | ||
2646 | 119 | with patch('openlp.plugins.bibles.lib.importers.osis.verse_in_chapter', return_value=True), \ | ||
2647 | 120 | patch('openlp.plugins.bibles.lib.importers.osis.text_in_verse', return_value=True), \ | ||
2648 | 121 | patch.object(OSISBible, 'set_current_chapter') as mocked_set_current_chapter, \ | ||
2649 | 122 | patch.object(OSISBible, 'process_verse') as mocked_process_verse: | ||
2650 | 123 | |||
2651 | 124 | # GIVEN: Some test data and an instance of OSISBible | ||
2652 | 125 | test_book = MagicMock() | ||
2653 | 126 | test_verse = MagicMock() | ||
2654 | 127 | test_verse.tail = '\n ' # Whitespace | ||
2655 | 128 | test_verse.text = 'Verse Text' | ||
2656 | 129 | test_chapter = MagicMock() | ||
2657 | 130 | test_chapter.__iter__.return_value = [test_verse] | ||
2658 | 131 | test_chapter.get.side_effect = lambda x: {'osisID': '1.2.4', 'sID': '999'}.get(x) | ||
2659 | 132 | importer = OSISBible(MagicMock(), path='.', name='.', filename='') | ||
2660 | 133 | |||
2661 | 134 | # WHEN: Calling process_chapters | ||
2662 | 135 | importer.process_chapters(test_book, [test_chapter]) | ||
2663 | 136 | |||
2664 | 137 | # THEN: set_current_chapter and process_verse should have been called with the test data | ||
2665 | 138 | mocked_set_current_chapter.assert_called_once_with(test_book.name, 2) | ||
2666 | 139 | mocked_process_verse.assert_called_once_with(test_book, 2, test_verse) | ||
2667 | 140 | |||
2668 | 141 | def process_chapters_verse_in_chapter_verse_milestone_test(self): | ||
2669 | 142 | """ | ||
2670 | 143 | Test process_chapters when supplied with an etree element with a verse element nested, when the verse system is | ||
2671 | 144 | based on milestones | ||
2672 | 145 | """ | ||
2673 | 146 | with patch('openlp.plugins.bibles.lib.importers.osis.verse_in_chapter', return_value=True), \ | ||
2674 | 147 | patch('openlp.plugins.bibles.lib.importers.osis.text_in_verse', return_value=False), \ | ||
2675 | 148 | patch.object(OSISBible, 'set_current_chapter') as mocked_set_current_chapter, \ | ||
2676 | 149 | patch.object(OSISBible, 'process_verse') as mocked_process_verse: | ||
2677 | 150 | |||
2678 | 151 | # GIVEN: Some test data and an instance of OSISBible | ||
2679 | 152 | test_book = MagicMock() | ||
2680 | 153 | test_verse = MagicMock() | ||
2681 | 154 | test_verse.tail = '\n ' # Whitespace | ||
2682 | 155 | test_verse.text = 'Verse Text' | ||
2683 | 156 | test_chapter = MagicMock() | ||
2684 | 157 | test_chapter.__iter__.return_value = [test_verse] | ||
2685 | 158 | test_chapter.get.side_effect = lambda x: {'osisID': '1.2.4', 'sID': '999'}.get(x) | ||
2686 | 159 | importer = OSISBible(MagicMock(), path='.', name='.', filename='') | ||
2687 | 160 | |||
2688 | 161 | # WHEN: Calling process_chapters | ||
2689 | 162 | importer.process_chapters(test_book, [test_chapter]) | ||
2690 | 163 | |||
2691 | 164 | # THEN: set_current_chapter and process_verse should have been called with the test data | ||
2692 | 165 | mocked_set_current_chapter.assert_called_once_with(test_book.name, 2) | ||
2693 | 166 | mocked_process_verse.assert_called_once_with(test_book, 2, test_verse, use_milestones=True) | ||
2694 | 167 | |||
2695 | 168 | def process_chapters_milestones_chapter_no_sid_test(self): | ||
2696 | 169 | """ | ||
2697 | 170 | Test process_chapters when supplied with an etree element with a chapter and verse element in the milestone | ||
2698 | 171 | configuration, where the chapter is the "closing" milestone. (Missing the sID attribute) | ||
2699 | 172 | """ | ||
2700 | 173 | with patch('openlp.plugins.bibles.lib.importers.osis.verse_in_chapter', return_value=False), \ | ||
2701 | 174 | patch.object(OSISBible, 'set_current_chapter') as mocked_set_current_chapter, \ | ||
2702 | 175 | patch.object(OSISBible, 'process_verse') as mocked_process_verse: | ||
2703 | 176 | |||
2704 | 177 | # GIVEN: Some test data and an instance of OSISBible | ||
2705 | 178 | test_book = MagicMock() | ||
2706 | 179 | test_chapter = MagicMock() | ||
2707 | 180 | test_chapter.tag = '{http://www.bibletechnologies.net/2003/OSIS/namespace}chapter' | ||
2708 | 181 | test_chapter.get.side_effect = lambda x: {'osisID': '1.2.4'}.get(x) | ||
2709 | 182 | |||
2710 | 183 | # WHEN: Calling process_chapters | ||
2711 | 184 | importer = OSISBible(MagicMock(), path='.', name='.', filename='') | ||
2712 | 185 | importer.process_chapters(test_book, [test_chapter]) | ||
2713 | 186 | |||
2714 | 187 | # THEN: neither set_current_chapter or process_verse should have been called | ||
2715 | 188 | self.assertFalse(mocked_set_current_chapter.called) | ||
2716 | 189 | self.assertFalse(mocked_process_verse.called) | ||
2717 | 190 | |||
2718 | 191 | def process_chapters_milestones_chapter_sid_test(self): | ||
2719 | 192 | """ | ||
2720 | 193 | Test process_chapters when supplied with an etree element with a chapter and verse element in the milestone | ||
2721 | 194 | configuration, where the chapter is the "opening" milestone. (Has the sID attribute) | ||
2722 | 195 | """ | ||
2723 | 196 | with patch('openlp.plugins.bibles.lib.importers.osis.verse_in_chapter', return_value=False), \ | ||
2724 | 197 | patch.object(OSISBible, 'set_current_chapter') as mocked_set_current_chapter, \ | ||
2725 | 198 | patch.object(OSISBible, 'process_verse') as mocked_process_verse: | ||
2726 | 199 | |||
2727 | 200 | # GIVEN: Some test data and an instance of OSISBible | ||
2728 | 201 | test_book = MagicMock() | ||
2729 | 202 | test_chapter = MagicMock() | ||
2730 | 203 | test_chapter.tag = '{http://www.bibletechnologies.net/2003/OSIS/namespace}chapter' | ||
2731 | 204 | test_chapter.get.side_effect = lambda x: {'osisID': '1.2.4', 'sID': '999'}.get(x) | ||
2732 | 205 | importer = OSISBible(MagicMock(), path='.', name='.', filename='') | ||
2733 | 206 | |||
2734 | 207 | # WHEN: Calling process_chapters | ||
2735 | 208 | importer.process_chapters(test_book, [test_chapter]) | ||
2736 | 209 | |||
2737 | 210 | # THEN: set_current_chapter should have been called with the test data | ||
2738 | 211 | mocked_set_current_chapter.assert_called_once_with(test_book.name, 2) | ||
2739 | 212 | self.assertFalse(mocked_process_verse.called) | ||
2740 | 213 | |||
2741 | 214 | def process_chapters_milestones_verse_tag_test(self): | ||
2742 | 215 | """ | ||
2743 | 216 | Test process_chapters when supplied with an etree element with a chapter and verse element in the milestone | ||
2744 | 217 | configuration, where the verse is the "opening" milestone. (Has the sID attribute) | ||
2745 | 218 | """ | ||
2746 | 219 | with patch('openlp.plugins.bibles.lib.importers.osis.verse_in_chapter', return_value=False), \ | ||
2747 | 220 | patch.object(OSISBible, 'set_current_chapter') as mocked_set_current_chapter, \ | ||
2748 | 221 | patch.object(OSISBible, 'process_verse') as mocked_process_verse: | ||
2749 | 222 | |||
2750 | 223 | # GIVEN: Some test data and an instance of OSISBible | ||
2751 | 224 | test_book = MagicMock() | ||
2752 | 225 | test_verse = MagicMock() | ||
2753 | 226 | test_verse.get.side_effect = lambda x: {'osisID': '1.2.4', 'sID': '999'}.get(x) | ||
2754 | 227 | test_verse.tag = '{http://www.bibletechnologies.net/2003/OSIS/namespace}verse' | ||
2755 | 228 | test_verse.tail = '\n ' # Whitespace | ||
2756 | 229 | test_verse.text = 'Verse Text' | ||
2757 | 230 | |||
2758 | 231 | # WHEN: Calling process_chapters | ||
2759 | 232 | importer = OSISBible(MagicMock(), path='.', name='.', filename='') | ||
2760 | 233 | importer.process_chapters(test_book, [test_verse]) | ||
2761 | 234 | |||
2762 | 235 | # THEN: process_verse should have been called with the test data | ||
2763 | 236 | self.assertFalse(mocked_set_current_chapter.called) | ||
2764 | 237 | mocked_process_verse.assert_called_once_with(test_book, 0, test_verse, use_milestones=True) | ||
2765 | 238 | |||
2766 | 239 | def process_verse_no_osis_id_test(self): | ||
2767 | 240 | """ | ||
2768 | 241 | Test process_verse when the element supplied does not have and osisID attribute | ||
2769 | 242 | """ | ||
2770 | 243 | # GIVEN: An instance of OSISBible, and some mocked test data | ||
2771 | 244 | test_book = MagicMock() | ||
2772 | 245 | test_verse = MagicMock() | ||
2773 | 246 | test_verse.get.side_effect = lambda x: {}.get(x) | ||
2774 | 247 | test_verse.tail = 'Verse Text' | ||
2775 | 248 | test_verse.text = None | ||
2776 | 249 | importer = OSISBible(MagicMock(), path='.', name='.', filename='') | ||
2777 | 250 | |||
2778 | 251 | # WHEN: Calling process_verse with the test data | ||
2779 | 252 | importer.process_verse(test_book, 2, test_verse) | ||
2780 | 253 | |||
2781 | 254 | # THEN: create_verse should not have been called | ||
2782 | 255 | self.assertFalse(self.mocked_create_verse.called) | ||
2783 | 256 | |||
2784 | 257 | def process_verse_use_milestones_no_s_id_test(self): | ||
2785 | 258 | """ | ||
2786 | 259 | Test process_verse when called with use_milestones set to True, but the element supplied does not have and sID | ||
2787 | 260 | attribute | ||
2788 | 261 | """ | ||
2789 | 262 | # GIVEN: An instance of OSISBible, and some mocked test data | ||
2790 | 263 | test_book = MagicMock() | ||
2791 | 264 | test_verse = MagicMock() | ||
2792 | 265 | test_verse.get.side_effect = lambda x: {}.get(x) | ||
2793 | 266 | test_verse.tail = 'Verse Text' | ||
2794 | 267 | test_verse.text = None | ||
2795 | 268 | importer = OSISBible(MagicMock(), path='.', name='.', filename='') | ||
2796 | 269 | |||
2797 | 270 | # WHEN: Calling process_verse with the test data | ||
2798 | 271 | importer.process_verse(test_book, 2, test_verse) | ||
2799 | 272 | |||
2800 | 273 | # THEN: create_verse should not have been called | ||
2801 | 274 | self.assertFalse(self.mocked_create_verse.called) | ||
2802 | 275 | |||
2803 | 276 | def process_verse_use_milestones_no_tail_test(self): | ||
2804 | 277 | """ | ||
2805 | 278 | Test process_verse when called with use_milestones set to True, but the element supplied does not have a 'tail' | ||
2806 | 279 | """ | ||
2807 | 280 | # GIVEN: An instance of OSISBible, and some mocked test data | ||
2808 | 281 | test_book = MagicMock() | ||
2809 | 282 | test_verse = MagicMock() | ||
2810 | 283 | test_verse.tail = None | ||
2811 | 284 | test_verse.text = None | ||
2812 | 285 | test_verse.get.side_effect = lambda x: {'osisID': '1.2.4', 'sID': '999'}.get(x) | ||
2813 | 286 | importer = OSISBible(MagicMock(), path='.', name='.', filename='') | ||
2814 | 287 | |||
2815 | 288 | # WHEN: Calling process_verse with the test data | ||
2816 | 289 | importer.process_verse(test_book, 2, test_verse, use_milestones=True) | ||
2817 | 290 | |||
2818 | 291 | # THEN: create_verse should not have been called | ||
2819 | 292 | self.assertFalse(self.mocked_create_verse.called) | ||
2820 | 293 | |||
2821 | 294 | def process_verse_use_milestones_success_test(self): | ||
2822 | 295 | """ | ||
2823 | 296 | Test process_verse when called with use_milestones set to True, and the verse element successfully imports | ||
2824 | 297 | """ | ||
2825 | 298 | # GIVEN: An instance of OSISBible, and some mocked test data | ||
2826 | 299 | test_book = MagicMock() | ||
2827 | 300 | test_book.id = 1 | ||
2828 | 301 | test_verse = MagicMock() | ||
2829 | 302 | test_verse.tail = 'Verse Text' | ||
2830 | 303 | test_verse.text = None | ||
2831 | 304 | test_verse.get.side_effect = lambda x: {'osisID': '1.2.4', 'sID': '999'}.get(x) | ||
2832 | 305 | importer = OSISBible(MagicMock(), path='.', name='.', filename='') | ||
2833 | 306 | |||
2834 | 307 | # WHEN: Calling process_verse with the test data | ||
2835 | 308 | importer.process_verse(test_book, 2, test_verse, use_milestones=True) | ||
2836 | 309 | |||
2837 | 310 | # THEN: create_verse should have been called with the test data | ||
2838 | 311 | self.mocked_create_verse.assert_called_once_with(1, 2, 4, 'Verse Text') | ||
2839 | 312 | |||
2840 | 313 | def process_verse_no_text_test(self): | ||
2841 | 314 | """ | ||
2842 | 315 | Test process_verse when called with an empty verse element | ||
2843 | 316 | """ | ||
2844 | 317 | # GIVEN: An instance of OSISBible, and some mocked test data | ||
2845 | 318 | test_book = MagicMock() | ||
2846 | 319 | test_book.id = 1 | ||
2847 | 320 | test_verse = MagicMock() | ||
2848 | 321 | test_verse.tail = '\n ' # Whitespace | ||
2849 | 322 | test_verse.text = None | ||
2850 | 323 | test_verse.get.side_effect = lambda x: {'osisID': '1.2.4', 'sID': '999'}.get(x) | ||
2851 | 324 | importer = OSISBible(MagicMock(), path='.', name='.', filename='') | ||
2852 | 325 | |||
2853 | 326 | # WHEN: Calling process_verse with the test data | ||
2854 | 327 | importer.process_verse(test_book, 2, test_verse) | ||
2855 | 328 | |||
2856 | 329 | # THEN: create_verse should not have been called | ||
2857 | 330 | self.assertFalse(self.mocked_create_verse.called) | ||
2858 | 331 | |||
2859 | 332 | def process_verse_success_test(self): | ||
2860 | 333 | """ | ||
2861 | 334 | Test process_verse when called with an element with text set | ||
2862 | 335 | """ | ||
2863 | 336 | # GIVEN: An instance of OSISBible, and some mocked test data | ||
2864 | 337 | test_book = MagicMock() | ||
2865 | 338 | test_book.id = 1 | ||
2866 | 339 | test_verse = MagicMock() | ||
2867 | 340 | test_verse.tail = '\n ' # Whitespace | ||
2868 | 341 | test_verse.text = 'Verse Text' | ||
2869 | 342 | test_verse.get.side_effect = lambda x: {'osisID': '1.2.4', 'sID': '999'}.get(x) | ||
2870 | 343 | importer = OSISBible(MagicMock(), path='.', name='.', filename='') | ||
2871 | 344 | |||
2872 | 345 | # WHEN: Calling process_verse with the test data | ||
2873 | 346 | importer.process_verse(test_book, 2, test_verse) | ||
2874 | 347 | |||
2875 | 348 | # THEN: create_verse should have been called with the test data | ||
2876 | 349 | self.mocked_create_verse.assert_called_once_with(1, 2, 4, 'Verse Text') | ||
2877 | 350 | |||
2878 | 351 | def do_import_parse_xml_fails_test(self): | ||
2879 | 352 | """ | ||
2880 | 353 | Test do_import when parse_xml fails (returns None) | ||
2881 | 354 | """ | ||
2882 | 355 | # GIVEN: An instance of OpenSongBible and a mocked parse_xml which returns False | ||
2883 | 356 | with patch.object(OSISBible, 'log_debug'), \ | ||
2884 | 357 | patch.object(OSISBible, 'validate_xml_file'), \ | ||
2885 | 358 | patch.object(OSISBible, 'parse_xml', return_value=None), \ | ||
2886 | 359 | patch.object(OSISBible, 'get_language_id') as mocked_language_id: | ||
2887 | 360 | importer = OSISBible(MagicMock(), path='.', name='.', filename='') | ||
2888 | 361 | |||
2889 | 362 | # WHEN: Calling do_import | ||
2890 | 363 | result = importer.do_import() | ||
2891 | 364 | |||
2892 | 365 | # THEN: do_import should return False and get_language_id should have not been called | ||
2893 | 366 | self.assertFalse(result) | ||
2894 | 367 | self.assertFalse(mocked_language_id.called) | ||
2895 | 368 | |||
2896 | 369 | def do_import_no_language_test(self): | ||
2897 | 370 | """ | ||
2898 | 371 | Test do_import when the user cancels the language selection dialog | ||
2899 | 372 | """ | ||
2900 | 373 | # GIVEN: An instance of OpenSongBible and a mocked get_language which returns False | ||
2901 | 374 | with patch.object(OSISBible, 'log_debug'), \ | ||
2902 | 375 | patch.object(OSISBible, 'validate_xml_file'), \ | ||
2903 | 376 | patch.object(OSISBible, 'parse_xml'), \ | ||
2904 | 377 | patch.object(OSISBible, 'get_language_id', **{'return_value': False}), \ | ||
2905 | 378 | patch.object(OSISBible, 'process_books') as mocked_process_books: | ||
2906 | 379 | importer = OSISBible(MagicMock(), path='.', name='.', filename='') | ||
2907 | 380 | |||
2908 | 381 | # WHEN: Calling do_import | ||
2909 | 382 | result = importer.do_import() | ||
2910 | 383 | |||
2911 | 384 | # THEN: do_import should return False and process_books should have not been called | ||
2912 | 385 | self.assertFalse(result) | ||
2913 | 386 | self.assertFalse(mocked_process_books.called) | ||
2914 | 387 | |||
2915 | 388 | def do_import_completes_test(self): | ||
2916 | 389 | """ | ||
2917 | 390 | Test do_import when it completes successfully | ||
2918 | 391 | """ | ||
2919 | 392 | # GIVEN: An instance of OpenSongBible | ||
2920 | 393 | with patch.object(OSISBible, 'log_debug'), \ | ||
2921 | 394 | patch.object(OSISBible, 'validate_xml_file'), \ | ||
2922 | 395 | patch.object(OSISBible, 'parse_xml'), \ | ||
2923 | 396 | patch.object(OSISBible, 'get_language_id', **{'return_value': 10}), \ | ||
2924 | 397 | patch.object(OSISBible, 'process_books'): | ||
2925 | 398 | importer = OSISBible(MagicMock(), path='.', name='.', filename='') | ||
2926 | 399 | |||
2927 | 400 | # WHEN: Calling do_import | ||
2928 | 401 | result = importer.do_import() | ||
2929 | 402 | |||
2930 | 403 | # THEN: do_import should return True | ||
2931 | 404 | self.assertTrue(result) | ||
2932 | 405 | |||
2933 | 406 | |||
2934 | 407 | class TestOsisImportFileImports(TestCase): | ||
2935 | 408 | """ | ||
2936 | 409 | Test the functions in the :mod:`osisimport` module. | ||
2937 | 410 | """ | ||
2938 | 411 | def setUp(self): | ||
2939 | 412 | self.registry_patcher = patch('openlp.plugins.bibles.lib.bibleimport.Registry') | ||
2940 | 413 | self.addCleanup(self.registry_patcher.stop) | ||
2941 | 414 | self.registry_patcher.start() | ||
2942 | 415 | self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager') | ||
2943 | 416 | self.addCleanup(self.manager_patcher.stop) | ||
2944 | 417 | self.manager_patcher.start() | ||
2945 | 418 | |||
2946 | 66 | def test_file_import_nested_tags(self): | 419 | def test_file_import_nested_tags(self): |
2947 | 67 | """ | 420 | """ |
2948 | 68 | Test the actual import of OSIS Bible file, with nested chapter and verse tags | 421 | Test the actual import of OSIS Bible file, with nested chapter and verse tags |
2949 | @@ -91,7 +444,7 @@ | |||
2950 | 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. |
2951 | 92 | self.assertTrue(importer.create_verse.called) | 445 | self.assertTrue(importer.create_verse.called) |
2952 | 93 | for verse_tag, verse_text in test_data['verses']: | 446 | for verse_tag, verse_text in test_data['verses']: |
2954 | 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) |
2955 | 95 | 448 | ||
2956 | 96 | def test_file_import_mixed_tags(self): | 449 | def test_file_import_mixed_tags(self): |
2957 | 97 | """ | 450 | """ |
2958 | @@ -121,7 +474,7 @@ | |||
2959 | 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. |
2960 | 122 | self.assertTrue(importer.create_verse.called) | 475 | self.assertTrue(importer.create_verse.called) |
2961 | 123 | for verse_tag, verse_text in test_data['verses']: | 476 | for verse_tag, verse_text in test_data['verses']: |
2963 | 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) |
2964 | 125 | 478 | ||
2965 | 126 | def test_file_import_milestone_tags(self): | 479 | def test_file_import_milestone_tags(self): |
2966 | 127 | """ | 480 | """ |
2967 | @@ -151,7 +504,7 @@ | |||
2968 | 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. |
2969 | 152 | self.assertTrue(importer.create_verse.called) | 505 | self.assertTrue(importer.create_verse.called) |
2970 | 153 | for verse_tag, verse_text in test_data['verses']: | 506 | for verse_tag, verse_text in test_data['verses']: |
2972 | 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) |
2973 | 155 | 508 | ||
2974 | 156 | def test_file_import_empty_verse_tags(self): | 509 | def test_file_import_empty_verse_tags(self): |
2975 | 157 | """ | 510 | """ |
2976 | @@ -181,4 +534,4 @@ | |||
2977 | 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. |
2978 | 182 | self.assertTrue(importer.create_verse.called) | 535 | self.assertTrue(importer.create_verse.called) |
2979 | 183 | for verse_tag, verse_text in test_data['verses']: | 536 | for verse_tag, verse_text in test_data['verses']: |
2981 | 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) |
2982 | 185 | 538 | ||
2983 | === modified file 'tests/functional/openlp_plugins/bibles/test_swordimport.py' | |||
2984 | --- tests/functional/openlp_plugins/bibles/test_swordimport.py 2016-08-09 20:45:25 +0000 | |||
2985 | +++ tests/functional/openlp_plugins/bibles/test_swordimport.py 2016-09-09 21:59:44 +0000 | |||
2986 | @@ -46,7 +46,7 @@ | |||
2987 | 46 | """ | 46 | """ |
2988 | 47 | 47 | ||
2989 | 48 | def setUp(self): | 48 | def setUp(self): |
2991 | 49 | self.registry_patcher = patch('openlp.plugins.bibles.lib.db.Registry') | 49 | self.registry_patcher = patch('openlp.plugins.bibles.lib.bibleimport.Registry') |
2992 | 50 | self.registry_patcher.start() | 50 | self.registry_patcher.start() |
2993 | 51 | self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager') | 51 | self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager') |
2994 | 52 | self.manager_patcher.start() | 52 | self.manager_patcher.start() |
2995 | 53 | 53 | ||
2996 | === modified file 'tests/functional/openlp_plugins/bibles/test_zefaniaimport.py' | |||
2997 | --- tests/functional/openlp_plugins/bibles/test_zefaniaimport.py 2016-08-09 20:45:25 +0000 | |||
2998 | +++ tests/functional/openlp_plugins/bibles/test_zefaniaimport.py 2016-09-09 21:59:44 +0000 | |||
2999 | @@ -41,15 +41,13 @@ | |||
3000 | 41 | """ | 41 | """ |
3001 | 42 | 42 | ||
3002 | 43 | def setUp(self): | 43 | def setUp(self): |
3004 | 44 | self.registry_patcher = patch('openlp.plugins.bibles.lib.db.Registry') | 44 | self.registry_patcher = patch('openlp.plugins.bibles.lib.bibleimport.Registry') |
3005 | 45 | self.addCleanup(self.registry_patcher.stop) | ||
3006 | 45 | self.registry_patcher.start() | 46 | self.registry_patcher.start() |
3007 | 46 | self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager') | 47 | self.manager_patcher = patch('openlp.plugins.bibles.lib.db.Manager') |
3008 | 48 | self.addCleanup(self.manager_patcher.stop) | ||
3009 | 47 | self.manager_patcher.start() | 49 | self.manager_patcher.start() |
3010 | 48 | 50 | ||
3011 | 49 | def tearDown(self): | ||
3012 | 50 | self.registry_patcher.stop() | ||
3013 | 51 | self.manager_patcher.stop() | ||
3014 | 52 | |||
3015 | 53 | def test_create_importer(self): | 51 | def test_create_importer(self): |
3016 | 54 | """ | 52 | """ |
3017 | 55 | Test creating an instance of the Zefania file importer | 53 | Test creating an instance of the Zefania file importer |
3018 | @@ -90,7 +88,7 @@ | |||
3019 | 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. |
3020 | 91 | self.assertTrue(importer.create_verse.called) | 89 | self.assertTrue(importer.create_verse.called) |
3021 | 92 | for verse_tag, verse_text in test_data['verses']: | 90 | for verse_tag, verse_text in test_data['verses']: |
3023 | 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) |
3024 | 94 | importer.create_book.assert_any_call('Genesis', 1, 1) | 92 | importer.create_book.assert_any_call('Genesis', 1, 1) |
3025 | 95 | 93 | ||
3026 | 96 | def test_file_import_no_book_name(self): | 94 | def test_file_import_no_book_name(self): |
3027 | @@ -120,5 +118,5 @@ | |||
3028 | 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. |
3029 | 121 | self.assertTrue(importer.create_verse.called) | 119 | self.assertTrue(importer.create_verse.called) |
3030 | 122 | for verse_tag, verse_text in test_data['verses']: | 120 | for verse_tag, verse_text in test_data['verses']: |
3032 | 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) |
3033 | 124 | importer.create_book.assert_any_call('Exodus', 2, 1) | 122 | importer.create_book.assert_any_call('Exodus', 2, 1) |
3034 | 125 | 123 | ||
3035 | === modified file 'tests/resources/bibles/dk1933.json' | |||
3036 | --- tests/resources/bibles/dk1933.json 2014-08-24 14:40:45 +0000 | |||
3037 | +++ tests/resources/bibles/dk1933.json 2016-09-09 21:59:44 +0000 | |||
3038 | @@ -2,15 +2,15 @@ | |||
3039 | 2 | "book": "Genesis", | 2 | "book": "Genesis", |
3040 | 3 | "chapter": 1, | 3 | "chapter": 1, |
3041 | 4 | "verses": [ | 4 | "verses": [ |
3052 | 5 | [ "1", "I Begyndelsen skabte Gud Himmelen og Jorden."], | 5 | [ 1, "I Begyndelsen skabte Gud Himmelen og Jorden."], |
3053 | 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." ], |
3054 | 7 | [ "3", "Og Gud sagde: \"Der blive Lys!\" Og der blev Lys." ], | 7 | [ 3, "Og Gud sagde: \"Der blive Lys!\" Og der blev Lys." ], |
3055 | 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," ], |
3056 | 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." ], |
3057 | 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!\"" ], |
3058 | 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;" ], |
3059 | 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." ], |
3060 | 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;" ], |
3061 | 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." ] |
3062 | 15 | ] | 15 | ] |
3063 | 16 | } | 16 | } |
3064 | 17 | \ No newline at end of file | 17 | \ No newline at end of file |
3065 | 18 | 18 | ||
3066 | === modified file 'tests/resources/bibles/kjv.json' | |||
3067 | --- tests/resources/bibles/kjv.json 2014-08-24 14:40:45 +0000 | |||
3068 | +++ tests/resources/bibles/kjv.json 2016-09-09 21:59:44 +0000 | |||
3069 | @@ -2,15 +2,15 @@ | |||
3070 | 2 | "book": "Genesis", | 2 | "book": "Genesis", |
3071 | 3 | "chapter": 1, | 3 | "chapter": 1, |
3072 | 4 | "verses": [ | 4 | "verses": [ |
3083 | 5 | [ "1", "In the beginning God created the heaven and the earth."], | 5 | [ 1, "In the beginning God created the heaven and the earth."], |
3084 | 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." ], |
3085 | 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." ], |
3086 | 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." ], |
3087 | 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." ], |
3088 | 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." ], |
3089 | 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." ], |
3090 | 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." ], |
3091 | 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." ], |
3092 | 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." ] |
3093 | 15 | ] | 15 | ] |
3094 | 16 | } | 16 | } |
3095 | 17 | 17 | ||
3096 | === modified file 'tests/resources/bibles/rst.json' | |||
3097 | --- tests/resources/bibles/rst.json 2015-02-02 20:40:31 +0000 | |||
3098 | +++ tests/resources/bibles/rst.json 2016-09-09 21:59:44 +0000 | |||
3099 | @@ -2,15 +2,15 @@ | |||
3100 | 2 | "book": "Exodus", | 2 | "book": "Exodus", |
3101 | 3 | "chapter": 1, | 3 | "chapter": 1, |
3102 | 4 | "verses": [ | 4 | "verses": [ |
3113 | 5 | [ "1", "Вот имена сынов Израилевых, которые вошли в Египет с Иаковом, вошли каждый с домом своим:" ], | 5 | [ 1, "Вот имена сынов Израилевых, которые вошли в Египет с Иаковом, вошли каждый с домом своим:" ], |
3114 | 6 | [ "2", "Рувим, Симеон, Левий и Иуда," ], | 6 | [ 2, "Рувим, Симеон, Левий и Иуда," ], |
3115 | 7 | [ "3", "Иссахар, Завулон и Вениамин," ], | 7 | [ 3, "Иссахар, Завулон и Вениамин," ], |
3116 | 8 | [ "4", "Дан и Неффалим, Гад и Асир." ], | 8 | [ 4, "Дан и Неффалим, Гад и Асир." ], |
3117 | 9 | [ "5", "Всех же душ, происшедших от чресл Иакова, было семьдесят, а Иосиф был [уже] в Египте." ], | 9 | [ 5, "Всех же душ, происшедших от чресл Иакова, было семьдесят, а Иосиф был [уже] в Египте." ], |
3118 | 10 | [ "6", "И умер Иосиф и все братья его и весь род их;" ], | 10 | [ 6, "И умер Иосиф и все братья его и весь род их;" ], |
3119 | 11 | [ "7", "а сыны Израилевы расплодились и размножились, и возросли и усилились чрезвычайно, и наполнилась ими земля та." ], | 11 | [ 7, "а сыны Израилевы расплодились и размножились, и возросли и усилились чрезвычайно, и наполнилась ими земля та." ], |
3120 | 12 | [ "8", "И восстал в Египте новый царь, который не знал Иосифа," ], | 12 | [ 8, "И восстал в Египте новый царь, который не знал Иосифа," ], |
3121 | 13 | [ "9", "и сказал народу своему: вот, народ сынов Израилевых многочислен и сильнее нас;" ], | 13 | [ 9, "и сказал народу своему: вот, народ сынов Израилевых многочислен и сильнее нас;" ], |
3122 | 14 | [ "10", "перехитрим же его, чтобы он не размножался; иначе, когда случится война, соединится и он с нашими неприятелями, и вооружится против нас, и выйдет из земли [нашей]." ] | 14 | [ 10, "перехитрим же его, чтобы он не размножался; иначе, когда случится война, соединится и он с нашими неприятелями, и вооружится против нас, и выйдет из земли [нашей]." ] |
3123 | 15 | ] | 15 | ] |
3124 | 16 | } | 16 | } |
3125 | 17 | 17 | ||
3126 | === modified file 'tests/resources/bibles/web.json' | |||
3127 | --- tests/resources/bibles/web.json 2014-08-24 14:40:45 +0000 | |||
3128 | +++ tests/resources/bibles/web.json 2016-09-09 21:59:44 +0000 | |||
3129 | @@ -2,15 +2,15 @@ | |||
3130 | 2 | "book": "Genesis", | 2 | "book": "Genesis", |
3131 | 3 | "chapter": "1", | 3 | "chapter": "1", |
3132 | 4 | "verses": [ | 4 | "verses": [ |
3143 | 5 | [ "1", "In the beginning God created the heavens and the earth."], | 5 | [ 1, "In the beginning God created the heavens and the earth."], |
3144 | 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." ], |
3145 | 7 | [ "3", "God said, “Let there be light,” and there was light." ], | 7 | [ 3, "God said, “Let there be light,” and there was light." ], |
3146 | 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." ], |
3147 | 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." ], |
3148 | 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.”" ], |
3149 | 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." ], |
3150 | 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." ], |
3151 | 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." ], |
3152 | 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." ] |
3153 | 15 | ] | 15 | ] |
3154 | 16 | } | 16 | } |
Sorry one small change needed.