Skip to content

Commit 5b4f2c6

Browse files
authored
Validate variant_label in make_variant_dist_info, allow dots (#109)
1 parent 3fcb8cc commit 5b4f2c6

File tree

3 files changed

+44
-2
lines changed

3 files changed

+44
-2
lines changed

tests/test_api.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
from variantlib.constants import VARIANTS_JSON_SCHEMA_URL
4646
from variantlib.constants import VARIANTS_JSON_VARIANT_DATA_KEY
4747
from variantlib.constants import VariantsJsonDict
48+
from variantlib.errors import ValidationError
4849
from variantlib.models import provider as pconfig
4950
from variantlib.models import variant as vconfig
5051
from variantlib.models.configuration import VariantConfiguration as VConfigurationModel
@@ -349,8 +350,10 @@ def test_validate_variant(mocked_plugin_apis: list[str], optional: bool) -> None
349350
@pytest.mark.parametrize(
350351
"pyproject_toml", [None, PYPROJECT_TOML, PYPROJECT_TOML_MINIMAL]
351352
)
353+
@pytest.mark.parametrize("label", [None, "foo", "xy1.2"])
352354
def test_make_variant_dist_info(
353355
pyproject_toml: VariantsJsonDict | None,
356+
label: str | None,
354357
) -> None:
355358
expected: VariantsJsonDict = {
356359
VARIANTS_JSON_SCHEMA_KEY: VARIANTS_JSON_SCHEMA_URL,
@@ -359,7 +362,7 @@ def test_make_variant_dist_info(
359362
},
360363
VARIANT_INFO_PROVIDER_DATA_KEY: {},
361364
VARIANTS_JSON_VARIANT_DATA_KEY: {
362-
"67fcaf38": {
365+
label if label else "67fcaf38": {
363366
"ns1": {
364367
"f1": ["p1"],
365368
"f2": ["p2"],
@@ -424,6 +427,7 @@ def test_make_variant_dist_info(
424427
variant_info=VariantPyProjectToml(pyproject_toml) # type: ignore[arg-type]
425428
if pyproject_toml is not None
426429
else None,
430+
variant_label=label,
427431
)
428432
)
429433
== expected
@@ -542,3 +546,28 @@ def test_get_variant_environment_dict() -> None:
542546
"ns3 :: feat2 :: val2",
543547
},
544548
}
549+
550+
551+
def test_make_variant_dist_info_invalid_label():
552+
with pytest.raises(
553+
ValidationError, match=r"Variant label cannot be specified for the null variant"
554+
):
555+
make_variant_dist_info(VariantDescription([]), variant_label="foo")
556+
with pytest.raises(
557+
ValidationError,
558+
match=rf"{NULL_VARIANT_HASH} label can be used only for the null variant",
559+
):
560+
make_variant_dist_info(
561+
VariantDescription([VariantProperty("a", "b", "c")]),
562+
variant_label=NULL_VARIANT_HASH,
563+
)
564+
with pytest.raises(ValidationError, match=r"Invalid variant label: foo/bar"):
565+
make_variant_dist_info(
566+
VariantDescription([VariantProperty("a", "b", "c")]),
567+
variant_label="foo/bar",
568+
)
569+
with pytest.raises(ValidationError, match=r"Invalid variant label: 123456789"):
570+
make_variant_dist_info(
571+
VariantDescription([VariantProperty("a", "b", "c")]),
572+
variant_label="123456789",
573+
)

variantlib/api.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99

1010
from variantlib.configuration import VariantConfiguration
1111
from variantlib.constants import NULL_VARIANT_HASH
12+
from variantlib.constants import VALIDATION_VARIANT_LABEL_REGEX
1213
from variantlib.constants import VARIANT_HASH_LEN
1314
from variantlib.constants import VariantsJsonDict
15+
from variantlib.errors import ValidationError
1416
from variantlib.models.provider import ProviderConfig
1517
from variantlib.models.provider import VariantFeatureConfig
1618
from variantlib.models.variant import VariantDescription
@@ -147,6 +149,17 @@ def make_variant_dist_info(
147149
variant_json = VariantDistInfo(variant_info)
148150
variant_json.variant_desc = vdesc
149151
if variant_label is not None:
152+
if vdesc.is_null_variant():
153+
if variant_label != NULL_VARIANT_HASH:
154+
raise ValidationError(
155+
"Variant label cannot be specified for the null variant"
156+
)
157+
elif variant_label == NULL_VARIANT_HASH:
158+
raise ValidationError(
159+
f"{NULL_VARIANT_HASH} label can be used only for the null variant"
160+
)
161+
elif not VALIDATION_VARIANT_LABEL_REGEX.fullmatch(variant_label):
162+
raise ValidationError(f"Invalid variant label: {variant_label}")
150163
variant_json.variant_label = variant_label
151164

152165
return variant_json.to_str()

variantlib/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
VARIANTS_JSON_SCHEMA_URL = "https://variants-schema.wheelnext.dev/"
2727
VARIANTS_JSON_VARIANT_DATA_KEY: Literal["variants"] = "variants"
2828

29-
VALIDATION_VARIANT_LABEL_REGEX = re.compile(r"[0-9a-z_]{1,8}")
29+
VALIDATION_VARIANT_LABEL_REGEX = re.compile(r"[0-9a-z._]{1,8}")
3030

3131
VALIDATION_NAMESPACE_REGEX = re.compile(r"[a-z0-9_]+")
3232
VALIDATION_FEATURE_NAME_REGEX = re.compile(r"[a-z0-9_]+")

0 commit comments

Comments
 (0)