Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions tests/artifacts/test-plugin-package/test_plugin_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ class FeatConfig:
multi_value: bool = False


namespace = "installable_plugin"


def get_all_configs(
) -> list[FeatConfig]:
return [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
"requires": [
"provider-fictional-hw == 1.0.0"
],
"enable-if": "python_version >= '3.12'",
"plugin-api": "provider_fictional_hw.plugin:FictionalHWPlugin"
},
"fictional_tech": {
Expand Down
5 changes: 0 additions & 5 deletions tests/commands/test_update_pyproject_toml.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from variantlib.constants import VARIANT_INFO_DEFAULT_PRIO_KEY
from variantlib.constants import VARIANT_INFO_NAMESPACE_KEY
from variantlib.constants import VARIANT_INFO_PROVIDER_DATA_KEY
from variantlib.constants import VARIANT_INFO_PROVIDER_ENABLE_IF_KEY
from variantlib.constants import VARIANT_INFO_PROVIDER_PLUGIN_API_KEY
from variantlib.constants import VARIANT_INFO_PROVIDER_REQUIRES_KEY

Expand All @@ -34,7 +33,6 @@ def test_update_pyproject_toml(
VARIANT_INFO_PROVIDER_DATA_KEY: {
"test_namespace": {
VARIANT_INFO_PROVIDER_REQUIRES_KEY: ["frobnicate", "barnicate"],
VARIANT_INFO_PROVIDER_ENABLE_IF_KEY: "python_version >= '3.11'",
VARIANT_INFO_PROVIDER_PLUGIN_API_KEY: "wrong_value",
},
"foo": {
Expand Down Expand Up @@ -77,9 +75,6 @@ def test_update_pyproject_toml(
"test_namespace",
]
)
del toml_data[PYPROJECT_TOML_TOP_KEY][VARIANT_INFO_PROVIDER_DATA_KEY][
"test_namespace"
][VARIANT_INFO_PROVIDER_ENABLE_IF_KEY]
toml_data[PYPROJECT_TOML_TOP_KEY][VARIANT_INFO_PROVIDER_DATA_KEY]["test_namespace"][
VARIANT_INFO_PROVIDER_REQUIRES_KEY
].clear()
Expand Down
22 changes: 12 additions & 10 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from pytest_mock import MockerFixture
from variantlib.plugins.loader import VARIANT_PROVIDER_CACHE_TABLE
from variantlib.plugins.loader import BasePluginLoader
from variantlib.plugins.loader import ListPluginLoader
from variantlib.plugins.loader import DictPluginLoader

from tests.mocked_plugins import MockedEntryPoint

Expand All @@ -24,16 +24,16 @@
)


MOCKED_PLUGIN_APIS = [
"tests.mocked_plugins:MockedPluginA",
"tests.mocked_plugins:MockedPluginB",
"tests.mocked_plugins:MockedPluginC",
]
MOCKED_PLUGIN_APIS = {
"test_namespace": "tests.mocked_plugins:MockedPluginA",
"second_namespace": "tests.mocked_plugins:MockedPluginB",
"incompatible_namespace": "tests.mocked_plugins:MockedPluginC",
}


@pytest.fixture(scope="session")
def mocked_plugin_loader() -> Generator[BasePluginLoader]:
with ListPluginLoader(MOCKED_PLUGIN_APIS) as loader:
with DictPluginLoader(MOCKED_PLUGIN_APIS) as loader:
yield loader


Expand All @@ -42,9 +42,11 @@ def mocked_entry_points(
mocker: MockerFixture,
) -> None:
mocker.patch("variantlib.plugins.loader.entry_points")().select.return_value = [
MockedEntryPoint("test", "tests.mocked_plugins:MockedPluginA"),
MockedEntryPoint("second", "tests.mocked_plugins:MockedPluginB"),
MockedEntryPoint("third", "tests.mocked_plugins:MockedPluginC"),
MockedEntryPoint("test_namespace", "tests.mocked_plugins:MockedPluginA"),
MockedEntryPoint("second_namespace", "tests.mocked_plugins:MockedPluginB"),
MockedEntryPoint(
"incompatible_namespace", "tests.mocked_plugins:MockedPluginC"
),
]


Expand Down
3 changes: 1 addition & 2 deletions tests/mocked_plugin_as_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ class VariantFeatureConfig:
multi_value: bool = False


namespace = "module_namespace"
is_aot_plugin = False
all_properties_compatible = False


def get_all_configs() -> list[VariantFeatureConfigType]:
Expand Down
14 changes: 2 additions & 12 deletions tests/mocked_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ class MockedEntryPoint:


class MockedPluginA(PluginType):
namespace = "test_namespace" # pyright: ignore[reportAssignmentType,reportIncompatibleMethodOverride]

@staticmethod
def get_all_configs() -> list[VariantFeatureConfigType]:
return [
Expand Down Expand Up @@ -47,8 +45,6 @@ def get_supported_configs() -> list[VariantFeatureConfigType]:
# NB: this plugin deliberately does not inherit from PluginType
# to test that we don't rely on that inheritance
class MockedPluginB:
namespace = "second_namespace"

@classmethod
def get_all_configs(cls) -> list[MyVariantFeatureConfig]:
return [
Expand All @@ -74,8 +70,6 @@ def __init__(self, name: str) -> None:


class MockedPluginC(PluginType):
namespace = "incompatible_namespace"

@classmethod
def get_all_configs(cls) -> list[VariantFeatureConfigType]:
return [
Expand All @@ -89,9 +83,7 @@ def get_supported_configs() -> list[VariantFeatureConfigType]:


class MockedAoTPlugin(PluginType):
namespace = "aot_plugin"

is_aot_plugin = True
all_properties_compatible = True

@staticmethod
def get_all_configs() -> list[VariantFeatureConfigType]:
Expand All @@ -113,9 +105,7 @@ def get_supported_configs() -> list[VariantFeatureConfigType]:


class MultiValueAoTPlugin(PluginType):
namespace = "aot_plugin"

is_aot_plugin = True
all_properties_compatible = True

@staticmethod
def get_all_configs() -> list[VariantFeatureConfigType]:
Expand Down
84 changes: 25 additions & 59 deletions tests/plugins/test_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
from variantlib.models.variant_info import ProviderInfo
from variantlib.models.variant_info import VariantInfo
from variantlib.plugins.loader import BasePluginLoader
from variantlib.plugins.loader import DictPluginLoader
from variantlib.plugins.loader import EntryPointPluginLoader
from variantlib.plugins.loader import ListPluginLoader
from variantlib.plugins.loader import PluginLoader
from variantlib.protocols import PluginType
from variantlib.protocols import VariantFeatureConfigType
Expand All @@ -46,8 +46,6 @@


class ClashingPlugin(PluginType):
namespace = "test_namespace" # pyright: ignore[reportAssignmentType,reportIncompatibleMethodOverride]

@classmethod
def get_all_configs(cls) -> list[VariantFeatureConfigType]:
return [
Expand All @@ -62,8 +60,6 @@ def get_supported_configs(cls) -> list[VariantFeatureConfigType]:


class ExceptionPluginBase(PluginType):
namespace = "exception_test" # pyright: ignore[reportAssignmentType,reportIncompatibleMethodOverride]

returned_value: list[VariantFeatureConfigType]

@classmethod
Expand Down Expand Up @@ -156,25 +152,6 @@ def test_get_supported_configs(
}


def test_namespace_clash() -> None:
with (
pytest.raises(
RuntimeError,
match=(
r"Two plugins found using the same namespace test_namespace. "
r"Refusing to proceed."
),
),
ListPluginLoader(
[
"tests.mocked_plugins:MockedPluginA",
"tests.plugins.test_loader:ClashingPlugin",
]
),
):
pass


class IncorrectListTypePlugin(ExceptionPluginBase):
returned_value = (
VariantFeatureConfig("k1", ["v1"], multi_value=False),
Expand All @@ -185,14 +162,14 @@ class IncorrectListTypePlugin(ExceptionPluginBase):
@pytest.mark.parametrize("method", GET_CONFIG_METHODS)
def test_get_supported_configs_incorrect_list_type(method: str) -> None:
with (
ListPluginLoader(
["tests.plugins.test_loader:IncorrectListTypePlugin"]
DictPluginLoader(
{"test": "tests.plugins.test_loader:IncorrectListTypePlugin"}
) as loader,
pytest.raises(
PluginError,
match=r".*"
+ re.escape(
f"Provider exception_test, {method}() method returned "
f"IncorrectListTypePlugin, {method}() method returned "
"incorrect type. Expected "
"list[_variantlib_protocols.VariantFeatureConfigType], "
"got <class 'tuple'>"
Expand All @@ -208,8 +185,8 @@ class IncorrectListLengthPlugin(ExceptionPluginBase):

def test_get_configs_empty_list() -> None:
with (
ListPluginLoader(
["tests.plugins.test_loader:IncorrectListLengthPlugin"]
DictPluginLoader(
{"exception_test": "tests.plugins.test_loader:IncorrectListLengthPlugin"}
) as loader,
pytest.raises(
PluginError,
Expand All @@ -229,14 +206,14 @@ class IncorrectListMemberTypePlugin(ExceptionPluginBase):
@pytest.mark.parametrize("method", GET_CONFIG_METHODS)
def test_get_configs_incorrect_list_member_type(method: str) -> None:
with (
ListPluginLoader(
["tests.plugins.test_loader:IncorrectListMemberTypePlugin"]
DictPluginLoader(
{"test": "tests.plugins.test_loader:IncorrectListMemberTypePlugin"}
) as loader,
pytest.raises(
PluginError,
match=r".*"
+ re.escape(
f"Provider exception_test, {method}() method returned "
f"IncorrectListMemberTypePlugin, {method}() method returned "
"incorrect type. Expected "
"list[_variantlib_protocols.VariantFeatureConfigType], "
"got list[typing.Union[_variantlib_protocols.VariantFeatureConfigType, "
Expand All @@ -256,7 +233,7 @@ def test_namespace_missing_module() -> None:
r"No module named 'tests.no_such_module'"
),
),
ListPluginLoader(["tests.no_such_module:foo"]),
DictPluginLoader({"test": "tests.no_such_module:foo"}),
):
pass

Expand All @@ -271,14 +248,12 @@ def test_namespace_incorrect_name() -> None:
"'no_such_name'"
),
),
ListPluginLoader([("tests.plugins.test_loader:no_such_name")]),
DictPluginLoader({"test": "tests.plugins.test_loader:no_such_name"}),
):
pass


class IncompletePlugin:
namespace = "incomplete_plugin"

@classmethod
def get_supported_configs(cls) -> list[VariantFeatureConfigType]:
return []
Expand All @@ -290,9 +265,9 @@ def test_namespace_incorrect_type() -> None:
PluginError,
match=r"'tests.plugins.test_loader:RANDOM_STUFF' does not meet "
r"the PluginType prototype: 123 \(missing attributes: "
r"get_all_configs, get_supported_configs, namespace\)",
r"get_all_configs, get_supported_configs\)",
),
ListPluginLoader(["tests.plugins.test_loader:RANDOM_STUFF"]),
DictPluginLoader({"test": "tests.plugins.test_loader:RANDOM_STUFF"}),
):
pass

Expand All @@ -310,7 +285,7 @@ def test_namespace_instantiation_returns_incorrect_type(
"(missing attributes: get_all_configs)"
),
),
ListPluginLoader([f"tests.plugins.test_loader:{cls}"]),
DictPluginLoader({"test": f"tests.plugins.test_loader:{cls}"}),
):
pass

Expand All @@ -326,28 +301,27 @@ def test_namespaces(


def test_non_callable_plugin() -> None:
with ListPluginLoader(
[
"tests.mocked_plugins:IndirectPath.MoreIndirection.object_a",
"tests.mocked_plugins:OBJECT_B",
]
) as loader:
plugins = {
"test_namespace": "tests.mocked_plugins:IndirectPath.MoreIndirection.object_a",
"second_namespace": "tests.mocked_plugins:OBJECT_B",
}
with DictPluginLoader(plugins) as loader:
assert loader.namespaces == ["test_namespace", "second_namespace"]


def test_plugin_module() -> None:
with ListPluginLoader(
[
"tests.mocked_plugin_as_module",
]
with DictPluginLoader(
{
"module_namespace": "tests.mocked_plugin_as_module",
}
) as loader:
assert loader.namespaces == ["module_namespace"]


def test_load_plugin_invalid_arg() -> None:
with (
pytest.raises(ValidationError),
ListPluginLoader(["tests.mocked_plugins:foo:bar"]),
DictPluginLoader({"test": "tests.mocked_plugins:foo:bar"}),
):
pass

Expand All @@ -368,17 +342,9 @@ def test_load_plugin_invalid_arg() -> None:
plugin_api="tests.mocked_plugins:MockedPluginA",
),
"second_namespace": ProviderInfo(
# always true
enable_if="python_version >= '3.10'",
requires=["variantlib"],
plugin_api="tests.mocked_plugins:MockedPluginB",
),
"incompatible_namespace": ProviderInfo(
# always false (hopefully)
enable_if='platform_machine == "frobnicator"',
requires=["variantlib"],
plugin_api="tests.mocked_plugins:MockedPluginC",
),
"one_more": ProviderInfo(
requires=["variantlib"],
plugin_api="tests.mocked_plugins:NoSuchClass",
Expand Down Expand Up @@ -515,7 +481,7 @@ def test_optional_plugins(value: bool | list[VariantNamespace], expected: bool)
"loader_call",
[
partial(PluginLoader, VariantInfo(), include_aot_plugins=True),
partial(ListPluginLoader, []),
partial(DictPluginLoader, {}),
],
)
def test_empty_plugin_list(loader_call: Callable[[], BasePluginLoader]) -> None:
Expand Down
Loading
Loading