Status: | Merged |
---|---|
Approved by: | Tim Bentley |
Approved revision: | 2777 |
Merged at revision: | 2768 |
Proposed branch: | lp:~phill-ridout/openlp/pathlib5 |
Merge into: | lp:openlp |
Diff against target: |
2711 lines (+810/-604) 35 files modified
openlp/core/__init__.py (+18/-25) openlp/core/common/applocation.py (+0/-1) openlp/core/common/httputils.py (+20/-22) openlp/core/common/languagemanager.py (+1/-1) openlp/core/common/path.py (+116/-0) openlp/core/common/registry.py (+1/-1) openlp/core/common/uistrings.py (+0/-3) openlp/core/lib/__init__.py (+14/-38) openlp/core/lib/mediamanageritem.py (+0/-2) openlp/core/ui/firsttimeform.py (+3/-3) openlp/core/ui/lib/filedialog.py (+1/-2) openlp/core/ui/lib/wizard.py (+1/-1) openlp/core/ui/mainwindow.py (+10/-10) openlp/core/ui/servicemanager.py (+20/-20) openlp/core/ui/thememanager.py (+1/-1) openlp/plugins/images/lib/mediaitem.py (+1/-1) openlp/plugins/presentations/lib/impresscontroller.py (+19/-25) openlp/plugins/presentations/lib/mediaitem.py (+79/-79) openlp/plugins/presentations/lib/messagelistener.py (+16/-13) openlp/plugins/presentations/lib/pdfcontroller.py (+54/-51) openlp/plugins/presentations/lib/powerpointcontroller.py (+7/-7) openlp/plugins/presentations/lib/pptviewcontroller.py (+18/-17) openlp/plugins/presentations/lib/presentationcontroller.py (+83/-71) openlp/plugins/presentations/lib/presentationtab.py (+5/-4) openlp/plugins/remotes/deploy.py (+1/-1) openlp/plugins/songs/reporting.py (+41/-47) tests/functional/openlp_core_common/test_httputils.py (+2/-1) tests/functional/openlp_core_common/test_path.py (+203/-2) tests/functional/openlp_core_lib/test_lib.py (+23/-70) tests/functional/openlp_core_ui/test_exceptionform.py (+1/-1) tests/functional/openlp_plugins/presentations/test_impresscontroller.py (+3/-4) tests/functional/openlp_plugins/presentations/test_mediaitem.py (+10/-9) tests/functional/openlp_plugins/presentations/test_pdfcontroller.py (+8/-7) tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py (+7/-7) tests/functional/openlp_plugins/presentations/test_presentationcontroller.py (+23/-57) |
To merge this branch: | bzr merge lp:~phill-ridout/openlp/pathlib5 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Tim Bentley | Approve | ||
Tomas Groth | Approve | ||
Raoul Snyman | Pending | ||
Review via email: mp+331127@code.launchpad.net |
This proposal supersedes a proposal from 2017-09-21.
Commit message
Description of the change
More pathlib changes, focused mainly on the presentation plugin
Add this to your merge proposal:
-------
lp:~phill-ridout/openlp/pathlib5 (revision 2777)
[SUCCESS] https:/
[SUCCESS] https:/
[SUCCESS] https:/
[SUCCESS] https:/
[SUCCESS] https:/
[SUCCESS] https:/
[FAILURE] https:/
Stopping after failure
Tim Bentley (trb143) wrote : Posted in a previous version of this proposal | # |
Tim Bentley (trb143) : Posted in a previous version of this proposal | # |
Raoul Snyman (raoul-snyman) wrote : Posted in a previous version of this proposal | # |
One request: Please don't create a shutil file, just put those methods into your existing path file.
Tomas Groth (tomasgroth) : | # |
Tim Bentley (trb143) : | # |
Preview Diff
1 | === modified file 'openlp/core/__init__.py' |
2 | --- openlp/core/__init__.py 2017-09-03 10:18:14 +0000 |
3 | +++ openlp/core/__init__.py 2017-09-21 09:08:49 +0000 |
4 | @@ -29,8 +29,6 @@ |
5 | |
6 | import argparse |
7 | import logging |
8 | -import os |
9 | -import shutil |
10 | import sys |
11 | import time |
12 | from datetime import datetime |
13 | @@ -40,7 +38,7 @@ |
14 | |
15 | from openlp.core.common import Registry, OpenLPMixin, AppLocation, LanguageManager, Settings, UiStrings, \ |
16 | check_directory_exists, is_macosx, is_win, translate |
17 | -from openlp.core.common.path import Path |
18 | +from openlp.core.common.path import Path, copytree |
19 | from openlp.core.common.versionchecker import VersionThread, get_application_version |
20 | from openlp.core.lib import ScreenList |
21 | from openlp.core.resources import qInitResources |
22 | @@ -181,25 +179,20 @@ |
23 | """ |
24 | Check if the data folder path exists. |
25 | """ |
26 | - data_folder_path = str(AppLocation.get_data_path()) |
27 | - if not os.path.exists(data_folder_path): |
28 | - log.critical('Database was not found in: ' + data_folder_path) |
29 | - status = QtWidgets.QMessageBox.critical(None, translate('OpenLP', 'Data Directory Error'), |
30 | - translate('OpenLP', 'OpenLP data folder was not found in:\n\n{path}' |
31 | - '\n\nThe location of the data folder was ' |
32 | - 'previously changed from the OpenLP\'s ' |
33 | - 'default location. If the data was stored on ' |
34 | - 'removable device, that device needs to be ' |
35 | - 'made available.\n\nYou may reset the data ' |
36 | - 'location back to the default location, ' |
37 | - 'or you can try to make the current location ' |
38 | - 'available.\n\nDo you want to reset to the ' |
39 | - 'default data location? If not, OpenLP will be ' |
40 | - 'closed so you can try to fix the the problem.') |
41 | - .format(path=data_folder_path), |
42 | - QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes | |
43 | - QtWidgets.QMessageBox.No), |
44 | - QtWidgets.QMessageBox.No) |
45 | + data_folder_path = AppLocation.get_data_path() |
46 | + if not data_folder_path.exists(): |
47 | + log.critical('Database was not found in: %s', data_folder_path) |
48 | + status = QtWidgets.QMessageBox.critical( |
49 | + None, translate('OpenLP', 'Data Directory Error'), |
50 | + translate('OpenLP', 'OpenLP data folder was not found in:\n\n{path}\n\nThe location of the data folder ' |
51 | + 'was previously changed from the OpenLP\'s default location. If the data was ' |
52 | + 'stored on removable device, that device needs to be made available.\n\nYou may ' |
53 | + 'reset the data location back to the default location, or you can try to make the ' |
54 | + 'current location available.\n\nDo you want to reset to the default data location? ' |
55 | + 'If not, OpenLP will be closed so you can try to fix the the problem.') |
56 | + .format(path=data_folder_path), |
57 | + QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No), |
58 | + QtWidgets.QMessageBox.No) |
59 | if status == QtWidgets.QMessageBox.No: |
60 | # If answer was "No", return "True", it will shutdown OpenLP in def main |
61 | log.info('User requested termination') |
62 | @@ -253,11 +246,11 @@ |
63 | 'a backup of the old data folder?'), |
64 | defaultButton=QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.Yes: |
65 | # Create copy of data folder |
66 | - data_folder_path = str(AppLocation.get_data_path()) |
67 | + data_folder_path = AppLocation.get_data_path() |
68 | timestamp = time.strftime("%Y%m%d-%H%M%S") |
69 | - data_folder_backup_path = data_folder_path + '-' + timestamp |
70 | + data_folder_backup_path = data_folder_path.with_name(data_folder_path.name + '-' + timestamp) |
71 | try: |
72 | - shutil.copytree(data_folder_path, data_folder_backup_path) |
73 | + copytree(data_folder_path, data_folder_backup_path) |
74 | except OSError: |
75 | QtWidgets.QMessageBox.warning(None, translate('OpenLP', 'Backup'), |
76 | translate('OpenLP', 'Backup of the data folder failed!')) |
77 | |
78 | === modified file 'openlp/core/common/applocation.py' |
79 | --- openlp/core/common/applocation.py 2017-08-26 15:06:11 +0000 |
80 | +++ openlp/core/common/applocation.py 2017-09-21 09:08:49 +0000 |
81 | @@ -29,7 +29,6 @@ |
82 | from openlp.core.common import Settings, is_win, is_macosx |
83 | from openlp.core.common.path import Path |
84 | |
85 | - |
86 | if not is_win() and not is_macosx(): |
87 | try: |
88 | from xdg import BaseDirectory |
89 | |
90 | === modified file 'openlp/core/common/httputils.py' |
91 | --- openlp/core/common/httputils.py 2017-08-13 05:50:44 +0000 |
92 | +++ openlp/core/common/httputils.py 2017-09-21 09:08:49 +0000 |
93 | @@ -211,7 +211,7 @@ |
94 | |
95 | :param callback: the class which needs to be updated |
96 | :param url: URL to download |
97 | - :param f_path: Destination file |
98 | + :param openlp.core.common.path.Path f_path: Destination file |
99 | :param sha256: The check sum value to be checked against the download value |
100 | """ |
101 | block_count = 0 |
102 | @@ -220,29 +220,23 @@ |
103 | log.debug("url_get_file: " + url) |
104 | while True: |
105 | try: |
106 | - filename = open(f_path, "wb") |
107 | - url_file = urllib.request.urlopen(url, timeout=CONNECTION_TIMEOUT) |
108 | if sha256: |
109 | hasher = hashlib.sha256() |
110 | - # Download until finished or canceled. |
111 | - while not callback.was_cancelled: |
112 | - data = url_file.read(block_size) |
113 | - if not data: |
114 | - break |
115 | - filename.write(data) |
116 | - if sha256: |
117 | - hasher.update(data) |
118 | - block_count += 1 |
119 | - callback._download_progress(block_count, block_size) |
120 | - filename.close() |
121 | - if sha256 and hasher.hexdigest() != sha256: |
122 | - log.error('sha256 sums did not match for file: {file}'.format(file=f_path)) |
123 | - os.remove(f_path) |
124 | - return False |
125 | - except (urllib.error.URLError, socket.timeout) as err: |
126 | + with f_path.open('wb') as file: |
127 | + url_file = urllib.request.urlopen(url, timeout=CONNECTION_TIMEOUT) |
128 | + # Download until finished or canceled. |
129 | + while not callback.was_cancelled: |
130 | + data = url_file.read(block_size) |
131 | + if not data: |
132 | + break |
133 | + file.write(data) |
134 | + if sha256: |
135 | + hasher.update(data) |
136 | + block_count += 1 |
137 | + callback._download_progress(block_count, block_size) |
138 | + except (urllib.error.URLError, socket.timeout): |
139 | trace_error_handler(log) |
140 | - filename.close() |
141 | - os.remove(f_path) |
142 | + f_path.unlink() |
143 | if retries > CONNECTION_RETRIES: |
144 | return False |
145 | else: |
146 | @@ -251,8 +245,12 @@ |
147 | continue |
148 | break |
149 | # Delete file if cancelled, it may be a partial file. |
150 | + if sha256 and hasher.hexdigest() != sha256: |
151 | + log.error('sha256 sums did not match for file: {file}'.format(file=f_path)) |
152 | + f_path.unlink() |
153 | + return False |
154 | if callback.was_cancelled: |
155 | - os.remove(f_path) |
156 | + f_path.unlink() |
157 | return True |
158 | |
159 | |
160 | |
161 | === modified file 'openlp/core/common/languagemanager.py' |
162 | --- openlp/core/common/languagemanager.py 2017-08-01 20:59:41 +0000 |
163 | +++ openlp/core/common/languagemanager.py 2017-09-21 09:08:49 +0000 |
164 | @@ -141,7 +141,7 @@ |
165 | if reg_ex.exactMatch(qmf): |
166 | name = '{regex}'.format(regex=reg_ex.cap(1)) |
167 | LanguageManager.__qm_list__[ |
168 | - '{count:>2i} {name}'.format(count=counter + 1, name=LanguageManager.language_name(qmf))] = name |
169 | + '{count:>2d} {name}'.format(count=counter + 1, name=LanguageManager.language_name(qmf))] = name |
170 | |
171 | @staticmethod |
172 | def get_qm_list(): |
173 | |
174 | === modified file 'openlp/core/common/path.py' |
175 | --- openlp/core/common/path.py 2017-08-27 17:37:54 +0000 |
176 | +++ openlp/core/common/path.py 2017-09-21 09:08:49 +0000 |
177 | @@ -19,6 +19,7 @@ |
178 | # with this program; if not, write to the Free Software Foundation, Inc., 59 # |
179 | # Temple Place, Suite 330, Boston, MA 02111-1307 USA # |
180 | ############################################################################### |
181 | +import shutil |
182 | from contextlib import suppress |
183 | |
184 | from openlp.core.common import is_win |
185 | @@ -29,6 +30,121 @@ |
186 | from pathlib import PosixPath as PathVariant |
187 | |
188 | |
189 | +def replace_params(args, kwargs, params): |
190 | + """ |
191 | + Apply a transformation function to the specified args or kwargs |
192 | + |
193 | + :param tuple args: Positional arguments |
194 | + :param dict kwargs: Key Word arguments |
195 | + :param params: A tuple of tuples with the position and the key word to replace. |
196 | + :return: The modified positional and keyword arguments |
197 | + :rtype: tuple[tuple, dict] |
198 | + |
199 | + |
200 | + Usage: |
201 | + Take a method with the following signature, and assume we which to apply the str function to arg2: |
202 | + def method(arg1=None, arg2=None, arg3=None) |
203 | + |
204 | + As arg2 can be specified postitionally as the second argument (1 with a zero index) or as a keyword, the we |
205 | + would call this function as follows: |
206 | + |
207 | + replace_params(args, kwargs, ((1, 'arg2', str),)) |
208 | + """ |
209 | + args = list(args) |
210 | + for position, key_word, transform in params: |
211 | + if len(args) > position: |
212 | + args[position] = transform(args[position]) |
213 | + elif key_word in kwargs: |
214 | + kwargs[key_word] = transform(kwargs[key_word]) |
215 | + return tuple(args), kwargs |
216 | + |
217 | + |
218 | +def copy(*args, **kwargs): |
219 | + """ |
220 | + Wraps :func:`shutil.copy` so that we can accept Path objects. |
221 | + |
222 | + :param src openlp.core.common.path.Path: Takes a Path object which is then converted to a str object |
223 | + :param dst openlp.core.common.path.Path: Takes a Path object which is then converted to a str object |
224 | + :return: Converts the str object received from :func:`shutil.copy` to a Path or NoneType object |
225 | + :rtype: openlp.core.common.path.Path | None |
226 | + |
227 | + See the following link for more information on the other parameters: |
228 | + https://docs.python.org/3/library/shutil.html#shutil.copy |
229 | + """ |
230 | + |
231 | + args, kwargs = replace_params(args, kwargs, ((0, 'src', path_to_str), (1, 'dst', path_to_str))) |
232 | + |
233 | + return str_to_path(shutil.copy(*args, **kwargs)) |
234 | + |
235 | + |
236 | +def copyfile(*args, **kwargs): |
237 | + """ |
238 | + Wraps :func:`shutil.copyfile` so that we can accept Path objects. |
239 | + |
240 | + :param openlp.core.common.path.Path src: Takes a Path object which is then converted to a str object |
241 | + :param openlp.core.common.path.Path dst: Takes a Path object which is then converted to a str object |
242 | + :return: Converts the str object received from :func:`shutil.copyfile` to a Path or NoneType object |
243 | + :rtype: openlp.core.common.path.Path | None |
244 | + |
245 | + See the following link for more information on the other parameters: |
246 | + https://docs.python.org/3/library/shutil.html#shutil.copyfile |
247 | + """ |
248 | + |
249 | + args, kwargs = replace_params(args, kwargs, ((0, 'src', path_to_str), (1, 'dst', path_to_str))) |
250 | + |
251 | + return str_to_path(shutil.copyfile(*args, **kwargs)) |
252 | + |
253 | + |
254 | +def copytree(*args, **kwargs): |
255 | + """ |
256 | + Wraps :func:shutil.copytree` so that we can accept Path objects. |
257 | + |
258 | + :param openlp.core.common.path.Path src : Takes a Path object which is then converted to a str object |
259 | + :param openlp.core.common.path.Path dst: Takes a Path object which is then converted to a str object |
260 | + :return: Converts the str object received from :func:`shutil.copytree` to a Path or NoneType object |
261 | + :rtype: openlp.core.common.path.Path | None |
262 | + |
263 | + See the following link for more information on the other parameters: |
264 | + https://docs.python.org/3/library/shutil.html#shutil.copytree |
265 | + """ |
266 | + |
267 | + args, kwargs = replace_params(args, kwargs, ((0, 'src', path_to_str), (1, 'dst', path_to_str))) |
268 | + |
269 | + return str_to_path(shutil.copytree(*args, **kwargs)) |
270 | + |
271 | + |
272 | +def rmtree(*args, **kwargs): |
273 | + """ |
274 | + Wraps :func:shutil.rmtree` so that we can accept Path objects. |
275 | + |
276 | + :param openlp.core.common.path.Path path: Takes a Path object which is then converted to a str object |
277 | + :return: Passes the return from :func:`shutil.rmtree` back |
278 | + :rtype: None |
279 | + |
280 | + See the following link for more information on the other parameters: |
281 | + https://docs.python.org/3/library/shutil.html#shutil.rmtree |
282 | + """ |
283 | + |
284 | + args, kwargs = replace_params(args, kwargs, ((0, 'path', path_to_str),)) |
285 | + |
286 | + return shutil.rmtree(*args, **kwargs) |
287 | + |
288 | + |
289 | +def which(*args, **kwargs): |
290 | + """ |
291 | + Wraps :func:shutil.which` so that it return a Path objects. |
292 | + |
293 | + :rtype: openlp.core.common.Path |
294 | + |
295 | + See the following link for more information on the other parameters: |
296 | + https://docs.python.org/3/library/shutil.html#shutil.which |
297 | + """ |
298 | + file_name = shutil.which(*args, **kwargs) |
299 | + if file_name: |
300 | + return str_to_path(file_name) |
301 | + return None |
302 | + |
303 | + |
304 | def path_to_str(path=None): |
305 | """ |
306 | A utility function to convert a Path object or NoneType to a string equivalent. |
307 | |
308 | === modified file 'openlp/core/common/registry.py' |
309 | --- openlp/core/common/registry.py 2017-03-03 19:27:31 +0000 |
310 | +++ openlp/core/common/registry.py 2017-09-21 09:08:49 +0000 |
311 | @@ -143,7 +143,7 @@ |
312 | log.exception('Exception for function {function}'.format(function=function)) |
313 | else: |
314 | trace_error_handler(log) |
315 | - log.error("Event {event} called but not registered".format(event=event)) |
316 | + log.exception('Event {event} called but not registered'.format(event=event)) |
317 | return results |
318 | |
319 | def get_flag(self, key): |
320 | |
321 | === modified file 'openlp/core/common/uistrings.py' |
322 | --- openlp/core/common/uistrings.py 2017-08-03 17:54:40 +0000 |
323 | +++ openlp/core/common/uistrings.py 2017-09-21 09:08:49 +0000 |
324 | @@ -88,9 +88,6 @@ |
325 | self.Error = translate('OpenLP.Ui', 'Error') |
326 | self.Export = translate('OpenLP.Ui', 'Export') |
327 | self.File = translate('OpenLP.Ui', 'File') |
328 | - self.FileNotFound = translate('OpenLP.Ui', 'File Not Found') |
329 | - self.FileNotFoundMessage = translate('OpenLP.Ui', |
330 | - 'File {name} not found.\nPlease try selecting it individually.') |
331 | self.FontSizePtUnit = translate('OpenLP.Ui', 'pt', 'Abbreviated font pointsize unit') |
332 | self.Help = translate('OpenLP.Ui', 'Help') |
333 | self.Hours = translate('OpenLP.Ui', 'h', 'The abbreviated unit for hours') |
334 | |
335 | === modified file 'openlp/core/lib/__init__.py' |
336 | --- openlp/core/lib/__init__.py 2017-08-25 20:03:25 +0000 |
337 | +++ openlp/core/lib/__init__.py 2017-09-21 09:08:49 +0000 |
338 | @@ -32,6 +32,7 @@ |
339 | from PyQt5 import QtCore, QtGui, Qt, QtWidgets |
340 | |
341 | from openlp.core.common import translate |
342 | +from openlp.core.common.path import Path |
343 | |
344 | log = logging.getLogger(__name__ + '.__init__') |
345 | |
346 | @@ -125,10 +126,11 @@ |
347 | Build a QIcon instance from an existing QIcon, a resource location, or a physical file location. If the icon is a |
348 | QIcon instance, that icon is simply returned. If not, it builds a QIcon instance from the resource or file name. |
349 | |
350 | - :param icon: |
351 | - The icon to build. This can be a QIcon, a resource string in the form ``:/resource/file.png``, or a file |
352 | - location like ``/path/to/file.png``. However, the **recommended** way is to specify a resource string. |
353 | + :param QtGui.QIcon | Path | QtGui.QIcon | str icon: |
354 | + The icon to build. This can be a QIcon, a resource string in the form ``:/resource/file.png``, or a file path |
355 | + location like ``Path(/path/to/file.png)``. However, the **recommended** way is to specify a resource string. |
356 | :return: The build icon. |
357 | + :rtype: QtGui.QIcon |
358 | """ |
359 | if isinstance(icon, QtGui.QIcon): |
360 | return icon |
361 | @@ -136,6 +138,8 @@ |
362 | button_icon = QtGui.QIcon() |
363 | if isinstance(icon, str): |
364 | pix_map = QtGui.QPixmap(icon) |
365 | + elif isinstance(icon, Path): |
366 | + pix_map = QtGui.QPixmap(str(icon)) |
367 | elif isinstance(icon, QtGui.QImage): |
368 | pix_map = QtGui.QPixmap.fromImage(icon) |
369 | if pix_map: |
370 | @@ -217,14 +221,15 @@ |
371 | Validates whether an file's thumb still exists and if is up to date. **Note**, you must **not** call this function, |
372 | before checking the existence of the file. |
373 | |
374 | - :param file_path: The path to the file. The file **must** exist! |
375 | - :param thumb_path: The path to the thumb. |
376 | - :return: True, False if the image has changed since the thumb was created. |
377 | + :param openlp.core.common.path.Path file_path: The path to the file. The file **must** exist! |
378 | + :param openlp.core.common.path.Path thumb_path: The path to the thumb. |
379 | + :return: Has the image changed since the thumb was created? |
380 | + :rtype: bool |
381 | """ |
382 | - if not os.path.exists(thumb_path): |
383 | + if not thumb_path.exists(): |
384 | return False |
385 | - image_date = os.stat(file_path).st_mtime |
386 | - thumb_date = os.stat(thumb_path).st_mtime |
387 | + image_date = file_path.stat().st_mtime |
388 | + thumb_date = thumb_path.stat().st_mtime |
389 | return image_date <= thumb_date |
390 | |
391 | |
392 | @@ -606,35 +611,6 @@ |
393 | return list_to_string |
394 | |
395 | |
396 | -def replace_params(args, kwargs, params): |
397 | - """ |
398 | - Apply a transformation function to the specified args or kwargs |
399 | - |
400 | - :param tuple args: Positional arguments |
401 | - :param dict kwargs: Key Word arguments |
402 | - :param params: A tuple of tuples with the position and the key word to replace. |
403 | - :return: The modified positional and keyword arguments |
404 | - :rtype: tuple[tuple, dict] |
405 | - |
406 | - |
407 | - Usage: |
408 | - Take a method with the following signature, and assume we which to apply the str function to arg2: |
409 | - def method(arg1=None, arg2=None, arg3=None) |
410 | - |
411 | - As arg2 can be specified postitionally as the second argument (1 with a zero index) or as a keyword, the we |
412 | - would call this function as follows: |
413 | - |
414 | - replace_params(args, kwargs, ((1, 'arg2', str),)) |
415 | - """ |
416 | - args = list(args) |
417 | - for position, key_word, transform in params: |
418 | - if len(args) > position: |
419 | - args[position] = transform(args[position]) |
420 | - elif key_word in kwargs: |
421 | - kwargs[key_word] = transform(kwargs[key_word]) |
422 | - return tuple(args), kwargs |
423 | - |
424 | - |
425 | from .exceptions import ValidationError |
426 | from .screen import ScreenList |
427 | from .formattingtags import FormattingTags |
428 | |
429 | === modified file 'openlp/core/lib/mediamanageritem.py' |
430 | --- openlp/core/lib/mediamanageritem.py 2017-08-26 15:06:11 +0000 |
431 | +++ openlp/core/lib/mediamanageritem.py 2017-09-21 09:08:49 +0000 |
432 | @@ -359,10 +359,8 @@ |
433 | :param files: The files to be loaded. |
434 | :param target_group: The QTreeWidgetItem of the group that will be the parent of the added files |
435 | """ |
436 | - names = [] |
437 | full_list = [] |
438 | for count in range(self.list_view.count()): |
439 | - names.append(self.list_view.item(count).text()) |
440 | full_list.append(self.list_view.item(count).data(QtCore.Qt.UserRole)) |
441 | duplicates_found = False |
442 | files_added = False |
443 | |
444 | === modified file 'openlp/core/ui/firsttimeform.py' |
445 | --- openlp/core/ui/firsttimeform.py 2017-08-25 20:03:25 +0000 |
446 | +++ openlp/core/ui/firsttimeform.py 2017-09-21 09:08:49 +0000 |
447 | @@ -563,7 +563,7 @@ |
448 | filename, sha256 = item.data(QtCore.Qt.UserRole) |
449 | self._increment_progress_bar(self.downloading.format(name=filename), 0) |
450 | self.previous_size = 0 |
451 | - destination = os.path.join(songs_destination, str(filename)) |
452 | + destination = Path(songs_destination, str(filename)) |
453 | if not url_get_file(self, '{path}{name}'.format(path=self.songs_url, name=filename), |
454 | destination, sha256): |
455 | missed_files.append('Song: {name}'.format(name=filename)) |
456 | @@ -576,7 +576,7 @@ |
457 | self._increment_progress_bar(self.downloading.format(name=bible), 0) |
458 | self.previous_size = 0 |
459 | if not url_get_file(self, '{path}{name}'.format(path=self.bibles_url, name=bible), |
460 | - os.path.join(bibles_destination, bible), |
461 | + Path(bibles_destination, bible), |
462 | sha256): |
463 | missed_files.append('Bible: {name}'.format(name=bible)) |
464 | bibles_iterator += 1 |
465 | @@ -588,7 +588,7 @@ |
466 | self._increment_progress_bar(self.downloading.format(name=theme), 0) |
467 | self.previous_size = 0 |
468 | if not url_get_file(self, '{path}{name}'.format(path=self.themes_url, name=theme), |
469 | - os.path.join(themes_destination, theme), |
470 | + Path(themes_destination, theme), |
471 | sha256): |
472 | missed_files.append('Theme: {name}'.format(name=theme)) |
473 | if missed_files: |
474 | |
475 | === modified file 'openlp/core/ui/lib/filedialog.py' |
476 | --- openlp/core/ui/lib/filedialog.py 2017-08-25 20:03:25 +0000 |
477 | +++ openlp/core/ui/lib/filedialog.py 2017-09-21 09:08:49 +0000 |
478 | @@ -22,8 +22,7 @@ |
479 | """ Patch the QFileDialog so it accepts and returns Path objects""" |
480 | from PyQt5 import QtWidgets |
481 | |
482 | -from openlp.core.common.path import Path, path_to_str, str_to_path |
483 | -from openlp.core.lib import replace_params |
484 | +from openlp.core.common.path import Path, path_to_str, replace_params, str_to_path |
485 | |
486 | |
487 | class FileDialog(QtWidgets.QFileDialog): |
488 | |
489 | === modified file 'openlp/core/ui/lib/wizard.py' |
490 | --- openlp/core/ui/lib/wizard.py 2017-08-26 15:06:11 +0000 |
491 | +++ openlp/core/ui/lib/wizard.py 2017-09-21 09:08:49 +0000 |
492 | @@ -310,7 +310,7 @@ |
493 | """ |
494 | folder_path = FileDialog.getExistingDirectory( |
495 | self, title, Settings().value(self.plugin.settings_section + '/' + setting_name), |
496 | - QtWidgets.QFileDialog.ShowDirsOnly) |
497 | + FileDialog.ShowDirsOnly) |
498 | if folder_path: |
499 | editbox.setText(str(folder_path)) |
500 | Settings().setValue(self.plugin.settings_section + '/' + setting_name, folder_path) |
501 | |
502 | === modified file 'openlp/core/ui/mainwindow.py' |
503 | --- openlp/core/ui/mainwindow.py 2017-09-03 10:18:14 +0000 |
504 | +++ openlp/core/ui/mainwindow.py 2017-09-21 09:08:49 +0000 |
505 | @@ -39,7 +39,7 @@ |
506 | from openlp.core.common import Registry, RegistryProperties, AppLocation, LanguageManager, Settings, UiStrings, \ |
507 | check_directory_exists, translate, is_win, is_macosx, add_actions |
508 | from openlp.core.common.actions import ActionList, CategoryOrder |
509 | -from openlp.core.common.path import Path, path_to_str, str_to_path |
510 | +from openlp.core.common.path import Path, copyfile, path_to_str, str_to_path |
511 | from openlp.core.common.versionchecker import get_application_version |
512 | from openlp.core.lib import Renderer, PluginManager, ImageManager, PluginStatus, ScreenList, build_icon |
513 | from openlp.core.lib.ui import create_action |
514 | @@ -848,12 +848,12 @@ |
515 | QtWidgets.QMessageBox.No) |
516 | if answer == QtWidgets.QMessageBox.No: |
517 | return |
518 | - import_file_name, filter_used = QtWidgets.QFileDialog.getOpenFileName( |
519 | + import_file_path, filter_used = FileDialog.getOpenFileName( |
520 | self, |
521 | translate('OpenLP.MainWindow', 'Import settings'), |
522 | - '', |
523 | + None, |
524 | translate('OpenLP.MainWindow', 'OpenLP Settings (*.conf)')) |
525 | - if not import_file_name: |
526 | + if import_file_path is None: |
527 | return |
528 | setting_sections = [] |
529 | # Add main sections. |
530 | @@ -871,12 +871,12 @@ |
531 | # Add plugin sections. |
532 | setting_sections.extend([plugin.name for plugin in self.plugin_manager.plugins]) |
533 | # Copy the settings file to the tmp dir, because we do not want to change the original one. |
534 | - temp_directory = os.path.join(str(gettempdir()), 'openlp') |
535 | - check_directory_exists(Path(temp_directory)) |
536 | - temp_config = os.path.join(temp_directory, os.path.basename(import_file_name)) |
537 | - shutil.copyfile(import_file_name, temp_config) |
538 | + temp_dir_path = Path(gettempdir(), 'openlp') |
539 | + check_directory_exists(temp_dir_path) |
540 | + temp_config_path = temp_dir_path / import_file_path.name |
541 | + copyfile(import_file_path, temp_config_path) |
542 | settings = Settings() |
543 | - import_settings = Settings(temp_config, Settings.IniFormat) |
544 | + import_settings = Settings(str(temp_config_path), Settings.IniFormat) |
545 | |
546 | log.info('hook upgrade_plugin_settings') |
547 | self.plugin_manager.hook_upgrade_plugin_settings(import_settings) |
548 | @@ -920,7 +920,7 @@ |
549 | settings.setValue('{key}'.format(key=section_key), value) |
550 | now = datetime.now() |
551 | settings.beginGroup(self.header_section) |
552 | - settings.setValue('file_imported', import_file_name) |
553 | + settings.setValue('file_imported', import_file_path) |
554 | settings.setValue('file_date_imported', now.strftime("%Y-%m-%d %H:%M")) |
555 | settings.endGroup() |
556 | settings.sync() |
557 | |
558 | === modified file 'openlp/core/ui/servicemanager.py' |
559 | --- openlp/core/ui/servicemanager.py 2017-08-26 15:06:11 +0000 |
560 | +++ openlp/core/ui/servicemanager.py 2017-09-21 09:08:49 +0000 |
561 | @@ -366,16 +366,20 @@ |
562 | """ |
563 | return self._modified |
564 | |
565 | - def set_file_name(self, file_name): |
566 | + def set_file_name(self, file_path): |
567 | """ |
568 | Setter for service file. |
569 | |
570 | - :param file_name: The service file name |
571 | + :param openlp.core.common.path.Path file_path: The service file name |
572 | + :rtype: None |
573 | """ |
574 | - self._file_name = str(file_name) |
575 | + self._file_name = path_to_str(file_path) |
576 | self.main_window.set_service_modified(self.is_modified(), self.short_file_name()) |
577 | - Settings().setValue('servicemanager/last file', Path(file_name)) |
578 | - self._save_lite = self._file_name.endswith('.oszl') |
579 | + Settings().setValue('servicemanager/last file', file_path) |
580 | + if file_path and file_path.suffix() == '.oszl': |
581 | + self._save_lite = True |
582 | + else: |
583 | + self._save_lite = False |
584 | |
585 | def file_name(self): |
586 | """ |
587 | @@ -474,7 +478,7 @@ |
588 | """ |
589 | self.service_manager_list.clear() |
590 | self.service_items = [] |
591 | - self.set_file_name('') |
592 | + self.set_file_name(None) |
593 | self.service_id += 1 |
594 | self.set_modified(False) |
595 | Settings().setValue('servicemanager/last file', None) |
596 | @@ -695,27 +699,23 @@ |
597 | default_file_name = format_time(default_pattern, local_time) |
598 | else: |
599 | default_file_name = '' |
600 | - directory = path_to_str(Settings().value(self.main_window.service_manager_settings_section + '/last directory')) |
601 | - path = os.path.join(directory, default_file_name) |
602 | + directory_path = Settings().value(self.main_window.service_manager_settings_section + '/last directory') |
603 | + file_path = directory_path / default_file_name |
604 | # SaveAs from osz to oszl is not valid as the files will be deleted on exit which is not sensible or usable in |
605 | # the long term. |
606 | if self._file_name.endswith('oszl') or self.service_has_all_original_files: |
607 | - file_name, filter_used = QtWidgets.QFileDialog.getSaveFileName( |
608 | - self.main_window, UiStrings().SaveService, path, |
609 | + file_path, filter_used = FileDialog.getSaveFileName( |
610 | + self.main_window, UiStrings().SaveService, file_path, |
611 | translate('OpenLP.ServiceManager', |
612 | 'OpenLP Service Files (*.osz);; OpenLP Service Files - lite (*.oszl)')) |
613 | else: |
614 | - file_name, filter_used = QtWidgets.QFileDialog.getSaveFileName( |
615 | - self.main_window, UiStrings().SaveService, path, |
616 | + file_path, filter_used = FileDialog.getSaveFileName( |
617 | + self.main_window, UiStrings().SaveService, file_path, |
618 | translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz);;')) |
619 | - if not file_name: |
620 | + if not file_path: |
621 | return False |
622 | - if os.path.splitext(file_name)[1] == '': |
623 | - file_name += '.osz' |
624 | - else: |
625 | - ext = os.path.splitext(file_name)[1] |
626 | - file_name.replace(ext, '.osz') |
627 | - self.set_file_name(file_name) |
628 | + file_path.with_suffix('.osz') |
629 | + self.set_file_name(file_path) |
630 | self.decide_save_method() |
631 | |
632 | def decide_save_method(self, field=None): |
633 | @@ -772,7 +772,7 @@ |
634 | return |
635 | file_to.close() |
636 | self.new_file() |
637 | - self.set_file_name(file_name) |
638 | + self.set_file_name(str_to_path(file_name)) |
639 | self.main_window.display_progress_bar(len(items)) |
640 | self.process_service_items(items) |
641 | delete_file(Path(p_file)) |
642 | |
643 | === modified file 'openlp/core/ui/thememanager.py' |
644 | --- openlp/core/ui/thememanager.py 2017-08-26 16:50:54 +0000 |
645 | +++ openlp/core/ui/thememanager.py 2017-09-21 09:08:49 +0000 |
646 | @@ -483,7 +483,7 @@ |
647 | name = text_name |
648 | thumb = os.path.join(self.thumb_path, '{name}.png'.format(name=text_name)) |
649 | item_name = QtWidgets.QListWidgetItem(name) |
650 | - if validate_thumb(theme, thumb): |
651 | + if validate_thumb(Path(theme), Path(thumb)): |
652 | icon = build_icon(thumb) |
653 | else: |
654 | icon = create_thumb(theme, thumb) |
655 | |
656 | === modified file 'openlp/plugins/images/lib/mediaitem.py' |
657 | --- openlp/plugins/images/lib/mediaitem.py 2017-08-26 15:06:11 +0000 |
658 | +++ openlp/plugins/images/lib/mediaitem.py 2017-09-21 09:08:49 +0000 |
659 | @@ -360,7 +360,7 @@ |
660 | if not os.path.exists(image_file.filename): |
661 | icon = build_icon(':/general/general_delete.png') |
662 | else: |
663 | - if validate_thumb(image_file.filename, thumb): |
664 | + if validate_thumb(Path(image_file.filename), Path(thumb)): |
665 | icon = build_icon(thumb) |
666 | else: |
667 | icon = create_thumb(image_file.filename, thumb) |
668 | |
669 | === modified file 'openlp/plugins/presentations/lib/impresscontroller.py' |
670 | --- openlp/plugins/presentations/lib/impresscontroller.py 2017-08-25 20:03:25 +0000 |
671 | +++ openlp/plugins/presentations/lib/impresscontroller.py 2017-09-21 09:08:49 +0000 |
672 | @@ -32,11 +32,14 @@ |
673 | # http://nxsy.org/comparing-documents-with-openoffice-and-python |
674 | |
675 | import logging |
676 | -import os |
677 | import time |
678 | |
679 | -from openlp.core.common import is_win, Registry, delete_file |
680 | -from openlp.core.common.path import Path |
681 | +from PyQt5 import QtCore |
682 | + |
683 | +from openlp.core.common import Registry, delete_file, get_uno_command, get_uno_instance, is_win |
684 | +from openlp.core.lib import ScreenList |
685 | +from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument, \ |
686 | + TextType |
687 | |
688 | if is_win(): |
689 | from win32com.client import Dispatch |
690 | @@ -55,14 +58,6 @@ |
691 | except ImportError: |
692 | uno_available = False |
693 | |
694 | -from PyQt5 import QtCore |
695 | - |
696 | -from openlp.core.lib import ScreenList |
697 | -from openlp.core.common import get_uno_command, get_uno_instance |
698 | -from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument, \ |
699 | - TextType |
700 | - |
701 | - |
702 | log = logging.getLogger(__name__) |
703 | |
704 | |
705 | @@ -203,12 +198,15 @@ |
706 | Class which holds information and controls a single presentation. |
707 | """ |
708 | |
709 | - def __init__(self, controller, presentation): |
710 | + def __init__(self, controller, document_path): |
711 | """ |
712 | Constructor, store information about the file and initialise. |
713 | + |
714 | + :param openlp.core.common.path.Path document_path: File path for the document to load |
715 | + :rtype: None |
716 | """ |
717 | log.debug('Init Presentation OpenOffice') |
718 | - super(ImpressDocument, self).__init__(controller, presentation) |
719 | + super().__init__(controller, document_path) |
720 | self.document = None |
721 | self.presentation = None |
722 | self.control = None |
723 | @@ -225,10 +223,9 @@ |
724 | if desktop is None: |
725 | self.controller.start_process() |
726 | desktop = self.controller.get_com_desktop() |
727 | - url = 'file:///' + self.file_path.replace('\\', '/').replace(':', '|').replace(' ', '%20') |
728 | else: |
729 | desktop = self.controller.get_uno_desktop() |
730 | - url = uno.systemPathToFileUrl(self.file_path) |
731 | + url = self.file_path.as_uri() |
732 | if desktop is None: |
733 | return False |
734 | self.desktop = desktop |
735 | @@ -254,11 +251,8 @@ |
736 | log.debug('create thumbnails OpenOffice') |
737 | if self.check_thumbnails(): |
738 | return |
739 | - if is_win(): |
740 | - thumb_dir_url = 'file:///' + self.get_temp_folder().replace('\\', '/') \ |
741 | - .replace(':', '|').replace(' ', '%20') |
742 | - else: |
743 | - thumb_dir_url = uno.systemPathToFileUrl(self.get_temp_folder()) |
744 | + temp_folder_path = self.get_temp_folder() |
745 | + thumb_dir_url = temp_folder_path.as_uri() |
746 | properties = [] |
747 | properties.append(self.create_property('FilterName', 'impress_png_Export')) |
748 | properties = tuple(properties) |
749 | @@ -266,17 +260,17 @@ |
750 | pages = doc.getDrawPages() |
751 | if not pages: |
752 | return |
753 | - if not os.path.isdir(self.get_temp_folder()): |
754 | - os.makedirs(self.get_temp_folder()) |
755 | + if not temp_folder_path.is_dir(): |
756 | + temp_folder_path.mkdir(parents=True) |
757 | for index in range(pages.getCount()): |
758 | page = pages.getByIndex(index) |
759 | doc.getCurrentController().setCurrentPage(page) |
760 | - url_path = '{path}/{name}.png'.format(path=thumb_dir_url, name=str(index + 1)) |
761 | - path = os.path.join(self.get_temp_folder(), str(index + 1) + '.png') |
762 | + url_path = '{path}/{name:d}.png'.format(path=thumb_dir_url, name=index + 1) |
763 | + path = temp_folder_path / '{number:d}.png'.format(number=index + 1) |
764 | try: |
765 | doc.storeToURL(url_path, properties) |
766 | self.convert_thumbnail(path, index + 1) |
767 | - delete_file(Path(path)) |
768 | + delete_file(path) |
769 | except ErrorCodeIOException as exception: |
770 | log.exception('ERROR! ErrorCodeIOException {error:d}'.format(error=exception.ErrCode)) |
771 | except: |
772 | |
773 | === modified file 'openlp/plugins/presentations/lib/mediaitem.py' |
774 | --- openlp/plugins/presentations/lib/mediaitem.py 2017-08-26 15:06:11 +0000 |
775 | +++ openlp/plugins/presentations/lib/mediaitem.py 2017-09-21 09:08:49 +0000 |
776 | @@ -19,15 +19,13 @@ |
777 | # with this program; if not, write to the Free Software Foundation, Inc., 59 # |
778 | # Temple Place, Suite 330, Boston, MA 02111-1307 USA # |
779 | ############################################################################### |
780 | - |
781 | import logging |
782 | -import os |
783 | |
784 | from PyQt5 import QtCore, QtGui, QtWidgets |
785 | |
786 | from openlp.core.common import Registry, Settings, UiStrings, translate |
787 | from openlp.core.common.languagemanager import get_locale_key |
788 | -from openlp.core.common.path import path_to_str |
789 | +from openlp.core.common.path import Path, path_to_str, str_to_path |
790 | from openlp.core.lib import MediaManagerItem, ItemCapabilities, ServiceItemContext,\ |
791 | build_icon, check_item_selected, create_thumb, validate_thumb |
792 | from openlp.core.lib.ui import critical_error_message_box, create_horizontal_adjusting_combo_box |
793 | @@ -128,7 +126,7 @@ |
794 | """ |
795 | self.list_view.setIconSize(QtCore.QSize(88, 50)) |
796 | file_paths = Settings().value(self.settings_section + '/presentations files') |
797 | - self.load_list([path_to_str(file) for file in file_paths], initial_load=True) |
798 | + self.load_list([path_to_str(path) for path in file_paths], initial_load=True) |
799 | self.populate_display_types() |
800 | |
801 | def populate_display_types(self): |
802 | @@ -152,54 +150,57 @@ |
803 | else: |
804 | self.presentation_widget.hide() |
805 | |
806 | - def load_list(self, files, target_group=None, initial_load=False): |
807 | + def load_list(self, file_paths, target_group=None, initial_load=False): |
808 | """ |
809 | Add presentations into the media manager. This is called both on initial load of the plugin to populate with |
810 | existing files, and when the user adds new files via the media manager. |
811 | + |
812 | + :param list[openlp.core.common.path.Path] file_paths: List of file paths to add to the media manager. |
813 | """ |
814 | - current_list = self.get_file_list() |
815 | - titles = [file_path.name for file_path in current_list] |
816 | + file_paths = [str_to_path(filename) for filename in file_paths] |
817 | + current_paths = self.get_file_list() |
818 | + titles = [file_path.name for file_path in current_paths] |
819 | self.application.set_busy_cursor() |
820 | if not initial_load: |
821 | - self.main_window.display_progress_bar(len(files)) |
822 | + self.main_window.display_progress_bar(len(file_paths)) |
823 | # Sort the presentations by its filename considering language specific characters. |
824 | - files.sort(key=lambda filename: get_locale_key(os.path.split(str(filename))[1])) |
825 | - for file in files: |
826 | + file_paths.sort(key=lambda file_path: get_locale_key(file_path.name)) |
827 | + for file_path in file_paths: |
828 | if not initial_load: |
829 | self.main_window.increment_progress_bar() |
830 | - if current_list.count(file) > 0: |
831 | + if current_paths.count(file_path) > 0: |
832 | continue |
833 | - filename = os.path.split(file)[1] |
834 | - if not os.path.exists(file): |
835 | - item_name = QtWidgets.QListWidgetItem(filename) |
836 | + file_name = file_path.name |
837 | + if not file_path.exists(): |
838 | + item_name = QtWidgets.QListWidgetItem(file_name) |
839 | item_name.setIcon(build_icon(ERROR_IMAGE)) |
840 | - item_name.setData(QtCore.Qt.UserRole, file) |
841 | - item_name.setToolTip(file) |
842 | + item_name.setData(QtCore.Qt.UserRole, path_to_str(file_path)) |
843 | + item_name.setToolTip(str(file_path)) |
844 | self.list_view.addItem(item_name) |
845 | else: |
846 | - if titles.count(filename) > 0: |
847 | + if titles.count(file_name) > 0: |
848 | if not initial_load: |
849 | critical_error_message_box(translate('PresentationPlugin.MediaItem', 'File Exists'), |
850 | translate('PresentationPlugin.MediaItem', |
851 | 'A presentation with that filename already exists.')) |
852 | continue |
853 | - controller_name = self.find_controller_by_type(filename) |
854 | + controller_name = self.find_controller_by_type(file_path) |
855 | if controller_name: |
856 | controller = self.controllers[controller_name] |
857 | - doc = controller.add_document(file) |
858 | - thumb = os.path.join(doc.get_thumbnail_folder(), 'icon.png') |
859 | - preview = doc.get_thumbnail_path(1, True) |
860 | - if not preview and not initial_load: |
861 | + doc = controller.add_document(file_path) |
862 | + thumbnail_path = doc.get_thumbnail_folder() / 'icon.png' |
863 | + preview_path = doc.get_thumbnail_path(1, True) |
864 | + if not preview_path and not initial_load: |
865 | doc.load_presentation() |
866 | - preview = doc.get_thumbnail_path(1, True) |
867 | + preview_path = doc.get_thumbnail_path(1, True) |
868 | doc.close_presentation() |
869 | - if not (preview and os.path.exists(preview)): |
870 | + if not (preview_path and preview_path.exists()): |
871 | icon = build_icon(':/general/general_delete.png') |
872 | else: |
873 | - if validate_thumb(preview, thumb): |
874 | - icon = build_icon(thumb) |
875 | + if validate_thumb(Path(preview_path), Path(thumbnail_path)): |
876 | + icon = build_icon(thumbnail_path) |
877 | else: |
878 | - icon = create_thumb(preview, thumb) |
879 | + icon = create_thumb(str(preview_path), str(thumbnail_path)) |
880 | else: |
881 | if initial_load: |
882 | icon = build_icon(':/general/general_delete.png') |
883 | @@ -208,10 +209,10 @@ |
884 | translate('PresentationPlugin.MediaItem', |
885 | 'This type of presentation is not supported.')) |
886 | continue |
887 | - item_name = QtWidgets.QListWidgetItem(filename) |
888 | - item_name.setData(QtCore.Qt.UserRole, file) |
889 | + item_name = QtWidgets.QListWidgetItem(file_name) |
890 | + item_name.setData(QtCore.Qt.UserRole, path_to_str(file_path)) |
891 | item_name.setIcon(icon) |
892 | - item_name.setToolTip(file) |
893 | + item_name.setToolTip(str(file_path)) |
894 | self.list_view.addItem(item_name) |
895 | if not initial_load: |
896 | self.main_window.finished_progress_bar() |
897 | @@ -228,8 +229,8 @@ |
898 | self.application.set_busy_cursor() |
899 | self.main_window.display_progress_bar(len(row_list)) |
900 | for item in items: |
901 | - filepath = str(item.data(QtCore.Qt.UserRole)) |
902 | - self.clean_up_thumbnails(filepath) |
903 | + file_path = str_to_path(item.data(QtCore.Qt.UserRole)) |
904 | + self.clean_up_thumbnails(file_path) |
905 | self.main_window.increment_progress_bar() |
906 | self.main_window.finished_progress_bar() |
907 | for row in row_list: |
908 | @@ -237,30 +238,29 @@ |
909 | Settings().setValue(self.settings_section + '/presentations files', self.get_file_list()) |
910 | self.application.set_normal_cursor() |
911 | |
912 | - def clean_up_thumbnails(self, filepath, clean_for_update=False): |
913 | + def clean_up_thumbnails(self, file_path, clean_for_update=False): |
914 | """ |
915 | Clean up the files created such as thumbnails |
916 | |
917 | - :param filepath: File path of the presention to clean up after |
918 | - :param clean_for_update: Only clean thumbnails if update is needed |
919 | - :return: None |
920 | + :param openlp.core.common.path.Path file_path: File path of the presention to clean up after |
921 | + :param bool clean_for_update: Only clean thumbnails if update is needed |
922 | + :rtype: None |
923 | """ |
924 | for cidx in self.controllers: |
925 | - root, file_ext = os.path.splitext(filepath) |
926 | - file_ext = file_ext[1:] |
927 | + file_ext = file_path.suffix[1:] |
928 | if file_ext in self.controllers[cidx].supports or file_ext in self.controllers[cidx].also_supports: |
929 | - doc = self.controllers[cidx].add_document(filepath) |
930 | + doc = self.controllers[cidx].add_document(file_path) |
931 | if clean_for_update: |
932 | thumb_path = doc.get_thumbnail_path(1, True) |
933 | - if not thumb_path or not os.path.exists(filepath) or os.path.getmtime( |
934 | - thumb_path) < os.path.getmtime(filepath): |
935 | + if not thumb_path or not file_path.exists() or \ |
936 | + thumb_path.stat().st_mtime < file_path.stat().st_mtime: |
937 | doc.presentation_deleted() |
938 | else: |
939 | doc.presentation_deleted() |
940 | doc.close_presentation() |
941 | |
942 | def generate_slide_data(self, service_item, item=None, xml_version=False, remote=False, |
943 | - context=ServiceItemContext.Service, presentation_file=None): |
944 | + context=ServiceItemContext.Service, file_path=None): |
945 | """ |
946 | Generate the slide data. Needs to be implemented by the plugin. |
947 | |
948 | @@ -276,10 +276,9 @@ |
949 | items = self.list_view.selectedItems() |
950 | if len(items) > 1: |
951 | return False |
952 | - filename = presentation_file |
953 | - if filename is None: |
954 | - filename = items[0].data(QtCore.Qt.UserRole) |
955 | - file_type = os.path.splitext(filename.lower())[1][1:] |
956 | + if file_path is None: |
957 | + file_path = str_to_path(items[0].data(QtCore.Qt.UserRole)) |
958 | + file_type = file_path.suffix.lower()[1:] |
959 | if not self.display_type_combo_box.currentText(): |
960 | return False |
961 | service_item.add_capability(ItemCapabilities.CanEditTitle) |
962 | @@ -292,29 +291,28 @@ |
963 | # force a nonexistent theme |
964 | service_item.theme = -1 |
965 | for bitem in items: |
966 | - filename = presentation_file |
967 | - if filename is None: |
968 | - filename = bitem.data(QtCore.Qt.UserRole) |
969 | - (path, name) = os.path.split(filename) |
970 | - service_item.title = name |
971 | - if os.path.exists(filename): |
972 | - processor = self.find_controller_by_type(filename) |
973 | + if file_path is None: |
974 | + file_path = str_to_path(bitem.data(QtCore.Qt.UserRole)) |
975 | + path, file_name = file_path.parent, file_path.name |
976 | + service_item.title = file_name |
977 | + if file_path.exists(): |
978 | + processor = self.find_controller_by_type(file_path) |
979 | if not processor: |
980 | return False |
981 | controller = self.controllers[processor] |
982 | service_item.processor = None |
983 | - doc = controller.add_document(filename) |
984 | - if doc.get_thumbnail_path(1, True) is None or not os.path.isfile( |
985 | - os.path.join(doc.get_temp_folder(), 'mainslide001.png')): |
986 | + doc = controller.add_document(file_path) |
987 | + if doc.get_thumbnail_path(1, True) is None or \ |
988 | + not (doc.get_temp_folder() / 'mainslide001.png').is_file(): |
989 | doc.load_presentation() |
990 | i = 1 |
991 | - image = os.path.join(doc.get_temp_folder(), 'mainslide{number:0>3d}.png'.format(number=i)) |
992 | - thumbnail = os.path.join(doc.get_thumbnail_folder(), 'slide%d.png' % i) |
993 | - while os.path.isfile(image): |
994 | - service_item.add_from_image(image, name, thumbnail=thumbnail) |
995 | + image_path = doc.get_temp_folder() / 'mainslide{number:0>3d}.png'.format(number=i) |
996 | + thumbnail_path = doc.get_thumbnail_folder() / 'slide{number:d}.png'.format(number=i) |
997 | + while image_path.is_file(): |
998 | + service_item.add_from_image(str(image_path), file_name, thumbnail=str(thumbnail_path)) |
999 | i += 1 |
1000 | - image = os.path.join(doc.get_temp_folder(), 'mainslide{number:0>3d}.png'.format(number=i)) |
1001 | - thumbnail = os.path.join(doc.get_thumbnail_folder(), 'slide{number:d}.png'.format(number=i)) |
1002 | + image_path = doc.get_temp_folder() / 'mainslide{number:0>3d}.png'.format(number=i) |
1003 | + thumbnail_path = doc.get_thumbnail_folder() / 'slide{number:d}.png'.format(number=i) |
1004 | service_item.add_capability(ItemCapabilities.HasThumbnails) |
1005 | doc.close_presentation() |
1006 | return True |
1007 | @@ -324,34 +322,34 @@ |
1008 | critical_error_message_box(translate('PresentationPlugin.MediaItem', 'Missing Presentation'), |
1009 | translate('PresentationPlugin.MediaItem', |
1010 | 'The presentation {name} no longer exists.' |
1011 | - ).format(name=filename)) |
1012 | + ).format(name=file_path)) |
1013 | return False |
1014 | else: |
1015 | service_item.processor = self.display_type_combo_box.currentText() |
1016 | service_item.add_capability(ItemCapabilities.ProvidesOwnDisplay) |
1017 | for bitem in items: |
1018 | - filename = bitem.data(QtCore.Qt.UserRole) |
1019 | - (path, name) = os.path.split(filename) |
1020 | - service_item.title = name |
1021 | - if os.path.exists(filename): |
1022 | + file_path = str_to_path(bitem.data(QtCore.Qt.UserRole)) |
1023 | + path, file_name = file_path.parent, file_path.name |
1024 | + service_item.title = file_name |
1025 | + if file_path.exists(): |
1026 | if self.display_type_combo_box.itemData(self.display_type_combo_box.currentIndex()) == 'automatic': |
1027 | - service_item.processor = self.find_controller_by_type(filename) |
1028 | + service_item.processor = self.find_controller_by_type(file_path) |
1029 | if not service_item.processor: |
1030 | return False |
1031 | controller = self.controllers[service_item.processor] |
1032 | - doc = controller.add_document(filename) |
1033 | + doc = controller.add_document(file_path) |
1034 | if doc.get_thumbnail_path(1, True) is None: |
1035 | doc.load_presentation() |
1036 | i = 1 |
1037 | - img = doc.get_thumbnail_path(i, True) |
1038 | - if img: |
1039 | + thumbnail_path = doc.get_thumbnail_path(i, True) |
1040 | + if thumbnail_path: |
1041 | # Get titles and notes |
1042 | titles, notes = doc.get_titles_and_notes() |
1043 | service_item.add_capability(ItemCapabilities.HasDisplayTitle) |
1044 | if notes.count('') != len(notes): |
1045 | service_item.add_capability(ItemCapabilities.HasNotes) |
1046 | service_item.add_capability(ItemCapabilities.HasThumbnails) |
1047 | - while img: |
1048 | + while thumbnail_path: |
1049 | # Use title and note if available |
1050 | title = '' |
1051 | if titles and len(titles) >= i: |
1052 | @@ -359,9 +357,9 @@ |
1053 | note = '' |
1054 | if notes and len(notes) >= i: |
1055 | note = notes[i - 1] |
1056 | - service_item.add_from_command(path, name, img, title, note) |
1057 | + service_item.add_from_command(str(path), file_name, str(thumbnail_path), title, note) |
1058 | i += 1 |
1059 | - img = doc.get_thumbnail_path(i, True) |
1060 | + thumbnail_path = doc.get_thumbnail_path(i, True) |
1061 | doc.close_presentation() |
1062 | return True |
1063 | else: |
1064 | @@ -371,7 +369,7 @@ |
1065 | 'Missing Presentation'), |
1066 | translate('PresentationPlugin.MediaItem', |
1067 | 'The presentation {name} is incomplete, ' |
1068 | - 'please reload.').format(name=filename)) |
1069 | + 'please reload.').format(name=file_path)) |
1070 | return False |
1071 | else: |
1072 | # File is no longer present |
1073 | @@ -379,18 +377,20 @@ |
1074 | critical_error_message_box(translate('PresentationPlugin.MediaItem', 'Missing Presentation'), |
1075 | translate('PresentationPlugin.MediaItem', |
1076 | 'The presentation {name} no longer exists.' |
1077 | - ).format(name=filename)) |
1078 | + ).format(name=file_path)) |
1079 | return False |
1080 | |
1081 | - def find_controller_by_type(self, filename): |
1082 | + def find_controller_by_type(self, file_path): |
1083 | """ |
1084 | Determine the default application controller to use for the selected file type. This is used if "Automatic" is |
1085 | set as the preferred controller. Find the first (alphabetic) enabled controller which "supports" the extension. |
1086 | If none found, then look for a controller which "also supports" it instead. |
1087 | |
1088 | - :param filename: The file name |
1089 | + :param openlp.core.common.path.Path file_path: The file path |
1090 | + :return: The default application controller for this file type, or None if not supported |
1091 | + :rtype: PresentationController |
1092 | """ |
1093 | - file_type = os.path.splitext(filename)[1][1:] |
1094 | + file_type = file_path.suffix[1:] |
1095 | if not file_type: |
1096 | return None |
1097 | for controller in self.controllers: |
1098 | |
1099 | === modified file 'openlp/plugins/presentations/lib/messagelistener.py' |
1100 | --- openlp/plugins/presentations/lib/messagelistener.py 2016-12-31 11:01:36 +0000 |
1101 | +++ openlp/plugins/presentations/lib/messagelistener.py 2017-09-21 09:08:49 +0000 |
1102 | @@ -19,16 +19,15 @@ |
1103 | # with this program; if not, write to the Free Software Foundation, Inc., 59 # |
1104 | # Temple Place, Suite 330, Boston, MA 02111-1307 USA # |
1105 | ############################################################################### |
1106 | - |
1107 | +import copy |
1108 | import logging |
1109 | -import copy |
1110 | -import os |
1111 | |
1112 | from PyQt5 import QtCore |
1113 | |
1114 | from openlp.core.common import Registry, Settings |
1115 | +from openlp.core.common.path import Path |
1116 | +from openlp.core.lib import ServiceItemContext |
1117 | from openlp.core.ui import HideMode |
1118 | -from openlp.core.lib import ServiceItemContext |
1119 | from openlp.plugins.presentations.lib.pdfcontroller import PDF_CONTROLLER_FILETYPES |
1120 | |
1121 | log = logging.getLogger(__name__) |
1122 | @@ -325,21 +324,25 @@ |
1123 | is_live = message[1] |
1124 | item = message[0] |
1125 | hide_mode = message[2] |
1126 | - file = item.get_frame_path() |
1127 | + file_path = Path(item.get_frame_path()) |
1128 | self.handler = item.processor |
1129 | # When starting presentation from the servicemanager we convert |
1130 | # PDF/XPS/OXPS-serviceitems into image-serviceitems. When started from the mediamanager |
1131 | # the conversion has already been done at this point. |
1132 | - file_type = os.path.splitext(file.lower())[1][1:] |
1133 | + file_type = file_path.suffix.lower()[1:] |
1134 | if file_type in PDF_CONTROLLER_FILETYPES: |
1135 | - log.debug('Converting from pdf/xps/oxps to images for serviceitem with file {name}'.format(name=file)) |
1136 | + log.debug('Converting from pdf/xps/oxps to images for serviceitem with file {name}'.format(name=file_path)) |
1137 | # Create a copy of the original item, and then clear the original item so it can be filled with images |
1138 | item_cpy = copy.copy(item) |
1139 | item.__init__(None) |
1140 | if is_live: |
1141 | - self.media_item.generate_slide_data(item, item_cpy, False, False, ServiceItemContext.Live, file) |
1142 | + # TODO: To Path object |
1143 | + self.media_item.generate_slide_data(item, item_cpy, False, False, ServiceItemContext.Live, |
1144 | + str(file_path)) |
1145 | else: |
1146 | - self.media_item.generate_slide_data(item, item_cpy, False, False, ServiceItemContext.Preview, file) |
1147 | + # TODO: To Path object |
1148 | + self.media_item.generate_slide_data(item, item_cpy, False, False, ServiceItemContext.Preview, |
1149 | + str(file_path)) |
1150 | # Some of the original serviceitem attributes is needed in the new serviceitem |
1151 | item.footer = item_cpy.footer |
1152 | item.from_service = item_cpy.from_service |
1153 | @@ -352,13 +355,13 @@ |
1154 | self.handler = None |
1155 | else: |
1156 | if self.handler == self.media_item.automatic: |
1157 | - self.handler = self.media_item.find_controller_by_type(file) |
1158 | + self.handler = self.media_item.find_controller_by_type(file_path) |
1159 | if not self.handler: |
1160 | return |
1161 | else: |
1162 | - # the saved handler is not present so need to use one based on file suffix. |
1163 | + # the saved handler is not present so need to use one based on file_path suffix. |
1164 | if not self.controllers[self.handler].available: |
1165 | - self.handler = self.media_item.find_controller_by_type(file) |
1166 | + self.handler = self.media_item.find_controller_by_type(file_path) |
1167 | if not self.handler: |
1168 | return |
1169 | if is_live: |
1170 | @@ -370,7 +373,7 @@ |
1171 | if self.handler is None: |
1172 | self.controller = controller |
1173 | else: |
1174 | - controller.add_handler(self.controllers[self.handler], file, hide_mode, message[3]) |
1175 | + controller.add_handler(self.controllers[self.handler], file_path, hide_mode, message[3]) |
1176 | self.timer.start() |
1177 | |
1178 | def slide(self, message): |
1179 | |
1180 | === modified file 'openlp/plugins/presentations/lib/pdfcontroller.py' |
1181 | --- openlp/plugins/presentations/lib/pdfcontroller.py 2017-08-26 15:06:11 +0000 |
1182 | +++ openlp/plugins/presentations/lib/pdfcontroller.py 2017-09-21 09:08:49 +0000 |
1183 | @@ -23,12 +23,11 @@ |
1184 | import os |
1185 | import logging |
1186 | import re |
1187 | -from shutil import which |
1188 | from subprocess import check_output, CalledProcessError |
1189 | |
1190 | from openlp.core.common import AppLocation, check_binary_exists |
1191 | from openlp.core.common import Settings, is_win |
1192 | -from openlp.core.common.path import Path, path_to_str |
1193 | +from openlp.core.common.path import which |
1194 | from openlp.core.lib import ScreenList |
1195 | from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument |
1196 | |
1197 | @@ -66,11 +65,12 @@ |
1198 | Function that checks whether a binary is either ghostscript or mudraw or neither. |
1199 | Is also used from presentationtab.py |
1200 | |
1201 | - :param program_path:The full path to the binary to check. |
1202 | + :param openlp.core.common.path.Path program_path: The full path to the binary to check. |
1203 | :return: Type of the binary, 'gs' if ghostscript, 'mudraw' if mudraw, None if invalid. |
1204 | + :rtype: str | None |
1205 | """ |
1206 | program_type = None |
1207 | - runlog = check_binary_exists(Path(program_path)) |
1208 | + runlog = check_binary_exists(program_path) |
1209 | # Analyse the output to see it the program is mudraw, ghostscript or neither |
1210 | for line in runlog.splitlines(): |
1211 | decoded_line = line.decode() |
1212 | @@ -107,30 +107,29 @@ |
1213 | :return: True if program to open PDF-files was found, otherwise False. |
1214 | """ |
1215 | log.debug('check_installed Pdf') |
1216 | - self.mudrawbin = '' |
1217 | - self.mutoolbin = '' |
1218 | - self.gsbin = '' |
1219 | + self.mudrawbin = None |
1220 | + self.mutoolbin = None |
1221 | + self.gsbin = None |
1222 | self.also_supports = [] |
1223 | # Use the user defined program if given |
1224 | if Settings().value('presentations/enable_pdf_program'): |
1225 | - pdf_program = path_to_str(Settings().value('presentations/pdf_program')) |
1226 | - program_type = self.process_check_binary(pdf_program) |
1227 | + program_path = Settings().value('presentations/pdf_program') |
1228 | + program_type = self.process_check_binary(program_path) |
1229 | if program_type == 'gs': |
1230 | - self.gsbin = pdf_program |
1231 | + self.gsbin = program_path |
1232 | elif program_type == 'mudraw': |
1233 | - self.mudrawbin = pdf_program |
1234 | + self.mudrawbin = program_path |
1235 | elif program_type == 'mutool': |
1236 | - self.mutoolbin = pdf_program |
1237 | + self.mutoolbin = program_path |
1238 | else: |
1239 | # Fallback to autodetection |
1240 | - application_path = str(AppLocation.get_directory(AppLocation.AppDir)) |
1241 | + application_path = AppLocation.get_directory(AppLocation.AppDir) |
1242 | if is_win(): |
1243 | # for windows we only accept mudraw.exe or mutool.exe in the base folder |
1244 | - application_path = str(AppLocation.get_directory(AppLocation.AppDir)) |
1245 | - if os.path.isfile(os.path.join(application_path, 'mudraw.exe')): |
1246 | - self.mudrawbin = os.path.join(application_path, 'mudraw.exe') |
1247 | - elif os.path.isfile(os.path.join(application_path, 'mutool.exe')): |
1248 | - self.mutoolbin = os.path.join(application_path, 'mutool.exe') |
1249 | + if (application_path / 'mudraw.exe').is_file(): |
1250 | + self.mudrawbin = application_path / 'mudraw.exe' |
1251 | + elif (application_path / 'mutool.exe').is_file(): |
1252 | + self.mutoolbin = application_path / 'mutool.exe' |
1253 | else: |
1254 | DEVNULL = open(os.devnull, 'wb') |
1255 | # First try to find mudraw |
1256 | @@ -143,11 +142,11 @@ |
1257 | self.gsbin = which('gs') |
1258 | # Last option: check if mudraw or mutool is placed in OpenLP base folder |
1259 | if not self.mudrawbin and not self.mutoolbin and not self.gsbin: |
1260 | - application_path = str(AppLocation.get_directory(AppLocation.AppDir)) |
1261 | - if os.path.isfile(os.path.join(application_path, 'mudraw')): |
1262 | - self.mudrawbin = os.path.join(application_path, 'mudraw') |
1263 | - elif os.path.isfile(os.path.join(application_path, 'mutool')): |
1264 | - self.mutoolbin = os.path.join(application_path, 'mutool') |
1265 | + application_path = AppLocation.get_directory(AppLocation.AppDir) |
1266 | + if (application_path / 'mudraw').is_file(): |
1267 | + self.mudrawbin = application_path / 'mudraw' |
1268 | + elif (application_path / 'mutool').is_file(): |
1269 | + self.mutoolbin = application_path / 'mutool' |
1270 | if self.mudrawbin or self.mutoolbin: |
1271 | self.also_supports = ['xps', 'oxps'] |
1272 | return True |
1273 | @@ -172,12 +171,15 @@ |
1274 | image-serviceitem on the fly and present as such. Therefore some of the 'playback' |
1275 | functions is not implemented. |
1276 | """ |
1277 | - def __init__(self, controller, presentation): |
1278 | + def __init__(self, controller, document_path): |
1279 | """ |
1280 | Constructor, store information about the file and initialise. |
1281 | + |
1282 | + :param openlp.core.common.path.Path document_path: Path to the document to load |
1283 | + :rtype: None |
1284 | """ |
1285 | log.debug('Init Presentation Pdf') |
1286 | - PresentationDocument.__init__(self, controller, presentation) |
1287 | + super().__init__(controller, document_path) |
1288 | self.presentation = None |
1289 | self.blanked = False |
1290 | self.hidden = False |
1291 | @@ -200,13 +202,13 @@ |
1292 | :return: The resolution dpi to be used. |
1293 | """ |
1294 | # Use a postscript script to get size of the pdf. It is assumed that all pages have same size |
1295 | - gs_resolution_script = str(AppLocation.get_directory( |
1296 | - AppLocation.PluginsDir)) + '/presentations/lib/ghostscript_get_resolution.ps' |
1297 | + gs_resolution_script = AppLocation.get_directory( |
1298 | + AppLocation.PluginsDir) / 'presentations' / 'lib' / 'ghostscript_get_resolution.ps' |
1299 | # Run the script on the pdf to get the size |
1300 | runlog = [] |
1301 | try: |
1302 | - runlog = check_output([self.controller.gsbin, '-dNOPAUSE', '-dNODISPLAY', '-dBATCH', |
1303 | - '-sFile=' + self.file_path, gs_resolution_script], |
1304 | + runlog = check_output([str(self.controller.gsbin), '-dNOPAUSE', '-dNODISPLAY', '-dBATCH', |
1305 | + '-sFile={file_path}'.format(file_path=self.file_path), str(gs_resolution_script)], |
1306 | startupinfo=self.startupinfo) |
1307 | except CalledProcessError as e: |
1308 | log.debug(' '.join(e.cmd)) |
1309 | @@ -240,46 +242,47 @@ |
1310 | :return: True is loading succeeded, otherwise False. |
1311 | """ |
1312 | log.debug('load_presentation pdf') |
1313 | + temp_dir_path = self.get_temp_folder() |
1314 | # Check if the images has already been created, and if yes load them |
1315 | - if os.path.isfile(os.path.join(self.get_temp_folder(), 'mainslide001.png')): |
1316 | - created_files = sorted(os.listdir(self.get_temp_folder())) |
1317 | - for fn in created_files: |
1318 | - if os.path.isfile(os.path.join(self.get_temp_folder(), fn)): |
1319 | - self.image_files.append(os.path.join(self.get_temp_folder(), fn)) |
1320 | + if (temp_dir_path / 'mainslide001.png').is_file(): |
1321 | + created_files = sorted(temp_dir_path.glob('*')) |
1322 | + for image_path in created_files: |
1323 | + if image_path.is_file(): |
1324 | + self.image_files.append(image_path) |
1325 | self.num_pages = len(self.image_files) |
1326 | return True |
1327 | size = ScreenList().current['size'] |
1328 | # Generate images from PDF that will fit the frame. |
1329 | runlog = '' |
1330 | try: |
1331 | - if not os.path.isdir(self.get_temp_folder()): |
1332 | - os.makedirs(self.get_temp_folder()) |
1333 | + if not temp_dir_path.is_dir(): |
1334 | + temp_dir_path.mkdir(parents=True) |
1335 | # The %03d in the file name is handled by each binary |
1336 | if self.controller.mudrawbin: |
1337 | log.debug('loading presentation using mudraw') |
1338 | - runlog = check_output([self.controller.mudrawbin, '-w', str(size.width()), '-h', str(size.height()), |
1339 | - '-o', os.path.join(self.get_temp_folder(), 'mainslide%03d.png'), self.file_path], |
1340 | + runlog = check_output([str(self.controller.mudrawbin), '-w', str(size.width()), |
1341 | + '-h', str(size.height()), |
1342 | + '-o', str(temp_dir_path / 'mainslide%03d.png'), str(self.file_path)], |
1343 | startupinfo=self.startupinfo) |
1344 | elif self.controller.mutoolbin: |
1345 | log.debug('loading presentation using mutool') |
1346 | - runlog = check_output([self.controller.mutoolbin, 'draw', '-w', str(size.width()), '-h', |
1347 | - str(size.height()), |
1348 | - '-o', os.path.join(self.get_temp_folder(), 'mainslide%03d.png'), self.file_path], |
1349 | + runlog = check_output([str(self.controller.mutoolbin), 'draw', '-w', str(size.width()), |
1350 | + '-h', str(size.height()), '-o', str(temp_dir_path / 'mainslide%03d.png'), |
1351 | + str(self.file_path)], |
1352 | startupinfo=self.startupinfo) |
1353 | elif self.controller.gsbin: |
1354 | log.debug('loading presentation using gs') |
1355 | resolution = self.gs_get_resolution(size) |
1356 | - runlog = check_output([self.controller.gsbin, '-dSAFER', '-dNOPAUSE', '-dBATCH', '-sDEVICE=png16m', |
1357 | - '-r' + str(resolution), '-dTextAlphaBits=4', '-dGraphicsAlphaBits=4', |
1358 | - '-sOutputFile=' + os.path.join(self.get_temp_folder(), 'mainslide%03d.png'), |
1359 | - self.file_path], startupinfo=self.startupinfo) |
1360 | - created_files = sorted(os.listdir(self.get_temp_folder())) |
1361 | - for fn in created_files: |
1362 | - if os.path.isfile(os.path.join(self.get_temp_folder(), fn)): |
1363 | - self.image_files.append(os.path.join(self.get_temp_folder(), fn)) |
1364 | + runlog = check_output([str(self.controller.gsbin), '-dSAFER', '-dNOPAUSE', '-dBATCH', '-sDEVICE=png16m', |
1365 | + '-r{res}'.format(res=resolution), '-dTextAlphaBits=4', '-dGraphicsAlphaBits=4', |
1366 | + '-sOutputFile={output}'.format(output=temp_dir_path / 'mainslide%03d.png'), |
1367 | + str(self.file_path)], startupinfo=self.startupinfo) |
1368 | + created_files = sorted(temp_dir_path.glob('*')) |
1369 | + for image_path in created_files: |
1370 | + if image_path.is_file(): |
1371 | + self.image_files.append(image_path) |
1372 | except Exception as e: |
1373 | - log.debug(e) |
1374 | - log.debug(runlog) |
1375 | + log.exception(runlog) |
1376 | return False |
1377 | self.num_pages = len(self.image_files) |
1378 | # Create thumbnails |
1379 | |
1380 | === modified file 'openlp/plugins/presentations/lib/powerpointcontroller.py' |
1381 | --- openlp/plugins/presentations/lib/powerpointcontroller.py 2017-07-04 23:13:51 +0000 |
1382 | +++ openlp/plugins/presentations/lib/powerpointcontroller.py 2017-09-21 09:08:49 +0000 |
1383 | @@ -120,15 +120,16 @@ |
1384 | Class which holds information and controls a single presentation. |
1385 | """ |
1386 | |
1387 | - def __init__(self, controller, presentation): |
1388 | + def __init__(self, controller, document_path): |
1389 | """ |
1390 | Constructor, store information about the file and initialise. |
1391 | |
1392 | :param controller: |
1393 | - :param presentation: |
1394 | + :param openlp.core.common.path.Path document_path: Path to the document to load |
1395 | + :rtype: None |
1396 | """ |
1397 | log.debug('Init Presentation Powerpoint') |
1398 | - super(PowerpointDocument, self).__init__(controller, presentation) |
1399 | + super().__init__(controller, document_path) |
1400 | self.presentation = None |
1401 | self.index_map = {} |
1402 | self.slide_count = 0 |
1403 | @@ -145,7 +146,7 @@ |
1404 | try: |
1405 | if not self.controller.process: |
1406 | self.controller.start_process() |
1407 | - self.controller.process.Presentations.Open(os.path.normpath(self.file_path), False, False, False) |
1408 | + self.controller.process.Presentations.Open(str(self.file_path), False, False, False) |
1409 | self.presentation = self.controller.process.Presentations(self.controller.process.Presentations.Count) |
1410 | self.create_thumbnails() |
1411 | self.create_titles_and_notes() |
1412 | @@ -177,7 +178,7 @@ |
1413 | if not self.presentation.Slides(num + 1).SlideShowTransition.Hidden: |
1414 | self.index_map[key] = num + 1 |
1415 | self.presentation.Slides(num + 1).Export( |
1416 | - os.path.join(self.get_thumbnail_folder(), 'slide{key:d}.png'.format(key=key)), 'png', 320, 240) |
1417 | + str(self.get_thumbnail_folder() / 'slide{key:d}.png'.format(key=key)), 'png', 320, 240) |
1418 | key += 1 |
1419 | self.slide_count = key - 1 |
1420 | |
1421 | @@ -363,9 +364,8 @@ |
1422 | width=size.width(), |
1423 | horizontal=(right - left))) |
1424 | log.debug('window title: {title}'.format(title=window_title)) |
1425 | - filename_root, filename_ext = os.path.splitext(os.path.basename(self.file_path)) |
1426 | if size.y() == top and size.height() == (bottom - top) and size.x() == left and \ |
1427 | - size.width() == (right - left) and filename_root in window_title: |
1428 | + size.width() == (right - left) and self.file_path.stem in window_title: |
1429 | log.debug('Found a match and will save the handle') |
1430 | self.presentation_hwnd = hwnd |
1431 | # Stop powerpoint from flashing in the taskbar |
1432 | |
1433 | === modified file 'openlp/plugins/presentations/lib/pptviewcontroller.py' |
1434 | --- openlp/plugins/presentations/lib/pptviewcontroller.py 2017-08-01 20:59:41 +0000 |
1435 | +++ openlp/plugins/presentations/lib/pptviewcontroller.py 2017-09-21 09:08:49 +0000 |
1436 | @@ -85,9 +85,9 @@ |
1437 | if self.process: |
1438 | return |
1439 | log.debug('start PPTView') |
1440 | - dll_path = os.path.join(str(AppLocation.get_directory(AppLocation.AppDir)), |
1441 | - 'plugins', 'presentations', 'lib', 'pptviewlib', 'pptviewlib.dll') |
1442 | - self.process = cdll.LoadLibrary(dll_path) |
1443 | + dll_path = AppLocation.get_directory(AppLocation.AppDir) \ |
1444 | + / 'plugins' / 'presentations' / 'lib' / 'pptviewlib' / 'pptviewlib.dll' |
1445 | + self.process = cdll.LoadLibrary(str(dll_path)) |
1446 | if log.isEnabledFor(logging.DEBUG): |
1447 | self.process.SetDebug(1) |
1448 | |
1449 | @@ -104,12 +104,15 @@ |
1450 | """ |
1451 | Class which holds information and controls a single presentation. |
1452 | """ |
1453 | - def __init__(self, controller, presentation): |
1454 | + def __init__(self, controller, document_path): |
1455 | """ |
1456 | Constructor, store information about the file and initialise. |
1457 | + |
1458 | + :param openlp.core.common.path.Path document_path: File path to the document to load |
1459 | + :rtype: None |
1460 | """ |
1461 | log.debug('Init Presentation PowerPoint') |
1462 | - super(PptviewDocument, self).__init__(controller, presentation) |
1463 | + super().__init__(controller, document_path) |
1464 | self.presentation = None |
1465 | self.ppt_id = None |
1466 | self.blanked = False |
1467 | @@ -121,17 +124,16 @@ |
1468 | the background PptView task started earlier. |
1469 | """ |
1470 | log.debug('LoadPresentation') |
1471 | - temp_folder = self.get_temp_folder() |
1472 | + temp_path = self.get_temp_folder() |
1473 | size = ScreenList().current['size'] |
1474 | rect = RECT(size.x(), size.y(), size.right(), size.bottom()) |
1475 | - self.file_path = os.path.normpath(self.file_path) |
1476 | - preview_path = os.path.join(temp_folder, 'slide') |
1477 | + preview_path = temp_path / 'slide' |
1478 | # Ensure that the paths are null terminated |
1479 | - byte_file_path = self.file_path.encode('utf-16-le') + b'\0' |
1480 | - preview_path = preview_path.encode('utf-16-le') + b'\0' |
1481 | - if not os.path.isdir(temp_folder): |
1482 | - os.makedirs(temp_folder) |
1483 | - self.ppt_id = self.controller.process.OpenPPT(byte_file_path, None, rect, preview_path) |
1484 | + file_path_utf16 = str(self.file_path).encode('utf-16-le') + b'\0' |
1485 | + preview_path_utf16 = str(preview_path).encode('utf-16-le') + b'\0' |
1486 | + if not temp_path.is_dir(): |
1487 | + temp_path.mkdir(parents=True) |
1488 | + self.ppt_id = self.controller.process.OpenPPT(file_path_utf16, None, rect, preview_path_utf16) |
1489 | if self.ppt_id >= 0: |
1490 | self.create_thumbnails() |
1491 | self.stop_presentation() |
1492 | @@ -148,7 +150,7 @@ |
1493 | return |
1494 | log.debug('create_thumbnails proceeding') |
1495 | for idx in range(self.get_slide_count()): |
1496 | - path = '{folder}\\slide{index}.bmp'.format(folder=self.get_temp_folder(), index=str(idx + 1)) |
1497 | + path = self.get_temp_folder() / 'slide{index:d}.bmp'.format(index=idx + 1) |
1498 | self.convert_thumbnail(path, idx + 1) |
1499 | |
1500 | def create_titles_and_notes(self): |
1501 | @@ -161,13 +163,12 @@ |
1502 | """ |
1503 | titles = None |
1504 | notes = None |
1505 | - filename = os.path.normpath(self.file_path) |
1506 | # let's make sure we have a valid zipped presentation |
1507 | - if os.path.exists(filename) and zipfile.is_zipfile(filename): |
1508 | + if self.file_path.exists() and zipfile.is_zipfile(str(self.file_path)): |
1509 | namespaces = {"p": "http://schemas.openxmlformats.org/presentationml/2006/main", |
1510 | "a": "http://schemas.openxmlformats.org/drawingml/2006/main"} |
1511 | # open the file |
1512 | - with zipfile.ZipFile(filename) as zip_file: |
1513 | + with zipfile.ZipFile(str(self.file_path)) as zip_file: |
1514 | # find the presentation.xml to get the slide count |
1515 | with zip_file.open('ppt/presentation.xml') as pres: |
1516 | tree = ElementTree.parse(pres) |
1517 | |
1518 | === modified file 'openlp/plugins/presentations/lib/presentationcontroller.py' |
1519 | --- openlp/plugins/presentations/lib/presentationcontroller.py 2017-08-25 20:03:25 +0000 |
1520 | +++ openlp/plugins/presentations/lib/presentationcontroller.py 2017-09-21 09:08:49 +0000 |
1521 | @@ -19,15 +19,12 @@ |
1522 | # with this program; if not, write to the Free Software Foundation, Inc., 59 # |
1523 | # Temple Place, Suite 330, Boston, MA 02111-1307 USA # |
1524 | ############################################################################### |
1525 | - |
1526 | import logging |
1527 | -import os |
1528 | -import shutil |
1529 | |
1530 | from PyQt5 import QtCore |
1531 | |
1532 | from openlp.core.common import Registry, AppLocation, Settings, check_directory_exists, md5_hash |
1533 | -from openlp.core.common.path import Path |
1534 | +from openlp.core.common.path import Path, rmtree |
1535 | from openlp.core.lib import create_thumb, validate_thumb |
1536 | |
1537 | log = logging.getLogger(__name__) |
1538 | @@ -86,20 +83,27 @@ |
1539 | Returns a path to an image containing a preview for the requested slide |
1540 | |
1541 | """ |
1542 | - def __init__(self, controller, name): |
1543 | + def __init__(self, controller, document_path): |
1544 | """ |
1545 | Constructor for the PresentationController class |
1546 | + |
1547 | + :param controller: |
1548 | + :param openlp.core.common.path.Path document_path: Path to the document to load. |
1549 | + :rtype: None |
1550 | """ |
1551 | self.controller = controller |
1552 | - self._setup(name) |
1553 | + self._setup(document_path) |
1554 | |
1555 | - def _setup(self, name): |
1556 | + def _setup(self, document_path): |
1557 | """ |
1558 | Run some initial setup. This method is separate from __init__ in order to mock it out in tests. |
1559 | + |
1560 | + :param openlp.core.common.path.Path document_path: Path to the document to load. |
1561 | + :rtype: None |
1562 | """ |
1563 | self.slide_number = 0 |
1564 | - self.file_path = name |
1565 | - check_directory_exists(Path(self.get_thumbnail_folder())) |
1566 | + self.file_path = document_path |
1567 | + check_directory_exists(self.get_thumbnail_folder()) |
1568 | |
1569 | def load_presentation(self): |
1570 | """ |
1571 | @@ -116,49 +120,54 @@ |
1572 | a file, e.g. thumbnails |
1573 | """ |
1574 | try: |
1575 | - if os.path.exists(self.get_thumbnail_folder()): |
1576 | - shutil.rmtree(self.get_thumbnail_folder()) |
1577 | - if os.path.exists(self.get_temp_folder()): |
1578 | - shutil.rmtree(self.get_temp_folder()) |
1579 | + thumbnail_folder_path = self.get_thumbnail_folder() |
1580 | + temp_folder_path = self.get_temp_folder() |
1581 | + if thumbnail_folder_path.exists(): |
1582 | + rmtree(thumbnail_folder_path) |
1583 | + if temp_folder_path.exists(): |
1584 | + rmtree(temp_folder_path) |
1585 | except OSError: |
1586 | log.exception('Failed to delete presentation controller files') |
1587 | |
1588 | - def get_file_name(self): |
1589 | - """ |
1590 | - Return just the filename of the presentation, without the directory |
1591 | - """ |
1592 | - return os.path.split(self.file_path)[1] |
1593 | - |
1594 | def get_thumbnail_folder(self): |
1595 | """ |
1596 | The location where thumbnail images will be stored |
1597 | + |
1598 | + :return: The path to the thumbnail |
1599 | + :rtype: openlp.core.common.path.Path |
1600 | """ |
1601 | # TODO: If statement can be removed when the upgrade path from 2.0.x to 2.2.x is no longer needed |
1602 | if Settings().value('presentations/thumbnail_scheme') == 'md5': |
1603 | - folder = md5_hash(self.file_path.encode('utf-8')) |
1604 | + folder = md5_hash(bytes(self.file_path)) |
1605 | else: |
1606 | - folder = self.get_file_name() |
1607 | - return os.path.join(self.controller.thumbnail_folder, folder) |
1608 | + folder = self.file_path.name |
1609 | + return Path(self.controller.thumbnail_folder, folder) |
1610 | |
1611 | def get_temp_folder(self): |
1612 | """ |
1613 | The location where thumbnail images will be stored |
1614 | + |
1615 | + :return: The path to the temporary file folder |
1616 | + :rtype: openlp.core.common.path.Path |
1617 | """ |
1618 | # TODO: If statement can be removed when the upgrade path from 2.0.x to 2.2.x is no longer needed |
1619 | if Settings().value('presentations/thumbnail_scheme') == 'md5': |
1620 | - folder = md5_hash(self.file_path.encode('utf-8')) |
1621 | + folder = md5_hash(bytes(self.file_path)) |
1622 | else: |
1623 | - folder = folder = self.get_file_name() |
1624 | - return os.path.join(self.controller.temp_folder, folder) |
1625 | + folder = self.file_path.name |
1626 | + return Path(self.controller.temp_folder, folder) |
1627 | |
1628 | def check_thumbnails(self): |
1629 | """ |
1630 | - Returns ``True`` if the thumbnail images exist and are more recent than the powerpoint file. |
1631 | + Check that the last thumbnail image exists and is valid and are more recent than the powerpoint file. |
1632 | + |
1633 | + :return: If the thumbnail is valid |
1634 | + :rtype: bool |
1635 | """ |
1636 | - last_image = self.get_thumbnail_path(self.get_slide_count(), True) |
1637 | - if not (last_image and os.path.isfile(last_image)): |
1638 | + last_image_path = self.get_thumbnail_path(self.get_slide_count(), True) |
1639 | + if not (last_image_path and last_image_path.is_file()): |
1640 | return False |
1641 | - return validate_thumb(self.file_path, last_image) |
1642 | + return validate_thumb(Path(self.file_path), Path(last_image_path)) |
1643 | |
1644 | def close_presentation(self): |
1645 | """ |
1646 | @@ -241,25 +250,31 @@ |
1647 | """ |
1648 | pass |
1649 | |
1650 | - def convert_thumbnail(self, file, idx): |
1651 | + def convert_thumbnail(self, image_path, index): |
1652 | """ |
1653 | Convert the slide image the application made to a scaled 360px height .png image. |
1654 | + |
1655 | + :param openlp.core.common.path.Path image_path: Path to the image to create a thumb nail of |
1656 | + :param int index: The index of the slide to create the thumbnail for. |
1657 | + :rtype: None |
1658 | """ |
1659 | if self.check_thumbnails(): |
1660 | return |
1661 | - if os.path.isfile(file): |
1662 | - thumb_path = self.get_thumbnail_path(idx, False) |
1663 | - create_thumb(file, thumb_path, False, QtCore.QSize(-1, 360)) |
1664 | + if image_path.is_file(): |
1665 | + thumb_path = self.get_thumbnail_path(index, False) |
1666 | + create_thumb(str(image_path), str(thumb_path), False, QtCore.QSize(-1, 360)) |
1667 | |
1668 | - def get_thumbnail_path(self, slide_no, check_exists): |
1669 | + def get_thumbnail_path(self, slide_no, check_exists=False): |
1670 | """ |
1671 | Returns an image path containing a preview for the requested slide |
1672 | |
1673 | - :param slide_no: The slide an image is required for, starting at 1 |
1674 | - :param check_exists: |
1675 | + :param int slide_no: The slide an image is required for, starting at 1 |
1676 | + :param bool check_exists: Check if the generated path exists |
1677 | + :return: The path, or None if the :param:`check_exists` is True and the file does not exist |
1678 | + :rtype: openlp.core.common.path.Path | None |
1679 | """ |
1680 | - path = os.path.join(self.get_thumbnail_folder(), self.controller.thumbnail_prefix + str(slide_no) + '.png') |
1681 | - if os.path.isfile(path) or not check_exists: |
1682 | + path = self.get_thumbnail_folder() / (self.controller.thumbnail_prefix + str(slide_no) + '.png') |
1683 | + if path.is_file() or not check_exists: |
1684 | return path |
1685 | else: |
1686 | return None |
1687 | @@ -302,44 +317,38 @@ |
1688 | Reads the titles from the titles file and |
1689 | the notes files and returns the content in two lists |
1690 | """ |
1691 | - titles = [] |
1692 | notes = [] |
1693 | - titles_file = os.path.join(self.get_thumbnail_folder(), 'titles.txt') |
1694 | - if os.path.exists(titles_file): |
1695 | + titles_path = self.get_thumbnail_folder() / 'titles.txt' |
1696 | + try: |
1697 | + titles = titles_path.read_text().splitlines() |
1698 | + except: |
1699 | + log.exception('Failed to open/read existing titles file') |
1700 | + titles = [] |
1701 | + for slide_no, title in enumerate(titles, 1): |
1702 | + notes_path = self.get_thumbnail_folder() / 'slideNotes{number:d}.txt'.format(number=slide_no) |
1703 | try: |
1704 | - with open(titles_file, encoding='utf-8') as fi: |
1705 | - titles = fi.read().splitlines() |
1706 | + note = notes_path.read_text() |
1707 | except: |
1708 | - log.exception('Failed to open/read existing titles file') |
1709 | - titles = [] |
1710 | - for slide_no, title in enumerate(titles, 1): |
1711 | - notes_file = os.path.join(self.get_thumbnail_folder(), 'slideNotes{number:d}.txt'.format(number=slide_no)) |
1712 | - note = '' |
1713 | - if os.path.exists(notes_file): |
1714 | - try: |
1715 | - with open(notes_file, encoding='utf-8') as fn: |
1716 | - note = fn.read() |
1717 | - except: |
1718 | - log.exception('Failed to open/read notes file') |
1719 | - note = '' |
1720 | + log.exception('Failed to open/read notes file') |
1721 | + note = '' |
1722 | notes.append(note) |
1723 | return titles, notes |
1724 | |
1725 | def save_titles_and_notes(self, titles, notes): |
1726 | """ |
1727 | - Performs the actual persisting of titles to the titles.txt |
1728 | - and notes to the slideNote%.txt |
1729 | + Performs the actual persisting of titles to the titles.txt and notes to the slideNote%.txt |
1730 | + |
1731 | + :param list[str] titles: The titles to save |
1732 | + :param list[str] notes: The notes to save |
1733 | + :rtype: None |
1734 | """ |
1735 | if titles: |
1736 | - titles_file = os.path.join(self.get_thumbnail_folder(), 'titles.txt') |
1737 | - with open(titles_file, mode='wt', encoding='utf-8') as fo: |
1738 | - fo.writelines(titles) |
1739 | + titles_path = self.get_thumbnail_folder() / 'titles.txt' |
1740 | + titles_path.write_text('\n'.join(titles)) |
1741 | if notes: |
1742 | for slide_no, note in enumerate(notes, 1): |
1743 | - notes_file = os.path.join(self.get_thumbnail_folder(), |
1744 | - 'slideNotes{number:d}.txt'.format(number=slide_no)) |
1745 | - with open(notes_file, mode='wt', encoding='utf-8') as fn: |
1746 | - fn.write(note) |
1747 | + notes_path = self.get_thumbnail_folder() / 'slideNotes{number:d}.txt'.format(number=slide_no) |
1748 | + notes_path.write_text(note) |
1749 | |
1750 | |
1751 | class PresentationController(object): |
1752 | @@ -416,12 +425,11 @@ |
1753 | self.document_class = document_class |
1754 | self.settings_section = self.plugin.settings_section |
1755 | self.available = None |
1756 | - self.temp_folder = os.path.join(str(AppLocation.get_section_data_path(self.settings_section)), name) |
1757 | - self.thumbnail_folder = os.path.join( |
1758 | - str(AppLocation.get_section_data_path(self.settings_section)), 'thumbnails') |
1759 | + self.temp_folder = AppLocation.get_section_data_path(self.settings_section) / name |
1760 | + self.thumbnail_folder = AppLocation.get_section_data_path(self.settings_section) / 'thumbnails' |
1761 | self.thumbnail_prefix = 'slide' |
1762 | - check_directory_exists(Path(self.thumbnail_folder)) |
1763 | - check_directory_exists(Path(self.temp_folder)) |
1764 | + check_directory_exists(self.thumbnail_folder) |
1765 | + check_directory_exists(self.temp_folder) |
1766 | |
1767 | def enabled(self): |
1768 | """ |
1769 | @@ -456,11 +464,15 @@ |
1770 | log.debug('Kill') |
1771 | self.close_presentation() |
1772 | |
1773 | - def add_document(self, name): |
1774 | + def add_document(self, document_path): |
1775 | """ |
1776 | Called when a new presentation document is opened. |
1777 | + |
1778 | + :param openlp.core.common.path.Path document_path: Path to the document to load |
1779 | + :return: The document |
1780 | + :rtype: PresentationDocument |
1781 | """ |
1782 | - document = self.document_class(self, name) |
1783 | + document = self.document_class(self, document_path) |
1784 | self.docs.append(document) |
1785 | return document |
1786 | |
1787 | |
1788 | === modified file 'openlp/plugins/presentations/lib/presentationtab.py' |
1789 | --- openlp/plugins/presentations/lib/presentationtab.py 2017-08-26 15:06:11 +0000 |
1790 | +++ openlp/plugins/presentations/lib/presentationtab.py 2017-09-21 09:08:49 +0000 |
1791 | @@ -38,7 +38,6 @@ |
1792 | """ |
1793 | Constructor |
1794 | """ |
1795 | - self.parent = parent |
1796 | self.controllers = controllers |
1797 | super(PresentationTab, self).__init__(parent, title, visible_title, icon_path) |
1798 | self.activated = False |
1799 | @@ -194,7 +193,7 @@ |
1800 | pdf_program_path = self.program_path_edit.path |
1801 | enable_pdf_program = self.pdf_program_check_box.checkState() |
1802 | # If the given program is blank disable using the program |
1803 | - if not pdf_program_path: |
1804 | + if pdf_program_path is None: |
1805 | enable_pdf_program = 0 |
1806 | if pdf_program_path != Settings().value(self.settings_section + '/pdf_program'): |
1807 | Settings().setValue(self.settings_section + '/pdf_program', pdf_program_path) |
1808 | @@ -220,9 +219,11 @@ |
1809 | |
1810 | def on_program_path_edit_path_changed(self, new_path): |
1811 | """ |
1812 | - Select the mudraw or ghostscript binary that should be used. |
1813 | + Handle the `pathEditChanged` signal from program_path_edit |
1814 | + |
1815 | + :param openlp.core.common.path.Path new_path: File path to the new program |
1816 | + :rtype: None |
1817 | """ |
1818 | - new_path = path_to_str(new_path) |
1819 | if new_path: |
1820 | if not PdfController.process_check_binary(new_path): |
1821 | critical_error_message_box(UiStrings().Error, |
1822 | |
1823 | === modified file 'openlp/plugins/remotes/deploy.py' |
1824 | --- openlp/plugins/remotes/deploy.py 2017-08-12 20:58:16 +0000 |
1825 | +++ openlp/plugins/remotes/deploy.py 2017-09-21 09:08:49 +0000 |
1826 | @@ -64,6 +64,6 @@ |
1827 | file_size = get_url_file_size('https://get.openlp.org/webclient/site.zip') |
1828 | callback.setRange(0, file_size) |
1829 | if url_get_file(callback, '{host}{name}'.format(host='https://get.openlp.org/webclient/', name='site.zip'), |
1830 | - os.path.join(str(AppLocation.get_section_data_path('remotes')), 'site.zip'), |
1831 | + AppLocation.get_section_data_path('remotes') / 'site.zip', |
1832 | sha256=sha256): |
1833 | deploy_zipfile(str(AppLocation.get_section_data_path('remotes')), 'site.zip') |
1834 | |
1835 | === modified file 'openlp/plugins/songs/reporting.py' |
1836 | --- openlp/plugins/songs/reporting.py 2016-12-31 11:01:36 +0000 |
1837 | +++ openlp/plugins/songs/reporting.py 2017-09-21 09:08:49 +0000 |
1838 | @@ -25,10 +25,10 @@ |
1839 | import csv |
1840 | import logging |
1841 | |
1842 | -from PyQt5 import QtWidgets |
1843 | - |
1844 | from openlp.core.common import Registry, translate |
1845 | +from openlp.core.common.path import Path |
1846 | from openlp.core.lib.ui import critical_error_message_box |
1847 | +from openlp.core.ui.lib.filedialog import FileDialog |
1848 | from openlp.plugins.songs.lib.db import Song |
1849 | |
1850 | |
1851 | @@ -42,58 +42,55 @@ |
1852 | """ |
1853 | main_window = Registry().get('main_window') |
1854 | plugin = Registry().get('songs').plugin |
1855 | - report_file_name, filter_used = QtWidgets.QFileDialog.getSaveFileName( |
1856 | + report_file_path, filter_used = FileDialog.getSaveFileName( |
1857 | main_window, |
1858 | translate('SongPlugin.ReportSongList', 'Save File'), |
1859 | - translate('SongPlugin.ReportSongList', 'song_extract.csv'), |
1860 | + Path(translate('SongPlugin.ReportSongList', 'song_extract.csv')), |
1861 | translate('SongPlugin.ReportSongList', 'CSV format (*.csv)')) |
1862 | |
1863 | - if not report_file_name: |
1864 | + if report_file_path is None: |
1865 | main_window.error_message( |
1866 | translate('SongPlugin.ReportSongList', 'Output Path Not Selected'), |
1867 | - translate('SongPlugin.ReportSongList', 'You have not set a valid output location for your ' |
1868 | - 'report. \nPlease select an existing path ' |
1869 | - 'on your computer.') |
1870 | + translate('SongPlugin.ReportSongList', 'You have not set a valid output location for your report. \n' |
1871 | + 'Please select an existing path on your computer.') |
1872 | ) |
1873 | return |
1874 | - if not report_file_name.endswith('csv'): |
1875 | - report_file_name += '.csv' |
1876 | - file_handle = None |
1877 | + report_file_path.with_suffix('.csv') |
1878 | Registry().get('application').set_busy_cursor() |
1879 | try: |
1880 | - file_handle = open(report_file_name, 'wt') |
1881 | - fieldnames = ('Title', 'Alternative Title', 'Copyright', 'Author(s)', 'Song Book', 'Topic') |
1882 | - writer = csv.DictWriter(file_handle, fieldnames=fieldnames, quoting=csv.QUOTE_ALL) |
1883 | - headers = dict((n, n) for n in fieldnames) |
1884 | - writer.writerow(headers) |
1885 | - song_list = plugin.manager.get_all_objects(Song) |
1886 | - for song in song_list: |
1887 | - author_list = [] |
1888 | - for author_song in song.authors_songs: |
1889 | - author_list.append(author_song.author.display_name) |
1890 | - author_string = ' | '.join(author_list) |
1891 | - book_list = [] |
1892 | - for book_song in song.songbook_entries: |
1893 | - if hasattr(book_song, 'entry') and book_song.entry: |
1894 | - book_list.append('{name} #{entry}'.format(name=book_song.songbook.name, entry=book_song.entry)) |
1895 | - book_string = ' | '.join(book_list) |
1896 | - topic_list = [] |
1897 | - for topic_song in song.topics: |
1898 | - if hasattr(topic_song, 'name'): |
1899 | - topic_list.append(topic_song.name) |
1900 | - topic_string = ' | '.join(topic_list) |
1901 | - writer.writerow({'Title': song.title, |
1902 | - 'Alternative Title': song.alternate_title, |
1903 | - 'Copyright': song.copyright, |
1904 | - 'Author(s)': author_string, |
1905 | - 'Song Book': book_string, |
1906 | - 'Topic': topic_string}) |
1907 | - Registry().get('application').set_normal_cursor() |
1908 | - main_window.information_message( |
1909 | - translate('SongPlugin.ReportSongList', 'Report Creation'), |
1910 | - translate('SongPlugin.ReportSongList', |
1911 | - 'Report \n{name} \nhas been successfully created. ').format(name=report_file_name) |
1912 | - ) |
1913 | + with report_file_path.open('wt') as file_handle: |
1914 | + fieldnames = ('Title', 'Alternative Title', 'Copyright', 'Author(s)', 'Song Book', 'Topic') |
1915 | + writer = csv.DictWriter(file_handle, fieldnames=fieldnames, quoting=csv.QUOTE_ALL) |
1916 | + headers = dict((n, n) for n in fieldnames) |
1917 | + writer.writerow(headers) |
1918 | + song_list = plugin.manager.get_all_objects(Song) |
1919 | + for song in song_list: |
1920 | + author_list = [] |
1921 | + for author_song in song.authors_songs: |
1922 | + author_list.append(author_song.author.display_name) |
1923 | + author_string = ' | '.join(author_list) |
1924 | + book_list = [] |
1925 | + for book_song in song.songbook_entries: |
1926 | + if hasattr(book_song, 'entry') and book_song.entry: |
1927 | + book_list.append('{name} #{entry}'.format(name=book_song.songbook.name, entry=book_song.entry)) |
1928 | + book_string = ' | '.join(book_list) |
1929 | + topic_list = [] |
1930 | + for topic_song in song.topics: |
1931 | + if hasattr(topic_song, 'name'): |
1932 | + topic_list.append(topic_song.name) |
1933 | + topic_string = ' | '.join(topic_list) |
1934 | + writer.writerow({'Title': song.title, |
1935 | + 'Alternative Title': song.alternate_title, |
1936 | + 'Copyright': song.copyright, |
1937 | + 'Author(s)': author_string, |
1938 | + 'Song Book': book_string, |
1939 | + 'Topic': topic_string}) |
1940 | + Registry().get('application').set_normal_cursor() |
1941 | + main_window.information_message( |
1942 | + translate('SongPlugin.ReportSongList', 'Report Creation'), |
1943 | + translate('SongPlugin.ReportSongList', |
1944 | + 'Report \n{name} \nhas been successfully created. ').format(name=report_file_path) |
1945 | + ) |
1946 | except OSError as ose: |
1947 | Registry().get('application').set_normal_cursor() |
1948 | log.exception('Failed to write out song usage records') |
1949 | @@ -101,6 +98,3 @@ |
1950 | translate('SongPlugin.ReportSongList', |
1951 | 'An error occurred while extracting: {error}' |
1952 | ).format(error=ose.strerror)) |
1953 | - finally: |
1954 | - if file_handle: |
1955 | - file_handle.close() |
1956 | |
1957 | === modified file 'tests/functional/openlp_core_common/test_httputils.py' |
1958 | --- tests/functional/openlp_core_common/test_httputils.py 2017-06-09 20:53:13 +0000 |
1959 | +++ tests/functional/openlp_core_common/test_httputils.py 2017-09-21 09:08:49 +0000 |
1960 | @@ -29,6 +29,7 @@ |
1961 | from unittest.mock import MagicMock, patch |
1962 | |
1963 | from openlp.core.common.httputils import get_user_agent, get_web_page, get_url_file_size, url_get_file, ping |
1964 | +from openlp.core.common.path import Path |
1965 | |
1966 | from tests.helpers.testmixin import TestMixin |
1967 | |
1968 | @@ -267,7 +268,7 @@ |
1969 | mocked_urlopen.side_effect = socket.timeout() |
1970 | |
1971 | # WHEN: Attempt to retrieve a file |
1972 | - url_get_file(MagicMock(), url='http://localhost/test', f_path=self.tempfile) |
1973 | + url_get_file(MagicMock(), url='http://localhost/test', f_path=Path(self.tempfile)) |
1974 | |
1975 | # THEN: socket.timeout should have been caught |
1976 | # NOTE: Test is if $tmpdir/tempfile is still there, then test fails since ftw deletes bad downloaded files |
1977 | |
1978 | === modified file 'tests/functional/openlp_core_common/test_path.py' |
1979 | --- tests/functional/openlp_core_common/test_path.py 2017-08-25 20:03:25 +0000 |
1980 | +++ tests/functional/openlp_core_common/test_path.py 2017-09-21 09:08:49 +0000 |
1981 | @@ -24,8 +24,209 @@ |
1982 | """ |
1983 | import os |
1984 | from unittest import TestCase |
1985 | - |
1986 | -from openlp.core.common.path import Path, path_to_str, str_to_path |
1987 | +from unittest.mock import ANY, MagicMock, patch |
1988 | + |
1989 | +from openlp.core.common.path import Path, copy, copyfile, copytree, path_to_str, replace_params, rmtree, str_to_path, \ |
1990 | + which |
1991 | + |
1992 | + |
1993 | +class TestShutil(TestCase): |
1994 | + """ |
1995 | + Tests for the :mod:`openlp.core.common.path` module |
1996 | + """ |
1997 | + def test_replace_params_no_params(self): |
1998 | + """ |
1999 | + Test replace_params when called with and empty tuple instead of parameters to replace |
2000 | + """ |
2001 | + # GIVEN: Some test data |
2002 | + test_args = (1, 2) |
2003 | + test_kwargs = {'arg3': 3, 'arg4': 4} |
2004 | + test_params = tuple() |
2005 | + |
2006 | + # WHEN: Calling replace_params |
2007 | + result_args, result_kwargs = replace_params(test_args, test_kwargs, test_params) |
2008 | + |
2009 | + # THEN: The positional and keyword args should not have changed |
2010 | + self.assertEqual(test_args, result_args) |
2011 | + self.assertEqual(test_kwargs, result_kwargs) |
2012 | + |
2013 | + def test_replace_params_params(self): |
2014 | + """ |
2015 | + Test replace_params when given a positional and a keyword argument to change |
2016 | + """ |
2017 | + # GIVEN: Some test data |
2018 | + test_args = (1, 2) |
2019 | + test_kwargs = {'arg3': 3, 'arg4': 4} |
2020 | + test_params = ((1, 'arg2', str), (2, 'arg3', str)) |
2021 | + |
2022 | + # WHEN: Calling replace_params |
2023 | + result_args, result_kwargs = replace_params(test_args, test_kwargs, test_params) |
2024 | + |
2025 | + # THEN: The positional and keyword args should have have changed |
2026 | + self.assertEqual(result_args, (1, '2')) |
2027 | + self.assertEqual(result_kwargs, {'arg3': '3', 'arg4': 4}) |
2028 | + |
2029 | + def test_copy(self): |
2030 | + """ |
2031 | + Test :func:`openlp.core.common.path.copy` |
2032 | + """ |
2033 | + # GIVEN: A mocked `shutil.copy` which returns a test path as a string |
2034 | + with patch('openlp.core.common.path.shutil.copy', return_value=os.path.join('destination', 'test', 'path')) \ |
2035 | + as mocked_shutil_copy: |
2036 | + |
2037 | + # WHEN: Calling :func:`openlp.core.common.path.copy` with the src and dst parameters as Path object types |
2038 | + result = copy(Path('source', 'test', 'path'), Path('destination', 'test', 'path')) |
2039 | + |
2040 | + # THEN: :func:`shutil.copy` should have been called with the str equivalents of the Path objects. |
2041 | + # :func:`openlp.core.common.path.copy` should return the str type result of calling |
2042 | + # :func:`shutil.copy` as a Path object. |
2043 | + mocked_shutil_copy.assert_called_once_with(os.path.join('source', 'test', 'path'), |
2044 | + os.path.join('destination', 'test', 'path')) |
2045 | + self.assertEqual(result, Path('destination', 'test', 'path')) |
2046 | + |
2047 | + def test_copy_follow_optional_params(self): |
2048 | + """ |
2049 | + Test :func:`openlp.core.common.path.copy` when follow_symlinks is set to false |
2050 | + """ |
2051 | + # GIVEN: A mocked `shutil.copy` |
2052 | + with patch('openlp.core.common.path.shutil.copy', return_value='') as mocked_shutil_copy: |
2053 | + |
2054 | + # WHEN: Calling :func:`openlp.core.common.path.copy` with :param:`follow_symlinks` set to False |
2055 | + copy(Path('source', 'test', 'path'), Path('destination', 'test', 'path'), follow_symlinks=False) |
2056 | + |
2057 | + # THEN: :func:`shutil.copy` should have been called with :param:`follow_symlinks` set to false |
2058 | + mocked_shutil_copy.assert_called_once_with(ANY, ANY, follow_symlinks=False) |
2059 | + |
2060 | + def test_copyfile(self): |
2061 | + """ |
2062 | + Test :func:`openlp.core.common.path.copyfile` |
2063 | + """ |
2064 | + # GIVEN: A mocked :func:`shutil.copyfile` which returns a test path as a string |
2065 | + with patch('openlp.core.common.path.shutil.copyfile', |
2066 | + return_value=os.path.join('destination', 'test', 'path')) as mocked_shutil_copyfile: |
2067 | + |
2068 | + # WHEN: Calling :func:`openlp.core.common.path.copyfile` with the src and dst parameters as Path object |
2069 | + # types |
2070 | + result = copyfile(Path('source', 'test', 'path'), Path('destination', 'test', 'path')) |
2071 | + |
2072 | + # THEN: :func:`shutil.copyfile` should have been called with the str equivalents of the Path objects. |
2073 | + # :func:`openlp.core.common.path.copyfile` should return the str type result of calling |
2074 | + # :func:`shutil.copyfile` as a Path object. |
2075 | + mocked_shutil_copyfile.assert_called_once_with(os.path.join('source', 'test', 'path'), |
2076 | + os.path.join('destination', 'test', 'path')) |
2077 | + self.assertEqual(result, Path('destination', 'test', 'path')) |
2078 | + |
2079 | + def test_copyfile_optional_params(self): |
2080 | + """ |
2081 | + Test :func:`openlp.core.common.path.copyfile` when follow_symlinks is set to false |
2082 | + """ |
2083 | + # GIVEN: A mocked :func:`shutil.copyfile` |
2084 | + with patch('openlp.core.common.path.shutil.copyfile', return_value='') as mocked_shutil_copyfile: |
2085 | + |
2086 | + # WHEN: Calling :func:`openlp.core.common.path.copyfile` with :param:`follow_symlinks` set to False |
2087 | + copyfile(Path('source', 'test', 'path'), Path('destination', 'test', 'path'), follow_symlinks=False) |
2088 | + |
2089 | + # THEN: :func:`shutil.copyfile` should have been called with the optional parameters, with out any of the |
2090 | + # values being modified |
2091 | + mocked_shutil_copyfile.assert_called_once_with(ANY, ANY, follow_symlinks=False) |
2092 | + |
2093 | + def test_copytree(self): |
2094 | + """ |
2095 | + Test :func:`openlp.core.common.path.copytree` |
2096 | + """ |
2097 | + # GIVEN: A mocked :func:`shutil.copytree` which returns a test path as a string |
2098 | + with patch('openlp.core.common.path.shutil.copytree', |
2099 | + return_value=os.path.join('destination', 'test', 'path')) as mocked_shutil_copytree: |
2100 | + |
2101 | + # WHEN: Calling :func:`openlp.core.common.path.copytree` with the src and dst parameters as Path object |
2102 | + # types |
2103 | + result = copytree(Path('source', 'test', 'path'), Path('destination', 'test', 'path')) |
2104 | + |
2105 | + # THEN: :func:`shutil.copytree` should have been called with the str equivalents of the Path objects. |
2106 | + # :func:`openlp.core.common.path.copytree` should return the str type result of calling |
2107 | + # :func:`shutil.copytree` as a Path object. |
2108 | + mocked_shutil_copytree.assert_called_once_with(os.path.join('source', 'test', 'path'), |
2109 | + os.path.join('destination', 'test', 'path')) |
2110 | + self.assertEqual(result, Path('destination', 'test', 'path')) |
2111 | + |
2112 | + def test_copytree_optional_params(self): |
2113 | + """ |
2114 | + Test :func:`openlp.core.common.path.copytree` when optional parameters are passed |
2115 | + """ |
2116 | + # GIVEN: A mocked :func:`shutil.copytree` |
2117 | + with patch('openlp.core.common.path.shutil.copytree', return_value='') as mocked_shutil_copytree: |
2118 | + mocked_ignore = MagicMock() |
2119 | + mocked_copy_function = MagicMock() |
2120 | + |
2121 | + # WHEN: Calling :func:`openlp.core.common.path.copytree` with the optional parameters set |
2122 | + copytree(Path('source', 'test', 'path'), Path('destination', 'test', 'path'), symlinks=True, |
2123 | + ignore=mocked_ignore, copy_function=mocked_copy_function, ignore_dangling_symlinks=True) |
2124 | + |
2125 | + # THEN: :func:`shutil.copytree` should have been called with the optional parameters, with out any of the |
2126 | + # values being modified |
2127 | + mocked_shutil_copytree.assert_called_once_with(ANY, ANY, symlinks=True, ignore=mocked_ignore, |
2128 | + copy_function=mocked_copy_function, |
2129 | + ignore_dangling_symlinks=True) |
2130 | + |
2131 | + def test_rmtree(self): |
2132 | + """ |
2133 | + Test :func:`rmtree` |
2134 | + """ |
2135 | + # GIVEN: A mocked :func:`shutil.rmtree` |
2136 | + with patch('openlp.core.common.path.shutil.rmtree', return_value=None) as mocked_shutil_rmtree: |
2137 | + |
2138 | + # WHEN: Calling :func:`openlp.core.common.path.rmtree` with the path parameter as Path object type |
2139 | + result = rmtree(Path('test', 'path')) |
2140 | + |
2141 | + # THEN: :func:`shutil.rmtree` should have been called with the str equivalents of the Path object. |
2142 | + mocked_shutil_rmtree.assert_called_once_with(os.path.join('test', 'path')) |
2143 | + self.assertIsNone(result) |
2144 | + |
2145 | + def test_rmtree_optional_params(self): |
2146 | + """ |
2147 | + Test :func:`openlp.core.common.path.rmtree` when optional parameters are passed |
2148 | + """ |
2149 | + # GIVEN: A mocked :func:`shutil.rmtree` |
2150 | + with patch('openlp.core.common.path.shutil.rmtree', return_value='') as mocked_shutil_rmtree: |
2151 | + mocked_on_error = MagicMock() |
2152 | + |
2153 | + # WHEN: Calling :func:`openlp.core.common.path.rmtree` with :param:`ignore_errors` set to True and |
2154 | + # :param:`onerror` set to a mocked object |
2155 | + rmtree(Path('test', 'path'), ignore_errors=True, onerror=mocked_on_error) |
2156 | + |
2157 | + # THEN: :func:`shutil.rmtree` should have been called with the optional parameters, with out any of the |
2158 | + # values being modified |
2159 | + mocked_shutil_rmtree.assert_called_once_with(ANY, ignore_errors=True, onerror=mocked_on_error) |
2160 | + |
2161 | + def test_which_no_command(self): |
2162 | + """ |
2163 | + Test :func:`openlp.core.common.path.which` when the command is not found. |
2164 | + """ |
2165 | + # GIVEN: A mocked :func:`shutil.which` when the command is not found. |
2166 | + with patch('openlp.core.common.path.shutil.which', return_value=None) as mocked_shutil_which: |
2167 | + |
2168 | + # WHEN: Calling :func:`openlp.core.common.path.which` with a command that does not exist. |
2169 | + result = which('no_command') |
2170 | + |
2171 | + # THEN: :func:`shutil.which` should have been called with the command, and :func:`which` should return None. |
2172 | + mocked_shutil_which.assert_called_once_with('no_command') |
2173 | + self.assertIsNone(result) |
2174 | + |
2175 | + def test_which_command(self): |
2176 | + """ |
2177 | + Test :func:`openlp.core.common.path.which` when a command has been found. |
2178 | + """ |
2179 | + # GIVEN: A mocked :func:`shutil.which` when the command is found. |
2180 | + with patch('openlp.core.common.path.shutil.which', |
2181 | + return_value=os.path.join('path', 'to', 'command')) as mocked_shutil_which: |
2182 | + |
2183 | + # WHEN: Calling :func:`openlp.core.common.path.which` with a command that exists. |
2184 | + result = which('command') |
2185 | + |
2186 | + # THEN: :func:`shutil.which` should have been called with the command, and :func:`which` should return a |
2187 | + # Path object equivalent of the command path. |
2188 | + mocked_shutil_which.assert_called_once_with('command') |
2189 | + self.assertEqual(result, Path('path', 'to', 'command')) |
2190 | |
2191 | |
2192 | class TestPath(TestCase): |
2193 | |
2194 | === modified file 'tests/functional/openlp_core_lib/test_lib.py' |
2195 | --- tests/functional/openlp_core_lib/test_lib.py 2017-08-25 20:03:25 +0000 |
2196 | +++ tests/functional/openlp_core_lib/test_lib.py 2017-09-21 09:08:49 +0000 |
2197 | @@ -32,7 +32,7 @@ |
2198 | from openlp.core.common.path import Path |
2199 | from openlp.core.lib import FormattingTags, build_icon, check_item_selected, clean_tags, compare_chord_lyric, \ |
2200 | create_separated_list, create_thumb, expand_chords, expand_chords_for_printing, expand_tags, find_formatting_tags, \ |
2201 | - get_text_file_string, image_to_byte, replace_params, resize_image, str_to_bool, validate_thumb |
2202 | + get_text_file_string, image_to_byte, resize_image, str_to_bool, validate_thumb |
2203 | |
2204 | TEST_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'resources')) |
2205 | |
2206 | @@ -595,93 +595,46 @@ |
2207 | Test the validate_thumb() function when the thumbnail does not exist |
2208 | """ |
2209 | # GIVEN: A mocked out os module, with path.exists returning False, and fake paths to a file and a thumb |
2210 | - with patch('openlp.core.lib.os') as mocked_os: |
2211 | - file_path = 'path/to/file' |
2212 | - thumb_path = 'path/to/thumb' |
2213 | - mocked_os.path.exists.return_value = False |
2214 | + with patch.object(Path, 'exists', return_value=False) as mocked_path_exists: |
2215 | + file_path = Path('path', 'to', 'file') |
2216 | + thumb_path = Path('path', 'to', 'thumb') |
2217 | |
2218 | # WHEN: we run the validate_thumb() function |
2219 | result = validate_thumb(file_path, thumb_path) |
2220 | |
2221 | # THEN: we should have called a few functions, and the result should be False |
2222 | - mocked_os.path.exists.assert_called_with(thumb_path) |
2223 | - assert result is False, 'The result should be False' |
2224 | + thumb_path.exists.assert_called_once_with() |
2225 | + self.assertFalse(result, 'The result should be False') |
2226 | |
2227 | def test_validate_thumb_file_exists_and_newer(self): |
2228 | """ |
2229 | Test the validate_thumb() function when the thumbnail exists and has a newer timestamp than the file |
2230 | """ |
2231 | - # GIVEN: A mocked out os module, functions rigged to work for us, and fake paths to a file and a thumb |
2232 | - with patch('openlp.core.lib.os') as mocked_os: |
2233 | - file_path = 'path/to/file' |
2234 | - thumb_path = 'path/to/thumb' |
2235 | - file_mocked_stat = MagicMock() |
2236 | - file_mocked_stat.st_mtime = datetime.now() |
2237 | - thumb_mocked_stat = MagicMock() |
2238 | - thumb_mocked_stat.st_mtime = datetime.now() + timedelta(seconds=10) |
2239 | - mocked_os.path.exists.return_value = True |
2240 | - mocked_os.stat.side_effect = [file_mocked_stat, thumb_mocked_stat] |
2241 | + with patch.object(Path, 'exists'), patch.object(Path, 'stat'): |
2242 | + # GIVEN: Mocked file_path and thumb_path which return different values fo the modified times |
2243 | + file_path = MagicMock(**{'stat.return_value': MagicMock(st_mtime=10)}) |
2244 | + thumb_path = MagicMock(**{'exists.return_value': True, 'stat.return_value': MagicMock(st_mtime=11)}) |
2245 | |
2246 | # WHEN: we run the validate_thumb() function |
2247 | + result = validate_thumb(file_path, thumb_path) |
2248 | |
2249 | - # THEN: we should have called a few functions, and the result should be True |
2250 | - # mocked_os.path.exists.assert_called_with(thumb_path) |
2251 | + # THEN: `validate_thumb` should return True |
2252 | + self.assertTrue(result) |
2253 | |
2254 | def test_validate_thumb_file_exists_and_older(self): |
2255 | """ |
2256 | Test the validate_thumb() function when the thumbnail exists but is older than the file |
2257 | """ |
2258 | - # GIVEN: A mocked out os module, functions rigged to work for us, and fake paths to a file and a thumb |
2259 | - with patch('openlp.core.lib.os') as mocked_os: |
2260 | - file_path = 'path/to/file' |
2261 | - thumb_path = 'path/to/thumb' |
2262 | - file_mocked_stat = MagicMock() |
2263 | - file_mocked_stat.st_mtime = datetime.now() |
2264 | - thumb_mocked_stat = MagicMock() |
2265 | - thumb_mocked_stat.st_mtime = datetime.now() - timedelta(seconds=10) |
2266 | - mocked_os.path.exists.return_value = True |
2267 | - mocked_os.stat.side_effect = lambda fname: file_mocked_stat if fname == file_path else thumb_mocked_stat |
2268 | - |
2269 | - # WHEN: we run the validate_thumb() function |
2270 | - result = validate_thumb(file_path, thumb_path) |
2271 | - |
2272 | - # THEN: we should have called a few functions, and the result should be False |
2273 | - mocked_os.path.exists.assert_called_with(thumb_path) |
2274 | - mocked_os.stat.assert_any_call(file_path) |
2275 | - mocked_os.stat.assert_any_call(thumb_path) |
2276 | - assert result is False, 'The result should be False' |
2277 | - |
2278 | - def test_replace_params_no_params(self): |
2279 | - """ |
2280 | - Test replace_params when called with and empty tuple instead of parameters to replace |
2281 | - """ |
2282 | - # GIVEN: Some test data |
2283 | - test_args = (1, 2) |
2284 | - test_kwargs = {'arg3': 3, 'arg4': 4} |
2285 | - test_params = tuple() |
2286 | - |
2287 | - # WHEN: Calling replace_params |
2288 | - result_args, result_kwargs = replace_params(test_args, test_kwargs, test_params) |
2289 | - |
2290 | - # THEN: The positional and keyword args should not have changed |
2291 | - self.assertEqual(test_args, result_args) |
2292 | - self.assertEqual(test_kwargs, result_kwargs) |
2293 | - |
2294 | - def test_replace_params_params(self): |
2295 | - """ |
2296 | - Test replace_params when given a positional and a keyword argument to change |
2297 | - """ |
2298 | - # GIVEN: Some test data |
2299 | - test_args = (1, 2) |
2300 | - test_kwargs = {'arg3': 3, 'arg4': 4} |
2301 | - test_params = ((1, 'arg2', str), (2, 'arg3', str)) |
2302 | - |
2303 | - # WHEN: Calling replace_params |
2304 | - result_args, result_kwargs = replace_params(test_args, test_kwargs, test_params) |
2305 | - |
2306 | - # THEN: The positional and keyword args should have have changed |
2307 | - self.assertEqual(result_args, (1, '2')) |
2308 | - self.assertEqual(result_kwargs, {'arg3': '3', 'arg4': 4}) |
2309 | + # GIVEN: Mocked file_path and thumb_path which return different values fo the modified times |
2310 | + file_path = MagicMock(**{'stat.return_value': MagicMock(st_mtime=10)}) |
2311 | + thumb_path = MagicMock(**{'exists.return_value': True, 'stat.return_value': MagicMock(st_mtime=9)}) |
2312 | + |
2313 | + # WHEN: we run the validate_thumb() function |
2314 | + result = validate_thumb(file_path, thumb_path) |
2315 | + |
2316 | + # THEN: `validate_thumb` should return False |
2317 | + thumb_path.stat.assert_called_once_with() |
2318 | + self.assertFalse(result, 'The result should be False') |
2319 | |
2320 | def test_resize_thumb(self): |
2321 | """ |
2322 | |
2323 | === modified file 'tests/functional/openlp_core_ui/test_exceptionform.py' |
2324 | --- tests/functional/openlp_core_ui/test_exceptionform.py 2017-08-26 15:06:11 +0000 |
2325 | +++ tests/functional/openlp_core_ui/test_exceptionform.py 2017-09-21 09:08:49 +0000 |
2326 | @@ -103,7 +103,7 @@ |
2327 | os.remove(self.tempfile) |
2328 | |
2329 | @patch("openlp.core.ui.exceptionform.Ui_ExceptionDialog") |
2330 | - @patch("openlp.core.ui.exceptionform.QtWidgets.QFileDialog") |
2331 | + @patch("openlp.core.ui.exceptionform.FileDialog") |
2332 | @patch("openlp.core.ui.exceptionform.QtCore.QUrl") |
2333 | @patch("openlp.core.ui.exceptionform.QtCore.QUrlQuery.addQueryItem") |
2334 | @patch("openlp.core.ui.exceptionform.Qt") |
2335 | |
2336 | === modified file 'tests/functional/openlp_plugins/presentations/test_impresscontroller.py' |
2337 | --- tests/functional/openlp_plugins/presentations/test_impresscontroller.py 2017-06-08 21:36:17 +0000 |
2338 | +++ tests/functional/openlp_plugins/presentations/test_impresscontroller.py 2017-09-21 09:08:49 +0000 |
2339 | @@ -24,13 +24,12 @@ |
2340 | """ |
2341 | from unittest import TestCase |
2342 | from unittest.mock import MagicMock |
2343 | -import os |
2344 | import shutil |
2345 | from tempfile import mkdtemp |
2346 | |
2347 | from openlp.core.common import Settings |
2348 | -from openlp.plugins.presentations.lib.impresscontroller import \ |
2349 | - ImpressController, ImpressDocument, TextType |
2350 | +from openlp.core.common.path import Path |
2351 | +from openlp.plugins.presentations.lib.impresscontroller import ImpressController, ImpressDocument, TextType |
2352 | from openlp.plugins.presentations.presentationplugin import __default_settings__ |
2353 | |
2354 | from tests.utils.constants import TEST_RESOURCES_PATH |
2355 | @@ -82,7 +81,7 @@ |
2356 | mocked_plugin = MagicMock() |
2357 | mocked_plugin.settings_section = 'presentations' |
2358 | Settings().extend_default_settings(__default_settings__) |
2359 | - self.file_name = os.path.join(TEST_RESOURCES_PATH, 'presentations', 'test.pptx') |
2360 | + self.file_name = Path(TEST_RESOURCES_PATH, 'presentations', 'test.pptx') |
2361 | self.ppc = ImpressController(mocked_plugin) |
2362 | self.doc = ImpressDocument(self.ppc, self.file_name) |
2363 | |
2364 | |
2365 | === modified file 'tests/functional/openlp_plugins/presentations/test_mediaitem.py' |
2366 | --- tests/functional/openlp_plugins/presentations/test_mediaitem.py 2017-04-24 05:17:55 +0000 |
2367 | +++ tests/functional/openlp_plugins/presentations/test_mediaitem.py 2017-09-21 09:08:49 +0000 |
2368 | @@ -26,6 +26,7 @@ |
2369 | from unittest.mock import patch, MagicMock, call |
2370 | |
2371 | from openlp.core.common import Registry |
2372 | +from openlp.core.common.path import Path |
2373 | from openlp.plugins.presentations.lib.mediaitem import PresentationMediaItem |
2374 | |
2375 | from tests.helpers.testmixin import TestMixin |
2376 | @@ -92,17 +93,18 @@ |
2377 | """ |
2378 | # GIVEN: A mocked controller, and mocked os.path.getmtime |
2379 | mocked_controller = MagicMock() |
2380 | - mocked_doc = MagicMock() |
2381 | + mocked_doc = MagicMock(**{'get_thumbnail_path.return_value': Path()}) |
2382 | mocked_controller.add_document.return_value = mocked_doc |
2383 | mocked_controller.supports = ['tmp'] |
2384 | self.media_item.controllers = { |
2385 | 'Mocked': mocked_controller |
2386 | } |
2387 | - presentation_file = 'file.tmp' |
2388 | - with patch('openlp.plugins.presentations.lib.mediaitem.os.path.getmtime') as mocked_getmtime, \ |
2389 | - patch('openlp.plugins.presentations.lib.mediaitem.os.path.exists') as mocked_exists: |
2390 | - mocked_getmtime.side_effect = [100, 200] |
2391 | - mocked_exists.return_value = True |
2392 | + |
2393 | + thmub_path = MagicMock(st_mtime=100) |
2394 | + file_path = MagicMock(st_mtime=400) |
2395 | + with patch.object(Path, 'stat', side_effect=[thmub_path, file_path]), \ |
2396 | + patch.object(Path, 'exists', return_value=True): |
2397 | + presentation_file = Path('file.tmp') |
2398 | |
2399 | # WHEN: calling clean_up_thumbnails |
2400 | self.media_item.clean_up_thumbnails(presentation_file, True) |
2401 | @@ -123,9 +125,8 @@ |
2402 | self.media_item.controllers = { |
2403 | 'Mocked': mocked_controller |
2404 | } |
2405 | - presentation_file = 'file.tmp' |
2406 | - with patch('openlp.plugins.presentations.lib.mediaitem.os.path.exists') as mocked_exists: |
2407 | - mocked_exists.return_value = False |
2408 | + presentation_file = Path('file.tmp') |
2409 | + with patch.object(Path, 'exists', return_value=False): |
2410 | |
2411 | # WHEN: calling clean_up_thumbnails |
2412 | self.media_item.clean_up_thumbnails(presentation_file, True) |
2413 | |
2414 | === modified file 'tests/functional/openlp_plugins/presentations/test_pdfcontroller.py' |
2415 | --- tests/functional/openlp_plugins/presentations/test_pdfcontroller.py 2017-04-24 05:17:55 +0000 |
2416 | +++ tests/functional/openlp_plugins/presentations/test_pdfcontroller.py 2017-09-21 09:08:49 +0000 |
2417 | @@ -32,6 +32,7 @@ |
2418 | |
2419 | from openlp.plugins.presentations.lib.pdfcontroller import PdfController, PdfDocument |
2420 | from openlp.core.common import Settings |
2421 | +from openlp.core.common.path import Path |
2422 | from openlp.core.lib import ScreenList |
2423 | |
2424 | from tests.utils.constants import TEST_RESOURCES_PATH |
2425 | @@ -66,8 +67,8 @@ |
2426 | self.desktop.screenGeometry.return_value = SCREEN['size'] |
2427 | self.screens = ScreenList.create(self.desktop) |
2428 | Settings().extend_default_settings(__default_settings__) |
2429 | - self.temp_folder = mkdtemp() |
2430 | - self.thumbnail_folder = mkdtemp() |
2431 | + self.temp_folder = Path(mkdtemp()) |
2432 | + self.thumbnail_folder = Path(mkdtemp()) |
2433 | self.mock_plugin = MagicMock() |
2434 | self.mock_plugin.settings_section = self.temp_folder |
2435 | |
2436 | @@ -77,8 +78,8 @@ |
2437 | """ |
2438 | del self.screens |
2439 | self.destroy_settings() |
2440 | - shutil.rmtree(self.thumbnail_folder) |
2441 | - shutil.rmtree(self.temp_folder) |
2442 | + shutil.rmtree(str(self.thumbnail_folder)) |
2443 | + shutil.rmtree(str(self.temp_folder)) |
2444 | |
2445 | def test_constructor(self): |
2446 | """ |
2447 | @@ -98,7 +99,7 @@ |
2448 | Test loading of a Pdf using the PdfController |
2449 | """ |
2450 | # GIVEN: A Pdf-file |
2451 | - test_file = os.path.join(TEST_RESOURCES_PATH, 'presentations', 'pdf_test1.pdf') |
2452 | + test_file = Path(TEST_RESOURCES_PATH, 'presentations', 'pdf_test1.pdf') |
2453 | |
2454 | # WHEN: The Pdf is loaded |
2455 | controller = PdfController(plugin=self.mock_plugin) |
2456 | @@ -118,7 +119,7 @@ |
2457 | Test loading of a Pdf and check size of generate pictures |
2458 | """ |
2459 | # GIVEN: A Pdf-file |
2460 | - test_file = os.path.join(TEST_RESOURCES_PATH, 'presentations', 'pdf_test1.pdf') |
2461 | + test_file = Path(TEST_RESOURCES_PATH, 'presentations', 'pdf_test1.pdf') |
2462 | |
2463 | # WHEN: The Pdf is loaded |
2464 | controller = PdfController(plugin=self.mock_plugin) |
2465 | @@ -131,7 +132,7 @@ |
2466 | |
2467 | # THEN: The load should succeed and pictures should be created and have been scales to fit the screen |
2468 | self.assertTrue(loaded, 'The loading of the PDF should succeed.') |
2469 | - image = QtGui.QImage(os.path.join(self.temp_folder, 'pdf_test1.pdf', 'mainslide001.png')) |
2470 | + image = QtGui.QImage(os.path.join(str(self.temp_folder), 'pdf_test1.pdf', 'mainslide001.png')) |
2471 | # Based on the converter used the resolution will differ a bit |
2472 | if controller.gsbin: |
2473 | self.assertEqual(760, image.height(), 'The height should be 760') |
2474 | |
2475 | === modified file 'tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py' |
2476 | --- tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py 2017-05-30 18:42:35 +0000 |
2477 | +++ tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py 2017-09-21 09:08:49 +0000 |
2478 | @@ -22,7 +22,6 @@ |
2479 | """ |
2480 | This module contains tests for the pptviewcontroller module of the Presentations plugin. |
2481 | """ |
2482 | -import os |
2483 | import shutil |
2484 | from tempfile import mkdtemp |
2485 | from unittest import TestCase |
2486 | @@ -30,6 +29,7 @@ |
2487 | |
2488 | from openlp.plugins.presentations.lib.pptviewcontroller import PptviewDocument, PptviewController |
2489 | from openlp.core.common import is_win |
2490 | +from openlp.core.common.path import Path |
2491 | |
2492 | from tests.helpers.testmixin import TestMixin |
2493 | from tests.utils.constants import TEST_RESOURCES_PATH |
2494 | @@ -184,7 +184,7 @@ |
2495 | """ |
2496 | # GIVEN: mocked PresentationController.save_titles_and_notes and a pptx file |
2497 | doc = PptviewDocument(self.mock_controller, self.mock_presentation) |
2498 | - doc.file_path = os.path.join(TEST_RESOURCES_PATH, 'presentations', 'test.pptx') |
2499 | + doc.file_path = Path(TEST_RESOURCES_PATH, 'presentations', 'test.pptx') |
2500 | doc.save_titles_and_notes = MagicMock() |
2501 | |
2502 | # WHEN reading the titles and notes |
2503 | @@ -201,13 +201,13 @@ |
2504 | """ |
2505 | # GIVEN: mocked PresentationController.save_titles_and_notes and an nonexistent file |
2506 | with patch('builtins.open') as mocked_open, \ |
2507 | - patch('openlp.plugins.presentations.lib.pptviewcontroller.os.path.exists') as mocked_exists, \ |
2508 | + patch.object(Path, 'exists') as mocked_path_exists, \ |
2509 | patch('openlp.plugins.presentations.lib.presentationcontroller.check_directory_exists') as \ |
2510 | mocked_dir_exists: |
2511 | - mocked_exists.return_value = False |
2512 | + mocked_path_exists.return_value = False |
2513 | mocked_dir_exists.return_value = False |
2514 | doc = PptviewDocument(self.mock_controller, self.mock_presentation) |
2515 | - doc.file_path = 'Idontexist.pptx' |
2516 | + doc.file_path = Path('Idontexist.pptx') |
2517 | doc.save_titles_and_notes = MagicMock() |
2518 | |
2519 | # WHEN: Reading the titles and notes |
2520 | @@ -215,7 +215,7 @@ |
2521 | |
2522 | # THEN: File existens should have been checked, and not have been opened. |
2523 | doc.save_titles_and_notes.assert_called_once_with(None, None) |
2524 | - mocked_exists.assert_any_call('Idontexist.pptx') |
2525 | + mocked_path_exists.assert_called_with() |
2526 | self.assertEqual(mocked_open.call_count, 0, 'There should be no calls to open a file.') |
2527 | |
2528 | def test_create_titles_and_notes_invalid_file(self): |
2529 | @@ -228,7 +228,7 @@ |
2530 | mocked_is_zf.return_value = False |
2531 | mocked_open.filesize = 10 |
2532 | doc = PptviewDocument(self.mock_controller, self.mock_presentation) |
2533 | - doc.file_path = os.path.join(TEST_RESOURCES_PATH, 'presentations', 'test.ppt') |
2534 | + doc.file_path = Path(TEST_RESOURCES_PATH, 'presentations', 'test.ppt') |
2535 | doc.save_titles_and_notes = MagicMock() |
2536 | |
2537 | # WHEN: reading the titles and notes |
2538 | |
2539 | === modified file 'tests/functional/openlp_plugins/presentations/test_presentationcontroller.py' |
2540 | --- tests/functional/openlp_plugins/presentations/test_presentationcontroller.py 2017-08-25 20:03:25 +0000 |
2541 | +++ tests/functional/openlp_plugins/presentations/test_presentationcontroller.py 2017-09-21 09:08:49 +0000 |
2542 | @@ -23,9 +23,8 @@ |
2543 | Functional tests to test the PresentationController and PresentationDocument |
2544 | classes and related methods. |
2545 | """ |
2546 | -import os |
2547 | from unittest import TestCase |
2548 | -from unittest.mock import MagicMock, mock_open, patch |
2549 | +from unittest.mock import MagicMock, call, patch |
2550 | |
2551 | from openlp.core.common.path import Path |
2552 | from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument |
2553 | @@ -67,23 +66,18 @@ |
2554 | Test PresentationDocument.save_titles_and_notes method with two valid lists |
2555 | """ |
2556 | # GIVEN: two lists of length==2 and a mocked open and get_thumbnail_folder |
2557 | - mocked_open = mock_open() |
2558 | - with patch('builtins.open', mocked_open), patch(FOLDER_TO_PATCH) as mocked_get_thumbnail_folder: |
2559 | + with patch('openlp.plugins.presentations.lib.presentationcontroller.Path.write_text') as mocked_write_text, \ |
2560 | + patch(FOLDER_TO_PATCH) as mocked_get_thumbnail_folder: |
2561 | titles = ['uno', 'dos'] |
2562 | notes = ['one', 'two'] |
2563 | |
2564 | # WHEN: calling save_titles_and_notes |
2565 | - mocked_get_thumbnail_folder.return_value = 'test' |
2566 | + mocked_get_thumbnail_folder.return_value = Path('test') |
2567 | self.document.save_titles_and_notes(titles, notes) |
2568 | |
2569 | # THEN: the last call to open should have been for slideNotes2.txt |
2570 | - mocked_open.assert_any_call(os.path.join('test', 'titles.txt'), mode='wt', encoding='utf-8') |
2571 | - mocked_open.assert_any_call(os.path.join('test', 'slideNotes1.txt'), mode='wt', encoding='utf-8') |
2572 | - mocked_open.assert_any_call(os.path.join('test', 'slideNotes2.txt'), mode='wt', encoding='utf-8') |
2573 | - self.assertEqual(mocked_open.call_count, 3, 'There should be exactly three files opened') |
2574 | - mocked_open().writelines.assert_called_once_with(['uno', 'dos']) |
2575 | - mocked_open().write.assert_any_call('one') |
2576 | - mocked_open().write.assert_any_call('two') |
2577 | + self.assertEqual(mocked_write_text.call_count, 3, 'There should be exactly three files written') |
2578 | + mocked_write_text.assert_has_calls([call('uno\ndos'), call('one'), call('two')]) |
2579 | |
2580 | def test_save_titles_and_notes_with_None(self): |
2581 | """ |
2582 | @@ -107,10 +101,11 @@ |
2583 | """ |
2584 | # GIVEN: A mocked open, get_thumbnail_folder and exists |
2585 | |
2586 | - with patch('builtins.open', mock_open(read_data='uno\ndos\n')) as mocked_open, \ |
2587 | + with patch('openlp.plugins.presentations.lib.presentationcontroller.Path.read_text', |
2588 | + return_value='uno\ndos\n') as mocked_read_text, \ |
2589 | patch(FOLDER_TO_PATCH) as mocked_get_thumbnail_folder, \ |
2590 | - patch('openlp.plugins.presentations.lib.presentationcontroller.os.path.exists') as mocked_exists: |
2591 | - mocked_get_thumbnail_folder.return_value = 'test' |
2592 | + patch('openlp.plugins.presentations.lib.presentationcontroller.Path.exists') as mocked_exists: |
2593 | + mocked_get_thumbnail_folder.return_value = Path('test') |
2594 | mocked_exists.return_value = True |
2595 | |
2596 | # WHEN: calling get_titles_and_notes |
2597 | @@ -121,45 +116,36 @@ |
2598 | self.assertEqual(len(result_titles), 2, 'There should be two items in the titles') |
2599 | self.assertIs(type(result_notes), list, 'result_notes should be of type list') |
2600 | self.assertEqual(len(result_notes), 2, 'There should be two items in the notes') |
2601 | - self.assertEqual(mocked_open.call_count, 3, 'Three files should be opened') |
2602 | - mocked_open.assert_any_call(os.path.join('test', 'titles.txt'), encoding='utf-8') |
2603 | - mocked_open.assert_any_call(os.path.join('test', 'slideNotes1.txt'), encoding='utf-8') |
2604 | - mocked_open.assert_any_call(os.path.join('test', 'slideNotes2.txt'), encoding='utf-8') |
2605 | - self.assertEqual(mocked_exists.call_count, 3, 'Three files should have been checked') |
2606 | + self.assertEqual(mocked_read_text.call_count, 3, 'Three files should be read') |
2607 | |
2608 | def test_get_titles_and_notes_with_file_not_found(self): |
2609 | """ |
2610 | Test PresentationDocument.get_titles_and_notes method with file not found |
2611 | """ |
2612 | # GIVEN: A mocked open, get_thumbnail_folder and exists |
2613 | - with patch('builtins.open') as mocked_open, \ |
2614 | - patch(FOLDER_TO_PATCH) as mocked_get_thumbnail_folder, \ |
2615 | - patch('openlp.plugins.presentations.lib.presentationcontroller.os.path.exists') as mocked_exists: |
2616 | - mocked_get_thumbnail_folder.return_value = 'test' |
2617 | - mocked_exists.return_value = False |
2618 | + with patch('openlp.plugins.presentations.lib.presentationcontroller.Path.read_text') as mocked_read_text, \ |
2619 | + patch(FOLDER_TO_PATCH) as mocked_get_thumbnail_folder: |
2620 | + mocked_read_text.side_effect = FileNotFoundError() |
2621 | + mocked_get_thumbnail_folder.return_value = Path('test') |
2622 | |
2623 | # WHEN: calling get_titles_and_notes |
2624 | result_titles, result_notes = self.document.get_titles_and_notes() |
2625 | |
2626 | # THEN: it should return two empty lists |
2627 | - self.assertIs(type(result_titles), list, 'result_titles should be of type list') |
2628 | + self.assertIsInstance(result_titles, list, 'result_titles should be of type list') |
2629 | self.assertEqual(len(result_titles), 0, 'there be no titles') |
2630 | - self.assertIs(type(result_notes), list, 'result_notes should be a list') |
2631 | + self.assertIsInstance(result_notes, list, 'result_notes should be a list') |
2632 | self.assertEqual(len(result_notes), 0, 'but the list should be empty') |
2633 | - self.assertEqual(mocked_open.call_count, 0, 'No calls to open files') |
2634 | - self.assertEqual(mocked_exists.call_count, 1, 'There should be one call to file exists') |
2635 | |
2636 | def test_get_titles_and_notes_with_file_error(self): |
2637 | """ |
2638 | Test PresentationDocument.get_titles_and_notes method with file errors |
2639 | """ |
2640 | # GIVEN: A mocked open, get_thumbnail_folder and exists |
2641 | - with patch('builtins.open') as mocked_open, \ |
2642 | - patch(FOLDER_TO_PATCH) as mocked_get_thumbnail_folder, \ |
2643 | - patch('openlp.plugins.presentations.lib.presentationcontroller.os.path.exists') as mocked_exists: |
2644 | - mocked_get_thumbnail_folder.return_value = 'test' |
2645 | - mocked_exists.return_value = True |
2646 | - mocked_open.side_effect = IOError() |
2647 | + with patch('openlp.plugins.presentations.lib.presentationcontroller.Path.read_text') as mocked_read_text, \ |
2648 | + patch(FOLDER_TO_PATCH) as mocked_get_thumbnail_folder: |
2649 | + mocked_read_text.side_effect = IOError() |
2650 | + mocked_get_thumbnail_folder.return_value = Path('test') |
2651 | |
2652 | # WHEN: calling get_titles_and_notes |
2653 | result_titles, result_notes = self.document.get_titles_and_notes() |
2654 | @@ -180,18 +166,16 @@ |
2655 | patch('openlp.plugins.presentations.lib.presentationcontroller.check_directory_exists') |
2656 | self.get_thumbnail_folder_patcher = \ |
2657 | patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder') |
2658 | - self.os_patcher = patch('openlp.plugins.presentations.lib.presentationcontroller.os') |
2659 | self._setup_patcher = \ |
2660 | patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument._setup') |
2661 | |
2662 | self.mock_check_directory_exists = self.check_directory_exists_patcher.start() |
2663 | self.mock_get_thumbnail_folder = self.get_thumbnail_folder_patcher.start() |
2664 | - self.mock_os = self.os_patcher.start() |
2665 | self.mock_setup = self._setup_patcher.start() |
2666 | |
2667 | self.mock_controller = MagicMock() |
2668 | |
2669 | - self.mock_get_thumbnail_folder.return_value = 'returned/path/' |
2670 | + self.mock_get_thumbnail_folder.return_value = Path('returned/path/') |
2671 | |
2672 | def tearDown(self): |
2673 | """ |
2674 | @@ -199,7 +183,6 @@ |
2675 | """ |
2676 | self.check_directory_exists_patcher.stop() |
2677 | self.get_thumbnail_folder_patcher.stop() |
2678 | - self.os_patcher.stop() |
2679 | self._setup_patcher.stop() |
2680 | |
2681 | def test_initialise_presentation_document(self): |
2682 | @@ -227,7 +210,7 @@ |
2683 | PresentationDocument(self.mock_controller, 'Name') |
2684 | |
2685 | # THEN: check_directory_exists should have been called with 'returned/path/' |
2686 | - self.mock_check_directory_exists.assert_called_once_with(Path('returned', 'path')) |
2687 | + self.mock_check_directory_exists.assert_called_once_with(Path('returned', 'path/')) |
2688 | |
2689 | self._setup_patcher.start() |
2690 | |
2691 | @@ -244,20 +227,3 @@ |
2692 | |
2693 | # THEN: load_presentation should return false |
2694 | self.assertFalse(result, "PresentationDocument.load_presentation should return false.") |
2695 | - |
2696 | - def test_get_file_name(self): |
2697 | - """ |
2698 | - Test the PresentationDocument.get_file_name method. |
2699 | - """ |
2700 | - |
2701 | - # GIVEN: A mocked os.path.split which returns a list, an instance of PresentationDocument and |
2702 | - # arbitary file_path. |
2703 | - self.mock_os.path.split.return_value = ['directory', 'file.ext'] |
2704 | - instance = PresentationDocument(self.mock_controller, 'Name') |
2705 | - instance.file_path = 'filepath' |
2706 | - |
2707 | - # WHEN: Calling get_file_name |
2708 | - result = instance.get_file_name() |
2709 | - |
2710 | - # THEN: get_file_name should return 'file.ext' |
2711 | - self.assertEqual(result, 'file.ext') |
Sorry but you removed too much code!