1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
|
# Copyright 2016-2018 Dirk Thomas
# Licensed under the Apache License, Version 2.0
import os
import sys
from unittest.mock import Mock
from unittest.mock import patch
import warnings
import pytest
with warnings.catch_warnings():
warnings.filterwarnings(
'ignore', message='.*entry_point.*deprecated.*', category=UserWarning)
try:
from colcon_core.entry_point import EXTENSION_POINT_GROUP_NAME
from colcon_core.entry_point import get_all_entry_points
from colcon_core.entry_point import get_entry_points
from colcon_core.entry_point import load_entry_point
from colcon_core.entry_point import load_entry_points
except ModuleNotFoundError:
if sys.version_info >= (3, 13):
pytest.skip(
'pkg_resources is no longer available in Python 3.13+',
allow_module_level=True)
raise
from .environment_context import EnvironmentContext
class Group1:
name = 'group1'
class Group2:
name = 'group2'
class Dist():
def __init__(self, group_name, group):
self._group_name = group_name
self._group = group
def __lt__(self, other):
return self._group_name < other._group_name
def get_entry_map(self):
return self._group
class EntryPoint:
pass
def iter_entry_points(*, group):
if group == EXTENSION_POINT_GROUP_NAME:
return [Group1, Group2]
assert group == Group1.name
ep1 = EntryPoint()
ep1.name = 'extA'
ep2 = EntryPoint()
ep2.name = 'extB'
return [ep1, ep2]
def working_set():
return [
Dist('group1', {
'group1': {ep.name: ep for ep in iter_entry_points(group='group1')}
}),
Dist('group2', {'group2': {'extC': EntryPoint()}}),
Dist('other_group', {'other_group': {'extD': EntryPoint()}}),
]
def test_all_entry_points():
with patch(
'colcon_core.entry_point.iter_entry_points',
side_effect=iter_entry_points
):
with patch(
'colcon_core.entry_point.WorkingSet',
side_effect=working_set
):
# successfully load a known entry point
assert set(get_all_entry_points().keys()) == {'group1', 'group2'}
assert set(get_all_entry_points()['group1'].keys()) == \
{'extA', 'extB'}
assert len(get_all_entry_points()['group1']['extA']) == 2
assert isinstance(
get_all_entry_points()['group1']['extA'][1], EntryPoint)
assert get_all_entry_points()['group1']['extA'][1] .group_name == \
'group1'
assert get_all_entry_points()['group1']['extA'][1] .name == 'extA'
def test_entry_point_blocklist():
# successful loading of entry point without a blocklist
with patch(
'colcon_core.entry_point.iter_entry_points',
side_effect=iter_entry_points
):
with patch(
'colcon_core.entry_point.WorkingSet',
side_effect=working_set
):
entry_points = get_entry_points('group1')
assert 'extA' in entry_points.keys()
entry_point = entry_points['extA']
assert entry_point.group_name == 'group1'
assert entry_point.name == 'extA'
entry_point.load = Mock()
assert isinstance(entry_point, EntryPoint)
load_entry_point(entry_point)
assert entry_point.load.call_count == 1
# successful loading of entry point not in blocklist
entry_point.load.reset_mock()
with EnvironmentContext(COLCON_EXTENSION_BLOCKLIST=os.pathsep.join([
'group1.extB', 'group2.extC'])
):
load_entry_point(entry_point)
assert entry_point.load.call_count == 1
# entry point in a blocked group can't be loaded
entry_point.load.reset_mock()
with EnvironmentContext(COLCON_EXTENSION_BLOCKLIST='group1'):
with pytest.raises(RuntimeError) as e:
load_entry_point(entry_point)
assert 'The entry point group name is listed in the environment ' \
'variable' in str(e.value)
assert entry_point.load.call_count == 0
# entry point listed in the blocklist can't be loaded
with EnvironmentContext(COLCON_EXTENSION_BLOCKLIST=os.pathsep.join([
'group1.extA', 'group1.extB'])
):
with pytest.raises(RuntimeError) as e:
load_entry_point(entry_point)
assert 'The entry point name is listed in the environment variable' \
in str(e.value)
assert entry_point.load.call_count == 0
# mock entry points
class EntryPointRaisingException:
group_name = 'group'
name = 'exception'
def load(self):
raise Exception('entry point raising exception')
class EntryPointRaisingRuntimeError:
group_name = 'group'
name = 'runtime_error'
def load(self):
raise RuntimeError('entry point raising runtime error')
class EntryPointSuccess:
group_name = 'group'
name = 'success'
def load(self):
pass
@patch(
'colcon_core.entry_point.get_entry_points',
return_value={
EntryPointRaisingException.name: EntryPointRaisingException(),
EntryPointRaisingRuntimeError.name: EntryPointRaisingRuntimeError(),
EntryPointSuccess.name: EntryPointSuccess(),
})
def test_load_entry_points_with_exception(_):
with patch('colcon_core.entry_point.logger.error') as error:
extensions = load_entry_points('group')
# the entry point raising an exception different than a runtime error
# results in an error message
assert error.call_count == 1
assert len(error.call_args[0]) == 1
assert "Exception loading extension 'group.exception'" \
in error.call_args[0][0]
assert 'entry point raising exception' in error.call_args[0][0]
# neither of the entry points was loaded successfully
assert extensions == {'success': None}
|