Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/msgspec/yaml.py: 40%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

42 statements  

1from __future__ import annotations 

2 

3import datetime as _datetime 

4from typing import TYPE_CHECKING, Any, TypeVar, overload 

5 

6from . import ( 

7 DecodeError as _DecodeError, 

8 convert as _convert, 

9 to_builtins as _to_builtins, 

10) 

11 

12if TYPE_CHECKING: 

13 from typing import Callable, Literal, Optional, Type, Union 

14 

15 from typing_extensions import Buffer 

16 

17 

18__all__ = ("encode", "decode") 

19 

20 

21def __dir__(): 

22 return __all__ 

23 

24 

25def _import_pyyaml(name): 

26 try: 

27 import yaml # type: ignore 

28 except ImportError: 

29 raise ImportError( 

30 f"`msgspec.yaml.{name}` requires PyYAML be installed.\n\n" 

31 "Please either `pip` or `conda` install it as follows:\n\n" 

32 " $ python -m pip install pyyaml # using pip\n" 

33 " $ conda install pyyaml # or using conda" 

34 ) from None 

35 else: 

36 return yaml 

37 

38 

39def encode( 

40 obj: Any, 

41 *, 

42 enc_hook: Optional[Callable[[Any], Any]] = None, 

43 order: Literal[None, "deterministic", "sorted"] = None, 

44) -> bytes: 

45 """Serialize an object as YAML. 

46 

47 Parameters 

48 ---------- 

49 obj : Any 

50 The object to serialize. 

51 enc_hook : callable, optional 

52 A callable to call for objects that aren't supported msgspec types. 

53 Takes the unsupported object and should return a supported object, or 

54 raise a ``NotImplementedError`` if unsupported. 

55 order : {None, 'deterministic', 'sorted'}, optional 

56 The ordering to use when encoding unordered compound types. 

57 

58 - ``None``: All objects are encoded in the most efficient manner 

59 matching their in-memory representations. The default. 

60 - `'deterministic'`: Unordered collections (sets, dicts) are sorted to 

61 ensure a consistent output between runs. Useful when 

62 comparison/hashing of the encoded binary output is necessary. 

63 - `'sorted'`: Like `'deterministic'`, but *all* object-like types 

64 (structs, dataclasses, ...) are also sorted by field name before 

65 encoding. This is slower than `'deterministic'`, but may produce more 

66 human-readable output. 

67 

68 Returns 

69 ------- 

70 data : bytes 

71 The serialized object. 

72 

73 Notes 

74 ----- 

75 This function requires that the third-party `PyYAML library 

76 <https://pyyaml.org/>`_ is installed. 

77 

78 See Also 

79 -------- 

80 decode 

81 """ 

82 yaml = _import_pyyaml("encode") 

83 # Use the C extension if available 

84 Dumper = getattr(yaml, "CSafeDumper", yaml.SafeDumper) 

85 

86 return yaml.dump_all( 

87 [ 

88 _to_builtins( 

89 obj, 

90 builtin_types=(_datetime.datetime, _datetime.date), 

91 enc_hook=enc_hook, 

92 order=order, 

93 ) 

94 ], 

95 encoding="utf-8", 

96 Dumper=Dumper, 

97 allow_unicode=True, 

98 sort_keys=False, 

99 ) 

100 

101 

102T = TypeVar("T") 

103 

104 

105@overload 

106def decode( 

107 buf: Union[Buffer, str], 

108 *, 

109 strict: bool = True, 

110 dec_hook: Optional[Callable[[type, Any], Any]] = None, 

111) -> Any: 

112 pass 

113 

114 

115@overload 

116def decode( 

117 buf: Union[bytes, str], 

118 *, 

119 type: Type[T] = ..., 

120 strict: bool = True, 

121 dec_hook: Optional[Callable[[type, Any], Any]] = None, 

122) -> T: 

123 pass 

124 

125 

126@overload 

127def decode( 

128 buf: Union[bytes, str], 

129 *, 

130 type: Any = ..., 

131 strict: bool = True, 

132 dec_hook: Optional[Callable[[type, Any], Any]] = None, 

133) -> Any: 

134 pass 

135 

136 

137def decode(buf, *, type=Any, strict=True, dec_hook=None): 

138 """Deserialize an object from YAML. 

139 

140 Parameters 

141 ---------- 

142 buf : bytes-like or str 

143 The message to decode. 

144 type : type, optional 

145 A Python type (in type annotation form) to decode the object as. If 

146 provided, the message will be type checked and decoded as the specified 

147 type. Defaults to `Any`, in which case the message will be decoded 

148 using the default YAML types. 

149 strict : bool, optional 

150 Whether type coercion rules should be strict. Setting to False enables 

151 a wider set of coercion rules from string to non-string types for all 

152 values. Default is True. 

153 dec_hook : callable, optional 

154 An optional callback for handling decoding custom types. Should have 

155 the signature ``dec_hook(type: Type, obj: Any) -> Any``, where ``type`` 

156 is the expected message type, and ``obj`` is the decoded representation 

157 composed of only basic YAML types. This hook should transform ``obj`` 

158 into type ``type``, or raise a ``NotImplementedError`` if unsupported. 

159 

160 Returns 

161 ------- 

162 obj : Any 

163 The deserialized object. 

164 

165 Notes 

166 ----- 

167 This function requires that the third-party `PyYAML library 

168 <https://pyyaml.org/>`_ is installed. 

169 

170 See Also 

171 -------- 

172 encode 

173 """ 

174 yaml = _import_pyyaml("decode") 

175 # Use the C extension if available 

176 Loader = getattr(yaml, "CSafeLoader", yaml.SafeLoader) 

177 if not isinstance(buf, (str, bytes)): 

178 # call `memoryview` first, since `bytes(1)` is actually valid 

179 buf = bytes(memoryview(buf)) 

180 try: 

181 obj = yaml.load(buf, Loader) 

182 except yaml.YAMLError as exc: 

183 raise _DecodeError(str(exc)) from None 

184 

185 if type is Any: 

186 return obj 

187 return _convert( 

188 obj, 

189 type, 

190 builtin_types=(_datetime.datetime, _datetime.date), 

191 strict=strict, 

192 dec_hook=dec_hook, 

193 )