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

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

55 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_tomllib(): 

26 try: 

27 import tomllib # type: ignore 

28 

29 return tomllib 

30 except ImportError: 

31 pass 

32 

33 try: 

34 import tomli # type: ignore 

35 

36 return tomli 

37 except ImportError: 

38 raise ImportError( 

39 "`msgspec.toml.decode` requires `tomli` be installed.\n\n" 

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

41 " $ python -m pip install tomli # using pip\n" 

42 " $ conda install tomli # or using conda" 

43 ) from None 

44 

45 

46def _import_tomli_w(): 

47 try: 

48 import tomli_w # type: ignore 

49 

50 return tomli_w 

51 except ImportError: 

52 raise ImportError( 

53 "`msgspec.toml.encode` requires `tomli_w` be installed.\n\n" 

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

55 " $ python -m pip install tomli_w # using pip\n" 

56 " $ conda install tomli_w # or using conda" 

57 ) from None 

58 

59 

60def encode( 

61 obj: Any, 

62 *, 

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

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

65) -> bytes: 

66 """Serialize an object as TOML. 

67 

68 Parameters 

69 ---------- 

70 obj : Any 

71 The object to serialize. 

72 enc_hook : callable, optional 

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

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

75 raise a ``NotImplementedError`` if unsupported. 

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

77 The ordering to use when encoding unordered compound types. 

78 

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

80 matching their in-memory representations. The default. 

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

82 ensure a consistent output between runs. Useful when 

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

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

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

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

87 human-readable output. 

88 

89 Returns 

90 ------- 

91 data : bytes 

92 The serialized object. 

93 

94 See Also 

95 -------- 

96 decode 

97 """ 

98 toml = _import_tomli_w() 

99 msg = _to_builtins( 

100 obj, 

101 builtin_types=(_datetime.datetime, _datetime.date, _datetime.time), 

102 str_keys=True, 

103 enc_hook=enc_hook, 

104 order=order, 

105 ) 

106 return toml.dumps(msg).encode("utf-8") 

107 

108 

109T = TypeVar("T") 

110 

111 

112@overload 

113def decode( 

114 buf: Union[Buffer, str], 

115 *, 

116 strict: bool = True, 

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

118) -> Any: 

119 pass 

120 

121 

122@overload 

123def decode( 

124 buf: Union[Buffer, str], 

125 *, 

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

127 strict: bool = True, 

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

129) -> T: 

130 pass 

131 

132 

133@overload 

134def decode( 

135 buf: Union[Buffer, str], 

136 *, 

137 type: Any = ..., 

138 strict: bool = True, 

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

140) -> Any: 

141 pass 

142 

143 

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

145 """Deserialize an object from TOML. 

146 

147 Parameters 

148 ---------- 

149 buf : bytes-like or str 

150 The message to decode. 

151 type : type, optional 

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

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

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

155 using the default TOML types. 

156 strict : bool, optional 

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

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

159 values. Default is True. 

160 dec_hook : callable, optional 

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

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

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

164 composed of only basic TOML types. This hook should transform ``obj`` 

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

166 

167 Returns 

168 ------- 

169 obj : Any 

170 The deserialized object. 

171 

172 See Also 

173 -------- 

174 encode 

175 """ 

176 toml = _import_tomllib() 

177 if isinstance(buf, str): 

178 str_buf = buf 

179 elif isinstance(buf, (bytes, bytearray)): 

180 str_buf = buf.decode("utf-8") 

181 else: 

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

183 str_buf = bytes(memoryview(buf)).decode("utf-8") 

184 try: 

185 obj = toml.loads(str_buf) 

186 except toml.TOMLDecodeError as exc: 

187 raise _DecodeError(str(exc)) from None 

188 

189 if type is Any: 

190 return obj 

191 return _convert( 

192 obj, 

193 type, 

194 builtin_types=(_datetime.datetime, _datetime.date, _datetime.time), 

195 str_keys=True, 

196 strict=strict, 

197 dec_hook=dec_hook, 

198 )