serde.yaml
Serialize and Deserialize in YAML format. This module depends on pyyaml package.
1""" 2Serialize and Deserialize in YAML format. This module depends on 3[pyyaml](https://pypi.org/project/PyYAML/) package. 4""" 5 6from typing import Any, overload 7 8import yaml 9 10from .compat import SerdeError, T 11from .de import Deserializer, from_dict 12from .se import Serializer, to_dict 13 14__all__ = ["from_yaml", "to_yaml", "deserialize_yaml_numbers"] 15 16 17class YamlSerializer(Serializer[str]): 18 @classmethod 19 def serialize(cls, obj: Any, **opts: Any) -> str: 20 return yaml.safe_dump(obj, **opts) # type: ignore 21 22 23class YamlDeserializer(Deserializer[str]): 24 @classmethod 25 def deserialize(cls, data: str, **opts: Any) -> Any: 26 return yaml.safe_load(data, **opts) 27 28 29def deserialize_yaml_numbers(value: Any) -> float: 30 """ 31 Convert YAML numbers to float, accepting ints/floats and numeric strings (e.g. scientific 32 notation). Rejects booleans and non-numeric inputs. 33 """ 34 if isinstance(value, bool): 35 raise SerdeError(f"Expected YAML number but got boolean {value!r}") 36 if isinstance(value, (int, float)): 37 return float(value) 38 if isinstance(value, str): 39 try: 40 return float(value) 41 except ValueError as e: 42 raise SerdeError(f"Could not convert YAML number string {value!r} to float") from e 43 raise SerdeError(f"Expected YAML number but got {type(value).__name__}") 44 45 46def to_yaml( 47 obj: Any, 48 cls: Any | None = None, 49 se: type[Serializer[str]] = YamlSerializer, 50 reuse_instances: bool = False, 51 convert_sets: bool = True, 52 skip_none: bool = False, 53 **opts: Any, 54) -> str: 55 """ 56 Serialize the object into YAML. 57 58 You can pass any serializable `obj`. If you supply keyword arguments other than `se`, 59 they will be passed in `yaml.safe_dump` function. 60 61 * `skip_none`: When set to True, any field in the class with a None value is excluded from the 62 serialized output. Defaults to False. 63 64 If you want to use the other yaml package, you can subclass `YamlSerializer` and implement 65 your own logic. 66 """ 67 return se.serialize( 68 to_dict( 69 obj, 70 c=cls, 71 reuse_instances=reuse_instances, 72 convert_sets=convert_sets, 73 skip_none=skip_none, 74 ), 75 **opts, 76 ) 77 78 79@overload 80def from_yaml( 81 c: type[T], 82 s: str, 83 de: type[Deserializer[str]] = YamlDeserializer, 84 coerce_numbers: bool = True, 85 **opts: Any, 86) -> T: ... 87 88 89# For Union, Optional etc. 90@overload 91def from_yaml( 92 c: Any, 93 s: str, 94 de: type[Deserializer[str]] = YamlDeserializer, 95 coerce_numbers: bool = True, 96 **opts: Any, 97) -> Any: ... 98 99 100def from_yaml( 101 c: Any, 102 s: str, 103 de: type[Deserializer[str]] = YamlDeserializer, 104 coerce_numbers: bool = True, 105 **opts: Any, 106) -> Any: 107 """ 108 `c` is a class object and `s` is YAML string. If you supply keyword arguments other than `de`, 109 they will be passed in `yaml.safe_load` function. 110 111 * `coerce_numbers`: When True (default), numeric YAML scalars or numeric strings (e.g. 112 "1e-3") are coerced to floats when the target type is float. Booleans are rejected. 113 114 If you want to use the other yaml package, you can subclass `YamlDeserializer` and implement 115 your own logic. 116 """ 117 deserialize_numbers = deserialize_yaml_numbers if coerce_numbers else None 118 return from_dict( 119 c, 120 de.deserialize(s, **opts), 121 reuse_instances=False, 122 deserialize_numbers=deserialize_numbers, 123 )
def
from_yaml( c: Any, s: str, de: type[serde.de.Deserializer[str]] = <class 'serde.yaml.YamlDeserializer'>, coerce_numbers: bool = True, **opts: Any) -> Any:
101def from_yaml( 102 c: Any, 103 s: str, 104 de: type[Deserializer[str]] = YamlDeserializer, 105 coerce_numbers: bool = True, 106 **opts: Any, 107) -> Any: 108 """ 109 `c` is a class object and `s` is YAML string. If you supply keyword arguments other than `de`, 110 they will be passed in `yaml.safe_load` function. 111 112 * `coerce_numbers`: When True (default), numeric YAML scalars or numeric strings (e.g. 113 "1e-3") are coerced to floats when the target type is float. Booleans are rejected. 114 115 If you want to use the other yaml package, you can subclass `YamlDeserializer` and implement 116 your own logic. 117 """ 118 deserialize_numbers = deserialize_yaml_numbers if coerce_numbers else None 119 return from_dict( 120 c, 121 de.deserialize(s, **opts), 122 reuse_instances=False, 123 deserialize_numbers=deserialize_numbers, 124 )
c is a class object and s is YAML string. If you supply keyword arguments other than de,
they will be passed in yaml.safe_load function.
coerce_numbers: When True (default), numeric YAML scalars or numeric strings (e.g. "1e-3") are coerced to floats when the target type is float. Booleans are rejected.
If you want to use the other yaml package, you can subclass YamlDeserializer and implement
your own logic.
def
to_yaml( obj: Any, cls: typing.Any | None = None, se: type[serde.se.Serializer[str]] = <class 'serde.yaml.YamlSerializer'>, reuse_instances: bool = False, convert_sets: bool = True, skip_none: bool = False, **opts: Any) -> str:
47def to_yaml( 48 obj: Any, 49 cls: Any | None = None, 50 se: type[Serializer[str]] = YamlSerializer, 51 reuse_instances: bool = False, 52 convert_sets: bool = True, 53 skip_none: bool = False, 54 **opts: Any, 55) -> str: 56 """ 57 Serialize the object into YAML. 58 59 You can pass any serializable `obj`. If you supply keyword arguments other than `se`, 60 they will be passed in `yaml.safe_dump` function. 61 62 * `skip_none`: When set to True, any field in the class with a None value is excluded from the 63 serialized output. Defaults to False. 64 65 If you want to use the other yaml package, you can subclass `YamlSerializer` and implement 66 your own logic. 67 """ 68 return se.serialize( 69 to_dict( 70 obj, 71 c=cls, 72 reuse_instances=reuse_instances, 73 convert_sets=convert_sets, 74 skip_none=skip_none, 75 ), 76 **opts, 77 )
Serialize the object into YAML.
You can pass any serializable obj. If you supply keyword arguments other than se,
they will be passed in yaml.safe_dump function.
skip_none: When set to True, any field in the class with a None value is excluded from the serialized output. Defaults to False.
If you want to use the other yaml package, you can subclass YamlSerializer and implement
your own logic.
def
deserialize_yaml_numbers(value: Any) -> float:
30def deserialize_yaml_numbers(value: Any) -> float: 31 """ 32 Convert YAML numbers to float, accepting ints/floats and numeric strings (e.g. scientific 33 notation). Rejects booleans and non-numeric inputs. 34 """ 35 if isinstance(value, bool): 36 raise SerdeError(f"Expected YAML number but got boolean {value!r}") 37 if isinstance(value, (int, float)): 38 return float(value) 39 if isinstance(value, str): 40 try: 41 return float(value) 42 except ValueError as e: 43 raise SerdeError(f"Could not convert YAML number string {value!r} to float") from e 44 raise SerdeError(f"Expected YAML number but got {type(value).__name__}")
Convert YAML numbers to float, accepting ints/floats and numeric strings (e.g. scientific notation). Rejects booleans and non-numeric inputs.