Source code for haive.core.schema.compatibility.converters
"""Type conversion system for schema compatibility."""from__future__importannotationsfromabcimportABC,abstractmethodfromtypingimportAnyfromhaive.core.schema.compatibility.typesimportConversionContext,ConversionQuality
[docs]classTypeConverter(ABC):"""Abstract base class for type converters."""@property@abstractmethoddefname(self)->str:"""Unique name for this converter."""@propertydefpriority(self)->int:"""Priority for converter selection (higher = preferred)."""return0
[docs]@abstractmethoddefcan_convert(self,source_type:type[Any],target_type:type[Any])->bool:"""Check if this converter can handle the conversion."""
[docs]@abstractmethoddefconvert(self,value:Any,context:ConversionContext)->Any:"""Convert a value from source to target type."""
[docs]defestimate_quality(self,source_type:type[Any],target_type:type[Any])->ConversionQuality:"""Estimate the quality of conversion."""returnConversionQuality.SAFE
[docs]classConverterRegistry:"""Registry for type converters."""def__init__(self):"""Init ."""self._converters:dict[str,TypeConverter]={}self._type_cache:dict[tuple[type[Any],type[Any]],TypeConverter|None]={}
[docs]defregister(self,converter:TypeConverter)->None:"""Register a type converter."""self._converters[converter.name]=converter# Clear cache when new converter is registeredself._type_cache.clear()
[docs]defunregister(self,name:str)->None:"""Unregister a type converter."""ifnameinself._converters:delself._converters[name]self._type_cache.clear()
[docs]defget_converter(self,source_type:type[Any],target_type:type[Any])->TypeConverter|None:"""Get the best converter for a type pair."""# Check cache firstcache_key=(source_type,target_type)ifcache_keyinself._type_cache:returnself._type_cache[cache_key]# Find compatible converterscompatible_converters:list[TypeConverter]=[]forconverterinself._converters.values():ifconverter.can_convert(source_type,target_type):compatible_converters.append(converter)# Select best converter by priorityifcompatible_converters:best_converter=max(compatible_converters,key=lambdac:c.priority)self._type_cache[cache_key]=best_converterreturnbest_converterself._type_cache[cache_key]=NonereturnNone
[docs]defcan_convert(self,source_type:type[Any],target_type:type[Any])->bool:"""Check if conversion is possible."""returnself.get_converter(source_type,target_type)isnotNone
[docs]defconvert(self,value:Any,source_type:type[Any],target_type:type[Any])->Any:"""Convert a value using the best available converter."""converter=self.get_converter(source_type,target_type)ifnotconverter:raiseValueError(f"No converter found for {source_type} -> {target_type}")context=ConversionContext(source_type=str(source_type),target_type=str(target_type))context.add_step(f"Using converter: {converter.name}")returnconverter.convert(value,context)
[docs]deflist_converters(self)->list[str]:"""List all registered converter names."""returnlist(self._converters.keys())
# Global converter registry_global_registry=ConverterRegistry()
[docs]defregister_converter(converter:TypeConverter)->None:"""Register a converter in the global registry."""_global_registry.register(converter)
[docs]defget_converter_registry()->ConverterRegistry:"""Get the global converter registry."""return_global_registry