Merge lp:~phill-ridout/openlp/fixes-mkII into lp:openlp

Proposed by Phill
Status: Merged
Approved by: Raoul Snyman
Approved revision: 2794
Merged at revision: 2784
Proposed branch: lp:~phill-ridout/openlp/fixes-mkII
Merge into: lp:openlp
Diff against target: 1063 lines (+167/-143)
47 files modified
openlp/core/common/__init__.py (+21/-3)
openlp/core/common/applocation.py (+1/-1)
openlp/core/common/httputils.py (+4/-4)
openlp/core/common/i18n.py (+1/-1)
openlp/core/common/mixins.py (+14/-0)
openlp/core/common/path.py (+1/-1)
openlp/core/common/settings.py (+4/-1)
openlp/core/lib/__init__.py (+1/-1)
openlp/core/lib/mediamanageritem.py (+4/-2)
openlp/core/ui/exceptionform.py (+1/-1)
openlp/core/ui/formattingtagcontroller.py (+1/-1)
openlp/core/ui/mainwindow.py (+2/-2)
openlp/core/ui/servicemanager.py (+28/-28)
openlp/core/ui/thememanager.py (+3/-3)
openlp/core/version.py (+2/-2)
openlp/core/widgets/edits.py (+13/-3)
openlp/core/widgets/views.py (+1/-1)
openlp/plugins/bibles/forms/booknameform.py (+1/-2)
openlp/plugins/bibles/lib/__init__.py (+3/-3)
openlp/plugins/bibles/lib/db.py (+1/-2)
openlp/plugins/images/lib/mediaitem.py (+2/-1)
openlp/plugins/presentations/lib/pptviewcontroller.py (+1/-1)
openlp/plugins/songs/forms/editsongform.py (+3/-3)
openlp/plugins/songs/lib/__init__.py (+2/-3)
openlp/plugins/songs/lib/importers/easyslides.py (+2/-1)
openlp/plugins/songs/lib/importers/mediashout.py (+1/-1)
openlp/plugins/songs/lib/importers/openoffice.py (+2/-2)
openlp/plugins/songs/lib/importers/opensong.py (+2/-1)
openlp/plugins/songs/lib/importers/songimport.py (+2/-21)
openlp/plugins/songs/lib/importers/songsoffellowship.py (+0/-1)
openlp/plugins/songs/lib/importers/zionworx.py (+5/-15)
openlp/plugins/songs/lib/openlyricsxml.py (+1/-1)
openlp/plugins/songusage/forms/songusagedetailform.py (+8/-2)
openlp/plugins/songusage/songusageplugin.py (+6/-9)
tests/functional/openlp_core/common/test_actions.py (+1/-0)
tests/functional/openlp_core/common/test_httputils.py (+1/-1)
tests/functional/openlp_core/common/test_i18n.py (+1/-1)
tests/functional/openlp_core/common/test_path.py (+4/-4)
tests/functional/openlp_core/lib/test_lib.py (+1/-1)
tests/functional/openlp_core/ui/test_first_time.py (+1/-1)
tests/functional/openlp_core/widgets/test_views.py (+0/-1)
tests/functional/openlp_plugins/presentations/test_presentationcontroller.py (+1/-1)
tests/interfaces/openlp_core/ui/test_projectormanager.py (+1/-1)
tests/interfaces/openlp_core/ui/test_projectorsourceform.py (+1/-1)
tests/interfaces/openlp_core/ui/test_thememanager.py (+1/-1)
tests/utils/__init__.py (+1/-1)
tests/utils/test_pylint.py (+9/-5)
To merge this branch: bzr merge lp:~phill-ridout/openlp/fixes-mkII
Reviewer Review Type Date Requested Status
Raoul Snyman Pending
Tim Bentley Pending
Review via email: mp+333573@code.launchpad.net

This proposal supersedes a proposal from 2017-11-10.

Description of the change

Fixed a number of bugs, and tests.

Failing on Code Analysis2, but this looks like fallout from the refactors (it hasn't passed since the beginning of october)

Also contains superflys branch lp:~raoul-snyman/openlp/fix-linting

--------------------------------
lp:~phill-ridout/openlp/fixes-mkII (revision 2794)
[SUCCESS] https://ci.openlp.io/job/Branch-01-Pull/2276/
[SUCCESS] https://ci.openlp.io/job/Branch-02-Functional-Tests/2178/
[SUCCESS] https://ci.openlp.io/job/Branch-03-Interface-Tests/2059/
[SUCCESS] https://ci.openlp.io/job/Branch-04a-Code_Analysis/1390/
[SUCCESS] https://ci.openlp.io/job/Branch-04b-Test_Coverage/1215/
[SUCCESS] https://ci.openlp.io/job/Branch-04c-Code_Analysis2/345/
[FAILURE] https://ci.openlp.io/job/Branch-05-AppVeyor-Tests/179/
Stopping after failure

To post a comment you must log in.
Revision history for this message
Tim Bentley (trb143) wrote : Posted in a previous version of this proposal

Looks good.

review: Approve
Revision history for this message
Tim Bentley (trb143) wrote : Posted in a previous version of this proposal

Still approved

review: Approve
Revision history for this message
Raoul Snyman (raoul-snyman) wrote : Posted in a previous version of this proposal

One small request....

review: Needs Fixing

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openlp/core/common/__init__.py'
2--- openlp/core/common/__init__.py 2017-10-07 07:05:07 +0000
3+++ openlp/core/common/__init__.py 2017-11-10 23:08:30 +0000
4@@ -43,9 +43,13 @@
5
6 FIRST_CAMEL_REGEX = re.compile('(.)([A-Z][a-z]+)')
7 SECOND_CAMEL_REGEX = re.compile('([a-z0-9])([A-Z])')
8-CONTROL_CHARS = re.compile(r'[\x00-\x1F\x7F-\x9F]', re.UNICODE)
9-INVALID_FILE_CHARS = re.compile(r'[\\/:\*\?"<>\|\+\[\]%]', re.UNICODE)
10+CONTROL_CHARS = re.compile(r'[\x00-\x1F\x7F-\x9F]')
11+INVALID_FILE_CHARS = re.compile(r'[\\/:\*\?"<>\|\+\[\]%]')
12 IMAGES_FILTER = None
13+REPLACMENT_CHARS_MAP = str.maketrans({'\u2018': '\'', '\u2019': '\'', '\u201c': '"', '\u201d': '"', '\u2026': '...',
14+ '\u2013': '-', '\u2014': '-', '\v': '\n\n', '\f': '\n\n'})
15+NEW_LINE_REGEX = re.compile(r' ?(\r\n?|\n) ?')
16+WHITESPACE_REGEX = re.compile(r'[ \t]+')
17
18
19 def trace_error_handler(logger):
20@@ -339,7 +343,7 @@
21 if file_path.exists():
22 file_path.unlink()
23 return True
24- except (IOError, OSError):
25+ except OSError:
26 log.exception('Unable to delete file {file_path}'.format(file_path=file_path))
27 return False
28
29@@ -436,3 +440,17 @@
30 return detector.result
31 except OSError:
32 log.exception('Error detecting file encoding')
33+
34+
35+def normalize_str(irreg_str):
36+ """
37+ Normalize the supplied string. Remove unicode control chars and tidy up white space.
38+
39+ :param str irreg_str: The string to normalize.
40+ :return: The normalized string
41+ :rtype: str
42+ """
43+ irreg_str = irreg_str.translate(REPLACMENT_CHARS_MAP)
44+ irreg_str = CONTROL_CHARS.sub('', irreg_str)
45+ irreg_str = NEW_LINE_REGEX.sub('\n', irreg_str)
46+ return WHITESPACE_REGEX.sub(' ', irreg_str)
47
48=== modified file 'openlp/core/common/applocation.py'
49--- openlp/core/common/applocation.py 2017-10-07 07:05:07 +0000
50+++ openlp/core/common/applocation.py 2017-11-10 23:08:30 +0000
51@@ -83,7 +83,7 @@
52 """
53 # Check if we have a different data location.
54 if Settings().contains('advanced/data path'):
55- path = Settings().value('advanced/data path')
56+ path = Path(Settings().value('advanced/data path'))
57 else:
58 path = AppLocation.get_directory(AppLocation.DataDir)
59 create_paths(path)
60
61=== modified file 'openlp/core/common/httputils.py'
62--- openlp/core/common/httputils.py 2017-10-07 07:05:07 +0000
63+++ openlp/core/common/httputils.py 2017-11-10 23:08:30 +0000
64@@ -97,8 +97,8 @@
65 response = requests.get(url, headers=headers, proxies=proxies, timeout=float(CONNECTION_TIMEOUT))
66 log.debug('Downloaded page {url}'.format(url=response.url))
67 break
68- except IOError:
69- # For now, catch IOError. All requests errors inherit from IOError
70+ except OSError:
71+ # For now, catch OSError. All requests errors inherit from OSError
72 log.exception('Unable to connect to {url}'.format(url=url))
73 response = None
74 if retries >= CONNECTION_RETRIES:
75@@ -127,7 +127,7 @@
76 try:
77 response = requests.head(url, timeout=float(CONNECTION_TIMEOUT), allow_redirects=True)
78 return int(response.headers['Content-Length'])
79- except IOError:
80+ except OSError:
81 if retries > CONNECTION_RETRIES:
82 raise ConnectionError('Unable to download {url}'.format(url=url))
83 else:
84@@ -173,7 +173,7 @@
85 file_path.unlink()
86 return False
87 break
88- except IOError:
89+ except OSError:
90 trace_error_handler(log)
91 if retries > CONNECTION_RETRIES:
92 if file_path.exists():
93
94=== modified file 'openlp/core/common/i18n.py'
95--- openlp/core/common/i18n.py 2017-10-07 07:05:07 +0000
96+++ openlp/core/common/i18n.py 2017-11-10 23:08:30 +0000
97@@ -53,7 +53,7 @@
98
99 Language = namedtuple('Language', ['id', 'name', 'code'])
100 ICU_COLLATOR = None
101-DIGITS_OR_NONDIGITS = re.compile(r'\d+|\D+', re.UNICODE)
102+DIGITS_OR_NONDIGITS = re.compile(r'\d+|\D+')
103 LANGUAGES = sorted([
104 Language(1, translate('common.languages', '(Afan) Oromo', 'Language code: om'), 'om'),
105 Language(2, translate('common.languages', 'Abkhazian', 'Language code: ab'), 'ab'),
106
107=== modified file 'openlp/core/common/mixins.py'
108--- openlp/core/common/mixins.py 2017-10-23 22:09:57 +0000
109+++ openlp/core/common/mixins.py 2017-11-10 23:08:30 +0000
110@@ -101,6 +101,20 @@
111 """
112 This adds registry components to classes to use at run time.
113 """
114+ _application = None
115+ _plugin_manager = None
116+ _image_manager = None
117+ _media_controller = None
118+ _service_manager = None
119+ _preview_controller = None
120+ _live_controller = None
121+ _main_window = None
122+ _renderer = None
123+ _theme_manager = None
124+ _settings_form = None
125+ _alerts_manager = None
126+ _projector_manager = None
127+
128 @property
129 def application(self):
130 """
131
132=== modified file 'openlp/core/common/path.py'
133--- openlp/core/common/path.py 2017-10-07 07:05:07 +0000
134+++ openlp/core/common/path.py 2017-11-10 23:08:30 +0000
135@@ -233,7 +233,7 @@
136 try:
137 if not path.exists():
138 path.mkdir(parents=True)
139- except IOError:
140+ except OSError:
141 if not kwargs.get('do_not_log', False):
142 log.exception('failed to check if directory exists or create directory')
143
144
145=== modified file 'openlp/core/common/settings.py'
146--- openlp/core/common/settings.py 2017-10-07 07:05:07 +0000
147+++ openlp/core/common/settings.py 2017-11-10 23:08:30 +0000
148@@ -255,7 +255,10 @@
149 ('core/logo file', 'core/logo file', [(str_to_path, None)]),
150 ('presentations/last directory', 'presentations/last directory', [(str_to_path, None)]),
151 ('images/last directory', 'images/last directory', [(str_to_path, None)]),
152- ('media/last directory', 'media/last directory', [(str_to_path, None)])
153+ ('media/last directory', 'media/last directory', [(str_to_path, None)]),
154+ ('songuasge/db password', 'songusage/db password', []),
155+ ('songuasge/db hostname', 'songusage/db hostname', []),
156+ ('songuasge/db database', 'songusage/db database', [])
157 ]
158
159 @staticmethod
160
161=== modified file 'openlp/core/lib/__init__.py'
162--- openlp/core/lib/__init__.py 2017-10-10 07:08:44 +0000
163+++ openlp/core/lib/__init__.py 2017-11-10 23:08:30 +0000
164@@ -104,7 +104,7 @@
165 # no BOM was found
166 file_handle.seek(0)
167 content = file_handle.read()
168- except (IOError, UnicodeError):
169+ except (OSError, UnicodeError):
170 log.exception('Failed to open text file {text}'.format(text=text_file_path))
171 return content
172
173
174=== modified file 'openlp/core/lib/mediamanageritem.py'
175--- openlp/core/lib/mediamanageritem.py 2017-10-23 22:09:57 +0000
176+++ openlp/core/lib/mediamanageritem.py 2017-11-10 23:08:30 +0000
177@@ -92,7 +92,7 @@
178 Run some initial setup. This method is separate from __init__ in order to mock it out in tests.
179 """
180 self.hide()
181- self.whitespace = re.compile(r'[\W_]+', re.UNICODE)
182+ self.whitespace = re.compile(r'[\W_]+')
183 visible_title = self.plugin.get_string(StringContent.VisibleName)
184 self.title = str(visible_title['title'])
185 Registry().register(self.plugin.name, self)
186@@ -344,7 +344,9 @@
187 else:
188 new_files.append(file_name)
189 if new_files:
190- self.validate_and_load(new_files, data['target'])
191+ if 'target' in data:
192+ self.validate_and_load(new_files, data['target'])
193+ self.validate_and_load(new_files)
194
195 def dnd_move_internal(self, target):
196 """
197
198=== modified file 'openlp/core/ui/exceptionform.py'
199--- openlp/core/ui/exceptionform.py 2017-10-23 22:09:57 +0000
200+++ openlp/core/ui/exceptionform.py 2017-11-10 23:08:30 +0000
201@@ -155,7 +155,7 @@
202 try:
203 with file_path.open('w') as report_file:
204 report_file.write(report_text)
205- except IOError:
206+ except OSError:
207 log.exception('Failed to write crash report')
208
209 def on_send_report_button_clicked(self):
210
211=== modified file 'openlp/core/ui/formattingtagcontroller.py'
212--- openlp/core/ui/formattingtagcontroller.py 2017-10-07 07:05:07 +0000
213+++ openlp/core/ui/formattingtagcontroller.py 2017-11-10 23:08:30 +0000
214@@ -43,7 +43,7 @@
215 r'(?P<tag>[^\s/!\?>]+)(?:\s+[^\s=]+="[^"]*")*\s*(?P<empty>/)?'
216 r'|(?P<cdata>!\[CDATA\[(?:(?!\]\]>).)*\]\])'
217 r'|(?P<procinst>\?(?:(?!\?>).)*\?)'
218- r'|(?P<comment>!--(?:(?!-->).)*--))>', re.UNICODE)
219+ r'|(?P<comment>!--(?:(?!-->).)*--))>')
220 self.html_regex = re.compile(r'^(?:[^<>]*%s)*[^<>]*$' % self.html_tag_regex.pattern)
221
222 def pre_save(self):
223
224=== added directory 'openlp/core/ui/lib'
225=== modified file 'openlp/core/ui/mainwindow.py'
226--- openlp/core/ui/mainwindow.py 2017-10-23 22:09:57 +0000
227+++ openlp/core/ui/mainwindow.py 2017-11-10 23:08:30 +0000
228@@ -180,7 +180,7 @@
229 triggers=self.service_manager_contents.on_load_service_clicked)
230 self.file_save_item = create_action(main_window, 'fileSaveItem', icon=':/general/general_save.png',
231 can_shortcuts=True, category=UiStrings().File,
232- triggers=self.service_manager_contents.save_file)
233+ triggers=self.service_manager_contents.decide_save_method)
234 self.file_save_as_item = create_action(main_window, 'fileSaveAsItem', can_shortcuts=True,
235 category=UiStrings().File,
236 triggers=self.service_manager_contents.save_file_as)
237@@ -1367,7 +1367,7 @@
238 '- Please wait for copy to finish').format(path=self.new_data_path))
239 dir_util.copy_tree(str(old_data_path), str(self.new_data_path))
240 log.info('Copy successful')
241- except (IOError, os.error, DistutilsFileError) as why:
242+ except (OSError, DistutilsFileError) as why:
243 self.application.set_normal_cursor()
244 log.exception('Data copy failed {err}'.format(err=str(why)))
245 err_text = translate('OpenLP.MainWindow',
246
247=== modified file 'openlp/core/ui/servicemanager.py'
248--- openlp/core/ui/servicemanager.py 2017-10-23 22:09:57 +0000
249+++ openlp/core/ui/servicemanager.py 2017-11-10 23:08:30 +0000
250@@ -193,18 +193,6 @@
251 text=translate('OpenLP.ServiceManager', 'Move to &bottom'), icon=':/services/service_bottom.png',
252 tooltip=translate('OpenLP.ServiceManager', 'Move item to the end of the service.'),
253 can_shortcuts=True, category=UiStrings().Service, triggers=self.on_service_end)
254- self.down_action = self.order_toolbar.add_toolbar_action(
255- 'down',
256- text=translate('OpenLP.ServiceManager', 'Move &down'), can_shortcuts=True,
257- tooltip=translate('OpenLP.ServiceManager', 'Moves the selection down the window.'), visible=False,
258- triggers=self.on_move_selection_down)
259- action_list.add_action(self.down_action)
260- self.up_action = self.order_toolbar.add_toolbar_action(
261- 'up',
262- text=translate('OpenLP.ServiceManager', 'Move up'), can_shortcuts=True,
263- tooltip=translate('OpenLP.ServiceManager', 'Moves the selection up the window.'), visible=False,
264- triggers=self.on_move_selection_up)
265- action_list.add_action(self.up_action)
266 self.order_toolbar.addSeparator()
267 self.delete_action = self.order_toolbar.add_toolbar_action(
268 'delete', can_shortcuts=True,
269@@ -300,8 +288,8 @@
270 self.theme_menu = QtWidgets.QMenu(translate('OpenLP.ServiceManager', '&Change Item Theme'))
271 self.menu.addMenu(self.theme_menu)
272 self.service_manager_list.addActions([self.move_down_action, self.move_up_action, self.make_live_action,
273- self.move_top_action, self.move_bottom_action, self.up_action,
274- self.down_action, self.expand_action, self.collapse_action])
275+ self.move_top_action, self.move_bottom_action, self.expand_action,
276+ self.collapse_action])
277 Registry().register_function('theme_update_list', self.update_theme_list)
278 Registry().register_function('config_screen_changed', self.regenerate_service_items)
279 Registry().register_function('theme_update_global', self.theme_change)
280@@ -474,6 +462,12 @@
281 Load a recent file as the service triggered by mainwindow recent service list.
282 :param field:
283 """
284+ if self.is_modified():
285+ result = self.save_modified_service()
286+ if result == QtWidgets.QMessageBox.Cancel:
287+ return False
288+ elif result == QtWidgets.QMessageBox.Save:
289+ self.decide_save_method()
290 sender = self.sender()
291 self.load_file(sender.data())
292
293@@ -603,7 +597,7 @@
294 if not os.path.exists(save_file):
295 shutil.copy(audio_from, save_file)
296 zip_file.write(audio_from, audio_to)
297- except IOError:
298+ except OSError:
299 self.log_exception('Failed to save service to disk: {name}'.format(name=temp_file_name))
300 self.main_window.error_message(translate('OpenLP.ServiceManager', 'Error Saving File'),
301 translate('OpenLP.ServiceManager', 'There was an error saving your file.'))
302@@ -664,7 +658,7 @@
303 zip_file = zipfile.ZipFile(temp_file_name, 'w', zipfile.ZIP_STORED, True)
304 # First we add service contents.
305 zip_file.writestr(service_file_name, service_content)
306- except IOError:
307+ except OSError:
308 self.log_exception('Failed to save service to disk: {name}'.format(name=temp_file_name))
309 self.main_window.error_message(translate('OpenLP.ServiceManager', 'Error Saving File'),
310 translate('OpenLP.ServiceManager', 'There was an error saving your file.'))
311@@ -712,18 +706,23 @@
312 default_file_path = directory_path / default_file_path
313 # SaveAs from osz to oszl is not valid as the files will be deleted on exit which is not sensible or usable in
314 # the long term.
315+ lite_filter = translate('OpenLP.ServiceManager', 'OpenLP Service Files - lite (*.oszl)')
316+ packaged_filter = translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz)')
317+
318 if self._file_name.endswith('oszl') or self.service_has_all_original_files:
319 file_path, filter_used = FileDialog.getSaveFileName(
320 self.main_window, UiStrings().SaveService, default_file_path,
321- translate('OpenLP.ServiceManager',
322- 'OpenLP Service Files (*.osz);; OpenLP Service Files - lite (*.oszl)'))
323+ '{packaged};; {lite}'.format(packaged=packaged_filter, lite=lite_filter))
324 else:
325 file_path, filter_used = FileDialog.getSaveFileName(
326- self.main_window, UiStrings().SaveService, file_path,
327- translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz);;'))
328+ self.main_window, UiStrings().SaveService, default_file_path,
329+ '{packaged};;'.format(packaged=packaged_filter))
330 if not file_path:
331 return False
332- file_path.with_suffix('.osz')
333+ if filter_used == lite_filter:
334+ file_path = file_path.with_suffix('.oszl')
335+ else:
336+ file_path = file_path.with_suffix('.osz')
337 self.set_file_name(file_path)
338 self.decide_save_method()
339
340@@ -791,11 +790,11 @@
341 else:
342 critical_error_message_box(message=translate('OpenLP.ServiceManager', 'File is not a valid service.'))
343 self.log_error('File contains no service data')
344- except (IOError, NameError):
345+ except (OSError, NameError):
346 self.log_exception('Problem loading service file {name}'.format(name=file_name))
347 critical_error_message_box(message=translate('OpenLP.ServiceManager',
348 'File could not be opened because it is corrupt.'))
349- except zipfile.BadZipfile:
350+ except zipfile.BadZipFile:
351 if os.path.getsize(file_name) == 0:
352 self.log_exception('Service file is zero sized: {name}'.format(name=file_name))
353 QtWidgets.QMessageBox.information(self, translate('OpenLP.ServiceManager', 'Empty File'),
354@@ -1657,14 +1656,15 @@
355 if start_pos == -1:
356 return
357 if item is None:
358- end_pos = len(self.service_items)
359+ end_pos = len(self.service_items) - 1
360 else:
361 end_pos = get_parent_item_data(item) - 1
362 service_item = self.service_items[start_pos]
363- self.service_items.remove(service_item)
364- self.service_items.insert(end_pos, service_item)
365- self.repaint_service_list(end_pos, child)
366- self.set_modified()
367+ if start_pos != end_pos:
368+ self.service_items.remove(service_item)
369+ self.service_items.insert(end_pos, service_item)
370+ self.repaint_service_list(end_pos, child)
371+ self.set_modified()
372 else:
373 # we are not over anything so drop
374 replace = False
375
376=== modified file 'openlp/core/ui/thememanager.py'
377--- openlp/core/ui/thememanager.py 2017-10-23 22:09:57 +0000
378+++ openlp/core/ui/thememanager.py 2017-11-10 23:08:30 +0000
379@@ -604,7 +604,7 @@
380 else:
381 with full_name.open('wb') as out_file:
382 out_file.write(theme_zip.read(zipped_file))
383- except (IOError, zipfile.BadZipfile):
384+ except (OSError, zipfile.BadZipFile):
385 self.log_exception('Importing theme from zip failed {name}'.format(name=file_path))
386 raise ValidationError
387 except ValidationError:
388@@ -667,7 +667,7 @@
389 theme_path = theme_dir / '{file_name}.json'.format(file_name=name)
390 try:
391 theme_path.write_text(theme_pretty)
392- except IOError:
393+ except OSError:
394 self.log_exception('Saving theme to file failed')
395 if image_source_path and image_destination_path:
396 if self.old_background_image_path and image_destination_path != self.old_background_image_path:
397@@ -675,7 +675,7 @@
398 if image_source_path != image_destination_path:
399 try:
400 copyfile(image_source_path, image_destination_path)
401- except IOError:
402+ except OSError:
403 self.log_exception('Failed to save theme image')
404 self.generate_and_save_image(name, theme)
405
406
407=== modified file 'openlp/core/version.py'
408--- openlp/core/version.py 2017-10-07 07:05:07 +0000
409+++ openlp/core/version.py 2017-11-10 23:08:30 +0000
410@@ -96,7 +96,7 @@
411 remote_version = response.text
412 log.debug('New version found: %s', remote_version)
413 break
414- except IOError:
415+ except OSError:
416 log.exception('Unable to connect to OpenLP server to download version file')
417 retries += 1
418 else:
419@@ -182,7 +182,7 @@
420 try:
421 version_file = open(file_path, 'r')
422 full_version = str(version_file.read()).rstrip()
423- except IOError:
424+ except OSError:
425 log.exception('Error in version file.')
426 full_version = '0.0.0-bzr000'
427 finally:
428
429=== modified file 'openlp/core/widgets/edits.py'
430--- openlp/core/widgets/edits.py 2017-10-23 22:09:57 +0000
431+++ openlp/core/widgets/edits.py 2017-11-10 23:08:30 +0000
432@@ -27,6 +27,7 @@
433
434 from PyQt5 import QtCore, QtGui, QtWidgets
435
436+from openlp.core.common import CONTROL_CHARS
437 from openlp.core.common.i18n import UiStrings, translate
438 from openlp.core.common.path import Path, path_to_str, str_to_path
439 from openlp.core.common.settings import Settings
440@@ -241,7 +242,7 @@
441 self.line_edit.editingFinished.connect(self.on_line_edit_editing_finished)
442 self.update_button_tool_tips()
443
444- @property
445+ @QtCore.pyqtProperty('QVariant')
446 def path(self):
447 """
448 A property getter method to return the selected path.
449@@ -349,7 +350,7 @@
450 :rtype: None
451 """
452 if self._path != path:
453- self.path = path
454+ self._path = path
455 self.pathChanged.emit(path)
456
457
458@@ -470,12 +471,21 @@
459 cursor.insertText(html['start tag'])
460 cursor.insertText(html['end tag'])
461
462+ def insertFromMimeData(self, source):
463+ """
464+ Reimplement `insertFromMimeData` so that we can remove any control characters
465+
466+ :param QtCore.QMimeData source: The mime data to insert
467+ :rtype: None
468+ """
469+ self.insertPlainText(CONTROL_CHARS.sub('', source.text()))
470+
471
472 class Highlighter(QtGui.QSyntaxHighlighter):
473 """
474 Provides a text highlighter for pointing out spelling errors in text.
475 """
476- WORDS = r'(?iu)[\w\']+'
477+ WORDS = r'(?i)[\w\']+'
478
479 def __init__(self, *args):
480 """
481
482=== modified file 'openlp/core/widgets/views.py'
483--- openlp/core/widgets/views.py 2017-10-23 22:09:57 +0000
484+++ openlp/core/widgets/views.py 2017-11-10 23:08:30 +0000
485@@ -336,7 +336,7 @@
486 for file in listing:
487 files.append(os.path.join(local_file, file))
488 Registry().execute('{mime_data}_dnd'.format(mime_data=self.mime_data_text),
489- {'files': files, 'target': self.itemAt(event.pos())})
490+ {'files': files})
491 else:
492 event.ignore()
493
494
495=== modified file 'openlp/plugins/bibles/forms/booknameform.py'
496--- openlp/plugins/bibles/forms/booknameform.py 2017-10-07 07:05:07 +0000
497+++ openlp/plugins/bibles/forms/booknameform.py 2017-11-10 23:08:30 +0000
498@@ -113,8 +113,7 @@
499 cor_book = self.corresponding_combo_box.currentText()
500 for character in '\\.^$*+?{}[]()':
501 cor_book = cor_book.replace(character, '\\' + character)
502- books = [key for key in list(self.book_names.keys()) if re.match(cor_book, str(self.book_names[key]),
503- re.UNICODE)]
504+ books = [key for key in list(self.book_names.keys()) if re.match(cor_book, str(self.book_names[key]))]
505 books = [_f for _f in map(BiblesResourcesDB.get_book, books) if _f]
506 if books:
507 self.book_id = books[0]['id']
508
509=== modified file 'openlp/plugins/bibles/lib/__init__.py'
510--- openlp/plugins/bibles/lib/__init__.py 2017-10-07 07:05:07 +0000
511+++ openlp/plugins/bibles/lib/__init__.py 2017-11-10 23:08:30 +0000
512@@ -224,13 +224,13 @@
513 range_regex = '(?:(?P<from_chapter>[0-9]+){sep_v})?' \
514 '(?P<from_verse>[0-9]+)(?P<range_to>{sep_r}(?:(?:(?P<to_chapter>' \
515 '[0-9]+){sep_v})?(?P<to_verse>[0-9]+)|{sep_e})?)?'.format_map(REFERENCE_SEPARATORS)
516- REFERENCE_MATCHES['range'] = re.compile(r'^\s*{range}\s*$'.format(range=range_regex), re.UNICODE)
517- REFERENCE_MATCHES['range_separator'] = re.compile(REFERENCE_SEPARATORS['sep_l'], re.UNICODE)
518+ REFERENCE_MATCHES['range'] = re.compile(r'^\s*{range}\s*$'.format(range=range_regex))
519+ REFERENCE_MATCHES['range_separator'] = re.compile(REFERENCE_SEPARATORS['sep_l'])
520 # full reference match: <book>(<range>(,(?!$)|(?=$)))+
521 REFERENCE_MATCHES['full'] = \
522 re.compile(r'^\s*(?!\s)(?P<book>[\d]*[.]?[^\d\.]+)\.*(?<!\s)\s*'
523 r'(?P<ranges>(?:{range_regex}(?:{sep_l}(?!\s*$)|(?=\s*$)))+)\s*$'.format(
524- range_regex=range_regex, sep_l=REFERENCE_SEPARATORS['sep_l']), re.UNICODE)
525+ range_regex=range_regex, sep_l=REFERENCE_SEPARATORS['sep_l']))
526
527
528 def get_reference_separator(separator_type):
529
530=== modified file 'openlp/plugins/bibles/lib/db.py'
531--- openlp/plugins/bibles/lib/db.py 2017-10-23 22:09:57 +0000
532+++ openlp/plugins/bibles/lib/db.py 2017-11-10 23:08:30 +0000
533@@ -307,8 +307,7 @@
534 book_escaped = book
535 for character in RESERVED_CHARACTERS:
536 book_escaped = book_escaped.replace(character, '\\' + character)
537- regex_book = re.compile('\\s*{book}\\s*'.format(book='\\s*'.join(book_escaped.split())),
538- re.UNICODE | re.IGNORECASE)
539+ regex_book = re.compile('\\s*{book}\\s*'.format(book='\\s*'.join(book_escaped.split())), re.IGNORECASE)
540 if language_selection == LanguageSelection.Bible:
541 db_book = self.get_book(book)
542 if db_book:
543
544=== modified file 'openlp/plugins/images/lib/mediaitem.py'
545--- openlp/plugins/images/lib/mediaitem.py 2017-10-23 22:09:57 +0000
546+++ openlp/plugins/images/lib/mediaitem.py 2017-11-10 23:08:30 +0000
547@@ -366,7 +366,7 @@
548 if validate_thumb(image.file_path, thumbnail_path):
549 icon = build_icon(thumbnail_path)
550 else:
551- icon = create_thumb(image.file_path, thumbnail_path)
552+ icon = create_thumb(str(image.file_path), str(thumbnail_path))
553 item_name = QtWidgets.QTreeWidgetItem([file_name])
554 item_name.setText(0, file_name)
555 item_name.setIcon(0, icon)
556@@ -390,6 +390,7 @@
557 :param files: A List of strings containing the filenames of the files to be loaded
558 :param target_group: The QTreeWidgetItem of the group that will be the parent of the added files
559 """
560+ file_paths = [Path(file) for file in file_paths]
561 self.application.set_normal_cursor()
562 self.load_list(file_paths, target_group)
563 last_dir = file_paths[0].parent
564
565=== modified file 'openlp/plugins/presentations/lib/pptviewcontroller.py'
566--- openlp/plugins/presentations/lib/pptviewcontroller.py 2017-10-10 07:08:44 +0000
567+++ openlp/plugins/presentations/lib/pptviewcontroller.py 2017-11-10 23:08:30 +0000
568@@ -70,7 +70,7 @@
569 try:
570 self.start_process()
571 return self.process.CheckInstalled()
572- except WindowsError:
573+ except OSError:
574 return False
575
576 def start_process(self):
577
578=== modified file 'openlp/plugins/songs/forms/editsongform.py'
579--- openlp/plugins/songs/forms/editsongform.py 2017-10-23 22:09:57 +0000
580+++ openlp/plugins/songs/forms/editsongform.py 2017-11-10 23:08:30 +0000
581@@ -105,9 +105,9 @@
582 self.topics_list_view.setSortingEnabled(False)
583 self.topics_list_view.setAlternatingRowColors(True)
584 self.audio_list_widget.setAlternatingRowColors(True)
585- self.find_verse_split = re.compile('---\[\]---\n', re.UNICODE)
586- self.whitespace = re.compile(r'\W+', re.UNICODE)
587- self.find_tags = re.compile(u'\{/?\w+\}', re.UNICODE)
588+ self.find_verse_split = re.compile('---\[\]---\n')
589+ self.whitespace = re.compile(r'\W+')
590+ self.find_tags = re.compile(r'\{/?\w+\}')
591
592 def _load_objects(self, cls, combo, cache):
593 """
594
595=== modified file 'openlp/plugins/songs/lib/__init__.py'
596--- openlp/plugins/songs/lib/__init__.py 2017-10-10 02:29:56 +0000
597+++ openlp/plugins/songs/lib/__init__.py 2017-11-10 23:08:30 +0000
598@@ -24,7 +24,6 @@
599 """
600
601 import logging
602-import os
603 import re
604
605 from PyQt5 import QtWidgets
606@@ -39,8 +38,8 @@
607
608 log = logging.getLogger(__name__)
609
610-WHITESPACE = re.compile(r'[\W_]+', re.UNICODE)
611-APOSTROPHE = re.compile('[\'`’ʻ′]', re.UNICODE)
612+WHITESPACE = re.compile(r'[\W_]+')
613+APOSTROPHE = re.compile(r'[\'`’ʻ′]')
614 # PATTERN will look for the next occurence of one of these symbols:
615 # \controlword - optionally preceded by \*, optionally followed by a number
616 # \'## - where ## is a pair of hex digits, representing a single character
617
618=== modified file 'openlp/plugins/songs/lib/importers/easyslides.py'
619--- openlp/plugins/songs/lib/importers/easyslides.py 2017-09-30 20:16:30 +0000
620+++ openlp/plugins/songs/lib/importers/easyslides.py 2017-11-10 23:08:30 +0000
621@@ -25,6 +25,7 @@
622
623 from lxml import etree, objectify
624
625+from openlp.core.common import normalize_str
626 from openlp.plugins.songs.lib import VerseType
627 from openlp.plugins.songs.lib.importers.songimport import SongImport
628
629@@ -225,7 +226,7 @@
630 verses[reg].setdefault(vt, {})
631 verses[reg][vt].setdefault(vn, {})
632 verses[reg][vt][vn].setdefault(inst, [])
633- verses[reg][vt][vn][inst].append(self.tidy_text(line))
634+ verses[reg][vt][vn][inst].append(normalize_str(line))
635 # done parsing
636 versetags = []
637 # we use our_verse_order to ensure, we insert lyrics in the same order
638
639=== modified file 'openlp/plugins/songs/lib/importers/mediashout.py'
640--- openlp/plugins/songs/lib/importers/mediashout.py 2017-10-07 07:05:07 +0000
641+++ openlp/plugins/songs/lib/importers/mediashout.py 2017-11-10 23:08:30 +0000
642@@ -101,7 +101,7 @@
643 self.song_book_name = song.SongID
644 for verse in verses:
645 tag = VERSE_TAGS[verse.Type] + str(verse.Number) if verse.Type < len(VERSE_TAGS) else 'O'
646- self.add_verse(self.tidy_text(verse.Text), tag)
647+ self.add_verse(verse.Text, tag)
648 for order in verse_order:
649 if order.Type < len(VERSE_TAGS):
650 self.verse_order_list.append(VERSE_TAGS[order.Type] + str(order.Number))
651
652=== modified file 'openlp/plugins/songs/lib/importers/openoffice.py'
653--- openlp/plugins/songs/lib/importers/openoffice.py 2017-10-10 02:29:56 +0000
654+++ openlp/plugins/songs/lib/importers/openoffice.py 2017-11-10 23:08:30 +0000
655@@ -24,7 +24,7 @@
656
657 from PyQt5 import QtCore
658
659-from openlp.core.common import is_win, get_uno_command, get_uno_instance
660+from openlp.core.common import get_uno_command, get_uno_instance, is_win, normalize_str
661 from openlp.core.common.i18n import translate
662 from .songimport import SongImport
663
664@@ -241,7 +241,7 @@
665
666 :param text: The text.
667 """
668- song_texts = self.tidy_text(text).split('\f')
669+ song_texts = normalize_str(text).split('\f')
670 self.set_defaults()
671 for song_text in song_texts:
672 if song_text.strip():
673
674=== modified file 'openlp/plugins/songs/lib/importers/opensong.py'
675--- openlp/plugins/songs/lib/importers/opensong.py 2017-10-10 02:29:56 +0000
676+++ openlp/plugins/songs/lib/importers/opensong.py 2017-11-10 23:08:30 +0000
677@@ -25,6 +25,7 @@
678 from lxml import objectify
679 from lxml.etree import Error, LxmlError
680
681+from openlp.core.common import normalize_str
682 from openlp.core.common.i18n import translate
683 from openlp.core.common.settings import Settings
684 from openlp.plugins.songs.lib import VerseType
685@@ -262,7 +263,7 @@
686 post=this_line[offset + column:])
687 offset += len(chord) + 2
688 # Tidy text and remove the ____s from extended words
689- this_line = self.tidy_text(this_line)
690+ this_line = normalize_str(this_line)
691 this_line = this_line.replace('_', '')
692 this_line = this_line.replace('||', '\n[---]\n')
693 this_line = this_line.strip()
694
695=== modified file 'openlp/plugins/songs/lib/importers/songimport.py'
696--- openlp/plugins/songs/lib/importers/songimport.py 2017-10-23 22:09:57 +0000
697+++ openlp/plugins/songs/lib/importers/songimport.py 2017-11-10 23:08:30 +0000
698@@ -25,6 +25,7 @@
699
700 from PyQt5 import QtCore
701
702+from openlp.core.common import normalize_str
703 from openlp.core.common.applocation import AppLocation
704 from openlp.core.common.i18n import translate
705 from openlp.core.common.path import copyfile, create_paths
706@@ -130,26 +131,6 @@
707 def register(self, import_wizard):
708 self.import_wizard = import_wizard
709
710- def tidy_text(self, text):
711- """
712- Get rid of some dodgy unicode and formatting characters we're not interested in. Some can be converted to ascii.
713- """
714- text = text.replace('\u2018', '\'')
715- text = text.replace('\u2019', '\'')
716- text = text.replace('\u201c', '"')
717- text = text.replace('\u201d', '"')
718- text = text.replace('\u2026', '...')
719- text = text.replace('\u2013', '-')
720- text = text.replace('\u2014', '-')
721- # Replace vertical tab with 2 linebreaks
722- text = text.replace('\v', '\n\n')
723- # Replace form feed (page break) with 2 linebreaks
724- text = text.replace('\f', '\n\n')
725- # Remove surplus blank lines, spaces, trailing/leading spaces
726- text = re.sub(r'[ \t]+', ' ', text)
727- text = re.sub(r' ?(\r\n?|\n) ?', '\n', text)
728- return text
729-
730 def process_song_text(self, text):
731 """
732 Process the song text from import
733@@ -368,7 +349,7 @@
734 verse_tag = VerseType.tags[VerseType.Other]
735 log.info('Versetype {old} changing to {new}'.format(old=verse_def, new=new_verse_def))
736 verse_def = new_verse_def
737- sxml.add_verse_to_lyrics(verse_tag, verse_def[1:], verse_text, lang)
738+ sxml.add_verse_to_lyrics(verse_tag, verse_def[1:], normalize_str(verse_text), lang)
739 song.lyrics = str(sxml.extract_xml(), 'utf-8')
740 if not self.verse_order_list and self.verse_order_list_generated_useful:
741 self.verse_order_list = self.verse_order_list_generated
742
743=== modified file 'openlp/plugins/songs/lib/importers/songsoffellowship.py'
744--- openlp/plugins/songs/lib/importers/songsoffellowship.py 2016-12-31 11:01:36 +0000
745+++ openlp/plugins/songs/lib/importers/songsoffellowship.py 2017-11-10 23:08:30 +0000
746@@ -194,7 +194,6 @@
747 :param text_portion: A Piece of text
748 """
749 text = text_portion.getString()
750- text = self.tidy_text(text)
751 if text.strip() == '':
752 return text
753 if text_portion.CharWeight == BOLD:
754
755=== modified file 'openlp/plugins/songs/lib/importers/zionworx.py'
756--- openlp/plugins/songs/lib/importers/zionworx.py 2017-10-10 02:29:56 +0000
757+++ openlp/plugins/songs/lib/importers/zionworx.py 2017-11-10 23:08:30 +0000
758@@ -30,9 +30,6 @@
759
760 log = logging.getLogger(__name__)
761
762-# Used to strip control chars (except 10=LF, 13=CR)
763-CONTROL_CHARS_MAP = dict.fromkeys(list(range(10)) + [11, 12] + list(range(14, 32)) + [127])
764-
765
766 class ZionWorxImport(SongImport):
767 """
768@@ -95,12 +92,12 @@
769 return
770 self.set_defaults()
771 try:
772- self.title = self._decode(record['Title1'])
773+ self.title = record['Title1']
774 if record['Title2']:
775- self.alternate_title = self._decode(record['Title2'])
776- self.parse_author(self._decode(record['Writer']))
777- self.add_copyright(self._decode(record['Copyright']))
778- lyrics = self._decode(record['Lyrics'])
779+ self.alternate_title = record['Title2']
780+ self.parse_author(record['Writer'])
781+ self.add_copyright(record['Copyright'])
782+ lyrics = record['Lyrics']
783 except UnicodeDecodeError as e:
784 self.log_error(translate('SongsPlugin.ZionWorxImport', 'Record {index}').format(index=index),
785 translate('SongsPlugin.ZionWorxImport', 'Decoding error: {error}').format(error=e))
786@@ -122,10 +119,3 @@
787 if not self.finish():
788 self.log_error(translate('SongsPlugin.ZionWorxImport', 'Record %d') % index +
789 (': "' + title + '"' if title else ''))
790-
791- def _decode(self, str):
792- """
793- Strips all control characters (except new lines).
794- """
795- # ZionWorx has no option for setting the encoding for its songs, so we assume encoding is always the same.
796- return str.translate(CONTROL_CHARS_MAP)
797
798=== modified file 'openlp/plugins/songs/lib/openlyricsxml.py'
799--- openlp/plugins/songs/lib/openlyricsxml.py 2017-10-10 02:29:56 +0000
800+++ openlp/plugins/songs/lib/openlyricsxml.py 2017-11-10 23:08:30 +0000
801@@ -281,7 +281,7 @@
802 # Process the formatting tags.
803 # Have we any tags in song lyrics?
804 tags_element = None
805- match = re.search('\{/?\w+\}', song.lyrics, re.UNICODE)
806+ match = re.search(r'\{/?\w+\}', song.lyrics)
807 if match:
808 # Named 'format_' - 'format' is built-in function in Python.
809 format_ = etree.SubElement(song_xml, 'format')
810
811=== modified file 'openlp/plugins/songusage/forms/songusagedetailform.py'
812--- openlp/plugins/songusage/forms/songusagedetailform.py 2017-10-23 22:09:57 +0000
813+++ openlp/plugins/songusage/forms/songusagedetailform.py 2017-11-10 23:08:30 +0000
814@@ -54,8 +54,14 @@
815 """
816 We need to set up the screen
817 """
818- self.from_date_calendar.setSelectedDate(Settings().value(self.plugin.settings_section + '/from date'))
819- self.to_date_calendar.setSelectedDate(Settings().value(self.plugin.settings_section + '/to date'))
820+ to_date = Settings().value(self.plugin.settings_section + '/to date')
821+ if not (isinstance(to_date, QtCore.QDate) and to_date.isValid()):
822+ to_date = QtCore.QDate.currentDate()
823+ from_date = Settings().value(self.plugin.settings_section + '/from date')
824+ if not (isinstance(from_date, QtCore.QDate) and from_date.isValid()):
825+ from_date = to_date.addYears(-1)
826+ self.from_date_calendar.setSelectedDate(from_date)
827+ self.to_date_calendar.setSelectedDate(to_date)
828 self.report_path_edit.path = Settings().value(self.plugin.settings_section + '/last directory export')
829
830 def on_report_path_edit_path_changed(self, file_path):
831
832=== modified file 'openlp/plugins/songusage/songusageplugin.py'
833--- openlp/plugins/songusage/songusageplugin.py 2017-10-07 07:05:07 +0000
834+++ openlp/plugins/songusage/songusageplugin.py 2017-11-10 23:08:30 +0000
835@@ -38,20 +38,17 @@
836
837 log = logging.getLogger(__name__)
838
839-YEAR = QtCore.QDate().currentDate().year()
840-if QtCore.QDate().currentDate().month() < 9:
841- YEAR -= 1
842-
843+TODAY = QtCore.QDate.currentDate()
844
845 __default_settings__ = {
846 'songusage/db type': 'sqlite',
847 'songusage/db username': '',
848- 'songuasge/db password': '',
849- 'songuasge/db hostname': '',
850- 'songuasge/db database': '',
851+ 'songusage/db password': '',
852+ 'songusage/db hostname': '',
853+ 'songusage/db database': '',
854 'songusage/active': False,
855- 'songusage/to date': QtCore.QDate(YEAR, 8, 31),
856- 'songusage/from date': QtCore.QDate(YEAR - 1, 9, 1),
857+ 'songusage/to date': TODAY,
858+ 'songusage/from date': TODAY.addYears(-1),
859 'songusage/last directory export': None
860 }
861
862
863=== modified file 'tests/functional/openlp_core/common/test_actions.py'
864--- tests/functional/openlp_core/common/test_actions.py 2017-10-07 07:05:07 +0000
865+++ tests/functional/openlp_core/common/test_actions.py 2017-11-10 23:08:30 +0000
866@@ -153,6 +153,7 @@
867 """
868 Prepare the tests
869 """
870+ self.setup_application()
871 self.action_list = ActionList.get_instance()
872 self.build_settings()
873 self.settings = Settings()
874
875=== modified file 'tests/functional/openlp_core/common/test_httputils.py'
876--- tests/functional/openlp_core/common/test_httputils.py 2017-09-25 20:34:05 +0000
877+++ tests/functional/openlp_core/common/test_httputils.py 2017-11-10 23:08:30 +0000
878@@ -233,7 +233,7 @@
879 Test socket timeout gets caught
880 """
881 # GIVEN: Mocked urlopen to fake a network disconnect in the middle of a download
882- mocked_requests.get.side_effect = IOError
883+ mocked_requests.get.side_effect = OSError
884
885 # WHEN: Attempt to retrieve a file
886 url_get_file(MagicMock(), url='http://localhost/test', file_path=Path(self.tempfile))
887
888=== modified file 'tests/functional/openlp_core/common/test_i18n.py'
889--- tests/functional/openlp_core/common/test_i18n.py 2017-10-07 07:05:07 +0000
890+++ tests/functional/openlp_core/common/test_i18n.py 2017-11-10 23:08:30 +0000
891@@ -155,7 +155,7 @@
892 assert first_instance is second_instance, 'Two UiStrings objects should be the same instance'
893
894
895-def test_translate(self):
896+def test_translate():
897 """
898 Test the translate() function
899 """
900
901=== modified file 'tests/functional/openlp_core/common/test_path.py'
902--- tests/functional/openlp_core/common/test_path.py 2017-10-07 07:05:07 +0000
903+++ tests/functional/openlp_core/common/test_path.py 2017-11-10 23:08:30 +0000
904@@ -371,13 +371,13 @@
905 @patch('openlp.core.common.path.log')
906 def test_create_paths_dir_io_error(self, mocked_logger):
907 """
908- Test the create_paths() when an IOError is raised
909+ Test the create_paths() when an OSError is raised
910 """
911 # GIVEN: A `Path` to check with patched out mkdir and exists methods
912 mocked_path = MagicMock()
913- mocked_path.exists.side_effect = IOError('Cannot make directory')
914+ mocked_path.exists.side_effect = OSError('Cannot make directory')
915
916- # WHEN: An IOError is raised when checking the if the path exists.
917+ # WHEN: An OSError is raised when checking the if the path exists.
918 create_paths(mocked_path)
919
920 # THEN: The Error should have been logged
921@@ -385,7 +385,7 @@
922
923 def test_create_paths_dir_value_error(self):
924 """
925- Test the create_paths() when an error other than IOError is raised
926+ Test the create_paths() when an error other than OSError is raised
927 """
928 # GIVEN: A `Path` to check with patched out mkdir and exists methods
929 mocked_path = MagicMock()
930
931=== modified file 'tests/functional/openlp_core/lib/test_lib.py'
932--- tests/functional/openlp_core/lib/test_lib.py 2017-10-10 07:08:44 +0000
933+++ tests/functional/openlp_core/lib/test_lib.py 2017-11-10 23:08:30 +0000
934@@ -168,7 +168,7 @@
935 patch.object(Path, 'open'):
936 file_path = Path('testfile.txt')
937 file_path.is_file.return_value = True
938- file_path.open.side_effect = IOError()
939+ file_path.open.side_effect = OSError()
940
941 # WHEN: get_text_file_string is called
942 result = get_text_file_string(file_path)
943
944=== modified file 'tests/functional/openlp_core/ui/test_first_time.py'
945--- tests/functional/openlp_core/ui/test_first_time.py 2017-09-20 16:55:21 +0000
946+++ tests/functional/openlp_core/ui/test_first_time.py 2017-11-10 23:08:30 +0000
947@@ -40,7 +40,7 @@
948 Test get_web_page will attempt CONNECTION_RETRIES+1 connections - bug 1409031
949 """
950 # GIVEN: Initial settings and mocks
951- mocked_requests.get.side_effect = IOError('Unable to connect')
952+ mocked_requests.get.side_effect = OSError('Unable to connect')
953
954 # WHEN: A webpage is requested
955 try:
956
957=== modified file 'tests/functional/openlp_core/widgets/test_views.py'
958--- tests/functional/openlp_core/widgets/test_views.py 2017-10-23 22:09:57 +0000
959+++ tests/functional/openlp_core/widgets/test_views.py 2017-11-10 23:08:30 +0000
960@@ -627,4 +627,3 @@
961 assert widget.allow_internal_dnd is False
962 assert widget.indentation() == 0
963 assert widget.isAnimated() is True
964-
965
966=== modified file 'tests/functional/openlp_plugins/presentations/test_presentationcontroller.py'
967--- tests/functional/openlp_plugins/presentations/test_presentationcontroller.py 2017-10-07 07:05:07 +0000
968+++ tests/functional/openlp_plugins/presentations/test_presentationcontroller.py 2017-11-10 23:08:30 +0000
969@@ -144,7 +144,7 @@
970 # GIVEN: A mocked open, get_thumbnail_folder and exists
971 with patch('openlp.plugins.presentations.lib.presentationcontroller.Path.read_text') as mocked_read_text, \
972 patch(FOLDER_TO_PATCH) as mocked_get_thumbnail_folder:
973- mocked_read_text.side_effect = IOError()
974+ mocked_read_text.side_effect = OSError()
975 mocked_get_thumbnail_folder.return_value = Path('test')
976
977 # WHEN: calling get_titles_and_notes
978
979=== modified file 'tests/interfaces/openlp_core/ui/test_projectormanager.py'
980--- tests/interfaces/openlp_core/ui/test_projectormanager.py 2017-10-07 07:05:07 +0000
981+++ tests/interfaces/openlp_core/ui/test_projectormanager.py 2017-11-10 23:08:30 +0000
982@@ -42,8 +42,8 @@
983 """
984 Create the UI and setup necessary options
985 """
986+ self.setup_application()
987 self.build_settings()
988- self.setup_application()
989 Registry.create()
990 with patch('openlp.core.lib.projector.db.init_url') as mocked_init_url:
991 if os.path.exists(TEST_DB):
992
993=== modified file 'tests/interfaces/openlp_core/ui/test_projectorsourceform.py'
994--- tests/interfaces/openlp_core/ui/test_projectorsourceform.py 2017-10-07 07:05:07 +0000
995+++ tests/interfaces/openlp_core/ui/test_projectorsourceform.py 2017-11-10 23:08:30 +0000
996@@ -64,8 +64,8 @@
997 Set up anything necessary for all tests
998 """
999 mocked_init_url.return_value = 'sqlite:///{}'.format(TEST_DB)
1000+ self.setup_application()
1001 self.build_settings()
1002- self.setup_application()
1003 Registry.create()
1004 # Do not try to recreate if we've already been created from a previous test
1005 if not hasattr(self, 'projectordb'):
1006
1007=== modified file 'tests/interfaces/openlp_core/ui/test_thememanager.py'
1008--- tests/interfaces/openlp_core/ui/test_thememanager.py 2017-10-10 01:08:09 +0000
1009+++ tests/interfaces/openlp_core/ui/test_thememanager.py 2017-11-10 23:08:30 +0000
1010@@ -41,8 +41,8 @@
1011 """
1012 Create the UI
1013 """
1014+ self.setup_application()
1015 self.build_settings()
1016- self.setup_application()
1017 Registry.create()
1018 self.theme_manager = ThemeManager()
1019
1020
1021=== modified file 'tests/utils/__init__.py'
1022--- tests/utils/__init__.py 2016-12-31 11:01:36 +0000
1023+++ tests/utils/__init__.py 2017-11-10 23:08:30 +0000
1024@@ -36,7 +36,7 @@
1025 try:
1026 items = json.load(open_file)
1027 first_line = items[row]
1028- except IOError:
1029+ except OSError:
1030 first_line = ''
1031 finally:
1032 open_file.close()
1033
1034=== modified file 'tests/utils/test_pylint.py'
1035--- tests/utils/test_pylint.py 2016-12-31 11:01:36 +0000
1036+++ tests/utils/test_pylint.py 2017-11-10 23:08:30 +0000
1037@@ -58,17 +58,21 @@
1038 # GIVEN: Some checks to disable and enable, and the pylint script
1039 disabled_checks = 'import-error,no-member'
1040 enabled_checks = 'missing-format-argument-key,unused-format-string-argument,bad-format-string'
1041- if is_win() or 'arch' in platform.dist()[0].lower():
1042- pylint_script = 'pylint'
1043- else:
1044- pylint_script = 'pylint3'
1045+ pylint_kwargs = {
1046+ 'return_std': True
1047+ }
1048+ if version < '1.7.0':
1049+ if is_win() or 'arch' in platform.dist()[0].lower():
1050+ pylint_kwargs.update({'script': 'pylint'})
1051+ else:
1052+ pylint_kwargs.update({'script': 'pylint3'})
1053
1054 # WHEN: Running pylint
1055 (pylint_stdout, pylint_stderr) = \
1056 lint.py_run('openlp --errors-only --disable={disabled} --enable={enabled} '
1057 '--reports=no --output-format=parseable'.format(disabled=disabled_checks,
1058 enabled=enabled_checks),
1059- return_std=True, script=pylint_script)
1060+ **pylint_kwargs)
1061 stdout = pylint_stdout.read()
1062 stderr = pylint_stderr.read()
1063 filtered_stdout = self._filter_tolerated_errors(stdout)