mirror of https://gitlab.com/openlp/openlp.git
Merge branch 'imports_2' into 'master'
Working version of Community Imports See merge request openlp/openlp!703
This commit is contained in:
commit
3778448e76
|
@ -28,7 +28,9 @@ import logging
|
|||
import re
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
from ipaddress import IPv4Address, IPv6Address, AddressValueError
|
||||
from pathlib import Path
|
||||
from shutil import which
|
||||
|
||||
from PyQt5 import QtGui
|
||||
|
@ -100,15 +102,19 @@ def trace_error_handler(logger):
|
|||
logger.error(log_string)
|
||||
|
||||
|
||||
def path_to_module(path):
|
||||
def path_to_module(path: Path, community: bool = None) -> str:
|
||||
"""
|
||||
Convert a path to a module name (i.e openlp.core.common)
|
||||
|
||||
:param pathlib.Path path: The path to convert to a module name.
|
||||
:param bool False community: Are we in Community Mode?
|
||||
:return: The module name.
|
||||
:rtype: str
|
||||
"""
|
||||
module_path = path.with_suffix('')
|
||||
if community:
|
||||
return 'contrib.' + '.'.join(module_path.parts)
|
||||
else:
|
||||
return 'openlp.' + '.'.join(module_path.parts)
|
||||
|
||||
|
||||
|
@ -119,7 +125,7 @@ def import_openlp_module(module_name):
|
|||
importlib.import_module(module_name)
|
||||
|
||||
|
||||
def extension_loader(glob_pattern, excluded_files=None):
|
||||
def extension_loader(glob_pattern: str, excluded_files: list = None, community: bool = False) -> None:
|
||||
"""
|
||||
A utility function to find and load OpenLP extensions, such as plugins, presentation and media controllers and
|
||||
importers.
|
||||
|
@ -127,16 +133,22 @@ def extension_loader(glob_pattern, excluded_files=None):
|
|||
:param str glob_pattern: A glob pattern used to find the extension(s) to be imported. Should be relative to the
|
||||
application directory. i.e. plugins/*/*plugin.py
|
||||
:param list[str] | None excluded_files: A list of file names to exclude that the glob pattern may find.
|
||||
:param bool | False community: are we using the community directory path
|
||||
:rtype: None
|
||||
"""
|
||||
from openlp.core.common.applocation import AppLocation
|
||||
if community:
|
||||
app_dir = AppLocation.get_directory(AppLocation.DataDir)
|
||||
sys.path.insert(0, str(app_dir))
|
||||
app_dir = app_dir / 'contrib'
|
||||
else:
|
||||
app_dir = AppLocation.get_directory(AppLocation.AppDir)
|
||||
for extension_path in app_dir.glob(glob_pattern):
|
||||
extension_path = extension_path.relative_to(app_dir)
|
||||
if extension_path.name in (excluded_files or []):
|
||||
continue
|
||||
log.debug('Attempting to import %s', extension_path)
|
||||
module_name = path_to_module(extension_path)
|
||||
module_name = path_to_module(extension_path, community)
|
||||
try:
|
||||
import_openlp_module(module_name)
|
||||
except (ImportError, OSError):
|
||||
|
|
|
@ -56,6 +56,7 @@ class PluginManager(RegistryBase, LogMixin, RegistryProperties):
|
|||
"""
|
||||
glob_pattern = os.path.join('plugins', '*', '[!.]*plugin.py')
|
||||
extension_loader(glob_pattern)
|
||||
extension_loader(glob_pattern, community=True)
|
||||
plugin_classes = Plugin.__subclasses__()
|
||||
for p in plugin_classes:
|
||||
try:
|
||||
|
|
|
@ -22,12 +22,13 @@
|
|||
Functional tests to test the :mod:`~openlp.core.common` module
|
||||
"""
|
||||
import os
|
||||
import pytest
|
||||
import sys
|
||||
|
||||
from io import BytesIO
|
||||
from pathlib import Path
|
||||
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, md5_hash, \
|
||||
normalize_str, path_to_module, qmd5_hash, sha256_file_hash, trace_error_handler, verify_ip_address
|
||||
|
@ -86,6 +87,31 @@ def test_extension_loader_files_found():
|
|||
# files listed in the `excluded_files` argument
|
||||
mocked_import_module.assert_has_calls([call('openlp.import_dir.file1'),
|
||||
call('openlp.import_dir.file4')])
|
||||
assert "/app/dir/community" not in sys.path, "Community path has been added to the application sys.path"
|
||||
|
||||
|
||||
def test_extension_loader_files_found_community():
|
||||
"""
|
||||
Test the `extension_loader` function when it successfully finds and loads some files
|
||||
"""
|
||||
# GIVEN: A mocked `Path.glob` method which returns a list of files
|
||||
with patch('openlp.core.common.applocation.AppLocation.get_directory',
|
||||
return_value=Path('/', 'app', 'dir')), \
|
||||
patch.object(Path, 'glob', return_value=[
|
||||
Path('/', 'app', 'dir', 'contrib', 'import_dir', 'file1.py'),
|
||||
Path('/', 'app', 'dir', 'contrib', 'import_dir', 'file2.py'),
|
||||
Path('/', 'app', 'dir', 'contrib', 'import_dir', 'file3.py'),
|
||||
Path('/', 'app', 'dir', 'contrib', 'import_dir', 'file4.py')]), \
|
||||
patch('openlp.core.common.import_openlp_module') as mocked_import_module:
|
||||
|
||||
# WHEN: Calling `extension_loader` with a list of files to exclude
|
||||
extension_loader('glob', ['file2.py', 'file3.py'], True)
|
||||
|
||||
# THEN: `extension_loader` should only try to import the files that are matched by the blob, excluding the
|
||||
# files listed in the `excluded_files` argument
|
||||
mocked_import_module.assert_has_calls([call('contrib.import_dir.file1'),
|
||||
call('contrib.import_dir.file4')])
|
||||
assert "/app/dir" in sys.path, "app/dir path has not been added to the application sys.path"
|
||||
|
||||
|
||||
def test_extension_loader_import_error():
|
||||
|
@ -168,6 +194,20 @@ def test_path_to_module():
|
|||
assert result == 'openlp.core.ui.media.vlcplayer'
|
||||
|
||||
|
||||
def test_path_to_module_community():
|
||||
"""
|
||||
Test `path_to_module` when supplied with a `Path` object
|
||||
"""
|
||||
# GIVEN: A `Path` object
|
||||
path = Path('core', 'ui', 'media', 'vlcplayer.py')
|
||||
|
||||
# WHEN: Calling path_to_module with the `Path` object
|
||||
result = path_to_module(path, True)
|
||||
|
||||
# THEN: path_to_module should return the module name
|
||||
assert result == 'contrib.core.ui.media.vlcplayer'
|
||||
|
||||
|
||||
def test_trace_error_handler():
|
||||
"""
|
||||
Test the trace_error_handler() method
|
||||
|
|
Loading…
Reference in New Issue