|
|
|
|
@ -47,6 +47,10 @@ class UnsupportedSegmentTypeError(Exception):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TypeMismatchError(Exception):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Define the constant
|
|
|
|
|
SEGMENT_TO_VARIABLE_MAP = {
|
|
|
|
|
StringSegment: StringVariable,
|
|
|
|
|
@ -148,10 +152,80 @@ def build_segment(value: Any, /) -> Segment:
|
|
|
|
|
case SegmentType.NONE:
|
|
|
|
|
return ArrayAnySegment(value=value)
|
|
|
|
|
case _:
|
|
|
|
|
# This should be unreachable.
|
|
|
|
|
raise ValueError(f"not supported value {value}")
|
|
|
|
|
raise ValueError(f"not supported value {value}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def build_segment_with_type(segment_type: SegmentType, value: Any) -> Segment:
|
|
|
|
|
"""
|
|
|
|
|
Build a segment with explicit type checking.
|
|
|
|
|
|
|
|
|
|
This function creates a segment from a value while enforcing type compatibility
|
|
|
|
|
with the specified segment_type. It provides stricter type validation compared
|
|
|
|
|
to the standard build_segment function.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
segment_type: The expected SegmentType for the resulting segment
|
|
|
|
|
value: The value to be converted into a segment
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
Segment: A segment instance of the appropriate type
|
|
|
|
|
|
|
|
|
|
Raises:
|
|
|
|
|
TypeMismatchError: If the value type doesn't match the expected segment_type
|
|
|
|
|
|
|
|
|
|
Special Cases:
|
|
|
|
|
- For empty list [] values, if segment_type is array[*], returns the corresponding array type
|
|
|
|
|
- Type validation is performed before segment creation
|
|
|
|
|
|
|
|
|
|
Examples:
|
|
|
|
|
>>> build_segment_with_type(SegmentType.STRING, "hello")
|
|
|
|
|
StringSegment(value="hello")
|
|
|
|
|
|
|
|
|
|
>>> build_segment_with_type(SegmentType.ARRAY_STRING, [])
|
|
|
|
|
ArrayStringSegment(value=[])
|
|
|
|
|
|
|
|
|
|
>>> build_segment_with_type(SegmentType.STRING, 123)
|
|
|
|
|
# Raises TypeMismatchError
|
|
|
|
|
"""
|
|
|
|
|
# Handle None values
|
|
|
|
|
if value is None:
|
|
|
|
|
if segment_type == SegmentType.NONE:
|
|
|
|
|
return NoneSegment()
|
|
|
|
|
else:
|
|
|
|
|
raise TypeMismatchError(f"Expected {segment_type}, but got None")
|
|
|
|
|
|
|
|
|
|
# Handle empty list special case for array types
|
|
|
|
|
if isinstance(value, list) and len(value) == 0:
|
|
|
|
|
if segment_type == SegmentType.ARRAY_ANY:
|
|
|
|
|
return ArrayAnySegment(value=value)
|
|
|
|
|
elif segment_type == SegmentType.ARRAY_STRING:
|
|
|
|
|
return ArrayStringSegment(value=value)
|
|
|
|
|
elif segment_type == SegmentType.ARRAY_NUMBER:
|
|
|
|
|
return ArrayNumberSegment(value=value)
|
|
|
|
|
elif segment_type == SegmentType.ARRAY_OBJECT:
|
|
|
|
|
return ArrayObjectSegment(value=value)
|
|
|
|
|
elif segment_type == SegmentType.ARRAY_FILE:
|
|
|
|
|
return ArrayFileSegment(value=value)
|
|
|
|
|
else:
|
|
|
|
|
raise TypeMismatchError(f"Expected {segment_type}, but got empty list")
|
|
|
|
|
|
|
|
|
|
# Build segment using existing logic to infer actual type
|
|
|
|
|
inferred_segment = build_segment(value)
|
|
|
|
|
inferred_type = inferred_segment.value_type
|
|
|
|
|
|
|
|
|
|
# Type compatibility checking
|
|
|
|
|
if inferred_type == segment_type:
|
|
|
|
|
return inferred_segment
|
|
|
|
|
|
|
|
|
|
# Type mismatch - raise error with descriptive message
|
|
|
|
|
raise TypeMismatchError(
|
|
|
|
|
f"Type mismatch: expected {segment_type}, but value '{value}' "
|
|
|
|
|
f"(type: {type(value).__name__}) corresponds to {inferred_type}"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def segment_to_variable(
|
|
|
|
|
*,
|
|
|
|
|
segment: Segment,
|
|
|
|
|
|