Merge branch 'fix-resolve' into 'master'

Fix the resolve issue on Windows

See merge request openlp/openlp!465
This commit is contained in:
Raoul Snyman 2022-06-28 19:26:11 +00:00
commit a467a3a91e
48 changed files with 371 additions and 234 deletions

View File

@ -29,9 +29,9 @@ import multiprocessing
# from OpenGL import GL # noqa
from openlp.core.app import main
from openlp.core.common import is_win
from openlp.core.common.applocation import AppLocation
from openlp.core.common.path import create_paths
from openlp.core.common.platform import is_win
log = logging.getLogger(__name__)
error_log_file = None

View File

@ -38,11 +38,11 @@ from traceback import format_exception
from PyQt5 import QtCore, QtGui, QtWebEngineWidgets, QtWidgets # noqa
from openlp.core.api.deploy import check_for_remote_update
from openlp.core.common import is_macosx, is_win
from openlp.core.common.applocation import AppLocation
from openlp.core.common.i18n import LanguageManager, UiStrings, translate
from openlp.core.common.mixins import LogMixin
from openlp.core.common.path import create_paths
from openlp.core.common.path import create_paths, resolve
from openlp.core.common.platform import is_macosx, is_win
from openlp.core.common.registry import Registry
from openlp.core.common.settings import Settings
from openlp.core.display.screens import ScreenList
@ -418,7 +418,7 @@ def main():
portable_path = AppLocation.get_directory(AppLocation.AppDir) / '..' / args.portablepath
else:
portable_path = AppLocation.get_directory(AppLocation.AppDir) / '..' / '..'
portable_path = portable_path.resolve()
portable_path = resolve(portable_path)
data_path = portable_path / 'Data'
set_up_logging(portable_path / 'Other')
log.info('Running portable')

View File

@ -25,7 +25,6 @@ OpenLP work.
import hashlib
import importlib
import logging
import os
import re
import sys
import traceback
@ -37,13 +36,6 @@ from PyQt5.QtCore import QCryptographicHash as QHash
from PyQt5.QtNetwork import QAbstractSocket, QHostAddress, QNetworkInterface
from chardet.universaldetector import UniversalDetector
try:
from distro import id as distro_id
except ImportError:
# The distro module is only valid for Linux, so if it doesn't exist, create a function that always returns False
def distro_id():
return False
log = logging.getLogger(__name__ + '.__init__')
@ -200,47 +192,6 @@ def de_hump(name):
return SECOND_CAMEL_REGEX.sub(r'\1_\2', sub_name).lower()
def is_win():
"""
Returns true if running on a system with a nt kernel e.g. Windows, Wine
:return: True if system is running a nt kernel false otherwise
"""
return os.name.startswith('nt')
def is_macosx():
"""
Returns true if running on a system with a darwin kernel e.g. Mac OS X
:return: True if system is running a darwin kernel false otherwise
"""
return sys.platform.startswith('darwin')
def is_linux(distro=None):
"""
Returns true if running on a system with a linux kernel e.g. Ubuntu, Debian, etc
:param distro: If not None, check if running that Linux distro
:return: True if system is running a linux kernel false otherwise
"""
result = sys.platform.startswith('linux')
if result and distro:
result = result and distro == distro_id()
return result
def is_64bit_instance():
"""
Returns true if the python/OpenLP instance running is 64 bit. If running a 32 bit instance on
a 64 bit system this will return false.
:return: True if the python/OpenLP instance running is 64 bit, otherwise False.
"""
return (sys.maxsize > 2**32)
def verify_ipv4(addr):
"""
Validate an IPv4 address

View File

@ -29,8 +29,9 @@ from pathlib import Path
import appdirs
import openlp
from openlp.core.common import get_frozen_path, is_macosx, is_win
from openlp.core.common.path import create_paths
from openlp.core.common import get_frozen_path
from openlp.core.common.path import create_paths, resolve
from openlp.core.common.platform import is_macosx, is_win
from openlp.core.common.registry import Registry
@ -68,11 +69,7 @@ class AppLocation(object):
path = get_frozen_path(FROZEN_APP_PATH, _get_os_dir_path(dir_type)) / 'i18n'
else:
path = _get_os_dir_path(dir_type)
# resolve() does not work on windows
if is_win():
return Path.cwd() / path
else:
return path.resolve()
return resolve(path)
@staticmethod
def get_data_path():
@ -134,7 +131,7 @@ def _get_os_dir_path(dir_type):
"""
# If running from source, return the language directory from the source directory
if dir_type == AppLocation.LanguageDir:
directory = Path(openlp.__file__, '..', '..').resolve() / 'resources'
directory = resolve(Path(openlp.__file__, '..', '..')) / 'resources'
if directory.exists():
return directory
if is_win():

View File

@ -28,8 +28,9 @@ from collections import namedtuple
from PyQt5 import QtCore, QtWidgets
from openlp.core.common import Singleton, is_macosx, is_win
from openlp.core.common import Singleton
from openlp.core.common.applocation import AppLocation
from openlp.core.common.platform import is_macosx, is_win
from openlp.core.common.registry import Registry
log = logging.getLogger(__name__)

View File

@ -24,7 +24,8 @@ Provide Error Handling and login Services
import inspect
import logging
from openlp.core.common import is_win, trace_error_handler
from openlp.core.common import trace_error_handler
from openlp.core.common.platform import is_win
from openlp.core.common.registry import Registry

View File

@ -19,9 +19,13 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
##########################################################################
import logging
import os
import shutil
from pathlib import Path
from openlp.core.common.platform import is_win
log = logging.getLogger(__name__)
@ -135,3 +139,20 @@ def files_to_paths(file_names):
"""
if file_names:
return [str_to_path(file_name) for file_name in file_names]
def resolve(path_obj, is_strict=False):
"""
Resolve a Path object, bypassing symlink resolving on Windows
:param Path path_obj: The path object to resolve
:return: The resolved Path object
:rtype: Path
"""
if is_win():
resolved_path = Path(os.path.abspath(path_obj))
if is_strict:
# Mirror the behaviour of Path.resolve(strict=True)
resolved_path.lstat()
return resolved_path
return path_obj.resolve(strict=is_strict)

View File

@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
##########################################################################
# OpenLP - Open Source Lyrics Projection #
# ---------------------------------------------------------------------- #
# Copyright (c) 2008-2022 OpenLP Developers #
# ---------------------------------------------------------------------- #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
##########################################################################
"""
The :mod:`~openlp.core.common.platform` module contains functions related to the platform that
OpenLP is currently running on.
"""
import os
import sys
try:
from distro import id as distro_id
except ImportError:
# The distro module is only valid for Linux, so if it doesn't exist, create a function that always
# returns False
def distro_id():
return False
def is_win():
"""
Returns true if running on a system with a nt kernel e.g. Windows, Wine
:return: True if system is running a nt kernel false otherwise
"""
return os.name.startswith('nt')
def is_macosx():
"""
Returns true if running on a system with a darwin kernel e.g. Mac OS X
:return: True if system is running a darwin kernel false otherwise
"""
return sys.platform.startswith('darwin')
def is_linux(distro=None):
"""
Returns true if running on a system with a linux kernel e.g. Ubuntu, Debian, etc
:param distro: If not None, check if running that Linux distro
:return: True if system is running a linux kernel false otherwise
"""
result = sys.platform.startswith('linux')
if result and distro:
result = result and distro == distro_id()
return result
def is_64bit_instance():
"""
Returns true if the python/OpenLP instance running is 64 bit. If running a 32 bit instance on
a 64 bit system this will return false.
:return: True if the python/OpenLP instance running is 64 bit, otherwise False.
"""
return (sys.maxsize > 2**32)

View File

@ -32,11 +32,12 @@ from tempfile import gettempdir
from PyQt5 import QtCore, QtGui
from openlp.core.common import SlideLimits, ThemeLevel, is_linux, is_win
from openlp.core.common import SlideLimits, ThemeLevel
from openlp.core.common.enum import AlertLocation, BibleSearch, CustomSearch, ImageThemeMode, LayoutStyle, \
DisplayStyle, LanguageSelection, SongSearch, PluginStatus
from openlp.core.common.json import OpenLPJSONDecoder, OpenLPJSONEncoder, is_serializable
from openlp.core.common.path import files_to_paths, str_to_path
from openlp.core.common.platform import is_linux, is_win
log = logging.getLogger(__name__)

View File

@ -29,12 +29,12 @@ import re
from PyQt5 import QtCore, QtWebChannel, QtWidgets
from openlp.core.common import is_win, is_macosx
from openlp.core.common.applocation import AppLocation
from openlp.core.common.enum import ServiceItemType
from openlp.core.common.i18n import translate
from openlp.core.common.mixins import LogMixin, RegistryProperties
from openlp.core.common.path import path_to_str
from openlp.core.common.platform import is_win, is_macosx
from openlp.core.common.registry import Registry
from openlp.core.common.utils import wait_for
from openlp.core.display.screens import ScreenList

View File

@ -25,9 +25,9 @@ import logging
from PyQt5 import QtCore, QtGui, QtWidgets
from openlp.core.common import is_macosx
from openlp.core.common.actions import ActionList
from openlp.core.common.i18n import UiStrings, translate
from openlp.core.common.platform import is_macosx
from openlp.core.common.registry import Registry
from openlp.core.lib import build_icon
from openlp.core.ui.icons import UiIcons

View File

@ -27,8 +27,8 @@ import logging
from PyQt5 import QtCore, QtWidgets
from openlp.core.common import is_macosx
from openlp.core.common.i18n import translate
from openlp.core.common.platform import is_macosx
from openlp.core.lib import build_icon
from openlp.core.projectors.constants import PJLINK_DEFAULT_CODES, PJLINK_DEFAULT_SOURCES
from openlp.core.projectors.db import ProjectorSource

View File

@ -28,9 +28,9 @@ import re
from PyQt5 import QtCore, QtGui, QtWidgets
from openlp.core.common import is_linux
from openlp.core.common.i18n import UiStrings, translate
from openlp.core.common.mixins import RegistryProperties
from openlp.core.common.platform import is_linux
from openlp.core.ui.exceptiondialog import Ui_ExceptionDialog
from openlp.core.version import get_library_versions, get_version
from openlp.core.widgets.dialogs import FileDialog

View File

@ -23,7 +23,8 @@ The UI widgets for the first time wizard.
"""
from PyQt5 import QtCore, QtGui, QtWidgets
from openlp.core.common import clean_button_text, is_macosx
from openlp.core.common import clean_button_text
from openlp.core.common.platform import is_macosx
from openlp.core.common.i18n import translate
from openlp.core.lib.ui import add_welcome_page
from openlp.core.ui.icons import UiIcons

View File

@ -28,22 +28,23 @@ from tempfile import gettempdir
from PyQt5 import QtCore, QtGui, QtWidgets
from openlp.core.state import State
from openlp.core.api.websockets import WebSocketServer
from openlp.core.api.http.server import HttpServer
from openlp.core.api.websockets import WebSocketServer
from openlp.core.api.zeroconf import start_zeroconf
from openlp.core.common import add_actions, is_macosx, is_win
from openlp.core.common import add_actions
from openlp.core.common.actions import ActionList, CategoryOrder
from openlp.core.common.applocation import AppLocation
from openlp.core.common.i18n import LanguageManager, UiStrings, translate
from openlp.core.common.mixins import LogMixin, RegistryProperties
from openlp.core.common.path import create_paths
from openlp.core.common.path import create_paths, resolve
from openlp.core.common.platform import is_macosx, is_win
from openlp.core.common.registry import Registry
from openlp.core.common.settings import Settings
from openlp.core.display.screens import ScreenList
from openlp.core.lib.plugin import PluginStatus
from openlp.core.lib.ui import create_action
from openlp.core.projectors.manager import ProjectorManager
from openlp.core.state import State
from openlp.core.ui.aboutform import AboutForm
from openlp.core.ui.firsttimeform import FirstTimeForm
from openlp.core.ui.formattingtagform import FormattingTagForm
@ -1339,7 +1340,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert
max_recent_files = self.settings.value('advanced/max recent files')
file_path = Path(filename)
# Some cleanup to reduce duplication in the recent file list
file_path = file_path.resolve()
file_path = resolve(file_path)
if file_path in self.recent_files:
self.recent_files.remove(file_path)
self.recent_files.insert(0, file_path)
@ -1444,7 +1445,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert
for arg in args:
try:
# Resolve the file, and use strict mode to throw an exception if the file does not exist
file_path = Path(arg).resolve(strict=True)
file_path = resolve(Path(arg), is_strict=True)
# Check if this is actually a file
if file_path.is_file():
break
@ -1458,7 +1459,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert
for arg in args:
path_so_far.append(arg)
try:
file_path = Path(' '.join(path_so_far)).resolve(strict=True)
file_path = resolve(Path(' '.join(path_so_far)), is_strict=True)
if file_path.is_file():
break
else:

View File

@ -32,14 +32,14 @@ except ImportError:
from PyQt5 import QtCore
from openlp.core.state import State
from openlp.core.common import is_linux, is_macosx
from openlp.core.common.i18n import translate
from openlp.core.common.mixins import LogMixin, RegistryProperties
from openlp.core.common.path import path_to_str
from openlp.core.common.platform import is_linux, is_macosx
from openlp.core.common.registry import Registry, RegistryBase
from openlp.core.lib.serviceitem import ItemCapabilities
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.state import State
from openlp.core.ui import DisplayControllerType, HideMode
from openlp.core.ui.media import MediaState, ItemMediaInfo, MediaType, parse_optical_path, parse_stream_path
from openlp.core.ui.media.remote import register_views

View File

@ -31,8 +31,8 @@ from time import sleep
from PyQt5 import QtCore, QtWidgets
from openlp.core.common import is_linux, is_macosx, is_win
from openlp.core.common.i18n import translate
from openlp.core.common.platform import is_linux, is_macosx, is_win
from openlp.core.display.screens import ScreenList
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui.media import MediaState, MediaType

View File

@ -25,7 +25,7 @@ from subprocess import Popen, PIPE
from enum import Enum
from PyQt5 import QtCore, QtGui, QtWidgets
from openlp.core.common import is_macosx, is_win
from openlp.core.common.platform import is_macosx, is_win
from openlp.core.common.registry import Registry
try:

View File

@ -23,8 +23,8 @@ The Create/Edit theme wizard
"""
from PyQt5 import QtCore, QtGui, QtWidgets
from openlp.core.common import is_macosx
from openlp.core.common.i18n import translate
from openlp.core.common.platform import is_macosx
from openlp.core.display.render import ThemePreviewRenderer
from openlp.core.lib.ui import add_welcome_page
from openlp.core.pages.alignment import AlignmentTransitionsPage

View File

@ -26,9 +26,9 @@ from pathlib import Path
from PyQt5 import QtCore, QtGui, QtWidgets
from openlp.core.common import is_win
from openlp.core.common.i18n import UiStrings
from openlp.core.common.mixins import RegistryProperties
from openlp.core.common.platform import is_win
from openlp.core.common.registry import Registry
from openlp.core.lib.serviceitem import ItemCapabilities, ServiceItem
from openlp.core.widgets.layouts import AspectRatioLayout

View File

@ -25,9 +25,9 @@ import logging
from PyQt5 import QtCore, QtGui, QtWidgets
from openlp.core.common import is_macosx
from openlp.core.common.i18n import translate
from openlp.core.common.mixins import RegistryProperties
from openlp.core.common.platform import is_macosx
from openlp.core.common.registry import Registry
from openlp.core.lib.ui import add_welcome_page
from openlp.core.ui.icons import UiIcons

View File

@ -27,9 +27,9 @@ from time import sleep
from PyQt5 import QtCore, QtWidgets
from openlp.core.common import is_linux, is_macosx, is_win
from openlp.core.common.i18n import translate
from openlp.core.common.mixins import RegistryProperties
from openlp.core.common.platform import is_linux, is_macosx, is_win
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui.icons import UiIcons
from openlp.core.ui.media.vlcplayer import get_vlc

View File

@ -32,8 +32,8 @@ import re
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtMultimedia import QCameraInfo, QAudioDeviceInfo, QAudio
from openlp.core.common import is_linux, is_macosx, is_win
from openlp.core.common.i18n import translate
from openlp.core.common.platform import is_linux, is_macosx, is_win
from openlp.plugins.media.forms import VLCOptionsWidget
# Copied from VLC source code: modules/access/v4l2/v4l2.c

View File

@ -30,7 +30,7 @@ except ImportError:
APPLESCRIPT_AVAILABLE = False
from openlp.core.common import is_macosx
from openlp.core.common.platform import is_macosx
from openlp.core.display.screens import ScreenList
from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument

View File

@ -35,7 +35,8 @@ import time
from PyQt5 import QtCore
from openlp.core.common import delete_file, get_uno_command, get_uno_instance, is_win, trace_error_handler
from openlp.core.common import delete_file, get_uno_command, get_uno_instance, trace_error_handler
from openlp.core.common.platform import is_win
from openlp.core.common.registry import Registry
from openlp.core.common.settings import Settings
from openlp.core.display.screens import ScreenList

View File

@ -22,10 +22,11 @@
import logging
from subprocess import Popen
from openlp.core.common import delete_file, is_macosx
from openlp.core.common import delete_file
from openlp.core.common.applocation import AppLocation
from openlp.core.common.mixins import LogMixin
from openlp.core.common.path import Path
from openlp.core.common.platform import is_macosx
from openlp.core.common.registry import Registry
from openlp.core.display.screens import ScreenList
from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument

View File

@ -26,8 +26,9 @@ This module is for controlling powerpoint. PPT API documentation:
"""
import logging
from openlp.core.common import is_win, trace_error_handler
from openlp.core.common import trace_error_handler
from openlp.core.common.i18n import UiStrings
from openlp.core.common.platform import is_win
from openlp.core.common.registry import Registry
from openlp.core.display.screens import ScreenList
from openlp.core.lib.ui import critical_error_message_box, translate

View File

@ -23,8 +23,8 @@ The :mod:`importer` modules provides the general song import functionality.
"""
import logging
from openlp.core.common import is_win
from openlp.core.common.i18n import UiStrings, translate
from openlp.core.common.platform import is_win
from openlp.core.widgets.wizard import WizardStrings
from .importers.cclifile import CCLIFileImport

View File

@ -23,8 +23,9 @@ import time
from PyQt5 import QtCore
from openlp.core.common import get_uno_command, get_uno_instance, is_win, normalize_str
from openlp.core.common import get_uno_command, get_uno_instance, normalize_str
from openlp.core.common.i18n import translate
from openlp.core.common.platform import is_win
from .songimport import SongImport

View File

@ -28,8 +28,9 @@ import os
import re
from pathlib import Path
from openlp.core.common import get_file_encoding, is_macosx, is_win
from openlp.core.common import get_file_encoding
from openlp.core.common.i18n import translate
from openlp.core.common.platform import is_macosx, is_win
from openlp.plugins.songs.lib import VerseType
from openlp.plugins.songs.lib.importers.songimport import SongImport

View File

@ -28,7 +28,7 @@
import logging
import re
from openlp.core.common import is_win
from openlp.core.common.platform import is_win
from .openoffice import OpenOfficeImport

View File

@ -19,20 +19,18 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
##########################################################################
"""
Functional tests to test the AppLocation class and related methods.
Functional tests to test the :mod:`~openlp.core.common` module
"""
import os
from io import BytesIO
from pathlib import Path
from unittest import skipUnless
from unittest.mock import MagicMock, PropertyMock, call, patch
import pytest
from openlp.core.common import Singleton, add_actions, clean_filename, clean_button_text, de_hump, delete_file, \
extension_loader, get_file_encoding, get_filesystem_encoding, get_uno_command, get_uno_instance, is_linux, \
is_macosx, is_win, is_64bit_instance, md5_hash, normalize_str, path_to_module, qmd5_hash, sha256_file_hash, \
trace_error_handler, verify_ip_address
extension_loader, get_file_encoding, get_filesystem_encoding, get_uno_command, get_uno_instance, md5_hash, \
normalize_str, path_to_module, qmd5_hash, sha256_file_hash, trace_error_handler, verify_ip_address
from tests.resources.projector.data import TEST_HASH, TEST_PIN, TEST_SALT
from tests.utils.constants import TEST_RESOURCES_PATH
@ -231,93 +229,6 @@ def test_singleton_metaclass_multiple_classes():
assert isinstance(s_c2, SingletonClass2)
def test_is_win():
"""
Test the is_win() function
"""
# GIVEN: Mocked out objects
with patch('openlp.core.common.os') as mocked_os, patch('openlp.core.common.sys') as mocked_sys:
# WHEN: The mocked os.name and sys.platform are set to 'nt' and 'win32' repectivly
mocked_os.name = 'nt'
mocked_sys.platform = 'win32'
# THEN: The three platform functions should perform properly
assert is_win() is True, 'is_win() should return True'
assert is_macosx() is False, 'is_macosx() should return False'
assert is_linux() is False, 'is_linux() should return False'
def test_is_macosx():
"""
Test the is_macosx() function
"""
# GIVEN: Mocked out objects
with patch('openlp.core.common.os') as mocked_os, patch('openlp.core.common.sys') as mocked_sys:
# WHEN: The mocked os.name and sys.platform are set to 'posix' and 'darwin' repectivly
mocked_os.name = 'posix'
mocked_sys.platform = 'darwin'
# THEN: The three platform functions should perform properly
assert is_macosx() is True, 'is_macosx() should return True'
assert is_win() is False, 'is_win() should return False'
assert is_linux() is False, 'is_linux() should return False'
def test_is_linux():
"""
Test the is_linux() function
"""
# GIVEN: Mocked out objects
with patch('openlp.core.common.os') as mocked_os, patch('openlp.core.common.sys') as mocked_sys:
# WHEN: The mocked os.name and sys.platform are set to 'posix' and 'linux3' repectively
mocked_os.name = 'posix'
mocked_sys.platform = 'linux3'
# THEN: The three platform functions should perform properly
assert is_linux() is True, 'is_linux() should return True'
assert is_win() is False, 'is_win() should return False'
assert is_macosx() is False, 'is_macosx() should return False'
@skipUnless(is_linux(), 'This can only run on Linux')
def test_is_linux_distro():
"""
Test the is_linux() function for a particular Linux distribution
"""
# GIVEN: Mocked out objects
with patch('openlp.core.common.os') as mocked_os, \
patch('openlp.core.common.sys') as mocked_sys, \
patch('openlp.core.common.distro_id') as mocked_distro_id:
# WHEN: The mocked os.name and sys.platform are set to 'posix' and 'linux3' repectively
# and the distro is Fedora
mocked_os.name = 'posix'
mocked_sys.platform = 'linux3'
mocked_distro_id.return_value = 'fedora'
# THEN: The three platform functions should perform properly
assert is_linux(distro='fedora') is True, 'is_linux(distro="fedora") should return True'
assert is_win() is False, 'is_win() should return False'
assert is_macosx() is False, 'is_macosx() should return False'
def test_is_64bit_instance():
"""
Test the is_64bit_instance() function
"""
# GIVEN: Mocked out objects
with patch('openlp.core.common.sys') as mocked_sys:
# WHEN: The mocked sys.maxsize is set to 32-bit
mocked_sys.maxsize = 2**32
# THEN: The result should be False
assert is_64bit_instance() is False, 'is_64bit_instance() should return False'
def test_normalize_str_leaves_newlines():
# GIVEN: a string containing newlines
string = 'something\nelse'
@ -782,13 +693,15 @@ def test_delete_file_path_success():
"""
Test the delete_file function when it successfully deletes a file
"""
# GIVEN: A mocked os which returns True when os.path.exists is called
with patch('openlp.core.common.os', **{'path.exists.return_value': False}):
# GIVEN: A patched 'exists' method which returns True when called
with patch.object(Path, 'exists', return_value=True), \
patch.object(Path, 'unlink') as mocked_unlink:
# WHEN: Calling delete_file with a file path
result = delete_file(Path('path', 'file.ext'))
# THEN: delete_file should return True
assert mocked_unlink.called is True
assert result is True, 'delete_file should return True when it successfully deletes a file'

View File

@ -27,8 +27,8 @@ from pathlib import Path
from unittest import TestCase
from unittest.mock import patch
from openlp.core.common import is_win
from openlp.core.common.json import JSONMixin, OpenLPJSONDecoder, OpenLPJSONEncoder, PathSerializer, _registered_classes
from openlp.core.common.platform import is_win
class BaseTestClass(object):

View File

@ -27,7 +27,8 @@ from pathlib import Path
from unittest.mock import MagicMock, patch
from openlp.core.common.path import create_paths, files_to_paths, path_to_str, replace_params, str_to_path, which
from openlp.core.common.path import create_paths, files_to_paths, path_to_str, replace_params, str_to_path, which, \
resolve
def test_replace_params_no_params():
@ -242,3 +243,36 @@ def test_files_to_paths():
# THEN: The result should be a list of Paths
assert result == [Path('/tmp/openlp/file1.txt'), Path('/tmp/openlp/file2.txt')]
@patch('openlp.core.common.path.is_win')
def test_resolve_posix(mocked_is_win):
"""Test the resolve() method correctly resolves POSIX paths"""
# GIVEN: A mocked PosixPath class
mocked_is_win.return_value = False
mocked_path = MagicMock()
# WHEN: resolve() is called
resolve(mocked_path)
# THEN: the Path.resolve() method should have been called
mocked_path.resolve.assert_called_once_with(strict=False)
@patch('openlp.core.common.path.is_win')
@patch('openlp.core.common.path.os.path.abspath')
@patch('openlp.core.common.path.Path')
def test_resolve_windows(MockPath, mocked_abspath, mocked_is_win):
"""Test the resolve() method correctly resolves Windows paths"""
# GIVEN: A mocked WindowsPath class
mocked_is_win.return_value = True
mocked_path = MagicMock()
# Reuse the object, even though the code creates a new Path object
MockPath.return_value = mocked_path
# WHEN: resolve() is called
resolve(mocked_path, is_strict=True)
# THEN: the Path.resolve() method should have been called
mocked_abspath.assert_called_once_with(mocked_path)
mocked_path.lstat.assert_called_once_with()

View File

@ -0,0 +1,118 @@
# -*- coding: utf-8 -*-
##########################################################################
# OpenLP - Open Source Lyrics Projection #
# ---------------------------------------------------------------------- #
# Copyright (c) 2008-2022 OpenLP Developers #
# ---------------------------------------------------------------------- #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
##########################################################################
"""
Functional tests to test the :mod:`~openlp.core.common.platform` module.
"""
from unittest.mock import patch
import pytest
from openlp.core.common.platform import is_win, is_macosx, is_linux, is_64bit_instance
def test_is_win():
"""
Test the is_win() function
"""
# GIVEN: Mocked out objects
with patch('openlp.core.common.platform.os') as mocked_os, \
patch('openlp.core.common.platform.sys') as mocked_sys:
# WHEN: The mocked os.name and sys.platform are set to 'nt' and 'win32' repectivly
mocked_os.name = 'nt'
mocked_sys.platform = 'win32'
# THEN: The three platform functions should perform properly
assert is_win() is True, 'is_win() should return True'
assert is_macosx() is False, 'is_macosx() should return False'
assert is_linux() is False, 'is_linux() should return False'
def test_is_macosx():
"""
Test the is_macosx() function
"""
# GIVEN: Mocked out objects
with patch('openlp.core.common.platform.os') as mocked_os, \
patch('openlp.core.common.platform.sys') as mocked_sys:
# WHEN: The mocked os.name and sys.platform are set to 'posix' and 'darwin' repectivly
mocked_os.name = 'posix'
mocked_sys.platform = 'darwin'
# THEN: The three platform functions should perform properly
assert is_macosx() is True, 'is_macosx() should return True'
assert is_win() is False, 'is_win() should return False'
assert is_linux() is False, 'is_linux() should return False'
def test_is_linux():
"""
Test the is_linux() function
"""
# GIVEN: Mocked out objects
with patch('openlp.core.common.platform.os') as mocked_os, \
patch('openlp.core.common.platform.sys') as mocked_sys:
# WHEN: The mocked os.name and sys.platform are set to 'posix' and 'linux3' repectively
mocked_os.name = 'posix'
mocked_sys.platform = 'linux3'
# THEN: The three platform functions should perform properly
assert is_linux() is True, 'is_linux() should return True'
assert is_win() is False, 'is_win() should return False'
assert is_macosx() is False, 'is_macosx() should return False'
@pytest.mark.skipif(not is_linux(), reason='This can only run on Linux')
def test_is_linux_distro():
"""
Test the is_linux() function for a particular Linux distribution
"""
# GIVEN: Mocked out objects
with patch('openlp.core.common.platform.os') as mocked_os, \
patch('openlp.core.common.platform.sys') as mocked_sys, \
patch('openlp.core.common.platform.distro_id') as mocked_distro_id:
# WHEN: The mocked os.name and sys.platform are set to 'posix' and 'linux3' repectively
# and the distro is Fedora
mocked_os.name = 'posix'
mocked_sys.platform = 'linux3'
mocked_distro_id.return_value = 'fedora'
# THEN: The three platform functions should perform properly
assert is_linux(distro='fedora') is True, 'is_linux(distro="fedora") should return True'
assert is_win() is False, 'is_win() should return False'
assert is_macosx() is False, 'is_macosx() should return False'
def test_is_64bit_instance():
"""
Test the is_64bit_instance() function
"""
# GIVEN: Mocked out objects
with patch('openlp.core.common.platform.sys') as mocked_sys:
# WHEN: The mocked sys.maxsize is set to 32-bit
mocked_sys.maxsize = 2**32
# THEN: The result should be False
assert is_64bit_instance() is False, 'is_64bit_instance() should return False'

View File

@ -34,7 +34,7 @@ from PyQt5 import QtCore
sys.modules['PyQt5.QtWebEngineWidgets'] = MagicMock()
from openlp.core.display.window import TRANSITION_END_EVENT_NAME, DisplayWindow, DisplayWatcher
from openlp.core.common import is_win
from openlp.core.common.platform import is_win
from openlp.core.common.enum import ServiceItemType
from openlp.core.lib.theme import Theme
from openlp.core.ui import HideMode

View File

@ -32,7 +32,7 @@ from unittest.mock import MagicMock, patch
from PyQt5 import QtWidgets
from openlp.core.state import State
from openlp.core.common import is_win
from openlp.core.common.platform import is_win
from openlp.core.common.registry import Registry
from openlp.core.common.settings import Settings
from openlp.core.lib.plugin import PluginStatus

View File

@ -26,8 +26,9 @@ import pytest
from pathlib import Path
from unittest.mock import Mock, MagicMock, patch
from openlp.core.common import ThemeLevel, is_win
from openlp.core.common import ThemeLevel
from openlp.core.common.enum import ServiceItemType
from openlp.core.common.platform import is_win
from openlp.core.common.registry import Registry
from openlp.core.lib.formattingtags import FormattingTags
from openlp.core.lib.serviceitem import ItemCapabilities, ServiceItem

View File

@ -32,7 +32,7 @@ from PyQt5 import QtCore, QtWidgets
sys.modules['PyQt5.QtWebEngineWidgets'] = MagicMock()
from openlp.core.app import parse_options, backup_if_version_changed, main as app_main
from openlp.core.common import is_win
from openlp.core.common.platform import is_win
@pytest.fixture

View File

@ -23,12 +23,12 @@ Package to test the openlp.core.ui.media.vlcplayer package.
"""
import os
import sys
import pytest
from datetime import timedelta
from unittest import skipIf
from unittest.mock import MagicMock, call, patch, ANY
from openlp.core.common import is_macosx
import pytest
from openlp.core.common.platform import is_macosx
from openlp.core.common.registry import Registry
from openlp.core.ui.media import ItemMediaInfo, MediaState, MediaType
from openlp.core.ui.media.vlcplayer import VlcPlayer, get_vlc
@ -46,7 +46,7 @@ def vlc_env():
MockDateTime.revert()
@skipIf(is_macosx(), 'Test doesn\'t apply to macOS')
@pytest.mark.skipif(is_macosx(), reason='Test doesn\'t apply to macOS')
@patch.dict(os.environ)
@patch('openlp.core.ui.media.vlcplayer.is_macosx')
def test_not_osx_fix_vlc_22_plugin_path(mocked_is_macosx):

View File

@ -22,16 +22,16 @@
Package to test openlp.core.ui.mainwindow package.
"""
import os
import pytest
from pathlib import Path
from unittest.mock import MagicMock, patch
from shutil import rmtree
from tempfile import mkdtemp
import pytest
from PyQt5 import QtCore, QtWidgets, QtGui
from openlp.core.common import is_macosx
from openlp.core.common.i18n import UiStrings
from openlp.core.common.platform import is_macosx
from openlp.core.common.registry import Registry
from openlp.core.display.screens import ScreenList
from openlp.core.lib.plugin import PluginStatus
@ -197,15 +197,14 @@ def test_cmd_line_arg_other_args(main_window):
mocked_load_file.assert_called_with(Path(service_file))
@patch('openlp.core.ui.mainwindow.Path')
def test_cmd_line_filename_with_spaces(MockPath, main_window):
@patch('openlp.core.ui.mainwindow.resolve')
def test_cmd_line_filename_with_spaces(mocked_resolve, main_window):
"""
Test that a service file with spaces that split across arguments loads the file properly
"""
# GIVEN a set of arguments with a file separated by spaces
mocked_path_is_file = MagicMock(**{'is_file.return_value': True, 'suffix': '.osz'})
MockPath.return_value.resolve.side_effect = [FileNotFoundError, FileNotFoundError,
FileNotFoundError, mocked_path_is_file]
mocked_resolve.side_effect = [FileNotFoundError, FileNotFoundError, FileNotFoundError, mocked_path_is_file]
args = ['Service', '2022-02-06.osz']
# WHEN the argument is processed
@ -213,19 +212,18 @@ def test_cmd_line_filename_with_spaces(MockPath, main_window):
main_window.open_cmd_line_files(args)
# THEN the file should be looked for
assert MockPath.return_value.resolve.call_count == 4
assert mocked_resolve.call_count == 4
mocked_load_file.assert_called_with(mocked_path_is_file)
@patch('openlp.core.ui.mainwindow.Path')
def test_cmd_line_filename_with_spaces_and_security(MockPath, main_window):
@patch('openlp.core.ui.mainwindow.resolve')
def test_cmd_line_filename_with_spaces_and_security(mocked_resolve, main_window):
"""
Test that passing a service file with spaces and a command line argument loads properly
"""
# GIVEN a set of arguments with a file separated by spaces
mocked_path_is_file = MagicMock(**{'is_file.return_value': True, 'suffix': '.osz'})
MockPath.return_value.resolve.side_effect = [FileNotFoundError, FileNotFoundError,
FileNotFoundError, mocked_path_is_file]
mocked_resolve.side_effect = [FileNotFoundError, FileNotFoundError, FileNotFoundError, mocked_path_is_file]
args = ['--disable-web-security', 'Service', '2022-02-06.osz']
# WHEN the argument is processed
@ -233,7 +231,7 @@ def test_cmd_line_filename_with_spaces_and_security(MockPath, main_window):
main_window.open_cmd_line_files(args)
# THEN the file should be looked for
assert MockPath.return_value.resolve.call_count == 4
assert mocked_resolve.call_count == 4
mocked_load_file.assert_called_with(mocked_path_is_file)

View File

@ -21,15 +21,16 @@
"""
Package to test the :mod:`~openlp.core.ui.style` module.
"""
from unittest import skipIf
from unittest.mock import MagicMock, patch, call
import pytest
from openlp.core.ui.style import MEDIA_MANAGER_STYLE, UiThemes, WIN_REPAIR_STYLESHEET, get_application_stylesheet, \
get_library_stylesheet, has_ui_theme, is_ui_theme_dark, set_default_theme
import openlp.core.ui.style
@skipIf(not hasattr(openlp.core.ui.style, 'qdarkstyle'), 'qdarkstyle is not installed')
@pytest.mark.skipif(not hasattr(openlp.core.ui.style, 'qdarkstyle'), reason='qdarkstyle is not installed')
@patch('openlp.core.ui.style.HAS_DARK_THEME', True)
@patch('openlp.core.ui.style.qdarkstyle')
def test_get_application_stylesheet_qdarkstyle(mocked_qdarkstyle, mock_settings):
@ -45,7 +46,7 @@ def test_get_application_stylesheet_qdarkstyle(mocked_qdarkstyle, mock_settings)
assert result == 'dark_style'
@skipIf(not hasattr(openlp.core.ui.style, 'qdarkstyle'), 'qdarkstyle is not installed')
@pytest.mark.skipif(not hasattr(openlp.core.ui.style, 'qdarkstyle'), reason='qdarkstyle is not installed')
@patch('openlp.core.ui.style.HAS_DARK_THEME', True)
def test_has_ui_theme_qdarkstyle_true_when_available(mock_settings):
"""Test that the QDarkStyle UI theme exists when qdarkstyle is available """
@ -179,7 +180,7 @@ def test_get_library_stylesheet_defaultdark_ui_theme(mock_settings):
assert result == MEDIA_MANAGER_STYLE
@skipIf(not hasattr(openlp.core.ui.style, 'qdarkstyle'), 'qdarkstyle is not installed')
@pytest.mark.skipif(not hasattr(openlp.core.ui.style, 'qdarkstyle'), reason='qdarkstyle is not installed')
@patch('openlp.core.ui.style.HAS_DARK_THEME', True)
def test_get_library_stylesheet_qdarktheme_ui_theme(mock_settings):
"""Test that the media manager stylesheet is not returned for QDarkStyle UI theme"""
@ -249,7 +250,7 @@ def test_is_ui_theme_dark_defaultdark_dark(mock_settings):
assert result is True
@skipIf(not hasattr(openlp.core.ui.style, 'qdarkstyle'), 'qdarkstyle is not installed')
@pytest.mark.skipif(not hasattr(openlp.core.ui.style, 'qdarkstyle'), reason='qdarkstyle is not installed')
@patch('openlp.core.ui.style.HAS_DARK_THEME', True)
def test_is_ui_theme_dark_qdarkstyle_dark(mock_settings):
"""Test that the QDarkStyle UI Theme is Dark"""

View File

@ -22,9 +22,11 @@
Package to test the openlp.plugin.bible.lib.https package.
"""
import os
from unittest import TestCase, skipIf
from unittest import TestCase
from unittest.mock import MagicMock
import pytest
from openlp.core.common.registry import Registry
from openlp.core.common.settings import Settings
from openlp.plugins.bibles.lib.importers.http import BGExtract, BSExtract, CWExtract
@ -32,7 +34,7 @@ from openlp.plugins.bibles.lib.importers.http import BGExtract, BSExtract, CWExt
IS_CI = 'GITLAB_CI' in os.environ or 'APPVEYOR' in os.environ
@skipIf(IS_CI, 'Skip Bible HTTP tests to prevent GitLab CI from being blacklisted')
@pytest.mark.skipif(IS_CI, reason='Skip Bible HTTP tests to prevent GitLab CI from being blacklisted')
class TestBibleHTTP(TestCase):
def setUp(self):

View File

@ -21,19 +21,26 @@
"""
Functional tests to test the LibreOffice Pyro server
"""
from unittest import SkipTest
from unittest.mock import MagicMock, patch, call
from openlp.core.common import is_macosx
import pytest
from openlp.core.common.platform import is_macosx
try:
import Pyro4 # noqa: F401
has_pyro4 = True
except ImportError:
raise SkipTest('Pyro4 is not installed, skipping testing the LibreOffice server')
if not is_macosx():
raise SkipTest('Not on macOS, skipping testing the LibreOffice server')
has_pyro4 = False
from openlp.plugins.presentations.lib.libreofficeserver import LibreOfficeServer, TextType, main
if has_pyro4:
from openlp.plugins.presentations.lib.libreofficeserver import LibreOfficeServer, TextType, main
pytestmark = [
pytest.mark.skipif(not has_pyro4, reason='Pyro4 is not installed, skipping testing the LibreOffice server'),
pytest.mark.skipif(not is_macosx(), reason='Not on macOS, skipping testing the LibreOffice server')
]
def test_constructor():

View File

@ -23,11 +23,13 @@ Functional tests to test the Mac LibreOffice class and related methods.
"""
import shutil
from tempfile import mkdtemp
from unittest import TestCase, skipIf, SkipTest
from unittest import TestCase
from unittest.mock import MagicMock, patch, call
from openlp.core.common import is_macosx
import pytest
from openlp.core.common.path import Path
from openlp.core.common.platform import is_macosx
from openlp.core.common.registry import Registry
from openlp.core.common.settings import Settings
from openlp.plugins.presentations.lib.maclocontroller import MacLOController, MacLODocument
@ -37,13 +39,17 @@ from tests.utils.constants import TEST_RESOURCES_PATH
try:
import Pyro4 # noqa: F401
has_pyro4 = True
except ImportError:
raise SkipTest('Pyro4 is not installed, skipping testing the Mac LibreOffice controller')
if not is_macosx():
raise SkipTest('Not on macOS, skipping testing the Mac LibreOffice controller')
has_pyro4 = False
pytestmark = [
pytest.mark.skipif(not has_pyro4, reason='Pyro4 is not installed, skipping testing the Mac LibreOffice controller'),
pytest.mark.skipif(not is_macosx(), reason='Not on macOS, skipping testing the Mac LibreOffice controller')
]
@skipIf(is_macosx(), 'Skip on macOS until we can figure out what the problem is or the tests are refactored')
@pytest.mark.skipif(is_macosx(), reason='Skip on macOS until we can figure out what the problem is')
class TestMacLOController(TestCase, TestMixin):
"""
Test the MacLOController Class

View File

@ -24,7 +24,7 @@ Functional tests to test the PowerPointController class and related methods.
import pytest
from unittest.mock import MagicMock, patch
from openlp.core.common import is_win
from openlp.core.common.platform import is_win
from openlp.core.common.registry import Registry
from openlp.plugins.presentations.lib.powerpointcontroller import PowerpointController, PowerpointDocument, \
_get_text_from_shapes

View File

@ -21,9 +21,11 @@
"""
This module contains tests for the OpenOffice/LibreOffice importer.
"""
from unittest import TestCase, skipIf
from unittest import TestCase
from unittest.mock import MagicMock, patch
import pytest
from openlp.core.common.registry import Registry
from tests.helpers.testmixin import TestMixin
@ -34,7 +36,8 @@ except ImportError:
OpenOfficeImport = None
@skipIf(OpenOfficeImport is None, 'Could not import OpenOfficeImport probably due to unavailability of uno')
@pytest.mark.skipif(OpenOfficeImport is None,
reason='Could not import OpenOfficeImport probably due to unavailability of uno')
class TestOpenOfficeImport(TestCase, TestMixin):
"""
Test the :class:`~openlp.plugins.songs.lib.importer.openoffice.OpenOfficeImport` class

View File

@ -21,9 +21,9 @@
"""
This module contains tests for the PresentationManager song importer.
"""
from unittest import skipIf
import pytest
from openlp.core.common import is_macosx
from openlp.core.common.platform import is_macosx
from tests.helpers.songfileimport import SongImportTestHelper
from tests.utils.constants import RESOURCE_PATH
@ -31,7 +31,7 @@ from tests.utils.constants import RESOURCE_PATH
TEST_PATH = RESOURCE_PATH / 'songs' / 'presentationmanager'
@skipIf(is_macosx(), 'This test fails for an undetermined reason on macOS')
@pytest.mark.skipif(is_macosx(), reason='This test fails for an undetermined reason on macOS')
def test_presenter_manager(mock_settings):
test_file_import = SongImportTestHelper('PresentationManagerImport', 'presentationmanager')