Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/tomlkit/api.py: 54%
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
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
1from __future__ import annotations
3import contextlib
4import datetime as _datetime
6from collections.abc import Iterable
7from collections.abc import Mapping
8from typing import IO
9from typing import TYPE_CHECKING
10from typing import Any
11from typing import TypeVar
13from tomlkit._utils import parse_rfc3339
14from tomlkit.container import Container
15from tomlkit.exceptions import UnexpectedCharError
16from tomlkit.items import CUSTOM_ENCODERS
17from tomlkit.items import AoT
18from tomlkit.items import Array
19from tomlkit.items import Bool
20from tomlkit.items import Comment
21from tomlkit.items import Date
22from tomlkit.items import DateTime
23from tomlkit.items import DottedKey
24from tomlkit.items import Float
25from tomlkit.items import InlineTable
26from tomlkit.items import Integer
27from tomlkit.items import Item as _Item
28from tomlkit.items import Key
29from tomlkit.items import SingleKey
30from tomlkit.items import String
31from tomlkit.items import StringType as _StringType
32from tomlkit.items import Table
33from tomlkit.items import Time
34from tomlkit.items import Trivia
35from tomlkit.items import Whitespace
36from tomlkit.items import item as item
37from tomlkit.parser import Parser
38from tomlkit.toml_document import TOMLDocument as TOMLDocument
41if TYPE_CHECKING:
42 from tomlkit.items import Encoder
44 E = TypeVar("E", bound=Encoder)
47def loads(string: str | bytes) -> TOMLDocument:
48 """
49 Parses a string into a TOMLDocument.
51 Alias for parse().
52 """
53 return parse(string)
56def dumps(data: Mapping[str, Any], sort_keys: bool = False) -> str:
57 """
58 Dumps a TOMLDocument into a string.
59 """
60 if isinstance(data, (Table, InlineTable, Container)):
61 if not sort_keys:
62 return data.as_string()
64 return item(data, _sort_keys=True).as_string()
66 if isinstance(data, Mapping):
67 return item(dict(data), _sort_keys=sort_keys).as_string()
69 try:
70 # mapping-like wrappers (e.g. dotty_dict's Dotty) delegate
71 # ``as_string`` to the document they wrap; rendering it directly
72 # preserves the original layout, which re-encoding through a plain
73 # dict would lose
74 return data.as_string() # type: ignore[attr-defined]
75 except AttributeError as ex:
76 msg = f"Expecting Mapping or TOML Table or Container, {type(data)} given"
77 raise TypeError(msg) from ex
80def load(fp: IO[str] | IO[bytes]) -> TOMLDocument:
81 """
82 Load toml document from a file-like object.
83 """
84 return parse(fp.read())
87def dump(data: Mapping[str, Any], fp: IO[str], *, sort_keys: bool = False) -> None:
88 """
89 Dump a TOMLDocument into a writable file stream.
91 :param data: a dict-like object to dump
92 :param sort_keys: if true, sort the keys in alphabetic order
94 :Example:
96 >>> with open("output.toml", "w") as fp:
97 ... tomlkit.dump(data, fp)
98 """
99 fp.write(dumps(data, sort_keys=sort_keys))
102def parse(string: str | bytes) -> TOMLDocument:
103 """
104 Parses a string or bytes into a TOMLDocument.
105 """
106 return Parser(string).parse()
109def document() -> TOMLDocument:
110 """
111 Returns a new TOMLDocument instance.
112 """
113 return TOMLDocument()
116# Items
117def integer(raw: str | int) -> Integer:
118 """Create an integer item from a number or string."""
119 return item(int(raw))
122def float_(raw: str | float) -> Float:
123 """Create an float item from a number or string."""
124 return item(float(raw))
127def boolean(raw: str | bool) -> Bool:
128 """Turn `true` or `false` into a boolean item."""
129 return item(raw == "true" if isinstance(raw, str) else raw)
132def string(
133 raw: str,
134 *,
135 literal: bool = False,
136 multiline: bool = False,
137 escape: bool = True,
138) -> String:
139 """Create a string item.
141 By default, this function will create *single line basic* strings, but
142 boolean flags (e.g. ``literal=True`` and/or ``multiline=True``)
143 can be used for personalization.
145 For more information, please check the spec: `<https://toml.io/en/v1.0.0#string>`__.
147 Common escaping rules will be applied for basic strings.
148 This can be controlled by explicitly setting ``escape=False``.
149 Please note that, if you disable escaping, you will have to make sure that
150 the given strings don't contain any forbidden character or sequence.
151 """
152 type_ = _StringType.select(literal, multiline)
153 return String.from_raw(raw, type_, escape)
156def date(raw: str) -> Date:
157 """Create a TOML date."""
158 value = parse_rfc3339(raw)
159 if not isinstance(value, _datetime.date):
160 raise ValueError("date() only accepts date strings.")
162 return item(value)
165def time(raw: str) -> Time:
166 """Create a TOML time."""
167 value = parse_rfc3339(raw)
168 if not isinstance(value, _datetime.time):
169 raise ValueError("time() only accepts time strings.")
171 return item(value)
174def datetime(raw: str) -> DateTime:
175 """Create a TOML datetime."""
176 value = parse_rfc3339(raw)
177 if not isinstance(value, _datetime.datetime):
178 raise ValueError("datetime() only accepts datetime strings.")
180 return item(value)
183def array(raw: str = "[]") -> Array:
184 """Create an array item for its string representation.
186 :Example:
188 >>> array("[1, 2, 3]") # Create from a string
189 [1, 2, 3]
190 >>> a = array()
191 >>> a.extend([1, 2, 3]) # Create from a list
192 >>> a
193 [1, 2, 3]
194 """
195 v = value(raw)
196 if not isinstance(v, Array):
197 raise ValueError(f"Expected an array, got {type(v)}")
198 return v
201def table(is_super_table: bool | None = None) -> Table:
202 """Create an empty table.
204 :param is_super_table: if true, the table is a super table
206 :Example:
208 >>> doc = document()
209 >>> foo = table(True)
210 >>> bar = table()
211 >>> bar.update({'x': 1})
212 >>> foo.append('bar', bar)
213 >>> doc.append('foo', foo)
214 >>> print(doc.as_string())
215 [foo.bar]
216 x = 1
217 """
218 return Table(Container(), Trivia(), False, is_super_table)
221def inline_table() -> InlineTable:
222 """Create an inline table.
224 :Example:
226 >>> table = inline_table()
227 >>> table.update({'x': 1, 'y': 2})
228 >>> print(table.as_string())
229 {x = 1, y = 2}
230 """
231 return InlineTable(Container(), Trivia(), new=True)
234def aot() -> AoT:
235 """Create an array of table.
237 :Example:
239 >>> doc = document()
240 >>> aot = aot()
241 >>> aot.append(item({'x': 1}))
242 >>> doc.append('foo', aot)
243 >>> print(doc.as_string())
244 [[foo]]
245 x = 1
246 """
247 return AoT([])
250def key(k: str | Iterable[str]) -> Key:
251 """Create a key from a string. When a list of string is given,
252 it will create a dotted key.
254 :Example:
256 >>> doc = document()
257 >>> doc.append(key('foo'), 1)
258 >>> doc.append(key(['bar', 'baz']), 2)
259 >>> print(doc.as_string())
260 foo = 1
261 bar.baz = 2
262 """
263 if isinstance(k, str):
264 return SingleKey(k)
265 return DottedKey([SingleKey(_k) for _k in k])
268def value(raw: str) -> _Item:
269 """Parse a simple value from a string.
271 :Example:
273 >>> value("1")
274 1
275 >>> value("true")
276 True
277 >>> value("[1, 2, 3]")
278 [1, 2, 3]
279 """
280 parser = Parser(raw)
281 v = parser._parse_value()
282 if not parser.end():
283 raise parser.parse_error(UnexpectedCharError, char=parser._current)
284 return v
287def key_value(src: str) -> tuple[Key, _Item]:
288 """Parse a key-value pair from a string.
290 :Example:
292 >>> key_value("foo = 1")
293 (Key('foo'), 1)
294 """
295 return Parser(src)._parse_key_value()
298def ws(src: str) -> Whitespace:
299 """Create a whitespace from a string."""
300 return Whitespace(src, fixed=True)
303def nl() -> Whitespace:
304 """Create a newline item."""
305 return ws("\n")
308def comment(string: str) -> Comment:
309 """Create a comment item."""
310 return Comment(Trivia(comment_ws=" ", comment="# " + string))
313def register_encoder(encoder: E) -> E:
314 """Add a custom encoder, which should be a function that will be called
315 if the value can't otherwise be converted.
317 The encoder should return a TOMLKit item or raise a ``ConvertError``.
319 Example:
320 @register_encoder
321 def encode_custom_dict(obj, _parent=None, _sort_keys=False):
322 if isinstance(obj, CustomDict):
323 tbl = table()
324 for key, value in obj.items():
325 # Pass along parameters when encoding nested values
326 tbl[key] = item(value, _parent=tbl, _sort_keys=_sort_keys)
327 return tbl
328 raise ConvertError("Not a CustomDict")
329 """
330 CUSTOM_ENCODERS.append(encoder)
331 return encoder
334def unregister_encoder(encoder: Encoder) -> None:
335 """Unregister a custom encoder."""
336 with contextlib.suppress(ValueError):
337 CUSTOM_ENCODERS.remove(encoder)