Merge lp:~phill-ridout/openlp/pathlib3 into lp:openlp

Proposed by Phill
Status: Superseded
Proposed branch: lp:~phill-ridout/openlp/pathlib3
Merge into: lp:openlp
Diff against target: 1730 lines (+292/-327)
42 files modified
openlp/core/__init__.py (+16/-12)
openlp/core/common/__init__.py (+47/-47)
openlp/core/common/applocation.py (+8/-19)
openlp/core/common/settings.py (+0/-28)
openlp/core/lib/__init__.py (+13/-15)
openlp/core/lib/db.py (+2/-2)
openlp/core/lib/pluginmanager.py (+1/-1)
openlp/core/lib/theme.py (+2/-3)
openlp/core/ui/firsttimeform.py (+3/-2)
openlp/core/ui/mainwindow.py (+2/-1)
openlp/core/ui/media/mediacontroller.py (+1/-1)
openlp/core/ui/printserviceform.py (+1/-1)
openlp/core/ui/servicemanager.py (+6/-5)
openlp/core/ui/themeform.py (+3/-1)
openlp/core/ui/thememanager.py (+13/-12)
openlp/plugins/bibles/lib/importers/csvbible.py (+2/-1)
openlp/plugins/bibles/lib/manager.py (+3/-2)
openlp/plugins/images/lib/mediaitem.py (+6/-5)
openlp/plugins/media/lib/mediaitem.py (+2/-1)
openlp/plugins/media/mediaplugin.py (+2/-2)
openlp/plugins/presentations/lib/impresscontroller.py (+2/-1)
openlp/plugins/presentations/lib/pdfcontroller.py (+2/-1)
openlp/plugins/presentations/lib/presentationcontroller.py (+4/-3)
openlp/plugins/presentations/presentationplugin.py (+1/-1)
openlp/plugins/songs/forms/editsongform.py (+1/-1)
openlp/plugins/songs/lib/importers/songbeamer.py (+2/-1)
openlp/plugins/songs/lib/importers/songimport.py (+2/-1)
openlp/plugins/songs/lib/mediaitem.py (+3/-2)
openlp/plugins/songs/lib/openlyricsexport.py (+2/-1)
openlp/plugins/songusage/forms/songusagedetailform.py (+2/-1)
tests/functional/openlp_core_common/test_applocation.py (+5/-7)
tests/functional/openlp_core_common/test_common.py (+61/-35)
tests/functional/openlp_core_common/test_init.py (+36/-32)
tests/functional/openlp_core_lib/test_db.py (+5/-4)
tests/functional/openlp_core_lib/test_file_dialog.py (+0/-45)
tests/functional/openlp_core_lib/test_lib.py (+15/-15)
tests/functional/openlp_core_ui/test_firsttimeform.py (+2/-1)
tests/functional/openlp_core_ui/test_thememanager.py (+2/-2)
tests/functional/openlp_plugins/bibles/test_manager.py (+2/-2)
tests/functional/openlp_plugins/media/test_mediaplugin.py (+3/-5)
tests/functional/openlp_plugins/presentations/test_presentationcontroller.py (+4/-2)
tests/interfaces/openlp_core_common/test_utils.py (+3/-3)
To merge this branch: bzr merge lp:~phill-ridout/openlp/pathlib3
Reviewer Review Type Date Requested Status
Tomas Groth Needs Fixing
Raoul Snyman Needs Information
Tim Bentley Needs Fixing
Review via email: mp+328950@code.launchpad.net

This proposal has been superseded by a proposal from 2017-08-23.

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

See inline

review: Needs Fixing
Revision history for this message
Raoul Snyman (raoul-snyman) :
review: Needs Information
Revision history for this message
Phill (phill-ridout) wrote :

> See inline
See my inline reply.

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

See my inline reply.

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

See inline

lp:~phill-ridout/openlp/pathlib3 updated
2760. By Phill

made some more changes to core/__init__ and applocation

Revision history for this message
Tomas Groth (tomasgroth) wrote :
review: Needs Fixing
lp:~phill-ridout/openlp/pathlib3 updated
2761. By Phill

indentation fix

2762. By Phill

HEAD

2763. By Phill

Patched appveyor.yml

2764. By Phill

Fixed issues with this branch and recent commits to trunk

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openlp/core/__init__.py'
2--- openlp/core/__init__.py 2017-08-03 17:54:40 +0000
3+++ openlp/core/__init__.py 2017-08-23 20:14:53 +0000
4@@ -33,6 +33,7 @@
5 import shutil
6 import sys
7 import time
8+from pathlib import Path
9 from traceback import format_exception
10
11 from PyQt5 import QtCore, QtGui, QtWidgets
12@@ -346,15 +347,18 @@
13 """
14 Setup our logging using log_path
15
16- :param log_path: the path
17+ :param pathlib.Path log_path: The file to save the log to
18+ :return: None
19+ :rtype: None
20 """
21 check_directory_exists(log_path, True)
22- filename = os.path.join(log_path, 'openlp.log')
23- logfile = logging.FileHandler(filename, 'w', encoding="UTF-8")
24+ file_path = log_path / 'openlp.log'
25+ # TODO: FileHandler accepts a Path object in Py3.6
26+ logfile = logging.FileHandler(str(file_path), 'w', encoding='UTF-8')
27 logfile.setFormatter(logging.Formatter('%(asctime)s %(name)-55s %(levelname)-8s %(message)s'))
28 log.addHandler(logfile)
29 if log.isEnabledFor(logging.DEBUG):
30- print('Logging to: {name}'.format(name=filename))
31+ print('Logging to: {name}'.format(name=file_path))
32
33
34 def main(args=None):
35@@ -390,24 +394,24 @@
36 application.setApplicationName('OpenLPPortable')
37 Settings.setDefaultFormat(Settings.IniFormat)
38 # Get location OpenLPPortable.ini
39- application_path = str(AppLocation.get_directory(AppLocation.AppDir))
40- set_up_logging(os.path.abspath(os.path.join(application_path, '..', '..', 'Other')))
41+ portable_path = (AppLocation.get_directory(AppLocation.AppDir) / '..' / '..').resolve()
42+ data_path = portable_path / 'Data'
43+ set_up_logging(portable_path / 'Other')
44 log.info('Running portable')
45- portable_settings_file = os.path.abspath(os.path.join(application_path, '..', '..', 'Data', 'OpenLP.ini'))
46+ portable_settings_path = data_path / 'OpenLP.ini'
47 # Make this our settings file
48- log.info('INI file: {name}'.format(name=portable_settings_file))
49- Settings.set_filename(portable_settings_file)
50+ log.info('INI file: {name}'.format(name=portable_settings_path))
51+ Settings.set_filename(str(portable_settings_path))
52 portable_settings = Settings()
53 # Set our data path
54- data_path = os.path.abspath(os.path.join(application_path, '..', '..', 'Data',))
55 log.info('Data path: {name}'.format(name=data_path))
56 # Point to our data path
57- portable_settings.setValue('advanced/data path', data_path)
58+ portable_settings.setValue('advanced/data path', str(data_path))
59 portable_settings.setValue('advanced/is portable', True)
60 portable_settings.sync()
61 else:
62 application.setApplicationName('OpenLP')
63- set_up_logging(str(AppLocation.get_directory(AppLocation.CacheDir)))
64+ set_up_logging(AppLocation.get_directory(AppLocation.CacheDir))
65 Registry.create()
66 Registry().register('application', application)
67 Registry().set_flag('no_web_server', args.no_web_server)
68
69=== modified file 'openlp/core/common/__init__.py'
70--- openlp/core/common/__init__.py 2017-08-01 20:59:41 +0000
71+++ openlp/core/common/__init__.py 2017-08-23 20:14:53 +0000
72@@ -32,7 +32,6 @@
73 import traceback
74 from chardet.universaldetector import UniversalDetector
75 from ipaddress import IPv4Address, IPv6Address, AddressValueError
76-from pathlib import Path
77 from shutil import which
78 from subprocess import check_output, CalledProcessError, STDOUT
79
80@@ -65,17 +64,19 @@
81
82 def check_directory_exists(directory, do_not_log=False):
83 """
84- Check a theme directory exists and if not create it
85+ Check a directory exists and if not create it
86
87- :param directory: The directory to make sure exists
88- :param do_not_log: To not log anything. This is need for the start up, when the log isn't ready.
89+ :param pathlib.Path directory: The directory to make sure exists
90+ :param bool do_not_log: To not log anything. This is need for the start up, when the log isn't ready.
91+ :return: None
92+ :rtype: None
93 """
94 if not do_not_log:
95 log.debug('check_directory_exists {text}'.format(text=directory))
96 try:
97- if not os.path.exists(directory):
98- os.makedirs(directory)
99- except IOError as e:
100+ if not directory.exists():
101+ directory.mkdir(parents=True)
102+ except IOError:
103 if not do_not_log:
104 log.exception('failed to check if directory exists or create directory')
105
106@@ -85,19 +86,15 @@
107 A utility function to find and load OpenLP extensions, such as plugins, presentation and media controllers and
108 importers.
109
110- :param glob_pattern: A glob pattern used to find the extension(s) to be imported. Should be relative to the
111- application directory. i.e. openlp/plugins/*/*plugin.py
112- :type glob_pattern: str
113-
114- :param excluded_files: A list of file names to exclude that the glob pattern may find.
115- :type excluded_files: list of strings
116-
117+ :param str glob_pattern: A glob pattern used to find the extension(s) to be imported. Should be relative to the
118+ application directory. i.e. plugins/*/*plugin.py
119+ :param list[str] excluded_files: A list of file names to exclude that the glob pattern may find.
120 :return: None
121 :rtype: None
122 """
123- base_dir_path = AppLocation.get_directory(AppLocation.AppDir).parent
124- for extension_path in base_dir_path.glob(glob_pattern):
125- extension_path = extension_path.relative_to(base_dir_path)
126+ app_dir = AppLocation.get_directory(AppLocation.AppDir)
127+ for extension_path in app_dir.glob(glob_pattern):
128+ extension_path = extension_path.relative_to(app_dir)
129 if extension_path.name in excluded_files:
130 continue
131 module_name = path_to_module(extension_path)
132@@ -106,21 +103,19 @@
133 except (ImportError, OSError):
134 # On some platforms importing vlc.py might cause OSError exceptions. (e.g. Mac OS X)
135 log.warning('Failed to import {module_name} on path {extension_path}'
136- .format(module_name=module_name, extension_path=str(extension_path)))
137+ .format(module_name=module_name, extension_path=extension_path))
138
139
140 def path_to_module(path):
141 """
142 Convert a path to a module name (i.e openlp.core.common)
143
144- :param path: The path to convert to a module name.
145- :type path: Path
146-
147+ :param pathlib.Path path: The path to convert to a module name.
148 :return: The module name.
149 :rtype: str
150 """
151 module_path = path.with_suffix('')
152- return '.'.join(module_path.parts)
153+ return 'openlp.' + '.'.join(module_path.parts)
154
155
156 def get_frozen_path(frozen_option, non_frozen_option):
157@@ -378,20 +373,22 @@
158 return os.path.split(path)
159
160
161-def delete_file(file_path_name):
162+def delete_file(file_path):
163 """
164 Deletes a file from the system.
165
166- :param file_path_name: The file, including path, to delete.
167+ :param pathlib.Path file_path: The file, including path, to delete.
168+ :return: True if the deletion was successful, or the file never existed. False otherwise.
169+ :rtype: bool
170 """
171- if not file_path_name:
172+ if not file_path:
173 return False
174 try:
175- if os.path.exists(file_path_name):
176- os.remove(file_path_name)
177+ if file_path.exists():
178+ file_path.unlink()
179 return True
180 except (IOError, OSError):
181- log.exception("Unable to delete file {text}".format(text=file_path_name))
182+ log.exception('Unable to delete file {file_path}'.format(file_path=file_path))
183 return False
184
185
186@@ -411,18 +408,19 @@
187 return IMAGES_FILTER
188
189
190-def is_not_image_file(file_name):
191+def is_not_image_file(file_path):
192 """
193 Validate that the file is not an image file.
194
195- :param file_name: File name to be checked.
196+ :param pathlib.Path file_path: The file to be checked.
197+ :return: If the file is not an image
198+ :rtype: bool
199 """
200- if not file_name:
201+ if not (file_path and file_path.exists()):
202 return True
203 else:
204 formats = [bytes(fmt).decode().lower() for fmt in QtGui.QImageReader.supportedImageFormats()]
205- file_part, file_extension = os.path.splitext(str(file_name))
206- if file_extension[1:].lower() in formats and os.path.exists(file_name):
207+ if file_path.suffix[1:].lower() in formats:
208 return False
209 return True
210
211@@ -431,10 +429,10 @@
212 """
213 Removes invalid characters from the given ``filename``.
214
215- :param filename: The "dirty" file name to clean.
216+ :param str filename: The "dirty" file name to clean.
217+ :return: The cleaned string
218+ :rtype: str
219 """
220- if not isinstance(filename, str):
221- filename = str(filename, 'utf-8')
222 return INVALID_FILE_CHARS.sub('_', CONTROL_CHARS.sub('', filename))
223
224
225@@ -442,8 +440,9 @@
226 """
227 Function that checks whether a binary exists.
228
229- :param program_path: The full path to the binary to check.
230+ :param pathlib.Path program_path: The full path to the binary to check.
231 :return: program output to be parsed
232+ :rtype: bytes
233 """
234 log.debug('testing program_path: {text}'.format(text=program_path))
235 try:
236@@ -453,26 +452,27 @@
237 startupinfo.dwFlags |= STARTF_USESHOWWINDOW
238 else:
239 startupinfo = None
240- runlog = check_output([program_path, '--help'], stderr=STDOUT, startupinfo=startupinfo)
241+ run_log = check_output([str(program_path), '--help'], stderr=STDOUT, startupinfo=startupinfo)
242 except CalledProcessError as e:
243- runlog = e.output
244+ run_log = e.output
245 except Exception:
246 trace_error_handler(log)
247- runlog = ''
248- log.debug('check_output returned: {text}'.format(text=runlog))
249- return runlog
250-
251-
252-def get_file_encoding(filename):
253+ run_log = ''
254+ log.debug('check_output returned: {text}'.format(text=run_log))
255+ return run_log
256+
257+
258+def get_file_encoding(file_path):
259 """
260 Utility function to incrementally detect the file encoding.
261
262- :param filename: Filename for the file to determine the encoding for. Str
263+ :param pathlib.Path file_path: Filename for the file to determine the encoding for.
264 :return: A dict with the keys 'encoding' and 'confidence'
265+ :rtype: dict[str, float]
266 """
267 detector = UniversalDetector()
268 try:
269- with open(filename, 'rb') as detect_file:
270+ with file_path.open('rb') as detect_file:
271 while not detector.done:
272 chunk = detect_file.read(1024)
273 if not chunk:
274
275=== modified file 'openlp/core/common/applocation.py'
276--- openlp/core/common/applocation.py 2017-08-02 06:09:38 +0000
277+++ openlp/core/common/applocation.py 2017-08-23 20:14:53 +0000
278@@ -58,9 +58,6 @@
279 CacheDir = 5
280 LanguageDir = 6
281
282- # Base path where data/config/cache dir is located
283- BaseDir = None
284-
285 @staticmethod
286 def get_directory(dir_type=AppDir):
287 """
288@@ -78,8 +75,6 @@
289 return get_frozen_path(FROZEN_APP_PATH, APP_PATH) / 'plugins'
290 elif dir_type == AppLocation.LanguageDir:
291 return get_frozen_path(FROZEN_APP_PATH, _get_os_dir_path(dir_type)) / 'i18n'
292- elif dir_type == AppLocation.DataDir and AppLocation.BaseDir:
293- return Path(AppLocation.BaseDir, 'data')
294 else:
295 return _get_os_dir_path(dir_type)
296
297@@ -96,7 +91,7 @@
298 path = Path(Settings().value('advanced/data path'))
299 else:
300 path = AppLocation.get_directory(AppLocation.DataDir)
301- check_directory_exists(str(path))
302+ check_directory_exists(path)
303 return path
304
305 @staticmethod
306@@ -104,14 +99,10 @@
307 """
308 Get a list of files from the data files path.
309
310- :param section: Defaults to *None*. The section of code getting the files - used to load from a section's data
311- subdirectory.
312- :type section: None | str
313-
314- :param extension: Defaults to ''. The extension to search for. For example::
315+ :param None | str section: Defaults to *None*. The section of code getting the files - used to load from a
316+ section's data subdirectory.
317+ :param str extension: Defaults to ''. The extension to search for. For example::
318 '.png'
319- :type extension: str
320-
321 :return: List of files found.
322 :rtype: list[pathlib.Path]
323 """
324@@ -134,7 +125,7 @@
325 :rtype: pathlib.Path
326 """
327 path = AppLocation.get_data_path() / section
328- check_directory_exists(str(path))
329+ check_directory_exists(path)
330 return path
331
332
333@@ -143,14 +134,12 @@
334 Return a path based on which OS and environment we are running in.
335
336 :param dir_type: AppLocation Enum of the requested path type
337- :type dir_type: AppLocation Enum
338-
339 :return: The requested path
340 :rtype: pathlib.Path
341 """
342 # If running from source, return the language directory from the source directory
343 if dir_type == AppLocation.LanguageDir:
344- directory = Path(os.path.abspath(os.path.join(os.path.dirname(openlp.__file__), '..', 'resources')))
345+ directory = Path(openlp.__file__, '..', '..').resolve() / 'resources'
346 if directory.exists():
347 return directory
348 if is_win():
349@@ -158,14 +147,14 @@
350 if dir_type == AppLocation.DataDir:
351 return openlp_folder_path / 'data'
352 elif dir_type == AppLocation.LanguageDir:
353- return os.path.dirname(openlp.__file__)
354+ return Path(openlp.__file__).parent
355 return openlp_folder_path
356 elif is_macosx():
357 openlp_folder_path = Path(os.getenv('HOME'), 'Library', 'Application Support', 'openlp')
358 if dir_type == AppLocation.DataDir:
359 return openlp_folder_path / 'Data'
360 elif dir_type == AppLocation.LanguageDir:
361- return os.path.dirname(openlp.__file__)
362+ return Path(openlp.__file__).parent
363 return openlp_folder_path
364 else:
365 if dir_type == AppLocation.LanguageDir:
366
367=== modified file 'openlp/core/common/settings.py'
368--- openlp/core/common/settings.py 2017-06-09 15:56:40 +0000
369+++ openlp/core/common/settings.py 2017-08-23 20:14:53 +0000
370@@ -501,31 +501,3 @@
371 if isinstance(default_value, int):
372 return int(setting)
373 return setting
374-
375- def get_files_from_config(self, plugin):
376- """
377- This removes the settings needed for old way we saved files (e. g. the image paths for the image plugin). A list
378- of file paths are returned.
379-
380- **Note**: Only a list of paths is returned; this does not convert anything!
381-
382- :param plugin: The Plugin object.The caller has to convert/save the list himself; o
383- """
384- files_list = []
385- # We need QSettings instead of Settings here to bypass our central settings dict.
386- # Do NOT do this anywhere else!
387- settings = QtCore.QSettings(self.fileName(), Settings.IniFormat)
388- settings.beginGroup(plugin.settings_section)
389- if settings.contains('{name} count'.format(name=plugin.name)):
390- # Get the count.
391- list_count = int(settings.value('{name} count'.format(name=plugin.name), 0))
392- if list_count:
393- for counter in range(list_count):
394- # The keys were named e. g.: "image 0"
395- item = settings.value('{name} {counter:d}'.format(name=plugin.name, counter=counter), '')
396- if item:
397- files_list.append(item)
398- settings.remove('{name} {counter:d}'.format(name=plugin.name, counter=counter))
399- settings.remove('{name} count'.format(name=plugin.name))
400- settings.endGroup()
401- return files_list
402
403=== modified file 'openlp/core/lib/__init__.py'
404--- openlp/core/lib/__init__.py 2017-08-07 20:51:50 +0000
405+++ openlp/core/lib/__init__.py 2017-08-23 20:14:53 +0000
406@@ -83,30 +83,28 @@
407 Next = 3
408
409
410-def get_text_file_string(text_file):
411+def get_text_file_string(text_file_path):
412 """
413- Open a file and return its content as unicode string. If the supplied file name is not a file then the function
414+ Open a file and return its content as a string. If the supplied file path is not a file then the function
415 returns False. If there is an error loading the file or the content can't be decoded then the function will return
416 None.
417
418- :param text_file: The name of the file.
419- :return: The file as a single string
420+ :param pathlib.Path text_file_path: The path to the file.
421+ :return: The contents of the file, False if the file does not exist, or None if there is an Error reading or
422+ decoding the file.
423+ :rtype: str | False | None
424 """
425- if not os.path.isfile(text_file):
426+ if not text_file_path.is_file():
427 return False
428- file_handle = None
429 content = None
430 try:
431- file_handle = open(text_file, 'r', encoding='utf-8')
432- if file_handle.read(3) != '\xEF\xBB\xBF':
433- # no BOM was found
434- file_handle.seek(0)
435- content = file_handle.read()
436+ with text_file_path.open('r', encoding='utf-8') as file_handle:
437+ if file_handle.read(3) != '\xEF\xBB\xBF':
438+ # no BOM was found
439+ file_handle.seek(0)
440+ content = file_handle.read()
441 except (IOError, UnicodeError):
442- log.exception('Failed to open text file {text}'.format(text=text_file))
443- finally:
444- if file_handle:
445- file_handle.close()
446+ log.exception('Failed to open text file {text}'.format(text=text_file_path))
447 return content
448
449
450
451=== modified file 'openlp/core/lib/db.py'
452--- openlp/core/lib/db.py 2017-08-01 20:59:41 +0000
453+++ openlp/core/lib/db.py 2017-08-23 20:14:53 +0000
454@@ -274,9 +274,9 @@
455 :param db_file_name: The database file name. Defaults to None resulting in the plugin_name being used.
456 """
457 if db_file_name:
458- db_file_path = os.path.join(str(AppLocation.get_section_data_path(plugin_name)), db_file_name)
459+ db_file_path = AppLocation.get_section_data_path(plugin_name) / db_file_name
460 else:
461- db_file_path = os.path.join(str(AppLocation.get_section_data_path(plugin_name)), plugin_name)
462+ db_file_path = AppLocation.get_section_data_path(plugin_name) / plugin_name
463 return delete_file(db_file_path)
464
465
466
467=== modified file 'openlp/core/lib/pluginmanager.py'
468--- openlp/core/lib/pluginmanager.py 2017-08-01 20:59:41 +0000
469+++ openlp/core/lib/pluginmanager.py 2017-08-23 20:14:53 +0000
470@@ -69,7 +69,7 @@
471 """
472 Scan a directory for objects inheriting from the ``Plugin`` class.
473 """
474- glob_pattern = os.path.join('openlp', 'plugins', '*', '*plugin.py')
475+ glob_pattern = os.path.join('plugins', '*', '*plugin.py')
476 extension_loader(glob_pattern)
477 plugin_classes = Plugin.__subclasses__()
478 plugin_objects = []
479
480=== modified file 'openlp/core/lib/theme.py'
481--- openlp/core/lib/theme.py 2017-08-01 20:59:41 +0000
482+++ openlp/core/lib/theme.py 2017-08-23 20:14:53 +0000
483@@ -158,9 +158,8 @@
484 Initialise the theme object.
485 """
486 # basic theme object with defaults
487- json_dir = os.path.join(str(AppLocation.get_directory(AppLocation.AppDir)), 'core', 'lib', 'json')
488- json_file = os.path.join(json_dir, 'theme.json')
489- jsn = get_text_file_string(json_file)
490+ json_path = AppLocation.get_directory(AppLocation.AppDir) / 'core' / 'lib' / 'json' / 'theme.json'
491+ jsn = get_text_file_string(json_path)
492 jsn = json.loads(jsn)
493 self.expand_json(jsn)
494 self.background_filename = ''
495
496=== modified file 'openlp/core/ui/firsttimeform.py'
497--- openlp/core/ui/firsttimeform.py 2017-08-03 17:54:40 +0000
498+++ openlp/core/ui/firsttimeform.py 2017-08-23 20:14:53 +0000
499@@ -29,8 +29,9 @@
500 import urllib.request
501 import urllib.parse
502 import urllib.error
503+from configparser import ConfigParser, MissingSectionHeaderError, NoOptionError, NoSectionError
504+from pathlib import Path
505 from tempfile import gettempdir
506-from configparser import ConfigParser, MissingSectionHeaderError, NoSectionError, NoOptionError
507
508 from PyQt5 import QtCore, QtWidgets
509
510@@ -282,7 +283,7 @@
511 self.no_internet_cancel_button.setVisible(False)
512 # Check if this is a re-run of the wizard.
513 self.has_run_wizard = Settings().value('core/has run wizard')
514- check_directory_exists(os.path.join(gettempdir(), 'openlp'))
515+ check_directory_exists(Path(gettempdir(), 'openlp'))
516
517 def update_screen_list_combo(self):
518 """
519
520=== modified file 'openlp/core/ui/mainwindow.py'
521--- openlp/core/ui/mainwindow.py 2017-08-03 17:54:40 +0000
522+++ openlp/core/ui/mainwindow.py 2017-08-23 20:14:53 +0000
523@@ -30,6 +30,7 @@
524 from datetime import datetime
525 from distutils import dir_util
526 from distutils.errors import DistutilsFileError
527+from pathlib import Path
528 from tempfile import gettempdir
529
530 from PyQt5 import QtCore, QtGui, QtWidgets
531@@ -870,7 +871,7 @@
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(temp_directory)
536+ check_directory_exists(Path(temp_directory))
537 temp_config = os.path.join(temp_directory, os.path.basename(import_file_name))
538 shutil.copyfile(import_file_name, temp_config)
539 settings = Settings()
540
541=== modified file 'openlp/core/ui/media/mediacontroller.py'
542--- openlp/core/ui/media/mediacontroller.py 2017-06-25 17:03:31 +0000
543+++ openlp/core/ui/media/mediacontroller.py 2017-08-23 20:14:53 +0000
544@@ -177,7 +177,7 @@
545 Check to see if we have any media Player's available.
546 """
547 log.debug('_check_available_media_players')
548- controller_dir = os.path.join('openlp', 'core', 'ui', 'media')
549+ controller_dir = os.path.join('core', 'ui', 'media')
550 glob_pattern = os.path.join(controller_dir, '*player.py')
551 extension_loader(glob_pattern, ['mediaplayer.py'])
552 player_classes = MediaPlayer.__subclasses__()
553
554=== modified file 'openlp/core/ui/printserviceform.py'
555--- openlp/core/ui/printserviceform.py 2017-08-01 20:59:41 +0000
556+++ openlp/core/ui/printserviceform.py 2017-08-23 20:14:53 +0000
557@@ -176,7 +176,7 @@
558 html_data = self._add_element('html')
559 self._add_element('head', parent=html_data)
560 self._add_element('title', self.title_line_edit.text(), html_data.head)
561- css_path = os.path.join(str(AppLocation.get_data_path()), 'serviceprint', 'service_print.css')
562+ css_path = AppLocation.get_data_path() / 'serviceprint' / 'service_print.css'
563 custom_css = get_text_file_string(css_path)
564 if not custom_css:
565 custom_css = DEFAULT_CSS
566
567=== modified file 'openlp/core/ui/servicemanager.py'
568--- openlp/core/ui/servicemanager.py 2017-08-03 17:54:40 +0000
569+++ openlp/core/ui/servicemanager.py 2017-08-23 20:14:53 +0000
570@@ -28,6 +28,7 @@
571 import shutil
572 import zipfile
573 from datetime import datetime, timedelta
574+from pathlib import Path
575 from tempfile import mkstemp
576
577 from PyQt5 import QtCore, QtGui, QtWidgets
578@@ -587,7 +588,7 @@
579 audio_from = os.path.join(self.service_path, audio_from)
580 save_file = os.path.join(self.service_path, audio_to)
581 save_path = os.path.split(save_file)[0]
582- check_directory_exists(save_path)
583+ check_directory_exists(Path(save_path))
584 if not os.path.exists(save_file):
585 shutil.copy(audio_from, save_file)
586 zip_file.write(audio_from, audio_to)
587@@ -614,7 +615,7 @@
588 success = False
589 self.main_window.add_recent_file(path_file_name)
590 self.set_modified(False)
591- delete_file(temp_file_name)
592+ delete_file(Path(temp_file_name))
593 return success
594
595 def save_local_file(self):
596@@ -669,7 +670,7 @@
597 return self.save_file_as()
598 self.main_window.add_recent_file(path_file_name)
599 self.set_modified(False)
600- delete_file(temp_file_name)
601+ delete_file(Path(temp_file_name))
602 return success
603
604 def save_file_as(self, field=None):
605@@ -774,7 +775,7 @@
606 self.set_file_name(file_name)
607 self.main_window.display_progress_bar(len(items))
608 self.process_service_items(items)
609- delete_file(p_file)
610+ delete_file(Path(p_file))
611 self.main_window.add_recent_file(file_name)
612 self.set_modified(False)
613 Settings().setValue('servicemanager/last file', file_name)
614@@ -1343,7 +1344,7 @@
615 Empties the service_path of temporary files on system exit.
616 """
617 for file_name in os.listdir(self.service_path):
618- file_path = os.path.join(self.service_path, file_name)
619+ file_path = Path(self.service_path, file_name)
620 delete_file(file_path)
621 if os.path.exists(os.path.join(self.service_path, 'audio')):
622 shutil.rmtree(os.path.join(self.service_path, 'audio'), True)
623
624=== modified file 'openlp/core/ui/themeform.py'
625--- openlp/core/ui/themeform.py 2017-08-07 20:50:01 +0000
626+++ openlp/core/ui/themeform.py 2017-08-23 20:14:53 +0000
627@@ -24,6 +24,7 @@
628 """
629 import logging
630 import os
631+from pathlib import Path
632
633 from PyQt5 import QtCore, QtGui, QtWidgets
634
635@@ -188,7 +189,8 @@
636 """
637 background_image = BackgroundType.to_string(BackgroundType.Image)
638 if self.page(self.currentId()) == self.background_page and \
639- self.theme.background_type == background_image and is_not_image_file(self.theme.background_filename):
640+ self.theme.background_type == background_image and \
641+ is_not_image_file(Path(self.theme.background_filename)):
642 QtWidgets.QMessageBox.critical(self, translate('OpenLP.ThemeWizard', 'Background Image Empty'),
643 translate('OpenLP.ThemeWizard', 'You have not selected a '
644 'background image. Please select one before continuing.'))
645
646=== modified file 'openlp/core/ui/thememanager.py'
647--- openlp/core/ui/thememanager.py 2017-08-07 20:50:01 +0000
648+++ openlp/core/ui/thememanager.py 2017-08-23 20:14:53 +0000
649@@ -25,6 +25,7 @@
650 import os
651 import zipfile
652 import shutil
653+from pathlib import Path
654
655 from xml.etree.ElementTree import ElementTree, XML
656 from PyQt5 import QtCore, QtGui, QtWidgets
657@@ -161,9 +162,9 @@
658 Set up the theme path variables
659 """
660 self.path = str(AppLocation.get_section_data_path(self.settings_section))
661- check_directory_exists(self.path)
662+ check_directory_exists(Path(self.path))
663 self.thumb_path = os.path.join(self.path, 'thumbnails')
664- check_directory_exists(self.thumb_path)
665+ check_directory_exists(Path(self.thumb_path))
666
667 def check_list_state(self, item, field=None):
668 """
669@@ -355,8 +356,8 @@
670 """
671 self.theme_list.remove(theme)
672 thumb = '{name}.png'.format(name=theme)
673- delete_file(os.path.join(self.path, thumb))
674- delete_file(os.path.join(self.thumb_path, thumb))
675+ delete_file(Path(self.path, thumb))
676+ delete_file(Path(self.thumb_path, thumb))
677 try:
678 # Windows is always unicode, so no need to encode filenames
679 if is_win():
680@@ -450,7 +451,7 @@
681 for theme_file in files:
682 theme_file = os.path.join(self.path, str(theme_file))
683 self.unzip_theme(theme_file, self.path)
684- delete_file(theme_file)
685+ delete_file(Path(theme_file))
686 files = AppLocation.get_files(self.settings_section, '.png')
687 # No themes have been found so create one
688 if not files:
689@@ -514,12 +515,12 @@
690 :return: The theme object.
691 """
692 self.log_debug('get theme data for theme {name}'.format(name=theme_name))
693- theme_file = os.path.join(self.path, str(theme_name), str(theme_name) + '.json')
694- theme_data = get_text_file_string(theme_file)
695+ theme_file_path = Path(self.path, str(theme_name), '{file_name}.json'.format(file_name=theme_name))
696+ theme_data = get_text_file_string(theme_file_path)
697 jsn = True
698 if not theme_data:
699- theme_file = os.path.join(self.path, str(theme_name), str(theme_name) + '.xml')
700- theme_data = get_text_file_string(theme_file)
701+ theme_file_path = theme_file_path.with_suffix('.xml')
702+ theme_data = get_text_file_string(theme_file_path)
703 jsn = False
704 if not theme_data:
705 self.log_debug('No theme data - using default theme')
706@@ -592,7 +593,7 @@
707 # is directory or preview file
708 continue
709 full_name = os.path.join(directory, out_name)
710- check_directory_exists(os.path.dirname(full_name))
711+ check_directory_exists(Path(os.path.dirname(full_name)))
712 if os.path.splitext(name)[1].lower() == '.xml' or os.path.splitext(name)[1].lower() == '.json':
713 file_xml = str(theme_zip.read(name), 'utf-8')
714 out_file = open(full_name, 'w', encoding='utf-8')
715@@ -670,10 +671,10 @@
716 name = theme.theme_name
717 theme_pretty = theme.export_theme()
718 theme_dir = os.path.join(self.path, name)
719- check_directory_exists(theme_dir)
720+ check_directory_exists(Path(theme_dir))
721 theme_file = os.path.join(theme_dir, name + '.json')
722 if self.old_background_image and image_to != self.old_background_image:
723- delete_file(self.old_background_image)
724+ delete_file(Path(self.old_background_image))
725 out_file = None
726 try:
727 out_file = open(theme_file, 'w', encoding='utf-8')
728
729=== modified file 'openlp/plugins/bibles/lib/importers/csvbible.py'
730--- openlp/plugins/bibles/lib/importers/csvbible.py 2016-12-31 11:01:36 +0000
731+++ openlp/plugins/bibles/lib/importers/csvbible.py 2017-08-23 20:14:53 +0000
732@@ -51,6 +51,7 @@
733 """
734 import csv
735 from collections import namedtuple
736+from pathlib import Path
737
738 from openlp.core.common import get_file_encoding, translate
739 from openlp.core.lib.exceptions import ValidationError
740@@ -100,7 +101,7 @@
741 :return: An iterable yielding namedtuples of type results_tuple
742 """
743 try:
744- encoding = get_file_encoding(filename)['encoding']
745+ encoding = get_file_encoding(Path(filename))['encoding']
746 with open(filename, 'r', encoding=encoding, newline='') as csv_file:
747 csv_reader = csv.reader(csv_file, delimiter=',', quotechar='"')
748 return [results_tuple(*line) for line in csv_reader]
749
750=== modified file 'openlp/plugins/bibles/lib/manager.py'
751--- openlp/plugins/bibles/lib/manager.py 2017-08-01 20:59:41 +0000
752+++ openlp/plugins/bibles/lib/manager.py 2017-08-23 20:14:53 +0000
753@@ -22,6 +22,7 @@
754
755 import logging
756 import os
757+from pathlib import Path
758
759 from openlp.core.common import AppLocation, OpenLPMixin, RegistryProperties, Settings, translate, delete_file, UiStrings
760 from openlp.plugins.bibles.lib import LanguageSelection, parse_reference
761@@ -137,7 +138,7 @@
762 # Remove corrupted files.
763 if name is None:
764 bible.session.close_all()
765- delete_file(os.path.join(self.path, filename))
766+ delete_file(Path(self.path, filename))
767 continue
768 log.debug('Bible Name: "{name}"'.format(name=name))
769 self.db_cache[name] = bible
770@@ -185,7 +186,7 @@
771 bible = self.db_cache[name]
772 bible.session.close_all()
773 bible.session = None
774- return delete_file(os.path.join(bible.path, bible.file))
775+ return delete_file(Path(bible.path, bible.file))
776
777 def get_bibles(self):
778 """
779
780=== modified file 'openlp/plugins/images/lib/mediaitem.py'
781--- openlp/plugins/images/lib/mediaitem.py 2017-08-03 17:54:40 +0000
782+++ openlp/plugins/images/lib/mediaitem.py 2017-08-23 20:14:53 +0000
783@@ -22,6 +22,7 @@
784
785 import logging
786 import os
787+from pathlib import Path
788
789 from PyQt5 import QtCore, QtGui, QtWidgets
790
791@@ -99,7 +100,7 @@
792 self.list_view.setIndentation(self.list_view.default_indentation)
793 self.list_view.allow_internal_dnd = True
794 self.service_path = os.path.join(str(AppLocation.get_section_data_path(self.settings_section)), 'thumbnails')
795- check_directory_exists(self.service_path)
796+ check_directory_exists(Path(self.service_path))
797 # Load images from the database
798 self.load_full_list(
799 self.manager.get_all_objects(ImageFilenames, order_by_ref=ImageFilenames.filename), initial_load=True)
800@@ -210,8 +211,8 @@
801 """
802 images = self.manager.get_all_objects(ImageFilenames, ImageFilenames.group_id == image_group.id)
803 for image in images:
804- delete_file(os.path.join(self.service_path, os.path.split(image.filename)[1]))
805- delete_file(self.generate_thumbnail_path(image))
806+ delete_file(Path(self.service_path, os.path.split(image.filename)[1]))
807+ delete_file(Path(self.generate_thumbnail_path(image)))
808 self.manager.delete_object(ImageFilenames, image.id)
809 image_groups = self.manager.get_all_objects(ImageGroups, ImageGroups.parent_id == image_group.id)
810 for group in image_groups:
811@@ -233,8 +234,8 @@
812 if row_item:
813 item_data = row_item.data(0, QtCore.Qt.UserRole)
814 if isinstance(item_data, ImageFilenames):
815- delete_file(os.path.join(self.service_path, row_item.text(0)))
816- delete_file(self.generate_thumbnail_path(item_data))
817+ delete_file(Path(self.service_path, row_item.text(0)))
818+ delete_file(Path(self.generate_thumbnail_path(item_data)))
819 if item_data.group_id == 0:
820 self.list_view.takeTopLevelItem(self.list_view.indexOfTopLevelItem(row_item))
821 else:
822
823=== modified file 'openlp/plugins/media/lib/mediaitem.py'
824--- openlp/plugins/media/lib/mediaitem.py 2017-08-03 17:54:40 +0000
825+++ openlp/plugins/media/lib/mediaitem.py 2017-08-23 20:14:53 +0000
826@@ -22,6 +22,7 @@
827
828 import logging
829 import os
830+from pathlib import Path
831
832 from PyQt5 import QtCore, QtWidgets
833
834@@ -301,7 +302,7 @@
835 """
836 self.list_view.clear()
837 self.service_path = os.path.join(str(AppLocation.get_section_data_path(self.settings_section)), 'thumbnails')
838- check_directory_exists(self.service_path)
839+ check_directory_exists(Path(self.service_path))
840 self.load_list(Settings().value(self.settings_section + '/media files'))
841 self.rebuild_players()
842
843
844=== modified file 'openlp/plugins/media/mediaplugin.py'
845--- openlp/plugins/media/mediaplugin.py 2017-08-03 17:54:40 +0000
846+++ openlp/plugins/media/mediaplugin.py 2017-08-23 20:14:53 +0000
847@@ -26,6 +26,7 @@
848 import logging
849 import os
850 import re
851+from pathlib import Path
852
853 from PyQt5 import QtCore
854
855@@ -165,8 +166,7 @@
856 :param program_path:The full path to the binary to check.
857 :return: If exists or not
858 """
859- program_type = None
860- runlog = check_binary_exists(program_path)
861+ runlog = check_binary_exists(Path(program_path))
862 # Analyse the output to see it the program is mediainfo
863 for line in runlog.splitlines():
864 decoded_line = line.decode()
865
866=== modified file 'openlp/plugins/presentations/lib/impresscontroller.py'
867--- openlp/plugins/presentations/lib/impresscontroller.py 2017-05-14 10:11:10 +0000
868+++ openlp/plugins/presentations/lib/impresscontroller.py 2017-08-23 20:14:53 +0000
869@@ -34,6 +34,7 @@
870 import logging
871 import os
872 import time
873+from pathlib import Path
874
875 from openlp.core.common import is_win, Registry, get_uno_command, get_uno_instance, delete_file
876
877@@ -275,7 +276,7 @@
878 try:
879 doc.storeToURL(url_path, properties)
880 self.convert_thumbnail(path, index + 1)
881- delete_file(path)
882+ delete_file(Path(path))
883 except ErrorCodeIOException as exception:
884 log.exception('ERROR! ErrorCodeIOException {error:d}'.format(error=exception.ErrCode))
885 except:
886
887=== modified file 'openlp/plugins/presentations/lib/pdfcontroller.py'
888--- openlp/plugins/presentations/lib/pdfcontroller.py 2017-08-01 20:59:41 +0000
889+++ openlp/plugins/presentations/lib/pdfcontroller.py 2017-08-23 20:14:53 +0000
890@@ -23,6 +23,7 @@
891 import os
892 import logging
893 import re
894+from pathlib import Path
895 from shutil import which
896 from subprocess import check_output, CalledProcessError
897
898@@ -69,7 +70,7 @@
899 :return: Type of the binary, 'gs' if ghostscript, 'mudraw' if mudraw, None if invalid.
900 """
901 program_type = None
902- runlog = check_binary_exists(program_path)
903+ runlog = check_binary_exists(Path(program_path))
904 # Analyse the output to see it the program is mudraw, ghostscript or neither
905 for line in runlog.splitlines():
906 decoded_line = line.decode()
907
908=== modified file 'openlp/plugins/presentations/lib/presentationcontroller.py'
909--- openlp/plugins/presentations/lib/presentationcontroller.py 2017-08-01 20:59:41 +0000
910+++ openlp/plugins/presentations/lib/presentationcontroller.py 2017-08-23 20:14:53 +0000
911@@ -23,6 +23,7 @@
912 import logging
913 import os
914 import shutil
915+from pathlib import Path
916
917 from PyQt5 import QtCore
918
919@@ -98,7 +99,7 @@
920 """
921 self.slide_number = 0
922 self.file_path = name
923- check_directory_exists(self.get_thumbnail_folder())
924+ check_directory_exists(Path(self.get_thumbnail_folder()))
925
926 def load_presentation(self):
927 """
928@@ -419,8 +420,8 @@
929 self.thumbnail_folder = os.path.join(
930 str(AppLocation.get_section_data_path(self.settings_section)), 'thumbnails')
931 self.thumbnail_prefix = 'slide'
932- check_directory_exists(self.thumbnail_folder)
933- check_directory_exists(self.temp_folder)
934+ check_directory_exists(Path(self.thumbnail_folder))
935+ check_directory_exists(Path(self.temp_folder))
936
937 def enabled(self):
938 """
939
940=== modified file 'openlp/plugins/presentations/presentationplugin.py'
941--- openlp/plugins/presentations/presentationplugin.py 2017-06-09 15:56:40 +0000
942+++ openlp/plugins/presentations/presentationplugin.py 2017-08-23 20:14:53 +0000
943@@ -125,7 +125,7 @@
944 Check to see if we have any presentation software available. If not do not install the plugin.
945 """
946 log.debug('check_pre_conditions')
947- controller_dir = os.path.join('openlp', 'plugins', 'presentations', 'lib')
948+ controller_dir = os.path.join('plugins', 'presentations', 'lib')
949 glob_pattern = os.path.join(controller_dir, '*controller.py')
950 extension_loader(glob_pattern, ['presentationcontroller.py'])
951 controller_classes = PresentationController.__subclasses__()
952
953=== modified file 'openlp/plugins/songs/forms/editsongform.py'
954--- openlp/plugins/songs/forms/editsongform.py 2017-08-11 20:47:52 +0000
955+++ openlp/plugins/songs/forms/editsongform.py 2017-08-23 20:14:53 +0000
956@@ -1071,7 +1071,7 @@
957 log.debug(audio_files)
958 save_path = os.path.join(str(AppLocation.get_section_data_path(self.media_item.plugin.name)), 'audio',
959 str(self.song.id))
960- check_directory_exists(save_path)
961+ check_directory_exists(Path(save_path))
962 self.song.media_files = []
963 files = []
964 for row in range(self.audio_list_widget.count()):
965
966=== modified file 'openlp/plugins/songs/lib/importers/songbeamer.py'
967--- openlp/plugins/songs/lib/importers/songbeamer.py 2017-05-11 19:53:47 +0000
968+++ openlp/plugins/songs/lib/importers/songbeamer.py 2017-08-23 20:14:53 +0000
969@@ -27,6 +27,7 @@
970 import re
971 import base64
972 import math
973+from pathlib import Path
974
975 from openlp.plugins.songs.lib import VerseType
976 from openlp.plugins.songs.lib.importers.songimport import SongImport
977@@ -122,7 +123,7 @@
978 file_name = os.path.split(import_file)[1]
979 if os.path.isfile(import_file):
980 # Detect the encoding
981- self.input_file_encoding = get_file_encoding(import_file)['encoding']
982+ self.input_file_encoding = get_file_encoding(Path(import_file))['encoding']
983 # The encoding should only be ANSI (cp1252), UTF-8, Unicode, Big-Endian-Unicode.
984 # So if it doesn't start with 'u' we default to cp1252. See:
985 # https://forum.songbeamer.com/viewtopic.php?p=419&sid=ca4814924e37c11e4438b7272a98b6f2
986
987=== modified file 'openlp/plugins/songs/lib/importers/songimport.py'
988--- openlp/plugins/songs/lib/importers/songimport.py 2017-08-01 20:59:41 +0000
989+++ openlp/plugins/songs/lib/importers/songimport.py 2017-08-23 20:14:53 +0000
990@@ -24,6 +24,7 @@
991 import re
992 import shutil
993 import os
994+from pathlib import Path
995
996 from PyQt5 import QtCore
997
998@@ -423,7 +424,7 @@
999 if not hasattr(self, 'save_path'):
1000 self.save_path = os.path.join(str(AppLocation.get_section_data_path(self.import_wizard.plugin.name)),
1001 'audio', str(song_id))
1002- check_directory_exists(self.save_path)
1003+ check_directory_exists(Path(self.save_path))
1004 if not filename.startswith(self.save_path):
1005 old_file, filename = filename, os.path.join(self.save_path, os.path.split(filename)[1])
1006 shutil.copyfile(old_file, filename)
1007
1008=== modified file 'openlp/plugins/songs/lib/mediaitem.py'
1009--- openlp/plugins/songs/lib/mediaitem.py 2017-08-03 17:54:40 +0000
1010+++ openlp/plugins/songs/lib/mediaitem.py 2017-08-23 20:14:53 +0000
1011@@ -23,6 +23,7 @@
1012 import logging
1013 import os
1014 import shutil
1015+from pathlib import Path
1016
1017 from PyQt5 import QtCore, QtWidgets
1018 from sqlalchemy.sql import and_, or_
1019@@ -89,7 +90,7 @@
1020 for i, bga in enumerate(item.background_audio):
1021 dest_file = os.path.join(
1022 str(AppLocation.get_section_data_path(self.plugin.name)), 'audio', str(song.id), os.path.split(bga)[1])
1023- check_directory_exists(os.path.split(dest_file)[0])
1024+ check_directory_exists(Path(os.path.split(dest_file)[0]))
1025 shutil.copyfile(os.path.join(str(AppLocation.get_section_data_path('servicemanager')), bga), dest_file)
1026 song.media_files.append(MediaFile.populate(weight=i, file_name=dest_file))
1027 self.plugin.manager.save_object(song, True)
1028@@ -535,7 +536,7 @@
1029 if len(old_song.media_files) > 0:
1030 save_path = os.path.join(
1031 str(AppLocation.get_section_data_path(self.plugin.name)), 'audio', str(new_song.id))
1032- check_directory_exists(save_path)
1033+ check_directory_exists(Path(save_path))
1034 for media_file in old_song.media_files:
1035 new_media_file_name = os.path.join(save_path, os.path.basename(media_file.file_name))
1036 shutil.copyfile(media_file.file_name, new_media_file_name)
1037
1038=== modified file 'openlp/plugins/songs/lib/openlyricsexport.py'
1039--- openlp/plugins/songs/lib/openlyricsexport.py 2016-12-31 11:01:36 +0000
1040+++ openlp/plugins/songs/lib/openlyricsexport.py 2017-08-23 20:14:53 +0000
1041@@ -25,6 +25,7 @@
1042 """
1043 import logging
1044 import os
1045+from pathlib import Path
1046
1047 from lxml import etree
1048
1049@@ -47,7 +48,7 @@
1050 self.manager = parent.plugin.manager
1051 self.songs = songs
1052 self.save_path = save_path
1053- check_directory_exists(self.save_path)
1054+ check_directory_exists(Path(self.save_path))
1055
1056 def do_export(self):
1057 """
1058
1059=== modified file 'openlp/plugins/songusage/forms/songusagedetailform.py'
1060--- openlp/plugins/songusage/forms/songusagedetailform.py 2017-08-04 17:40:57 +0000
1061+++ openlp/plugins/songusage/forms/songusagedetailform.py 2017-08-23 20:14:53 +0000
1062@@ -22,6 +22,7 @@
1063
1064 import logging
1065 import os
1066+from pathlib import Path
1067
1068 from PyQt5 import QtCore, QtWidgets
1069 from sqlalchemy.sql import and_
1070@@ -78,7 +79,7 @@
1071 ' song usage report. \nPlease select an existing path on your computer.')
1072 )
1073 return
1074- check_directory_exists(path)
1075+ check_directory_exists(Path(path))
1076 file_name = translate('SongUsagePlugin.SongUsageDetailForm',
1077 'usage_detail_{old}_{new}.txt'
1078 ).format(old=self.from_date_calendar.selectedDate().toString('ddMMyyyy'),
1079
1080=== modified file 'tests/functional/openlp_core_common/test_applocation.py'
1081--- tests/functional/openlp_core_common/test_applocation.py 2017-08-01 20:59:41 +0000
1082+++ tests/functional/openlp_core_common/test_applocation.py 2017-08-23 20:14:53 +0000
1083@@ -43,14 +43,12 @@
1084 """
1085 with patch('openlp.core.common.applocation.Settings') as mocked_class, \
1086 patch('openlp.core.common.AppLocation.get_directory') as mocked_get_directory, \
1087- patch('openlp.core.common.applocation.check_directory_exists') as mocked_check_directory_exists, \
1088- patch('openlp.core.common.applocation.os') as mocked_os:
1089+ patch('openlp.core.common.applocation.check_directory_exists') as mocked_check_directory_exists:
1090 # GIVEN: A mocked out Settings class and a mocked out AppLocation.get_directory()
1091 mocked_settings = mocked_class.return_value
1092 mocked_settings.contains.return_value = False
1093- mocked_get_directory.return_value = os.path.join('test', 'dir')
1094+ mocked_get_directory.return_value = Path('test', 'dir')
1095 mocked_check_directory_exists.return_value = True
1096- mocked_os.path.normpath.return_value = os.path.join('test', 'dir')
1097
1098 # WHEN: we call AppLocation.get_data_path()
1099 data_path = AppLocation.get_data_path()
1100@@ -58,8 +56,8 @@
1101 # THEN: check that all the correct methods were called, and the result is correct
1102 mocked_settings.contains.assert_called_with('advanced/data path')
1103 mocked_get_directory.assert_called_with(AppLocation.DataDir)
1104- mocked_check_directory_exists.assert_called_with(os.path.join('test', 'dir'))
1105- self.assertEqual(os.path.join('test', 'dir'), data_path, 'Result should be "test/dir"')
1106+ mocked_check_directory_exists.assert_called_with(Path('test', 'dir'))
1107+ self.assertEqual(Path('test', 'dir'), data_path, 'Result should be "test/dir"')
1108
1109 def test_get_data_path_with_custom_location(self):
1110 """
1111@@ -125,7 +123,7 @@
1112 data_path = AppLocation.get_section_data_path('section')
1113
1114 # THEN: check that all the correct methods were called, and the result is correct
1115- mocked_check_directory_exists.assert_called_with(os.path.join('test', 'dir', 'section'))
1116+ mocked_check_directory_exists.assert_called_with(Path('test', 'dir', 'section'))
1117 self.assertEqual(Path('test', 'dir', 'section'), data_path, 'Result should be "test/dir/section"')
1118
1119 def test_get_directory_for_app_dir(self):
1120
1121=== modified file 'tests/functional/openlp_core_common/test_common.py'
1122--- tests/functional/openlp_core_common/test_common.py 2017-08-01 20:59:41 +0000
1123+++ tests/functional/openlp_core_common/test_common.py 2017-08-23 20:14:53 +0000
1124@@ -35,44 +35,70 @@
1125 """
1126 A test suite to test out various functions in the openlp.core.common module.
1127 """
1128- def test_check_directory_exists(self):
1129- """
1130- Test the check_directory_exists() function
1131- """
1132- with patch('openlp.core.lib.os.path.exists') as mocked_exists, \
1133- patch('openlp.core.lib.os.makedirs') as mocked_makedirs:
1134- # GIVEN: A directory to check and a mocked out os.makedirs and os.path.exists
1135- directory_to_check = 'existing/directory'
1136+ def test_check_directory_exists_dir_exists(self):
1137+ """
1138+ Test the check_directory_exists() function when the path already exists
1139+ """
1140+ # GIVEN: A `Path` to check with patched out mkdir and exists methods
1141+ with patch.object(Path, 'exists') as mocked_exists, \
1142+ patch.object(Path, 'mkdir') as mocked_mkdir, \
1143+ patch('openlp.core.common.log'):
1144
1145- # WHEN: os.path.exists returns True and we check to see if the directory exists
1146+ # WHEN: `check_directory_exists` is called and the path exists
1147 mocked_exists.return_value = True
1148- check_directory_exists(directory_to_check)
1149-
1150- # THEN: Only os.path.exists should have been called
1151- mocked_exists.assert_called_with(directory_to_check)
1152- self.assertIsNot(mocked_makedirs.called, 'os.makedirs should not have been called')
1153-
1154- # WHEN: os.path.exists returns False and we check the directory exists
1155+ check_directory_exists(Path('existing', 'directory'))
1156+
1157+ # THEN: The function should not attempt to create the directory
1158+ mocked_exists.assert_called_with()
1159+ self.assertFalse(mocked_mkdir.called)
1160+
1161+ def test_check_directory_exists_dir_doesnt_exists(self):
1162+ """
1163+ Test the check_directory_exists() function when the path does not already exist
1164+ """
1165+ # GIVEN: A `Path` to check with patched out mkdir and exists methods
1166+ with patch.object(Path, 'exists') as mocked_exists, \
1167+ patch.object(Path, 'mkdir') as mocked_mkdir, \
1168+ patch('openlp.core.common.log'):
1169+
1170+ # WHEN: `check_directory_exists` is called and the path does not exist
1171 mocked_exists.return_value = False
1172- check_directory_exists(directory_to_check)
1173-
1174- # THEN: Both the mocked functions should have been called
1175- mocked_exists.assert_called_with(directory_to_check)
1176- mocked_makedirs.assert_called_with(directory_to_check)
1177-
1178- # WHEN: os.path.exists raises an IOError
1179+ check_directory_exists(Path('existing', 'directory'))
1180+
1181+ # THEN: The directory should have been created
1182+ mocked_exists.assert_called_with()
1183+ mocked_mkdir.assert_called_with(parents=True)
1184+
1185+ def test_check_directory_exists_dir_io_error(self):
1186+ """
1187+ Test the check_directory_exists() when an IOError is raised
1188+ """
1189+ # GIVEN: A `Path` to check with patched out mkdir and exists methods
1190+ with patch.object(Path, 'exists') as mocked_exists, \
1191+ patch.object(Path, 'mkdir'), \
1192+ patch('openlp.core.common.log') as mocked_logger:
1193+
1194+ # WHEN: An IOError is raised when checking the if the path exists.
1195 mocked_exists.side_effect = IOError()
1196- check_directory_exists(directory_to_check)
1197-
1198- # THEN: We shouldn't get an exception though the mocked exists has been called
1199- mocked_exists.assert_called_with(directory_to_check)
1200+ check_directory_exists(Path('existing', 'directory'))
1201+
1202+ # THEN: The Error should have been logged
1203+ mocked_logger.exception.assert_called_once_with('failed to check if directory exists or create directory')
1204+
1205+ def test_check_directory_exists_dir_value_error(self):
1206+ """
1207+ Test the check_directory_exists() when an error other than IOError is raised
1208+ """
1209+ # GIVEN: A `Path` to check with patched out mkdir and exists methods
1210+ with patch.object(Path, 'exists') as mocked_exists, \
1211+ patch.object(Path, 'mkdir'), \
1212+ patch('openlp.core.common.log'):
1213
1214 # WHEN: Some other exception is raised
1215 mocked_exists.side_effect = ValueError()
1216
1217- # THEN: check_directory_exists raises an exception
1218- mocked_exists.assert_called_with(directory_to_check)
1219- self.assertRaises(ValueError, check_directory_exists, directory_to_check)
1220+ # THEN: `check_directory_exists` raises an exception
1221+ self.assertRaises(ValueError, check_directory_exists, Path('existing', 'directory'))
1222
1223 def test_extension_loader_no_files_found(self):
1224 """
1225@@ -80,7 +106,7 @@
1226 """
1227 # GIVEN: A mocked `Path.glob` method which does not match any files
1228 with patch('openlp.core.common.AppLocation.get_directory', return_value=Path('/', 'app', 'dir', 'openlp')), \
1229- patch.object(common.Path, 'glob', return_value=[]), \
1230+ patch.object(Path, 'glob', return_value=[]), \
1231 patch('openlp.core.common.importlib.import_module') as mocked_import_module:
1232
1233 # WHEN: Calling `extension_loader`
1234@@ -95,7 +121,7 @@
1235 """
1236 # GIVEN: A mocked `Path.glob` method which returns a list of files
1237 with patch('openlp.core.common.AppLocation.get_directory', return_value=Path('/', 'app', 'dir', 'openlp')), \
1238- patch.object(common.Path, 'glob', return_value=[
1239+ patch.object(Path, 'glob', return_value=[
1240 Path('/', 'app', 'dir', 'openlp', 'import_dir', 'file1.py'),
1241 Path('/', 'app', 'dir', 'openlp', 'import_dir', 'file2.py'),
1242 Path('/', 'app', 'dir', 'openlp', 'import_dir', 'file3.py'),
1243@@ -115,7 +141,7 @@
1244 """
1245 # GIVEN: A mocked `import_module` which raises an `ImportError`
1246 with patch('openlp.core.common.AppLocation.get_directory', return_value=Path('/', 'app', 'dir', 'openlp')), \
1247- patch.object(common.Path, 'glob', return_value=[
1248+ patch.object(Path, 'glob', return_value=[
1249 Path('/', 'app', 'dir', 'openlp', 'import_dir', 'file1.py')]), \
1250 patch('openlp.core.common.importlib.import_module', side_effect=ImportError()), \
1251 patch('openlp.core.common.log') as mocked_logger:
1252@@ -132,7 +158,7 @@
1253 """
1254 # GIVEN: A mocked `SourceFileLoader` which raises an `OSError`
1255 with patch('openlp.core.common.AppLocation.get_directory', return_value=Path('/', 'app', 'dir', 'openlp')), \
1256- patch.object(common.Path, 'glob', return_value=[
1257+ patch.object(Path, 'glob', return_value=[
1258 Path('/', 'app', 'dir', 'openlp', 'import_dir', 'file1.py')]), \
1259 patch('openlp.core.common.importlib.import_module', side_effect=OSError()), \
1260 patch('openlp.core.common.log') as mocked_logger:
1261@@ -174,7 +200,7 @@
1262 Test `path_to_module` when supplied with a `Path` object
1263 """
1264 # GIVEN: A `Path` object
1265- path = Path('openlp/core/ui/media/webkitplayer.py')
1266+ path = Path('core', 'ui', 'media', 'webkitplayer.py')
1267
1268 # WHEN: Calling path_to_module with the `Path` object
1269 result = path_to_module(path)
1270
1271=== modified file 'tests/functional/openlp_core_common/test_init.py'
1272--- tests/functional/openlp_core_common/test_init.py 2017-04-24 05:17:55 +0000
1273+++ tests/functional/openlp_core_common/test_init.py 2017-08-23 20:14:53 +0000
1274@@ -24,6 +24,7 @@
1275 """
1276 import os
1277 from io import BytesIO
1278+from pathlib import Path
1279 from unittest import TestCase
1280 from unittest.mock import MagicMock, PropertyMock, call, patch
1281
1282@@ -296,10 +297,10 @@
1283 """
1284 # GIVEN: A blank path
1285 # WEHN: Calling delete_file
1286- result = delete_file('')
1287+ result = delete_file(None)
1288
1289 # THEN: delete_file should return False
1290- self.assertFalse(result, "delete_file should return False when called with ''")
1291+ self.assertFalse(result, "delete_file should return False when called with None")
1292
1293 def test_delete_file_path_success(self):
1294 """
1295@@ -309,84 +310,87 @@
1296 with patch('openlp.core.common.os', **{'path.exists.return_value': False}):
1297
1298 # WHEN: Calling delete_file with a file path
1299- result = delete_file('path/file.ext')
1300+ result = delete_file(Path('path', 'file.ext'))
1301
1302 # THEN: delete_file should return True
1303 self.assertTrue(result, 'delete_file should return True when it successfully deletes a file')
1304
1305 def test_delete_file_path_no_file_exists(self):
1306 """
1307- Test the delete_file function when the file to remove does not exist
1308+ Test the `delete_file` function when the file to remove does not exist
1309 """
1310- # GIVEN: A mocked os which returns False when os.path.exists is called
1311- with patch('openlp.core.common.os', **{'path.exists.return_value': False}):
1312-
1313- # WHEN: Calling delete_file with a file path
1314- result = delete_file('path/file.ext')
1315-
1316- # THEN: delete_file should return True
1317+ # GIVEN: A patched `exists` methods on the Path object, which returns False
1318+ with patch.object(Path, 'exists', return_value=False), \
1319+ patch.object(Path, 'unlink') as mocked_unlink:
1320+
1321+ # WHEN: Calling `delete_file with` a file path
1322+ result = delete_file(Path('path', 'file.ext'))
1323+
1324+ # THEN: The function should not attempt to delete the file and it should return True
1325+ self.assertFalse(mocked_unlink.called)
1326 self.assertTrue(result, 'delete_file should return True when the file doesnt exist')
1327
1328 def test_delete_file_path_exception(self):
1329 """
1330- Test the delete_file function when os.remove raises an exception
1331+ Test the delete_file function when an exception is raised
1332 """
1333- # GIVEN: A mocked os which returns True when os.path.exists is called and raises an OSError when os.remove is
1334+ # GIVEN: A test `Path` object with a patched exists method which raises an OSError
1335 # called.
1336- with patch('openlp.core.common.os', **{'path.exists.return_value': True, 'path.exists.side_effect': OSError}), \
1337+ with patch.object(Path, 'exists') as mocked_exists, \
1338 patch('openlp.core.common.log') as mocked_log:
1339-
1340- # WHEN: Calling delete_file with a file path
1341- result = delete_file('path/file.ext')
1342-
1343- # THEN: delete_file should log and exception and return False
1344- self.assertEqual(mocked_log.exception.call_count, 1)
1345- self.assertFalse(result, 'delete_file should return False when os.remove raises an OSError')
1346-
1347- def test_get_file_name_encoding_done_test(self):
1348+ mocked_exists.side_effect = OSError
1349+
1350+ # WHEN: Calling delete_file with a the test Path object
1351+ result = delete_file(Path('path', 'file.ext'))
1352+
1353+ # THEN: The exception should be logged and `delete_file` should return False
1354+ self.assertTrue(mocked_log.exception.called)
1355+ self.assertFalse(result, 'delete_file should return False when an OSError is raised')
1356+
1357+ def test_get_file_encoding_done_test(self):
1358 """
1359 Test get_file_encoding when the detector sets done to True
1360 """
1361 # GIVEN: A mocked UniversalDetector instance with done attribute set to True after first iteration
1362 with patch('openlp.core.common.UniversalDetector') as mocked_universal_detector, \
1363- patch('builtins.open', return_value=BytesIO(b"data" * 260)) as mocked_open:
1364+ patch.object(Path, 'open', return_value=BytesIO(b"data" * 260)) as mocked_open:
1365 encoding_result = {'encoding': 'UTF-8', 'confidence': 0.99}
1366 mocked_universal_detector_inst = MagicMock(result=encoding_result)
1367 type(mocked_universal_detector_inst).done = PropertyMock(side_effect=[False, True])
1368 mocked_universal_detector.return_value = mocked_universal_detector_inst
1369
1370 # WHEN: Calling get_file_encoding
1371- result = get_file_encoding('file name')
1372+ result = get_file_encoding(Path('file name'))
1373
1374 # THEN: The feed method of UniversalDetector should only br called once before returning a result
1375- mocked_open.assert_called_once_with('file name', 'rb')
1376+ mocked_open.assert_called_once_with('rb')
1377 self.assertEqual(mocked_universal_detector_inst.feed.mock_calls, [call(b"data" * 256)])
1378 mocked_universal_detector_inst.close.assert_called_once_with()
1379 self.assertEqual(result, encoding_result)
1380
1381- def test_get_file_name_encoding_eof_test(self):
1382+ def test_get_file_encoding_eof_test(self):
1383 """
1384 Test get_file_encoding when the end of the file is reached
1385 """
1386 # GIVEN: A mocked UniversalDetector instance which isn't set to done and a mocked open, with 1040 bytes of test
1387 # data (enough to run the iterator twice)
1388 with patch('openlp.core.common.UniversalDetector') as mocked_universal_detector, \
1389- patch('builtins.open', return_value=BytesIO(b"data" * 260)) as mocked_open:
1390+ patch.object(Path, 'open', return_value=BytesIO(b"data" * 260)) as mocked_open:
1391 encoding_result = {'encoding': 'UTF-8', 'confidence': 0.99}
1392 mocked_universal_detector_inst = MagicMock(mock=mocked_universal_detector,
1393 **{'done': False, 'result': encoding_result})
1394 mocked_universal_detector.return_value = mocked_universal_detector_inst
1395
1396 # WHEN: Calling get_file_encoding
1397- result = get_file_encoding('file name')
1398+ result = get_file_encoding(Path('file name'))
1399
1400 # THEN: The feed method of UniversalDetector should have been called twice before returning a result
1401- mocked_open.assert_called_once_with('file name', 'rb')
1402+ mocked_open.assert_called_once_with('rb')
1403 self.assertEqual(mocked_universal_detector_inst.feed.mock_calls, [call(b"data" * 256), call(b"data" * 4)])
1404 mocked_universal_detector_inst.close.assert_called_once_with()
1405 self.assertEqual(result, encoding_result)
1406
1407- def test_get_file_name_encoding_oserror_test(self):
1408+ def test_get_file_encoding_oserror_test(self):
1409 """
1410 Test get_file_encoding when the end of the file is reached
1411 """
1412@@ -397,7 +401,7 @@
1413 patch('openlp.core.common.log') as mocked_log:
1414
1415 # WHEN: Calling get_file_encoding
1416- result = get_file_encoding('file name')
1417+ result = get_file_encoding(Path('file name'))
1418
1419 # THEN: log.exception should be called and get_file_encoding should return None
1420 mocked_log.exception.assert_called_once_with('Error detecting file encoding')
1421
1422=== modified file 'tests/functional/openlp_core_lib/test_db.py'
1423--- tests/functional/openlp_core_lib/test_db.py 2017-06-09 13:45:18 +0000
1424+++ tests/functional/openlp_core_lib/test_db.py 2017-08-23 20:14:53 +0000
1425@@ -24,6 +24,7 @@
1426 """
1427 import os
1428 import shutil
1429+from pathlib import Path
1430
1431 from tempfile import mkdtemp
1432 from unittest import TestCase
1433@@ -129,10 +130,10 @@
1434 # GIVEN: Mocked out AppLocation class and delete_file method, a test plugin name and a db location
1435 with patch('openlp.core.lib.db.AppLocation') as MockedAppLocation, \
1436 patch('openlp.core.lib.db.delete_file') as mocked_delete_file:
1437- MockedAppLocation.get_section_data_path.return_value = 'test-dir'
1438+ MockedAppLocation.get_section_data_path.return_value = Path('test-dir')
1439 mocked_delete_file.return_value = True
1440 test_plugin = 'test'
1441- test_location = os.path.join('test-dir', test_plugin)
1442+ test_location = Path('test-dir', test_plugin)
1443
1444 # WHEN: delete_database is run without a database file
1445 result = delete_database(test_plugin)
1446@@ -149,11 +150,11 @@
1447 # GIVEN: Mocked out AppLocation class and delete_file method, a test plugin name and a db location
1448 with patch('openlp.core.lib.db.AppLocation') as MockedAppLocation, \
1449 patch('openlp.core.lib.db.delete_file') as mocked_delete_file:
1450- MockedAppLocation.get_section_data_path.return_value = 'test-dir'
1451+ MockedAppLocation.get_section_data_path.return_value = Path('test-dir')
1452 mocked_delete_file.return_value = False
1453 test_plugin = 'test'
1454 test_db_file = 'mydb.sqlite'
1455- test_location = os.path.join('test-dir', test_db_file)
1456+ test_location = Path('test-dir', test_db_file)
1457
1458 # WHEN: delete_database is run without a database file
1459 result = delete_database(test_plugin, test_db_file)
1460
1461=== removed file 'tests/functional/openlp_core_lib/test_file_dialog.py'
1462--- tests/functional/openlp_core_lib/test_file_dialog.py 2017-08-07 21:12:42 +0000
1463+++ tests/functional/openlp_core_lib/test_file_dialog.py 1970-01-01 00:00:00 +0000
1464@@ -1,45 +0,0 @@
1465-# -*- coding: utf-8 -*-
1466-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
1467-
1468-###############################################################################
1469-# OpenLP - Open Source Lyrics Projection #
1470-# --------------------------------------------------------------------------- #
1471-# Copyright (c) 2008-2017 OpenLP Developers #
1472-# --------------------------------------------------------------------------- #
1473-# This program is free software; you can redistribute it and/or modify it #
1474-# under the terms of the GNU General Public License as published by the Free #
1475-# Software Foundation; version 2 of the License. #
1476-# #
1477-# This program is distributed in the hope that it will be useful, but WITHOUT #
1478-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
1479-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
1480-# more details. #
1481-# #
1482-# You should have received a copy of the GNU General Public License along #
1483-# with this program; if not, write to the Free Software Foundation, Inc., 59 #
1484-# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
1485-###############################################################################
1486-"""
1487-Package to test the openlp.core.ui.lib.filedialog package.
1488-"""
1489-from unittest import TestCase
1490-from unittest.mock import MagicMock, patch
1491-
1492-
1493-class TestFileDialog(TestCase):
1494- """
1495- Test the functions in the :mod:`filedialog` module.
1496- """
1497- def setUp(self):
1498- self.os_patcher = patch('openlp.core.ui.lib.filedialog.os')
1499- self.qt_gui_patcher = patch('openlp.core.ui.lib.filedialog.QtWidgets')
1500- self.ui_strings_patcher = patch('openlp.core.ui.lib.filedialog.UiStrings')
1501- self.mocked_os = self.os_patcher.start()
1502- self.mocked_qt_gui = self.qt_gui_patcher.start()
1503- self.mocked_ui_strings = self.ui_strings_patcher.start()
1504- self.mocked_parent = MagicMock()
1505-
1506- def tearDown(self):
1507- self.os_patcher.stop()
1508- self.qt_gui_patcher.stop()
1509- self.ui_strings_patcher.stop()
1510
1511=== modified file 'tests/functional/openlp_core_lib/test_lib.py'
1512--- tests/functional/openlp_core_lib/test_lib.py 2017-08-04 17:40:57 +0000
1513+++ tests/functional/openlp_core_lib/test_lib.py 2017-08-23 20:14:53 +0000
1514@@ -24,6 +24,7 @@
1515 """
1516 import os
1517 from datetime import datetime, timedelta
1518+from pathlib import Path
1519 from unittest import TestCase
1520 from unittest.mock import MagicMock, patch
1521
1522@@ -148,35 +149,34 @@
1523 """
1524 Test the get_text_file_string() function when a file does not exist
1525 """
1526- with patch('openlp.core.lib.os.path.isfile') as mocked_isfile:
1527- # GIVEN: A mocked out isfile which returns true, and a text file name
1528- filename = 'testfile.txt'
1529- mocked_isfile.return_value = False
1530+ # GIVEN: A patched is_file which returns False, and a file path
1531+ with patch.object(Path, 'is_file', return_value=False):
1532+ file_path = Path('testfile.txt')
1533
1534 # WHEN: get_text_file_string is called
1535- result = get_text_file_string(filename)
1536+ result = get_text_file_string(file_path)
1537
1538 # THEN: The result should be False
1539- mocked_isfile.assert_called_with(filename)
1540+ file_path.is_file.assert_called_with()
1541 self.assertFalse(result, 'False should be returned if no file exists')
1542
1543 def test_get_text_file_string_read_error(self):
1544 """
1545 Test the get_text_file_string() method when a read error happens
1546 """
1547- with patch('openlp.core.lib.os.path.isfile') as mocked_isfile, \
1548- patch('openlp.core.lib.open', create=True) as mocked_open:
1549- # GIVEN: A mocked-out open() which raises an exception and isfile returns True
1550- filename = 'testfile.txt'
1551- mocked_isfile.return_value = True
1552- mocked_open.side_effect = IOError()
1553+ # GIVEN: A patched open which raises an exception and is_file which returns True
1554+ with patch.object(Path, 'is_file'), \
1555+ patch.object(Path, 'open'):
1556+ file_path = Path('testfile.txt')
1557+ file_path.is_file.return_value = True
1558+ file_path.open.side_effect = IOError()
1559
1560 # WHEN: get_text_file_string is called
1561- result = get_text_file_string(filename)
1562+ result = get_text_file_string(file_path)
1563
1564 # THEN: None should be returned
1565- mocked_isfile.assert_called_with(filename)
1566- mocked_open.assert_called_with(filename, 'r', encoding='utf-8')
1567+ file_path.is_file.assert_called_once_with()
1568+ file_path.open.assert_called_once_with('r', encoding='utf-8')
1569 self.assertIsNone(result, 'None should be returned if the file cannot be opened')
1570
1571 def test_get_text_file_string_decode_error(self):
1572
1573=== modified file 'tests/functional/openlp_core_ui/test_firsttimeform.py'
1574--- tests/functional/openlp_core_ui/test_firsttimeform.py 2017-04-24 05:17:55 +0000
1575+++ tests/functional/openlp_core_ui/test_firsttimeform.py 2017-08-23 20:14:53 +0000
1576@@ -25,6 +25,7 @@
1577 import os
1578 import tempfile
1579 import urllib
1580+from pathlib import Path
1581 from unittest import TestCase
1582 from unittest.mock import MagicMock, patch
1583
1584@@ -116,7 +117,7 @@
1585 mocked_settings.value.return_value = True
1586 MockedSettings.return_value = mocked_settings
1587 mocked_gettempdir.return_value = 'temp'
1588- expected_temp_path = os.path.join('temp', 'openlp')
1589+ expected_temp_path = Path('temp', 'openlp')
1590
1591 # WHEN: The set_defaults() method is run
1592 frw.set_defaults()
1593
1594=== modified file 'tests/functional/openlp_core_ui/test_thememanager.py'
1595--- tests/functional/openlp_core_ui/test_thememanager.py 2017-06-01 06:18:47 +0000
1596+++ tests/functional/openlp_core_ui/test_thememanager.py 2017-08-23 20:14:53 +0000
1597@@ -90,7 +90,7 @@
1598 # theme, check_directory_exists and thememanager-attributes.
1599 with patch('builtins.open') as mocked_open, \
1600 patch('openlp.core.ui.thememanager.shutil.copyfile') as mocked_copyfile, \
1601- patch('openlp.core.ui.thememanager.check_directory_exists') as mocked_check_directory_exists:
1602+ patch('openlp.core.ui.thememanager.check_directory_exists'):
1603 mocked_open.return_value = MagicMock()
1604 theme_manager = ThemeManager(None)
1605 theme_manager.old_background_image = None
1606@@ -118,7 +118,7 @@
1607 # theme, check_directory_exists and thememanager-attributes.
1608 with patch('builtins.open') as mocked_open, \
1609 patch('openlp.core.ui.thememanager.shutil.copyfile') as mocked_copyfile, \
1610- patch('openlp.core.ui.thememanager.check_directory_exists') as mocked_check_directory_exists:
1611+ patch('openlp.core.ui.thememanager.check_directory_exists'):
1612 mocked_open.return_value = MagicMock()
1613 theme_manager = ThemeManager(None)
1614 theme_manager.old_background_image = None
1615
1616=== modified file 'tests/functional/openlp_plugins/bibles/test_manager.py'
1617--- tests/functional/openlp_plugins/bibles/test_manager.py 2016-12-31 11:01:36 +0000
1618+++ tests/functional/openlp_plugins/bibles/test_manager.py 2017-08-23 20:14:53 +0000
1619@@ -22,6 +22,7 @@
1620 """
1621 This module contains tests for the manager submodule of the Bibles plugin.
1622 """
1623+from pathlib import Path
1624 from unittest import TestCase
1625 from unittest.mock import MagicMock, patch
1626
1627@@ -50,7 +51,6 @@
1628 """
1629 # GIVEN: An instance of BibleManager and a mocked bible
1630 with patch.object(BibleManager, 'reload_bibles'), \
1631- patch('openlp.plugins.bibles.lib.manager.os.path.join', side_effect=lambda x, y: '{}/{}'.format(x, y)),\
1632 patch('openlp.plugins.bibles.lib.manager.delete_file', return_value=True) as mocked_delete_file:
1633 instance = BibleManager(MagicMock())
1634 # We need to keep a reference to the mock for close_all as it gets set to None later on!
1635@@ -66,4 +66,4 @@
1636 self.assertTrue(result)
1637 mocked_close_all.assert_called_once_with()
1638 self.assertIsNone(mocked_bible.session)
1639- mocked_delete_file.assert_called_once_with('bibles/KJV.sqlite')
1640+ mocked_delete_file.assert_called_once_with(Path('bibles', 'KJV.sqlite'))
1641
1642=== modified file 'tests/functional/openlp_plugins/media/test_mediaplugin.py'
1643--- tests/functional/openlp_plugins/media/test_mediaplugin.py 2017-06-06 20:58:12 +0000
1644+++ tests/functional/openlp_plugins/media/test_mediaplugin.py 2017-08-23 20:14:53 +0000
1645@@ -38,20 +38,18 @@
1646 def setUp(self):
1647 Registry.create()
1648
1649- @patch(u'openlp.plugins.media.mediaplugin.Plugin.initialise')
1650+ @patch('openlp.plugins.media.mediaplugin.Plugin.initialise')
1651 def test_initialise(self, mocked_initialise):
1652 """
1653 Test that the initialise() method overwrites the built-in one, but still calls it
1654 """
1655- # GIVEN: A media plugin instance and a mocked settings object
1656+ # GIVEN: A media plugin instance
1657 media_plugin = MediaPlugin()
1658- mocked_settings = MagicMock()
1659- mocked_settings.get_files_from_config.return_value = True # Not the real value, just need something "true-ish"
1660
1661 # WHEN: initialise() is called
1662 media_plugin.initialise()
1663
1664- # THEN: The settings should be upgraded and the base initialise() method should be called
1665+ # THEN: The the base initialise() method should be called
1666 mocked_initialise.assert_called_with()
1667
1668 def test_about_text(self):
1669
1670=== modified file 'tests/functional/openlp_plugins/presentations/test_presentationcontroller.py'
1671--- tests/functional/openlp_plugins/presentations/test_presentationcontroller.py 2017-05-30 18:42:35 +0000
1672+++ tests/functional/openlp_plugins/presentations/test_presentationcontroller.py 2017-08-23 20:14:53 +0000
1673@@ -24,6 +24,7 @@
1674 classes and related methods.
1675 """
1676 import os
1677+from pathlib import Path
1678 from unittest import TestCase
1679 from unittest.mock import MagicMock, mock_open, patch
1680
1681@@ -38,7 +39,8 @@
1682 """
1683 def setUp(self):
1684 self.get_thumbnail_folder_patcher = \
1685- patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder')
1686+ patch('openlp.plugins.presentations.lib.presentationcontroller.PresentationDocument.get_thumbnail_folder',
1687+ return_value=Path())
1688 self.get_thumbnail_folder_patcher.start()
1689 mocked_plugin = MagicMock()
1690 mocked_plugin.settings_section = 'presentations'
1691@@ -225,7 +227,7 @@
1692 PresentationDocument(self.mock_controller, 'Name')
1693
1694 # THEN: check_directory_exists should have been called with 'returned/path/'
1695- self.mock_check_directory_exists.assert_called_once_with('returned/path/')
1696+ self.mock_check_directory_exists.assert_called_once_with(Path('returned', 'path'))
1697
1698 self._setup_patcher.start()
1699
1700
1701=== modified file 'tests/interfaces/openlp_core_common/test_utils.py'
1702--- tests/interfaces/openlp_core_common/test_utils.py 2016-12-31 11:01:36 +0000
1703+++ tests/interfaces/openlp_core_common/test_utils.py 2017-08-23 20:14:53 +0000
1704@@ -22,7 +22,7 @@
1705 """
1706 Functional tests to test the AppLocation class and related methods.
1707 """
1708-import os
1709+from pathlib import Path
1710 from unittest import TestCase
1711
1712 from openlp.core.common import is_not_image_file
1713@@ -59,7 +59,7 @@
1714 Test the method handles an image file
1715 """
1716 # Given and empty string
1717- file_name = os.path.join(TEST_RESOURCES_PATH, 'church.jpg')
1718+ file_name = Path(TEST_RESOURCES_PATH, 'church.jpg')
1719
1720 # WHEN testing for it
1721 result = is_not_image_file(file_name)
1722@@ -72,7 +72,7 @@
1723 Test the method handles a non image file
1724 """
1725 # Given and empty string
1726- file_name = os.path.join(TEST_RESOURCES_PATH, 'serviceitem_custom_1.osj')
1727+ file_name = Path(TEST_RESOURCES_PATH, 'serviceitem_custom_1.osj')
1728
1729 # WHEN testing for it
1730 result = is_not_image_file(file_name)