Skip to content
Merged
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
30 changes: 20 additions & 10 deletions scripts/ci/validation_utils.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
#!/usr/bin/env python3
"""
Reusable validation helpers for CI scripts.
"""Reusable validation helpers for CI scripts.

These helpers reduce boilerplate and provide clearer failure semantics
using specific exception types.
These helpers reduce boilerplate and provide clearer failure semantics using specific
exception types.
"""

from typing import Any, Iterable


def validate_metric_ranges(metrics: dict[str, Any], fields: Iterable[str]) -> None:
"""Ensure each metric in fields is within [0, 1].

Raises:
Raises
------
Comment on lines +14 to +15

Copilot AI Sep 25, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring format should use 'Raises:' with a colon instead of 'Raises' with dashes for consistency with Python docstring conventions.

Copilot uses AI. Check for mistakes.
ValueError: if any metric is missing or out of range.
"""
for field in fields:
Expand All @@ -27,10 +28,15 @@ def validate_metric_ranges(metrics: dict[str, Any], fields: Iterable[str]) -> No
raise ValueError(f"{pretty} should be between 0 and 1")


def validate_required_keys(obj: dict[str, Any], keys: Iterable[str], label: str = "object") -> None:
def validate_required_keys(
obj: dict[str, Any],
keys: Iterable[str],
label: str = "object",
) -> None:
Comment on lines +31 to +35

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current implementation iterates through keys and fails on the first one that's missing. For a better developer experience, consider collecting all missing keys and reporting them in a single KeyError. This would allow a developer to fix all missing keys at once. You could achieve this efficiently using set operations to find the difference between the required keys and the keys present in the object.

"""Validate that all keys exist in obj.

Raises:
Raises
------
Comment on lines +38 to +39

Copilot AI Sep 25, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring format should use 'Raises:' with a colon instead of 'Raises' with dashes for consistency with Python docstring conventions.

Copilot uses AI. Check for mistakes.
KeyError: if a required key is missing.
"""
for key in keys:
Expand All @@ -39,10 +45,15 @@ def validate_required_keys(obj: dict[str, Any], keys: Iterable[str], label: str
raise KeyError(f"{label} should have {pretty}")


def validate_hasattrs(instance: Any, attrs: Iterable[str], label: str = "object") -> None:
def validate_hasattrs(
instance: Any,
attrs: Iterable[str],
label: str = "object",
) -> None:
Comment on lines +48 to +52

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to validate_required_keys, this function fails on the first missing attribute. It would be more helpful to report all missing attributes in a single AttributeError. You could do this by iterating through all attributes, collecting the missing ones in a list, and then raising an exception with a consolidated error message if the list is not empty.

"""Validate that instance has all attributes in attrs.

Raises:
Raises
------
Comment on lines +55 to +56

Copilot AI Sep 25, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring format should use 'Raises:' with a colon instead of 'Raises' with dashes for consistency with Python docstring conventions.

Copilot uses AI. Check for mistakes.
AttributeError: if a required attribute is missing.
"""
for attr in attrs:
Expand All @@ -57,4 +68,3 @@ def ensure(condition: bool, message: str) -> None:
"""
if not condition:
raise AssertionError(message)

Loading