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
48 changes: 44 additions & 4 deletions tests/mocked_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,14 @@ class MockedEntryPoint:
class MockedPluginA(PluginType):
namespace = "test_namespace" # pyright: ignore[reportAssignmentType,reportIncompatibleMethodOverride]

is_build_plugin = True

@staticmethod
def get_all_configs() -> list[VariantFeatureConfigType]:
return [
VariantFeatureConfig(
"name1", ["val1a", "val1b", "val1c", "val1d"], multi_value=False
),
VariantFeatureConfig(
"name2", ["val2a", "val2b", "val2c"], multi_value=False
"name2", ["val2a", "val2b", "val2c"], multi_value=True
),
]

Expand All @@ -36,7 +34,7 @@ def get_supported_configs() -> list[VariantFeatureConfigType]:
return [
VariantFeatureConfig("name1", ["val1a", "val1b"], multi_value=False),
VariantFeatureConfig(
"name2", ["val2a", "val2b", "val2c"], multi_value=False
"name2", ["val2a", "val2b", "val2c"], multi_value=True
),
]

Expand Down Expand Up @@ -90,6 +88,48 @@ def get_supported_configs() -> list[VariantFeatureConfigType]:
return []


class MockedAoTPlugin(PluginType):
namespace = "aot_plugin"

is_build_plugin = True

@staticmethod
def get_all_configs() -> list[VariantFeatureConfigType]:
return [
VariantFeatureConfig("name1", ["val1a", "val1b"], multi_value=False),
VariantFeatureConfig(
"name2", ["val2a", "val2b", "val2c"], multi_value=False
),
]

@staticmethod
def get_supported_configs() -> list[VariantFeatureConfigType]:
return [
VariantFeatureConfig("name1", ["val1a", "val1b"], multi_value=False),
VariantFeatureConfig(
"name2", ["val2a", "val2b", "val2c"], multi_value=False
),
]


class MultiValueAoTPlugin(PluginType):
namespace = "aot_plugin"

is_build_plugin = True

@staticmethod
def get_all_configs() -> list[VariantFeatureConfigType]:
return [
VariantFeatureConfig("name1", ["val1a"], multi_value=True),
]

@staticmethod
def get_supported_configs() -> list[VariantFeatureConfigType]:
return [
VariantFeatureConfig("name1", ["val1a"], multi_value=True),
]


class IndirectPath:
class MoreIndirection:
object_a = MockedPluginA()
Expand Down
10 changes: 5 additions & 5 deletions tests/plugins/test_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def test_get_all_configs(
"name1", ["val1a", "val1b", "val1c", "val1d"], multi_value=False
),
VariantFeatureConfig(
"name2", ["val2a", "val2b", "val2c"], multi_value=False
"name2", ["val2a", "val2b", "val2c"], multi_value=True
),
],
),
Expand All @@ -150,7 +150,7 @@ def test_get_supported_configs(
configs=[
VariantFeatureConfig("name1", ["val1a", "val1b"], multi_value=False),
VariantFeatureConfig(
"name2", ["val2a", "val2b", "val2c"], multi_value=False
"name2", ["val2a", "val2b", "val2c"], multi_value=True
),
],
),
Expand Down Expand Up @@ -626,7 +626,7 @@ def test_package_defined_properties(include_build_plugins: bool) -> None:
"val2b",
"val2c",
],
multi_value=False,
multi_value=True,
),
],
),
Expand All @@ -639,7 +639,7 @@ def test_package_defined_properties(include_build_plugins: bool) -> None:
"v3",
"v4",
],
multi_value=True,
multi_value=False,
),
],
),
Expand All @@ -652,7 +652,7 @@ def test_package_defined_properties(include_build_plugins: bool) -> None:
"v5",
"v6",
],
multi_value=True,
multi_value=False,
),
],
),
Expand Down
69 changes: 48 additions & 21 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,8 +336,6 @@ def test_validate_variant(optional: bool) -> None:
VariantProperty("incompatible_namespace", "flag5", "on"): False,
VariantProperty("missing_namespace", "name", "val"): None,
VariantProperty("private", "build_type", "debug"): True,
VariantProperty("private", "build_type", "minsizerel"): False,
VariantProperty("private", "build_type", "release"): True,
VariantProperty("private", "cow", "moo"): False,
}

Expand Down Expand Up @@ -691,14 +689,14 @@ def test_make_variant_dist_info_expand_build_plugin_properties(
) -> None:
vdesc = VariantDescription(
[
VariantProperty("test_namespace", "name1", "val1a"),
VariantProperty("aot_plugin", "name1", "val1a"),
]
)
plugin_api = "tests.mocked_plugins:MockedPluginA"
plugin_api = "tests.mocked_plugins:MockedAoTPlugin"
vinfo = VariantInfo(
namespace_priorities=["test_namespace"],
namespace_priorities=["aot_plugin"],
providers={
"test_namespace": ProviderInfo(
"aot_plugin": ProviderInfo(
requires=["variantlib"],
plugin_api=plugin_api,
optional=True,
Expand All @@ -710,37 +708,37 @@ def test_make_variant_dist_info_expand_build_plugin_properties(
expected: VariantsJsonDict = {
VARIANTS_JSON_SCHEMA_KEY: VARIANTS_JSON_SCHEMA_URL,
VARIANT_INFO_DEFAULT_PRIO_KEY: {
VARIANT_INFO_NAMESPACE_KEY: ["test_namespace"],
VARIANT_INFO_NAMESPACE_KEY: ["aot_plugin"],
},
VARIANT_INFO_PROVIDER_DATA_KEY: {
"test_namespace": {
"aot_plugin": {
VARIANT_INFO_PROVIDER_REQUIRES_KEY: ["variantlib"],
VARIANT_INFO_PROVIDER_OPTIONAL_KEY: True,
VARIANT_INFO_PROVIDER_PLUGIN_API_KEY: plugin_api,
},
},
VARIANTS_JSON_VARIANT_DATA_KEY: {
"test": {
"test_namespace": {
"aot_plugin": {
"name1": ["val1a"],
}
},
},
}

if plugin_use == PluginUse.NONE:
expected[VARIANT_INFO_PROVIDER_DATA_KEY]["test_namespace"][
expected[VARIANT_INFO_PROVIDER_DATA_KEY]["aot_plugin"][
VARIANT_INFO_PROVIDER_PLUGIN_USE_KEY
] = "none"
if plugin_use == PluginUse.BUILD:
expected[VARIANT_INFO_PROVIDER_DATA_KEY]["test_namespace"][
expected[VARIANT_INFO_PROVIDER_DATA_KEY]["aot_plugin"][
VARIANT_INFO_PROVIDER_PLUGIN_USE_KEY
] = "build"
expected[VARIANT_INFO_DEFAULT_PRIO_KEY][VARIANT_INFO_FEATURE_KEY] = {
"test_namespace": ["name1", "name2"],
"aot_plugin": ["name1", "name2"],
}
expected[VARIANT_INFO_DEFAULT_PRIO_KEY][VARIANT_INFO_PROPERTY_KEY] = {
"test_namespace": {
"aot_plugin": {
"name1": ["val1a", "val1b"],
"name2": ["val2a", "val2b", "val2c"],
},
Expand All @@ -759,17 +757,48 @@ def test_make_variant_dist_info_expand_build_plugin_properties(
)


def test_make_variant_dist_info_invalid_build_plugin() -> None:
def test_make_variant_dist_info_invalid_aot_plugin_property() -> None:
vdesc = VariantDescription(
[
VariantProperty("test_namespace", "name1", "val1d"),
VariantProperty("aot_plugin", "name1", "val1d"),
]
)
plugin_api = "tests.mocked_plugins:MockedPluginA"
plugin_api = "tests.mocked_plugins:MockedAoTPlugin"
vinfo = VariantInfo(
namespace_priorities=["test_namespace"],
namespace_priorities=["aot_plugin"],
providers={
"test_namespace": ProviderInfo(
"aot_plugin": ProviderInfo(
requires=["variantlib"],
plugin_api=plugin_api,
optional=True,
plugin_use=PluginUse.BUILD,
)
},
)

with pytest.raises(
ValidationError,
match=r"Property 'aot_plugin :: name1 :: val1d' is not installable "
r"according to the respective provider plugin",
):
make_variant_dist_info(
vdesc,
variant_info=vinfo,
expand_build_plugin_properties=True,
)


def test_make_variant_dist_info_invalid_aot_plugin_multi_value() -> None:
vdesc = VariantDescription(
[
VariantProperty("aot_plugin", "name1", "val1a"),
]
)
plugin_api = "tests.mocked_plugins:MultiValueAoTPlugin"
vinfo = VariantInfo(
namespace_priorities=["aot_plugin"],
providers={
"aot_plugin": ProviderInfo(
requires=["variantlib"],
plugin_api=plugin_api,
optional=True,
Expand All @@ -780,9 +809,7 @@ def test_make_variant_dist_info_invalid_build_plugin() -> None:

with pytest.raises(
ValidationError,
match=r"Property 'test_namespace :: name1 :: val1d' is not installable "
r"according to the respective provider plugin; is plugin-use == 'build' valid "
"for this plugin?",
match=r"Feature 'aot_plugin :: name1' is multi-value",
):
make_variant_dist_info(
vdesc,
Expand Down
9 changes: 7 additions & 2 deletions variantlib/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,11 @@ def make_variant_dist_info(
if config.namespace not in build_namespaces:
continue
for vfeat in config.configs:
if vfeat.multi_value:
raise ValidationError(
f"Feature '{config.namespace} :: {vfeat.name}' is "
"multi-value, which is invalid for ahead-of-time plugins"
)
feature_prios = variant_json.feature_priorities.setdefault(
config.namespace, []
)
Expand Down Expand Up @@ -261,8 +266,8 @@ def make_variant_dist_info(
):
raise ValidationError(
f"Property {vprop.to_str()!r} is not installable according to the "
"respective provider plugin; is plugin-use == 'build' valid for "
"this plugin?"
"respective provider plugin, which is invalid for ahead-of-time "
"plugins"
)

return variant_json.to_str()
Expand Down
2 changes: 1 addition & 1 deletion variantlib/plugins/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ def _get_configs(
namespace: ProviderConfig(
namespace=namespace,
configs=[
VariantFeatureConfig(name=name, values=values, multi_value=True)
VariantFeatureConfig(name=name, values=values, multi_value=False)
for name, values in features.items()
],
)
Expand Down