2Validation for PyHelios DataTypes (vec2, vec3, vec4, colors, etc.)
4Provides comprehensive validation for all geometric data types,
5ensuring finite values and appropriate ranges before C++ operations.
9from .core
import is_finite_numeric
10from .exceptions
import ValidationError, create_validation_error
14 """Validate a color component is in valid range [0,1]."""
15 if not is_finite_numeric(value):
16 raise create_validation_error(
17 f
"Color component {component_name} must be a finite number, got {value} ({type(value).__name__})",
18 param_name=f
"{param_name}.{component_name}",
19 function_name=function_name,
20 expected_type=
"finite number in range [0,1]",
22 suggestion=
"Color components must be normalized values between 0 and 1."
25 if not (0.0 <= value <= 1.0):
26 raise create_validation_error(
27 f
"Color component {component_name}={value} is outside valid range [0,1]",
28 param_name=f
"{param_name}.{component_name}",
29 function_name=function_name,
30 expected_type=
"number in range [0,1]",
32 suggestion=
"Color components must be normalized values between 0 and 1."
36def validate_rgb_color(color: Any, param_name: str =
"color", function_name: str =
None):
38 Validate RGBcolor has finite values in [0,1] range.
41 color: RGBcolor object to validate
42 param_name: Parameter name for error messages
43 function_name: Function name for error messages
46 ValidationError: If color is invalid or components out of range
52 if not hasattr(color,
'r')
or not hasattr(color,
'g')
or not hasattr(color,
'b'):
53 raise create_validation_error(
54 f
"Parameter must be an RGBcolor object with .r, .g, .b attributes",
55 param_name=param_name,
56 function_name=function_name,
57 expected_type=
"RGBcolor",
59 suggestion=
"Use RGBcolor(r, g, b) where r, g, b are values between 0 and 1."
69 Validate RGBAcolor has finite values in [0,1] range.
72 color: RGBAcolor object to validate
73 param_name: Parameter name for error messages
74 function_name: Function name for error messages
77 ValidationError: If color is invalid or components out of range
83 if not hasattr(color,
'r')
or not hasattr(color,
'g')
or not hasattr(color,
'b')
or not hasattr(color,
'a'):
84 raise create_validation_error(
85 f
"Parameter must be an RGBAcolor object with .r, .g, .b, .a attributes",
86 param_name=param_name,
87 function_name=function_name,
88 expected_type=
"RGBAcolor",
90 suggestion=
"Use RGBAcolor(r, g, b, a) where all values are between 0 and 1."
99def validate_vector_finite(vector: Any, param_name: str =
"vector", expected_dims: int = 3, function_name: str =
None):
101 Validate vector has finite components.
104 vector: Vector object to validate (vec2, vec3, vec4, etc.)
105 param_name: Parameter name for error messages
106 expected_dims: Expected number of dimensions
107 function_name: Function name for error messages
110 ValidationError: If vector is invalid or has non-finite components
116 attrs = [
'x',
'y',
'z',
'w'][:expected_dims]
120 if not hasattr(vector, attr):
121 raise create_validation_error(
122 f
"Parameter must be a vector with {'.'.join(attrs)} attributes",
123 param_name=param_name,
124 function_name=function_name,
125 expected_type=f
"vec{expected_dims}",
127 suggestion=f
"Use vec{expected_dims}() constructor or provide object with {'.'.join(attrs)} attributes."
130 value = getattr(vector, attr)
131 if not is_finite_numeric(value):
132 raise create_validation_error(
133 f
"Vector component {attr} must be a finite number, got {value} ({type(value).__name__})",
134 param_name=f
"{param_name}.{attr}",
135 function_name=function_name,
136 expected_type=
"finite number",
138 suggestion=
"Ensure all vector components are finite numbers (not NaN or infinity)."
142def validate_vec2(vector: Any, param_name: str =
"vector", function_name: str =
None):
144 Validate vec2 has finite x,y components.
147 vector: vec2 object to validate
148 param_name: Parameter name for error messages
149 function_name: Function name for error messages
152 The validated vec2 object
158def validate_vec3(vector: Any, param_name: str =
"vector", function_name: str =
None):
160 Validate vec3 has finite x,y,z components.
163 vector: vec3 object to validate
164 param_name: Parameter name for error messages
165 function_name: Function name for error messages
168 The validated vec3 object
174def validate_vec4(vector: Any, param_name: str =
"vector", function_name: str =
None):
176 Validate vec4 has finite x,y,z,w components.
179 vector: vec4 object to validate
180 param_name: Parameter name for error messages
181 function_name: Function name for error messages
188 Validate SphericalCoord has valid values.
191 coord: SphericalCoord object to validate
192 param_name: Parameter name for error messages
193 function_name: Function name for error messages
196 ValidationError: If coordinate has invalid values
201 if not hasattr(coord,
'radius')
or not hasattr(coord,
'elevation')
or not hasattr(coord,
'azimuth'):
202 raise create_validation_error(
203 f
"Parameter must be a SphericalCoord with .radius, .elevation, .azimuth attributes",
204 param_name=param_name,
205 function_name=function_name,
206 expected_type=
"SphericalCoord",
208 suggestion=
"Use SphericalCoord(radius, elevation, azimuth) constructor."
212 if not is_finite_numeric(coord.radius)
or coord.radius <= 0:
213 raise create_validation_error(
214 f
"SphericalCoord radius must be a positive finite number, got {coord.radius}",
215 param_name=f
"{param_name}.radius",
216 function_name=function_name,
217 expected_type=
"positive finite number",
218 actual_value=coord.radius,
219 suggestion=
"Radius must be greater than 0."
223 if not is_finite_numeric(coord.elevation):
224 raise create_validation_error(
225 f
"SphericalCoord elevation must be a finite number, got {coord.elevation} ({type(coord.elevation).__name__})",
226 param_name=f
"{param_name}.elevation",
227 function_name=function_name,
228 expected_type=
"finite number",
229 actual_value=coord.elevation,
230 suggestion=
"Elevation angle must be a finite number (not NaN or infinity)."
233 if not is_finite_numeric(coord.azimuth):
234 raise create_validation_error(
235 f
"SphericalCoord azimuth must be a finite number, got {coord.azimuth} ({type(coord.azimuth).__name__})",
236 param_name=f
"{param_name}.azimuth",
237 function_name=function_name,
238 expected_type=
"finite number",
239 actual_value=coord.azimuth,
240 suggestion=
"Azimuth angle must be a finite number (not NaN or infinity)."
244def validate_integer_vector(vector: Any, param_name: str =
"vector", expected_dims: int = 3, function_name: str =
None):
246 Validate integer vector (int2, int3, int4) has valid integer components.
249 vector: Integer vector object to validate
250 param_name: Parameter name for error messages
251 expected_dims: Expected number of dimensions
252 function_name: Function name for error messages
255 ValidationError: If vector has invalid or non-integer components
261 attrs = [
'x',
'y',
'z',
'w'][:expected_dims]
265 if not hasattr(vector, attr):
266 raise create_validation_error(
267 f
"Parameter must be an integer vector with {'.'.join(attrs)} attributes",
268 param_name=param_name,
269 function_name=function_name,
270 expected_type=f
"int{expected_dims}",
272 suggestion=f
"Use int{expected_dims}() constructor or provide object with {'.'.join(attrs)} attributes."
275 value = getattr(vector, attr)
276 if not isinstance(value, int):
277 raise create_validation_error(
278 f
"Integer vector component {attr} must be an integer, got {value} ({type(value).__name__})",
279 param_name=f
"{param_name}.{attr}",
280 function_name=function_name,
281 expected_type=
"integer",
283 suggestion=
"Ensure all vector components are integers."
287def validate_int2(vector: Any, param_name: str =
"vector", function_name: str =
None):
289 Validate int2 has valid integer x,y components.
292 vector: int2 object to validate
293 param_name: Parameter name for error messages
294 function_name: Function name for error messages
303def validate_int3(vector: Any, param_name: str =
"vector", function_name: str =
None):
305 Validate int3 has valid integer x,y,z components.
308 vector: int3 object to validate
309 param_name: Parameter name for error messages
310 function_name: Function name for error messages
315def validate_int4(vector: Any, param_name: str =
"vector", function_name: str =
None):
317 Validate int4 has valid integer x,y,z,w components.
320 vector: int4 object to validate
321 param_name: Parameter name for error messages
322 function_name: Function name for error messages
validate_vector_finite(Any vector, str param_name="vector", int expected_dims=3, str function_name=None)
Validate vector has finite components.
validate_integer_vector(Any vector, str param_name="vector", int expected_dims=3, str function_name=None)
Validate integer vector (int2, int3, int4) has valid integer components.
validate_vec4(Any vector, str param_name="vector", str function_name=None)
Validate vec4 has finite x,y,z,w components.
validate_vec3(Any vector, str param_name="vector", str function_name=None)
Validate vec3 has finite x,y,z components.
validate_int4(Any vector, str param_name="vector", str function_name=None)
Validate int4 has valid integer x,y,z,w components.
validate_int3(Any vector, str param_name="vector", str function_name=None)
Validate int3 has valid integer x,y,z components.
validate_rgba_color(Any color, str param_name="color", str function_name=None)
Validate RGBAcolor has finite values in [0,1] range.
validate_int2(Any vector, str param_name="vector", str function_name=None)
Validate int2 has valid integer x,y components.
validate_vec2(Any vector, str param_name="vector", str function_name=None)
Validate vec2 has finite x,y components.
validate_rgb_color(Any color, str param_name="color", str function_name=None)
Validate RGBcolor has finite values in [0,1] range.
validate_spherical_coord(Any coord, str param_name="coordinate", str function_name=None)
Validate SphericalCoord has valid values.
validate_color_component(float value, str component_name, str param_name, str function_name=None)
Validate a color component is in valid range [0,1].