Merge lp:~tomasgroth/openlp/bugfixes16 into lp:openlp

Proposed by Tomas Groth
Status: Merged
Approved by: Tim Bentley
Approved revision: 2526
Merged at revision: 2521
Proposed branch: lp:~tomasgroth/openlp/bugfixes16
Merge into: lp:openlp
Diff against target: 441 lines (+114/-39)
15 files modified
openlp/core/ui/formattingtagcontroller.py (+2/-2)
openlp/core/ui/servicemanager.py (+1/-1)
openlp/core/ui/slidecontroller.py (+2/-2)
openlp/plugins/alerts/lib/alertsmanager.py (+2/-2)
openlp/plugins/bibles/lib/opensong.py (+2/-2)
openlp/plugins/bibles/lib/osis.py (+6/-5)
openlp/plugins/bibles/lib/zefania.py (+4/-3)
openlp/plugins/presentations/lib/mediaitem.py (+13/-4)
openlp/plugins/presentations/lib/presentationcontroller.py (+6/-6)
openlp/plugins/presentations/presentationplugin.py (+1/-1)
openlp/plugins/songs/lib/importers/worshipassistant.py (+2/-2)
openlp/plugins/songs/lib/importers/zionworx.py (+2/-2)
scripts/translation_utils.py (+41/-0)
tests/functional/openlp_plugins/presentations/test_mediaitem.py (+24/-1)
tests/functional/openlp_plugins/presentations/test_presentationcontroller.py (+6/-6)
To merge this branch: bzr merge lp:~tomasgroth/openlp/bugfixes16
Reviewer Review Type Date Requested Status
Tim Bentley Approve
Raoul Snyman Approve
Review via email: mp+252543@code.launchpad.net

Description of the change

Only update presentation thumbnails if needed. Fixes bug 1424330.
Make presentation controller save and read notes and titles in utf-8 encoding. Fixes bug 1424972.
Moved string format input outside calls to translate. Fixes bug 1425035.
Added option for check of format input strings in translation util script.
Removed tab from text since transifex cannot handle it.
Some PEP8 fixes (from pep8 1.6.1)
Use the language id when importing bibles.

To post a comment you must log in.
Revision history for this message
Tomas Groth (tomasgroth) wrote :

lp:~tomasgroth/openlp/bugfixes16 (revision 2526)
[SUCCESS] https//ci.openlp.io/job/Branch-01-Pull/993/
[SUCCESS] https//ci.openlp.io/job/Branch-02-Functional-Tests/916/
[SUCCESS] https//ci.openlp.io/job/Branch-03-Interface-Tests/858/
[SUCCESS] https//ci.openlp.io/job/Branch-04a-Windows_Functional_Tests/747/
[SUCCESS] https//ci.openlp.io/job/Branch-04b-Windows_Interface_Tests/346/
[SUCCESS] https//ci.openlp.io/job/Branch-05a-Code_Analysis/483/
[SUCCESS] https//ci.openlp.io/job/Branch-05b-Test_Coverage/354/

Revision history for this message
Raoul Snyman (raoul-snyman) wrote :

This looks OK to me

review: Approve
Revision history for this message
Tim Bentley (trb143) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openlp/core/ui/formattingtagcontroller.py'
2--- openlp/core/ui/formattingtagcontroller.py 2015-01-18 13:39:21 +0000
3+++ openlp/core/ui/formattingtagcontroller.py 2015-03-11 08:46:59 +0000
4@@ -146,7 +146,7 @@
5 end = self.start_html_to_end_html(start_html)
6 if not end_html:
7 if not end:
8- return translate('OpenLP.FormattingTagForm', 'Start tag %s is not valid HTML' % start_html), None
9+ return translate('OpenLP.FormattingTagForm', 'Start tag %s is not valid HTML') % start_html, None
10 return None, end
11 return None, None
12
13@@ -166,5 +166,5 @@
14 return None, end
15 if end and end != end_html:
16 return translate('OpenLP.FormattingTagForm',
17- 'End tag %s does not match end tag for start tag %s' % (end, start_html)), None
18+ 'End tag %s does not match end tag for start tag %s') % (end, start_html), None
19 return None, None
20
21=== modified file 'openlp/core/ui/servicemanager.py'
22--- openlp/core/ui/servicemanager.py 2015-02-10 22:25:30 +0000
23+++ openlp/core/ui/servicemanager.py 2015-03-11 08:46:59 +0000
24@@ -533,7 +533,7 @@
25 self.application.set_normal_cursor()
26 title = translate('OpenLP.ServiceManager', 'Service File(s) Missing')
27 message = translate('OpenLP.ServiceManager',
28- 'The following file(s) in the service are missing:\n\t%s\n\n'
29+ 'The following file(s) in the service are missing: %s\n\n'
30 'These files will be removed if you continue to save.') % "\n\t".join(missing_list)
31 answer = QtGui.QMessageBox.critical(self, title, message,
32 QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok |
33
34=== modified file 'openlp/core/ui/slidecontroller.py'
35--- openlp/core/ui/slidecontroller.py 2015-02-16 21:59:55 +0000
36+++ openlp/core/ui/slidecontroller.py 2015-03-11 08:46:59 +0000
37@@ -717,8 +717,8 @@
38 self.play_slides_loop.setChecked(False)
39 self.play_slides_loop.setIcon(build_icon(':/media/media_time.png'))
40 if item.is_text():
41- if (Settings().value(self.main_window.songs_settings_section + '/display songbar')
42- and not self.song_menu.menu().isEmpty()):
43+ if (Settings().value(self.main_window.songs_settings_section + '/display songbar') and
44+ not self.song_menu.menu().isEmpty()):
45 self.toolbar.set_widget_visible(['song_menu'], True)
46 if item.is_capable(ItemCapabilities.CanLoop) and len(item.get_frames()) > 1:
47 self.toolbar.set_widget_visible(LOOP_LIST)
48
49=== modified file 'openlp/plugins/alerts/lib/alertsmanager.py'
50--- openlp/plugins/alerts/lib/alertsmanager.py 2015-02-27 23:02:19 +0000
51+++ openlp/plugins/alerts/lib/alertsmanager.py 2015-03-11 08:46:59 +0000
52@@ -70,8 +70,8 @@
53 """
54 Format and request the Alert and start the timer.
55 """
56- if not self.alert_list or (self.live_controller.display.screens.display_count == 1
57- and not Settings().value('core/display on monitor')):
58+ if not self.alert_list or (self.live_controller.display.screens.display_count == 1 and
59+ not Settings().value('core/display on monitor')):
60 return
61 text = self.alert_list.pop(0)
62 alert_tab = self.parent().settings_tab
63
64=== modified file 'openlp/plugins/bibles/lib/opensong.py'
65--- openlp/plugins/bibles/lib/opensong.py 2015-01-18 13:39:21 +0000
66+++ openlp/plugins/bibles/lib/opensong.py 2015-03-11 08:46:59 +0000
67@@ -123,8 +123,8 @@
68 verse_number += 1
69 self.create_verse(db_book.id, chapter_number, verse_number, self.get_text(verse))
70 self.wizard.increment_progress_bar(
71- translate('BiblesPlugin.Opensong', 'Importing %(bookname)s %(chapter)s...' %
72- {'bookname': db_book.name, 'chapter': chapter_number}))
73+ translate('BiblesPlugin.Opensong', 'Importing %(bookname)s %(chapter)s...') %
74+ {'bookname': db_book.name, 'chapter': chapter_number})
75 self.session.commit()
76 self.application.process_events()
77 except etree.XMLSyntaxError as inst:
78
79=== modified file 'openlp/plugins/bibles/lib/osis.py'
80--- openlp/plugins/bibles/lib/osis.py 2015-02-02 20:40:31 +0000
81+++ openlp/plugins/bibles/lib/osis.py 2015-03-11 08:46:59 +0000
82@@ -71,6 +71,7 @@
83 if not language_id:
84 log.error('Importing books from "%s" failed' % self.filename)
85 return False
86+ self.save_meta('language_id', language_id)
87 num_books = int(osis_bible_tree.xpath("count(//ns:div[@type='book'])", namespaces=namespace))
88 self.wizard.increment_progress_bar(translate('BiblesPlugin.OsisImport',
89 'Removing unused tags (this may take a few minutes)...'))
90@@ -124,7 +125,7 @@
91 break
92 # Remove div-tags in the book
93 etree.strip_tags(book, ('{http://www.bibletechnologies.net/2003/OSIS/namespace}div'))
94- book_ref_id = self.get_book_ref_id_by_name(book.get('osisID'), num_books)
95+ book_ref_id = self.get_book_ref_id_by_name(book.get('osisID'), num_books, language_id)
96 if not book_ref_id:
97 book_ref_id = self.get_book_ref_id_by_localised_name(book.get('osisID'))
98 if not book_ref_id:
99@@ -154,8 +155,8 @@
100 verse_number = verse.get("osisID").split('.')[2]
101 self.create_verse(db_book.id, chapter_number, verse_number, verse.text.strip())
102 self.wizard.increment_progress_bar(
103- translate('BiblesPlugin.OsisImport', 'Importing %(bookname)s %(chapter)s...' %
104- {'bookname': db_book.name, 'chapter': chapter_number}))
105+ translate('BiblesPlugin.OsisImport', 'Importing %(bookname)s %(chapter)s...') %
106+ {'bookname': db_book.name, 'chapter': chapter_number})
107 else:
108 # The chapter tags is used as milestones. For now we assume verses is also milestones
109 chapter_number = 0
110@@ -164,8 +165,8 @@
111 and element.get('sID'):
112 chapter_number = element.get("osisID").split('.')[1]
113 self.wizard.increment_progress_bar(
114- translate('BiblesPlugin.OsisImport', 'Importing %(bookname)s %(chapter)s...' %
115- {'bookname': db_book.name, 'chapter': chapter_number}))
116+ translate('BiblesPlugin.OsisImport', 'Importing %(bookname)s %(chapter)s...') %
117+ {'bookname': db_book.name, 'chapter': chapter_number})
118 elif element.tag == '{http://www.bibletechnologies.net/2003/OSIS/namespace}verse' \
119 and element.get('sID'):
120 # If this tag marks the start of a verse, the verse text is between this tag and
121
122=== modified file 'openlp/plugins/bibles/lib/zefania.py'
123--- openlp/plugins/bibles/lib/zefania.py 2015-02-02 20:40:31 +0000
124+++ openlp/plugins/bibles/lib/zefania.py 2015-03-11 08:46:59 +0000
125@@ -69,6 +69,7 @@
126 if not language_id:
127 log.error('Importing books from "%s" failed' % self.filename)
128 return False
129+ self.save_meta('language_id', language_id)
130 num_books = int(zefania_bible_tree.xpath("count(//BIBLEBOOK)"))
131 # Strip tags we don't use - keep content
132 etree.strip_tags(zefania_bible_tree, ('STYLE', 'GRAM', 'NOTE', 'SUP', 'XREF'))
133@@ -83,7 +84,7 @@
134 if not bname and not bnumber:
135 continue
136 if bname:
137- book_ref_id = self.get_book_ref_id_by_name(bname, num_books)
138+ book_ref_id = self.get_book_ref_id_by_name(bname, num_books, language_id)
139 if not book_ref_id:
140 book_ref_id = self.get_book_ref_id_by_localised_name(bname)
141 else:
142@@ -102,8 +103,8 @@
143 verse_number = VERS.get("vnumber")
144 self.create_verse(db_book.id, chapter_number, verse_number, VERS.text.replace('<BR/>', '\n'))
145 self.wizard.increment_progress_bar(
146- translate('BiblesPlugin.Zefnia', 'Importing %(bookname)s %(chapter)s...' %
147- {'bookname': db_book.name, 'chapter': chapter_number}))
148+ translate('BiblesPlugin.Zefnia', 'Importing %(bookname)s %(chapter)s...') %
149+ {'bookname': db_book.name, 'chapter': chapter_number})
150 self.session.commit()
151 self.application.process_events()
152 except Exception as e:
153
154=== modified file 'openlp/plugins/presentations/lib/mediaitem.py'
155--- openlp/plugins/presentations/lib/mediaitem.py 2015-01-27 14:59:06 +0000
156+++ openlp/plugins/presentations/lib/mediaitem.py 2015-03-11 08:46:59 +0000
157@@ -230,17 +230,26 @@
158 Settings().setValue(self.settings_section + '/presentations files', self.get_file_list())
159 self.application.set_normal_cursor()
160
161- def clean_up_thumbnails(self, filepath):
162+ def clean_up_thumbnails(self, filepath, clean_for_update=False):
163 """
164 Clean up the files created such as thumbnails
165
166 :param filepath: File path of the presention to clean up after
167+ :param clean_for_update: Only clean thumbnails if update is needed
168 :return: None
169 """
170 for cidx in self.controllers:
171- doc = self.controllers[cidx].add_document(filepath)
172- doc.presentation_deleted()
173- doc.close_presentation()
174+ root, file_ext = os.path.splitext(filepath)
175+ file_ext = file_ext[1:]
176+ if file_ext in self.controllers[cidx].supports or file_ext in self.controllers[cidx].also_supports:
177+ doc = self.controllers[cidx].add_document(filepath)
178+ if clean_for_update:
179+ thumb_path = doc.get_thumbnail_path(1, True)
180+ if not thumb_path or os.path.getmtime(thumb_path) < os.path.getmtime(filepath):
181+ doc.presentation_deleted()
182+ else:
183+ doc.presentation_deleted()
184+ doc.close_presentation()
185
186 def generate_slide_data(self, service_item, item=None, xml_version=False, remote=False,
187 context=ServiceItemContext.Service, presentation_file=None):
188
189=== modified file 'openlp/plugins/presentations/lib/presentationcontroller.py'
190--- openlp/plugins/presentations/lib/presentationcontroller.py 2015-02-10 21:01:22 +0000
191+++ openlp/plugins/presentations/lib/presentationcontroller.py 2015-03-11 08:46:59 +0000
192@@ -132,7 +132,7 @@
193 """
194 The location where thumbnail images will be stored
195 """
196- # TODO: If statment can be removed when the upgrade path from 2.0.x to 2.2.x is no longer needed
197+ # TODO: If statement can be removed when the upgrade path from 2.0.x to 2.2.x is no longer needed
198 if Settings().value('presentations/thumbnail_scheme') == 'md5':
199 folder = md5_hash(self.file_path.encode('utf-8'))
200 else:
201@@ -143,7 +143,7 @@
202 """
203 The location where thumbnail images will be stored
204 """
205- # TODO: If statment can be removed when the upgrade path from 2.0.x to 2.2.x is no longer needed
206+ # TODO: If statement can be removed when the upgrade path from 2.0.x to 2.2.x is no longer needed
207 if Settings().value('presentations/thumbnail_scheme') == 'md5':
208 folder = md5_hash(self.file_path.encode('utf-8'))
209 else:
210@@ -306,7 +306,7 @@
211 titles_file = os.path.join(self.get_thumbnail_folder(), 'titles.txt')
212 if os.path.exists(titles_file):
213 try:
214- with open(titles_file) as fi:
215+ with open(titles_file, encoding='utf-8') as fi:
216 titles = fi.read().splitlines()
217 except:
218 log.exception('Failed to open/read existing titles file')
219@@ -316,7 +316,7 @@
220 note = ''
221 if os.path.exists(notes_file):
222 try:
223- with open(notes_file) as fn:
224+ with open(notes_file, encoding='utf-8') as fn:
225 note = fn.read()
226 except:
227 log.exception('Failed to open/read notes file')
228@@ -331,12 +331,12 @@
229 """
230 if titles:
231 titles_file = os.path.join(self.get_thumbnail_folder(), 'titles.txt')
232- with open(titles_file, mode='w') as fo:
233+ with open(titles_file, mode='wt', encoding='utf-8') as fo:
234 fo.writelines(titles)
235 if notes:
236 for slide_no, note in enumerate(notes, 1):
237 notes_file = os.path.join(self.get_thumbnail_folder(), 'slideNotes%d.txt' % slide_no)
238- with open(notes_file, mode='w') as fn:
239+ with open(notes_file, mode='wt', encoding='utf-8') as fn:
240 fn.write(note)
241
242
243
244=== modified file 'openlp/plugins/presentations/presentationplugin.py'
245--- openlp/plugins/presentations/presentationplugin.py 2015-01-27 19:57:09 +0000
246+++ openlp/plugins/presentations/presentationplugin.py 2015-03-11 08:46:59 +0000
247@@ -144,7 +144,7 @@
248 files_from_config = Settings().value('presentations/presentations files')
249 for file in files_from_config:
250 try:
251- self.media_item.clean_up_thumbnails(file)
252+ self.media_item.clean_up_thumbnails(file, True)
253 except AttributeError:
254 pass
255 self.media_item.list_view.clear()
256
257=== modified file 'openlp/plugins/songs/lib/importers/worshipassistant.py'
258--- openlp/plugins/songs/lib/importers/worshipassistant.py 2015-01-18 13:39:21 +0000
259+++ openlp/plugins/songs/lib/importers/worshipassistant.py 2015-03-11 08:46:59 +0000
260@@ -179,6 +179,6 @@
261 cleaned_verse_order_list.append(verse)
262 self.verse_order_list = cleaned_verse_order_list
263 if not self.finish():
264- self.log_error(translate('SongsPlugin.WorshipAssistantImport', 'Record %d') % index
265- + (': "' + self.title + '"' if self.title else ''))
266+ self.log_error(translate('SongsPlugin.WorshipAssistantImport', 'Record %d') % index +
267+ (': "' + self.title + '"' if self.title else ''))
268 songs_file.close()
269
270=== modified file 'openlp/plugins/songs/lib/importers/zionworx.py'
271--- openlp/plugins/songs/lib/importers/zionworx.py 2015-01-18 13:39:21 +0000
272+++ openlp/plugins/songs/lib/importers/zionworx.py 2015-03-11 08:46:59 +0000
273@@ -118,8 +118,8 @@
274 self.add_verse(verse)
275 title = self.title
276 if not self.finish():
277- self.log_error(translate('SongsPlugin.ZionWorxImport', 'Record %d') % index
278- + (': "' + title + '"' if title else ''))
279+ self.log_error(translate('SongsPlugin.ZionWorxImport', 'Record %d') % index +
280+ (': "' + title + '"' if title else ''))
281
282 def _decode(self, str):
283 """
284
285=== modified file 'scripts/translation_utils.py'
286--- scripts/translation_utils.py 2015-01-22 18:40:12 +0000
287+++ scripts/translation_utils.py 2015-03-11 08:46:59 +0000
288@@ -53,7 +53,9 @@
289 import base64
290 import json
291 import webbrowser
292+import glob
293
294+from lxml import etree, objectify
295 from optparse import OptionParser
296 from PyQt4 import QtCore
297
298@@ -76,6 +78,7 @@
299 Prepare = 3
300 Update = 4
301 Generate = 5
302+ Check = 6
303
304
305 class CommandStack(object):
306@@ -292,6 +295,38 @@
307 print_quiet('Opening browser to OpenLP project...')
308
309
310+def check_format_strings():
311+ """
312+ This method runs through the ts-files and looks for mismatches between format strings in the original text
313+ and in the translations.
314+ """
315+ path = os.path.join(os.path.abspath('..'), 'resources', 'i18n', '*.ts')
316+ file_list = glob.glob(path)
317+ for filename in file_list:
318+ print_quiet('Checking %s' % filename)
319+ file = open(filename, 'rb')
320+ tree = objectify.parse(file)
321+ root = tree.getroot()
322+ for tag in root.iter('message'):
323+ location = tag.location.get('filename')
324+ line = tag.location.get('line')
325+ org_text = tag.source.text
326+ translation = tag.translation.text
327+ if not translation:
328+ for num in tag.iter('numerusform'):
329+ print_verbose('parsed numerusform: location: %s, source: %s, translation: %s' % (
330+ location, org_text, num.text))
331+ if num and org_text.count('%') != num.text.count('%'):
332+ print_quiet(
333+ 'ERROR: Translation from %s at line %s has a mismatch of format input:\n%s\n%s\n' % (
334+ location, line, org_text, num.text))
335+ else:
336+ print_verbose('parsed: location: %s, source: %s, translation: %s' % (location, org_text, translation))
337+ if org_text.count('%') != translation.count('%'):
338+ print_quiet('ERROR: Translation from %s at line %s has a mismatch of format input:\n%s\n%s\n' % (
339+ location, line, org_text, translation))
340+
341+
342 def process_stack(command_stack):
343 """
344 This method looks at the commands in the command stack, and processes them
345@@ -315,6 +350,8 @@
346 generate_binaries()
347 elif command == Command.Create:
348 create_translation()
349+ elif command == Command.Check:
350+ check_format_strings()
351 print_quiet('Finished processing commands.')
352 else:
353 print_quiet('No commands to process.')
354@@ -345,6 +382,8 @@
355 help='show extra information while processing translations')
356 parser.add_option('-q', '--quiet', dest='quiet', action='store_true',
357 help='suppress all output other than errors')
358+ parser.add_option('-f', '--check-format-strings', dest='check', action='store_true',
359+ help='check that format strings are matching in translations')
360 (options, args) = parser.parse_args()
361 # Create and populate the command stack
362 command_stack = CommandStack()
363@@ -358,6 +397,8 @@
364 command_stack.append(Command.Update)
365 if options.generate:
366 command_stack.append(Command.Generate)
367+ if options.check:
368+ command_stack.append(Command.Check)
369 verbose_mode = options.verbose
370 quiet_mode = options.quiet
371 if options.username:
372
373=== modified file 'tests/functional/openlp_plugins/presentations/test_mediaitem.py'
374--- tests/functional/openlp_plugins/presentations/test_mediaitem.py 2015-01-18 13:39:21 +0000
375+++ tests/functional/openlp_plugins/presentations/test_mediaitem.py 2015-03-11 08:46:59 +0000
376@@ -26,7 +26,7 @@
377
378 from openlp.core.common import Registry
379 from openlp.plugins.presentations.lib.mediaitem import PresentationMediaItem
380-from tests.functional import patch, MagicMock
381+from tests.functional import patch, MagicMock, call
382 from tests.helpers.testmixin import TestMixin
383
384
385@@ -84,3 +84,26 @@
386 self.assertIn('*.pdf', self.media_item.on_new_file_masks, 'The file mask should contain the pdf extension')
387 self.assertIn('*.xps', self.media_item.on_new_file_masks, 'The file mask should contain the xps extension')
388 self.assertIn('*.oxps', self.media_item.on_new_file_masks, 'The file mask should contain the oxps extension')
389+
390+ def clean_up_thumbnails_test(self):
391+ """
392+ Test that the clean_up_thumbnails method works as expected.
393+ """
394+ # GIVEN: A mocked controller, and mocked os.path.getmtime
395+ mocked_controller = MagicMock()
396+ mocked_doc = MagicMock()
397+ mocked_controller.add_document.return_value = mocked_doc
398+ mocked_controller.supports = ['tmp']
399+ self.media_item.controllers = {
400+ 'Mocked': mocked_controller
401+ }
402+ presentation_file = 'file.tmp'
403+ with patch('openlp.plugins.presentations.lib.mediaitem.os.path.getmtime') as mocked_getmtime:
404+ mocked_getmtime.side_effect = [100, 200]
405+
406+ # WHEN: calling clean_up_thumbnails
407+ self.media_item.clean_up_thumbnails(presentation_file, True)
408+
409+ # THEN: doc.presentation_deleted should have been called since the thumbnails mtime will be greater than
410+ # the presentation_file's mtime.
411+ mocked_doc.assert_has_calls([call.get_thumbnail_path(1, True), call.presentation_deleted()], True)
412
413=== modified file 'tests/functional/openlp_plugins/presentations/test_presentationcontroller.py'
414--- tests/functional/openlp_plugins/presentations/test_presentationcontroller.py 2015-01-18 13:39:21 +0000
415+++ tests/functional/openlp_plugins/presentations/test_presentationcontroller.py 2015-03-11 08:46:59 +0000
416@@ -81,9 +81,9 @@
417 self.document.save_titles_and_notes(titles, notes)
418
419 # THEN: the last call to open should have been for slideNotes2.txt
420- mocked_open.assert_any_call(os.path.join('test', 'titles.txt'), mode='w')
421- mocked_open.assert_any_call(os.path.join('test', 'slideNotes1.txt'), mode='w')
422- mocked_open.assert_any_call(os.path.join('test', 'slideNotes2.txt'), mode='w')
423+ mocked_open.assert_any_call(os.path.join('test', 'titles.txt'), mode='wt', encoding='utf-8')
424+ mocked_open.assert_any_call(os.path.join('test', 'slideNotes1.txt'), mode='wt', encoding='utf-8')
425+ mocked_open.assert_any_call(os.path.join('test', 'slideNotes2.txt'), mode='wt', encoding='utf-8')
426 self.assertEqual(mocked_open.call_count, 3, 'There should be exactly three files opened')
427 mocked_open().writelines.assert_called_once_with(['uno', 'dos'])
428 mocked_open().write.assert_called_any('one')
429@@ -126,9 +126,9 @@
430 self.assertIs(type(result_notes), list, 'result_notes should be of type list')
431 self.assertEqual(len(result_notes), 2, 'There should be two items in the notes')
432 self.assertEqual(mocked_open.call_count, 3, 'Three files should be opened')
433- mocked_open.assert_any_call(os.path.join('test', 'titles.txt'))
434- mocked_open.assert_any_call(os.path.join('test', 'slideNotes1.txt'))
435- mocked_open.assert_any_call(os.path.join('test', 'slideNotes2.txt'))
436+ mocked_open.assert_any_call(os.path.join('test', 'titles.txt'), encoding='utf-8')
437+ mocked_open.assert_any_call(os.path.join('test', 'slideNotes1.txt'), encoding='utf-8')
438+ mocked_open.assert_any_call(os.path.join('test', 'slideNotes2.txt'), encoding='utf-8')
439 self.assertEqual(mocked_exists.call_count, 3, 'Three files should have been checked')
440
441 def get_titles_and_notes_with_file_not_found_test(self):