Coverage for lintro / tools / core / option_validators.py: 97%
37 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
1"""Option validation utilities for tool plugins.
3This module provides common validation functions to reduce boilerplate
4in tool set_options() methods.
5"""
7from typing import Any
10def validate_bool(value: Any, name: str) -> None:
11 """Validate that value is a boolean if not None.
13 Args:
14 value: Value to validate.
15 name: Parameter name for error message.
17 Raises:
18 ValueError: If value is not None and not a boolean.
19 """
20 if value is not None and not isinstance(value, bool):
21 raise ValueError(f"{name} must be a boolean")
24def validate_str(value: Any, name: str) -> None:
25 """Validate that value is a string if not None.
27 Args:
28 value: Value to validate.
29 name: Parameter name for error message.
31 Raises:
32 ValueError: If value is not None and not a string.
33 """
34 if value is not None and not isinstance(value, str):
35 raise ValueError(f"{name} must be a string")
38def validate_int(
39 value: Any,
40 name: str,
41 min_value: int | None = None,
42 max_value: int | None = None,
43) -> None:
44 """Validate that value is an integer if not None.
46 Args:
47 value: Value to validate.
48 name: Parameter name for error message.
49 min_value: Optional minimum allowed value (inclusive).
50 max_value: Optional maximum allowed value (inclusive).
52 Raises:
53 ValueError: If value is not None and not an integer, or if value
54 is outside the specified range.
55 """
56 if value is None:
57 return
59 if not isinstance(value, int) or isinstance(value, bool):
60 raise ValueError(f"{name} must be an integer")
62 if min_value is not None and value < min_value:
63 raise ValueError(f"{name} must be at least {min_value}")
65 if max_value is not None and value > max_value:
66 raise ValueError(f"{name} must be at most {max_value}")
69def validate_positive_int(value: Any, name: str) -> None:
70 """Validate that value is a positive integer if not None.
72 Args:
73 value: Value to validate.
74 name: Parameter name for error message.
76 Raises:
77 ValueError: If value is not None and not a positive integer.
78 """
79 if value is not None:
80 if not isinstance(value, int) or isinstance(value, bool):
81 raise ValueError(f"{name} must be an integer")
82 if value <= 0:
83 raise ValueError(f"{name} must be positive")
86def validate_list(value: Any, name: str) -> None:
87 """Validate that value is a list if not None.
89 Args:
90 value: Value to validate.
91 name: Parameter name for error message.
93 Raises:
94 ValueError: If value is not None and not a list.
95 """
96 if value is not None and not isinstance(value, list):
97 raise ValueError(f"{name} must be a list")
100def normalize_str_or_list(value: Any, name: str) -> list[str] | None:
101 """Normalize a string or list value to a list.
103 Args:
104 value: Value to normalize (string, list, or None).
105 name: Parameter name for error message.
107 Returns:
108 List of strings, or None if input was None.
110 Raises:
111 ValueError: If value is not None, string, or list.
112 """
113 if value is None:
114 return None
115 if isinstance(value, str):
116 return [value]
117 if isinstance(value, list):
118 if not all(isinstance(item, str) for item in value):
119 raise ValueError(f"{name} must be a string or list of strings")
120 return value
121 raise ValueError(f"{name} must be a string or list")
124def filter_none_options(**kwargs: Any) -> dict[str, Any]:
125 """Filter out None values from keyword arguments.
127 Args:
128 **kwargs: Keyword arguments to filter.
130 Returns:
131 Dictionary with only non-None values.
132 """
133 return {k: v for k, v in kwargs.items() if v is not None}