def parse_value( cls, value: Any, types: List[Type], default: Any = None, ns_map: Optional[Dict] = None, tokens: bool = False, _format: Optional[str] = None, ) -> Any: """Convert xml string values to s python primitive type.""" if value is None: if callable(default): return default() if tokens else None return default if tokens: value = value if isinstance(value, list) else value.split() return [ converter.deserialize(val, types, ns_map=ns_map, format=_format) for val in value ] return converter.deserialize(value, types, ns_map=ns_map, format=_format)
def test_register_converter_with_lambda(self): class MinusOneInt(int): pass converter.register_converter(MinusOneInt, lambda x: int(x) - 1) self.assertEqual(1, converter.deserialize("2", [MinusOneInt])) self.assertEqual(2, converter.deserialize("3", [MinusOneInt])) converter.unregister_converter(MinusOneInt)
def test_deserialize(self): with warnings.catch_warnings(record=True) as w: self.assertEqual("a", converter.deserialize("a", [int])) self.assertEqual( "Failed to convert value `a` to one of [<class 'int'>]", str(w[-1].message)) self.assertFalse(converter.deserialize("false", [int, bool])) self.assertEqual(1, converter.deserialize("1", [int, bool]))
def field_default_tokens(self, attr: Attr, types: List[Type]) -> str: assert isinstance(attr.default, str) tokens = ", ".join( str(self.prepare_default_value(converter.deserialize(val, types))) for val in attr.default.split()) return f"lambda: [{tokens}]"
def field_default_value(self, attr: Attr, ns_map: Optional[Dict] = None) -> Any: """Generate the field default value/factory for the given attribute.""" if attr.is_list or (attr.is_tokens and not attr.default): return "list" if attr.is_dict: return "dict" if attr.default is None: return None if not isinstance(attr.default, str): return self.literal_value(attr.default) if attr.default.startswith("@enum@"): return self.field_default_enum(attr) types = converter.sort_types(attr.native_types) if attr.is_tokens: return self.field_default_tokens(attr, types, ns_map) return self.literal_value( converter.deserialize(attr.default, types, ns_map=ns_map, format=attr.restrictions.format))
def test_register_converter(self): class MinusOneInt(int): pass class MinusOneIntConverter(Converter): def deserialize(self, value: str, **kwargs: Any) -> Any: return int(value) - 1 def serialize(self, value: Any, **kwargs: Any) -> str: return str(value) self.assertEqual(1, converter.deserialize("1", [MinusOneInt])) converter.register_converter(MinusOneInt, MinusOneIntConverter()) self.assertEqual(1, converter.deserialize("2", [MinusOneInt])) self.assertEqual(2, converter.deserialize("3", [MinusOneInt])) self.assertEqual("3", converter.serialize(MinusOneInt("3"))) converter.unregister_converter(MinusOneInt)
def test_register_converter(self): class MinusOneInt(int): pass class MinusOneIntConverter(Converter): def deserialize(self, value: str, **kwargs: Any) -> Any: return int(value) - 1 def serialize(self, value: Any, **kwargs: Any) -> str: return str(value) with warnings.catch_warnings(record=True) as w: self.assertEqual("1", converter.deserialize("1", [MinusOneInt])) self.assertEqual(f"No converter registered for `{MinusOneInt}`", str(w[-1].message)) converter.register_converter(MinusOneInt, MinusOneIntConverter()) self.assertEqual(1, converter.deserialize("2", [MinusOneInt])) self.assertEqual(2, converter.deserialize("3", [MinusOneInt])) self.assertEqual("3", converter.serialize(MinusOneInt("3"))) converter.unregister_converter(MinusOneInt)
def field_default_tokens(self, attr: Attr, types: List[Type], ns_map: Optional[Dict]) -> str: assert isinstance(attr.default, str) fmt = attr.restrictions.format tokens = [ converter.deserialize(val, types, ns_map=ns_map, format=fmt) for val in attr.default.split() ] if attr.is_enumeration: return self.format_metadata(tuple(tokens), indent=8) return f"lambda: {self.format_metadata(tokens, indent=8)}"
def test_serialize(self): with warnings.catch_warnings(record=True): self.assertEqual(None, converter.deserialize(None, [int])) self.assertEqual("1", converter.serialize(1)) self.assertEqual("1 2 3", converter.serialize([1, "2", 3])) self.assertEqual(None, converter.serialize(None)) self.assertEqual("1", converter.serialize(1)) self.assertEqual("1.5", converter.serialize(1.5)) self.assertEqual("true", converter.serialize(True)) self.assertEqual("optional", converter.serialize(UseType.OPTIONAL)) self.assertEqual("8.77683E-8", converter.serialize(Decimal("8.77683E-8"))) self.assertEqual("8.77683E-08", converter.serialize(float("8.77683E-8")))
def field_default_value(self, attr: Attr, ns_map: Optional[Dict] = None) -> Any: """Generate the field default value/factory for the given attribute.""" if attr.is_list or (attr.is_tokens and not attr.default): return "list" if attr.is_dict: return "dict" if not isinstance(attr.default, str): return attr.default if attr.default.startswith("@enum@"): return self.field_default_enum(attr) types = converter.sort_types( list({ attr_type.native_type for attr_type in attr.types if attr_type.native })) if attr.is_tokens: return self.field_default_tokens(attr, types) return self.prepare_default_value( converter.deserialize(attr.default, types, ns_map=ns_map))
def asdict(self, types: Optional[List[Type]] = None) -> Dict: """ Return the initialized only properties as a dictionary. Skip None or implied values, and optionally use the parent attribute types to convert relevant options. """ result = {} sorted_types = converter.sort_types(types) if types else [] for key, value in asdict(self).items(): if value is None or key == "choice": continue elif key == "max_occurs" and value >= sys.maxsize: continue elif key == "min_occurs" and value == 0: continue elif key.endswith("clusive") and types: value = converter.deserialize(value, sorted_types) result[key] = value return result