| from __future__ import annotations |
| |
| import contextlib |
| import datetime as _datetime |
| |
| from collections.abc import Mapping |
| from typing import IO |
| from typing import Iterable |
| from typing import TypeVar |
| |
| from tomlkit._utils import parse_rfc3339 |
| from tomlkit.container import Container |
| from tomlkit.exceptions import UnexpectedCharError |
| from tomlkit.items import CUSTOM_ENCODERS |
| from tomlkit.items import AoT |
| from tomlkit.items import Array |
| from tomlkit.items import Bool |
| from tomlkit.items import Comment |
| from tomlkit.items import Date |
| from tomlkit.items import DateTime |
| from tomlkit.items import DottedKey |
| from tomlkit.items import Encoder |
| from tomlkit.items import Float |
| from tomlkit.items import InlineTable |
| from tomlkit.items import Integer |
| from tomlkit.items import Item as _Item |
| from tomlkit.items import Key |
| from tomlkit.items import SingleKey |
| from tomlkit.items import String |
| from tomlkit.items import StringType as _StringType |
| from tomlkit.items import Table |
| from tomlkit.items import Time |
| from tomlkit.items import Trivia |
| from tomlkit.items import Whitespace |
| from tomlkit.items import item |
| from tomlkit.parser import Parser |
| from tomlkit.toml_document import TOMLDocument |
| |
| |
| def loads(string: str | bytes) -> TOMLDocument: |
| """ |
| Parses a string into a TOMLDocument. |
| |
| Alias for parse(). |
| """ |
| return parse(string) |
| |
| |
| def dumps(data: Mapping, sort_keys: bool = False) -> str: |
| """ |
| Dumps a TOMLDocument into a string. |
| """ |
| if not isinstance(data, Container) and isinstance(data, Mapping): |
| data = item(dict(data), _sort_keys=sort_keys) |
| |
| try: |
| # data should be a `Container` (and therefore implement `as_string`) |
| # for all type safe invocations of this function |
| return data.as_string() # type: ignore[attr-defined] |
| except AttributeError as ex: |
| msg = f"Expecting Mapping or TOML Container, {type(data)} given" |
| raise TypeError(msg) from ex |
| |
| |
| def load(fp: IO[str] | IO[bytes]) -> TOMLDocument: |
| """ |
| Load toml document from a file-like object. |
| """ |
| return parse(fp.read()) |
| |
| |
| def dump(data: Mapping, fp: IO[str], *, sort_keys: bool = False) -> None: |
| """ |
| Dump a TOMLDocument into a writable file stream. |
| |
| :param data: a dict-like object to dump |
| :param sort_keys: if true, sort the keys in alphabetic order |
| """ |
| fp.write(dumps(data, sort_keys=sort_keys)) |
| |
| |
| def parse(string: str | bytes) -> TOMLDocument: |
| """ |
| Parses a string or bytes into a TOMLDocument. |
| """ |
| return Parser(string).parse() |
| |
| |
| def document() -> TOMLDocument: |
| """ |
| Returns a new TOMLDocument instance. |
| """ |
| return TOMLDocument() |
| |
| |
| # Items |
| def integer(raw: str | int) -> Integer: |
| """Create an integer item from a number or string.""" |
| return item(int(raw)) |
| |
| |
| def float_(raw: str | float) -> Float: |
| """Create an float item from a number or string.""" |
| return item(float(raw)) |
| |
| |
| def boolean(raw: str) -> Bool: |
| """Turn `true` or `false` into a boolean item.""" |
| return item(raw == "true") |
| |
| |
| def string( |
| raw: str, |
| *, |
| literal: bool = False, |
| multiline: bool = False, |
| escape: bool = True, |
| ) -> String: |
| """Create a string item. |
| |
| By default, this function will create *single line basic* strings, but |
| boolean flags (e.g. ``literal=True`` and/or ``multiline=True``) |
| can be used for personalization. |
| |
| For more information, please check the spec: `<https://toml.io/en/v1.0.0#string>`__. |
| |
| Common escaping rules will be applied for basic strings. |
| This can be controlled by explicitly setting ``escape=False``. |
| Please note that, if you disable escaping, you will have to make sure that |
| the given strings don't contain any forbidden character or sequence. |
| """ |
| type_ = _StringType.select(literal, multiline) |
| return String.from_raw(raw, type_, escape) |
| |
| |
| def date(raw: str) -> Date: |
| """Create a TOML date.""" |
| value = parse_rfc3339(raw) |
| if not isinstance(value, _datetime.date): |
| raise ValueError("date() only accepts date strings.") |
| |
| return item(value) |
| |
| |
| def time(raw: str) -> Time: |
| """Create a TOML time.""" |
| value = parse_rfc3339(raw) |
| if not isinstance(value, _datetime.time): |
| raise ValueError("time() only accepts time strings.") |
| |
| return item(value) |
| |
| |
| def datetime(raw: str) -> DateTime: |
| """Create a TOML datetime.""" |
| value = parse_rfc3339(raw) |
| if not isinstance(value, _datetime.datetime): |
| raise ValueError("datetime() only accepts datetime strings.") |
| |
| return item(value) |
| |
| |
| def array(raw: str = "[]") -> Array: |
| """Create an array item for its string representation. |
| |
| :Example: |
| |
| >>> array("[1, 2, 3]") # Create from a string |
| [1, 2, 3] |
| >>> a = array() |
| >>> a.extend([1, 2, 3]) # Create from a list |
| >>> a |
| [1, 2, 3] |
| """ |
| return value(raw) |
| |
| |
| def table(is_super_table: bool | None = None) -> Table: |
| """Create an empty table. |
| |
| :param is_super_table: if true, the table is a super table |
| |
| :Example: |
| |
| >>> doc = document() |
| >>> foo = table(True) |
| >>> bar = table() |
| >>> bar.update({'x': 1}) |
| >>> foo.append('bar', bar) |
| >>> doc.append('foo', foo) |
| >>> print(doc.as_string()) |
| [foo.bar] |
| x = 1 |
| """ |
| return Table(Container(), Trivia(), False, is_super_table) |
| |
| |
| def inline_table() -> InlineTable: |
| """Create an inline table. |
| |
| :Example: |
| |
| >>> table = inline_table() |
| >>> table.update({'x': 1, 'y': 2}) |
| >>> print(table.as_string()) |
| {x = 1, y = 2} |
| """ |
| return InlineTable(Container(), Trivia(), new=True) |
| |
| |
| def aot() -> AoT: |
| """Create an array of table. |
| |
| :Example: |
| |
| >>> doc = document() |
| >>> aot = aot() |
| >>> aot.append(item({'x': 1})) |
| >>> doc.append('foo', aot) |
| >>> print(doc.as_string()) |
| [[foo]] |
| x = 1 |
| """ |
| return AoT([]) |
| |
| |
| def key(k: str | Iterable[str]) -> Key: |
| """Create a key from a string. When a list of string is given, |
| it will create a dotted key. |
| |
| :Example: |
| |
| >>> doc = document() |
| >>> doc.append(key('foo'), 1) |
| >>> doc.append(key(['bar', 'baz']), 2) |
| >>> print(doc.as_string()) |
| foo = 1 |
| bar.baz = 2 |
| """ |
| if isinstance(k, str): |
| return SingleKey(k) |
| return DottedKey([key(_k) for _k in k]) |
| |
| |
| def value(raw: str) -> _Item: |
| """Parse a simple value from a string. |
| |
| :Example: |
| |
| >>> value("1") |
| 1 |
| >>> value("true") |
| True |
| >>> value("[1, 2, 3]") |
| [1, 2, 3] |
| """ |
| parser = Parser(raw) |
| v = parser._parse_value() |
| if not parser.end(): |
| raise parser.parse_error(UnexpectedCharError, char=parser._current) |
| return v |
| |
| |
| def key_value(src: str) -> tuple[Key, _Item]: |
| """Parse a key-value pair from a string. |
| |
| :Example: |
| |
| >>> key_value("foo = 1") |
| (Key('foo'), 1) |
| """ |
| return Parser(src)._parse_key_value() |
| |
| |
| def ws(src: str) -> Whitespace: |
| """Create a whitespace from a string.""" |
| return Whitespace(src, fixed=True) |
| |
| |
| def nl() -> Whitespace: |
| """Create a newline item.""" |
| return ws("\n") |
| |
| |
| def comment(string: str) -> Comment: |
| """Create a comment item.""" |
| return Comment(Trivia(comment_ws=" ", comment="# " + string)) |
| |
| |
| E = TypeVar("E", bound=Encoder) |
| |
| |
| def register_encoder(encoder: E) -> E: |
| """Add a custom encoder, which should be a function that will be called |
| if the value can't otherwise be converted. It should takes a single value |
| and return a TOMLKit item or raise a ``TypeError``. |
| """ |
| CUSTOM_ENCODERS.append(encoder) |
| return encoder |
| |
| |
| def unregister_encoder(encoder: Encoder) -> None: |
| """Unregister a custom encoder.""" |
| with contextlib.suppress(ValueError): |
| CUSTOM_ENCODERS.remove(encoder) |