Skip to content
Merged
3 changes: 1 addition & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,7 @@ show = "variantlib.commands.config.show:show"

[project.entry-points."variantlib.actions.plugins"]
list = "variantlib.commands.plugins.list_plugins:list_plugins"
get-supported-configs = "variantlib.commands.plugins.get_supported_configs:get_supported_configs"
validate-property = "variantlib.commands.plugins.validate_property:validate_property"
get-configs = "variantlib.commands.plugins.get_configs:get_configs"

[tool.pytest.ini_options]
testpaths = ["tests/"]
Expand Down
Binary file not shown.
21 changes: 6 additions & 15 deletions tests/artifacts/test-plugin-package/test_plugin_package.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
from __future__ import annotations

from dataclasses import dataclass
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from variantlib.protocols import VariantPropertyType


@dataclass
Expand All @@ -14,23 +10,18 @@ class FeatConfig:


namespace = "installable_plugin"
dynamic = False


def validate_property(
variant_property: VariantPropertyType,
) -> bool:
assert variant_property.namespace == namespace
return (
(variant_property.feature == "feat1" and variant_property.value in ["val1a", "val1b", "val1c"])
or (variant_property.feature == "feat2" and variant_property.value in ["val2a", "val2b"])
)
def get_all_configs(
) -> list[FeatConfig]:
return [
FeatConfig("feat1", ["val1a", "val1b", "val1c"]),
FeatConfig("feat2", ["val2a", "val2b",]),
]


def get_supported_configs(
known_properties: frozenset[VariantPropertyType] | None,
) -> list[FeatConfig]:
assert known_properties is None
return [
FeatConfig("feat1", ["val1c", "val1b"]),
]
81 changes: 54 additions & 27 deletions tests/commands/test_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,76 +23,103 @@ def test_plugins_list(
)


def test_plugins_get_supported_configs(
def test_plugins_get_all_configs(
capsys: pytest.CaptureFixture[str],
mocked_entry_points: None,
) -> None:
main(["plugins", "get-supported-configs"])
main(["plugins", "get-configs", "--all"])
assert (
capsys.readouterr().out
== """\
test_namespace :: name1 :: val1a
test_namespace :: name1 :: val1b
test_namespace :: name1 :: val1c
test_namespace :: name1 :: val1d
test_namespace :: name2 :: val2a
test_namespace :: name2 :: val2b
test_namespace :: name2 :: val2c
second_namespace :: name3 :: val3a
second_namespace :: name3 :: val3b
second_namespace :: name3 :: val3c
incompatible_namespace :: flag1 :: on
incompatible_namespace :: flag2 :: on
incompatible_namespace :: flag3 :: on
incompatible_namespace :: flag4 :: on
"""
)


def test_plugins_get_supported_configs_filter_namespace(
def test_plugins_get_all_configs_filter_namespace(
capsys: pytest.CaptureFixture[str],
mocked_entry_points: None,
) -> None:
main(["plugins", "get-supported-configs", "-n", "second_namespace"])
main(["plugins", "get-configs", "--all", "-n", "second_namespace"])
assert (
capsys.readouterr().out
== """\
second_namespace :: name3 :: val3a
second_namespace :: name3 :: val3b
second_namespace :: name3 :: val3c
"""
)


def test_plugins_get_supported_configs_filter_feature(
def test_plugins_get_all_configs_filter_feature(
capsys: pytest.CaptureFixture[str],
mocked_entry_points: None,
) -> None:
main(["plugins", "get-configs", "--all", "-f", "name1"])
assert (
capsys.readouterr().out
== """\
test_namespace :: name1 :: val1a
test_namespace :: name1 :: val1b
test_namespace :: name1 :: val1c
test_namespace :: name1 :: val1d
"""
)


def test_plugins_get_supported_configs(
capsys: pytest.CaptureFixture[str],
mocked_entry_points: None,
) -> None:
main(["plugins", "get-supported-configs", "-f", "name1"])
main(["plugins", "get-configs", "--supported"])
assert (
capsys.readouterr().out
== """\
test_namespace :: name1 :: val1a
test_namespace :: name1 :: val1b
test_namespace :: name2 :: val2a
test_namespace :: name2 :: val2b
test_namespace :: name2 :: val2c
second_namespace :: name3 :: val3a
"""
)


def test_plugins_validate_property(
capsys: pytest.CaptureFixture[str], mocked_entry_points: None
def test_plugins_get_supported_configs_filter_namespace(
capsys: pytest.CaptureFixture[str],
mocked_entry_points: None,
) -> None:
main(
[
"plugins",
"validate-property",
"test_namespace :: name1 :: val1a",
"test_namespace :: name1::val1b",
"test_namespace :: name2 :: val2a",
"second_namespace:: name1:: val1a",
"second_namespace::name3 :: val3a",
"test_namespace :: name3 :: val3a",
"unknown_namespace::foo::bar",
]
main(["plugins", "get-configs", "--supported", "-n", "second_namespace"])
assert (
capsys.readouterr().out
== """\
second_namespace :: name3 :: val3a
"""
)


def test_plugins_get_supported_configs_filter_feature(
capsys: pytest.CaptureFixture[str],
mocked_entry_points: None,
) -> None:
main(["plugins", "get-configs", "--supported", "-f", "name1"])
assert (
capsys.readouterr().out
== """\
test_namespace :: name1 :: val1a : valid
test_namespace :: name1 :: val1b : valid
test_namespace :: name2 :: val2a : valid
second_namespace :: name1 :: val1a : invalid
second_namespace :: name3 :: val3a : valid
test_namespace :: name3 :: val3a : invalid
unknown_namespace :: foo :: bar : no-plugin
test_namespace :: name1 :: val1a
test_namespace :: name1 :: val1b
"""
)
24 changes: 10 additions & 14 deletions tests/mocked_plugin_as_module.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,24 @@
from __future__ import annotations

from dataclasses import dataclass
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from variantlib.protocols import VariantFeatureConfigType
from variantlib.protocols import VariantPropertyType


@dataclass
class VariantFeatureConfig:
name: str
values: list[str]


namespace = "module_namespace"
dynamic = False


def validate_property(
variant_property: VariantPropertyType,
) -> bool:
assert variant_property.namespace == namespace
return variant_property.feature == "feature" and variant_property.value in [
"a",
"b",
]
def get_all_configs() -> list[VariantFeatureConfigType]:
return [VariantFeatureConfig("feature", ["a", "b"])]


def get_supported_configs(
known_properties: frozenset[VariantPropertyType] | None,
) -> list[VariantFeatureConfigType]:
assert known_properties is None
def get_supported_configs() -> list[VariantFeatureConfigType]:
return []
72 changes: 24 additions & 48 deletions tests/mocked_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from variantlib.models.provider import VariantFeatureConfig
from variantlib.protocols import PluginType
from variantlib.protocols import VariantFeatureConfigType
from variantlib.protocols import VariantPropertyType


@dataclass
Expand All @@ -18,22 +17,14 @@ class MockedEntryPoint:

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

def validate_property(self, variant_property: VariantPropertyType) -> bool:
assert variant_property.namespace == self.namespace
return (
variant_property.feature == "name1"
and variant_property.value in ["val1a", "val1b", "val1c", "val1d"]
) or (
variant_property.feature == "name2"
and variant_property.value in ["val2a", "val2b", "val2c"]
)

def get_supported_configs(
self, known_properties: frozenset[VariantPropertyType] | None
) -> list[VariantFeatureConfigType]:
assert known_properties is None

def get_all_configs(self) -> list[VariantFeatureConfigType]:
return [
VariantFeatureConfig("name1", ["val1a", "val1b", "val1c", "val1d"]),
VariantFeatureConfig("name2", ["val2a", "val2b", "val2c"]),
]

def get_supported_configs(self) -> list[VariantFeatureConfigType]:
return [
VariantFeatureConfig("name1", ["val1a", "val1b"]),
VariantFeatureConfig("name2", ["val2a", "val2b", "val2c"]),
Expand All @@ -47,25 +38,15 @@ def get_supported_configs(
# to test that we don't rely on that inheritance
class MockedPluginB:
namespace = "second_namespace"
dynamic = True

def validate_property(self, variant_property: VariantPropertyType) -> bool:
assert variant_property.namespace == self.namespace
return variant_property.feature == "name3"

def get_supported_configs(
self, known_properties: frozenset[VariantPropertyType] | None
) -> list[MyVariantFeatureConfig]:
assert known_properties is not None
assert all(prop.namespace == self.namespace for prop in known_properties)
vals3 = ["val3a"]
vals3.extend(
x.value
for x in known_properties
if x.feature == "name3" and x.value not in vals3
)

def get_all_configs(self) -> list[MyVariantFeatureConfig]:
return [
MyVariantFeatureConfig("name3", vals3),
MyVariantFeatureConfig("name3", ["val3a", "val3b", "val3c"]),
]

def get_supported_configs(self) -> list[MyVariantFeatureConfig]:
return [
MyVariantFeatureConfig("name3", ["val3a"]),
]


Expand All @@ -80,19 +61,14 @@ def __init__(self, name: str) -> None:

class MockedPluginC(PluginType):
namespace = "incompatible_namespace"
dynamic = False

def validate_property(self, variant_property: VariantPropertyType) -> bool:
assert variant_property.namespace == self.namespace
return (
variant_property.feature in ("flag1", "flag2", "flag3", "flag4")
and variant_property.value == "on"
)

def get_supported_configs(
self, known_properties: frozenset[VariantPropertyType] | None
) -> list[VariantFeatureConfigType]:
assert known_properties is None

def get_all_configs(self) -> list[VariantFeatureConfigType]:
return [
MyVariantFeatureConfig(x, ["on"])
for x in ("flag1", "flag2", "flag3", "flag4")
]

def get_supported_configs(self) -> list[VariantFeatureConfigType]:
return []


Expand Down
Loading
Loading