From 41624a7a543b4d7e1a203b956cdc28092b2a4878 Mon Sep 17 00:00:00 2001 From: Jonathan Dekhtiar Date: Tue, 15 Apr 2025 13:00:28 -0400 Subject: [PATCH 1/2] Validator All Unique - Tune Up to make error explicit --- variantlib/models/provider.py | 3 +-- variantlib/models/validators.py | 17 +++++++++++------ variantlib/models/variant.py | 3 +-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/variantlib/models/provider.py b/variantlib/models/provider.py index f6274c4..ecf5a09 100644 --- a/variantlib/models/provider.py +++ b/variantlib/models/provider.py @@ -2,7 +2,6 @@ from dataclasses import dataclass from dataclasses import field -from operator import attrgetter from variantlib.constants import VALIDATION_FEATURE_REGEX from variantlib.constants import VALIDATION_NAMESPACE_REGEX @@ -67,7 +66,7 @@ class ProviderConfig(BaseModel): [ lambda v: validate_type(v, list[VariantFeatureConfig]), lambda v: validate_list_min_len(v, 1), - lambda v: validate_list_all_unique(v, key=attrgetter("name")), + lambda v: validate_list_all_unique(v, keys=["name"]), ], value=val, ), diff --git a/variantlib/models/validators.py b/variantlib/models/validators.py index 5c4b330..9b8bb2e 100644 --- a/variantlib/models/validators.py +++ b/variantlib/models/validators.py @@ -3,6 +3,7 @@ import logging import re from collections.abc import Iterable +from operator import attrgetter from types import GenericAlias from typing import Any from typing import Callable @@ -32,7 +33,7 @@ def validate_list_min_len(values: list, min_length: int) -> None: ) -def validate_list_all_unique(values: list[Any], key: None | Callable = None) -> None: +def validate_list_all_unique(values: list[Any], keys: list[str] | None = None) -> None: """ Validate that all elements in the list are unique. Raises a ValueError if duplicates are found. @@ -40,13 +41,17 @@ def validate_list_all_unique(values: list[Any], key: None | Callable = None) -> seen = set() for value in values: - if key is not None: - value = key(value) # noqa: PLW2901 + _value = value - if value in seen: - raise ValidationError(f"Duplicate value found: '{value}' in list.") + if keys is not None: + _value = tuple([attrgetter(key)(value) for key in keys]) + if len(_value) == 1: + _value = _value[0] - seen.add(value) + if _value in seen: + raise ValidationError(f"Duplicate value found: '{_value}' in list.") + + seen.add(_value) def validate_or(validators: list[Callable], value: Any) -> None: diff --git a/variantlib/models/variant.py b/variantlib/models/variant.py index fc980c7..e56389f 100644 --- a/variantlib/models/variant.py +++ b/variantlib/models/variant.py @@ -7,7 +7,6 @@ from dataclasses import asdict from dataclasses import dataclass from dataclasses import field -from operator import attrgetter from variantlib.constants import VALIDATION_FEATURE_REGEX from variantlib.constants import VALIDATION_NAMESPACE_REGEX @@ -165,7 +164,7 @@ class VariantDescription(BaseModel): lambda v: validate_type(v, list[VariantProperty]), lambda v: validate_list_min_len(v, 1), lambda v: validate_list_all_unique( - v, key=attrgetter("feature_hash") + v, keys=["namespace", "feature"] ), ], value=val, From d3dd5b5121872ef292ecc309474726a14a77d2e3 Mon Sep 17 00:00:00 2001 From: Jonathan DEKHTIAR Date: Tue, 15 Apr 2025 13:42:51 -0400 Subject: [PATCH 2/2] Update variantlib/models/validators.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michał Górny --- variantlib/models/validators.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/variantlib/models/validators.py b/variantlib/models/validators.py index 9b8bb2e..e9fbacb 100644 --- a/variantlib/models/validators.py +++ b/variantlib/models/validators.py @@ -3,7 +3,6 @@ import logging import re from collections.abc import Iterable -from operator import attrgetter from types import GenericAlias from typing import Any from typing import Callable @@ -44,7 +43,7 @@ def validate_list_all_unique(values: list[Any], keys: list[str] | None = None) - _value = value if keys is not None: - _value = tuple([attrgetter(key)(value) for key in keys]) + _value = tuple([getattr(value, key) for key in keys]) if len(_value) == 1: _value = _value[0]